Clover coverage report - Ant Coverage
Coverage timestamp: Tue Apr 8 2003 20:43:55 EST
file stats: LOC: 481   Methods: 28
NCLOC: 290   Classes: 2
 
 Source file Conditionals Statements Methods TOTAL
PatternSet.java 59.6% 67.6% 92.9% 67.4%
 1   
 /*
 2   
  * The Apache Software License, Version 1.1
 3   
  *
 4   
  * Copyright (c) 2000-2002 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.types;
 56   
 
 57   
 import java.io.BufferedReader;
 58   
 import java.io.File;
 59   
 import java.io.FileReader;
 60   
 import java.io.IOException;
 61   
 import java.util.Enumeration;
 62   
 import java.util.Stack;
 63   
 import java.util.StringTokenizer;
 64   
 import java.util.Vector;
 65   
 import org.apache.tools.ant.BuildException;
 66   
 import org.apache.tools.ant.Project;
 67   
 
 68   
 /**
 69   
  * Named collection of include/exclude tags.
 70   
  *
 71   
  * <p>Moved out of MatchingTask to make it a standalone object that
 72   
  * could be referenced (by scripts for example).
 73   
  *
 74   
  * @author Arnout J. Kuiper <a href="mailto:ajkuiper@wxs.nl">ajkuiper@wxs.nl</a> 
 75   
  * @author Stefano Mazzocchi <a href="mailto:stefano@apache.org">stefano@apache.org</a>
 76   
  * @author Sam Ruby <a href="mailto:rubys@us.ibm.com">rubys@us.ibm.com</a>
 77   
  * @author Jon S. Stevens <a href="mailto:jon@clearink.com">jon@clearink.com</a>
 78   
  * @author Stefan Bodewig
 79   
  */
 80   
 public class PatternSet extends DataType {
 81   
     private Vector includeList = new Vector();
 82   
     private Vector excludeList = new Vector();
 83   
     private Vector includesFileList = new Vector();
 84   
     private Vector excludesFileList = new Vector();
 85   
 
 86   
     /**
 87   
      * inner class to hold a name on list.  "If" and "Unless" attributes
 88   
      * may be used to invalidate the entry based on the existence of a 
 89   
      * property (typically set thru the use of the Available task).
 90   
      */
 91   
     public class NameEntry {
 92   
         private String name;
 93   
         private String ifCond;
 94   
         private String unlessCond;
 95   
 
 96  314
         public void setName(String name) { 
 97  314
             this.name = name; 
 98   
         }
 99   
 
 100  4
         public void setIf(String cond) {
 101  4
             ifCond = cond;
 102   
         }
 103   
 
 104  25
         public void setUnless(String cond) {
 105  25
             unlessCond = cond;
 106   
         }
 107   
 
 108  0
         public String getName() {
 109  0
             return name;
 110   
         }
 111   
 
 112  455
         public String evalName(Project p) { 
 113  455
             return valid(p) ? name : null; 
 114   
         }
 115   
 
 116  455
         private boolean valid(Project p) {
 117  455
             if (ifCond != null && p.getProperty(ifCond) == null) {
 118  4
                 return false;
 119  451
             } else if (unlessCond != null && p.getProperty(unlessCond) != null) {
 120  16
                 return false;
 121   
             }
 122  435
             return true;
 123   
         }
 124   
 
 125  437
         public String toString() {
 126  437
             StringBuffer buf = new StringBuffer(name);
 127  437
             if ((ifCond != null) || (unlessCond != null)) {
 128  29
                 buf.append(":");
 129  29
                 String connector = "";
 130   
                 
 131  29
                 if (ifCond != null) {
 132  4
                     buf.append("if->");
 133  4
                     buf.append(ifCond);
 134  4
                     connector = ";";
 135   
                 }
 136  29
                 if (unlessCond != null) {
 137  25
                     buf.append(connector);
 138  25
                     buf.append("unless->");
 139  25
                     buf.append(unlessCond);
 140   
                 }
 141   
             }
 142   
 
 143  437
             return buf.toString();
 144   
         }
 145   
     }
 146   
 
 147  1707
     public PatternSet() {
 148  1707
         super();
 149   
     }
 150   
 
 151   
     /**
 152   
      * Makes this instance in effect a reference to another PatternSet
 153   
      * instance.
 154   
      *
 155   
      * <p>You must not set another attribute or nest elements inside
 156   
      * this element if you make it a reference.</p> 
 157   
      */
 158  11
     public void setRefid(Reference r) throws BuildException {
 159  11
         if (!includeList.isEmpty() || !excludeList.isEmpty()) {
 160  1
             throw tooManyAttributes();
 161   
         }
 162  10
         super.setRefid(r);
 163   
     }
 164   
 
 165  1
     public void addConfiguredPatternset(PatternSet p) {
 166  1
         if (isReference()) {
 167  0
             throw noChildrenAllowed();
 168   
         }
 169   
 
 170  1
         String[] nestedIncludes = p.getIncludePatterns(getProject());
 171  1
         String[] nestedExcludes = p.getExcludePatterns(getProject());
 172   
 
 173  1
         if (nestedIncludes != null) {
 174  0
             for (int i = 0; i < nestedIncludes.length; i++) {
 175  0
                 createInclude().setName(nestedIncludes[i]);
 176   
             }
 177   
         }
 178   
 
 179  1
         if (nestedExcludes != null) {
 180  1
             for (int i = 0; i < nestedExcludes.length; i++) {
 181  1
                 createExclude().setName(nestedExcludes[i]);
 182   
             }
 183   
         }
 184   
     }
 185   
 
 186   
     /**
 187   
      * add a name entry on the include list
 188   
      */
 189  192
     public NameEntry createInclude() {
 190  192
         if (isReference()) {
 191  1
             throw noChildrenAllowed();
 192   
         }
 193  191
         return addPatternToList(includeList);
 194   
     }
 195   
 
 196   
     /**
 197   
      * add a name entry on the include files list
 198   
      */
 199  1
     public NameEntry createIncludesFile() {
 200  1
         if (isReference()) {
 201  1
             throw noChildrenAllowed();
 202   
         }
 203  0
         return addPatternToList(includesFileList);
 204   
     }
 205   
     
 206   
     /**
 207   
      * add a name entry on the exclude list
 208   
      */
 209  126
     public NameEntry createExclude() {
 210  126
         if (isReference()) {
 211  1
             throw noChildrenAllowed();
 212   
         }
 213  125
         return addPatternToList(excludeList);
 214   
     }
 215   
     
 216   
     /**
 217   
      * add a name entry on the exclude files list
 218   
      */
 219  1
     public NameEntry createExcludesFile() {
 220  1
         if (isReference()) {
 221  1
             throw noChildrenAllowed();
 222   
         }
 223  0
         return addPatternToList(excludesFileList);
 224   
     }
 225   
 
 226   
     /**
 227   
      * Appends <code>includes</code> to the current list of include patterns. 
 228   
      * Patterns may be separated by a comma or a space.
 229   
      *
 230   
      * @param includes the string containing the include patterns
 231   
      */
 232  136
     public void setIncludes(String includes) {
 233  136
         if (isReference()) {
 234  1
             throw tooManyAttributes();
 235   
         }
 236  135
         if (includes != null && includes.length() > 0) {
 237  135
             StringTokenizer tok = new StringTokenizer(includes, ", ", false);
 238  135
             while (tok.hasMoreTokens()) {
 239  136
                 createInclude().setName(tok.nextToken());
 240   
             }
 241   
         }
 242   
     }
 243   
 
 244   
     /**
 245   
      * Appends <code>excludes</code> to the current list of exclude patterns. 
 246   
      * Patterns may be separated by a comma or a space.
 247   
      *
 248   
      * @param excludes the string containing the exclude patterns
 249   
      */
 250  7
     public void setExcludes(String excludes) {
 251  7
         if (isReference()) {
 252  1
             throw tooManyAttributes();
 253   
         }
 254  6
         if (excludes != null && excludes.length() > 0) {
 255  6
             StringTokenizer tok = new StringTokenizer(excludes, ", ", false);
 256  6
             while (tok.hasMoreTokens()) {
 257  6
                 createExclude().setName(tok.nextToken());
 258   
             }
 259   
         }
 260   
     }
 261   
 
 262   
     /**
 263   
      * add a name entry to the given list
 264   
      */
 265  316
     private NameEntry addPatternToList(Vector list) {
 266  316
         NameEntry result = new NameEntry();
 267  316
         list.addElement(result);
 268  316
         return result;
 269   
     }
 270   
 
 271   
     /**
 272   
      * Sets the name of the file containing the includes patterns.
 273   
      *
 274   
      * @param includesFile The file to fetch the include patterns from.  
 275   
      */
 276  1
      public void setIncludesfile(File includesFile) throws BuildException {
 277  1
          if (isReference()) {
 278  1
              throw tooManyAttributes();
 279   
          }
 280  0
          createIncludesFile().setName(includesFile.getAbsolutePath());
 281   
      }
 282   
 
 283   
     /**
 284   
      * Sets the name of the file containing the excludes patterns.
 285   
      *
 286   
      * @param excludesFile The file to fetch the exclude patterns from.  
 287   
      */
 288  1
      public void setExcludesfile(File excludesFile) throws BuildException {
 289  1
          if (isReference()) {
 290  1
              throw tooManyAttributes();
 291   
          }
 292  0
          createExcludesFile().setName(excludesFile.getAbsolutePath());
 293   
      }
 294   
     
 295   
     /**
 296   
      *  Reads path matching patterns from a file and adds them to the
 297   
      *  includes or excludes list (as appropriate).  
 298   
      */
 299  0
     private void readPatterns(File patternfile, Vector patternlist, Project p)
 300   
         throws BuildException {
 301   
         
 302  0
         BufferedReader patternReader = null;
 303  0
         try {
 304   
             // Get a FileReader
 305  0
             patternReader = 
 306   
                 new BufferedReader(new FileReader(patternfile)); 
 307   
         
 308   
             // Create one NameEntry in the appropriate pattern list for each 
 309   
             // line in the file.
 310  0
             String line = patternReader.readLine();
 311  0
             while (line != null) {
 312  0
                 if (line.length() > 0) {
 313  0
                     line = p.replaceProperties(line);
 314  0
                     addPatternToList(patternlist).setName(line);
 315   
                 }
 316  0
                 line = patternReader.readLine();
 317   
             }
 318   
         } catch (IOException ioe)  {
 319  0
             String msg = "An error occured while reading from pattern file: " 
 320   
                 + patternfile;
 321  0
             throw new BuildException(msg, ioe);
 322   
         } finally {
 323  0
             if (null != patternReader) {
 324  0
                 try {
 325  0
                     patternReader.close();
 326   
                 } catch (IOException ioe) { 
 327   
                     //Ignore exception
 328   
                 }
 329   
             }
 330   
         }
 331   
     }
 332   
 
 333   
     /**
 334   
      * Adds the patterns of the other instance to this set.
 335   
      */
 336  2
     public void append(PatternSet other, Project p) {
 337  2
         if (isReference()) {
 338  0
             throw new BuildException("Cannot append to a reference");
 339   
         }
 340   
 
 341  2
         String[] incl = other.getIncludePatterns(p);
 342  2
         if (incl != null) {
 343  0
             for (int i = 0; i < incl.length; i++) {
 344  0
                 createInclude().setName(incl[i]);
 345   
             }
 346   
         }
 347   
         
 348  2
         String[] excl = other.getExcludePatterns(p);
 349  2
         if (excl != null) {
 350  2
             for (int i = 0; i < excl.length; i++) {
 351  2
                 createExclude().setName(excl[i]);
 352   
             }
 353   
         }
 354   
     }
 355   
 
 356   
     /**
 357   
      * Returns the filtered include patterns.
 358   
      */
 359  427
     public String[] getIncludePatterns(Project p) {
 360  427
         if (isReference()) {
 361  6
             return getRef(p).getIncludePatterns(p);
 362   
         } else {
 363  421
             readFiles(p);
 364  421
             return makeArray(includeList, p);
 365   
         }
 366   
     }
 367   
 
 368   
     /**
 369   
      * Returns the filtered include patterns.
 370   
      */
 371  421
     public String[] getExcludePatterns(Project p) {
 372  421
         if (isReference()) {
 373  4
             return getRef(p).getExcludePatterns(p);
 374   
         } else {
 375  417
             readFiles(p);
 376  417
             return makeArray(excludeList, p);
 377   
         }
 378   
     }
 379   
 
 380   
     /**
 381   
      * helper for FileSet.
 382   
      */
 383  24
     boolean hasPatterns(Project p) {
 384  24
         if (isReference()) {
 385  0
             return getRef(p).hasPatterns(p);
 386   
         } else {
 387  24
             return includesFileList.size() > 0 || excludesFileList.size() > 0 
 388   
                 || includeList.size() > 0 || excludeList.size() > 0;
 389   
         }
 390   
     }
 391   
 
 392   
     /**
 393   
      * Performs the check for circular references and returns the
 394   
      * referenced PatternSet.  
 395   
      */
 396  10
     private PatternSet getRef(Project p) {
 397  10
         if (!isChecked()) {
 398  7
             Stack stk = new Stack();
 399  7
             stk.push(this);
 400  7
             dieOnCircularReference(stk, p);
 401   
         }
 402   
         
 403  6
         Object o = getRefid().getReferencedObject(p);
 404  6
         if (!(o instanceof PatternSet)) {
 405  0
             String msg = getRefid().getRefId() + " doesn\'t denote a patternset";
 406  0
             throw new BuildException(msg);
 407   
         } else {
 408  6
             return (PatternSet) o;
 409   
         }
 410   
     }
 411   
 
 412   
     /**
 413   
      * Convert a vector of NameEntry elements into an array of Strings.
 414   
      */
 415  838
     private String[] makeArray(Vector list, Project p) {
 416  838
         if (list.size() == 0) {
 417  484
           return null;
 418   
         }
 419   
 
 420  354
         Vector tmpNames = new Vector();
 421  354
         for (Enumeration e = list.elements() ; e.hasMoreElements() ;) {
 422  455
             NameEntry ne = (NameEntry) e.nextElement();
 423  455
             String pattern = ne.evalName(p);
 424  455
             if (pattern != null && pattern.length() > 0) {
 425  435
                 tmpNames.addElement(pattern);
 426   
             }
 427   
         }
 428   
 
 429  354
         String[] result = new String[tmpNames.size()];
 430  354
         tmpNames.copyInto(result);
 431  354
         return result;
 432   
     }
 433   
         
 434   
     /**
 435   
      * Read includesfile ot excludesfile if not already done so.
 436   
      */
 437  838
     private void readFiles(Project p) {
 438  838
         if (includesFileList.size() > 0) {
 439  0
             Enumeration e = includesFileList.elements();
 440  0
             while (e.hasMoreElements()) {
 441  0
                 NameEntry ne = (NameEntry) e.nextElement();
 442  0
                 String fileName = ne.evalName(p);
 443  0
                 if (fileName != null) {
 444  0
                     File inclFile = p.resolveFile(fileName);
 445  0
                     if (!inclFile.exists()) {
 446  0
                         throw new BuildException("Includesfile "
 447   
                                                  + inclFile.getAbsolutePath()
 448   
                                                  + " not found.");
 449   
                     }
 450  0
                     readPatterns(inclFile, includeList, p);
 451   
                 }
 452   
             }
 453  0
             includesFileList.removeAllElements();
 454   
         }
 455   
 
 456  838
         if (excludesFileList.size() > 0) {
 457  0
             Enumeration e = excludesFileList.elements();
 458  0
             while (e.hasMoreElements()) {
 459  0
                 NameEntry ne = (NameEntry) e.nextElement();
 460  0
                 String fileName = ne.evalName(p);
 461  0
                 if (fileName != null) {
 462  0
                     File exclFile = p.resolveFile(fileName);
 463  0
                     if (!exclFile.exists()) {
 464  0
                         throw new BuildException("Excludesfile "
 465   
                                                  + exclFile.getAbsolutePath()
 466   
                                                  + " not found.");
 467   
                     }
 468  0
                     readPatterns(exclFile, excludeList, p);
 469   
                 }
 470   
             }
 471  0
             excludesFileList.removeAllElements();
 472   
         }
 473   
     }
 474   
 
 475  408
     public String toString() {
 476  408
         return "patternSet{ includes: " + includeList + 
 477   
             " excludes: " + excludeList + " }";
 478   
     }
 479   
 
 480   
 }
 481