1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.commons.lang;
18
19 import java.io.ByteArrayInputStream;
20 import java.io.ByteArrayOutputStream;
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.io.ObjectInputStream;
24 import java.io.ObjectOutputStream;
25 import java.io.OutputStream;
26 import java.io.Serializable;
27
28 /**
29 * <p>Assists with the serialization process and performs additional functionality based
30 * on serialization.</p>
31 * <p>
32 * <ul>
33 * <li>Deep clone using serialization
34 * <li>Serialize managing finally and IOException
35 * <li>Deserialize managing finally and IOException
36 * </ul>
37 *
38 * <p>This class throws exceptions for invalid <code>null</code> inputs.
39 * Each method documents its behaviour in more detail.</p>
40 *
41 * @author <a href="mailto:nissim@nksystems.com">Nissim Karpenstein</a>
42 * @author <a href="mailto:janekdb@yahoo.co.uk">Janek Bogucki</a>
43 * @author Daniel L. Rall
44 * @author Stephen Colebourne
45 * @author Jeff Varszegi
46 * @author Gary Gregory
47 * @since 1.0
48 * @version $Id: SerializationUtils.java 512889 2007-02-28 18:18:20Z dlr $
49 */
50 public class SerializationUtils {
51
52 /**
53 * <p>SerializationUtils instances should NOT be constructed in standard programming.
54 * Instead, the class should be used as <code>SerializationUtils.clone(object)</code>.</p>
55 *
56 * <p>This constructor is public to permit tools that require a JavaBean instance
57 * to operate.</p>
58 * @since 2.0
59 */
60 public SerializationUtils() {
61 super();
62 }
63
64 // Clone
65 //-----------------------------------------------------------------------
66 /**
67 * <p>Deep clone an <code>Object</code> using serialization.</p>
68 *
69 * <p>This is many times slower than writing clone methods by hand
70 * on all objects in your object graph. However, for complex object
71 * graphs, or for those that don't support deep cloning this can
72 * be a simple alternative implementation. Of course all the objects
73 * must be <code>Serializable</code>.</p>
74 *
75 * @param object the <code>Serializable</code> object to clone
76 * @return the cloned object
77 * @throws SerializationException (runtime) if the serialization fails
78 */
79 public static Object clone(Serializable object) {
80 return deserialize(serialize(object));
81 }
82
83 // Serialize
84 //-----------------------------------------------------------------------
85 /**
86 * <p>Serializes an <code>Object</code> to the specified stream.</p>
87 *
88 * <p>The stream will be closed once the object is written.
89 * This avoids the need for a finally clause, and maybe also exception
90 * handling, in the application code.</p>
91 *
92 * <p>The stream passed in is not buffered internally within this method.
93 * This is the responsibility of your application if desired.</p>
94 *
95 * @param obj the object to serialize to bytes, may be null
96 * @param outputStream the stream to write to, must not be null
97 * @throws IllegalArgumentException if <code>outputStream</code> is <code>null</code>
98 * @throws SerializationException (runtime) if the serialization fails
99 */
100 public static void serialize(Serializable obj, OutputStream outputStream) {
101 if (outputStream == null) {
102 throw new IllegalArgumentException("The OutputStream must not be null");
103 }
104 ObjectOutputStream out = null;
105 try {
106 // stream closed in the finally
107 out = new ObjectOutputStream(outputStream);
108 out.writeObject(obj);
109
110 } catch (IOException ex) {
111 throw new SerializationException(ex);
112 } finally {
113 try {
114 if (out != null) {
115 out.close();
116 }
117 } catch (IOException ex) {
118 // ignore close exception
119 }
120 }
121 }
122
123 /**
124 * <p>Serializes an <code>Object</code> to a byte array for
125 * storage/serialization.</p>
126 *
127 * @param obj the object to serialize to bytes
128 * @return a byte[] with the converted Serializable
129 * @throws SerializationException (runtime) if the serialization fails
130 */
131 public static byte[] serialize(Serializable obj) {
132 ByteArrayOutputStream baos = new ByteArrayOutputStream(512);
133 serialize(obj, baos);
134 return baos.toByteArray();
135 }
136
137 // Deserialize
138 //-----------------------------------------------------------------------
139 /**
140 * <p>Deserializes an <code>Object</code> from the specified stream.</p>
141 *
142 * <p>The stream will be closed once the object is written. This
143 * avoids the need for a finally clause, and maybe also exception
144 * handling, in the application code.</p>
145 *
146 * <p>The stream passed in is not buffered internally within this method.
147 * This is the responsibility of your application if desired.</p>
148 *
149 * @param inputStream the serialized object input stream, must not be null
150 * @return the deserialized object
151 * @throws IllegalArgumentException if <code>inputStream</code> is <code>null</code>
152 * @throws SerializationException (runtime) if the serialization fails
153 */
154 public static Object deserialize(InputStream inputStream) {
155 if (inputStream == null) {
156 throw new IllegalArgumentException("The InputStream must not be null");
157 }
158 ObjectInputStream in = null;
159 try {
160 // stream closed in the finally
161 in = new ObjectInputStream(inputStream);
162 return in.readObject();
163
164 } catch (ClassNotFoundException ex) {
165 throw new SerializationException(ex);
166 } catch (IOException ex) {
167 throw new SerializationException(ex);
168 } finally {
169 try {
170 if (in != null) {
171 in.close();
172 }
173 } catch (IOException ex) {
174 // ignore close exception
175 }
176 }
177 }
178
179 /**
180 * <p>Deserializes a single <code>Object</code> from an array of bytes.</p>
181 *
182 * @param objectData the serialized object, must not be null
183 * @return the deserialized object
184 * @throws IllegalArgumentException if <code>objectData</code> is <code>null</code>
185 * @throws SerializationException (runtime) if the serialization fails
186 */
187 public static Object deserialize(byte[] objectData) {
188 if (objectData == null) {
189 throw new IllegalArgumentException("The byte[] must not be null");
190 }
191 ByteArrayInputStream bais = new ByteArrayInputStream(objectData);
192 return deserialize(bais);
193 }
194
195 }