001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.commons.lang; 018 019 import java.io.ByteArrayInputStream; 020 import java.io.ByteArrayOutputStream; 021 import java.io.IOException; 022 import java.io.InputStream; 023 import java.io.ObjectInputStream; 024 import java.io.ObjectOutputStream; 025 import java.io.OutputStream; 026 import java.io.Serializable; 027 028 /** 029 * <p>Assists with the serialization process and performs additional functionality based 030 * on serialization.</p> 031 * <p> 032 * <ul> 033 * <li>Deep clone using serialization 034 * <li>Serialize managing finally and IOException 035 * <li>Deserialize managing finally and IOException 036 * </ul> 037 * 038 * <p>This class throws exceptions for invalid <code>null</code> inputs. 039 * Each method documents its behaviour in more detail.</p> 040 * 041 * <p>#ThreadSafe#</p> 042 * @author Apache Software Foundation 043 * @author <a href="mailto:nissim@nksystems.com">Nissim Karpenstein</a> 044 * @author <a href="mailto:janekdb@yahoo.co.uk">Janek Bogucki</a> 045 * @author Daniel L. Rall 046 * @author Jeff Varszegi 047 * @author Gary Gregory 048 * @since 1.0 049 * @version $Id: SerializationUtils.java 1056988 2011-01-09 17:58:53Z niallp $ 050 */ 051 public class SerializationUtils { 052 053 /** 054 * <p>SerializationUtils instances should NOT be constructed in standard programming. 055 * Instead, the class should be used as <code>SerializationUtils.clone(object)</code>.</p> 056 * 057 * <p>This constructor is public to permit tools that require a JavaBean instance 058 * to operate.</p> 059 * @since 2.0 060 */ 061 public SerializationUtils() { 062 super(); 063 } 064 065 // Clone 066 //----------------------------------------------------------------------- 067 /** 068 * <p>Deep clone an <code>Object</code> using serialization.</p> 069 * 070 * <p>This is many times slower than writing clone methods by hand 071 * on all objects in your object graph. However, for complex object 072 * graphs, or for those that don't support deep cloning this can 073 * be a simple alternative implementation. Of course all the objects 074 * must be <code>Serializable</code>.</p> 075 * 076 * @param object the <code>Serializable</code> object to clone 077 * @return the cloned object 078 * @throws SerializationException (runtime) if the serialization fails 079 */ 080 public static Object clone(Serializable object) { 081 return deserialize(serialize(object)); 082 } 083 084 // Serialize 085 //----------------------------------------------------------------------- 086 /** 087 * <p>Serializes an <code>Object</code> to the specified stream.</p> 088 * 089 * <p>The stream will be closed once the object is written. 090 * This avoids the need for a finally clause, and maybe also exception 091 * handling, in the application code.</p> 092 * 093 * <p>The stream passed in is not buffered internally within this method. 094 * This is the responsibility of your application if desired.</p> 095 * 096 * @param obj the object to serialize to bytes, may be null 097 * @param outputStream the stream to write to, must not be null 098 * @throws IllegalArgumentException if <code>outputStream</code> is <code>null</code> 099 * @throws SerializationException (runtime) if the serialization fails 100 */ 101 public static void serialize(Serializable obj, OutputStream outputStream) { 102 if (outputStream == null) { 103 throw new IllegalArgumentException("The OutputStream must not be null"); 104 } 105 ObjectOutputStream out = null; 106 try { 107 // stream closed in the finally 108 out = new ObjectOutputStream(outputStream); 109 out.writeObject(obj); 110 111 } catch (IOException ex) { 112 throw new SerializationException(ex); 113 } finally { 114 try { 115 if (out != null) { 116 out.close(); 117 } 118 } catch (IOException ex) { 119 // ignore close exception 120 } 121 } 122 } 123 124 /** 125 * <p>Serializes an <code>Object</code> to a byte array for 126 * storage/serialization.</p> 127 * 128 * @param obj the object to serialize to bytes 129 * @return a byte[] with the converted Serializable 130 * @throws SerializationException (runtime) if the serialization fails 131 */ 132 public static byte[] serialize(Serializable obj) { 133 ByteArrayOutputStream baos = new ByteArrayOutputStream(512); 134 serialize(obj, baos); 135 return baos.toByteArray(); 136 } 137 138 // Deserialize 139 //----------------------------------------------------------------------- 140 /** 141 * <p>Deserializes an <code>Object</code> from the specified stream.</p> 142 * 143 * <p>The stream will be closed once the object is written. This 144 * avoids the need for a finally clause, and maybe also exception 145 * handling, in the application code.</p> 146 * 147 * <p>The stream passed in is not buffered internally within this method. 148 * This is the responsibility of your application if desired.</p> 149 * 150 * @param inputStream the serialized object input stream, must not be null 151 * @return the deserialized object 152 * @throws IllegalArgumentException if <code>inputStream</code> is <code>null</code> 153 * @throws SerializationException (runtime) if the serialization fails 154 */ 155 public static Object deserialize(InputStream inputStream) { 156 if (inputStream == null) { 157 throw new IllegalArgumentException("The InputStream must not be null"); 158 } 159 ObjectInputStream in = null; 160 try { 161 // stream closed in the finally 162 in = new ObjectInputStream(inputStream); 163 return in.readObject(); 164 165 } catch (ClassNotFoundException ex) { 166 throw new SerializationException(ex); 167 } catch (IOException ex) { 168 throw new SerializationException(ex); 169 } finally { 170 try { 171 if (in != null) { 172 in.close(); 173 } 174 } catch (IOException ex) { 175 // ignore close exception 176 } 177 } 178 } 179 180 /** 181 * <p>Deserializes a single <code>Object</code> from an array of bytes.</p> 182 * 183 * @param objectData the serialized object, must not be null 184 * @return the deserialized object 185 * @throws IllegalArgumentException if <code>objectData</code> is <code>null</code> 186 * @throws SerializationException (runtime) if the serialization fails 187 */ 188 public static Object deserialize(byte[] objectData) { 189 if (objectData == null) { 190 throw new IllegalArgumentException("The byte[] must not be null"); 191 } 192 ByteArrayInputStream bais = new ByteArrayInputStream(objectData); 193 return deserialize(bais); 194 } 195 196 }