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 java.io.IOException;
020import java.io.InputStream;
021import java.util.ArrayList;
022import java.util.Arrays;
023import java.util.Iterator;
024import java.util.List;
025import java.util.NoSuchElementException;
026
027/**
028 * @version $Rev$ $Date$
029 */
030public class CompositeArchive implements Archive {
031
032    private final List<Archive> archives = new ArrayList<Archive>();
033
034    public CompositeArchive(Archive... archives) {
035        this(Arrays.asList(archives));
036    }
037
038    public CompositeArchive(Iterable<Archive> archives) {
039        for (Archive archive : archives) {
040            this.archives.add(archive);
041        }
042    }
043
044    public InputStream getBytecode(String className) throws IOException, ClassNotFoundException {
045        for (Archive archive : archives) {
046            try {
047                return archive.getBytecode(className);
048            } catch (ClassNotFoundException e) {
049            }
050        }
051
052        throw new ClassNotFoundException(className);
053    }
054
055    public Class<?> loadClass(String className) throws ClassNotFoundException {
056        for (Archive archive : archives) {
057            try {
058                return archive.loadClass(className);
059            } catch (ClassNotFoundException e) {
060            }
061        }
062
063        throw new ClassNotFoundException(className);
064    }
065
066    public Iterator<Entry> iterator() {
067        if (archives.size() == 1) return archives.get(0).iterator();
068        return new CompositeIterator(archives);
069    }
070
071    private static class CompositeIterator implements Iterator<Entry> {
072
073        private Iterator<Archive> archives;
074        private Iterator<Entry> current;
075
076        private CompositeIterator(Iterable<Archive> archives) {
077            this.archives = archives.iterator();
078            if (this.archives.hasNext()) {
079                current = this.archives.next().iterator();
080            }
081        }
082
083        public boolean hasNext() {
084            if (current == null) return false;
085            if (current.hasNext()) return true;
086            
087            if (archives.hasNext()) {
088                current = archives.next().iterator();
089                return hasNext();
090            }
091            return false;
092        }
093
094        public Entry next() {
095            if (!hasNext()) throw new NoSuchElementException();
096
097            return current.next();
098        }
099
100        public void remove() {
101            throw new UnsupportedOperationException();
102        }
103    }
104}