public void executeTask() throws Exception {

    final PooledOfficeManagerSettings settings = new PooledOfficeManagerSettings(CONNECTION_MODE);
    settings.setProcessManager(OfficeUtils.findBestProcessManager());
    final PooledOfficeManager officeManager = new PooledOfficeManager(settings);
    ManagedOfficeProcess managedOfficeProcess =
        (ManagedOfficeProcess)
            FieldUtils.readDeclaredField(officeManager, "managedOfficeProcess", true);
    OfficeProcess process =
        (OfficeProcess) FieldUtils.readDeclaredField(managedOfficeProcess, "process", true);
    OfficeConnection connection =
        (OfficeConnection) FieldUtils.readDeclaredField(managedOfficeProcess, "connection", true);

    try {
      officeManager.start();
      assertTrue(process.isRunning());
      assertTrue(connection.isConnected());

      MockOfficeTask task = new MockOfficeTask();
      officeManager.execute(task);
      assertTrue(task.isCompleted());

    } finally {
      officeManager.stop();
      assertFalse(connection.isConnected());
      assertFalse(process.isRunning());
      assertEquals(process.getExitCode(0, 0), 0);
    }
  }
  public void restartAfterCrash() throws Exception {

    final PooledOfficeManagerSettings settings = new PooledOfficeManagerSettings(CONNECTION_MODE);
    settings.setProcessManager(OfficeUtils.findBestProcessManager());
    final PooledOfficeManager officeManager = new PooledOfficeManager(settings);
    ManagedOfficeProcess managedOfficeProcess =
        (ManagedOfficeProcess)
            FieldUtils.readDeclaredField(officeManager, "managedOfficeProcess", true);
    OfficeProcess process =
        (OfficeProcess) FieldUtils.readDeclaredField(managedOfficeProcess, "process", true);
    OfficeConnection connection =
        (OfficeConnection) FieldUtils.readDeclaredField(managedOfficeProcess, "connection", true);
    assertNotNull(connection);

    try {
      officeManager.start();
      assertTrue(process.isRunning());
      assertTrue(connection.isConnected());

      new Thread() {
        public void run() {
          MockOfficeTask badTask = new MockOfficeTask(10 * 1000);
          try {
            officeManager.execute(badTask);
            fail("task should be cancelled");
            // FIXME being in a separate thread the test won't actually fail
          } catch (OfficeException officeEx) {
            assertTrue(officeEx.getCause() instanceof CancellationException);
          }
        }
      }.start();
      Thread.sleep(500);
      Process underlyingProcess = (Process) FieldUtils.readDeclaredField(process, "process", true);
      assertNotNull(underlyingProcess);
      logger.debug("Simulating the crash");
      underlyingProcess.destroy(); // simulate crash

      Thread.sleep(RESTART_WAIT_TIME);
      assertTrue(process.isRunning());
      assertTrue(connection.isConnected());

      MockOfficeTask goodTask = new MockOfficeTask();
      officeManager.execute(goodTask);
      assertTrue(goodTask.isCompleted());

    } finally {
      officeManager.stop();
      assertFalse(connection.isConnected());
      assertFalse(process.isRunning());
      assertEquals(process.getExitCode(0, 0), 0);
    }
  }
 public void execute(final OfficeTask task) throws OfficeException {
   Future<?> futureTask =
       taskExecutor.submit(
           new Runnable() {
             public void run() {
               if (settings.getMaxTasksPerProcess() > 0
                   && ++taskCount == settings.getMaxTasksPerProcess() + 1) {
                 logger.info(
                     String.format(
                         "reached limit of %d maxTasksPerProcess: restarting",
                         settings.getMaxTasksPerProcess()));
                 taskExecutor.setAvailable(false);
                 stopping = true;
                 managedOfficeProcess.restartAndWait();
                 // FIXME taskCount will be 0 rather than 1 at this point
               }
               task.execute(managedOfficeProcess.getConnection());
             }
           });
   currentTask = futureTask;
   try {
     futureTask.get(settings.getTaskExecutionTimeout(), TimeUnit.MILLISECONDS);
   } catch (TimeoutException timeoutException) {
     managedOfficeProcess.restartDueToTaskTimeout();
     throw new OfficeException("task did not complete within timeout", timeoutException);
   } catch (ExecutionException executionException) {
     if (executionException.getCause() instanceof OfficeException) {
       throw (OfficeException) executionException.getCause();
     } else {
       throw new OfficeException("task failed", executionException.getCause());
     }
   } catch (Exception exception) {
     throw new OfficeException("task failed", exception);
   }
 }
  public void restartAfterTaskTimeout() throws Exception {
    final PooledOfficeManagerSettings settings = new PooledOfficeManagerSettings(CONNECTION_MODE);
    settings.setProcessManager(OfficeUtils.findBestProcessManager());
    settings.setTaskExecutionTimeout(1500L);
    final PooledOfficeManager officeManager = new PooledOfficeManager(settings);

    ManagedOfficeProcess managedOfficeProcess =
        (ManagedOfficeProcess)
            FieldUtils.readDeclaredField(officeManager, "managedOfficeProcess", true);
    OfficeProcess process =
        (OfficeProcess) FieldUtils.readDeclaredField(managedOfficeProcess, "process", true);
    OfficeConnection connection =
        (OfficeConnection) FieldUtils.readDeclaredField(managedOfficeProcess, "connection", true);
    assertNotNull(connection);

    try {
      officeManager.start();
      assertTrue(process.isRunning());
      assertTrue(connection.isConnected());

      MockOfficeTask task = new MockOfficeTask(2000);
      try {
        officeManager.execute(task);
        fail("task should be timed out");
      } catch (OfficeException officeEx) {
        assertTrue(officeEx.getCause() instanceof TimeoutException);
      }

      Thread.sleep(RESTART_WAIT_TIME);

      assertTrue(process.isRunning());
      assertTrue(connection.isConnected());

      MockOfficeTask goodTask = new MockOfficeTask();
      officeManager.execute(goodTask);
      assertTrue(goodTask.isCompleted());
    } finally {

      officeManager.stop();
      assertFalse(connection.isConnected());
      assertFalse(process.isRunning());
      assertEquals(process.getExitCode(0, 0), 0);
    }
  }
  public void restartWhenMaxTasksPerProcessReached() throws Exception {
    PooledOfficeManagerSettings configuration = new PooledOfficeManagerSettings(CONNECTION_MODE);
    configuration.setMaxTasksPerProcess(3);
    final PooledOfficeManager officeManager = new PooledOfficeManager(configuration);

    ManagedOfficeProcess managedOfficeProcess =
        (ManagedOfficeProcess)
            FieldUtils.readDeclaredField(officeManager, "managedOfficeProcess", true);
    OfficeProcess process =
        (OfficeProcess) FieldUtils.readDeclaredField(managedOfficeProcess, "process", true);
    OfficeConnection connection =
        (OfficeConnection) FieldUtils.readDeclaredField(managedOfficeProcess, "connection", true);
    assertNotNull(connection);

    try {
      officeManager.start();
      assertTrue(process.isRunning());
      assertTrue(connection.isConnected());

      for (int i = 0; i < 3; i++) {
        MockOfficeTask task = new MockOfficeTask();
        officeManager.execute(task);
        assertTrue(task.isCompleted());
        int taskCount =
            ((AtomicInteger) FieldUtils.readDeclaredField(officeManager, "taskCount", true)).get();
        assertEquals(taskCount, i + 1);
      }

      MockOfficeTask task = new MockOfficeTask();
      officeManager.execute(task);
      assertTrue(task.isCompleted());
      int taskCount =
          ((AtomicInteger) FieldUtils.readDeclaredField(officeManager, "taskCount", true)).get();
      assertEquals(taskCount, 1);

    } finally {
      officeManager.stop();
      assertFalse(connection.isConnected());
      assertFalse(process.isRunning());
      assertEquals(process.getExitCode(0, 0), 0);
    }
  }