public synchronized void save() throws IOException {
    OutputStream os = null;
    try {
      File newSaved = new File(saved.getParentFile(), saved.getName() + ".new");
      File backupSaved = new File(saved.getParentFile(), saved.getName() + ".bak");
      os = new FileOutputStream(newSaved);
      marshaller.marshall(os, session);
      os.close();
      os = null;

      if (backupSaved.exists()) {
        if (!backupSaved.delete()) {
          throw new IOException("could not remove backup " + backupSaved.getAbsolutePath());
        }
      }
      if (saved.exists()) {
        if (!saved.renameTo(backupSaved)) {
          throw new IOException("could not backup " + saved.getAbsolutePath());
        }
      }
      if (!newSaved.renameTo(saved)) {
        backupSaved.renameTo(saved);
        throw new IOException("could not rename " + saved.getAbsolutePath());
      }

    } finally {
      if (os != null) os.close();
    }
  }
  public DroolsSession(File saved, String processXML, int initialProcessInstanceId)
      throws IOException {
    this.saved = saved;

    KnowledgeBuilder kbuilder =
        KnowledgeBuilderFactory.newKnowledgeBuilder(new PackageBuilderConfiguration());
    kbuilder.add(new ReaderResource(new StringReader(processXML)), ResourceType.DRF);
    KnowledgeBuilderErrors errors = kbuilder.getErrors();
    StringBuilder sb = new StringBuilder();
    if (errors.size() > 0) {

      for (KnowledgeBuilderError error : errors) {
        sb.append(error.getMessage()).append("\n");
      }

      throw new IllegalArgumentException("Could not parse knowledge:\n" + sb);
    }

    Collection<KnowledgePackage> knowledgePackages = kbuilder.getKnowledgePackages();

    Process process = knowledgePackages.iterator().next().getProcesses().iterator().next();

    processId = process.getId();

    kbase = KnowledgeBaseFactory.newKnowledgeBase();
    kbase.addKnowledgePackages(knowledgePackages);

    marshaller = MarshallerFactory.newMarshaller(kbase);

    SessionConfiguration conf = new SessionConfiguration();
    Properties p = new Properties();
    p.setProperty(
        "drools.processInstanceManagerFactory",
        HudsonProcessInstanceManagerFactory.class.getName());
    conf.addProperties(p);
    Environment env = EnvironmentFactory.newEnvironment();
    if (!saved.exists() || saved.length() == 0) {
      session = kbase.newStatefulKnowledgeSession(conf, env);
    } else {
      InputStream is = null;
      try {
        is = new FileInputStream(saved);
        session = marshaller.unmarshall(is, conf, env);
      } catch (ClassNotFoundException e) {
        throw new IOException2("Class not found while unmarshalling " + saved.getAbsolutePath(), e);
      } catch (IOException e) {
        throw new IOException2("Error while unmarshalling " + saved.getAbsolutePath(), e);
      } finally {
        is.close();
      }
    }

    ((HudsonProcessInstanceManager)
            ((InternalWorkingMemoryEntryPoint) session)
                .getInternalWorkingMemory()
                .getProcessInstanceManager())
        .setProcessCounter(initialProcessInstanceId);
  }
  public void test6() throws Exception {
    String process =
        "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
            + "<process xmlns=\"http://drools.org/drools-5.0/process\"\n"
            + "  xmlns:xs=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
            + "  xs:schemaLocation=\"http://drools.org/drools-5.0/process drools-processes-5.0.xsd\"\n"
            + "  type=\"RuleFlow\" name=\"ruleflow\" id=\"com.sample.ruleflow\" package-name=\"com.sample\" >\n"
            + "\n"
            + "    <header>\n"
            + "    </header>\n"
            + "\n"
            + "    <nodes>\n"
            + "      <start id=\"1\" name=\"Start\" />\n"
            + "      <timerNode id=\"4\" name=\"Timer\" delay=\"200\" />\n"
            + "      <end id=\"3\" name=\"End\" />\n"
            + "    </nodes>\n"
            + "\n"
            + "    <connections>\n"
            + "      <connection from=\"1\" to=\"4\" />\n"
            + "      <connection from=\"4\" to=\"3\" />\n"
            + "    </connections>\n"
            + "\n"
            + "</process>\n";
    final PackageBuilder builder = new PackageBuilder();
    builder.addProcessFromXml(new StringReader(process));
    final Package pkg = builder.getPackage();
    final RuleBase ruleBase = RuleBaseFactory.newRuleBase();
    ruleBase.addPackage(pkg);

    final StatefulSession session = ruleBase.newStatefulSession();

    new Thread(
            new Runnable() {
              public void run() {
                session.fireUntilHalt();
              }
            })
        .start();

    session.startProcess("com.sample.ruleflow", null);
    assertEquals(1, session.getProcessInstances().size());

    StatefulKnowledgeSession ksession =
        new StatefulKnowledgeSessionImpl((ReteooWorkingMemory) session);
    Marshaller marshaller = MarshallerFactory.newMarshaller(ksession.getKnowledgeBase());

    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    marshaller.marshall(baos, ksession);
    byte[] b1 = baos.toByteArray();
    session.halt();
    session.dispose();
    Thread.sleep(400);

    ByteArrayInputStream bais = new ByteArrayInputStream(b1);
    final StatefulSession session2 =
        (StatefulSession) ((StatefulKnowledgeSessionImpl) marshaller.unmarshall(bais)).session;

    new Thread(
            new Runnable() {
              public void run() {
                session2.fireUntilHalt();
              }
            })
        .start();

    Thread.sleep(100);

    assertEquals(0, session2.getProcessInstances().size());
    session2.halt();
  }