| 1 25 26 package org.objectweb.jonas.ear; 27 28 import java.io.File ; 29 import java.io.IOException ; 30 import java.net.MalformedURLException ; 31 import java.net.URL ; 32 import java.net.URLClassLoader ; 33 import java.security.Policy ; 34 import java.util.ArrayList ; 35 import java.util.Date ; 36 import java.util.Enumeration ; 37 import java.util.HashSet ; 38 import java.util.Hashtable ; 39 import java.util.Iterator ; 40 import java.util.LinkedList ; 41 import java.util.List ; 42 import java.util.Map ; 43 import java.util.Set ; 44 import java.util.StringTokenizer ; 45 import java.util.Vector ; 46 47 import javax.management.InstanceAlreadyExistsException ; 48 import javax.management.MBeanRegistrationException ; 49 import javax.management.MBeanServer ; 50 import javax.management.NotCompliantMBeanException ; 51 import javax.management.ObjectName ; 52 import javax.management.modelmbean.ModelMBean ; 53 import javax.naming.Context ; 54 import javax.naming.NamingException ; 55 import javax.security.jacc.PolicyConfiguration ; 56 import javax.security.jacc.PolicyConfigurationFactory ; 57 import javax.security.jacc.PolicyContextException ; 58 59 import org.apache.commons.modeler.ManagedBean; 60 import org.apache.commons.modeler.Registry; 61 import org.objectweb.jonas.client.AppClientModule; 62 import org.objectweb.jonas.common.JModule; 63 import org.objectweb.jonas.common.JProp; 64 import org.objectweb.jonas.common.Log; 65 import org.objectweb.jonas.container.EJBService; 66 import org.objectweb.jonas.container.EJBServiceImpl; 67 import org.objectweb.jonas.ear.lib.EarClassPathManager; 68 import org.objectweb.jonas.ear.lib.EarClassPathManagerException; 69 import org.objectweb.jonas.ear.lib.JarList; 70 import org.objectweb.jonas.ear.lib.JarListException; 71 import org.objectweb.jonas.jmx.J2eeObjectName; 72 import org.objectweb.jonas.jmx.JmxService; 73 import org.objectweb.jonas.jmx.JonasObjectName; 74 import org.objectweb.jonas.management.JonasMBeanTools; 75 import org.objectweb.jonas.naming.CompNamingContext; 76 import org.objectweb.jonas.resource.ResourceService; 77 import org.objectweb.jonas.resource.ResourceServiceException; 78 import org.objectweb.jonas.security.jacc.JPolicyUserRoleMapping; 79 import org.objectweb.jonas.server.JClassLoader; 80 import org.objectweb.jonas.server.LoaderManager; 81 import org.objectweb.jonas.service.AbsServiceImpl; 82 import org.objectweb.jonas.service.ServiceException; 83 import org.objectweb.jonas.service.ServiceManager; 84 import org.objectweb.jonas.web.JWebContainerService; 85 import org.objectweb.jonas.web.JWebContainerServiceException; 86 import org.objectweb.jonas.ws.AbsWebServicesServiceImpl; 87 import org.objectweb.jonas.ws.WSServiceException; 88 import org.objectweb.jonas.ws.WebServicesService; 89 import org.objectweb.jonas_client.deployment.api.ClientContainerDeploymentDesc; 90 import org.objectweb.jonas_client.deployment.api.ClientContainerDeploymentDescException; 91 import org.objectweb.jonas_client.deployment.lib.wrapper.ClientManagerWrapper; 92 import org.objectweb.jonas_ear.deployment.api.EarDeploymentDesc; 93 import org.objectweb.jonas_ear.deployment.api.EarDeploymentDescException; 94 import org.objectweb.jonas_ear.deployment.lib.wrapper.EarManagerWrapper; 95 import org.objectweb.jonas_ear.deployment.xml.Web; 96 97 import org.objectweb.jonas_ejb.deployment.lib.wrapper.EjbManagerWrapper; 98 import org.objectweb.jonas_lib.deployment.work.CleanerException; 99 import org.objectweb.jonas_lib.deployment.work.DeployerLog; 100 import org.objectweb.jonas_lib.deployment.work.DeployerLogException; 101 import org.objectweb.jonas_lib.deployment.work.EarCleanTask; 102 import org.objectweb.jonas_lib.deployment.work.EarFileManager; 103 import org.objectweb.jonas_lib.deployment.work.FileManagerException; 104 import org.objectweb.jonas_lib.deployment.work.WorkCleaner; 105 import org.objectweb.jonas_lib.loader.ClientClassLoader; 106 import org.objectweb.jonas_lib.loader.EjbJarClassLoader; 107 import org.objectweb.jonas_web.deployment.lib.wrapper.WebManagerWrapper; 108 import org.objectweb.util.monolog.api.BasicLevel; 109 import org.objectweb.util.monolog.api.Logger; 110 111 119 public class EarServiceImpl extends AbsServiceImpl implements EarService, EarServiceImplMBean { 120 121 124 protected static final String JONAS_BASE = JProp.getJonasBase(); 125 126 129 protected static final String APPS_DIR = JONAS_BASE + File.separator + "apps"; 130 131 134 protected static final String WORK_DIR = JProp.getWorkDir(); 135 136 139 protected static final String WORK_APPS_DIR = WORK_DIR + File.separator + "apps"; 140 141 144 protected static final String DESCRIPTORS = "jonas.service.ear.descriptors"; 145 146 149 protected static final String AUTOLOADDIR = "jonas.service.ear.autoloaddir"; 150 151 154 protected static final String PARSINGWITHVALIDATION = "jonas.service.ear.parsingwithvalidation"; 155 156 159 protected static final String CLASS = "jonas.service.ear.class"; 160 161 164 private static Logger logger = null; 165 166 169 private static WorkCleaner workCleaner = null; 170 171 174 private MBeanServer mbeanServer = null; 175 176 179 private Vector earNames = new Vector (); 180 181 184 private EJBService ejbService = null; 185 186 189 private JWebContainerService webContainerService = null; 190 191 194 private WebServicesService wsService = null; 195 196 199 private ResourceService resourceService = null; 200 201 204 private Hashtable ears = null; 205 206 209 private ArrayList autoloadDirectories = new ArrayList (); 210 211 215 private DeployerLog earDeployerLog = null; 216 217 220 private ClassLoader appsClassLoader; 221 222 227 protected void doInit(Context ctx) throws ServiceException { 228 229 logger = Log.getLogger(Log.JONAS_EAR_PREFIX); 231 232 try { 234 LoaderManager lm = LoaderManager.getInstance(); 235 appsClassLoader = lm.getAppsLoader(); 236 } catch (Exception e) { 237 logger.log(BasicLevel.ERROR, "Cannot get the Applications ClassLoader from EAR Container Service: " + e); 238 throw new ServiceException("Cannot get the Applications ClassLoader from EAR Container Service", e); 239 } 240 241 ServiceManager sm = null; 242 243 try { 244 sm = ServiceManager.getInstance(); 245 } catch (Exception e) { 246 String err = "Cannot get ServiceManager instance"; 247 logger.log(BasicLevel.ERROR, err); 248 throw new ServiceException(err, e); 249 } 250 251 try { 253 mbeanServer = ((JmxService) sm.getJmxService()).getJmxServer(); 254 } catch (ServiceException e) { 255 mbeanServer = null; 257 } 258 259 try { 261 ejbService = (EJBService) sm.getEjbService(); 262 } catch (ServiceException e) { 263 ejbService = null; 265 } 266 267 try { 269 webContainerService = (JWebContainerService) sm.getWebContainerService(); 270 } catch (ServiceException e) { 271 webContainerService = null; 273 } 274 275 try { 277 wsService = (WebServicesService) sm.getWebServicesService(); 278 } catch (ServiceException e) { 279 wsService = null; 281 } 282 283 try { 285 resourceService = (ResourceService) sm.getResourceService(); 286 } catch (ServiceException e) { 287 resourceService = null; 289 } 290 291 String parsingMode = "false"; 293 try { 294 parsingMode = (String ) ctx.lookup(PARSINGWITHVALIDATION); 295 } catch (NamingException e) { 296 300 if (logger.isLoggable(BasicLevel.DEBUG)) { 301 logger.log(BasicLevel.DEBUG, "No XML parsing validation property, use default"); 302 } 303 } 304 EarManagerWrapper.setParsingWithValidation("true".equalsIgnoreCase(parsingMode)); 305 if ("false".equalsIgnoreCase(parsingMode)) { 306 if (logger.isLoggable(BasicLevel.DEBUG)) { 307 logger.log(BasicLevel.DEBUG, "Ear XML parsing without validation"); 308 } 309 } else { 310 if (logger.isLoggable(BasicLevel.DEBUG)) { 311 logger.log(BasicLevel.DEBUG, "Ear XML parsing with validation"); 312 } 313 } 314 315 String descsValue = null; 317 try { 318 descsValue = (String ) ctx.lookup(DESCRIPTORS); 319 } catch (NamingException e) { 320 if (logger.isLoggable(BasicLevel.DEBUG)) { 321 logger.log(BasicLevel.DEBUG, "No property DESCRIPTORS"); 322 } 323 } 326 if (descsValue != null) { 327 StringTokenizer st = new StringTokenizer (descsValue, ","); 328 while (st.hasMoreTokens()) { 329 String fileName = st.nextToken().trim(); 330 earNames.add(fileName); 331 } 332 } 333 334 String dirValue = null; 336 ArrayList autoDirs = new ArrayList (); 337 try { 338 dirValue = (String ) ctx.lookup(AUTOLOADDIR); 339 } catch (NamingException e) { 340 if (logger.isLoggable(BasicLevel.DEBUG)) { 341 logger.log(BasicLevel.DEBUG, "No AUTOLOADDIR property"); 342 } 343 } 346 if (dirValue != null) { 347 StringTokenizer st = new StringTokenizer (dirValue, ","); 348 while (st.hasMoreTokens()) { 349 String dirName = st.nextToken().trim(); 350 addEars(dirName); 351 autoDirs.add(dirName); 352 } 353 } 354 File oFile; 356 Iterator it = autoDirs.iterator(); 357 while (it.hasNext()) { 358 String dirName = (String ) it.next(); 359 try { 360 oFile = new File (APPS_DIR, dirName); 361 if (!oFile.exists()) { 362 oFile = new File (dirName); 363 } 364 if (oFile.exists()) { 365 autoloadDirectories.add(oFile.getCanonicalPath()); 366 } 367 } catch (Exception e) { 368 String err = "Error when trying to verify Application EAR autoload directory : " + dirName; 369 logger.log(BasicLevel.ERROR, err, e); 370 } 371 } 372 373 ears = new Hashtable (); 375 376 } 379 380 384 protected void doStop() throws ServiceException { 385 386 URL earFileName = null; 388 for (Enumeration earEntries = ears.keys(); earEntries.hasMoreElements();) { 391 earFileName = (URL ) earEntries.nextElement(); 392 try { 394 Context ctx = new CompNamingContext(earFileName.getFile()); 395 ctx.rebind("filename", earFileName); 396 unDeployEar(ctx); 397 } catch (Exception e) { 398 String err = "Error when undeploying the ear :" + earFileName; 401 logger.log(BasicLevel.ERROR, err, e); 402 } 403 } 404 405 if (mbeanServer != null) { 406 try { 407 mbeanServer.unregisterMBean(JonasObjectName.earService()); 409 } catch (Exception e) { 410 logger.log(BasicLevel.ERROR, "Cannot stop the EarService", e); 411 } 412 } 413 414 if (logger.isLoggable(BasicLevel.DEBUG)) { 416 logger.log(BasicLevel.DEBUG, "EarService stopped"); 417 } 418 419 } 420 421 430 public String deployEar(Context ctx) throws EarServiceException { 431 432 if ((webContainerService == null) && (ejbService == null)) { 434 throw new EarServiceException( 435 "The ear service requires that at least the service ejb or web is launched for deploying an ear file."); 436 } 437 438 String fileName; 441 try { 442 fileName = (String ) ctx.lookup("filename"); 443 } catch (NamingException e) { 444 throw new EarServiceException("Error during performing lookup a fileName", e); 445 } 446 447 File f = null; 448 try { 449 f = new File (fileName).getCanonicalFile(); 451 452 if (!f.exists()) { 453 boolean found = false; 454 String earFileName = null; 455 if (fileName.toLowerCase().endsWith(".ear")) { 456 earFileName = APPS_DIR + File.separator + fileName; 459 f = new File (earFileName).getCanonicalFile(); 460 found = f.exists(); 461 } 462 if (found) { 463 fileName = earFileName; 464 } else { 465 String err = "deployEar: The file " + fileName 466 + " was not found neither in the current directory nor in the " + APPS_DIR + " directory"; 467 logger.log(BasicLevel.ERROR, err); 468 throw new EarServiceException(err); 469 } 470 } 471 } catch (IOException e) { 472 String err = "Error when trying to get the canonical file from " + fileName; 473 logger.log(BasicLevel.ERROR, err + " " + e.getMessage()); 474 throw new EarServiceException(err, e); 475 } 476 477 URL [] earUrl = new URL [1]; 479 URL earRootUrl = null; 480 481 try { 482 earUrl[0] = f.toURL(); 483 earRootUrl = (new File (WORK_APPS_DIR + File.separator + getJonasServerName())).toURL(); 484 } catch (MalformedURLException e) { 485 String err = "Invalid ear file name '" + fileName; 486 logger.log(BasicLevel.ERROR, err + "': " + e.getMessage()); 487 throw new EarServiceException(err, e); 488 } 489 490 if (ears.get(earUrl[0]) != null) { 492 String err = "The ear file : " + f.getName() + " is already deployed ('" + earUrl[0].getFile() 493 + "'). You must undeploy the application " + "before a new deployment."; 494 logger.log(BasicLevel.ERROR, err); 495 throw new EarServiceException(err); 496 } 497 498 URLClassLoader loaderCls = new URLClassLoader (earUrl, appsClassLoader); 501 502 EarDeploymentDesc earDD = null; 503 if (logger.isLoggable(BasicLevel.DEBUG)) { 504 logger.log(BasicLevel.DEBUG, "Getting the deployment descriptor of the file" + f.getName()); 505 } 506 try { 507 earDD = EarManagerWrapper.getDeploymentDesc(earUrl[0].getFile(), loaderCls); 508 } catch (EarDeploymentDescException e) { 509 String err = "Error in the Deployment descriptor '" + fileName + "': " + e; 510 logger.log(BasicLevel.ERROR, err); 511 throw new EarServiceException(err, e); 512 } 513 514 Web[] webTags = earDD.getWebTags(); 516 String [] ejbTags = earDD.getEjbTags(); 517 String [] connectorTags = earDD.getConnectorTags(); 518 String [] clientTags = earDD.getClientTags(); 519 String [] altDDClients = earDD.getAltDDClients(); 520 String [] altDDEjbs = earDD.getAltDDEjbs(); 521 String [] altDDWebs = earDD.getAltDDWebs(); 522 String [] altDDConnectors = earDD.getAltDDConnectors(); 523 String [] securityRoles = earDD.getSecurityRolesNames(); 524 525 528 File fEar = new File (earUrl[0].getFile()); 529 File tmpFile = null; 530 531 try { 532 File fCanonicEar = fEar.getCanonicalFile(); 533 for (int i = 0; i < ejbTags.length; i++) { 534 tmpFile = new File (fEar, ejbTags[i]); 535 tmpFile = tmpFile.getCanonicalFile(); 536 if (!tmpFile.getPath().startsWith(fCanonicEar.getPath())) { 537 String err = "Error : The ejb-jar file " + ejbTags[i] + " is not inside the ear file " + fEar; 538 logger.log(BasicLevel.ERROR, err); 539 throw new EarServiceException(err); 540 } 541 } 542 543 for (int i = 0; i < webTags.length; i++) { 544 tmpFile = new File (fEar, webTags[i].getWebUri()); 545 tmpFile = tmpFile.getCanonicalFile(); 546 if (!tmpFile.getPath().startsWith(fCanonicEar.getPath())) { 547 String err = "Error : The war file " + webTags[i].getWebUri() + " is not inside the ear file " 548 + fEar; 549 logger.log(BasicLevel.ERROR, err); 550 throw new EarServiceException(err); 551 } 552 } 553 554 for (int i = 0; i < connectorTags.length; i++) { 555 tmpFile = new File (fEar, connectorTags[i]); 556 tmpFile = tmpFile.getCanonicalFile(); 557 if (!tmpFile.getPath().startsWith(fCanonicEar.getPath())) { 558 String err = "Error : The rar file " + connectorTags[i] + " is not inside the ear file " + fEar; 559 logger.log(BasicLevel.ERROR, err); 560 throw new EarServiceException(err); 561 } 562 } 563 564 565 for (int i = 0; i < clientTags.length; i++) { 566 tmpFile = new File (fEar, clientTags[i]); 567 tmpFile = tmpFile.getCanonicalFile(); 568 569 if (!tmpFile.getPath().startsWith(fCanonicEar.getPath())) { 570 String err = "Error : The client jar file " + clientTags[i] + " is not inside the ear file " + fEar; 571 throw new EarServiceException(err); 572 } 573 } 574 } catch (IOException ioe) { 575 String err = "Error while trying to get the canonical file of " + tmpFile; 576 logger.log(BasicLevel.ERROR, err + " : " + ioe.getMessage()); 577 throw new EarServiceException(err, ioe); 578 } 579 580 JarList ejbsList = new JarList(ejbTags); 582 JarList warsList = new JarList(webTags); 583 JarList connectorsList = new JarList(connectorTags); 584 JarList clientsList = new JarList(clientTags); 585 586 URL dirUnpackURL = null; 588 try { 589 dirUnpackURL = EarFileManager.unpackEar(earUrl[0], earRootUrl); 590 } catch (FileManagerException e) { 591 String err = "Error while unpacking the file '" + earUrl[0] + "'"; 592 logger.log(BasicLevel.ERROR, err + " : " + e.getMessage()); 593 throw new EarServiceException(err, e); 594 } 595 596 if (new File (earUrl[0].getFile()).isFile()) { 599 try { 600 earDeployerLog.addEntry(new File (earUrl[0].getFile()), new File (dirUnpackURL.getFile())); 601 } catch (DeployerLogException e) { 602 String err = "Error while adding the " + earUrl[0] + " entry in the log file"; 603 logger.log(BasicLevel.ERROR, err + " : " + e.getMessage()); 604 throw new EarServiceException(err, e); 605 } 606 } 607 608 EarClassPathManager earCPManager = null; 611 try { 612 earCPManager = new EarClassPathManager(ejbsList, warsList, dirUnpackURL); 613 } catch (EarClassPathManagerException e) { 614 String err = "Error while creating the Ear class path manager of the ear : '" + earUrl[0] + "'"; 615 logger.log(BasicLevel.ERROR, err + " : " + e.getMessage()); 616 throw new EarServiceException(err, e); 617 } 618 619 URL [] classpathURLs = null; 620 try { 622 classpathURLs = earCPManager.getResolvedClassPath(); 623 } catch (EarClassPathManagerException e) { 624 String err = "Error while trying to resolve the classpath of the ejbjars and wars of the ear : '" 625 + earUrl[0] + "'"; 626 logger.log(BasicLevel.ERROR, err + " : " + e.getMessage()); 627 throw new EarServiceException(err, e); 628 } 629 630 634 if (logger.isLoggable(BasicLevel.DEBUG)) { 635 logger.log(BasicLevel.DEBUG, "Creating the EAR classLoader"); 636 } 637 JClassLoader earClassLoader = new JClassLoader(earUrl[0].toExternalForm() , new URL [0], appsClassLoader); 638 639 URL [] jarUrls = null; 641 URL [] warUrls = null; 642 URL [] connectorUrls = null; 643 URL [] clientUrls = null; 644 try { 645 jarUrls = ejbsList.getURLs(dirUnpackURL.toExternalForm()); 646 warUrls = warsList.getURLs(dirUnpackURL.toExternalForm()); 647 connectorUrls = connectorsList.getURLs(dirUnpackURL.toExternalForm()); 648 clientUrls = clientsList.getURLs(dirUnpackURL.toExternalForm()); 649 } catch (JarListException e) { 650 String err = "Error while geting the Urls from jarlist of the ear : '" + earUrl[0] + "'"; 651 logger.log(BasicLevel.ERROR, err + " : " + e.getMessage()); 652 throw new EarServiceException(err, e); 653 } 654 655 String [] warsContextRoots = new String [webTags.length]; 658 String ctxRoot = null; 659 for (int i = 0; i < webTags.length; i++) { 660 ctxRoot = webTags[i].getContextRoot(); 661 if (ctxRoot != null) { 662 warsContextRoots[i] = ctxRoot; 663 } 664 } 665 666 String altdd = null; 668 File fAltDD = null; 669 670 URL [] warsAltDDs = new URL [altDDWebs.length]; 673 for (int i = 0; i < altDDWebs.length; i++) { 674 if (altDDWebs[i] != null) { 675 altdd = altDDWebs[i]; 676 if (altdd != null) { 677 try { 678 fAltDD = new File (new URL (dirUnpackURL.toExternalForm() + File.separator + altdd).getFile()); 679 warsAltDDs[i] = fAltDD.getCanonicalFile().toURL(); 680 } catch (MalformedURLException e) { 681 String err = "Can't build URL for alt-dd '" + altdd; 682 logger.log(BasicLevel.ERROR, err + "': " + e.getMessage()); 683
|