1 16 package com.google.gwt.user.rebind.rpc; 17 18 import com.google.gwt.core.ext.TreeLogger; 19 import com.google.gwt.core.ext.UnableToCompleteException; 20 import com.google.gwt.core.ext.typeinfo.JClassType; 21 import com.google.gwt.core.ext.typeinfo.JMethod; 22 import com.google.gwt.core.ext.typeinfo.JPackage; 23 import com.google.gwt.core.ext.typeinfo.JParameter; 24 import com.google.gwt.core.ext.typeinfo.JPrimitiveType; 25 import com.google.gwt.core.ext.typeinfo.NotFoundException; 26 import com.google.gwt.core.ext.typeinfo.TypeOracle; 27 import com.google.gwt.user.client.rpc.AsyncCallback; 28 29 import java.util.Map ; 30 import java.util.TreeMap ; 31 32 36 class RemoteServiceAsyncValidator { 37 private static String synthesizeAsynchronousInterfaceDefinition( 38 JClassType serviceIntf) { 39 StringBuffer sb = new StringBuffer (); 40 JPackage pkg = serviceIntf.getPackage(); 41 if (pkg != null) { 42 sb.append("\npackage "); 43 sb.append(pkg.getName()); 44 sb.append(";\n"); 45 } 46 47 sb.append("\npublic interface "); 48 sb.append(serviceIntf.getSimpleSourceName()); 49 sb.append("Async {\n"); 50 51 JMethod[] methods = serviceIntf.getOverridableMethods(); 52 for (int index = 0; index < methods.length; ++index) { 53 JMethod method = methods[index]; 54 assert (method != null); 55 56 sb.append("\tvoid "); 57 sb.append(method.getName()); 58 sb.append("("); 59 60 JParameter[] params = method.getParameters(); 61 for (int paramIndex = 0; paramIndex < params.length; ++paramIndex) { 62 JParameter param = params[paramIndex]; 63 64 if (paramIndex > 0) { 65 sb.append(", "); 66 } 67 68 sb.append(param.toString()); 69 } 70 71 if (params.length > 0) { 72 sb.append(", "); 73 } 74 75 sb.append(AsyncCallback.class.getName()); 76 sb.append(" arg"); 77 sb.append(Integer.toString(params.length + 1)); 78 sb.append(");\n"); 79 } 80 81 sb.append("}"); 82 83 return sb.toString(); 84 } 85 86 private final JClassType asyncCallbackClass; 87 private final TypeOracle typeOracle; 88 89 RemoteServiceAsyncValidator(TypeOracle typeOracle) throws NotFoundException { 90 this.typeOracle = typeOracle; 91 asyncCallbackClass = typeOracle.getType(AsyncCallback.class.getName()); 92 } 93 94 105 public void validateRemoteServiceAsync(TreeLogger logger, 106 JClassType remoteService) throws UnableToCompleteException { 107 TreeLogger branch = logger.branch(TreeLogger.DEBUG, 108 "Checking the synchronous interface '" 109 + remoteService.getQualifiedSourceName() 110 + "' against its asynchronous version '" 111 + remoteService.getQualifiedSourceName() + "Async'", null); 112 boolean failed = false; 113 JClassType serviceAsync = typeOracle.findType(remoteService.getQualifiedSourceName() 114 + "Async"); 115 if (serviceAsync == null) { 116 failed = true; 117 branch.branch(TreeLogger.ERROR, 118 "Could not find an asynchronous version for the service interface " 119 + remoteService.getQualifiedSourceName(), null); 120 } else { 121 JMethod[] asyncMethods = serviceAsync.getOverridableMethods(); 122 JMethod[] syncMethods = remoteService.getOverridableMethods(); 123 124 if (asyncMethods.length != syncMethods.length) { 125 branch.branch(TreeLogger.ERROR, "The asynchronous version of " 126 + remoteService.getQualifiedSourceName() + " has " 127 + (asyncMethods.length > syncMethods.length ? "more" : "less") 128 + " methods than the synchronous version", null); 129 failed = true; 130 } else { 131 Map asyncMethodMap = initializeAsyncMethodMap(asyncMethods); 132 for (int i = 0; i < syncMethods.length; ++i) { 133 JMethod syncMethod = syncMethods[i]; 134 String asyncSig = computeAsyncMethodSignature(syncMethod); 135 JMethod asyncMethod = (JMethod) asyncMethodMap.get(asyncSig); 136 if (asyncMethod == null) { 137 branch.branch(TreeLogger.ERROR, 138 "Missing asynchronous version of the synchronous method '" 139 + syncMethod.getReadableDeclaration() + "'", null); 140 failed = true; 141 } else if (asyncMethod.getReturnType() != JPrimitiveType.VOID) { 142 branch.branch(TreeLogger.ERROR, 143 "The asynchronous version of the synchronous method '" 144 + syncMethod.getReadableDeclaration() 145 + "' must have a 'void' return type", null); 146 failed = true; 147 } 148 } 149 } 150 } 151 152 if (failed) { 153 logValidAsyncInterfaceDeclaration(branch, remoteService); 154 throw new UnableToCompleteException(); 155 } 156 } 157 158 private String computeAsyncMethodSignature(JMethod syncMethod) { 159 return computeInternalSignature(syncMethod) + "/" 160 + asyncCallbackClass.getQualifiedSourceName(); 161 } 162 163 private String computeInternalSignature(JMethod method) { 164 StringBuffer sb = new StringBuffer (); 165 sb.setLength(0); 166 sb.append(method.getName()); 167 JParameter[] params = method.getParameters(); 168 for (int j = 0; j < params.length; j++) { 169 JParameter param = params[j]; 170 sb.append("/"); 171 sb.append(param.getType().getQualifiedSourceName()); 172 } 173 return sb.toString(); 174 } 175 176 180 private Map initializeAsyncMethodMap(JMethod[] asyncMethods) { 181 Map sigs = new TreeMap (); 182 for (int i = 0; i < asyncMethods.length; ++i) { 183 JMethod asyncMethod = asyncMethods[i]; 184 sigs.put(computeInternalSignature(asyncMethod), asyncMethod); 185 } 186 return sigs; 187 } 188 189 private void logValidAsyncInterfaceDeclaration(TreeLogger logger, 190 JClassType remoteService) { 191 TreeLogger branch = logger.branch(TreeLogger.INFO, 192 "A valid definition for the asynchronous version of interface '" 193 + remoteService.getQualifiedSourceName() + "' would be:\n", null); 194 branch.log(TreeLogger.ERROR, 195 synthesizeAsynchronousInterfaceDefinition(remoteService), null); 196 } 197 } | Popular Tags |