001    /*
002     * Copyright (C) 2012 eXo Platform SAS.
003     *
004     * This is free software; you can redistribute it and/or modify it
005     * under the terms of the GNU Lesser General Public License as
006     * published by the Free Software Foundation; either version 2.1 of
007     * the License, or (at your option) any later version.
008     *
009     * This software is distributed in the hope that it will be useful,
010     * but WITHOUT ANY WARRANTY; without even the implied warranty of
011     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012     * Lesser General Public License for more details.
013     *
014     * You should have received a copy of the GNU Lesser General Public
015     * License along with this software; if not, write to the Free
016     * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
017     * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
018     */
019    
020    package org.crsh.processor.term;
021    
022    import org.crsh.shell.ShellProcess;
023    import org.crsh.shell.ShellProcessContext;
024    import org.crsh.shell.ShellResponse;
025    import org.crsh.text.Chunk;
026    import org.crsh.term.TermEvent;
027    import org.crsh.text.Text;
028    
029    import java.io.IOException;
030    
031    class ProcessContext implements ShellProcessContext, Runnable {
032    
033      /** . */
034      final Processor processor;
035    
036      /** . */
037      final ShellProcess process;
038    
039      ProcessContext(Processor processor, ShellProcess process) {
040        this.process = process;
041        this.processor = processor;
042      }
043    
044      public void run() {
045        process.execute(this);
046      }
047    
048      public int getWidth() {
049        return processor.term.getWidth();
050      }
051    
052      public int getHeight() {
053        return processor.term.getHeight();
054      }
055    
056      public String getProperty(String name) {
057        return processor.term.getProperty(name);
058      }
059    
060      public String readLine(String msg, boolean echo) {
061        try {
062          processor.term.provide(Text.create(msg));
063        }
064        catch (IOException e) {
065          return null;
066        }
067        boolean done = false;
068        while (true) {
069          synchronized (processor.lock) {
070            switch (processor.status) {
071              case CLOSED:
072              case CANCELLING:
073                return null;
074              case PROCESSING:
075                if (processor.queue.size() > 0) {
076                  TermEvent event = processor.queue.removeFirst();
077                  if (event instanceof TermEvent.ReadLine) {
078                    return ((TermEvent.ReadLine)event).getLine().toString();
079                  }
080                }
081                break;
082              default:
083                throw new AssertionError("Does not make sense " + processor.status);
084            }
085          }
086          if (done) {
087            return null;
088          } else {
089            done = true;
090            processor.waitingEvent = true;
091            try {
092              processor.term.setEcho(echo);
093              processor.readTerm();
094              processor.term.provide(Text.create("\r\n"));
095            }
096            catch (IOException e) {
097              processor.log.error("Error when readline line");
098            }
099            finally {
100              processor.waitingEvent = false;
101              processor.term.setEcho(true);
102            }
103          }
104        }
105      }
106    
107      public void provide(Chunk element) throws IOException {
108        processor.term.provide(element);
109      }
110    
111      public void flush() {
112        processor.term.flush();
113      }
114    
115      public void end(ShellResponse response) {
116        Runnable runnable;
117        ProcessContext context;
118        Status status;
119        synchronized (processor.lock) {
120    
121          //
122          processor.current = null;
123          switch (processor.status) {
124            case PROCESSING:
125              if (response instanceof ShellResponse.Close) {
126                runnable = processor.CLOSE;
127                processor.status = Status.CLOSED;
128              } else if (response instanceof ShellResponse.Cancelled) {
129                runnable = Processor.NOOP;
130                processor.status = Status.AVAILABLE;
131              } else {
132                final String message = response.getMessage();
133                runnable = new Runnable() {
134                  public void run() {
135                    try {
136                      processor.provide(Text.create(message));
137                    }
138                    catch (IOException e) {
139                      // todo ???
140                      e.printStackTrace();
141                    }
142                    finally {
143                      // Be sure to flush
144                      processor.term.flush();
145                    }
146                  }
147                };
148                processor.status = Status.AVAILABLE;
149              }
150              break;
151            case CANCELLING:
152              runnable = Processor.NOOP;
153              processor.status = Status.AVAILABLE;
154              break;
155            default:
156              throw new AssertionError("Does not make sense " + processor.status);
157          }
158    
159          // Do we have a next process to execute ?
160          context = processor.peekProcess();
161          status = processor.status;
162        }
163    
164        //
165        runnable.run();
166    
167        //
168        if (context != null) {
169          context.run();
170        } else if (status == Status.AVAILABLE) {
171          processor.writePromptFlush();
172        }
173      }
174    }