KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > tools > ant > taskdefs > optional > pvcs > Pvcs


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 package org.apache.tools.ant.taskdefs.optional.pvcs;
19
20 import java.io.BufferedReader JavaDoc;
21 import java.io.BufferedWriter JavaDoc;
22 import java.io.File JavaDoc;
23 import java.io.FileNotFoundException JavaDoc;
24 import java.io.FileOutputStream JavaDoc;
25 import java.io.FileReader JavaDoc;
26 import java.io.FileWriter JavaDoc;
27 import java.io.IOException JavaDoc;
28 import java.text.MessageFormat JavaDoc;
29 import java.text.ParseException JavaDoc;
30 import java.util.Enumeration JavaDoc;
31 import java.util.Random JavaDoc;
32 import java.util.Vector JavaDoc;
33 import org.apache.tools.ant.BuildException;
34 import org.apache.tools.ant.Project;
35 import org.apache.tools.ant.taskdefs.Execute;
36 import org.apache.tools.ant.taskdefs.ExecuteStreamHandler;
37 import org.apache.tools.ant.taskdefs.LogOutputStream;
38 import org.apache.tools.ant.taskdefs.LogStreamHandler;
39 import org.apache.tools.ant.taskdefs.PumpStreamHandler;
40 import org.apache.tools.ant.types.Commandline;
41
42 /**
43  *
44  * Extracts the latest edition of the source code from a PVCS repository.
45  * PVCS is a version control system
46  * developed by <a HREF="http://www.merant.com/products/pvcs">Merant</a>.
47  * <br>
48  * Before using this tag, the user running ant must have access to the commands
49  * of PVCS (get and pcli) and must have access to the repository. Note that the way to specify
50  * the repository is platform dependent so use property to specify location of repository.
51  * <br>
52  * This version has been tested agains PVCS version 6.5 and 6.6 under Windows and Solaris.
53
54  *
55  * <b>19-04-2001</b> <p>The task now has a more robust
56  * parser. It allows for platform independant file paths
57  * and supports file names with <i>()</i>. Thanks to Erik Husby for
58  * bringing the bug to my attention.
59  *
60  * <b>27-04-2001</b> <p>UNC paths are now handled properly.
61  * Fix provided by Don Jeffery. He also added an <i>UpdateOnly</i> flag
62  * that, when true, conditions the PVCS get using the -U option to only
63  * update those files that have a modification time (in PVCS) that is newer
64  * than the existing workfile.
65  *
66  * <b>25-10-2002</b> <p>Added a revision attribute that currently is a
67  * synonym for label, but in a future release the behavior of the label
68  * attribute will change to use the -v option of GET. See bug #13847 for
69  * discussion.
70  *
71  */

72 public class Pvcs extends org.apache.tools.ant.Task {
73     // CheckStyle - magic numbers
74
// checking for "X:\ 0=dquote,1=letter,2=:,3=\
75
private static final int POS_1 = 1;
76     private static final int POS_2 = 2;
77     private static final int POS_3 = 3;
78
79     private String JavaDoc pvcsbin;
80     private String JavaDoc repository;
81     private String JavaDoc pvcsProject;
82     private Vector JavaDoc pvcsProjects;
83     private String JavaDoc workspace;
84     private String JavaDoc force;
85     private String JavaDoc promotiongroup;
86     private String JavaDoc label;
87     private String JavaDoc revision;
88     private boolean ignorerc;
89     private boolean updateOnly;
90     private String JavaDoc filenameFormat;
91     private String JavaDoc lineStart;
92     private String JavaDoc userId;
93     private String JavaDoc config;
94     /**
95      * Constant for the thing to execute
96      */

97     private static final String JavaDoc PCLI_EXE = "pcli";
98
99     /*
100      * Constant for the PCLI listversionedfiles recursive i a format "get" understands
101      */

102     // private static final String PCLI_LVF_ARGS = "lvf -z -aw";
103

104     /**
105      * Constant for the thing to execute
106      */

107     private static final String JavaDoc GET_EXE = "get";
108
109
110     /**
111      * Run the command.
112      * @param cmd the command line to use.
113      * @param out the output stream handler to use.
114      * @return the exit code of the command.
115      */

116     protected int runCmd(Commandline cmd, ExecuteStreamHandler out) {
117         try {
118             Project aProj = getProject();
119             Execute exe = new Execute(out);
120             exe.setAntRun(aProj);
121             exe.setWorkingDirectory(aProj.getBaseDir());
122             exe.setCommandline(cmd.getCommandline());
123             return exe.execute();
124         } catch (java.io.IOException JavaDoc e) {
125             String JavaDoc msg = "Failed executing: " + cmd.toString()
126                 + ". Exception: " + e.getMessage();
127             throw new BuildException(msg, getLocation());
128         }
129     }
130
131     private String JavaDoc getExecutable(String JavaDoc exe) {
132         StringBuffer JavaDoc correctedExe = new StringBuffer JavaDoc();
133         if (getPvcsbin() != null) {
134             if (pvcsbin.endsWith(File.separator)) {
135                 correctedExe.append(pvcsbin);
136             } else {
137                 correctedExe.append(pvcsbin).append(File.separator);
138             }
139         }
140         return correctedExe.append(exe).toString();
141     }
142
143     /**
144      * @exception org.apache.tools.ant.BuildException Something is stopping the build...
145      */

146     public void execute() throws org.apache.tools.ant.BuildException {
147         int result = 0;
148
149         if (repository == null || repository.trim().equals("")) {
150             throw new BuildException("Required argument repository not specified");
151         }
152
153         // Check workspace exists
154
// Launch PCLI listversionedfiles -z -aw
155
// Capture output
156
// build the command line from what we got the format is
157
Commandline commandLine = new Commandline();
158         commandLine.setExecutable(getExecutable(PCLI_EXE));
159
160         commandLine.createArgument().setValue("lvf");
161         commandLine.createArgument().setValue("-z");
162         commandLine.createArgument().setValue("-aw");
163         if (getWorkspace() != null) {
164             commandLine.createArgument().setValue("-sp" + getWorkspace());
165         }
166         commandLine.createArgument().setValue("-pr" + getRepository());
167
168         String JavaDoc uid = getUserId();
169
170         if (uid != null) {
171             commandLine.createArgument().setValue("-id" + uid);
172         }
173
174         // default pvcs project is "/"
175
if (getPvcsproject() == null && getPvcsprojects().isEmpty()) {
176             pvcsProject = "/";
177         }
178
179         if (getPvcsproject() != null) {
180             commandLine.createArgument().setValue(getPvcsproject());
181         }
182         if (!getPvcsprojects().isEmpty()) {
183             Enumeration JavaDoc e = getPvcsprojects().elements();
184             while (e.hasMoreElements()) {
185                 String JavaDoc projectName = ((PvcsProject) e.nextElement()).getName();
186                 if (projectName == null || (projectName.trim()).equals("")) {
187                     throw new BuildException("name is a required attribute "
188                         + "of pvcsproject");
189                 }
190                 commandLine.createArgument().setValue(projectName);
191             }
192         }
193
194         File JavaDoc tmp = null;
195         File JavaDoc tmp2 = null;
196         try {
197             Random JavaDoc rand = new Random JavaDoc(System.currentTimeMillis());
198             tmp = new File JavaDoc("pvcs_ant_" + rand.nextLong() + ".log");
199             FileOutputStream JavaDoc fos = new FileOutputStream JavaDoc(tmp);
200             tmp2 = new File JavaDoc("pvcs_ant_" + rand.nextLong() + ".log");
201             log(commandLine.describeCommand(), Project.MSG_VERBOSE);
202             try {
203                 result = runCmd(commandLine,
204                                 new PumpStreamHandler(fos,
205                                     new LogOutputStream(this,
206                                                         Project.MSG_WARN)));
207             } finally {
208                 fos.close();
209             }
210
211             if (Execute.isFailure(result) && !ignorerc) {
212                 String JavaDoc msg = "Failed executing: " + commandLine.toString();
213                 throw new BuildException(msg, getLocation());
214             }
215
216             if (!tmp.exists()) {
217                 throw new BuildException("Communication between ant and pvcs "
218                     + "failed. No output generated from executing PVCS "
219                     + "commandline interface \"pcli\" and \"get\"");
220             }
221
222             // Create folders in workspace
223
log("Creating folders", Project.MSG_INFO);
224             createFolders(tmp);
225
226             // Massage PCLI lvf output transforming '\' to '/' so get command works appropriately
227
massagePCLI(tmp, tmp2);
228
229             // Launch get on output captured from PCLI lvf
230
commandLine.clearArgs();
231             commandLine.setExecutable(getExecutable(GET_EXE));
232
233             if (getConfig() != null && getConfig().length() > 0) {
234                 commandLine.createArgument().setValue("-c" + getConfig());
235             }
236
237             if (getForce() != null && getForce().equals("yes")) {
238                 commandLine.createArgument().setValue("-Y");
239             } else {
240                 commandLine.createArgument().setValue("-N");
241             }
242
243             if (getPromotiongroup() != null) {
244                 commandLine.createArgument().setValue("-G"
245                     + getPromotiongroup());
246             } else {
247                 if (getLabel() != null) {
248                     commandLine.createArgument().setValue("-v" + getLabel());
249                 } else {
250                     if (getRevision() != null) {
251                         commandLine.createArgument().setValue("-r"
252                             + getRevision());
253                     }
254                 }
255             }
256
257             if (updateOnly) {
258                 commandLine.createArgument().setValue("-U");
259             }
260
261             commandLine.createArgument().setValue("@" + tmp2.getAbsolutePath());
262             log("Getting files", Project.MSG_INFO);
263             log("Executing " + commandLine.toString(), Project.MSG_VERBOSE);
264             result = runCmd(commandLine,
265                 new LogStreamHandler(this, Project.MSG_INFO, Project.MSG_WARN));
266             if (result != 0 && !ignorerc) {
267                 String JavaDoc msg = "Failed executing: " + commandLine.toString()
268                     + ". Return code was " + result;
269                 throw new BuildException(msg, getLocation());
270             }
271
272         } catch (FileNotFoundException JavaDoc e) {
273             String JavaDoc msg = "Failed executing: " + commandLine.toString()
274                 + ". Exception: " + e.getMessage();
275             throw new BuildException(msg, getLocation());
276         } catch (IOException JavaDoc e) {
277             String JavaDoc msg = "Failed executing: " + commandLine.toString()
278                 + ". Exception: " + e.getMessage();
279             throw new BuildException(msg, getLocation());
280         } catch (ParseException JavaDoc e) {
281             String JavaDoc msg = "Failed executing: " + commandLine.toString()
282                 + ". Exception: " + e.getMessage();
283             throw new BuildException(msg, getLocation());
284         } finally {
285             if (tmp != null) {
286                 tmp.delete();
287             }
288             if (tmp2 != null) {
289                 tmp2.delete();
290             }
291         }
292     }
293
294     /**
295      * Parses the file and creates the folders specified in the output section
296      */

297     private void createFolders(File JavaDoc file) throws IOException JavaDoc, ParseException JavaDoc {
298         BufferedReader JavaDoc in = null;
299         try {
300             in = new BufferedReader JavaDoc(new FileReader JavaDoc(file));
301             MessageFormat JavaDoc mf = new MessageFormat JavaDoc(getFilenameFormat());
302             String JavaDoc line = in.readLine();
303             while (line != null) {
304                 log("Considering \"" + line + "\"", Project.MSG_VERBOSE);
305                 if (line.startsWith("\"\\") // Checking for "\
306
|| line.startsWith("\"/") // or "/
307
// or "X:\...
308
|| (line.length() > POS_3 && line.startsWith("\"")
309                         && Character.isLetter(line.charAt(POS_1))
310                         && String.valueOf(line.charAt(POS_2)).equals(":")
311                         && String.valueOf(line.charAt(POS_3)).equals("\\"))) {
312                     Object JavaDoc[] objs = mf.parse(line);
313                     String JavaDoc f = (String JavaDoc) objs[1];
314                     // Extract the name of the directory from the filename
315
int index = f.lastIndexOf(File.separator);
316                     if (index > -1) {
317                         File JavaDoc dir = new File JavaDoc(f.substring(0, index));
318                         if (!dir.exists()) {
319                             log("Creating " + dir.getAbsolutePath(),
320                                 Project.MSG_VERBOSE);
321                             if (dir.mkdirs()) {
322                                 log("Created " + dir.getAbsolutePath(),
323                                     Project.MSG_INFO);
324                             } else {
325                                 log("Failed to create "
326                                     + dir.getAbsolutePath(),
327                                     Project.MSG_INFO);
328                             }
329                         } else {
330                             log(dir.getAbsolutePath() + " exists. Skipping",
331                                 Project.MSG_VERBOSE);
332                         }
333                     } else {
334                         log("File separator problem with " + line,
335                             Project.MSG_WARN);
336                     }
337                 } else {
338                     log("Skipped \"" + line + "\"", Project.MSG_VERBOSE);
339                 }
340                 line = in.readLine();
341             }
342         } finally {
343             if (in != null) {
344                 in.close();
345             }
346         }
347     }
348
349
350     /**
351      * Simple hack to handle the PVCS command-line tools botch when
352      * handling UNC notation.
353      * @throws IOException if there is an error.
354      */

355     private void massagePCLI(File JavaDoc in, File JavaDoc out)
356         throws IOException JavaDoc {
357         BufferedReader JavaDoc inReader = null;
358         BufferedWriter JavaDoc outWriter = null;
359         try {
360             inReader = new BufferedReader JavaDoc(new FileReader JavaDoc(in));
361             outWriter = new BufferedWriter JavaDoc(new FileWriter JavaDoc(out));
362             String JavaDoc s = null;
363             while ((s = inReader.readLine()) != null) {
364                 String JavaDoc sNormal = s.replace('\\', '/');
365                 outWriter.write(sNormal);
366                 outWriter.newLine();
367             }
368         } finally {
369             if (inReader != null) {
370                 inReader.close();
371             }
372             if (outWriter != null) {
373                 outWriter.close();
374             }
375         }
376     }
377
378     /**
379      * Get network name of the PVCS repository
380      * @return String
381      */

382     public String JavaDoc getRepository() {
383         return repository;
384     }
385
386     /**
387      * The filenameFormat attribute defines a MessageFormat string used
388      * to parse the output of the pcli command. It defaults to
389      * <code>{0}-arc({1})</code>. Repositories where the archive
390      * extension is not -arc should set this.
391      * @return the filename format attribute.
392      */

393     public String JavaDoc getFilenameFormat() {
394         return filenameFormat;
395     }
396
397     /**
398      * The format of the folder names; optional.
399      * This must be in a format suitable for
400      * <code>java.text.MessageFormat</code>.
401      * Index 1 of the format will be used as the file name.
402      * Defaults to <code>{0}-arc({1})</code>
403      * @param f the format to use.
404      */

405     public void setFilenameFormat(String JavaDoc f) {
406         filenameFormat = f;
407     }
408
409     /**
410
411      * The lineStart attribute is used to parse the output of the pcli
412      * command. It defaults to <code>&quot;P:</code>. The parser already
413      * knows about / and \\, this property is useful in cases where the
414      * repository is accessed on a Windows platform via a drive letter
415      * mapping.
416      * @return the lineStart attribute.
417      */

418     public String JavaDoc getLineStart() {
419         return lineStart;
420     }
421
422     /**
423      * What a valid return value from PVCS looks like
424      * when it describes a file. Defaults to <code>&quot;P:</code>.
425      * If you are not using an UNC name for your repository and the
426      * drive letter <code>P</code> is incorrect for your setup, you may
427      * need to change this value, UNC names will always be
428      * accepted.
429      * @param l the value to use.
430      */

431     public void setLineStart(String JavaDoc l) {
432         lineStart = l;
433     }
434
435     /**
436      * The network name of the PVCS repository; required.
437      * @param repo String
438      */

439     public void setRepository(String JavaDoc repo) {
440         repository = repo;
441     }
442
443     /**
444      * Get name of the project in the PVCS repository
445      * @return String
446      */

447     public String JavaDoc getPvcsproject() {
448         return pvcsProject;
449     }
450
451     /**
452      * The project within the PVCS repository to extract files from;
453      * optional, default &quot;/&quot;
454      * @param prj String
455      */

456     public void setPvcsproject(String JavaDoc prj) {
457         pvcsProject = prj;
458     }
459
460     /**
461      * Get name of the project in the PVCS repository
462      * @return Vector
463      */

464     public Vector JavaDoc getPvcsprojects() {
465         return pvcsProjects;
466     }
467
468     /**
469      * Get name of the workspace to store the retrieved files
470      * @return String
471      */

472     public String JavaDoc getWorkspace() {
473         return workspace;
474     }
475
476     /**
477      * Workspace to use; optional.
478      * By specifying a workspace, the files are extracted to that location.
479      * A PVCS workspace is a name for a location of the workfiles and
480      * isn't as such the location itself.
481      * You define the location for a workspace using the PVCS GUI clients.
482      * If this isn't specified the default workspace for the current user is used.
483      * @param ws String
484      */

485     public void setWorkspace(String JavaDoc ws) {
486         workspace = ws;
487     }
488
489     /**
490      * Get name of the PVCS bin directory
491      * @return String
492      */

493     public String JavaDoc getPvcsbin() {
494         return pvcsbin;
495     }
496
497     /**
498      * Specifies the location of the PVCS bin directory; optional if on the PATH.
499      * On some systems the PVCS executables <i>pcli</i>
500      * and <i>get</i> are not found in the PATH. In such cases this attribute
501      * should be set to the bin directory of the PVCS installation containing
502      * the executables mentioned before. If this attribute isn't specified the
503      * tag expects the executables to be found using the PATH environment variable.
504      * @param bin PVCS bin directory
505      * @todo use a File setter and resolve paths.
506      */

507     public void setPvcsbin(String JavaDoc bin) {
508         pvcsbin = bin;
509     }
510
511     /**
512      * Get value of force
513      * @return String
514      */

515     public String JavaDoc getForce() {
516         return force;
517     }
518
519     /**
520      * Specifies the value of the force argument; optional.
521      * If set to <i>yes</i> all files that exists and are
522      * writable are overwritten. Default <i>no</i> causes the files
523      * that are writable to be ignored. This stops the PVCS command
524      * <i>get</i> to stop asking questions!
525      * @todo make a boolean setter
526      * @param f String (yes/no)
527      */

528     public void setForce(String JavaDoc f) {
529         if (f != null && f.equalsIgnoreCase("yes")) {
530             force = "yes";
531         } else {
532             force = "no";
533         }
534     }
535
536     /**
537      * Get value of promotiongroup
538      * @return String
539      */

540     public String JavaDoc getPromotiongroup() {
541         return promotiongroup;
542     }
543
544     /**
545      * Specifies the name of the promotiongroup argument
546      * @param w String
547      */

548     public void setPromotiongroup(String JavaDoc w) {
549         promotiongroup = w;
550     }
551
552     /**
553      * Get value of label
554      * @return String
555      */

556     public String JavaDoc getLabel() {
557         return label;
558     }
559
560     /**
561      * Only files marked with this label are extracted; optional.
562      * @param l String
563      */

564     public void setLabel(String JavaDoc l) {
565         label = l;
566     }
567
568     /**
569      * Get value of revision
570      * @return String
571      */

572     public String JavaDoc getRevision() {
573         return revision;
574     }
575
576     /**
577      * Only files with this revision are extract; optional.
578      * @param r String
579      */

580     public void setRevision(String JavaDoc r) {
581         revision = r;
582     }
583
584     /**
585      * Get value of ignorereturncode
586      * @return String
587      */

588     public boolean getIgnoreReturnCode() {
589         return ignorerc;
590     }
591
592     /**
593      * If set to true the return value from executing the pvcs
594      * commands are ignored; optional, default false.
595      * @param b a <code>boolean</code> value.
596      */

597     public void setIgnoreReturnCode(boolean b) {
598         ignorerc = b;
599     }
600
601     /**
602      * Specify a project within the PVCS repository to extract files from.
603      * @param p the pvcs project to use.
604      */

605     public void addPvcsproject(PvcsProject p) {
606         pvcsProjects.addElement(p);
607     }
608
609     /**
610      * get the updateOnly attribute.
611      * @return the updateOnly attribute.
612      */

613     public boolean getUpdateOnly() {
614         return updateOnly;
615     }
616
617     /**
618      * If set to <i>true</i> files are fetched only if
619      * newer than existing local files; optional, default false.
620      * @param l a <code>boolean</code> value.
621      */

622     public void setUpdateOnly(boolean l) {
623         updateOnly = l;
624     }
625
626     /**
627      * returns the path of the configuration file to be used
628      * @return the path of the config file
629      */

630     public String JavaDoc getConfig() {
631         return config;
632     }
633
634     /**
635      * Sets a configuration file other than the default to be used.
636      * These files have a .cfg extension and are often found in archive or pvcsprop folders.
637      * @param f config file - can be given absolute or relative to ant basedir
638      */

639     public void setConfig(File JavaDoc f) {
640         config = f.toString();
641     }
642
643
644     /**
645      * Get the userid.
646      * @return the userid.
647      */

648     public String JavaDoc getUserId() {
649         return userId;
650     }
651
652     /**
653      * User ID
654      * @param u the value to use.
655      */

656     public void setUserId(String JavaDoc u) {
657         userId = u;
658     }
659
660     /**
661      * Creates a Pvcs object
662      */

663     public Pvcs() {
664         super();
665         pvcsProject = null;
666         pvcsProjects = new Vector JavaDoc();
667         workspace = null;
668         repository = null;
669         pvcsbin = null;
670         force = null;
671         promotiongroup = null;
672         label = null;
673         ignorerc = false;
674         updateOnly = false;
675         lineStart = "\"P:";
676         filenameFormat = "{0}-arc({1})";
677     }
678 }
679
680
Popular Tags