001    package org.crsh.processor.term;
002    
003    import org.crsh.shell.ShellProcess;
004    import org.crsh.shell.ShellProcessContext;
005    import org.crsh.shell.ShellResponse;
006    import org.crsh.text.CharReader;
007    import org.crsh.term.TermEvent;
008    
009    import java.io.IOException;
010    
011    /** @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a> */
012    class ProcessContext implements ShellProcessContext, Runnable {
013    
014      /** . */
015      final Processor processor;
016    
017      /** . */
018      final ShellProcess process;
019    
020      ProcessContext(Processor processor, ShellProcess process) {
021        this.process = process;
022        this.processor = processor;
023      }
024    
025      public void run() {
026        process.execute(this);
027      }
028    
029      public int getWidth() {
030        return processor.term.getWidth();
031      }
032    
033      public String getProperty(String name) {
034        return processor.term.getProperty(name);
035      }
036    
037      public String readLine(String msg, boolean echo) {
038        try {
039          processor.term.write(new CharReader(msg));
040        }
041        catch (IOException e) {
042          return null;
043        }
044        boolean done = false;
045        while (true) {
046          synchronized (processor.lock) {
047            switch (processor.status) {
048              case CLOSED:
049              case CANCELLING:
050                return null;
051              case PROCESSING:
052                if (processor.queue.size() > 0) {
053                  TermEvent event = processor.queue.removeFirst();
054                  if (event instanceof TermEvent.ReadLine) {
055                    return ((TermEvent.ReadLine)event).getLine().toString();
056                  }
057                }
058                break;
059              default:
060                throw new AssertionError("Does not make sense " + processor.status);
061            }
062          }
063          if (done) {
064            return null;
065          } else {
066            done = true;
067            processor.waitingEvent = true;
068            try {
069              processor.term.setEcho(echo);
070              processor.readTerm();
071              processor.term.write(new CharReader("\r\n"));
072            }
073            catch (IOException e) {
074              processor.log.error("Error when readline line");
075            }
076            finally {
077              processor.waitingEvent = false;
078              processor.term.setEcho(true);
079            }
080          }
081        }
082      }
083    
084      public void end(ShellResponse response) {
085        Runnable runnable;
086        ProcessContext context;
087        Status status;
088        synchronized (processor.lock) {
089    
090          //
091          processor.current = null;
092          switch (processor.status) {
093            case PROCESSING:
094              if (response instanceof ShellResponse.Close) {
095                runnable = processor.CLOSE;
096                processor.status = Status.CLOSED;
097              } else if (response instanceof ShellResponse.Cancelled) {
098                runnable = Processor.NOOP;
099                processor.status = Status.AVAILABLE;
100              } else {
101                final CharReader reader = response.getReader();
102                runnable = new Runnable() {
103                  public void run() {
104                    processor.write(reader);
105                  }
106                };
107                processor.status = Status.AVAILABLE;
108              }
109              break;
110            case CANCELLING:
111              runnable = Processor.NOOP;
112              processor.status = Status.AVAILABLE;
113              break;
114            default:
115              throw new AssertionError("Does not make sense " + processor.status);
116          }
117    
118          // Do we have a next process to execute ?
119          context = processor.peekProcess();
120          status = processor.status;
121        }
122    
123        //
124        runnable.run();
125    
126        //
127        if (context != null) {
128          context.run();
129        } else if (status == Status.AVAILABLE) {
130          processor.writePrompt();
131        }
132      }
133    }