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.Arrays;
026import java.util.Enumeration;
027import java.util.Iterator;
028import java.util.LinkedList;
029import java.util.NoSuchElementException;
030import java.util.Queue;
031
032/**
033 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
034 */
035public class FileIterator implements Iterator<File>, Enumeration<File> {
036
037    protected FileFilter filter;
038
039    protected Queue<File> files;
040
041    protected File file;
042
043    protected boolean skipDirs = false;
044
045    public static Iterator<URL> asUrlIterator(final Iterator<File> it) {
046        return new Iterator<>() {
047            @Override
048            public boolean hasNext() {
049                return it.hasNext();
050            }
051
052            @Override
053            public URL next() {
054                try {
055                    return it.next().toURI().toURL();
056                } catch (MalformedURLException e) {
057                    throw new RuntimeException(e);
058                }
059            }
060
061            @Override
062            public void remove() {
063                it.remove();
064            }
065        };
066    }
067
068    public static Enumeration<URL> asUrlEnumeration(final Iterator<File> it) {
069        return new Enumeration<>() {
070            @Override
071            public boolean hasMoreElements() {
072                return it.hasNext();
073            }
074
075            @Override
076            public URL nextElement() {
077                try {
078                    return it.next().toURI().toURL();
079                } catch (MalformedURLException e) {
080                    throw new RuntimeException(e);
081                }
082            }
083        };
084    }
085
086    public FileIterator(File file) {
087        this(file, null);
088    }
089
090    public FileIterator(File file, FileFilter filter) {
091        this.files = new LinkedList<>();
092        this.filter = filter;
093        feed(file);
094    }
095
096    public void setSkipDirs(boolean skipDirs) {
097        this.skipDirs = skipDirs;
098    }
099
100    public boolean getSkipDirs() {
101        return skipDirs;
102    }
103
104    @Override
105    public boolean hasNext() {
106        if (file != null) {
107            return true;
108        }
109        file = files.poll();
110        if (file == null) {
111            return false;
112        }
113        if (skipDirs) { // feed and get next file
114            while (file != null && file.isDirectory()) {
115                feed(file);
116                file = files.poll();
117            }
118        } else {
119            feed(file);
120        }
121        return file != null;
122    }
123
124    @Override
125    public File next() {
126        if (file == null) {
127            hasNext();
128            if (file == null) {
129                throw new NoSuchElementException();
130            }
131        }
132        File f = file;
133        file = null;
134        return f;
135    }
136
137    @Override
138    public void remove() {
139        throw new UnsupportedOperationException("remove ot supported");
140    }
141
142    /**
143     * Feed the iterator with the given directory content if any
144     */
145    public void feed(File file) {
146        File[] content = file.listFiles(filter);
147        if (content != null) {
148            files.addAll(Arrays.asList(content));
149        }
150    }
151
152    /** Enumeration API */
153
154    @Override
155    public boolean hasMoreElements() {
156        return hasNext();
157    }
158
159    @Override
160    public File nextElement() {
161        return next();
162    }
163
164}