diff options
Diffstat (limited to 'framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSS.java')
-rw-r--r-- | framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSS.java | 784 |
1 files changed, 784 insertions, 0 deletions
diff --git a/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSS.java b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSS.java new file mode 100644 index 00000000..f514fc62 --- /dev/null +++ b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSS.java @@ -0,0 +1,784 @@ +/* + * 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.vss; + +import java.io.File; +import java.io.IOException; +import java.text.DateFormat; +import java.text.ParseException; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.Task; +import org.apache.tools.ant.taskdefs.Execute; +import org.apache.tools.ant.taskdefs.LogStreamHandler; +import org.apache.tools.ant.types.Commandline; +import org.apache.tools.ant.types.EnumeratedAttribute; +import org.apache.tools.ant.util.FileUtils; + +/** + * A base class for creating tasks for executing commands on Visual SourceSafe. + * <p> + * The class extends the 'exec' task as it operates by executing the ss.exe program + * supplied with SourceSafe. By default the task expects ss.exe to be in the path, + * you can override this be specifying the ssdir attribute. + * </p> + * <p> + * This class provides set and get methods for 'login' and 'vsspath' attributes. It + * also contains constants for the flags that can be passed to SS. + * </p> + * + */ +public abstract class MSVSS extends Task implements MSVSSConstants { + + private String ssDir = null; + private String vssLogin = null; + private String vssPath = null; + private String serverPath = null; + + /** Version */ + private String version = null; + /** Date */ + private String date = null; + /** Label */ + private String label = null; + /** Auto response */ + private String autoResponse = null; + /** Local path */ + private String localPath = null; + /** Comment */ + private String comment = null; + /** From label */ + private String fromLabel = null; + /** To label */ + private String toLabel = null; + /** Output file name */ + private String outputFileName = null; + /** User */ + private String user = null; + /** From date */ + private String fromDate = null; + /** To date */ + private String toDate = null; + /** History style */ + private String style = null; + /** Quiet defaults to false */ + private boolean quiet = false; + /** Recursive defaults to false */ + private boolean recursive = false; + /** Writable defaults to false */ + private boolean writable = false; + /** Fail on error defaults to true */ + private boolean failOnError = true; + /** Get local copy for checkout defaults to true */ + private boolean getLocalCopy = true; + /** Number of days offset for History */ + private int numDays = Integer.MIN_VALUE; + /** Date format for History */ + private DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.SHORT); + /** Timestamp for retreived files */ + private CurrentModUpdated timestamp = null; + /** Behaviour for writable files */ + private WritableFiles writableFiles = null; + + /** + * Each sub-class must implemnt this method and return the constructed + * command line to be executed. It is up to the sub-task to determine the + * required attrubutes and their order. + * @return The Constructed command line. + */ + abstract Commandline buildCmdLine(); + + /** + * Directory where <code>ss.exe</code> resides. + * By default the task expects it to be in the PATH. + * @param dir The directory containing ss.exe. + */ + public final void setSsdir(String dir) { + this.ssDir = FileUtils.translatePath(dir); + } + + /** + * Login to use when accessing VSS, formatted as "username,password". + * <p> + * You can omit the password if your database is not password protected. + * If you have a password and omit it, Ant will hang. + * @param vssLogin The login string to use. + */ + public final void setLogin(final String vssLogin) { + this.vssLogin = vssLogin; + } + + /** + * SourceSafe path which specifies the project/file(s) you wish to perform + * the action on. + * <p> + * A prefix of 'vss://' will be removed if specified. + * @param vssPath The VSS project path. + * @ant.attribute group="required" + */ + public final void setVsspath(final String vssPath) { + String projectPath; + // CheckStyle:MagicNumber OFF + if (vssPath.startsWith("vss://")) { //$NON-NLS-1$ + projectPath = vssPath.substring(5); + } else { + projectPath = vssPath; + } + // CheckStyle:MagicNumber ON + + if (projectPath.startsWith(PROJECT_PREFIX)) { + this.vssPath = projectPath; + } else { + this.vssPath = PROJECT_PREFIX + projectPath; + } + } + + /** + * Directory where <code>srssafe.ini</code> resides. + * @param serverPath The path to the VSS server. + */ + public final void setServerpath(final String serverPath) { + this.serverPath = serverPath; + } + + /** + * Indicates if the build should fail if the Sourcesafe command does. Defaults to true. + * @param failOnError True if task should fail on any error. + */ + public final void setFailOnError(final boolean failOnError) { + this.failOnError = failOnError; + } + + /** + * Executes the task. <br> + * Builds a command line to execute ss.exe and then calls Exec's run method + * to execute the command line. + * @throws BuildException if the command cannot execute. + */ + public void execute() throws BuildException { + int result = 0; + Commandline commandLine = buildCmdLine(); + result = run(commandLine); + if (Execute.isFailure(result) && getFailOnError()) { + String msg = "Failed executing: " + formatCommandLine(commandLine) + + " With a return code of " + result; + throw new BuildException(msg, getLocation()); + } + } + + // Special setters for the sub-classes + + /** + * Set the internal comment attribute. + * @param comment the value to use. + */ + protected void setInternalComment(final String comment) { + this.comment = comment; + } + + /** + * Set the auto response attribute. + * @param autoResponse the value to use. + */ + protected void setInternalAutoResponse(final String autoResponse) { + this.autoResponse = autoResponse; + } + + /** + * Set the date attribute. + * @param date the value to use. + */ + protected void setInternalDate(final String date) { + this.date = date; + } + + /** + * Set the date format attribute. + * @param dateFormat the value to use. + */ + protected void setInternalDateFormat(final DateFormat dateFormat) { + this.dateFormat = dateFormat; + } + + /** + * Set the failOnError attribute. + * @param failOnError the value to use. + */ + protected void setInternalFailOnError(final boolean failOnError) { + this.failOnError = failOnError; + } + + /** + * Set the from date attribute. + * @param fromDate the value to use. + */ + protected void setInternalFromDate(final String fromDate) { + this.fromDate = fromDate; + } + + /** + * Set the from label attribute. + * @param fromLabel the value to use. + */ + protected void setInternalFromLabel(final String fromLabel) { + this.fromLabel = fromLabel; + } + + /** + * Set the label attribute. + * @param label the value to use. + */ + protected void setInternalLabel(final String label) { + this.label = label; + } + + /** + * Set the local path comment attribute. + * @param localPath the value to use. + */ + protected void setInternalLocalPath(final String localPath) { + this.localPath = localPath; + } + + /** + * Set the num days attribute. + * @param numDays the value to use. + */ + protected void setInternalNumDays(final int numDays) { + this.numDays = numDays; + } + + /** + * Set the outputFileName comment attribute. + * @param outputFileName the value to use. + */ + protected void setInternalOutputFilename(final String outputFileName) { + this.outputFileName = outputFileName; + } + + /** + * Set the quiet attribute. + * @param quiet the value to use. + */ + protected void setInternalQuiet(final boolean quiet) { + this.quiet = quiet; + } + + /** + * Set the recursive attribute. + * @param recursive the value to use. + */ + protected void setInternalRecursive(final boolean recursive) { + this.recursive = recursive; + } + + /** + * Set the style attribute. + * @param style the value to use. + */ + protected void setInternalStyle(final String style) { + this.style = style; + } + + /** + * Set the to date attribute. + * @param toDate the value to use. + */ + protected void setInternalToDate(final String toDate) { + this.toDate = toDate; + } + + /** + * Set the to label attribute. + * @param toLabel the value to use. + */ + protected void setInternalToLabel(final String toLabel) { + this.toLabel = toLabel; + } + + /** + * Set the user attribute. + * @param user the value to use. + */ + protected void setInternalUser(final String user) { + this.user = user; + } + + /** + * Set the version attribute. + * @param version the value to use. + */ + protected void setInternalVersion(final String version) { + this.version = version; + } + + /** + * Set the writable attribute. + * @param writable the value to use. + */ + protected void setInternalWritable(final boolean writable) { + this.writable = writable; + } + + /** + * Set the timestamp attribute. + * @param timestamp the value to use. + */ + protected void setInternalFileTimeStamp(final CurrentModUpdated timestamp) { + this.timestamp = timestamp; + } + + /** + * Set the writableFiles attribute. + * @param writableFiles the value to use. + */ + protected void setInternalWritableFiles(final WritableFiles writableFiles) { + this.writableFiles = writableFiles; + } + + /** + * Set the getLocalCopy attribute. + * @param getLocalCopy the value to use. + */ + protected void setInternalGetLocalCopy(final boolean getLocalCopy) { + this.getLocalCopy = getLocalCopy; + } + + /** + * Gets the sscommand string. "ss" or "c:\path\to\ss" + * @return The path to ss.exe or just ss if sscommand is not set. + */ + protected String getSSCommand() { + if (ssDir == null) { + return SS_EXE; + } + return ssDir.endsWith(File.separator) ? ssDir + SS_EXE : ssDir + + File.separator + SS_EXE; + } + + /** + * Gets the vssserverpath string. + * @return null if vssserverpath is not set. + */ + protected String getVsspath() { + return vssPath; + } + + /** + * Gets the quiet string. -O- + * @return An empty string if quiet is not set or is false. + */ + protected String getQuiet() { + return quiet ? FLAG_QUIET : ""; + } + + /** + * Gets the recursive string. "-R" + * @return An empty string if recursive is not set or is false. + */ + protected String getRecursive() { + return recursive ? FLAG_RECURSION : ""; + } + + /** + * Gets the writable string. "-W" + * @return An empty string if writable is not set or is false. + */ + protected String getWritable() { + return writable ? FLAG_WRITABLE : ""; + } + + /** + * Gets the label string. "-Lbuild1" + * Max label length is 32 chars + * @return An empty string if label is not set. + */ + protected String getLabel() { + String shortLabel = ""; + if (label != null && label.length() > 0) { + shortLabel = FLAG_LABEL + getShortLabel(); + } + return shortLabel; + } + /** + * Return at most the 30 first chars of the label, + * logging a warning message about the truncation + * @return at most the 30 first chars of the label + */ + private String getShortLabel() { + String shortLabel; + // CheckStyle:MagicNumber OFF + if (label != null && label.length() > 31) { + shortLabel = this.label.substring(0, 30); + log("Label is longer than 31 characters, truncated to: " + shortLabel, + Project.MSG_WARN); + } else { + shortLabel = label; + } + // CheckStyle:MagicNumber ON + return shortLabel; + } + /** + * Gets the style string. "-Lbuild1" + * @return An empty string if label is not set. + */ + protected String getStyle() { + return style != null ? style : ""; + } + + /** + * Gets the version string. Returns the first specified of version "-V1.0", + * date "-Vd01.01.01", label "-Vlbuild1". + * @return An empty string if a version, date and label are not set. + */ + protected String getVersionDateLabel() { + String versionDateLabel = ""; + if (version != null) { + versionDateLabel = FLAG_VERSION + version; + } else if (date != null) { + versionDateLabel = FLAG_VERSION_DATE + date; + } else { + // Use getShortLabel() so labels longer then 30 char are truncated + // and the user is warned + String shortLabel = getShortLabel(); + if (shortLabel != null && !shortLabel.equals("")) { + versionDateLabel = FLAG_VERSION_LABEL + shortLabel; + } + } + return versionDateLabel; + } + + /** + * Gets the version string. + * @return An empty string if a version is not set. + */ + protected String getVersion() { + return version != null ? FLAG_VERSION + version : ""; + } + + /** + * Gets the localpath string. "-GLc:\source" <p> + * The localpath is created if it didn't exist. + * @return An empty string if localpath is not set. + */ + protected String getLocalpath() { + String lclPath = ""; //set to empty str if no local path return + if (localPath != null) { + //make sure m_LocalDir exists, create it if it doesn't + File dir = getProject().resolveFile(localPath); + if (!dir.exists()) { + boolean done = dir.mkdirs(); + if (!done) { + String msg = "Directory " + localPath + " creation was not " + + "successful for an unknown reason"; + throw new BuildException(msg, getLocation()); + } + getProject().log("Created dir: " + dir.getAbsolutePath()); + } + lclPath = FLAG_OVERRIDE_WORKING_DIR + localPath; + } + return lclPath; + } + + /** + * Gets the comment string. "-Ccomment text" + * @return A comment of "-" if comment is not set. + */ + protected String getComment() { + return comment != null ? FLAG_COMMENT + comment : FLAG_COMMENT + "-"; + } + + /** + * Gets the auto response string. This can be Y "-I-Y" or N "-I-N". + * @return The default value "-I-" if autoresponse is not set. + */ + protected String getAutoresponse() { + if (autoResponse == null) { + return FLAG_AUTORESPONSE_DEF; + } + if (autoResponse.equalsIgnoreCase("Y")) { + return FLAG_AUTORESPONSE_YES; + } else if (autoResponse.equalsIgnoreCase("N")) { + return FLAG_AUTORESPONSE_NO; + } else { + return FLAG_AUTORESPONSE_DEF; + } + } + + /** + * Gets the login string. This can be user and password, "-Yuser,password" + * or just user "-Yuser". + * @return An empty string if login is not set. + */ + protected String getLogin() { + return vssLogin != null ? FLAG_LOGIN + vssLogin : ""; + } + + /** + * Gets the output file string. "-Ooutput.file" + * @return An empty string if user is not set. + */ + protected String getOutput() { + return outputFileName != null ? FLAG_OUTPUT + outputFileName : ""; + } + + /** + * Gets the user string. "-Uusername" + * @return An empty string if user is not set. + */ + protected String getUser() { + return user != null ? FLAG_USER + user : ""; + } + + /** + * Gets the version string. This can be to-from "-VLbuild2~Lbuild1", from + * "~Lbuild1" or to "-VLbuild2". + * @return An empty string if neither tolabel or fromlabel are set. + */ + protected String getVersionLabel() { + if (fromLabel == null && toLabel == null) { + return ""; + } + // CheckStyle:MagicNumber OFF + if (fromLabel != null && toLabel != null) { + if (fromLabel.length() > 31) { + fromLabel = fromLabel.substring(0, 30); + log("FromLabel is longer than 31 characters, truncated to: " + + fromLabel, Project.MSG_WARN); + } + if (toLabel.length() > 31) { + toLabel = toLabel.substring(0, 30); + log("ToLabel is longer than 31 characters, truncated to: " + + toLabel, Project.MSG_WARN); + } + return FLAG_VERSION_LABEL + toLabel + VALUE_FROMLABEL + fromLabel; + } else if (fromLabel != null) { + if (fromLabel.length() > 31) { + fromLabel = fromLabel.substring(0, 30); + log("FromLabel is longer than 31 characters, truncated to: " + + fromLabel, Project.MSG_WARN); + } + return FLAG_VERSION + VALUE_FROMLABEL + fromLabel; + } else { + if (toLabel.length() > 31) { + toLabel = toLabel.substring(0, 30); + log("ToLabel is longer than 31 characters, truncated to: " + + toLabel, Project.MSG_WARN); + } + return FLAG_VERSION_LABEL + toLabel; + } + // CheckStyle:MagicNumber ON + } + + /** + * Gets the Version date string. + * @return An empty string if neither Todate or from date are set. + * @throws BuildException if there is an error. + */ + protected String getVersionDate() throws BuildException { + if (fromDate == null && toDate == null + && numDays == Integer.MIN_VALUE) { + return ""; + } + if (fromDate != null && toDate != null) { + return FLAG_VERSION_DATE + toDate + VALUE_FROMDATE + fromDate; + } else if (toDate != null && numDays != Integer.MIN_VALUE) { + try { + return FLAG_VERSION_DATE + toDate + VALUE_FROMDATE + + calcDate(toDate, numDays); + } catch (ParseException ex) { + String msg = "Error parsing date: " + toDate; + throw new BuildException(msg, getLocation()); + } + } else if (fromDate != null && numDays != Integer.MIN_VALUE) { + try { + return FLAG_VERSION_DATE + calcDate(fromDate, numDays) + + VALUE_FROMDATE + fromDate; + } catch (ParseException ex) { + String msg = "Error parsing date: " + fromDate; + throw new BuildException(msg, getLocation()); + } + } else { + return fromDate != null ? FLAG_VERSION + VALUE_FROMDATE + + fromDate : FLAG_VERSION_DATE + toDate; + } + } + + /** + * Builds and returns the -G- flag if required. + * @return An empty string if get local copy is true. + */ + protected String getGetLocalCopy() { + return (!getLocalCopy) ? FLAG_NO_GET : ""; + } + + /** + * Gets the value of the fail on error flag. + * @return True if the FailOnError flag has been set or if 'writablefiles=skip'. + */ + private boolean getFailOnError() { + return getWritableFiles().equals(WRITABLE_SKIP) ? false : failOnError; + } + + + /** + * Gets the value set for the FileTimeStamp. + * if it equals "current" then we return -GTC + * if it equals "modified" then we return -GTM + * if it equals "updated" then we return -GTU + * otherwise we return -GTC + * + * @return The default file time flag, if not set. + */ + public String getFileTimeStamp() { + if (timestamp == null) { + return ""; + } else if (timestamp.getValue().equals(TIME_MODIFIED)) { + return FLAG_FILETIME_MODIFIED; + } else if (timestamp.getValue().equals(TIME_UPDATED)) { + return FLAG_FILETIME_UPDATED; + } else { + return FLAG_FILETIME_DEF; + } + } + + + /** + * Gets the value to determine the behaviour when encountering writable files. + * @return An empty String, if not set. + */ + public String getWritableFiles() { + if (writableFiles == null) { + return ""; + } else if (writableFiles.getValue().equals(WRITABLE_REPLACE)) { + return FLAG_REPLACE_WRITABLE; + } else if (writableFiles.getValue().equals(WRITABLE_SKIP)) { + // ss.exe exits with '100', when files have been skipped + // so we have to ignore the failure + failOnError = false; + return FLAG_SKIP_WRITABLE; + } else { + return ""; + } + } + + /** + * Sets up the required environment and executes the command line. + * + * @param cmd The command line to execute. + * @return The return code from the exec'd process. + */ + private int run(Commandline cmd) { + try { + Execute exe = new Execute(new LogStreamHandler(this, + Project.MSG_INFO, + Project.MSG_WARN)); + + // If location of ss.ini is specified we need to set the + // environment-variable SSDIR to this value + if (serverPath != null) { + String[] env = exe.getEnvironment(); + if (env == null) { + env = new String[0]; + } + String[] newEnv = new String[env.length + 1]; + System.arraycopy(env, 0, newEnv, 0, env.length); + newEnv[env.length] = "SSDIR=" + serverPath; + + exe.setEnvironment(newEnv); + } + + exe.setAntRun(getProject()); + exe.setWorkingDirectory(getProject().getBaseDir()); + exe.setCommandline(cmd.getCommandline()); + // Use the OS launcher so we get environment variables + exe.setVMLauncher(false); + return exe.execute(); + } catch (IOException e) { + throw new BuildException(e, getLocation()); + } + } + + /** + * Calculates the start date for version comparison. + * <p> + * Calculates the date numDay days earlier than startdate. + * @param startDate The start date. + * @param daysToAdd The number of days to add. + * @return The calculated date. + * @throws ParseException + */ + private String calcDate(String startDate, int daysToAdd) throws ParseException { + Calendar calendar = new GregorianCalendar(); + Date currentDate = dateFormat.parse(startDate); + calendar.setTime(currentDate); + calendar.add(Calendar.DATE, daysToAdd); + return dateFormat.format(calendar.getTime()); + } + + /** + * Changes the password to '***' so it isn't displayed on screen if the build fails + * + * @param cmd The command line to clean + * @return The command line as a string with out the password + */ + private String formatCommandLine(Commandline cmd) { + StringBuffer sBuff = new StringBuffer(cmd.toString()); + int indexUser = sBuff.substring(0).indexOf(FLAG_LOGIN); + if (indexUser > 0) { + int indexPass = sBuff.substring(0).indexOf(",", indexUser); + int indexAfterPass = sBuff.substring(0).indexOf(" ", indexPass); + + for (int i = indexPass + 1; i < indexAfterPass; i++) { + sBuff.setCharAt(i, '*'); + } + } + return sBuff.toString(); + } + + /** + * Extension of EnumeratedAttribute to hold the values for file time stamp. + */ + public static class CurrentModUpdated extends EnumeratedAttribute { + /** + * Gets the list of allowable values. + * @return The values. + */ + public String[] getValues() { + return new String[] {TIME_CURRENT, TIME_MODIFIED, TIME_UPDATED}; + } + } + + /** + * Extension of EnumeratedAttribute to hold the values for writable filess. + */ + public static class WritableFiles extends EnumeratedAttribute { + /** + * Gets the list of allowable values. + * @return The values. + */ + public String[] getValues() { + return new String[] {WRITABLE_REPLACE, WRITABLE_SKIP, WRITABLE_FAIL}; + } + } +} |