001: /**
002: * JOnAS : Java(TM) OpenSource Application Server
003: * Copyright (C) 1999-2004 Bull S.A.
004: * Contact: jonas-team@objectweb.org
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2.1 of the License, or any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
019: * USA
020: *
021: * --------------------------------------------------------------------------
022: * $Id: WebApp.java 9457 2006-08-24 12:58:41Z sauthieg $
023: * --------------------------------------------------------------------------
024: */package org.objectweb.jonas_lib.genbase.archive;
025:
026: import java.io.File;
027: import java.io.FileInputStream;
028: import java.io.IOException;
029: import java.io.InputStream;
030: import java.util.Hashtable;
031: import java.util.List;
032: import java.util.Map;
033: import java.util.Vector;
034: import java.util.jar.JarFile;
035:
036: import javax.xml.parsers.ParserConfigurationException;
037:
038: import org.objectweb.jonas_lib.deployment.api.DeploymentDescException;
039: import org.objectweb.jonas_lib.deployment.api.EjbRefDesc;
040: import org.objectweb.jonas_lib.files.FileUtils;
041: import org.objectweb.jonas_lib.files.FileUtilsException;
042: import org.objectweb.jonas_lib.genbase.GenBaseException;
043: import org.objectweb.jonas_lib.genbase.utils.TempRepository;
044: import org.objectweb.jonas_lib.genbase.utils.XMLUtils;
045: import org.objectweb.jonas_lib.loader.WebappClassLoader;
046: import org.objectweb.jonas_web.deployment.api.WebContainerDeploymentDesc;
047: import org.objectweb.jonas_web.deployment.lib.WebDeploymentDescManager;
048: import org.objectweb.jonas_ws.deployment.api.ServiceRefDesc;
049: import org.objectweb.jonas_ws.deployment.api.WSDeploymentDesc;
050: import org.objectweb.jonas_ws.deployment.lib.WSDeploymentDescManager;
051: import org.objectweb.jonas_ws.wsgen.WsGenException;
052: import org.objectweb.util.monolog.api.BasicLevel;
053: import org.w3c.dom.Document;
054: import org.xml.sax.SAXException;
055:
056: /**
057: * A <code>WebApp</code> is a wrapper class around a Web Archive.
058: *
059: * @author Guillaume Sauthier
060: */
061: public class WebApp extends J2EEArchive implements EjbRefModule,
062: WsClient, WsEndpoint {
063:
064: /** Application containing the webapp */
065: private Application app = null;
066:
067: /** webapp archive filename */
068: private String webFilename;
069:
070: /** Web deployment descriptor */
071: private WebContainerDeploymentDesc webDD;
072:
073: /** WebServices deployment descriptor */
074: private WSDeploymentDesc wsDD = null;
075:
076: /** service-ref list */
077: private List sRefs;
078:
079: /** web-app */
080: private Document webApp = null;
081:
082: /** jonas-web-app */
083: private Document jonasWebApp = null;
084:
085: /** webservices */
086: private Document webservices = null;
087:
088: /** jonas-webservices */
089: private Document jonasWebservices = null;
090:
091: /** context */
092: private Document context = null;
093:
094: /** webjetty */
095: private Document webjetty = null;
096:
097: /** web descriptors */
098: private Map descriptors;
099:
100: /**
101: * ejb-ref list
102: */
103: private List ejbRefs;
104:
105: /**
106: * Create an alone WebApp (not in an ear).
107: *
108: * @param archive file archive
109: *
110: * @throws GenBaseException When Init fails
111: */
112: public WebApp(Archive archive) throws GenBaseException {
113: super (archive);
114: webFilename = archive.getName();
115: if (getLogger().isLoggable(BasicLevel.DEBUG)) {
116: getLogger().log(BasicLevel.DEBUG,
117: "Wrapping '" + archive.getName() + "' in WebApp");
118: }
119: init();
120: }
121:
122: /**
123: * Create an embded WebApp.
124: *
125: * @param archive Web Archive
126: * @param app container application
127: *
128: * @throws GenBaseException When init fails
129: */
130: public WebApp(Archive archive, Application app)
131: throws GenBaseException {
132: super (archive);
133: webFilename = archive.getName();
134: setApplication(app);
135: if (getLogger().isLoggable(BasicLevel.DEBUG)) {
136: getLogger().log(BasicLevel.DEBUG,
137: "Wrapping '" + archive.getName() + "' in WebApp");
138: }
139: init();
140: }
141:
142: /**
143: * Initialize the WebApp module.
144: *
145: * @throws GenBaseException When classloader cannot be created or when
146: * decriptor loading fails.
147: */
148: private void init() throws GenBaseException {
149: // load Deployment Descs
150: loadDescriptors();
151: }
152:
153: /**
154: * Load Deployment Descriptor of a WebApp.
155: *
156: * @throws GenBaseException When descriptor cannot be parsed
157: */
158: private void loadDescriptors() throws GenBaseException {
159: try {
160: webApp = XMLUtils.newDocument(getWebInputStream(),
161: "WEB-INF/web.xml", isDTDsAllowed());
162:
163: // jonas-web.xml (optionnal)
164: InputStream is = getJonasWebInputStream();
165:
166: if (is != null) {
167: jonasWebApp = XMLUtils.newDocument(is,
168: "WEB-INF/jonas-web.xml", isDTDsAllowed());
169: }
170:
171: // webservices.xml (optionnal)
172: InputStream isWS = getWebservicesInputStream();
173:
174: if (isWS != null) {
175: webservices = XMLUtils.newDocument(isWS,
176: "WEB-INF/webservices.xml", isDTDsAllowed());
177: }
178:
179: // jonas-webservices.xml (optionnal)
180: InputStream isJWS = getJonasWebservicesInputStream();
181:
182: if (isJWS != null) {
183: jonasWebservices = XMLUtils.newDocument(isJWS,
184: "WEB-INF/jonas-webservices.xml",
185: isDTDsAllowed());
186: }
187:
188: // context.xml (optional)
189: InputStream isContext = getContextInputStream();
190: if (isContext != null) {
191: context = XMLUtils.newDocument(isContext,
192: "META-INF/context.xml", isDTDsAllowed(), false);
193: }
194:
195: //web-jetty.xml (optional)
196: InputStream isWebJetty = getWebJettyInputStream();
197: if (isWebJetty != null) {
198: // Jetty needs web-jetty.xml to have a dtd
199: webjetty = XMLUtils.newDocument(isWebJetty,
200: "WEB-INF/web-jetty.xml", true, true);
201: }
202:
203: } catch (SAXException saxe) {
204: String err = getI18n().getMessage(
205: "WebApp.loadDescriptors.parseError");
206: throw new GenBaseException(err, saxe);
207: } catch (ParserConfigurationException pce) {
208: String err = getI18n().getMessage(
209: "WebApp.loadDescriptors.prepare");
210: throw new GenBaseException(err, pce);
211: } catch (IOException ioe) {
212: String err = getI18n().getMessage(
213: "WebApp.loadDescriptors.parseError");
214: throw new GenBaseException(err, ioe);
215: }
216:
217: descriptors = new Hashtable();
218: descriptors.put("WEB-INF/web.xml", webApp);
219:
220: if (jonasWebApp != null) {
221: descriptors.put("WEB-INF/jonas-web.xml", jonasWebApp);
222: }
223:
224: if (webservices != null) {
225: descriptors.put("WEB-INF/webservices.xml", webservices);
226: }
227:
228: if (jonasWebservices != null) {
229: descriptors.put("WEB-INF/jonas-webservices.xml",
230: jonasWebservices);
231: }
232:
233: if (context != null) {
234: descriptors.put("META-INF/context.xml", context);
235: }
236:
237: if (webjetty != null) {
238: descriptors.put("WEB-INF/web-jetty.xml", webjetty);
239: }
240: }
241:
242: /**
243: * Returns the name of the Archive. Overrides J2EEArchive.getName();
244: *
245: * @see org.objectweb.jonas_lib.genbase.archive.J2EEArchive#getName()
246: *
247: * @return the name of the Archive.
248: */
249: public String getName() {
250: return webFilename;
251: }
252:
253: /**
254: * Set the container application.
255: *
256: * @param app the container application.
257: */
258: public void setApplication(Application app) {
259: this .app = app;
260: }
261:
262: /**
263: * Returns the container application (can be null).
264: *
265: * @return the container application (can be null).
266: */
267: public Application getApplication() {
268: return app;
269: }
270:
271: /**
272: * Returns the list of service-ref elements contained by a module.
273: *
274: * @return the list of service-ref elements contained by a module.
275: */
276: public List getServiceRefDescs() {
277: return sRefs;
278: }
279:
280: /**
281: * Returns the list of webservice-description elements contained by a
282: * module.
283: *
284: * @return the list of webservice-description elements contained by a
285: * module.
286: */
287: public List getServiceDescs() {
288: if (wsDD != null) {
289: return wsDD.getServiceDescs();
290: } else {
291: return new Vector();
292: }
293: }
294:
295: /**
296: * Add Archive classes.
297: *
298: * @param classes root directory containing classes.
299: */
300: public void addClasses(File classes) {
301: addDirectoryIn("WEB-INF/classes", classes);
302: }
303:
304: /**
305: * Returns the Document of the web.xml file.
306: *
307: * @return the Document of the web.xml file.
308: */
309: public Document getWebAppDoc() {
310: return webApp;
311: }
312:
313: /**
314: * Returns the Document of the jonas-web.xml file.
315: *
316: * @return the Document of the jonas-web.xml file.
317: */
318: public Document getJonasWebAppDoc() {
319: return jonasWebApp;
320: }
321:
322: /**
323: * Returns the Document of the webservices.xml file.
324: *
325: * @return the Document of the webservices.xml file.
326: */
327: public Document getWebservicesDoc() {
328: return webservices;
329: }
330:
331: /**
332: * Returns the Document of the jonas-webservices.xml file.
333: *
334: * @return the Document of the jonas-webservices.xml file.
335: */
336: public Document getJonasWebservicesDoc() {
337: return jonasWebservices;
338: }
339:
340: /**
341: * Returns a new Document of the context.xml file
342: *
343: * @return the Document of the context.xml file.
344: * @throws WsGenException if context.xml Document cannot be produced.
345: */
346: public Document newContextDoc() throws WsGenException {
347: String jonasRoot = System.getProperty("install.root");
348:
349: //Load context.xml, used by Tomcat to determine security realm to use (if any)
350: File contextTemplate = new File(new File(jonasRoot),
351: "templates" + File.separator + "wsgen" + File.separator
352: + "context.xml");
353:
354: try {
355: context = XMLUtils.newDocument(new FileInputStream(
356: contextTemplate), "META-INF/context.xml", true);
357: } catch (Exception e) {
358: e.printStackTrace();
359: throw new WsGenException("Cannot load '" + contextTemplate
360: + "'", e);
361: }
362:
363: // save the context in the descriptor Map
364: descriptors.put("META-INF/context.xml", context);
365:
366: return context;
367: }
368:
369: /**
370: * Returns a new Document of the web-jetty.xml file
371: *
372: * @return the document of the web-jetty.xml file
373: * @throws WsGenException if context.xml Document cannot be produced.
374: */
375: public Document newWebJettyDoc() throws WsGenException {
376: String jonasRoot = System.getProperty("install.root");
377:
378: //Load web-jetty.xml, used by Jetty to determine security realm to use (if any)
379: File webjettyTemplate = new File(new File(jonasRoot),
380: "templates" + File.separator + "wsgen" + File.separator
381: + "web-jetty.xml");
382:
383: try {
384: webjetty = XMLUtils.newDocument(new FileInputStream(
385: webjettyTemplate), "WEB-INF/web-jetty.xml", true);
386: } catch (Exception e) {
387: e.printStackTrace();
388: throw new WsGenException("Cannot load '" + webjettyTemplate
389: + "'", e);
390: }
391:
392: // save the web-jetty in the descriptor Map
393: descriptors.put("WEB-INF/web-jetty.xml", webjetty);
394:
395: return webjetty;
396: }
397:
398: /**
399: * Returns the Document of the context.xml file
400: *
401: * @return the Document of the context.xml file.
402: */
403: public Document getContextDoc() {
404: return context;
405: }
406:
407: /**
408: * Returns the Document of the web-=jetty.xml file
409: *
410: * @return the document of the web-jetty.xml file
411: */
412: public Document getWebJettyDoc() {
413: return webjetty;
414: }
415:
416: /**
417: * Returns the InputStream of the web.xml file.
418: *
419: * @return the InputStream of the web.xml file.
420: *
421: * @throws IOException When InputStream cannot be returned.
422: */
423: private InputStream getWebInputStream() throws IOException {
424: InputStream is = null;
425:
426: if (isPacked()) {
427: is = getInputStream("WEB-INF/web.xml");
428: } else {
429: is = getInputStream("WEB-INF" + File.separator + "web.xml");
430: }
431:
432: return is;
433: }
434:
435: /**
436: * Returns the InputStream of the jonas-web.xml file.
437: *
438: * @return the InputStream of the jonas-web.xml file.
439: *
440: * @throws IOException When InputStream cannot be returned.
441: */
442: private InputStream getJonasWebInputStream() throws IOException {
443: InputStream is = null;
444:
445: if (isPacked()) {
446: is = getInputStream("WEB-INF/jonas-web.xml");
447: } else {
448: is = getInputStream("WEB-INF" + File.separator
449: + "jonas-web.xml");
450: }
451:
452: return is;
453: }
454:
455: /**
456: * Returns the InputStream of the webservices.xml file.
457: *
458: * @return the InputStream of the webservices.xml file.
459: *
460: * @throws IOException When InputStream cannot be returned.
461: */
462: private InputStream getWebservicesInputStream() throws IOException {
463: InputStream is = null;
464:
465: if (isPacked()) {
466: is = getInputStream("WEB-INF/webservices.xml");
467: } else {
468: is = getInputStream("WEB-INF" + File.separator
469: + "webservices.xml");
470: }
471:
472: return is;
473: }
474:
475: /**
476: * Returns the InputStream of the jonas-webservices.xml file.
477: *
478: * @return the InputStream of the jonas-webservices.xml file.
479: *
480: * @throws IOException When InputStream cannot be returned.
481: */
482: private InputStream getJonasWebservicesInputStream()
483: throws IOException {
484: InputStream is = null;
485:
486: if (isPacked()) {
487: is = getInputStream("WEB-INF/jonas-webservices.xml");
488: } else {
489: is = getInputStream("WEB-INF" + File.separator
490: + "jonas-webservices.xml");
491: }
492:
493: return is;
494: }
495:
496: /**
497: * Returns the InputStream of the context.xml file.
498: *
499: * @return the InputStream of the context.xml file.
500: * @throws IOException When InputStream cannot be returned
501: */
502: private InputStream getContextInputStream() throws IOException {
503: InputStream is = null;
504: if (isPacked()) {
505: is = getInputStream("META-INF/context.xml");
506: } else {
507: is = getInputStream("META-INF" + File.separator
508: + "context.xml");
509: }
510:
511: return is;
512: }
513:
514: /**
515: * Returns the InputStream of the web-jetty.xml file
516: *
517: * @return the InputStream of the web-jetty.xml file
518: * @throws IOException When InputStream cannot be returned
519: */
520: private InputStream getWebJettyInputStream() throws IOException {
521: InputStream is = null;
522: if (isPacked()) {
523: is = getInputStream("WEB-INF/web-jetty.xml");
524: } else {
525: is = getInputStream("WEB-INF" + File.separator
526: + "web-jetty.xml");
527: }
528:
529: return is;
530: }
531:
532: /**
533: * Returns a Map of name to Document for each modified Descriptor of the
534: * archive.
535: *
536: * @return a Map of name to Document
537: */
538: public Map getDescriptors() {
539: return descriptors;
540: }
541:
542: /**
543: * Returns true if filename must be omitted in the archive.
544: *
545: * @param name filename to be tested
546: *
547: * @return true if filename must be omitted.
548: */
549: public boolean omit(String name) {
550: return (name.equals("WEB-INF/web.xml")
551: || name.equals("WEB-INF\\web.xml")
552: || name.equals("WEB-INF/jonas-web.xml")
553: || name.equals("WEB-INF\\jonas-web.xml")
554: || name.equals("WEB-INF/webservices.xml")
555: || name.equals("WEB-INF\\webservices.xml")
556: || name.equals("WEB-INF/jonas-webservices.xml")
557: || name.equals("WEB-INF\\jonas-webservices.xml")
558: || name.equals("META-INF/context.xml")
559: || name.equals("META-INF\\context.xml")
560: || name.equals("WEB-INF/web-jetty.xml") || name
561: .equals("WEB-INF\\web-jetty.xml"));
562: }
563:
564: /**
565: * Initialize the Archive.
566: * @throws GenBaseException When initialization fails.
567: */
568: public void initialize() throws GenBaseException {
569: File webappUnpackDir = getRootFile();
570: try {
571:
572: if (getArchive().isPacked()) {
573: JarFile jf = new JarFile(getRootFile());
574: TempRepository tr = TempRepository.getInstance();
575: webappUnpackDir = tr.createDir();
576: FileUtils.unpack(jf, webappUnpackDir);
577: jf.close();
578: setArchive(new FileArchive(webappUnpackDir));
579: }
580:
581: if (app == null) {
582: // simple webapp case
583: setModuleClassloader(new WebappClassLoader(
584: webappUnpackDir.toURL(), Thread.currentThread()
585: .getContextClassLoader()));
586: } else {
587: // embedded webapp case
588: setModuleClassloader(new WebappClassLoader(
589: webappUnpackDir.toURL(), app
590: .getEJBClassLoader()));
591: }
592: } catch (IOException ioe) {
593: String err = getI18n().getMessage("WebApp.init.loader",
594: getArchive().getRootFile());
595: throw new GenBaseException(err, ioe);
596: } catch (FileUtilsException fue) {
597: String err = getI18n().getMessage("WebApp.init.loader",
598: getArchive().getRootFile());
599: throw new GenBaseException(err, fue);
600: }
601:
602: try {
603: webDD = WebDeploymentDescManager.getDeploymentDesc(
604: webappUnpackDir.getAbsolutePath(),
605: getModuleClassloader());
606: } catch (DeploymentDescException dde) {
607: throw new GenBaseException(dde);
608: }
609:
610: try {
611: wsDD = WSDeploymentDescManager.getDeploymentDesc(
612: webappUnpackDir.getAbsolutePath(),
613: getModuleClassloader());
614: } catch (DeploymentDescException dde) {
615: throw new GenBaseException(dde);
616: }
617:
618: // we want a List of service-ref
619: sRefs = new Vector();
620:
621: ServiceRefDesc[] refs = webDD.getServiceRefDesc();
622:
623: for (int i = 0; i < refs.length; i++) {
624: sRefs.add(refs[i]);
625: }
626:
627: // List of ejb-refs
628: ejbRefs = new Vector();
629: EjbRefDesc[] refDesc = webDD.getEjbRefDesc();
630:
631: for (int i = 0; i < refDesc.length; i++) {
632: ejbRefs.add(refDesc[i]);
633: }
634:
635: }
636:
637: /**
638: * @return Returns the context-root to use for this group of Services.
639: */
640: public String getContextRoot() {
641: return this .wsDD.getContextRoot();
642: }
643:
644: /**
645: * Returns the list of ejb-ref elements contained by a module.
646: * @return the list of ejb-ref elements contained by a module.
647: */
648: public List getEjbRefDescs() {
649: return ejbRefs;
650: }
651:
652: /**
653: * Close this archive
654: */
655: public void close() {
656: sRefs = null;
657: ejbRefs = null;
658: webDD = null;
659: wsDD = null;
660: webApp = null;
661: app = null;
662: descriptors = null;
663: jonasWebApp = null;
664: webFilename = null;
665: webservices = null;
666: jonasWebservices = null;
667: context = null;
668: webjetty = null;
669: }
670: }
|