001: /*
002: * Copyright 2007 Google Inc.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005: * use this file except in compliance with the License. You may obtain a copy of
006: * the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013: * License for the specific language governing permissions and limitations under
014: * the License.
015: */
016: package com.google.gwt.user.server.rpc.impl;
017:
018: import com.google.gwt.user.client.rpc.SerializationException;
019: import com.google.gwt.user.client.rpc.SerializationStreamReader;
020: import com.google.gwt.user.client.rpc.impl.AbstractSerializationStreamReader;
021: import com.google.gwt.user.server.rpc.RPC;
022: import com.google.gwt.user.server.rpc.SerializationPolicy;
023: import com.google.gwt.user.server.rpc.SerializationPolicyProvider;
024:
025: import java.lang.reflect.Array;
026: import java.lang.reflect.Field;
027: import java.lang.reflect.InvocationTargetException;
028: import java.lang.reflect.Method;
029: import java.lang.reflect.Modifier;
030: import java.util.ArrayList;
031: import java.util.IdentityHashMap;
032: import java.util.Map;
033:
034: /**
035: * For internal use only. Used for server call serialization. This class is
036: * carefully matched with the client-side version.
037: */
038: public final class ServerSerializationStreamReader extends
039: AbstractSerializationStreamReader {
040:
041: /**
042: * Enumeration used to provided typed instance readers.
043: */
044: private enum ValueReader {
045: BOOLEAN {
046: @Override
047: Object readValue(ServerSerializationStreamReader stream) {
048: return stream.readBoolean();
049: }
050: },
051: BYTE {
052: @Override
053: Object readValue(ServerSerializationStreamReader stream) {
054: return stream.readByte();
055: }
056: },
057: CHAR {
058: @Override
059: Object readValue(ServerSerializationStreamReader stream) {
060: return stream.readChar();
061: }
062: },
063: DOUBLE {
064: @Override
065: Object readValue(ServerSerializationStreamReader stream) {
066: return stream.readDouble();
067: }
068: },
069: FLOAT {
070: @Override
071: Object readValue(ServerSerializationStreamReader stream) {
072: return stream.readFloat();
073: }
074: },
075: INT {
076: @Override
077: Object readValue(ServerSerializationStreamReader stream) {
078: return stream.readInt();
079: }
080: },
081: LONG {
082: @Override
083: Object readValue(ServerSerializationStreamReader stream) {
084: return stream.readLong();
085: }
086: },
087: OBJECT {
088: @Override
089: Object readValue(ServerSerializationStreamReader stream)
090: throws SerializationException {
091: return stream.readObject();
092: }
093: },
094: SHORT {
095: @Override
096: Object readValue(ServerSerializationStreamReader stream) {
097: return stream.readShort();
098: }
099: },
100: STRING {
101: @Override
102: Object readValue(ServerSerializationStreamReader stream) {
103: return stream.readString();
104: }
105: };
106:
107: abstract Object readValue(ServerSerializationStreamReader stream)
108: throws SerializationException;
109: }
110:
111: /**
112: * Enumeration used to provided typed instance readers for vectors.
113: */
114: private enum VectorReader {
115: BOOLEAN_VECTOR {
116: @Override
117: void read(ServerSerializationStreamReader stream,
118: Object instance) {
119: boolean[] vector = (boolean[]) instance;
120: for (int i = 0, n = vector.length; i < n; ++i) {
121: vector[i] = stream.readBoolean();
122: }
123: }
124: },
125: BYTE_VECTOR {
126: @Override
127: void read(ServerSerializationStreamReader stream,
128: Object instance) {
129: byte[] vector = (byte[]) instance;
130: for (int i = 0, n = vector.length; i < n; ++i) {
131: vector[i] = stream.readByte();
132: }
133: }
134: },
135: CHAR_VECTOR {
136: @Override
137: void read(ServerSerializationStreamReader stream,
138: Object instance) {
139: char[] vector = (char[]) instance;
140: for (int i = 0, n = vector.length; i < n; ++i) {
141: vector[i] = stream.readChar();
142: }
143: }
144: },
145: DOUBLE_VECTOR {
146: @Override
147: void read(ServerSerializationStreamReader stream,
148: Object instance) {
149: double[] vector = (double[]) instance;
150: for (int i = 0, n = vector.length; i < n; ++i) {
151: vector[i] = stream.readDouble();
152: }
153: }
154: },
155: FLOAT_VECTOR {
156: @Override
157: void read(ServerSerializationStreamReader stream,
158: Object instance) {
159: float[] vector = (float[]) instance;
160: for (int i = 0, n = vector.length; i < n; ++i) {
161: vector[i] = stream.readFloat();
162: }
163: }
164: },
165:
166: INT_VECTOR {
167: @Override
168: void read(ServerSerializationStreamReader stream,
169: Object instance) {
170: int[] vector = (int[]) instance;
171: for (int i = 0, n = vector.length; i < n; ++i) {
172: vector[i] = stream.readInt();
173: }
174: }
175: },
176: LONG_VECTOR {
177: @Override
178: void read(ServerSerializationStreamReader stream,
179: Object instance) {
180: long[] vector = (long[]) instance;
181: for (int i = 0, n = vector.length; i < n; ++i) {
182: vector[i] = stream.readLong();
183: }
184: }
185: },
186: OBJECT_VECTOR {
187: @Override
188: void read(ServerSerializationStreamReader stream,
189: Object instance) throws SerializationException {
190: Object[] vector = (Object[]) instance;
191: for (int i = 0, n = vector.length; i < n; ++i) {
192: vector[i] = stream.readObject();
193: }
194: }
195: },
196: SHORT_VECTOR {
197: @Override
198: void read(ServerSerializationStreamReader stream,
199: Object instance) {
200: short[] vector = (short[]) instance;
201: for (int i = 0, n = vector.length; i < n; ++i) {
202: vector[i] = stream.readShort();
203: }
204: }
205: },
206: STRING_VECTOR {
207: @Override
208: void read(ServerSerializationStreamReader stream,
209: Object instance) {
210: String[] vector = (String[]) instance;
211: for (int i = 0, n = vector.length; i < n; ++i) {
212: vector[i] = stream.readString();
213: }
214: }
215: };
216:
217: abstract void read(ServerSerializationStreamReader stream,
218: Object instance) throws SerializationException;
219: }
220:
221: /**
222: * Map of {@link Class} objects to {@link ValueReader}s.
223: */
224: private static final Map<Class<?>, ValueReader> CLASS_TO_VALUE_READER = new IdentityHashMap<Class<?>, ValueReader>();
225:
226: /**
227: * Map of {@link Class} objects to {@link VectorReader}s.
228: */
229: private static final Map<Class<?>, VectorReader> CLASS_TO_VECTOR_READER = new IdentityHashMap<Class<?>, VectorReader>();
230:
231: private final ClassLoader classLoader;
232:
233: private String[] stringTable;
234:
235: private final ArrayList<String> tokenList = new ArrayList<String>();
236:
237: private SerializationPolicy serializationPolicy = RPC
238: .getDefaultSerializationPolicy();
239:
240: private int tokenListIndex;
241:
242: private final SerializationPolicyProvider serializationPolicyProvider;
243: {
244: CLASS_TO_VECTOR_READER.put(boolean[].class,
245: VectorReader.BOOLEAN_VECTOR);
246: CLASS_TO_VECTOR_READER.put(byte[].class,
247: VectorReader.BYTE_VECTOR);
248: CLASS_TO_VECTOR_READER.put(char[].class,
249: VectorReader.CHAR_VECTOR);
250: CLASS_TO_VECTOR_READER.put(double[].class,
251: VectorReader.DOUBLE_VECTOR);
252: CLASS_TO_VECTOR_READER.put(float[].class,
253: VectorReader.FLOAT_VECTOR);
254: CLASS_TO_VECTOR_READER
255: .put(int[].class, VectorReader.INT_VECTOR);
256: CLASS_TO_VECTOR_READER.put(long[].class,
257: VectorReader.LONG_VECTOR);
258: CLASS_TO_VECTOR_READER.put(Object[].class,
259: VectorReader.OBJECT_VECTOR);
260: CLASS_TO_VECTOR_READER.put(short[].class,
261: VectorReader.SHORT_VECTOR);
262: CLASS_TO_VECTOR_READER.put(String[].class,
263: VectorReader.STRING_VECTOR);
264:
265: CLASS_TO_VALUE_READER.put(boolean.class, ValueReader.BOOLEAN);
266: CLASS_TO_VALUE_READER.put(byte.class, ValueReader.BYTE);
267: CLASS_TO_VALUE_READER.put(char.class, ValueReader.CHAR);
268: CLASS_TO_VALUE_READER.put(double.class, ValueReader.DOUBLE);
269: CLASS_TO_VALUE_READER.put(float.class, ValueReader.FLOAT);
270: CLASS_TO_VALUE_READER.put(int.class, ValueReader.INT);
271: CLASS_TO_VALUE_READER.put(long.class, ValueReader.LONG);
272: CLASS_TO_VALUE_READER.put(Object.class, ValueReader.OBJECT);
273: CLASS_TO_VALUE_READER.put(short.class, ValueReader.SHORT);
274: CLASS_TO_VALUE_READER.put(String.class, ValueReader.STRING);
275: }
276:
277: public ServerSerializationStreamReader(ClassLoader classLoader,
278: SerializationPolicyProvider serializationPolicyProvider) {
279: this .classLoader = classLoader;
280: this .serializationPolicyProvider = serializationPolicyProvider;
281: }
282:
283: public Object deserializeValue(Class<?> type)
284: throws SerializationException {
285: ValueReader valueReader = CLASS_TO_VALUE_READER.get(type);
286: if (valueReader != null) {
287: return valueReader.readValue(this );
288: } else {
289: // Arrays of primitive or reference types need to go through readObject.
290: return ValueReader.OBJECT.readValue(this );
291: }
292: }
293:
294: public SerializationPolicy getSerializationPolicy() {
295: return serializationPolicy;
296: }
297:
298: @Override
299: public void prepareToRead(String encodedTokens)
300: throws SerializationException {
301: tokenList.clear();
302: tokenListIndex = 0;
303: stringTable = null;
304:
305: int idx = 0, nextIdx;
306: while (-1 != (nextIdx = encodedTokens.indexOf('\uffff', idx))) {
307: String current = encodedTokens.substring(idx, nextIdx);
308: tokenList.add(current);
309: idx = nextIdx + 1;
310: }
311:
312: super .prepareToRead(encodedTokens);
313:
314: // Read the type name table
315: //
316: deserializeStringTable();
317:
318: // If this stream encodes resource file information, read it and get a
319: // SerializationPolicy
320: if (hasSerializationPolicyInfo()) {
321: String moduleBaseURL = readString();
322: String strongName = readString();
323: if (serializationPolicyProvider != null) {
324: serializationPolicy = serializationPolicyProvider
325: .getSerializationPolicy(moduleBaseURL,
326: strongName);
327:
328: if (serializationPolicy == null) {
329: throw new NullPointerException(
330: "serializationPolicyProvider.getSerializationPolicy()");
331: }
332: }
333: }
334: }
335:
336: public boolean readBoolean() {
337: return !extract().equals("0");
338: }
339:
340: public byte readByte() {
341: return Byte.parseByte(extract());
342: }
343:
344: public char readChar() {
345: // just use an int, it's more foolproof
346: return (char) Integer.parseInt(extract());
347: }
348:
349: public double readDouble() {
350: return Double.parseDouble(extract());
351: }
352:
353: public float readFloat() {
354: return Float.parseFloat(extract());
355: }
356:
357: public int readInt() {
358: return Integer.parseInt(extract());
359: }
360:
361: public long readLong() {
362: return Long.parseLong(extract());
363: }
364:
365: public short readShort() {
366: return Short.parseShort(extract());
367: }
368:
369: public String readString() {
370: return getString(readInt());
371: }
372:
373: @Override
374: protected Object deserialize(String typeSignature)
375: throws SerializationException {
376: Object instance = null;
377: SerializedInstanceReference serializedInstRef = SerializabilityUtil
378: .decodeSerializedInstanceReference(typeSignature);
379:
380: try {
381: Class<?> instanceClass = Class.forName(serializedInstRef
382: .getName(), false, classLoader);
383:
384: assert (serializationPolicy != null);
385:
386: serializationPolicy.validateDeserialize(instanceClass);
387:
388: validateTypeVersions(instanceClass, serializedInstRef);
389:
390: Class<?> customSerializer = SerializabilityUtil
391: .hasCustomFieldSerializer(instanceClass);
392:
393: instance = instantiate(customSerializer, instanceClass);
394:
395: rememberDecodedObject(instance);
396:
397: deserializeImpl(customSerializer, instanceClass, instance);
398:
399: return instance;
400:
401: } catch (ClassNotFoundException e) {
402: throw new SerializationException(e);
403:
404: } catch (InstantiationException e) {
405: throw new SerializationException(e);
406:
407: } catch (IllegalAccessException e) {
408: throw new SerializationException(e);
409:
410: } catch (IllegalArgumentException e) {
411: throw new SerializationException(e);
412:
413: } catch (InvocationTargetException e) {
414: throw new SerializationException(e);
415:
416: } catch (NoSuchMethodException e) {
417: throw new SerializationException(e);
418: }
419: }
420:
421: @Override
422: protected String getString(int index) {
423: if (index == 0) {
424: return null;
425: }
426: // index is 1-based
427: assert (index > 0);
428: assert (index <= stringTable.length);
429: return stringTable[index - 1];
430: }
431:
432: /**
433: * Deserialize an instance that is an array. Will default to deserializing as
434: * an Object vector if the instance is not a primitive vector.
435: *
436: * @param instanceClass
437: * @param instance
438: * @throws SerializationException
439: */
440: private void deserializeArray(Class<?> instanceClass,
441: Object instance) throws SerializationException {
442: assert (instanceClass.isArray());
443:
444: VectorReader instanceReader = CLASS_TO_VECTOR_READER
445: .get(instanceClass);
446: if (instanceReader != null) {
447: instanceReader.read(this , instance);
448: } else {
449: VectorReader.OBJECT_VECTOR.read(this , instance);
450: }
451: }
452:
453: private void deserializeClass(Class<?> instanceClass,
454: Object instance) throws SerializationException,
455: IllegalAccessException, NoSuchMethodException,
456: InvocationTargetException, ClassNotFoundException {
457: Field[] serializableFields = SerializabilityUtil
458: .applyFieldSerializationPolicy(instanceClass);
459:
460: for (Field declField : serializableFields) {
461: assert (declField != null);
462:
463: Object value = deserializeValue(declField.getType());
464:
465: boolean isAccessible = declField.isAccessible();
466: boolean needsAccessOverride = !isAccessible
467: && !Modifier.isPublic(declField.getModifiers());
468: if (needsAccessOverride) {
469: // Override access restrictions
470: declField.setAccessible(true);
471: }
472:
473: declField.set(instance, value);
474:
475: if (needsAccessOverride) {
476: // Restore access restrictions
477: declField.setAccessible(isAccessible);
478: }
479: }
480:
481: Class<?> super Class = instanceClass.getSuperclass();
482: if (serializationPolicy.shouldDeserializeFields(super Class)) {
483: deserializeImpl(SerializabilityUtil
484: .hasCustomFieldSerializer(super Class), super Class,
485: instance);
486: }
487: }
488:
489: private void deserializeImpl(Class<?> customSerializer,
490: Class<?> instanceClass, Object instance)
491: throws NoSuchMethodException, IllegalArgumentException,
492: IllegalAccessException, InvocationTargetException,
493: SerializationException, ClassNotFoundException {
494:
495: if (customSerializer != null) {
496: deserializeWithCustomFieldDeserializer(customSerializer,
497: instanceClass, instance);
498: } else if (instanceClass.isArray()) {
499: deserializeArray(instanceClass, instance);
500: } else if (instanceClass.isEnum()) {
501: // Enums are deserialized when they are instantiated
502: } else {
503: deserializeClass(instanceClass, instance);
504: }
505: }
506:
507: private void deserializeStringTable() {
508: int typeNameCount = readInt();
509: stringTable = new String[typeNameCount];
510: for (int typeNameIndex = 0; typeNameIndex < typeNameCount; ++typeNameIndex) {
511: stringTable[typeNameIndex] = extract();
512: }
513: }
514:
515: private void deserializeWithCustomFieldDeserializer(
516: Class<?> customSerializer, Class<?> instanceClass,
517: Object instance) throws NoSuchMethodException,
518: IllegalAccessException, InvocationTargetException {
519: assert (!instanceClass.isArray());
520:
521: Method deserialize = customSerializer.getMethod("deserialize",
522: SerializationStreamReader.class, instanceClass);
523: deserialize.invoke(null, this , instance);
524: }
525:
526: private String extract() {
527: return tokenList.get(tokenListIndex++);
528: }
529:
530: private Object instantiate(Class<?> customSerializer,
531: Class<?> instanceClass) throws InstantiationException,
532: IllegalAccessException, IllegalArgumentException,
533: InvocationTargetException {
534: if (customSerializer != null) {
535: try {
536: Method instantiate = customSerializer.getMethod(
537: "instantiate", SerializationStreamReader.class);
538: return instantiate.invoke(null, this );
539: } catch (NoSuchMethodException e) {
540: // purposely ignored
541: }
542: }
543:
544: if (instanceClass.isArray()) {
545: int length = readInt();
546: Class<?> componentType = instanceClass.getComponentType();
547: return Array.newInstance(componentType, length);
548: } else if (instanceClass.isEnum()) {
549: Enum[] enumConstants = (Enum[]) instanceClass
550: .getEnumConstants();
551: int ordinal = readInt();
552: assert (ordinal >= 0 && ordinal < enumConstants.length);
553: return enumConstants[ordinal];
554: } else {
555: return instanceClass.newInstance();
556: }
557: }
558:
559: private void validateTypeVersions(Class<?> instanceClass,
560: SerializedInstanceReference serializedInstRef)
561: throws SerializationException {
562: String clientTypeSignature = serializedInstRef.getSignature();
563: if (clientTypeSignature.length() == 0) {
564: if (shouldEnforceTypeVersioning()) {
565: throw new SerializationException(
566: "Missing type signature for "
567: + instanceClass.getName());
568: }
569:
570: return;
571: }
572:
573: String serverTypeSignature = SerializabilityUtil
574: .getSerializationSignature(instanceClass);
575:
576: if (!clientTypeSignature.equals(serverTypeSignature)) {
577: throw new SerializationException(
578: "Invalid type signature for "
579: + instanceClass.getName());
580: }
581: }
582: }
|