source: other-projects/trunk/gs3-release-maker/apache-ant-1.6.5/src/main/org/apache/tools/ant/taskdefs/optional/ejb/WeblogicDeploymentTool.java@ 14627

Last change on this file since 14627 was 14627, checked in by oranfry, 17 years ago

initial import of the gs3-release-maker

File size: 33.3 KB
Line 
1/*
2 * Copyright 2000-2004 The Apache Software Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17package org.apache.tools.ant.taskdefs.optional.ejb;
18
19import java.io.File;
20import java.io.FileInputStream;
21import java.io.FileOutputStream;
22import java.io.IOException;
23import java.io.InputStream;
24import java.util.Enumeration;
25import java.util.Hashtable;
26import java.util.Iterator;
27import java.util.Vector;
28import java.util.jar.JarEntry;
29import java.util.jar.JarFile;
30import java.util.jar.JarOutputStream;
31import javax.xml.parsers.SAXParser;
32import javax.xml.parsers.SAXParserFactory;
33import org.apache.tools.ant.AntClassLoader;
34import org.apache.tools.ant.BuildException;
35import org.apache.tools.ant.Project;
36import org.apache.tools.ant.taskdefs.Java;
37import org.apache.tools.ant.types.Environment;
38import org.apache.tools.ant.types.Path;
39import org.apache.tools.ant.util.FileUtils;
40import org.xml.sax.InputSource;
41
42/**
43 The weblogic element is used to control the weblogic.ejbc compiler for
44 generating weblogic EJB jars. Prior to Ant 1.3, the method of locating CMP
45 descriptors was to use the ejbjar naming convention. So if your ejb-jar was
46 called, Customer-ejb-jar.xml, your weblogic descriptor was called Customer-
47 weblogic-ejb-jar.xml and your CMP descriptor had to be Customer-weblogic-cmp-
48 rdbms-jar.xml. In addition, the <type-storage> element in the weblogic
49 descriptor had to be set to the standard name META-INF/weblogic-cmp-rdbms-
50 jar.xml, as that is where the CMP descriptor was mapped to in the generated
51 jar.
52*/
53public class WeblogicDeploymentTool extends GenericDeploymentTool {
54 public static final String PUBLICID_EJB11
55 = "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 1.1//EN";
56 public static final String PUBLICID_EJB20
57 = "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN";
58 public static final String PUBLICID_WEBLOGIC_EJB510
59 = "-//BEA Systems, Inc.//DTD WebLogic 5.1.0 EJB//EN";
60 public static final String PUBLICID_WEBLOGIC_EJB600
61 = "-//BEA Systems, Inc.//DTD WebLogic 6.0.0 EJB//EN";
62 public static final String PUBLICID_WEBLOGIC_EJB700
63 = "-//BEA Systems, Inc.//DTD WebLogic 7.0.0 EJB//EN";
64
65 protected static final String DEFAULT_WL51_EJB11_DTD_LOCATION
66 = "/weblogic/ejb/deployment/xml/ejb-jar.dtd";
67 protected static final String DEFAULT_WL60_EJB11_DTD_LOCATION
68 = "/weblogic/ejb20/dd/xml/ejb11-jar.dtd";
69 protected static final String DEFAULT_WL60_EJB20_DTD_LOCATION
70 = "/weblogic/ejb20/dd/xml/ejb20-jar.dtd";
71
72 protected static final String DEFAULT_WL51_DTD_LOCATION
73 = "/weblogic/ejb/deployment/xml/weblogic-ejb-jar.dtd";
74 protected static final String DEFAULT_WL60_51_DTD_LOCATION
75 = "/weblogic/ejb20/dd/xml/weblogic510-ejb-jar.dtd";
76 protected static final String DEFAULT_WL60_DTD_LOCATION
77 = "/weblogic/ejb20/dd/xml/weblogic600-ejb-jar.dtd";
78 protected static final String DEFAULT_WL70_DTD_LOCATION
79 = "/weblogic/ejb20/dd/xml/weblogic700-ejb-jar.dtd";
80
81 protected static final String DEFAULT_COMPILER = "default";
82
83 protected static final String WL_DD = "weblogic-ejb-jar.xml";
84 protected static final String WL_CMP_DD = "weblogic-cmp-rdbms-jar.xml";
85
86 protected static final String COMPILER_EJB11 = "weblogic.ejbc";
87 protected static final String COMPILER_EJB20 = "weblogic.ejbc20";
88
89 /** Instance variable that stores the suffix for the weblogic jarfile. */
90 private String jarSuffix = ".jar";
91
92 /** Instance variable that stores the location of the weblogic DTD file. */
93 private String weblogicDTD;
94
95 /** Instance variable that stores the location of the ejb 1.1 DTD file. */
96 private String ejb11DTD;
97
98 /** Instance variable that determines whether generic ejb jars are kept. */
99 private boolean keepgenerated = false;
100
101 /**
102 * Instance variable that stores the fully qualified classname of the
103 * weblogic EJBC compiler
104 */
105 private String ejbcClass = null;
106
107 private String additionalArgs = "";
108
109 /**
110 * additional args to pass to the spawned jvm
111 */
112 private String additionalJvmArgs = "";
113
114 private boolean keepGeneric = false;
115
116 private String compiler = null;
117
118 private boolean alwaysRebuild = true;
119
120 /** controls whether ejbc is run on the generated jar */
121 private boolean noEJBC = false;
122
123 /** Indicates if the old CMP location convention is to be used. */
124 private boolean newCMP = false;
125
126 /** The classpath to the weblogic classes. */
127 private Path wlClasspath = null;
128
129 /** System properties for the JVM. */
130 private Vector sysprops = new Vector();
131
132 /**
133 * The weblogic.StdoutSeverityLevel to use when running the JVM that
134 * executes ejbc. Set to 16 to avoid the warnings about EJB Home and
135 * Remotes being in the classpath
136 */
137 private Integer jvmDebugLevel = null;
138
139 /** File utilities instance for copying jars */
140 private FileUtils fileUtils = FileUtils.newFileUtils();
141
142 private File outputDir;
143
144 /**
145 * Add a nested sysproperty element.
146 */
147 public void addSysproperty(Environment.Variable sysp) {
148 sysprops.add(sysp);
149 }
150
151
152 /** Get the classpath to the weblogic classpaths */
153 public Path createWLClasspath() {
154 if (wlClasspath == null) {
155 wlClasspath = new Path(getTask().getProject());
156 }
157 return wlClasspath.createPath();
158 }
159
160 /**
161 * If set ejbc will use this directory as the output
162 * destination rather than a jar file. This allows for the
163 * generation of "exploded" jars.
164 */
165 public void setOutputDir(File outputDir) {
166 this.outputDir = outputDir;
167 }
168
169
170 /**
171 * Optional classpath to WL6.0.
172 * Weblogic 6.0 will give a warning if the home and remote interfaces
173 * of a bean are on the system classpath used to run weblogic.ejbc.
174 * In that case, the standard weblogic classes should be set with
175 * this attribute (or equivalent nested element) and the
176 * home and remote interfaces located with the standard classpath
177 * attribute
178 */
179 public void setWLClasspath(Path wlClasspath) {
180 this.wlClasspath = wlClasspath;
181 }
182
183
184 /**
185 * The compiler (switch <code>-compiler</code>) to use; optional.
186 * This allows for the selection of a different compiler
187 * to be used for the compilation of the generated Java
188 * files. This could be set, for example, to Jikes to
189 * compile with the Jikes compiler. If this is not set
190 * and the <code>build.compiler</code> property is set
191 * to jikes, the Jikes compiler will be used. If this
192 * is not desired, the value &quot;<code>default</code>&quot;
193 * may be given to use the default compiler
194 */
195 public void setCompiler(String compiler) {
196 this.compiler = compiler;
197 }
198
199
200 /**
201 * Set the rebuild flag to false to only update changes in the jar rather
202 * than rerunning ejbc; optional, default true.
203 * This flag controls whether weblogic.ejbc is always
204 * invoked to build the jar file. In certain circumstances,
205 * such as when only a bean class has been changed, the jar
206 * can be generated by merely replacing the changed classes
207 * and not rerunning ejbc. Setting this to false will reduce
208 * the time to run ejbjar.
209 */
210 public void setRebuild(boolean rebuild) {
211 this.alwaysRebuild = rebuild;
212 }
213
214
215 /**
216 * Sets the weblogic.StdoutSeverityLevel to use when running the JVM that
217 * executes ejbc; optional. Set to 16 to avoid the warnings about EJB Home and
218 * Remotes being in the classpath
219 */
220 public void setJvmDebugLevel(Integer jvmDebugLevel) {
221 this.jvmDebugLevel = jvmDebugLevel;
222 }
223
224
225 public Integer getJvmDebugLevel() {
226 return jvmDebugLevel;
227 }
228
229
230
231 /**
232 * Setter used to store the suffix for the generated weblogic jar file.
233 *
234 * @param inString the string to use as the suffix.
235 */
236 public void setSuffix(String inString) {
237 this.jarSuffix = inString;
238 }
239
240
241 /**
242 * controls whether the generic file used as input to
243 * ejbc is retained; defaults to false
244 *
245 * @param inValue true for keep generic
246 */
247 public void setKeepgeneric(boolean inValue) {
248 this.keepGeneric = inValue;
249 }
250
251
252 /**
253 * Controls whether weblogic will keep the generated Java
254 * files used to build the class files added to the
255 * jar. This can be useful when debugging; default is false.
256 *
257 * @param inValue either 'true' or 'false'
258 */
259 public void setKeepgenerated(String inValue) {
260 this.keepgenerated = Boolean.valueOf(inValue).booleanValue();
261 }
262
263
264 /**
265 * Any optional extra arguments pass to the weblogic.ejbc
266 * tool.
267 */
268 public void setArgs(String args) {
269 this.additionalArgs = args;
270 }
271
272
273 /**
274 * Set any additional arguments to pass to the weblogic JVM; optional.
275 * @param args the arguments to be passed to the JVM
276 */
277 public void setJvmargs(String args) {
278 this.additionalJvmArgs = args;
279 }
280
281 /**
282 * Set the classname of the ejbc compiler; optional
283 * Normally ejbjar determines
284 * the appropriate class based on the DTD used for the EJB. The EJB 2.0 compiler
285 * featured in weblogic 6 has, however, been deprecated in version 7. When
286 * using with version 7 this attribute should be set to
287 * &quot;weblogic.ejbc&quot; to avoid the deprecation warning.
288 */
289 public void setEjbcClass(String ejbcClass) {
290 this.ejbcClass = ejbcClass;
291 }
292
293
294 /** Get the ejbc compiler class */
295 public String getEjbcClass() {
296 return ejbcClass;
297 }
298
299
300 /**
301 * <b>Deprecated</b>. Defines the location of the ejb-jar DTD in
302 * the weblogic class hierarchy. Should not be needed, and the
303 * nested &lt;dtd&gt; element is recommended when it is.
304 *
305 * @param inString the string to use as the DTD location.
306 */
307 public void setWeblogicdtd(String inString) {
308 setEJBdtd(inString);
309 }
310
311
312 /**
313 * <b>Deprecated</b>. Defines the location of weblogic DTD in
314 * the weblogic class hierarchy. Should not be needed, and the
315 * nested &lt;dtd&gt; element is recommended when it is.
316 *
317 * @param inString the string to use as the DTD location.
318 */
319 public void setWLdtd(String inString) {
320 this.weblogicDTD = inString;
321 }
322
323
324 /**
325 * <b>Deprecated</b>. Defines the location of Sun's EJB DTD in
326 * the weblogic class hierarchy. Should not be needed, and the
327 * nested &lt;dtd&gt; element is recommended when it is.
328 *
329 * @param inString the string to use as the DTD location.
330 */
331 public void setEJBdtd(String inString) {
332 this.ejb11DTD = inString;
333 }
334
335
336 /**
337 * Set the value of the oldCMP scheme. This is an antonym for newCMP
338 * @ant.attribute ignore="true'
339 */
340 public void setOldCMP(boolean oldCMP) {
341 this.newCMP = !oldCMP;
342 }
343
344
345 /**
346 * If this is set to true, the new method for locating
347 * CMP descriptors will be used; optional, default false.
348 * <P>
349 * The old CMP scheme locates the
350 * weblogic CMP descriptor based on the naming convention where the
351 * weblogic CMP file is expected to be named with the bean name as the
352 * prefix. Under this scheme the name of the CMP descriptor does not match
353 * the name actually used in the main weblogic EJB descriptor. Also,
354 * descriptors which contain multiple CMP references could not be used.
355 */
356 public void setNewCMP(boolean newCMP) {
357 this.newCMP = newCMP;
358 }
359
360
361 /**
362 * Do not EJBC the jar after it has been put together;
363 * optional, default false
364 */
365 public void setNoEJBC(boolean noEJBC) {
366 this.noEJBC = noEJBC;
367 }
368
369
370 protected void registerKnownDTDs(DescriptorHandler handler) {
371 // register all the known DTDs
372 handler.registerDTD(PUBLICID_EJB11, DEFAULT_WL51_EJB11_DTD_LOCATION);
373 handler.registerDTD(PUBLICID_EJB11, DEFAULT_WL60_EJB11_DTD_LOCATION);
374 handler.registerDTD(PUBLICID_EJB11, ejb11DTD);
375 handler.registerDTD(PUBLICID_EJB20, DEFAULT_WL60_EJB20_DTD_LOCATION);
376 }
377
378
379 protected DescriptorHandler getWeblogicDescriptorHandler(final File srcDir) {
380 DescriptorHandler handler =
381 new DescriptorHandler(getTask(), srcDir) {
382 protected void processElement() {
383 if (currentElement.equals("type-storage")) {
384 // Get the filename of vendor specific descriptor
385 String fileNameWithMETA = currentText;
386 //trim the META_INF\ off of the file name
387 String fileName
388 = fileNameWithMETA.substring(META_DIR.length(),
389 fileNameWithMETA.length());
390 File descriptorFile = new File(srcDir, fileName);
391
392 ejbFiles.put(fileNameWithMETA, descriptorFile);
393 }
394 }
395 };
396
397 handler.registerDTD(PUBLICID_WEBLOGIC_EJB510, DEFAULT_WL51_DTD_LOCATION);
398 handler.registerDTD(PUBLICID_WEBLOGIC_EJB510, DEFAULT_WL60_51_DTD_LOCATION);
399 handler.registerDTD(PUBLICID_WEBLOGIC_EJB600, DEFAULT_WL60_DTD_LOCATION);
400 handler.registerDTD(PUBLICID_WEBLOGIC_EJB700, DEFAULT_WL70_DTD_LOCATION);
401 handler.registerDTD(PUBLICID_WEBLOGIC_EJB510, weblogicDTD);
402 handler.registerDTD(PUBLICID_WEBLOGIC_EJB600, weblogicDTD);
403
404 for (Iterator i = getConfig().dtdLocations.iterator(); i.hasNext();) {
405 EjbJar.DTDLocation dtdLocation = (EjbJar.DTDLocation) i.next();
406
407 handler.registerDTD(dtdLocation.getPublicId(), dtdLocation.getLocation());
408 }
409 return handler;
410 }
411
412
413 /**
414 * Add any vendor specific files which should be included in the EJB Jar.
415 */
416 protected void addVendorFiles(Hashtable ejbFiles, String ddPrefix) {
417 File weblogicDD = new File(getConfig().descriptorDir, ddPrefix + WL_DD);
418
419 if (weblogicDD.exists()) {
420 ejbFiles.put(META_DIR + WL_DD,
421 weblogicDD);
422 } else {
423 log("Unable to locate weblogic deployment descriptor. "
424 + "It was expected to be in "
425 + weblogicDD.getPath(), Project.MSG_WARN);
426 return;
427 }
428
429 if (!newCMP) {
430 log("The old method for locating CMP files has been DEPRECATED.", Project.MSG_VERBOSE);
431 log("Please adjust your weblogic descriptor and set "
432 + "newCMP=\"true\" to use the new CMP descriptor "
433 + "inclusion mechanism. ", Project.MSG_VERBOSE);
434 // The the weblogic cmp deployment descriptor
435 File weblogicCMPDD = new File(getConfig().descriptorDir, ddPrefix + WL_CMP_DD);
436
437 if (weblogicCMPDD.exists()) {
438 ejbFiles.put(META_DIR + WL_CMP_DD,
439 weblogicCMPDD);
440 }
441 } else {
442 // now that we have the weblogic descriptor, we parse the file
443 // to find other descriptors needed to deploy the bean.
444 // this could be the weblogic-cmp-rdbms.xml or any other O/R
445 // mapping tool descriptors.
446 try {
447 File ejbDescriptor = (File) ejbFiles.get(META_DIR + EJB_DD);
448 SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
449
450 saxParserFactory.setValidating(true);
451
452 SAXParser saxParser = saxParserFactory.newSAXParser();
453 DescriptorHandler handler
454 = getWeblogicDescriptorHandler(ejbDescriptor.getParentFile());
455
456 saxParser.parse(new InputSource
457 (new FileInputStream(weblogicDD)),
458 handler);
459
460 Hashtable ht = handler.getFiles();
461 Enumeration e = ht.keys();
462
463 while (e.hasMoreElements()) {
464 String key = (String) e.nextElement();
465
466 ejbFiles.put(key, ht.get(key));
467 }
468 } catch (Exception e) {
469 String msg = "Exception while adding Vendor specific files: " + e.toString();
470
471 throw new BuildException(msg, e);
472 }
473 }
474 }
475
476
477 /**
478 * Get the vendor specific name of the Jar that will be output. The
479 * modification date of this jar will be checked against the dependent
480 * bean classes.
481 */
482 File getVendorOutputJarFile(String baseName) {
483 return new File(getDestDir(), baseName + jarSuffix);
484 }
485
486
487 /**
488 * Helper method invoked by execute() for each WebLogic jar to be built.
489 * Encapsulates the logic of constructing a java task for calling
490 * weblogic.ejbc and executing it.
491 *
492 * @param sourceJar java.io.File representing the source (EJB1.1) jarfile.
493 * @param destJar java.io.File representing the destination, WebLogic
494 * jarfile.
495 */
496 private void buildWeblogicJar(File sourceJar, File destJar, String publicId) {
497 Java javaTask = null;
498
499 if (noEJBC) {
500 try {
501 fileUtils.copyFile(sourceJar, destJar);
502 if (!keepgenerated) {
503 sourceJar.delete();
504 }
505 return;
506 } catch (IOException e) {
507 throw new BuildException("Unable to write EJB jar", e);
508 }
509 }
510
511 String ejbcClassName = ejbcClass;
512
513 try {
514 javaTask = (Java) getTask().getProject().createTask("java");
515 javaTask.setTaskName("ejbc");
516
517 javaTask.createJvmarg().setLine(additionalJvmArgs);
518 if (!(sysprops.isEmpty())) {
519 for (Enumeration en = sysprops.elements(); en.hasMoreElements();) {
520 Environment.Variable entry
521 = (Environment.Variable) en.nextElement();
522 javaTask.addSysproperty(entry);
523 }
524 }
525
526 if (getJvmDebugLevel() != null) {
527 javaTask.createJvmarg().setLine(" -Dweblogic.StdoutSeverityLevel=" + jvmDebugLevel);
528 }
529
530 if (ejbcClassName == null) {
531 // try to determine it from publicId
532 if (PUBLICID_EJB11.equals(publicId)) {
533 ejbcClassName = COMPILER_EJB11;
534 } else if (PUBLICID_EJB20.equals(publicId)) {
535 ejbcClassName = COMPILER_EJB20;
536 } else {
537 log("Unrecognized publicId " + publicId
538 + " - using EJB 1.1 compiler", Project.MSG_WARN);
539 ejbcClassName = COMPILER_EJB11;
540 }
541 }
542
543 javaTask.setClassname(ejbcClassName);
544 javaTask.createArg().setLine(additionalArgs);
545 if (keepgenerated) {
546 javaTask.createArg().setValue("-keepgenerated");
547 }
548 if (compiler == null) {
549 // try to use the compiler specified by build.compiler.
550 // Right now we are just going to allow Jikes
551 String buildCompiler
552 = getTask().getProject().getProperty("build.compiler");
553
554 if (buildCompiler != null && buildCompiler.equals("jikes")) {
555 javaTask.createArg().setValue("-compiler");
556 javaTask.createArg().setValue("jikes");
557 }
558 } else {
559 if (!compiler.equals(DEFAULT_COMPILER)) {
560 javaTask.createArg().setValue("-compiler");
561 javaTask.createArg().setLine(compiler);
562 }
563 }
564
565 Path combinedClasspath = getCombinedClasspath();
566 if (wlClasspath != null && combinedClasspath != null
567 && combinedClasspath.toString().trim().length() > 0) {
568 javaTask.createArg().setValue("-classpath");
569 javaTask.createArg().setPath(combinedClasspath);
570 }
571
572 javaTask.createArg().setValue(sourceJar.getPath());
573 if (outputDir == null) {
574 javaTask.createArg().setValue(destJar.getPath());
575 } else {
576 javaTask.createArg().setValue(outputDir.getPath());
577 }
578
579 Path classpath = wlClasspath;
580
581 if (classpath == null) {
582 classpath = getCombinedClasspath();
583 }
584
585 javaTask.setFork(true);
586 if (classpath != null) {
587 javaTask.setClasspath(classpath);
588 }
589
590 log("Calling " + ejbcClassName + " for " + sourceJar.toString(),
591 Project.MSG_VERBOSE);
592
593 if (javaTask.executeJava() != 0) {
594 throw new BuildException("Ejbc reported an error");
595 }
596 } catch (Exception e) {
597 // Have to catch this because of the semantics of calling main()
598 String msg = "Exception while calling " + ejbcClassName
599 + ". Details: " + e.toString();
600
601 throw new BuildException(msg, e);
602 }
603 }
604
605
606 /**
607 * Method used to encapsulate the writing of the JAR file. Iterates over
608 * the filenames/java.io.Files in the Hashtable stored on the instance
609 * variable ejbFiles.
610 */
611 protected void writeJar(String baseName, File jarFile, Hashtable files,
612 String publicId) throws BuildException {
613 // need to create a generic jar first.
614 File genericJarFile = super.getVendorOutputJarFile(baseName);
615
616 super.writeJar(baseName, genericJarFile, files, publicId);
617
618 if (alwaysRebuild || isRebuildRequired(genericJarFile, jarFile)) {
619 buildWeblogicJar(genericJarFile, jarFile, publicId);
620 }
621 if (!keepGeneric) {
622 log("deleting generic jar " + genericJarFile.toString(),
623 Project.MSG_VERBOSE);
624 genericJarFile.delete();
625 }
626 }
627
628
629 /**
630 * Called to validate that the tool parameters have been configured.
631 */
632 public void validateConfigured() throws BuildException {
633 super.validateConfigured();
634 }
635
636
637 /**
638 * Helper method to check to see if a weblogic EBJ1.1 jar needs to be
639 * rebuilt using ejbc. Called from writeJar it sees if the "Bean" classes
640 * are the only thing that needs to be updated and either updates the Jar
641 * with the Bean classfile or returns true, saying that the whole weblogic
642 * jar needs to be regened with ejbc. This allows faster build times for
643 * working developers. <p>
644 *
645 * The way weblogic ejbc works is it creates wrappers for the publicly
646 * defined methods as they are exposed in the remote interface. If the
647 * actual bean changes without changing the the method signatures then
648 * only the bean classfile needs to be updated and the rest of the
649 * weblogic jar file can remain the same. If the Interfaces, ie. the
650 * method signatures change or if the xml deployment descriptors changed,
651 * the whole jar needs to be rebuilt with ejbc. This is not strictly true
652 * for the xml files. If the JNDI name changes then the jar doesnt have to
653 * be rebuild, but if the resources references change then it does. At
654 * this point the weblogic jar gets rebuilt if the xml files change at
655 * all.
656 *
657 * @param genericJarFile java.io.File The generic jar file.
658 * @param weblogicJarFile java.io.File The weblogic jar file to check to
659 * see if it needs to be rebuilt.
660 */
661 protected boolean isRebuildRequired(File genericJarFile, File weblogicJarFile) {
662 boolean rebuild = false;
663
664 JarFile genericJar = null;
665 JarFile wlJar = null;
666 File newWLJarFile = null;
667 JarOutputStream newJarStream = null;
668
669 try {
670 log("Checking if weblogic Jar needs to be rebuilt for jar " + weblogicJarFile.getName(),
671 Project.MSG_VERBOSE);
672 // Only go forward if the generic and the weblogic file both exist
673 if (genericJarFile.exists() && genericJarFile.isFile()
674 && weblogicJarFile.exists() && weblogicJarFile.isFile()) {
675 //open jar files
676 genericJar = new JarFile(genericJarFile);
677 wlJar = new JarFile(weblogicJarFile);
678
679 Hashtable genericEntries = new Hashtable();
680 Hashtable wlEntries = new Hashtable();
681 Hashtable replaceEntries = new Hashtable();
682
683 //get the list of generic jar entries
684 for (Enumeration e = genericJar.entries(); e.hasMoreElements();) {
685 JarEntry je = (JarEntry) e.nextElement();
686
687 genericEntries.put(je.getName().replace('\\', '/'), je);
688 }
689 //get the list of weblogic jar entries
690 for (Enumeration e = wlJar.entries(); e.hasMoreElements();) {
691 JarEntry je = (JarEntry) e.nextElement();
692
693 wlEntries.put(je.getName(), je);
694 }
695
696 //Cycle Through generic and make sure its in weblogic
697 ClassLoader genericLoader
698 = getClassLoaderFromJar(genericJarFile);
699
700 for (Enumeration e = genericEntries.keys(); e.hasMoreElements();) {
701 String filepath = (String) e.nextElement();
702
703 if (wlEntries.containsKey(filepath)) {
704 // File name/path match
705
706 // Check files see if same
707 JarEntry genericEntry = (JarEntry) genericEntries.get(filepath);
708 JarEntry wlEntry = (JarEntry) wlEntries.get(filepath);
709
710 if ((genericEntry.getCrc() != wlEntry.getCrc())
711 || (genericEntry.getSize() != wlEntry.getSize())) {
712
713 if (genericEntry.getName().endsWith(".class")) {
714 //File are different see if its an object or an interface
715 String classname
716 = genericEntry.getName().replace(File.separatorChar, '.');
717
718 classname = classname.substring(0, classname.lastIndexOf(".class"));
719
720 Class genclass = genericLoader.loadClass(classname);
721
722 if (genclass.isInterface()) {
723 //Interface changed rebuild jar.
724 log("Interface " + genclass.getName()
725 + " has changed", Project.MSG_VERBOSE);
726 rebuild = true;
727 break;
728 } else {
729 //Object class Changed update it.
730 replaceEntries.put(filepath, genericEntry);
731 }
732 } else {
733 // is it the manifest. If so ignore it
734 if (!genericEntry.getName().equals("META-INF/MANIFEST.MF")) {
735 //File other then class changed rebuild
736 log("Non class file " + genericEntry.getName()
737 + " has changed", Project.MSG_VERBOSE);
738 rebuild = true;
739 break;
740 }
741 }
742 }
743 } else {
744 // a file doesnt exist rebuild
745
746 log("File " + filepath + " not present in weblogic jar",
747 Project.MSG_VERBOSE);
748 rebuild = true;
749 break;
750 }
751 }
752
753 if (!rebuild) {
754 log("No rebuild needed - updating jar", Project.MSG_VERBOSE);
755 newWLJarFile = new File(weblogicJarFile.getAbsolutePath() + ".temp");
756 if (newWLJarFile.exists()) {
757 newWLJarFile.delete();
758 }
759
760 newJarStream = new JarOutputStream(new FileOutputStream(newWLJarFile));
761 newJarStream.setLevel(0);
762
763 //Copy files from old weblogic jar
764 for (Enumeration e = wlEntries.elements(); e.hasMoreElements();) {
765 byte[] buffer = new byte[1024];
766 int bytesRead;
767 InputStream is;
768 JarEntry je = (JarEntry) e.nextElement();
769
770 if (je.getCompressedSize() == -1
771 || je.getCompressedSize() == je.getSize()) {
772 newJarStream.setLevel(0);
773 } else {
774 newJarStream.setLevel(9);
775 }
776
777 // Update with changed Bean class
778 if (replaceEntries.containsKey(je.getName())) {
779 log("Updating Bean class from generic Jar "
780 + je.getName(), Project.MSG_VERBOSE);
781 // Use the entry from the generic jar
782 je = (JarEntry) replaceEntries.get(je.getName());
783 is = genericJar.getInputStream(je);
784 } else {
785 //use fle from original weblogic jar
786
787 is = wlJar.getInputStream(je);
788 }
789 newJarStream.putNextEntry(new JarEntry(je.getName()));
790
791 while ((bytesRead = is.read(buffer)) != -1) {
792 newJarStream.write(buffer, 0, bytesRead);
793 }
794 is.close();
795 }
796 } else {
797 log("Weblogic Jar rebuild needed due to changed "
798 + "interface or XML", Project.MSG_VERBOSE);
799 }
800
801 if (genericLoader instanceof AntClassLoader) {
802 AntClassLoader loader = (AntClassLoader) genericLoader;
803 loader.cleanup();
804 }
805 } else {
806 rebuild = true;
807 }
808 } catch (ClassNotFoundException cnfe) {
809 String cnfmsg = "ClassNotFoundException while processing ejb-jar file"
810 + ". Details: "
811 + cnfe.getMessage();
812
813 throw new BuildException(cnfmsg, cnfe);
814 } catch (IOException ioe) {
815 String msg = "IOException while processing ejb-jar file "
816 + ". Details: "
817 + ioe.getMessage();
818
819 throw new BuildException(msg, ioe);
820 } finally {
821 // need to close files and perhaps rename output
822 if (genericJar != null) {
823 try {
824 genericJar.close();
825 } catch (IOException closeException) {
826 }
827 }
828
829 if (wlJar != null) {
830 try {
831 wlJar.close();
832 } catch (IOException closeException) {
833 }
834 }
835
836 if (newJarStream != null) {
837 try {
838 newJarStream.close();
839 } catch (IOException closeException) {
840 }
841
842 try {
843 fileUtils.rename(newWLJarFile, weblogicJarFile);
844 } catch (IOException renameException) {
845 log(renameException.getMessage(), Project.MSG_WARN);
846 rebuild = true;
847 }
848 }
849 }
850
851 return rebuild;
852 }
853
854
855 /**
856 * Helper method invoked by isRebuildRequired to get a ClassLoader for a
857 * Jar File passed to it.
858 *
859 * @param classjar java.io.File representing jar file to get classes from.
860 */
861 protected ClassLoader getClassLoaderFromJar(File classjar) throws IOException {
862 Path lookupPath = new Path(getTask().getProject());
863
864 lookupPath.setLocation(classjar);
865
866 Path classpath = getCombinedClasspath();
867
868 if (classpath != null) {
869 lookupPath.append(classpath);
870 }
871
872 return getTask().getProject().createClassLoader(lookupPath);
873 }
874}
875
Note: See TracBrowser for help on using the repository browser.