001/*
002 * (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     bstefanescu
018 */
019package org.nuxeo.osgi.util;
020
021import java.io.File;
022import java.io.FileFilter;
023import java.net.MalformedURLException;
024import java.net.URL;
025import java.util.Enumeration;
026import java.util.Iterator;
027import java.util.LinkedList;
028import java.util.NoSuchElementException;
029import java.util.Queue;
030
031/**
032 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
033 */
034public class FileIterator implements Iterator<File>, Enumeration<File> {
035
036    protected FileFilter filter;
037
038    protected Queue<File> files;
039
040    protected File file;
041
042    protected boolean skipDirs = false;
043
044    public static Iterator<URL> asUrlIterator(final Iterator<File> it) {
045        return new Iterator<URL>() {
046            @Override
047            public boolean hasNext() {
048                return it.hasNext();
049            }
050
051            @Override
052            public URL next() {
053                try {
054                    return it.next().toURI().toURL();
055                } catch (MalformedURLException e) {
056                    throw new RuntimeException(e);
057                }
058            }
059
060            @Override
061            public void remove() {
062                it.remove();
063            }
064        };
065    }
066
067    public static Enumeration<URL> asUrlEnumeration(final Iterator<File> it) {
068        return new Enumeration<URL>() {
069            @Override
070            public boolean hasMoreElements() {
071                return it.hasNext();
072            }
073
074            @Override
075            public URL nextElement() {
076                try {
077                    return it.next().toURI().toURL();
078                } catch (MalformedURLException e) {
079                    throw new RuntimeException(e);
080                }
081            }
082        };
083    }
084
085    public FileIterator(File file) {
086        this(file, null);
087    }
088
089    public FileIterator(File file, FileFilter filter) {
090        this.files = new LinkedList<File>();
091        this.filter = filter;
092        feed(file);
093    }
094
095    public void setSkipDirs(boolean skipDirs) {
096        this.skipDirs = skipDirs;
097    }
098
099    public boolean getSkipDirs() {
100        return skipDirs;
101    }
102
103    @Override
104    public boolean hasNext() {
105        if (file != null) {
106            return true;
107        }
108        file = files.poll();
109        if (file == null) {
110            return false;
111        }
112        if (skipDirs) { // feed and get next file
113            while (file != null && file.isDirectory()) {
114                feed(file);
115                file = files.poll();
116            }
117        } else {
118            feed(file);
119        }
120        return file != null;
121    }
122
123    @Override
124    public File next() {
125        if (file == null) {
126            hasNext();
127            if (file == null) {
128                throw new NoSuchElementException();
129            }
130        }
131        File f = file;
132        file = null;
133        return f;
134    }
135
136    @Override
137    public void remove() {
138        throw new UnsupportedOperationException("remove ot supported");
139    }
140
141    /**
142     * Feed the iterator with the given directory content if any
143     *
144     * @param file
145     */
146    public void feed(File file) {
147        File[] content = file.listFiles(filter);
148        if (content != null) {
149            for (File f : content) {
150                files.add(f);
151            }
152        }
153    }
154
155    /** Enumeration API */
156
157    @Override
158    public boolean hasMoreElements() {
159        return hasNext();
160    }
161
162    @Override
163    public File nextElement() {
164        return next();
165    }
166
167}