Package org.prevayler.foundation

Source Code of org.prevayler.foundation.DeepCopier$Receiver

package org.prevayler.foundation;

import org.prevayler.foundation.serialization.JavaSerializer;
import org.prevayler.foundation.serialization.Serializer;

import java.io.*;

public class DeepCopier {

  /**
   * Same as deepCopy(original, new JavaSerializer()).
   *
   * @throws ClassNotFoundException
   * @throws IOException
   */
  public static Object deepCopy(Object original) {
    return deepCopy(original, new JavaSerializer());
  }

  /**
   * Produce a deep copy of the given object. Serializes the entire object to a byte array in memory. Recommended for
   * relatively small objects, such as individual transactions.
   */
  public static Object deepCopy(Object original, Serializer serializer) {
    try {
      ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
      serializer.writeObject(byteOut, original);
      ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
      return serializer.readObject(byteIn);
    } catch (Exception e) {
      Cool.unexpected(e);
      return null;
    }
  }

  /**
   * Produce a deep copy of the given object. Serializes the object through a pipe between two threads. Recommended for
   * very large objects, such as an entire prevalent system. The current thread is used for serializing the original
   * object in order to respect any synchronization the caller may have around it, and a new thread is used for
   * deserializing the copy.
   */
  public static Object deepCopyParallel(Object original, Serializer serializer) throws Exception {
    PipedOutputStream outputStream = new PipedOutputStream();
    PipedInputStream inputStream = new PipedInputStream(outputStream);

    Receiver receiver = new Receiver(inputStream, serializer);

    try {
      serializer.writeObject(outputStream, original);
    } finally {
      outputStream.close();
    }

    return receiver.getResult();
  }

  private static class Receiver extends Thread {

    private InputStream _inputStream;
    private Serializer _serializer;
    private Object _result;
    private Exception _exception;
    private Error _error;

    public Receiver(InputStream inputStream, Serializer serializer) {
      _inputStream = inputStream;
      _serializer = serializer;
      start();
    }

    public void run() {
      try {
        _result = _serializer.readObject(_inputStream);
      } catch (Exception e) {
        _exception = e;
      } catch (Error e) {
        _error = e;
        throw e;
      }

      try {
        // Some serializers may write more than they actually need to deserialize the object, but if
        // we don't read it all the PipedOutputStream will choke.
        while (_inputStream.read() != -1) {
        }
      } catch (IOException e) {
        // The object has been successfully deserialized, so ignore problems at this point (for example,
        // the serializer may have explicitly closed the _inputStream itself, causing this read to fail).
      }
    }

    public Object getResult() throws Exception {
      try {
        join();
      } catch (InterruptedException e) {
        throw new RuntimeException("Unexpected InterruptedException", e);
      }

      // join() guarantees that all shared memory is synchronized between the two threads

      if (_error != null) throw new RuntimeException("Error during deserialization", _error);
      if (_exception != null) throw _exception;
      if (_result == null) throw new RuntimeException("Deep copy failed in an unknown way");

      return _result;
    }

  }

}
TOP

Related Classes of org.prevayler.foundation.DeepCopier$Receiver

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.