001: /*
002: * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved.
003: *
004: * The Apache Software License, Version 1.1
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * 1. Redistributions of source code must retain the above copyright
011: * notice, this list of conditions and the following disclaimer.
012: *
013: * 2. Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in
015: * the documentation and/or other materials provided with the
016: * distribution.
017: *
018: * 3. The end-user documentation included with the redistribution, if
019: * any, must include the following acknowlegement:
020: * "This product includes software developed by the
021: * Caucho Technology (http://www.caucho.com/)."
022: * Alternately, this acknowlegement may appear in the software itself,
023: * if and wherever such third-party acknowlegements normally appear.
024: *
025: * 4. The names "Burlap", "Resin", and "Caucho" must not be used to
026: * endorse or promote products derived from this software without prior
027: * written permission. For written permission, please contact
028: * info@caucho.com.
029: *
030: * 5. Products derived from this software may not be called "Resin"
031: * nor may "Resin" appear in their names without prior written
032: * permission of Caucho Technology.
033: *
034: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
035: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
036: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
037: * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS
038: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
039: * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
040: * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
041: * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
042: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
043: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
044: * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
045: *
046: * @author Scott Ferguson
047: */
048:
049: package com.caucho.hessian.io;
050:
051: import java.io.IOException;
052: import java.io.Serializable;
053: import java.lang.reflect.Field;
054: import java.lang.reflect.Method;
055: import java.lang.reflect.Modifier;
056: import java.util.ArrayList;
057: import java.util.logging.Level;
058: import java.util.logging.Logger;
059:
060: /**
061: * Serializing an object for known object types.
062: */
063: public class JavaSerializer extends AbstractSerializer {
064: private static final Logger log = Logger
065: .getLogger(JavaSerializer.class.getName());
066:
067: private static Object[] NULL_ARGS = new Object[0];
068:
069: private Field[] _fields;
070: private FieldSerializer[] _fieldSerializers;
071: private Method _writeReplace;
072:
073: public JavaSerializer(Class cl) {
074: _writeReplace = getWriteReplace(cl);
075: if (_writeReplace != null)
076: _writeReplace.setAccessible(true);
077:
078: ArrayList primitiveFields = new ArrayList();
079: ArrayList compoundFields = new ArrayList();
080:
081: for (; cl != null; cl = cl.getSuperclass()) {
082: Field[] fields = cl.getDeclaredFields();
083: for (int i = 0; i < fields.length; i++) {
084: Field field = fields[i];
085:
086: if (Modifier.isTransient(field.getModifiers())
087: || Modifier.isStatic(field.getModifiers()))
088: continue;
089:
090: // XXX: could parameterize the handler to only deal with public
091: field.setAccessible(true);
092:
093: if (field.getType().isPrimitive()
094: || (field.getType().getName().startsWith(
095: "java.lang.") && !field.getType()
096: .equals(Object.class)))
097: primitiveFields.add(field);
098: else
099: compoundFields.add(field);
100: }
101: }
102:
103: ArrayList fields = new ArrayList();
104: fields.addAll(primitiveFields);
105: fields.addAll(compoundFields);
106:
107: _fields = new Field[fields.size()];
108: fields.toArray(_fields);
109:
110: _fieldSerializers = new FieldSerializer[_fields.length];
111:
112: for (int i = 0; i < _fields.length; i++) {
113: _fieldSerializers[i] = getFieldSerializer(_fields[i]
114: .getType());
115: }
116: }
117:
118: /**
119: * Returns the writeReplace method
120: */
121: public static Method getWriteReplace(Class cl) {
122: for (; cl != null; cl = cl.getSuperclass()) {
123: Method[] methods = cl.getDeclaredMethods();
124:
125: for (int i = 0; i < methods.length; i++) {
126: Method method = methods[i];
127:
128: if (method.getName().equals("writeReplace")
129: && method.getParameterTypes().length == 0)
130: return method;
131: }
132: }
133:
134: return null;
135: }
136:
137: public void writeObject(Object obj, AbstractHessianOutput out)
138: throws IOException {
139: if (out.addRef(obj)) {
140: return;
141: }
142:
143: Class cl = obj.getClass();
144:
145: try {
146: if (_writeReplace != null) {
147: Object repl = _writeReplace.invoke(obj, NULL_ARGS);
148:
149: out.removeRef(obj);
150:
151: out.writeObject(repl);
152:
153: out.replaceRef(repl, obj);
154:
155: return;
156: }
157: } catch (RuntimeException e) {
158: throw e;
159: } catch (Exception e) {
160: // log.log(Level.FINE, e.toString(), e);
161: throw new RuntimeException(e);
162: }
163:
164: int ref = out.writeObjectBegin(cl.getName());
165:
166: if (ref < -1) {
167: writeObject10(obj, out);
168: } else {
169: if (ref == -1) {
170: writeDefinition20(out);
171: out.writeObjectBegin(cl.getName());
172: }
173:
174: writeInstance(obj, out);
175: }
176: }
177:
178: private void writeObject10(Object obj, AbstractHessianOutput out)
179: throws IOException {
180: for (int i = 0; i < _fields.length; i++) {
181: Field field = _fields[i];
182:
183: out.writeString(field.getName());
184:
185: _fieldSerializers[i].serialize(out, obj, field);
186: }
187:
188: out.writeMapEnd();
189: }
190:
191: private void writeDefinition20(AbstractHessianOutput out)
192: throws IOException {
193: out.writeClassFieldLength(_fields.length);
194:
195: for (int i = 0; i < _fields.length; i++) {
196: Field field = _fields[i];
197:
198: out.writeString(field.getName());
199: }
200: }
201:
202: public void writeInstance(Object obj, AbstractHessianOutput out)
203: throws IOException {
204: for (int i = 0; i < _fields.length; i++) {
205: Field field = _fields[i];
206:
207: _fieldSerializers[i].serialize(out, obj, field);
208: }
209: }
210:
211: private static FieldSerializer getFieldSerializer(Class type) {
212: if (int.class.equals(type) || byte.class.equals(type)
213: || short.class.equals(type) || int.class.equals(type)) {
214: return IntFieldSerializer.SER;
215: } else if (long.class.equals(type)) {
216: return LongFieldSerializer.SER;
217: } else if (double.class.equals(type)
218: || float.class.equals(type)) {
219: return DoubleFieldSerializer.SER;
220: } else if (boolean.class.equals(type)) {
221: return BooleanFieldSerializer.SER;
222: } else if (String.class.equals(type)) {
223: return StringFieldSerializer.SER;
224: } else
225: return FieldSerializer.SER;
226: }
227:
228: static class FieldSerializer {
229: static final FieldSerializer SER = new FieldSerializer();
230:
231: void serialize(AbstractHessianOutput out, Object obj,
232: Field field) throws IOException {
233: Object value = null;
234:
235: try {
236: value = field.get(obj);
237: } catch (IllegalAccessException e) {
238: log.log(Level.FINE, e.toString(), e);
239: }
240:
241: out.writeObject(value);
242: }
243: }
244:
245: static class BooleanFieldSerializer extends FieldSerializer {
246: static final FieldSerializer SER = new BooleanFieldSerializer();
247:
248: void serialize(AbstractHessianOutput out, Object obj,
249: Field field) throws IOException {
250: boolean value = false;
251:
252: try {
253: value = field.getBoolean(obj);
254: } catch (IllegalAccessException e) {
255: log.log(Level.FINE, e.toString(), e);
256: }
257:
258: out.writeBoolean(value);
259: }
260: }
261:
262: static class IntFieldSerializer extends FieldSerializer {
263: static final FieldSerializer SER = new IntFieldSerializer();
264:
265: void serialize(AbstractHessianOutput out, Object obj,
266: Field field) throws IOException {
267: int value = 0;
268:
269: try {
270: value = field.getInt(obj);
271: } catch (IllegalAccessException e) {
272: log.log(Level.FINE, e.toString(), e);
273: }
274:
275: out.writeInt(value);
276: }
277: }
278:
279: static class LongFieldSerializer extends FieldSerializer {
280: static final FieldSerializer SER = new LongFieldSerializer();
281:
282: void serialize(AbstractHessianOutput out, Object obj,
283: Field field) throws IOException {
284: long value = 0;
285:
286: try {
287: value = field.getLong(obj);
288: } catch (IllegalAccessException e) {
289: log.log(Level.FINE, e.toString(), e);
290: }
291:
292: out.writeLong(value);
293: }
294: }
295:
296: static class DoubleFieldSerializer extends FieldSerializer {
297: static final FieldSerializer SER = new DoubleFieldSerializer();
298:
299: void serialize(AbstractHessianOutput out, Object obj,
300: Field field) throws IOException {
301: double value = 0;
302:
303: try {
304: value = field.getDouble(obj);
305: } catch (IllegalAccessException e) {
306: log.log(Level.FINE, e.toString(), e);
307: }
308:
309: out.writeDouble(value);
310: }
311: }
312:
313: static class StringFieldSerializer extends FieldSerializer {
314: static final FieldSerializer SER = new StringFieldSerializer();
315:
316: void serialize(AbstractHessianOutput out, Object obj,
317: Field field) throws IOException {
318: String value = null;
319:
320: try {
321: value = (String) field.get(obj);
322: } catch (IllegalAccessException e) {
323: log.log(Level.FINE, e.toString(), e);
324: }
325:
326: out.writeString(value);
327: }
328: }
329: }
|