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      public ClientAutomaton(ObjectOutputStream out, ObjectInputStream in, Shell shell) {
061        CloseableList listeners = new CloseableList();
062        listeners.add(in);
063        listeners.add(out);
064    
065        //
066        this.in = in;
067        this.out = out;
068        this.shell = shell;
069        this.listeners = listeners;
070        this.width = null;
071        this.height = null;
072      }
073    
074      public ClientAutomaton(InputStream in,OutputStream out, Shell shell) throws IOException {
075        this(new ObjectOutputStream(out), new ObjectInputStream(in), shell);
076      }
077    
078      public ClientAutomaton addCloseListener(Closeable closeable) {
079        listeners.add(closeable);
080        return this;
081      }
082    
083      public void run() {
084        try {
085          while (!listeners.isClosed()) {
086            ClientMessage msg = (ClientMessage)in.readObject();
087            switch (msg) {
088              case GET_WELCOME:
089                String welcome = shell.getWelcome();
090                out.writeObject(welcome);
091                out.flush();
092                break;
093              case GET_PROMPT:
094                String prompt = shell.getPrompt();
095                out.writeObject(prompt);
096                out.flush();
097                break;
098              case GET_COMPLETION:
099                String prefix = (String)in.readObject();
100                CommandCompletion completion = shell.complete(prefix);
101                out.writeObject(completion);
102                out.flush();
103                break;
104              case EXECUTE:
105                width = (Integer) in.readObject();
106                height = (Integer) in.readObject();
107                String line = (String)in.readObject();
108                ShellProcess process = shell.createProcess(line);
109                current = new ClientProcessContext(this, process);
110                process.execute(current);
111                break;
112              case CANCEL:
113                if (current != null) {
114                  current.process.cancel();
115                }
116                break;
117              case CLOSE:
118                close();
119                break;
120            }
121          }
122        }
123        catch (Exception e) {
124    //      e.printStackTrace();
125          //
126        }
127      }
128    
129      void close() {
130        listeners.close();
131      }
132    
133      public int getWidth() {
134        return width;
135      }
136    
137      public int getHeight() {
138        return height;
139      }
140    }