1 22 package org.jboss.web; 23 24 import java.io.BufferedInputStream ; 25 import java.io.BufferedReader ; 26 import java.io.ByteArrayOutputStream ; 27 import java.io.DataOutputStream ; 28 import java.io.IOException ; 29 import java.io.InputStream ; 30 import java.io.InputStreamReader ; 31 import java.net.InetAddress ; 32 import java.net.MalformedURLException ; 33 import java.net.ServerSocket ; 34 import java.net.Socket ; 35 import java.net.URL ; 36 import java.net.UnknownHostException ; 37 import java.util.Properties ; 38 39 import org.jboss.logging.Logger; 40 import org.jboss.util.StringPropertyReplacer; 41 import org.jboss.util.threadpool.BasicThreadPool; 42 import org.jboss.util.threadpool.BasicThreadPoolMBean; 43 44 import EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap; 45 46 61 public class WebServer 62 implements Runnable 63 { 64 66 private static Logger log = Logger.getLogger(WebServer.class); 68 71 private int port = 8083; 72 73 77 private InetAddress bindAddress; 78 81 private int backlog = 50; 82 83 86 private final ConcurrentReaderHashMap loaderMap = new ConcurrentReaderHashMap(); 87 90 private ServerSocket server = null; 91 96 private boolean downloadServerClasses = true; 97 101 private boolean downloadResources = false; 102 106 private static final Properties mimeTypes = new Properties (); 107 110 private BasicThreadPoolMBean threadPool; 111 112 114 117 public void setPort(int p) 118 { 119 port = p; 120 } 121 122 126 public int getPort() 127 { 128 return port; 129 } 130 131 public String getBindAddress() 132 { 133 String address = null; 134 if (bindAddress != null) 135 address = bindAddress.getHostAddress(); 136 return address; 137 } 138 139 public String getBindHostname() 140 { 141 return bindAddress.getHostName(); 142 } 143 144 public void setBindAddress(String host) 145 { 146 try 147 { 148 if (host != null) 149 { 150 String h = StringPropertyReplacer.replaceProperties(host); 151 bindAddress = InetAddress.getByName(h); 152 } 153 } 154 catch (UnknownHostException e) 155 { 156 String msg = "Invalid host address specified: " + host; 157 log.error(msg, e); 158 } 159 } 160 161 165 public int getBacklog() 166 { 167 return backlog; 168 } 169 170 173 public void setBacklog(int backlog) 174 { 175 if (backlog <= 0) 176 backlog = 50; 177 this.backlog = backlog; 178 } 179 180 public boolean getDownloadServerClasses() 181 { 182 return downloadServerClasses; 183 } 184 185 public void setDownloadServerClasses(boolean flag) 186 { 187 downloadServerClasses = flag; 188 } 189 190 public boolean getDownloadResources() 191 { 192 return downloadResources; 193 } 194 195 public void setDownloadResources(boolean flag) 196 { 197 downloadResources = flag; 198 } 199 200 201 public BasicThreadPoolMBean getThreadPool() 202 { 203 return threadPool; 204 } 205 206 public void setThreadPool(BasicThreadPoolMBean threadPool) 207 { 208 this.threadPool = threadPool; 209 } 210 211 216 public void addMimeType(String extension, String type) 217 { 218 mimeTypes.put(extension, type); 219 } 220 221 224 public void start() throws Exception 225 { 226 if (threadPool == null) 227 threadPool = new BasicThreadPool("ClassLoadingPool"); 228 try 229 { 230 server = new ServerSocket (port, backlog, bindAddress); 231 log.debug("Started server: " + server); 232 listen(); 233 } 234 catch(java.net.BindException be) 235 { 236 throw new Exception ("Port "+port+" already in use.",be); 237 } 238 catch (IOException e) 239 { 240 throw e; 241 } 242 } 243 244 247 public void stop() 248 { 249 try 250 { 251 ServerSocket srv = server; 252 server = null; 253 srv.close(); 254 } 255 catch (Exception e) 256 { 257 } 258 } 259 260 272 public URL addClassLoader(ClassLoader cl) 273 { 274 String key = (cl instanceof WebClassLoader) ? 275 ((WebClassLoader) cl).getKey() : 276 getClassLoaderKey(cl); 277 loaderMap.put(key, cl); 278 URL loaderURL = null; 279 String codebase = System.getProperty("java.rmi.server.codebase"); 280 if (codebase != null) 281 { 282 if (codebase.endsWith("/") == false) 283 codebase += '/'; 284 codebase += key; 285 codebase += '/'; 286 try 287 { 288 loaderURL = new URL (codebase); 289 } 290 catch (MalformedURLException e) 291 { 292 log.error("invalid url", e); 293 } 294 } 295 log.trace("Added ClassLoader: " + cl + " URL: " + loaderURL); 296 return loaderURL; 297 } 298 299 303 public void removeClassLoader(ClassLoader cl) 304 { 305 String key = getClassLoaderKey(cl); 306 loaderMap.remove(key); 307 } 308 309 315 public void run() 316 { 317 if (server == null) 319 return; 320 321 Socket socket = null; 323 try 324 { 325 socket = server.accept(); 326 } 327 catch (IOException e) 328 { 329 if (server != null) 331 log.error("Failed to accept connection", e); 332 return; 333 } 334 335 listen(); 337 338 try 339 { 340 DataOutputStream out = new DataOutputStream (socket.getOutputStream()); 342 try 343 { 344 String httpCode = "200 OK"; 345 BufferedReader in = new BufferedReader (new InputStreamReader (socket.getInputStream())); 347 String rawPath = getPath(in); 348 349 360 int endOfKey = rawPath.indexOf(']'); 361 String filePath = rawPath.substring(endOfKey + 2); 362 String loaderKey = rawPath.substring(0, endOfKey + 1); 363 log.trace("loaderKey = " + loaderKey); 364 log.trace("filePath = " + filePath); 365 ClassLoader loader = (ClassLoader ) loaderMap.get(loaderKey); 366 371 if (loader == null && rawPath.indexOf('[') < 0 && downloadServerClasses) 372 { 373 filePath = rawPath; 374 log.trace("No loader, reset filePath = " + filePath); 375 loader = Thread.currentThread().getContextClassLoader(); 376 } 377 log.trace("loader = " + loader); 378 byte[] bytes = {}; 379 if (loader != null && filePath.endsWith(".class")) 380 { 381 String className = filePath.substring(0, filePath.length() - 6).replace('/', '.'); 383 log.trace("loading className = " + className); 384 Class clazz = loader.loadClass(className); 385 URL clazzUrl = clazz.getProtectionDomain().getCodeSource().getLocation(); 386 log.trace("clazzUrl = " + clazzUrl); 387 if (clazzUrl == null) 388 { 389 bytes = ((WebClassLoader) clazz.getClassLoader()).getBytes(clazz); 392 if (bytes == null) 393 throw new Exception ("Class not found: " + className); 394 } 395 else 396 { 397 if (clazzUrl.getFile().endsWith("/") == false) 398 { 399 clazzUrl = new URL ("jar:" + clazzUrl + "!/" + filePath); 400 } 401 else if (clazzUrl.getFile().indexOf("/org_jboss_aop_proxy$") < 0) 403 { 404 clazzUrl = new URL (clazzUrl, filePath); 405 } 406 407 log.trace("new clazzUrl: " + clazzUrl); 409 bytes = getBytes(clazzUrl); 410 } 411 } 412 else if (loader != null && filePath.length() > 0 && downloadServerClasses && downloadResources) 413 { 414 log.trace("loading resource = " + filePath); 416 URL resourceURL = loader.getResource(filePath); 417 if (resourceURL == null) 418 httpCode = "404 Resource not found:" + filePath; 419 else 420 { 421 log.trace("resourceURL = " + resourceURL); 423 bytes = getBytes(resourceURL); 424 } 425 } 426 else 427 { 428 httpCode = "404 Not Found"; 429 } 430 431 432 try 434 { 435 log.trace("HTTP code=" + httpCode + ", Content-Length: " + bytes.length); 436 out.writeBytes("HTTP/1.0 " + httpCode + "\r\n"); 438 out.writeBytes("Content-Length: " + bytes.length + "\r\n"); 439 out.writeBytes("Content-Type: " + getMimeType(filePath)); 440 out.writeBytes("\r\n\r\n"); 441 out.write(bytes); 443 out.flush(); 444 } 445 catch (IOException ie) 446 { 447 return; 448 } 449 } 450 catch (Throwable e) 451 { 452 try 453 { 454 log.trace("HTTP code=404 " + e.getMessage()); 455 out.writeBytes("HTTP/1.0 400 " + e.getMessage() + "\r\n"); 457 out.writeBytes("Content-Type: text/html\r\n\r\n"); 458 out.flush(); 459 } 460 catch (IOException ex) 461 { 462 } 464 } 465 } 466 catch (IOException ex) 467 { 468 log.error("error writting response", ex); 469 } 470 finally 471 { 472 try 474 { 475 socket.close(); 476 } 477 catch (IOException e) 478 { 479 } 480 } 481 } 482 483 488 protected String getClassLoaderKey(ClassLoader cl) 489 { 490 String className = cl.getClass().getName(); 491 int dot = className.lastIndexOf('.'); 492 if (dot >= 0) 493 className = className.substring(dot + 1); 494 String key = className + '[' + cl.hashCode() + ']'; 495 return key; 496 } 497 498 protected void listen() 499 { 500 threadPool.getInstance().run(this); 501 } 502 503 506 protected String getPath(BufferedReader in) throws IOException 507 { 508 String line = in.readLine(); 509 log.trace("raw request=" + line); 510 int start = line.indexOf(' ') + 1; 512 int end = line.indexOf(' ', start + 1); 513 String filePath = line.substring(start + 1, end); 515 return filePath; 516 } 517 518 521 protected byte[] getBytes(URL url) throws IOException 522 { 523 InputStream in = new BufferedInputStream (url.openStream()); 524 log.debug("Retrieving " + url); 525 ByteArrayOutputStream out = new ByteArrayOutputStream (); 526 byte[] tmp = new byte[1024]; 527 int bytes; 528 while ((bytes = in.read(tmp)) != -1) 529 { 530 out.write(tmp, 0, bytes); 531 } 532 in.close(); 533 return out.toByteArray(); 534 } 535 536 540 protected String getMimeType(String path) 541 { 542 int dot = path.lastIndexOf("."); 543 String type = "text/html"; 544 if (dot >= 0) 545 { 546 String suffix = path.substring(dot + 1); 548 String mimeType = mimeTypes.getProperty(suffix); 549 if (mimeType != null) 550 type = mimeType; 551 } 552 return type; 553 } 554 555 } 556 | Popular Tags |