KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > tools > ant > taskdefs > AbstractCvsTask


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

18
19 package org.apache.tools.ant.taskdefs;
20
21 import java.io.BufferedOutputStream JavaDoc;
22 import java.io.File JavaDoc;
23 import java.io.FileOutputStream JavaDoc;
24 import java.io.IOException JavaDoc;
25 import java.io.OutputStream JavaDoc;
26 import java.io.PrintStream JavaDoc;
27 import java.util.Vector JavaDoc;
28 import org.apache.tools.ant.BuildException;
29 import org.apache.tools.ant.Project;
30 import org.apache.tools.ant.Task;
31 import org.apache.tools.ant.types.Commandline;
32 import org.apache.tools.ant.types.Environment;
33 import org.apache.tools.ant.util.StringUtils;
34 import org.apache.tools.ant.util.FileUtils;
35
36 /**
37  * original Cvs.java 1.20
38  *
39  * NOTE: This implementation has been moved here from Cvs.java with
40  * the addition of some accessors for extensibility. Another task
41  * can extend this with some customized output processing.
42  *
43  * @since Ant 1.5
44  */

45 public abstract class AbstractCvsTask extends Task {
46     /**
47      * Default compression level to use, if compression is enabled via
48      * setCompression( true ).
49      */

50     public static final int DEFAULT_COMPRESSION_LEVEL = 3;
51     private static final int MAXIMUM_COMRESSION_LEVEL = 9;
52
53     private Commandline cmd = new Commandline();
54
55     /** list of Commandline children */
56     private Vector JavaDoc vecCommandlines = new Vector JavaDoc();
57
58     /**
59      * the CVSROOT variable.
60      */

61     private String JavaDoc cvsRoot;
62
63     /**
64      * the CVS_RSH variable.
65      */

66     private String JavaDoc cvsRsh;
67
68     /**
69      * the package/module to check out.
70      */

71     private String JavaDoc cvsPackage;
72     /**
73      * the tag
74      */

75     private String JavaDoc tag;
76     /**
77      * the default command.
78      */

79     private static final String JavaDoc DEFAULT_COMMAND = "checkout";
80     /**
81      * the CVS command to execute.
82      */

83     private String JavaDoc command = null;
84
85     /**
86      * suppress information messages.
87      */

88     private boolean quiet = false;
89
90     /**
91      * suppress all messages.
92      */

93     private boolean reallyquiet = false;
94
95     /**
96      * compression level to use.
97      */

98     private int compression = 0;
99
100     /**
101      * report only, don't change any files.
102      */

103     private boolean noexec = false;
104
105     /**
106      * CVS port
107      */

108     private int port = 0;
109
110     /**
111      * CVS password file
112      */

113     private File JavaDoc passFile = null;
114
115     /**
116      * the directory where the checked out files should be placed.
117      */

118     private File JavaDoc dest;
119
120     /** whether or not to append stdout/stderr to existing files */
121     private boolean append = false;
122
123     /**
124      * the file to direct standard output from the command.
125      */

126     private File JavaDoc output;
127
128     /**
129      * the file to direct standard error from the command.
130      */

131     private File JavaDoc error;
132
133     /**
134      * If true it will stop the build if cvs exits with error.
135      * Default is false. (Iulian)
136      */

137     private boolean failOnError = false;
138
139     /**
140      * Create accessors for the following, to allow different handling of
141      * the output.
142      */

143     private ExecuteStreamHandler executeStreamHandler;
144     private OutputStream JavaDoc outputStream;
145     private OutputStream JavaDoc errorStream;
146
147     /** empty no-arg constructor*/
148     public AbstractCvsTask() {
149         super();
150     }
151
152     /**
153      * sets the handler
154      * @param handler a handler able of processing the output and error streams from the cvs exe
155      */

156     public void setExecuteStreamHandler(ExecuteStreamHandler handler) {
157         this.executeStreamHandler = handler;
158     }
159
160     /**
161      * find the handler and instantiate it if it does not exist yet
162      * @return handler for output and error streams
163      */

164     protected ExecuteStreamHandler getExecuteStreamHandler() {
165
166         if (this.executeStreamHandler == null) {
167             setExecuteStreamHandler(new PumpStreamHandler(getOutputStream(),
168                                                           getErrorStream()));
169         }
170
171         return this.executeStreamHandler;
172     }
173
174     /**
175      * sets a stream to which the output from the cvs executable should be sent
176      * @param outputStream stream to which the stdout from cvs should go
177      */

178     protected void setOutputStream(OutputStream JavaDoc outputStream) {
179
180         this.outputStream = outputStream;
181     }
182
183     /**
184      * access the stream to which the stdout from cvs should go
185      * if this stream has already been set, it will be returned
186      * if the stream has not yet been set, if the attribute output
187      * has been set, the output stream will go to the output file
188      * otherwise the output will go to ant's logging system
189      * @return output stream to which cvs' stdout should go to
190      */

191     protected OutputStream JavaDoc getOutputStream() {
192
193         if (this.outputStream == null) {
194
195             if (output != null) {
196                 try {
197                     setOutputStream(new PrintStream JavaDoc(
198                                         new BufferedOutputStream JavaDoc(
199                                             new FileOutputStream JavaDoc(output
200                                                                  .getPath(),
201                                                                  append))));
202                 } catch (IOException JavaDoc e) {
203                     throw new BuildException(e, getLocation());
204                 }
205             } else {
206                 setOutputStream(new LogOutputStream(this, Project.MSG_INFO));
207             }
208         }
209
210         return this.outputStream;
211     }
212
213     /**
214      * sets a stream to which the stderr from the cvs exe should go
215      * @param errorStream an output stream willing to process stderr
216      */

217     protected void setErrorStream(OutputStream JavaDoc errorStream) {
218
219         this.errorStream = errorStream;
220     }
221
222     /**
223      * access the stream to which the stderr from cvs should go
224      * if this stream has already been set, it will be returned
225      * if the stream has not yet been set, if the attribute error
226      * has been set, the output stream will go to the file denoted by the error attribute
227      * otherwise the stderr output will go to ant's logging system
228      * @return output stream to which cvs' stderr should go to
229      */

230     protected OutputStream JavaDoc getErrorStream() {
231
232         if (this.errorStream == null) {
233
234             if (error != null) {
235
236                 try {
237                     setErrorStream(new PrintStream JavaDoc(
238                                        new BufferedOutputStream JavaDoc(
239                                            new FileOutputStream JavaDoc(error.getPath(),
240                                                                 append))));
241                 } catch (IOException JavaDoc e) {
242                     throw new BuildException(e, getLocation());
243                 }
244             } else {
245                 setErrorStream(new LogOutputStream(this, Project.MSG_WARN));
246             }
247         }
248
249         return this.errorStream;
250     }
251
252     /**
253      * Sets up the environment for toExecute and then runs it.
254      * @param toExecute the command line to execute
255      * @throws BuildException if failonError is set to true and the cvs command fails
256      */

257     protected void runCommand(Commandline toExecute) throws BuildException {
258         // XXX: we should use JCVS (www.ice.com/JCVS) instead of
259
// command line execution so that we don't rely on having
260
// native CVS stuff around (SM)
261

262         // We can't do it ourselves as jCVS is GPLed, a third party task
263
// outside of jakarta repositories would be possible though (SB).
264

265         Environment env = new Environment();
266
267         if (port > 0) {
268             Environment.Variable var = new Environment.Variable();
269             var.setKey("CVS_CLIENT_PORT");
270             var.setValue(String.valueOf(port));
271             env.addVariable(var);
272         }
273
274         /**
275          * Need a better cross platform integration with <cvspass>, so
276          * use the same filename.
277          */

278         if (passFile == null) {
279
280             File JavaDoc defaultPassFile = new File JavaDoc(
281                 System.getProperty("cygwin.user.home",
282                     System.getProperty("user.home"))
283                 + File.separatorChar + ".cvspass");
284
285             if (defaultPassFile.exists()) {
286                 this.setPassfile(defaultPassFile);
287             }
288         }
289
290         if (passFile != null) {
291             if (passFile.isFile() && passFile.canRead()) {
292                 Environment.Variable var = new Environment.Variable();
293                 var.setKey("CVS_PASSFILE");
294                 var.setValue(String.valueOf(passFile));
295                 env.addVariable(var);
296                 log("Using cvs passfile: " + String.valueOf(passFile),
297                     Project.MSG_VERBOSE);
298             } else if (!passFile.canRead()) {
299                 log("cvs passfile: " + String.valueOf(passFile)
300                     + " ignored as it is not readable",
301                     Project.MSG_WARN);
302             } else {
303                 log("cvs passfile: " + String.valueOf(passFile)
304                     + " ignored as it is not a file",
305                     Project.MSG_WARN);
306             }
307         }
308
309         if (cvsRsh != null) {
310             Environment.Variable var = new Environment.Variable();
311             var.setKey("CVS_RSH");
312             var.setValue(String.valueOf(cvsRsh));
313             env.addVariable(var);
314         }
315
316         //
317
// Just call the getExecuteStreamHandler() and let it handle
318
// the semantics of instantiation or retrieval.
319
//
320
Execute exe = new Execute(getExecuteStreamHandler(), null);
321
322         exe.setAntRun(getProject());
323         if (dest == null) {
324             dest = getProject().getBaseDir();
325         }
326
327         if (!dest.exists()) {
328             dest.mkdirs();
329         }
330
331         exe.setWorkingDirectory(dest);
332         exe.setCommandline(toExecute.getCommandline());
333         exe.setEnvironment(env.getVariables());
334
335         try {
336             String JavaDoc actualCommandLine = executeToString(exe);
337             log(actualCommandLine, Project.MSG_VERBOSE);
338             int retCode = exe.execute();
339             log("retCode=" + retCode, Project.MSG_DEBUG);
340             /*Throw an exception if cvs exited with error. (Iulian)*/
341             if (failOnError && Execute.isFailure(retCode)) {
342                 throw new BuildException("cvs exited with error code "
343                                          + retCode
344                                          + StringUtils.LINE_SEP
345                                          + "Command line was ["
346                                          + actualCommandLine + "]",
347                                          getLocation());
348             }
349         } catch (IOException JavaDoc e) {
350             if (failOnError) {
351                 throw new BuildException(e, getLocation());
352             }
353             log("Caught exception: " + e.getMessage(), Project.MSG_WARN);
354         } catch (BuildException e) {
355             if (failOnError) {
356                 throw(e);
357             }
358             Throwable JavaDoc t = e.getException();
359             if (t == null) {
360                 t = e;
361             }
362             log("Caught exception: " + t.getMessage(), Project.MSG_WARN);
363         } catch (Exception JavaDoc e) {
364             if (failOnError) {
365                 throw new BuildException(e, getLocation());
366             }
367             log("Caught exception: " + e.getMessage(), Project.MSG_WARN);
368         }
369     }
370
371     /**
372      * do the work
373      * @throws BuildException if failonerror is set to true and the
374      * cvs command fails.
375      */

376     public void execute() throws BuildException {
377
378         String JavaDoc savedCommand = getCommand();
379
380         if (this.getCommand() == null && vecCommandlines.size() == 0) {
381             // re-implement legacy behaviour:
382
this.setCommand(AbstractCvsTask.DEFAULT_COMMAND);
383         }
384
385         String JavaDoc c = this.getCommand();
386         Commandline cloned = null;
387         if (c != null) {
388             cloned = (Commandline) cmd.clone();
389             cloned.createArgument(true).setLine(c);
390             this.addConfiguredCommandline(cloned, true);
391         }
392
393         try {
394             for (int i = 0; i < vecCommandlines.size(); i++) {
395                 this.runCommand((Commandline) vecCommandlines.elementAt(i));
396             }
397         } finally {
398             if (cloned != null) {
399                 removeCommandline(cloned);
400             }
401             setCommand(savedCommand);
402             FileUtils.close(outputStream);
403             FileUtils.close(errorStream);
404         }
405     }
406
407     private String JavaDoc executeToString(Execute execute) {
408
409         StringBuffer JavaDoc stringBuffer =
410             new StringBuffer JavaDoc(Commandline.describeCommand(execute
411                                                          .getCommandline()));
412
413         String JavaDoc newLine = StringUtils.LINE_SEP;
414         String JavaDoc[] variableArray = execute.getEnvironment();
415
416         if (variableArray != null) {
417             stringBuffer.append(newLine);
418             stringBuffer.append(newLine);
419             stringBuffer.append("environment:");
420             stringBuffer.append(newLine);
421             for (int z = 0; z < variableArray.length; z++) {
422                 stringBuffer.append(newLine);
423                 stringBuffer.append("\t");
424                 stringBuffer.append(variableArray[z]);
425             }
426         }
427
428         return stringBuffer.toString();
429     }
430
431     /**
432      * The CVSROOT variable.
433      *
434      * @param root the CVSROOT variable
435      */

436     public void setCvsRoot(String JavaDoc root) {
437
438         // Check if not real cvsroot => set it to null
439
if (root != null) {
440             if (root.trim().equals("")) {
441                 root = null;
442             }
443         }
444
445         this.cvsRoot = root;
446     }
447
448     /**
449      * access the CVSROOT variable
450      * @return CVSROOT
451      */

452     public String JavaDoc getCvsRoot() {
453
454         return this.cvsRoot;
455     }
456
457     /**
458      * The CVS_RSH variable.
459      *
460      * @param rsh the CVS_RSH variable
461      */

462     public void setCvsRsh(String JavaDoc rsh) {
463         // Check if not real cvsrsh => set it to null
464
if (rsh != null) {
465             if (rsh.trim().equals("")) {
466                 rsh = null;
467             }
468         }
469
470         this.cvsRsh = rsh;
471     }
472
473     /**
474      * access the CVS_RSH variable
475      * @return the CVS_RSH variable
476      */

477     public String JavaDoc getCvsRsh() {
478
479         return this.cvsRsh;
480     }
481
482     /**
483      * Port used by CVS to communicate with the server.
484      *
485      * @param port port of CVS
486      */

487     public void setPort(int port) {
488         this.port = port;
489     }
490
491     /**
492      * access the port of CVS
493      * @return the port of CVS
494      */

495     public int getPort() {
496
497         return this.port;
498     }
499
500     /**
501      * Password file to read passwords from.
502      *
503      * @param passFile password file to read passwords from
504      */

505     public void setPassfile(File JavaDoc passFile) {
506         this.passFile = passFile;
507     }
508
509     /**
510      * find the password file
511      * @return password file
512      */

513     public File JavaDoc getPassFile() {
514
515         return this.passFile;
516     }
517
518     /**
519      * The directory where the checked out files should be placed.
520      *
521      * <p>Note that this is different from CVS's -d command line
522      * switch as Ant will never shorten pathnames to avoid empty
523      * directories.</p>
524      *
525      * @param dest directory where the checked out files should be placed
526      */

527     public void setDest(File JavaDoc dest) {
528         this.dest = dest;
529     }
530
531     /**
532      * get the file where the checked out files should be placed
533      *
534      * @return directory where the checked out files should be placed
535      */

536     public File JavaDoc getDest() {
537
538         return this.dest;
539     }
540
541     /**
542      * The package/module to operate upon.
543      *
544      * @param p package or module to operate upon
545      */

546     public void setPackage(String JavaDoc p) {
547         this.cvsPackage = p;
548     }
549
550     /**
551      * access the package or module to operate upon
552      *
553      * @return package/module
554      */

555     public String JavaDoc getPackage() {
556
557         return this.cvsPackage;
558     }
559     /**
560      * tag or branch
561      * @return tag or branch
562      * @since ant 1.6.1
563      */

564     public String JavaDoc getTag() {
565         return tag;
566     }
567
568     /**
569      * The tag of the package/module to operate upon.
570      * @param p tag
571      */

572     public void setTag(String JavaDoc p) {
573         // Check if not real tag => set it to null
574
if (p != null && p.trim().length() > 0) {
575             tag = p;
576             addCommandArgument("-r" + p);
577         }
578     }
579
580     /**
581      * This needs to be public to allow configuration
582      * of commands externally.
583      * @param arg command argument
584      */

585     public void addCommandArgument(String JavaDoc arg) {
586         this.addCommandArgument(cmd, arg);
587     }
588
589     /**
590      * This method adds a command line argument to an external command.
591      *
592      * I do not understand what this method does in this class ???
593      * particularly not why it is public ????
594      * AntoineLL July 23d 2003
595      *
596      * @param c command line to which one argument should be added
597      * @param arg argument to add
598      */

599     public void addCommandArgument(Commandline c, String JavaDoc arg) {
600         c.createArgument().setValue(arg);
601     }
602
603
604     /**
605      * Use the most recent revision no later than the given date.
606      * @param p a date as string in a format that the CVS executable
607      * can understand see man cvs
608      */

609     public void setDate(String JavaDoc p) {
610         if (p != null && p.trim().length() > 0) {
611             addCommandArgument("-D");
612             addCommandArgument(p);
613         }
614     }
615
616     /**
617      * The CVS command to execute.
618      *
619      * This should be deprecated, it is better to use the Commandline class ?
620      * AntoineLL July 23d 2003
621      *
622      * @param c a command as string
623      */

624     public void setCommand(String JavaDoc c) {
625         this.command = c;
626     }
627     /**
628      * accessor to a command line as string
629      *
630      * This should be deprecated
631      * AntoineLL July 23d 2003
632      *
633      * @return command line as string
634      */

635     public String JavaDoc getCommand() {
636         return this.command;
637     }
638
639     /**
640      * If true, suppress informational messages.
641      * @param q if true, suppress informational messages
642      */

643     public void setQuiet(boolean q) {
644         quiet = q;
645     }
646
647     /**
648      * If true, suppress all messages.
649      * @param q if true, suppress all messages
650      * @since Ant 1.6
651      */

652     public void setReallyquiet(boolean q) {
653         reallyquiet = q;
654     }
655
656
657     /**
658      * If true, report only and don't change any files.
659      *
660      * @param ne if true, report only and do not change any files.
661      */

662     public void setNoexec(boolean ne) {
663         noexec = ne;
664     }
665
666     /**
667      * The file to direct standard output from the command.
668      * @param output a file to which stdout should go
669      */

670     public void setOutput(File JavaDoc output) {
671         this.output = output;
672     }
673
674     /**
675      * The file to direct standard error from the command.
676      *
677      * @param error a file to which stderr should go
678      */

679     public void setError(File JavaDoc error) {
680         this.error = error;
681     }
682
683     /**
684      * Whether to append output/error when redirecting to a file.
685      * @param value true indicated you want to append
686      */

687     public void setAppend(boolean value) {
688         this.append = value;
689     }
690
691     /**
692      * Stop the build process if the command exits with
693      * a return code other than 0.
694      * Defaults to false.
695      * @param failOnError stop the build process if the command exits with
696      * a return code other than 0
697      */

698     public void setFailOnError(boolean failOnError) {
699         this.failOnError = failOnError;
700     }
701
702     /**
703      * Configure a commandline element for things like cvsRoot, quiet, etc.
704      * @param c the command line which will be configured
705      * if the commandline is initially null, the function is a noop
706      * otherwise the function append to the commandline arguments concerning
707      * <ul>
708      * <li>
709      * cvs package
710      * </li>
711      * <li>
712      * compression
713      * </li>
714      * <li>
715      * quiet or reallyquiet
716      * </li>
717      * <li>cvsroot</li>
718      * <li>noexec</li>
719      * </ul>
720      */

721     protected void configureCommandline(Commandline c) {
722         if (c == null) {
723             return;
724         }
725         c.setExecutable("cvs");
726         if (cvsPackage != null) {
727             c.createArgument().setLine(cvsPackage);
728         }
729         if (this.compression > 0
730             && this.compression <= MAXIMUM_COMRESSION_LEVEL) {
731             c.createArgument(true).setValue("-z" + this.compression);
732         }
733         if (quiet && !reallyquiet) {
734             c.createArgument(true).setValue("-q");
735         }
736         if (reallyquiet) {
737             c.createArgument(true).setValue("-Q");
738         }
739         if (noexec) {
740             c.createArgument(true).setValue("-n");
741         }
742         if (cvsRoot != null) {
743             c.createArgument(true).setLine("-d" + cvsRoot);
744         }
745     }
746
747     /**
748      * remove a particular command from a vector of command lines
749      * @param c command line which should be removed
750      */

751     protected void removeCommandline(Commandline c) {
752         vecCommandlines.removeElement(c);
753     }
754
755     /**
756      * Adds direct command-line to execute.
757      * @param c command line to execute
758      */

759     public void addConfiguredCommandline(Commandline c) {
760         this.addConfiguredCommandline(c, false);
761     }
762
763     /**
764      * Configures and adds the given Commandline.
765      * @param c commandline to insert
766      * @param insertAtStart If true, c is
767      * inserted at the beginning of the vector of command lines
768     */

769     public void addConfiguredCommandline(Commandline c,
770                                          boolean insertAtStart) {
771         if (c == null) {
772             return;
773         }
774         this.configureCommandline(c);
775         if (insertAtStart) {
776             vecCommandlines.insertElementAt(c, 0);
777         } else {
778             vecCommandlines.addElement(c);
779         }
780     }
781
782     /**
783     * If set to a value 1-9 it adds -zN to the cvs command line, else
784     * it disables compression.
785      * @param level compression level 1 to 9
786     */

787     public void setCompressionLevel(int level) {
788         this.compression = level;
789     }
790
791     /**
792      * If true, this is the same as compressionlevel="3".
793      *
794      * @param usecomp If true, turns on compression using default
795      * level, AbstractCvsTask.DEFAULT_COMPRESSION_LEVEL.
796      */

797     public void setCompression(boolean usecomp) {
798         setCompressionLevel(usecomp
799             ? AbstractCvsTask.DEFAULT_COMPRESSION_LEVEL : 0);
800     }
801
802 }
803
Popular Tags