KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > tools > ant > taskdefs > optional > ejb > WeblogicDeploymentTool


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */

18 package org.apache.tools.ant.taskdefs.optional.ejb;
19
20 import java.io.File JavaDoc;
21 import java.io.FileInputStream JavaDoc;
22 import java.io.FileOutputStream JavaDoc;
23 import java.io.IOException JavaDoc;
24 import java.io.InputStream JavaDoc;
25 import java.util.Enumeration JavaDoc;
26 import java.util.Hashtable JavaDoc;
27 import java.util.Iterator JavaDoc;
28 import java.util.Vector JavaDoc;
29 import java.util.jar.JarEntry JavaDoc;
30 import java.util.jar.JarFile JavaDoc;
31 import java.util.jar.JarOutputStream JavaDoc;
32 import javax.xml.parsers.SAXParser JavaDoc;
33 import javax.xml.parsers.SAXParserFactory JavaDoc;
34 import org.apache.tools.ant.AntClassLoader;
35 import org.apache.tools.ant.BuildException;
36 import org.apache.tools.ant.Project;
37 import org.apache.tools.ant.taskdefs.Java;
38 import org.apache.tools.ant.types.Environment;
39 import org.apache.tools.ant.types.Path;
40 import org.apache.tools.ant.util.FileUtils;
41 import org.xml.sax.InputSource JavaDoc;
42
43 /**
44     The weblogic element is used to control the weblogic.ejbc compiler for
45     generating weblogic EJB jars. Prior to Ant 1.3, the method of locating CMP
46     descriptors was to use the ejbjar naming convention. So if your ejb-jar was
47     called, Customer-ejb-jar.xml, your weblogic descriptor was called Customer-
48     weblogic-ejb-jar.xml and your CMP descriptor had to be Customer-weblogic-cmp-
49     rdbms-jar.xml. In addition, the <type-storage> element in the weblogic
50     descriptor had to be set to the standard name META-INF/weblogic-cmp-rdbms-
51     jar.xml, as that is where the CMP descriptor was mapped to in the generated
52     jar.
53 */

54 public class WeblogicDeploymentTool extends GenericDeploymentTool {
55     /** EJB11 id */
56     public static final String JavaDoc PUBLICID_EJB11
57          = "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 1.1//EN";
58     /** EJB20 id */
59     public static final String JavaDoc PUBLICID_EJB20
60          = "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN";
61     /** Weblogic 5.1.0 id */
62     public static final String JavaDoc PUBLICID_WEBLOGIC_EJB510
63          = "-//BEA Systems, Inc.//DTD WebLogic 5.1.0 EJB//EN";
64     /** Weblogic 6.0.0 id */
65     public static final String JavaDoc PUBLICID_WEBLOGIC_EJB600
66          = "-//BEA Systems, Inc.//DTD WebLogic 6.0.0 EJB//EN";
67     /** Weblogic 7.0.0 id */
68     public static final String JavaDoc PUBLICID_WEBLOGIC_EJB700
69          = "-//BEA Systems, Inc.//DTD WebLogic 7.0.0 EJB//EN";
70
71     /** Weblogic 5.1 dtd location */
72     protected static final String JavaDoc DEFAULT_WL51_EJB11_DTD_LOCATION
73          = "/weblogic/ejb/deployment/xml/ejb-jar.dtd";
74     /** Weblogic 6.0 ejb 1.1 dtd location */
75     protected static final String JavaDoc DEFAULT_WL60_EJB11_DTD_LOCATION
76          = "/weblogic/ejb20/dd/xml/ejb11-jar.dtd";
77     /** Weblogic 6.0 ejb 2.0 dtd location */
78     protected static final String JavaDoc DEFAULT_WL60_EJB20_DTD_LOCATION
79          = "/weblogic/ejb20/dd/xml/ejb20-jar.dtd";
80
81     protected static final String JavaDoc DEFAULT_WL51_DTD_LOCATION
82          = "/weblogic/ejb/deployment/xml/weblogic-ejb-jar.dtd";
83     protected static final String JavaDoc DEFAULT_WL60_51_DTD_LOCATION
84          = "/weblogic/ejb20/dd/xml/weblogic510-ejb-jar.dtd";
85     protected static final String JavaDoc DEFAULT_WL60_DTD_LOCATION
86          = "/weblogic/ejb20/dd/xml/weblogic600-ejb-jar.dtd";
87     protected static final String JavaDoc DEFAULT_WL70_DTD_LOCATION
88          = "/weblogic/ejb20/dd/xml/weblogic700-ejb-jar.dtd";
89
90     protected static final String JavaDoc DEFAULT_COMPILER = "default";
91
92     protected static final String JavaDoc WL_DD = "weblogic-ejb-jar.xml";
93     protected static final String JavaDoc WL_CMP_DD = "weblogic-cmp-rdbms-jar.xml";
94
95     protected static final String JavaDoc COMPILER_EJB11 = "weblogic.ejbc";
96     protected static final String JavaDoc COMPILER_EJB20 = "weblogic.ejbc20";
97
98     /** File utilities instance for copying jars */
99     private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
100
101     /** Instance variable that stores the suffix for the weblogic jarfile. */
102     private String JavaDoc jarSuffix = ".jar";
103
104     /** Instance variable that stores the location of the weblogic DTD file. */
105     private String JavaDoc weblogicDTD;
106
107     /** Instance variable that stores the location of the ejb 1.1 DTD file. */
108     private String JavaDoc ejb11DTD;
109
110     /** Instance variable that determines whether generic ejb jars are kept. */
111     private boolean keepgenerated = false;
112
113     /**
114      * Instance variable that stores the fully qualified classname of the
115      * weblogic EJBC compiler
116      */

117     private String JavaDoc ejbcClass = null;
118
119     private String JavaDoc additionalArgs = "";
120
121     /**
122      * additional args to pass to the spawned jvm
123      */

124     private String JavaDoc additionalJvmArgs = "";
125
126     private boolean keepGeneric = false;
127
128     private String JavaDoc compiler = null;
129
130     private boolean alwaysRebuild = true;
131
132     /** controls whether ejbc is run on the generated jar */
133     private boolean noEJBC = false;
134
135     /** Indicates if the old CMP location convention is to be used. */
136     private boolean newCMP = false;
137
138     /** The classpath to the weblogic classes. */
139     private Path wlClasspath = null;
140
141     /** System properties for the JVM. */
142     private Vector JavaDoc sysprops = new Vector JavaDoc();
143
144     /**
145      * The weblogic.StdoutSeverityLevel to use when running the JVM that
146      * executes ejbc. Set to 16 to avoid the warnings about EJB Home and
147      * Remotes being in the classpath
148      */

149     private Integer JavaDoc jvmDebugLevel = null;
150
151     private File JavaDoc outputDir;
152
153     /**
154      * Add a nested sysproperty element.
155      * @param sysp the element to add.
156      */

157     public void addSysproperty(Environment.Variable sysp) {
158         sysprops.add(sysp);
159     }
160
161
162     /**
163      * Get the classpath to the weblogic classpaths.
164      * @return the classpath to configure.
165      */

166     public Path createWLClasspath() {
167         if (wlClasspath == null) {
168             wlClasspath = new Path(getTask().getProject());
169         }
170         return wlClasspath.createPath();
171     }
172
173     /**
174      * If set ejbc will use this directory as the output
175      * destination rather than a jar file. This allows for the
176      * generation of "exploded" jars.
177      * @param outputDir the directory to be used.
178      */

179     public void setOutputDir(File JavaDoc outputDir) {
180         this.outputDir = outputDir;
181     }
182
183
184     /**
185      * Optional classpath to WL6.0.
186      * Weblogic 6.0 will give a warning if the home and remote interfaces
187      * of a bean are on the system classpath used to run weblogic.ejbc.
188      * In that case, the standard weblogic classes should be set with
189      * this attribute (or equivalent nested element) and the
190      * home and remote interfaces located with the standard classpath
191      * attribute.
192      * @param wlClasspath the path to be used.
193      */

194     public void setWLClasspath(Path wlClasspath) {
195         this.wlClasspath = wlClasspath;
196     }
197
198
199     /**
200      * The compiler (switch <code>-compiler</code>) to use; optional.
201      * This allows for the selection of a different compiler
202      * to be used for the compilation of the generated Java
203      * files. This could be set, for example, to Jikes to
204      * compile with the Jikes compiler. If this is not set
205      * and the <code>build.compiler</code> property is set
206      * to jikes, the Jikes compiler will be used. If this
207      * is not desired, the value &quot;<code>default</code>&quot;
208      * may be given to use the default compiler.
209      * @param compiler the compiler to be used.
210      */

211     public void setCompiler(String JavaDoc compiler) {
212         this.compiler = compiler;
213     }
214
215
216     /**
217      * Set the rebuild flag to false to only update changes in the jar rather
218      * than rerunning ejbc; optional, default true.
219      * This flag controls whether weblogic.ejbc is always
220      * invoked to build the jar file. In certain circumstances,
221      * such as when only a bean class has been changed, the jar
222      * can be generated by merely replacing the changed classes
223      * and not rerunning ejbc. Setting this to false will reduce
224      * the time to run ejbjar.
225      * @param rebuild a <code>boolean</code> value.
226      */

227     public void setRebuild(boolean rebuild) {
228         this.alwaysRebuild = rebuild;
229     }
230
231
232     /**
233      * Sets the weblogic.StdoutSeverityLevel to use when running the JVM that
234      * executes ejbc; optional. Set to 16 to avoid the warnings about EJB Home and
235      * Remotes being in the classpath
236      * @param jvmDebugLevel the value to use.
237      */

238     public void setJvmDebugLevel(Integer JavaDoc jvmDebugLevel) {
239         this.jvmDebugLevel = jvmDebugLevel;
240     }
241
242
243     /**
244      * Get the debug level.
245      * @return the jvm debug level (may be null).
246      */

247     public Integer JavaDoc getJvmDebugLevel() {
248         return jvmDebugLevel;
249     }
250
251
252
253     /**
254      * Setter used to store the suffix for the generated weblogic jar file.
255      *
256      * @param inString the string to use as the suffix.
257      */

258     public void setSuffix(String JavaDoc inString) {
259         this.jarSuffix = inString;
260     }
261
262
263     /**
264      * controls whether the generic file used as input to
265      * ejbc is retained; defaults to false
266      *
267      * @param inValue true for keep generic
268      */

269     public void setKeepgeneric(boolean inValue) {
270         this.keepGeneric = inValue;
271     }
272
273
274     /**
275      * Controls whether weblogic will keep the generated Java
276      * files used to build the class files added to the
277      * jar. This can be useful when debugging; default is false.
278      *
279      * @param inValue either 'true' or 'false'
280      */

281     public void setKeepgenerated(String JavaDoc inValue) {
282         this.keepgenerated = Boolean.valueOf(inValue).booleanValue();
283     }
284
285
286     /**
287      * Any optional extra arguments pass to the weblogic.ejbc
288      * tool.
289      * @param args extra arguments to pass to the ejbc tool.
290      */

291     public void setArgs(String JavaDoc args) {
292         this.additionalArgs = args;
293     }
294
295
296     /**
297      * Set any additional arguments to pass to the weblogic JVM; optional.
298      * @param args the arguments to be passed to the JVM
299      */

300     public void setJvmargs(String JavaDoc args) {
301         this.additionalJvmArgs = args;
302     }
303
304     /**
305      * Set the classname of the ejbc compiler; optional
306      * Normally ejbjar determines
307      * the appropriate class based on the DTD used for the EJB. The EJB 2.0 compiler
308      * featured in weblogic 6 has, however, been deprecated in version 7. When
309      * using with version 7 this attribute should be set to
310      * &quot;weblogic.ejbc&quot; to avoid the deprecation warning.
311      * @param ejbcClass the name of the class to use.
312      */

313     public void setEjbcClass(String JavaDoc ejbcClass) {
314         this.ejbcClass = ejbcClass;
315     }
316
317
318     /**
319      * Get the ejbc compiler class.
320      * @return the name of the ejbc compiler class.
321      */

322     public String JavaDoc getEjbcClass() {
323         return ejbcClass;
324     }
325
326
327     /**
328      * <b>Deprecated</b>. Defines the location of the ejb-jar DTD in
329      * the weblogic class hierarchy. Should not be needed, and the
330      * nested &lt;dtd&gt; element is recommended when it is.
331      *
332      * @param inString the string to use as the DTD location.
333      */

334     public void setWeblogicdtd(String JavaDoc inString) {
335         setEJBdtd(inString);
336     }
337
338
339     /**
340      * <b>Deprecated</b>. Defines the location of weblogic DTD in
341      * the weblogic class hierarchy. Should not be needed, and the
342      * nested &lt;dtd&gt; element is recommended when it is.
343      *
344      * @param inString the string to use as the DTD location.
345      */

346     public void setWLdtd(String JavaDoc inString) {
347         this.weblogicDTD = inString;
348     }
349
350
351     /**
352      * <b>Deprecated</b>. Defines the location of Sun's EJB DTD in
353      * the weblogic class hierarchy. Should not be needed, and the
354      * nested &lt;dtd&gt; element is recommended when it is.
355      *
356      * @param inString the string to use as the DTD location.
357      */

358     public void setEJBdtd(String JavaDoc inString) {
359         this.ejb11DTD = inString;
360     }
361
362
363     /**
364      * Set the value of the oldCMP scheme. This is an antonym for newCMP
365      * @ant.attribute ignore="true'
366      * @param oldCMP a <code>boolean</code> value.
367      */

368     public void setOldCMP(boolean oldCMP) {
369         this.newCMP = !oldCMP;
370     }
371
372
373     /**
374      * If this is set to true, the new method for locating
375      * CMP descriptors will be used; optional, default false.
376      * <P>
377      * The old CMP scheme locates the
378      * weblogic CMP descriptor based on the naming convention where the
379      * weblogic CMP file is expected to be named with the bean name as the
380      * prefix. Under this scheme the name of the CMP descriptor does not match
381      * the name actually used in the main weblogic EJB descriptor. Also,
382      * descriptors which contain multiple CMP references could not be used.
383      * @param newCMP a <code>boolean</code> value.
384      */

385     public void setNewCMP(boolean newCMP) {
386         this.newCMP = newCMP;
387     }
388
389
390     /**
391      * Do not EJBC the jar after it has been put together;
392      * optional, default false
393      * @param noEJBC a <code>boolean</code> value.
394      */

395     public void setNoEJBC(boolean noEJBC) {
396         this.noEJBC = noEJBC;
397     }
398
399
400     /**
401      * Register the DTDs.
402      * @param handler the handler to use.
403      */

404     protected void registerKnownDTDs(DescriptorHandler handler) {
405         // register all the known DTDs
406
handler.registerDTD(PUBLICID_EJB11, DEFAULT_WL51_EJB11_DTD_LOCATION);
407         handler.registerDTD(PUBLICID_EJB11, DEFAULT_WL60_EJB11_DTD_LOCATION);
408         handler.registerDTD(PUBLICID_EJB11, ejb11DTD);
409         handler.registerDTD(PUBLICID_EJB20, DEFAULT_WL60_EJB20_DTD_LOCATION);
410     }
411
412
413     /**
414      * Get the weblogic descriptor handler.
415      * @param srcDir the source directory.
416      * @return the descriptor.
417      */

418     protected DescriptorHandler getWeblogicDescriptorHandler(final File JavaDoc srcDir) {
419         DescriptorHandler handler =
420             new DescriptorHandler(getTask(), srcDir) {
421                 protected void processElement() {
422                     if (currentElement.equals("type-storage")) {
423                         // Get the filename of vendor specific descriptor
424
String JavaDoc fileNameWithMETA = currentText;
425                         //trim the META_INF\ off of the file name
426
String JavaDoc fileName
427                              = fileNameWithMETA.substring(META_DIR.length(),
428                             fileNameWithMETA.length());
429                         File JavaDoc descriptorFile = new File JavaDoc(srcDir, fileName);
430
431                         ejbFiles.put(fileNameWithMETA, descriptorFile);
432                     }
433                 }
434             };
435
436         handler.registerDTD(PUBLICID_WEBLOGIC_EJB510, DEFAULT_WL51_DTD_LOCATION);
437         handler.registerDTD(PUBLICID_WEBLOGIC_EJB510, DEFAULT_WL60_51_DTD_LOCATION);
438         handler.registerDTD(PUBLICID_WEBLOGIC_EJB600, DEFAULT_WL60_DTD_LOCATION);
439         handler.registerDTD(PUBLICID_WEBLOGIC_EJB700, DEFAULT_WL70_DTD_LOCATION);
440         handler.registerDTD(PUBLICID_WEBLOGIC_EJB510, weblogicDTD);
441         handler.registerDTD(PUBLICID_WEBLOGIC_EJB600, weblogicDTD);
442
443         for (Iterator JavaDoc i = getConfig().dtdLocations.iterator(); i.hasNext();) {
444             EjbJar.DTDLocation dtdLocation = (EjbJar.DTDLocation) i.next();
445
446             handler.registerDTD(dtdLocation.getPublicId(), dtdLocation.getLocation());
447         }
448         return handler;
449     }
450
451
452     /**
453      * Add any vendor specific files which should be included in the EJB Jar.
454      * @param ejbFiles the hash table to be populated.
455      * @param ddPrefix the prefix to use.
456      */

457     protected void addVendorFiles(Hashtable JavaDoc ejbFiles, String JavaDoc ddPrefix) {
458         File JavaDoc weblogicDD = new File JavaDoc(getConfig().descriptorDir, ddPrefix + WL_DD);
459
460         if (weblogicDD.exists()) {
461             ejbFiles.put(META_DIR + WL_DD,
462                 weblogicDD);
463         } else {
464             log("Unable to locate weblogic deployment descriptor. "
465                 + "It was expected to be in "
466                 + weblogicDD.getPath(), Project.MSG_WARN);
467             return;
468         }
469
470         if (!newCMP) {
471             log("The old method for locating CMP files has been DEPRECATED.", Project.MSG_VERBOSE);
472             log("Please adjust your weblogic descriptor and set "
473                 + "newCMP=\"true\" to use the new CMP descriptor "
474                 + "inclusion mechanism. ", Project.MSG_VERBOSE);
475             // The the weblogic cmp deployment descriptor
476
File JavaDoc weblogicCMPDD = new File JavaDoc(getConfig().descriptorDir, ddPrefix + WL_CMP_DD);
477
478             if (weblogicCMPDD.exists()) {
479                 ejbFiles.put(META_DIR + WL_CMP_DD,
480                     weblogicCMPDD);
481             }
482         } else {
483             // now that we have the weblogic descriptor, we parse the file
484
// to find other descriptors needed to deploy the bean.
485
// this could be the weblogic-cmp-rdbms.xml or any other O/R
486
// mapping tool descriptors.
487
try {
488                 File JavaDoc ejbDescriptor = (File JavaDoc) ejbFiles.get(META_DIR + EJB_DD);
489                 SAXParserFactory JavaDoc saxParserFactory = SAXParserFactory.newInstance();
490
491                 saxParserFactory.setValidating(true);
492
493                 SAXParser JavaDoc saxParser = saxParserFactory.newSAXParser();
494                 DescriptorHandler handler
495                     = getWeblogicDescriptorHandler(ejbDescriptor.getParentFile());
496
497                 saxParser.parse(new InputSource JavaDoc
498                     (new FileInputStream JavaDoc(weblogicDD)),
499                         handler);
500
501                 Hashtable JavaDoc ht = handler.getFiles();
502                 Enumeration JavaDoc e = ht.keys();
503
504                 while (e.hasMoreElements()) {
505                     String JavaDoc key = (String JavaDoc) e.nextElement();
506
507                     ejbFiles.put(key, ht.get(key));
508                 }
509             } catch (Exception JavaDoc e) {
510                 String JavaDoc msg = "Exception while adding Vendor specific files: " + e.toString();
511
512                 throw new BuildException(msg, e);
513             }
514         }
515     }
516
517
518     /**
519      * Get the vendor specific name of the Jar that will be output. The
520      * modification date of this jar will be checked against the dependent
521      * bean classes.
522      */

523     File JavaDoc getVendorOutputJarFile(String JavaDoc baseName) {
524         return new File JavaDoc(getDestDir(), baseName + jarSuffix);
525     }
526
527
528     /**
529      * Helper method invoked by execute() for each WebLogic jar to be built.
530      * Encapsulates the logic of constructing a java task for calling
531      * weblogic.ejbc and executing it.
532      *
533      * @param sourceJar java.io.File representing the source (EJB1.1) jarfile.
534      * @param destJar java.io.File representing the destination, WebLogic
535      * jarfile.
536      */

537     private void buildWeblogicJar(File JavaDoc sourceJar, File JavaDoc destJar, String JavaDoc publicId) {
538         Java javaTask = null;
539
540         if (noEJBC) {
541             try {
542                 FILE_UTILS.copyFile(sourceJar, destJar);
543                 if (!keepgenerated) {
544                     sourceJar.delete();
545                 }
546                 return;
547             } catch (IOException JavaDoc e) {
548                 throw new BuildException("Unable to write EJB jar", e);
549             }
550         }
551
552         String JavaDoc ejbcClassName = ejbcClass;
553
554         try {
555             javaTask = new Java(getTask());
556             javaTask.setTaskName("ejbc");
557
558             javaTask.createJvmarg().setLine(additionalJvmArgs);
559             if (!(sysprops.isEmpty())) {
560                 for (Enumeration JavaDoc en = sysprops.elements(); en.hasMoreElements();) {
561                     Environment.Variable entry
562                         = (Environment.Variable) en.nextElement();
563                     javaTask.addSysproperty(entry);
564                 }
565             }
566
567             if (getJvmDebugLevel() != null) {
568                 javaTask.createJvmarg().setLine(" -Dweblogic.StdoutSeverityLevel=" + jvmDebugLevel);
569             }
570
571             if (ejbcClassName == null) {
572                 // try to determine it from publicId
573
if (PUBLICID_EJB11.equals(publicId)) {
574                     ejbcClassName = COMPILER_EJB11;
575                 } else if (PUBLICID_EJB20.equals(publicId)) {
576                     ejbcClassName = COMPILER_EJB20;
577                 } else {
578                     log("Unrecognized publicId " + publicId
579                         + " - using EJB 1.1 compiler", Project.MSG_WARN);
580                     ejbcClassName = COMPILER_EJB11;
581                 }
582             }
583
584             javaTask.setClassname(ejbcClassName);
585             javaTask.createArg().setLine(additionalArgs);
586             if (keepgenerated) {
587                 javaTask.createArg().setValue("-keepgenerated");
588             }
589             if (compiler == null) {
590                 // try to use the compiler specified by build.compiler.
591
// Right now we are just going to allow Jikes
592
String JavaDoc buildCompiler
593                     = getTask().getProject().getProperty("build.compiler");
594
595                 if (buildCompiler != null && buildCompiler.equals("jikes")) {
596                     javaTask.createArg().setValue("-compiler");
597                     javaTask.createArg().setValue("jikes");
598                 }
599             } else {
600                 if (!compiler.equals(DEFAULT_COMPILER)) {
601                     javaTask.createArg().setValue("-compiler");
602                     javaTask.createArg().setLine(compiler);
603                 }
604             }
605
606             Path combinedClasspath = getCombinedClasspath();
607             if (wlClasspath != null && combinedClasspath != null
608                  && combinedClasspath.toString().trim().length() > 0) {
609                 javaTask.createArg().setValue("-classpath");
610                 javaTask.createArg().setPath(combinedClasspath);
611             }
612
613             javaTask.createArg().setValue(sourceJar.getPath());
614             if (outputDir == null) {
615                 javaTask.createArg().setValue(destJar.getPath());
616             } else {
617                 javaTask.createArg().setValue(outputDir.getPath());
618             }
619
620             Path classpath = wlClasspath;
621
622             if (classpath == null) {
623                 classpath = getCombinedClasspath();
624             }
625
626             javaTask.setFork(true);
627             if (classpath != null) {
628                 javaTask.setClasspath(classpath);
629             }
630
631             log("Calling " + ejbcClassName + " for " + sourceJar.toString(),
632                 Project.MSG_VERBOSE);
633
634             if (javaTask.executeJava() != 0) {
635                 throw new BuildException("Ejbc reported an error");
636             }
637         } catch (Exception JavaDoc e) {
638             // Have to catch this because of the semantics of calling main()
639
String JavaDoc msg = "Exception while calling " + ejbcClassName
640                 + ". Details: " + e.toString();
641
642             throw new BuildException(msg, e);
643         }
644     }
645
646
647     /**
648      * Method used to encapsulate the writing of the JAR file. Iterates over
649      * the filenames/java.io.Files in the Hashtable stored on the instance
650      * variable ejbFiles.
651      * @param baseName the base name.
652      * @param jarFile the jar file to populate.
653      * @param files the hash table of files to write.
654      * @param publicId the id to use.
655      * @throws BuildException if there is a problem.
656      */

657     protected void writeJar(String JavaDoc baseName, File JavaDoc jarFile, Hashtable JavaDoc files,
658                             String JavaDoc publicId) throws BuildException {
659         // need to create a generic jar first.
660
File JavaDoc genericJarFile = super.getVendorOutputJarFile(baseName);
661
662         super.writeJar(baseName, genericJarFile, files, publicId);
663
664         if (alwaysRebuild || isRebuildRequired(genericJarFile, jarFile)) {
665             buildWeblogicJar(genericJarFile, jarFile, publicId);
666         }
667         if (!keepGeneric) {
668             log("deleting generic jar " + genericJarFile.toString(),
669                 Project.MSG_VERBOSE);
670             genericJarFile.delete();
671         }
672     }
673
674
675     /**
676      * Called to validate that the tool parameters have been configured.
677      * @throws BuildException if there is an error.
678      */

679     public void validateConfigured() throws BuildException {
680         super.validateConfigured();
681     }
682
683
684     /**
685      * Helper method to check to see if a weblogic EBJ1.1 jar needs to be
686      * rebuilt using ejbc. Called from writeJar it sees if the "Bean" classes
687      * are the only thing that needs to be updated and either updates the Jar
688      * with the Bean classfile or returns true, saying that the whole weblogic
689      * jar needs to be regened with ejbc. This allows faster build times for
690      * working developers. <p>
691      *
692      * The way weblogic ejbc works is it creates wrappers for the publicly
693      * defined methods as they are exposed in the remote interface. If the
694      * actual bean changes without changing the the method signatures then
695      * only the bean classfile needs to be updated and the rest of the
696      * weblogic jar file can remain the same. If the Interfaces, ie. the
697      * method signatures change or if the xml deployment descriptors changed,
698      * the whole jar needs to be rebuilt with ejbc. This is not strictly true
699      * for the xml files. If the JNDI name changes then the jar doesnt have to
700      * be rebuild, but if the resources references change then it does. At
701      * this point the weblogic jar gets rebuilt if the xml files change at
702      * all.
703      *
704      * @param genericJarFile java.io.File The generic jar file.
705      * @param weblogicJarFile java.io.File The weblogic jar file to check to
706      * see if it needs to be rebuilt.
707      * @return true if the jar needs to be rebuilt.
708      */

709     protected boolean isRebuildRequired(File JavaDoc genericJarFile, File JavaDoc weblogicJarFile) {
710         boolean rebuild = false;
711
712         JarFile JavaDoc genericJar = null;
713         JarFile JavaDoc wlJar = null;
714         File JavaDoc newWLJarFile = null;
715         JarOutputStream JavaDoc newJarStream = null;
716         ClassLoader JavaDoc genericLoader = null;
717
718         try {
719             log("Checking if weblogic Jar needs to be rebuilt for jar " + weblogicJarFile.getName(),
720                 Project.MSG_VERBOSE);
721             // Only go forward if the generic and the weblogic file both exist
722
if (genericJarFile.exists() && genericJarFile.isFile()
723                  && weblogicJarFile.exists() && weblogicJarFile.isFile()) {
724                 //open jar files
725
genericJar = new JarFile JavaDoc(genericJarFile);
726                 wlJar = new JarFile JavaDoc(weblogicJarFile);
727
728                 Hashtable JavaDoc genericEntries = new Hashtable JavaDoc();
729                 Hashtable JavaDoc wlEntries = new Hashtable JavaDoc();
730                 Hashtable JavaDoc replaceEntries = new Hashtable JavaDoc();
731
732                 //get the list of generic jar entries
733
for (Enumeration JavaDoc e = genericJar.entries(); e.hasMoreElements();) {
734                     JarEntry JavaDoc je = (JarEntry JavaDoc) e.nextElement();
735
736                     genericEntries.put(je.getName().replace('\\', '/'), je);
737                 }
738                 //get the list of weblogic jar entries
739
for (Enumeration JavaDoc e = wlJar.entries(); e.hasMoreElements();) {
740                     JarEntry JavaDoc je = (JarEntry JavaDoc) e.nextElement();
741
742                     wlEntries.put(je.getName(), je);
743                 }
744
745                 //Cycle Through generic and make sure its in weblogic
746
genericLoader = getClassLoaderFromJar(genericJarFile);
747
748                 for (Enumeration JavaDoc e = genericEntries.keys(); e.hasMoreElements();) {
749                     String JavaDoc filepath = (String JavaDoc) e.nextElement();
750
751                     if (wlEntries.containsKey(filepath)) {
752                         // File name/path match
753

754                         // Check files see if same
755
JarEntry JavaDoc genericEntry = (JarEntry JavaDoc) genericEntries.get(filepath);
756                         JarEntry JavaDoc wlEntry = (JarEntry JavaDoc) wlEntries.get(filepath);
757
758                         if ((genericEntry.getCrc() != wlEntry.getCrc())
759                             || (genericEntry.getSize() != wlEntry.getSize())) {
760
761                             if (genericEntry.getName().endsWith(".class")) {
762                                 //File are different see if its an object or an interface
763
String JavaDoc classname
764                                     = genericEntry.getName().replace(File.separatorChar, '.');
765
766                                 classname = classname.substring(0, classname.lastIndexOf(".class"));
767
768                                 Class JavaDoc genclass = genericLoader.loadClass(classname);
769
770                                 if (genclass.isInterface()) {
771                                     //Interface changed rebuild jar.
772
log("Interface " + genclass.getName()
773                                         + " has changed", Project.MSG_VERBOSE);
774                                     rebuild = true;
775                                     break;
776                                 } else {
777                                     //Object class Changed update it.
778
replaceEntries.put(filepath, genericEntry);
779                                 }
780                             } else {
781                                 // is it the manifest. If so ignore it
782
if (!genericEntry.getName().equals("META-INF/MANIFEST.MF")) {
783                                     //File other then class changed rebuild
784
log("Non class file " + genericEntry.getName()
785                                         + " has changed", Project.MSG_VERBOSE);
786                                     rebuild = true;
787                                     break;
788                                 }
789                             }
790                         }
791                     } else {
792                         // a file doesnt exist rebuild
793

794                         log("File " + filepath + " not present in weblogic jar",
795                             Project.MSG_VERBOSE);
796                         rebuild = true;
797                         break;
798                     }
799                 }
800
801                 if (!rebuild) {
802                     log("No rebuild needed - updating jar", Project.MSG_VERBOSE);
803                     newWLJarFile = new File JavaDoc(weblogicJarFile.getAbsolutePath() + ".temp");
804                     if (newWLJarFile.exists()) {
805                         newWLJarFile.delete();
806                     }
807
808                     newJarStream = new JarOutputStream JavaDoc(new FileOutputStream JavaDoc(newWLJarFile));
809                     newJarStream.setLevel(0);
810
811                     //Copy files from old weblogic jar
812
for (Enumeration JavaDoc e = wlEntries.elements(); e.hasMoreElements();) {
813                         byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
814                         int bytesRead;
815                         InputStream JavaDoc is;
816                         JarEntry JavaDoc je = (JarEntry JavaDoc) e.nextElement();
817
818                         if (je.getCompressedSize() == -1
819                             || je.getCompressedSize() == je.getSize()) {
820                             newJarStream.setLevel(0);
821                         } else {
822                             newJarStream.setLevel(JAR_COMPRESS_LEVEL);
823                         }
824
825                         // Update with changed Bean class
826
if (replaceEntries.containsKey(je.getName())) {
827                             log("Updating Bean class from generic Jar "
828                                 + je.getName(), Project.MSG_VERBOSE);
829                             // Use the entry from the generic jar
830
je = (JarEntry JavaDoc) replaceEntries.get(je.getName());
831                             is = genericJar.getInputStream(je);
832                         } else {
833                             //use fle from original weblogic jar
834

835                             is = wlJar.getInputStream(je);
836                         }
837                         newJarStream.putNextEntry(new JarEntry JavaDoc(je.getName()));
838
839                         while ((bytesRead = is.read(buffer)) != -1) {
840                             newJarStream.write(buffer, 0, bytesRead);
841                         }
842                         is.close();
843                     }
844                 } else {
845                     log("Weblogic Jar rebuild needed due to changed "
846                          + "interface or XML", Project.MSG_VERBOSE);
847                 }
848             } else {
849                 rebuild = true;
850             }
851         } catch (ClassNotFoundException JavaDoc cnfe) {
852             String JavaDoc cnfmsg = "ClassNotFoundException while processing ejb-jar file"
853                  + ". Details: "
854                  + cnfe.getMessage();
855
856             throw new BuildException(cnfmsg, cnfe);
857         } catch (IOException JavaDoc ioe) {
858             String JavaDoc msg = "IOException while processing ejb-jar file "
859                  + ". Details: "
860                  + ioe.getMessage();
861
862             throw new BuildException(msg, ioe);
863         } finally {
864             // need to close files and perhaps rename output
865
if (genericJar != null) {
866                 try {
867                     genericJar.close();
868                 } catch (IOException JavaDoc closeException) {
869                     // empty
870
}
871             }
872
873             if (wlJar != null) {
874                 try {
875                     wlJar.close();
876                 } catch (IOException JavaDoc closeException) {
877                     // empty
878
}
879             }
880
881             if (newJarStream != null) {
882                 try {
883                     newJarStream.close();
884                 } catch (IOException JavaDoc closeException) {
885                     // empty
886
}
887
888                 try {
889                     FILE_UTILS.rename(newWLJarFile, weblogicJarFile);
890                 } catch (IOException JavaDoc renameException) {
891                     log(renameException.getMessage(), Project.MSG_WARN);
892                     rebuild = true;
893                 }
894             }
895             if (genericLoader != null
896                 && genericLoader instanceof AntClassLoader) {
897                 AntClassLoader loader = (AntClassLoader) genericLoader;
898                 loader.cleanup();
899             }
900         }
901
902         return rebuild;
903     }
904
905
906     /**
907      * Helper method invoked by isRebuildRequired to get a ClassLoader for a
908      * Jar File passed to it.
909      *
910      * @param classjar java.io.File representing jar file to get classes from.
911      * @return the classloader for the jarfile.
912      * @throws IOException if there is a problem.
913      */

914     protected ClassLoader JavaDoc getClassLoaderFromJar(File JavaDoc classjar) throws IOException JavaDoc {
915         Path lookupPath = new Path(getTask().getProject());
916
917         lookupPath.setLocation(classjar);
918
919         Path classpath = getCombinedClasspath();
920
921         if (classpath != null) {
922             lookupPath.append(classpath);
923         }
924
925         return getTask().getProject().createClassLoader(lookupPath);
926     }
927 }
928
Popular Tags