Revision: 10348
Author:   b...@google.com
Date:     Fri Jun 17 10:00:12 2011
Log: Make TypeTokenResolver and RequestFactory's annotation processor easier to integrate with Adroid ADT build process by generating a pre-populated TypeTokenBuilder class. This avoids the need to manipulate resource inclusion in the usual project setup.
Patch by: bobv
Review by: rjrjr, rice

Review at http://gwt-code-reviews.appspot.com/1462801

http://code.google.com/p/google-web-toolkit/source/detail?r=10348

Modified:
 /trunk/user/src/com/google/web/bindery/requestfactory/apt/RfApt.java
/trunk/user/src/com/google/web/bindery/requestfactory/vm/impl/TypeTokenResolver.java

=======================================
--- /trunk/user/src/com/google/web/bindery/requestfactory/apt/RfApt.java Thu Jun 9 11:31:51 2011 +++ /trunk/user/src/com/google/web/bindery/requestfactory/apt/RfApt.java Fri Jun 17 10:00:12 2011
@@ -22,10 +22,13 @@
 import com.google.web.bindery.requestfactory.vm.impl.TypeTokenResolver;

 import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Map;
 import java.util.Set;

 import javax.annotation.processing.AbstractProcessor;
 import javax.annotation.processing.Filer;
+import javax.annotation.processing.FilerException;
 import javax.annotation.processing.ProcessingEnvironment;
 import javax.annotation.processing.RoundEnvironment;
 import javax.annotation.processing.SupportedAnnotationTypes;
@@ -41,6 +44,7 @@
 import javax.lang.model.util.Types;
 import javax.tools.Diagnostic.Kind;
 import javax.tools.FileObject;
+import javax.tools.JavaFileObject;
 import javax.tools.StandardLocation;

 /**
@@ -108,7 +112,7 @@

     // Extract data
new Finder().scan(ElementFilter.typesIn(roundEnv.getRootElements()), null);
-
+
     // On the last round, write out accumulated data
     if (roundEnv.processingOver()) {
       TypeTokenResolver d = builder.build();
@@ -119,6 +123,39 @@
       } catch (IOException e) {
         error("Could not write output: " + e.getMessage());
       }
+
+      /*
+ * Getting the TOKEN_MANIFEST resource into an Android APK generated by + * the Android Eclipse plugin is non-trivial. (Users of ant and apkbuilder + * can just use -rf to include the relevant file). To support the common + * use-case, we'll generate a subclass of TypeTokenResolver.Builder that + * has all of the data already baked into it. This synthetic subtype is + * looked for first by TypeTokenResolver and any manifests that are on the
+       * classpath will be added on top.
+       */
+      try {
+ String packageName = TypeTokenResolver.class.getPackage().getName(); + String simpleName = TypeTokenResolver.class.getSimpleName() + "BuilderImpl"; + JavaFileObject classfile = filer.createSourceFile(packageName + "." + simpleName);
+        PrintWriter pw = new PrintWriter(classfile.openWriter());
+        pw.println("package " + packageName + ";");
+        pw.println("public class " + simpleName + " extends "
+            + TypeTokenResolver.Builder.class.getCanonicalName() + " {");
+        pw.println("public " + simpleName + "() {");
+ for (Map.Entry<String, String> entry : d.getAllTypeTokens().entrySet()) {
+          if (elements.getTypeElement(entry.getValue()) != null) {
+ pw.println("addTypeToken(\"" + entry.getKey() + "\", " + entry.getValue()
+                + ".class.getName());");
+          }
+        }
+        pw.println("}");
+        pw.println("}");
+        pw.close();
+      } catch (FilerException e) {
+        log("Ignoring exception: %s", e.getMessage());
+      } catch (IOException e) {
+        error("Could not write BuilderImpl: " + e.getMessage());
+      }
       log("Finished!");
     }
     return false;
=======================================
--- /trunk/user/src/com/google/web/bindery/requestfactory/vm/impl/TypeTokenResolver.java Fri Jun 10 11:06:22 2011 +++ /trunk/user/src/com/google/web/bindery/requestfactory/vm/impl/TypeTokenResolver.java Fri Jun 17 10:00:12 2011
@@ -26,6 +26,8 @@
 import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
+import java.util.SortedMap;
+import java.util.TreeMap;

 /**
  * Resolves payload type tokens to binary class names.
@@ -75,10 +77,26 @@
    * TypeTokenResolver.
    */
   public static TypeTokenResolver loadFromClasspath() throws IOException {
-    Builder builder = new Builder();
+    Builder builder;
+    boolean mustLoad = true;
+    try {
+      // Look for a pre-cooked Builder type
+      Class<?> maybeBuilderImpl =
+ Class.forName(TypeTokenResolver.class.getName() + "BuilderImpl", false, Thread
+              .currentThread().getContextClassLoader());
+      builder = maybeBuilderImpl.asSubclass(Builder.class).newInstance();
+      mustLoad = false;
+    } catch (ClassNotFoundException ignored) {
+      // Try manifest-based approach
+      builder = new Builder();
+    } catch (InstantiationException e) {
+ throw new RuntimeException("Could not instantiate TypeTokenResolverImpl", e);
+    } catch (IllegalAccessException e) {
+ throw new RuntimeException("Could not instantiate TypeTokenResolverImpl", e);
+    }
     Enumeration<URL> locations =
Thread.currentThread().getContextClassLoader().getResources(TOKEN_MANIFEST);
-    if (!locations.hasMoreElements()) {
+    if (mustLoad && !locations.hasMoreElements()) {
throw new RuntimeException("No token manifest found. Did the RequestFactory annotation" + " processor run? Check classpath for " + TOKEN_MANIFEST + " file and ensure that" + " your proxy types are compiled with the requestfactory-apt.jar on javac's classpath.");
@@ -99,6 +117,10 @@
    */
   private Map<String, String> typeTokens = new HashMap<String, String>();

+  public SortedMap<String, String> getAllTypeTokens() {
+    return new TreeMap<String, String>(typeTokens);
+  }
+
   public String getTypeFromToken(String typeToken) {
     return typeTokens.get(typeToken);
   }

--
http://groups.google.com/group/Google-Web-Toolkit-Contributors

Reply via email to