Clover coverage report - Ant Coverage
Coverage timestamp: Tue Apr 8 2003 20:43:55 EST
file stats: LOC: 556   Methods: 31
NCLOC: 297   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
Property.java 68.6% 67.6% 51.6% 65.8%
 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;
 56   
 
 57   
 import java.io.File;
 58   
 import java.io.FileInputStream;
 59   
 import java.io.IOException;
 60   
 import java.io.InputStream;
 61   
 import java.util.Enumeration;
 62   
 import java.util.Properties;
 63   
 import java.util.Vector;
 64   
 import org.apache.tools.ant.AntClassLoader;
 65   
 import org.apache.tools.ant.BuildException;
 66   
 import org.apache.tools.ant.Project;
 67   
 import org.apache.tools.ant.ProjectHelper;
 68   
 import org.apache.tools.ant.Task;
 69   
 import org.apache.tools.ant.types.Path;
 70   
 import org.apache.tools.ant.types.Reference;
 71   
 
 72   
 /**
 73   
  * Sets a property by name, or set of properties (from file or
 74   
  * resource) in the project.  </p>
 75   
  * Properties are immutable: whoever sets a property first freezes it for the
 76   
  * rest of the build; they are most definately not variable.
 77   
  * <p>There are five ways to set properties:</p>
 78   
  * <ul>
 79   
  *   <li>By supplying both the <i>name</i> and <i>value</i> attribute.</li>
 80   
  *   <li>By supplying both the <i>name</i> and <i>refid</i> attribute.</li>
 81   
  *   <li>By setting the <i>file</i> attribute with the filename of the property
 82   
  *     file to load. This property file has the format as defined by the file used
 83   
  *     in the class java.util.Properties.</li>
 84   
  *   <li>By setting the <i>resource</i> attribute with the resource name of the
 85   
  *     property file to load. This property file has the format as defined by the
 86   
  *     file used in the class java.util.Properties.</li>
 87   
  *   <li>By setting the <i>environment</i> attribute with a prefix to use.
 88   
  *     Properties will be defined for every environment variable by
 89   
  *     prefixing the supplied name and a period to the name of the variable.</li>
 90   
  * </ul>
 91   
  * <p>Although combinations of these ways are possible, only one should be used
 92   
  * at a time. Problems might occur with the order in which properties are set, for
 93   
  * instance.</p>
 94   
  * <p>The value part of the properties being set, might contain references to other
 95   
  * properties. These references are resolved at the time these properties are set.
 96   
  * This also holds for properties loaded from a property file.</p>
 97   
  * Properties are case sensitive.
 98   
  *
 99   
  * @author costin@dnt.ro
 100   
  * @author <a href="mailto:rubys@us.ibm.com">Sam Ruby</a>
 101   
  * @author <a href="mailto:glennm@ca.ibm.com">Glenn McAllister</a>
 102   
  * @since Ant 1.1
 103   
  */
 104   
 public class Property extends Task {
 105   
 
 106   
     protected String name;
 107   
     protected String value;
 108   
     protected File file;
 109   
     protected String resource;
 110   
     protected Path classpath;
 111   
     protected String env;
 112   
     protected Reference ref;
 113   
     protected String prefix;
 114   
     private Project fallback;
 115   
 
 116   
     protected boolean userProperty; // set read-only properties
 117   
 
 118  508
     public Property() {
 119  508
         this(false);
 120   
     }
 121   
 
 122   
     /**
 123   
      * @since Ant 1.5
 124   
      */
 125  508
     protected Property(boolean userProperty) {
 126  508
         this(userProperty, null);
 127   
     }
 128   
 
 129   
     /**
 130   
      * @since Ant 1.5
 131   
      */
 132  517
     protected Property(boolean userProperty, Project fallback) {
 133  517
         this.userProperty = userProperty;
 134  517
         this.fallback = fallback;
 135   
     }
 136   
 
 137   
     /**
 138   
      * sets the name of the property to set.
 139   
      * @param name property name
 140   
      */
 141  502
     public void setName(String name) {
 142  502
         this.name = name;
 143   
     }
 144   
 
 145  0
     public String getName() {
 146  0
         return name;
 147   
     }
 148   
 
 149   
     /**
 150   
      * Sets the property to the absolute filename of the
 151   
      * given file. If the value of this attribute is an absolute path, it
 152   
      * is left unchanged (with / and \ characters converted to the
 153   
      * current platforms conventions). Otherwise it is taken as a path
 154   
      * relative to the project's basedir and expanded.
 155   
      * @param location path to set
 156   
      */
 157  132
     public void setLocation(File location) {
 158  132
         setValue(location.getAbsolutePath());
 159   
     }
 160   
 
 161   
     /**
 162   
      * Sets the value of the property.
 163   
      * @param value value to assign
 164   
      */
 165  500
     public void setValue(String value) {
 166  500
         this.value = value;
 167   
     }
 168   
 
 169  0
     public String getValue() {
 170  0
         return value;
 171   
     }
 172   
 
 173   
     /**
 174   
      * the filename of a property file to load.
 175   
      *@param file filename
 176   
      */
 177  13
     public void setFile(File file) {
 178  13
         this.file = file;
 179   
     }
 180   
 
 181  0
     public File getFile() {
 182  0
         return file;
 183   
     }
 184   
 
 185   
     /**
 186   
      * Prefix to apply to properties loaded using <code>file</code>
 187   
      * or <code>resource</code>.
 188   
      * A "." is appended to the prefix if not specified.
 189   
      * @param prefix prefix string
 190   
      * @since Ant 1.5
 191   
      */
 192  2
     public void setPrefix(String prefix) {
 193  2
         this.prefix = prefix;
 194  2
         if (!prefix.endsWith(".")) {
 195  2
             this.prefix += ".";
 196   
         }
 197   
     }
 198   
 
 199   
     /**
 200   
      * @since Ant 1.5
 201   
      */
 202  0
     public String getPrefix() {
 203  0
         return prefix;
 204   
     }
 205   
 
 206   
     /**
 207   
      * Sets a reference to an Ant datatype
 208   
      * declared elsewhere.
 209   
      * Only yields reasonable results for references
 210   
      * PATH like structures or properties.
 211   
      * @param ref reference
 212   
      */
 213  2
     public void setRefid(Reference ref) {
 214  2
         this.ref = ref;
 215   
     }
 216   
 
 217  0
     public Reference getRefid() {
 218  0
         return ref;
 219   
     }
 220   
 
 221   
     /**
 222   
      * the resource name of a property file to load
 223   
      * @param resource resource on classpath
 224   
      */
 225  0
     public void setResource(String resource) {
 226  0
         this.resource = resource;
 227   
     }
 228   
 
 229  0
     public String getResource() {
 230  0
         return resource;
 231   
     }
 232   
 
 233   
     /**
 234   
     * the prefix to use when retrieving environment variables.
 235   
     * Thus if you specify environment=&quot;myenv&quot;
 236   
     * you will be able to access OS-specific
 237   
     * environment variables via property names &quot;myenv.PATH&quot; or
 238   
     * &quot;myenv.TERM&quot;.
 239   
     * <p>
 240   
     * Note that if you supply a property name with a final
 241   
     * &quot;.&quot; it will not be doubled. ie environment=&quot;myenv.&quot; will still
 242   
     * allow access of environment variables through &quot;myenv.PATH&quot; and
 243   
     * &quot;myenv.TERM&quot;. This functionality is currently only implemented
 244   
     * on select platforms. Feel free to send patches to increase the number of platforms
 245   
     * this functionality is supported on ;).<br>
 246   
     * Note also that properties are case sensitive, even if the
 247   
     * environment variables on your operating system are not, e.g. it
 248   
     * will be ${env.Path} not ${env.PATH} on Windows 2000.
 249   
     * @param env prefix
 250   
     */
 251  2
     public void setEnvironment(String env) {
 252  2
         this.env = env;
 253   
     }
 254   
 
 255   
     /**
 256   
      * @since Ant 1.5
 257   
      */
 258  0
     public String getEnvironment() {
 259  0
         return env;
 260   
     }
 261   
 
 262   
     /**
 263   
      * The classpath to use when looking up a resource.
 264   
      * @param classpath to add to any existing classpath
 265   
      */
 266  0
     public void setClasspath(Path classpath) {
 267  0
         if (this.classpath == null) {
 268  0
             this.classpath = classpath;
 269   
         } else {
 270  0
             this.classpath.append(classpath);
 271   
         }
 272   
     }
 273   
 
 274   
     /**
 275   
      * The classpath to use when looking up a resource.
 276   
      */
 277  0
     public Path createClasspath() {
 278  0
         if (this.classpath == null) {
 279  0
             this.classpath = new Path(getProject());
 280   
         }
 281  0
         return this.classpath.createPath();
 282   
     }
 283   
 
 284   
     /**
 285   
      * the classpath to use when looking up a resource,
 286   
      * given as reference to a &lt;path&gt; defined elsewhere
 287   
      */
 288  0
     public void setClasspathRef(Reference r) {
 289  0
         createClasspath().setRefid(r);
 290   
     }
 291   
 
 292   
     /**
 293   
      * @since Ant 1.5
 294   
      */
 295  0
     public Path getClasspath() {
 296  0
         return classpath;
 297   
     }
 298   
 
 299   
     /**
 300   
      * @deprecated This was never a supported feature and has been
 301   
      * deprecated without replacement
 302   
      * @ant.setter skip="true"
 303   
      */
 304  0
     public void setUserProperty(boolean userProperty) {
 305  0
         log("DEPRECATED: Ignoring request to set user property in Property"
 306   
             + " task.", Project.MSG_WARN);
 307   
     }
 308   
 
 309   
     /**
 310   
      * get the value of this property
 311   
      * @return the current value or the empty string
 312   
      */
 313  0
     public String toString() {
 314  0
         return value == null ? "" : value;
 315   
     }
 316   
 
 317   
     /**
 318   
      * set the property in the project to the value.
 319   
      * if the task was give a file, resource or env attribute
 320   
      * here is where it is loaded
 321   
      */
 322  517
     public void execute() throws BuildException {
 323  517
         if (getProject() == null) {
 324  0
             throw new IllegalStateException("project has not been set");
 325   
         }
 326   
 
 327  517
         if (name != null) {
 328  502
             if (value == null && ref == null) {
 329  0
                 throw new BuildException("You must specify value, location or "
 330   
                                          + "refid with the name attribute",
 331   
                                          getLocation());
 332   
             }
 333   
         } else {
 334  15
             if (file == null && resource == null && env == null) {
 335  0
                 throw new BuildException("You must specify file, resource or "
 336   
                                          + "environment when not using the "
 337   
                                          + "name attribute", getLocation());
 338   
             }
 339   
         }
 340   
 
 341  517
         if (file == null && resource == null && prefix != null) {
 342  1
             throw new BuildException("Prefix is only valid when loading from "
 343   
                                      + "a file or resource", getLocation());
 344   
         }
 345   
 
 346  516
         if ((name != null) && (value != null)) {
 347  499
             addProperty(name, value);
 348   
         }
 349   
 
 350  516
         if (file != null) {
 351  13
             loadFile(file);
 352   
         }
 353   
 
 354  515
         if (resource != null) {
 355  0
             loadResource(resource);
 356   
         }
 357   
 
 358  515
         if (env != null) {
 359  2
             loadEnvironment(env);
 360   
         }
 361   
 
 362  515
         if ((name != null) && (ref != null)) {
 363  2
             try {
 364  2
                 addProperty(name,
 365   
                             ref.getReferencedObject(getProject()).toString());
 366   
             } catch (BuildException be) {
 367  1
                 if (fallback != null) {
 368  1
                     addProperty(name,
 369   
                                 ref.getReferencedObject(fallback).toString());
 370   
                 } else {
 371  0
                     throw be;
 372   
                 }
 373   
             }
 374   
         }
 375   
     }
 376   
 
 377   
     /**
 378   
      * load properties from a file
 379   
      * @param file file to load
 380   
      */
 381  13
     protected void loadFile(File file) throws BuildException {
 382  13
         Properties props = new Properties();
 383  13
         log("Loading " + file.getAbsolutePath(), Project.MSG_VERBOSE);
 384  13
         try {
 385  13
             if (file.exists()) {
 386  11
                 FileInputStream fis = new FileInputStream(file);
 387  11
                 try {
 388  11
                     props.load(fis);
 389   
                 } finally {
 390  11
                     if (fis != null) {
 391  11
                         fis.close();
 392   
                     }
 393   
                 }
 394  11
                 addProperties(props);
 395   
             } else {
 396  2
                 log("Unable to find property file: " + file.getAbsolutePath(),
 397   
                     Project.MSG_VERBOSE);
 398   
             }
 399   
         } catch (IOException ex) {
 400  0
             throw new BuildException(ex, getLocation());
 401   
         }
 402   
     }
 403   
 
 404   
     /**
 405   
      * load properties from a resource in the current classpath
 406   
      * @param name name of resource to load
 407   
      */
 408  0
     protected void loadResource(String name) {
 409  0
         Properties props = new Properties();
 410  0
         log("Resource Loading " + name, Project.MSG_VERBOSE);
 411  0
         InputStream is = null;
 412  0
         try {
 413  0
             ClassLoader cL = null;
 414   
 
 415  0
             if (classpath != null) {
 416  0
                 cL = getProject().createClassLoader(classpath);
 417   
             } else {
 418  0
                 cL = this.getClass().getClassLoader();
 419   
             }
 420   
 
 421  0
             if (cL == null) {
 422  0
                 is = ClassLoader.getSystemResourceAsStream(name);
 423   
             } else {
 424  0
                 is = cL.getResourceAsStream(name);
 425   
             }
 426   
 
 427  0
             if (is != null) {
 428  0
                 props.load(is);
 429  0
                 addProperties(props);
 430   
             } else {
 431  0
                 log("Unable to find resource " + name, Project.MSG_WARN);
 432   
             }
 433   
         } catch (IOException ex) {
 434  0
             throw new BuildException(ex, getLocation());
 435   
         } finally {
 436  0
             if (is != null) {
 437  0
                 try {
 438  0
                     is.close();
 439   
                 } catch (IOException e) {}
 440   
             }
 441   
         }
 442   
 
 443   
     }
 444   
 
 445   
     /**
 446   
      * load the environment values
 447   
      * @param prefix prefix to place before them
 448   
      */
 449  2
     protected void loadEnvironment(String prefix) {
 450  2
         Properties props = new Properties();
 451  2
         if (!prefix.endsWith(".")) {
 452  2
             prefix += ".";
 453   
         }
 454  2
         log("Loading Environment " + prefix, Project.MSG_VERBOSE);
 455  2
         Vector osEnv = Execute.getProcEnvironment();
 456  2
         for (Enumeration e = osEnv.elements(); e.hasMoreElements();) {
 457  82
             String entry = (String) e.nextElement();
 458  82
             int pos = entry.indexOf('=');
 459  82
             if (pos == -1) {
 460  0
                 log("Ignoring: " + entry, Project.MSG_WARN);
 461   
             } else {
 462  82
                 props.put(prefix + entry.substring(0, pos),
 463   
                 entry.substring(pos + 1));
 464   
             }
 465   
         }
 466  2
         addProperties(props);
 467   
     }
 468   
 
 469   
     /**
 470   
      * iterate through a set of properties,
 471   
      * resolve them then assign them
 472   
      */
 473  13
     protected void addProperties(Properties props) {
 474  13
         resolveAllProperties(props);
 475  12
         Enumeration e = props.keys();
 476  12
         while (e.hasMoreElements()) {
 477  119
             String name = (String) e.nextElement();
 478  119
             String value = props.getProperty(name);
 479   
 
 480  119
             String v = getProject().replaceProperties(value);
 481   
 
 482  119
             if (prefix != null) {
 483  2
                 name = prefix + name;
 484   
             }
 485   
 
 486  119
             addProperty(name, v);
 487   
         }
 488   
     }
 489   
 
 490   
     /**
 491   
      * add a name value pair to the project property set
 492   
      * @param n name of property
 493   
      * @param v value to set
 494   
      */
 495  620
     protected void addProperty(String n, String v) {
 496  620
         if (userProperty) {
 497  9
             if (getProject().getUserProperty(n) == null) {
 498  5
                 getProject().setInheritedProperty(n, v);
 499   
             } else {
 500  4
                 log("Override ignored for " + n, Project.MSG_VERBOSE);
 501   
             }
 502   
         } else {
 503  611
             getProject().setNewProperty(n, v);
 504   
         }
 505   
     }
 506   
 
 507   
     /**
 508   
      * resolve properties inside a properties hashtable
 509   
      * @param props properties object to resolve
 510   
      */
 511  13
     private void resolveAllProperties(Properties props) throws BuildException {
 512  13
         for (Enumeration e = props.keys(); e.hasMoreElements();) {
 513  120
             String name = (String) e.nextElement();
 514  120
             String value = props.getProperty(name);
 515   
 
 516  120
             boolean resolved = false;
 517  120
             while (!resolved) {
 518  123
                 Vector fragments = new Vector();
 519  123
                 Vector propertyRefs = new Vector();
 520  123
                 ProjectHelper.parsePropertyString(value, fragments,
 521   
                                                   propertyRefs);
 522   
 
 523  123
                 resolved = true;
 524  123
                 if (propertyRefs.size() != 0) {
 525  6
                     StringBuffer sb = new StringBuffer();
 526  6
                     Enumeration i = fragments.elements();
 527  6
                     Enumeration j = propertyRefs.elements();
 528  6
                     while (i.hasMoreElements()) {
 529  13
                         String fragment = (String) i.nextElement();
 530  13
                         if (fragment == null) {
 531  6
                             String propertyName = (String) j.nextElement();
 532  6
                             if (propertyName.equals(name)) {
 533  1
                                 throw new BuildException("Property " + name
 534   
                                                          + " was circularly "
 535   
                                                          + "defined.");
 536   
                             }
 537  5
                             fragment = getProject().getProperty(propertyName);
 538  5
                             if (fragment == null) {
 539  3
                                 if (props.containsKey(propertyName)) {
 540  3
                                     fragment = props.getProperty(propertyName);
 541  3
                                     resolved = false;
 542   
                                 } else {
 543  0
                                     fragment = "${" + propertyName + "}";
 544   
                                 }
 545   
                             }
 546   
                         }
 547  12
                         sb.append(fragment);
 548   
                     }
 549  5
                     value = sb.toString();
 550  5
                     props.put(name, value);
 551   
                 }
 552   
             }
 553   
         }
 554   
     }
 555   
 }
 556