KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > google > gwt > user > server > rpc > impl > ServerSerializationStreamReader


1 /*
2  * Copyright 2006 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.impl;
17
18 import com.google.gwt.user.client.rpc.SerializationException;
19 import com.google.gwt.user.client.rpc.SerializationStreamReader;
20 import com.google.gwt.user.client.rpc.impl.AbstractSerializationStreamReader;
21
22 import java.lang.reflect.Array JavaDoc;
23 import java.lang.reflect.Field JavaDoc;
24 import java.lang.reflect.InvocationTargetException JavaDoc;
25 import java.lang.reflect.Method JavaDoc;
26 import java.lang.reflect.Modifier JavaDoc;
27 import java.util.ArrayList JavaDoc;
28
29 /**
30  * For internal use only. Used for server call serialization. This class is
31  * carefully matched with the client-side version.
32  */

33 public final class ServerSerializationStreamReader extends
34     AbstractSerializationStreamReader {
35
36   private ServerSerializableTypeOracle serializableTypeOracle;
37
38   private String JavaDoc[] stringTable;
39
40   private ArrayList JavaDoc tokenList = new ArrayList JavaDoc();
41
42   private int tokenListIndex;
43
44   public ServerSerializationStreamReader(
45       ServerSerializableTypeOracle serializableTypeOracle) {
46     this.serializableTypeOracle = serializableTypeOracle;
47   }
48
49   public Object JavaDoc deserializeValue(Class JavaDoc type) throws SerializationException {
50     if (type == boolean.class) {
51       return Boolean.valueOf(readBoolean());
52     } else if (type == byte.class) {
53       return new Byte JavaDoc(readByte());
54     } else if (type == char.class) {
55       return new Character JavaDoc(readChar());
56     } else if (type == double.class) {
57       return new Double JavaDoc(readDouble());
58     } else if (type == float.class) {
59       return new Float JavaDoc(readFloat());
60     } else if (type == int.class) {
61       return new Integer JavaDoc(readInt());
62     } else if (type == long.class) {
63       return new Long JavaDoc(readLong());
64     } else if (type == short.class) {
65       return new Short JavaDoc(readShort());
66     } else if (type == String JavaDoc.class) {
67       return readString();
68     }
69
70     return readObject();
71   }
72
73   public void prepareToRead(String JavaDoc encodedTokens) throws SerializationException {
74     tokenList.clear();
75     tokenListIndex = 0;
76     stringTable = null;
77
78     int idx = 0, nextIdx;
79     while (-1 != (nextIdx = encodedTokens.indexOf('\uffff', idx))) {
80       String JavaDoc current = encodedTokens.substring(idx, nextIdx);
81       tokenList.add(current);
82       idx = nextIdx + 1;
83     }
84
85     super.prepareToRead(encodedTokens);
86
87     // Read the type name table
88
//
89
deserializeStringTable();
90   }
91
92   public boolean readBoolean() {
93     return !extract().equals("0");
94   }
95
96   public byte readByte() {
97     return Byte.parseByte(extract());
98   }
99
100   public char readChar() {
101     // just use an int, it's more foolproof
102
return (char) Integer.parseInt(extract());
103   }
104
105   public double readDouble() {
106     return Double.parseDouble(extract());
107   }
108
109   public float readFloat() {
110     return Float.parseFloat(extract());
111   }
112
113   public int readInt() {
114     return Integer.parseInt(extract());
115   }
116
117   public long readLong() {
118     return Long.parseLong(extract());
119   }
120
121   public short readShort() {
122     return Short.parseShort(extract());
123   }
124
125   public String JavaDoc readString() throws SerializationException {
126     return getString(readInt());
127   }
128
129   protected Object JavaDoc deserialize(String JavaDoc typeSignature)
130       throws SerializationException {
131     Object JavaDoc instance = null;
132     SerializedInstanceReference serializedInstRef = serializableTypeOracle.decodeSerializedInstanceReference(typeSignature);
133
134     try {
135       Class JavaDoc instanceClass = Class.forName(serializedInstRef.getName(), false,
136           this.getClass().getClassLoader());
137
138       if (!serializableTypeOracle.isSerializable(instanceClass)) {
139         throw new SerializationException("Class '" + instanceClass.getName()
140             + "' is not serializable");
141       }
142
143       validateTypeVersions(instanceClass, serializedInstRef);
144
145       Class JavaDoc customSerializer = serializableTypeOracle.hasCustomFieldSerializer(instanceClass);
146
147       instance = instantiate(customSerializer, instanceClass);
148
149       rememberDecodedObject(instance);
150
151       deserializeImpl(customSerializer, instanceClass, instance);
152
153       return instance;
154
155     } catch (ClassNotFoundException JavaDoc e) {
156       throw new SerializationException(e);
157
158     } catch (InstantiationException JavaDoc e) {
159       throw new SerializationException(e);
160
161     } catch (IllegalAccessException JavaDoc e) {
162       throw new SerializationException(e);
163
164     } catch (IllegalArgumentException JavaDoc e) {
165       throw new SerializationException(e);
166
167     } catch (InvocationTargetException JavaDoc e) {
168       throw new SerializationException(e);
169
170     } catch (NoSuchMethodException JavaDoc e) {
171       throw new SerializationException(e);
172     }
173   }
174
175   protected String JavaDoc getString(int index) {
176     if (index == 0) {
177       return null;
178     }
179     // index is 1-based
180
assert (index > 0);
181     assert (index <= stringTable.length);
182     return stringTable[index - 1];
183   }
184
185   private void deserializeImpl(Class JavaDoc customSerializer, Class JavaDoc instanceClass,
186       Object JavaDoc instance) throws NoSuchMethodException JavaDoc, IllegalArgumentException JavaDoc,
187       IllegalAccessException JavaDoc, InvocationTargetException JavaDoc,
188       SerializationException, ClassNotFoundException JavaDoc {
189     if (customSerializer != null) {
190       deserializeWithCustomFieldDeserializer(customSerializer, instanceClass,
191           instance);
192     } else {
193       deserializeWithDefaultFieldDeserializer(instanceClass, instance);
194     }
195   }
196
197   private void deserializeStringTable() {
198     int typeNameCount = readInt();
199     stringTable = new String JavaDoc[typeNameCount];
200     for (int typeNameIndex = 0; typeNameIndex < typeNameCount; ++typeNameIndex) {
201       stringTable[typeNameIndex] = extract();
202     }
203   }
204
205   private void deserializeWithCustomFieldDeserializer(Class JavaDoc customSerializer,
206       Class JavaDoc instanceClass, Object JavaDoc instance) throws ClassNotFoundException JavaDoc,
207       NoSuchMethodException JavaDoc, IllegalAccessException JavaDoc, InvocationTargetException JavaDoc {
208     if (instanceClass.isArray()) {
209       Class JavaDoc componentType = instanceClass.getComponentType();
210       if (!componentType.isPrimitive()) {
211         instanceClass = Class.forName("[Ljava.lang.Object;");
212       }
213     }
214     Method JavaDoc deserialize = customSerializer.getMethod("deserialize", new Class JavaDoc[] {
215         SerializationStreamReader.class, instanceClass});
216     deserialize.invoke(null, new Object JavaDoc[] {this, instance});
217   }
218
219   private void deserializeWithDefaultFieldDeserializer(Class JavaDoc instanceClass,
220       Object JavaDoc instance) throws SerializationException, IllegalAccessException JavaDoc,
221       NoSuchMethodException JavaDoc, InvocationTargetException JavaDoc, ClassNotFoundException JavaDoc {
222     Field JavaDoc[] declFields = instanceClass.getDeclaredFields();
223     Field JavaDoc[] serializableFields = serializableTypeOracle.applyFieldSerializationPolicy(declFields);
224
225     for (int index = 0; index < serializableFields.length; ++index) {
226       Field JavaDoc declField = serializableFields[index];
227       assert (declField != null);
228
229       Object JavaDoc value = deserializeValue(declField.getType());
230
231       boolean isAccessible = declField.isAccessible();
232       boolean needsAccessOverride = !isAccessible
233           && !Modifier.isPublic(declField.getModifiers());
234       if (needsAccessOverride) {
235         // Override access restrictions
236
declField.setAccessible(true);
237       }
238
239       declField.set(instance, value);
240
241       if (needsAccessOverride) {
242         // Restore access restrictions
243
declField.setAccessible(isAccessible);
244       }
245     }
246
247     Class JavaDoc superClass = instanceClass.getSuperclass();
248     if (superClass != null && serializableTypeOracle.isSerializable(superClass)) {
249       deserializeImpl(
250           serializableTypeOracle.hasCustomFieldSerializer(superClass),
251           superClass, instance);
252     }
253   }
254
255   private String JavaDoc extract() {
256     return (String JavaDoc) tokenList.get(tokenListIndex++);
257   }
258
259   private Object JavaDoc instantiate(Class JavaDoc customSerializer, Class JavaDoc instanceClass)
260       throws InstantiationException JavaDoc, IllegalAccessException JavaDoc,
261       IllegalArgumentException JavaDoc, InvocationTargetException JavaDoc {
262     if (customSerializer != null) {
263       try {
264         Method JavaDoc instantiate = customSerializer.getMethod("instantiate",
265             new Class JavaDoc[] {SerializationStreamReader.class});
266         return instantiate.invoke(null, new Object JavaDoc[] {this});
267       } catch (NoSuchMethodException JavaDoc e) {
268         // purposely ignored
269
}
270     }
271
272     if (instanceClass.isArray()) {
273       int length = readInt();
274       Class JavaDoc componentType = instanceClass.getComponentType();
275       return Array.newInstance(componentType, length);
276     } else {
277       return instanceClass.newInstance();
278     }
279   }
280
281   private void validateTypeVersions(Class JavaDoc instanceClass,
282       SerializedInstanceReference serializedInstRef)
283       throws SerializationException {
284     String JavaDoc clientTypeSignature = serializedInstRef.getSignature();
285     if (clientTypeSignature.length() == 0) {
286       if (shouldEnforceTypeVersioning()) {
287         throw new SerializationException("Missing type signature for "
288             + instanceClass.getName());
289       }
290
291       return;
292     }
293
294     String JavaDoc serverTypeSignature = serializableTypeOracle.getSerializationSignature(instanceClass);
295
296     if (!clientTypeSignature.equals(serverTypeSignature)) {
297       throw new SerializationException("Invalid type signature for "
298           + instanceClass.getName());
299     }
300   }
301 }
302
Popular Tags