/** * Test whether all contents of the specified directory must be excluded. * @param path the path to check. * @return whether all the specified directory's contents are excluded. */ /* package */ boolean contentsExcluded(final TokenizedPath path) { return Stream.of(excludePatterns) .filter(p -> p.endsWith(SelectorUtils.DEEP_TREE_MATCH)) .map(TokenizedPattern::withoutLastToken) .anyMatch(wlt -> wlt.matchPath(path, isCaseSensitive())); }
/** * Lists recursive files of this directory with pattern matching. * <p>The default implementation calls {@link #list()} recursively inside {@link #run} and applies filtering to the result. * Implementations may wish to override this more efficiently. * @param includes comma-separated Ant-style globs as per {@link Util#createFileSet(File, String, String)} using {@code /} as a path separator; * the empty string means <em>no matches</em> (use {@link SelectorUtils#DEEP_TREE_MATCH} if you want to match everything except some excludes) * @param excludes optional excludes in similar format to {@code includes} * @param useDefaultExcludes as per {@link AbstractFileSet#setDefaultexcludes} * @return a list of {@code /}-separated relative names of children (files directly inside or in subdirectories) * @throws IOException if this is not a directory, or listing was not possible for some other reason * @since 2.118 */ @Restricted(Beta.class) public @Nonnull Collection<String> list(@Nonnull String includes, @CheckForNull String excludes, boolean useDefaultExcludes) throws IOException { Collection<String> r = run(new CollectFiles(this)); List<TokenizedPattern> includePatterns = patterns(includes); List<TokenizedPattern> excludePatterns = patterns(excludes); if (useDefaultExcludes) { for (String patt : DirectoryScanner.getDefaultExcludes()) { excludePatterns.add(new TokenizedPattern(patt.replace('/', File.separatorChar))); } } return r.stream().filter(p -> { TokenizedPath path = new TokenizedPath(p.replace('/', File.separatorChar)); return includePatterns.stream().anyMatch(patt -> patt.matchPath(path, true)) && !excludePatterns.stream().anyMatch(patt -> patt.matchPath(path, true)); }).collect(Collectors.toSet()); } private static final class CollectFiles extends MasterToSlaveCallable<Collection<String>, IOException> {
/** * Test whether or not a name matches against at least one exclude * pattern. * * @param name The name to match. Must not be <code>null</code>. * @return <code>true</code> when the name matches against at least one * exclude pattern, or <code>false</code> otherwise. */ private boolean isExcluded(final TokenizedPath name) { ensureNonPatternSetsReady(); String toMatch = name.toString(); if (!isCaseSensitive()) { toMatch = toMatch.toUpperCase(); } return excludeNonPatterns.containsKey(toMatch) || Stream.of(excludePatterns).anyMatch(p -> p.matchPath(name, isCaseSensitive())); }
/** * Test whether or not a name matches against at least one include * pattern. * * @param path The tokenized path to match. Must not be <code>null</code>. * @return <code>true</code> when the name matches against at least one * include pattern, or <code>false</code> otherwise. */ private boolean isIncluded(final TokenizedPath path) { ensureNonPatternSetsReady(); String toMatch = path.toString(); if (!isCaseSensitive()) { toMatch = toMatch.toUpperCase(); } return includeNonPatterns.containsKey(toMatch) || Stream.of(includePatterns).anyMatch(p -> p.matchPath(path, isCaseSensitive())); }