00001
00027 package org.objectweb.jonas_client.deployment.lib;
00028
00029
00030 import java.io.File;
00031 import java.io.FileInputStream;
00032 import java.io.FileNotFoundException;
00033 import java.io.IOException;
00034 import java.io.InputStream;
00035 import java.io.InputStreamReader;
00036 import java.io.Reader;
00037 import java.net.MalformedURLException;
00038 import java.net.URL;
00039 import java.net.URLClassLoader;
00040 import java.util.Enumeration;
00041 import java.util.Hashtable;
00042 import java.util.List;
00043 import java.util.StringTokenizer;
00044 import java.util.jar.JarFile;
00045 import java.util.zip.ZipEntry;
00046
00047 import org.objectweb.jonas_client.deployment.api.ClientContainerDeploymentDesc;
00048 import org.objectweb.jonas_client.deployment.api.ClientContainerDeploymentDescException;
00049 import org.objectweb.jonas_client.deployment.rules.ApplicationClientRuleSet;
00050 import org.objectweb.jonas_client.deployment.rules.JonasClientRuleSet;
00051 import org.objectweb.jonas_client.deployment.xml.ApplicationClient;
00052 import org.objectweb.jonas_client.deployment.xml.JonasClient;
00053
00054 import org.objectweb.jonas_ejb.deployment.api.DeploymentDesc;
00055 import org.objectweb.jonas_ejb.deployment.lib.EjbDeploymentDescManager;
00056
00057 import org.objectweb.jonas_lib.deployment.api.DeploymentDescException;
00058 import org.objectweb.jonas_lib.deployment.api.EjbRefDesc;
00059 import org.objectweb.jonas_lib.deployment.api.MessageDestinationRefDesc;
00060 import org.objectweb.jonas_lib.deployment.digester.JDigester;
00061 import org.objectweb.jonas_lib.deployment.lib.AbsDeploymentDescManager;
00062 import org.objectweb.jonas_lib.deployment.xml.JonasMessageDestination;
00063 import org.objectweb.jonas_lib.loader.WebappClassLoader;
00064
00065 import org.objectweb.jonas_ws.deployment.api.PortComponentDesc;
00066 import org.objectweb.jonas_ws.deployment.api.PortComponentRefDesc;
00067 import org.objectweb.jonas_ws.deployment.api.ServiceDesc;
00068 import org.objectweb.jonas_ws.deployment.api.ServiceRefDesc;
00069 import org.objectweb.jonas_ws.deployment.api.WSDeploymentDesc;
00070 import org.objectweb.jonas_ws.deployment.lib.WSDeploymentDescManager;
00071
00076 public class ClientDeploymentDescManager extends AbsDeploymentDescManager {
00077
00081 private static ClientDeploymentDescManager unique;
00082
00086 private EjbDeploymentDescManager ejbDDManager = null;
00087
00092 private Hashtable earCLAltDDBindings = null;
00093
00097 public static final String CLIENT_FILE_NAME = "META-INF/application-client.xml";
00098
00102 public static final String JONAS_CLIENT_FILE_NAME = "META-INF/jonas-client.xml";
00103
00107 private static JDigester appClientDigester = null;
00108
00112 private static JDigester jonasAppClientDigester = null;
00113
00117 private static boolean parsingWithValidation = true;
00118
00122 private static ApplicationClientRuleSet appClientRuleSet = new ApplicationClientRuleSet();
00123
00127 private static JonasClientRuleSet jonasAppClientRuleSet = new JonasClientRuleSet();
00128
00132 private ClientDeploymentDescManager() {
00133 ejbDDManager = EjbDeploymentDescManager.getInstance();
00134 earCLAltDDBindings = new Hashtable();
00135 }
00136
00141 public static ClientDeploymentDescManager getInstance() {
00142 if (unique == null) {
00143 unique = new ClientDeploymentDescManager();
00144 }
00145 return unique;
00146 }
00147
00158 public ClientContainerDeploymentDesc getDeploymentDesc(URL url, ClassLoader loaderForCls, ClassLoader earLoader)
00159 throws DeploymentDescException {
00160
00161
00162 if (!new File(url.getFile()).exists()) {
00163 String err = "Cannot get the deployment descriptor for ";
00164 err = err + "'" + url.getFile() + "'. The file doesn't exist.";
00165 throw new ClientContainerDeploymentDescException(err);
00166 }
00167
00168
00169 URL altDDUrl = null;
00170
00171
00172 Hashtable urlAltddBindings = null;
00173 if (earLoader != null) {
00174
00175 urlAltddBindings = (Hashtable) earCLAltDDBindings.get(earLoader);
00176 if (urlAltddBindings == null) {
00177
00178
00179 String err = "Cannot find if there is alt-dd for '" + url.getFile()
00180 + "', the setAltDD function was badly called";
00181 throw new ClientContainerDeploymentDescException(err);
00182 }
00183
00184 altDDUrl = (URL) urlAltddBindings.get(url);
00185 }
00186
00187
00188
00189
00190 ClientContainerDeploymentDesc clientDD = null;
00191 try {
00192 if (altDDUrl != null) {
00193 clientDD = getInstance(url.getFile(), loaderForCls, altDDUrl.getFile());
00194 } else {
00195 clientDD = getInstance(url.getFile(), loaderForCls);
00196 }
00197 } catch (org.objectweb.jonas_lib.deployment.api.DeploymentDescException dde) {
00198 throw new ClientContainerDeploymentDescException(dde);
00199 }
00200
00201
00202 EjbRefDesc[] ejbRef = clientDD.getEjbRefDesc();
00203 for (int i = 0; i < ejbRef.length; i++) {
00204 if (ejbRef[i].getJndiName() == null) {
00205 String ejbLink = ejbRef[i].getEjbLink();
00206 String ejbRefType = ejbRef[i].getEjbRefType();
00207 if (ejbLink != null) {
00208 if (earLoader == null) {
00209 throw new ClientContainerDeploymentDescException(
00210 "Ejb-link is not authorized from a single client jar. The client jar must be in an ear.");
00211 } else {
00212 String jndiName = getJndiName(url, ejbLink, earLoader, ejbRefType);
00213 ejbRef[i].setJndiName(jndiName);
00214 }
00215 }
00216 }
00217 }
00218
00219 ServiceRefDesc[] serviceRef = clientDD.getServiceRefDesc();
00220
00221 for (int i = 0; i < serviceRef.length; i++) {
00222
00223 List pcRefs = serviceRef[i].getPortComponentRefs();
00224 for (int j = 0; j < pcRefs.size(); j++) {
00225
00226 PortComponentRefDesc pcr = (PortComponentRefDesc) pcRefs.get(j);
00227 String pclink = pcr.getPortComponentLink();
00228 if (pclink != null) {
00229
00230 PortComponentDesc pcDesc = getPCDesc(url, pclink, earLoader);
00231 pcr.setPortComponentDesc(pcDesc);
00232 }
00233 }
00234 }
00235
00236
00237
00238 MessageDestinationRefDesc[] mdRef = clientDD.getMessageDestinationRefDesc();
00239 for (int i = 0; i < mdRef.length; i++) {
00240 if (mdRef[i].getJndiName() == null) {
00241 String jndiName = mdRef[i].getJndiName();
00242 String mdLink = mdRef[i].getMessageDestinationLink();
00243 String mdType = mdRef[i].getMessageDestinationType();
00244 String mdUsage = mdRef[i].getMessageDestinationUsage();
00245 if (mdLink != null) {
00246 if (earLoader == null) {
00247 throw new ClientContainerDeploymentDescException(
00248 "Message-destination-link is not authorized from a single client jar. The client jar must be in an ear.");
00249 } else {
00250 String mdName = getMDJndiName(url, mdLink, mdType, mdUsage, earLoader);
00251
00252
00253 mdRef[i].setJndiName(jndiName);
00254 }
00255 }
00256 }
00257 }
00258 return clientDD;
00259 }
00271 private PortComponentDesc getPCDesc(URL warURL, String pcLink, ClassLoader earLoader)
00272 throws DeploymentDescException {
00273
00274
00275
00276
00277 String moduleLink = null;
00278 String pcNameLink = null;
00279
00280
00281 if ((pcLink.toLowerCase().indexOf(".war" + LINK_SEPARATOR) == -1)
00282 && (pcLink.toLowerCase().indexOf(".jar" + LINK_SEPARATOR) == -1)) {
00283
00284 String err = "PC-link " + pcLink
00285 + " has a bad format. Correct format : filename.(jar|war)#portComponentName";
00286 throw new DeploymentDescException(err);
00287 }
00288 StringTokenizer st = new StringTokenizer(pcLink, LINK_SEPARATOR);
00289
00290
00291
00292 if (st.countTokens() != 2 || pcLink.startsWith(LINK_SEPARATOR) || pcLink.endsWith(LINK_SEPARATOR)) {
00293 String err = "PC-link " + pcLink
00294 + " has a bad format. Correct format : filename.[jar or war]#portComponentName";
00295 throw new DeploymentDescException(err);
00296 }
00297
00298
00299 moduleLink = st.nextToken();
00300 pcNameLink = st.nextToken();
00301
00302
00303
00304 URL moduleLinkUrl = null;
00305 try {
00306 moduleLinkUrl = new File(new File(warURL.getFile()).getParent() + File.separator + moduleLink)
00307 .getCanonicalFile().toURL();
00308 } catch (MalformedURLException mue) {
00309 String err = "Error when creating an url for the module filename. Error :" + mue.getMessage();
00310 throw new DeploymentDescException(err);
00311 } catch (IOException ioe) {
00312 String err = "Error when creating/accessing a file. Error :" + ioe.getMessage();
00313 throw new DeploymentDescException(err);
00314 }
00315
00316
00317 if (!new File(moduleLinkUrl.getFile()).exists()) {
00318 String err = "Cannot get the deployment descriptor for '" + moduleLinkUrl.getFile()
00319 + "'. The file doesn't exist.";
00320 throw new DeploymentDescException(err);
00321 }
00322
00323
00324
00325 ClassLoader loaderForCls = null;
00326 ClassLoader current = Thread.currentThread().getContextClassLoader();
00327 if (moduleLink.toLowerCase().endsWith(".war")) {
00328 try {
00329
00330 loaderForCls = new WebappClassLoader(moduleLinkUrl, current);
00331 } catch (IOException ioe) {
00332 throw new DeploymentDescException("Unable to create Web ClassLoader", ioe);
00333 }
00334 } else {
00335
00336 loaderForCls = current;
00337 }
00338
00339 WSDeploymentDesc wsDD = null;
00340
00341 try {
00342 wsDD = WSDeploymentDescManager.getInstance().getDeploymentDesc(moduleLinkUrl, loaderForCls, earLoader);
00343 } catch (DeploymentDescException e) {
00344 String err = "Cannot get the deployment descriptor for '" + moduleLinkUrl.getFile() + "'.";
00345 throw new DeploymentDescException(err, e);
00346 }
00347 if (wsDD == null) {
00348
00349 String err = "Port component link " + pcNameLink + " not found in " + moduleLinkUrl.getFile();
00350 throw new DeploymentDescException(err);
00351 }
00352
00353
00354 List sdl = wsDD.getServiceDescs();
00355 boolean isFound = false;
00356 PortComponentDesc pcd = null;
00357 for (int i = 0; (i < sdl.size()) && !isFound; i++) {
00358 if (sdl.get(i) != null) {
00359 pcd = ((ServiceDesc) sdl.get(i)).getPortComponent(pcNameLink);
00360 isFound = (pcd != null);
00361
00362 }
00363 }
00364 if (!isFound) {
00365
00366 String err = "the port component link " + pcNameLink + " doesn't exist in " + moduleLinkUrl.getFile();
00367 throw new DeploymentDescException(err);
00368 }
00369
00370 return pcd;
00371 }
00372
00373
00386 public static ClientContainerDeploymentDesc getInstance(String clientFileName, ClassLoader classLoaderForCls)
00387 throws DeploymentDescException {
00388
00389 return getInstance(clientFileName, classLoaderForCls, null);
00390 }
00391
00407 public static ClientContainerDeploymentDesc getInstance(String clientFileName, ClassLoader classLoaderForCls,
00408 String altClientXmlFilename)
00409
00410 throws DeploymentDescException {
00411
00412
00413 JarFile clientFile = null;
00414
00415
00416 InputStream applicationClientInputStream = null;
00417 InputStream jonasClientInputStream = null;
00418
00419
00420 ZipEntry applicationClientZipEntry = null;
00421 ZipEntry jonasClientZipEntry = null;
00422
00423
00424 ApplicationClient applicationClient;
00425 JonasClient jonasClient;
00426
00427
00428 String xmlContent = "";
00429 String jonasXmlContent = "";
00430
00431
00432 File fClient = new File(clientFileName);
00433
00434
00435 if (!(fClient.exists())) {
00436 String err = "' " + clientFileName + "' was not found.";
00437 throw new ClientContainerDeploymentDescException(err);
00438 }
00439
00440
00441
00442 if ((altClientXmlFilename != null) && (!new File(altClientXmlFilename).exists())) {
00443 String err = "The file for the altdd tag for the EAR case '" + altClientXmlFilename + "' was not found.";
00444 throw new ClientContainerDeploymentDescException(err);
00445 }
00446
00447
00448
00449
00450
00451 if (altClientXmlFilename == null) {
00452 try {
00453 clientFile = new JarFile(clientFileName);
00454
00455
00456
00457 applicationClientZipEntry = clientFile.getEntry(CLIENT_FILE_NAME);
00458 if (applicationClientZipEntry == null) {
00459 throw new ClientContainerDeploymentDescException("The entry '" + CLIENT_FILE_NAME
00460 + "' was not found in the file '" + clientFileName + "'.");
00461 }
00462
00463 applicationClientInputStream = clientFile.getInputStream(applicationClientZipEntry);
00464 xmlContent = xmlContent(applicationClientInputStream);
00465
00466 applicationClientInputStream = clientFile.getInputStream(applicationClientZipEntry);
00467 } catch (Exception e) {
00468 if (clientFile != null) {
00469 try {
00470 clientFile.close();
00471 } catch (IOException ioe) {
00472
00473 }
00474 }
00475 throw new ClientContainerDeploymentDescException(
00476 "Can not read the XML deployment descriptors of the client jar file '" + clientFileName + "'.",
00477 e);
00478 }
00479 } else {
00480 try {
00481 applicationClientInputStream = new FileInputStream(altClientXmlFilename);
00482 xmlContent = xmlContent(applicationClientInputStream);
00483
00484 applicationClientInputStream = new FileInputStream(altClientXmlFilename);
00485 } catch (FileNotFoundException ioe) {
00486 throw new ClientContainerDeploymentDescException("The altDD file '" + altClientXmlFilename
00487 + "' was not found.");
00488 } catch (Exception e) {
00489 if (applicationClientInputStream != null) {
00490 try {
00491 applicationClientInputStream.close();
00492 } catch (IOException ioe) {
00493
00494 }
00495 }
00496 throw new ClientContainerDeploymentDescException("Cannot read the XML deployment descriptors of the client jar file '"
00497 + clientFileName + "'.", e);
00498 }
00499 }
00500
00501 applicationClient = loadApplicationClient(new InputStreamReader(applicationClientInputStream), CLIENT_FILE_NAME);
00502
00503 try {
00504 clientFile = new JarFile(clientFileName);
00505
00506
00507
00508 jonasClientZipEntry = clientFile.getEntry(JONAS_CLIENT_FILE_NAME);
00509 if (jonasClientZipEntry != null) {
00510
00511 jonasClientInputStream = clientFile.getInputStream(jonasClientZipEntry);
00512 jonasXmlContent = xmlContent(jonasClientInputStream);
00513
00514 jonasClientInputStream = clientFile.getInputStream(jonasClientZipEntry);
00515 }
00516 } catch (Exception e) {
00517 if (clientFile != null) {
00518 try {
00519 clientFile.close();
00520 } catch (IOException ioe) {
00521
00522 }
00523 }
00524 throw new ClientContainerDeploymentDescException(
00525 "Can not read the XML deployment descriptors of the client jar file '" + clientFileName + "'.", e);
00526 }
00527
00528
00529
00530 if (jonasClientInputStream != null) {
00531 jonasClient = loadJonasClient(new InputStreamReader(jonasClientInputStream), JONAS_CLIENT_FILE_NAME);
00532 try {
00533 jonasClientInputStream.close();
00534 } catch (IOException e) {
00535
00536 }
00537 } else {
00538 jonasClient = new JonasClient();
00539 }
00540
00541
00542 ClientContainerDeploymentDesc clientDD = new ClientContainerDeploymentDesc(classLoaderForCls, applicationClient, jonasClient);
00543 clientDD.setXmlContent(xmlContent);
00544 clientDD.setJOnASXmlContent(jonasXmlContent);
00545 return clientDD;
00546 }
00547
00557 public static ApplicationClient loadApplicationClient(Reader reader, String fileName)
00558 throws DeploymentDescException {
00559
00560 ApplicationClient appc = new ApplicationClient();
00561
00562
00563 if (appClientDigester == null) {
00564
00565 appClientDigester = new JDigester(appClientRuleSet, getParsingWithValidation(), true, new AppClientDTDs(),
00566 new AppClientSchemas());
00567 }
00568
00569 try {
00570 appClientDigester.parse(reader, fileName, appc);
00571 } catch (DeploymentDescException e) {
00572 throw e;
00573 } finally {
00574 appClientDigester.push(null);
00575 }
00576 return appc;
00577 }
00578
00588 public static JonasClient loadJonasClient(Reader reader, String fileName) throws DeploymentDescException {
00589
00590 JonasClient jc = new JonasClient();
00591
00592
00593 if (jonasAppClientDigester == null) {
00594 jonasAppClientDigester = new JDigester(jonasAppClientRuleSet, getParsingWithValidation(), true,
00595 new JonasAppClientDTDs(), new JonasAppClientSchemas());
00596 }
00597
00598 try {
00599 jonasAppClientDigester.parse(reader, fileName, jc);
00600
00601 } catch (DeploymentDescException e) {
00602 throw e;
00603 } finally {
00604 jonasAppClientDigester.push(null);
00605 }
00606 return jc;
00607 }
00608
00621 private String getJndiName(URL clientURL, String ejbLink, ClassLoader earLoader, String ejbType)
00622 throws DeploymentDescException {
00623
00624
00625 return ejbDDManager.getJndiName(clientURL, ejbLink, earLoader, ejbType, null, true);
00626 }
00627
00644 private String getMDJndiName(URL clientURL, String mdLink, String mdType, String mdUsage, ClassLoader earLoader)
00645 throws ClientContainerDeploymentDescException {
00646
00647
00648
00649
00650 String ejbJarLink = null;
00651 String destNameLink = null;
00652 DeploymentDesc dd = null;
00653
00654
00655 if (mdLink.toLowerCase().indexOf(".jar#") == -1) {
00656 String err = "Message-destination-link " + mdLink
00657 + " has a bad format. Correct format : filename.jar#messageDestinationName";
00658 throw new ClientContainerDeploymentDescException(err);
00659 }
00660
00661 StringTokenizer st = new StringTokenizer(mdLink, LINK_SEPARATOR);
00662
00663
00664
00665 if (st.countTokens() != 2 || mdLink.startsWith(LINK_SEPARATOR) || mdLink.endsWith(LINK_SEPARATOR)) {
00666
00667 String err = "Message-destination-link " + mdLink
00668 + " has a bad format. Correct format : filename.jar#messageDestinationName.";
00669 throw new ClientContainerDeploymentDescException(err);
00670 }
00671
00672
00673 ejbJarLink = st.nextToken();
00674 destNameLink = st.nextToken();
00675
00676
00677 if (!ejbJarLink.endsWith(".jar")) {
00678 String err = "Ejbjar filename " + ejbJarLink + " from the message-destination-link " + mdLink
00679 + " has a bad format. Correct format : filename.jar";
00680 throw new ClientContainerDeploymentDescException(err);
00681 }
00682
00683
00684
00685
00686 URL ejbJarLinkUrl = null;
00687 try {
00688 ejbJarLinkUrl = new File(new File(clientURL.getFile()).getParent() + File.separator + ejbJarLink)
00689 .getCanonicalFile().toURL();
00690 } catch (MalformedURLException mue) {
00691 String err = "Error when creating an url for the ejb jar filename. Error :" + mue.getMessage();
00692 throw new ClientContainerDeploymentDescException(err);
00693 } catch (IOException ioe) {
00694 String err = "Error when creating/accessing a file. Error :" + ioe.getMessage();
00695 throw new ClientContainerDeploymentDescException(err);
00696 }
00697
00698
00699 if (!new File(ejbJarLinkUrl.getFile()).exists()) {
00700 String err = "Cannot get the deployment descriptor for '" + ejbJarLinkUrl.getFile()
00701 + "'. The file doesn't exist.";
00702 throw new ClientContainerDeploymentDescException(err);
00703 }
00704
00705
00706
00707 URL[] ddURL = new URL[1];
00708 ddURL[0] = ejbJarLinkUrl;
00709 URLClassLoader loaderForClsEjb = new URLClassLoader(ddURL, earLoader);
00710 try {
00711 dd = ejbDDManager.getDeploymentDesc(ejbJarLinkUrl, loaderForClsEjb, earLoader);
00712 } catch (DeploymentDescException e) {
00713 String err = "Cannot get the deployment descriptor for '" + ejbJarLinkUrl.getFile() + "'.";
00714 throw new ClientContainerDeploymentDescException(err, e);
00715 }
00716
00717 JonasMessageDestination md = dd.getJonasMessageDestination(mdLink);
00718
00719 if (md == null) {
00720 String err = "No message-destination-link was found for '" + mdLink + "' in the file "
00721 + clientURL.getFile() + " specified.";
00722 throw new ClientContainerDeploymentDescException(err);
00723 }
00724
00725
00726
00727
00728 return md.getJndiName();
00729 }
00730
00737 public void removeCache(ClassLoader earClassLoader) {
00738
00739 earCLAltDDBindings.remove(earClassLoader);
00740
00741
00742 ejbDDManager.removeCache(earClassLoader);
00743 }
00744
00755 public void setAltDD(ClassLoader earClassLoader, URL[] urls, URL[] altDDs) {
00756
00757
00758 Hashtable urlAltddBindings = new Hashtable();
00759
00760
00761 for (int i = 0; i < urls.length; i++) {
00762 if (altDDs[i] != null) {
00763 urlAltddBindings.put(urls[i], altDDs[i]);
00764 }
00765 }
00766
00767
00768 earCLAltDDBindings.put(earClassLoader, urlAltddBindings);
00769
00770 }
00771
00777 public int getCacheSize() {
00778 int bufferSize = 0;
00779
00780 Enumeration keys = earCLAltDDBindings.keys();
00781 while (keys.hasMoreElements()) {
00782 ClassLoader loader = (ClassLoader) keys.nextElement();
00783 Hashtable hashtab = (Hashtable) earCLAltDDBindings.get(loader);
00784 bufferSize = bufferSize + hashtab.size();
00785 }
00786
00787 return bufferSize;
00788 }
00789
00794 public static boolean getParsingWithValidation() {
00795 return parsingWithValidation;
00796 }
00797
00802 public static void setParsingWithValidation(boolean validation) {
00803 ClientDeploymentDescManager.parsingWithValidation = validation;
00804 }
00805 }