1 16 package com.google.gwt.user.rebind.rpc; 17 18 import com.google.gwt.core.client.GWT; 19 import com.google.gwt.core.client.GWT.UncaughtExceptionHandler; 20 import com.google.gwt.core.ext.GeneratorContext; 21 import com.google.gwt.core.ext.TreeLogger; 22 import com.google.gwt.core.ext.UnableToCompleteException; 23 import com.google.gwt.core.ext.typeinfo.JClassType; 24 import com.google.gwt.core.ext.typeinfo.JMethod; 25 import com.google.gwt.core.ext.typeinfo.JPackage; 26 import com.google.gwt.core.ext.typeinfo.JParameter; 27 import com.google.gwt.core.ext.typeinfo.JParameterizedType; 28 import com.google.gwt.core.ext.typeinfo.JPrimitiveType; 29 import com.google.gwt.core.ext.typeinfo.JType; 30 import com.google.gwt.dev.generator.NameFactory; 31 import com.google.gwt.user.client.ResponseTextHandler; 32 import com.google.gwt.user.client.rpc.AsyncCallback; 33 import com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException; 34 import com.google.gwt.user.client.rpc.InvocationException; 35 import com.google.gwt.user.client.rpc.SerializationException; 36 import com.google.gwt.user.client.rpc.ServiceDefTarget; 37 import com.google.gwt.user.client.rpc.ServiceDefTarget.NoServiceEntryPointSpecifiedException; 38 import com.google.gwt.user.client.rpc.impl.ClientSerializationStreamReader; 39 import com.google.gwt.user.client.rpc.impl.ClientSerializationStreamWriter; 40 import com.google.gwt.user.rebind.ClassSourceFileComposerFactory; 41 import com.google.gwt.user.rebind.SourceWriter; 42 43 import java.io.PrintWriter ; 44 45 50 class ProxyCreator { 51 private static final String ENTRY_POINT_TAG = "gwt.defaultEntryPoint"; 52 private static final String PROXY_SUFFIX = "_Proxy"; 53 54 private static final String SERIALIZATION_STREAM_READER_INSTANTIATION = ClientSerializationStreamReader.class.getName() 55 + " streamReader = new " 56 + ClientSerializationStreamReader.class.getName() + "(SERIALIZER);"; 57 58 private static final String SERIALIZATION_STREAM_WRITER_INSTANTIATION = ClientSerializationStreamWriter.class.getName() 59 + " streamWriter = new " 60 + ClientSerializationStreamWriter.class.getName() + "(SERIALIZER);"; 61 62 66 private static String getJavaTypeName(JType type) { 67 JParameterizedType parameterizedType = type.isParameterized(); 68 if (parameterizedType != null) { 69 return parameterizedType.getRawType().getQualifiedSourceName(); 70 } 71 72 return type.getQualifiedSourceName(); 73 } 74 75 private boolean enforceTypeVersioning; 76 77 private JClassType serviceIntf; 78 79 public ProxyCreator(JClassType serviceIntf) { 80 assert (serviceIntf.isInterface() != null); 81 82 this.serviceIntf = serviceIntf; 83 } 84 85 90 public String create(TreeLogger logger, GeneratorContext context) 91 throws UnableToCompleteException { 92 SourceWriter srcWriter = getSourceWriter(logger, context); 93 if (srcWriter == null) { 94 return getProxyQualifiedName(); 95 } 96 97 SerializableTypeOracleBuilder stob = new SerializableTypeOracleBuilder( 98 logger, context.getTypeOracle()); 99 SerializableTypeOracle sto = stob.build(context.getPropertyOracle(), 100 serviceIntf); 101 102 TypeSerializerCreator tsc = new TypeSerializerCreator(logger, sto, context, 103 serviceIntf); 104 tsc.realize(logger); 105 106 enforceTypeVersioning = Shared.shouldEnforceTypeVersioning(logger, 107 context.getPropertyOracle()); 108 109 generateProxyFields(srcWriter, sto); 110 111 generateServiceDefTargetImpl(srcWriter); 112 113 generateProxyMethods(srcWriter, sto); 114 115 srcWriter.commit(logger); 116 117 return getProxyQualifiedName(); 118 } 119 120 125 protected final void generateDecodeCall(SourceWriter w, JType type) { 126 w.print("streamReader."); 127 w.print("read" + Shared.getCallSuffix(type) + "()"); 128 } 129 130 134 protected void generateEncodeCall(SourceWriter w, JParameter parameter) { 135 JType paramType = parameter.getType(); 136 w.print("streamWriter."); 137 w.print("write" + Shared.getCallSuffix(paramType)); 138 w.println("(" + parameter.getName() + ");"); 139 } 140 141 144 private void generateAsynchronousProxyMethod(SourceWriter w, JMethod method) { 145 146 JType returnType = method.getReturnType(); 147 JParameter[] params = method.getParameters(); 148 149 NameFactory nameFactory = new NameFactory(); 150 151 for (int i = 0; i < params.length; ++i) { 152 nameFactory.addName(params[i].getName()); 153 } 154 155 w.println(); 156 w.print("public void " + method.getName() + "("); 157 int i; 158 for (i = 0; i < params.length; i++) { 159 JParameter param = params[i]; 160 w.print((i > 0 ? ", " : "") + getJavaTypeName(param.getType()) + " " 161 + param.getName()); 162 } 163 164 w.println((i > 0 ? ", final " : "final ") + AsyncCallback.class.getName() 165 + " callback) {"); 166 w.indent(); 167 w.println("final " + SERIALIZATION_STREAM_READER_INSTANTIATION); 168 w.println("final " + SERIALIZATION_STREAM_WRITER_INSTANTIATION); 169 w.println("try {"); 170 w.indent(); 171 { 172 w.print("__" + method.getName() + "(streamWriter"); 173 for (i = 0; i < params.length; i++) { 174 w.print(", " + params[i].getName()); 175 } 176 w.println(");"); 177 } 178 w.outdent(); 179 180 String exceptionName = nameFactory.createName("e"); 181 w.println("} catch (" + SerializationException.class.getName() + " " 182 + exceptionName + ") {"); 183 w.indentln("callback.onFailure(" + exceptionName + ");"); 184 w.indentln("return;"); 185 w.println("}"); 186 187 w.println(ResponseTextHandler.class.getName() + " handler = new " 190 + ResponseTextHandler.class.getName() + "() {"); 191 w.indent(); 192 { 193 w.println("public final void onCompletion(String encodedResponse) {"); 194 w.indent(); 195 { 196 w.println("UncaughtExceptionHandler handler = GWT.getUncaughtExceptionHandler();"); 197 w.println("if (handler != null)"); 198 w.indent(); 199 { 200 w.println("onCompletionAndCatch(encodedResponse, handler);"); 201 } 202 w.outdent(); 203 w.println("else"); 204 w.indent(); 205 { 206 w.println("onCompletionImpl(encodedResponse);"); 207 } 208 w.outdent(); 209 } 210 w.outdent(); 211 w.println("}"); 212 213 w.println("private void onCompletionAndCatch(String encodedResponse, UncaughtExceptionHandler handler) {"); 214 w.indent(); 215 { 216 w.println("try {"); 217 w.indent(); 218 { 219 w.println("onCompletionImpl(encodedResponse);"); 220 } 221 w.outdent(); 222 w.println("} catch (Throwable e) {"); 223 w.indent(); 224 { 225 w.println("handler.onUncaughtException(e);"); 226 } 227 w.outdent(); 228 w.println("}"); 229 } 230 w.outdent(); 231 w.println("}"); 232 233 w.println("private void onCompletionImpl(String encodedResponse) {"); 234 w.indent(); 235 { 236 w.println("Object result = null;"); 237 w.println("Throwable caught = null;"); 238 w.println("try {"); 239 w.indent(); 240 { 241 w.println("if (encodedResponse.startsWith(\"//OK\")) {"); 242 w.indent(); 243 { 244 w.println("streamReader.prepareToRead(encodedResponse.substring(4));"); 245 w.print("result = "); 246 247 JPrimitiveType primitive = returnType.isPrimitive(); 248 if (primitive == JPrimitiveType.VOID) { 249 w.print("null"); 250 } else { 251 if (primitive != null) { 252 w.print("new "); 253 w.print(getObjectWrapperName(primitive)); 254 w.print("("); 255 generateDecodeCall(w, returnType); 256 w.print(")"); 257 } else { 258 generateDecodeCall(w, returnType); 259 } 260 } 261 w.println(";"); 262 } 263 w.outdent(); 264 w.println("} else if (encodedResponse.startsWith(\"//EX\")) {"); 265 w.indent(); 266 { 267 w.println("streamReader.prepareToRead(encodedResponse.substring(4));"); 268 w.println("caught = (Throwable) streamReader.readObject();"); 269 } 270 w.outdent(); 271 w.println("} else {"); 272 w.indent(); 273 { 274 w.println("caught = new " + InvocationException.class.getName() 275 + "(encodedResponse);"); 276 } 277 w.outdent(); 278 w.println("}"); 279 } 280 w.outdent(); 281 w.println("} catch (" + SerializationException.class.getName() + " e) {"); 282 w.indent(); 283 { 284 w.println("caught = new " + IncompatibleRemoteServiceException.class.getName() + "();"); 285 } 286 w.outdent(); 287 w.println("} catch (Throwable e) {"); 288 w.indent(); 289 { 290 w.println("caught = e;"); 291 } 292 w.outdent(); 293 w.println("}"); 294 295 w.println("if (caught == null)"); 296 w.indent(); 297 { 298 w.println("callback.onSuccess(result);"); 299 } 300 w.outdent(); 301 w.println("else"); 302 w.indent(); 303 { 304 w.println("callback.onFailure(caught);"); 305 } 306 w.outdent(); 307 } 308 w.outdent(); 309 w.println("}"); 310 } 311 w.outdent(); 312 w.println("};"); 313 314 w.println("if (!com.google.gwt.user.client.HTTPRequest.asyncPost(getServiceEntryPoint(), streamWriter.toString(), handler))"); 317 w.indentln("callback.onFailure(new " 318 + InvocationException.class.getName() 319 + "(\"Unable to initiate the asynchronous service invocation -- check the network connection\"));"); 320 w.outdent(); 321 322 w.println("}"); 323 } 324 325 328 private void generateProxyEncode(SourceWriter w, 329 SerializableTypeOracle serializableTypeOracle, JMethod method) { 330 String methodName = method.getName(); 331 JParameter[] params = method.getParameters(); 332 w.println(); 333 w.print("private void __" + methodName + "(" 334 + ClientSerializationStreamWriter.class.getName() + " streamWriter"); 335 for (int i = 0; i < params.length; i++) { 336 JParameter param = params[i]; 337 w.print(", " + getJavaTypeName(param.getType()) + " " + param.getName()); 338 } 339 340 w.println(") throws " + SerializationException.class.getName() + " {"); 341 w.indent(); 342 343 w.println("if (getServiceEntryPoint() == null)"); 346 String className = NoServiceEntryPointSpecifiedException.class.getName(); 347 className = className.replace('$', '.'); 348 w.indentln("throw new " + className + "();"); 349 350 w.println("streamWriter.prepareToWrite();"); 354 355 if (!shouldEnforceTypeVersioning()) { 356 w.println("streamWriter.addFlags(" 357 + ClientSerializationStreamReader.class.getName() 358 + ".SERIALIZATION_STREAM_FLAGS_NO_TYPE_VERSIONING);"); 359 } 360 w.println("streamWriter.writeString(\"" 361 + serializableTypeOracle.getSerializedTypeName(method.getEnclosingType()) 362 + "\");"); 363 w.println("streamWriter.writeString(\"" + methodName + "\");"); 364 w.println("streamWriter.writeInt(" + params.length + ");"); 365 for (int i = 0; i < params.length; ++i) { 366 JParameter param = params[i]; 367 w.println("streamWriter.writeString(\"" 368 + serializableTypeOracle.getSerializedTypeName(param.getType()) 369 + "\");"); 370 } 371 372 for (int i = 0; i < params.length; i++) { 375 JParameter param = params[i]; 376 generateEncodeCall(w, param); 377 } 378 379 w.outdent(); 380 w.println("}"); 381 } 382 383 386 private void generateProxyFields(SourceWriter srcWriter, 387 SerializableTypeOracle serializableTypeOracle) { 388 String typeSerializerName = serializableTypeOracle.getTypeSerializerQualifiedName(serviceIntf); 389 srcWriter.println("private static final " + typeSerializerName 390 + " SERIALIZER = new " + typeSerializerName + "();"); 391 } 392 393 private void generateProxyMethods(SourceWriter w, 394 SerializableTypeOracle serializableTypeOracle) { 395 396 JMethod[] methods = serviceIntf.getOverridableMethods(); 397 for (int i = 0; i < methods.length; ++i) { 398 JMethod method = methods[i]; 399 generateProxyEncode(w, serializableTypeOracle, method); 400 generateAsynchronousProxyMethod(w, method); 401 } 402 } 403 404 408 private void generateServiceDefTargetImpl(SourceWriter w) { 409 String serverDefName = getDefaultServiceDefName(); 410 if (serverDefName != null) { 411 serverDefName = "\"" + serverDefName + "\""; 412 } else { 413 serverDefName = "null"; 414 } 415 416 w.println(); 417 w.println("String fServiceEntryPoint = " + serverDefName + ";"); 418 w.println(); 419 w.println("public String getServiceEntryPoint() { return fServiceEntryPoint; }"); 420 w.println(); 421 w.println("public void setServiceEntryPoint(String s) { fServiceEntryPoint = s; }"); 422 } 423 424 private String getAsyncIntfQualifiedName() { 425 String asyncIntf = serviceIntf.getQualifiedSourceName() + "Async"; 426 return asyncIntf; 427 } 428 429 private String getDefaultServiceDefName() { 430 String [][] metaData = serviceIntf.getMetaData(ENTRY_POINT_TAG); 431 if (metaData.length == 0) { 432 return null; 433 } 434 return serviceIntf.getMetaData(ENTRY_POINT_TAG)[0][0]; 435 } 436 437 441 private String getObjectWrapperName(JPrimitiveType primitive) { 442 if (primitive == JPrimitiveType.INT) { 443 return "Integer"; 444 } else if (primitive == JPrimitiveType.CHAR) { 445 return "Character"; 446 } 447 448 return Shared.capitalize(primitive.getSimpleSourceName()); 449 } 450 451 private String getPackageName() { 452 JPackage pkg = serviceIntf.getPackage(); 453 if (pkg != null) { 454 return pkg.getName(); 455 } 456 457 return ""; 458 } 459 460 private String getProxyQualifiedName() { 461 String [] name = Shared.synthesizeTopLevelClassName(serviceIntf, 462 PROXY_SUFFIX); 463 return name[0].length() == 0 ? name[1] : name[0] + "." + name[1]; 464 } 465 466 private String getProxySimpleName() { 467 String [] name = Shared.synthesizeTopLevelClassName(serviceIntf, 468 PROXY_SUFFIX); 469 return name[1]; 470 } 471 472 private SourceWriter getSourceWriter(TreeLogger logger, GeneratorContext ctx) { 473 PrintWriter printWriter = ctx.tryCreate(logger, getPackageName(), 474 getProxySimpleName()); 475 if (printWriter == null) { 476 return null; 477 } 478 479 ClassSourceFileComposerFactory composerFactory = new ClassSourceFileComposerFactory( 480 getPackageName(), getProxySimpleName()); 481 482 composerFactory.addImport(GWT.class.getName()); 483 String className = UncaughtExceptionHandler.class.getName(); 484 className = className.replace('$', '.'); 485 composerFactory.addImport(className); 486 487 composerFactory.addImplementedInterface(ServiceDefTarget.class.getName()); 488 composerFactory.addImplementedInterface(getAsyncIntfQualifiedName()); 489 490 return composerFactory.createSourceWriter(ctx, printWriter); 491 } 492 493 private boolean shouldEnforceTypeVersioning() { 494 return enforceTypeVersioning; 495 } 496 } 497 | Popular Tags |