Coverage Report - org.apache.maven.it.util.SelectorUtils
 
Classes in this File Line Coverage Branch Coverage Complexity
SelectorUtils
0%
0/209
0%
0/172
10.364
 
 1  
 /*
 2  
  * The Apache Software License, Version 1.1
 3  
  *
 4  
  * Copyright (c) 2002-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.maven.it.util;
 56  
 
 57  
 import java.io.File;
 58  
 import java.util.StringTokenizer;
 59  
 import java.util.Vector;
 60  
 
 61  
 /**
 62  
  * <p>This is a utility class used by selectors and DirectoryScanner. The
 63  
  * functionality more properly belongs just to selectors, but unfortunately
 64  
  * DirectoryScanner exposed these as protected methods. Thus we have to
 65  
  * support any subclasses of DirectoryScanner that may access these methods.
 66  
  * </p>
 67  
  * <p>This is a Singleton.</p>
 68  
  *
 69  
  * @author Arnout J. Kuiper
 70  
  * <a href="mailto:ajkuiper@wxs.nl">ajkuiper@wxs.nl</a>
 71  
  * @author Magesh Umasankar
 72  
  * @author <a href="mailto:bruce@callenish.com">Bruce Atherton</a>
 73  
  * @since 1.5
 74  
  */
 75  
 public final class SelectorUtils
 76  
 {
 77  
 
 78  0
     private static SelectorUtils instance = new SelectorUtils();
 79  
 
 80  
     /**
 81  
      * Private Constructor
 82  
      */
 83  
     private SelectorUtils()
 84  0
     {
 85  0
     }
 86  
 
 87  
     /**
 88  
      * Retrieves the manager of the Singleton.
 89  
      */
 90  
     public static SelectorUtils getInstance()
 91  
     {
 92  0
         return instance;
 93  
     }
 94  
 
 95  
     /**
 96  
      * Tests whether or not a given path matches the start of a given
 97  
      * pattern up to the first "**".
 98  
      * <p>
 99  
      * This is not a general purpose test and should only be used if you
 100  
      * can live with false positives. For example, <code>pattern=**\a</code>
 101  
      * and <code>str=b</code> will yield <code>true</code>.
 102  
      *
 103  
      * @param pattern The pattern to match against. Must not be
 104  
      *                <code>null</code>.
 105  
      * @param str     The path to match, as a String. Must not be
 106  
      *                <code>null</code>.
 107  
      *
 108  
      * @return whether or not a given path matches the start of a given
 109  
      * pattern up to the first "**".
 110  
      */
 111  
     public static boolean matchPatternStart( String pattern, String str )
 112  
     {
 113  0
         return matchPatternStart( pattern, str, true );
 114  
     }
 115  
 
 116  
     /**
 117  
      * Tests whether or not a given path matches the start of a given
 118  
      * pattern up to the first "**".
 119  
      * <p>
 120  
      * This is not a general purpose test and should only be used if you
 121  
      * can live with false positives. For example, <code>pattern=**\a</code>
 122  
      * and <code>str=b</code> will yield <code>true</code>.
 123  
      *
 124  
      * @param pattern The pattern to match against. Must not be
 125  
      *                <code>null</code>.
 126  
      * @param str     The path to match, as a String. Must not be
 127  
      *                <code>null</code>.
 128  
      * @param isCaseSensitive Whether or not matching should be performed
 129  
      *                        case sensitively.
 130  
      *
 131  
      * @return whether or not a given path matches the start of a given
 132  
      * pattern up to the first "**".
 133  
      */
 134  
     public static boolean matchPatternStart( String pattern, String str,
 135  
                                              boolean isCaseSensitive )
 136  
     {
 137  
         // When str starts with a File.separator, pattern has to start with a
 138  
         // File.separator.
 139  
         // When pattern starts with a File.separator, str has to start with a
 140  
         // File.separator.
 141  0
         if ( str.startsWith( File.separator ) !=
 142  
             pattern.startsWith( File.separator ) )
 143  
         {
 144  0
             return false;
 145  
         }
 146  
 
 147  0
         Vector patDirs = tokenizePath( pattern );
 148  0
         Vector strDirs = tokenizePath( str );
 149  
 
 150  0
         int patIdxStart = 0;
 151  0
         int patIdxEnd = patDirs.size() - 1;
 152  0
         int strIdxStart = 0;
 153  0
         int strIdxEnd = strDirs.size() - 1;
 154  
 
 155  
         // up to first '**'
 156  0
         while ( patIdxStart <= patIdxEnd && strIdxStart <= strIdxEnd )
 157  
         {
 158  0
             String patDir = (String) patDirs.elementAt( patIdxStart );
 159  0
             if ( patDir.equals( "**" ) )
 160  
             {
 161  0
                 break;
 162  
             }
 163  0
             if ( !match( patDir, (String) strDirs.elementAt( strIdxStart ),
 164  
                          isCaseSensitive ) )
 165  
             {
 166  0
                 return false;
 167  
             }
 168  0
             patIdxStart++;
 169  0
             strIdxStart++;
 170  0
         }
 171  
 
 172  0
         if ( strIdxStart > strIdxEnd )
 173  
         {
 174  
             // String is exhausted
 175  0
             return true;
 176  
         }
 177  0
         else if ( patIdxStart > patIdxEnd )
 178  
         {
 179  
             // String not exhausted, but pattern is. Failure.
 180  0
             return false;
 181  
         }
 182  
         else
 183  
         {
 184  
             // pattern now holds ** while string is not exhausted
 185  
             // this will generate false positives but we can live with that.
 186  0
             return true;
 187  
         }
 188  
     }
 189  
 
 190  
     /**
 191  
      * Tests whether or not a given path matches a given pattern.
 192  
      *
 193  
      * @param pattern The pattern to match against. Must not be
 194  
      *                <code>null</code>.
 195  
      * @param str     The path to match, as a String. Must not be
 196  
      *                <code>null</code>.
 197  
      *
 198  
      * @return <code>true</code> if the pattern matches against the string,
 199  
      *         or <code>false</code> otherwise.
 200  
      */
 201  
     public static boolean matchPath( String pattern, String str )
 202  
     {
 203  0
         return matchPath( pattern, str, true );
 204  
     }
 205  
 
 206  
     /**
 207  
      * Tests whether or not a given path matches a given pattern.
 208  
      *
 209  
      * @param pattern The pattern to match against. Must not be
 210  
      *                <code>null</code>.
 211  
      * @param str     The path to match, as a String. Must not be
 212  
      *                <code>null</code>.
 213  
      * @param isCaseSensitive Whether or not matching should be performed
 214  
      *                        case sensitively.
 215  
      *
 216  
      * @return <code>true</code> if the pattern matches against the string,
 217  
      *         or <code>false</code> otherwise.
 218  
      */
 219  
     public static boolean matchPath( String pattern, String str,
 220  
                                      boolean isCaseSensitive )
 221  
     {
 222  
         // When str starts with a File.separator, pattern has to start with a
 223  
         // File.separator.
 224  
         // When pattern starts with a File.separator, str has to start with a
 225  
         // File.separator.
 226  0
         if ( str.startsWith( File.separator ) !=
 227  
             pattern.startsWith( File.separator ) )
 228  
         {
 229  0
             return false;
 230  
         }
 231  
 
 232  0
         Vector patDirs = tokenizePath( pattern );
 233  0
         Vector strDirs = tokenizePath( str );
 234  
 
 235  0
         int patIdxStart = 0;
 236  0
         int patIdxEnd = patDirs.size() - 1;
 237  0
         int strIdxStart = 0;
 238  0
         int strIdxEnd = strDirs.size() - 1;
 239  
 
 240  
         // up to first '**'
 241  0
         while ( patIdxStart <= patIdxEnd && strIdxStart <= strIdxEnd )
 242  
         {
 243  0
             String patDir = (String) patDirs.elementAt( patIdxStart );
 244  0
             if ( patDir.equals( "**" ) )
 245  
             {
 246  0
                 break;
 247  
             }
 248  0
             if ( !match( patDir, (String) strDirs.elementAt( strIdxStart ),
 249  
                          isCaseSensitive ) )
 250  
             {
 251  0
                 patDirs = null;
 252  0
                 strDirs = null;
 253  0
                 return false;
 254  
             }
 255  0
             patIdxStart++;
 256  0
             strIdxStart++;
 257  0
         }
 258  0
         if ( strIdxStart > strIdxEnd )
 259  
         {
 260  
             // String is exhausted
 261  0
             for ( int i = patIdxStart; i <= patIdxEnd; i++ )
 262  
             {
 263  0
                 if ( !patDirs.elementAt( i ).equals( "**" ) )
 264  
                 {
 265  0
                     patDirs = null;
 266  0
                     strDirs = null;
 267  0
                     return false;
 268  
                 }
 269  
             }
 270  0
             return true;
 271  
         }
 272  
         else
 273  
         {
 274  0
             if ( patIdxStart > patIdxEnd )
 275  
             {
 276  
                 // String not exhausted, but pattern is. Failure.
 277  0
                 patDirs = null;
 278  0
                 strDirs = null;
 279  0
                 return false;
 280  
             }
 281  
         }
 282  
 
 283  
         // up to last '**'
 284  0
         while ( patIdxStart <= patIdxEnd && strIdxStart <= strIdxEnd )
 285  
         {
 286  0
             String patDir = (String) patDirs.elementAt( patIdxEnd );
 287  0
             if ( patDir.equals( "**" ) )
 288  
             {
 289  0
                 break;
 290  
             }
 291  0
             if ( !match( patDir, (String) strDirs.elementAt( strIdxEnd ),
 292  
                          isCaseSensitive ) )
 293  
             {
 294  0
                 patDirs = null;
 295  0
                 strDirs = null;
 296  0
                 return false;
 297  
             }
 298  0
             patIdxEnd--;
 299  0
             strIdxEnd--;
 300  0
         }
 301  0
         if ( strIdxStart > strIdxEnd )
 302  
         {
 303  
             // String is exhausted
 304  0
             for ( int i = patIdxStart; i <= patIdxEnd; i++ )
 305  
             {
 306  0
                 if ( !patDirs.elementAt( i ).equals( "**" ) )
 307  
                 {
 308  0
                     patDirs = null;
 309  0
                     strDirs = null;
 310  0
                     return false;
 311  
                 }
 312  
             }
 313  0
             return true;
 314  
         }
 315  
 
 316  0
         while ( patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd )
 317  
         {
 318  0
             int patIdxTmp = -1;
 319  0
             for ( int i = patIdxStart + 1; i <= patIdxEnd; i++ )
 320  
             {
 321  0
                 if ( patDirs.elementAt( i ).equals( "**" ) )
 322  
                 {
 323  0
                     patIdxTmp = i;
 324  0
                     break;
 325  
                 }
 326  
             }
 327  0
             if ( patIdxTmp == patIdxStart + 1 )
 328  
             {
 329  
                 // '**/**' situation, so skip one
 330  0
                 patIdxStart++;
 331  0
                 continue;
 332  
             }
 333  
             // Find the pattern between padIdxStart & padIdxTmp in str between
 334  
             // strIdxStart & strIdxEnd
 335  0
             int patLength = ( patIdxTmp - patIdxStart - 1 );
 336  0
             int strLength = ( strIdxEnd - strIdxStart + 1 );
 337  0
             int foundIdx = -1;
 338  
             strLoop:
 339  0
                         for ( int i = 0; i <= strLength - patLength; i++ )
 340  
                         {
 341  0
                             for ( int j = 0; j < patLength; j++ )
 342  
                             {
 343  0
                                 String subPat = (String) patDirs.elementAt( patIdxStart + j + 1 );
 344  0
                                 String subStr = (String) strDirs.elementAt( strIdxStart + i + j );
 345  0
                                 if ( !match( subPat, subStr, isCaseSensitive ) )
 346  
                                 {
 347  0
                                     continue strLoop;
 348  
                                 }
 349  
                             }
 350  
 
 351  0
                             foundIdx = strIdxStart + i;
 352  0
                             break;
 353  
                         }
 354  
 
 355  0
             if ( foundIdx == -1 )
 356  
             {
 357  0
                 patDirs = null;
 358  0
                 strDirs = null;
 359  0
                 return false;
 360  
             }
 361  
 
 362  0
             patIdxStart = patIdxTmp;
 363  0
             strIdxStart = foundIdx + patLength;
 364  0
         }
 365  
 
 366  0
         for ( int i = patIdxStart; i <= patIdxEnd; i++ )
 367  
         {
 368  0
             if ( !patDirs.elementAt( i ).equals( "**" ) )
 369  
             {
 370  0
                 patDirs = null;
 371  0
                 strDirs = null;
 372  0
                 return false;
 373  
             }
 374  
         }
 375  
 
 376  0
         return true;
 377  
     }
 378  
 
 379  
     /**
 380  
      * Tests whether or not a string matches against a pattern.
 381  
      * The pattern may contain two special characters:<br>
 382  
      * '*' means zero or more characters<br>
 383  
      * '?' means one and only one character
 384  
      *
 385  
      * @param pattern The pattern to match against.
 386  
      *                Must not be <code>null</code>.
 387  
      * @param str     The string which must be matched against the pattern.
 388  
      *                Must not be <code>null</code>.
 389  
      *
 390  
      * @return <code>true</code> if the string matches against the pattern,
 391  
      *         or <code>false</code> otherwise.
 392  
      */
 393  
     public static boolean match( String pattern, String str )
 394  
     {
 395  0
         return match( pattern, str, true );
 396  
     }
 397  
 
 398  
     /**
 399  
      * Tests whether or not a string matches against a pattern.
 400  
      * The pattern may contain two special characters:<br>
 401  
      * '*' means zero or more characters<br>
 402  
      * '?' means one and only one character
 403  
      *
 404  
      * @param pattern The pattern to match against.
 405  
      *                Must not be <code>null</code>.
 406  
      * @param str     The string which must be matched against the pattern.
 407  
      *                Must not be <code>null</code>.
 408  
      * @param isCaseSensitive Whether or not matching should be performed
 409  
      *                        case sensitively.
 410  
      *
 411  
      *
 412  
      * @return <code>true</code> if the string matches against the pattern,
 413  
      *         or <code>false</code> otherwise.
 414  
      */
 415  
     public static boolean match( String pattern, String str,
 416  
                                  boolean isCaseSensitive )
 417  
     {
 418  0
         char[] patArr = pattern.toCharArray();
 419  0
         char[] strArr = str.toCharArray();
 420  0
         int patIdxStart = 0;
 421  0
         int patIdxEnd = patArr.length - 1;
 422  0
         int strIdxStart = 0;
 423  0
         int strIdxEnd = strArr.length - 1;
 424  
         char ch;
 425  
 
 426  0
         boolean containsStar = false;
 427  0
         for ( int i = 0; i < patArr.length; i++ )
 428  
         {
 429  0
             if ( patArr[i] == '*' )
 430  
             {
 431  0
                 containsStar = true;
 432  0
                 break;
 433  
             }
 434  
         }
 435  
 
 436  0
         if ( !containsStar )
 437  
         {
 438  
             // No '*'s, so we make a shortcut
 439  0
             if ( patIdxEnd != strIdxEnd )
 440  
             {
 441  0
                 return false; // Pattern and string do not have the same size
 442  
             }
 443  0
             for ( int i = 0; i <= patIdxEnd; i++ )
 444  
             {
 445  0
                 ch = patArr[i];
 446  0
                 if ( ch != '?' )
 447  
                 {
 448  0
                     if ( isCaseSensitive && ch != strArr[i] )
 449  
                     {
 450  0
                         return false;// Character mismatch
 451  
                     }
 452  0
                     if ( !isCaseSensitive && Character.toUpperCase( ch ) !=
 453  
                         Character.toUpperCase( strArr[i] ) )
 454  
                     {
 455  0
                         return false; // Character mismatch
 456  
                     }
 457  
                 }
 458  
             }
 459  0
             return true; // String matches against pattern
 460  
         }
 461  
 
 462  0
         if ( patIdxEnd == 0 )
 463  
         {
 464  0
             return true; // Pattern contains only '*', which matches anything
 465  
         }
 466  
 
 467  
         // Process characters before first star
 468  0
         while ( ( ch = patArr[patIdxStart] ) != '*' && strIdxStart <= strIdxEnd )
 469  
         {
 470  0
             if ( ch != '?' )
 471  
             {
 472  0
                 if ( isCaseSensitive && ch != strArr[strIdxStart] )
 473  
                 {
 474  0
                     return false;// Character mismatch
 475  
                 }
 476  0
                 if ( !isCaseSensitive && Character.toUpperCase( ch ) !=
 477  
                     Character.toUpperCase( strArr[strIdxStart] ) )
 478  
                 {
 479  0
                     return false;// Character mismatch
 480  
                 }
 481  
             }
 482  0
             patIdxStart++;
 483  0
             strIdxStart++;
 484  
         }
 485  0
         if ( strIdxStart > strIdxEnd )
 486  
         {
 487  
             // All characters in the string are used. Check if only '*'s are
 488  
             // left in the pattern. If so, we succeeded. Otherwise failure.
 489  0
             for ( int i = patIdxStart; i <= patIdxEnd; i++ )
 490  
             {
 491  0
                 if ( patArr[i] != '*' )
 492  
                 {
 493  0
                     return false;
 494  
                 }
 495  
             }
 496  0
             return true;
 497  
         }
 498  
 
 499  
         // Process characters after last star
 500  0
         while ( ( ch = patArr[patIdxEnd] ) != '*' && strIdxStart <= strIdxEnd )
 501  
         {
 502  0
             if ( ch != '?' )
 503  
             {
 504  0
                 if ( isCaseSensitive && ch != strArr[strIdxEnd] )
 505  
                 {
 506  0
                     return false;// Character mismatch
 507  
                 }
 508  0
                 if ( !isCaseSensitive && Character.toUpperCase( ch ) !=
 509  
                     Character.toUpperCase( strArr[strIdxEnd] ) )
 510  
                 {
 511  0
                     return false;// Character mismatch
 512  
                 }
 513  
             }
 514  0
             patIdxEnd--;
 515  0
             strIdxEnd--;
 516  
         }
 517  0
         if ( strIdxStart > strIdxEnd )
 518  
         {
 519  
             // All characters in the string are used. Check if only '*'s are
 520  
             // left in the pattern. If so, we succeeded. Otherwise failure.
 521  0
             for ( int i = patIdxStart; i <= patIdxEnd; i++ )
 522  
             {
 523  0
                 if ( patArr[i] != '*' )
 524  
                 {
 525  0
                     return false;
 526  
                 }
 527  
             }
 528  0
             return true;
 529  
         }
 530  
 
 531  
         // process pattern between stars. padIdxStart and patIdxEnd point
 532  
         // always to a '*'.
 533  0
         while ( patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd )
 534  
         {
 535  0
             int patIdxTmp = -1;
 536  0
             for ( int i = patIdxStart + 1; i <= patIdxEnd; i++ )
 537  
             {
 538  0
                 if ( patArr[i] == '*' )
 539  
                 {
 540  0
                     patIdxTmp = i;
 541  0
                     break;
 542  
                 }
 543  
             }
 544  0
             if ( patIdxTmp == patIdxStart + 1 )
 545  
             {
 546  
                 // Two stars next to each other, skip the first one.
 547  0
                 patIdxStart++;
 548  0
                 continue;
 549  
             }
 550  
             // Find the pattern between padIdxStart & padIdxTmp in str between
 551  
             // strIdxStart & strIdxEnd
 552  0
             int patLength = ( patIdxTmp - patIdxStart - 1 );
 553  0
             int strLength = ( strIdxEnd - strIdxStart + 1 );
 554  0
             int foundIdx = -1;
 555  
             strLoop:
 556  0
             for ( int i = 0; i <= strLength - patLength; i++ )
 557  
             {
 558  0
                 for ( int j = 0; j < patLength; j++ )
 559  
                 {
 560  0
                     ch = patArr[patIdxStart + j + 1];
 561  0
                     if ( ch != '?' )
 562  
                     {
 563  0
                         if ( isCaseSensitive && ch != strArr[strIdxStart + i + j] )
 564  
                         {
 565  0
                             continue strLoop;
 566  
                         }
 567  0
                         if ( !isCaseSensitive && Character.toUpperCase( ch ) !=
 568  
                             Character.toUpperCase( strArr[strIdxStart + i + j] ) )
 569  
                         {
 570  0
                             continue strLoop;
 571  
                         }
 572  
                     }
 573  
                 }
 574  
 
 575  0
                 foundIdx = strIdxStart + i;
 576  0
                 break;
 577  
             }
 578  
 
 579  0
             if ( foundIdx == -1 )
 580  
             {
 581  0
                 return false;
 582  
             }
 583  
 
 584  0
             patIdxStart = patIdxTmp;
 585  0
             strIdxStart = foundIdx + patLength;
 586  0
         }
 587  
 
 588  
         // All characters in the string are used. Check if only '*'s are left
 589  
         // in the pattern. If so, we succeeded. Otherwise failure.
 590  0
         for ( int i = patIdxStart; i <= patIdxEnd; i++ )
 591  
         {
 592  0
             if ( patArr[i] != '*' )
 593  
             {
 594  0
                 return false;
 595  
             }
 596  
         }
 597  0
         return true;
 598  
     }
 599  
 
 600  
     /**
 601  
      * Breaks a path up into a Vector of path elements, tokenizing on
 602  
      * <code>File.separator</code>.
 603  
      *
 604  
      * @param path Path to tokenize. Must not be <code>null</code>.
 605  
      *
 606  
      * @return a Vector of path elements from the tokenized path
 607  
      */
 608  
     public static Vector tokenizePath( String path )
 609  
     {
 610  0
         Vector ret = new Vector();
 611  0
         StringTokenizer st = new StringTokenizer( path, File.separator );
 612  0
         while ( st.hasMoreTokens() )
 613  
         {
 614  0
             ret.addElement( st.nextToken() );
 615  
         }
 616  0
         return ret;
 617  
     }
 618  
 
 619  
 
 620  
     /**
 621  
      * Returns dependency information on these two files. If src has been
 622  
      * modified later than target, it returns true. If target doesn't exist,
 623  
      * it likewise returns true. Otherwise, target is newer than src and
 624  
      * is not out of date, thus the method returns false. It also returns
 625  
      * false if the src file doesn't even exist, since how could the
 626  
      * target then be out of date.
 627  
      *
 628  
      * @param src the original file
 629  
      * @param target the file being compared against
 630  
      * @param granularity the amount in seconds of slack we will give in
 631  
      *        determining out of dateness
 632  
      * @return whether the target is out of date
 633  
      */
 634  
     public static boolean isOutOfDate( File src, File target, int granularity )
 635  
     {
 636  0
         if ( !src.exists() )
 637  
         {
 638  0
             return false;
 639  
         }
 640  0
         if ( !target.exists() )
 641  
         {
 642  0
             return true;
 643  
         }
 644  0
         if ( ( src.lastModified() - granularity ) > target.lastModified() )
 645  
         {
 646  0
             return true;
 647  
         }
 648  0
         return false;
 649  
     }
 650  
 
 651  
     /**
 652  
      * "Flattens" a string by removing all whitespace (space, tab, linefeed,
 653  
      * carriage return, and formfeed). This uses StringTokenizer and the
 654  
      * default set of tokens as documented in the single arguement constructor.
 655  
      *
 656  
      * @param input a String to remove all whitespace.
 657  
      * @return a String that has had all whitespace removed.
 658  
      */
 659  
     public static String removeWhitespace( String input )
 660  
     {
 661  0
         StringBuffer result = new StringBuffer();
 662  0
         if ( input != null )
 663  
         {
 664  0
             StringTokenizer st = new StringTokenizer( input );
 665  0
             while ( st.hasMoreTokens() )
 666  
             {
 667  0
                 result.append( st.nextToken() );
 668  
             }
 669  
         }
 670  0
         return result.toString();
 671  
     }
 672  
 }