All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.day.util.FileExpander Maven / Gradle / Ivy

There is a newer version: 2024.11.18598.20241113T125352Z-241000
Show 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);
	}
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy