* Handles the read serialization of the Package. Patterns in Rules may reference generated data
   * which cannot be serialized by default methods. The Package uses PackageCompilationData to hold
   * a reference to the generated bytecode; which must be restored before any Rules. A custom
   * ObjectInputStream, able to resolve classes against the bytecode in the PackageCompilationData,
   * is used to restore the Rules.
  public void doReadExternal(final ObjectInput stream, final Object[] objects)
      throws IOException, ClassNotFoundException {
    // PackageCompilationData must be restored before Rules as it has the ClassLoader needed to
    // resolve the generated code references in Rules
    this.pkgs = (Map) stream.readObject();

    this.packageClassLoader =
        new CompositePackageClassLoader(Thread.currentThread().getContextClassLoader());
    for (final Iterator it = this.pkgs.values().iterator(); it.hasNext(); ) {
          ((Package) it.next()).getPackageCompilationData().getClassLoader());

    // Return the rules stored as a byte[]
    final byte[] bytes = (byte[]) stream.readObject();

    //  Use a custom ObjectInputStream that can resolve against a given classLoader
    final ObjectInputStreamWithLoader streamWithLoader =
        new ObjectInputStreamWithLoader(new ByteArrayInputStream(bytes), this.packageClassLoader);

    this.factHandleFactory = (FactHandleFactory) streamWithLoader.readObject();
    this.globals = (Map) streamWithLoader.readObject();

    this.config = (RuleBaseConfiguration) streamWithLoader.readObject();

    this.workingMemories = new WeakHashMap();

    for (int i = 0, length = objects.length; i < length; i++) {
      objects[i] = streamWithLoader.readObject();
  public WorkingMemory newWorkingMemory(InputStream stream, boolean keepReference)
      throws IOException, ClassNotFoundException {

    final ObjectInputStreamWithLoader streamWithLoader =
        new ObjectInputStreamWithLoader(stream, this.packageClassLoader);

    AbstractWorkingMemory workingMemory = (AbstractWorkingMemory) streamWithLoader.readObject();

    return workingMemory;