KickJava   Java API By Example, From Geeks To Geeks.

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


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

59 public class BeanSerializer extends AbstractSerializer {
60   private Method JavaDoc []_methods;
61   private String JavaDoc []_names;
62   
63   private Method JavaDoc _writeReplace;
64   
65   public BeanSerializer(Class JavaDoc cl)
66   {
67     _writeReplace = getWriteReplace(cl);
68
69     ArrayList JavaDoc primitiveMethods = new ArrayList JavaDoc();
70     ArrayList JavaDoc compoundMethods = new ArrayList JavaDoc();
71     
72     for (; cl != null; cl = cl.getSuperclass()) {
73       Method JavaDoc []methods = cl.getDeclaredMethods();
74       
75       for (int i = 0; i < methods.length; i++) {
76     Method JavaDoc method = methods[i];
77
78     if (Modifier.isStatic(method.getModifiers()))
79       continue;
80
81     if (method.getParameterTypes().length != 0)
82       continue;
83
84     String JavaDoc name = method.getName();
85
86     if (! name.startsWith("get"))
87       continue;
88
89     Class JavaDoc type = method.getReturnType();
90
91     if (type.equals(void.class))
92       continue;
93
94     if (findSetter(methods, name, type) == null)
95       continue;
96
97     // XXX: could parameterize the handler to only deal with public
98
method.setAccessible(true);
99
100     if (type.isPrimitive() ||
101         type.getName().startsWith("java.lang.") &&
102         ! type.equals(Object JavaDoc.class))
103       primitiveMethods.add(method);
104     else
105       compoundMethods.add(method);
106       }
107     }
108
109     ArrayList JavaDoc methodList = new ArrayList JavaDoc();
110     methodList.addAll(primitiveMethods);
111     methodList.addAll(compoundMethods);
112
113     _methods = new Method JavaDoc[methodList.size()];
114     methodList.toArray(_methods);
115
116     _names = new String JavaDoc[_methods.length];
117     
118     for (int i = 0; i < _methods.length; i++) {
119       String JavaDoc name = _methods[i].getName();
120
121       name = name.substring(3);
122
123       int j = 0;
124       for (; j < name.length() && Character.isUpperCase(name.charAt(j)); j++) {
125       }
126
127       if (j == 1)
128     name = name.substring(0, j).toLowerCase() + name.substring(j);
129       else if (j > 1)
130     name = name.substring(0, j - 1).toLowerCase() + name.substring(j - 1);
131
132       _names[i] = name;
133     }
134   }
135
136   /**
137    * Returns the writeReplace method
138    */

139   protected Method JavaDoc getWriteReplace(Class JavaDoc cl)
140   {
141     for (; cl != null; cl = cl.getSuperclass()) {
142       Method JavaDoc []methods = cl.getDeclaredMethods();
143       
144       for (int i = 0; i < methods.length; i++) {
145     Method JavaDoc method = methods[i];
146
147     if (method.getName().equals("writeReplace") &&
148         method.getParameterTypes().length == 0)
149       return method;
150       }
151     }
152
153     return null;
154   }
155   
156   public void writeObject(Object JavaDoc obj, AbstractHessianOutput out)
157     throws IOException JavaDoc
158   {
159     if (out.addRef(obj))
160       return;
161     
162     Class JavaDoc cl = obj.getClass();
163     
164     try {
165       if (_writeReplace != null) {
166     Object JavaDoc repl = _writeReplace.invoke(obj, new Object JavaDoc[0]);
167
168     out.removeRef(obj);
169
170     out.writeObject(repl);
171
172     out.replaceRef(repl, obj);
173
174     return;
175       }
176     } catch (Exception JavaDoc e) {
177     }
178
179     int ref = out.writeObjectBegin(cl.getName());
180
181     if (ref < 0) {
182       // Hessian 1.1 uses a map
183

184       for (int i = 0; i < _methods.length; i++) {
185     Method JavaDoc method = _methods[i];
186     Object JavaDoc value = null;
187
188     try {
189       value = _methods[i].invoke(obj, (Object JavaDoc []) null);
190     } catch (Throwable JavaDoc e) {
191       // XXX: log when available
192
}
193
194     out.writeString(_names[i]);
195     
196     out.writeObject(value);
197       }
198       
199       out.writeMapEnd();
200     }
201     else {
202       if (ref == 0) {
203     out.writeInt(_names.length);
204     
205     for (int i = 0; i < _names.length; i++)
206       out.writeString(_names[i]);
207       }
208
209       for (int i = 0; i < _methods.length; i++) {
210     Method JavaDoc method = _methods[i];
211     Object JavaDoc value = null;
212
213     try {
214       value = _methods[i].invoke(obj, (Object JavaDoc []) null);
215     } catch (Throwable JavaDoc e) {
216       // log when available
217
}
218     
219     out.writeObject(value);
220       }
221     }
222   }
223
224   /**
225    * Finds any matching setter.
226    */

227   private Method JavaDoc findSetter(Method JavaDoc []methods, String JavaDoc getterName, Class JavaDoc arg)
228   {
229     String JavaDoc setterName = "set" + getterName.substring(3);
230     
231     for (int i = 0; i < methods.length; i++) {
232       Method JavaDoc method = methods[i];
233
234       if (! method.getName().equals(setterName))
235     continue;
236       
237       if (! method.getReturnType().equals(void.class))
238     continue;
239
240       Class JavaDoc []params = method.getParameterTypes();
241
242       if (params.length == 1 && params[0].equals(arg))
243     return method;
244     }
245
246     return null;
247   }
248 }
249
Popular Tags