/** * Checks type and its supertypes for {@link ExtraTypes} annotations. * * @param type the type to examine * @param addModelExtraTypes if {@code true} the contents of the {@link #extraTypes} field will be * added to the returned list. */ private List<EntityProxyModel> checkExtraTypes(JClassType type, boolean addModelExtraTypes) throws UnableToCompleteException { Set<EntityProxyModel> toReturn = new LinkedHashSet<EntityProxyModel>(); if (addModelExtraTypes && extraTypes != null) { toReturn.addAll(extraTypes); } for (JClassType toExamine : type.getFlattenedSupertypeHierarchy()) { ExtraTypes proxyExtraTypes = toExamine.getAnnotation(ExtraTypes.class); if (proxyExtraTypes != null) { for (Class<? extends BaseProxy> clazz : proxyExtraTypes.value()) { JClassType proxy = oracle.findType(clazz.getCanonicalName()); if (proxy == null) { poison( "Unknown class %s in @%s", clazz.getCanonicalName(), ExtraTypes.class.getSimpleName()); } else { toReturn.add(getEntityProxyType(proxy)); } } } } if (toReturn.isEmpty()) { return Collections.emptyList(); } return new ArrayList<EntityProxyModel>(toReturn); }
@Override public String generate(TreeLogger logger, GeneratorContext context, String typeName) throws UnableToCompleteException { this.logger = logger; typeOracle = context.getTypeOracle(); try { // find XulEventSource implementors implementingTypes = new ArrayList<JClassType>(); JClassType eventSourceType = typeOracle.getType("org.pentaho.ui.xul.XulEventSource"); for (JClassType type : typeOracle.getTypes()) { if (type.isAssignableTo(eventSourceType)) { implementingTypes.add(type); } } // get classType and save instance variables JClassType classType = typeOracle.getType(typeName); packageName = classType.getPackage().getName(); className = classType.getSimpleSourceName() + "Impl"; // Generate class source code generateClass(logger, context); } catch (Exception e) { // record to logger that Map generation threw an exception logger.log(TreeLogger.ERROR, "Error generating BindingContext!!!", e); } // return the fully qualifed name of the class generated return packageName + "." + className; }
@Override void toJS(FragmentGeneratorContext context) throws UnableToCompleteException { TreeLogger logger = context.parentLogger.branch( TreeLogger.DEBUG, "Writing function() wrapper for JSFunction", null); SourceWriter sw = context.sw; TypeOracle typeOracle = context.typeOracle; JClassType functionClass = context.returnType.isClassOrInterface(); if (functionClass.equals(typeOracle.findType(JSFunction.class.getName()))) { logger.log( TreeLogger.ERROR, "You must use a subinterface of JSFunction" + " so that the generator can extract a method signature.", null); throw new UnableToCompleteException(); } // This is to support the JSFunction having the same lifetime as the // JSFunction object without having to use GWT.create on every JSFunction // object as that would discourage anonymous classes. sw.print("("); sw.print(context.parameterName); // sw.print("[email protected]::exportedFunction || ("); sw.print(".@" + JSFunction.class.getName() + "::exportedFunction || ("); sw.print(context.parameterName); // sw.print("[email protected]::exportedFunction = "); sw.print(".@" + JSFunction.class.getName() + "::exportedFunction = "); writeFunctionForMethod(context, findExportedMethod(logger, functionClass)); sw.print("))"); }
private static Map<JType, JClassType> findCustomSerializers(TypeOracle oracle) throws NotFoundException { Map<JType, JClassType> serializers = new HashMap<JType, JClassType>(); JClassType serializerInterface = oracle.findType(JSONSerializer.class.getName()); JType[] deserializeParamTypes = new JType[] { oracle.findType(com.vaadin.client.metadata.Type.class.getName()), oracle.findType(JSONValue.class.getName()), oracle.findType(ApplicationConnection.class.getName()) }; String deserializeMethodName = "deserialize"; // Just test that the method exists serializerInterface.getMethod(deserializeMethodName, deserializeParamTypes); for (JClassType serializer : serializerInterface.getSubtypes()) { JMethod deserializeMethod = serializer.findMethod(deserializeMethodName, deserializeParamTypes); if (deserializeMethod == null) { continue; } JType returnType = deserializeMethod.getReturnType(); serializers.put(returnType, serializer); } return serializers; }
// BEGIN MODIFICATION private FieldManager getFieldManager( TypeOracle oracle, MortalLogger logger, PropertyOracle propertyOracle, boolean useLazyWidgetBuilder) throws UnableToCompleteException { // Find ginjector FieldManager fieldManager; try { String ginjectorClassName = propertyOracle.getConfigurationProperty("gin.ginjector").getValues().get(0); JClassType ginjectorClass = oracle.findType(ginjectorClassName); if (ginjectorClass == null || !ginjectorClass.isAssignableTo(oracle.findType(Ginjector.class.getCanonicalName()))) { logger.die( "The configuration property 'gin.ginjector' is '%s' " + " which doesn't identify a type inheriting from 'Ginjector'.", ginjectorClassName); } fieldManager = new GinFieldManager(oracle, logger, ginjectorClass, useLazyWidgetBuilder); } catch (BadPropertyValueException e) { logger.warn( "The configuration property 'gin.ginjector' was not found, it is required to use " + "gin injection for UiBinder fields. If you don't need this consider using " + "UiBinder.gwt.xml instead of GinUiBinder.gwt.xml in your module."); fieldManager = new FieldManager(oracle, logger, useLazyWidgetBuilder); } return fieldManager; }
@Override public String interpretElement(XMLElement elem) throws UnableToCompleteException { if (!uiWriter.isWidgetElement(elem)) { return super.interpretElement(elem); } JClassType type = uiWriter.findFieldType(elem); TypeOracle oracle = uiWriter.getOracle(); MessagesWriter mw = uiWriter.getMessages(); String name = mw.consumeMessageAttribute("ph", elem); if ("".equals(name)) { name = "widget" + (++serial); } String idHolder = uiWriter.declareDomIdHolder(null); idToWidgetElement.put(idHolder, elem); if (oracle.findType(HasHTML.class.getName()).isAssignableFrom(type)) { return handleHasHTMLPlaceholder(elem, name, idHolder); } if (oracle.findType(HasText.class.getName()).isAssignableFrom(type)) { return handleHasTextPlaceholder(elem, name, idHolder); } return handleOpaqueWidgetPlaceholder(elem, name, idHolder); }
/** Implement additional methods defined in {@link AbstractUiCommonModelEditorDriver} */ @Override protected void writeAdditionalContent( TreeLogger logger, GeneratorContext context, EditorModel model, SourceWriter sw) throws UnableToCompleteException { TypeOracle typeOracle = context.getTypeOracle(); baseModelType = eraseType( typeOracle.findType("org.ovirt.engine.ui.uicommonweb.models.Model")); // $NON-NLS-1$ entityModelType = eraseType( typeOracle.findType( "org.ovirt.engine.ui.uicommonweb.models.EntityModel")); //$NON-NLS-1$ listModelType = eraseType( typeOracle.findType("org.ovirt.engine.ui.uicommonweb.models.ListModel")); // $NON-NLS-1$ hasCleanupType = eraseType(typeOracle.findType("org.ovirt.engine.ui.uicommonweb.HasCleanup")); // $NON-NLS-1$ this.logger = logger; this.model = model; this.sw = sw; logger.log(Type.DEBUG, "Starting to write additional Driver code"); // $NON-NLS-1$ writeListenerMap(); writeEventMap(); writeOwnerModels(); writeCleanup(); }
/** * Erases the {@link MetaClassFactory} cache, then populates it with types discovered via GWT's * TypeOracle. The reason for the initial flush of the MetaClassFactory is to support hot redeploy * in Dev Mode. The reason for doing this operation at all is so that the overridden class * definitions (super-source classes) are used in preference to the Java reflection based class * definitions. * * @param context The GeneratorContext supplied by the GWT compiler. Not null. * @param logger The TreeLogger supplied by the GWT compiler. Not null. */ public static void populateMetaClassFactoryFromTypeOracle( final GeneratorContext context, final TreeLogger logger) { // if we're in production mode -- it means we're compiling, and we do not need to accommodate // dynamically // changing classes. Therefore, do a NOOP after the first successful call. if (typeOraclePopulated && (context.equals(populatedFrom.get()) || EnvUtil.isProdMode())) { return; } final TypeOracle typeOracle = context.getTypeOracle(); MetaClassFactory.emptyCache(); if (typeOracle != null) { final Set<String> translatable = new HashSet<String>(RebindUtils.findTranslatablePackages(context)); translatable.remove("java.lang"); translatable.remove("java.lang.annotation"); for (final JClassType type : typeOracle.getTypes()) { if (!translatable.contains(type.getPackage().getName())) { logger.log( com.google.gwt.core.ext.TreeLogger.Type.DEBUG, "Skipping non-translatable " + type.getQualifiedSourceName()); continue; } if (type.isAnnotation() != null || type.getQualifiedSourceName().equals("java.lang.annotation.Annotation")) { logger.log( com.google.gwt.core.ext.TreeLogger.Type.DEBUG, "Caching annotation type " + type.getQualifiedSourceName()); if (!MetaClassFactory.canLoadClass(type.getQualifiedBinaryName())) { throw new RuntimeException( "a new annotation has been introduced (" + type.getQualifiedSourceName() + "); " + "you cannot currently introduce new annotations in devmode. Please restart."); } MetaClassFactory.pushCache( JavaReflectionClass.newUncachedInstance( MetaClassFactory.loadClass(type.getQualifiedBinaryName()))); } else { logger.log( com.google.gwt.core.ext.TreeLogger.Type.DEBUG, "Caching translatable type " + type.getQualifiedSourceName()); MetaClassFactory.pushCache(GWTClass.newInstance(typeOracle, type)); } } } typeOraclePopulated = true; populatedFrom = new SoftReference<GeneratorContext>(context); }
/** * Add the implicit root types that are needed to make RPC work. These would be {@link String} and * {@link IncompatibleRemoteServiceException}. */ private static void addRequiredRoots( TreeLogger logger, TypeOracle typeOracle, SerializableTypeOracleBuilder stob) throws NotFoundException { logger = logger.branch(TreeLogger.DEBUG, "Analyzing implicit types"); // String is always instantiable. JClassType stringType = typeOracle.getType(String.class.getName()); stob.addRootType(logger, stringType); // IncompatibleRemoteServiceException is always serializable JClassType icseType = typeOracle.getType(IncompatibleRemoteServiceException.class.getName()); stob.addRootType(logger, icseType); }
public RequestFactoryModel(TreeLogger logger, JClassType factoryType) throws UnableToCompleteException { this.logger = logger; this.factoryType = factoryType; this.oracle = factoryType.getOracle(); collectionInterface = oracle.findType(Collection.class.getCanonicalName()); entityProxyInterface = oracle.findType(EntityProxy.class.getCanonicalName()); instanceRequestInterface = oracle.findType(InstanceRequest.class.getCanonicalName()); listInterface = oracle.findType(List.class.getCanonicalName()); mapInterface = oracle.findType(Map.class.getCanonicalName()); requestContextInterface = oracle.findType(RequestContext.class.getCanonicalName()); requestFactoryInterface = oracle.findType(RequestFactory.class.getCanonicalName()); requestInterface = oracle.findType(Request.class.getCanonicalName()); setInterface = oracle.findType(Set.class.getCanonicalName()); splittableType = oracle.findType(Splittable.class.getCanonicalName()); valueProxyInterface = oracle.findType(ValueProxy.class.getCanonicalName()); extraTypes = checkExtraTypes(factoryType, false); for (JMethod method : factoryType.getOverridableMethods()) { if (method.getEnclosingType().equals(requestFactoryInterface)) { // Ignore methods defined an RequestFactory itself continue; } if (method.getParameters().length > 0) { poison("Unexpected parameter on method %s", method.getName()); continue; } JClassType contextType = method.getReturnType().isInterface(); if (contextType == null || !requestContextInterface.isAssignableFrom(contextType)) { poison( "Unexpected return type %s on method %s is not" + " an interface assignable to %s", method.getReturnType().getQualifiedSourceName(), method.getName(), requestContextInterface.getSimpleSourceName()); continue; } ContextMethod.Builder builder = new ContextMethod.Builder(); builder.setDeclaredMethod(method); buildContextMethod(builder, contextType); contextMethods.add(builder.build()); } if (poisoned) { die(poisonedMessage()); } }
public static MetaClass newInstance(final TypeOracle oracle, final String type) { try { return newUncachedInstance(oracle, oracle.getType(type)); } catch (NotFoundException e) { return null; } }
private JType getIntType(TypeOracle oracle) { try { return oracle.parse("int"); } catch (TypeOracleException e) { throw new RuntimeException(e); } }
public void testDashesMatchesCamels() { JClassType stringType = types.findType("java.lang.String"); JClassType cssResourceType = stringType; // TODO(rjrjr) get real someday ImplicitCssResource css = new ImplicitCssResource( "package", "ClassName", "fieldName", new String[] {}, cssResourceType, ".ableBaker {}", MortalLogger.NULL, Collections.<JClassType>emptySet()); FieldWriterOfGeneratedCssResource f = new FieldWriterOfGeneratedCssResource(stringType, css, MortalLogger.NULL); assertEquals( stringType, f.getReturnType( new String[] {"fieldName", "able-baker"}, new MonitoredLogger(MortalLogger.NULL))); assertEquals(FieldWriterType.GENERATED_CSS, f.getFieldType()); }
protected void generateCheckRpcTokenTypeOverride( SourceWriter srcWriter, TypeOracle typeOracle, SerializableTypeOracle typesSentFromBrowser) { JClassType rpcTokenType = typeOracle.findType(RpcToken.class.getName()); JClassType[] rpcTokenSubtypes = rpcTokenType.getSubtypes(); String rpcTokenImplementation = ""; for (JClassType rpcTokenSubtype : rpcTokenSubtypes) { if (typesSentFromBrowser.isSerializable(rpcTokenSubtype)) { if (rpcTokenImplementation.length() > 0) { // >1 implematation of RpcToken, bail rpcTokenImplementation = ""; break; } else { rpcTokenImplementation = rpcTokenSubtype.getQualifiedSourceName(); } } } if (rpcTokenImplementation.length() > 0) { srcWriter.println("@Override"); srcWriter.println("protected void checkRpcTokenType(RpcToken token) {"); srcWriter.indent(); srcWriter.println("if (!(token instanceof " + rpcTokenImplementation + ")) {"); srcWriter.indent(); srcWriter.println( "throw new RpcTokenException(\"Invalid RpcToken type: " + "expected '" + rpcTokenImplementation + "' but got '\" + " + "token.getClass() + \"'\");"); srcWriter.outdent(); srcWriter.println("}"); srcWriter.outdent(); srcWriter.println("}"); } }
private JClassType getType(TypeOracle oracle, Class cls) { try { return oracle.getType(cls.getName()); } catch (NotFoundException e) { throw new RuntimeException(e); } }
@Override public MetaClass asArrayOf(final int dimensions) { JType type = getEnclosedMetaObject(); for (int i = 0; i < dimensions; i++) { type = oracle.getArrayType(type); } return new GWTClass(oracle, type, false); }
@Override public String generate(TreeLogger logger, GeneratorContext genCtx, String fqInterfaceName) throws UnableToCompleteException { TypeOracle oracle = genCtx.getTypeOracle(); ResourceOracle resourceOracle = genCtx.getResourcesOracle(); JClassType interfaceType; try { interfaceType = oracle.getType(fqInterfaceName); } catch (NotFoundException e) { throw new RuntimeException(e); } DesignTimeUtils designTime; if (DesignTimeUtilsImpl.isDesignTime(fqInterfaceName)) { designTime = new DesignTimeUtilsImpl(); } else { designTime = DesignTimeUtilsStub.EMPTY; } String implName = interfaceType.getName().replace('.', '_') + "Impl"; implName = designTime.getImplName(implName); String packageName = interfaceType.getPackage().getName(); PrintWriterManager writers = new PrintWriterManager(genCtx, logger, packageName); PrintWriter printWriter = writers.tryToMakePrintWriterFor(implName); if (printWriter != null) { generateOnce( interfaceType, implName, printWriter, logger, oracle, resourceOracle, genCtx.getPropertyOracle(), writers, designTime); } return packageName + "." + implName; }
/** * Generate an implementation for the given type. * * @param logger error logger * @param context generator context * @param typeName target type name * @return generated class name * @throws UnableToCompleteException */ @Override public final String generate(TreeLogger logger, GeneratorContext context, String typeName) throws UnableToCompleteException { assert CURRENCY_LIST.equals(typeName); TypeOracle typeOracle = context.getTypeOracle(); PropertyOracle propertyOracle = context.getPropertyOracle(); LocaleUtils localeUtils = LocaleUtils.getInstance(logger, propertyOracle, context); GwtLocale locale = localeUtils.getCompileLocale(); Set<GwtLocale> runtimeLocales = localeUtils.getRuntimeLocales(); JClassType targetClass; try { targetClass = typeOracle.getType(typeName); } catch (NotFoundException e) { logger.log(TreeLogger.ERROR, "No such type", e); throw new UnableToCompleteException(); } if (runtimeLocales.isEmpty()) { return generateLocaleTree(logger, context, targetClass, locale); } CachedGeneratorContext cachedContext = new CachedGeneratorContext(context); return generateRuntimeSelection(logger, cachedContext, targetClass, locale, runtimeLocales); }
private Set<BeanResolver> getFileDeclaredTypes(TreeLogger logger, TypeOracle oralce) throws UnableToCompleteException { HashSet<BeanResolver> results = new HashSet<BeanResolver>(); ClassLoader ctxLoader = Thread.currentThread().getContextClassLoader(); try { Enumeration<URL> introspections = ctxLoader.getResources("gwittir-introspection.properties"); while (introspections.hasMoreElements()) { URL propsUrl = introspections.nextElement(); logger.log(TreeLogger.Type.INFO, "Loading: " + propsUrl.toString()); Properties props = new Properties(); props.load(propsUrl.openStream()); for (Entry entry : props.entrySet()) { String className = entry.getKey().toString(); String[] includedProps = entry.getValue().toString().split(","); JClassType type = oralce.findType(className); if (type == null) { logger.log( TreeLogger.Type.ERROR, "Unable to find type " + className + " declared in " + propsUrl); throw new UnableToCompleteException(); } results.add(new BeanResolver(logger, type, includedProps)); } } } catch (IOException ioe) { logger.log(TreeLogger.Type.WARN, "Exception looking for properties files", ioe); } return results; }
@Override public String generate(TreeLogger logger, GeneratorContext context, String typeName) throws UnableToCompleteException { TypeOracle oracle = context.getTypeOracle(); // JClassType requestQueue = oracle.findType(RequestQueue.class.getName()); JClassType toGenerate = oracle.findType(typeName); if (toGenerate == null) { logger.log(TreeLogger.ERROR, typeName + " is not an interface type"); throw new UnableToCompleteException(); } String packageName = toGenerate.getPackage().getName(); String simpleSourceName = toGenerate.getName().replace('.', '_') + "_Impl"; PrintWriter pw = context.tryCreate(logger, packageName, simpleSourceName); if (pw == null) { return packageName + "." + simpleSourceName; } ClassSourceFileComposerFactory factory = new ClassSourceFileComposerFactory(packageName, simpleSourceName); factory.setSuperclass(AbstractRequestQueueImpl.class.getName()); factory.addImplementedInterface(typeName); SourceWriter sw = factory.createSourceWriter(context, pw); // Collect async services we need to provide access to, and the rpc calls they'll make RequestQueueModel model = collectModel(logger.branch(Type.DEBUG, "Collecting service info"), context, toGenerate); // Build a pair of RPC interfaces for serialization String realRpcInterfaceName = buildRpcInterfaces(logger.branch(Type.DEBUG, "Writing RPC interfaces"), context, model); // Build the getRealService() method String serviceQueueAsync = ServiceQueueBaseAsync.class.getName(); sw.println("public %1$s getRealService() {", serviceQueueAsync); sw.indentln( "return %3$s.<%1$s>create(%2$s.class);", serviceQueueAsync, realRpcInterfaceName, GWT.class.getName()); sw.println("}"); // Build the methods (and maybe types?) that call addRequest() for (AsyncServiceModel service : model.getServices()) { sw.println( "public %1$s %2$s() {", service.getAsyncServiceInterfaceName(), service.getDeclaredMethodName()); sw.indent(); sw.println("return new %1$s() {", service.getAsyncServiceInterfaceName()); sw.indent(); for (AsyncServiceMethodModel method : service.getMethods()) { sw.println("public void %1$s(", method.getMethodName()); StringBuilder argList = new StringBuilder(); StringBuilder types = new StringBuilder("new String[]{"); for (int i = 0; i < method.getArgTypes().size(); i++) { if (i != 0) { sw.print(", "); argList.append(", "); types.append(", "); } JType arg = method.getArgTypes().get(i); sw.print("%1$s arg%2$d", arg.getParameterizedQualifiedSourceName(), i); argList.append("arg").append(i); types.append("\"").append(escape(SerializationUtils.getRpcTypeName(arg))).append("\""); } types.append("}"); if (method.hasCallback()) { if (method.getArgTypes().size() != 0) { sw.print(", "); } sw.print( "%1$s<%2$s> callback", AsyncCallback.class.getName(), method.getReturnTypeName()); } sw.println(") {"); sw.indent(); sw.println( "addRequest(\"%1$s\", \"%2$s\",\n%3$s,\n", escape(service.getServiceName()), escape(method.getMethodName()), types.toString()); if (method.hasCallback()) { sw.indentln("callback,"); } else { sw.indentln("null,"); } sw.indentln("new Object[]{%1$s});", argList.toString()); sw.outdent(); sw.println("}"); } sw.outdent(); sw.println("};"); sw.outdent(); sw.println("}"); } sw.commit(logger); return factory.getCreatedClassName(); }
@Override public String generate(TreeLogger logger, GeneratorContext context, String typeName) throws UnableToCompleteException { // make sure it is an interface TypeOracle oracle = context.getTypeOracle(); propertyAccessInterface = oracle.findType(Name.getSourceNameForClass(PropertyAccess.class)); modelKeyProviderInterface = oracle.findType(Name.getSourceNameForClass(ModelKeyProvider.class)); valueProviderInterface = oracle.findType(Name.getSourceNameForClass(ValueProvider.class)); labelProviderInterface = oracle.findType(Name.getSourceNameForClass(LabelProvider.class)); JClassType toGenerate = oracle.findType(typeName).isInterface(); if (toGenerate == null) { logger.log(TreeLogger.ERROR, typeName + " is not an interface type"); throw new UnableToCompleteException(); } if (!toGenerate.isAssignableTo(propertyAccessInterface)) { logger.log(Type.ERROR, "This isn't a PropertyAccess subtype..."); throw new UnableToCompleteException(); } // Get the name of the new type String packageName = toGenerate.getPackage().getName(); String simpleSourceName = toGenerate.getName().replace('.', '_') + "Impl"; PrintWriter pw = context.tryCreate(logger, packageName, simpleSourceName); if (pw == null) { return packageName + "." + simpleSourceName; } // start making the class, with basic imports ClassSourceFileComposerFactory factory = new ClassSourceFileComposerFactory(packageName, simpleSourceName); factory.addImplementedInterface(typeName); SourceWriter sw = factory.createSourceWriter(context, pw); // for each method, for (JMethod m : toGenerate.getOverridableMethods()) { TreeLogger l = logger.branch(Type.DEBUG, "Building method: " + m.getReadableDeclaration()); // no support for params at this time if (m.getParameters().length != 0) { l.log(Type.ERROR, "Method " + m.toString() + " must not have parameters."); throw new UnableToCompleteException(); } // ask for the types that provide the property data JClassType ret = m.getReturnType().isClassOrInterface(); final AbstractCreator c; if (ret.isAssignableTo(valueProviderInterface)) { c = new ValueProviderCreator(context, l, m); } else if (ret.isAssignableTo(modelKeyProviderInterface)) { c = new ModelKeyProviderCreator(context, l, m); } else if (ret.isAssignableTo(labelProviderInterface)) { c = new LabelProviderCreator(context, l, m); } else { logger.log(Type.ERROR, "Method uses a return type that cannot be generated"); throw new UnableToCompleteException(); } c.create(); // build the method // public ValueProvider<T, V> name() { return NameValueProvider.instance; // } sw.println("public %1$s %2$s() {", m.getReturnType().getQualifiedSourceName(), m.getName()); sw.indentln("return %1$s;", c.getInstanceExpression()); sw.println("}"); } sw.commit(logger); return factory.getCreatedClassName(); }
/** Adds a root type for each type that appears in the RemoteService interface methods. */ private static void addRemoteServiceRootTypes( TreeLogger logger, TypeOracle typeOracle, SerializableTypeOracleBuilder typesSentFromBrowser, SerializableTypeOracleBuilder typesSentToBrowser, JClassType remoteService) throws NotFoundException, UnableToCompleteException { logger = logger.branch( TreeLogger.DEBUG, "Analyzing '" + remoteService.getParameterizedQualifiedSourceName() + "' for serializable types", null); JMethod[] methods = remoteService.getOverridableMethods(); JClassType exceptionClass = typeOracle.getType(Exception.class.getName()); JClassType rteType = typeOracle.getType(RpcTokenException.class.getName()); JClassType rpcTokenClass = typeOracle.getType(RpcToken.class.getName()); RpcTokenImplementation tokenClassToUse = remoteService.findAnnotationInTypeHierarchy(RpcTokenImplementation.class); if (tokenClassToUse != null) { // only include serializer for the specified class literal JClassType rpcTokenType = typeOracle.getType(tokenClassToUse.value()); if (rpcTokenType.isAssignableTo(rpcTokenClass)) { typesSentFromBrowser.addRootType(logger, rpcTokenType); typesSentToBrowser.addRootType(logger, rteType); } else { logger.branch( TreeLogger.ERROR, "RPC token class " + tokenClassToUse.value() + " must implement " + RpcToken.class.getName(), null); throw new UnableToCompleteException(); } } else { JClassType[] rpcTokenSubclasses = rpcTokenClass.getSubtypes(); for (JClassType rpcTokenSubclass : rpcTokenSubclasses) { typesSentFromBrowser.addRootType(logger, rpcTokenSubclass); } if (rpcTokenSubclasses.length > 0) { typesSentToBrowser.addRootType(logger, rteType); } } TreeLogger validationLogger = logger.branch(TreeLogger.DEBUG, "Analyzing methods:", null); for (JMethod method : methods) { TreeLogger methodLogger = validationLogger.branch(TreeLogger.DEBUG, method.toString(), null); JType returnType = method.getReturnType(); if (returnType != JPrimitiveType.VOID) { TreeLogger returnTypeLogger = methodLogger.branch( TreeLogger.DEBUG, "Return type: " + returnType.getParameterizedQualifiedSourceName(), null); typesSentToBrowser.addRootType(returnTypeLogger, returnType); } JParameter[] params = method.getParameters(); for (JParameter param : params) { TreeLogger paramLogger = methodLogger.branch(TreeLogger.DEBUG, "Parameter: " + param.toString(), null); JType paramType = param.getType(); typesSentFromBrowser.addRootType(paramLogger, paramType); } JType[] exs = method.getThrows(); if (exs.length > 0) { TreeLogger throwsLogger = methodLogger.branch(TreeLogger.DEBUG, "Throws:", null); for (JType ex : exs) { if (!exceptionClass.isAssignableFrom(ex.isClass())) { throwsLogger = throwsLogger.branch( TreeLogger.WARN, "'" + ex.getQualifiedSourceName() + "' is not a checked exception; only checked exceptions may be used", null); } typesSentToBrowser.addRootType(throwsLogger, ex); } } } }
protected List<BeanResolver> getIntrospectableTypes(TreeLogger logger, TypeOracle oracle) { ArrayList<BeanResolver> results = new ArrayList<BeanResolver>(); HashSet<BeanResolver> resolvers = new HashSet<BeanResolver>(); HashSet<String> found = new HashSet<String>(); try { JClassType[] types = oracle.getTypes(); for (JClassType type : types) { if (!found.contains(type.getQualifiedSourceName()) && isIntrospectable(logger, type) && (type.isInterface() == null)) { found.add(type.getQualifiedSourceName()); resolvers.add(new BeanResolver(logger, type)); } } // Do a crazy assed sort to make sure least // assignable types are at the bottom of the list results.addAll(resolvers); results.addAll(this.getFileDeclaredTypes(logger, oracle)); boolean swap = true; // .print("Ordering "+results.size()+" by heirarchy "); while (swap) { // .print("."); swap = false; for (int i = results.size() - 1; i >= 0; i--) { BeanResolver type = (BeanResolver) results.get(i); for (int j = i - 1; j >= 0; j--) { BeanResolver check = (BeanResolver) results.get(j); if (type.getType().isAssignableTo(check.getType())) { results.set(i, check); results.set(j, type); type = check; swap = true; } } } } // System.out.println(); } catch (Exception e) { logger.log(TreeLogger.ERROR, "Unable to finad Introspectable types.", e); } // for(BeanResolver rs:results){ // logger.log(TreeLogger.ERROR, rs.toString()); // } // System.out.println("Found "+results.size()+" introspectable types."); for (BeanResolver resolver : results) { logger.log( TreeLogger.Type.INFO, "Introspectable: " + resolver.getType().getQualifiedSourceName()); } logger.log(TreeLogger.Type.INFO, "Found introspectable types: " + results.size()); return results; }
/** * Creates the client-side proxy class. * * @throws UnableToCompleteException */ public String create(TreeLogger logger, GeneratorContextExt context) throws UnableToCompleteException { TypeOracle typeOracle = context.getTypeOracle(); JClassType serviceAsync = typeOracle.findType(serviceIntf.getQualifiedSourceName() + "Async"); if (serviceAsync == null) { logger.branch( TreeLogger.ERROR, "Could not find an asynchronous version for the service interface " + serviceIntf.getQualifiedSourceName(), null); RemoteServiceAsyncValidator.logValidAsyncInterfaceDeclaration(logger, serviceIntf); throw new UnableToCompleteException(); } SourceWriter srcWriter = getSourceWriter(logger, context, serviceAsync); if (srcWriter == null) { return getProxyQualifiedName(); } // Make sure that the async and synchronous versions of the RemoteService // agree with one another // RemoteServiceAsyncValidator rsav = new RemoteServiceAsyncValidator(logger, typeOracle); Map<JMethod, JMethod> syncMethToAsyncMethMap = rsav.validate(logger, serviceIntf, serviceAsync); final PropertyOracle propertyOracle = context.getPropertyOracle(); // Load the blacklist/whitelist TypeFilter blacklistTypeFilter = new BlacklistTypeFilter(logger, propertyOracle); // Determine the set of serializable types Event event = SpeedTracerLogger.start(CompilerEventType.GENERATOR_RPC_STOB); SerializableTypeOracleBuilder typesSentFromBrowserBuilder = new SerializableTypeOracleBuilder(logger, propertyOracle, context); typesSentFromBrowserBuilder.setTypeFilter(blacklistTypeFilter); SerializableTypeOracleBuilder typesSentToBrowserBuilder = new SerializableTypeOracleBuilder(logger, propertyOracle, context); typesSentToBrowserBuilder.setTypeFilter(blacklistTypeFilter); addRoots(logger, typeOracle, typesSentFromBrowserBuilder, typesSentToBrowserBuilder); try { ConfigurationProperty prop = context .getPropertyOracle() .getConfigurationProperty(TypeSerializerCreator.GWT_ELIDE_TYPE_NAMES_FROM_RPC); elideTypeNames = Boolean.parseBoolean(prop.getValues().get(0)); } catch (BadPropertyValueException e) { logger.log( TreeLogger.ERROR, "Configuration property " + TypeSerializerCreator.GWT_ELIDE_TYPE_NAMES_FROM_RPC + " is not defined. Is RemoteService.gwt.xml inherited?"); throw new UnableToCompleteException(); } // Decide what types to send in each direction. // Log the decisions to a string that will be written later in this method SerializableTypeOracle typesSentFromBrowser; SerializableTypeOracle typesSentToBrowser; String rpcLog; { StringWriter stringWriter = new StringWriter(); PrintWriter writer = new PrintWriter(stringWriter); typesSentFromBrowserBuilder.setLogOutputWriter(writer); typesSentToBrowserBuilder.setLogOutputWriter(writer); writer.write("====================================\n"); writer.write("Types potentially sent from browser:\n"); writer.write("====================================\n\n"); writer.flush(); typesSentFromBrowser = typesSentFromBrowserBuilder.build(logger); writer.write("===================================\n"); writer.write("Types potentially sent from server:\n"); writer.write("===================================\n\n"); writer.flush(); typesSentToBrowser = typesSentToBrowserBuilder.build(logger); writer.close(); rpcLog = stringWriter.toString(); } event.end(); generateTypeHandlers(logger, context, typesSentFromBrowser, typesSentToBrowser); String serializationPolicyStrongName = writeSerializationPolicyFile(logger, context, typesSentFromBrowser, typesSentToBrowser); String remoteServiceInterfaceName = elideTypeNames ? TypeNameObfuscator.SERVICE_INTERFACE_ID : SerializationUtils.getRpcTypeName(serviceIntf); generateProxyFields( srcWriter, typesSentFromBrowser, serializationPolicyStrongName, remoteServiceInterfaceName); generateProxyContructor(srcWriter); generateProxyMethods(srcWriter, typesSentFromBrowser, typeOracle, syncMethToAsyncMethMap); generateStreamWriterOverride(srcWriter); generateCheckRpcTokenTypeOverride(srcWriter, typeOracle, typesSentFromBrowser); srcWriter.commit(logger); if (context.isProdMode() || logger.isLoggable(TreeLogger.DEBUG)) { // Create an artifact explaining STOB's decisions. It will be emitted by // RpcLogLinker context.commitArtifact( logger, new RpcLogArtifact( serviceIntf.getQualifiedSourceName(), serializationPolicyStrongName, rpcLog)); } return getProxyQualifiedName(); }
private void createFindMethod(SourceWriter sourceWriter) { // We create more than one findMethod as the body of one method would be too large. This is the // int that we // increment to add to the name // i.e. findMethod0() int methodNum = 0; // This int keeps track of how many methods are generated. When it gets to 200 we create a new // findMethodX() // and chain it to the previous. int methodCount = 0; sourceWriter.println( "private GwtBindingMethod findOrCreateMethod(String obj, String methodName){ "); sourceWriter.indent(); sourceWriter.println("GwtBindingMethod newMethod;"); // dummy first condition, rest are "else if". Keeps us from having conditional logic. sourceWriter.println("if(false){ }"); for (JClassType type : implementingTypes) { // close last method, chain it to a new one. if (methodCount > 200) { sourceWriter.println("return findOrCreateMethod" + (methodNum) + "(obj, methodName);"); sourceWriter.println("}"); sourceWriter.println( "private GwtBindingMethod findOrCreateMethod" + (methodNum++) + "(String obj, String methodName){ "); sourceWriter.println("GwtBindingMethod newMethod;"); // dummy first condition, rest are "else if". Keeps us from having conditional logic. sourceWriter.println("if(false){ }"); methodCount = 0; } String keyRoot = generateTypeKey(type); // if(type.isAbstract()){ // System.out.println("abstract"); // continue; // } // determine if there are any methods that are bindable before writing out conditional for // class JClassType loopType = type; boolean hasBindableMethods = false; JClassType eventSourceType = null; try { eventSourceType = typeOracle.getType("org.pentaho.ui.xul.XulEventSource"); } catch (NotFoundException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } // CHECKSTYLE IGNORE Indentation FOR NEXT 1 LINES outer: while (loopType.getSuperclass() != null && loopType.getSimpleSourceName().equals("Object") == false && loopType.isAssignableTo(eventSourceType)) { for (JMethod m : loopType.getMethods()) { if (m.isPublic() && m.getAnnotation(Bindable.class) != null) { hasBindableMethods = true; break outer; } } loopType = loopType.getSuperclass(); } if (hasBindableMethods == false) { continue; } sourceWriter.println("else if(obj.equals(\"" + type.getQualifiedSourceName() + "\")){ "); try { loopType = type; sourceWriter.indent(); // Loop over class heirarchy and generate methods for every object that is declared a // XulEventSource while (loopType.getSuperclass() != null && loopType.getSimpleSourceName().equals("Object") == false && loopType.isAssignableTo(eventSourceType)) { String superName = generateTypeKey(loopType); boolean first = true; for (JMethod m : loopType.getMethods()) { methodCount++; if (!m.isPublic() || m.getAnnotation(Bindable.class) == null) { continue; } sourceWriter.println( (first ? "" : "else ") + "if(methodName.equals(\"" + m.getName() + "\")){ "); if (first) { first = false; } sourceWriter.indent(); String methodName = m.getName(); // check to see if we've already processed this classes' method. Point to that class // instead. if (generatedMethods.contains((superName + "_" + methodName).toLowerCase()) && type != loopType) { sourceWriter.println("return findOrCreateMethod(\"" + superName + "\", methodName);"); } else { // See if it's already been created and cached. If so, return that. String keyName = (keyRoot + "_" + methodName).toLowerCase(); sourceWriter.println( "GwtBindingMethod found = wrappedTypes.get(\"" + keyName + "\");"); sourceWriter.println("if(found != null){"); sourceWriter.indent(); sourceWriter.println("return found;"); sourceWriter.outdent(); sourceWriter.println("} else {"); sourceWriter.indent(); // Not cached, create a new instance and put it in the cache. sourceWriter.println("newMethod = new GwtBindingMethod(){"); sourceWriter.println( "public Object invoke(Object obj, Object[] args) throws XulException { "); sourceWriter.indent(); sourceWriter.println("try{"); sourceWriter.println( loopType.getQualifiedSourceName() + " target = (" + loopType.getQualifiedSourceName() + ") obj;"); JParameter[] params = m.getParameters(); String argList = ""; int pos = 0; for (JParameter param : params) { if (pos > 0) { argList += ", "; } argList += "(" + getTypeName(param.getType()) + ") args[" + pos + "]"; pos++; } if (isVoidReturn(m.getReturnType())) { sourceWriter.println("target." + methodName + "(" + argList + ");"); sourceWriter.println("return null;"); } else { sourceWriter.println( "return " + boxReturnType(m) + " target." + methodName + "(" + argList + ");"); } sourceWriter.println( "}catch(Exception e){ e.printStackTrace(); throw new XulException(\"error with " + type.getQualifiedSourceName() + "\"+e.getMessage());}"); sourceWriter.println("}"); sourceWriter.outdent(); sourceWriter.println("};"); // Add it to the HashMap cache as type and decendant type if available. sourceWriter.println("wrappedTypes.put((\"" + keyName + "\"), newMethod);"); if (keyRoot.equals(superName) == false) { sourceWriter.println("wrappedTypes.put((\"" + keyName + "\"), newMethod);"); } generatedMethods.add((keyRoot + "_" + methodName).toLowerCase()); generatedMethods.add((superName + "_" + methodName).toLowerCase()); sourceWriter.println("return newMethod;"); sourceWriter.outdent(); sourceWriter.println("}"); } sourceWriter.outdent(); sourceWriter.println("}"); } // go up a level in the heirarchy and check again. loopType = loopType.getSuperclass(); } sourceWriter.outdent(); sourceWriter.println("}"); } catch (Exception e) { // record to logger that Map generation threw an exception logger.log(TreeLogger.ERROR, "PropertyMap ERROR!!!", e); } } sourceWriter.outdent(); // This is the end of the line, if not found return null. sourceWriter.println("return null;"); sourceWriter.println("}"); }
private boolean hasDateTimeFormatConstructor(TypeOracle typeOracle, JClassType type) { JType dateTimeFormatType = typeOracle.findType(DateTimeFormat.class.getName()); return TypeOracleUtils.hasCompatibleConstructor(type, dateTimeFormatType); }
private RequestQueueModel collectModel( TreeLogger logger, GeneratorContext context, JClassType toGenerate) throws UnableToCompleteException { RequestQueueModel.Builder rqBuilder = new RequestQueueModel.Builder(); TypeOracle typeOracle = context.getTypeOracle(); JClassType requestQueue = typeOracle.findType(RequestQueue.class.getName()); JClassType asyncCallback = typeOracle.findType(AsyncCallback.class.getName()); JClassType voidType = typeOracle.findType(Void.class.getName()); rqBuilder.setRequestQueueInterfaceName(toGenerate.getParameterizedQualifiedSourceName()); AsyncServiceModel.Builder serviceBuilder = new AsyncServiceModel.Builder(); for (JMethod m : toGenerate.getMethods()) { TreeLogger serviceLogger = logger.branch(Type.DEBUG, "Reading async service " + m.getReadableDeclaration()); // Skip those defined at RequestQueue if (m.getEnclosingType().equals(requestQueue)) { continue; } JClassType returnType = m.getReturnType().isClassOrInterface(); if (returnType == null) { serviceLogger.log(Type.ERROR, "Unexpected method return type " + returnType); throw new UnableToCompleteException(); } serviceBuilder.setAsyncServiceInterfaceName(returnType.getParameterizedQualifiedSourceName()); serviceBuilder.setDeclaredMethodName(m.getName()); Service serviceAnnotation = m.getAnnotation(Service.class); if (serviceAnnotation == null) { serviceLogger.log(Type.ERROR, "Missing @Service annotation"); throw new UnableToCompleteException(); } serviceBuilder.setService(serviceAnnotation.value().getName()); AsyncServiceMethodModel.Builder methodBuilder = new AsyncServiceMethodModel.Builder(); for (JMethod asyncMethod : m.getReturnType().isClassOrInterface().getMethods()) { TreeLogger methodLogger = serviceLogger.branch( Type.DEBUG, "Reading service method " + asyncMethod.getReadableDeclaration()); List<JType> types = new ArrayList<JType>(); methodBuilder.setReturnTypeName(voidType.getParameterizedQualifiedSourceName()); boolean asyncFound = false; for (JType param : asyncMethod.getParameterTypes()) { if (asyncFound) { methodLogger.log( Type.WARN, "Already passed an AsyncCallback param - is that what you meant?"); } if (param.isClassOrInterface() != null && param.isClassOrInterface().isAssignableTo(asyncCallback)) { JClassType boxedReturnType = ModelUtils.findParameterizationOf(asyncCallback, param.isClassOrInterface())[0]; methodBuilder .setHasCallback(true) .setReturnTypeName(boxedReturnType.getParameterizedQualifiedSourceName()); asyncFound = true; continue; // should be last, check for this... } types.add(param); } Set<JClassType> throwables = new HashSet<JClassType>(); Throws t = asyncMethod.getAnnotation(Throws.class); if (t != null) { for (Class<? extends Throwable> throwable : t.value()) { throwables.add(typeOracle.findType(throwable.getName())); } } methodBuilder .setMethodName(asyncMethod.getName()) .setArgTypes(types) .setThrowables(throwables); serviceBuilder.addMethod(methodBuilder.build()); } rqBuilder.addService(serviceBuilder.build()); } return rqBuilder.build(); }