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 }