KickJava   Java API By Example, From Geeks To Geeks.

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


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.Method JavaDoc;
54 import java.lang.reflect.Modifier JavaDoc;
55 import java.util.HashMap JavaDoc;
56
57 /**
58  * Serializing an object for known object types.
59  */

60 public class BeanDeserializer extends AbstractMapDeserializer {
61   private Class JavaDoc _type;
62   private HashMap JavaDoc _methodMap;
63   private Method JavaDoc _readResolve;
64   private Constructor JavaDoc _constructor;
65   private Object JavaDoc []_constructorArgs;
66   
67   public BeanDeserializer(Class JavaDoc cl)
68   {
69     _type = cl;
70     _methodMap = getMethodMap(cl);
71
72     _readResolve = getReadResolve(cl);
73
74     Constructor JavaDoc []constructors = cl.getConstructors();
75     int bestLength = Integer.MAX_VALUE;
76     
77     for (int i = 0; i < constructors.length; i++) {
78       if (constructors[i].getParameterTypes().length < bestLength) {
79         _constructor = constructors[i];
80         bestLength = _constructor.getParameterTypes().length;
81       }
82     }
83
84     if (_constructor != null) {
85       _constructor.setAccessible(true);
86       Class JavaDoc []params = _constructor.getParameterTypes();
87       _constructorArgs = new Object JavaDoc[params.length];
88       for (int i = 0; i < params.length; i++) {
89         _constructorArgs[i] = getParamArg(params[i]);
90       }
91     }
92   }
93
94   public Class JavaDoc getType()
95   {
96     return _type;
97   }
98     
99   public Object JavaDoc readMap(AbstractHessianInput in)
100     throws IOException JavaDoc
101   {
102     try {
103       Object JavaDoc obj = instantiate();
104
105       return readMap(in, obj);
106     } catch (IOException JavaDoc e) {
107       throw e;
108     } catch (Exception JavaDoc e) {
109       throw new IOExceptionWrapper(e);
110     }
111   }
112     
113   public Object JavaDoc readMap(AbstractHessianInput in, Object JavaDoc obj)
114     throws IOException JavaDoc
115   {
116     try {
117       int ref = in.addRef(obj);
118
119       while (! in.isEnd()) {
120         Object JavaDoc key = in.readObject();
121         
122         Method JavaDoc method = (Method JavaDoc) _methodMap.get(key);
123
124         if (method != null) {
125           Object JavaDoc value = in.readObject(method.getParameterTypes()[0]);
126       
127           method.invoke(obj, new Object JavaDoc[] {value });
128         }
129         else {
130           Object JavaDoc value = in.readObject();
131         }
132       }
133       
134       in.readMapEnd();
135
136       Object JavaDoc resolve = resolve(obj);
137
138       if (obj != resolve)
139     in.setRef(ref, resolve);
140
141       return resolve;
142     } catch (IOException JavaDoc e) {
143       throw e;
144     } catch (Exception JavaDoc e) {
145       throw new IOExceptionWrapper(e);
146     }
147   }
148
149   private Object JavaDoc resolve(Object JavaDoc obj)
150   {
151     // if there's a readResolve method, call it
152
try {
153       if (_readResolve != null)
154         return _readResolve.invoke(obj, new Object JavaDoc[0]);
155     } catch (Exception JavaDoc e) {
156     }
157
158     return obj;
159   }
160
161   protected Object JavaDoc instantiate()
162     throws Exception JavaDoc
163   {
164     return _constructor.newInstance(_constructorArgs);
165   }
166
167   /**
168    * Returns the readResolve method
169    */

170   protected Method JavaDoc getReadResolve(Class JavaDoc cl)
171   {
172     for (; cl != null; cl = cl.getSuperclass()) {
173       Method JavaDoc []methods = cl.getDeclaredMethods();
174       
175       for (int i = 0; i < methods.length; i++) {
176     Method JavaDoc method = methods[i];
177
178     if (method.getName().equals("readResolve") &&
179         method.getParameterTypes().length == 0)
180       return method;
181       }
182     }
183
184     return null;
185   }
186
187   /**
188    * Creates a map of the classes fields.
189    */

190   protected HashMap JavaDoc getMethodMap(Class JavaDoc cl)
191   {
192     HashMap JavaDoc methodMap = new HashMap JavaDoc();
193     
194     for (; cl != null; cl = cl.getSuperclass()) {
195       Method JavaDoc []methods = cl.getDeclaredMethods();
196       
197       for (int i = 0; i < methods.length; i++) {
198     Method JavaDoc method = methods[i];
199
200     if (Modifier.isStatic(method.getModifiers()))
201       continue;
202
203     String JavaDoc name = method.getName();
204
205     if (! name.startsWith("set"))
206       continue;
207
208     Class JavaDoc []paramTypes = method.getParameterTypes();
209     if (paramTypes.length != 1)
210       continue;
211
212     if (! method.getReturnType().equals(void.class))
213       continue;
214
215     if (findGetter(methods, name, paramTypes[0]) == null)
216       continue;
217
218     // XXX: could parameterize the handler to only deal with public
219
try {
220       method.setAccessible(true);
221     } catch (Throwable JavaDoc e) {
222       e.printStackTrace();
223     }
224     
225     name = name.substring(3);
226
227     int j = 0;
228     for (; j < name.length() && Character.isUpperCase(name.charAt(j)); j++) {
229     }
230
231     if (j == 1)
232       name = name.substring(0, j).toLowerCase() + name.substring(j);
233     else if (j > 1)
234       name = name.substring(0, j - 1).toLowerCase() + name.substring(j - 1);
235
236
237     methodMap.put(name, method);
238       }
239     }
240
241     return methodMap;
242   }
243
244   /**
245    * Finds any matching setter.
246    */

247   private Method JavaDoc findGetter(Method JavaDoc []methods, String JavaDoc setterName, Class JavaDoc arg)
248   {
249     String JavaDoc getterName = "get" + setterName.substring(3);
250     
251     for (int i = 0; i < methods.length; i++) {
252       Method JavaDoc method = methods[i];
253
254       if (! method.getName().equals(getterName))
255     continue;
256       
257       if (! method.getReturnType().equals(arg))
258     continue;
259
260       Class JavaDoc []params = method.getParameterTypes();
261
262       if (params.length == 0)
263     return method;
264     }
265
266     return null;
267   }
268
269   /**
270    * Creates a map of the classes fields.
271    */

272   protected static Object JavaDoc getParamArg(Class JavaDoc cl)
273   {
274     if (! cl.isPrimitive())
275       return null;
276     else if (boolean.class.equals(cl))
277       return Boolean.FALSE;
278     else if (byte.class.equals(cl))
279       return new Byte JavaDoc((byte) 0);
280     else if (short.class.equals(cl))
281       return new Short JavaDoc((short) 0);
282     else if (char.class.equals(cl))
283       return new Character JavaDoc((char) 0);
284     else if (int.class.equals(cl))
285       return new Integer JavaDoc(0);
286     else if (long.class.equals(cl))
287       return new Long JavaDoc(0);
288     else if (float.class.equals(cl))
289       return new Double JavaDoc(0);
290     else if (double.class.equals(cl))
291       return new Double JavaDoc(0);
292     else
293       throw new UnsupportedOperationException JavaDoc();
294   }
295 }
296
Popular Tags