You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

DirectoryScanner.java 36 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959
  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 "The Jakarta Project", "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. package org.apache.tools.ant;
  55. import java.io.File;
  56. import java.io.IOException;
  57. import java.util.Vector;
  58. import org.apache.tools.ant.types.selectors.FileSelector;
  59. import org.apache.tools.ant.types.selectors.SelectorScanner;
  60. import org.apache.tools.ant.types.selectors.SelectorUtils;
  61. import org.apache.tools.ant.util.FileUtils;
  62. /**
  63. * Class for scanning a directory for files/directories which match certain
  64. * criteria.
  65. * <p>
  66. * These criteria consist of selectors and patterns which have been specified.
  67. * With the selectors you can select which files you want to have included.
  68. * Files which are not selected are excluded. With patterns you can include
  69. * or exclude files based on their filename.
  70. * <p>
  71. * The idea is simple. A given directory is recursively scanned for all files
  72. * and directories. Each file/directory is matched against a set of selectors,
  73. * including special support for matching against filenames with include and
  74. * and exclude patterns. Only files/directories which match at least one
  75. * pattern of the include pattern list or other file selector, and don't match
  76. * any pattern of the exclude pattern list or fail to match against a required
  77. * selector will be placed in the list of files/directories found.
  78. * <p>
  79. * When no list of include patterns is supplied, "**" will be used, which
  80. * means that everything will be matched. When no list of exclude patterns is
  81. * supplied, an empty list is used, such that nothing will be excluded. When
  82. * no selectors are supplied, none are applied.
  83. * <p>
  84. * The filename pattern matching is done as follows:
  85. * The name to be matched is split up in path segments. A path segment is the
  86. * name of a directory or file, which is bounded by
  87. * <code>File.separator</code> ('/' under UNIX, '\' under Windows).
  88. * For example, "abc/def/ghi/xyz.java" is split up in the segments "abc",
  89. * "def","ghi" and "xyz.java".
  90. * The same is done for the pattern against which should be matched.
  91. * <p>
  92. * The segments of the name and the pattern are then matched against each
  93. * other. When '**' is used for a path segment in the pattern, it matches
  94. * zero or more path segments of the name.
  95. * <p>
  96. * There is a special case regarding the use of <code>File.separator</code>s
  97. * at the beginning of the pattern and the string to match:<br>
  98. * When a pattern starts with a <code>File.separator</code>, the string
  99. * to match must also start with a <code>File.separator</code>.
  100. * When a pattern does not start with a <code>File.separator</code>, the
  101. * string to match may not start with a <code>File.separator</code>.
  102. * When one of these rules is not obeyed, the string will not
  103. * match.
  104. * <p>
  105. * When a name path segment is matched against a pattern path segment, the
  106. * following special characters can be used:<br>
  107. * '*' matches zero or more characters<br>
  108. * '?' matches one character.
  109. * <p>
  110. * Examples:
  111. * <p>
  112. * "**\*.class" matches all .class files/dirs in a directory tree.
  113. * <p>
  114. * "test\a??.java" matches all files/dirs which start with an 'a', then two
  115. * more characters and then ".java", in a directory called test.
  116. * <p>
  117. * "**" matches everything in a directory tree.
  118. * <p>
  119. * "**\test\**\XYZ*" matches all files/dirs which start with "XYZ" and where
  120. * there is a parent directory called test (e.g. "abc\test\def\ghi\XYZ123").
  121. * <p>
  122. * Case sensitivity may be turned off if necessary. By default, it is
  123. * turned on.
  124. * <p>
  125. * Example of usage:
  126. * <pre>
  127. * String[] includes = {"**\\*.class"};
  128. * String[] excludes = {"modules\\*\\**"};
  129. * ds.setIncludes(includes);
  130. * ds.setExcludes(excludes);
  131. * ds.setBasedir(new File("test"));
  132. * ds.setCaseSensitive(true);
  133. * ds.scan();
  134. *
  135. * System.out.println("FILES:");
  136. * String[] files = ds.getIncludedFiles();
  137. * for (int i = 0; i < files.length; i++) {
  138. * System.out.println(files[i]);
  139. * }
  140. * </pre>
  141. * This will scan a directory called test for .class files, but excludes all
  142. * files in all proper subdirectories of a directory called "modules"
  143. *
  144. * @author Arnout J. Kuiper
  145. * <a href="mailto:ajkuiper@wxs.nl">ajkuiper@wxs.nl</a>
  146. * @author Magesh Umasankar
  147. * @author <a href="mailto:bruce@callenish.com">Bruce Atherton</a>
  148. */
  149. public class DirectoryScanner implements FileScanner, SelectorScanner {
  150. /**
  151. * Patterns which should be excluded by default.
  152. *
  153. * @see #addDefaultExcludes()
  154. */
  155. protected static final String[] DEFAULTEXCLUDES = {
  156. "**/*~",
  157. "**/#*#",
  158. "**/.#*",
  159. "**/%*%",
  160. "**/._*",
  161. "**/CVS",
  162. "**/CVS/**",
  163. "**/.cvsignore",
  164. "**/SCCS",
  165. "**/SCCS/**",
  166. "**/vssver.scc",
  167. "**/.svn",
  168. "**/.svn/**"
  169. };
  170. /** The base directory to be scanned. */
  171. protected File basedir;
  172. /** The patterns for the files to be included. */
  173. protected String[] includes;
  174. /** The patterns for the files to be excluded. */
  175. protected String[] excludes;
  176. /** Selectors that will filter which files are in our candidate list. */
  177. protected FileSelector[] selectors = null;
  178. /** The files which matched at least one include and no excludes
  179. * and were selected.
  180. */
  181. protected Vector filesIncluded;
  182. /** The files which did not match any includes or selectors. */
  183. protected Vector filesNotIncluded;
  184. /**
  185. * The files which matched at least one include and at least
  186. * one exclude.
  187. */
  188. protected Vector filesExcluded;
  189. /** The directories which matched at least one include and no excludes
  190. * and were selected.
  191. */
  192. protected Vector dirsIncluded;
  193. /** The directories which were found and did not match any includes. */
  194. protected Vector dirsNotIncluded;
  195. /**
  196. * The directories which matched at least one include and at least one
  197. * exclude.
  198. */
  199. protected Vector dirsExcluded;
  200. /** The files which matched at least one include and no excludes and
  201. * which a selector discarded.
  202. */
  203. protected Vector filesDeselected;
  204. /** The directories which matched at least one include and no excludes
  205. * but which a selector discarded.
  206. */
  207. protected Vector dirsDeselected;
  208. /** Whether or not our results were built by a slow scan. */
  209. protected boolean haveSlowResults = false;
  210. /**
  211. * Whether or not the file system should be treated as a case sensitive
  212. * one.
  213. */
  214. protected boolean isCaseSensitive = true;
  215. /**
  216. * Whether or not symbolic links should be followed.
  217. *
  218. * @since Ant 1.5
  219. */
  220. private boolean followSymlinks = true;
  221. /** Helper. */
  222. private static final FileUtils fileUtils = FileUtils.newFileUtils();
  223. /** Whether or not everything tested so far has been included. */
  224. protected boolean everythingIncluded = true;
  225. /**
  226. * Sole constructor.
  227. */
  228. public DirectoryScanner() {
  229. }
  230. /**
  231. * Tests whether or not a given path matches the start of a given
  232. * pattern up to the first "**".
  233. * <p>
  234. * This is not a general purpose test and should only be used if you
  235. * can live with false positives. For example, <code>pattern=**\a</code>
  236. * and <code>str=b</code> will yield <code>true</code>.
  237. *
  238. * @param pattern The pattern to match against. Must not be
  239. * <code>null</code>.
  240. * @param str The path to match, as a String. Must not be
  241. * <code>null</code>.
  242. *
  243. * @return whether or not a given path matches the start of a given
  244. * pattern up to the first "**".
  245. */
  246. protected static boolean matchPatternStart(String pattern, String str) {
  247. return SelectorUtils.matchPatternStart(pattern, str);
  248. }
  249. /**
  250. * Tests whether or not a given path matches the start of a given
  251. * pattern up to the first "**".
  252. * <p>
  253. * This is not a general purpose test and should only be used if you
  254. * can live with false positives. For example, <code>pattern=**\a</code>
  255. * and <code>str=b</code> will yield <code>true</code>.
  256. *
  257. * @param pattern The pattern to match against. Must not be
  258. * <code>null</code>.
  259. * @param str The path to match, as a String. Must not be
  260. * <code>null</code>.
  261. * @param isCaseSensitive Whether or not matching should be performed
  262. * case sensitively.
  263. *
  264. * @return whether or not a given path matches the start of a given
  265. * pattern up to the first "**".
  266. */
  267. protected static boolean matchPatternStart(String pattern, String str,
  268. boolean isCaseSensitive) {
  269. return SelectorUtils.matchPatternStart(pattern, str, isCaseSensitive);
  270. }
  271. /**
  272. * Tests whether or not a given path matches a given pattern.
  273. *
  274. * @param pattern The pattern to match against. Must not be
  275. * <code>null</code>.
  276. * @param str The path to match, as a String. Must not be
  277. * <code>null</code>.
  278. *
  279. * @return <code>true</code> if the pattern matches against the string,
  280. * or <code>false</code> otherwise.
  281. */
  282. protected static boolean matchPath(String pattern, String str) {
  283. return SelectorUtils.matchPath(pattern, str);
  284. }
  285. /**
  286. * Tests whether or not a given path matches a given pattern.
  287. *
  288. * @param pattern The pattern to match against. Must not be
  289. * <code>null</code>.
  290. * @param str The path to match, as a String. Must not be
  291. * <code>null</code>.
  292. * @param isCaseSensitive Whether or not matching should be performed
  293. * case sensitively.
  294. *
  295. * @return <code>true</code> if the pattern matches against the string,
  296. * or <code>false</code> otherwise.
  297. */
  298. protected static boolean matchPath(String pattern, String str,
  299. boolean isCaseSensitive) {
  300. return SelectorUtils.matchPath(pattern, str, isCaseSensitive);
  301. }
  302. /**
  303. * Tests whether or not a string matches against a pattern.
  304. * The pattern may contain two special characters:<br>
  305. * '*' means zero or more characters<br>
  306. * '?' means one and only one character
  307. *
  308. * @param pattern The pattern to match against.
  309. * Must not be <code>null</code>.
  310. * @param str The string which must be matched against the pattern.
  311. * Must not be <code>null</code>.
  312. *
  313. * @return <code>true</code> if the string matches against the pattern,
  314. * or <code>false</code> otherwise.
  315. */
  316. public static boolean match(String pattern, String str) {
  317. return SelectorUtils.match(pattern, str);
  318. }
  319. /**
  320. * Tests whether or not a string matches against a pattern.
  321. * The pattern may contain two special characters:<br>
  322. * '*' means zero or more characters<br>
  323. * '?' means one and only one character
  324. *
  325. * @param pattern The pattern to match against.
  326. * Must not be <code>null</code>.
  327. * @param str The string which must be matched against the pattern.
  328. * Must not be <code>null</code>.
  329. * @param isCaseSensitive Whether or not matching should be performed
  330. * case sensitively.
  331. *
  332. *
  333. * @return <code>true</code> if the string matches against the pattern,
  334. * or <code>false</code> otherwise.
  335. */
  336. protected static boolean match(String pattern, String str,
  337. boolean isCaseSensitive) {
  338. return SelectorUtils.match(pattern, str, isCaseSensitive);
  339. }
  340. /**
  341. * Sets the base directory to be scanned. This is the directory which is
  342. * scanned recursively. All '/' and '\' characters are replaced by
  343. * <code>File.separatorChar</code>, so the separator used need not match
  344. * <code>File.separatorChar</code>.
  345. *
  346. * @param basedir The base directory to scan.
  347. * Must not be <code>null</code>.
  348. */
  349. public void setBasedir(String basedir) {
  350. setBasedir(new File(basedir.replace('/', File.separatorChar).replace(
  351. '\\', File.separatorChar)));
  352. }
  353. /**
  354. * Sets the base directory to be scanned. This is the directory which is
  355. * scanned recursively.
  356. *
  357. * @param basedir The base directory for scanning.
  358. * Should not be <code>null</code>.
  359. */
  360. public void setBasedir(File basedir) {
  361. this.basedir = basedir;
  362. }
  363. /**
  364. * Returns the base directory to be scanned.
  365. * This is the directory which is scanned recursively.
  366. *
  367. * @return the base directory to be scanned
  368. */
  369. public File getBasedir() {
  370. return basedir;
  371. }
  372. /**
  373. * Sets whether or not the file system should be regarded as case sensitive.
  374. *
  375. * @param isCaseSensitive whether or not the file system should be
  376. * regarded as a case sensitive one
  377. */
  378. public void setCaseSensitive(boolean isCaseSensitive) {
  379. this.isCaseSensitive = isCaseSensitive;
  380. }
  381. /**
  382. * Sets whether or not symbolic links should be followed.
  383. *
  384. * @param followSymlinks whether or not symbolic links should be followed
  385. */
  386. public void setFollowSymlinks(boolean followSymlinks) {
  387. this.followSymlinks = followSymlinks;
  388. }
  389. /**
  390. * Sets the list of include patterns to use. All '/' and '\' characters
  391. * are replaced by <code>File.separatorChar</code>, so the separator used
  392. * need not match <code>File.separatorChar</code>.
  393. * <p>
  394. * When a pattern ends with a '/' or '\', "**" is appended.
  395. *
  396. * @param includes A list of include patterns.
  397. * May be <code>null</code>, indicating that all files
  398. * should be included. If a non-<code>null</code>
  399. * list is given, all elements must be
  400. * non-<code>null</code>.
  401. */
  402. public void setIncludes(String[] includes) {
  403. if (includes == null) {
  404. this.includes = null;
  405. } else {
  406. this.includes = new String[includes.length];
  407. for (int i = 0; i < includes.length; i++) {
  408. String pattern;
  409. pattern = includes[i].replace('/', File.separatorChar).replace(
  410. '\\', File.separatorChar);
  411. if (pattern.endsWith(File.separator)) {
  412. pattern += "**";
  413. }
  414. this.includes[i] = pattern;
  415. }
  416. }
  417. }
  418. /**
  419. * Sets the list of exclude patterns to use. All '/' and '\' characters
  420. * are replaced by <code>File.separatorChar</code>, so the separator used
  421. * need not match <code>File.separatorChar</code>.
  422. * <p>
  423. * When a pattern ends with a '/' or '\', "**" is appended.
  424. *
  425. * @param excludes A list of exclude patterns.
  426. * May be <code>null</code>, indicating that no files
  427. * should be excluded. If a non-<code>null</code> list is
  428. * given, all elements must be non-<code>null</code>.
  429. */
  430. public void setExcludes(String[] excludes) {
  431. if (excludes == null) {
  432. this.excludes = null;
  433. } else {
  434. this.excludes = new String[excludes.length];
  435. for (int i = 0; i < excludes.length; i++) {
  436. String pattern;
  437. pattern = excludes[i].replace('/', File.separatorChar).replace(
  438. '\\', File.separatorChar);
  439. if (pattern.endsWith(File.separator)) {
  440. pattern += "**";
  441. }
  442. this.excludes[i] = pattern;
  443. }
  444. }
  445. }
  446. /**
  447. * Sets the selectors that will select the filelist.
  448. *
  449. * @param selectors specifies the selectors to be invoked on a scan
  450. */
  451. public void setSelectors(FileSelector[] selectors) {
  452. this.selectors = selectors;
  453. }
  454. /**
  455. * Returns whether or not the scanner has included all the files or
  456. * directories it has come across so far.
  457. *
  458. * @return <code>true</code> if all files and directories which have
  459. * been found so far have been included.
  460. */
  461. public boolean isEverythingIncluded() {
  462. return everythingIncluded;
  463. }
  464. /**
  465. * Scans the base directory for files which match at least one include
  466. * pattern and don't match any exclude patterns. If there are selectors
  467. * then the files must pass muster there, as well.
  468. *
  469. * @exception IllegalStateException if the base directory was set
  470. * incorrectly (i.e. if it is <code>null</code>, doesn't exist,
  471. * or isn't a directory).
  472. */
  473. public void scan() throws IllegalStateException {
  474. if (basedir == null) {
  475. throw new IllegalStateException("No basedir set");
  476. }
  477. if (!basedir.exists()) {
  478. throw new IllegalStateException("basedir " + basedir
  479. + " does not exist");
  480. }
  481. if (!basedir.isDirectory()) {
  482. throw new IllegalStateException("basedir " + basedir
  483. + " is not a directory");
  484. }
  485. if (includes == null) {
  486. // No includes supplied, so set it to 'matches all'
  487. includes = new String[1];
  488. includes[0] = "**";
  489. }
  490. if (excludes == null) {
  491. excludes = new String[0];
  492. }
  493. filesIncluded = new Vector();
  494. filesNotIncluded = new Vector();
  495. filesExcluded = new Vector();
  496. filesDeselected = new Vector();
  497. dirsIncluded = new Vector();
  498. dirsNotIncluded = new Vector();
  499. dirsExcluded = new Vector();
  500. dirsDeselected = new Vector();
  501. if (isIncluded("")) {
  502. if (!isExcluded("")) {
  503. if (isSelected("",basedir)) {
  504. dirsIncluded.addElement("");
  505. } else {
  506. dirsDeselected.addElement("");
  507. }
  508. } else {
  509. dirsExcluded.addElement("");
  510. }
  511. } else {
  512. dirsNotIncluded.addElement("");
  513. }
  514. scandir(basedir, "", true);
  515. }
  516. /**
  517. * Top level invocation for a slow scan. A slow scan builds up a full
  518. * list of excluded/included files/directories, whereas a fast scan
  519. * will only have full results for included files, as it ignores
  520. * directories which can't possibly hold any included files/directories.
  521. * <p>
  522. * Returns immediately if a slow scan has already been completed.
  523. */
  524. protected void slowScan() {
  525. if (haveSlowResults) {
  526. return;
  527. }
  528. String[] excl = new String[dirsExcluded.size()];
  529. dirsExcluded.copyInto(excl);
  530. String[] notIncl = new String[dirsNotIncluded.size()];
  531. dirsNotIncluded.copyInto(notIncl);
  532. for (int i = 0; i < excl.length; i++) {
  533. if (!couldHoldIncluded(excl[i])) {
  534. scandir(new File(basedir, excl[i]),
  535. excl[i] + File.separator, false);
  536. }
  537. }
  538. for (int i = 0; i < notIncl.length; i++) {
  539. if (!couldHoldIncluded(notIncl[i])) {
  540. scandir(new File(basedir, notIncl[i]),
  541. notIncl[i] + File.separator, false);
  542. }
  543. }
  544. haveSlowResults = true;
  545. }
  546. /**
  547. * Scans the given directory for files and directories. Found files and
  548. * directories are placed in their respective collections, based on the
  549. * matching of includes, excludes, and the selectors. When a directory
  550. * is found, it is scanned recursively.
  551. *
  552. * @param dir The directory to scan. Must not be <code>null</code>.
  553. * @param vpath The path relative to the base directory (needed to
  554. * prevent problems with an absolute path when using
  555. * dir). Must not be <code>null</code>.
  556. * @param fast Whether or not this call is part of a fast scan.
  557. *
  558. * @see #filesIncluded
  559. * @see #filesNotIncluded
  560. * @see #filesExcluded
  561. * @see #dirsIncluded
  562. * @see #dirsNotIncluded
  563. * @see #dirsExcluded
  564. * @see #slowScan
  565. */
  566. protected void scandir(File dir, String vpath, boolean fast) {
  567. String[] newfiles = dir.list();
  568. if (newfiles == null) {
  569. /*
  570. * two reasons are mentioned in the API docs for File.list
  571. * (1) dir is not a directory. This is impossible as
  572. * we wouldn't get here in this case.
  573. * (2) an IO error occurred (why doesn't it throw an exception
  574. * then???)
  575. */
  576. throw new BuildException("IO error scanning directory "
  577. + dir.getAbsolutePath());
  578. }
  579. if (!followSymlinks) {
  580. Vector noLinks = new Vector();
  581. for (int i = 0; i < newfiles.length; i++) {
  582. try {
  583. if (fileUtils.isSymbolicLink(dir, newfiles[i])) {
  584. String name = vpath + newfiles[i];
  585. File file = new File(dir, newfiles[i]);
  586. if (file.isDirectory()) {
  587. dirsExcluded.addElement(name);
  588. } else {
  589. filesExcluded.addElement(name);
  590. }
  591. } else {
  592. noLinks.addElement(newfiles[i]);
  593. }
  594. } catch (IOException ioe) {
  595. String msg = "IOException caught while checking "
  596. + "for links, couldn't get cannonical path!";
  597. // will be caught and redirected to Ant's logging system
  598. System.err.println(msg);
  599. noLinks.addElement(newfiles[i]);
  600. }
  601. }
  602. newfiles = new String[noLinks.size()];
  603. noLinks.copyInto(newfiles);
  604. }
  605. for (int i = 0; i < newfiles.length; i++) {
  606. String name = vpath + newfiles[i];
  607. File file = new File(dir, newfiles[i]);
  608. if (file.isDirectory()) {
  609. if (isIncluded(name)) {
  610. if (!isExcluded(name)) {
  611. if (isSelected(name,file)) {
  612. dirsIncluded.addElement(name);
  613. if (fast) {
  614. scandir(file, name + File.separator, fast);
  615. }
  616. } else {
  617. everythingIncluded = false;
  618. dirsDeselected.addElement(name);
  619. if (fast && couldHoldIncluded(name)) {
  620. scandir(file, name + File.separator, fast);
  621. }
  622. }
  623. } else {
  624. everythingIncluded = false;
  625. dirsExcluded.addElement(name);
  626. if (fast && couldHoldIncluded(name)) {
  627. scandir(file, name + File.separator, fast);
  628. }
  629. }
  630. } else {
  631. everythingIncluded = false;
  632. dirsNotIncluded.addElement(name);
  633. if (fast && couldHoldIncluded(name)) {
  634. scandir(file, name + File.separator, fast);
  635. }
  636. }
  637. if (!fast) {
  638. scandir(file, name + File.separator, fast);
  639. }
  640. } else if (file.isFile()) {
  641. if (isIncluded(name)) {
  642. if (!isExcluded(name)) {
  643. if (isSelected(name,file)) {
  644. filesIncluded.addElement(name);
  645. } else {
  646. everythingIncluded = false;
  647. filesDeselected.addElement(name);
  648. }
  649. } else {
  650. everythingIncluded = false;
  651. filesExcluded.addElement(name);
  652. }
  653. } else {
  654. everythingIncluded = false;
  655. filesNotIncluded.addElement(name);
  656. }
  657. }
  658. }
  659. }
  660. /**
  661. * Tests whether or not a name matches against at least one include
  662. * pattern.
  663. *
  664. * @param name The name to match. Must not be <code>null</code>.
  665. * @return <code>true</code> when the name matches against at least one
  666. * include pattern, or <code>false</code> otherwise.
  667. */
  668. protected boolean isIncluded(String name) {
  669. for (int i = 0; i < includes.length; i++) {
  670. if (matchPath(includes[i], name, isCaseSensitive)) {
  671. return true;
  672. }
  673. }
  674. return false;
  675. }
  676. /**
  677. * Tests whether or not a name matches the start of at least one include
  678. * pattern.
  679. *
  680. * @param name The name to match. Must not be <code>null</code>.
  681. * @return <code>true</code> when the name matches against the start of at
  682. * least one include pattern, or <code>false</code> otherwise.
  683. */
  684. protected boolean couldHoldIncluded(String name) {
  685. for (int i = 0; i < includes.length; i++) {
  686. if (matchPatternStart(includes[i], name, isCaseSensitive)) {
  687. return true;
  688. }
  689. }
  690. return false;
  691. }
  692. /**
  693. * Tests whether or not a name matches against at least one exclude
  694. * pattern.
  695. *
  696. * @param name The name to match. Must not be <code>null</code>.
  697. * @return <code>true</code> when the name matches against at least one
  698. * exclude pattern, or <code>false</code> otherwise.
  699. */
  700. protected boolean isExcluded(String name) {
  701. for (int i = 0; i < excludes.length; i++) {
  702. if (matchPath(excludes[i], name, isCaseSensitive)) {
  703. return true;
  704. }
  705. }
  706. return false;
  707. }
  708. /**
  709. * Tests whether a name should be selected.
  710. *
  711. * @param name the filename to check for selecting
  712. * @param file the java.io.File object for this filename
  713. * @return <code>false</code> when the selectors says that the file
  714. * should not be selected, <code>true</code> otherwise.
  715. */
  716. protected boolean isSelected(String name, File file) {
  717. if (selectors != null) {
  718. for (int i = 0; i < selectors.length; i++) {
  719. if ((selectors[i].isSelected(basedir, name, file)) == false) {
  720. return false;
  721. }
  722. }
  723. }
  724. return true;
  725. }
  726. /**
  727. * Returns the names of the files which matched at least one of the
  728. * include patterns and none of the exclude patterns.
  729. * The names are relative to the base directory.
  730. *
  731. * @return the names of the files which matched at least one of the
  732. * include patterns and none of the exclude patterns.
  733. */
  734. public String[] getIncludedFiles() {
  735. int count = filesIncluded.size();
  736. String[] files = new String[count];
  737. for (int i = 0; i < count; i++) {
  738. files[i] = (String)filesIncluded.elementAt(i);
  739. }
  740. return files;
  741. }
  742. /**
  743. * Returns the names of the files which matched none of the include
  744. * patterns. The names are relative to the base directory. This involves
  745. * performing a slow scan if one has not already been completed.
  746. *
  747. * @return the names of the files which matched none of the include
  748. * patterns.
  749. *
  750. * @see #slowScan
  751. */
  752. public String[] getNotIncludedFiles() {
  753. slowScan();
  754. int count = filesNotIncluded.size();
  755. String[] files = new String[count];
  756. for (int i = 0; i < count; i++) {
  757. files[i] = (String)filesNotIncluded.elementAt(i);
  758. }
  759. return files;
  760. }
  761. /**
  762. * Returns the names of the files which matched at least one of the
  763. * include patterns and at least one of the exclude patterns.
  764. * The names are relative to the base directory. This involves
  765. * performing a slow scan if one has not already been completed.
  766. *
  767. * @return the names of the files which matched at least one of the
  768. * include patterns and at at least one of the exclude patterns.
  769. *
  770. * @see #slowScan
  771. */
  772. public String[] getExcludedFiles() {
  773. slowScan();
  774. int count = filesExcluded.size();
  775. String[] files = new String[count];
  776. for (int i = 0; i < count; i++) {
  777. files[i] = (String)filesExcluded.elementAt(i);
  778. }
  779. return files;
  780. }
  781. /**
  782. * <p>Returns the names of the files which were selected out and
  783. * therefore not ultimately included.</p>
  784. *
  785. * <p>The names are relative to the base directory. This involves
  786. * performing a slow scan if one has not already been completed.</p>
  787. *
  788. * @return the names of the files which were deselected.
  789. *
  790. * @see #slowScan
  791. */
  792. public String[] getDeselectedFiles() {
  793. slowScan();
  794. int count = filesDeselected.size();
  795. String[] files = new String[count];
  796. for (int i = 0; i < count; i++) {
  797. files[i] = (String)filesDeselected.elementAt(i);
  798. }
  799. return files;
  800. }
  801. /**
  802. * Returns the names of the directories which matched at least one of the
  803. * include patterns and none of the exclude patterns.
  804. * The names are relative to the base directory.
  805. *
  806. * @return the names of the directories which matched at least one of the
  807. * include patterns and none of the exclude patterns.
  808. */
  809. public String[] getIncludedDirectories() {
  810. int count = dirsIncluded.size();
  811. String[] directories = new String[count];
  812. for (int i = 0; i < count; i++) {
  813. directories[i] = (String)dirsIncluded.elementAt(i);
  814. }
  815. return directories;
  816. }
  817. /**
  818. * Returns the names of the directories which matched none of the include
  819. * patterns. The names are relative to the base directory. This involves
  820. * performing a slow scan if one has not already been completed.
  821. *
  822. * @return the names of the directories which matched none of the include
  823. * patterns.
  824. *
  825. * @see #slowScan
  826. */
  827. public String[] getNotIncludedDirectories() {
  828. slowScan();
  829. int count = dirsNotIncluded.size();
  830. String[] directories = new String[count];
  831. for (int i = 0; i < count; i++) {
  832. directories[i] = (String)dirsNotIncluded.elementAt(i);
  833. }
  834. return directories;
  835. }
  836. /**
  837. * Returns the names of the directories which matched at least one of the
  838. * include patterns and at least one of the exclude patterns.
  839. * The names are relative to the base directory. This involves
  840. * performing a slow scan if one has not already been completed.
  841. *
  842. * @return the names of the directories which matched at least one of the
  843. * include patterns and at least one of the exclude patterns.
  844. *
  845. * @see #slowScan
  846. */
  847. public String[] getExcludedDirectories() {
  848. slowScan();
  849. int count = dirsExcluded.size();
  850. String[] directories = new String[count];
  851. for (int i = 0; i < count; i++) {
  852. directories[i] = (String)dirsExcluded.elementAt(i);
  853. }
  854. return directories;
  855. }
  856. /**
  857. * <p>Returns the names of the directories which were selected out and
  858. * therefore not ultimately included.</p>
  859. *
  860. * <p>The names are relative to the base directory. This involves
  861. * performing a slow scan if one has not already been completed.</p>
  862. *
  863. * @return the names of the directories which were deselected.
  864. *
  865. * @see #slowScan
  866. */
  867. public String[] getDeselectedDirectories() {
  868. slowScan();
  869. int count = dirsDeselected.size();
  870. String[] directories = new String[count];
  871. for (int i = 0; i < count; i++) {
  872. directories[i] = (String)dirsDeselected.elementAt(i);
  873. }
  874. return directories;
  875. }
  876. /**
  877. * Adds default exclusions to the current exclusions set.
  878. */
  879. public void addDefaultExcludes() {
  880. int excludesLength = excludes == null ? 0 : excludes.length;
  881. String[] newExcludes;
  882. newExcludes = new String[excludesLength + DEFAULTEXCLUDES.length];
  883. if (excludesLength > 0) {
  884. System.arraycopy(excludes, 0, newExcludes, 0, excludesLength);
  885. }
  886. for (int i = 0; i < DEFAULTEXCLUDES.length; i++) {
  887. newExcludes[i + excludesLength] = DEFAULTEXCLUDES[i].replace('/',
  888. File.separatorChar).replace('\\', File.separatorChar);
  889. }
  890. excludes = newExcludes;
  891. }
  892. }