/** * Writes a method to produce a map of class name to type string for Java. * * <pre> * private static Map<String<?>, String> loadSignaturesJava() { * Map<String<?>, String> result = new HashMap<String<?>, String>(); * result.put( * com.google.gwt.user.client.rpc.core.java.lang.String_FieldSerializer.concreteType(), * "java.lang.String/2004016611"); * ... * return result; * } * </pre> */ private void writeLoadSignaturesJava() { srcWriter.println("@SuppressWarnings(\"deprecation\")"); srcWriter.println("private static Map<String, String> loadSignaturesJava() {"); srcWriter.indent(); srcWriter.println("Map<String, String> result = new HashMap<String, String>();"); for (JType type : getSerializableTypes()) { String typeString = typeStrings.get(type); if (!serializationOracle.maybeInstantiated(type) && !deserializationOracle.maybeInstantiated(type)) { continue; } String typeRef; JClassType customSerializer = SerializableTypeOracleBuilder.findCustomFieldSerializer(typeOracle, type); if (customSerializer != null && CustomFieldSerializerValidator.getConcreteTypeMethod(customSerializer) != null) { typeRef = customSerializer.getQualifiedSourceName() + ".concreteType()"; } else { typeRef = '"' + SerializationUtils.getRpcTypeName(type) + '"'; } srcWriter.println("result.put(" + typeRef + ", \"" + typeString + "\");"); } srcWriter.println("return result;"); srcWriter.outdent(); srcWriter.println("}"); srcWriter.println(); }
/** * Writes a method to produce a map of type string -> class name of {@link TypeHandler} for Java. * * <pre> * private static Map<String, String> loadMethodsJava() { * Map<String, String> result = new HashMap<String, String>(); * result.put( * "java.lang.String/2004016611", * "com.google.gwt.user.client.rpc.core.java.lang.String_FieldSerializer" * ... * return result; * } * </pre> */ private void writeLoadMethodsJava() { srcWriter.println("@SuppressWarnings(\"deprecation\")"); srcWriter.println("private static Map<String, String> loadMethodsJava() {"); srcWriter.indent(); srcWriter.println("Map<String, String> result = new HashMap<String, String>();"); List<JType> filteredTypes = new ArrayList<JType>(); JType[] types = getSerializableTypes(); int n = types.length; for (int index = 0; index < n; ++index) { JType type = types[index]; if (serializationOracle.maybeInstantiated(type) || deserializationOracle.maybeInstantiated(type)) { filteredTypes.add(type); } } for (JType type : filteredTypes) { String typeString = typeStrings.get(type); assert typeString != null : "Missing type signature for " + type.getQualifiedSourceName(); srcWriter.println( "result.put(\"" + typeString + "\", \"" + SerializationUtils.getStandardSerializerName((JClassType) type) + "\");"); } srcWriter.println("return result;"); srcWriter.outdent(); srcWriter.println("}"); srcWriter.println(); }
/** * Writes a method to produce a native map of type string -> handler funcs. * * <pre> * private static native MethodMap loadMethodsNative() /*-{ * var result = {}; * result["java.lang.String/2004016611"] = [ * @com.google.gwt.user.client.rpc.core.java.lang.String_CustomFieldSerializer::instantiate(Lcom/google/gwt/user/client/rpc/SerializationStreamReader;), * @com.google.gwt.user.client.rpc.core.java.lang.String_CustomFieldSerializer::deserialize(Lcom/google/gwt/user/client/rpc/SerializationStreamReader;Ljava/lang/String;), * @com.google.gwt.user.client.rpc.core.java.lang.String_CustomFieldSerializer::serialize(Lcom/google/gwt/user/client/rpc/SerializationStreamWriter;Ljava/lang/String;) * ]; * ... * return result; * }-*/; * </pre> */ private void writeLoadMethodsNative() { srcWriter.println("@SuppressWarnings(\"deprecation\")"); srcWriter.println("@GwtScriptOnly"); srcWriter.println("private static native MethodMap loadMethodsNative() /*-{"); srcWriter.indent(); srcWriter.println("var result = {};"); List<JType> filteredTypes = new ArrayList<JType>(); JType[] types = getSerializableTypes(); int n = types.length; for (int index = 0; index < n; ++index) { JType type = types[index]; if (serializationOracle.maybeInstantiated(type) || deserializationOracle.maybeInstantiated(type)) { filteredTypes.add(type); } } boolean shard = shardSize > 0 && filteredTypes.size() > shardSize; int shardCount = 0; if (shard) { srcWriter.println("(function() {"); } for (JType type : filteredTypes) { if (shard && ++shardCount % shardSize == 0) { srcWriter.println("})();"); srcWriter.println("(function() {"); } String typeString = typeStrings.get(type); assert typeString != null : "Missing type signature for " + type.getQualifiedSourceName(); srcWriter.println("result[\"" + typeString + "\"] = ["); srcWriter.indent(); writeTypeMethodsNative(type); srcWriter.outdent(); srcWriter.indentln("];"); srcWriter.println(); } if (shard) { srcWriter.println("})();"); } srcWriter.println("return result;"); srcWriter.outdent(); srcWriter.println("}-*/;"); srcWriter.println(); }
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("}"); } }
/** * Writes a method to produce a native map of system hash code to type string. * * <pre> * private static native JsArrayString loadSignaturesNative() /*-{ * var result = []; * result[@com.google.gwt.core.client.impl.Impl::getHashCode(Ljava/lang/Object;)(@java.lang.String::class)] = "java.lang.String/2004016611"; * ... * return result; * }-*/; * </pre> */ private void writeLoadSignaturesNative() { srcWriter.println("@SuppressWarnings(\"deprecation\")"); srcWriter.println("@GwtScriptOnly"); srcWriter.println("private static native JsArrayString loadSignaturesNative() /*-{"); srcWriter.indent(); srcWriter.println("var result = [];"); boolean shard = shardSize > 0 && getSerializableTypes().length > shardSize; int shardCount = 0; if (shard) { srcWriter.println("(function() {"); } for (JType type : getSerializableTypes()) { String typeString = typeStrings.get(type); if (!serializationOracle.maybeInstantiated(type) && !deserializationOracle.maybeInstantiated(type)) { continue; } if (shard && ++shardCount % shardSize == 0) { srcWriter.println("})();"); srcWriter.println("(function() {"); } srcWriter.println( "result[@com.google.gwt.core.client.impl.Impl::getHashCode(Ljava/lang/Object;)(@" + type.getQualifiedSourceName() + "::class)] = \"" + typeString + "\";"); } if (shard) { srcWriter.println("})();"); } srcWriter.println("return result;"); srcWriter.outdent(); srcWriter.println("}-*/;"); srcWriter.println(); }
public TypeSerializerCreator( TreeLogger logger, SerializableTypeOracle serializationOracle, SerializableTypeOracle deserializationOracle, GeneratorContextExt context, String typeSerializerClassName, String typeSerializerSimpleName) throws UnableToCompleteException { this.context = context; this.typeSerializerClassName = typeSerializerClassName; this.typeSerializerSimpleName = typeSerializerSimpleName; this.serializationOracle = serializationOracle; this.deserializationOracle = deserializationOracle; this.typeOracle = context.getTypeOracle(); Set<JType> typesSet = new HashSet<JType>(); typesSet.addAll(Arrays.asList(serializationOracle.getSerializableTypes())); typesSet.addAll(Arrays.asList(deserializationOracle.getSerializableTypes())); serializableTypes = typesSet.toArray(new JType[0]); Arrays.sort(serializableTypes, SerializableTypeOracleBuilder.JTYPE_COMPARATOR); srcWriter = getSourceWriter(logger, context); if (shardSize < 0) { computeShardSize(logger); } logger.log( TreeLogger.TRACE, "Using a shard size of " + shardSize + " for TypeSerializerCreator createMethodMap"); try { ConfigurationProperty prop = context.getPropertyOracle().getConfigurationProperty(GWT_ELIDE_TYPE_NAMES_FROM_RPC); elideTypeNames = Boolean.parseBoolean(prop.getValues().get(0)); } catch (BadPropertyValueException e) { logger.log( TreeLogger.ERROR, "The configuration property " + GWT_ELIDE_TYPE_NAMES_FROM_RPC + " was not defined. Is RemoteService.gwt.xml inherited?"); throw new UnableToCompleteException(); } }
/* * Create a field serializer for a type if it does not have a custom * serializer. */ private void createFieldSerializer(TreeLogger logger, GeneratorContextExt ctx, JType type) { Event event = SpeedTracerLogger.start(CompilerEventType.GENERATOR_RPC_FIELD_SERIALIZER); try { assert (type != null); assert (serializationOracle.isSerializable(type) || deserializationOracle.isSerializable(type)); JParameterizedType parameterizedType = type.isParameterized(); if (parameterizedType != null) { createFieldSerializer(logger, ctx, parameterizedType.getRawType()); return; } /* * Only a JClassType can reach this point in the code. JPrimitives have been * removed because their serialization is built in, interfaces have been * removed because they are not an instantiable type and parameterized types * have been broken down into their raw types. */ assert (type.isClass() != null || type.isArray() != null); if (findCacheableFieldSerializerAndMarkForReuseIfAvailable(ctx, type)) { // skip generation of field serializer return; } JClassType customFieldSerializer = SerializableTypeOracleBuilder.findCustomFieldSerializer(typeOracle, type); FieldSerializerCreator creator = new FieldSerializerCreator( context, serializationOracle, deserializationOracle, (JClassType) type, customFieldSerializer); creator.realize(logger, ctx); } finally { event.end(); } }
protected String writeSerializationPolicyFile( TreeLogger logger, GeneratorContextExt ctx, SerializableTypeOracle serializationSto, SerializableTypeOracle deserializationSto) throws UnableToCompleteException { try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); OutputStreamWriter osw = new OutputStreamWriter( baos, SerializationPolicyLoader.SERIALIZATION_POLICY_FILE_ENCODING); TypeOracle oracle = ctx.getTypeOracle(); PrintWriter pw = new PrintWriter(osw); JType[] serializableTypes = unionOfTypeArrays( serializationSto.getSerializableTypes(), deserializationSto.getSerializableTypes(), new JType[] {serviceIntf}); for (int i = 0; i < serializableTypes.length; ++i) { JType type = serializableTypes[i]; String binaryTypeName = SerializationUtils.getRpcTypeName(type); pw.print(binaryTypeName); pw.print(", " + Boolean.toString(deserializationSto.isSerializable(type))); pw.print(", " + Boolean.toString(deserializationSto.maybeInstantiated(type))); pw.print(", " + Boolean.toString(serializationSto.isSerializable(type))); pw.print(", " + Boolean.toString(serializationSto.maybeInstantiated(type))); pw.print(", " + typeStrings.get(type)); /* * Include the serialization signature to bump the RPC file name if * obfuscated identifiers are used. */ pw.print(", " + SerializationUtils.getSerializationSignature(oracle, type)); pw.print('\n'); /* * Emit client-side field information for classes that may be enhanced * on the server. Each line consists of a comma-separated list * containing the keyword '@ClientFields', the class name, and a list of * all potentially serializable client-visible fields. */ if ((type instanceof JClassType) && ((JClassType) type).isEnhanced()) { JField[] fields = ((JClassType) type).getFields(); JField[] rpcFields = new JField[fields.length]; int numRpcFields = 0; for (JField f : fields) { if (f.isTransient() || f.isStatic() || f.isFinal()) { continue; } rpcFields[numRpcFields++] = f; } pw.print(SerializationPolicyLoader.CLIENT_FIELDS_KEYWORD); pw.print(','); pw.print(binaryTypeName); for (int idx = 0; idx < numRpcFields; idx++) { pw.print(','); pw.print(rpcFields[idx].getName()); } pw.print('\n'); } } // Closes the wrapped streams. pw.close(); byte[] serializationPolicyFileContents = baos.toByteArray(); String serializationPolicyName = Util.computeStrongName(serializationPolicyFileContents); String serializationPolicyFileName = SerializationPolicyLoader.getSerializationPolicyFileName(serializationPolicyName); OutputStream os = ctx.tryCreateResource(logger, serializationPolicyFileName); if (os != null) { os.write(serializationPolicyFileContents); GeneratedResource resource = ctx.commitResource(logger, os); /* * Record which proxy class created the resource. A manifest will be * emitted by the RpcPolicyManifestLinker. */ emitPolicyFileArtifact(logger, ctx, resource.getPartialPath()); } else { if (logger.isLoggable(TreeLogger.TRACE)) { logger.log( TreeLogger.TRACE, "SerializationPolicy file for RemoteService '" + serviceIntf.getQualifiedSourceName() + "' already exists; no need to rewrite it.", null); } } return serializationPolicyName; } catch (UnsupportedEncodingException e) { logger.log( TreeLogger.ERROR, SerializationPolicyLoader.SERIALIZATION_POLICY_FILE_ENCODING + " is not supported", e); throw new UnableToCompleteException(); } catch (IOException e) { logger.log(TreeLogger.ERROR, null, e); throw new UnableToCompleteException(); } }
/** * Write an entry in the methodMapNative for one type. * * @param type type to generate entry for */ private void writeTypeMethodsNative(JType type) { srcWriter.indent(); String serializerName = SerializationUtils.getFieldSerializerName(typeOracle, type); JClassType customSerializer = SerializableTypeOracleBuilder.findCustomFieldSerializer(typeOracle, type); // First the initialization method if (deserializationOracle.maybeInstantiated(type)) { srcWriter.print("@"); if (customSerializer != null) { if (hasInstantiateMethod(customSerializer, type)) { srcWriter.print(serializerName); } else { srcWriter.print(SerializationUtils.getStandardSerializerName((JClassType) type)); } } else { srcWriter.print(serializerName); } srcWriter.print("::instantiate"); srcWriter.print("(L" + SerializationStreamReader.class.getName().replace('.', '/') + ";)"); } srcWriter.println(","); // Now the deserialization method if (deserializationOracle.isSerializable(type)) { // Assume param type is the concrete type of the serialized type. JType paramType = type; if (customSerializer != null) { // But a custom serializer may specify a looser type. JMethod deserializationMethod = CustomFieldSerializerValidator.getDeserializationMethod( customSerializer, (JClassType) type); paramType = deserializationMethod.getParameters()[1].getType(); } srcWriter.print("@" + serializerName); srcWriter.print( "::deserialize(L" + SerializationStreamReader.class.getName().replace('.', '/') + ";" + paramType.getJNISignature() + ")"); } srcWriter.println(","); // Now the serialization method if (serializationOracle.isSerializable(type)) { // Assume param type is the concrete type of the serialized type. JType paramType = type; if (customSerializer != null) { // But a custom serializer may specify a looser type. JMethod serializationMethod = CustomFieldSerializerValidator.getSerializationMethod( customSerializer, (JClassType) type); paramType = serializationMethod.getParameters()[1].getType(); } srcWriter.print("@" + serializerName); srcWriter.print( "::serialize(L" + SerializationStreamWriter.class.getName().replace('.', '/') + ";" + paramType.getJNISignature() + ")"); srcWriter.println(); } srcWriter.outdent(); }