00001
00027 package org.objectweb.jonas_web.deployment.lib;
00028
00029 import java.io.File;
00030 import java.io.FileInputStream;
00031 import java.io.IOException;
00032 import java.io.InputStream;
00033 import java.io.InputStreamReader;
00034 import java.io.Reader;
00035 import java.net.MalformedURLException;
00036 import java.net.URL;
00037 import java.net.URLClassLoader;
00038 import java.util.Enumeration;
00039 import java.util.Hashtable;
00040 import java.util.List;
00041 import java.util.StringTokenizer;
00042 import java.util.jar.JarFile;
00043 import java.util.zip.ZipEntry;
00044
00045 import org.objectweb.jonas_ejb.deployment.lib.EjbDeploymentDescManager;
00046
00047 import org.objectweb.jonas_lib.deployment.api.DeploymentDescException;
00048 import org.objectweb.jonas_lib.deployment.api.EjbLocalRefDesc;
00049 import org.objectweb.jonas_lib.deployment.api.EjbRefDesc;
00050 import org.objectweb.jonas_lib.deployment.api.MessageDestinationRefDesc;
00051 import org.objectweb.jonas_lib.deployment.digester.JDigester;
00052 import org.objectweb.jonas_lib.deployment.lib.AbsDeploymentDescManager;
00053 import org.objectweb.jonas_lib.deployment.xml.JonasMessageDestination;
00054
00055 import org.objectweb.jonas_web.deployment.api.WebContainerDeploymentDesc;
00056 import org.objectweb.jonas_web.deployment.api.WebContainerDeploymentDescException;
00057 import org.objectweb.jonas_web.deployment.rules.JonasWebAppRuleSet;
00058 import org.objectweb.jonas_web.deployment.rules.WebAppRuleSet;
00059 import org.objectweb.jonas_web.deployment.xml.JonasWebApp;
00060 import org.objectweb.jonas_web.deployment.xml.WebApp;
00061
00062 import org.objectweb.jonas_ws.deployment.api.PortComponentDesc;
00063 import org.objectweb.jonas_ws.deployment.api.PortComponentRefDesc;
00064 import org.objectweb.jonas_ws.deployment.api.ServiceRefDesc;
00065 import org.objectweb.jonas_ws.deployment.api.WSDeploymentDescException;
00066 import org.objectweb.jonas_ws.deployment.lib.WSDeploymentDescManager;
00067
00068 import org.objectweb.jonas.common.Log;
00069
00070 import org.objectweb.util.monolog.api.BasicLevel;
00071 import org.objectweb.util.monolog.api.Logger;
00072
00080 public class WebDeploymentDescManager extends AbsDeploymentDescManager {
00081
00085 public static final String WEB_FILE_NAME = "WEB-INF/web.xml";
00086
00090 public static final String JONAS_WEB_FILE_NAME = "WEB-INF/jonas-web.xml";
00091
00095 private static boolean parsingWithValidation = true;
00096
00100 private static JDigester webAppDigester = null;
00101
00105 private static JDigester jonasWebAppDigester = null;
00106
00110 private static WebAppRuleSet webAppRuleSet = new WebAppRuleSet();
00111
00115 private static JonasWebAppRuleSet jonasWebAppRuleSet = new JonasWebAppRuleSet();
00116
00120 private static WebDeploymentDescManager unique;
00121
00125 private EjbDeploymentDescManager ejbDDManager = null;
00126
00130 private WSDeploymentDescManager wsDDManager = null;
00131
00135 private static Logger logger = Log.getLogger(Log.JONAS_WEB_PREFIX);
00136
00138 private static Hashtable staticCache = new Hashtable();
00139
00143 private WebDeploymentDescManager() {
00144 ejbDDManager = EjbDeploymentDescManager.getInstance();
00145 earCLAltDDBindings = new Hashtable();
00146 }
00147
00152 private Hashtable earCLAltDDBindings = null;
00153
00158 public static WebDeploymentDescManager getInstance() {
00159 if (unique == null) {
00160 unique = new WebDeploymentDescManager();
00161 }
00162 return unique;
00163 }
00164
00174 public WebContainerDeploymentDesc getDeploymentDesc(URL url, ClassLoader loaderForCls, ClassLoader earLoader)
00175 throws DeploymentDescException {
00176
00177
00178 if (wsDDManager == null) {
00179 wsDDManager = WSDeploymentDescManager.getInstance();
00180 }
00181
00182
00183 if (!new File(url.getFile()).exists()) {
00184 String err = "Cannot get the deployment descriptor for ";
00185 err = err + "'" + url.getFile() + "'. The file doesn't exist.";
00186 throw new WebContainerDeploymentDescException(err);
00187 }
00188
00189
00190 URL altDDUrl = null;
00191
00192
00193 Hashtable urlAltddBindings = null;
00194 if (earLoader != null) {
00195
00196 urlAltddBindings = (Hashtable) earCLAltDDBindings.get(earLoader);
00197 if (urlAltddBindings == null) {
00198
00199
00200 String err = "Cannot find if there is alt-dd for '" + url.getFile()
00201 + "', the setAltDD function was badly called";
00202 throw new WebContainerDeploymentDescException(err);
00203 }
00204
00205 altDDUrl = (URL) urlAltddBindings.get(url);
00206 }
00207
00208
00209
00210
00211 WebContainerDeploymentDesc webDD = null;
00212 try {
00213 if (altDDUrl != null) {
00214 webDD = getInstance(url.getFile(), loaderForCls, altDDUrl.getFile());
00215 } else {
00216 webDD = getInstance(url.getFile(), loaderForCls);
00217 }
00218 } catch (DeploymentDescException dde) {
00219 throw new WebContainerDeploymentDescException(dde);
00220 }
00221
00222
00223 EjbRefDesc[] ejbRef = webDD.getEjbRefDesc();
00224 for (int i = 0; i < ejbRef.length; i++) {
00225 if (ejbRef[i].getJndiName() == null) {
00226 String ejbLink = ejbRef[i].getEjbLink();
00227 String ejbRefType = ejbRef[i].getEjbRefType();
00228 if (ejbLink != null) {
00229 if (earLoader == null) {
00230 throw new WebContainerDeploymentDescException(
00231 "Ejb-link is not authorized from a single war. The war must be in an ear.");
00232 } else {
00233 String jndiName = getJndiName(url, ejbLink, earLoader, ejbRefType, true);
00234 ejbRef[i].setJndiName(jndiName);
00235 }
00236 }
00237 }
00238 }
00239
00240
00241 EjbLocalRefDesc[] ejbLocalRef = webDD.getEjbLocalRefDesc();
00242 for (int i = 0; i < ejbLocalRef.length; i++) {
00243 String ejblink = ejbLocalRef[i].getEjbLink();
00244 if (earLoader == null) {
00245 throw new WebContainerDeploymentDescException(
00246 "Ejb-link is not authorized from a single war. The war must be in an ear.");
00247 }
00248 String ejbRefType = ejbLocalRef[i].getEjbRefType();
00249 String ejbName = getJndiName(url, ejblink, earLoader, ejbRefType, false);
00250 ejbLocalRef[i].setJndiLocalName(ejbName);
00251 }
00252
00253
00254 ServiceRefDesc[] serviceRef = webDD.getServiceRefDesc();
00255
00256 for (int i = 0; i < serviceRef.length; i++) {
00257
00258 List pcRefs = serviceRef[i].getPortComponentRefs();
00259 for (int j = 0; j < pcRefs.size(); j++) {
00260
00261 PortComponentRefDesc pcr = (PortComponentRefDesc) pcRefs.get(j);
00262 String pclink = pcr.getPortComponentLink();
00263 if (pclink != null) {
00264
00265 PortComponentDesc pcDesc = getPCDesc(url, pclink, loaderForCls, earLoader);
00266 pcr.setPortComponentDesc(pcDesc);
00267 }
00268 }
00269 }
00270
00271
00272 MessageDestinationRefDesc[] mdRef = webDD.getMessageDestinationRefDesc();
00273 for (int i = 0; i < mdRef.length; i++) {
00274 if (mdRef[i].getJndiName() == null) {
00275 String jndiName = mdRef[i].getJndiName();
00276 String mdLink = mdRef[i].getMessageDestinationLink();
00277 String mdType = mdRef[i].getMessageDestinationType();
00278 String mdUsage = mdRef[i].getMessageDestinationUsage();
00279 if (mdLink != null) {
00280 if (earLoader == null) {
00281 throw new WebContainerDeploymentDescException(
00282 "Message-destination-link is not authorized from a single client jar. The client jar must be in an ear.");
00283 } else {
00284 String mdName = getMDJndiName(url, mdLink, mdType, mdUsage, earLoader);
00285 mdRef[i].setJndiName(jndiName);
00286 }
00287 }
00288 }
00289 }
00290
00291 return webDD;
00292 }
00293
00306 private PortComponentDesc getPCDesc(URL warURL, String pcLink, ClassLoader moduleLoader, ClassLoader earLoader)
00307 throws WSDeploymentDescException {
00308
00309
00310 return wsDDManager.getPortComponentDesc(warURL, pcLink, moduleLoader, earLoader);
00311 }
00312
00327 private String getJndiName(URL warURL, String ejbLink, ClassLoader earLoader, String ejbType, boolean isEjbRef)
00328 throws DeploymentDescException {
00329
00330
00331 return ejbDDManager.getJndiName(warURL, ejbLink, earLoader, ejbType, null, isEjbRef);
00332 }
00333
00349 private String getMDJndiName(URL warURL, String mdLink, String mdType, String mdUsage, ClassLoader earLoader)
00350 throws WebContainerDeploymentDescException {
00351
00352
00353
00354
00355 String ejbJarLink = null;
00356 String destNameLink = null;
00357 org.objectweb.jonas_ejb.deployment.api.DeploymentDesc dd = null;
00358
00359
00360 if (mdLink.toLowerCase().indexOf(".jar#") == -1) {
00361 String err = "Message-destination-link " + mdLink
00362 + " has a bad format. Correct format : filename.jar#messageDestinationName";
00363 throw new WebContainerDeploymentDescException(err);
00364 }
00365
00366 StringTokenizer st = new StringTokenizer(mdLink, LINK_SEPARATOR);
00367
00368
00369
00370 if (st.countTokens() != 2 || mdLink.startsWith(LINK_SEPARATOR) || mdLink.endsWith(LINK_SEPARATOR)) {
00371
00372 String err = "Message-destination-link " + mdLink
00373 + " has a bad format. Correct format : filename.jar#messageDestinationName.";
00374 throw new WebContainerDeploymentDescException(err);
00375 }
00376
00377
00378 ejbJarLink = st.nextToken();
00379 destNameLink = st.nextToken();
00380
00381
00382 if (!ejbJarLink.endsWith(".jar")) {
00383 String err = "Ejbjar filename " + ejbJarLink + " from the message-destination-link " + mdLink
00384 + " has a bad format. Correct format : filename.jar";
00385 throw new WebContainerDeploymentDescException(err);
00386 }
00387
00388
00389
00390 URL ejbJarLinkUrl = null;
00391 try {
00392 ejbJarLinkUrl = new File(new File(warURL.getFile()).getParent() + File.separator + ejbJarLink)
00393 .getCanonicalFile().toURL();
00394 } catch (MalformedURLException mue) {
00395 String err = "Error when creating an url for the ejb jar filename. Error :" + mue.getMessage();
00396 throw new WebContainerDeploymentDescException(err);
00397 } catch (IOException ioe) {
00398 String err = "Error when creating/accessing a file. Error :" + ioe.getMessage();
00399 throw new WebContainerDeploymentDescException(err);
00400 }
00401
00402
00403 if (!new File(ejbJarLinkUrl.getFile()).exists()) {
00404 String err = "Cannot get the deployment descriptor for '" + ejbJarLinkUrl.getFile()
00405 + "'. The file doesn't exist.";
00406 throw new WebContainerDeploymentDescException(err);
00407 }
00408
00409
00410
00411 URL[] ddURL = new URL[1];
00412 ddURL[0] = ejbJarLinkUrl;
00413 URLClassLoader loaderForClsEjb = new URLClassLoader(ddURL, earLoader);
00414 try {
00415 dd = ejbDDManager.getDeploymentDesc(ejbJarLinkUrl, loaderForClsEjb, earLoader);
00416 } catch (DeploymentDescException e) {
00417 String err = "Cannot get the deployment descriptor for '" + ejbJarLinkUrl.getFile() + "'.";
00418 throw new WebContainerDeploymentDescException(err, e);
00419 }
00420
00421 JonasMessageDestination md = dd.getJonasMessageDestination(mdLink);
00422
00423 if (md == null) {
00424 String err = "No message-destination-link was found for '" + mdLink + "' in the file " + warURL.getFile()
00425 + " specified.";
00426 throw new WebContainerDeploymentDescException(err);
00427 }
00428
00429
00430
00431
00432 return md.getJndiName();
00433 }
00434
00441 public void removeCache(ClassLoader earClassLoader) {
00442
00443 earCLAltDDBindings.remove(earClassLoader);
00444
00445
00446 ejbDDManager.removeCache(earClassLoader);
00447 }
00448
00459 public void setAltDD(ClassLoader earClassLoader, URL[] urls, URL[] altDDs) {
00460
00461
00462 Hashtable urlAltddBindings = new Hashtable();
00463
00464
00465 for (int i = 0; i < urls.length; i++) {
00466 if (altDDs[i] != null) {
00467 urlAltddBindings.put(urls[i], altDDs[i]);
00468 }
00469 }
00470
00471
00472 earCLAltDDBindings.put(earClassLoader, urlAltddBindings);
00473
00474 }
00475
00481 public int getCacheSize() {
00482 int bufferSize = 0;
00483
00484 Enumeration classLoaders = earCLAltDDBindings.keys();
00485 while (classLoaders.hasMoreElements()) {
00486 ClassLoader loader = (ClassLoader) classLoaders.nextElement();
00487 Hashtable hashtab = (Hashtable) earCLAltDDBindings.get(loader);
00488 bufferSize = bufferSize + hashtab.size();
00489 }
00490
00491 return bufferSize;
00492 }
00493
00503 public static WebContainerDeploymentDesc getDeploymentDesc(String filename, ClassLoader loader)
00504 throws WebContainerDeploymentDescException {
00505
00506 WebContainerDeploymentDesc wcdd = null;
00507
00508 if (staticCache.containsKey(filename)) {
00509 wcdd = (WebContainerDeploymentDesc) staticCache.get(filename);
00510 } else {
00511
00512 if (!new File(filename).exists()) {
00513 String err = "Cannot get the deployment descriptor for ";
00514 err += "'" + filename + "'. The file doesn't exist.";
00515 throw new WebContainerDeploymentDescException(err);
00516 }
00517
00518 try {
00519 wcdd = getInstance(filename, loader);
00520 } catch (DeploymentDescException dde) {
00521 throw new WebContainerDeploymentDescException(dde);
00522 }
00523
00524 staticCache.put(filename, wcdd);
00525 }
00526
00527 return wcdd;
00528 }
00529
00543 public static WebContainerDeploymentDesc getInstance(String warFileName, ClassLoader classLoaderForCls,
00544 String altWebXmlFilename) throws DeploymentDescException {
00545
00546
00547 String xmlContent = "";
00548 String jonasXmlContent = "";
00549
00550
00551 JarFile warFile = null;
00552
00553
00554 InputStream webInputStream = null;
00555 InputStream jonasWebInputStream = null;
00556
00557
00558 ZipEntry webZipEntry = null;
00559 ZipEntry jonasWebZipEntry = null;
00560
00561
00562 WebApp webApp;
00563 JonasWebApp jonasWebApp;
00564
00565
00566 File fWar = new File(warFileName);
00567
00568
00569 if (!(fWar.exists())) {
00570 String err = "' " + warFileName + "' was not found.";
00571 throw new WebContainerDeploymentDescException(err);
00572 }
00573
00574
00575
00576 if ((altWebXmlFilename != null) && (!new File(altWebXmlFilename).exists())) {
00577 String err = "The file for the altdd tag for the EAR case '" + altWebXmlFilename + "' was not found.";
00578 throw new WebContainerDeploymentDescException(err);
00579 }
00580
00581
00582
00583 try {
00584
00585
00586 if (altWebXmlFilename == null) {
00587
00588
00589
00590 if (fWar.isDirectory()) {
00591
00592 File webXmlF = new File(warFileName, WEB_FILE_NAME);
00593 if (!webXmlF.exists()) {
00594 String err = "You have choose to deploy a war directory but there is no " + WEB_FILE_NAME
00595 + " file in the directory " + warFileName;
00596 throw new WebContainerDeploymentDescException(err);
00597 }
00598 webInputStream = new FileInputStream(webXmlF);
00599 xmlContent = xmlContent(webInputStream);
00600 webInputStream = new FileInputStream(webXmlF);
00601 } else {
00602 warFile = new JarFile(warFileName);
00603
00604
00605 webZipEntry = warFile.getEntry(WEB_FILE_NAME);
00606 if (webZipEntry == null) {
00607 throw new WebContainerDeploymentDescException("The entry '" + WEB_FILE_NAME
00608 + "' was not found in the file '" + warFileName + "'.");
00609 }
00610
00611 webInputStream = warFile.getInputStream(webZipEntry);
00612 xmlContent = xmlContent(webInputStream);
00613 webInputStream = warFile.getInputStream(webZipEntry);
00614 }
00615 } else {
00616 webInputStream = new FileInputStream(altWebXmlFilename);
00617 xmlContent = xmlContent(webInputStream);
00618 webInputStream = new FileInputStream(altWebXmlFilename);
00619 }
00620
00621
00622 if (fWar.isDirectory()) {
00623
00624 File webJXmlF = new File(warFileName, JONAS_WEB_FILE_NAME);
00625 if (webJXmlF.exists()) {
00626 jonasWebInputStream = new FileInputStream(webJXmlF);
00627 jonasXmlContent = xmlContent(jonasWebInputStream);
00628 jonasWebInputStream = new FileInputStream(webJXmlF);
00629 }
00630 } else {
00631 if (warFile == null) {
00632 warFile = new JarFile(warFileName);
00633 }
00634
00635
00636 jonasWebZipEntry = warFile.getEntry(JONAS_WEB_FILE_NAME);
00637
00638
00639 if (jonasWebZipEntry != null) {
00640 jonasWebInputStream = warFile.getInputStream(jonasWebZipEntry);
00641 jonasXmlContent = xmlContent(jonasWebInputStream);
00642 jonasWebInputStream = warFile.getInputStream(jonasWebZipEntry);
00643
00644 }
00645 }
00646
00647 } catch (Exception e) {
00648 if (warFile != null) {
00649 try {
00650 warFile.close();
00651 } catch (IOException ioe) {
00652
00653 logger.log(BasicLevel.WARN, "Can't close file '" + warFileName + "'");
00654 }
00655 }
00656 throw new WebContainerDeploymentDescException(
00657 "Cannot read the XML deployment descriptors of the war file '" + warFileName + "'.", e);
00658 }
00659
00660 webApp = loadWebApp(new InputStreamReader(webInputStream), WEB_FILE_NAME);
00661 try {
00662 webInputStream.close();
00663 } catch (IOException e) {
00664
00665 logger.log(BasicLevel.WARN, "Can't close InputStream of web.xml from '" + warFileName + "'");
00666 }
00667
00668
00669
00670 if (jonasWebInputStream != null) {
00671 jonasWebApp = loadJonasWebApp(new InputStreamReader(jonasWebInputStream), JONAS_WEB_FILE_NAME);
00672 try {
00673 jonasWebInputStream.close();
00674 } catch (IOException e) {
00675
00676 logger.log(BasicLevel.WARN, "Can't close InputStream of jonas-web.xml from '" + warFileName + "'");
00677 }
00678 } else {
00679 jonasWebApp = new JonasWebApp();
00680 }
00681
00682
00683 if (warFile != null) {
00684 try {
00685 warFile.close();
00686 } catch (IOException ioe) {
00687
00688 logger.log(BasicLevel.WARN, "Can't close file '" + warFileName + "'");
00689 }
00690 }
00691
00692
00693 WebContainerDeploymentDesc webDD = new WebContainerDeploymentDesc(warFileName, classLoaderForCls, webApp,
00694 jonasWebApp);
00695 webDD.setXmlContent(xmlContent);
00696 webDD.setJOnASXmlContent(jonasXmlContent);
00697 return webDD;
00698 }
00699
00711 public static WebContainerDeploymentDesc getInstance(String warFileName, ClassLoader classLoaderForCls)
00712 throws DeploymentDescException {
00713
00714 return getInstance(warFileName, classLoaderForCls, null);
00715 }
00716
00725 public static WebApp loadWebApp(Reader reader, String fileName) throws DeploymentDescException {
00726
00727 WebApp webApp = new WebApp();
00728
00729
00730 if (webAppDigester == null) {
00731 webAppDigester = new JDigester(webAppRuleSet, getParsingWithValidation(), true, new WebAppDTDs(),
00732 new WebAppSchemas());
00733 }
00734
00735 try {
00736 webAppDigester.parse(reader, fileName, webApp);
00737 } catch (DeploymentDescException e) {
00738 throw e;
00739 } finally {
00740 webAppDigester.push(null);
00741 }
00742 return webApp;
00743 }
00744
00753 public static JonasWebApp loadJonasWebApp(Reader reader, String fileName) throws DeploymentDescException {
00754
00755 JonasWebApp jonasWebApp = new JonasWebApp();
00756
00757
00758 if (jonasWebAppDigester == null) {
00759 jonasWebAppDigester = new JDigester(jonasWebAppRuleSet, getParsingWithValidation(), true,
00760 new JonasWebAppDTDs(), new JonasWebAppSchemas());
00761 }
00762
00763 try {
00764 jonasWebAppDigester.parse(reader, fileName, jonasWebApp);
00765 } catch (DeploymentDescException e) {
00766 throw e;
00767 } finally {
00768 jonasWebAppDigester.push(null);
00769 }
00770 return jonasWebApp;
00771 }
00772
00777 public static boolean getParsingWithValidation() {
00778 return parsingWithValidation;
00779 }
00780
00785 public static void setParsingWithValidation(boolean validation) {
00786 WebDeploymentDescManager.parsingWithValidation = validation;
00787 }
00788
00789 }