Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

ConnectorBundleLoaderFactory.java 9.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. /*
  2. @VaadinApache2LicenseForJavaFiles@
  3. */
  4. package com.vaadin.terminal.gwt.widgetsetutils;
  5. import java.io.PrintWriter;
  6. import java.util.ArrayList;
  7. import java.util.Arrays;
  8. import java.util.Collection;
  9. import java.util.Collections;
  10. import java.util.HashMap;
  11. import java.util.List;
  12. import java.util.Map;
  13. import java.util.Map.Entry;
  14. import java.util.Set;
  15. import com.google.gwt.core.client.GWT;
  16. import com.google.gwt.core.ext.Generator;
  17. import com.google.gwt.core.ext.GeneratorContext;
  18. import com.google.gwt.core.ext.TreeLogger;
  19. import com.google.gwt.core.ext.TreeLogger.Type;
  20. import com.google.gwt.core.ext.UnableToCompleteException;
  21. import com.google.gwt.core.ext.typeinfo.JClassType;
  22. import com.google.gwt.core.ext.typeinfo.NotFoundException;
  23. import com.google.gwt.core.ext.typeinfo.TypeOracle;
  24. import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
  25. import com.google.gwt.user.rebind.SourceWriter;
  26. import com.vaadin.shared.communication.ClientRpc;
  27. import com.vaadin.shared.communication.ServerRpc;
  28. import com.vaadin.shared.ui.Connect;
  29. import com.vaadin.shared.ui.Connect.LoadStyle;
  30. import com.vaadin.terminal.gwt.client.ServerConnector;
  31. import com.vaadin.terminal.gwt.client.metadata.ConnectorBundleLoader;
  32. import com.vaadin.terminal.gwt.client.metadata.TypeDataBundle;
  33. import com.vaadin.terminal.gwt.client.metadata.TypeDataStore;
  34. import com.vaadin.terminal.gwt.widgetsetutils.metadata.ConnectorBundle;
  35. import com.vaadin.terminal.gwt.widgetsetutils.metadata.ConnectorInitVisitor;
  36. import com.vaadin.terminal.gwt.widgetsetutils.metadata.TypeVisitor;
  37. public class ConnectorBundleLoaderFactory extends Generator {
  38. @Override
  39. public String generate(TreeLogger logger, GeneratorContext context,
  40. String typeName) throws UnableToCompleteException {
  41. TypeOracle typeOracle = context.getTypeOracle();
  42. try {
  43. JClassType classType = typeOracle.getType(typeName);
  44. String packageName = classType.getPackage().getName();
  45. String className = classType.getSimpleSourceName() + "Impl";
  46. generateClass(logger, context, packageName, className, typeName);
  47. return packageName + "." + className;
  48. } catch (UnableToCompleteException e) {
  49. // Just rethrow
  50. throw e;
  51. } catch (Exception e) {
  52. logger.log(Type.ERROR, getClass() + " failed", e);
  53. throw new UnableToCompleteException();
  54. }
  55. }
  56. private void generateClass(TreeLogger logger, GeneratorContext context,
  57. String packageName, String className, String requestedType)
  58. throws Exception {
  59. PrintWriter printWriter = context.tryCreate(logger, packageName,
  60. className);
  61. if (printWriter == null) {
  62. return;
  63. }
  64. List<ConnectorBundle> bundles = buildBundles(logger,
  65. context.getTypeOracle());
  66. ClassSourceFileComposerFactory composer = new ClassSourceFileComposerFactory(
  67. packageName, className);
  68. composer.setSuperclass(requestedType);
  69. SourceWriter w = composer.createSourceWriter(context, printWriter);
  70. w.println("public void init() {");
  71. w.indent();
  72. for (ConnectorBundle bundle : bundles) {
  73. String name = bundle.getName();
  74. boolean isEager = name
  75. .equals(ConnectorBundleLoader.EAGER_BUNDLE_NAME);
  76. w.print("addAsyncBlockLoader(new AsyncBundleLoader(\"");
  77. w.print(escape(name));
  78. w.print("\", ");
  79. w.print("new String[] {");
  80. for (Entry<JClassType, Set<String>> entry : bundle.getIdentifiers()
  81. .entrySet()) {
  82. Set<String> identifiers = entry.getValue();
  83. for (String id : identifiers) {
  84. w.print("\"");
  85. w.print(escape(id));
  86. w.print("\",");
  87. }
  88. }
  89. w.println("}) {");
  90. w.indent();
  91. w.print("protected void load(final ");
  92. w.print(TypeDataStore.class.getName());
  93. w.println(" store) {");
  94. w.indent();
  95. if (!isEager) {
  96. w.print(GWT.class.getName());
  97. w.print(".runAsync(");
  98. }
  99. w.print("new ");
  100. w.print(TypeDataBundle.class.getName());
  101. w.println("(getName()) {");
  102. w.indent();
  103. w.println("public void load() {");
  104. w.indent();
  105. printBundleData(w, bundle);
  106. // Close load method
  107. w.outdent();
  108. w.println("}");
  109. // Close new TypeDataBundle() {}
  110. w.outdent();
  111. w.print("}");
  112. if (isEager) {
  113. w.println(".onSuccess();");
  114. } else {
  115. w.println(");");
  116. }
  117. // Close load method
  118. w.outdent();
  119. w.println("}");
  120. // Close add(new ...
  121. w.outdent();
  122. w.println("});");
  123. }
  124. w.outdent();
  125. w.println("}");
  126. w.commit(logger);
  127. }
  128. private void printBundleData(SourceWriter w, ConnectorBundle bundle) {
  129. writeIdentifiers(w, bundle);
  130. writeGwtConstructors(w, bundle);
  131. }
  132. private void writeGwtConstructors(SourceWriter w, ConnectorBundle bundle) {
  133. Set<JClassType> constructors = bundle.getGwtConstructors();
  134. for (JClassType type : constructors) {
  135. w.print("store.setConstructor(");
  136. printClassLiteral(w, type);
  137. w.print(", new Invoker() {");
  138. w.indent();
  139. w.println("public Object invoke(Object target, Object[] params) {");
  140. w.indent();
  141. w.print("return ");
  142. w.print(GWT.class.getName());
  143. w.print(".create(");
  144. printClassLiteral(w, type);
  145. w.println(");");
  146. w.outdent();
  147. w.println("}");
  148. w.outdent();
  149. w.println("});");
  150. }
  151. }
  152. private void printClassLiteral(SourceWriter w, JClassType type) {
  153. w.print(type.getQualifiedSourceName());
  154. w.print(".class");
  155. }
  156. private void writeIdentifiers(SourceWriter w, ConnectorBundle bundle) {
  157. Map<JClassType, Set<String>> identifiers = bundle.getIdentifiers();
  158. for (Entry<JClassType, Set<String>> entry : identifiers.entrySet()) {
  159. Set<String> ids = entry.getValue();
  160. JClassType type = entry.getKey();
  161. for (String id : ids) {
  162. w.print("store.setClass(\"");
  163. w.print(escape(id));
  164. w.print("\", ");
  165. printClassLiteral(w, type);
  166. w.println(");");
  167. }
  168. }
  169. }
  170. private List<ConnectorBundle> buildBundles(TreeLogger logger,
  171. TypeOracle typeOracle) throws NotFoundException {
  172. Map<LoadStyle, Collection<JClassType>> connectorsByLoadStyle = new HashMap<LoadStyle, Collection<JClassType>>();
  173. for (LoadStyle loadStyle : LoadStyle.values()) {
  174. connectorsByLoadStyle.put(loadStyle, new ArrayList<JClassType>());
  175. }
  176. JClassType connectorType = typeOracle.getType(ServerConnector.class
  177. .getName());
  178. JClassType[] subtypes = connectorType.getSubtypes();
  179. for (JClassType connectorSubtype : subtypes) {
  180. if (!connectorSubtype.isAnnotationPresent(Connect.class)) {
  181. continue;
  182. }
  183. LoadStyle loadStyle = getLoadStyle(connectorSubtype);
  184. if (loadStyle != null) {
  185. connectorsByLoadStyle.get(loadStyle).add(connectorSubtype);
  186. }
  187. }
  188. List<ConnectorBundle> bundles = new ArrayList<ConnectorBundle>();
  189. Collection<TypeVisitor> visitors = getVisitors(typeOracle);
  190. ConnectorBundle eagerBundle = new ConnectorBundle(
  191. ConnectorBundleLoader.EAGER_BUNDLE_NAME, null);
  192. // Eager connectors and all RPC interfaces are loaded by default
  193. eagerBundle.visitTypes(connectorsByLoadStyle.get(LoadStyle.EAGER),
  194. visitors);
  195. eagerBundle.visitSubTypes(
  196. typeOracle.getType(ClientRpc.class.getName()), visitors);
  197. eagerBundle.visitSubTypes(
  198. typeOracle.getType(ServerRpc.class.getName()), visitors);
  199. bundles.add(eagerBundle);
  200. ConnectorBundle deferredBundle = new ConnectorBundle(
  201. ConnectorBundleLoader.DEFERRED_BUNDLE_NAME, eagerBundle);
  202. deferredBundle.visitTypes(
  203. connectorsByLoadStyle.get(LoadStyle.DEFERRED), visitors);
  204. bundles.add(deferredBundle);
  205. Collection<JClassType> lazy = connectorsByLoadStyle.get(LoadStyle.LAZY);
  206. for (JClassType type : lazy) {
  207. ConnectorBundle bundle = new ConnectorBundle(type.getName(),
  208. deferredBundle);
  209. bundle.visitTypes(Collections.singleton(type), visitors);
  210. bundles.add(bundle);
  211. }
  212. return bundles;
  213. }
  214. private Collection<TypeVisitor> getVisitors(TypeOracle oracle)
  215. throws NotFoundException {
  216. List<TypeVisitor> visitors = Arrays
  217. .<TypeVisitor> asList(new ConnectorInitVisitor());
  218. for (TypeVisitor typeVisitor : visitors) {
  219. typeVisitor.init(oracle);
  220. }
  221. return visitors;
  222. }
  223. protected LoadStyle getLoadStyle(JClassType connectorType) {
  224. Connect annotation = connectorType.getAnnotation(Connect.class);
  225. return annotation.loadStyle();
  226. }
  227. }