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 | */
|
---|
17 | package org.apache.tools.ant.taskdefs.optional.ejb;
|
---|
18 |
|
---|
19 | import java.io.File;
|
---|
20 | import java.io.FileInputStream;
|
---|
21 | import java.io.FileOutputStream;
|
---|
22 | import java.io.IOException;
|
---|
23 | import java.io.InputStream;
|
---|
24 | import java.util.Enumeration;
|
---|
25 | import java.util.Hashtable;
|
---|
26 | import java.util.Iterator;
|
---|
27 | import java.util.Vector;
|
---|
28 | import java.util.jar.JarEntry;
|
---|
29 | import java.util.jar.JarFile;
|
---|
30 | import java.util.jar.JarOutputStream;
|
---|
31 | import javax.xml.parsers.SAXParser;
|
---|
32 | import javax.xml.parsers.SAXParserFactory;
|
---|
33 | import org.apache.tools.ant.AntClassLoader;
|
---|
34 | import org.apache.tools.ant.BuildException;
|
---|
35 | import org.apache.tools.ant.Project;
|
---|
36 | import org.apache.tools.ant.taskdefs.Java;
|
---|
37 | import org.apache.tools.ant.types.Environment;
|
---|
38 | import org.apache.tools.ant.types.Path;
|
---|
39 | import org.apache.tools.ant.util.FileUtils;
|
---|
40 | import 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 | */
|
---|
53 | public 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 "<code>default</code>"
|
---|
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 | * "weblogic.ejbc" 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 <dtd> 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 <dtd> 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 <dtd> 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 |
|
---|