1 22 package org.jboss.deployment; 23 24 import java.io.File ; 25 import java.io.FileOutputStream ; 26 import java.io.IOException ; 27 import java.io.InputStream ; 28 import java.net.URL ; 29 import java.net.URLClassLoader ; 30 import java.util.ArrayList ; 31 import java.util.Enumeration ; 32 import java.util.HashMap ; 33 import java.util.Iterator ; 34 import java.util.List ; 35 import java.util.ListIterator ; 36 import java.util.Map ; 37 import java.util.jar.JarEntry ; 38 import java.util.jar.JarFile ; 39 40 import javax.management.MBeanServer ; 41 import javax.management.MalformedObjectNameException ; 42 import javax.management.ObjectName ; 43 import javax.xml.parsers.DocumentBuilder ; 44 import javax.xml.parsers.DocumentBuilderFactory ; 45 46 import org.jboss.mx.loading.LoaderRepositoryFactory; 47 import org.jboss.mx.loading.LoaderRepositoryFactory.LoaderRepositoryConfig; 48 import org.jboss.mx.util.MBeanProxyExt; 49 import org.jboss.net.protocol.URLLister; 50 import org.jboss.net.protocol.URLListerFactory; 51 import org.jboss.system.ServiceControllerMBean; 52 import org.jboss.system.server.ServerConfig; 53 import org.jboss.system.server.ServerConfigLocator; 54 import org.jboss.util.StringPropertyReplacer; 55 import org.jboss.util.Strings; 56 import org.jboss.util.stream.Streams; 57 import org.jboss.util.xml.JBossEntityResolver; 58 import org.w3c.dom.Element ; 59 import org.w3c.dom.Node ; 60 import org.w3c.dom.NodeList ; 61 import org.xml.sax.InputSource ; 62 63 import EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap; 64 65 79 public class SARDeployer extends SubDeployerSupport 80 implements SARDeployerMBean 81 { 82 83 private static final String [] DEFAULT_ENHANCED_SUFFIXES = new String [] { 84 "050:.deployer", 85 "050:-deployer.xml", 86 "150:.sar", 87 "150:-service.xml" 88 }; 89 90 91 private static final String JBOSS_SERVICE = "META-INF/jboss-service.xml"; 92 93 94 private ServiceControllerMBean serviceController; 95 96 97 private File dataDir; 98 99 103 private URL serverHomeURL; 104 105 106 private HashMap serviceDeploymentMap = new HashMap (); 107 108 112 private Map suffixToDescriptorMap = new ConcurrentReaderHashMap(); 113 114 115 private boolean useNamespaceAwareParser; 116 117 120 public SARDeployer() 121 { 122 setEnhancedSuffixes(DEFAULT_ENHANCED_SUFFIXES); 123 ArrayList tmp = new ArrayList (); 125 tmp.add(JBOSS_SERVICE); 126 tmp.add("META-INF/hibernate-service.xml"); 127 suffixToDescriptorMap.put(".har", tmp); 128 } 129 130 public boolean isUseNamespaceAwareParser() 131 { 132 return useNamespaceAwareParser; 133 } 134 135 public void setUseNamespaceAwareParser(boolean useNamespaceAwareParser) 136 { 137 this.useNamespaceAwareParser = useNamespaceAwareParser; 138 } 139 140 147 public DeploymentInfo getService(ObjectName serviceName) 148 { 149 DeploymentInfo di = null; 150 synchronized( serviceDeploymentMap ) 151 { 152 di = (DeploymentInfo) serviceDeploymentMap.get(serviceName); 153 } 154 return di; 155 } 156 157 164 public void init(DeploymentInfo di) 165 throws DeploymentException 166 { 167 try 168 { 169 if (di.url.getPath().endsWith("/")) 170 { 171 di.watch = new URL (di.url, JBOSS_SERVICE); 173 } 174 else 175 { 176 di.watch = di.url; 178 } 179 180 parseDocument(di); 182 183 NodeList loaders = di.document.getElementsByTagName("loader-repository"); 185 if( loaders.getLength() > 0 ) 186 { 187 Element loader = (Element ) loaders.item(0); 188 LoaderRepositoryConfig config = LoaderRepositoryFactory.parseRepositoryConfig(loader); 189 di.setRepositoryInfo(config); 190 } 191 192 parseXMLClasspath(di); 194 195 NodeList lds = di.document.getElementsByTagName("local-directory"); 197 log.debug("about to copy " + lds.getLength() + " local directories"); 198 199 for (int i = 0; i< lds.getLength(); i++) 200 { 201 Element ld = (Element )lds.item(i); 202 String path = ld.getAttribute("path"); 203 log.debug("about to copy local directory at " + path); 204 205 log.debug("copying from " + di.localUrl + path + " -> " + dataDir); 207 208 inflateJar(di.localUrl, dataDir, path); 209 } 210 } 211 catch (DeploymentException de) 212 { 213 throw de; 214 } 215 catch (Exception e) 216 { 217 throw new DeploymentException(e); 218 } 219 220 super.init(di); 222 } 223 224 231 public void create(DeploymentInfo di) 232 throws DeploymentException 233 { 234 try 235 { 236 log.debug("Deploying SAR, create step: url " + di.url); 238 239 ObjectName uclName = di.ucl.getObjectName(); 241 if( getServer().isRegistered(uclName) == false ) 242 { 243 log.debug("Registering service UCL="+uclName); 244 getServer().registerMBean(di.ucl, uclName); 245 } 246 247 List mbeans = di.mbeans; 248 mbeans.clear(); 249 List descriptorMbeans = serviceController.install(di.document.getDocumentElement(), uclName); 250 mbeans.addAll(descriptorMbeans); 251 252 for (Iterator iter = di.mbeans.iterator(); iter.hasNext(); ) 254 { 255 ObjectName service = (ObjectName )iter.next(); 256 257 serviceController.create(service); 259 synchronized( this.serviceDeploymentMap ) 260 { 261 serviceDeploymentMap.put(service, di); 262 } 263 } 264 265 super.create(di); 267 } 268 catch(DeploymentException e) 269 { 270 log.debug("create operation failed for package "+ di.url, e); 271 destroy(di); 272 throw e; 273 } 274 catch (Exception e) 275 { 276 log.debug("create operation failed for package "+ di.url, e); 277 destroy(di); 278 throw new DeploymentException("create operation failed for package " 279 + di.url, e); 280 } 281 } 282 283 290 public void start(DeploymentInfo di) throws DeploymentException 291 { 292 log.debug("Deploying SAR, start step: url " + di.url); 293 try 294 { 295 297 for (Iterator iter = di.mbeans.iterator(); iter.hasNext(); ) 298 { 299 ObjectName service = (ObjectName )iter.next(); 300 301 serviceController.start(service); 303 } 304 super.start(di); 306 } 307 catch (Exception e) 308 { 309 stop(di); 310 destroy(di); 311 throw new DeploymentException("start operation failed on package " 312 + di.url, e); 313 } 314 } 315 316 322 public void stop(DeploymentInfo di) 323 { 324 log.debug("undeploying document " + di.url); 325 326 List services = di.mbeans; 327 int lastService = services.size(); 328 329 for (ListIterator i = services.listIterator(lastService); i.hasPrevious();) 331 { 332 ObjectName name = (ObjectName )i.previous(); 333 log.debug("stopping mbean " + name); 334 try 335 { 336 serviceController.stop(name); 337 } 338 catch (Exception e) 339 { 340 log.error("Could not stop mbean: " + name, e); 341 } } 343 344 try 346 { 347 super.stop(di); 348 } 349 catch(Exception ignore) 350 { 351 } 352 } 353 354 360 public void destroy(DeploymentInfo di) 361 { 362 List services = di.mbeans; 363 int lastService = services.size(); 364 365 for (ListIterator i = services.listIterator(lastService); i.hasPrevious();) 366 { 367 ObjectName name = (ObjectName )i.previous(); 368 log.debug("destroying mbean " + name); 369 synchronized( serviceDeploymentMap ) 370 { 371 serviceDeploymentMap.remove(name); 372 } 373 374 try 375 { 376 serviceController.destroy(name); 377 } 378 catch (Exception e) 379 { 380 log.error("Could not destroy mbean: " + name, e); 381 } } 383 384 for (ListIterator i = services.listIterator(lastService); i.hasPrevious();) 385 { 386 ObjectName name = (ObjectName )i.previous(); 387 log.debug("removing mbean " + name); 388 try 389 { 390 serviceController.remove(name); 391 } 392 catch (Exception e) 393 { 394 log.error("Could not remove mbean: " + name, e); 395 } } 397 398 try 400 { 401 ObjectName uclName = di.ucl.getObjectName(); 402 if( getServer().isRegistered(uclName) == true ) 403 { 404 log.debug("Unregistering service UCL="+uclName); 405 getServer().unregisterMBean(uclName); 406 } 407 } 408 catch(Exception ignore) 409 { 410 } 411 412 try 414 { 415 super.destroy(di); 416 } 417 catch(Exception ignore) 418 { 419 } 420 } 421 422 424 430 protected void startService() throws Exception 431 { 432 super.startService(); 433 434 serviceController = (ServiceControllerMBean) 436 MBeanProxyExt.create(ServiceControllerMBean.class, 437 ServiceControllerMBean.OBJECT_NAME, server); 438 439 ServerConfig config = ServerConfigLocator.locate(); 441 dataDir = config.getServerDataDir(); 442 serverHomeURL = config.getServerHomeURL(); 443 } 444 445 448 protected void stopService() throws Exception 449 { 450 super.stopService(); 452 453 serviceController = null; 455 serverHomeURL = null; 456 dataDir = null; 457 } 458 459 460 protected ObjectName getObjectName(MBeanServer server, ObjectName name) 461 throws MalformedObjectNameException 462 { 463 return name == null ? OBJECT_NAME : name; 464 } 465 466 468 protected File [] listFiles(final String urlspec) throws Exception 469 { 470 URL url = Strings.toURL(urlspec); 471 472 File dir = new File (url.getFile()); 474 475 File [] files = dir.listFiles(new java.io.FileFilter () 476 { 477 public boolean accept(File pathname) 478 { 479 String name = pathname.getName().toLowerCase(); 480 return (name.endsWith(".jar") || name.endsWith(".zip")); 481 } 482 }); 483 484 return files; 485 } 486 487 491 protected void parseXMLClasspath(DeploymentInfo di) 492 throws Exception 493 { 494 ArrayList classpath = new ArrayList (); 495 URLListerFactory listerFactory = new URLListerFactory(); 496 497 NodeList children = di.document.getDocumentElement().getChildNodes(); 498 for (int i = 0; i < children.getLength(); i++) 499 { 500 if (children.item(i).getNodeType() == Node.ELEMENT_NODE) 501 { 502 Element classpathElement = (Element )children.item(i); 503 if (classpathElement.getTagName().equals("classpath")) 504 { 505 log.debug("Found classpath element: " + classpathElement); 506 if (!classpathElement.hasAttribute("codebase")) 507 { 508 throw new DeploymentException 509 ("Invalid classpath element missing codebase: " + classpathElement); 510 } 511 String codebase = classpathElement.getAttribute("codebase").trim(); 512 codebase = StringPropertyReplacer.replaceProperties(codebase); 514 515 String archives = null; 516 if (classpathElement.hasAttribute("archives")) 517 { 518 archives = classpathElement.getAttribute("archives").trim(); 519 archives = StringPropertyReplacer.replaceProperties(archives); 521 if ("".equals(archives)) 522 { 523 archives = null; 524 } 525 } 526 527 URL codebaseUrl; 531 if (".".equals(codebase)) 532 { 533 codebaseUrl = new URL (di.url, "./"); 534 } 535 else 536 { 537 if (archives != null && codebase.endsWith("/") == false) 538 { 539 codebase += "/"; 540 } 541 codebaseUrl = new URL (serverHomeURL, codebase); 542 } 543 log.debug("codebase URL is " + codebaseUrl); 544 545 if (archives == null) 546 { 547 classpath.add(codebaseUrl); 549 log.debug("added codebase to classpath"); 550 } 551 else 552 { 553 log.debug("listing codebase for archives matching " + archives); 556 URLLister lister = listerFactory.createURLLister(codebaseUrl); 557 log.debug("URLLister class is " + lister.getClass().getName()); 558 classpath.addAll(lister.listMembers(codebaseUrl, archives)); 559 } 560 } 562 } } 565 Iterator jars = classpath.iterator(); 567 while (jars.hasNext()) 568 { 569 URL neededURL = (URL ) jars.next(); 570 di.addLibraryJar(neededURL); 571 log.debug("deployed classes for " + neededURL); 572 } 573 } 574 575 577 protected void parseDocument(DeploymentInfo di) 578 throws Exception 579 { 580 InputStream stream = null; 581 try 582 { 583 if (di.document == null) 584 { 585 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 586 factory.setNamespaceAware(useNamespaceAwareParser); 587 DocumentBuilder parser = factory.newDocumentBuilder(); 588 URL docURL = di.localUrl; 589 URLClassLoader localCL = di.localCl; 590 if (di.isXML == false) 592 { 593 String [] descriptors = getDescriptorName(di); 595 for(int n = 0; n < descriptors.length; n ++) 596 { 597 String descriptor = descriptors[n]; 598 docURL = localCL.findResource(descriptor); 599 if( docURL != null ) 600 { 601 if (di.url.getPath().endsWith("/")) 603 { 604 di.watch = new URL (di.url, descriptor); 605 log.debug("Updated watch URL to: "+di.watch); 606 } 607 break; 608 } 609 } 610 if( docURL == null ) 612 docURL = localCL.findResource(JBOSS_SERVICE); 613 } 614 if (docURL == null) 616 throw new DeploymentException("Failed to find META-INF/jboss-service.xml for archive " + di.shortName); 617 618 stream = docURL.openStream(); 619 InputSource is = new InputSource (stream); 620 is.setSystemId(docURL.toString()); 621 parser.setEntityResolver(new JBossEntityResolver()); 622 di.document = parser.parse(is); 623 } 624 else 625 { 626 log.debug("Using existing deployment.document"); 627 } 628 } 629 finally 630 { 631 try 633 { 634 stream.close(); 635 } 636 catch (Exception ignore) 637 { 638 } 639 } 640 } 641 642 655 protected void inflateJar(URL url, File destDir, String path) 656 throws DeploymentException, IOException 657 { 658 String filename = url.getFile(); 659 JarFile jarFile = new JarFile (filename); 660 try 661 { 662 for (Enumeration e = jarFile.entries(); e.hasMoreElements(); ) 663 { 664 JarEntry entry = (JarEntry )e.nextElement(); 665 String name = entry.getName(); 666 667 if (path == null || name.startsWith(path)) 668 { 669 File outFile = new File (destDir, name); 670 if (!outFile.exists()) 671 { 672 if (entry.isDirectory()) 673 { 674 outFile.mkdirs(); 675 } 676 else 677 { 678 Streams.copyb(jarFile.getInputStream(entry), 679 new FileOutputStream (outFile)); 680 } 681 } } } 684 } 685 finally 686 { 687 jarFile.close(); 688 } 689 } 690 691 693 702 private String [] getDescriptorName(DeploymentInfo sdi) 703 { 704 String [] descriptorNames = {JBOSS_SERVICE}; 705 String shortName = sdi.shortName; 706 int dot = shortName.lastIndexOf('.'); 707 if( dot >= 0 ) 708 { 709 String suffix = shortName.substring(dot); 710 List descriptors = (List ) suffixToDescriptorMap.get(suffix); 711 if( descriptors != null ) 712 { 713 descriptorNames = new String [descriptors.size()]; 714 descriptors.toArray(descriptorNames); 715 } 716 } 717 return descriptorNames; 718 } 719 } 720 | Popular Tags |