de.fhg.iais.commons.fs.FileSystemScanner.java Source code

Java tutorial

Introduction

Here is the source code for de.fhg.iais.commons.fs.FileSystemScanner.java

Source

package de.fhg.iais.commons.fs;

/******************************************************************************
 * Copyright 2011 (c) Fraunhofer IAIS Netmedia  http://www.iais.fraunhofer.de *
 * ************************************************************************** *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may    *
 * not use this file except in compliance with the License.                   *
 * You may obtain a copy of the License at                                    *
 * http://www.apache.org/licenses/LICENSE-2.0                                 *
 * Unless required by applicable law or agreed to in writing,                 *
 * software distributed under the License is distributed on an "AS IS" BASIS, *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
 * See the License for the specific language governing permissions and        *
 * limitations under the License.                                             *
 ******************************************************************************/

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Der FileSystemScanner traversiert durch das Dateisystem. Um ihn nutzen zu koennen, muss ein andere Klasse
 * (die aufrufende Klasse) zumindest eine der Schnittstellen {@link FileEventListener} oder {@link DirectoryEventListener} implementieren.
 * 
 * @author ks
 * @since Donnerstag, 4. Mai 2001 01:04:12
 */
public final class FileSystemScanner {

    private static final Logger LOGGER = LoggerFactory.getLogger(FileSystemScanner.class);

    private static final boolean DOWNSORT = false;

    private File startPath = null;
    private boolean recursive = true;
    private FolderEventListener onDir = null;
    //    private static final String FILESEPARATOR = System.getProperty("file.separator");
    private Pattern[] patterns = null;

    //    private int startPathLength = 0; // unused variable

    /** Enthaelt die Listener */
    private final List<FileEventListener> fileEventListener = new ArrayList<FileEventListener>();

    private static final Comparator<File> UPSORT = new Comparator<File>() {
        @Override
        public int compare(File o1, File o2) {
            return o1.getName().compareTo(o2.getName());
        }
    };

    private static final Comparator<File> DOWNSORTCOMPARATOR = new Comparator<File>() {
        @Override
        public int compare(File o1, File o2) {
            return o2.getName().compareTo(o1.getName());
        }
    };

    //    public static void main(String[] args) {
    //        FolderLister folderLister = new FolderLister("/", 0, null); // , "/*.svn*,*/test*,*/lib*");
    //        System.out.println("\n" + join(folderLister.getFolders(), "\n")); //NOSONAR
    //    }

    private void expandFileMask(String[] in) {
        if (in == null) {
            return;
        }
        this.patterns = new Pattern[in.length];
        for (int i = 0; i < in.length; i++) {
            String p = in[i].toLowerCase(Locale.GERMAN);
            p = StringUtils.replace(p, ".", "\\.");
            p = StringUtils.replace(p, "?", ".?");
            p = StringUtils.replace(p, "*", ".*");
            this.patterns[i] = Pattern.compile(p);
        }
    }

    private void setPattern(String[] pattern) {
        expandFileMask(pattern);
    }

    private boolean patternAccept(File file) {
        if (this.patterns.length == 0) {
            return true;
        }
        String f = file.getName().toLowerCase(Locale.GERMAN);
        for (Pattern p : this.patterns) {
            if (p.matcher(f).matches()) {
                return true;
            }
        }
        return false;
    }

    public FileSystemScanner(FileFolderEventAdapter adapter) {
        if (adapter != null) {
            this.onDir = adapter;
            this.fileEventListener.add(adapter);
        }
    }

    private FileSystemScanner(FolderEventListener del) {
        this.onDir = del;
    }

    public FileSystemScanner(FileEventListener fel) {
        this.fileEventListener.add(fel);
    }

    public FileSystemScanner(FileEventListener fel, FolderEventListener del) {
        this.fileEventListener.add(fel);
        this.onDir = del;
    }

    public void startScan(File start, boolean recursive) {
        this.recursive = recursive;
        startScan(start);
    }

    public void startScan(String start, boolean recursive) {
        this.recursive = recursive;
        LOGGER.debug("Scanning {}", start);
        startScan(start);
    }

    private void startScan(final File start) {
        if (start != null) {
            this.startPath = start;
        } else {
            this.startPath = new File(".");
        }

        //        if ( this.startPath.getAbsolutePath().endsWith(FILESEPARATOR) ) {
        //            this.startPathLength = this.startPath.getAbsolutePath().length();
        //        } else {
        //            this.startPathLength = this.startPath.getAbsolutePath().length() + FILESEPARATOR.length();
        //        }
        if (this.patterns == null || this.patterns.length == 0) {
            rScanAll(this.startPath);
        } else {
            rscan(this.startPath);
        }
    }

    //    public File getRoot() {
    //        return this.startPath;
    //    }

    private void startScan(String start) {
        File f = new File(start == null ? "." : start);
        this.startPath = new File(f.getAbsolutePath());
        //        if ( start.endsWith(FILESEPARATOR) ) {
        //            this.startPathLength = this.startPath.getAbsolutePath().length();
        //        } else {
        //            this.startPathLength = this.startPath.getAbsolutePath().length() + FILESEPARATOR.length();
        //        }
        if (this.patterns == null || this.patterns.length == 0) {
            rScanAll(this.startPath);
        } else {
            rscan(this.startPath);
        }
    }

    private boolean rscan(File currentDir) {
        File[] fileList = currentDir.listFiles();
        if (fileList == null) {
            return true;
        }
        ArrayList<File> files = new ArrayList<File>();
        ArrayList<File> folders = new ArrayList<File>();
        for (File element : fileList) {
            if (element.isDirectory()) {
                folders.add(element);
            } else {
                files.add(element);
            }
        }
        // scan this folder
        Collections.sort(files, FileSystemScanner.DOWNSORT ? DOWNSORTCOMPARATOR : UPSORT);
        // tell listener what they should expect
        for (FileEventListener listener : this.fileEventListener) {
            listener.expect(files.size());
        }
        // operate listener on files
        for (File f : files) {
            for (FileEventListener currentListener : this.fileEventListener) {
                if (patternAccept(f) && currentListener.acceptFile(f) && currentListener.nextFile(f)) {
                    return true;
                }
            }
        }
        // scan folders recursively
        Collections.sort(folders, FileSystemScanner.DOWNSORT ? DOWNSORTCOMPARATOR : UPSORT);
        for (File f : folders) {
            if (this.onDir != null) {
                this.onDir.nextFolder(f);
            }
            if (this.recursive) {
                if (this.onDir != null) {
                    this.onDir.changeDown(f);
                }
                if (rscan(f)) {
                    return true;
                }
                if (this.onDir != null) {
                    this.onDir.changeUp(f);
                }
            }
        }
        return false;
    }

    private boolean rScanAll(File currentDir) {
        File[] fileList = currentDir.listFiles();
        if (fileList == null) {
            return true;
        }
        ArrayList<File> files = new ArrayList<File>();
        ArrayList<File> folders = new ArrayList<File>();
        for (File element : fileList) {
            if (element.isDirectory()) {
                folders.add(element);
            } else {
                files.add(element);
            }
        }
        // scan this folder
        Collections.sort(files, FileSystemScanner.DOWNSORT ? DOWNSORTCOMPARATOR : UPSORT);
        // tell listener what they should expect
        for (FileEventListener listener : this.fileEventListener) {
            listener.expect(files.size());
        }
        // operate listener on files
        for (File f : files) {
            for (FileEventListener currentListener : this.fileEventListener) {
                if (currentListener.acceptFile(f) && currentListener.nextFile(f)) {
                    return true;
                }
            }
        }
        // scan folders recursively
        Collections.sort(folders, FileSystemScanner.DOWNSORT ? DOWNSORTCOMPARATOR : UPSORT);
        for (File f : folders) {
            if (this.onDir != null) {
                this.onDir.nextFolder(f);
            }
            if (this.recursive) {
                if (this.onDir != null) {
                    this.onDir.changeDown(f);
                }
                if (rScanAll(f)) {
                    return true;
                }
                if (this.onDir != null) {
                    this.onDir.changeUp(f);
                }
            }
        }
        return false;
    }

    private static final class FolderLister implements FolderEventListener {
        private final List<File> folders = new ArrayList<File>();
        private final int depth;
        private int currentDepth = 0;
        private Pattern[] excludedPatterns = new Pattern[0];

        /**
         * Scan recursive, store folders in a given depth below root.
         * 
         * @param root
         * @param depth
         */
        private FolderLister(String root, int depth, String excludedPatterns) {
            this.depth = depth;
            String[] xp = split(excludedPatterns);
            if (xp != null) {
                this.excludedPatterns = new Pattern[xp.length];
                for (int i = 0; i < xp.length; i++) {
                    String p = xp[i].toLowerCase(Locale.GERMAN);
                    p = StringUtils.replace(p, ".", "\\.");
                    p = StringUtils.replace(p, "?", ".?");
                    p = StringUtils.replace(p, "*", ".*");
                    this.excludedPatterns[i] = Pattern.compile(p);
                }
            }
            FileSystemScanner fss = new FileSystemScanner(this);
            fss.setPattern(new String[] { "*.*" });
            fss.startScan(root, true);
        }

        private List<File> getFolders() {
            return this.folders;
        }

        @Override
        public void changeDown(File file) {
            this.currentDepth++;
        }

        @Override
        public void changeUp(File file) {
            this.currentDepth--;
        }

        @Override
        public boolean nextFolder(File file) {
            if (this.currentDepth == this.depth && isNotExcluded(file)) {
                this.folders.add(file);
            }
            return false;
        }

        private boolean isNotExcluded(File f) {
            String path = f.getAbsolutePath();
            for (Pattern p : this.excludedPatterns) {
                if (p.matcher(path).matches()) {
                    return false;
                }
            }
            return true;
        }
    } // ------------------------------- test ------------------------------//

    /*
     * Join a collection, build a string by concatenation of elements, separate elements by delimiter.
     */
    private static synchronized String join(List<?> s, String delim) {
        StringBuilder sb = new StringBuilder(Math.max(16, 40 * s.size()));
        Object[] m = s.toArray();
        if (m != null && m.length > 0) {
            sb.append(m[0]);
            for (int i = 1; i < m.length; i++) {
                sb.append(delim);
                sb.append(m[i]);
            }
        }
        String r = sb.toString();
        if (r.endsWith(delim)) {
            r = r.substring(0, r.length() - delim.length());
        }
        return (r);
    }

    private static synchronized String[] split(String commaSeparatedString) {
        if (commaSeparatedString == null) {
            return new String[] {};
        }
        String[] s = split(commaSeparatedString, ",", true);
        int j = 0, i = 0;
        for (; i < s.length; i++) {
            if (!empty(s[i])) {
                s[j++] = s[i];
            }
        }
        if (j == i) {
            return s;
        }
        String[] r = new String[j];
        System.arraycopy(s, 0, r, 0, j);
        return r;
    }

    private static synchronized String[] split(String s, String delim, boolean trimElements) {
        if (s == null) {
            return new String[0];
        }
        int pos, lastpos, count = 0, delimLen = delim.length();
        for (lastpos = 0, pos = s.indexOf(delim, lastpos); pos > -1; pos = s.indexOf(delim, lastpos)) {
            count++;
            lastpos = pos + delimLen;
        }
        String[] r = new String[count + 1];
        if (trimElements) {
            for (count = 0, lastpos = 0, pos = s.indexOf(delim, lastpos); pos > -1; pos = s.indexOf(delim,
                    lastpos)) {
                r[count++] = s.substring(lastpos, pos).trim();
                lastpos = pos + delimLen;
            }
            r[count] = s.substring(lastpos).trim();
        } else {
            for (count = 0, lastpos = 0, pos = s.indexOf(delim, lastpos); pos > -1; pos = s.indexOf(delim,
                    lastpos)) {
                r[count++] = s.substring(lastpos, pos);
                lastpos = pos + delimLen;
            }
            r[count] = s.substring(lastpos);
        }
        return r;
    }

    private static boolean empty(Object s) {
        return s == null || s.toString().trim().length() == 0;
    }

}