001: /**
002: * The Apache Software License, Version 1.1
003: *
004: * Copyright (c) 2002 The Apache Software Foundation. All rights
005: * reserved.
006: *
007: * Redistribution and use in source and binary forms, with or without
008: * modification, are permitted provided that the following conditions
009: * are met:
010: *
011: * 1. Redistributions of source code must retain the above copyright
012: * notice, this list of conditions and the following disclaimer.
013: *
014: * 2. Redistributions in binary form must reproduce the above copyright
015: * notice, this list of conditions and the following disclaimer in
016: * the documentation and/or other materials provided with the
017: * distribution.
018: *
019: * 3. The end-user documentation included with the redistribution, if
020: * any, must include the following acknowlegement:
021: * "This product includes software developed by the
022: * Apache Software Foundation (http://www.apache.org/)."
023: * Alternately, this acknowlegement may appear in the software itself,
024: * if and wherever such third-party acknowlegements normally appear.
025: *
026: * 4. The names "The Jakarta Project", "Ant", and "Apache Software
027: * Foundation" must not be used to endorse or promote products derived
028: * from this software without prior written permission. For written
029: * permission, please contact apache@apache.org.
030: *
031: * 5. Products derived from this software may not be called "Apache"
032: * nor may "Apache" appear in their names without prior written
033: * permission of the Apache Group.
034: *
035: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
036: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
037: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
038: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
039: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
040: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
041: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
042: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
043: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
044: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
045: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
046: * SUCH DAMAGE.
047: * ====================================================================
048: *
049: * This software consists of voluntary contributions made by many
050: * individuals on behalf of the Apache Software Foundation. For more
051: * information on the Apache Software Foundation, please see
052: * <http://www.apache.org/>.
053: */package org.objectweb.jonas.ant;
054:
055: import java.io.BufferedReader;
056: import java.io.BufferedWriter;
057: import java.io.File;
058: import java.io.FileInputStream;
059: import java.io.FileOutputStream;
060: import java.io.FileReader;
061: import java.io.FileWriter;
062: import java.io.IOException;
063: import java.io.InputStream;
064: import java.util.Hashtable;
065: import java.util.Iterator;
066: import java.util.Map;
067: import java.util.Set;
068: import java.util.jar.Attributes;
069: import java.util.jar.Manifest;
070:
071: import javax.xml.parsers.SAXParser;
072:
073: import org.apache.tools.ant.AntClassLoader;
074: import org.apache.tools.ant.BuildException;
075: import org.apache.tools.ant.Project;
076: import org.apache.tools.ant.taskdefs.Java;
077: import org.apache.tools.ant.types.Path;
078: import org.apache.tools.ant.types.Reference;
079:
080: /**
081: * The deployment tool to add the jonas specific deployment descriptors to the
082: * ejb JAR file. JONAS only requires one additional file jonas-ejb-jar.xml.
083: * @author <a href="mailto:cmorvan@ingenosya.com">Cyrille Morvan </a>, <a
084: * href="http://www.ingenosya.com">Ingenosya France </a>,
085: * Contributor(s): <a href="mailto:mathieu.peltier@inrialpes.fr">Mathieu
086: * Peltier </a> Adriana Danes: change configuration directory name from
087: * "config" to "conf"
088: * @version 1.0
089: * @see EjbJar#createJonas
090: */
091: public class JonasDeploymentTool extends GenericDeploymentTool {
092:
093: /** Public Id of the standard deployment descriptor DTD. */
094: protected static final String EJB_JAR_1_1_PUBLIC_ID = "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 1.1//EN";
095: protected static final String EJB_JAR_2_0_PUBLIC_ID = "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN";
096:
097: /** Public Id of the JOnAS-specific deployment descriptor DTD. */
098: protected static final String JONAS_EJB_JAR_2_4_PUBLIC_ID = "-//ObjectWeb//DTD JOnAS 2.4//EN";
099: protected static final String JONAS_EJB_JAR_2_5_PUBLIC_ID = "-//ObjectWeb//DTD JOnAS 2.5//EN";
100: protected static final String JONAS_EJB_JAR_3_0_PUBLIC_ID = "-//ObjectWeb//DTD JOnAS 3.0//EN";
101: protected static final String JONAS_EJB_JAR_3_2_PUBLIC_ID = "-//ObjectWeb//DTD JOnAS 3.2//EN";
102: protected static final String JONAS_EJB_JAR_3_3_PUBLIC_ID = "-//ObjectWeb//DTD JOnAS 3.3//EN";
103: protected static final String JONAS_EJB_JAR_3_3_2_PUBLIC_ID = "-//ObjectWeb//DTD JOnAS 3.3.2//EN";
104:
105: /**
106: * Name of the standard deployment descriptor DTD (these files are stored in
107: * the ${JONAS_ROOT}/xml directory).
108: */
109: protected static final String EJB_JAR_1_1_DTD = "ejb-jar_1_1.dtd";
110: protected static final String EJB_JAR_2_0_DTD = "ejb-jar_2_0.dtd";
111:
112: /**
113: * Name of the JOnAS-specific deployment descriptor DTD (these files are
114: * stored in the ${JONAS_ROOT}/xml directory).
115: */
116: protected static final String JONAS_EJB_JAR_2_4_DTD = "jonas-ejb-jar_2_4.dtd";
117: protected static final String JONAS_EJB_JAR_2_5_DTD = "jonas-ejb-jar_2_5.dtd";
118: protected static final String JONAS_EJB_JAR_3_0_DTD = "jonas-ejb-jar_3_0.dtd";
119: protected static final String JONAS_EJB_JAR_3_2_DTD = "jonas-ejb-jar_3_2.dtd";
120: protected static final String JONAS_EJB_JAR_3_3_DTD = "jonas-ejb-jar_3_3.dtd";
121: protected static final String JONAS_EJB_JAR_3_3_2_DTD = "jonas-ejb-jar_3_3_2.dtd";
122:
123: /** Default JOnAS deployment descriptor name. */
124: protected static final String JONAS_DD = "jonas-ejb-jar.xml";
125:
126: /** Bootstrap class name. */
127: protected static final String BOOTSTRAP_CLASS = "org.objectweb.jonas.server.Bootstrap";
128:
129: /** GenIC class name (JOnAS 2.6). */
130: protected static final String GENIC_CLASS = "org.objectweb.jonas_ejb.genic.GenIC";
131:
132: /**
133: * Filename of the standard EJB descriptor (which is passed to this class
134: * from the parent "ejbjar" task). This file is relative to the directory
135: * specified by the "srcdir" attribute in the ejbjar task.
136: */
137: private String descriptorName;
138:
139: /**
140: * Filename of the JOnAS-specific EJB descriptor (which is passed to this
141: * class from the parent "ejbjar" task). This file is relative to the
142: * directory specified by the "srcdir" attribute in the ejbjar task.
143: */
144: private String jonasDescriptorName;
145:
146: /* ------------- */
147: /* GenIC options */
148: /* ------------- */
149:
150: /**
151: * Temporary output directory used by GenIC.
152: */
153: private File outputdir;
154:
155: /**
156: * <code>true</code> if the intermediate Java source files generated by
157: * GenIC must be deleted or not. The default is <code>false</code>
158: */
159: private boolean keepgenerated = false;
160:
161: /**
162: * If true, the JDK-provided RMIC compiler is used. If false, the built-in
163: * rmic compiler is used.
164: */
165: private boolean nofastrmic = false;
166:
167: /**
168: * <code>true</code> if the generated source files must not be compiled
169: * via the java and rmi compilers. The default is <code>false</code>.
170: */
171: private boolean nocompil = false;
172:
173: /**
174: * Equivalent to the <code>-invokecmd</code> GenIC option. The default is
175: * <code>false</code>.
176: */
177: private boolean invokeCmd = false;
178:
179: /**
180: * <code>true</code> if the XML deployment descriptors must be parsed
181: * without validation. The default is <code>false</code>.
182: */
183: private boolean novalidation = false;
184:
185: /**
186: * Java compiler to use. The default is the value of
187: * <code>build.compiler</code> property.
188: */
189: private String javac;
190:
191: /** Options to pass to the java compiler. */
192: private String javacopts;
193:
194: /** Options to pass to the rmi compiler. */
195: private String rmicopts;
196:
197: /**
198: * <code>true</code> if the GenIC call must be verbose. The default is
199: * <code>false</code>.
200: */
201: private boolean verbose = false;
202:
203: /** Additional args to send to GenIC. */
204: private String additionalargs;
205:
206: /** Additional args to pass to the GenIC JVM. */
207: private String jvmopts = null;
208:
209: /** List of protocols (used for Carol) */
210: private String protocols = null;
211:
212: /* ------------- */
213: /* other options */
214: /* ------------- */
215:
216: /** JOnAS root directory. */
217: private File jonasroot;
218:
219: /** JOnAS base directory. */
220: private File jonasbase;
221:
222: /**
223: * <code>true</code> if the generic JAR file used as input to GenIC must
224: * be retained. The default is <code>false</code>.
225: */
226: private boolean keepgeneric = false;
227:
228: /** Stores the suffix for the JOnAS JAR file. The default is '.jar'. */
229: private String suffix = ".jar";
230:
231: /**
232: * <code>true</code> if GenIC must not be run on the EJB JAR. The default
233: * is <code>false</code>.
234: */
235: private boolean nogenic = false;
236:
237: /* -------------------- */
238: /* GenIC options setter */
239: /* -------------------- */
240:
241: /**
242: * Set the {@link #keepgenerated}flag.
243: * @param aBoolean <code>true</code> if the flag must be set.
244: */
245: public void setKeepgenerated(boolean aBoolean) {
246: keepgenerated = aBoolean;
247: }
248:
249: public void setNoFastRMIC(boolean value) {
250: nofastrmic = value;
251: }
252:
253: /**
254: * Do nothing because the mappernames attribute is deprecated
255: * @param aString list of mapper names separed by ,
256: */
257: public void setMappernames(String aString) {
258: log("'mappernames' attribute ignored (deprecated)",
259: Project.MSG_WARN);
260: }
261:
262: /**
263: * Set the protocols list
264: * @param aString list of the protocol names separed by ,
265: */
266: public void setProtocols(String aString) {
267: protocols = aString;
268: }
269:
270: /**
271: * Set the classpath as a Reference on another path
272: * @param r Referenced Classpath
273: */
274: public void setClasspathref(Reference r) {
275: createClasspath().setRefid(r);
276: }
277:
278: /**
279: * Set the {@link #additionalargs}.
280: * @param aString additional args.
281: */
282: public void setAdditionalargs(String aString) {
283: additionalargs = aString;
284: }
285:
286: /**
287: * Set the {@link #nocompil}flag.
288: * @param aBoolean <code>true</code> if the flag must be set.
289: */
290: public void setNocompil(boolean aBoolean) {
291: nocompil = aBoolean;
292: }
293:
294: /**
295: * Set the {@link #invokecmd}flag.
296: * @param aBoolean <code>true</code> if the flag must be set.
297: */
298: public void setInvokecmd(boolean aBoolean) {
299: invokeCmd = aBoolean;
300: }
301:
302: /**
303: * Set the {@link #novalidation}flag.
304: * @param aBoolean <code>true</code> if the flag must be set.
305: */
306: public void setNovalidation(boolean aBoolean) {
307: novalidation = aBoolean;
308: }
309:
310: /**
311: * Set the java compiler {@link #javac}to use.
312: * @param aString the java compiler.
313: */
314: public void setJavac(String aString) {
315: javac = aString;
316: }
317:
318: /**
319: * Set the options to pass to the java compiler.
320: * @param aString the options.
321: */
322: public void setJavacopts(String aString) {
323: javacopts = aString;
324: }
325:
326: /**
327: * Set the options to pass to the rmi compiler.
328: * @param aString the options.
329: */
330: public void setRmicopts(String aString) {
331: rmicopts = aString;
332: }
333:
334: /**
335: * Set the {@link #verbose}flag.
336: * @param aBoolean <code>true</code> if the flag must be set.
337: */
338: public void setVerbose(boolean aBoolean) {
339: verbose = aBoolean;
340: }
341:
342: /* -------------------- */
343: /* other options setter */
344: /* -------------------- */
345:
346: /**
347: * Set the JOnAS root directory.
348: * @param aFile the JOnAS root directory.
349: */
350: public void setJonasroot(File aFile) {
351: jonasroot = aFile;
352: }
353:
354: /**
355: * Set the JOnAS base directory.
356: * @param aFile the JOnAS base directory.
357: */
358: public void setJonasbase(File aFile) {
359: jonasbase = aFile;
360: }
361:
362: /**
363: * Set the {@link #keepgeneric}flag.
364: * @param aBoolean <code>true</code> if the flag must be set.
365: */
366: public void setKeepgeneric(boolean aBoolean) {
367: keepgeneric = aBoolean;
368: }
369:
370: /**
371: * Set the {@link #jarsuffix}.
372: * @param aString the string to use as the suffix.
373: */
374: public void setJarsuffix(String aString) {
375: suffix = aString;
376: }
377:
378: /**
379: * Set the {@link #nogenic}flag.
380: * @param aBoolean <code>true</code> if the flag must be set.
381: */
382: public void setNogenic(boolean aBoolean) {
383: nogenic = aBoolean;
384: }
385:
386: /**
387: * Set the additional args to pass to the GenIC JVM.
388: * @param aString the options.
389: */
390: public void setJvmopts(String aString) {
391: jvmopts = aString;
392: }
393:
394: /* ------------- */
395: /* other methods */
396: /* ------------- */
397:
398: public void processDescriptor(String aDescriptorName,
399: SAXParser saxParser) {
400:
401: descriptorName = aDescriptorName;
402:
403: log("JOnAS Deployment Tool processing for JOnAS: "
404: + descriptorName, Project.MSG_VERBOSE);
405:
406: super .processDescriptor(descriptorName, saxParser);
407:
408: if (outputdir != null) {
409: // the method deleteOnExit() do not work because the directory is
410: // not empty
411: log("Deleting temp output directory '" + outputdir + "'.",
412: Project.MSG_VERBOSE);
413: JOnASAntTool.deleteAllFiles(outputdir);
414: }
415: }
416:
417: protected void writeJar(String baseName, File jarfile,
418: Hashtable ejbFiles, String publicId,
419: boolean includeInnerClasses) throws BuildException {
420:
421: // create the generic jar first
422: File genericJarFile = super .getVendorOutputJarFile(baseName);
423:
424: super .writeJar(baseName, genericJarFile, ejbFiles, publicId,
425: true);
426:
427: // GenIC call on generic jar
428: addGenICGeneratedFiles(genericJarFile, ejbFiles);
429:
430: // merge Manifest give by user if exist with this generated by Genic
431: if (this .getConfig() != null
432: && this .getConfig().manifest != null
433: && this .getConfig().manifest.exists()) {
434: File filePathGenicManifest = (File) ejbFiles
435: .get("META-INF/MANIFEST.MF");
436: if (filePathGenicManifest != null)
437: mergeManifest(this .getConfig().manifest,
438: filePathGenicManifest);
439: else
440: ejbFiles.put("META-INF/MANIFEST.MF",
441: this .getConfig().manifest);
442: }
443:
444: // create the real jar
445: super .writeJar(baseName, getVendorOutputJarFile(baseName),
446: ejbFiles, publicId, false);
447:
448: //log("genericJarFile: " + genericJarFile, Project.MSG_VERBOSE);
449: //log("getVendorOutputJarFile(baseName): " +
450: //getVendorOutputJarFile(baseName), Project.MSG_VERBOSE);
451: //log("baseName: " + baseName, Project.MSG_VERBOSE);
452:
453: if (!keepgeneric) {
454: log("Deleting generic JAR " + genericJarFile.toString(),
455: Project.MSG_VERBOSE);
456: genericJarFile.delete();
457: }
458: }
459:
460: /**
461: * Merge Manifest file
462: * @param manifestUserFile : input file
463: * @param manifestGenicFile : output file
464: */
465: protected void mergeManifest(File manifestUserFile,
466: File manifestGenicFile) {
467: try {
468: InputStream userStream = new FileInputStream(
469: manifestUserFile);
470: InputStream genICStream = new FileInputStream(
471: manifestGenicFile);
472:
473: Manifest userManifest = new Manifest(userStream);
474: Manifest genICManifest = new Manifest(genICStream);
475:
476: // close streams
477: userStream.close();
478: genICStream.close();
479:
480: // Merge main attributes
481: Attributes userMainAttributes = userManifest
482: .getMainAttributes();
483: Attributes genICMainAttributes = genICManifest
484: .getMainAttributes();
485: Iterator itUserMainAttributes = userMainAttributes.keySet()
486: .iterator();
487: while (itUserMainAttributes.hasNext()) {
488: Object name = itUserMainAttributes.next();
489: Object value = userMainAttributes.get(name);
490: genICMainAttributes.put(name, value);
491: }
492:
493: // Merge specific entries
494: Map userEntries = userManifest.getEntries();
495: Set keys = userEntries.keySet();
496: Iterator itKeys = keys.iterator();
497:
498: // Get keys of user manifest
499: while (itKeys.hasNext()) {
500: String key = (String) itKeys.next();
501: Attributes attributes = userManifest.getAttributes(key);
502: // key is present in final manifest ?
503: Attributes genICAttributes = genICManifest
504: .getAttributes(key);
505: if (genICAttributes == null) {
506: genICAttributes = new Attributes();
507: genICManifest.getEntries()
508: .put(key, genICAttributes);
509: }
510:
511: // write attributes of user manifest into genic manifest
512: Set atKeys = attributes.keySet();
513: Iterator itAt = atKeys.iterator();
514: while (itAt.hasNext()) {
515: Object name = itAt.next();
516: Object value = attributes.get(name);
517: genICAttributes.put(name, value);
518: }
519: }
520: FileOutputStream fos = new FileOutputStream(
521: manifestGenicFile);
522: genICManifest.write(fos);
523: fos.close();
524:
525: } catch (IOException e) {
526: log("Unable to update Manifest with user manifest :"
527: + e.getMessage(), Project.MSG_WARN);
528: }
529: }
530:
531: protected void addVendorFiles(Hashtable ejbFiles, String ddPrefix) {
532:
533: // JOnAS-specific descriptor deployment
534: jonasDescriptorName = getJonasDescriptorName();
535: File jonasDD = new File(getConfig().descriptorDir,
536: jonasDescriptorName);
537:
538: if (jonasDD.exists()) {
539: ejbFiles.put(META_DIR + JONAS_DD, jonasDD);
540: } else {
541: log(
542: "Unable to locate the JOnAS deployment descriptor. It was expected to be in: "
543: + jonasDD.getPath() + ".", Project.MSG_WARN);
544: }
545: }
546:
547: protected File getVendorOutputJarFile(String baseName) {
548: return new File(getDestDir(), baseName + suffix);
549: }
550:
551: /**
552: * Determines the name of the JOnAS-specific EJB descriptor using the
553: * specified standard EJB descriptor name. In general, the standard
554: * descriptor will be named "[basename]-ejb-jar.xml", and this method will
555: * return "[basename]-jonas-ejb-jar.xml" or "jonas-[basename].xml"
556: * @return The name of the JOnAS-specific EJB descriptor file.
557: */
558: private String getJonasDescriptorName() {
559:
560: // descriptorName = <path><basename><basenameterminator><remainder>
561: // examples = /org/objectweb/fooAppli/foo/Foo-ejb-jar.xml
562: // examples = /org/objectweb/fooAppli/foo/Foo.xml (JOnAS convention)
563:
564: String jonasDescriptorName; // JOnAS-specific DD
565: boolean jonasConvention = false; // true if the JOnAS convention is used
566: // for the DD
567: String path; // Directory path of the EJB descriptor
568: String fileName; // EJB descriptor file name
569: String baseName; // Filename appearing before name terminator
570: String remainder; // Filename appearing after the name terminator
571:
572: int startOfFileName = descriptorName
573: .lastIndexOf(File.separatorChar);
574: if (startOfFileName != -1) {
575: // extract path info
576: path = descriptorName.substring(0, startOfFileName + 1);
577: fileName = descriptorName.substring(startOfFileName + 1);
578: } else {
579: // descriptorName is just a file without path
580: path = "";
581: fileName = descriptorName;
582: }
583:
584: if (fileName.startsWith(EJB_DD)) {
585: return path + JONAS_DD;
586: }
587:
588: int endOfBaseName = descriptorName.indexOf(
589: getConfig().baseNameTerminator, startOfFileName);
590:
591: /*
592: * Check for the odd case where the terminator and/or filename extension
593: * aren't found. These will ensure "jonas-" appears at the end of the
594: * name and before the '.' (if present).
595: */
596: if (endOfBaseName < 0) {
597: // baseNameTerminator not found: the descriptor use the
598: // JOnAS naming convention, ie [Foo.xml,jonas-Foo.xml] and
599: // not [Foo<baseNameTerminator>-ejb-jar.xml,
600: // Foo<baseNameTerminator>-jonas-ejb-jar.xml].
601: endOfBaseName = descriptorName.lastIndexOf('.') - 1;
602: if (endOfBaseName < 0) {
603: // no . found
604: endOfBaseName = descriptorName.length() - 1;
605: }
606:
607: jonasConvention = true;
608: }
609:
610: baseName = descriptorName.substring(startOfFileName + 1,
611: endOfBaseName + 1);
612: remainder = descriptorName.substring(endOfBaseName + 1);
613:
614: if (jonasConvention) {
615: jonasDescriptorName = path + "jonas-" + baseName + ".xml";
616: } else {
617: jonasDescriptorName = path + baseName + "jonas-"
618: + remainder;
619: }
620:
621: log("Standard EJB descriptor name: " + descriptorName,
622: Project.MSG_VERBOSE);
623: log("JOnAS-specific descriptor name: " + jonasDescriptorName,
624: Project.MSG_VERBOSE);
625:
626: return jonasDescriptorName;
627: }
628:
629: protected String getJarBaseName(String descriptorFileName) {
630:
631: String baseName = null;
632:
633: if (getConfig().namingScheme.getValue().equals(
634: EjbJar.NamingScheme.DESCRIPTOR)) {
635:
636: // try to find JOnAS specific convention name
637: if (descriptorFileName
638: .indexOf(getConfig().baseNameTerminator) == -1) {
639:
640: // baseNameTerminator not found: the descriptor use the
641: // JOnAS naming convention, ie [Foo.xml,jonas-Foo.xml] and
642: // not [Foo<baseNameTerminator>-ejb-jar.xml,
643: // Foo<baseNameTerminator>-jonas-ejb-jar.xml].
644:
645: String aCanonicalDescriptor = descriptorFileName
646: .replace('\\', '/');
647: int lastSeparatorIndex = aCanonicalDescriptor
648: .lastIndexOf('/');
649: int endOfBaseName;
650:
651: if (lastSeparatorIndex != -1) {
652: endOfBaseName = descriptorFileName.indexOf(".xml",
653: lastSeparatorIndex);
654: } else {
655: endOfBaseName = descriptorFileName.indexOf(".xml");
656: }
657:
658: if (endOfBaseName != -1) {
659: baseName = descriptorFileName.substring(0,
660: endOfBaseName);
661: }
662: }
663: }
664:
665: if (baseName == null) {
666: // else get standard baseName
667: baseName = super .getJarBaseName(descriptorFileName);
668: }
669:
670: log("JAR base name: " + baseName, Project.MSG_VERBOSE);
671:
672: return baseName;
673: }
674:
675: protected void registerKnownDTDs(DescriptorHandler handler) {
676:
677: handler.registerDTD(EJB_JAR_1_1_PUBLIC_ID, jonasroot
678: + File.separator + "xml" + File.separator
679: + EJB_JAR_1_1_DTD);
680: handler.registerDTD(EJB_JAR_2_0_PUBLIC_ID, jonasroot
681: + File.separator + "xml" + File.separator
682: + EJB_JAR_2_0_DTD);
683:
684: handler.registerDTD(JONAS_EJB_JAR_2_4_PUBLIC_ID, jonasroot
685: + File.separator + "xml" + File.separator
686: + JONAS_EJB_JAR_2_4_DTD);
687: handler.registerDTD(JONAS_EJB_JAR_2_5_PUBLIC_ID, jonasroot
688: + File.separator + "xml" + File.separator
689: + JONAS_EJB_JAR_2_5_DTD);
690: handler.registerDTD(JONAS_EJB_JAR_3_0_PUBLIC_ID, jonasroot
691: + File.separator + "xml" + File.separator
692: + JONAS_EJB_JAR_3_0_DTD);
693: handler.registerDTD(JONAS_EJB_JAR_3_2_PUBLIC_ID, jonasroot
694: + File.separator + "xml" + File.separator
695: + JONAS_EJB_JAR_3_2_DTD);
696: handler.registerDTD(JONAS_EJB_JAR_3_3_PUBLIC_ID, jonasroot
697: + File.separator + "xml" + File.separator
698: + JONAS_EJB_JAR_3_3_DTD);
699: handler.registerDTD(JONAS_EJB_JAR_3_3_2_PUBLIC_ID, jonasroot
700: + File.separator + "xml" + File.separator
701: + JONAS_EJB_JAR_3_3_2_DTD);
702: }
703:
704: /**
705: * Add to the given hashtable all the file generated by GenIC.
706: * @param genericJarFile jar file.
707: * @param ejbFiles the hashtable.
708: */
709: private void addGenICGeneratedFiles(File genericJarFile,
710: Hashtable ejbFiles) {
711:
712: Java genicTask = null; // GenIC task
713:
714: if (nogenic) {
715: return;
716: }
717:
718: genicTask = (Java) getTask().getProject().createTask("java");
719: genicTask.setTaskName("genic");
720: genicTask.setFork(true);
721:
722: // jonas root
723: genicTask.createJvmarg()
724: .setValue("-Dinstall.root=" + jonasroot);
725:
726: // jonas base
727: genicTask.createJvmarg().setValue("-Djonas.base=" + jonasbase);
728:
729: // Endorsed directory
730: File endorsedDir = new File(new File(jonasroot, "lib"),
731: "endorsed");
732: genicTask.createJvmarg().setValue(
733: "-Djava.endorsed.dirs=" + endorsedDir);
734:
735: // java policy file
736: String jonasConfigDir = jonasroot + File.separator + "conf";
737: File javaPolicyFile = new File(jonasConfigDir, "java.policy");
738: if (javaPolicyFile.exists()) {
739: genicTask.createJvmarg().setValue(
740: "-Djava.security.policy="
741: + javaPolicyFile.toString());
742: }
743:
744: // The bootstrap class must launch the GenIC class
745: genicTask.createArg().setValue(JonasDeploymentTool.GENIC_CLASS);
746:
747: // outputdir
748: try {
749: outputdir = createTempDir();
750: } catch (IOException aIOException) {
751: throw new BuildException("Cannot create temp dir",
752: aIOException);
753: }
754: log("Using temporary output directory: " + outputdir,
755: Project.MSG_VERBOSE);
756:
757: genicTask.createArg().setValue("-d");
758: genicTask.createArg().setFile(outputdir);
759:
760: // classpath
761: Path classpath = getCombinedClasspath();
762: if (classpath == null) {
763: classpath = new Path(getTask().getProject());
764: }
765: // add ow_jonas_bootstrap.jar
766: String bootJar = jonasroot + File.separator + "lib"
767: + File.separator + "common" + File.separator
768: + "ow_jonas_bootstrap.jar";
769: Path bootstrap = new Path(getTask().getProject(), bootJar);
770: //classpath.append(new Path(classpath.getProject(), bootJar));
771:
772: classpath.append(new Path(classpath.getProject(), outputdir
773: .toString()));
774:
775: log("Using classpath: " + bootstrap.toString(),
776: Project.MSG_VERBOSE);
777: genicTask.setClasspath(bootstrap);
778:
779: if (!checkBootstrapClassName(bootstrap)) {
780: log("Cannot find bootstrap class in classpath.",
781: Project.MSG_ERR);
782: throw new BuildException(
783: "Bootstrap class not found, please check the classpath.");
784: } else {
785: genicTask.setClassname(JonasDeploymentTool.BOOTSTRAP_CLASS);
786: }
787:
788: // classpath
789: genicTask.createArg().setValue("-classpath");
790: genicTask.createArg().setPath(classpath);
791:
792: // keepgenerated
793: if (keepgenerated) {
794: genicTask.createArg().setValue("-keepgenerated");
795: }
796:
797: if (nofastrmic) {
798: genicTask.createArg().setValue("-nofastrmic");
799: }
800:
801: // nocompil
802: if (nocompil) {
803: genicTask.createArg().setValue("-nocompil");
804: }
805:
806: // invokecmd
807: if (invokeCmd) {
808: genicTask.createArg().setValue("-invokecmd");
809: }
810:
811: // novalidation
812: if (novalidation) {
813: genicTask.createArg().setValue("-novalidation");
814: }
815:
816: // javac
817: if (javac != null) {
818: genicTask.createArg().setValue("-javac");
819: genicTask.createArg().setLine(javac);
820: }
821:
822: // javacopts
823: if (javacopts != null && !javacopts.equals("")) {
824: genicTask.createArg().setValue("-javacopts");
825: genicTask.createArg().setValue(javacopts);
826: }
827:
828: // rmicopts
829: if (rmicopts != null && !rmicopts.equals("")) {
830: genicTask.createArg().setValue("-rmicopts");
831: genicTask.createArg().setValue(rmicopts);
832: }
833:
834: // verbose
835: if (verbose) {
836: genicTask.createArg().setValue("-verbose");
837: }
838:
839: // additionalargs
840: if (additionalargs != null) {
841: genicTask.createArg().setLine(additionalargs);
842: }
843:
844: // protocols
845: if (protocols != null) {
846: genicTask.createArg().setValue("-protocols");
847: genicTask.createArg().setValue(protocols);
848: }
849:
850: // the generated classes must not be added in the generic JAR!
851: genicTask.createArg().setValue("-noaddinjar");
852:
853: // jvmopts
854: if (jvmopts != null && !jvmopts.equals("")) {
855: genicTask.createJvmarg().setLine(jvmopts);
856: }
857:
858: // input file to process by GenIC
859: genicTask.createArg().setValue(genericJarFile.getPath());
860:
861: // calling GenIC task
862: log("Calling GenIC task for " + getConfig().descriptorDir
863: + File.separator + descriptorName + ".",
864: Project.MSG_VERBOSE);
865:
866: if (genicTask.executeJava() != 0) {
867: // Don't delete the temp output directory in case of error:
868:
869: //log("Deleting temp output directory '" + outputdir + "'.",
870: // Project.MSG_VERBOSE);
871: // the method deleteOnExit() do not work because the directory is
872: // not empty
873: //JOnASAntTool.deleteAllFiles(outputdir);
874:
875: if (!keepgeneric) {
876: log(
877: "Deleting generic JAR "
878: + genericJarFile.toString(),
879: Project.MSG_VERBOSE);
880: genericJarFile.delete();
881: }
882:
883: throw new BuildException("GenIC reported an error.");
884: }
885:
886: // add the generated files to the ejbFiles
887: addAllFiles(outputdir, "", ejbFiles);
888: }
889:
890: /**
891: * Check the bootstrap class name to use in the given classpath.
892: * @param classpath classpath where the boostrap class must be searched.
893: * @return true if the bootstrap is available in the classpath
894: */
895: private boolean checkBootstrapClassName(Path classpath) {
896: log("Looking for bootstrap class in classpath: "
897: + classpath.toString(), Project.MSG_VERBOSE);
898: AntClassLoader cl = new AntClassLoader(classpath.getProject(),
899: classpath);
900: try {
901: cl.loadClass(JonasDeploymentTool.BOOTSTRAP_CLASS);
902: log("Found Bootstrap class '"
903: + JonasDeploymentTool.BOOTSTRAP_CLASS
904: + "' in classpath.", Project.MSG_VERBOSE);
905: } catch (ClassNotFoundException cnf1) {
906: log("Bootstrap class '"
907: + JonasDeploymentTool.BOOTSTRAP_CLASS
908: + "' not found in classpath.", Project.MSG_VERBOSE);
909: return false;
910: }
911: return true;
912: }
913:
914: protected void checkConfiguration(String descriptorFileName,
915: SAXParser saxParser) throws BuildException {
916: // jonasroot
917: if (jonasroot == null) {
918: throw new BuildException(
919: "The jonasroot attribute is not set.");
920: } else if (!jonasroot.isDirectory()) {
921: throw new BuildException("The jonasroot attribute '"
922: + jonasroot + "' is not a valid directory.");
923: }
924: // jonasbase default value is jonasroot
925: if (jonasbase == null) {
926: jonasbase = jonasroot;
927: }
928:
929: // additionalargs
930: if (additionalargs != null && additionalargs.equals("")) {
931: throw new BuildException("Empty additionalargs attribute.");
932: }
933:
934: // javac
935: if (javac != null && javac.equals("")) {
936: throw new BuildException("Empty javac attribute.");
937: }
938: }
939:
940: /* ----------------------------------------------------------------------------------- */
941: /* utilitary methods */
942: /* ----------------------------------------------------------------------------------- */
943:
944: /**
945: * Create a temporary directory for GenIC output.
946: * @return the temp directory.
947: * @throws BuildException if a temp directory cannot be created.
948: */
949: private File createTempDir() throws IOException {
950: File tmpDir = File.createTempFile("genic", null, null);
951: tmpDir.delete();
952: if (!tmpDir.mkdir()) {
953: throw new IOException(
954: "Cannot create the temporary directory '" + tmpDir
955: + "'.");
956: }
957: return tmpDir;
958: }
959:
960: /**
961: * Add a file to the a given hashtable. If the file is a directory, add
962: * recursivly all the files inside to the hashtable.
963: * @param file the file to add.
964: * @param rootDir the current sub-directory to scan.
965: * @param hashtable the hashtable where to add the files.
966: */
967: private void addAllFiles(File file, String rootDir,
968: Hashtable hashtable) {
969:
970: if (!file.exists()) {
971: throw new IllegalArgumentException();
972: }
973:
974: String newRootDir;
975: if (file.isDirectory()) {
976: File[] files = file.listFiles();
977: for (int i = 0; i < files.length; i++) {
978: if (rootDir.length() > 0) {
979: newRootDir = rootDir + File.separator
980: + files[i].getName();
981: } else {
982: newRootDir = files[i].getName();
983: }
984: addAllFiles(files[i], newRootDir, hashtable);
985: }
986: } else {
987: hashtable.put(rootDir.replace(File.separatorChar, '/'),
988: file); // for a window platform replace \ by / is necessary
989: }
990: }
991: }
|