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 }