protected void generateProxyMethods( SourceWriter w, SerializableTypeOracle serializableTypeOracle, TypeOracle typeOracle, Map<JMethod, JMethod> syncMethToAsyncMethMap) { JMethod[] syncMethods = serviceIntf.getOverridableMethods(); for (JMethod syncMethod : syncMethods) { JMethod asyncMethod = syncMethToAsyncMethMap.get(syncMethod); assert (asyncMethod != null); JClassType enclosingType = syncMethod.getEnclosingType(); JParameterizedType isParameterizedType = enclosingType.isParameterized(); if (isParameterizedType != null) { JMethod[] methods = isParameterizedType.getMethods(); for (int i = 0; i < methods.length; ++i) { if (methods[i] == syncMethod) { /* * Use the generic version of the method to ensure that the server * can find the method using the erasure of the generic signature. */ syncMethod = isParameterizedType.getBaseType().getMethods()[i]; } } } generateProxyMethod(w, serializableTypeOracle, typeOracle, syncMethod, asyncMethod); } }
/** Examines a type to see if it can be transported. */ private boolean validateTransportableType( RequestMethod.Builder methodBuilder, JType type, boolean requireObject) throws UnableToCompleteException { JClassType transportedClass = type.isClassOrInterface(); if (transportedClass == null) { if (requireObject) { poison( "The type %s cannot be transported by RequestFactory as" + " a return type", type.getQualifiedSourceName()); return false; } else { // Primitives always ok return true; } } if (ModelUtils.isValueType(oracle, transportedClass) || splittableType.equals(transportedClass)) { // Simple values, like Integer and String methodBuilder.setValueType(true); } else if (entityProxyInterface.isAssignableFrom(transportedClass) || valueProxyInterface.isAssignableFrom(transportedClass)) { // EntityProxy and ValueProxy return types methodBuilder.setEntityType(getEntityProxyType(transportedClass)); } else if (collectionInterface.isAssignableFrom(transportedClass)) { // Only allow certain collections for now JParameterizedType parameterized = transportedClass.isParameterized(); if (parameterized == null) { poison("Requests that return collections of List or Set must be parameterized"); return false; } if (listInterface.equals(parameterized.getBaseType())) { methodBuilder.setCollectionType(CollectionType.LIST); } else if (setInterface.equals(parameterized.getBaseType())) { methodBuilder.setCollectionType(CollectionType.SET); } else { poison( "Requests that return collections may be declared with" + " %s or %s only", listInterface.getQualifiedSourceName(), setInterface.getQualifiedSourceName()); return false; } // Also record the element type in the method builder JClassType elementType = ModelUtils.findParameterizationOf(collectionInterface, transportedClass)[0]; methodBuilder.setCollectionElementType(elementType); validateTransportableType(methodBuilder, elementType, requireObject); } else if (mapInterface.isAssignableFrom(transportedClass)) { JParameterizedType parameterized = transportedClass.isParameterized(); if (parameterized == null) { poison("Requests that return Maps must be parameterized"); return false; } if (mapInterface.equals(parameterized.getBaseType())) { methodBuilder.setCollectionType(CollectionType.MAP); } else { poison( "Requests that return maps may be declared with" + " %s only", mapInterface.getQualifiedSourceName()); return false; } // Also record the element type in the method builder JClassType[] params = ModelUtils.findParameterizationOf(mapInterface, transportedClass); JClassType keyType = params[0]; JClassType valueType = params[1]; methodBuilder.setMapKeyType(keyType); methodBuilder.setMapValueType(valueType); validateTransportableType(methodBuilder, keyType, requireObject); validateTransportableType(methodBuilder, valueType, requireObject); } else { // Unknown type, fail poison("Invalid Request parameterization %s", transportedClass.getQualifiedSourceName()); return false; } methodBuilder.setDataType(transportedClass); return true; }