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 boolean takeAlternateBuffer() {
045        throw new UnsupportedOperationException();
046      }
047    
048      public boolean releaseAlternateBuffer() {
049        throw new UnsupportedOperationException();
050      }
051    
052      public void run() {
053        process.execute(this);
054      }
055    
056      public int getWidth() {
057        return processor.term.getWidth();
058      }
059    
060      public int getHeight() {
061        return processor.term.getHeight();
062      }
063    
064      public String getProperty(String name) {
065        return processor.term.getProperty(name);
066      }
067    
068      public String readLine(String msg, boolean echo) {
069        try {
070          processor.term.provide(Text.create(msg));
071        }
072        catch (IOException e) {
073          return null;
074        }
075        boolean done = false;
076        while (true) {
077          synchronized (processor.lock) {
078            switch (processor.status) {
079              case CLOSED:
080              case CANCELLING:
081                return null;
082              case PROCESSING:
083                if (processor.queue.size() > 0) {
084                  TermEvent event = processor.queue.removeFirst();
085                  if (event instanceof TermEvent.ReadLine) {
086                    return ((TermEvent.ReadLine)event).getLine().toString();
087                  }
088                }
089                break;
090              default:
091                throw new AssertionError("Does not make sense " + processor.status);
092            }
093          }
094          if (done) {
095            return null;
096          } else {
097            done = true;
098            processor.waitingEvent = true;
099            try {
100              processor.term.setEcho(echo);
101              processor.readTerm();
102              processor.term.provide(Text.create("\r\n"));
103            }
104            catch (IOException e) {
105              processor.log.error("Error when readline line");
106            }
107            finally {
108              processor.waitingEvent = false;
109              processor.term.setEcho(true);
110            }
111          }
112        }
113      }
114    
115      public void provide(Chunk element) throws IOException {
116        processor.term.provide(element);
117      }
118    
119      public void flush() {
120        processor.term.flush();
121      }
122    
123      public void end(ShellResponse response) {
124        Runnable runnable;
125        ProcessContext context;
126        Status status;
127        synchronized (processor.lock) {
128    
129          //
130          processor.current = null;
131          switch (processor.status) {
132            case PROCESSING:
133              if (response instanceof ShellResponse.Close) {
134                runnable = processor.CLOSE;
135                processor.status = Status.CLOSED;
136              } else if (response instanceof ShellResponse.Cancelled) {
137                runnable = Processor.NOOP;
138                processor.status = Status.AVAILABLE;
139              } else {
140                final String message = response.getMessage();
141                runnable = new Runnable() {
142                  public void run() {
143                    try {
144                      processor.provide(Text.create(message));
145                    }
146                    catch (IOException e) {
147                      // todo ???
148                      e.printStackTrace();
149                    }
150                    finally {
151                      // Be sure to flush
152                      processor.term.flush();
153                    }
154                  }
155                };
156                processor.status = Status.AVAILABLE;
157              }
158              break;
159            case CANCELLING:
160              runnable = Processor.NOOP;
161              processor.status = Status.AVAILABLE;
162              break;
163            default:
164              throw new AssertionError("Does not make sense " + processor.status);
165          }
166    
167          // Do we have a next process to execute ?
168          context = processor.peekProcess();
169          status = processor.status;
170        }
171    
172        //
173        runnable.run();
174    
175        //
176        if (context != null) {
177          context.run();
178        } else if (status == Status.AVAILABLE) {
179          processor.writePromptFlush();
180        }
181      }
182    }