com.day.util.FileExpander Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aem-sdk-api Show documentation
Show all versions of aem-sdk-api Show documentation
The Adobe Experience Manager SDK
The newest version!
/*************************************************************************
* ADOBE CONFIDENTIAL
* __________________
*
* Copyright 2020 Adobe
* All Rights Reserved.
*
* NOTICE: All information contained herein is, and remains
* the property of Adobe and its suppliers, if any. The intellectual
* and technical concepts contained herein are proprietary to Adobe
* and its suppliers and are protected by all applicable intellectual
* property laws, including trade secret and copyright laws.
* Dissemination of this information or reproduction of this material
* is strictly forbidden unless prior written permission is obtained
* from Adobe.
**************************************************************************/
package com.day.util;
import java.io.File;
import java.io.FileFilter;
import java.util.ArrayList;
import java.util.List;
import com.day.text.GlobPattern;
/**
* The FileExpander
takes file names as input, expands them
* according to the globbing patterns and returns a list of file names.
*
* @version $Revision: 1.5 $, $Date: 2004-08-22 06:56:09 +0200 (Sun, 22 Aug 2004) $
* @author fmeschbe
* @since coati
* Audience wad
*/
public class FileExpander implements HandleExpander {
public static final BaseFilter RETURN_ALL = new BaseFilter("*");
public static final BaseFilter RETURN_FILES = new FileFileFilter("*");
public static final BaseFilter RETURN_DIRECTORIES = new DirectoryFileFilter("*");
private final File rootDirectory;
private final BaseFilter expandType;
public FileExpander() {
this.rootDirectory = null;
this.expandType = RETURN_FILES;
}
public FileExpander(String root, BaseFilter type) {
this(new File(root), type);
}
public FileExpander(File root, BaseFilter type) {
if (root.isFile()) {
root = root.getParentFile();
}
if (!root.isAbsolute()) {
root = root.getAbsoluteFile();
}
this.rootDirectory = root;
this.expandType = (type != null) ? type : RETURN_FILES;
}
/**
* Expands the file name pattern returning a list of file names matching
* to that pattern. This list will only contain names of real files
* regardless of whether a directory's name would match the pattern or not.
*
* @param pattern the pattern to match.
*
* @return A list of filenames matching the pattern
*
* @see GlobPattern for a description of the pattern format.
*/
public String[] expand(String pattern) {
// make sure the file separators are correct - not here actually ...
pattern = pattern.replace('/', File.separatorChar);
// check whether the pattern is considered absolute
File root = new File(pattern).isAbsolute() ? null : rootDirectory;
List result = traverse(new ArrayList(), root, pattern);
return (String[]) result.toArray(new String[result.size()]);
}
/**
* Recursively traverses the filesystem tree according to the rest parameter.
* The method starts working at the directory indicated by the directory
* parameter and takes the rest string as a globbing pattern to walk further
* down the tree.
*
* @param result The result list to append the result to.
* @param directory The directory to start walking down. May be
* null
to start at the root if rest is absolute or
* at the current working directory if rest is relative.
* @param rest The globbing pattern to be applied from the directory node
* downwards the tree.
*
* @return The list parameter.
*/
private List traverse(List result, File directory, String rest) {
// loop through the rest string
int end = rest.length();
for (int i=0; i < end; i++) {
char c = rest.charAt(i);
// if we stumbled upon a globbing character
if ("*?[]".indexOf(c) >= 0) {
// get the end of the fix part of the string
int lastSlash = rest.lastIndexOf(File.separatorChar, i);
// single part pattern, no subdirectory walk
if (lastSlash >= 0) {
String part;
//XXX hack thiz for absolute paths
if (lastSlash == 2 && rest.charAt(1) == ':') {
// for windose : the minimal part is drive letter,
// colon and first backslash, fix this up here
part = rest.substring(0, 3);
} else if (lastSlash == 0) {
// for unix : the minimal part is the first slash,
// fix this up here
part = rest.substring(0, 1);
} else {
part = rest.substring(0, lastSlash);
}
//XXX
directory = new File(directory, part);
}
// find the end of the globbing dir part
int nextSlash = rest.indexOf(File.separatorChar, i);
String pat;
if (nextSlash < 0) {
// this glob names the file
pat = rest.substring(lastSlash+1);
rest = null; // not really needed, for purity of concept :-)
// find the files and append to the list
File[] files = directory.listFiles(expandType.getInstance(pat));
if (files != null) {
for (int j=0; j < files.length; j++) {
result.add(files[j].getAbsolutePath());
}
}
} else {
// this glob is an intermediate directory
pat = rest.substring(lastSlash+1, nextSlash);
rest = rest.substring(nextSlash+1);
// find the files and append to the list
File[] dirs = directory.listFiles(new DirectoryFileFilter(pat));
if (dirs != null) {
for (int j=0; j < dirs.length; j++) {
traverse(result, dirs[j], rest);
}
}
}
return result;
}
}
// invariant : no pattern character found in the string
// create a file from the string
directory = new File(directory, rest);
// check that directory and add
if (directory.exists() && expandType.accept(directory)) {
result.add(directory.getAbsolutePath());
}
return result;
}
/**
* The BaseFilter
class is an abstract base class for the file
* and directory matcher class, which accepts files based on globbing
* patterns.
*
* @author fmeschbe
* @since coati
* Audience core
*/
public static class BaseFilter implements FileFilter {
private final GlobPattern glob;
BaseFilter(String pattern) {
this.glob = new GlobPattern(pattern.toLowerCase());
}
BaseFilter getInstance(String glob) {
return new BaseFilter(glob);
}
/**
* Returns true
if the name of the file matches the
* globbing pattern.
*/
public boolean accept(File pathname) {
return glob.matches(pathname.getName().toLowerCase());
}
}
/**
* The DirectoryFileFilter
extends the {@link BaseFilter}
* class by only accepting a File
if it denotes a directory.
*
* @author fmeschbe
* @since coati
* Audience core
*/
private static class DirectoryFileFilter extends BaseFilter {
/**
* Creates a DirectoryFileFilter
with the given pattern.
*/
DirectoryFileFilter(String pattern) {
super(pattern);
}
BaseFilter getInstance(String glob) {
return new DirectoryFileFilter(glob);
}
/**
* Returns true
if the name denotes a directory and matches
* the globbing pattern.
*/
public boolean accept(File pathname) {
return pathname.isDirectory() && super.accept(pathname);
}
}
/**
* The FileFileFilter
extends the {@link BaseFilter}
* class by only accepting a File
if it denotes a file.
*
* @author fmeschbe
* @since coati
* Audience core
*/
private static class FileFileFilter extends BaseFilter {
/**
* Creates a FileFileFilter
with the given pattern.
*/
FileFileFilter(String pattern) {
super(pattern);
}
BaseFilter getInstance(String glob) {
return new FileFileFilter(glob);
}
/**
* Returns true
if the name denotes a file and matches
* the globbing pattern.
*/
public boolean accept(File pathname) {
return pathname.isFile() && super.accept(pathname);
}
}
}