KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > hessian > io > JavaDeserializer


1 /*
2  * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved.
3  *
4  * The Apache Software License, Version 1.1
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in
15  * the documentation and/or other materials provided with the
16  * distribution.
17  *
18  * 3. The end-user documentation included with the redistribution, if
19  * any, must include the following acknowlegement:
20  * "This product includes software developed by the
21  * Caucho Technology (http://www.caucho.com/)."
22  * Alternately, this acknowlegement may appear in the software itself,
23  * if and wherever such third-party acknowlegements normally appear.
24  *
25  * 4. The names "Burlap", "Resin", and "Caucho" must not be used to
26  * endorse or promote products derived from this software without prior
27  * written permission. For written permission, please contact
28  * info@caucho.com.
29  *
30  * 5. Products derived from this software may not be called "Resin"
31  * nor may "Resin" appear in their names without prior written
32  * permission of Caucho Technology.
33  *
34  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
35  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
36  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
37  * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS
38  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
39  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
40  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
41  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
42  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
43  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
44  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45  *
46  * @author Scott Ferguson
47  */

48
49 package com.caucho.hessian.io;
50
51 import java.io.IOException JavaDoc;
52 import java.lang.reflect.Constructor JavaDoc;
53 import java.lang.reflect.Field JavaDoc;
54 import java.lang.reflect.InvocationTargetException JavaDoc;
55 import java.lang.reflect.Method JavaDoc;
56 import java.lang.reflect.Modifier JavaDoc;
57 import java.util.HashMap JavaDoc;
58
59 /**
60  * Serializing an object for known object types.
61  */

62 public class JavaDeserializer extends AbstractMapDeserializer {
63   private Class JavaDoc _type;
64   private HashMap JavaDoc _fieldMap;
65   private Method JavaDoc _readResolve;
66   private Constructor JavaDoc _constructor;
67   private Object JavaDoc []_constructorArgs;
68   
69   public JavaDeserializer(Class JavaDoc cl)
70   {
71     _type = cl;
72     _fieldMap = getFieldMap(cl);
73
74     _readResolve = getReadResolve(cl);
75
76     if (_readResolve != null) {
77       _readResolve.setAccessible(true);
78     }
79
80     Constructor JavaDoc []constructors = cl.getDeclaredConstructors();
81     long bestCost = Long.MAX_VALUE;
82
83     for (int i = 0; i < constructors.length; i++) {
84       Class JavaDoc []param = constructors[i].getParameterTypes();
85       long cost = 0;
86
87       for (int j = 0; j < param.length; j++) {
88     cost = 4 * cost;
89
90     if (Object JavaDoc.class.equals(param[j]))
91       cost += 1;
92     else if (String JavaDoc.class.equals(param[j]))
93       cost += 2;
94     else if (int.class.equals(param[j]))
95       cost += 3;
96     else if (long.class.equals(param[j]))
97       cost += 4;
98     else if (param[j].isPrimitive())
99       cost += 5;
100     else
101       cost += 6;
102       }
103
104       if (cost < 0 || cost > (1 << 48))
105     cost = 1 << 48;
106
107       cost += param.length << 48;
108
109       if (cost < bestCost) {
110         _constructor = constructors[i];
111         bestCost = cost;
112       }
113     }
114
115     if (_constructor != null) {
116       _constructor.setAccessible(true);
117       Class JavaDoc []params = _constructor.getParameterTypes();
118       _constructorArgs = new Object JavaDoc[params.length];
119       for (int i = 0; i < params.length; i++) {
120         _constructorArgs[i] = getParamArg(params[i]);
121       }
122     }
123   }
124
125   public Class JavaDoc getType()
126   {
127     return _type;
128   }
129     
130   public Object JavaDoc readMap(AbstractHessianInput in)
131     throws IOException JavaDoc
132   {
133     try {
134       Object JavaDoc obj = instantiate();
135
136       return readMap(in, obj);
137     } catch (IOException JavaDoc e) {
138       throw e;
139     } catch (RuntimeException JavaDoc e) {
140       throw e;
141     } catch (Exception JavaDoc e) {
142       throw new IOExceptionWrapper(_type.getName() + ":" + e.getMessage(), e);
143     }
144   }
145     
146   public Object JavaDoc readObject(AbstractHessianInput in, String JavaDoc []fieldNames)
147     throws IOException JavaDoc
148   {
149     try {
150       Object JavaDoc obj = instantiate();
151
152       return readObject(in, obj, fieldNames);
153     } catch (IOException JavaDoc e) {
154       throw e;
155     } catch (RuntimeException JavaDoc e) {
156       throw e;
157     } catch (Exception JavaDoc e) {
158       throw new IOExceptionWrapper(_type.getName() + ":" + e.getMessage(), e);
159     }
160   }
161
162   /**
163    * Returns the readResolve method
164    */

165   protected Method JavaDoc getReadResolve(Class JavaDoc cl)
166   {
167     for (; cl != null; cl = cl.getSuperclass()) {
168       Method JavaDoc []methods = cl.getDeclaredMethods();
169       
170       for (int i = 0; i < methods.length; i++) {
171     Method JavaDoc method = methods[i];
172
173     if (method.getName().equals("readResolve") &&
174         method.getParameterTypes().length == 0)
175       return method;
176       }
177     }
178
179     return null;
180   }
181     
182   public Object JavaDoc readMap(AbstractHessianInput in, Object JavaDoc obj)
183     throws IOException JavaDoc
184   {
185     try {
186       int ref = in.addRef(obj);
187
188       while (! in.isEnd()) {
189         Object JavaDoc key = in.readObject();
190         
191         FieldDeserializer deser = (FieldDeserializer) _fieldMap.get(key);
192
193         if (deser != null)
194       deser.deserialize(in, obj);
195         else
196           in.readObject();
197       }
198       
199       in.readMapEnd();
200
201       Object JavaDoc resolve = resolve(obj);
202
203       if (obj != resolve)
204     in.setRef(ref, resolve);
205
206       return resolve;
207     } catch (IOException JavaDoc e) {
208       throw e;
209     } catch (Exception JavaDoc e) {
210       throw new IOExceptionWrapper(e);
211     }
212   }
213     
214   public Object JavaDoc readObject(AbstractHessianInput in,
215                Object JavaDoc obj,
216                String JavaDoc []fieldNames)
217     throws IOException JavaDoc
218   {
219     try {
220       int ref = in.addRef(obj);
221
222       for (int i = 0; i < fieldNames.length; i++) {
223         String JavaDoc name = fieldNames[i];
224         
225         FieldDeserializer deser = (FieldDeserializer) _fieldMap.get(name);
226
227         if (deser != null)
228       deser.deserialize(in, obj);
229         else
230           in.readObject();
231       }
232
233       Object JavaDoc resolve = resolve(obj);
234
235       if (obj != resolve)
236     in.setRef(ref, resolve);
237
238       return resolve;
239     } catch (IOException JavaDoc e) {
240       throw e;
241     } catch (Exception JavaDoc e) {
242       throw new IOExceptionWrapper(obj.getClass().getName() + ":" + e, e);
243     }
244   }
245
246   private Object JavaDoc resolve(Object JavaDoc obj)
247     throws Exception JavaDoc
248   {
249     // if there's a readResolve method, call it
250
try {
251       if (_readResolve != null)
252         return _readResolve.invoke(obj, new Object JavaDoc[0]);
253     } catch (InvocationTargetException JavaDoc e) {
254       if (e.getTargetException() != null)
255     throw e;
256     }
257
258     return obj;
259   }
260
261   protected Object JavaDoc instantiate()
262     throws Exception JavaDoc
263   {
264     if (_constructor != null)
265       return _constructor.newInstance(_constructorArgs);
266     else
267       return _type.newInstance();
268   }
269
270   /**
271    * Creates a map of the classes fields.
272    */

273   protected HashMap JavaDoc getFieldMap(Class JavaDoc cl)
274   {
275     HashMap JavaDoc fieldMap = new HashMap JavaDoc();
276     
277     for (; cl != null; cl = cl.getSuperclass()) {
278       Field JavaDoc []fields = cl.getDeclaredFields();
279       for (int i = 0; i < fields.length; i++) {
280         Field JavaDoc field = fields[i];
281
282         if (Modifier.isTransient(field.getModifiers()) ||
283             Modifier.isStatic(field.getModifiers()))
284           continue;
285         else if (fieldMap.get(field.getName()) != null)
286           continue;
287
288         // XXX: could parameterize the handler to only deal with public
289
try {
290           field.setAccessible(true);
291         } catch (Throwable JavaDoc e) {
292           e.printStackTrace();
293         }
294
295     Class JavaDoc type = field.getType();
296     FieldDeserializer deser;
297
298     if (String JavaDoc.class.equals(type))
299       deser = new StringFieldDeserializer(field);
300     else if (byte.class.equals(type)) {
301       deser = new ByteFieldDeserializer(field);
302     }
303     else if (short.class.equals(type)) {
304       deser = new ShortFieldDeserializer(field);
305     }
306     else if (int.class.equals(type)) {
307       deser = new IntFieldDeserializer(field);
308     }
309     else if (long.class.equals(type)) {
310       deser = new LongFieldDeserializer(field);
311     }
312     else if (float.class.equals(type)) {
313       deser = new FloatFieldDeserializer(field);
314     }
315     else if (double.class.equals(type)) {
316       deser = new DoubleFieldDeserializer(field);
317     }
318     else if (boolean.class.equals(type)) {
319       deser = new BooleanFieldDeserializer(field);
320     }
321     else {
322       deser = new ObjectFieldDeserializer(field);
323     }
324
325         fieldMap.put(field.getName(), deser);
326       }
327     }
328
329     return fieldMap;
330   }
331
332   /**
333    * Creates a map of the classes fields.
334    */

335   protected static Object JavaDoc getParamArg(Class JavaDoc cl)
336   {
337     if (! cl.isPrimitive())
338       return null;
339     else if (boolean.class.equals(cl))
340       return Boolean.FALSE;
341     else if (byte.class.equals(cl))
342       return new Byte JavaDoc((byte) 0);
343     else if (short.class.equals(cl))
344       return new Short JavaDoc((short) 0);
345     else if (char.class.equals(cl))
346       return new Character JavaDoc((char) 0);
347     else if (int.class.equals(cl))
348       return new Integer JavaDoc(0);
349     else if (long.class.equals(cl))
350       return new Long JavaDoc(0);
351     else if (float.class.equals(cl))
352       return new Float JavaDoc(0);
353     else if (double.class.equals(cl))
354       return new Double JavaDoc(0);
355     else
356       throw new UnsupportedOperationException JavaDoc();
357   }
358
359   abstract static class FieldDeserializer {
360     abstract void deserialize(AbstractHessianInput in, Object JavaDoc obj)
361       throws IOException JavaDoc;
362   }
363
364   static class ObjectFieldDeserializer extends FieldDeserializer {
365     private final Field JavaDoc _field;
366
367     ObjectFieldDeserializer(Field JavaDoc field)
368     {
369       _field = field;
370     }
371     
372     void deserialize(AbstractHessianInput in, Object JavaDoc obj)
373       throws IOException JavaDoc
374     {
375       Object JavaDoc value = in.readObject(_field.getType());
376     
377       try {
378     _field.set(obj, value);
379       } catch (IllegalAccessException JavaDoc e) {
380     // XXX: log when available
381
}
382     }
383   }
384
385   static class BooleanFieldDeserializer extends FieldDeserializer {
386     private final Field JavaDoc _field;
387
388     BooleanFieldDeserializer(Field JavaDoc field)
389     {
390       _field = field;
391     }
392     
393     void deserialize(AbstractHessianInput in, Object JavaDoc obj)
394       throws IOException JavaDoc
395     {
396       boolean value = in.readBoolean();
397     
398       try {
399     _field.setBoolean(obj, value);
400       } catch (IllegalAccessException JavaDoc e) {
401     // XXX: log when available
402
}
403     }
404   }
405
406   static class ByteFieldDeserializer extends FieldDeserializer {
407     private final Field JavaDoc _field;
408
409     ByteFieldDeserializer(Field JavaDoc field)
410     {
411       _field = field;
412     }
413     
414     void deserialize(AbstractHessianInput in, Object JavaDoc obj)
415       throws IOException JavaDoc
416     {
417       int value = in.readInt();
418     
419       try {
420     _field.setByte(obj, (byte) value);
421       } catch (IllegalAccessException JavaDoc e) {
422     // XXX: log when available
423
}
424     }
425   }
426
427   static class ShortFieldDeserializer extends FieldDeserializer {
428     private final Field JavaDoc _field;
429
430     ShortFieldDeserializer(Field JavaDoc field)
431     {
432       _field = field;
433     }
434     
435     void deserialize(AbstractHessianInput in, Object JavaDoc obj)
436       throws IOException JavaDoc
437     {
438       int value = in.readInt();
439     
440       try {
441     _field.setShort(obj, (short) value);
442       } catch (IllegalAccessException JavaDoc e) {
443     // XXX: log when available
444
}
445     }
446   }
447
448   static class IntFieldDeserializer extends FieldDeserializer {
449     private final Field JavaDoc _field;
450
451     IntFieldDeserializer(Field JavaDoc field)
452     {
453       _field = field;
454     }
455     
456     void deserialize(AbstractHessianInput in, Object JavaDoc obj)
457       throws IOException JavaDoc
458     {
459       int value = in.readInt();
460     
461       try {
462     _field.setInt(obj, value);
463       } catch (IllegalAccessException JavaDoc e) {
464     // XXX: log when available
465
}
466     }
467   }
468
469   static class LongFieldDeserializer extends FieldDeserializer {
470     private final Field JavaDoc _field;
471
472     LongFieldDeserializer(Field JavaDoc field)
473     {
474       _field = field;
475     }
476     
477     void deserialize(AbstractHessianInput in, Object JavaDoc obj)
478       throws IOException JavaDoc
479     {
480       long value = in.readLong();
481     
482       try {
483     _field.setLong(obj, value);
484       } catch (IllegalAccessException JavaDoc e) {
485     // XXX: log when available
486
}
487     }
488   }
489
490   static class FloatFieldDeserializer extends FieldDeserializer {
491     private final Field JavaDoc _field;
492
493     FloatFieldDeserializer(Field JavaDoc field)
494     {
495       _field = field;
496     }
497     
498     void deserialize(AbstractHessianInput in, Object JavaDoc obj)
499       throws IOException JavaDoc
500     {
501       double value = in.readDouble();
502     
503       try {
504     _field.setFloat(obj, (float) value);
505       } catch (IllegalAccessException JavaDoc e) {
506     // XXX: log when available
507
}
508     }
509   }
510
511   static class DoubleFieldDeserializer extends FieldDeserializer {
512     private final Field JavaDoc _field;
513
514     DoubleFieldDeserializer(Field JavaDoc field)
515     {
516       _field = field;
517     }
518     
519     void deserialize(AbstractHessianInput in, Object JavaDoc obj)
520       throws IOException JavaDoc
521     {
522       double value = in.readDouble();
523     
524       try {
525     _field.setDouble(obj, value);
526       } catch (IllegalAccessException JavaDoc e) {
527     // XXX: log when available
528
}
529     }
530   }
531
532   static class StringFieldDeserializer extends FieldDeserializer {
533     private final Field JavaDoc _field;
534
535     StringFieldDeserializer(Field JavaDoc field)
536     {
537       _field = field;
538     }
539     
540     void deserialize(AbstractHessianInput in, Object JavaDoc obj)
541       throws IOException JavaDoc
542     {
543       String JavaDoc value = in.readString();
544     
545       try {
546     _field.set(obj, value);
547       } catch (IllegalAccessException JavaDoc e) {
548     // XXX: log when available
549
}
550     }
551   }
552 }
553
Popular Tags