Java tutorial
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; } }