Clover coverage report - Ant Coverage
Coverage timestamp: Tue Apr 8 2003 20:43:55 EST
file stats: LOC: 580   Methods: 43
NCLOC: 284   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
MSVSS.java 0% 0% 0% 0%
 1   
 /*
 2   
  * The Apache Software License, Version 1.1
 3   
  *
 4   
  * Copyright (c) 2000-2003 The Apache Software Foundation.  All rights
 5   
  * reserved.
 6   
  *
 7   
  * Redistribution and use in source and binary forms, with or without
 8   
  * modification, are permitted provided that the following conditions
 9   
  * are met:
 10   
  *
 11   
  * 1. Redistributions of source code must retain the above copyright
 12   
  *    notice, this list of conditions and the following disclaimer.
 13   
  *
 14   
  * 2. Redistributions in binary form must reproduce the above copyright
 15   
  *    notice, this list of conditions and the following disclaimer in
 16   
  *    the documentation and/or other materials provided with the
 17   
  *    distribution.
 18   
  *
 19   
  * 3. The end-user documentation included with the redistribution, if
 20   
  *    any, must include the following acknowlegement:
 21   
  *       "This product includes software developed by the
 22   
  *        Apache Software Foundation (http://www.apache.org/)."
 23   
  *    Alternately, this acknowlegement may appear in the software itself,
 24   
  *    if and wherever such third-party acknowlegements normally appear.
 25   
  *
 26   
  * 4. The names "Ant" and "Apache Software
 27   
  *    Foundation" must not be used to endorse or promote products derived
 28   
  *    from this software without prior written permission. For written
 29   
  *    permission, please contact apache@apache.org.
 30   
  *
 31   
  * 5. Products derived from this software may not be called "Apache"
 32   
  *    nor may "Apache" appear in their names without prior written
 33   
  *    permission of the Apache Group.
 34   
  *
 35   
  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 36   
  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 37   
  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 38   
  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 39   
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 40   
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 41   
  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 42   
  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 43   
  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 44   
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 45   
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 46   
  * SUCH DAMAGE.
 47   
  * ====================================================================
 48   
  *
 49   
  * This software consists of voluntary contributions made by many
 50   
  * individuals on behalf of the Apache Software Foundation.  For more
 51   
  * information on the Apache Software Foundation, please see
 52   
  * <http://www.apache.org/>.
 53   
  */
 54   
 
 55   
 package org.apache.tools.ant.taskdefs.optional.vss;
 56   
 
 57   
 import java.io.File;
 58   
 import java.io.IOException;
 59   
 import java.text.DateFormat;
 60   
 import java.text.ParseException;
 61   
 import java.util.Calendar;
 62   
 import java.util.Date;
 63   
 import java.util.GregorianCalendar;
 64   
 
 65   
 import org.apache.tools.ant.BuildException;
 66   
 import org.apache.tools.ant.Project;
 67   
 import org.apache.tools.ant.Task;
 68   
 import org.apache.tools.ant.taskdefs.Execute;
 69   
 import org.apache.tools.ant.taskdefs.LogStreamHandler;
 70   
 import org.apache.tools.ant.types.Commandline;
 71   
 
 72   
 /**
 73   
  * A base class for creating tasks for executing commands on Visual SourceSafe.
 74   
  * <p>
 75   
  * The class extends the 'exec' task as it operates by executing the ss.exe program
 76   
  * supplied with SourceSafe. By default the task expects ss.exe to be in the path,
 77   
  * you can override this be specifying the ssdir attribute.
 78   
  * </p>
 79   
  * <p>
 80   
  * This class provides set and get methods for 'login' and 'vsspath' attributes. It
 81   
  * also contains constants for the flags that can be passed to SS.
 82   
  * </p>
 83   
  *
 84   
  * @author Craig Cottingham
 85   
  * @author Andrew Everitt
 86   
  * @author Jesse Stockall
 87   
  */
 88   
 public abstract class MSVSS extends Task implements MSVSSConstants {
 89   
 
 90   
     private String m_SSDir = null;
 91   
     private String m_vssLogin = null;
 92   
     private String m_vssPath = null;
 93   
     private String m_serverPath = null;
 94   
 
 95   
     /**  Version */
 96   
     private String m_Version = null;
 97   
     /**  Date */
 98   
     private String m_Date = null;
 99   
     /**  Label */
 100   
     private String m_Label = null;
 101   
     /**  Auto response */
 102   
     private String m_AutoResponse = null;
 103   
     /**  Local path */
 104   
     private String m_LocalPath = null;
 105   
     /**  Comment */
 106   
     private String m_Comment = null;
 107   
     /**  From label */
 108   
     private String m_FromLabel = null;
 109   
     /**  To label */
 110   
     private String m_ToLabel = null;
 111   
     /**  Output file name */
 112   
     private String m_OutputFileName = null;
 113   
     /**  User */
 114   
     private String m_User = null;
 115   
     /**  From date */
 116   
     private String m_FromDate = null;
 117   
     /**  To date */
 118   
     private String m_ToDate = null;
 119   
     /**  History style */
 120   
     private String m_Style = null;
 121   
     /**  Quiet defaults to false */
 122   
     private boolean m_Quiet = false;
 123   
     /**  Recursive defaults to false */
 124   
     private boolean m_Recursive = false;
 125   
     /**  Writable defaults to false */
 126   
     private boolean m_Writable = false;
 127   
     /**  Fail on error defaults to true */
 128   
     private boolean m_FailOnError = true;
 129   
     /**  Number of days offset for History */
 130   
     private int m_NumDays = Integer.MIN_VALUE;
 131   
     /**  Date format for History */
 132   
     private DateFormat m_DateFormat = DateFormat.getDateInstance(DateFormat.SHORT);
 133   
 
 134   
     /**
 135   
      * Each sub-class must implemnt this method and return the constructed
 136   
      * command line to be executed. It is up to the sub-task to determine the
 137   
      * required attrubutes and their order.
 138   
      *
 139   
      * @return    The Constructed command line.
 140   
      */
 141   
     abstract Commandline buildCmdLine();
 142   
 
 143   
     /**
 144   
      * Directory where <code>ss.exe</code> resides; optional.
 145   
      * By default the task expects it to be in the PATH.
 146   
      *
 147   
      * @param  dir  The directory containing ss.exe.
 148   
      */
 149  0
     public final void setSsdir(String dir) {
 150  0
         m_SSDir = Project.translatePath(dir);
 151   
     }
 152   
 
 153   
     /**
 154   
      * The login to use when accessing VSS, formatted as "username,password";
 155   
      * optional.
 156   
      * <p>
 157   
      * You can omit the password if your database is not password protected.
 158   
      *  if you have a password and omit it, Ant/VSS will hang.
 159   
      *
 160   
      * @param  login  The login string to use.
 161   
      */
 162  0
     public final void setLogin(String login) {
 163  0
         m_vssLogin = login;
 164   
     }
 165   
 
 166   
     /**
 167   
      * SourceSafe path which specifies the project/file(s) you wish to perform
 168   
      * the action on; required.<p>
 169   
      *
 170   
      * Also we strip off any 'vss://' prefix which is an XMS special and should
 171   
      * probably be removed!
 172   
      *
 173   
      * @param  vssPath  The VSS project path.
 174   
      */
 175  0
     public final void setVsspath(String vssPath) {
 176  0
         String projectPath;
 177  0
         if (vssPath.startsWith("vss://")) {
 178  0
             projectPath = vssPath.substring(5);
 179   
         } else {
 180  0
             projectPath = vssPath;
 181   
         }
 182   
 
 183  0
         if (projectPath.startsWith(PROJECT_PREFIX)) {
 184  0
             m_vssPath = projectPath;
 185   
         } else {
 186  0
             m_vssPath = PROJECT_PREFIX + projectPath;
 187   
         }
 188   
     }
 189   
 
 190   
     /**
 191   
      * Set the directory where <code>srssafe.ini</code> resides; optional.
 192   
      *
 193   
      * @param  serverPath  The path to the VSS server.
 194   
      */
 195  0
     public final void setServerpath(String serverPath) {
 196  0
         m_serverPath = serverPath;
 197   
     }
 198   
 
 199   
     /**
 200   
      * Executes the task. <br>
 201   
      * Builds a command line to execute ss.exe and then calls Exec's run method
 202   
      * to execute the command line.
 203   
      * @throws BuildException
 204   
      */
 205  0
     public void execute()
 206   
         throws BuildException {
 207  0
         int result = 0;
 208  0
         Commandline commandLine = buildCmdLine();
 209  0
         result = run(commandLine);
 210  0
         if (result != 0 && getFailOnError()) {
 211  0
             String msg = "Failed executing: " + commandLine.toString()
 212   
                      + " With a return code of " + result;
 213  0
             throw new BuildException(msg, getLocation());
 214   
         }
 215   
     }
 216   
 
 217   
     // Special setters for the sub-classes
 218   
 
 219  0
     protected void setInternalComment(String text) {
 220  0
         m_Comment = text;
 221   
     }
 222   
 
 223  0
     protected void setInternalAutoResponse(String text) {
 224  0
         m_AutoResponse = text;
 225   
     }
 226   
 
 227  0
     protected void setInternalDate(String text) {
 228  0
         m_Date = text;
 229   
     }
 230   
 
 231  0
     protected void setInternalDateFormat(DateFormat date) {
 232  0
         m_DateFormat = date;
 233   
     }
 234   
 
 235  0
     protected void setInternalFailOnError(boolean fail) {
 236  0
         m_FailOnError = fail;
 237   
     }
 238   
 
 239  0
     protected void setInternalFromDate(String text) {
 240  0
         m_FromDate = text;
 241   
     }
 242   
 
 243  0
     protected void setInternalFromLabel(String text) {
 244  0
         m_FromLabel = text;
 245   
     }
 246   
 
 247  0
     protected void setInternalLabel(String text) {
 248  0
         m_Label = text;
 249   
     }
 250   
 
 251  0
     protected void setInternalLocalPath(String text) {
 252  0
         m_LocalPath = text;
 253   
     }
 254   
 
 255  0
     protected void setInternalNumDays(int days) {
 256  0
         m_NumDays = days;
 257   
     }
 258   
 
 259  0
     protected void setInternalOutputFilename(String text) {
 260  0
         m_OutputFileName = text;
 261   
     }
 262   
 
 263  0
     protected void setInternalQuiet(boolean quiet) {
 264  0
         m_Quiet = quiet;
 265   
     }
 266   
 
 267  0
     protected void setInternalRecursive(boolean recursive) {
 268  0
         m_Recursive = recursive;
 269   
     }
 270   
 
 271  0
     protected void setInternalStyle(String style) {
 272  0
         m_Style = style;
 273   
     }
 274   
 
 275  0
     protected void setInternalToDate(String text) {
 276  0
         m_ToDate = text;
 277   
     }
 278   
 
 279  0
     protected void setInternalToLabel(String text) {
 280  0
         m_ToLabel = text;
 281   
     }
 282   
 
 283  0
     protected void setInternalUser(String user) {
 284  0
         m_User = user;
 285   
     }
 286   
 
 287  0
     protected void setInternalVersion(String text) {
 288  0
         m_Version = text;
 289   
     }
 290   
 
 291  0
     protected void setInternalWritable(boolean writable) {
 292  0
         m_Writable = writable;
 293   
     }
 294   
 
 295   
     /**
 296   
      * Gets the sscommand string. "ss" or "c:\path\to\ss"
 297   
      *
 298   
      * @return    The path to ss.exe or just ss if sscommand is not set.
 299   
      */
 300  0
     protected String getSSCommand() {
 301  0
         if (m_SSDir == null) {
 302  0
             return SS_EXE;
 303   
         }
 304  0
         return m_SSDir.endsWith(File.separator) ? m_SSDir + SS_EXE : m_SSDir
 305   
                  + File.separator + SS_EXE;
 306   
     }
 307   
 
 308   
     /**
 309   
      * Gets the vssserverpath string.
 310   
      *
 311   
      * @return    null if vssserverpath is not set.
 312   
      */
 313  0
     protected String getVsspath() {
 314  0
         return m_vssPath;
 315   
     }
 316   
 
 317   
     /**
 318   
      *  Gets the quiet string. -O-
 319   
      *
 320   
      * @return    An empty string if quiet is not set or is false.
 321   
      */
 322  0
     protected String getQuiet() {
 323  0
         return m_Quiet ? FLAG_QUIET : "";
 324   
     }
 325   
 
 326   
     /**
 327   
      *  Gets the recursive string. "-R"
 328   
      *
 329   
      * @return    An empty string if recursive is not set or is false.
 330   
      */
 331  0
     protected String getRecursive() {
 332  0
         return m_Recursive ? FLAG_RECURSION : "";
 333   
     }
 334   
 
 335   
     /**
 336   
      *  Gets the writable string. "-W"
 337   
      *
 338   
      * @return    An empty string if writable is not set or is false.
 339   
      */
 340  0
     protected String getWritable() {
 341  0
         return m_Writable ? FLAG_WRITABLE : "";
 342   
     }
 343   
 
 344   
     /**
 345   
      *  Gets the label string. "-Lbuild1"
 346   
      *
 347   
      * @return    An empty string if label is not set.
 348   
      */
 349  0
     protected String getLabel() {
 350  0
         return m_Label != null ? FLAG_LABEL + m_Label : "";
 351   
     }
 352   
 
 353   
     /**
 354   
      *  Gets the style string. "-Lbuild1"
 355   
      *
 356   
      * @return    An empty string if label is not set.
 357   
      */
 358  0
     protected String getStyle() {
 359  0
         return m_Style != null ? m_Style : "";
 360   
     }
 361   
 
 362   
     /**
 363   
      *  Gets the version string. Returns the first specified of version "-V1.0",
 364   
      *  date "-Vd01.01.01", label "-Vlbuild1".
 365   
      *
 366   
      * @return    An empty string if a version is not set.
 367   
      */
 368  0
     protected String getVersion() {
 369  0
         if (m_Version != null) {
 370  0
             return FLAG_VERSION + m_Version;
 371  0
         } else if (m_Date != null) {
 372  0
             return FLAG_VERSION_DATE + m_Date;
 373  0
         } else if (m_Label != null) {
 374  0
             return FLAG_VERSION_LABEL + m_Label;
 375   
         } else {
 376  0
             return "";
 377   
         }
 378   
     }
 379   
 
 380   
     /**
 381   
      *  Gets the localpath string. "-GLc:\source" <p>
 382   
      *
 383   
      *  The localpath is created if it didn't exist.
 384   
      *
 385   
      * @return    An empty string if localpath is not set.
 386   
      */
 387  0
     protected String getLocalpath() {
 388  0
         if (m_LocalPath == null) {
 389  0
             return "";
 390   
         } else {
 391   
             // make sure m_LocalDir exists, create it if it doesn't
 392  0
             File dir = getProject().resolveFile(m_LocalPath);
 393  0
             if (! dir.exists()) {
 394  0
                 boolean done = dir.mkdirs();
 395  0
                 if (! done) {
 396  0
                     String msg = "Directory " + m_LocalPath + " creation was not "
 397   
                             + "successful for an unknown reason";
 398  0
                     throw new BuildException(msg, getLocation());
 399   
                 }
 400  0
                 getProject().log("Created dir: " + dir.getAbsolutePath());
 401   
             }
 402  0
             return FLAG_OVERRIDE_WORKING_DIR + m_LocalPath;
 403   
         }
 404   
     }
 405   
 
 406   
     /**
 407   
      *  Gets the comment string. "-Ccomment text"
 408   
      *
 409   
      * @return    A comment of "-" if comment is not set.
 410   
      */
 411  0
     protected String getComment() {
 412  0
         return m_Comment != null ? FLAG_COMMENT + m_Comment : FLAG_COMMENT + "-";
 413   
     }
 414   
 
 415   
     /**
 416   
      *  Gets the auto response string. This can be Y "-I-Y" or N "-I-N".
 417   
      *
 418   
      * @return    The default value "-I-" if autoresponse is not set.
 419   
      */
 420  0
     protected String getAutoresponse() {
 421  0
         if (m_AutoResponse == null) {
 422  0
             return FLAG_AUTORESPONSE_DEF;
 423  0
         } else if (m_AutoResponse.equalsIgnoreCase("Y")) {
 424  0
             return FLAG_AUTORESPONSE_YES;
 425  0
         } else if (m_AutoResponse.equalsIgnoreCase("N")) {
 426  0
             return FLAG_AUTORESPONSE_NO;
 427   
         } else {
 428  0
             return FLAG_AUTORESPONSE_DEF;
 429   
         }
 430   
     }
 431   
 
 432   
     /**
 433   
      *  Gets the login string. This can be user and password, "-Yuser,password"
 434   
      *  or just user "-Yuser".
 435   
      *
 436   
      * @return    An empty string if login is not set.
 437   
      */
 438  0
     protected String getLogin() {
 439  0
         return m_vssLogin != null ? FLAG_LOGIN + m_vssLogin : "";
 440   
     }
 441   
 
 442   
     /**
 443   
      *  Gets the output file string. "-Ooutput.file"
 444   
      *
 445   
      * @return    An empty string if user is not set.
 446   
      */
 447  0
     protected String getOutput() {
 448  0
         return m_OutputFileName != null ? FLAG_OUTPUT + m_OutputFileName : "";
 449   
     }
 450   
 
 451   
     /**
 452   
      *  Gets the user string. "-Uusername"
 453   
      *
 454   
      * @return    An empty string if user is not set.
 455   
      */
 456  0
     protected String getUser() {
 457  0
         return m_User != null ? FLAG_USER + m_User : "";
 458   
     }
 459   
 
 460   
     /**
 461   
      *  Gets the version string. This can be to-from "-VLbuild2~Lbuild1", from
 462   
      *  "~Lbuild1" or to "-VLbuild2".
 463   
      *
 464   
      * @return    An empty string if neither tolabel or fromlabel are set.
 465   
      */
 466  0
     protected String getVersionLabel() {
 467  0
         if (m_FromLabel == null && m_ToLabel == null) {
 468  0
             return "";
 469   
         }
 470  0
         if (m_FromLabel != null && m_ToLabel != null) {
 471  0
             return FLAG_VERSION_LABEL + m_ToLabel + VALUE_FROMLABEL + m_FromLabel;
 472  0
         } else if (m_FromLabel != null) {
 473  0
             return FLAG_VERSION + VALUE_FROMLABEL + m_FromLabel;
 474   
         } else {
 475  0
             return FLAG_VERSION_LABEL + m_ToLabel;
 476   
         }
 477   
     }
 478   
 
 479   
     /**
 480   
      * Gets the Version date string.
 481   
      * @return An empty string is neither Todate or from date are set.
 482   
      * @throws BuildException
 483   
      */
 484  0
     protected String getVersionDate() throws BuildException {
 485  0
         if (m_FromDate == null && m_ToDate == null
 486   
             && m_NumDays == Integer.MIN_VALUE) {
 487  0
             return "";
 488   
         }
 489  0
         if (m_FromDate != null && m_ToDate != null) {
 490  0
             return FLAG_VERSION_DATE + m_ToDate + VALUE_FROMDATE + m_FromDate;
 491  0
         } else if (m_ToDate != null && m_NumDays != Integer.MIN_VALUE) {
 492  0
             try {
 493  0
                 return FLAG_VERSION_DATE + m_ToDate + VALUE_FROMDATE
 494   
                         + calcDate(m_ToDate, m_NumDays);
 495   
             } catch (ParseException ex) {
 496  0
                 String msg = "Error parsing date: " + m_ToDate;
 497  0
                 throw new BuildException(msg, getLocation());
 498   
             }
 499  0
         } else if (m_FromDate != null && m_NumDays != Integer.MIN_VALUE) {
 500  0
             try {
 501  0
                 return FLAG_VERSION_DATE + calcDate(m_FromDate, m_NumDays)
 502   
                         + VALUE_FROMDATE + m_FromDate;
 503   
             } catch (ParseException ex) {
 504  0
                 String msg = "Error parsing date: " + m_FromDate;
 505  0
                 throw new BuildException(msg, getLocation());
 506   
             }
 507   
         } else {
 508  0
             return m_FromDate != null ? FLAG_VERSION + VALUE_FROMDATE
 509   
                     + m_FromDate : FLAG_VERSION_DATE + m_ToDate;
 510   
         }
 511   
     }
 512   
 
 513   
     /**
 514   
      *  Gets the value of the fail on error flag. This is only used by execute
 515   
      *  when checking the return code.
 516   
      *
 517   
      * @return    True if the FailOnError flag has been set.
 518   
      */
 519  0
     private boolean getFailOnError() {
 520  0
         return m_FailOnError;
 521   
     }
 522   
 
 523   
     /**
 524   
      *  Sets up the required environment and executes the command line.
 525   
      *
 526   
      * @param  cmd  The command line to execute.
 527   
      * @return      The return code from the exec'd process.
 528   
      */
 529  0
     private int run(Commandline cmd) {
 530  0
         try {
 531  0
             Execute exe = new Execute(new LogStreamHandler(this,
 532   
                     Project.MSG_INFO,
 533   
                     Project.MSG_WARN));
 534   
 
 535   
             // If location of ss.ini is specified we need to set the
 536   
             // environment-variable SSDIR to this value
 537  0
             if (m_serverPath != null) {
 538  0
                 String[] env = exe.getEnvironment();
 539  0
                 if (env == null) {
 540  0
                     env = new String[0];
 541   
                 }
 542  0
                 String[] newEnv = new String[env.length + 1];
 543  0
                 for (int i = 0; i < env.length; i++) {
 544  0
                     newEnv[i] = env[i];
 545   
                 }
 546  0
                 newEnv[env.length] = "SSDIR=" + m_serverPath;
 547   
 
 548  0
                 exe.setEnvironment(newEnv);
 549   
             }
 550   
 
 551  0
             exe.setAntRun(getProject());
 552  0
             exe.setWorkingDirectory(getProject().getBaseDir());
 553  0
             exe.setCommandline(cmd.getCommandline());
 554  0
             return exe.execute();
 555   
         } catch (IOException e) {
 556  0
             throw new BuildException(e, getLocation());
 557   
         }
 558   
     }
 559   
 
 560   
      /**
 561   
      * Calculates the start date for version comparison.
 562   
      * <p>
 563   
      * Calculates the date numDay days earlier than startdate.
 564   
      * @param   fromDate    The start date.
 565   
      * @param   numDays     The number of days to add.
 566   
      * @return The calculated date.
 567   
      * @throws ParseException
 568   
      */
 569  0
     private String calcDate(String fromDate, int numDays) throws ParseException {
 570  0
         String toDate = null;
 571  0
         Date currdate = new Date();
 572  0
         Calendar calend = new GregorianCalendar();
 573  0
         currdate = m_DateFormat.parse(fromDate);
 574  0
         calend.setTime(currdate);
 575  0
         calend.add(Calendar.DATE, numDays);
 576  0
         toDate = m_DateFormat.format(calend.getTime());
 577  0
         return toDate;
 578   
     }
 579   
 }
 580