00001
00027 package org.objectweb.jonas_ws.deployment.lib;
00028
00029 import java.io.File;
00030 import java.io.IOException;
00031 import java.io.InputStream;
00032 import java.io.InputStreamReader;
00033 import java.io.Reader;
00034 import java.net.MalformedURLException;
00035 import java.net.URL;
00036 import java.net.URLClassLoader;
00037 import java.net.URLConnection;
00038 import java.util.Enumeration;
00039 import java.util.HashMap;
00040 import java.util.Hashtable;
00041 import java.util.Iterator;
00042 import java.util.List;
00043 import java.util.Map;
00044 import java.util.StringTokenizer;
00045 import java.util.Vector;
00046
00047 import org.objectweb.jonas_ejb.deployment.api.BeanDesc;
00048 import org.objectweb.jonas_ejb.deployment.api.DeploymentDesc;
00049 import org.objectweb.jonas_ejb.deployment.api.SessionStatelessDesc;
00050 import org.objectweb.jonas_ejb.deployment.lib.EjbDeploymentDescManager;
00051
00052 import org.objectweb.jonas_lib.deployment.api.DeploymentDescException;
00053 import org.objectweb.jonas_lib.deployment.digester.JDigester;
00054 import org.objectweb.jonas_lib.deployment.lib.AbsDeploymentDescManager;
00055
00056 import org.objectweb.jonas_web.deployment.api.WebContainerDeploymentDesc;
00057 import org.objectweb.jonas_web.deployment.api.WebContainerDeploymentDescException;
00058 import org.objectweb.jonas_web.deployment.lib.WebDeploymentDescManager;
00059
00060 import org.objectweb.jonas_ws.deployment.api.PortComponentDesc;
00061 import org.objectweb.jonas_ws.deployment.api.ServiceDesc;
00062 import org.objectweb.jonas_ws.deployment.api.WSDeploymentDesc;
00063 import org.objectweb.jonas_ws.deployment.api.WSDeploymentDescException;
00064 import org.objectweb.jonas_ws.deployment.rules.JonasWebservicesRuleSet;
00065 import org.objectweb.jonas_ws.deployment.rules.WebservicesRuleSet;
00066 import org.objectweb.jonas_ws.deployment.xml.JonasWebservices;
00067 import org.objectweb.jonas_ws.deployment.xml.Webservices;
00068
00069 import org.objectweb.jonas.common.Log;
00070
00071 import org.objectweb.util.monolog.api.BasicLevel;
00072 import org.objectweb.util.monolog.api.Logger;
00073
00081 public class WSDeploymentDescManager extends AbsDeploymentDescManager {
00082
00086 public static final String WS_EJBJAR_FILE_NAME = "META-INF/webservices.xml";
00087
00091 public static final String JONAS_WS_EJBJAR_FILE_NAME = "META-INF/jonas-webservices.xml";
00092
00096 public static final String WS_WEBAPP_FILE_NAME = "WEB-INF/webservices.xml";
00097
00101 public static final String JONAS_WS_WEBAPP_FILE_NAME = "WEB-INF/jonas-webservices.xml";
00102
00106 private static JDigester wsDigester = null;
00107
00111 private static JDigester jwsDigester = null;
00112
00116 private static WebservicesRuleSet wsRuleSet = new WebservicesRuleSet();
00117
00121 private static JonasWebservicesRuleSet jwsRuleSet = new JonasWebservicesRuleSet();
00122
00126 private static boolean parsingWithValidation = true;
00127
00131 private static WSDeploymentDescManager unique = null;
00132
00136 private static boolean isInstanciated = false;
00137
00141 private static Logger logger = Log.getLogger(Log.JONAS_WS_PREFIX);
00142
00146 private HashMap urlWsddBindings;
00147
00152 private Map classLoader2URLs;
00153
00157 private EjbDeploymentDescManager ejbManager = null;
00158
00162 private WebDeploymentDescManager webManager = null;
00163
00168 private WSDeploymentDescManager() {
00169 urlWsddBindings = new HashMap();
00170 classLoader2URLs = new Hashtable();
00171
00172 ejbManager = EjbDeploymentDescManager.getInstance();
00173 webManager = WebDeploymentDescManager.getInstance();
00174 }
00175
00180 public static WSDeploymentDescManager getInstance() {
00181 if (!isInstanciated) {
00182 isInstanciated = true;
00183 unique = new WSDeploymentDescManager();
00184
00185 }
00186 return unique;
00187 }
00188
00199 public static WSDeploymentDesc getDeploymentDesc(String file, ClassLoader jarCL) throws WSDeploymentDescException {
00200
00201 URL fileUrl = null;
00202 try {
00203 fileUrl = new File(file).toURL();
00204 } catch (MalformedURLException mue) {
00205 throw new WSDeploymentDescException(mue);
00206 }
00207
00208 WSDeploymentDesc wsdd = loadDeploymentDesc(fileUrl, jarCL);
00209
00210
00211 if (wsdd == null) {
00212 return null;
00213
00214 }
00215
00216
00217 List sdl = wsdd.getServiceDescs();
00218
00219 for (int i = 0; i < sdl.size(); i++) {
00220 List pcdl = ((ServiceDesc) sdl.get(i)).getPortComponents();
00221
00222 for (int j = 0; j < pcdl.size(); j++) {
00223
00224 PortComponentDesc pcd = (PortComponentDesc) pcdl.get(j);
00225 String sibLink = pcd.getSibLink();
00226
00227
00228 if (pcd.hasBeanImpl()) {
00229 SessionStatelessDesc desc = getBeanDesc(file, sibLink, jarCL);
00230 pcd.setDesc(desc);
00231
00232 } else if (pcd.hasJaxRpcImpl()) {
00233 WebContainerDeploymentDesc desc = getWebDesc(file, sibLink, jarCL);
00234 pcd.setDesc(desc);
00235
00236 }
00237 }
00238 }
00239
00240 return wsdd;
00241 }
00242
00255 public WSDeploymentDesc getDeploymentDesc(URL url, ClassLoader jarCL, ClassLoader earCL)
00256 throws WSDeploymentDescException {
00257 return getDeploymentDesc(url, null, jarCL, earCL);
00258 }
00259
00273 public WSDeploymentDesc getDeploymentDesc(URL url, URL unpackedURL, ClassLoader jarCL, ClassLoader earCL)
00274 throws WSDeploymentDescException {
00275
00276 WSDeploymentDesc wsdd = null;
00277 File moduleFile = new File(url.getFile());
00278
00279 if (moduleFile.exists()) {
00280
00281 if (!urlWsddBindings.containsKey(url)) {
00282 wsdd = getDeploymentDescriptor(url, unpackedURL, jarCL, earCL);
00283 } else {
00284
00285
00286 wsdd = (WSDeploymentDesc) urlWsddBindings.get(url);
00287 }
00288 } else {
00289 throw new WSDeploymentDescException("'" + moduleFile.getName() + "' doesn't exists");
00290 }
00291
00292
00293 ClassLoader keyCL;
00294 if (earCL != null) {
00295 keyCL = earCL;
00296 } else {
00297 keyCL = jarCL;
00298 }
00299 List urls = (List) classLoader2URLs.get(keyCL);
00300 if (urls == null) {
00301 urls = new Vector();
00302 classLoader2URLs.put(keyCL, urls);
00303 }
00304 urls.add(url);
00305
00306 return wsdd;
00307 }
00308
00323 private WSDeploymentDesc getDeploymentDescriptor(URL url, URL unpackedURL, ClassLoader jarCL, ClassLoader earCL)
00324 throws WSDeploymentDescException {
00325
00326 URL baseURL = url;
00327 if (unpackedURL != null) {
00328 baseURL = unpackedURL;
00329 }
00330 WSDeploymentDesc wsdd = loadDeploymentDesc(baseURL, jarCL);
00331
00332
00333 urlWsddBindings.put(url, wsdd);
00334
00335
00336 if (wsdd == null) {
00337 return null;
00338 }
00339
00340
00341 List sdl = wsdd.getServiceDescs();
00342
00343 for (int i = 0; i < sdl.size(); i++) {
00344 List pcdl = ((ServiceDesc) sdl.get(i)).getPortComponents();
00345
00346 for (int j = 0; j < pcdl.size(); j++) {
00347
00348 PortComponentDesc pcd = (PortComponentDesc) pcdl.get(j);
00349 String sibLink = pcd.getSibLink();
00350
00351
00352 if (pcd.hasBeanImpl()) {
00353 SessionStatelessDesc desc = getBeanDesc(url.getFile(), sibLink, jarCL, earCL);
00354 pcd.setDesc(desc);
00355
00356 } else if (pcd.hasJaxRpcImpl()) {
00357 WebContainerDeploymentDesc desc = getWebDesc(url.getFile(), sibLink, jarCL, earCL);
00358 pcd.setDesc(desc);
00359
00360 }
00361 }
00362 }
00363
00364 return wsdd;
00365 }
00366
00377 private static WSDeploymentDesc loadDeploymentDesc(URL url, ClassLoader cl) throws WSDeploymentDescException {
00378
00379 URLClassLoader ucl = (URLClassLoader) cl;
00380
00381
00382 InputStream isWebservices = null;
00383
00384
00385 InputStream isJonasWebservices = null;
00386
00387 URL wsXml = null;
00388 URL jwsXml = null;
00389
00390 try {
00391
00392 boolean foundInEjb = false;
00393 for (Enumeration ejbWebservices = ucl.findResources("META-INF/webservices.xml"); ejbWebservices
00394 .hasMoreElements()
00395 && !foundInEjb;) {
00396 wsXml = (URL) ejbWebservices.nextElement();
00397 if (isResourceInFile(url, wsXml)) {
00398 foundInEjb = true;
00399 }
00400 }
00401
00402
00403 if (foundInEjb) {
00404 isWebservices = openInputStream(wsXml);
00405
00406 foundInEjb = false;
00407
00408 for (Enumeration ejbJonasWebservices = ucl.findResources("META-INF/jonas-webservices.xml"); ejbJonasWebservices
00409 .hasMoreElements()
00410 && !foundInEjb;) {
00411 jwsXml = (URL) ejbJonasWebservices.nextElement();
00412 if (isResourceInFile(url, jwsXml)) {
00413 foundInEjb = true;
00414 }
00415 }
00416 if (foundInEjb) {
00417 isJonasWebservices = openInputStream(jwsXml);
00418
00419 }
00420 }
00421
00422 boolean foundInWeb = false;
00423 for (Enumeration webWebservices = ucl.findResources("WEB-INF/webservices.xml"); webWebservices
00424 .hasMoreElements()
00425 && !foundInWeb;) {
00426 wsXml = (URL) webWebservices.nextElement();
00427 if (isResourceInFile(url, wsXml)) {
00428 foundInWeb = true;
00429 }
00430 }
00431
00432
00433 if (foundInWeb) {
00434 isWebservices = openInputStream(wsXml);
00435
00436 foundInWeb = false;
00437
00438 for (Enumeration webJonasWebservices = ucl.findResources("WEB-INF/jonas-webservices.xml"); webJonasWebservices
00439 .hasMoreElements()
00440 && !foundInWeb;) {
00441 jwsXml = (URL) webJonasWebservices.nextElement();
00442 if (isResourceInFile(url, jwsXml)) {
00443 foundInWeb = true;
00444 }
00445 }
00446 if (foundInWeb) {
00447 isJonasWebservices = openInputStream(jwsXml);
00448 }
00449 }
00450 } catch (IOException ioe) {
00451 String err = "Cannot open Streams on WebServices Deployment Descriptor for '" + url + "'";
00452 throw new WSDeploymentDescException(err, ioe);
00453 }
00454
00455
00456 if (isWebservices == null) {
00457 return null;
00458 }
00459
00460
00461 Webservices webservices = loadWebservices(new InputStreamReader(isWebservices), wsXml.getFile());
00462 JonasWebservices jonasWebservices = null;
00463
00464 if (isJonasWebservices != null) {
00465 jonasWebservices = loadJonasWebservices(new InputStreamReader(isJonasWebservices), jwsXml.getFile());
00466 }
00467
00468 try {
00469 if (isWebservices != null) {
00470 isWebservices.close();
00471 }
00472 if (isJonasWebservices != null) {
00473 isJonasWebservices.close();
00474 }
00475 } catch (IOException ioe) {
00476
00477 String err = "Cannot close InputStreams for '" + url + "'";
00478 logger.log(BasicLevel.WARN, err);
00479 }
00480
00481
00482 WSDeploymentDesc wsdd = new WSDeploymentDesc(cl, logger, webservices, jonasWebservices);
00483
00484 return wsdd;
00485
00486 }
00487
00493 private static InputStream openInputStream(URL xml) throws IOException {
00494 URLConnection conn = xml.openConnection();
00495 conn.setUseCaches(false);
00496 conn.setDefaultUseCaches(false);
00497 InputStream is = conn.getInputStream();
00498
00499 return is;
00500 }
00501
00508 private static boolean isResourceInFile(URL file, URL resource) {
00509
00510 boolean within = false;
00511
00512 File f = new File(file.getFile());
00513 if (f.isDirectory()) {
00514
00515
00516
00517 if (resource.toString().startsWith(file.toString())) {
00518 within = true;
00519 logger.log(BasicLevel.DEBUG, "Directory case. found '" + resource + "' in '" + file + "'");
00520 }
00521 } else if (f.isFile()) {
00522 if (f.getPath().endsWith(".xml")) {
00523
00524
00525
00526 if (file.equals(resource)) {
00527 within = true;
00528 logger.log(BasicLevel.DEBUG, "XML case. found '" + resource + "' in '" + file + "'");
00529 }
00530 } else if ((f.getPath().endsWith(".war")) || (f.getPath().endsWith(".jar"))) {
00531
00532
00533
00534 int index = resource.toString().indexOf("!/");
00535 if (index != -1) {
00536 if (resource.toString().startsWith(("jar:" + file.toString()))) {
00537 within = true;
00538 logger.log(BasicLevel.DEBUG, "Archive case. found '" + resource + "' in '" + file + "'");
00539 }
00540 }
00541 }
00542 }
00543 return within;
00544 }
00545
00554 public static Webservices loadWebservices(Reader reader, String fileName) throws WSDeploymentDescException {
00555
00556 Webservices ws = new Webservices();
00557
00558
00559 if (wsDigester == null) {
00560 try {
00561
00562 wsDigester = new JDigester(wsRuleSet, getParsingWithValidation(), true, null, new WsSchemas());
00563 } catch (DeploymentDescException e) {
00564 throw new WSDeploymentDescException(e);
00565 }
00566 }
00567
00568 try {
00569 wsDigester.parse(reader, fileName, ws);
00570 } catch (DeploymentDescException e) {
00571 throw new WSDeploymentDescException(e);
00572 } finally {
00573 wsDigester.push(null);
00574 }
00575
00576 return ws;
00577 }
00578
00587 public static JonasWebservices loadJonasWebservices(Reader reader, String fileName)
00588 throws WSDeploymentDescException {
00589
00590 JonasWebservices jws = new JonasWebservices();
00591
00592
00593 if (jwsDigester == null) {
00594 try {
00595
00596 jwsDigester = new JDigester(jwsRuleSet, getParsingWithValidation(), true, null, new JonasWsSchemas());
00597 } catch (DeploymentDescException e) {
00598 throw new WSDeploymentDescException(e);
00599 }
00600 }
00601
00602 try {
00603 jwsDigester.parse(reader, fileName, jws);
00604 } catch (DeploymentDescException e) {
00605 throw new WSDeploymentDescException(e);
00606 } finally {
00607 jwsDigester.push(null);
00608 }
00609
00610 return jws;
00611
00612 }
00613
00619 public int getCacheSize() {
00620 return urlWsddBindings.size();
00621
00622 }
00623
00627 public void clearCache() {
00628 urlWsddBindings = new HashMap();
00629 }
00630
00635 public void removeCache(ClassLoader cl) {
00636 List urls = (List) classLoader2URLs.remove(cl);
00637 if (urls != null) {
00638 for (Iterator i = urls.iterator(); i.hasNext();) {
00639 URL url = (URL) i.next();
00640 urlWsddBindings.remove(url);
00641 }
00642 }
00643 }
00644
00649 public String toString() {
00650 return "" + getCacheSize();
00651
00652 }
00653
00664 private static SessionStatelessDesc getBeanDesc(String filename, String link, ClassLoader cl)
00665 throws WSDeploymentDescException {
00666
00667 BeanDesc bd = null;
00668
00669 try {
00670
00671
00672
00673
00674
00675 DeploymentDesc dd = org.objectweb.jonas_ejb.deployment.lib.EjbDeploymentDescManager.getDeploymentDesc(
00676 filename, cl);
00677 bd = dd.getBeanDesc(link);
00678
00679 } catch (DeploymentDescException dde) {
00680 throw new WSDeploymentDescException("DeploymentDescException when searching '" + link + "' in '" + filename
00681 + "'", dde);
00682 }
00683
00684 if (bd == null) {
00685 throw new WSDeploymentDescException("Unable to find the ejb-link '" + link + "' in '" + filename + "'");
00686 }
00687
00688 if (!(bd instanceof SessionStatelessDesc)) {
00689 throw new WSDeploymentDescException("ejb-link '" + link + "' must be a Stateless Session Bean not a '"
00690 + bd.getClass().getName() + "'");
00691 }
00692
00693 return (SessionStatelessDesc) bd;
00694
00695 }
00696
00708 private SessionStatelessDesc getBeanDesc(String filename, String link, ClassLoader jarCL, ClassLoader earCL)
00709 throws WSDeploymentDescException {
00710 URL url;
00711
00712 try {
00713 url = new File(filename).toURL();
00714
00715 } catch (MalformedURLException mue) {
00716 throw new WSDeploymentDescException("Url Error with '" + filename + "'", mue);
00717 }
00718
00719 BeanDesc bd = null;
00720
00721 try {
00722 DeploymentDesc dd = ejbManager.getDeploymentDesc(url, jarCL, earCL);
00723 bd = dd.getBeanDesc(link);
00724
00725 } catch (DeploymentDescException dde) {
00726 throw new WSDeploymentDescException("Unable to load EjbJar '" + url + "'", dde);
00727 }
00728
00729
00730 if (bd == null) {
00731 throw new WSDeploymentDescException("Unable to find the ejb-link '" + link + "' in '" + filename + "'");
00732 }
00733
00734 if (!(bd instanceof SessionStatelessDesc)) {
00735 throw new WSDeploymentDescException("ejb-link '" + link + "' must be a Stateless Session Bean");
00736 }
00737
00738 return (SessionStatelessDesc) bd;
00739
00740 }
00741
00751 private static WebContainerDeploymentDesc getWebDesc(String filename, String link, ClassLoader cl)
00752 throws WSDeploymentDescException {
00753
00754 WebContainerDeploymentDesc wd = null;
00755
00756 try {
00757
00758
00759
00760
00761
00762 wd = org.objectweb.jonas_web.deployment.lib.WebDeploymentDescManager.getDeploymentDesc(filename, cl);
00763 } catch (WebContainerDeploymentDescException wcdde) {
00764 throw new WSDeploymentDescException("Error while reading/parsing " + filename, wcdde);
00765 }
00766
00767
00768 if (wd.getServletClassname(link) == null) {
00769 throw new WSDeploymentDescException("Unable to find the servlet-link '" + link + "' in '" + filename + "'");
00770 }
00771
00772 return wd;
00773
00774 }
00775
00787 private WebContainerDeploymentDesc getWebDesc(String filename, String link, ClassLoader jarCL, ClassLoader earCL)
00788 throws WSDeploymentDescException {
00789
00790 URL url;
00791
00792 try {
00793 url = new File(filename).toURL();
00794 } catch (MalformedURLException mue) {
00795 throw new WSDeploymentDescException("Url Error with '" + filename + "'", mue);
00796 }
00797
00798 WebContainerDeploymentDesc wd = null;
00799
00800 try {
00801 wd = webManager.getDeploymentDesc(url, jarCL, earCL);
00802 } catch (DeploymentDescException wcdde) {
00803 throw new WSDeploymentDescException("Error while reading/parsing " + filename, wcdde);
00804 }
00805
00806
00807 if (wd.getServletClassname(link) == null) {
00808 throw new WSDeploymentDescException("Unable to find the servlet-link '" + link + "' in '" + filename + "'");
00809 }
00810
00811 return wd;
00812
00813 }
00814
00819 public static boolean getParsingWithValidation() {
00820 return parsingWithValidation;
00821 }
00822
00827 public static void setParsingWithValidation(boolean validation) {
00828 WSDeploymentDescManager.parsingWithValidation = validation;
00829 }
00830
00843 public PortComponentDesc getPortComponentDesc(URL callerURL, String portComponentLinkName, ClassLoader moduleLoader, ClassLoader earLoader)
00844 throws WSDeploymentDescException {
00845
00846
00847
00848
00849 String moduleLink = null;
00850 String pcNameLink = null;
00851 URL moduleLinkUrl = null;
00852 URLClassLoader loaderForCls = null;
00853
00854
00855
00856 if (!portComponentLinkName.matches(".*#.*")) {
00857
00858
00859 pcNameLink = portComponentLinkName;
00860
00861 moduleLinkUrl = callerURL;
00862 loaderForCls = (URLClassLoader) moduleLoader;
00863 } else {
00864
00865
00866
00867 if ((portComponentLinkName.toLowerCase().indexOf(".war" + AbsDeploymentDescManager.LINK_SEPARATOR) == -1) && (portComponentLinkName.toLowerCase().indexOf(".jar" + AbsDeploymentDescManager.LINK_SEPARATOR) == -1)) {
00868
00869 String err = "PC-link " + portComponentLinkName + " has a bad format. Correct format : filename.[jar or war]#portComponentName or just portComponentName";
00870 throw new WSDeploymentDescException(err);
00871 }
00872 StringTokenizer st = new StringTokenizer(portComponentLinkName, LINK_SEPARATOR);
00873
00874
00875
00876 if (st.countTokens() != 2 || portComponentLinkName.startsWith(AbsDeploymentDescManager.LINK_SEPARATOR)
00877 || portComponentLinkName.endsWith(AbsDeploymentDescManager.LINK_SEPARATOR)) {
00878 String err = "PC-link " + portComponentLinkName + " has a bad format. Correct format : filename.[jar or war]#portComponentName or just portComponentName";
00879 throw new WSDeploymentDescException(err);
00880 }
00881
00882
00883 moduleLink = st.nextToken();
00884 pcNameLink = st.nextToken();
00885
00886
00887
00888 try {
00889 moduleLinkUrl = new File(new File(callerURL.getFile()).getParent() + File.separator + moduleLink).getCanonicalFile().toURL();
00890 } catch (MalformedURLException mue) {
00891 String err = "Error when creating an url for the module filename. Error :" + mue.getMessage();
00892 throw new WSDeploymentDescException(err, mue);
00893 } catch (IOException ioe) {
00894 String err = "Error when creating/accessing a file. Error :" + ioe.getMessage();
00895 throw new WSDeploymentDescException(err, ioe);
00896 }
00897
00898
00899 if (!new File(moduleLinkUrl.getFile()).exists()) {
00900 String err = "Cannot get the deployment descriptor for '" + moduleLinkUrl.getFile() + "'. The file doesn't exist.";
00901 throw new WSDeploymentDescException(err);
00902 }
00903
00904 URL[] ddURL = new URL[1];
00905 ddURL[0] = moduleLinkUrl;
00906 loaderForCls = new URLClassLoader(ddURL, earLoader);
00907
00908 }
00909
00910
00911
00912 WSDeploymentDesc wsDD = null;
00913
00914 try {
00915 wsDD = getDeploymentDesc(moduleLinkUrl, loaderForCls, earLoader);
00916 } catch (DeploymentDescException e) {
00917 String err = "Cannot get the deployment descriptor for '" + moduleLinkUrl.getFile() + "'.";
00918 throw new WSDeploymentDescException(err, e);
00919 }
00920 if (wsDD == null) {
00921
00922 String err = "Port component link " + pcNameLink + " not found in " + moduleLinkUrl.getFile();
00923 throw new WSDeploymentDescException(err);
00924 }
00925
00926
00927 List sdl = wsDD.getServiceDescs();
00928 boolean isFound = false;
00929 PortComponentDesc pcd = null;
00930 for (int i = 0; (i < sdl.size()) && !isFound; i++) {
00931 if (sdl.get(i) != null) {
00932 pcd = ((ServiceDesc) sdl.get(i)).getPortComponent(pcNameLink);
00933 isFound = (pcd != null);
00934
00935 }
00936 }
00937 if (!isFound) {
00938
00939 String err = "the port component link " + pcNameLink + " doesn't exist in " + moduleLinkUrl.getFile();
00940 throw new WSDeploymentDescException(err);
00941 }
00942
00943 return pcd;
00944 }
00945 }