code: /*
   * Licensed to the Apache Software Foundation (ASF) under one or more
   * contributor license agreements.  See the NOTICE file distributed with
   * this work for additional information regarding copyright ownership.
   * The ASF licenses this file to You under the Apache License, Version 2.0
   * (the "License"); you may not use this file except in compliance with
   * the License.  You may obtain a copy of the License at
   * 
   *      http://www.apache.org/licenses/LICENSE-2.0
   * 
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package org.apache.commons.lang;
  
  import java.io.ByteArrayInputStream;
  import java.io.ByteArrayOutputStream;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.ObjectInputStream;
  import java.io.ObjectOutputStream;
  import java.io.OutputStream;
  import java.io.Serializable;
  
  /**
   * <p>Assists with the serialization process and performs additional functionality based 
   * on serialization.</p>
   * <p>
   * <ul>
   * <li>Deep clone using serialization
   * <li>Serialize managing finally and IOException
   * <li>Deserialize managing finally and IOException
   * </ul>
   *
   * <p>This class throws exceptions for invalid <code>null</code> inputs.
   * Each method documents its behaviour in more detail.</p>
   *
   * @author <a href="mailto:nissim@nksystems.com">Nissim Karpenstein</a>
   * @author <a href="mailto:janekdb@yahoo.co.uk">Janek Bogucki</a>
   * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
   * @author Stephen Colebourne
   * @author Jeff Varszegi
   * @author Gary Gregory
   * @since 1.0
   * @version $Id: SerializationUtils.java 437554 2006-08-28 06:21:41Z bayard $
   */
  public class SerializationUtils {
      
      /**
       * <p>SerializationUtils instances should NOT be constructed in standard programming.
       * Instead, the class should be used as <code>SerializationUtils.clone(object)</code>.</p>
       *
       * <p>This constructor is public to permit tools that require a JavaBean instance
       * to operate.</p>
       * @since 2.0
       */
      public SerializationUtils() {
          super();
      }
  
      // Clone
      //-----------------------------------------------------------------------
      /**
       * <p>Deep clone an <code>Object</code> using serialization.</p>
       *
       * <p>This is many times slower than writing clone methods by hand
       * on all objects in your object graph. However, for complex object
       * graphs, or for those that don't support deep cloning this can
       * be a simple alternative implementation. Of course all the objects
       * must be <code>Serializable</code>.</p>
       * 
       * @param object  the <code>Serializable</code> object to clone
       * @return the cloned object
       * @throws SerializationException (runtime) if the serialization fails
       */
      public static Object clone(Serializable object) {
          return deserialize(serialize(object));
      }
      
      // Serialize
      //-----------------------------------------------------------------------
      /**
       * <p>Serializes an <code>Object</code> to the specified stream.</p>
       *
       * <p>The stream will be closed once the object is written.
       * This avoids the need for a finally clause, and maybe also exception
       * handling, in the application code.</p>
       * 
       * <p>The stream passed in is not buffered internally within this method.
       * This is the responsibility of your application if desired.</p>
       *
       * @param obj  the object to serialize to bytes, may be null
       * @param outputStream  the stream to write to, must not be null
       * @throws IllegalArgumentException if <code>outputStream</code> is <code>null</code>
       * @throws SerializationException (runtime) if the serialization fails
       */
      public static void serialize(Serializable obj, OutputStream outputStream) {
          if (outputStream == null) {
              throw new IllegalArgumentException("The OutputStream must not be null");
          }
          ObjectOutputStream out = null;
          try {
              // stream closed in the finally
              out = new ObjectOutputStream(outputStream);
              out.writeObject(obj);
              
          } catch (IOException ex) {
              throw new SerializationException(ex);
          } finally {
              try {
                  if (out != null) {
                      out.close();
                  }
              } catch (IOException ex) {
                  // ignore close exception
              }
          }
      }
  
      /**
       * <p>Serializes an <code>Object</code> to a byte array for
       * storage/serialization.</p>
       *
       * @param obj  the object to serialize to bytes
       * @return a byte[] with the converted Serializable
       * @throws SerializationException (runtime) if the serialization fails
       */
      public static byte[] serialize(Serializable obj) {
          ByteArrayOutputStream baos = new ByteArrayOutputStream(512);
          serialize(obj, baos);
          return baos.toByteArray();
      }
  
      // Deserialize
      //-----------------------------------------------------------------------
      /**
       * <p>Deserializes an <code>Object</code> from the specified stream.</p>
       *
       * <p>The stream will be closed once the object is written. This
       * avoids the need for a finally clause, and maybe also exception
       * handling, in the application code.</p>
       * 
       * <p>The stream passed in is not buffered internally within this method.
       * This is the responsibility of your application if desired.</p>
       *
       * @param inputStream  the serialized object input stream, must not be null
       * @return the deserialized object
       * @throws IllegalArgumentException if <code>inputStream</code> is <code>null</code>
       * @throws SerializationException (runtime) if the serialization fails
       */
      public static Object deserialize(InputStream inputStream) {
          if (inputStream == null) {
              throw new IllegalArgumentException("The InputStream must not be null");
          }
          ObjectInputStream in = null;
          try {
              // stream closed in the finally
              in = new ObjectInputStream(inputStream);
              return in.readObject();
              
          } catch (ClassNotFoundException ex) {
              throw new SerializationException(ex);
          } catch (IOException ex) {
              throw new SerializationException(ex);
          } finally {
              try {
                  if (in != null) {
                      in.close();
                  }
              } catch (IOException ex) {
                  // ignore close exception
              }
          }
      }
  
      /**
       * <p>Deserializes a single <code>Object</code> from an array of bytes.</p>
       *
       * @param objectData  the serialized object, must not be null
       * @return the deserialized object
       * @throws IllegalArgumentException if <code>objectData</code> is <code>null</code>
       * @throws SerializationException (runtime) if the serialization fails
       */
      public static Object deserialize(byte[] objectData) {
          if (objectData == null) {
              throw new IllegalArgumentException("The byte[] must not be null");
          }
          ByteArrayInputStream bais = new ByteArrayInputStream(objectData);
          return deserialize(bais);
      }
      
  }
  