1 | /*
|
---|
2 | * Copyright 2001-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.FileOutputStream;
|
---|
21 | import java.io.IOException;
|
---|
22 | import java.io.InputStream;
|
---|
23 | import java.util.Enumeration;
|
---|
24 | import java.util.Hashtable;
|
---|
25 | import java.util.Iterator;
|
---|
26 | import java.util.jar.JarEntry;
|
---|
27 | import java.util.jar.JarFile;
|
---|
28 | import java.util.jar.JarOutputStream;
|
---|
29 | import org.apache.tools.ant.BuildException;
|
---|
30 | import org.apache.tools.ant.Project;
|
---|
31 | import org.apache.tools.ant.taskdefs.Java;
|
---|
32 | import org.apache.tools.ant.types.EnumeratedAttribute;
|
---|
33 | import org.apache.tools.ant.types.Environment;
|
---|
34 | import org.apache.tools.ant.types.Path;
|
---|
35 | import org.apache.tools.ant.util.FileUtils;
|
---|
36 |
|
---|
37 | /**
|
---|
38 | * Websphere deployment tool that augments the ejbjar task.
|
---|
39 | * Searches for the websphere specific deployment descriptors and
|
---|
40 | * adds them to the final ejb jar file. Websphere has two specific descriptors for session
|
---|
41 | * beans:
|
---|
42 | * <ul>
|
---|
43 | * <li>ibm-ejb-jar-bnd.xmi</li>
|
---|
44 | * <li>ibm-ejb-jar-ext.xmi</li>
|
---|
45 | * </ul>
|
---|
46 | * and another two for container managed entity beans:
|
---|
47 | * <ul>
|
---|
48 | * <li>Map.mapxmi</li>
|
---|
49 | * <li>Schema.dbxmi</li>
|
---|
50 | * </ul>
|
---|
51 | * In terms of WebSphere, the generation of container code and stubs is
|
---|
52 | * called <code>deployment</code>. This step can be performed by the websphere
|
---|
53 | * element as part of the jar generation process. If the switch
|
---|
54 | * <code>ejbdeploy</code> is on, the ejbdeploy tool from the websphere toolset
|
---|
55 | * is called for every ejb-jar. Unfortunately, this step only works, if you
|
---|
56 | * use the ibm jdk. Otherwise, the rmic (called by ejbdeploy) throws a
|
---|
57 | * ClassFormatError. Be sure to switch ejbdeploy off, if run ant with
|
---|
58 | * sun jdk.
|
---|
59 | *
|
---|
60 | */
|
---|
61 | public class WebsphereDeploymentTool extends GenericDeploymentTool {
|
---|
62 | /**
|
---|
63 | * Enumerated attribute with the values for the database vendor types
|
---|
64 | *
|
---|
65 | */
|
---|
66 | public static class DBVendor extends EnumeratedAttribute {
|
---|
67 | public String[] getValues() {
|
---|
68 | return new String[]{
|
---|
69 | "SQL92", "SQL99", "DB2UDBWIN_V71", "DB2UDBOS390_V6", "DB2UDBAS400_V4R5",
|
---|
70 | "ORACLE_V8", "INFORMIX_V92", "SYBASE_V1192", "MSSQLSERVER_V7", "MYSQL_V323"
|
---|
71 | };
|
---|
72 | }
|
---|
73 | }
|
---|
74 |
|
---|
75 |
|
---|
76 | public static final String PUBLICID_EJB11
|
---|
77 | = "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 1.1//EN";
|
---|
78 | public static final String PUBLICID_EJB20
|
---|
79 | = "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN";
|
---|
80 | protected static final String SCHEMA_DIR = "Schema/";
|
---|
81 |
|
---|
82 | protected static final String WAS_EXT = "ibm-ejb-jar-ext.xmi";
|
---|
83 | protected static final String WAS_BND = "ibm-ejb-jar-bnd.xmi";
|
---|
84 | protected static final String WAS_CMP_MAP = "Map.mapxmi";
|
---|
85 | protected static final String WAS_CMP_SCHEMA = "Schema.dbxmi";
|
---|
86 |
|
---|
87 | /** Instance variable that stores the suffix for the websphere jarfile. */
|
---|
88 | private String jarSuffix = ".jar";
|
---|
89 |
|
---|
90 | /** Instance variable that stores the location of the ejb 1.1 DTD file. */
|
---|
91 | private String ejb11DTD;
|
---|
92 |
|
---|
93 | /** Instance variable that determines whether generic ejb jars are kept. */
|
---|
94 |
|
---|
95 | private boolean keepGeneric = false;
|
---|
96 |
|
---|
97 | private boolean alwaysRebuild = true;
|
---|
98 |
|
---|
99 | private boolean ejbdeploy = true;
|
---|
100 |
|
---|
101 | /** Indicates if the old CMP location convention is to be used. */
|
---|
102 | private boolean newCMP = false;
|
---|
103 |
|
---|
104 | /** The classpath to the websphere classes. */
|
---|
105 | private Path wasClasspath = null;
|
---|
106 |
|
---|
107 | /** The DB Vendor name, the EJB is persisted against */
|
---|
108 | private String dbVendor;
|
---|
109 |
|
---|
110 | /** The name of the database to create. (For top-down mapping only) */
|
---|
111 | private String dbName;
|
---|
112 |
|
---|
113 | /** The name of the schema to create. (For top-down mappings only) */
|
---|
114 | private String dbSchema;
|
---|
115 |
|
---|
116 | /** true - Only generate the deployment code, do not run RMIC or Javac */
|
---|
117 | private boolean codegen;
|
---|
118 |
|
---|
119 | /** true - Only output error messages, suppress informational messages */
|
---|
120 | private boolean quiet = true;
|
---|
121 |
|
---|
122 | /** true - Disable the validation steps */
|
---|
123 | private boolean novalidate;
|
---|
124 |
|
---|
125 | /** true - Disable warning and informational messages */
|
---|
126 | private boolean nowarn;
|
---|
127 |
|
---|
128 | /** true - Disable informational messages */
|
---|
129 | private boolean noinform;
|
---|
130 |
|
---|
131 | /** true - Enable internal tracing */
|
---|
132 | private boolean trace;
|
---|
133 |
|
---|
134 | /** Additional options for RMIC */
|
---|
135 | private String rmicOptions;
|
---|
136 |
|
---|
137 | /** true- Use the WebSphere 3.5 compatible mapping rules */
|
---|
138 | private boolean use35MappingRules;
|
---|
139 |
|
---|
140 | /** the scratchdir for the ejbdeploy operation */
|
---|
141 | private String tempdir = "_ejbdeploy_temp";
|
---|
142 |
|
---|
143 | /** the home directory for websphere */
|
---|
144 | private File websphereHome;
|
---|
145 |
|
---|
146 | /** Get the classpath to the websphere classpaths */
|
---|
147 | public Path createWASClasspath() {
|
---|
148 | if (wasClasspath == null) {
|
---|
149 | wasClasspath = new Path(getTask().getProject());
|
---|
150 | }
|
---|
151 | return wasClasspath.createPath();
|
---|
152 | }
|
---|
153 |
|
---|
154 |
|
---|
155 | public void setWASClasspath(Path wasClasspath) {
|
---|
156 | this.wasClasspath = wasClasspath;
|
---|
157 | }
|
---|
158 |
|
---|
159 |
|
---|
160 | /** Sets the DB Vendor for the Entity Bean mapping ; optional.
|
---|
161 | * Valid options are for example:
|
---|
162 | * <ul>
|
---|
163 | * <li>SQL92</li> <li>SQL99</li> <li>DB2UDBWIN_V71</li>
|
---|
164 | * <li>DB2UDBOS390_V6</li> <li>DB2UDBAS400_V4R5</li> <li>ORACLE_V8</li>
|
---|
165 | * <li>INFORMIX_V92</li> <li>SYBASE_V1192</li> <li>MYSQL_V323</li>
|
---|
166 | * </ul>
|
---|
167 | * This is also used to determine the name of the Map.mapxmi and
|
---|
168 | * Schema.dbxmi files, for example Account-DB2UDBWIN_V71-Map.mapxmi
|
---|
169 | * and Account-DB2UDBWIN_V71-Schema.dbxmi.
|
---|
170 | */
|
---|
171 | public void setDbvendor(DBVendor dbvendor) {
|
---|
172 | this.dbVendor = dbvendor.getValue();
|
---|
173 | }
|
---|
174 |
|
---|
175 |
|
---|
176 | /**
|
---|
177 | * Sets the name of the Database to create; optional.
|
---|
178 | *
|
---|
179 | * @param dbName name of the database
|
---|
180 | */
|
---|
181 | public void setDbname(String dbName) {
|
---|
182 | this.dbName = dbName;
|
---|
183 | }
|
---|
184 |
|
---|
185 |
|
---|
186 | /**
|
---|
187 | * Sets the name of the schema to create; optional.
|
---|
188 | *
|
---|
189 | * @param dbSchema name of the schema
|
---|
190 | */
|
---|
191 | public void setDbschema(String dbSchema) {
|
---|
192 | this.dbSchema = dbSchema;
|
---|
193 | }
|
---|
194 |
|
---|
195 |
|
---|
196 | /**
|
---|
197 | * Flag, default false, to only generate the deployment
|
---|
198 | * code, do not run RMIC or Javac
|
---|
199 | *
|
---|
200 | * @param codegen option
|
---|
201 | */
|
---|
202 | public void setCodegen(boolean codegen) {
|
---|
203 | this.codegen = codegen;
|
---|
204 | }
|
---|
205 |
|
---|
206 |
|
---|
207 | /**
|
---|
208 | * Flag, default true, to only output error messages.
|
---|
209 | *
|
---|
210 | * @param quiet option
|
---|
211 | */
|
---|
212 | public void setQuiet(boolean quiet) {
|
---|
213 | this.quiet = quiet;
|
---|
214 | }
|
---|
215 |
|
---|
216 |
|
---|
217 | /**
|
---|
218 | * Flag to disable the validation steps; optional, default false.
|
---|
219 | *
|
---|
220 | * @param novalidate option
|
---|
221 | */
|
---|
222 | public void setNovalidate(boolean novalidate) {
|
---|
223 | this.novalidate = novalidate;
|
---|
224 | }
|
---|
225 |
|
---|
226 |
|
---|
227 | /**
|
---|
228 | * Flag to disable warning and informational messages; optional, default false.
|
---|
229 | *
|
---|
230 | * @param nowarn option
|
---|
231 | */
|
---|
232 | public void setNowarn(boolean nowarn) {
|
---|
233 | this.nowarn = nowarn;
|
---|
234 | }
|
---|
235 |
|
---|
236 |
|
---|
237 | /**
|
---|
238 | * Flag to disable informational messages; optional, default false.
|
---|
239 | *
|
---|
240 | * @param noinform if true disables informational messages
|
---|
241 | */
|
---|
242 | public void setNoinform(boolean noinform) {
|
---|
243 | this.noinform = noinform;
|
---|
244 | }
|
---|
245 |
|
---|
246 |
|
---|
247 | /**
|
---|
248 | * Flag to enable internal tracing when set, optional, default false.
|
---|
249 | *
|
---|
250 | * @param trace
|
---|
251 | */
|
---|
252 | public void setTrace(boolean trace) {
|
---|
253 | this.trace = trace;
|
---|
254 | }
|
---|
255 |
|
---|
256 | /**
|
---|
257 | * Set the rmic options.
|
---|
258 | *
|
---|
259 | * @param options
|
---|
260 | */
|
---|
261 | public void setRmicoptions(String options) {
|
---|
262 | this.rmicOptions = options;
|
---|
263 | }
|
---|
264 |
|
---|
265 | /**
|
---|
266 | * Flag to use the WebSphere 3.5 compatible mapping rules ; optional, default false.
|
---|
267 | *
|
---|
268 | * @param attr
|
---|
269 | */
|
---|
270 | public void setUse35(boolean attr) {
|
---|
271 | use35MappingRules = attr;
|
---|
272 | }
|
---|
273 |
|
---|
274 |
|
---|
275 | /**
|
---|
276 | * Set the rebuild flag to false to only update changes in the jar rather
|
---|
277 | * than rerunning ejbdeploy; optional, default true.
|
---|
278 | */
|
---|
279 | public void setRebuild(boolean rebuild) {
|
---|
280 | this.alwaysRebuild = rebuild;
|
---|
281 | }
|
---|
282 |
|
---|
283 |
|
---|
284 | /**
|
---|
285 | * String value appended to the basename of the deployment
|
---|
286 | * descriptor to create the filename of the WebLogic EJB
|
---|
287 | * jar file. Optional, default '.jar'.
|
---|
288 | * @param inString the string to use as the suffix.
|
---|
289 | */
|
---|
290 | public void setSuffix(String inString) {
|
---|
291 | this.jarSuffix = inString;
|
---|
292 | }
|
---|
293 |
|
---|
294 |
|
---|
295 | /**
|
---|
296 | * This controls whether the generic file used as input to
|
---|
297 | * ejbdeploy is retained; optional, default false.
|
---|
298 | * @param inValue either 'true' or 'false'.
|
---|
299 | */
|
---|
300 | public void setKeepgeneric(boolean inValue) {
|
---|
301 | this.keepGeneric = inValue;
|
---|
302 | }
|
---|
303 |
|
---|
304 |
|
---|
305 | /**
|
---|
306 | * Decide, wether ejbdeploy should be called or not;
|
---|
307 | * optional, default true.
|
---|
308 | *
|
---|
309 | * @param ejbdeploy
|
---|
310 | */
|
---|
311 | public void setEjbdeploy(boolean ejbdeploy) {
|
---|
312 | this.ejbdeploy = ejbdeploy;
|
---|
313 | }
|
---|
314 |
|
---|
315 |
|
---|
316 | /**
|
---|
317 | * Setter used to store the location of the Sun's Generic EJB DTD. This
|
---|
318 | * can be a file on the system or a resource on the classpath.
|
---|
319 | *
|
---|
320 | * @param inString the string to use as the DTD location.
|
---|
321 | */
|
---|
322 | public void setEJBdtd(String inString) {
|
---|
323 | this.ejb11DTD = inString;
|
---|
324 | }
|
---|
325 |
|
---|
326 |
|
---|
327 | /**
|
---|
328 | * Set the value of the oldCMP scheme. This is an antonym for newCMP
|
---|
329 | * @ant.attribute ignore="true"
|
---|
330 | */
|
---|
331 | public void setOldCMP(boolean oldCMP) {
|
---|
332 | this.newCMP = !oldCMP;
|
---|
333 | }
|
---|
334 |
|
---|
335 |
|
---|
336 | /**
|
---|
337 | * Set the value of the newCMP scheme. The old CMP scheme locates the
|
---|
338 | * websphere CMP descriptor based on the naming convention where the
|
---|
339 | * websphere CMP file is expected to be named with the bean name as the
|
---|
340 | * prefix. Under this scheme the name of the CMP descriptor does not match
|
---|
341 | * the name actually used in the main websphere EJB descriptor. Also,
|
---|
342 | * descriptors which contain multiple CMP references could not be used.
|
---|
343 | */
|
---|
344 | public void setNewCMP(boolean newCMP) {
|
---|
345 | this.newCMP = newCMP;
|
---|
346 | }
|
---|
347 |
|
---|
348 |
|
---|
349 | /**
|
---|
350 | * The directory, where ejbdeploy will write temporary files;
|
---|
351 | * optional, defaults to '_ejbdeploy_temp'.
|
---|
352 | */
|
---|
353 |
|
---|
354 | public void setTempdir(String tempdir) {
|
---|
355 | this.tempdir = tempdir;
|
---|
356 | }
|
---|
357 |
|
---|
358 |
|
---|
359 | protected DescriptorHandler getDescriptorHandler(File srcDir) {
|
---|
360 | DescriptorHandler handler = new DescriptorHandler(getTask(), srcDir);
|
---|
361 | // register all the DTDs, both the ones that are known and
|
---|
362 | // any supplied by the user
|
---|
363 | handler.registerDTD(PUBLICID_EJB11, ejb11DTD);
|
---|
364 |
|
---|
365 | for (Iterator i = getConfig().dtdLocations.iterator(); i.hasNext();) {
|
---|
366 | EjbJar.DTDLocation dtdLocation = (EjbJar.DTDLocation) i.next();
|
---|
367 |
|
---|
368 | handler.registerDTD(dtdLocation.getPublicId(), dtdLocation.getLocation());
|
---|
369 | }
|
---|
370 |
|
---|
371 | return handler;
|
---|
372 | }
|
---|
373 |
|
---|
374 |
|
---|
375 | protected DescriptorHandler getWebsphereDescriptorHandler(final File srcDir) {
|
---|
376 | DescriptorHandler handler =
|
---|
377 | new DescriptorHandler(getTask(), srcDir) {
|
---|
378 | protected void processElement() {
|
---|
379 | }
|
---|
380 | };
|
---|
381 |
|
---|
382 | for (Iterator i = getConfig().dtdLocations.iterator(); i.hasNext();) {
|
---|
383 | EjbJar.DTDLocation dtdLocation = (EjbJar.DTDLocation) i.next();
|
---|
384 |
|
---|
385 | handler.registerDTD(dtdLocation.getPublicId(), dtdLocation.getLocation());
|
---|
386 | }
|
---|
387 | return handler;
|
---|
388 | }
|
---|
389 |
|
---|
390 |
|
---|
391 | /**
|
---|
392 | * Add any vendor specific files which should be included in the EJB Jar.
|
---|
393 | */
|
---|
394 | protected void addVendorFiles(Hashtable ejbFiles, String baseName) {
|
---|
395 |
|
---|
396 | String ddPrefix = (usingBaseJarName() ? "" : baseName);
|
---|
397 | String dbPrefix = (dbVendor == null) ? "" : dbVendor + "-";
|
---|
398 |
|
---|
399 | // Get the Extensions document
|
---|
400 | File websphereEXT = new File(getConfig().descriptorDir, ddPrefix + WAS_EXT);
|
---|
401 |
|
---|
402 | if (websphereEXT.exists()) {
|
---|
403 | ejbFiles.put(META_DIR + WAS_EXT,
|
---|
404 | websphereEXT);
|
---|
405 | } else {
|
---|
406 | log("Unable to locate websphere extensions. "
|
---|
407 | + "It was expected to be in "
|
---|
408 | + websphereEXT.getPath(), Project.MSG_VERBOSE);
|
---|
409 | }
|
---|
410 |
|
---|
411 | File websphereBND = new File(getConfig().descriptorDir, ddPrefix + WAS_BND);
|
---|
412 |
|
---|
413 | if (websphereBND.exists()) {
|
---|
414 | ejbFiles.put(META_DIR + WAS_BND,
|
---|
415 | websphereBND);
|
---|
416 | } else {
|
---|
417 | log("Unable to locate websphere bindings. "
|
---|
418 | + "It was expected to be in "
|
---|
419 | + websphereBND.getPath(), Project.MSG_VERBOSE);
|
---|
420 | }
|
---|
421 |
|
---|
422 | if (!newCMP) {
|
---|
423 | log("The old method for locating CMP files has been DEPRECATED.",
|
---|
424 | Project.MSG_VERBOSE);
|
---|
425 | log("Please adjust your websphere descriptor and set "
|
---|
426 | + "newCMP=\"true\" to use the new CMP descriptor "
|
---|
427 | + "inclusion mechanism. ", Project.MSG_VERBOSE);
|
---|
428 | } else {
|
---|
429 | // We attempt to put in the MAP and Schema files of CMP beans
|
---|
430 | try {
|
---|
431 | // Add the Map file
|
---|
432 | File websphereMAP = new File(getConfig().descriptorDir,
|
---|
433 | ddPrefix + dbPrefix + WAS_CMP_MAP);
|
---|
434 |
|
---|
435 | if (websphereMAP.exists()) {
|
---|
436 | ejbFiles.put(META_DIR + WAS_CMP_MAP,
|
---|
437 | websphereMAP);
|
---|
438 | } else {
|
---|
439 | log("Unable to locate the websphere Map: "
|
---|
440 | + websphereMAP.getPath(), Project.MSG_VERBOSE);
|
---|
441 | }
|
---|
442 |
|
---|
443 | File websphereSchema = new File(getConfig().descriptorDir,
|
---|
444 | ddPrefix + dbPrefix + WAS_CMP_SCHEMA);
|
---|
445 |
|
---|
446 | if (websphereSchema.exists()) {
|
---|
447 | ejbFiles.put(META_DIR + SCHEMA_DIR + WAS_CMP_SCHEMA,
|
---|
448 | websphereSchema);
|
---|
449 | } else {
|
---|
450 | log("Unable to locate the websphere Schema: "
|
---|
451 | + websphereSchema.getPath(), Project.MSG_VERBOSE);
|
---|
452 | }
|
---|
453 | // Theres nothing else to see here...keep moving sonny
|
---|
454 | } catch (Exception e) {
|
---|
455 | String msg = "Exception while adding Vendor specific files: "
|
---|
456 | + e.toString();
|
---|
457 |
|
---|
458 | throw new BuildException(msg, e);
|
---|
459 | }
|
---|
460 | }
|
---|
461 | }
|
---|
462 |
|
---|
463 |
|
---|
464 | /**
|
---|
465 | * Get the vendor specific name of the Jar that will be output. The
|
---|
466 | * modification date of this jar will be checked against the dependent
|
---|
467 | * bean classes.
|
---|
468 | */
|
---|
469 | File getVendorOutputJarFile(String baseName) {
|
---|
470 | return new File(getDestDir(), baseName + jarSuffix);
|
---|
471 | }
|
---|
472 |
|
---|
473 |
|
---|
474 | /**
|
---|
475 | * Gets the options for the EJB Deploy operation
|
---|
476 | *
|
---|
477 | * @return String
|
---|
478 | */
|
---|
479 | protected String getOptions() {
|
---|
480 | // Set the options
|
---|
481 | StringBuffer options = new StringBuffer();
|
---|
482 |
|
---|
483 | if (dbVendor != null) {
|
---|
484 | options.append(" -dbvendor ").append(dbVendor);
|
---|
485 | }
|
---|
486 | if (dbName != null) {
|
---|
487 | options.append(" -dbname \"").append(dbName).append("\"");
|
---|
488 | }
|
---|
489 |
|
---|
490 | if (dbSchema != null) {
|
---|
491 | options.append(" -dbschema \"").append(dbSchema).append("\"");
|
---|
492 | }
|
---|
493 |
|
---|
494 | if (codegen) {
|
---|
495 | options.append(" -codegen");
|
---|
496 | }
|
---|
497 |
|
---|
498 | if (quiet) {
|
---|
499 | options.append(" -quiet");
|
---|
500 | }
|
---|
501 |
|
---|
502 | if (novalidate) {
|
---|
503 | options.append(" -novalidate");
|
---|
504 | }
|
---|
505 |
|
---|
506 | if (nowarn) {
|
---|
507 | options.append(" -nowarn");
|
---|
508 | }
|
---|
509 |
|
---|
510 | if (noinform) {
|
---|
511 | options.append(" -noinform");
|
---|
512 | }
|
---|
513 |
|
---|
514 | if (trace) {
|
---|
515 | options.append(" -trace");
|
---|
516 | }
|
---|
517 |
|
---|
518 | if (use35MappingRules) {
|
---|
519 | options.append(" -35");
|
---|
520 | }
|
---|
521 |
|
---|
522 | if (rmicOptions != null) {
|
---|
523 | options.append(" -rmic \"").append(rmicOptions).append("\"");
|
---|
524 | }
|
---|
525 |
|
---|
526 | return options.toString();
|
---|
527 | }
|
---|
528 |
|
---|
529 |
|
---|
530 | /**
|
---|
531 | * Helper method invoked by execute() for each websphere jar to be built.
|
---|
532 | * Encapsulates the logic of constructing a java task for calling
|
---|
533 | * websphere.ejbdeploy and executing it.
|
---|
534 | *
|
---|
535 | * @param sourceJar java.io.File representing the source (EJB1.1) jarfile.
|
---|
536 | * @param destJar java.io.File representing the destination, websphere
|
---|
537 | * jarfile.
|
---|
538 | */
|
---|
539 | private void buildWebsphereJar(File sourceJar, File destJar) {
|
---|
540 | try {
|
---|
541 | if (ejbdeploy) {
|
---|
542 | Java javaTask = (Java) getTask().getProject().createTask("java");
|
---|
543 | // Set the JvmArgs
|
---|
544 | javaTask.createJvmarg().setValue("-Xms64m");
|
---|
545 | javaTask.createJvmarg().setValue("-Xmx128m");
|
---|
546 |
|
---|
547 | // Set the Environment variable
|
---|
548 | Environment.Variable var = new Environment.Variable();
|
---|
549 |
|
---|
550 | var.setKey("websphere.lib.dir");
|
---|
551 | File libdir = new File(websphereHome, "lib");
|
---|
552 | var.setValue(libdir.getAbsolutePath());
|
---|
553 | javaTask.addSysproperty(var);
|
---|
554 |
|
---|
555 | // Set the working directory
|
---|
556 | javaTask.setDir(websphereHome);
|
---|
557 |
|
---|
558 | // Set the Java class name
|
---|
559 | javaTask.setTaskName("ejbdeploy");
|
---|
560 | javaTask.setClassname("com.ibm.etools.ejbdeploy.EJBDeploy");
|
---|
561 |
|
---|
562 | javaTask.createArg().setValue(sourceJar.getPath());
|
---|
563 | javaTask.createArg().setValue(tempdir);
|
---|
564 | javaTask.createArg().setValue(destJar.getPath());
|
---|
565 | javaTask.createArg().setLine(getOptions());
|
---|
566 | if (getCombinedClasspath() != null
|
---|
567 | && getCombinedClasspath().toString().length() > 0) {
|
---|
568 | javaTask.createArg().setValue("-cp");
|
---|
569 | javaTask.createArg().setValue(getCombinedClasspath().toString());
|
---|
570 | }
|
---|
571 |
|
---|
572 | Path classpath = wasClasspath;
|
---|
573 |
|
---|
574 | if (classpath == null) {
|
---|
575 | classpath = getCombinedClasspath();
|
---|
576 | }
|
---|
577 |
|
---|
578 | if (classpath != null) {
|
---|
579 | javaTask.setClasspath(classpath);
|
---|
580 | javaTask.setFork(true);
|
---|
581 | } else {
|
---|
582 | javaTask.setFork(true);
|
---|
583 | }
|
---|
584 |
|
---|
585 | log("Calling websphere.ejbdeploy for " + sourceJar.toString(),
|
---|
586 | Project.MSG_VERBOSE);
|
---|
587 |
|
---|
588 | javaTask.execute();
|
---|
589 | }
|
---|
590 | } catch (Exception e) {
|
---|
591 | // Have to catch this because of the semantics of calling main()
|
---|
592 | String msg = "Exception while calling ejbdeploy. Details: " + e.toString();
|
---|
593 |
|
---|
594 | throw new BuildException(msg, e);
|
---|
595 | }
|
---|
596 | }
|
---|
597 |
|
---|
598 |
|
---|
599 | /**
|
---|
600 | * Method used to encapsulate the writing of the JAR file. Iterates over
|
---|
601 | * the filenames/java.io.Files in the Hashtable stored on the instance
|
---|
602 | * variable ejbFiles.
|
---|
603 | */
|
---|
604 | protected void writeJar(String baseName, File jarFile, Hashtable files, String publicId)
|
---|
605 | throws BuildException {
|
---|
606 | if (ejbdeploy) {
|
---|
607 | // create the -generic.jar, if required
|
---|
608 | File genericJarFile = super.getVendorOutputJarFile(baseName);
|
---|
609 |
|
---|
610 | super.writeJar(baseName, genericJarFile, files, publicId);
|
---|
611 |
|
---|
612 | // create the output .jar, if required
|
---|
613 | if (alwaysRebuild || isRebuildRequired(genericJarFile, jarFile)) {
|
---|
614 | buildWebsphereJar(genericJarFile, jarFile);
|
---|
615 | }
|
---|
616 | if (!keepGeneric) {
|
---|
617 | log("deleting generic jar " + genericJarFile.toString(),
|
---|
618 | Project.MSG_VERBOSE);
|
---|
619 | genericJarFile.delete();
|
---|
620 | }
|
---|
621 | } else {
|
---|
622 | // create the "undeployed" output .jar, if required
|
---|
623 | super.writeJar(baseName, jarFile, files, publicId);
|
---|
624 | }
|
---|
625 | }
|
---|
626 |
|
---|
627 |
|
---|
628 | /**
|
---|
629 | * Called to validate that the tool parameters have been configured.
|
---|
630 | */
|
---|
631 | public void validateConfigured() throws BuildException {
|
---|
632 | super.validateConfigured();
|
---|
633 | if (ejbdeploy) {
|
---|
634 | String home = getTask().getProject().getProperty("websphere.home");
|
---|
635 | if (home == null) {
|
---|
636 | throw new BuildException("The 'websphere.home' property must "
|
---|
637 | + "be set when 'ejbdeploy=true'");
|
---|
638 | }
|
---|
639 | websphereHome = getTask().getProject().resolveFile(home);
|
---|
640 | }
|
---|
641 | }
|
---|
642 |
|
---|
643 |
|
---|
644 | /**
|
---|
645 | * Helper method to check to see if a websphere EBJ1.1 jar needs to be
|
---|
646 | * rebuilt using ejbdeploy. Called from writeJar it sees if the "Bean"
|
---|
647 | * classes are the only thing that needs to be updated and either updates
|
---|
648 | * the Jar with the Bean classfile or returns true, saying that the whole
|
---|
649 | * websphere jar needs to be regened with ejbdeploy. This allows faster
|
---|
650 | * build times for working developers. <p>
|
---|
651 | *
|
---|
652 | * The way websphere ejbdeploy works is it creates wrappers for the
|
---|
653 | * publicly defined methods as they are exposed in the remote interface.
|
---|
654 | * If the actual bean changes without changing the the method signatures
|
---|
655 | * then only the bean classfile needs to be updated and the rest of the
|
---|
656 | * websphere jar file can remain the same. If the Interfaces, ie. the
|
---|
657 | * method signatures change or if the xml deployment descriptors changed,
|
---|
658 | * the whole jar needs to be rebuilt with ejbdeploy. This is not strictly
|
---|
659 | * true for the xml files. If the JNDI name changes then the jar doesnt
|
---|
660 | * have to be rebuild, but if the resources references change then it
|
---|
661 | * does. At this point the websphere jar gets rebuilt if the xml files
|
---|
662 | * change at all.
|
---|
663 | *
|
---|
664 | * @param genericJarFile java.io.File The generic jar file.
|
---|
665 | * @param websphereJarFile java.io.File The websphere jar file to check to
|
---|
666 | * see if it needs to be rebuilt.
|
---|
667 | */
|
---|
668 | protected boolean isRebuildRequired(File genericJarFile, File websphereJarFile) {
|
---|
669 | boolean rebuild = false;
|
---|
670 |
|
---|
671 | JarFile genericJar = null;
|
---|
672 | JarFile wasJar = null;
|
---|
673 | File newwasJarFile = null;
|
---|
674 | JarOutputStream newJarStream = null;
|
---|
675 |
|
---|
676 | try {
|
---|
677 | log("Checking if websphere Jar needs to be rebuilt for jar "
|
---|
678 | + websphereJarFile.getName(), Project.MSG_VERBOSE);
|
---|
679 | // Only go forward if the generic and the websphere file both exist
|
---|
680 | if (genericJarFile.exists() && genericJarFile.isFile()
|
---|
681 | && websphereJarFile.exists() && websphereJarFile.isFile()) {
|
---|
682 | //open jar files
|
---|
683 | genericJar = new JarFile(genericJarFile);
|
---|
684 | wasJar = new JarFile(websphereJarFile);
|
---|
685 |
|
---|
686 | Hashtable genericEntries = new Hashtable();
|
---|
687 | Hashtable wasEntries = new Hashtable();
|
---|
688 | Hashtable replaceEntries = new Hashtable();
|
---|
689 |
|
---|
690 | //get the list of generic jar entries
|
---|
691 | for (Enumeration e = genericJar.entries(); e.hasMoreElements();) {
|
---|
692 | JarEntry je = (JarEntry) e.nextElement();
|
---|
693 |
|
---|
694 | genericEntries.put(je.getName().replace('\\', '/'), je);
|
---|
695 | }
|
---|
696 | //get the list of websphere jar entries
|
---|
697 | for (Enumeration e = wasJar.entries(); e.hasMoreElements();) {
|
---|
698 | JarEntry je = (JarEntry) e.nextElement();
|
---|
699 |
|
---|
700 | wasEntries.put(je.getName(), je);
|
---|
701 | }
|
---|
702 |
|
---|
703 | //Cycle Through generic and make sure its in websphere
|
---|
704 | ClassLoader genericLoader = getClassLoaderFromJar(genericJarFile);
|
---|
705 |
|
---|
706 | for (Enumeration e = genericEntries.keys(); e.hasMoreElements();) {
|
---|
707 | String filepath = (String) e.nextElement();
|
---|
708 |
|
---|
709 | if (wasEntries.containsKey(filepath)) {
|
---|
710 | // File name/path match
|
---|
711 | // Check files see if same
|
---|
712 | JarEntry genericEntry = (JarEntry) genericEntries.get(filepath);
|
---|
713 | JarEntry wasEntry = (JarEntry) wasEntries.get(filepath);
|
---|
714 |
|
---|
715 | if ((genericEntry.getCrc() != wasEntry.getCrc())
|
---|
716 | || (genericEntry.getSize() != wasEntry.getSize())) {
|
---|
717 |
|
---|
718 | if (genericEntry.getName().endsWith(".class")) {
|
---|
719 | //File are different see if its an object or an interface
|
---|
720 | String classname
|
---|
721 | = genericEntry.getName().replace(File.separatorChar, '.');
|
---|
722 |
|
---|
723 | classname = classname.substring(0, classname.lastIndexOf(".class"));
|
---|
724 |
|
---|
725 | Class genclass = genericLoader.loadClass(classname);
|
---|
726 |
|
---|
727 | if (genclass.isInterface()) {
|
---|
728 | //Interface changed rebuild jar.
|
---|
729 | log("Interface " + genclass.getName()
|
---|
730 | + " has changed", Project.MSG_VERBOSE);
|
---|
731 | rebuild = true;
|
---|
732 | break;
|
---|
733 | } else {
|
---|
734 | //Object class Changed update it.
|
---|
735 | replaceEntries.put(filepath, genericEntry);
|
---|
736 | }
|
---|
737 | } else {
|
---|
738 | // is it the manifest. If so ignore it
|
---|
739 | if (!genericEntry.getName().equals("META-INF/MANIFEST.MF")) {
|
---|
740 | //File other then class changed rebuild
|
---|
741 | log("Non class file " + genericEntry.getName()
|
---|
742 | + " has changed", Project.MSG_VERBOSE);
|
---|
743 | rebuild = true;
|
---|
744 | }
|
---|
745 | break;
|
---|
746 | }
|
---|
747 | }
|
---|
748 | } else {
|
---|
749 | // a file doesn't exist rebuild
|
---|
750 |
|
---|
751 | log("File " + filepath + " not present in websphere jar",
|
---|
752 | Project.MSG_VERBOSE);
|
---|
753 | rebuild = true;
|
---|
754 | break;
|
---|
755 | }
|
---|
756 | }
|
---|
757 |
|
---|
758 | if (!rebuild) {
|
---|
759 | log("No rebuild needed - updating jar", Project.MSG_VERBOSE);
|
---|
760 | newwasJarFile = new File(websphereJarFile.getAbsolutePath() + ".temp");
|
---|
761 | if (newwasJarFile.exists()) {
|
---|
762 | newwasJarFile.delete();
|
---|
763 | }
|
---|
764 |
|
---|
765 | newJarStream = new JarOutputStream(new FileOutputStream(newwasJarFile));
|
---|
766 | newJarStream.setLevel(0);
|
---|
767 |
|
---|
768 | //Copy files from old websphere jar
|
---|
769 | for (Enumeration e = wasEntries.elements(); e.hasMoreElements();) {
|
---|
770 | byte[] buffer = new byte[1024];
|
---|
771 | int bytesRead;
|
---|
772 | InputStream is;
|
---|
773 | JarEntry je = (JarEntry) e.nextElement();
|
---|
774 |
|
---|
775 | if (je.getCompressedSize() == -1
|
---|
776 | || je.getCompressedSize() == je.getSize()) {
|
---|
777 | newJarStream.setLevel(0);
|
---|
778 | } else {
|
---|
779 | newJarStream.setLevel(9);
|
---|
780 | }
|
---|
781 |
|
---|
782 | // Update with changed Bean class
|
---|
783 | if (replaceEntries.containsKey(je.getName())) {
|
---|
784 | log("Updating Bean class from generic Jar " + je.getName(),
|
---|
785 | Project.MSG_VERBOSE);
|
---|
786 | // Use the entry from the generic jar
|
---|
787 | je = (JarEntry) replaceEntries.get(je.getName());
|
---|
788 | is = genericJar.getInputStream(je);
|
---|
789 | } else {
|
---|
790 | //use fle from original websphere jar
|
---|
791 |
|
---|
792 | is = wasJar.getInputStream(je);
|
---|
793 | }
|
---|
794 | newJarStream.putNextEntry(new JarEntry(je.getName()));
|
---|
795 |
|
---|
796 | while ((bytesRead = is.read(buffer)) != -1) {
|
---|
797 | newJarStream.write(buffer, 0, bytesRead);
|
---|
798 | }
|
---|
799 | is.close();
|
---|
800 | }
|
---|
801 | } else {
|
---|
802 | log("websphere Jar rebuild needed due to changed "
|
---|
803 | + "interface or XML", Project.MSG_VERBOSE);
|
---|
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 (wasJar != null) {
|
---|
830 | try {
|
---|
831 | wasJar.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.newFileUtils().rename(newwasJarFile,
|
---|
844 | websphereJarFile);
|
---|
845 | } catch (IOException renameException) {
|
---|
846 | log(renameException.getMessage(), Project.MSG_WARN);
|
---|
847 | rebuild = true;
|
---|
848 | }
|
---|
849 | }
|
---|
850 | }
|
---|
851 |
|
---|
852 | return rebuild;
|
---|
853 | }
|
---|
854 |
|
---|
855 |
|
---|
856 | /**
|
---|
857 | * Helper method invoked by isRebuildRequired to get a ClassLoader for a
|
---|
858 | * Jar File passed to it.
|
---|
859 | *
|
---|
860 | * @param classjar java.io.File representing jar file to get classes from.
|
---|
861 | */
|
---|
862 | protected ClassLoader getClassLoaderFromJar(File classjar) throws IOException {
|
---|
863 | Path lookupPath = new Path(getTask().getProject());
|
---|
864 |
|
---|
865 | lookupPath.setLocation(classjar);
|
---|
866 |
|
---|
867 | Path classpath = getCombinedClasspath();
|
---|
868 |
|
---|
869 | if (classpath != null) {
|
---|
870 | lookupPath.append(classpath);
|
---|
871 | }
|
---|
872 |
|
---|
873 | return getTask().getProject().createClassLoader(lookupPath);
|
---|
874 | }
|
---|
875 | }
|
---|
876 |
|
---|