source: release-kits/lirk3/resources/gs3-release-maker/apache-ant-1.6.5/src/main/org/apache/tools/ant/taskdefs/AbstractCvsTask.java@ 14982

Last change on this file since 14982 was 14982, checked in by oranfry, 16 years ago

initial import of LiRK3

File size: 23.5 KB
Line 
1/*
2 * Copyright 2002-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
18package org.apache.tools.ant.taskdefs;
19
20import java.io.BufferedOutputStream;
21import java.io.File;
22import java.io.FileOutputStream;
23import java.io.IOException;
24import java.io.OutputStream;
25import java.io.PrintStream;
26import java.util.Vector;
27import org.apache.tools.ant.BuildException;
28import org.apache.tools.ant.Project;
29import org.apache.tools.ant.Task;
30import org.apache.tools.ant.types.Commandline;
31import org.apache.tools.ant.types.Environment;
32import org.apache.tools.ant.util.StringUtils;
33
34/**
35 * original Cvs.java 1.20
36 *
37 * NOTE: This implementation has been moved here from Cvs.java with
38 * the addition of some accessors for extensibility. Another task
39 * can extend this with some customized output processing.
40 *
41 * @since Ant 1.5
42 */
43public abstract class AbstractCvsTask extends Task {
44 /**
45 * Default compression level to use, if compression is enabled via
46 * setCompression( true ).
47 */
48 public static final int DEFAULT_COMPRESSION_LEVEL = 3;
49 private static final int MAXIMUM_COMRESSION_LEVEL = 9;
50
51 private Commandline cmd = new Commandline();
52
53 /** list of Commandline children */
54 private Vector vecCommandlines = new Vector();
55
56 /**
57 * the CVSROOT variable.
58 */
59 private String cvsRoot;
60
61 /**
62 * the CVS_RSH variable.
63 */
64 private String cvsRsh;
65
66 /**
67 * the package/module to check out.
68 */
69 private String cvsPackage;
70 /**
71 * the tag
72 */
73 private String tag;
74 /**
75 * the default command.
76 */
77 private static final String DEFAULT_COMMAND = "checkout";
78 /**
79 * the CVS command to execute.
80 */
81 private String command = null;
82
83 /**
84 * suppress information messages.
85 */
86 private boolean quiet = false;
87
88 /**
89 * suppress all messages.
90 */
91 private boolean reallyquiet = false;
92
93 /**
94 * compression level to use.
95 */
96 private int compression = 0;
97
98 /**
99 * report only, don't change any files.
100 */
101 private boolean noexec = false;
102
103 /**
104 * CVS port
105 */
106 private int port = 0;
107
108 /**
109 * CVS password file
110 */
111 private File passFile = null;
112
113 /**
114 * the directory where the checked out files should be placed.
115 */
116 private File dest;
117
118 /** whether or not to append stdout/stderr to existing files */
119 private boolean append = false;
120
121 /**
122 * the file to direct standard output from the command.
123 */
124 private File output;
125
126 /**
127 * the file to direct standard error from the command.
128 */
129 private File error;
130
131 /**
132 * If true it will stop the build if cvs exits with error.
133 * Default is false. (Iulian)
134 */
135 private boolean failOnError = false;
136
137 /**
138 * Create accessors for the following, to allow different handling of
139 * the output.
140 */
141 private ExecuteStreamHandler executeStreamHandler;
142 private OutputStream outputStream;
143 private OutputStream errorStream;
144
145 /** empty no-arg constructor*/
146 public AbstractCvsTask() {
147 super();
148 }
149
150 /**
151 * sets the handler
152 * @param handler a handler able of processing the output and error streams from the cvs exe
153 */
154 public void setExecuteStreamHandler(ExecuteStreamHandler handler) {
155 this.executeStreamHandler = handler;
156 }
157
158 /**
159 * find the handler and instantiate it if it does not exist yet
160 * @return handler for output and error streams
161 */
162 protected ExecuteStreamHandler getExecuteStreamHandler() {
163
164 if (this.executeStreamHandler == null) {
165 setExecuteStreamHandler(new PumpStreamHandler(getOutputStream(),
166 getErrorStream()));
167 }
168
169 return this.executeStreamHandler;
170 }
171
172 /**
173 * sets a stream to which the output from the cvs executable should be sent
174 * @param outputStream stream to which the stdout from cvs should go
175 */
176 protected void setOutputStream(OutputStream outputStream) {
177
178 this.outputStream = outputStream;
179 }
180
181 /**
182 * access the stream to which the stdout from cvs should go
183 * if this stream has already been set, it will be returned
184 * if the stream has not yet been set, if the attribute output
185 * has been set, the output stream will go to the output file
186 * otherwise the output will go to ant's logging system
187 * @return output stream to which cvs' stdout should go to
188 */
189 protected OutputStream getOutputStream() {
190
191 if (this.outputStream == null) {
192
193 if (output != null) {
194 try {
195 setOutputStream(new PrintStream(
196 new BufferedOutputStream(
197 new FileOutputStream(output
198 .getPath(),
199 append))));
200 } catch (IOException e) {
201 throw new BuildException(e, getLocation());
202 }
203 } else {
204 setOutputStream(new LogOutputStream(this, Project.MSG_INFO));
205 }
206 }
207
208 return this.outputStream;
209 }
210
211 /**
212 * sets a stream to which the stderr from the cvs exe should go
213 * @param errorStream an output stream willing to process stderr
214 */
215 protected void setErrorStream(OutputStream errorStream) {
216
217 this.errorStream = errorStream;
218 }
219
220 /**
221 * access the stream to which the stderr from cvs should go
222 * if this stream has already been set, it will be returned
223 * if the stream has not yet been set, if the attribute error
224 * has been set, the output stream will go to the file denoted by the error attribute
225 * otherwise the stderr output will go to ant's logging system
226 * @return output stream to which cvs' stderr should go to
227 */
228 protected OutputStream getErrorStream() {
229
230 if (this.errorStream == null) {
231
232 if (error != null) {
233
234 try {
235 setErrorStream(new PrintStream(
236 new BufferedOutputStream(
237 new FileOutputStream(error.getPath(),
238 append))));
239 } catch (IOException e) {
240 throw new BuildException(e, getLocation());
241 }
242 } else {
243 setErrorStream(new LogOutputStream(this, Project.MSG_WARN));
244 }
245 }
246
247 return this.errorStream;
248 }
249
250 /**
251 * Sets up the environment for toExecute and then runs it.
252 * @param toExecute the command line to execute
253 * @throws BuildException if failonError is set to true and the cvs command fails
254 */
255 protected void runCommand(Commandline toExecute) throws BuildException {
256 // XXX: we should use JCVS (www.ice.com/JCVS) instead of
257 // command line execution so that we don't rely on having
258 // native CVS stuff around (SM)
259
260 // We can't do it ourselves as jCVS is GPLed, a third party task
261 // outside of jakarta repositories would be possible though (SB).
262
263 Environment env = new Environment();
264
265 if (port > 0) {
266 Environment.Variable var = new Environment.Variable();
267 var.setKey("CVS_CLIENT_PORT");
268 var.setValue(String.valueOf(port));
269 env.addVariable(var);
270 }
271
272 /**
273 * Need a better cross platform integration with <cvspass>, so
274 * use the same filename.
275 */
276 if (passFile == null) {
277
278 File defaultPassFile = new File(
279 System.getProperty("cygwin.user.home",
280 System.getProperty("user.home"))
281 + File.separatorChar + ".cvspass");
282
283 if (defaultPassFile.exists()) {
284 this.setPassfile(defaultPassFile);
285 }
286 }
287
288 if (passFile != null) {
289 if (passFile.isFile() && passFile.canRead()) {
290 Environment.Variable var = new Environment.Variable();
291 var.setKey("CVS_PASSFILE");
292 var.setValue(String.valueOf(passFile));
293 env.addVariable(var);
294 log("Using cvs passfile: " + String.valueOf(passFile),
295 Project.MSG_INFO);
296 } else if (!passFile.canRead()) {
297 log("cvs passfile: " + String.valueOf(passFile)
298 + " ignored as it is not readable",
299 Project.MSG_WARN);
300 } else {
301 log("cvs passfile: " + String.valueOf(passFile)
302 + " ignored as it is not a file",
303 Project.MSG_WARN);
304 }
305 }
306
307 if (cvsRsh != null) {
308 Environment.Variable var = new Environment.Variable();
309 var.setKey("CVS_RSH");
310 var.setValue(String.valueOf(cvsRsh));
311 env.addVariable(var);
312 }
313
314 //
315 // Just call the getExecuteStreamHandler() and let it handle
316 // the semantics of instantiation or retrieval.
317 //
318 Execute exe = new Execute(getExecuteStreamHandler(), null);
319
320 exe.setAntRun(getProject());
321 if (dest == null) {
322 dest = getProject().getBaseDir();
323 }
324
325 if (!dest.exists()) {
326 dest.mkdirs();
327 }
328
329 exe.setWorkingDirectory(dest);
330 exe.setCommandline(toExecute.getCommandline());
331 exe.setEnvironment(env.getVariables());
332
333 try {
334 String actualCommandLine = executeToString(exe);
335 log(actualCommandLine, Project.MSG_VERBOSE);
336 int retCode = exe.execute();
337 log("retCode=" + retCode, Project.MSG_DEBUG);
338 /*Throw an exception if cvs exited with error. (Iulian)*/
339 if (failOnError && Execute.isFailure(retCode)) {
340 throw new BuildException("cvs exited with error code "
341 + retCode
342 + StringUtils.LINE_SEP
343 + "Command line was ["
344 + actualCommandLine + "]", getLocation());
345 }
346 } catch (IOException e) {
347 if (failOnError) {
348 throw new BuildException(e, getLocation());
349 } else {
350 log("Caught exception: " + e.getMessage(), Project.MSG_WARN);
351 }
352 } catch (BuildException e) {
353 if (failOnError) {
354 throw(e);
355 } else {
356 Throwable t = e.getException();
357 if (t == null) {
358 t = e;
359 }
360 log("Caught exception: " + t.getMessage(), Project.MSG_WARN);
361 }
362 } catch (Exception e) {
363 if (failOnError) {
364 throw new BuildException(e, getLocation());
365 } else {
366 log("Caught exception: " + e.getMessage(), Project.MSG_WARN);
367 }
368 }
369 }
370
371 /**
372 * do the work
373 * @throws BuildException if failonerror is set to true and the cvs command fails.
374 */
375 public void execute() throws BuildException {
376
377 String savedCommand = getCommand();
378
379 if (this.getCommand() == null && vecCommandlines.size() == 0) {
380 // re-implement legacy behaviour:
381 this.setCommand(AbstractCvsTask.DEFAULT_COMMAND);
382 }
383
384 String c = this.getCommand();
385 Commandline cloned = null;
386 if (c != null) {
387 cloned = (Commandline) cmd.clone();
388 cloned.createArgument(true).setLine(c);
389 this.addConfiguredCommandline(cloned, true);
390 }
391
392 try {
393 for (int i = 0; i < vecCommandlines.size(); i++) {
394 this.runCommand((Commandline) vecCommandlines.elementAt(i));
395 }
396 } finally {
397 if (cloned != null) {
398 removeCommandline(cloned);
399 }
400 setCommand(savedCommand);
401
402 if (outputStream != null) {
403 try {
404 outputStream.close();
405 } catch (IOException e) {
406 //ignore
407 }
408 }
409 if (errorStream != null) {
410 try {
411 errorStream.close();
412 } catch (IOException e) {
413 //ignore
414 }
415 }
416 }
417 }
418
419 private String executeToString(Execute execute) {
420
421 StringBuffer stringBuffer =
422 new StringBuffer(Commandline.describeCommand(execute
423 .getCommandline()));
424
425 String newLine = StringUtils.LINE_SEP;
426 String[] variableArray = execute.getEnvironment();
427
428 if (variableArray != null) {
429 stringBuffer.append(newLine);
430 stringBuffer.append(newLine);
431 stringBuffer.append("environment:");
432 stringBuffer.append(newLine);
433 for (int z = 0; z < variableArray.length; z++) {
434 stringBuffer.append(newLine);
435 stringBuffer.append("\t");
436 stringBuffer.append(variableArray[z]);
437 }
438 }
439
440 return stringBuffer.toString();
441 }
442
443 /**
444 * The CVSROOT variable.
445 *
446 * @param root the CVSROOT variable
447 */
448 public void setCvsRoot(String root) {
449
450 // Check if not real cvsroot => set it to null
451 if (root != null) {
452 if (root.trim().equals("")) {
453 root = null;
454 }
455 }
456
457 this.cvsRoot = root;
458 }
459
460 /**
461 * access the CVSROOT variable
462 * @return CVSROOT
463 */
464 public String getCvsRoot() {
465
466 return this.cvsRoot;
467 }
468
469 /**
470 * The CVS_RSH variable.
471 *
472 * @param rsh the CVS_RSH variable
473 */
474 public void setCvsRsh(String rsh) {
475 // Check if not real cvsrsh => set it to null
476 if (rsh != null) {
477 if (rsh.trim().equals("")) {
478 rsh = null;
479 }
480 }
481
482 this.cvsRsh = rsh;
483 }
484
485 /**
486 * access the CVS_RSH variable
487 * @return the CVS_RSH variable
488 */
489 public String getCvsRsh() {
490
491 return this.cvsRsh;
492 }
493
494 /**
495 * Port used by CVS to communicate with the server.
496 *
497 * @param port port of CVS
498 */
499 public void setPort(int port) {
500 this.port = port;
501 }
502
503 /**
504 * access the port of CVS
505 * @return the port of CVS
506 */
507 public int getPort() {
508
509 return this.port;
510 }
511
512 /**
513 * Password file to read passwords from.
514 *
515 * @param passFile password file to read passwords from
516 */
517 public void setPassfile(File passFile) {
518 this.passFile = passFile;
519 }
520
521 /**
522 * find the password file
523 * @return password file
524 */
525 public File getPassFile() {
526
527 return this.passFile;
528 }
529
530 /**
531 * The directory where the checked out files should be placed.
532 *
533 * <p>Note that this is different from CVS's -d command line
534 * switch as Ant will never shorten pathnames to avoid empty
535 * directories.</p>
536 *
537 * @param dest directory where the checked out files should be placed
538 */
539 public void setDest(File dest) {
540 this.dest = dest;
541 }
542
543 /**
544 * get the file where the checked out files should be placed
545 *
546 * @return directory where the checked out files should be placed
547 */
548 public File getDest() {
549
550 return this.dest;
551 }
552
553 /**
554 * The package/module to operate upon.
555 *
556 * @param p package or module to operate upon
557 */
558 public void setPackage(String p) {
559 this.cvsPackage = p;
560 }
561
562 /**
563 * access the package or module to operate upon
564 *
565 * @return package/module
566 */
567 public String getPackage() {
568
569 return this.cvsPackage;
570 }
571 /**
572 * tag or branch
573 * @return tag or branch
574 * @since ant 1.6.1
575 */
576 public String getTag() {
577 return tag;
578 }
579
580 /**
581 * The tag of the package/module to operate upon.
582 * @param p tag
583 */
584 public void setTag(String p) {
585 // Check if not real tag => set it to null
586 if (p != null && p.trim().length() > 0) {
587 tag = p;
588 addCommandArgument("-r" + p);
589 }
590 }
591
592 /**
593 * This needs to be public to allow configuration
594 * of commands externally.
595 * @param arg command argument
596 */
597 public void addCommandArgument(String arg) {
598 this.addCommandArgument(cmd, arg);
599 }
600
601 /**
602 * This method adds a command line argument to an external command.
603 *
604 * I do not understand what this method does in this class ???
605 * particularly not why it is public ????
606 * AntoineLL July 23d 2003
607 *
608 * @param c command line to which one argument should be added
609 * @param arg argument to add
610 */
611 public void addCommandArgument(Commandline c, String arg) {
612 c.createArgument().setValue(arg);
613 }
614
615
616 /**
617 * Use the most recent revision no later than the given date.
618 * @param p a date as string in a format that the CVS executable can understand
619 * see man cvs
620 */
621 public void setDate(String p) {
622 if (p != null && p.trim().length() > 0) {
623 addCommandArgument("-D");
624 addCommandArgument(p);
625 }
626 }
627
628 /**
629 * The CVS command to execute.
630 *
631 * This should be deprecated, it is better to use the Commandline class ?
632 * AntoineLL July 23d 2003
633 *
634 * @param c a command as string
635 */
636 public void setCommand(String c) {
637 this.command = c;
638 }
639 /**
640 * accessor to a command line as string
641 *
642 * This should be deprecated
643 * AntoineLL July 23d 2003
644 *
645 * @return command line as string
646 */
647 public String getCommand() {
648 return this.command;
649 }
650
651 /**
652 * If true, suppress informational messages.
653 * @param q if true, suppress informational messages
654 */
655 public void setQuiet(boolean q) {
656 quiet = q;
657 }
658
659 /**
660 * If true, suppress all messages.
661 * @param q if true, suppress all messages
662 * @since Ant 1.6
663 */
664 public void setReallyquiet(boolean q) {
665 reallyquiet = q;
666 }
667
668
669 /**
670 * If true, report only and don't change any files.
671 *
672 * @param ne if true, report only and do not change any files.
673 */
674 public void setNoexec(boolean ne) {
675 noexec = ne;
676 }
677
678 /**
679 * The file to direct standard output from the command.
680 * @param output a file to which stdout should go
681 */
682 public void setOutput(File output) {
683 this.output = output;
684 }
685
686 /**
687 * The file to direct standard error from the command.
688 *
689 * @param error a file to which stderr should go
690 */
691 public void setError(File error) {
692 this.error = error;
693 }
694
695 /**
696 * Whether to append output/error when redirecting to a file.
697 * @param value true indicated you want to append
698 */
699 public void setAppend(boolean value) {
700 this.append = value;
701 }
702
703 /**
704 * Stop the build process if the command exits with
705 * a return code other than 0.
706 * Defaults to false.
707 * @param failOnError stop the build process if the command exits with
708 * a return code other than 0
709 */
710 public void setFailOnError(boolean failOnError) {
711 this.failOnError = failOnError;
712 }
713
714 /**
715 * Configure a commandline element for things like cvsRoot, quiet, etc.
716 * @param c the command line which will be configured
717 * if the commandline is initially null, the function is a noop
718 * otherwise the function append to the commandline arguments concerning
719 * <ul>
720 * <li>
721 * cvs package
722 * </li>
723 * <li>
724 * compression
725 * </li>
726 * <li>
727 * quiet or reallyquiet
728 * </li>
729 * <li>cvsroot</li>
730 * <li>noexec</li>
731 * </ul>
732 */
733 protected void configureCommandline(Commandline c) {
734 if (c == null) {
735 return;
736 }
737 c.setExecutable("cvs");
738 if (cvsPackage != null) {
739 c.createArgument().setLine(cvsPackage);
740 }
741 if (this.compression > 0 && this.compression <= MAXIMUM_COMRESSION_LEVEL) {
742 c.createArgument(true).setValue("-z" + this.compression);
743 }
744 if (quiet && !reallyquiet) {
745 c.createArgument(true).setValue("-q");
746 }
747 if (reallyquiet) {
748 c.createArgument(true).setValue("-Q");
749 }
750 if (noexec) {
751 c.createArgument(true).setValue("-n");
752 }
753 if (cvsRoot != null) {
754 c.createArgument(true).setLine("-d" + cvsRoot);
755 }
756 }
757
758 /**
759 * remove a particular command from a vector of command lines
760 * @param c command line which should be removed
761 */
762 protected void removeCommandline(Commandline c) {
763 vecCommandlines.removeElement(c);
764 }
765
766 /**
767 * Adds direct command-line to execute.
768 * @param c command line to execute
769 */
770 public void addConfiguredCommandline(Commandline c) {
771 this.addConfiguredCommandline(c, false);
772 }
773
774 /**
775 * Configures and adds the given Commandline.
776 * @param c commandline to insert
777 * @param insertAtStart If true, c is
778 * inserted at the beginning of the vector of command lines
779 */
780 public void addConfiguredCommandline(Commandline c,
781 boolean insertAtStart) {
782 if (c == null) {
783 return;
784 }
785 this.configureCommandline(c);
786 if (insertAtStart) {
787 vecCommandlines.insertElementAt(c, 0);
788 } else {
789 vecCommandlines.addElement(c);
790 }
791 }
792
793 /**
794 * If set to a value 1-9 it adds -zN to the cvs command line, else
795 * it disables compression.
796 * @param level compression level 1 to 9
797 */
798 public void setCompressionLevel(int level) {
799 this.compression = level;
800 }
801
802 /**
803 * If true, this is the same as compressionlevel="3".
804 *
805 * @param usecomp If true, turns on compression using default
806 * level, AbstractCvsTask.DEFAULT_COMPRESSION_LEVEL.
807 */
808 public void setCompression(boolean usecomp) {
809 setCompressionLevel(usecomp
810 ? AbstractCvsTask.DEFAULT_COMPRESSION_LEVEL : 0);
811 }
812
813}
Note: See TracBrowser for help on using the repository browser.