1 15 16 package javassist.web; 17 18 import java.net.*; 19 import java.io.*; 20 import java.util.Date ; 21 import javassist.*; 22 23 36 public class Webserver { 37 private ServerSocket socket; 38 private ClassPool classPool; 39 protected Translator translator; 40 41 private final static byte[] endofline = { 0x0d, 0x0a }; 42 private byte[] filebuffer = new byte[4096]; 43 44 private final static int typeHtml = 1; 45 private final static int typeClass = 2; 46 private final static int typeGif = 3; 47 private final static int typeJpeg = 4; 48 private final static int typeText = 5; 49 private final static int typeUnknown = 6; 50 51 57 public String debugDir = null; 58 59 73 public String htmlfileBase = null; 74 75 79 public static void main(String [] args) throws IOException { 80 if (args.length == 1) { 81 Webserver web = new Webserver(args[0]); 82 web.run(); 83 } 84 else 85 System.err.println( 86 "Usage: java javassist.web.Webserver <port number>"); 87 } 88 89 94 public Webserver(String port) throws IOException { 95 this(Integer.parseInt(port)); 96 } 97 98 103 public Webserver(int port) throws IOException { 104 socket = new ServerSocket(port); 105 classPool = null; 106 translator = null; 107 } 108 109 113 public void setClassPool(ClassPool loader) { 114 classPool = loader; 115 } 116 117 125 public void addTranslator(ClassPool cp, Translator t) 126 throws NotFoundException, CannotCompileException 127 { 128 classPool = cp; 129 translator = t; 130 t.start(classPool); 131 } 132 133 136 public void end() throws IOException { 137 socket.close(); 138 } 139 140 143 public void logging(String msg) { 144 System.out.println(msg); 145 } 146 147 150 public void logging(String msg1, String msg2) { 151 System.out.print(msg1); 152 System.out.print(" "); 153 System.out.println(msg2); 154 } 155 156 159 public void logging(String msg1, String msg2, String msg3) { 160 System.out.print(msg1); 161 System.out.print(" "); 162 System.out.print(msg2); 163 System.out.print(" "); 164 System.out.println(msg3); 165 } 166 167 170 public void logging2(String msg) { 171 System.out.print(" "); 172 System.out.println(msg); 173 } 174 175 178 public void run() { 179 System.err.println("ready to service..."); 180 for (;;) 181 try { 182 ServiceThread th = new ServiceThread(this, socket.accept()); 183 th.start(); 184 } 185 catch (IOException e) { 186 logging(e.toString()); 187 } 188 } 189 190 final void process(Socket clnt) throws IOException { 191 InputStream in = new BufferedInputStream(clnt.getInputStream()); 192 String cmd = readLine(in); 193 logging(clnt.getInetAddress().getHostName(), 194 new Date ().toString(), cmd); 195 while (skipLine(in) > 0){ 196 } 197 198 OutputStream out = new BufferedOutputStream(clnt.getOutputStream()); 199 try { 200 doReply(in, out, cmd); 201 } 202 catch (BadHttpRequest e) { 203 replyError(out, e); 204 } 205 206 out.flush(); 207 in.close(); 208 out.close(); 209 clnt.close(); 210 } 211 212 private String readLine(InputStream in) throws IOException { 213 StringBuffer buf = new StringBuffer (); 214 int c; 215 while ((c = in.read()) >= 0 && c != 0x0d) 216 buf.append((char)c); 217 218 in.read(); 219 return buf.toString(); 220 } 221 222 private int skipLine(InputStream in) throws IOException { 223 int c; 224 int len = 0; 225 while ((c = in.read()) >= 0 && c != 0x0d) 226 ++len; 227 228 in.read(); 229 return len; 230 } 231 232 238 public void doReply(InputStream in, OutputStream out, String cmd) 239 throws IOException, BadHttpRequest 240 { 241 int len; 242 int fileType; 243 String filename, urlName; 244 245 if (cmd.startsWith("GET /")) 246 filename = urlName = cmd.substring(5, cmd.indexOf(' ', 5)); 247 else 248 throw new BadHttpRequest(); 249 250 if (filename.endsWith(".class")) 251 fileType = typeClass; 252 else if (filename.endsWith(".html") || filename.endsWith(".htm")) 253 fileType = typeHtml; 254 else if (filename.endsWith(".gif")) 255 fileType = typeGif; 256 else if (filename.endsWith(".jpg")) 257 fileType = typeJpeg; 258 else 259 fileType = typeText; 261 len = filename.length(); 262 if (fileType == typeClass 263 && letUsersSendClassfile(out, filename, len)) 264 return; 265 266 checkFilename(filename, len); 267 if (htmlfileBase != null) 268 filename = htmlfileBase + filename; 269 270 if (File.separatorChar != '/') 271 filename = filename.replace('/', File.separatorChar); 272 273 File file = new File(filename); 274 if (file.canRead()) { 275 sendHeader(out, file.length(), fileType); 276 FileInputStream fin = new FileInputStream(file); 277 for (;;) { 278 len = fin.read(filebuffer); 279 if (len <= 0) 280 break; 281 else 282 out.write(filebuffer, 0, len); 283 } 284 285 fin.close(); 286 return; 287 } 288 289 292 if (fileType == typeClass) { 293 InputStream fin 294 = getClass().getResourceAsStream("/" + urlName); 295 if (fin != null) { 296 ByteArrayOutputStream barray = new ByteArrayOutputStream(); 297 for (;;) { 298 len = fin.read(filebuffer); 299 if (len <= 0) 300 break; 301 else 302 barray.write(filebuffer, 0, len); 303 } 304 305 byte[] classfile = barray.toByteArray(); 306 sendHeader(out, classfile.length, typeClass); 307 out.write(classfile); 308 fin.close(); 309 return; 310 } 311 } 312 313 throw new BadHttpRequest(); 314 } 315 316 private void checkFilename(String filename, int len) 317 throws BadHttpRequest 318 { 319 for (int i = 0; i < len; ++i) { 320 char c = filename.charAt(i); 321 if (!Character.isJavaIdentifierPart(c) && c != '.' && c != '/') 322 throw new BadHttpRequest(); 323 } 324 325 if (filename.indexOf("..") >= 0) 326 throw new BadHttpRequest(); 327 } 328 329 private boolean letUsersSendClassfile(OutputStream out, 330 String filename, int length) 331 throws IOException, BadHttpRequest 332 { 333 if (classPool == null) 334 return false; 335 336 byte[] classfile; 337 String classname 338 = filename.substring(0, length - 6).replace('/', '.'); 339 try { 340 if (translator != null) 341 translator.onLoad(classPool, classname); 342 343 CtClass c = classPool.get(classname); 344 classfile = c.toBytecode(); 345 if (debugDir != null) 346 c.writeFile(debugDir); 347 } 348 catch (Exception e) { 349 throw new BadHttpRequest(e); 350 } 351 352 sendHeader(out, classfile.length, typeClass); 353 out.write(classfile); 354 return true; 355 } 356 357 private void sendHeader(OutputStream out, long dataLength, int filetype) 358 throws IOException 359 { 360 out.write("HTTP/1.0 200 OK".getBytes()); 361 out.write(endofline); 362 out.write("Content-Length: ".getBytes()); 363 out.write(Long.toString(dataLength).getBytes()); 364 out.write(endofline); 365 if (filetype == typeClass) 366 out.write("Content-Type: application/octet-stream".getBytes()); 367 else if (filetype == typeHtml) 368 out.write("Content-Type: text/html".getBytes()); 369 else if (filetype == typeGif) 370 out.write("Content-Type: image/gif".getBytes()); 371 else if (filetype == typeJpeg) 372 out.write("Content-Type: image/jpg".getBytes()); 373 else if (filetype == typeText) 374 out.write("Content-Type: text/plain".getBytes()); 375 376 out.write(endofline); 377 out.write(endofline); 378 } 379 380 private void replyError(OutputStream out, BadHttpRequest e) 381 throws IOException 382 { 383 logging2("bad request: " + e.toString()); 384 out.write("HTTP/1.0 400 Bad Request".getBytes()); 385 out.write(endofline); 386 out.write(endofline); 387 out.write("<H1>Bad Request</H1>".getBytes()); 388 } 389 } 390 391 class ServiceThread extends Thread { 392 Webserver web; 393 Socket sock; 394 395 public ServiceThread(Webserver w, Socket s) { 396 web = w; 397 sock = s; 398 } 399 400 public void run() { 401 try { 402 web.process(sock); 403 } 404 catch (IOException e) { 405 } 406 } 407 } 408 | Popular Tags |