Cherry picks from trunk to releases/2.1:

r8958 Updating the doc build file to include the new examples for Cells
rTBD Resolves ROO-1508 by requiring CompositeEditors to return a canonical component Editor instance for path traversal



git-svn-id: https://google-web-toolkit.googlecode.com/svn/releases/2.1@8962 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/doc/build.xml b/doc/build.xml
index 6b40bb8..0f10a55 100644
--- a/doc/build.xml
+++ b/doc/build.xml
@@ -9,9 +9,6 @@
   <!-- Platform shouldn't matter here, just picking one -->
   <property.ensure name="gwt.dev.jar" location="${gwt.build.lib}/gwt-dev.jar" />
 
-  <!-- This file controls the contents of the javadoc -->
-  <property file="packages.properties" />
-
   <!--
     *** Note that if the USER_SOURCE_PATH paths are updated,
     the fileset dependencies in the outofdate tags in the
@@ -42,6 +39,7 @@
     <path refid="USER_SOURCE_PATH" />
   </path>
 
+  <!-- Rebuild the javadoc if a source file is newer than the index-->
   <target name="javadoc">
     <outofdate>
       <sourcefiles>
@@ -71,35 +69,51 @@
       </targetfiles>
       <sequential>
         <echo>Building javadoc</echo>
-        <java classpathref="DOC_PATH" classname="com.google.doctool.custom.GWTJavaDoclet" fork="yes" failonerror="true">
-          <jvmarg value="-Xmx512M" />
-          <arg value="-quiet" />
-          <arg value="-notimestamp" />
-          <arg value="-source" />
-          <arg value="1.5" />
-          <arg value="-windowtitle" />
-          <arg value="Google Web Toolkit Javadoc" />
-          <arg value="-doctitle" />
-          <arg value="Google Web Toolkit API Reference" />
-          <arg value="-header" />
-          <arg value="GWT ${gwt.version}" />
-          <arg value="-encoding"/>
-          <arg value="UTF-8"/>
-          <arg value="-d" />
-          <arg value="${project.build}/javadoc" />
-          <arg value="-classpath" />
-          <arg pathref="USER_CLASS_PATH" />
-          <arg value="-sourcepath" />
-          <arg pathref="USER_SOURCE_PATH" />
-          <arg value="-examplepackages" />
-          <arg value="com.google.gwt.examples;com.google.gwt.examples.i18n;com.google.gwt.examples.http.client;com.google.gwt.examples.rpc.server;com.google.gwt.examples.benchmarks" />
-          <arg value="-packages" />
-          <arg value="${USER_PKGS};${USER_CLASSES}" />
-        </java>
+        <antcall target="makeJavadoc" />
       </sequential>
     </outofdate>
   </target>
 
+  <!-- Really rebuild the javadoc -->
+  <target name="makeJavadoc">	
+    <exec executable="chmod">
+      <arg value="+x" />
+      <arg value="${gwt.root}/doc/find-packages.sh" />
+    </exec>
+    <exec executable="${gwt.root}/doc/find-packages.sh" />
+    <property file="packages.properties" />
+    <java classpathref="DOC_PATH" classname="com.google.doctool.custom.GWTJavaDoclet" fork="yes" failonerror="true">
+      <jvmarg value="-Xmx1024m" />
+      <arg value="-quiet" />
+      <arg value="-notimestamp" />
+      <arg value="-source" />
+      <arg value="1.5" />
+      <arg value="-windowtitle" />
+      <arg value="Google Web Toolkit Javadoc" />
+      <arg value="-doctitle" />
+      <arg value="Google Web Toolkit API Reference" />
+      <arg value="-header" />
+      <arg value="GWT ${gwt.version}" />
+      <arg value="-encoding"/>
+      <arg value="UTF-8"/>
+      <arg value="-d" />
+      <arg value="${project.build}/javadoc" />
+      <arg value="-linkoffline" />
+      <arg value="http://download.oracle.com/javaee/6/api/" />
+      <arg value="validation-package-list" />
+      <arg value="-link" />
+      <arg value="http://www.json.org/javadoc" />
+      <arg value="-classpath" />
+      <arg pathref="USER_CLASS_PATH" />
+      <arg value="-sourcepath" />
+      <arg pathref="USER_SOURCE_PATH" />
+      <arg value="-examplepackages" />
+      <arg value="com.google.gwt.examples;com.google.gwt.examples.i18n;com.google.gwt.examples.http.client;com.google.gwt.examples.rpc.server;com.google.gwt.examples.benchmarks;com.google.gwt.examples.cell;com.google.gwt.examples.cellview;com.google.gwt.examples.view" />
+      <arg value="-packages" />
+      <arg value="${USER_PKGS};${USER_CLASSES}" />
+    </java>
+  </target>
+
   <target name="emul-ezt">
     <outofdate>
       <sourcefiles>
@@ -112,6 +126,12 @@
       </targetfiles>
       <sequential>
         <echo>Building JRE emulation EZT</echo>
+        <exec executable="chmod">
+          <arg value="+x" />
+          <arg value="${gwt.root}/doc/find-packages.sh" />
+        </exec>
+        <exec executable="${gwt.root}/doc/find-packages.sh" />
+        <property file="packages.properties" />
         <java classpathref="DOC_PATH" classname="com.google.doctool.JreDocTool" fork="yes" failonerror="true">
           <arg value="-out" />
           <arg value="${project.build}/emul-ezt/fragment.html" />
diff --git a/doc/find-packages.sh b/doc/find-packages.sh
new file mode 100644
index 0000000..9383271
--- /dev/null
+++ b/doc/find-packages.sh
@@ -0,0 +1,93 @@
+#!/bin/bash
+set noglob
+
+OUTFILE=packages.properties
+TMPFILE=/tmp/gwt-javadoc-packages$$
+
+# Regex patterns to exclude from the list of packages
+EXCLUSIONS="\
+^com\.example\.|\
+^com\.google\.gwt\.dev(\.|$)|\
+^com\.google\.gwt\.emul\.|\
+^com\.google\.gwt\.examples(\.|$)|\
+^com\.google\.gwt\.i18n\.server(\.|$)|\
+^com\.google\.gwt\.i18n\.tools|\
+^com\.google\.gwt\.lang|\
+^com\.google\.gwt\.junit(\.|$)|\
+^com\.google\.gwt\.resources\.css(\.|$)|\
+^com\.google\.gwt\.resources\.rg(\.|$)|\
+^com\.google\.gwt\.rpc\.client\.ast(\.|$)|\
+^com\.google\.gwt\.soyc(\.|$)|\
+^com\.google\.gwt\.validation(.|$)|\
+^com\.google\.gwt\.user\.client\.rpc\.core\.|\
+^javax\.|\
+^junit\.|\
+^org\.|\
+\.impl(\.|$)|\
+\.rebind(\.|$)"
+
+# Generate the packages.properties file
+# Changes to LANG_PKGS and USER_CLASSES go here
+# Note that line continuation backslashes must be escaped
+cat > ${OUTFILE} <<EOF
+# THIS FILE IS AUTOMATICALLY GENERATED
+#
+# This file contains all of the user javadoc packages
+#
+# JRE emulation packages
+LANG_PKGS=\\
+java.lang;\\
+java.lang.annotation;\\
+java.io;\\
+java.sql;\\
+java.util
+# The last package should not have a trailing semicolon
+
+# Individual classes to include when we don't want to include an entire package
+USER_CLASSES=\\
+\${gwt.root}/user/src/com/google/gwt/junit/tools/GWTTestSuite.java:\\
+\${gwt.root}/user/src/com/google/gwt/i18n/rebind/LocaleUtils.java:\\
+\${gwt.root}/user/src/com/google/gwt/i18n/server/GwtLocaleFactoryImpl.java:\\
+\${gwt.root}/user/src/com/google/gwt/i18n/server/GwtLocaleImpl.java
+
+# Packages to include
+USER_PKGS=\\
+EOF
+
+rm -f ${TMPFILE}
+
+# Create a list of all packages with at least one Java source file
+# List all source files
+for dir in ../user/src ../user/javadoc ../user/super ../dev/core/src ../dev/core/super
+do
+(cd ${dir}; find . -name '*.java') >> ${TMPFILE}
+done
+
+cat ${TMPFILE} | \
+# Remove source file names
+sed 's@/[-A-Za-z0-9_]*\.java$@@'| \
+# Removce initial './'
+sed s@^\./@@ | \
+# Remove .../super/ and .../translatable prefixes
+sed s@^.*/super/@@ | \
+sed s@^.*/translatable/@@ | \
+# Change slashes to dots
+sed s@/@.@g | \
+# Remove excluded patters
+egrep -v ${EXCLUSIONS} > ${TMPFILE}-2
+mv ${TMPFILE}-2 ${TMPFILE}
+
+# Re-add whitelisted packages that would otherwise be excluded
+echo com.google.gwt.i18n.rebind.format >> ${TMPFILE}
+echo com.google.gwt.i18n.rebind.keygen >> ${TMPFILE}
+echo com.google.gwt.junit.client >> ${TMPFILE}
+
+# Sort, uniqify, and add ';\' to each line except the last
+cat ${TMPFILE} | \
+sort | \
+uniq | \
+sed '$q;s@$@;\\@' >> ${OUTFILE}
+echo '# The last package should not have a trailing semicolon' >> ${OUTFILE}
+
+# Clean up
+rm -f ${TMPFILE}
diff --git a/doc/json-package-list/package-list b/doc/json-package-list/package-list
new file mode 100644
index 0000000..6374a8e
--- /dev/null
+++ b/doc/json-package-list/package-list
@@ -0,0 +1 @@
+org.json
diff --git a/doc/packages.properties b/doc/packages.properties
deleted file mode 100644
index 413eae4..0000000
--- a/doc/packages.properties
+++ /dev/null
@@ -1,65 +0,0 @@
-# This file contains all of the user javadoc packages.
-LANG_PKGS=\
-java.lang;\
-java.lang.annotation;\
-java.io;\
-java.sql;\
-java.util
-# The last package should not have a trailing semicolon
-
-# Individual classes to include when we don't want to include an entire package.
-USER_CLASSES=\
-${gwt.root}/user/src/com/google/gwt/junit/tools/GWTTestSuite.java:\
-${gwt.root}/user/src/com/google/gwt/i18n/rebind/LocaleUtils.java:\
-${gwt.root}/user/src/com/google/gwt/i18n/server/GwtLocaleFactoryImpl.java:\
-${gwt.root}/user/src/com/google/gwt/i18n/server/GwtLocaleImpl.java
-
-USER_PKGS=\
-com.google.gwt.animation.client;\
-com.google.gwt.benchmarks.client;\
-com.google.gwt.cell.client;\
-com.google.gwt.core.client;\
-com.google.gwt.core.ext;\
-com.google.gwt.core.ext.soyc;\
-com.google.gwt.core.ext.linker;\
-com.google.gwt.core.ext.typeinfo;\
-com.google.gwt.core.linker;\
-com.google.gwt.debug.client;\
-com.google.gwt.dom.client;\
-com.google.gwt.editor.client;\
-com.google.gwt.editor.client.adapters;\
-com.google.gwt.editor.client.testing;\
-com.google.gwt.event.dom.client;\
-com.google.gwt.event.logical.shared;\
-com.google.gwt.event.shared;\
-com.google.gwt.http.client;\
-com.google.gwt.i18n.client;\
-com.google.gwt.i18n.shared;\
-com.google.gwt.i18n.client.constants;\
-com.google.gwt.i18n.rebind.format;\
-com.google.gwt.i18n.rebind.keygen;\
-com.google.gwt.json.client;\
-com.google.gwt.junit.client;\
-com.google.gwt.logging.client;\
-com.google.gwt.benchmarks.client;\
-com.google.gwt.regexp.shared;\
-com.google.gwt.resources.client;\
-com.google.gwt.resources.ext;\
-com.google.gwt.user.cellview.client;\
-com.google.gwt.user.client;\
-com.google.gwt.user.client.rpc;\
-com.google.gwt.user.client.ui;\
-com.google.gwt.user.datepicker.client;\
-com.google.gwt.user.server.rpc;\
-com.google.gwt.xml.client;\
-com.google.gwt.uibinder.client;\
-com.google.gwt.rpc.client;\
-com.google.gwt.rpc.server;\
-com.google.gwt.jsonp.client;\
-com.google.gwt.view.client;\
-com.google.gwt.app.client;\
-com.google.gwt.app.place;\
-com.google.gwt.requestfactory.client;\
-com.google.gwt.requestfactory.server;\
-com.google.gwt.requestfactory.shared
-# The last package should not have a trailing semicolon
diff --git a/doc/validation-package-list/package-list b/doc/validation-package-list/package-list
new file mode 100644
index 0000000..8b0d75a
--- /dev/null
+++ b/doc/validation-package-list/package-list
@@ -0,0 +1,2 @@
+javax.validation
+javax.validation.constraints
diff --git a/user/src/com/google/gwt/editor/client/CompositeEditor.java b/user/src/com/google/gwt/editor/client/CompositeEditor.java
index 11569de..95d48a6 100644
--- a/user/src/com/google/gwt/editor/client/CompositeEditor.java
+++ b/user/src/com/google/gwt/editor/client/CompositeEditor.java
@@ -82,6 +82,12 @@
   }
 
   /**
+   * Returns an canonical sub-editor instance that will be used by the driver
+   * for computing all edited paths.
+   */
+  E createEditorForTraversal();
+
+  /**
    * Used to implement {@link EditorDelegate#getPath()}.
    */
   String getPathElement(E subEditor);
diff --git a/user/src/com/google/gwt/editor/client/adapters/ListEditor.java b/user/src/com/google/gwt/editor/client/adapters/ListEditor.java
index 314be63..988aaa2 100644
--- a/user/src/com/google/gwt/editor/client/adapters/ListEditor.java
+++ b/user/src/com/google/gwt/editor/client/adapters/ListEditor.java
@@ -52,6 +52,12 @@
     this.editorSource = source;
   }
 
+  public E createEditorForTraversal() {
+    E toReturn = editorSource.create(0);
+    editorSource.dispose(toReturn);
+    return toReturn;
+  }
+
   public void flush() {
     list.flush();
   }
diff --git a/user/src/com/google/gwt/editor/client/adapters/OptionalFieldEditor.java b/user/src/com/google/gwt/editor/client/adapters/OptionalFieldEditor.java
index cac0a07..0373e16 100644
--- a/user/src/com/google/gwt/editor/client/adapters/OptionalFieldEditor.java
+++ b/user/src/com/google/gwt/editor/client/adapters/OptionalFieldEditor.java
@@ -63,6 +63,10 @@
     this.subEditor = subEditor;
   }
 
+  public E createEditorForTraversal() {
+    return subEditor;
+  }
+
   public void flush() {
     currentValue = chain.getValue(subEditor);
   }
diff --git a/user/src/com/google/gwt/editor/rebind/AbstractEditorDriverGenerator.java b/user/src/com/google/gwt/editor/rebind/AbstractEditorDriverGenerator.java
index 18f9f62..a33e03b 100644
--- a/user/src/com/google/gwt/editor/rebind/AbstractEditorDriverGenerator.java
+++ b/user/src/com/google/gwt/editor/rebind/AbstractEditorDriverGenerator.java
@@ -194,8 +194,8 @@
       for (EditorData d : data) {
         String mutableObjectExpression;
         if (d.getBeanOwnerExpression().length() > 0) {
-          mutableObjectExpression = mutableObjectExpression(d, String.format(
-              "(getObject()%s)", d.getBeanOwnerExpression()));
+          mutableObjectExpression = mutableObjectExpression(d,
+              String.format("(getObject()%s)", d.getBeanOwnerExpression()));
         } else {
           mutableObjectExpression = "getObject()";
         }
@@ -294,7 +294,8 @@
           editor.getQualifiedSourceName(), List.class.getName());
       sw.indent();
       for (EditorData d : data) {
-        if (d.isDelegateRequired() || d.isDeclaredPathNested()) {
+        if (d.isDelegateRequired() || d.isDeclaredPathNested()
+            || d.isCompositeEditor()) {
           // if (editor.subEditor != null) {
           sw.println("if (editor.%s != null) {", d.getSimpleExpression());
           sw.indent();
@@ -308,6 +309,15 @@
             sw.println("%s.traverseEditor(editor.%s, localPath, paths);",
                 getEditorDelegate(d), d.getSimpleExpression());
           }
+          if (d.isCompositeEditor()) {
+            /*
+             * composedDelegate.traverseEditor(editor.subEditor.
+             * createEditorForTraversal(), localPath, paths);
+             */
+            sw.println(
+                "%s.traverseEditor(editor.%s.createEditorForTraversal(), localPath, paths);",
+                getEditorDelegate(d.getComposedData()), d.getSimpleExpression());
+          }
           sw.outdent();
           sw.println("}");
         }
@@ -330,7 +340,7 @@
    * @param context
    * @param model
    * @param sw
-   *
+   * 
    * @throws UnableToCompleteException
    */
   protected void writeAdditionalContent(TreeLogger logger,
diff --git a/user/src/com/google/gwt/editor/rebind/model/EditorModel.java b/user/src/com/google/gwt/editor/rebind/model/EditorModel.java
index 3dab1b4..8577228 100644
--- a/user/src/com/google/gwt/editor/rebind/model/EditorModel.java
+++ b/user/src/com/google/gwt/editor/rebind/model/EditorModel.java
@@ -60,7 +60,7 @@
         if (compositeEditorIntf.equals(parameterized.getBaseType())) {
           JClassType[] typeArgs = parameterized.getTypeArgs();
           assert typeArgs.length == 3;
-          return new JClassType[] {typeArgs[1], typeArgs[2]};
+          return new JClassType[]{typeArgs[1], typeArgs[2]};
         }
       }
     }
@@ -83,8 +83,8 @@
     if (parameterization != null) {
       return parameterization[0];
     }
-    logger.log(TreeLogger.ERROR, noEditorParameterizationMessage(editorIntf,
-        editorType));
+    logger.log(TreeLogger.ERROR,
+        noEditorParameterizationMessage(editorIntf, editorType));
     throw new UnableToCompleteException();
   }
 
@@ -102,8 +102,8 @@
     if (parameterization != null) {
       return parameterization[0];
     }
-    logger.log(TreeLogger.ERROR, noEditorParameterizationMessage(editorIntf,
-        editorType));
+    logger.log(TreeLogger.ERROR,
+        noEditorParameterizationMessage(editorIntf, editorType));
     throw new UnableToCompleteException();
   }
 
@@ -326,6 +326,10 @@
               && isEditorIntf.isAssignableFrom(editorType)) {
             // Ignore IsEditor.asEditor()
             continue;
+          } else if (access.getPath().equals("createEditorForTraversal")
+              && compositeEditorIntf.isAssignableFrom(editorType)) {
+            // Ignore CompositeEditor.createEditorForTraversal();
+            continue;
           }
           List<EditorData> data = createEditorData(access);
           accumulateEditorData(data, flatData, toReturn);
@@ -376,8 +380,8 @@
 
     // Are we looking at a view that implements IsEditor?
     if (access.isEditor()) {
-      EditorAccess subAccess = EditorAccess.via(access, calculateIsEditedType(
-          subLogger, access.getEditorType()));
+      EditorAccess subAccess = EditorAccess.via(access,
+          calculateIsEditedType(subLogger, access.getEditorType()));
       toReturn = createEditorData(subAccess);
 
       // If an object only implements IsEditor, return now
diff --git a/user/test/com/google/gwt/requestfactory/client/ui/EditorTest.java b/user/test/com/google/gwt/requestfactory/client/ui/EditorTest.java
index 6b1cc48..d9b71ae 100644
--- a/user/test/com/google/gwt/requestfactory/client/ui/EditorTest.java
+++ b/user/test/com/google/gwt/requestfactory/client/ui/EditorTest.java
@@ -23,6 +23,8 @@
 import com.google.gwt.editor.client.EditorError;
 import com.google.gwt.editor.client.HasEditorDelegate;
 import com.google.gwt.editor.client.HasEditorErrors;
+import com.google.gwt.editor.client.adapters.EditorSource;
+import com.google.gwt.editor.client.adapters.ListEditor;
 import com.google.gwt.editor.client.adapters.SimpleEditor;
 import com.google.gwt.requestfactory.client.RequestFactoryEditorDriver;
 import com.google.gwt.requestfactory.client.RequestFactoryTestBase;
@@ -55,6 +57,10 @@
       RequestFactoryEditorDriver<SimpleFooProxy, SimpleFooEditor> {
   }
 
+  static class SimpleFooBarOnlyEditor implements Editor<SimpleFooProxy> {
+    SimpleBarEditor barField = new SimpleBarEditor();
+  }
+
   static class SimpleFooEditor implements HasEditorErrors<SimpleFooProxy> {
     /**
      * Test field-based access.
@@ -67,6 +73,13 @@
     @Path("barField.userName")
     final SimpleEditor<String> barName = SimpleEditor.of();
 
+    final ListEditor<SimpleFooProxy, SimpleFooBarOnlyEditor> selfOneToManyField = ListEditor.of(new EditorSource<SimpleFooBarOnlyEditor>() {
+      @Override
+      public SimpleFooBarOnlyEditor create(int index) {
+        return new SimpleFooBarOnlyEditor();
+      }
+    });
+
     private final SimpleBarEditor barEditor = new SimpleBarEditor();
 
     List<EditorError> errors;
@@ -108,32 +121,32 @@
     driver.initialize(req, editor);
 
     req.simpleFooRequest().findSimpleFooById(1L).with(driver.getPaths()).fire(
-    new Receiver<SimpleFooProxy>() {
-      @Override
-      public void onSuccess(SimpleFooProxy response) {
-    
-        SimpleFooRequest context = req.simpleFooRequest();
-        driver.edit(response, context);
-        context.persistAndReturnSelf().using(response).with(
-            driver.getPaths()).to(new Receiver<SimpleFooProxy>() {
+        new Receiver<SimpleFooProxy>() {
           @Override
           public void onSuccess(SimpleFooProxy response) {
-            assertEquals("EditorFooTest", response.getUserName());
-            assertEquals("EditorBarTest",
-                response.getBarField().getUserName());
-            finishTestAndReset();
+
+            SimpleFooRequest context = req.simpleFooRequest();
+            driver.edit(response, context);
+            context.persistAndReturnSelf().using(response).with(
+                driver.getPaths()).to(new Receiver<SimpleFooProxy>() {
+              @Override
+              public void onSuccess(SimpleFooProxy response) {
+                assertEquals("EditorFooTest", response.getUserName());
+                assertEquals("EditorBarTest",
+                    response.getBarField().getUserName());
+                finishTestAndReset();
+              }
+            });
+            assertEquals("GWT", editor.userName.getValue());
+            assertEquals("FOO", editor.barEditor().userName.getValue());
+            assertEquals("FOO", editor.barName.getValue());
+            editor.userName.setValue("EditorFooTest");
+            // When there are duplicate paths, last declared editor wins
+            editor.barEditor().userName.setValue("EditorBarTest");
+            editor.barName.setValue("ignored");
+            driver.flush().fire();
           }
         });
-        assertEquals("GWT", editor.userName.getValue());
-        assertEquals("FOO", editor.barEditor().userName.getValue());
-        assertEquals("FOO", editor.barName.getValue());
-        editor.userName.setValue("EditorFooTest");
-        // When there are duplicate paths, last declared editor wins
-        editor.barEditor().userName.setValue("EditorBarTest");
-        editor.barName.setValue("ignored");
-        driver.flush().fire();
-      }
-    });
   }
 
   public void testNoSubscription() {
@@ -141,10 +154,10 @@
 
     final SimpleFooDriver driver = GWT.create(SimpleFooDriver.class);
     driver.initialize(req, editor);
-    
+
     /*
      * Confirm that it's always safe to call subscribe. The editor's delegate
-     * isn't set until edit is called, so edit nothing. 
+     * isn't set until edit is called, so edit nothing.
      */
     driver.edit(null, null);
     assertNull(editor.delegate.subscribe());
@@ -157,10 +170,11 @@
     final SimpleFooDriver driver = GWT.create(SimpleFooDriver.class);
     driver.initialize(req, editor);
 
-    assertEquals(Arrays.asList("barField.userName", "barField"),
-        Arrays.asList(driver.getPaths()));
+    String[] paths = driver.getPaths();
+    assertEquals(Arrays.asList("barField.userName", "selfOneToManyField", 
+        "selfOneToManyField.barField", "barField"), Arrays.asList(paths));
 
-    req.simpleFooRequest().findSimpleFooById(1L).with(driver.getPaths()).fire(
+    req.simpleFooRequest().findSimpleFooById(1L).with(paths).fire(
         new Receiver<SimpleFooProxy>() {
           @Override
           public void onSuccess(SimpleFooProxy response) {
@@ -202,7 +216,7 @@
           }
         });
   }
-  
+
   public void testViolations() {
     delayTestFinish(TEST_TIMEOUT);
     final SimpleFooEditor editor = new SimpleFooEditor();