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