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.shell.impl.remoting;
021    
022    import org.crsh.cmdline.CommandCompletion;
023    import org.crsh.shell.Shell;
024    import org.crsh.shell.ShellProcess;
025    import org.crsh.util.CloseableList;
026    
027    import java.io.Closeable;
028    import java.io.IOException;
029    import java.io.InputStream;
030    import java.io.ObjectInputStream;
031    import java.io.ObjectOutputStream;
032    import java.io.OutputStream;
033    import java.util.concurrent.Callable;
034    import java.util.concurrent.Future;
035    import java.util.concurrent.FutureTask;
036    
037    public class ClientAutomaton implements Runnable {
038    
039      /** . */
040      final Shell shell;
041    
042      /** . */
043      final ObjectOutputStream out;
044    
045      /** . */
046      final ObjectInputStream in;
047    
048      /** . */
049      ClientProcessContext current;
050    
051      /** . */
052      final CloseableList listeners;
053    
054      /** . */
055      Integer width;
056    
057      /** . */
058      Integer height;
059    
060      /** . */
061      long last;
062    
063      public ClientAutomaton(ObjectOutputStream out, ObjectInputStream in, Shell shell) {
064        CloseableList listeners = new CloseableList();
065        listeners.add(in);
066        listeners.add(out);
067    
068        //
069        this.in = in;
070        this.out = out;
071        this.shell = shell;
072        this.listeners = listeners;
073        this.width = null;
074        this.height = null;
075      }
076    
077      public ClientAutomaton(InputStream in,OutputStream out, Shell shell) throws IOException {
078        this(new ObjectOutputStream(out), new ObjectInputStream(in), shell);
079      }
080    
081      public ClientAutomaton addCloseListener(Closeable closeable) {
082        listeners.add(closeable);
083        return this;
084      }
085    
086      public void run() {
087        try {
088          while (!listeners.isClosed()) {
089            ClientMessage msg = (ClientMessage)in.readObject();
090            switch (msg) {
091              case GET_WELCOME:
092                String welcome = shell.getWelcome();
093                out.writeObject(welcome);
094                out.flush();
095                break;
096              case GET_PROMPT:
097                String prompt = shell.getPrompt();
098                out.writeObject(prompt);
099                out.flush();
100                break;
101              case GET_COMPLETION:
102                String prefix = (String)in.readObject();
103                CommandCompletion completion = shell.complete(prefix);
104                out.writeObject(completion);
105                out.flush();
106                break;
107              case SET_SIZE:
108                width = (Integer) in.readObject();
109                height = (Integer) in.readObject();
110                last = System.currentTimeMillis();
111                break;
112              case EXECUTE:
113                width = (Integer) in.readObject();
114                height = (Integer) in.readObject();
115                last = System.currentTimeMillis();
116                String line = (String)in.readObject();
117                ShellProcess process = shell.createProcess(line);
118                current = new ClientProcessContext(this, process);
119                process.execute(current);
120                break;
121              case CANCEL:
122                if (current != null) {
123                  current.process.cancel();
124                }
125                break;
126              case CLOSE:
127                close();
128                break;
129            }
130          }
131        }
132        catch (Exception e) {
133          // e.printStackTrace();
134          //
135        }
136      }
137    
138      void close() {
139        listeners.close();
140      }
141    
142      public int getWidth() {
143        return width;
144      }
145    
146      public int getHeight() {
147        return height;
148      }
149    }