001: /*
002: * The Apache Software License, Version 1.1
003: *
004: * Copyright (c) 1999 The Apache Software Foundation. All rights
005: * reserved.
006: *
007: * Redistribution and use in source and binary forms, with or without
008: * modification, are permitted provided that the following conditions
009: * are met:
010: *
011: * 1. Redistributions of source code must retain the above copyright
012: * notice, this list of conditions and the following disclaimer.
013: *
014: * 2. Redistributions in binary form must reproduce the above copyright
015: * notice, this list of conditions and the following disclaimer in
016: * the documentation and/or other materials provided with the
017: * distribution.
018: *
019: * 3. The end-user documentation included with the redistribution, if
020: * any, must include the following acknowlegement:
021: * "This product includes software developed by the
022: * Apache Software Foundation (http://www.apache.org/)."
023: * Alternately, this acknowlegement may appear in the software itself,
024: * if and wherever such third-party acknowlegements normally appear.
025: *
026: * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
027: * Foundation" must not be used to endorse or promote products derived
028: * from this software without prior written permission. For written
029: * permission, please contact apache@apache.org.
030: *
031: * 5. Products derived from this software may not be called "Apache"
032: * nor may "Apache" appear in their names without prior written
033: * permission of the Apache Group.
034: *
035: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
036: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
037: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
038: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
039: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
040: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
041: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
042: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
043: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
044: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
045: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
046: * SUCH DAMAGE.
047: * ====================================================================
048: *
049: * This software consists of voluntary contributions made by many
050: * individuals on behalf of the Apache Software Foundation. For more
051: * information on the Apache Software Foundation, please see
052: * <http://www.apache.org/>.
053: *
054: * Modified for us in XuiEditor
055: */
056:
057: package net.xoetrope.builder.editor.ant;
058:
059: import java.io.File;
060: import java.util.StringTokenizer;
061: import java.util.Vector;
062:
063: /**
064: * Class for scanning a directory for files/directories that match a certain
065: * criteria.
066: * <p>
067: * These criteria consist of a set of include and exclude patterns. With these
068: * patterns, you can select which files you want to have included, and which
069: * files you want to have excluded.
070: * <p>
071: * The idea is simple. A given directory is recursively scanned for all files
072: * and directories. Each file/directory is matched against a set of include
073: * and exclude patterns. Only files/directories that match at least one
074: * pattern of the include pattern list, and don't match a pattern of the
075: * exclude pattern list will be placed in the list of files/directories found.
076: * <p>
077: * When no list of include patterns is supplied, "**" will be used, which
078: * means that everything will be matched. When no list of exclude patterns is
079: * supplied, an empty list is used, such that nothing will be excluded.
080: * <p>
081: * The pattern matching is done as follows:
082: * The name to be matched is split up in path segments. A path segment is the
083: * name of a directory or file, which is bounded by
084: * <code>File.separator</code> ('/' under UNIX, '\' under Windows).
085: * E.g. "abc/def/ghi/xyz.java" is split up in the segments "abc", "def", "ghi"
086: * and "xyz.java".
087: * The same is done for the pattern against which should be matched.
088: * <p>
089: * Then the segments of the name and the pattern will be matched against each
090: * other. When '**' is used for a path segment in the pattern, then it matches
091: * zero or more path segments of the name.
092: * <p>
093: * There are special case regarding the use of <code>File.separator</code>s at
094: * the beginningof the pattern and the string to match:<br>
095: * When a pattern starts with a <code>File.separator</code>, the string
096: * to match must also start with a <code>File.separator</code>.
097: * When a pattern does not start with a <code>File.separator</code>, the
098: * string to match may not start with a <code>File.separator</code>.
099: * When one of these rules is not obeyed, the string will not
100: * match.
101: * <p>
102: * When a name path segment is matched against a pattern path segment, the
103: * following special characters can be used:
104: * '*' matches zero or more characters,
105: * '?' matches one character.
106: * <p>
107: * Examples:
108: * <p>
109: * "**\*.class" matches all .class files/dirs in a directory tree.
110: * <p>
111: * "test\a??.java" matches all files/dirs which start with an 'a', then two
112: * more characters and then ".java", in a directory called test.
113: * <p>
114: * "**" matches everything in a directory tree.
115: * <p>
116: * "**\test\**\XYZ*" matches all files/dirs that start with "XYZ" and where
117: * there is a parent directory called test (e.g. "abc\test\def\ghi\XYZ123").
118: * <p>
119: * Example of usage:
120: * <pre>
121: * String[] includes = {"**\\*.class"};
122: * String[] excludes = {"modules\\*\\**"};
123: * ds.setIncludes(includes);
124: * ds.setExcludes(excludes);
125: * ds.setBasedir(new File("test"));
126: * ds.scan();
127: *
128: * System.out.println("FILES:");
129: * String[] files = ds.getIncludedFiles();
130: * for (int i = 0; i < files.length;i++) {
131: * System.out.println(files[i]);
132: * }
133: * </pre>
134: * This will scan a directory called test for .class files, but excludes all
135: * .class files in all directories under a directory called "modules"
136: *
137: * @author Arnout J. Kuiper <a href="mailto:ajkuiper@wxs.nl">ajkuiper@wxs.nl</a>
138: */
139: public class DirectoryScanner {
140:
141: /**
142: * Patterns that should be excluded by default.
143: *
144: * @see #addDefaultExcludes()
145: */
146: private final static String[] DEFAULTEXCLUDES = { "**/*~",
147: "**/#*#", "**/%*%", "**/CVS", "**/CVS/*", "**/.cvsignore" };
148:
149: /**
150: * The base directory which should be scanned.
151: */
152: private File basedir;
153:
154: /**
155: * The patterns for the files that should be included.
156: */
157: private String[] includes;
158:
159: /**
160: * The patterns for the files that should be excluded.
161: */
162: private String[] excludes;
163:
164: /**
165: * The files that where found and matched at least one includes, and matched
166: * no excludes.
167: */
168: private Vector filesIncluded;
169:
170: /**
171: * The files that where found and did not match any includes.
172: */
173: private Vector filesNotIncluded;
174:
175: /**
176: * The files that where found and matched at least one includes, and also
177: * matched at least one excludes.
178: */
179: private Vector filesExcluded;
180:
181: /**
182: * The directories that where found and matched at least one includes, and
183: * matched no excludes.
184: */
185: private Vector dirsIncluded;
186:
187: /**
188: * The directories that where found and did not match any includes.
189: */
190: private Vector dirsNotIncluded;
191:
192: /**
193: * The files that where found and matched at least one includes, and also
194: * matched at least one excludes.
195: */
196: private Vector dirsExcluded;
197:
198: /**
199: * Constructor.
200: */
201: public DirectoryScanner() {
202: }
203:
204: /**
205: * Matches a path against a pattern.
206: *
207: * @param pattern the (non-null) pattern to match against
208: * @param str the (non-null) string (path) to match
209: *
210: * @return <code>true</code> when the pattern matches against the string.
211: * <code>false</code> otherwise.
212: */
213: private static boolean matchPath(String pattern, String str) {
214: // When str starts with a File.separator, pattern has to start with a
215: // File.separator.
216: // When pattern starts with a File.separator, str has to start with a
217: // File.separator.
218: if (str.startsWith(File.separator) != pattern
219: .startsWith(File.separator)) {
220: return false;
221: }
222:
223: Vector patDirs = new Vector();
224: StringTokenizer st = new StringTokenizer(pattern,
225: File.separator);
226: while (st.hasMoreTokens()) {
227: patDirs.addElement(st.nextToken());
228: }
229:
230: Vector strDirs = new Vector();
231: st = new StringTokenizer(str, File.separator);
232: while (st.hasMoreTokens()) {
233: strDirs.addElement(st.nextToken());
234: }
235:
236: int patIdxStart = 0;
237: int patIdxEnd = patDirs.size() - 1;
238: int strIdxStart = 0;
239: int strIdxEnd = strDirs.size() - 1;
240:
241: // up to first '**'
242: while (patIdxStart <= patIdxEnd && strIdxStart <= strIdxEnd) {
243: String patDir = (String) patDirs.elementAt(patIdxStart);
244: if (patDir.equals("**")) {
245: break;
246: }
247: if (!match(patDir, (String) strDirs.elementAt(strIdxStart))) {
248: return false;
249: }
250: patIdxStart++;
251: strIdxStart++;
252: }
253: if (strIdxStart > strIdxEnd) {
254: // String is exhausted
255: for (int i = patIdxStart; i <= patIdxEnd; i++) {
256: if (!patDirs.elementAt(i).equals("**")) {
257: return false;
258: }
259: }
260: return true;
261: } else {
262: if (patIdxStart > patIdxEnd) {
263: // String not exhausted, but pattern is. Failure.
264: return false;
265: }
266: }
267:
268: // up to last '**'
269: while (patIdxStart <= patIdxEnd && strIdxStart <= strIdxEnd) {
270: String patDir = (String) patDirs.elementAt(patIdxEnd);
271: if (patDir.equals("**")) {
272: break;
273: }
274: if (!match(patDir, (String) strDirs.elementAt(strIdxEnd))) {
275: return false;
276: }
277: patIdxEnd--;
278: strIdxEnd--;
279: }
280: if (strIdxStart > strIdxEnd) {
281: // String is exhausted
282: for (int i = patIdxStart; i <= patIdxEnd; i++) {
283: if (!patDirs.elementAt(i).equals("**")) {
284: return false;
285: }
286: }
287: return true;
288: }
289:
290: while (patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd) {
291: int patIdxTmp = -1;
292: for (int i = patIdxStart + 1; i <= patIdxEnd; i++) {
293: if (patDirs.elementAt(i).equals("**")) {
294: patIdxTmp = i;
295: break;
296: }
297: }
298: if (patIdxTmp == patIdxStart + 1) {
299: // '**/**' situation, so skip one
300: patIdxStart++;
301: continue;
302: }
303: // Find the pattern between padIdxStart & padIdxTmp in str between
304: // strIdxStart & strIdxEnd
305: int patLength = (patIdxTmp - patIdxStart - 1);
306: int strLength = (strIdxEnd - strIdxStart + 1);
307: int foundIdx = -1;
308: strLoop: for (int i = 0; i <= strLength - patLength; i++) {
309: for (int j = 0; j < patLength; j++) {
310: String subPat = (String) patDirs
311: .elementAt(patIdxStart + j + 1);
312: String subStr = (String) strDirs
313: .elementAt(strIdxStart + i + j);
314: if (!match(subPat, subStr)) {
315: continue strLoop;
316: }
317: }
318:
319: foundIdx = strIdxStart + i;
320: break;
321: }
322:
323: if (foundIdx == -1) {
324: return false;
325: }
326:
327: patIdxStart = patIdxTmp;
328: strIdxStart = foundIdx + patLength;
329: }
330:
331: for (int i = patIdxStart; i <= patIdxEnd; i++) {
332: if (!patDirs.elementAt(i).equals("**")) {
333: return false;
334: }
335: }
336:
337: return true;
338: }
339:
340: /**
341: * Matches a string against a pattern. The pattern contains two special
342: * characters:
343: * '*' which means zero or more characters,
344: * '?' which means one and only one character.
345: *
346: * @param pattern the (non-null) pattern to match against
347: * @param str the (non-null) string that must be matched against the
348: * pattern
349: *
350: * @return <code>true</code> when the string matches against the pattern,
351: * <code>false</code> otherwise.
352: */
353: private static boolean match(String pattern, String str) {
354: char[] patArr = pattern.toCharArray();
355: char[] strArr = str.toCharArray();
356: int patIdxStart = 0;
357: int patIdxEnd = patArr.length - 1;
358: int strIdxStart = 0;
359: int strIdxEnd = strArr.length - 1;
360: char ch;
361:
362: boolean containsStar = false;
363: for (int i = 0; i < patArr.length; i++) {
364: if (patArr[i] == '*') {
365: containsStar = true;
366: break;
367: }
368: }
369:
370: if (!containsStar) {
371: // No '*'s, so we make a shortcut
372: if (patIdxEnd != strIdxEnd) {
373: return false; // Pattern and string do not have the same size
374: }
375: for (int i = 0; i <= patIdxEnd; i++) {
376: ch = patArr[i];
377: if (ch != '?' && ch != strArr[i]) {
378: return false; // Character mismatch
379: }
380: }
381: return true; // String matches against pattern
382: }
383:
384: if (patIdxEnd == 0) {
385: return true; // Pattern contains only '*', which matches anything
386: }
387:
388: // Process characters before first star
389: while ((ch = patArr[patIdxStart]) != '*'
390: && strIdxStart <= strIdxEnd) {
391: if (ch != '?' && ch != strArr[strIdxStart]) {
392: return false;
393: }
394: patIdxStart++;
395: strIdxStart++;
396: }
397: if (strIdxStart > strIdxEnd) {
398: // All characters in the string are used. Check if only '*'s are
399: // left in the pattern. If so, we succeeded. Otherwise failure.
400: for (int i = patIdxStart; i <= patIdxEnd; i++) {
401: if (patArr[i] != '*') {
402: return false;
403: }
404: }
405: return true;
406: }
407:
408: // Process characters after last star
409: while ((ch = patArr[patIdxEnd]) != '*'
410: && strIdxStart <= strIdxEnd) {
411: if (ch != '?' && ch != strArr[strIdxEnd]) {
412: return false;
413: }
414: patIdxEnd--;
415: strIdxEnd--;
416: }
417: if (strIdxStart > strIdxEnd) {
418: // All characters in the string are used. Check if only '*'s are
419: // left in the pattern. If so, we succeeded. Otherwise failure.
420: for (int i = patIdxStart; i <= patIdxEnd; i++) {
421: if (patArr[i] != '*') {
422: return false;
423: }
424: }
425: return true;
426: }
427:
428: // process pattern between stars. padIdxStart and patIdxEnd point
429: // always to a '*'.
430: while (patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd) {
431: int patIdxTmp = -1;
432: for (int i = patIdxStart + 1; i <= patIdxEnd; i++) {
433: if (patArr[i] == '*') {
434: patIdxTmp = i;
435: break;
436: }
437: }
438: if (patIdxTmp == patIdxStart + 1) {
439: // Two stars next to each other, skip the first one.
440: patIdxStart++;
441: continue;
442: }
443: // Find the pattern between padIdxStart & padIdxTmp in str between
444: // strIdxStart & strIdxEnd
445: int patLength = (patIdxTmp - patIdxStart - 1);
446: int strLength = (strIdxEnd - strIdxStart + 1);
447: int foundIdx = -1;
448: strLoop: for (int i = 0; i <= strLength - patLength; i++) {
449: for (int j = 0; j < patLength; j++) {
450: ch = patArr[patIdxStart + j + 1];
451: if (ch != '?' && ch != strArr[strIdxStart + i + j]) {
452: continue strLoop;
453: }
454: }
455:
456: foundIdx = strIdxStart + i;
457: break;
458: }
459:
460: if (foundIdx == -1) {
461: return false;
462: }
463:
464: patIdxStart = patIdxTmp;
465: strIdxStart = foundIdx + patLength;
466: }
467:
468: // All characters in the string are used. Check if only '*'s are left
469: // in the pattern. If so, we succeeded. Otherwise failure.
470: for (int i = patIdxStart; i <= patIdxEnd; i++) {
471: if (patArr[i] != '*') {
472: return false;
473: }
474: }
475: return true;
476: }
477:
478: /**
479: * Sets the basedir for scanning. This is the directory that is scanned
480: * recursively. All '/' and '\' characters are replaced by
481: * <code>File.separatorChar</code>. So the separator used need not match
482: * <code>File.separatorChar</code>.
483: *
484: * @param basedir the (non-null) basedir for scanning
485: */
486: public void setBasedir(String basedir) {
487: setBasedir(new File(basedir.replace('/', File.separatorChar)
488: .replace('\\', File.separatorChar)));
489: }
490:
491: /**
492: * Sets the basedir for scanning. This is the directory that is scanned
493: * recursively.
494: *
495: * @param basedir the basedir for scanning
496: */
497: public void setBasedir(File basedir) {
498: this .basedir = basedir;
499: }
500:
501: /**
502: * Gets the basedir that is used for scanning. This is the directory that
503: * is scanned recursively.
504: *
505: * @return the basedir that is used for scanning
506: */
507: public File getBasedir() {
508: return basedir;
509: }
510:
511: /**
512: * Sets the set of include patterns to use. All '/' and '\' characters are
513: * replaced by <code>File.separatorChar</code>. So the separator used need
514: * not match <code>File.separatorChar</code>.
515: * <p>
516: * When a pattern ends with a '/' or '\', "**" is appended.
517: *
518: * @param includes list of include patterns
519: */
520: public void setIncludes(String[] includes) {
521: if (includes == null) {
522: this .includes = null;
523: } else {
524: this .includes = new String[includes.length];
525: for (int i = 0; i < includes.length; i++) {
526: String pattern;
527: pattern = includes[i].replace('/', File.separatorChar)
528: .replace('\\', File.separatorChar);
529: if (pattern.endsWith(File.separator)) {
530: pattern += "**";
531: }
532: this .includes[i] = pattern;
533: }
534: }
535: }
536:
537: /**
538: * Sets the set of exclude patterns to use. All '/' and '\' characters are
539: * replaced by <code>File.separatorChar</code>. So the separator used need
540: * not match <code>File.separatorChar</code>.
541: * <p>
542: * When a pattern ends with a '/' or '\', "**" is appended.
543: *
544: * @param excludes list of exclude patterns
545: */
546: public void setExcludes(String[] excludes) {
547: if (excludes == null) {
548: this .excludes = null;
549: } else {
550: this .excludes = new String[excludes.length];
551: for (int i = 0; i < excludes.length; i++) {
552: String pattern;
553: pattern = excludes[i].replace('/', File.separatorChar)
554: .replace('\\', File.separatorChar);
555: if (pattern.endsWith(File.separator)) {
556: pattern += "**";
557: }
558: this .excludes[i] = pattern;
559: }
560: }
561: }
562:
563: /**
564: * Scans the base directory for files that match at least one include
565: * pattern, and don't match any exclude patterns.
566: *
567: * @exception IllegalStateException when basedir was set incorrecly
568: */
569: public void scan() {
570: if (basedir == null) {
571: throw new IllegalStateException("No basedir set");
572: }
573: if (!basedir.exists()) {
574: throw new IllegalStateException("basedir does not exist");
575: }
576: if (!basedir.isDirectory()) {
577: throw new IllegalStateException(
578: "basedir is not a directory");
579: }
580:
581: if (includes == null) {
582: // No includes supplied, so set it to 'matches all'
583: includes = new String[1];
584: includes[0] = "**";
585: }
586: if (excludes == null) {
587: excludes = new String[0];
588: }
589:
590: filesIncluded = new Vector();
591: filesNotIncluded = new Vector();
592: filesExcluded = new Vector();
593: dirsIncluded = new Vector();
594: dirsNotIncluded = new Vector();
595: dirsExcluded = new Vector();
596:
597: scandir(basedir, "");
598: }
599:
600: /**
601: * Scans the passed dir for files and directories. Found files and
602: * directories are placed in their respective collections, based on the
603: * matching of includes and excludes. When a directory is found, it is
604: * scanned recursively.
605: *
606: * @param dir the directory to scan
607: * @param vpath the path relative to the basedir (needed to prevent
608: * problems with an absolute path when using dir)
609: *
610: * @see #filesIncluded
611: * @see #filesNotIncluded
612: * @see #filesExcluded
613: * @see #dirsIncluded
614: * @see #dirsNotIncluded
615: * @see #dirsExcluded
616: */
617: private void scandir(File dir, String vpath) {
618: String[] newfiles = dir.list();
619: for (int i = 0; i < newfiles.length; i++) {
620: String name = vpath + newfiles[i];
621: File file = new File(dir, newfiles[i]);
622: if (file.isDirectory()) {
623: if (isIncluded(name)) {
624: if (!isExcluded(name)) {
625: dirsIncluded.addElement(name);
626: } else {
627: dirsExcluded.addElement(name);
628: }
629: } else {
630: dirsNotIncluded.addElement(name);
631: }
632: scandir(file, name + File.separator);
633: } else if (file.isFile()) {
634: if (isIncluded(name)) {
635: if (!isExcluded(name)) {
636: filesIncluded.addElement(name);
637: } else {
638: filesExcluded.addElement(name);
639: }
640: } else {
641: filesNotIncluded.addElement(name);
642: }
643: }
644: }
645: }
646:
647: /**
648: * Tests whether a name matches against at least one include pattern.
649: *
650: * @param name the name to match
651: * @return <code>true</code> when the name matches against at least one
652: * include pattern, <code>false</code> otherwise.
653: */
654: private boolean isIncluded(String name) {
655: for (int i = 0; i < includes.length; i++) {
656: if (matchPath(includes[i], name)) {
657: return true;
658: }
659: }
660: return false;
661: }
662:
663: /**
664: * Tests whether a name matches against at least one exclude pattern.
665: *
666: * @param name the name to match
667: * @return <code>true</code> when the name matches against at least one
668: * exclude pattern, <code>false</code> otherwise.
669: */
670: private boolean isExcluded(String name) {
671: for (int i = 0; i < excludes.length; i++) {
672: if (matchPath(excludes[i], name)) {
673: return true;
674: }
675: }
676: return false;
677: }
678:
679: /**
680: * Get the names of the files that matched at least one of the include
681: * patterns, an matched none of the exclude patterns.
682: * The names are relative to the basedir.
683: *
684: * @return the names of the files
685: */
686: public String[] getIncludedFiles() {
687: int count = filesIncluded.size();
688: String[] files = new String[count];
689: for (int i = 0; i < count; i++) {
690: files[i] = (String) filesIncluded.elementAt(i);
691: }
692: return files;
693: }
694:
695: /**
696: * Get the names of the files that matched at none of the include patterns.
697: * The names are relative to the basedir.
698: *
699: * @return the names of the files
700: */
701: public String[] getNotIncludedFiles() {
702: int count = filesNotIncluded.size();
703: String[] files = new String[count];
704: for (int i = 0; i < count; i++) {
705: files[i] = (String) filesNotIncluded.elementAt(i);
706: }
707: return files;
708: }
709:
710: /**
711: * Get the names of the files that matched at least one of the include
712: * patterns, an matched also at least one of the exclude patterns.
713: * The names are relative to the basedir.
714: *
715: * @return the names of the files
716: */
717: public String[] getExcludedFiles() {
718: int count = filesExcluded.size();
719: String[] files = new String[count];
720: for (int i = 0; i < count; i++) {
721: files[i] = (String) filesExcluded.elementAt(i);
722: }
723: return files;
724: }
725:
726: /**
727: * Get the names of the directories that matched at least one of the include
728: * patterns, an matched none of the exclude patterns.
729: * The names are relative to the basedir.
730: *
731: * @return the names of the directories
732: */
733: public String[] getIncludedDirectories() {
734: int count = dirsIncluded.size();
735: String[] directories = new String[count];
736: for (int i = 0; i < count; i++) {
737: directories[i] = (String) dirsIncluded.elementAt(i);
738: }
739: return directories;
740: }
741:
742: /**
743: * Get the names of the directories that matched at none of the include
744: * patterns.
745: * The names are relative to the basedir.
746: *
747: * @return the names of the directories
748: */
749: public String[] getNotIncludedDirectories() {
750: int count = dirsNotIncluded.size();
751: String[] directories = new String[count];
752: for (int i = 0; i < count; i++) {
753: directories[i] = (String) dirsNotIncluded.elementAt(i);
754: }
755: return directories;
756: }
757:
758: /**
759: * Get the names of the directories that matched at least one of the include
760: * patterns, an matched also at least one of the exclude patterns.
761: * The names are relative to the basedir.
762: *
763: * @return the names of the directories
764: */
765: public String[] getExcludedDirectories() {
766: int count = dirsExcluded.size();
767: String[] directories = new String[count];
768: for (int i = 0; i < count; i++) {
769: directories[i] = (String) dirsExcluded.elementAt(i);
770: }
771: return directories;
772: }
773:
774: /**
775: * Adds the array with default exclusions to the current exclusions set.
776: *
777: * @see #DEFAULTEXCLUDES
778: */
779: public void addDefaultExcludes() {
780: int excludesLength = excludes == null ? 0 : excludes.length;
781: String[] newExcludes;
782: newExcludes = new String[excludesLength
783: + DEFAULTEXCLUDES.length];
784: if (excludesLength > 0) {
785: System.arraycopy(excludes, 0, newExcludes, 0,
786: excludesLength);
787: }
788: for (int i = 0; i < DEFAULTEXCLUDES.length; i++) {
789: newExcludes[i + excludesLength] = DEFAULTEXCLUDES[i]
790: .replace('/', File.separatorChar).replace('\\',
791: File.separatorChar);
792: }
793: excludes = newExcludes;
794: }
795:
796: }
|