Frames | No Frames |
1: /** 2: * =================================================== 3: * JCommon-Serializer : a free serialization framework 4: * =================================================== 5: * 6: * Project Info: http://www.jfree.org/jfreereport/jcommon-serializer/ 7: * Project Lead: Thomas Morgner; 8: * 9: * (C) Copyright 2006, by Object Refinery Limited and Pentaho Corporation. 10: * 11: * This library is free software; you can redistribute it and/or modify it under the terms 12: * of the GNU Lesser General Public License as published by the Free Software Foundation; 13: * either version 2.1 of the License, or (at your option) any later version. 14: * 15: * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 16: * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 17: * See the GNU Lesser General Public License for more details. 18: * 19: * You should have received a copy of the GNU Lesser General Public License along with this 20: * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, 21: * Boston, MA 02111-1307, USA. 22: * 23: * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 24: * in the United States and other countries.] 25: * 26: * ------------ 27: * SerializerHelper.java 28: * ------------ 29: * (C) Copyright 2006, by Object Refinery Limited and Pentaho Corporation. 30: * 31: * Original Author: Thomas Morgner; 32: * Contributor(s): -; 33: * 34: * $Id: SerializerHelper.java 2429 2006-12-11 12:40:28Z taqua $ 35: * 36: * Changes 37: * ------- 38: * 39: * 40: */ 41: 42: package org.jfree.serializer; 43: 44: import java.io.IOException; 45: import java.io.NotSerializableException; 46: import java.io.ObjectInputStream; 47: import java.io.ObjectOutputStream; 48: import java.io.Serializable; 49: import java.util.HashMap; 50: import java.util.Iterator; 51: 52: import org.jfree.util.ClassComparator; 53: import org.jfree.util.Configuration; 54: import org.jfree.util.Log; 55: import org.jfree.util.ObjectUtilities; 56: 57: /** 58: * The SerializeHelper is used to make implementing custom serialization 59: * handlers easier. Handlers for certain object types need to be added to this 60: * helper before this implementation is usable. 61: * 62: * @author Thomas Morgner 63: */ 64: public class SerializerHelper 65: { 66: /** 67: * The singleton instance of the serialize helper. 68: */ 69: private static SerializerHelper singleton; 70: 71: /** 72: * Returns or creates a new SerializerHelper. When a new instance is created 73: * by this method, all known SerializeMethods are registered. 74: * 75: * @return the SerializerHelper singleton instance. 76: */ 77: public synchronized static SerializerHelper getInstance() 78: { 79: if (singleton == null) 80: { 81: singleton = new SerializerHelper(); 82: singleton.registerMethods(); 83: } 84: return singleton; 85: } 86: 87: 88: /** 89: * This method can be used to replace the singleton instance of this helper. 90: * 91: * @param helper the new instance of the serialize helper. 92: */ 93: protected static void setInstance(final SerializerHelper helper) 94: { 95: singleton = helper; 96: } 97: 98: /** 99: * A collection of the serializer methods. 100: */ 101: private final HashMap methods; 102: 103: /** 104: * A class comparator for searching the super class of an certain class. 105: */ 106: private final ClassComparator comparator; 107: 108: /** 109: * Creates a new SerializerHelper. 110: */ 111: protected SerializerHelper() 112: { 113: this.comparator = new ClassComparator(); 114: this.methods = new HashMap(); 115: } 116: 117: /** 118: * Registers a new SerializeMethod with this SerializerHelper. 119: * 120: * @param method the method that should be registered. 121: */ 122: public synchronized void registerMethod(final SerializeMethod method) 123: { 124: this.methods.put(method.getObjectClass(), method); 125: } 126: 127: protected void registerMethods() 128: { 129: final Configuration config = JCommonSerializerBoot.getInstance().getGlobalConfig(); 130: Iterator sit = config.findPropertyKeys("org.jfree.serializer.handler."); 131: 132: while (sit.hasNext()) 133: { 134: final String configkey = (String) sit.next(); 135: final String c = config.getConfigProperty(configkey); 136: Object maybeModule = ObjectUtilities.loadAndInstantiate 137: (c, SerializerHelper.class, SerializeMethod.class); 138: if (maybeModule != null) 139: { 140: SerializeMethod module = (SerializeMethod) maybeModule; 141: registerMethod(module); 142: } 143: else 144: { 145: Log.warn("Invalid SerializeMethod implementation: " + c); 146: } 147: } 148: } 149: 150: /** 151: * Deregisters a new SerializeMethod with this SerializerHelper. 152: * 153: * @param method the method that should be deregistered. 154: */ 155: public synchronized void unregisterMethod(final SerializeMethod method) 156: { 157: this.methods.remove(method.getObjectClass()); 158: } 159: 160: /** 161: * Returns the collection of all registered serialize methods. 162: * 163: * @return a collection of the registered serialize methods. 164: */ 165: protected HashMap getMethods() 166: { 167: return methods; 168: } 169: 170: /** 171: * Returns the class comparator instance used to find correct super classes. 172: * 173: * @return the class comparator. 174: */ 175: protected ClassComparator getComparator() 176: { 177: return comparator; 178: } 179: 180: /** 181: * Looks up the SerializeMethod for the given class or null if there is no 182: * SerializeMethod for the given class. 183: * 184: * @param c the class for which we want to lookup a serialize method. 185: * @return the method or null, if there is no registered method for the 186: * class. 187: */ 188: protected SerializeMethod getSerializer(final Class c) 189: { 190: final SerializeMethod sm = (SerializeMethod) methods.get(c); 191: if (sm != null) 192: { 193: return sm; 194: } 195: return getSuperClassObjectDescription(c); 196: } 197: 198: /** 199: * Looks up the SerializeMethod for the given class or null if there is no 200: * SerializeMethod for the given class. This method searches all 201: * superclasses. 202: * 203: * @param d the class for which we want to lookup a serialize 204: * method. 205: * @param knownSuperClass the known super class, if any or null. 206: * @return the method or null, if there is no registered method for the 207: * class. 208: */ 209: protected SerializeMethod getSuperClassObjectDescription 210: (final Class d) 211: { 212: SerializeMethod knownSuperClass = null; 213: final Iterator keys = methods.keySet().iterator(); 214: while (keys.hasNext()) 215: { 216: final Class keyClass = (Class) keys.next(); 217: if (keyClass.isAssignableFrom(d)) 218: { 219: final SerializeMethod od = (SerializeMethod) methods.get(keyClass); 220: if (knownSuperClass == null) 221: { 222: knownSuperClass = od; 223: } 224: else 225: { 226: if (comparator.isComparable 227: (knownSuperClass.getObjectClass(), od.getObjectClass())) 228: { 229: if (comparator.compare 230: (knownSuperClass.getObjectClass(), od.getObjectClass()) < 0) 231: { 232: knownSuperClass = od; 233: } 234: } 235: } 236: } 237: } 238: return knownSuperClass; 239: } 240: 241: 242: /** 243: * Writes a serializable object description to the given object output stream. 244: * This method selects the best serialize helper method for the given object. 245: * 246: * @param o the to be serialized object. 247: * @param out the outputstream that should receive the object. 248: * @throws IOException if an I/O error occured. 249: */ 250: public synchronized void writeObject(final Object o, 251: final ObjectOutputStream out) 252: throws IOException 253: { 254: if (o == null) 255: { 256: out.writeByte(0); 257: return; 258: } 259: if (o instanceof Serializable) 260: { 261: out.writeByte(1); 262: out.writeObject(o); 263: return; 264: } 265: 266: final SerializeMethod m = getSerializer(o.getClass()); 267: if (m == null) 268: { 269: throw new NotSerializableException(o.getClass().getName()); 270: } 271: out.writeByte(2); 272: out.writeObject(m.getObjectClass()); 273: m.writeObject(o, out); 274: } 275: 276: /** 277: * Reads the object from the object input stream. This object selects the best 278: * serializer to read the object. 279: * <p/> 280: * Make sure, that you use the same configuration (library and class versions, 281: * registered methods in the SerializerHelper) for reading as you used for 282: * writing. 283: * 284: * @param in the object input stream from where to read the serialized data. 285: * @return the generated object. 286: * @throws IOException if reading the stream failed. 287: * @throws ClassNotFoundException if serialized object class cannot be found. 288: */ 289: public synchronized Object readObject(final ObjectInputStream in) 290: throws IOException, ClassNotFoundException 291: { 292: final int type = in.readByte(); 293: if (type == 0) 294: { 295: return null; 296: } 297: if (type == 1) 298: { 299: return in.readObject(); 300: } 301: final Class c = (Class) in.readObject(); 302: final SerializeMethod m = getSerializer(c); 303: if (m == null) 304: { 305: throw new NotSerializableException(c.getName()); 306: } 307: return m.readObject(in); 308: } 309: }