1. /* ====================================================================
  2. * The Apache Software License, Version 1.1
  3. *
  4. * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
  5. * reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. *
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in
  16. * the documentation and/or other materials provided with the
  17. * distribution.
  18. *
  19. * 3. The end-user documentation included with the redistribution, if
  20. * any, must include the following acknowledgement:
  21. * "This product includes software developed by the
  22. * Apache Software Foundation (http://www.apache.org/)."
  23. * Alternately, this acknowledgement may appear in the software itself,
  24. * if and wherever such third-party acknowledgements normally appear.
  25. *
  26. * 4. The names "The Jakarta Project", "Commons", and "Apache Software
  27. * Foundation" must not be used to endorse or promote products derived
  28. * from this software without prior written permission. For written
  29. * permission, please contact apache@apache.org.
  30. *
  31. * 5. Products derived from this software may not be called "Apache"
  32. * nor may "Apache" appear in their names without prior written
  33. * permission of the Apache Software Foundation.
  34. *
  35. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  36. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  37. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  38. * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  39. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  41. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  42. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  43. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  44. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  45. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  46. * SUCH DAMAGE.
  47. * ====================================================================
  48. *
  49. * This software consists of voluntary contributions made by many
  50. * individuals on behalf of the Apache Software Foundation. For more
  51. * information on the Apache Software Foundation, please see
  52. * <http://www.apache.org/>.
  53. */
  54. package org.apache.commons.lang;
  55. import java.io.ByteArrayInputStream;
  56. import java.io.ByteArrayOutputStream;
  57. import java.io.IOException;
  58. import java.io.InputStream;
  59. import java.io.ObjectInputStream;
  60. import java.io.ObjectOutputStream;
  61. import java.io.OutputStream;
  62. import java.io.Serializable;
  63. /**
  64. * <p>Assists with the serialization process and performs additional functionality based
  65. * on serialization.</p>
  66. * <p>
  67. * <ul>
  68. * <li>Deep clone using serialization
  69. * <li>Serialize managing finally and IOException
  70. * <li>Deserialize managing finally and IOException
  71. * </ul>
  72. *
  73. * <p>This class throws exceptions for invalid <code>null</code> inputs.
  74. * Each method documents its behaviour in more detail.</p>
  75. *
  76. * @author <a href="mailto:nissim@nksystems.com">Nissim Karpenstein</a>
  77. * @author <a href="mailto:janekdb@yahoo.co.uk">Janek Bogucki</a>
  78. * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
  79. * @author Stephen Colebourne
  80. * @author Jeff Varszegi
  81. * @author Gary Gregory
  82. * @since 1.0
  83. * @version $Id: SerializationUtils.java,v 1.12 2003/08/22 17:25:33 ggregory Exp $
  84. */
  85. public class SerializationUtils {
  86. /**
  87. * <p>SerializationUtils instances should NOT be constructed in standard programming.
  88. * Instead, the class should be used as <code>SerializationUtils.clone(object)</code>.</p>
  89. *
  90. * <p>This constructor is public to permit tools that require a JavaBean instance
  91. * to operate.</p>
  92. * @since 2.0
  93. */
  94. public SerializationUtils() {
  95. super();
  96. }
  97. // Clone
  98. //-----------------------------------------------------------------------
  99. /**
  100. * <p>Deep clone an <code>Object</code> using serialization.</p>
  101. *
  102. * <p>This is many times slower than writing clone methods by hand
  103. * on all objects in your object graph. However, for complex object
  104. * graphs, or for those that don't support deep cloning this can
  105. * be a simple alternative implementation. Of course all the objects
  106. * must be <code>Serializable</code>.</p>
  107. *
  108. * @param object the <code>Serializable</code> object to clone
  109. * @return the cloned object
  110. * @throws SerializationException (runtime) if the serialization fails
  111. */
  112. public static Object clone(Serializable object) {
  113. return deserialize(serialize(object));
  114. }
  115. // Serialize
  116. //-----------------------------------------------------------------------
  117. /**
  118. * <p>Serializes an <code>Object</code> to the specified stream.</p>
  119. *
  120. * <p>The stream will be closed once the object is written.
  121. * This avoids the need for a finally clause, and maybe also exception
  122. * handling, in the application code.</p>
  123. *
  124. * <p>The stream passed in is not buffered internally within this method.
  125. * This is the responsibility of your application if desired.</p>
  126. *
  127. * @param obj the object to serialize to bytes, may be null
  128. * @param outputStream the stream to write to, must not be null
  129. * @throws IllegalArgumentException if <code>outputStream</code> is <code>null</code>
  130. * @throws SerializationException (runtime) if the serialization fails
  131. */
  132. public static void serialize(Serializable obj, OutputStream outputStream) {
  133. if (outputStream == null) {
  134. throw new IllegalArgumentException("The OutputStream must not be null");
  135. }
  136. ObjectOutputStream out = null;
  137. try {
  138. // stream closed in the finally
  139. out = new ObjectOutputStream(outputStream);
  140. out.writeObject(obj);
  141. } catch (IOException ex) {
  142. throw new SerializationException(ex);
  143. } finally {
  144. try {
  145. if (out != null) {
  146. out.close();
  147. }
  148. } catch (IOException ex) {
  149. // ignore;
  150. }
  151. }
  152. }
  153. /**
  154. * <p>Serializes an <code>Object</code> to a byte array for
  155. * storage/serialization.</p>
  156. *
  157. * @param obj the object to serialize to bytes
  158. * @return a byte[] with the converted Serializable
  159. * @throws SerializationException (runtime) if the serialization fails
  160. */
  161. public static byte[] serialize(Serializable obj) {
  162. ByteArrayOutputStream baos = new ByteArrayOutputStream(512);
  163. serialize(obj, baos);
  164. return baos.toByteArray();
  165. }
  166. // Deserialize
  167. //-----------------------------------------------------------------------
  168. /**
  169. * <p>Deserializes an <code>Object</code> from the specified stream.</p>
  170. *
  171. * <p>The stream will be closed once the object is written. This
  172. * avoids the need for a finally clause, and maybe also exception
  173. * handling, in the application code.</p>
  174. *
  175. * <p>The stream passed in is not buffered internally within this method.
  176. * This is the responsibility of your application if desired.</p>
  177. *
  178. * @param inputStream the serialized object input stream, must not be null
  179. * @return the deserialized object
  180. * @throws IllegalArgumentException if <code>inputStream</code> is <code>null</code>
  181. * @throws SerializationException (runtime) if the serialization fails
  182. */
  183. public static Object deserialize(InputStream inputStream) {
  184. if (inputStream == null) {
  185. throw new IllegalArgumentException("The InputStream must not be null");
  186. }
  187. ObjectInputStream in = null;
  188. try {
  189. // stream closed in the finally
  190. in = new ObjectInputStream(inputStream);
  191. return in.readObject();
  192. } catch (ClassNotFoundException ex) {
  193. throw new SerializationException(ex);
  194. } catch (IOException ex) {
  195. throw new SerializationException(ex);
  196. } finally {
  197. try {
  198. if (in != null) {
  199. in.close();
  200. }
  201. } catch (IOException ex) {
  202. // ignore
  203. }
  204. }
  205. }
  206. /**
  207. * <p>Deserializes a single <code>Object</code> from an array of bytes.</p>
  208. *
  209. * @param objectData the serialized object, must not be null
  210. * @return the deserialized object
  211. * @throws IllegalArgumentException if <code>objectData</code> is <code>null</code>
  212. * @throws SerializationException (runtime) if the serialization fails
  213. */
  214. public static Object deserialize(byte[] objectData) {
  215. if (objectData == null) {
  216. throw new IllegalArgumentException("The byte[] must not be null");
  217. }
  218. ByteArrayInputStream bais = new ByteArrayInputStream(objectData);
  219. return deserialize(bais);
  220. }
  221. }