    001package org.apache.turbine.services.assemblerbroker.util.java;
    002
    003
    004/*
    005 * Licensed to the Apache Software Foundation (ASF) under one
    006 * or more contributor license agreements.  See the NOTICE file
    007 * distributed with this work for additional information
    008 * regarding copyright ownership.  The ASF licenses this file
    009 * to you under the Apache License, Version 2.0 (the
    010 * "License"); you may not use this file except in compliance
    011 * with the License.  You may obtain a copy of the License at
    012 *
    013 *   http://www.apache.org/licenses/LICENSE-2.0
    014 *
    015 * Unless required by applicable law or agreed to in writing,
    016 * software distributed under the License is distributed on an
    017 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    018 * KIND, either express or implied.  See the License for the
    019 * specific language governing permissions and limitations
    020 * under the License.
    021 */
    022
    023import java.util.List;
    024import java.util.concurrent.ConcurrentHashMap;
    025
    026import org.apache.commons.lang.StringUtils;
    027import org.apache.commons.logging.Log;
    028import org.apache.commons.logging.LogFactory;
    029import org.apache.turbine.modules.Assembler;
    030import org.apache.turbine.modules.GenericLoader;
    031import org.apache.turbine.modules.Loader;
    032import org.apache.turbine.services.assemblerbroker.util.AssemblerFactory;
    033
    034/**
    035 * A screen factory that attempts to load a java class from
    036 * the module packages defined in the TurbineResource.properties.
    037 *
    038 * @author <a href="mailto:leon@opticode.co.za">Leon Messerschmidt</a>
    039 * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
    040 * @param <T> the specialized assembler type
    041 */
    042public abstract class JavaBaseFactory<T extends Assembler>
    043    implements AssemblerFactory<T>
    044{
    045    /** A vector of packages. */
    046    private static List<String> packages = GenericLoader.getPackages();
    047
    048    /** Logging */
    049    protected Log log = LogFactory.getLog(this.getClass());
    050
    051    /**
    052     * A cache for previously obtained Class instances, which we keep in order
    053     * to reduce the Class.forName() overhead (which can be sizable).
    054     */
    055    private final ConcurrentHashMap<String, Class<T>> classCache = new ConcurrentHashMap<String, Class<T>>();
    056
    057    /**
    058     * Get an Assembler.
    059     *
    060     * @param packageName java package name
    061     * @param name name of the requested Assembler
    062     * @return an Assembler
    063     */
    064    @SuppressWarnings("unchecked")
    065    public T getAssembler(String packageName, String name)
    066    {
    067        T assembler = null;
    068
    069        log.debug("Class Fragment is " + name);
    070
    071        if (StringUtils.isNotEmpty(name))
    072        {
    073            for (String p : packages)
    074            {
    075                StringBuilder sb = new StringBuilder();
    076
    077                sb.append(p).append('.').append(packageName).append('.').append(name);
    078                String className = sb.toString();
    079
    080                log.debug("Trying " + className);
    081
    082                try
    083                {
    084                    Class<T> servClass = classCache.get(className);
    085                    if (servClass == null)
    086                    {
    087                        servClass = (Class<T>) Class.forName(className);
    088                        classCache.put(className, servClass);
    089                    }
    090                    assembler = servClass.newInstance();
    091                    break; // for()
    092                }
    093                catch (ClassNotFoundException cnfe)
    094                {
    095                    // Do this so we loop through all the packages.
    096                    log.debug(className + ": Not found");
    097                }
    098                catch (NoClassDefFoundError ncdfe)
    099                {
    100                    // Do this so we loop through all the packages.
    101                    log.debug(className + ": No Class Definition found");
    102                }
    103                catch (ClassCastException cce)
    104                {
    105                    // This means trouble!
    106                    // Alternatively we can throw this exception so
    107                    // that it will appear on the client browser
    108                    log.error("Could not load "+className, cce);
    109                    break; // for()
    110                }
    111                catch (InstantiationException ine)
    112                {
    113                    // This means trouble!
    114                    // Alternatively we can throw this exception so
    115                    // that it will appear on the client browser
    116                    log.error("Could not load "+className, ine);
    117                    break; // for()
    118                }
    119                catch (IllegalAccessException ilae)
    120                {
    121                    // This means trouble!
    122                    // Alternatively we can throw this exception so
    123                    // that it will appear on the client browser
    124                    log.error("Could not load "+className, ilae);
    125                    break; // for()
    126                }
    127                // With ClassCastException, InstantiationException we hit big problems
    128            }
    129        }
    130        log.debug("Returning: " + assembler);
    131
    132        return assembler;
    133    }
    134
    135    /**
    136     * Get the loader for this type of assembler
    137     *
    138     * @return a Loader
    139     */
    140    @Override
    141    public abstract Loader<T> getLoader();
    142
    143    /**
    144     * Get the size of a possibly configured cache
    145     *
    146     * @return the size of the cache in bytes
    147     */
    148    @Override
    149    public int getCacheSize()
    150    {
    151        return getLoader().getCacheSize();
    152    }
    153}