001    package org.crsh.shell.impl.remoting;
002    
003    import org.crsh.cmdline.CommandCompletion;
004    import org.crsh.shell.Shell;
005    import org.crsh.shell.ShellProcess;
006    import org.crsh.shell.ShellProcessContext;
007    import org.crsh.shell.ShellResponse;
008    import org.crsh.util.CloseableList;
009    import org.slf4j.Logger;
010    import org.slf4j.LoggerFactory;
011    
012    import java.io.Closeable;
013    import java.io.IOException;
014    import java.io.InputStream;
015    import java.io.ObjectInputStream;
016    import java.io.ObjectOutputStream;
017    import java.io.OutputStream;
018    import java.lang.reflect.UndeclaredThrowableException;
019    
020    /** @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a> */
021    public class ServerAutomaton implements Shell {
022    
023      /** . */
024      final Logger log = LoggerFactory.getLogger(ServerAutomaton.class);
025    
026      /** . */
027      final ObjectInputStream in;
028    
029      /** . */
030      final ObjectOutputStream out;
031    
032      /** . */
033      ServerProcess process;
034    
035      /** . */
036      final CloseableList listeners;
037    
038      public ServerAutomaton(ObjectOutputStream out, ObjectInputStream in) {
039        CloseableList listeners = new CloseableList();
040        listeners.add(in);
041        listeners.add(out);
042    
043        //
044        this.in = in;
045        this.out = out;
046        this.listeners = listeners;
047      }
048    
049      public ServerAutomaton(InputStream in, OutputStream out) throws IOException {
050        this(new ObjectOutputStream(out), new ObjectInputStream(in));
051      }
052    
053      public ServerAutomaton addCloseListener(Closeable closeable) {
054        listeners.add(closeable);
055        return this;
056      }
057    
058      public String getWelcome() {
059        try {
060          out.writeObject(ClientMessage.GET_WELCOME);
061          out.flush();
062          return (String)in.readObject();
063        }
064        catch (Exception e) {
065          throw new UndeclaredThrowableException(e);
066        }
067      }
068    
069      public String getPrompt() {
070        try {
071          out.writeObject(ClientMessage.GET_PROMPT);
072          out.flush();
073          return (String)in.readObject();
074        }
075        catch (Exception e) {
076          throw new UndeclaredThrowableException(e);
077        }
078      }
079    
080      public ShellProcess createProcess(String request) throws IllegalStateException {
081        return new ServerProcess(this, request);
082      }
083    
084      public CommandCompletion complete(String prefix) {
085        try {
086          out.writeObject(ClientMessage.GET_COMPLETION);
087          out.writeObject(prefix);
088          out.flush();
089          return (CommandCompletion)in.readObject();
090        }
091        catch (Exception e) {
092          throw new UndeclaredThrowableException(e);
093        }
094      }
095    
096      void close() {
097        listeners.close();
098      }
099    
100      void execute(ServerProcess process, ShellProcessContext processContext) throws IllegalStateException {
101    
102        if (this.process == null) {
103          this.process = process;
104        } else {
105          throw new IllegalStateException();
106        }
107    
108        //
109        ShellResponse response = null;
110        try {
111          out.writeObject(ClientMessage.EXECUTE);
112          out.writeObject(process.line);
113          out.flush();
114    
115          //
116          while (response == null) {
117            ServerMessage msg = (ServerMessage)in.readObject();
118            switch (msg) {
119              case GET_WIDTH:
120                int width = processContext.getWidth();
121                out.writeObject(width);
122                out.flush();
123                break;
124              case READLINE:
125                String request = (String)in.readObject();
126                boolean echo = (Boolean)in.readObject();
127                String line = processContext.readLine(request, echo);
128                out.writeObject(line);
129                out.flush();
130                break;
131              case END:
132                response = (ShellResponse)in.readObject();
133                break;
134              default:
135                response = ShellResponse.internalError("Unexpected");
136                break;
137            }
138          }
139        }
140        catch (Exception e) {
141          log.error("Remoting issue", e);
142          response = ShellResponse.internalError("Remoting issue", e);
143        }
144        finally {
145    
146          //
147          this.process = null;
148    
149          //
150          if (response != null) {
151            processContext.end(response);
152          } else {
153            processContext.end(ShellResponse.internalError(""));
154          }
155        }
156      }
157    
158      void cancel(ServerProcess process) throws IllegalStateException {
159        if (process == this.process) {
160          this.process = null;
161          try {
162            out.writeObject(ClientMessage.CANCEL);
163            out.flush();
164          }
165          catch (IOException ignore) {
166          }
167        }
168      }
169    }