You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ant.apache.org by bo...@locus.apache.org on 2000/08/04 12:24:31 UTC

cvs commit: jakarta-ant/src/main/org/apache/tools/ant DirectoryScanner.java

bodewig     00/08/04 03:24:31

  Modified:    src/main/org/apache/tools/ant DirectoryScanner.java
  Log:
  DirectoryScanner will now only scan directories which are included or
  could hold included files. All other directories will only be scanned
  when one of the getExcluded... or getNotIncluded... methods is called.
  
  Revision  Changes    Path
  1.4       +126 -7    jakarta-ant/src/main/org/apache/tools/ant/DirectoryScanner.java
  
  Index: DirectoryScanner.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/src/main/org/apache/tools/ant/DirectoryScanner.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- DirectoryScanner.java	2000/06/29 15:32:37	1.3
  +++ DirectoryScanner.java	2000/08/04 10:24:30	1.4
  @@ -198,7 +198,10 @@
        */
       private Vector dirsExcluded;
   
  -
  +    /**
  +     * Have the Vectors holding our results been built by a slow scan?
  +     */
  +    private boolean haveSlowResults = false;
   
       /**
        * Constructor.
  @@ -207,7 +210,70 @@
       }
   
   
  +    /**
  +     * Does the path match the start of this pattern up to the first "**".
  +     +
  +     * <p>This is not a general purpose test and should only be used if you
  +     * can live with false positives.</p>
  +     *
  +     * <p><code>pattern=**\\a</code> and <code>str=b</code> will yield true.
  +     *
  +     * @param pattern the (non-null) pattern to match against
  +     * @param str     the (non-null) string (path) to match
  +     */
  +    private static boolean matchPatternStart(String pattern, String str) {
  +        // When str starts with a File.separator, pattern has to start with a
  +        // File.separator.
  +        // When pattern starts with a File.separator, str has to start with a
  +        // File.separator.
  +        if (str.startsWith(File.separator) !=
  +            pattern.startsWith(File.separator)) {
  +            return false;
  +        }
   
  +        Vector patDirs = new Vector();
  +        StringTokenizer st = new StringTokenizer(pattern,File.separator);
  +        while (st.hasMoreTokens()) {
  +            patDirs.addElement(st.nextToken());
  +        }
  +
  +        Vector strDirs = new Vector();
  +        st = new StringTokenizer(str,File.separator);
  +        while (st.hasMoreTokens()) {
  +            strDirs.addElement(st.nextToken());
  +        }
  +
  +        int patIdxStart = 0;
  +        int patIdxEnd   = patDirs.size()-1;
  +        int strIdxStart = 0;
  +        int strIdxEnd   = strDirs.size()-1;
  +
  +        // up to first '**'
  +        while (patIdxStart <= patIdxEnd && strIdxStart <= strIdxEnd) {
  +            String patDir = (String)patDirs.elementAt(patIdxStart);
  +            if (patDir.equals("**")) {
  +                break;
  +            }
  +            if (!match(patDir,(String)strDirs.elementAt(strIdxStart))) {
  +                return false;
  +            }
  +            patIdxStart++;
  +            strIdxStart++;
  +        }
  +
  +        if (strIdxStart > strIdxEnd) {
  +            // String is exhausted
  +            return true;
  +        } else if (patIdxStart > patIdxEnd) {
  +            // String not exhausted, but pattern is. Failure.
  +            return false;
  +        } else {
  +            // pattern now holds ** while string is not exhausted
  +            // this will generate false positives but we can live with that.
  +            return true;
  +        }
  +    }
  +
       /**
        * Matches a path against a pattern.
        *
  @@ -608,9 +674,38 @@
           dirsNotIncluded  = new Vector();
           dirsExcluded     = new Vector();
   
  -        scandir(basedir,"");
  +        scandir(basedir, "", true);
       }
   
  +    /**
  +     * Toplevel invocation for the scan.
  +     *
  +     * <p>Returns immediately if a slow scan has already been requested.
  +     */
  +    private void slowScan() {
  +        if (haveSlowResults) {
  +            return;
  +        }
  +
  +        String[] excl = new String[dirsExcluded.size()];
  +        dirsExcluded.copyInto(excl);
  +
  +        String[] notIncl = new String[dirsNotIncluded.size()];
  +        dirsNotIncluded.copyInto(notIncl);
  +
  +        for (int i=0; i<excl.length; i++) {
  +            scandir(new File(basedir, excl[i]), excl[i]+File.separator, false);
  +        }
  +        
  +        for (int i=0; i<notIncl.length; i++) {
  +            if (!couldHoldIncluded(notIncl[i])) {
  +                scandir(new File(basedir, notIncl[i]), 
  +                        notIncl[i]+File.separator, false);
  +            }
  +        }
  +
  +        haveSlowResults  = true;
  +    }
   
   
       /**
  @@ -630,7 +725,7 @@
        * @see #dirsNotIncluded
        * @see #dirsExcluded
        */
  -    private void scandir(File dir, String vpath) {
  +    private void scandir(File dir, String vpath, boolean fast) {
           String[] newfiles = dir.list();
           for (int i = 0; i < newfiles.length; i++) {
               String name = vpath+newfiles[i];
  @@ -639,13 +734,21 @@
                   if (isIncluded(name)) {
                       if (!isExcluded(name)) {
                           dirsIncluded.addElement(name);
  +                        if (fast) {
  +                            scandir(file, name+File.separator, fast);
  +                        }
                       } else {
                           dirsExcluded.addElement(name);
                       }
                   } else {
                       dirsNotIncluded.addElement(name);
  +                    if (fast && couldHoldIncluded(name)) {
  +                        scandir(file, name+File.separator, fast);
  +                    }
  +                }
  +                if (!fast) {
  +                    scandir(file, name+File.separator, fast);
                   }
  -                scandir(file, name+File.separator);
               } else if (file.isFile()) {
                   if (isIncluded(name)) {
                       if (!isExcluded(name)) {
  @@ -678,7 +781,21 @@
           return false;
       }
   
  -
  +    /**
  +     * Tests whether a name matches the start of at least one include pattern.
  +     *
  +     * @param name the name to match
  +     * @return <code>true</code> when the name matches against at least one
  +     *         include pattern, <code>false</code> otherwise.
  +     */
  +    private boolean couldHoldIncluded(String name) {
  +        for (int i = 0; i < includes.length; i++) {
  +            if (matchPatternStart(includes[i],name)) {
  +                return true;
  +            }
  +        }
  +        return false;
  +    }
   
       /**
        * Tests whether a name matches against at least one exclude pattern.
  @@ -723,6 +840,7 @@
        * @return the names of the files
        */
       public String[] getNotIncludedFiles() {
  +        slowScan();
           int count = filesNotIncluded.size();
           String[] files = new String[count];
           for (int i = 0; i < count; i++) {
  @@ -741,6 +859,7 @@
        * @return the names of the files
        */
       public String[] getExcludedFiles() {
  +        slowScan();
           int count = filesExcluded.size();
           String[] files = new String[count];
           for (int i = 0; i < count; i++) {
  @@ -777,6 +896,7 @@
        * @return the names of the directories
        */
       public String[] getNotIncludedDirectories() {
  +        slowScan();
           int count = dirsNotIncluded.size();
           String[] directories = new String[count];
           for (int i = 0; i < count; i++) {
  @@ -795,6 +915,7 @@
        * @return the names of the directories
        */
       public String[] getExcludedDirectories() {
  +        slowScan();
           int count = dirsExcluded.size();
           String[] directories = new String[count];
           for (int i = 0; i < count; i++) {
  @@ -821,7 +942,5 @@
           }
           excludes = newExcludes;
       }
  -
  -
   
   }
  
  
  

RE: DDCreator Tasks Seems Broken

Posted by Conor MacNeill <co...@m64.com>.
> Thank you, Conor, all is well again and my build completes.
>
> Just for my curiosity, I didn't see any diffs between the
> July 26 version of translateLine (which was the last one that
> worked for me), and the August 4 version that broke.  Was it
> that translateLine was now in the call chain where it wasn't
> before, or am I missing something?
>


No you have it right. Stefan has been progressively refactoring the use of
exec in most tasks.

Conor


RE: DDCreator Tasks Seems Broken

Posted by Paul Hodgetts <pa...@zzyzxtek.com>.
Conor MacNeill wrote:

 > translateLine is intended to break the command line into separate
 > components. It takes a pretty Unix centric view of the world allowing you to
 > quote arguments using ' and " and then use \ as an escape character for
 > those quote characters. I'll try to make it a little more Windows friendly.

Thank you, Conor, all is well again and my build completes.

Just for my curiosity, I didn't see any diffs between the
July 26 version of translateLine (which was the last one that
worked for me), and the August 4 version that broke.  Was it
that translateLine was now in the call chain where it wasn't
before, or am I missing something?

In any case, the August 7 build is fixed.  Thanks again.

Paul


Re: DDCreator Tasks Seems Broken

Posted by Stefan Bodewig <bo...@bost.de>.
>>>>> "CM" == Conor MacNeill <co...@m64.com> writes:

 CM> translateLine is intended to break the command line into separate
 CM> components. It takes a pretty Unix centric view of the world
 CM> allowing you to quote arguments using ' and " and then use \ as
 CM> an escape character for those quote characters. I'll try to make
 CM> it a little more Windows friendly.

Ouch! Mea culpa, mea maxima culpa.

It was intended to accept command lines like you would use them on Unix
or DOS and tokenize them into individual arguments. Of course I didn't
think about \ characters used for anything other than quoting ' or " -
an oversight you've corrected with your patch, thanks.

Stefan

RE: DDCreator Tasks Seems Broken

Posted by Conor MacNeill <co...@m64.com>.
Well that wasn't a very useful reply, was it? Sorry. I had seen the same
problem myself and in EjbJar added a quick hack for it (replace('\\', '/'))

translateLine is intended to break the command line into separate
components. It takes a pretty Unix centric view of the world allowing you to
quote arguments using ' and " and then use \ as an escape character for
those quote characters. I'll try to make it a little more Windows friendly.

Conor



> -----Original Message-----
> From: Conor MacNeill [mailto:conor@m64.com]
> Sent: Saturday, 5 August 2000 16:25
> To: ant-dev@jakarta.apache.org
> Subject: RE: DDCreator Tasks Seems Broken
>
>
> Paul,
>
> I think it something to do with the way \ characters are treated.
> I'll look
> into it.
>
> Conor
>
>
> > -----Original Message-----
> > From: Paul Hodgetts [mailto:paulh@zzyzxtek.com]
> > Sent: Saturday, 5 August 2000 11:29
> > To: ant-dev@jakarta.apache.org
> > Subject: DDCreator Tasks Seems Broken
> >
> >
> > After downloading last night's build (8/4 ~2 AM), it seems like
> > the DDCreator task has broken.
> >
> > I'm running on WinNT 4.0.
> >
> > When the argument list reaches DDCreatorHelper (at line 99 in the
> > constructor), the backslashes have been stripped from the
> > directories that specify the source and destination (the first two
> > arguments).  In DDCreator (line 115), before passing them to
> > DDCreatorHelper, they have the backslashes.
> >
> > I think the culprit is somewhere in the ddCreatorTask.setArgs(args)
> > call.  Possibly down in CommandLine, in the nested class Argument,
> > in the setLine() method, where it calls translateCommandLine().
> > It looks like translateCommandLine() is stripping out the
> > backslashes, but honestly I'm lost at this point and can't tell
> > for sure what's up or why.  But I don't see any diffs in
> > translateCommandLine() between the previous build I was running
> > and the new build, so maybe something somewhere up the ladder is
> > calling it when it shouldn't or something.
> >
> > Can anyone who knows the code better please take a look?  I'll be
> > happy to run any tests or help debug wherever I can, although I
> > won't be able to help much over the weekend, but I can Monday.
> >
> > Thanks,
> > Paul
> >
>


RE: DDCreator Tasks Seems Broken

Posted by Conor MacNeill <co...@m64.com>.
Paul,

I think it something to do with the way \ characters are treated. I'll look
into it.

Conor


> -----Original Message-----
> From: Paul Hodgetts [mailto:paulh@zzyzxtek.com]
> Sent: Saturday, 5 August 2000 11:29
> To: ant-dev@jakarta.apache.org
> Subject: DDCreator Tasks Seems Broken
>
>
> After downloading last night's build (8/4 ~2 AM), it seems like
> the DDCreator task has broken.
>
> I'm running on WinNT 4.0.
>
> When the argument list reaches DDCreatorHelper (at line 99 in the
> constructor), the backslashes have been stripped from the
> directories that specify the source and destination (the first two
> arguments).  In DDCreator (line 115), before passing them to
> DDCreatorHelper, they have the backslashes.
>
> I think the culprit is somewhere in the ddCreatorTask.setArgs(args)
> call.  Possibly down in CommandLine, in the nested class Argument,
> in the setLine() method, where it calls translateCommandLine().
> It looks like translateCommandLine() is stripping out the
> backslashes, but honestly I'm lost at this point and can't tell
> for sure what's up or why.  But I don't see any diffs in
> translateCommandLine() between the previous build I was running
> and the new build, so maybe something somewhere up the ladder is
> calling it when it shouldn't or something.
>
> Can anyone who knows the code better please take a look?  I'll be
> happy to run any tests or help debug wherever I can, although I
> won't be able to help much over the weekend, but I can Monday.
>
> Thanks,
> Paul
>


DDCreator Tasks Seems Broken

Posted by Paul Hodgetts <pa...@zzyzxtek.com>.
After downloading last night's build (8/4 ~2 AM), it seems like
the DDCreator task has broken.

I'm running on WinNT 4.0.

When the argument list reaches DDCreatorHelper (at line 99 in the
constructor), the backslashes have been stripped from the
directories that specify the source and destination (the first two
arguments).  In DDCreator (line 115), before passing them to
DDCreatorHelper, they have the backslashes.

I think the culprit is somewhere in the ddCreatorTask.setArgs(args)
call.  Possibly down in CommandLine, in the nested class Argument,
in the setLine() method, where it calls translateCommandLine().
It looks like translateCommandLine() is stripping out the
backslashes, but honestly I'm lost at this point and can't tell
for sure what's up or why.  But I don't see any diffs in
translateCommandLine() between the previous build I was running
and the new build, so maybe something somewhere up the ladder is
calling it when it shouldn't or something.

Can anyone who knows the code better please take a look?  I'll be
happy to run any tests or help debug wherever I can, although I
won't be able to help much over the weekend, but I can Monday.

Thanks,
Paul


Re: regular expression task?

Posted by Louis Tribble <lo...@metamata.com>.
Russell Gold wrote:
> Are there any good regexp libraries for Java which would facilitate 
> creating such a task or extending the Replace task to so this?

An embarrassment of riches:

http:/jakarta.apache.org/oro
http:/jakarta.apache.org/regexp

Both recent additions.

Louis
-- 

<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
Louis Tribble                                         louis@metamata.com
Metamata, Inc.                                   http://www.metamata.com
Tools for serious Java developers.                       +1 510 796 0915
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>

regular expression task?

Posted by Russell Gold <ru...@acm.org>.
Has anyone written a task to replace strings in files using regular expressions or other patterns?  Or possibly one to execute PERL commands (which would do the same thing)?

Are there any good regexp libraries for Java which would facilitate creating such a task or extending the Replace task to so this?

------------------------------------------------------------------------
Russell Gold                     | "... society is tradition and order
russgold@acm.org    (preferred)  | and reverence, not a series of cheap
russgold@netaxs.com              | bargains between selfish interests."
rgold@thesycamoregroup.com       |   - Poul Anderson, "Iron"



Re: cvs commit: jakarta-ant/src/main/org/apache/tools/ant DirectoryScanner.java

Posted by Stefan Bodewig <bo...@bost.de>.
This patch can have different effects depending on your setup, ranging
from a slight performance hit to a significant boost.

The old directory scanner would traverse the whole directory tree even
if it knew it was following a "dead" arc - somebody could call
getExcludedFiles of getNotIncludedFiles and then this information
would be needed.

No task in the Ant distribution ever calls those methods BTW.

In small directory trees this won't do much, but in a test setup like
this:

./docs                     <----- contains 35 dirs with ~ 650 files
./de                       <----- contains  > 500 source files in ~ 180
                                  directories together with ~ 2000
                                  additional files
./tests                    <----- ~ 180 source files in 50 directories

<javac srcdir=".">
  <include name="de/**/*.java" />
</javac>

would take 19 seconds to find that all source files were up to date in
the old setup and 7 seconds in the new version on my machine.

Stefan