1 22 package org.jboss.web; 23 24 import java.io.ByteArrayInputStream ; 25 import java.io.ByteArrayOutputStream ; 26 import java.io.File ; 27 import java.io.FileInputStream ; 28 import java.io.InputStream ; 29 import java.lang.reflect.Method ; 30 import java.net.URL ; 31 import java.net.URLClassLoader ; 32 import java.util.ArrayList ; 33 import java.util.Collection ; 34 import java.util.HashMap ; 35 import java.util.HashSet ; 36 import java.util.Iterator ; 37 import java.util.List ; 38 import java.util.Set ; 39 import java.util.jar.JarInputStream ; 40 import java.util.zip.ZipEntry ; 41 42 import javax.management.ObjectName ; 43 44 import org.jboss.deployment.DeploymentException; 45 import org.jboss.deployment.DeploymentInfo; 46 import org.jboss.deployment.SubDeployerSupport; 47 import org.jboss.metadata.WebMetaData; 48 import org.jboss.metadata.XmlFileLoader; 49 import org.jboss.mx.loading.LoaderRepositoryFactory; 50 import org.jboss.mx.loading.LoaderRepositoryFactory.LoaderRepositoryConfig; 51 import org.jboss.mx.util.MBeanProxyExt; 52 import org.jboss.mx.util.ObjectNameFactory; 53 import org.jboss.system.ServiceControllerMBean; 54 import org.jboss.util.file.FilenameSuffixFilter; 55 import org.jboss.util.file.JarUtils; 56 import org.w3c.dom.Document ; 57 import org.w3c.dom.Element ; 58 59 72 public abstract class AbstractWebContainer extends SubDeployerSupport 73 implements AbstractWebContainerMBean 74 { 75 public static final String DEPLOYER = "org.jboss.web.AbstractWebContainer.deployer"; 76 public static final String WEB_APP = "org.jboss.web.AbstractWebContainer.webApp"; 77 public static final String WEB_MODULE = "org.jboss.web.AbstractWebContainer.webModule"; 78 public static final String ERROR = "org.jboss.web.AbstractWebContainer.error"; 79 80 public static interface WebDescriptorParser 81 { 82 102 public void parseWebAppDescriptors(ClassLoader loader, WebMetaData metaData) throws Exception ; 103 104 110 public DeploymentInfo getDeploymentInfo(); 111 } 112 113 114 private static final String [] DEFAULT_ENHANCED_SUFFIXES = new String [] { 115 "500:.war" 116 }; 117 118 119 protected HashMap deploymentMap = new HashMap (); 120 121 protected boolean java2ClassLoadingCompliance = false; 122 123 protected boolean unpackWars = true; 124 126 protected boolean acceptNonWarDirs = false; 127 128 129 protected boolean lenientEjbLink = false; 130 131 132 protected String defaultSecurityDomain = "java:/jaas/other"; 133 134 private String subjectAttributeName = null; 135 136 protected ServiceControllerMBean serviceController; 137 138 public AbstractWebContainer() 139 { 140 setEnhancedSuffixes(DEFAULT_ENHANCED_SUFFIXES); 141 } 142 143 148 public boolean getJava2ClassLoadingCompliance() 149 { 150 return java2ClassLoadingCompliance; 151 } 152 153 158 public void setJava2ClassLoadingCompliance(boolean flag) 159 { 160 java2ClassLoadingCompliance = flag; 161 } 162 163 170 public boolean getUnpackWars() 171 { 172 return unpackWars; 173 } 174 175 182 public void setUnpackWars(boolean flag) 183 { 184 this.unpackWars = flag; 185 } 186 187 193 public boolean getAcceptNonWarDirs() 194 { 195 return acceptNonWarDirs; 196 } 197 203 public void setAcceptNonWarDirs(boolean flag) 204 { 205 this.acceptNonWarDirs = flag; 206 } 207 208 215 public boolean getLenientEjbLink() 216 { 217 return lenientEjbLink; 218 } 219 220 226 public void setLenientEjbLink(boolean flag) 227 { 228 lenientEjbLink = flag; 229 } 230 231 237 public String getDefaultSecurityDomain() 238 { 239 return defaultSecurityDomain; 240 } 241 248 public void setDefaultSecurityDomain(String defaultSecurityDomain) 249 { 250 this.defaultSecurityDomain = defaultSecurityDomain; 251 } 252 253 256 public String getSubjectAttributeName() 257 { 258 return subjectAttributeName; 259 } 260 263 public void setSubjectAttributeName(String subjectAttributeName) 264 { 265 this.subjectAttributeName = subjectAttributeName; 266 } 267 268 269 public abstract AbstractWebDeployer getDeployer(DeploymentInfo di) throws Exception ; 270 271 public boolean accepts(DeploymentInfo sdi) 272 { 273 boolean accepts = super.accepts(sdi); 275 276 if (accepts == false && acceptNonWarDirs == true) 277 { 278 if (sdi.url.getProtocol().equalsIgnoreCase("file")) 280 { 281 File webXml = new File (sdi.url.getFile(), "WEB-INF/web.xml"); 282 accepts = webXml.exists(); 283 } 284 } 285 return accepts; 286 } 287 288 public synchronized void init(DeploymentInfo di) 289 throws DeploymentException 290 { 291 log.debug("Begin init"); 292 this.server = di.getServer(); 293 try 294 { 295 if (di.url.getPath().endsWith("/")) 296 { 297 di.watch = new URL (di.url, "WEB-INF/web.xml"); 299 } 300 else 301 { 302 di.watch = di.url; 304 } 305 306 boolean unpackWebservice = di.localCl.findResource("WEB-INF/webservices.xml") != null; 309 unpackWebservice |= server.isRegistered(ObjectNameFactory.create("jboss.ws:service=ServiceEndpointManager")); 311 312 File warFile = new File (di.localUrl.getFile()); 314 if (warFile.isDirectory() == false && (unpackWars || unpackWebservice)) 315 { 316 String prefix = warFile.getCanonicalPath(); 319 prefix = prefix.substring(0, prefix.lastIndexOf(".war")); 320 File expWarFile = new File (prefix + "-exp.war"); 321 if( expWarFile.mkdir() == false ) 322 throw new DeploymentException("Was unable to mkdir: "+expWarFile); 323 log.debug("Unpacking war to: "+expWarFile); 324 FileInputStream fis = new FileInputStream (warFile); 325 JarUtils.unjar(fis, expWarFile); 326 fis.close(); 327 log.debug("Replaced war with unpacked contents"); 328 if (warFile.delete() == false) 329 log.debug("Was unable to delete war file"); 330 else 331 log.debug("Deleted war archive"); 332 di.localUrl = expWarFile.toURL(); 334 URL [] localCl = new URL []{di.localUrl}; 336 di.localCl = new URLClassLoader (localCl); 337 } 338 339 WebMetaData metaData = new WebMetaData(); 340 metaData.setResourceClassLoader(di.localCl); 341 metaData.setJava2ClassLoadingCompliance(this.java2ClassLoadingCompliance); 342 di.metaData = metaData; 343 344 String webContext = di.webContext; 345 if( webContext != null ) 346 { 347 if( webContext.length() > 0 && webContext.charAt(0) != '/' ) 348 webContext = "/" + webContext; 349 } 350 URL warURL = di.localUrl != null ? di.localUrl : di.url; 352 log.debug("webContext: " + webContext); 353 log.debug("warURL: " + warURL); 354 355 parseMetaData(webContext, warURL, di.shortName, metaData); 357 358 LoaderRepositoryConfig config = metaData.getLoaderConfig(); 360 if (config != null) 361 di.setRepositoryInfo(config); 362 363 super.init(di); 365 } 366 catch (DeploymentException e) 367 { 368 log.debug("Problem in init ", e); 369 throw e; 370 } 371 catch (Exception e) 372 { 373 log.error("Problem in init ", e); 374 throw new DeploymentException(e); 375 } 376 377 log.debug("End init"); 378 } 379 380 388 public void create(DeploymentInfo di) throws DeploymentException 389 { 390 log.debug("create, " + di.shortName); 391 try 392 { 393 URL loaderURL = (di.localUrl != null ? di.localUrl : di.url); 395 File warFile = new File (di.localUrl.getFile()); 396 if (warFile.isDirectory()) 397 { 398 List urlList = new ArrayList (); 399 urlList.add(new URL (loaderURL + "WEB-INF/classes/")); 400 401 File libDir = new File (warFile, "WEB-INF/lib/"); 402 String [] jarArr = libDir.list(new FilenameSuffixFilter(".jar")); 403 for (int i = 0; jarArr != null && i < jarArr.length; i++) 404 { 405 String urlStr = loaderURL + "WEB-INF/lib/" + jarArr[i]; 406 urlList.add(new URL (urlStr)); 407 } 408 URL [] urlArr = new URL [urlList.size()]; 409 urlList.toArray(urlArr); 410 di.annotationsCl = new URLClassLoader (urlArr, di.ucl); 411 } 412 else 413 { 414 List urlList = new ArrayList (); 415 urlList.add(new URL (warFile + "!WEB-INF/classes")); 416 417 FileInputStream fis = new FileInputStream (warFile); 418 JarInputStream jin = new JarInputStream (fis); 419 ZipEntry entry = jin.getNextEntry(); 420 while (entry != null) 421 { 422 String entryName = entry.getName(); 423 if (entryName.startsWith("WEB-INF/lib")) 424 { 425 urlList.add(new URL (warFile + "!" + entryName)); 426 } 427 entry = jin.getNextEntry(); 428 } 429 jin.close(); 430 431 URL [] urlArr = new URL [urlList.size()]; 432 urlList.toArray(urlArr); 433 di.annotationsCl = new URLClassLoader (urlArr, di.ucl); 434 } 435 436 AbstractWebDeployer deployer = getDeployer(di); 437 di.context.put(DEPLOYER, deployer); 438 WebMetaData metaData = (WebMetaData) di.metaData; 439 processMetaData(di); 440 Collection depends = metaData.getDepends(); 441 WebModule module = new WebModule(di, this, deployer); 442 ObjectName jmxName = new ObjectName ("jboss.web.deployment:war=" 443 + di.shortName + ",id="+di.hashCode()); 444 server.registerMBean(module, jmxName); 445 di.context.put(WEB_MODULE, jmxName); 446 serviceController.create(jmxName, depends); 447 super.create(di); 449 } 450 catch(Exception e) 451 { 452 throw new DeploymentException("Failed to create web module", e); 453 } 454 } 455 456 463 protected void processMetaData(DeploymentInfo di) 464 { 465 } 467 468 474 public synchronized void start(DeploymentInfo di) throws DeploymentException 475 { 476 ObjectName jmxName = (ObjectName ) di.context.get(WEB_MODULE); 477 try 478 { 479 serviceController.start(jmxName); 480 } 481 catch (DeploymentException e) 482 { 483 throw e; 484 } 485 catch(Exception e) 486 { 487 throw new DeploymentException("Unable to start web module", e); 488 } 489 DeploymentException e = (DeploymentException) di.context.get(ERROR); 491 if( e != null ) 492 throw e; 493 494 super.start(di); 496 } 497 498 504 public synchronized void stop(DeploymentInfo di) 505 throws DeploymentException 506 { 507 ObjectName jmxName = (ObjectName ) di.context.get(WEB_MODULE); 508 try 509 { 510 if (jmxName != null) 511 serviceController.stop(jmxName); 512 } 513 catch (DeploymentException e) 514 { 515 throw e; 516 } 517 catch(Exception e) 518 { 519 throw new DeploymentException("Unable to stop web module", e); 520 } 521 super.stop(di); 523 } 524 525 531 public synchronized void destroy(DeploymentInfo di) 532 throws DeploymentException 533 { 534 ObjectName jmxName = (ObjectName ) di.context.get(WEB_MODULE); 535 try 536 { 537 if( jmxName != null ) 538 { 539 try 540 { 541 serviceController.destroy(jmxName); 542 } 543 finally 544 { 545 serviceController.remove(jmxName); 546 } 547 } 548 } 549 catch (DeploymentException e) 550 { 551 throw e; 552 } 553 catch(Exception e) 554 { 555 throw new DeploymentException("Unable to stop web module", e); 556 } 557 super.destroy(di); 559 } 560 561 564 public boolean isDeployed(String warUrl) 565 { 566 return deploymentMap.containsKey(warUrl); 567 } 568 569 public void addDeployedApp(URL warURL, WebApplication webApp) 570 { 571 deploymentMap.put(warURL, webApp); 572 } 573 578 public WebApplication getDeployedApp(String warUrl) 579 { 580 WebApplication appInfo = (WebApplication) deploymentMap.get(warUrl); 581 return appInfo; 582 } 583 public WebApplication removeDeployedApp(URL warURL) 584 { 585 WebApplication appInfo = (WebApplication) deploymentMap.remove(warURL); 586 return appInfo; 587 } 588 589 593 public Iterator getDeployedApplications() 594 { 595 return deploymentMap.values().iterator(); 596 } 597 598 603 public Element getConfig() 604 { 605 return null; 606 } 607 608 613 public void setConfig(Element config) 614 { 615 } 616 617 620 public static URL [] getClassLoaderURLs(ClassLoader cl) 621 { 622 URL [] urls = {}; 623 try 624 { 625 Class returnType = urls.getClass(); 626 Class [] parameterTypes = {}; 627 Method getURLs = cl.getClass().getMethod("getURLs", parameterTypes); 628 if( returnType.isAssignableFrom(getURLs.getReturnType()) ) 629 { 630 Object [] args = {}; 631 urls = (URL []) getURLs.invoke(cl, args); 632 } 633 if( urls == null || urls.length == 0 ) 634 { 635 getURLs = cl.getClass().getMethod("getAllURLs", parameterTypes); 636 if( returnType.isAssignableFrom(getURLs.getReturnType()) ) 637 { 638 Object [] args = {}; 639 urls = (URL []) getURLs.invoke(cl, args); 640 } 641 } 642 } 643 catch(Exception ignore) 644 { 645 } 646 return urls; 647 } 648 649 653 public String [] getCompileClasspath(ClassLoader loader) 654 { 655 HashSet tmp = new HashSet (); 656 ClassLoader cl = loader; 657 while( cl != null ) 658 { 659 URL [] urls = getClassLoaderURLs(cl); 660 addURLs(tmp, urls); 661 cl = cl.getParent(); 662 } 663 try 664 { 665 URL [] globalUrls = (URL [])server.getAttribute(LoaderRepositoryFactory.DEFAULT_LOADER_REPOSITORY, 666 "URLs"); 667 addURLs(tmp, globalUrls); 668 } 669 catch (Exception e) 670 { 671 log.warn("Could not get global URL[] from default loader repository!"); 672 } log.trace("JSP CompileClasspath: " + tmp); 674 String [] cp = new String [tmp.size()]; 675 tmp.toArray(cp); 676 return cp; 677 } 678 679 682 protected void processNestedDeployments(DeploymentInfo di) throws DeploymentException 683 { 684 } 685 686 protected void startService() throws Exception 687 { 688 serviceController = (ServiceControllerMBean) 689 MBeanProxyExt.create(ServiceControllerMBean.class, 690 ServiceControllerMBean.OBJECT_NAME, 691 server); 692 super.startService(); 693 } 694 695 702 protected void parseMetaData(String ctxPath, URL warURL, String warName, 703 WebMetaData metaData) 704 throws DeploymentException 705 { 706 InputStream jbossWebIS = null; 707 InputStream webIS = null; 708 709 try 711 { 712 File warDir = new File (warURL.getFile()); 714 if( warURL.getProtocol().equals("file") && warDir.isDirectory() == true ) 715 { 716 File webDD = new File (warDir, "WEB-INF/web.xml"); 717 if( webDD.exists() == true ) 718 webIS = new FileInputStream (webDD); 719 File jbossWebDD = new File (warDir, "WEB-INF/jboss-web.xml"); 720 if( jbossWebDD.exists() == true ) 721 jbossWebIS = new FileInputStream (jbossWebDD); 722 } 723 else 724 { 725 InputStream warIS = warURL.openStream(); 727 java.util.zip.ZipInputStream zipIS = new java.util.zip.ZipInputStream (warIS); 728 java.util.zip.ZipEntry entry; 729 byte[] buffer = new byte[512]; 730 int bytes; 731 while( (entry = zipIS.getNextEntry()) != null ) 732 { 733 if( entry.getName().equals("WEB-INF/web.xml") ) 734 { 735 ByteArrayOutputStream baos = new ByteArrayOutputStream (); 736 while( (bytes = zipIS.read(buffer)) > 0 ) 737 { 738 baos.write(buffer, 0, bytes); 739 } 740 webIS = new ByteArrayInputStream (baos.toByteArray()); 741 } 742 else if( entry.getName().equals("WEB-INF/jboss-web.xml") ) 743 { 744 ByteArrayOutputStream baos = new ByteArrayOutputStream (); 745 while( (bytes = zipIS.read(buffer)) > 0 ) 746 { 747 baos.write(buffer, 0, bytes); 748 } 749 jbossWebIS = new ByteArrayInputStream (baos.toByteArray()); 750 } 751 } 752 zipIS.close(); 753 } 754 755 XmlFileLoader xmlLoader = new XmlFileLoader(); 756 String warURI = warURL.toExternalForm(); 757 try 758 { 759 if( webIS != null ) 760 { 761 Document webDoc = xmlLoader.getDocument(webIS, warURI+"/WEB-INF/web.xml"); 762 Element web = webDoc.getDocumentElement(); 763 metaData.importXml(web); 764 } 765 } 766 catch(Exception e) 767 { 768 throw new DeploymentException("Failed to parse WEB-INF/web.xml", e); 769 } 770 try 771 { 772 if( jbossWebIS != null ) 773 { 774 Document jbossWebDoc = xmlLoader.getDocument(jbossWebIS, warURI+"/WEB-INF/jboss-web.xml"); 775 Element jbossWeb = jbossWebDoc.getDocumentElement(); 776 metaData.importXml(jbossWeb); 777 } 778 } 779 catch(Exception e) 780 { 781 throw new DeploymentException("Failed to parse WEB-INF/jboss-web.xml", e); 782 } 783 784 } 785 catch(DeploymentException e) 786 { 787 throw e; 788 } 789 catch(Exception e) 790 { 791 log.warn("Failed to parse descriptors for war("+warURL+")", e); 792 } 793 794 String webContext = ctxPath; 796 if( webContext == null ) 797 webContext = metaData.getContextRoot(); 798 if( webContext == null ) 799 { 800 webContext = warName; 802 webContext = webContext.replace('\\', '/'); 803 if( webContext.endsWith("/") ) 804 webContext = webContext.substring(0, webContext.length()-1); 805 int prefix = webContext.lastIndexOf('/'); 806 if( prefix > 0 ) 807 webContext = webContext.substring(prefix+1); 808 int suffix = webContext.lastIndexOf(".war"); 809 if( suffix > 0 ) 810 webContext = webContext.substring(0, suffix); 811 int index = 0; 813 for(; index < webContext.length(); index ++) 814 { 815 char c = webContext.charAt(index); 816 if( Character.isDigit(c) == false && c != '.' ) 817 break; 818 } 819 webContext = webContext.substring(index); 820 } 821 822 if( webContext.length() > 0 && webContext.charAt(0) != '/' ) 824 webContext = "/" + webContext; 825 else if( webContext.equals("/") ) 827 webContext = ""; 828 metaData.setContextRoot(webContext); 829 } 830 831 private void addURLs(Set urlSet, URL [] urls) 832 { 833 for(int u = 0; u < urls.length; u ++) 834 { 835 URL url = urls[u]; 836 urlSet.add(url.toExternalForm()); 837 } 838 } 839 } 840 | Popular Tags |