001 package org.crsh.term.spi.net; 002 003 import org.crsh.term.CodeType; 004 import org.crsh.term.spi.TermIO; 005 import org.crsh.util.Safe; 006 007 import java.io.IOException; 008 import java.io.InputStream; 009 import java.io.OutputStream; 010 import java.net.InetSocketAddress; 011 import java.net.ServerSocket; 012 import java.net.Socket; 013 import java.nio.charset.Charset; 014 015 /** 016 * @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a> 017 */ 018 public class TermIOServer { 019 020 /** . */ 021 private static final Charset UTF_8 = Charset.forName("UTF-8"); 022 023 /** . */ 024 private final TermIO delegate; 025 026 /** . */ 027 private final int bindingPort; 028 029 /** . */ 030 private ServerSocket socketServer; 031 032 /** . */ 033 private Socket socket; 034 035 /** . */ 036 private InputStream in; 037 038 /** . */ 039 private OutputStream out; 040 041 /** . */ 042 private int port; 043 044 public TermIOServer(TermIO delegate, int bindingPort) { 045 this.delegate = delegate; 046 this.bindingPort = bindingPort; 047 } 048 049 public int getBindingPort() { 050 return socketServer.getLocalPort(); 051 } 052 053 public int getPort() { 054 return port; 055 } 056 057 public int bind() throws IOException { 058 ServerSocket socketServer = new ServerSocket(); 059 socketServer.bind(new InetSocketAddress(bindingPort)); 060 int port = socketServer.getLocalPort(); 061 062 // 063 this.socketServer = socketServer; 064 this.port = port; 065 066 // 067 return port; 068 } 069 070 public void accept() throws IOException { 071 if (socketServer == null) { 072 throw new IllegalStateException(); 073 } 074 075 // 076 this.socket = socketServer.accept(); 077 this.in = socket.getInputStream(); 078 this.out = socket.getOutputStream(); 079 } 080 081 private byte read() throws IOException, Done { 082 int b = in.read(); 083 if (b == -1) { 084 throw new Done(); 085 } 086 return (byte)b; 087 } 088 089 private int read(byte[] buffer, int off, int len) throws IOException, Done { 090 int b = in.read(buffer, off, len); 091 if (b == -1) { 092 throw new Done(); 093 } 094 return b; 095 } 096 097 private void write(byte b) throws IOException, Done { 098 out.write(b); 099 } 100 101 private void write(byte[] bytes) throws IOException, Done { 102 out.write(bytes); 103 } 104 105 private void flush() throws IOException, Done { 106 out.flush(); 107 } 108 109 public boolean execute() throws IOException, IllegalStateException { 110 if (socket == null) { 111 throw new IllegalStateException("No connection"); 112 } 113 try { 114 iterate(); 115 return true; 116 } catch (Done ignore) { 117 Safe.close(in); 118 Safe.close(out); 119 Safe.close(socket); 120 in = null; 121 out = null; 122 socket = null; 123 return false; 124 } 125 } 126 127 private void iterate() throws IOException, Done { 128 byte b = read(); 129 if (b == 0) { 130 int code = delegate.read(); 131 CodeType codeType = delegate.decode(code); 132 byte ordinal = (byte) codeType.ordinal(); 133 if (codeType == CodeType.CHAR) { 134 write(new byte[]{ordinal, (byte)((code & 0xFF00) >> 8), (byte)((code & 0xFF))}); 135 } else { 136 write(ordinal); 137 } 138 flush(); 139 } else if (b == 1) { 140 int b1 = in.read(); 141 int b2 = in.read(); 142 char c = (char)((b1 << 8) + b2); 143 delegate.write(c); 144 } else if (b == 2) { 145 b = read(); 146 int remaining = (b + 2) * 2; 147 int offset = 0; 148 byte[] buffer = new byte[remaining]; 149 while (remaining > 0) { 150 int r = read(buffer, offset, remaining); 151 offset += r; 152 remaining -= r; 153 } 154 char[] chars = new char[buffer.length / 2]; 155 int index = 0; 156 for (int i = 0;i < chars.length;i++) { 157 int high = buffer[index++]; 158 int low = buffer[index++]; 159 chars[i] = (char)((high << 8) + low); 160 } 161 String s = new String(chars); 162 delegate.write(s); 163 } else if (b == 3) { 164 delegate.writeDel(); 165 } else if (b == 4) { 166 delegate.writeCRLF(); 167 } else if (b == 5) { 168 int b1 = in.read(); 169 int b2 = in.read(); 170 char c = (char)((b1 << 8) + b2); 171 delegate.moveRight(c); 172 } else if (b == 6) { 173 delegate.moveLeft(); 174 } else if (b == 7) { 175 delegate.flush(); 176 } else if (b == 8) { 177 int len = read() + 1; 178 byte[] bytes = new byte[len]; 179 read(bytes, 0, len); 180 String propertyName = new String(bytes, UTF_8); 181 String propertyValue; 182 if ("width".equals(propertyName)) { 183 propertyValue = Integer.toString(delegate.getWidth()); 184 } else { 185 propertyValue = delegate.getProperty(propertyName); 186 } 187 if (propertyValue == null) { 188 write((byte)0); 189 } else if (propertyValue.length() == 0) { 190 write((byte)1); 191 } else { 192 bytes = propertyValue.getBytes(UTF_8); 193 len = bytes.length; 194 if (len > 254) { 195 // We don't process that for now 196 // so we say it's null 197 write((byte)0); 198 } else { 199 write((byte)(len + 1)); 200 write(bytes); 201 } 202 flush(); 203 } 204 } else { 205 throw new UnsupportedOperationException("cannot handle " + b); 206 } 207 } 208 }