001/**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *     http://www.apache.org/licenses/LICENSE-2.0
010 *
011 *  Unless required by applicable law or agreed to in writing, software
012 *  distributed under the License is distributed on an "AS IS" BASIS,
013 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 *  See the License for the specific language governing permissions and
015 *  limitations under the License.
016 */
017package org.apache.xbean.finder.archive;
018
019import org.apache.xbean.finder.filter.Filter;
020
021import java.io.IOException;
022import java.io.InputStream;
023import java.util.Iterator;
024import java.util.NoSuchElementException;
025
026/**
027 * @version $Rev$ $Date$
028 */
029public class FilteredArchive implements Archive, AutoCloseable{
030
031    private final Archive archive;
032
033    private final Filter filter;
034
035    public FilteredArchive(Archive archive, Filter filter) {
036        this.archive = archive;
037        this.filter = filter;
038    }
039
040    public InputStream getBytecode(String className) throws IOException, ClassNotFoundException {
041        return archive.getBytecode(className);
042    }
043
044    public Class<?> loadClass(String className) throws ClassNotFoundException {
045        return archive.loadClass(className);
046    }
047
048    public Iterator<Entry> iterator() {
049        return new FilteredIterator(archive.iterator());
050    }
051
052    @Override
053    public void close() throws Exception {
054        if (archive instanceof AutoCloseable) {
055            ((AutoCloseable) archive).close();
056        }
057    }
058
059    private final class FilteredIterator implements Iterator<Entry> {
060        private final Iterator<Entry> it;
061
062        private Entry next;
063
064        private FilteredIterator(Iterator<Entry> it) {
065            this.it = it;
066        }
067
068        public boolean hasNext() {
069            if (next != null) return true;
070            if (!it.hasNext()) return false;
071            seek();
072            return hasNext();
073        }
074
075        public Entry next() {
076            if (!hasNext()) throw new NoSuchElementException();
077
078            Entry s = next;
079            next = null;
080
081            return s;
082        }
083
084        public void remove() {
085            it.remove();
086        }
087
088        private void seek() {
089            while (next == null && it.hasNext()) {
090
091                next = it.next();
092
093                if (filter.accept(next.getName())) return;
094
095                next = null;
096            }
097        }
098
099    }
100}