KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > google > gwt > user > server > rpc > RPC


1 /*
2  * Copyright 2007 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy of
6  * the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations under
14  * the License.
15  */

16 package com.google.gwt.user.server.rpc;
17
18 import com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException;
19 import com.google.gwt.user.client.rpc.RemoteService;
20 import com.google.gwt.user.client.rpc.SerializationException;
21 import com.google.gwt.user.server.rpc.impl.ServerSerializableTypeOracle;
22 import com.google.gwt.user.server.rpc.impl.ServerSerializableTypeOracleImpl;
23 import com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader;
24 import com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter;
25
26 import java.lang.reflect.InvocationTargetException JavaDoc;
27 import java.lang.reflect.Method JavaDoc;
28 import java.util.Arrays JavaDoc;
29 import java.util.HashMap JavaDoc;
30 import java.util.HashSet JavaDoc;
31 import java.util.Map JavaDoc;
32 import java.util.Set JavaDoc;
33
34 /**
35  * Utility class for integrating with the RPC system. This class exposes methods
36  * for decoding of RPC requests, encoding of RPC responses, and invocation of
37  * RPC calls on service objects. The operations exposed by this class can be
38  * reused by framework implementors such as Spring and G4jsf to support a wide
39  * range of service invocation policies.
40  *
41  * <h3>Canonical Example</h3>
42  * The following example demonstrates the canonical way to use this class.
43  *
44  * {@example com.google.gwt.examples.rpc.server.CanonicalExample#processCall(String)}
45  *
46  * <h3>Advanced Example</h3>
47  * The following example shows a more advanced way of using this class to create
48  * an adapter between GWT RPC entities and POJOs.
49  *
50  * {@example com.google.gwt.examples.rpc.server.AdvancedExample#doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)}
51  */

52 public final class RPC {
53
54   /**
55    * Maps primitive wrapper classes to their corresponding primitive class.
56    */

57   private static final Map JavaDoc PRIMITIVE_WRAPPER_CLASS_TO_PRIMITIVE_CLASS = new HashMap JavaDoc();
58
59   /**
60    * Oracle used in stream construction. Encapsulates a set of static,
61    * synchronized caches.
62    */

63   private static ServerSerializableTypeOracle serializableTypeOracle;
64
65   /**
66    * Static map of classes to sets of interfaces (e.g. classes). Optimizes
67    * lookup of interfaces for security.
68    */

69   private static Map JavaDoc/* <Class, Set<String> > */serviceToImplementedInterfacesMap;
70
71   private static final HashMap JavaDoc TYPE_NAMES;
72   static {
73     PRIMITIVE_WRAPPER_CLASS_TO_PRIMITIVE_CLASS.put(Boolean JavaDoc.class, Boolean.TYPE);
74     PRIMITIVE_WRAPPER_CLASS_TO_PRIMITIVE_CLASS.put(Byte JavaDoc.class, Byte.TYPE);
75     PRIMITIVE_WRAPPER_CLASS_TO_PRIMITIVE_CLASS.put(Character JavaDoc.class,
76         Character.TYPE);
77     PRIMITIVE_WRAPPER_CLASS_TO_PRIMITIVE_CLASS.put(Double JavaDoc.class, Double.TYPE);
78     PRIMITIVE_WRAPPER_CLASS_TO_PRIMITIVE_CLASS.put(Float JavaDoc.class, Float.TYPE);
79     PRIMITIVE_WRAPPER_CLASS_TO_PRIMITIVE_CLASS.put(Integer JavaDoc.class, Integer.TYPE);
80     PRIMITIVE_WRAPPER_CLASS_TO_PRIMITIVE_CLASS.put(Long JavaDoc.class, Long.TYPE);
81     PRIMITIVE_WRAPPER_CLASS_TO_PRIMITIVE_CLASS.put(Short JavaDoc.class, Short.TYPE);
82
83     TYPE_NAMES = new HashMap JavaDoc();
84     TYPE_NAMES.put("Z", boolean.class);
85     TYPE_NAMES.put("B", byte.class);
86     TYPE_NAMES.put("C", char.class);
87     TYPE_NAMES.put("D", double.class);
88     TYPE_NAMES.put("F", float.class);
89     TYPE_NAMES.put("I", int.class);
90     TYPE_NAMES.put("J", long.class);
91     TYPE_NAMES.put("S", short.class);
92
93     serializableTypeOracle = new ServerSerializableTypeOracleImpl(
94         getPackagePaths());
95
96     serviceToImplementedInterfacesMap = new HashMap JavaDoc();
97   }
98
99   /**
100    * Returns an {@link RPCRequest} that is built by decoding the contents of an
101    * encoded RPC request.
102    *
103    * <p>
104    * This method is equivalent to calling {@link #decodeRequest(String, Class)}
105    * with <code>null</code> for the type parameter.
106    * </p>
107    *
108    * @param encodedRequest a string that encodes the {@link RemoteService}
109    * interface, the service method to call, and the arguments to for
110    * the service method
111    * @return an {@link RPCRequest} instance
112    *
113    * @throws IncompatibleRemoteServiceException if any of the following
114    * conditions apply:
115    * <ul>
116    * <li>if the types in the encoded request cannot be deserialized</li>
117    * <li><code>RPC.class.getClassLoader()</code> cannot load the
118    * service interface requested in the encodedRequest</li>
119    * <li>the requested interface is not assignable to
120    * {@link RemoteService}</li>
121    * <li>the service method requested in the encodedRequest is not a
122    * member of the requested service interface</li>
123    * <li>the type parameter is not <code>null</code> and is not
124    * assignable to the requested {@link RemoteService} interface
125    * </ul>
126    */

127   public static RPCRequest decodeRequest(String JavaDoc encodedRequest) {
128     return decodeRequest(encodedRequest, null);
129   }
130
131   /**
132    * Returns an {@link RPCRequest} that is built by decoding the contents of an
133    * encoded RPC request and optionally validating that type can handle the
134    * request. If the type parameter is not <code>null</code>, the
135    * implementation checks that the type is assignable to the
136    * {@link RemoteService} interface requested in the encoded request string.
137    *
138    * <p>
139    * Invoking this method with <code>null</code> for the type parameter,
140    * <code>decodeRequest(encodedRequest, null)</code>, is equivalent to
141    * calling <code>decodeRequest(encodedRequest)</code>.
142    * </p>
143    *
144    * @param encodedRequest a string that encodes the {@link RemoteService}
145    * interface, the service method, and the arguments to pass to the
146    * service method
147    * @param type if not <code>null</code>, the implementation checks that the
148    * type is assignable to the {@link RemoteService} interface encoded
149    * in the encoded request string.
150    * @return an {@link RPCRequest} instance
151    *
152    * @throws NullPointerException if the encodedRequest is <code>null</code>
153    * @throws IllegalArgumentException if the encodedRequest is an empty string
154    * @throws IncompatibleRemoteServiceException if any of the following
155    * conditions apply:
156    * <ul>
157    * <li>if the types in the encoded request cannot be deserialized</li>
158    * <li><code>RPC.class.getClassLoader()</code> cannot load the
159    * service interface requested in the encodedRequest</li>
160    * <li>the requested interface is not assignable to
161    * {@link RemoteService}</li>
162    * <li>the service method requested in the encodedRequest is not a
163    * member of the requested service interface</li>
164    * <li>the type parameter is not <code>null</code> and is not
165    * assignable to the requested {@link RemoteService} interface
166    * </ul>
167    */

168   public static RPCRequest decodeRequest(String JavaDoc encodedRequest, Class JavaDoc type) {
169     if (encodedRequest == null) {
170       throw new NullPointerException JavaDoc("encodedRequest cannot be null");
171     }
172
173     if (encodedRequest.length() == 0) {
174       throw new IllegalArgumentException JavaDoc("encodedRequest cannot be empty");
175     }
176
177     try {
178       ServerSerializationStreamReader streamReader = new ServerSerializationStreamReader(
179           serializableTypeOracle);
180       streamReader.prepareToRead(encodedRequest);
181
182       String JavaDoc serviceIntfName = streamReader.readString();
183
184       if (type != null) {
185         if (!implementsInterface(type, serviceIntfName)) {
186           // The service does not implement the requested interface
187
throw new IncompatibleRemoteServiceException(
188               "Blocked attempt to access interface '" + serviceIntfName
189                   + "', which is not implemented by '" + printTypeName(type)
190                   + "'; this is either misconfiguration or a hack attempt");
191         }
192       }
193
194       Class JavaDoc serviceIntf;
195       try {
196         serviceIntf = getClassFromSerializedName(serviceIntfName);
197         if (!RemoteService.class.isAssignableFrom(serviceIntf)) {
198           // The requested interface is not a RemoteService interface
199
throw new IncompatibleRemoteServiceException(
200               "Blocked attempt to access interface '"
201                   + printTypeName(serviceIntf)
202                   + "', which doesn't extend RemoteService; this is either misconfiguration or a hack attempt");
203         }
204       } catch (ClassNotFoundException JavaDoc e) {
205         throw new IncompatibleRemoteServiceException(
206             "Could not locate requested interface '" + serviceIntfName
207                 + "' in default classloader", e);
208       }
209
210       String JavaDoc serviceMethodName = streamReader.readString();
211
212       int paramCount = streamReader.readInt();
213       Class JavaDoc[] parameterTypes = new Class JavaDoc[paramCount];
214
215       for (int i = 0; i < parameterTypes.length; i++) {
216         String JavaDoc paramClassName = streamReader.readString();
217         try {
218           parameterTypes[i] = getClassFromSerializedName(paramClassName);
219         } catch (ClassNotFoundException JavaDoc e) {
220           throw new IncompatibleRemoteServiceException("Parameter " + i
221               + " of is of an unknown type '" + paramClassName + "'", e);
222         }
223       }
224
225       Method JavaDoc method = findInterfaceMethod(serviceIntf, serviceMethodName,
226           parameterTypes, true);
227
228       if (method == null) {
229         throw new IncompatibleRemoteServiceException(
230             formatMethodNotFoundErrorMessage(serviceIntf, serviceMethodName,
231                 parameterTypes));
232       }
233
234       Object JavaDoc[] parameterValues = new Object JavaDoc[parameterTypes.length];
235       for (int i = 0; i < parameterValues.length; i++) {
236         parameterValues[i] = streamReader.deserializeValue(parameterTypes[i]);
237       }
238
239       return new RPCRequest(method, parameterValues);
240
241     } catch (SerializationException ex) {
242       throw new IncompatibleRemoteServiceException(ex.getMessage(), ex);
243     }
244   }
245
246   /**
247    * Returns a string that encodes an exception. If method is not
248    * <code>null</code>, it is an error if the exception is not in the
249    * method's list of checked exceptions.
250    *
251    * @param serviceMethod the method that threw the exception, maybe
252    * <code>null</code>
253    * @param cause the {@link Throwable} that was thrown
254    * @return a string that encodes the exception
255    *
256    * @throws NullPointerException if the the cause is <code>null</code>
257    * @throws SerializationException if the result cannot be serialized
258    * @throws UnexpectedException if the result was an unexpected exception (a
259    * checked exception not declared in the serviceMethod's signature)
260    */

261   public static String JavaDoc encodeResponseForFailure(Method JavaDoc serviceMethod,
262       Throwable JavaDoc cause) throws SerializationException {
263     if (cause == null) {
264       throw new NullPointerException JavaDoc("cause cannot be null");
265     }
266
267     if (serviceMethod != null && !RPC.isExpectedException(serviceMethod, cause)) {
268       throw new UnexpectedException("Service method '"
269           + getSourceRepresentation(serviceMethod)
270           + "' threw an unexpected exception: " + cause.toString(), cause);
271     }
272
273     return encodeResponse(cause.getClass(), cause, true);
274   }
275
276   /**
277    * Returns a string that encodes the object. It is an error to try to encode
278    * an object that is not assignable to the service method's return type.
279    *
280    * @param serviceMethod the method whose result we are encoding
281    * @param object the instance that we wish to encode
282    * @return a string that encodes the object, if the object is compatible with
283    * the service method's declared return type
284    *
285    * @throws IllegalArgumentException if the result is not assignable to the
286    * service method's return type
287    * @throws NullPointerException if the service method is <code>null</code>
288    * @throws SerializationException if the result cannot be serialized
289    */

290   public static String JavaDoc encodeResponseForSuccess(Method JavaDoc serviceMethod,
291       Object JavaDoc object) throws SerializationException {
292     if (serviceMethod == null) {
293       throw new NullPointerException JavaDoc("serviceMethod cannot be null");
294     }
295
296     Class JavaDoc methodReturnType = serviceMethod.getReturnType();
297     if (methodReturnType != void.class && object != null) {
298       Class JavaDoc actualReturnType;
299       if (methodReturnType.isPrimitive()) {
300         actualReturnType = getPrimitiveClassFromWrapper(object.getClass());
301       } else {
302         actualReturnType = object.getClass();
303       }
304
305       if (actualReturnType == null
306           || !methodReturnType.isAssignableFrom(actualReturnType)) {
307         throw new IllegalArgumentException JavaDoc("Type '"
308             + printTypeName(object.getClass())
309             + "' does not match the return type in the method's signature: '"
310             + getSourceRepresentation(serviceMethod) + "'");
311       }
312     }
313
314     return encodeResponse(methodReturnType, object, false);
315   }
316
317   /**
318    * Returns a string that encodes the result of calling a service method, which
319    * could be the value returned by the method or an exception thrown by it.
320    *
321    * <p>
322    * This method does no security checking; security checking must be done on
323    * the method prior to this invocation.
324    * </p>
325    *
326    * @param target instance on which to invoke the serviceMethod
327    * @param serviceMethod the method to invoke
328    * @param args arguments used for the method invocation
329    * @return a string which encodes either the method's return or a checked
330    * exception thrown by the method
331    *
332    * @throws SecurityException if the method cannot be accessed or if the number
333    * or type of actual and formal arguments differ
334    * @throws SerializationException if an object could not be serialized by the
335    * stream
336    * @throws UnexpectedException if the serviceMethod throws a checked exception
337    * that is not declared in its signature
338    */

339   public static String JavaDoc invokeAndEncodeResponse(Object JavaDoc target,
340       Method JavaDoc serviceMethod, Object JavaDoc[] args) throws SerializationException {
341
342     if (serviceMethod == null) {
343       throw new NullPointerException JavaDoc("serviceMethod cannot be null");
344     }
345
346     String JavaDoc responsePayload;
347     try {
348       Object JavaDoc result = serviceMethod.invoke(target, args);
349
350       responsePayload = encodeResponseForSuccess(serviceMethod, result);
351     } catch (IllegalAccessException JavaDoc e) {
352       SecurityException JavaDoc securityException = new SecurityException JavaDoc(
353           formatIllegalAccessErrorMessage(target, serviceMethod));
354       securityException.initCause(e);
355       throw securityException;
356     } catch (IllegalArgumentException JavaDoc e) {
357       SecurityException JavaDoc securityException = new SecurityException JavaDoc(
358           formatIllegalArgumentErrorMessage(target, serviceMethod, args));
359       securityException.initCause(e);
360       throw securityException;
361     } catch (InvocationTargetException JavaDoc e) {
362       // Try to encode the caught exception
363
//
364
Throwable JavaDoc cause = e.getCause();
365
366       responsePayload = encodeResponseForFailure(serviceMethod, cause);
367     }
368
369     return responsePayload;
370   }
371
372   /**
373    * Returns a string that encodes the results of an RPC call. Private overload
374    * that takes a flag signaling the preamble of the response payload.
375    *
376    * @param serviceMethod the method whose return object we are encoding
377    * @param object the object that we wish to send back to the client
378    * @param wasThrown if true, the object being returned was an exception thrown
379    * by the service method; if false, it was the result of the service
380    * method's invocation
381    * @return a string that encodes the response from a service method
382    * @throws SerializationException if the object cannot be serialized
383    */

384   private static String JavaDoc encodeResponse(Class JavaDoc responseClass, Object JavaDoc object,
385       boolean wasThrown) throws SerializationException {
386
387     ServerSerializationStreamWriter stream = new ServerSerializationStreamWriter(
388         serializableTypeOracle);
389
390     stream.prepareToWrite();
391     if (responseClass != void.class) {
392       stream.serializeValue(object, responseClass);
393     }
394
395     String JavaDoc bufferStr = (wasThrown ? "//EX" : "//OK") + stream.toString();
396     return bufferStr;
397   }
398
399   /**
400    * Find the invoked method on either the specified interface or any super.
401    */

402   private static Method JavaDoc findInterfaceMethod(Class JavaDoc intf, String JavaDoc methodName,
403       Class JavaDoc[] paramTypes, boolean includeInherited) {
404     try {
405       return intf.getDeclaredMethod(methodName, paramTypes);
406     } catch (NoSuchMethodException JavaDoc e) {
407       if (includeInherited) {
408         Class JavaDoc[] superintfs = intf.getInterfaces();
409         for (int i = 0; i < superintfs.length; i++) {
410           Method JavaDoc method = findInterfaceMethod(superintfs[i], methodName,
411               paramTypes, true);
412           if (method != null) {
413             return method;
414           }
415         }
416       }
417
418       return null;
419     }
420   }
421
422   private static String JavaDoc formatIllegalAccessErrorMessage(Object JavaDoc target,
423       Method JavaDoc serviceMethod) {
424     StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
425     sb.append("Blocked attempt to access inaccessible method '");
426     sb.append(getSourceRepresentation(serviceMethod));
427     sb.append("'");
428
429     if (target != null) {
430       sb.append(" on target '");
431       sb.append(printTypeName(target.getClass()));
432       sb.append("'");
433     }
434
435     sb.append("; this is either misconfiguration or a hack attempt");
436
437     return sb.toString();
438   }
439
440   private static String JavaDoc formatIllegalArgumentErrorMessage(Object JavaDoc target,
441       Method JavaDoc serviceMethod, Object JavaDoc[] args) {
442     StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
443     sb.append("Blocked attempt to invoke method '");
444     sb.append(getSourceRepresentation(serviceMethod));
445     sb.append("'");
446
447     if (target != null) {
448       sb.append(" on target '");
449       sb.append(printTypeName(target.getClass()));
450       sb.append("'");
451     }
452
453     sb.append(" with invalid arguments");
454
455     if (args != null && args.length > 0) {
456       sb.append(Arrays.asList(args));
457     }
458
459     return sb.toString();
460   }
461
462   private static String JavaDoc formatMethodNotFoundErrorMessage(Class JavaDoc serviceIntf,
463       String JavaDoc serviceMethodName, Class JavaDoc[] parameterTypes) {
464     StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
465
466     sb.append("Could not locate requested method '");
467     sb.append(serviceMethodName);
468     sb.append("(");
469     for (int i = 0; i < parameterTypes.length; ++i) {
470       if (i > 0) {
471         sb.append(", ");
472       }
473       sb.append(printTypeName(parameterTypes[i]));
474     }
475     sb.append(")'");
476
477     sb.append(" in interface '");
478     sb.append(printTypeName(serviceIntf));
479     sb.append("'");
480
481     return sb.toString();
482   }
483
484   /**
485    * Returns the {@link Class} instance for the named class or primitive type.
486    *
487    * @param serializedName the serialized name of a class or primitive type
488    * @return Class instance for the given type name
489    * @throws ClassNotFoundException if the named type was not found
490    */

491   private static Class JavaDoc getClassFromSerializedName(String JavaDoc serializedName)
492       throws ClassNotFoundException JavaDoc {
493     Object JavaDoc value = TYPE_NAMES.get(serializedName);
494     if (value != null) {
495       return (Class JavaDoc) value;
496     }
497
498     return Class.forName(serializedName, false, RPC.class.getClassLoader());
499   }
500
501   /**
502    * Obtain the special package-prefixes we use to check for custom serializers
503    * that would like to live in a package that they cannot. For example,
504    * "java.util.ArrayList" is in a sealed package, so instead we use this prefix
505    * to check for a custom serializer in
506    * "com.google.gwt.user.client.rpc.core.java.util.ArrayList". Right now, it's
507    * hard-coded because we don't have a pressing need for this mechanism to be
508    * extensible, but it is imaginable, which is why it's implemented this way.
509    */

510   private static String JavaDoc[] getPackagePaths() {
511     return new String JavaDoc[] {"com.google.gwt.user.client.rpc.core"};
512   }
513
514   /**
515    * Returns the {@link java.lang.Class Class} for a primitive type given its
516    * corresponding wrapper {@link java.lang.Class Class}.
517    *
518    * @param wrapperClass primitive wrapper class
519    * @return primitive class
520    */

521   private static Class JavaDoc getPrimitiveClassFromWrapper(Class JavaDoc wrapperClass) {
522     return (Class JavaDoc) PRIMITIVE_WRAPPER_CLASS_TO_PRIMITIVE_CLASS.get(wrapperClass);
523   }
524
525   /**
526    * Returns the source representation for a method signature.
527    *
528    * @param method method to get the source signature for
529    * @return source representation for a method signature
530    */

531   private static String JavaDoc getSourceRepresentation(Method JavaDoc method) {
532     return method.toString().replace('$', '.');
533   }
534
535   /**
536    * Used to determine whether the specified interface name is implemented by
537    * the service class. This is done without loading the class (for security).
538    */

539   private static boolean implementsInterface(Class JavaDoc service, String JavaDoc intfName) {
540     synchronized (serviceToImplementedInterfacesMap) {
541       // See if it's cached.
542
//
543
Set JavaDoc/* <String> */interfaceSet = (Set JavaDoc) serviceToImplementedInterfacesMap.get(service);
544       if (interfaceSet != null) {
545         if (interfaceSet.contains(intfName)) {
546           return true;
547         }
548       } else {
549         interfaceSet = new HashSet JavaDoc/* <String> */();
550         serviceToImplementedInterfacesMap.put(service, interfaceSet);
551       }
552
553       if (!service.isInterface()) {
554         while ((service != null) && !RemoteServiceServlet.class.equals(service)) {
555           Class JavaDoc[] intfs = service.getInterfaces();
556           for (int i = 0; i < intfs.length; i++) {
557             Class JavaDoc intf = intfs[i];
558             if (implementsInterfaceRecursive(intf, intfName)) {
559               interfaceSet.add(intfName);
560               return true;
561             }
562           }
563
564           // did not find the interface in this class so we look in the
565
// superclass
566
//
567
service = service.getSuperclass();
568         }
569       } else {
570         if (implementsInterfaceRecursive(service, intfName)) {
571           interfaceSet.add(intfName);
572           return true;
573         }
574       }
575
576       return false;
577     }
578   }
579
580   /**
581    * Only called from implementsInterface().
582    */

583   private static boolean implementsInterfaceRecursive(Class JavaDoc clazz,
584       String JavaDoc intfName) {
585     assert (clazz.isInterface());
586
587     if (clazz.getName().equals(intfName)) {
588       return true;
589     }
590
591     // search implemented interfaces
592
Class JavaDoc[] intfs = clazz.getInterfaces();
593     for (int i = 0; i < intfs.length; i++) {
594       Class JavaDoc intf = intfs[i];
595       if (implementsInterfaceRecursive(intf, intfName)) {
596         return true;
597       }
598     }
599
600     return false;
601   }
602
603   /**
604    * Returns true if the {@link java.lang.reflect.Method Method} definition on
605    * the service is specified to throw the exception contained in the
606    * InvocationTargetException or false otherwise. NOTE we do not check that the
607    * type is serializable here. We assume that it must be otherwise the
608    * application would never have been allowed to run.
609    *
610    * @param serviceIntfMethod the method from the RPC request
611    * @param cause the exception that the method threw
612    * @return true if the exception's type is in the method's signature
613    */

614   private static boolean isExpectedException(Method JavaDoc serviceIntfMethod,
615       Throwable JavaDoc cause) {
616     assert (serviceIntfMethod != null);
617     assert (cause != null);
618
619     Class JavaDoc[] exceptionsThrown = serviceIntfMethod.getExceptionTypes();
620     if (exceptionsThrown.length <= 0) {
621       // The method is not specified to throw any exceptions
622
//
623
return false;
624     }
625
626     Class JavaDoc causeType = cause.getClass();
627
628     for (int index = 0; index < exceptionsThrown.length; ++index) {
629       Class JavaDoc exceptionThrown = exceptionsThrown[index];
630       assert (exceptionThrown != null);
631
632       if (exceptionThrown.isAssignableFrom(causeType)) {
633         return true;
634       }
635     }
636
637     return false;
638   }
639
640   /**
641    * Straight copy from
642    * {@link com.google.gwt.dev.util.TypeInfo#getSourceRepresentation(Class)} to
643    * avoid runtime dependency on gwt-dev.
644    */

645   private static String JavaDoc printTypeName(Class JavaDoc type) {
646     // Primitives
647
//
648
if (type.equals(Integer.TYPE)) {
649       return "int";
650     } else if (type.equals(Long.TYPE)) {
651       return "long";
652     } else if (type.equals(Short.TYPE)) {
653       return "short";
654     } else if (type.equals(Byte.TYPE)) {
655       return "byte";
656     } else if (type.equals(Character.TYPE)) {
657       return "char";
658     } else if (type.equals(Boolean.TYPE)) {
659       return "boolean";
660     } else if (type.equals(Float.TYPE)) {
661       return "float";
662     } else if (type.equals(Double.TYPE)) {
663       return "double";
664     }
665
666     // Arrays
667
//
668
if (type.isArray()) {
669       Class JavaDoc componentType = type.getComponentType();
670       return printTypeName(componentType) + "[]";
671     }
672
673     // Everything else
674
//
675
return type.getName().replace('$', '.');
676   }
677
678   /**
679    * Static classes have no constructability.
680    */

681   private RPC() {
682     // Not instantiable
683
}
684 }
685
Popular Tags