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     */
017    package org.apache.xbean.finder.archive;
018    
019    import java.io.IOException;
020    import java.io.InputStream;
021    import java.net.URL;
022    import java.util.Arrays;
023    import java.util.Iterator;
024    import java.util.LinkedHashMap;
025    import java.util.LinkedHashSet;
026    import java.util.Map;
027    import java.util.Set;
028    
029    /**
030     * @version $Rev$ $Date$
031     */
032    public class ClassesArchive implements Archive {
033    
034        private final Set<ClassLoader> loaders = new LinkedHashSet<ClassLoader>();
035        private final Map<String, Class<?>> classes = new LinkedHashMap<String, Class<?>>();
036    
037        public ClassesArchive(Class<?>... classes) {
038            this(Arrays.asList(classes));
039        }
040    
041        public ClassesArchive(Iterable<Class<?>> classes) {
042            assert classes != null;
043    
044            for (Class<?> clazz : classes) {
045                if (clazz == null) continue;
046                if (clazz.getClassLoader() == null) continue;
047                this.classes.put(clazz.getName(), clazz);
048                loaders.add(clazz.getClassLoader());
049            }
050        }
051    
052        @Override
053        public Iterator<String> iterator() {
054            return classes.keySet().iterator();
055        }
056    
057        @Override
058        public InputStream getBytecode(String className) throws IOException, ClassNotFoundException {
059            assert className != null;
060    
061            int pos = className.indexOf("<");
062            if (pos > -1) {
063                className = className.substring(0, pos);
064            }
065            pos = className.indexOf(">");
066            if (pos > -1) {
067                className = className.substring(0, pos);
068            }
069            if (!className.endsWith(".class")) {
070                className = className.replace('.', '/') + ".class";
071            }
072            for (ClassLoader loader : loaders) {
073                URL resource = loader.getResource(className);
074                if (resource != null) return resource.openStream();
075            }
076    
077            throw new ClassNotFoundException(className);
078        }
079    
080        @Override
081        public Class<?> loadClass(String className) throws ClassNotFoundException {
082            Class<?> clazz = classes.get(className);
083            if (clazz != null) return clazz;
084    
085            for (ClassLoader loader : loaders) {
086                try {
087                    return loader.loadClass(className);
088                } catch (ClassNotFoundException e) {
089                }
090            }
091    
092            throw new ClassNotFoundException(className);
093        }
094    }