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 disconnected(OfficeConnectionEvent event) {
   taskExecutor.setAvailable(false);
   if (stopping) {
     // expected
     stopping = false;
   } else {
     logger.warning("connection lost unexpectedly; attempting restart");
     if (currentTask != null) {
       currentTask.cancel(true);
     }
     managedOfficeProcess.restartDueToLostConnection();
   }
 }
 public PooledOfficeManager(PooledOfficeManagerSettings settings) {
   this.settings = settings;
   managedOfficeProcess = new ManagedOfficeProcess(settings);
   managedOfficeProcess.getConnection().addConnectionEventListener(connectionEventListener);
   taskExecutor = new SuspendableThreadPoolExecutor(new NamedThreadFactory("OfficeTaskThread"));
 }
 public boolean isRunning() {
   return managedOfficeProcess.isConnected();
 }
 public void stop() throws OfficeException {
   taskExecutor.setAvailable(false);
   stopping = true;
   taskExecutor.shutdownNow();
   managedOfficeProcess.stopAndWait();
 }
 public void start() throws OfficeException {
   managedOfficeProcess.startAndWait();
 }