001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common Development
008: * and Distribution License("CDDL") (collectively, the "License"). You
009: * may not use this file except in compliance with the License. You can obtain
010: * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
011: * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
012: * language governing permissions and limitations under the License.
013: *
014: * When distributing the software, include this License Header Notice in each
015: * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
016: * Sun designates this particular file as subject to the "Classpath" exception
017: * as provided by Sun in the GPL Version 2 section of the License file that
018: * accompanied this code. If applicable, add the following below the License
019: * Header, with the fields enclosed by brackets [] replaced by your own
020: * identifying information: "Portions Copyrighted [year]
021: * [name of copyright owner]"
022: *
023: * Contributor(s):
024: *
025: * If you wish your version of this file to be governed by only the CDDL or
026: * only the GPL Version 2, indicate your decision by adding "[Contributor]
027: * elects to include this software in this distribution under the [CDDL or GPL
028: * Version 2] license." If you don't indicate a single choice of license, a
029: * recipient has the option to distribute your version of this file under
030: * either the CDDL, the GPL Version 2 or to extend the choice of license to
031: * its licensees as provided above. However, if you add GPL Version 2 code
032: * and therefore, elected the GPL Version 2 license, then the option applies
033: * only if the new code is made subject to such option by the copyright
034: * holder.
035: */
036: package com.sun.tools.ws.ant;
037:
038: import com.sun.tools.ws.wscompile.Options;
039: import com.sun.tools.ws.wscompile.WsimportTool;
040: import org.apache.tools.ant.AntClassLoader;
041: import org.apache.tools.ant.BuildException;
042: import org.apache.tools.ant.DirectoryScanner;
043: import org.apache.tools.ant.Project;
044: import org.apache.tools.ant.taskdefs.Execute;
045: import org.apache.tools.ant.taskdefs.LogOutputStream;
046: import org.apache.tools.ant.taskdefs.LogStreamHandler;
047: import org.apache.tools.ant.taskdefs.MatchingTask;
048: import org.apache.tools.ant.types.Commandline;
049: import org.apache.tools.ant.types.CommandlineJava;
050: import org.apache.tools.ant.types.FileSet;
051: import org.apache.tools.ant.types.Path;
052: import org.apache.tools.ant.types.XMLCatalog;
053:
054: import java.io.File;
055: import java.io.IOException;
056: import java.io.PrintWriter;
057: import java.io.StringWriter;
058: import java.util.ArrayList;
059: import java.util.HashSet;
060: import java.util.List;
061: import java.util.Set;
062:
063: /**
064: * wscompile task for use with the JAXWS project.
065: *
066: */
067: public class WsImport2 extends MatchingTask {
068:
069: private final CommandlineJava cmd = new CommandlineJava();
070: /** -d option. */
071: private File destDir = null;
072:
073: /** Additional command line arguments for XJC. The equivalent of the -B option. */
074: private final Commandline xjcCmdLine = new Commandline();
075:
076: /** Enable/disable debug messages - stack trace **/
077: private boolean xdebug = false;
078:
079: public boolean isXdebug() {
080: return xdebug;
081: }
082:
083: public void setXdebug(boolean xdebug) {
084: this .xdebug = xdebug;
085: }
086:
087: /** Gets the base directory to output generated class. **/
088: public File getDestdir() {
089: return this .destDir;
090: }
091:
092: /** Sets the base directory to output generated class. **/
093: public void setDestdir(File base) {
094: this .destDir = base;
095: }
096:
097: /** wsdllocation - set @WebService.wsdlLocation and @WebServiceClient.wsdlLocation values */
098:
099: private String wsdlLocation;
100:
101: public String getWsdllocation() {
102: return wsdlLocation;
103: }
104:
105: public void setWsdllocation(String wsdlLocation) {
106: this .wsdlLocation = wsdlLocation;
107: }
108:
109: public void addConfiguredXMLCatalog(XMLCatalog entityResolver) {
110: if (this .xmlCatalog == null) {
111: this .xmlCatalog = new XMLCatalog();
112: xmlCatalog.setProject(getProject());
113: }
114: this .xmlCatalog.addConfiguredXMLCatalog(entityResolver);
115: }
116:
117: private XMLCatalog xmlCatalog;
118:
119: private String pkg;
120:
121: public void setPackage(String pkg) {
122: this .pkg = pkg;
123: }
124:
125: public String getPackage() {
126: return pkg;
127: }
128:
129: /**
130: * Adds a JVM argument.
131: *
132: * @return JVM argument created
133: */
134: public Commandline.Argument createJvmarg() {
135: return cmd.createVmArgument();
136: }
137:
138: /**
139: * Adds XJC argument.
140: *
141: * @since 2.1
142: */
143: public Commandline.Argument createXjcarg() {
144: return xjcCmdLine.createArgument();
145: }
146:
147: /********************* failonerror option ***********************/
148: /**
149: * False to continue the build even if the compilation fails.
150: */
151: private boolean failonerror = true;
152:
153: /**
154: * Mostly for our SQE teams and not to be advertized.
155: */
156: public void setFailonerror(boolean value) {
157: failonerror = value;
158: }
159:
160: /******************** -extensions option **********************/
161: protected boolean extension;
162:
163: /** Gets the "extension" flag. **/
164: public boolean getExtension() {
165: return extension;
166: }
167:
168: /** Sets the "extension" flag. **/
169: public void setExtension(boolean extension) {
170: this .extension = extension;
171: }
172:
173: public boolean getxNoAddressingDatabinding() {
174: return xNoAddressingDatabinding;
175: }
176:
177: public void setxNoAddressingDatabinding(
178: boolean xNoAddressingDatabinding) {
179: this .xNoAddressingDatabinding = xNoAddressingDatabinding;
180: }
181:
182: /**** -Xno-addressing-databinding ***/
183: protected boolean xNoAddressingDatabinding;
184:
185: /************************* -keep option *************************/
186: private boolean keep = false;
187:
188: /** Gets the "keep" flag. **/
189: public boolean getKeep() {
190: return keep;
191: }
192:
193: /** Sets the "keep" flag. **/
194: public void setKeep(boolean keep) {
195: this .keep = keep;
196: }
197:
198: /** -quiet switch **/
199: private boolean quiet = false;
200:
201: public boolean isQuiet() {
202: return quiet;
203: }
204:
205: public void setQuiet(boolean quiet) {
206: this .quiet = quiet;
207: }
208:
209: /**
210: * Sets the target version of the compilation
211: */
212: private String target;
213:
214: public void setTarget(String version) {
215: Options.Target targetVersion = Options.Target.parse(version);
216: if (targetVersion == null)
217: throw new BuildException(version
218: + " is not a valid version number");
219: target = targetVersion.getVersion();
220: }
221:
222: /************************* -fork option *************************/
223: private boolean fork = false;
224:
225: /** Gets the "fork" flag. **/
226: public boolean getFork() {
227: return fork;
228: }
229:
230: /** Sets the "fork" flag. **/
231: public void setFork(boolean fork) {
232: this .fork = fork;
233: }
234:
235: /************************* -O option *************************/
236: private boolean optimize = false;
237:
238: /** Gets the optimize flag. **/
239: public boolean getOptimize() {
240: return optimize;
241: }
242:
243: /** Sets the optimize flag. **/
244: public void setOptimize(boolean optimize) {
245: this .optimize = optimize;
246: }
247:
248: /************************* -s option *************************/
249: private File sourcedestdir;
250:
251: /** Sets the directory to place generated source java files. **/
252: public void setSourcedestdir(File sourceBase) {
253: keep = true;
254: this .sourcedestdir = sourceBase;
255: }
256:
257: /** Gets the directory to place generated source java files. **/
258: public File getSourcedestdir() {
259: return sourcedestdir;
260: }
261:
262: /************************* -verbose option *************************/
263: protected boolean verbose = false;
264:
265: /** Gets the "verbose" flag. **/
266: public boolean getVerbose() {
267: return verbose;
268: }
269:
270: /** Sets the "verbose" flag. **/
271: public void setVerbose(boolean verbose) {
272: this .verbose = verbose;
273: }
274:
275: /************************* -g option *************************/
276: private boolean debug = false;
277:
278: /** Gets the debug flag. **/
279: public boolean getDebug() {
280: return debug;
281: }
282:
283: /** Sets the debug flag. **/
284: public void setDebug(boolean debug) {
285: this .debug = debug;
286: }
287:
288: /*********************** include ant runtime **********************/
289: /** not sure if these methods are needed */
290: private boolean includeAntRuntime = false;
291:
292: /**
293: * Include ant's own classpath in this task's classpath?
294: */
295: public void setIncludeantruntime(boolean include) {
296: includeAntRuntime = include;
297: }
298:
299: /**
300: * Gets whether or not the ant classpath is to be included in the
301: * task's classpath.
302: */
303: public boolean getIncludeantruntime() {
304: return includeAntRuntime;
305: }
306:
307: /*********************** include java runtime **********************/
308: /** not sure if these methods are needed */
309: private boolean includeJavaRuntime = false;
310:
311: /**
312: * Sets whether or not to include the java runtime libraries to this
313: * task's classpath.
314: */
315: public void setIncludejavaruntime(boolean include) {
316: includeJavaRuntime = include;
317: }
318:
319: /**
320: * Gets whether or not the java runtime should be included in this
321: * task's classpath.
322: */
323: public boolean getIncludejavaruntime() {
324: return includeJavaRuntime;
325: }
326:
327: /**
328: * Files used to determine whether XJC should run or not.
329: */
330: private final ArrayList<File> dependsSet = new ArrayList<File>();
331: private final ArrayList<File> producesSet = new ArrayList<File>();
332:
333: /**
334: * Set to true once the <produces> element is used.
335: * This flag is used to issue a suggestion to users.
336: */
337: private boolean producesSpecified = false;
338:
339: /** Nested <depends> element. */
340: public void addConfiguredDepends(FileSet fs) {
341: addIndividualFilesTo(fs, dependsSet);
342: }
343:
344: /** Nested <produces> element. */
345: public void addConfiguredProduces(FileSet fs) {
346: producesSpecified = true;
347: if (!fs.getDir(getProject()).exists()) {
348: log(
349: fs.getDir(getProject()).getAbsolutePath()
350: + " is not found and thus excluded from the dependency check",
351: Project.MSG_INFO);
352: } else
353: addIndividualFilesTo(fs, producesSet);
354: }
355:
356: /**
357: * Extracts {@link File} objects that the given {@link FileSet}
358: * represents and adds them all to the given {@link java.util.List}.
359: */
360: private void addIndividualFilesTo(FileSet fs, List<File> lst) {
361: DirectoryScanner ds = fs.getDirectoryScanner(getProject());
362: String[] includedFiles = ds.getIncludedFiles();
363: File baseDir = ds.getBasedir();
364:
365: for (String value : includedFiles) {
366: lst.add(new File(baseDir, value));
367: }
368: }
369:
370: /**
371: * Determines the timestamp of the newest/oldest file in the given set.
372: */
373: private long computeTimestampFor(List<File> files,
374: boolean findNewest) {
375:
376: long lastModified = findNewest ? Long.MIN_VALUE
377: : Long.MAX_VALUE;
378:
379: for (File file : files) {
380: log("Checking timestamp of " + file.toString(),
381: Project.MSG_VERBOSE);
382:
383: if (findNewest)
384: lastModified = Math.max(lastModified, file
385: .lastModified());
386: else
387: lastModified = Math.min(lastModified, file
388: .lastModified());
389: }
390:
391: if (lastModified == Long.MIN_VALUE) // no file was found
392: return Long.MAX_VALUE; // force re-run
393:
394: if (lastModified == Long.MAX_VALUE) // no file was found
395: return Long.MIN_VALUE; // force re-run
396:
397: return lastModified;
398: }
399:
400: private String binding;
401:
402: /**
403: * @return Returns the binding.
404: */
405: public String getBinding() {
406: return binding;
407: }
408:
409: /**
410: * @param binding The binding to set.
411: */
412: public void setBinding(String binding) {
413: this .binding = binding;
414: dependsSet.add(new File(binding));
415: }
416:
417: /**
418: * Adds a new catalog file.
419: */
420: public void setCatalog(File catalog) {
421: this .catalog = catalog;
422: }
423:
424: public File getCatalog() {
425: return catalog;
426: }
427:
428: private File catalog;
429:
430: private String wsdl;
431:
432: /**
433: * @return Returns the wsdl.
434: */
435: public String getWsdl() {
436: return wsdl;
437: }
438:
439: /**
440: * @param wsdl The wsdl to set.
441: */
442: public void setWsdl(String wsdl) {
443: this .wsdl = wsdl;
444: dependsSet.add(new File(wsdl));
445: }
446:
447: public void addConfiguredBinding(FileSet fs) {
448: DirectoryScanner ds = fs.getDirectoryScanner(getProject());
449: String[] includedFiles = ds.getIncludedFiles();
450: File baseDir = ds.getBasedir();
451: for (String includedFile : includedFiles) {
452: bindingFiles.add(new File(baseDir, includedFile));
453: }
454: addIndividualFilesTo(fs, dependsSet);
455: }
456:
457: private void setupWsimportForkCommand() {
458: ClassLoader loader = this .getClass().getClassLoader();
459: while (loader != null && !(loader instanceof AntClassLoader)) {
460: loader = loader.getParent();
461: }
462:
463: if (loader != null) {
464: Path classpath = new Path(project,
465: ((AntClassLoader) loader).getClasspath());
466: cmd.createClasspath(getProject()).append(classpath);
467: }
468: cmd.setClassname("com.sun.tools.ws.WsImport");
469: //setupWsimportArgs();
470: //cmd.createArgument(true).setLine(forkCmd.toString());
471: }
472:
473: private void setupWsimportArgs() {
474: // d option
475: if (null != getDestdir() && !getDestdir().getName().equals("")) {
476: cmd.createArgument().setValue("-d");
477: cmd.createArgument().setFile(getDestdir());
478: }
479:
480: // extension flag
481: if (getExtension()) {
482: cmd.createArgument().setValue("-extension");
483: }
484:
485: if (getxNoAddressingDatabinding()) {
486: cmd.createArgument()
487: .setValue("-Xno-addressing-databinding");
488: }
489:
490: // g option
491: if (getDebug()) {
492: cmd.createArgument().setValue("-g");
493: }
494:
495: if (isXdebug()) {
496: cmd.createArgument().setValue("-Xdebug");
497: }
498:
499: // keep option
500: if (getKeep()) {
501: cmd.createArgument().setValue("-keep");
502: }
503:
504: // optimize option
505: if (getOptimize()) {
506: cmd.createArgument().setValue("-O");
507: }
508:
509: // s option
510: if (null != getSourcedestdir()
511: && !getSourcedestdir().getName().equals("")) {
512: cmd.createArgument().setValue("-s");
513: cmd.createArgument().setFile(getSourcedestdir());
514: }
515:
516: //catalog
517: if ((getCatalog() != null)
518: && (getCatalog().getName().length() > 0)) {
519: cmd.createArgument().setValue("-catalog");
520: cmd.createArgument().setFile(getCatalog());
521: }
522:
523: // verbose option
524: if (getVerbose()) {
525: cmd.createArgument().setValue("-verbose");
526: }
527:
528: if (quiet) {
529: cmd.createArgument().setValue("-quiet");
530: }
531:
532: if (target != null) {
533: cmd.createArgument().setValue("-target");
534: cmd.createArgument().setValue(target);
535: }
536:
537: //wsdl
538: if (getWsdl() != null) {
539: cmd.createArgument().setValue(getWsdl());
540: }
541:
542: //package
543: if ((getPackage() != null) && (getPackage().length() > 0)) {
544: cmd.createArgument().setValue("-p");
545: cmd.createArgument().setValue(getPackage());
546: }
547:
548: if (getBinding() != null) {
549: cmd.createArgument().setValue("-b");
550: cmd.createArgument().setValue(getBinding());
551: }
552:
553: for (String a : xjcCmdLine.getArguments()) {
554: if (a.startsWith("-")) {
555: cmd.createArgument().setValue("-B" + a);
556: } else {
557: cmd.createArgument().setValue(a);
558: }
559: }
560:
561: if ((wsdlLocation != null) && (wsdlLocation.length() != 0)) {
562: cmd.createArgument().setValue("-wsdllocation");
563: cmd.createArgument().setValue(wsdlLocation);
564: }
565:
566: if (!bindingFiles.isEmpty()) {
567: for (File binding : bindingFiles) {
568: cmd.createArgument().setValue("-b");
569: cmd.createArgument().setFile(binding);
570: }
571: }
572: }
573:
574: /** Called by the project to let the task do it's work **/
575: public void execute() throws BuildException {
576: /* Create an instance of the rmic, redirecting output to
577: * the project log
578: */
579: LogOutputStream logstr = null;
580: boolean ok = false;
581: try {
582: if (!producesSpecified) {
583: log(
584: "Consider using <depends>/<produces> so that wsimport won't do unnecessary compilation",
585: Project.MSG_INFO);
586: }
587:
588: // up to date check
589: long srcTime = computeTimestampFor(dependsSet, true);
590: long dstTime = computeTimestampFor(producesSet, false);
591: log("the last modified time of the inputs is " + srcTime,
592: Project.MSG_VERBOSE);
593: log("the last modified time of the outputs is " + dstTime,
594: Project.MSG_VERBOSE);
595:
596: if (srcTime < dstTime) {
597: log("files are up to date");
598: return;
599: }
600:
601: if (fork) {
602: setupWsimportForkCommand();
603: } else {
604: if (cmd.getVmCommand().size() > 1) {
605: log("JVM args ignored when same JVM is used.",
606: Project.MSG_WARN);
607: }
608: }
609: setupWsimportArgs();
610: if (fork) {
611: if (verbose) {
612: log("command line: " + "wsimport " + cmd.toString());
613: }
614: int status = run(cmd.getCommandline());
615: ok = (status == 0);
616: } else {
617: if (verbose) {
618: log("command line: " + "wsimport "
619: + cmd.getJavaCommand().toString());
620: }
621: logstr = new LogOutputStream(this , Project.MSG_WARN);
622:
623: ClassLoader old = Thread.currentThread()
624: .getContextClassLoader();
625: ClassLoader loader = this .getClass().getClassLoader();
626: Thread.currentThread().setContextClassLoader(loader);
627: String sysPath = System.getProperty("java.class.path");
628: try {
629: WsimportTool compTool = new WsimportTool(logstr);
630: if (xmlCatalog != null) {
631: compTool.setEntityResolver(xmlCatalog);
632: }
633: if (loader instanceof AntClassLoader) {
634: System.setProperty("java.class.path",
635: ((AntClassLoader) loader)
636: .getClasspath());
637: }
638: ok = compTool.run(cmd.getJavaCommand()
639: .getArguments());
640: } finally {
641: if (sysPath != null) {
642: System.setProperty("java.class.path", sysPath);
643: }
644: Thread.currentThread().setContextClassLoader(old);
645: }
646: }
647: if (!ok) {
648: if (!verbose) {
649: log("Command invoked: " + "wsimport "
650: + cmd.toString());
651: }
652: throw new BuildException("wsimport failed", location);
653: }
654: } catch (Exception ex) {
655: if (failonerror) {
656: if (ex instanceof BuildException) {
657: throw (BuildException) ex;
658: } else {
659: throw new BuildException(
660: "Error starting wsimport: ", ex,
661: getLocation());
662: }
663: } else {
664: StringWriter sw = new StringWriter();
665: ex.printStackTrace(new PrintWriter(sw));
666: getProject().log(sw.toString(), Project.MSG_WARN);
667: // continue
668: }
669:
670: } finally {
671: try {
672: if (logstr != null) {
673: logstr.close();
674: }
675: } catch (IOException e) {
676: throw new BuildException(e);
677: }
678: }
679: }
680:
681: /**
682: * Executes the given classname with the given arguments in a separate VM.
683: */
684: private int run(String[] command) throws BuildException {
685: LogStreamHandler logstr = new LogStreamHandler(this ,
686: Project.MSG_INFO, Project.MSG_WARN);
687: Execute exe = new Execute(logstr);
688: exe.setAntRun(project);
689: exe.setCommandline(command);
690: try {
691: int rc = exe.execute();
692: if (exe.killedProcess()) {
693: log("Timeout: killed the sub-process", Project.MSG_WARN);
694: }
695: return rc;
696: } catch (IOException e) {
697: throw new BuildException(e, location);
698: }
699: }
700:
701: private Set<File> bindingFiles = new HashSet<File>();
702:
703: }
|