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(processContext.getWidth()); 113 out.writeObject(process.line); 114 out.flush(); 115 116 // 117 while (response == null) { 118 ServerMessage msg = (ServerMessage)in.readObject(); 119 switch (msg) { 120 case GET_WIDTH: 121 int width = processContext.getWidth(); 122 out.writeObject(width); 123 out.flush(); 124 break; 125 case READLINE: 126 String request = (String)in.readObject(); 127 boolean echo = (Boolean)in.readObject(); 128 String line = processContext.readLine(request, echo); 129 out.writeObject(line); 130 out.flush(); 131 break; 132 case END: 133 response = (ShellResponse)in.readObject(); 134 break; 135 default: 136 response = ShellResponse.internalError("Unexpected"); 137 break; 138 } 139 } 140 } 141 catch (Exception e) { 142 log.error("Remoting issue", e); 143 response = ShellResponse.internalError("Remoting issue", e); 144 } 145 finally { 146 147 // 148 this.process = null; 149 150 // 151 if (response != null) { 152 processContext.end(response); 153 } else { 154 processContext.end(ShellResponse.internalError("")); 155 } 156 } 157 } 158 159 void cancel(ServerProcess process) throws IllegalStateException { 160 if (process == this.process) { 161 this.process = null; 162 try { 163 out.writeObject(ClientMessage.CANCEL); 164 out.flush(); 165 } 166 catch (IOException ignore) { 167 } 168 } 169 } 170 }