diff options
Diffstat (limited to 'framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/pvcs/Pvcs.java')
-rw-r--r-- | framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/pvcs/Pvcs.java | 675 |
1 files changed, 675 insertions, 0 deletions
diff --git a/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/pvcs/Pvcs.java b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/pvcs/Pvcs.java new file mode 100644 index 00000000..dd6016a8 --- /dev/null +++ b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/pvcs/Pvcs.java @@ -0,0 +1,675 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tools.ant.taskdefs.optional.pvcs; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.text.MessageFormat; +import java.text.ParseException; +import java.util.Enumeration; +import java.util.Random; +import java.util.Vector; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.taskdefs.Execute; +import org.apache.tools.ant.taskdefs.ExecuteStreamHandler; +import org.apache.tools.ant.taskdefs.LogOutputStream; +import org.apache.tools.ant.taskdefs.LogStreamHandler; +import org.apache.tools.ant.taskdefs.PumpStreamHandler; +import org.apache.tools.ant.types.Commandline; +import org.apache.tools.ant.util.FileUtils; + +/** + * + * Extracts the latest edition of the source code from a PVCS repository. + * PVCS is a version control system + * developed by <a href="http://www.merant.com/products/pvcs">Merant</a>. + * <br> + * Before using this tag, the user running ant must have access to the commands + * of PVCS (get and pcli) and must have access to the repository. Note that the way to specify + * the repository is platform dependent so use property to specify location of repository. + * <br> + * This version has been tested against PVCS version 6.5 and 6.6 under Windows and Solaris. + + * + * <b>19-04-2001</b> <p>The task now has a more robust + * parser. It allows for platform independent file paths + * and supports file names with <i>()</i>. Thanks to Erik Husby for + * bringing the bug to my attention. + * + * <b>27-04-2001</b> <p>UNC paths are now handled properly. + * Fix provided by Don Jeffery. He also added an <i>UpdateOnly</i> flag + * that, when true, conditions the PVCS get using the -U option to only + * update those files that have a modification time (in PVCS) that is newer + * than the existing workfile. + * + * <b>25-10-2002</b> <p>Added a revision attribute that currently is a + * synonym for label, but in a future release the behavior of the label + * attribute will change to use the -v option of GET. See bug #13847 for + * discussion. + * + */ +public class Pvcs extends org.apache.tools.ant.Task { + // CheckStyle - magic numbers + // checking for "X:\ 0=dquote,1=letter,2=:,3=\ + private static final int POS_1 = 1; + private static final int POS_2 = 2; + private static final int POS_3 = 3; + + private String pvcsbin; + private String repository; + private String pvcsProject; + private Vector pvcsProjects; + private String workspace; + private String force; + private String promotiongroup; + private String label; + private String revision; + private boolean ignorerc; + private boolean updateOnly; + private String filenameFormat; + private String lineStart; + private String userId; + private String config; + /** + * Constant for the thing to execute + */ + private static final String PCLI_EXE = "pcli"; + + /* + * Constant for the PCLI listversionedfiles recursive i a format "get" understands + */ + // private static final String PCLI_LVF_ARGS = "lvf -z -aw"; + + /** + * Constant for the thing to execute + */ + private static final String GET_EXE = "get"; + + + /** + * Run the command. + * @param cmd the command line to use. + * @param out the output stream handler to use. + * @return the exit code of the command. + */ + protected int runCmd(Commandline cmd, ExecuteStreamHandler out) { + try { + Project aProj = getProject(); + Execute exe = new Execute(out); + exe.setAntRun(aProj); + exe.setWorkingDirectory(aProj.getBaseDir()); + exe.setCommandline(cmd.getCommandline()); + return exe.execute(); + } catch (java.io.IOException e) { + String msg = "Failed executing: " + cmd.toString() + + ". Exception: " + e.getMessage(); + throw new BuildException(msg, getLocation()); + } + } + + private String getExecutable(String exe) { + StringBuffer correctedExe = new StringBuffer(); + if (getPvcsbin() != null) { + if (pvcsbin.endsWith(File.separator)) { + correctedExe.append(pvcsbin); + } else { + correctedExe.append(pvcsbin).append(File.separator); + } + } + return correctedExe.append(exe).toString(); + } + + /** + * @exception org.apache.tools.ant.BuildException Something is stopping the build... + */ + public void execute() throws org.apache.tools.ant.BuildException { + int result = 0; + + if (repository == null || repository.trim().equals("")) { + throw new BuildException("Required argument repository not specified"); + } + + // Check workspace exists + // Launch PCLI listversionedfiles -z -aw + // Capture output + // build the command line from what we got the format is + Commandline commandLine = new Commandline(); + commandLine.setExecutable(getExecutable(PCLI_EXE)); + + commandLine.createArgument().setValue("lvf"); + commandLine.createArgument().setValue("-z"); + commandLine.createArgument().setValue("-aw"); + if (getWorkspace() != null) { + commandLine.createArgument().setValue("-sp" + getWorkspace()); + } + commandLine.createArgument().setValue("-pr" + getRepository()); + + String uid = getUserId(); + + if (uid != null) { + commandLine.createArgument().setValue("-id" + uid); + } + + // default pvcs project is "/" + if (getPvcsproject() == null && getPvcsprojects().isEmpty()) { + pvcsProject = "/"; + } + + if (getPvcsproject() != null) { + commandLine.createArgument().setValue(getPvcsproject()); + } + if (!getPvcsprojects().isEmpty()) { + Enumeration e = getPvcsprojects().elements(); + while (e.hasMoreElements()) { + String projectName = ((PvcsProject) e.nextElement()).getName(); + if (projectName == null || (projectName.trim()).equals("")) { + throw new BuildException("name is a required attribute " + + "of pvcsproject"); + } + commandLine.createArgument().setValue(projectName); + } + } + + File tmp = null; + File tmp2 = null; + try { + Random rand = new Random(System.currentTimeMillis()); + tmp = new File("pvcs_ant_" + rand.nextLong() + ".log"); + FileOutputStream fos = new FileOutputStream(tmp); + tmp2 = new File("pvcs_ant_" + rand.nextLong() + ".log"); + log(commandLine.describeCommand(), Project.MSG_VERBOSE); + try { + result = runCmd(commandLine, + new PumpStreamHandler(fos, + new LogOutputStream(this, + Project.MSG_WARN))); + } finally { + FileUtils.close(fos); + } + + if (Execute.isFailure(result) && !ignorerc) { + String msg = "Failed executing: " + commandLine.toString(); + throw new BuildException(msg, getLocation()); + } + + if (!tmp.exists()) { + throw new BuildException("Communication between ant and pvcs " + + "failed. No output generated from executing PVCS " + + "commandline interface \"pcli\" and \"get\""); + } + + // Create folders in workspace + log("Creating folders", Project.MSG_INFO); + createFolders(tmp); + + // Massage PCLI lvf output transforming '\' to '/' so get command works appropriately + massagePCLI(tmp, tmp2); + + // Launch get on output captured from PCLI lvf + commandLine.clearArgs(); + commandLine.setExecutable(getExecutable(GET_EXE)); + + if (getConfig() != null && getConfig().length() > 0) { + commandLine.createArgument().setValue("-c" + getConfig()); + } + + if (getForce() != null && getForce().equals("yes")) { + commandLine.createArgument().setValue("-Y"); + } else { + commandLine.createArgument().setValue("-N"); + } + + if (getPromotiongroup() != null) { + commandLine.createArgument().setValue("-G" + + getPromotiongroup()); + } else { + if (getLabel() != null) { + commandLine.createArgument().setValue("-v" + getLabel()); + } else { + if (getRevision() != null) { + commandLine.createArgument().setValue("-r" + + getRevision()); + } + } + } + + if (updateOnly) { + commandLine.createArgument().setValue("-U"); + } + + commandLine.createArgument().setValue("@" + tmp2.getAbsolutePath()); + log("Getting files", Project.MSG_INFO); + log("Executing " + commandLine.toString(), Project.MSG_VERBOSE); + result = runCmd(commandLine, + new LogStreamHandler(this, Project.MSG_INFO, Project.MSG_WARN)); + if (result != 0 && !ignorerc) { + String msg = "Failed executing: " + commandLine.toString() + + ". Return code was " + result; + throw new BuildException(msg, getLocation()); + } + + } catch (FileNotFoundException e) { + String msg = "Failed executing: " + commandLine.toString() + + ". Exception: " + e.getMessage(); + throw new BuildException(msg, getLocation()); + } catch (IOException e) { + String msg = "Failed executing: " + commandLine.toString() + + ". Exception: " + e.getMessage(); + throw new BuildException(msg, getLocation()); + } catch (ParseException e) { + String msg = "Failed executing: " + commandLine.toString() + + ". Exception: " + e.getMessage(); + throw new BuildException(msg, getLocation()); + } finally { + if (tmp != null) { + tmp.delete(); + } + if (tmp2 != null) { + tmp2.delete(); + } + } + } + + /** + * Parses the file and creates the folders specified in the output section + */ + private void createFolders(File file) throws IOException, ParseException { + BufferedReader in = null; + try { + in = new BufferedReader(new FileReader(file)); + MessageFormat mf = new MessageFormat(getFilenameFormat()); + String line = in.readLine(); + while (line != null) { + log("Considering \"" + line + "\"", Project.MSG_VERBOSE); + if (line.startsWith("\"\\") // Checking for "\ + || line.startsWith("\"/") // or "/ + // or "X:\... + || (line.length() > POS_3 && line.startsWith("\"") + && Character.isLetter(line.charAt(POS_1)) + && String.valueOf(line.charAt(POS_2)).equals(":") + && String.valueOf(line.charAt(POS_3)).equals("\\"))) { + Object[] objs = mf.parse(line); + String f = (String) objs[1]; + // Extract the name of the directory from the filename + int index = f.lastIndexOf(File.separator); + if (index > -1) { + File dir = new File(f.substring(0, index)); + if (!dir.exists()) { + log("Creating " + dir.getAbsolutePath(), + Project.MSG_VERBOSE); + if (dir.mkdirs() || dir.isDirectory()) { + log("Created " + dir.getAbsolutePath(), + Project.MSG_INFO); + } else { + log("Failed to create " + + dir.getAbsolutePath(), + Project.MSG_INFO); + } + } else { + log(dir.getAbsolutePath() + " exists. Skipping", + Project.MSG_VERBOSE); + } + } else { + log("File separator problem with " + line, + Project.MSG_WARN); + } + } else { + log("Skipped \"" + line + "\"", Project.MSG_VERBOSE); + } + line = in.readLine(); + } + } finally { + FileUtils.close(in); + } + } + + + /** + * Simple hack to handle the PVCS command-line tools botch when + * handling UNC notation. + * @throws IOException if there is an error. + */ + private void massagePCLI(File in, File out) + throws IOException { + BufferedReader inReader = null; + BufferedWriter outWriter = null; + try { + inReader = new BufferedReader(new FileReader(in)); + outWriter = new BufferedWriter(new FileWriter(out)); + String s = null; + while ((s = inReader.readLine()) != null) { + String sNormal = s.replace('\\', '/'); + outWriter.write(sNormal); + outWriter.newLine(); + } + } finally { + FileUtils.close(inReader); + FileUtils.close(outWriter); + } + } + + /** + * Get network name of the PVCS repository + * @return String + */ + public String getRepository() { + return repository; + } + + /** + * The filenameFormat attribute defines a MessageFormat string used + * to parse the output of the pcli command. It defaults to + * <code>{0}-arc({1})</code>. Repositories where the archive + * extension is not -arc should set this. + * @return the filename format attribute. + */ + public String getFilenameFormat() { + return filenameFormat; + } + + /** + * The format of the folder names; optional. + * This must be in a format suitable for + * <code>java.text.MessageFormat</code>. + * Index 1 of the format will be used as the file name. + * Defaults to <code>{0}-arc({1})</code> + * @param f the format to use. + */ + public void setFilenameFormat(String f) { + filenameFormat = f; + } + + /** + + * The lineStart attribute is used to parse the output of the pcli + * command. It defaults to <code>"P:</code>. The parser already + * knows about / and \\, this property is useful in cases where the + * repository is accessed on a Windows platform via a drive letter + * mapping. + * @return the lineStart attribute. + */ + public String getLineStart() { + return lineStart; + } + + /** + * What a valid return value from PVCS looks like + * when it describes a file. Defaults to <code>"P:</code>. + * If you are not using an UNC name for your repository and the + * drive letter <code>P</code> is incorrect for your setup, you may + * need to change this value, UNC names will always be + * accepted. + * @param l the value to use. + */ + public void setLineStart(String l) { + lineStart = l; + } + + /** + * The network name of the PVCS repository; required. + * @param repo String + */ + public void setRepository(String repo) { + repository = repo; + } + + /** + * Get name of the project in the PVCS repository + * @return String + */ + public String getPvcsproject() { + return pvcsProject; + } + + /** + * The project within the PVCS repository to extract files from; + * optional, default "/" + * @param prj String + */ + public void setPvcsproject(String prj) { + pvcsProject = prj; + } + + /** + * Get name of the project in the PVCS repository + * @return Vector + */ + public Vector getPvcsprojects() { + return pvcsProjects; + } + + /** + * Get name of the workspace to store the retrieved files + * @return String + */ + public String getWorkspace() { + return workspace; + } + + /** + * Workspace to use; optional. + * By specifying a workspace, the files are extracted to that location. + * A PVCS workspace is a name for a location of the workfiles and + * isn't as such the location itself. + * You define the location for a workspace using the PVCS GUI clients. + * If this isn't specified the default workspace for the current user is used. + * @param ws String + */ + public void setWorkspace(String ws) { + workspace = ws; + } + + /** + * Get name of the PVCS bin directory + * @return String + */ + public String getPvcsbin() { + return pvcsbin; + } + + /** + * Specifies the location of the PVCS bin directory; optional if on the PATH. + * On some systems the PVCS executables <i>pcli</i> + * and <i>get</i> are not found in the PATH. In such cases this attribute + * should be set to the bin directory of the PVCS installation containing + * the executables mentioned before. If this attribute isn't specified the + * tag expects the executables to be found using the PATH environment variable. + * @param bin PVCS bin directory + * @todo use a File setter and resolve paths. + */ + public void setPvcsbin(String bin) { + pvcsbin = bin; + } + + /** + * Get value of force + * @return String + */ + public String getForce() { + return force; + } + + /** + * Specifies the value of the force argument; optional. + * If set to <i>yes</i> all files that exists and are + * writable are overwritten. Default <i>no</i> causes the files + * that are writable to be ignored. This stops the PVCS command + * <i>get</i> to stop asking questions! + * @todo make a boolean setter + * @param f String (yes/no) + */ + public void setForce(String f) { + if (f != null && f.equalsIgnoreCase("yes")) { + force = "yes"; + } else { + force = "no"; + } + } + + /** + * Get value of promotiongroup + * @return String + */ + public String getPromotiongroup() { + return promotiongroup; + } + + /** + * Specifies the name of the promotiongroup argument + * @param w String + */ + public void setPromotiongroup(String w) { + promotiongroup = w; + } + + /** + * Get value of label + * @return String + */ + public String getLabel() { + return label; + } + + /** + * Only files marked with this label are extracted; optional. + * @param l String + */ + public void setLabel(String l) { + label = l; + } + + /** + * Get value of revision + * @return String + */ + public String getRevision() { + return revision; + } + + /** + * Only files with this revision are extract; optional. + * @param r String + */ + public void setRevision(String r) { + revision = r; + } + + /** + * Get value of ignorereturncode + * @return String + */ + public boolean getIgnoreReturnCode() { + return ignorerc; + } + + /** + * If set to true the return value from executing the pvcs + * commands are ignored; optional, default false. + * @param b a <code>boolean</code> value. + */ + public void setIgnoreReturnCode(boolean b) { + ignorerc = b; + } + + /** + * Specify a project within the PVCS repository to extract files from. + * @param p the pvcs project to use. + */ + public void addPvcsproject(PvcsProject p) { + pvcsProjects.addElement(p); + } + + /** + * get the updateOnly attribute. + * @return the updateOnly attribute. + */ + public boolean getUpdateOnly() { + return updateOnly; + } + + /** + * If set to <i>true</i> files are fetched only if + * newer than existing local files; optional, default false. + * @param l a <code>boolean</code> value. + */ + public void setUpdateOnly(boolean l) { + updateOnly = l; + } + + /** + * returns the path of the configuration file to be used + * @return the path of the config file + */ + public String getConfig() { + return config; + } + + /** + * Sets a configuration file other than the default to be used. + * These files have a .cfg extension and are often found in archive or pvcsprop folders. + * @param f config file - can be given absolute or relative to ant basedir + */ + public void setConfig(File f) { + config = f.toString(); + } + + + /** + * Get the userid. + * @return the userid. + */ + public String getUserId() { + return userId; + } + + /** + * User ID + * @param u the value to use. + */ + public void setUserId(String u) { + userId = u; + } + + /** + * Creates a Pvcs object + */ + public Pvcs() { + super(); + pvcsProject = null; + pvcsProjects = new Vector(); + workspace = null; + repository = null; + pvcsbin = null; + force = null; + promotiongroup = null; + label = null; + ignorerc = false; + updateOnly = false; + lineStart = "\"P:"; + filenameFormat = "{0}-arc({1})"; + } +} + |