Clover coverage report - Ant Coverage
Coverage timestamp: Tue Apr 8 2003 20:43:55 EST
file stats: LOC: 532   Methods: 19
NCLOC: 214   Classes: 3
 
 Source file Conditionals Statements Methods TOTAL
PathConvert.java 36.5% 49.5% 47.4% 45.5%
 1   
 /*
 2   
  * The Apache Software License, Version 1.1
 3   
  *
 4   
  * Copyright (c) 2001-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   
 package org.apache.tools.ant.taskdefs;
 55   
 
 56   
 import java.io.File;
 57   
 import java.util.StringTokenizer;
 58   
 import java.util.Vector;
 59   
 import org.apache.tools.ant.BuildException;
 60   
 import org.apache.tools.ant.Project;
 61   
 import org.apache.tools.ant.Task;
 62   
 import org.apache.tools.ant.taskdefs.condition.Os;
 63   
 import org.apache.tools.ant.types.DirSet;
 64   
 import org.apache.tools.ant.types.EnumeratedAttribute;
 65   
 import org.apache.tools.ant.types.FileList;
 66   
 import org.apache.tools.ant.types.FileSet;
 67   
 import org.apache.tools.ant.types.Path;
 68   
 import org.apache.tools.ant.types.Reference;
 69   
 
 70   
 /**
 71   
  * Converts path and classpath information to a specific target OS
 72   
  * format. The resulting formatted path is placed into the specified property.
 73   
  *
 74   
  * @author Larry Streepy <a href="mailto:streepy@healthlanguage.com">
 75   
  *      streepy@healthlanguage.com</a>
 76   
  * @since Ant 1.4
 77   
  * @ant.task category="utility"
 78   
  */
 79   
 public class PathConvert extends Task {
 80   
 
 81   
     // Members
 82   
     /**
 83   
      * Path to be converted
 84   
      */
 85   
     private Path path = null;
 86   
     /**
 87   
      * Reference to path/fileset to convert
 88   
      */
 89   
     private Reference refid = null;
 90   
     /**
 91   
      * The target OS type
 92   
      */
 93   
     private String targetOS = null;
 94   
     /**
 95   
      * Set when targetOS is set to windows
 96   
      */
 97   
     private boolean targetWindows = false;
 98   
     /**
 99   
      * Set if we're running on windows
 100   
      */
 101   
     private boolean onWindows = false;
 102   
     /**
 103   
      * Set if we should create a new property even if the result is empty
 104   
      */
 105   
     private boolean setonempty = true;
 106   
     /**
 107   
      * The property to receive the conversion
 108   
      */
 109   
     private String property = null;//
 110   
     /**
 111   
      * Path prefix map
 112   
      */
 113   
     private Vector prefixMap = new Vector();
 114   
     /**
 115   
      * User override on path sep char
 116   
      */
 117   
     private String pathSep = null;
 118   
     /**
 119   
      * User override on directory sep char
 120   
      */
 121   
     private String dirSep = null;
 122   
 
 123   
     /**
 124   
      * constructor
 125   
      */
 126  1
     public PathConvert() {
 127  1
         onWindows = Os.isFamily("dos");
 128   
     }
 129   
 
 130   
 
 131   
     /**
 132   
      * Helper class, holds the nested &lt;map&gt; values. Elements will look like
 133   
      * this: &lt;map from=&quot;d:&quot; to=&quot;/foo&quot;/&gt;
 134   
      *
 135   
      * When running on windows, the prefix comparison will be case
 136   
      * insensitive.
 137   
      */
 138   
     public class MapEntry {
 139   
 
 140   
         /** Set the &quot;from&quot; attribute of the map entry  */
 141   
         /**
 142   
          * the prefix string to search for; required.
 143   
          * Note that this value is case-insensitive when the build is
 144   
          * running on a Windows platform and case-sensitive when running on
 145   
          * a Unix platform.
 146   
          * @param from
 147   
          */
 148  0
         public void setFrom(String from) {
 149  0
             this.from = from;
 150   
         }
 151   
 
 152   
         /**
 153   
          *  The replacement text to use when from is matched; required.
 154   
          * @param to new prefix
 155   
          */
 156  0
         public void setTo(String to) {
 157  0
             this.to = to;
 158   
         }
 159   
 
 160   
 
 161   
         /**
 162   
          * Apply this map entry to a given path element
 163   
          *
 164   
          * @param elem Path element to process
 165   
          * @return String Updated path element after mapping
 166   
          */
 167  0
         public String apply(String elem) {
 168  0
             if (from == null || to == null) {
 169  0
                 throw new BuildException("Both 'from' and 'to' must be set "
 170   
                      + "in a map entry");
 171   
             }
 172   
 
 173   
             // If we're on windows, then do the comparison ignoring case
 174  0
             String cmpElem = onWindows ? elem.toLowerCase() : elem;
 175  0
             String cmpFrom = onWindows ? from.toLowerCase() : from;
 176   
 
 177   
             // If the element starts with the configured prefix, then
 178   
             // convert the prefix to the configured 'to' value.
 179   
 
 180  0
             if (cmpElem.startsWith(cmpFrom)) {
 181  0
                 int len = from.length();
 182   
 
 183  0
                 if (len >= elem.length()) {
 184  0
                     elem = to;
 185   
                 } else {
 186  0
                     elem = to + elem.substring(len);
 187   
                 }
 188   
             }
 189   
 
 190  0
             return elem;
 191   
         }
 192   
 
 193   
         // Members
 194   
         private String from = null;
 195   
         private String to = null;
 196   
     }
 197   
 
 198   
 
 199   
     /**
 200   
      * an enumeration of supported targets:
 201   
      * windows", "unix", "netware", and "os/2".
 202   
      */
 203   
     public static class TargetOs extends EnumeratedAttribute {
 204  1
         public String[] getValues() {
 205  1
             return new String[]{"windows", "unix", "netware", "os/2", "tandem"};
 206   
         }
 207   
     }
 208   
 
 209   
 
 210   
     /** Create a nested PATH element  */
 211  1
     public Path createPath() {
 212   
 
 213  1
         if (isReference()) {
 214  0
             throw noChildrenAllowed();
 215   
         }
 216   
 
 217  1
         if (path == null) {
 218  1
             path = new Path(getProject());
 219   
         }
 220  1
         return path.createPath();
 221   
     }
 222   
 
 223   
 
 224   
     /**
 225   
      * Create a nested MAP element
 226   
      * @return a Map to configure
 227   
      */
 228  0
     public MapEntry createMap() {
 229   
 
 230  0
         MapEntry entry = new MapEntry();
 231   
 
 232  0
         prefixMap.addElement(entry);
 233  0
         return entry;
 234   
     }
 235   
 
 236   
 
 237   
     /**
 238   
      * Set targetos to a platform to one of
 239   
      * "windows", "unix", "netware", or "os/2".
 240   
      * 
 241   
      * Required unless unless pathsep and/or dirsep are specified.
 242   
      *
 243   
      * @deprecated use the method taking a TargetOs argument instead
 244   
      * @see #setTargetos(PathConvert.TargetOs)
 245   
      */
 246  0
     public void setTargetos(String target) {
 247  0
         TargetOs to = new TargetOs();
 248   
 
 249  0
         to.setValue(target);
 250  0
         setTargetos(to);
 251   
     }
 252   
 
 253   
 
 254   
     /**
 255   
      * Set targetos to a platform to one of
 256   
      * "windows", "unix", "netware", or "os/2"; required unless
 257   
      * unless pathsep and/or dirsep are specified.
 258   
      *
 259   
      * @since Ant 1.5
 260   
      */
 261  1
     public void setTargetos(TargetOs target) {
 262   
 
 263  1
         targetOS = target.getValue();
 264   
 
 265   
         // Currently, we deal with only two path formats: Unix and Windows
 266   
         // And Unix is everything that is not Windows
 267   
 
 268   
         // for NetWare and OS/2, piggy-back on Windows, since in the
 269   
         // validateSetup code, the same assumptions can be made as
 270   
         // with windows - that ; is the path separator
 271   
 
 272  1
         targetWindows = !targetOS.equals("unix") && !targetOS.equals("tandem");
 273   
     }
 274   
 
 275   
     /**
 276   
      * Set setonempty
 277   
      *
 278   
      * If false, don't set the new property if the result is the empty string.
 279   
      * @param setonempty true or false
 280   
      *
 281   
      * @since Ant 1.5
 282   
      */
 283  0
      public void setSetonempty(boolean setonempty) {
 284  0
          this.setonempty = setonempty;
 285   
      }
 286   
 
 287   
     /**
 288   
      * The property into which the converted path will be placed.
 289   
      */
 290  1
     public void setProperty(String p) {
 291  1
         property = p;
 292   
     }
 293   
 
 294   
 
 295   
     /**
 296   
      * Adds a reference to a Path, FileSet, DirSet, or FileList defined
 297   
      * elsewhere.
 298   
      */
 299  0
     public void setRefid(Reference r) {
 300  0
         if (path != null) {
 301  0
             throw noChildrenAllowed();
 302   
         }
 303   
 
 304  0
         refid = r;
 305   
     }
 306   
 
 307   
 
 308   
     /**
 309   
      * Set the default path separator string;
 310   
      * defaults to current JVM
 311   
      * {@link java.io.File#pathSeparator File.pathSeparator}
 312   
      * @param sep path separator string
 313   
      */
 314  0
     public void setPathSep(String sep) {
 315  0
         pathSep = sep;
 316   
     }
 317   
 
 318   
 
 319   
     /**
 320   
      * Set the default directory separator string;
 321   
      * defaults to current JVM {@link java.io.File#separator File.separator}
 322   
      * @param sep directory separator string
 323   
      */
 324  0
     public void setDirSep(String sep) {
 325  0
         dirSep = sep;
 326   
     }
 327   
 
 328   
 
 329   
     /**
 330   
      * Has the refid attribute of this element been set?
 331   
      * @return true if refid is valid
 332   
      */
 333  2
     public boolean isReference() {
 334  2
         return refid != null;
 335   
     }
 336   
 
 337   
 
 338   
     /** Do the execution.
 339   
      * @throws BuildException if something is invalid
 340   
      */
 341  1
     public void execute() throws BuildException {
 342  1
         Path savedPath = path;
 343  1
         String savedPathSep = pathSep;// may be altered in validateSetup
 344  1
         String savedDirSep = dirSep;// may be altered in validateSetup
 345   
 
 346  1
         try {
 347   
             // If we are a reference, create a Path from the reference
 348  1
             if (isReference()) {
 349  0
                 path = new Path(getProject()).createPath();
 350   
 
 351  0
                 Object obj = refid.getReferencedObject(getProject());
 352   
 
 353  0
                 if (obj instanceof Path) {
 354  0
                     path.setRefid(refid);
 355  0
                 } else if (obj instanceof FileSet) {
 356  0
                     FileSet fs = (FileSet) obj;
 357   
 
 358  0
                     path.addFileset(fs);
 359  0
                 } else if (obj instanceof DirSet) {
 360  0
                     DirSet ds = (DirSet) obj;
 361   
 
 362  0
                     path.addDirset(ds);
 363  0
                 } else if (obj instanceof FileList) {
 364  0
                     FileList fl = (FileList) obj;
 365   
 
 366  0
                     path.addFilelist(fl);
 367   
 
 368   
                 } else {
 369  0
                     throw new BuildException("'refid' does not refer to a "
 370   
                          + "path, fileset, dirset, or "
 371   
                          + "filelist.");
 372   
                 }
 373   
             }
 374   
 
 375  1
             validateSetup();// validate our setup
 376   
 
 377   
             // Currently, we deal with only two path formats: Unix and Windows
 378   
             // And Unix is everything that is not Windows
 379   
             // (with the exception for NetWare and OS/2 below)
 380   
 
 381   
             // for NetWare and OS/2, piggy-back on Windows, since here and
 382   
             // in the apply code, the same assumptions can be made as with
 383   
             // windows - that \\ is an OK separator, and do comparisons
 384   
             // case-insensitive.
 385  1
             String fromDirSep = onWindows ? "\\" : "/";
 386   
 
 387  1
             StringBuffer rslt = new StringBuffer(100);
 388   
 
 389   
             // Get the list of path components in canonical form
 390  1
             String[] elems = path.list();
 391   
 
 392  1
             for (int i = 0; i < elems.length; i++) {
 393  4
                 String elem = elems[i];
 394   
 
 395  4
                 elem = mapElement(elem);// Apply the path prefix map
 396   
 
 397   
                 // Now convert the path and file separator characters from the
 398   
                 // current os to the target os.
 399   
 
 400  4
                 if (i != 0) {
 401  3
                     rslt.append(pathSep);
 402   
                 }
 403   
 
 404  4
                 StringTokenizer stDirectory =
 405   
                     new StringTokenizer(elem, fromDirSep, true);
 406  4
                 String token = null;
 407   
 
 408  4
                 while (stDirectory.hasMoreTokens()) {
 409  26
                     token = stDirectory.nextToken();
 410   
 
 411  26
                     if (fromDirSep.equals(token)) {
 412  13
                         rslt.append(dirSep);
 413   
                     } else {
 414  13
                         rslt.append(token);
 415   
                     }
 416   
                 }
 417   
             }
 418   
 
 419   
             // Place the result into the specified property,
 420   
             // unless setonempty == false
 421  1
             String value = rslt.toString();
 422  1
             if(setonempty) {
 423  1
                 log("Set property " + property + " = " + value,
 424   
                     Project.MSG_VERBOSE);
 425  1
                 getProject().setNewProperty(property, value);
 426   
             } else {
 427  0
                 if(rslt.length() > 0) {
 428  0
                     log("Set property " + property + " = " + value,
 429   
                         Project.MSG_VERBOSE);
 430  0
                     getProject().setNewProperty(property, value);
 431   
                 }
 432   
             }
 433   
         } finally {
 434  1
             path = savedPath;
 435  1
             dirSep = savedDirSep;
 436  1
             pathSep = savedPathSep;
 437   
         }
 438   
     }
 439   
 
 440   
 
 441   
     /**
 442   
      * Apply the configured map to a path element. The map is used to convert
 443   
      * between Windows drive letters and Unix paths. If no map is configured,
 444   
      * then the input string is returned unchanged.
 445   
      *
 446   
      * @param elem The path element to apply the map to
 447   
      * @return String Updated element
 448   
      */
 449  4
     private String mapElement(String elem) {
 450   
 
 451  4
         int size = prefixMap.size();
 452   
 
 453  4
         if (size != 0) {
 454   
 
 455   
             // Iterate over the map entries and apply each one.
 456   
             // Stop when one of the entries actually changes the element.
 457   
 
 458  0
             for (int i = 0; i < size; i++) {
 459  0
                 MapEntry entry = (MapEntry) prefixMap.elementAt(i);
 460  0
                 String newElem = entry.apply(elem);
 461   
 
 462   
                 // Note I'm using "!=" to see if we got a new object back from
 463   
                 // the apply method.
 464   
 
 465  0
                 if (newElem != elem) {
 466  0
                     elem = newElem;
 467  0
                     break;// We applied one, so we're done
 468   
                 }
 469   
             }
 470   
         }
 471   
 
 472  4
         return elem;
 473   
     }
 474   
 
 475   
 
 476   
     /**
 477   
      * Validate that all our parameters have been properly initialized.
 478   
      *
 479   
      * @throws BuildException if something is not setup properly
 480   
      */
 481  1
     private void validateSetup() throws BuildException {
 482   
 
 483  1
         if (path == null) {
 484  0
             throw new BuildException("You must specify a path to convert");
 485   
         }
 486   
 
 487  1
         if (property == null) {
 488  0
             throw new BuildException("You must specify a property");
 489   
         }
 490   
 
 491   
         // Must either have a target OS or both a dirSep and pathSep
 492   
 
 493  1
         if (targetOS == null && pathSep == null && dirSep == null) {
 494  0
             throw new BuildException("You must specify at least one of "
 495   
                  + "targetOS, dirSep, or pathSep");
 496   
         }
 497   
 
 498   
         // Determine the separator strings.  The dirsep and pathsep attributes
 499   
         // override the targetOS settings.
 500  1
         String dsep = File.separator;
 501  1
         String psep = File.pathSeparator;
 502   
 
 503  1
         if (targetOS != null) {
 504  1
             psep = targetWindows ? ";" : ":";
 505  1
             dsep = targetWindows ? "\\" : "/";
 506   
         }
 507   
 
 508  1
         if (pathSep != null) {// override with pathsep=
 509  0
             psep = pathSep;
 510   
         }
 511   
 
 512  1
         if (dirSep != null) {// override with dirsep=
 513  0
             dsep = dirSep;
 514   
         }
 515   
 
 516  1
         pathSep = psep;
 517  1
         dirSep = dsep;
 518   
     }
 519   
 
 520   
 
 521   
     /**
 522   
      * Creates an exception that indicates that this XML element must not have
 523   
      * child elements if the refid attribute is set.
 524   
      */
 525  0
     private BuildException noChildrenAllowed() {
 526  0
         return new BuildException("You must not specify nested <path> "
 527   
              + "elements when using the refid attribute.");
 528   
     }
 529   
 
 530   
 }
 531   
 
 532