예제 #1
0
        public void end(ShellResponse response) {
          // Always leave the status in terminated status if the method succeeds
          // Cancelled -> Terminated
          // Evaluating -> Terminated
          // Terminated -> Terminated
          synchronized (lock) {
            switch (status) {
              case CONSTRUCTED:
              case QUEUED:
                throw new AssertionError("Should not happen");
              case CANCELED:
                // We substitute the response
                response = ShellResponse.cancelled();
                status = Status.TERMINATED;
                break;
              case EVALUATING:
                status = Status.TERMINATED;
                break;
              case TERMINATED:
                throw new IllegalStateException("Cannot end a process already terminated");
            }
          }

          //
          caller.end(response);
        }
예제 #2
0
  public void execute(ShellProcessContext processContext) {

    // Constructed -> Queued
    synchronized (lock) {
      if (status != Status.CONSTRUCTED) {
        throw new IllegalStateException("State was " + status);
      }

      // Update state
      status = Status.QUEUED;
      callee = shell.shell.createProcess(request);
      caller = processContext;
    }

    // Create the task
    Callable<AsyncProcess> task =
        new Callable<AsyncProcess>() {
          public AsyncProcess call() throws Exception {
            try {
              // Cancelled -> Cancelled
              // Queued -> Evaluating
              ShellResponse response;
              synchronized (lock) {
                switch (status) {
                  case CANCELED:
                    // Do nothing it was canceled in the mean time
                    response = ShellResponse.cancelled();
                    break;
                  case QUEUED:
                    // Ok we are going to run it
                    status = Status.EVALUATING;
                    response = null;
                    break;
                  default:
                    // Just in case but this can only be called by the queue
                    throw new AssertionError();
                }
              }

              // Execute the process if we are in evalating state
              if (response == null) {
                // Here the status could already be in status cancelled
                // it is a race condition, execution still happens
                // but the callback of the callee to the end method will make the process
                // terminate and use a cancel response
                try {
                  callee.execute(context);
                  response = ShellResponse.ok();
                } catch (Throwable t) {
                  response =
                      ShellResponse.internalError("Unexpected throwable when executing process", t);
                }
              }

              // Make the callback
              // Calling terminated twice will have no effect
              try {
                context.end(response);
              } catch (Throwable t) {
                // Log it
              }

              // We return this but we don't really care for now
              return AsyncProcess.this;
            } finally {
              synchronized (shell.lock) {
                shell.processes.remove(AsyncProcess.this);
              }
            }
          }
        };

    //
    synchronized (shell.lock) {
      if (!shell.closed) {
        shell.executor.submit(task);
        shell.processes.add(this);
      } else {
        boolean invokeEnd;
        synchronized (lock) {
          invokeEnd = status != Status.TERMINATED;
          status = Status.TERMINATED;
        }
        if (invokeEnd) {
          caller.end(ShellResponse.cancelled());
        }
      }
    }
  }
예제 #3
0
 public String getProperty(String name) {
   return caller.getProperty(name);
 }
예제 #4
0
 public String readLine(String msg, boolean echo) {
   return caller.readLine(msg, echo);
 }
예제 #5
0
 public int getWidth() {
   return caller.getWidth();
 }