001    /*
002     * Copyright 2002-2004 The Apache Software Foundation
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    package org.apache.commons.clazz.common;
017    
018    import java.lang.reflect.Constructor;
019    import java.util.ArrayList;
020    import java.util.List;
021    
022    import org.apache.commons.clazz.ClazzAccessException;
023    import org.apache.commons.clazz.ClazzLoader;
024    import org.apache.commons.clazz.ClazzLoaderFactory;
025    import org.apache.commons.clazz.ModelClazzLoader;
026    import org.apache.commons.collections.ReferenceMap;
027    
028    /**
029     * 
030     * @author <a href="mailto:dmitri@apache.org">Dmitri Plotnikov</a>
031     * @version $Id: ClazzLoaderFactorySupport.java 155436 2005-02-26 13:17:48Z dirkv $
032     */
033    public abstract class ClazzLoaderFactorySupport implements ClazzLoaderFactory {
034    
035        private List clazzLoaderClasses = new ArrayList();
036    
037        private ClazzLoader defaultClazzLoader;
038    
039        private ReferenceMap clazzLoaders =
040            new ReferenceMap(ReferenceMap.WEAK, ReferenceMap.HARD);
041    
042        /**
043         * Constructor for ClazzLoaderFactorySupport.
044         */
045        protected ClazzLoaderFactorySupport() {
046        }
047    
048        /**
049         * @see ClazzLoaderFactory#getClazzLoader(ClassLoader)
050         */
051        public synchronized ClazzLoader getClazzLoader(
052                ClassLoader contextClassLoader) 
053        {
054            if (contextClassLoader == null) {
055                if (defaultClazzLoader == null) {
056                    defaultClazzLoader = createClazzLoader(null);
057                }
058                return defaultClazzLoader;
059            }
060            else {
061                ClazzLoader loader =
062                    (ClazzLoader) clazzLoaders.get(contextClassLoader);
063                if (loader == null) {
064                    loader = createClazzLoader(contextClassLoader);
065                    clazzLoaders.put(contextClassLoader, loader);
066                }
067                return loader;
068            }
069        }
070    
071        protected ClazzLoader createClazzLoader(ClassLoader contextClassLoader) {
072            ModelClazzLoader modelClazzLoader =
073                new ModelClazzLoader(getClazzModel());
074    
075            for (int i = 0; i < clazzLoaderClasses.size(); i++) {
076                Class javaClass = (Class) clazzLoaderClasses.get(i);
077                ClazzLoader clazzLoader =
078                    allocateClazzLoader(
079                        modelClazzLoader,
080                        javaClass,
081                        contextClassLoader);
082                modelClazzLoader.addClazzLoader(clazzLoader);
083            }
084    
085            return modelClazzLoader;
086        }
087    
088        protected ClazzLoader allocateClazzLoader(
089            ModelClazzLoader modelClazzLoader,
090            Class javaClass,
091            ClassLoader contextClassLoader) 
092        {
093            try {
094                Constructor constructor = null;
095                try {
096                    constructor =
097                        javaClass.getConstructor(
098                            new Class[] {
099                                ModelClazzLoader.class,
100                                ClassLoader.class });
101                }
102                catch (NoSuchMethodException e) {
103                    // Won't happen
104                }
105                if (constructor != null) {
106                    return (ClazzLoader) constructor.newInstance(
107                        new Object[] { modelClazzLoader, contextClassLoader });
108                }
109    
110                try {
111                    constructor =
112                        javaClass.getConstructor(
113                            new Class[] { ModelClazzLoader.class });
114                }
115                catch (NoSuchMethodException e) {
116                    // Won't happen
117                }
118                if (constructor != null) {
119                    return (ClazzLoader) constructor.newInstance(
120                        new Object[] { modelClazzLoader });
121                }
122                throw new IllegalArgumentException("Missing constructor");
123            }
124            catch (Exception e) {
125                throw new ClazzAccessException(
126                    "Cannot allocate ClazzLoader " + javaClass.getName(),
127                    e);
128            }
129        }
130    
131        public void addClazzLoaderClass(Class clazzLoaderClass) {
132            clazzLoaderClasses.add(clazzLoaderClass);
133        }
134    }