1 package net.sf.openrocket.file.iterator;
3 import java.io.BufferedInputStream;
5 import java.io.FileFilter;
6 import java.io.FileInputStream;
7 import java.io.IOException;
8 import java.io.InputStream;
11 import net.sf.openrocket.logging.LogHelper;
12 import net.sf.openrocket.startup.Application;
13 import net.sf.openrocket.util.JarUtil;
14 import net.sf.openrocket.util.Pair;
17 * A DirectoryIterator that scans for files within a directory in the file system
18 * matching a FileFilter. The scan is optionally recursive.
20 * @author Sampo Niskanen <sampo.niskanen@iki.fi>
22 public class DirectoryIterator extends FileIterator {
24 private static final LogHelper logger = Application.getLogger();
26 private final FileFilter filter;
27 private final File[] files;
28 private final boolean recursive;
29 private int position = 0;
30 private DirectoryIterator subIterator = null;
35 * @param directory the directory to read.
36 * @param filter the filter for selecting files.
37 * @throws IOException if the directory cannot be read.
39 public DirectoryIterator(File directory, FileFilter filter, boolean recursive)
43 this.recursive = recursive;
45 this.files = directory.listFiles(new DirSelectionFileFilter(filter, recursive));
46 if (this.files == null) {
47 throw new IOException("not a directory or IOException occurred when listing files " +
57 protected Pair<String, InputStream> findNext() {
59 // Check if we're recursing
60 if (subIterator != null) {
61 if (subIterator.hasNext()) {
62 return subIterator.next();
69 // Scan through file entries
70 while (position < files.length) {
71 File file = files[position];
75 if (recursive && file.isDirectory()) {
76 subIterator = new DirectoryIterator(file, filter, recursive);
77 if (subIterator.hasNext()) {
78 return subIterator.next();
86 InputStream is = new BufferedInputStream(new FileInputStream(file));
87 return new Pair<String, InputStream>(file.getName(), is);
88 } catch (IOException e) {
89 logger.warn("Error opening file/directory " + file, e);
98 * Return a DirectoryIterator for a directory that can be located either
99 * within the containing JAR file, in the classpath or in the current directory
100 * (searched in this order). The first place that contains matching files
101 * will be iterated through.
103 * @param directory the directory to search for.
104 * @param filter the filter for matching files in the directory.
105 * @return a DirectoryIterator for iterating through the files in the
106 * directory, or <code>null</code> if no directory containing
107 * matching files can be found.
109 public static FileIterator findDirectory(String directory, FileFilter filter) {
110 FileIterator iterator = null;
112 // Try to load from containing JAR file
113 File jarFile = JarUtil.getCurrentJarFile();
114 if (jarFile != null) {
116 iterator = new ZipDirectoryIterator(jarFile, directory, filter);
117 if (iterator.hasNext()) {
121 } catch (IOException e) {
122 logger.error("Error opening containing JAR file " + jarFile, e);
127 // Try to find directory as a system resource
128 URL url = ClassLoader.getSystemResource(directory);
131 File dir = JarUtil.urlToFile(url);
132 iterator = new DirectoryIterator(dir, filter, true);
133 if (iterator.hasNext()) {
137 } catch (Exception e1) {
138 logger.error("Error opening directory from URL " + url);
143 // Try to open directory as such
145 iterator = new DirectoryIterator(new File(directory), filter, true);
146 if (iterator.hasNext()) {
150 } catch (IOException e) {
151 logger.error("Error opening directory " + directory);
160 * A FileFilter wrapper that accepts or discards directories.
162 private class DirSelectionFileFilter implements FileFilter {
164 private final boolean acceptDirs;
165 private final FileFilter parentFilter;
168 public DirSelectionFileFilter(FileFilter filter, boolean acceptDirs) {
169 this.acceptDirs = acceptDirs;
170 this.parentFilter = filter;
175 public boolean accept(File pathname) {
176 if (pathname.getName().startsWith(".")) {
179 if (pathname.isDirectory()) {
182 return parentFilter.accept(pathname);