1 18 19 package com.martiansoftware.nailgun; 20 21 import java.io.InputStream ; 22 import java.io.PrintStream ; 23 import java.lang.reflect.InvocationTargetException ; 24 import java.lang.reflect.Method ; 25 import java.net.Socket ; 26 import java.util.List ; 27 import java.util.Properties ; 28 29 import org.apache.tools.ant.ExitException; 30 31 39 class NGSession extends Thread { 40 41 44 private NGServer server = null; 45 46 50 private NGSessionPool sessionPool = null; 51 52 55 private Object lock = new Object (); 56 57 61 private Socket nextSocket = null; 62 63 67 private boolean done = false; 68 69 73 private long instanceNumber = 0; 74 75 78 private static Object sharedLock = new Object (); 79 80 83 private static long instanceCounter = 0; 84 85 88 private static Class [] mainSignature; 89 90 93 private static Class [] nailMainSignature; 94 95 static { 96 mainSignature = new Class [1]; 98 mainSignature[0] = String [].class; 99 100 nailMainSignature = new Class [1]; 101 nailMainSignature[0] = NGContext.class; 102 } 103 104 110 NGSession(NGSessionPool sessionPool, NGServer server) { 111 super(); 112 this.sessionPool = sessionPool; 113 this.server = server; 114 115 synchronized(sharedLock) { 116 this.instanceNumber = ++instanceCounter; 117 } 118 } 120 121 124 void shutdown() { 125 done = true; 126 synchronized(lock) { 127 nextSocket = null; 128 lock.notifyAll(); 129 } 130 } 131 132 137 public void run(Socket socket) { 138 synchronized(lock) { 139 nextSocket = socket; 140 lock.notify(); 141 } 142 Thread.yield(); 143 } 144 145 153 private Socket nextSocket() { 154 Socket result = null; 155 synchronized(lock) { 156 result = nextSocket; 157 while (!done && result == null) { 158 try { 159 lock.wait(); 160 } catch (InterruptedException e) { 161 done = true; 162 } 163 result = nextSocket; 164 } 165 nextSocket = null; 166 } 167 return (result); 168 } 169 170 174 public void run() { 175 176 updateThreadName(null); 177 178 Socket socket = nextSocket(); 179 while (socket != null) { 180 try { 181 byte[] lbuf = new byte[5]; 183 java.io.DataInputStream sockin = new java.io.DataInputStream (socket.getInputStream()); 184 java.io.OutputStream sockout = socket.getOutputStream(); 185 186 List remoteArgs = new java.util.ArrayList (); 188 Properties remoteEnv = new Properties (); 189 190 String cwd = null; String command = null; 193 while (command == null) { 195 sockin.readFully(lbuf); 196 long bytesToRead = LongUtils.fromArray(lbuf, 0); 197 char chunkType = (char) lbuf[4]; 198 199 byte[] b = new byte[(int) bytesToRead]; 200 sockin.readFully(b); 201 String line = new String (b, "US-ASCII"); 202 203 switch(chunkType) { 204 205 case NGConstants.CHUNKTYPE_ARGUMENT: 206 remoteArgs.add(line); 208 break; 209 210 case NGConstants.CHUNKTYPE_ENVIRONMENT: 211 int equalsIndex = line.indexOf('='); 213 if (equalsIndex > 0) { 214 remoteEnv.setProperty( 215 line.substring(0, equalsIndex), 216 line.substring(equalsIndex + 1)); 217 } 218 String key = line.substring(0, equalsIndex); 219 break; 220 221 case NGConstants.CHUNKTYPE_COMMAND: 222 command = line; 224 break; 225 226 case NGConstants.CHUNKTYPE_WORKINGDIRECTORY: 227 cwd = line; 229 break; 230 231 default: } 233 } 234 235 updateThreadName(socket.getInetAddress().getHostAddress() + ": " + command); 236 237 InputStream in = new NGInputStream(sockin); 241 PrintStream out = new PrintStream (new NGOutputStream(sockout, NGConstants.CHUNKTYPE_STDOUT)); 242 PrintStream err = new PrintStream (new NGOutputStream(sockout, NGConstants.CHUNKTYPE_STDERR)); 243 PrintStream exit = new PrintStream (new NGOutputStream(sockout, NGConstants.CHUNKTYPE_EXIT)); 244 245 ((ThreadLocalInputStream) System.in).init(in); 247 ((ThreadLocalPrintStream) System.out).init(out); 248 ((ThreadLocalPrintStream) System.err).init(err); 249 250 try { 251 Alias alias = server.getAliasManager().getAlias(command); 252 Class cmdclass = null; 253 if (alias != null) { 254 cmdclass = alias.getAliasedClass(); 255 } else if (server.allowsNailsByClassName()) { 256 cmdclass = Class.forName(command); 257 } else { 258 cmdclass = server.getDefaultNailClass(); 259 } 260 261 Object [] methodArgs = new Object [1]; 262 Method mainMethod = null; String [] cmdlineArgs = (String []) remoteArgs.toArray(new String [remoteArgs.size()]); 264 265 try { 266 mainMethod = cmdclass.getMethod("nailMain", nailMainSignature); 267 NGContext context = new NGContext(); 268 context.setArgs(cmdlineArgs); 269 context.in = in; 270 context.out = out; 271 context.err = err; 272 context.setCommand(command); 273 context.setExitStream(exit); 274 context.setNGServer(server); 275 context.setEnv(remoteEnv); 276 context.setInetAddress(socket.getInetAddress()); 277 context.setPort(socket.getPort()); 278 context.setWorkingDirectory(cwd); 279 methodArgs[0] = context; 280 } catch (NoSuchMethodException toDiscard) { 281 } 283 284 if (mainMethod == null) { 285 mainMethod = cmdclass.getMethod("main", mainSignature); 286 methodArgs[0] = cmdlineArgs; 287 } 288 289 if (mainMethod != null) { 290 server.nailStarted(cmdclass); 291 NGSecurityManager.setExit(exit); 292 293 try { 294 mainMethod.invoke(null, methodArgs); 295 } catch (InvocationTargetException ite) { 296 throw(ite.getCause()); 297 } catch (Throwable t) { 298 throw(t); 299 } finally { 300 server.nailFinished(cmdclass); 301 } 302 exit.println(0); 303 } 304 305 } catch (ExitException exitEx) { 306 exit.println(exitEx.getStatus()); 307 server.out.println(Thread.currentThread().getName() + " exited with status " + exitEx.getStatus()); 308 } catch (Throwable t) { 309 t.printStackTrace(); 310 exit.println(NGConstants.EXIT_EXCEPTION); } 312 313 socket.close(); 314 315 } catch (Throwable t) { 316 t.printStackTrace(); 317 } 318 319 ((ThreadLocalInputStream) System.in).init(null); 320 ((ThreadLocalPrintStream) System.out).init(null); 321 ((ThreadLocalPrintStream) System.err).init(null); 322 323 updateThreadName(null); 324 sessionPool.give(this); 325 socket = nextSocket(); 326 } 327 328 } 330 331 334 private void updateThreadName(String detail) { 335 setName("NGSession " + instanceNumber + ": " + ((detail == null) ? "(idle)" : detail)); 336 } 337 } 338 | Popular Tags |