    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        if (log.isDebugEnabled())
    070        {
    071            log.debug("Class Fragment is " + name);
    072        }
    073
    074        if (StringUtils.isNotEmpty(name))
    075        {
    076            for (String p : packages)
    077            {
    078                StringBuilder sb = new StringBuilder();
    079
    080                sb.append(p).append('.').append(packageName).append('.').append(name);
    081                String className = sb.toString();
    082
    083                if (log.isDebugEnabled())
    084                {
    085                    log.debug("Trying " + className);
    086                }
    087
    088                try
    089                {
    090                    Class<T> servClass = classCache.get(className);
    091                    if (servClass == null)
    092                    {
    093                        servClass = (Class<T>) Class.forName(className);
    094                        Class<T> _servClass = classCache.putIfAbsent(className, servClass);
    095                        if (_servClass != null)
    096                        {
    097                            servClass = _servClass;
    098                        }
    099                    }
    100                    assembler = servClass.newInstance();
    101                    break; // for()
    102                }
    103                catch (ClassNotFoundException cnfe)
    104                {
    105                    // Do this so we loop through all the packages.
    106                    log.debug(className + ": Not found");
    107                }
    108                catch (NoClassDefFoundError ncdfe)
    109                {
    110                    // Do this so we loop through all the packages.
    111                    log.debug(className + ": No Class Definition found");
    112                }
    113                catch (ClassCastException cce)
    114                {
    115                    // This means trouble!
    116                    // Alternatively we can throw this exception so
    117                    // that it will appear on the client browser
    118                    log.error("Could not load "+className, cce);
    119                    break; // for()
    120                }
    121                catch (InstantiationException ine)
    122                {
    123                    // This means trouble!
    124                    // Alternatively we can throw this exception so
    125                    // that it will appear on the client browser
    126                    log.error("Could not load "+className, ine);
    127                    break; // for()
    128                }
    129                catch (IllegalAccessException ilae)
    130                {
    131                    // This means trouble!
    132                    // Alternatively we can throw this exception so
    133                    // that it will appear on the client browser
    134                    log.error("Could not load "+className, ilae);
    135                    break; // for()
    136                }
    137                // With ClassCastException, InstantiationException we hit big problems
    138            }
    139        }
    140
    141        if (log.isDebugEnabled())
    142        {
    143            log.debug("Returning: " + assembler);
    144        }
    145
    146        return assembler;
    147    }
    148
    149    /**
    150     * Get the loader for this type of assembler
    151     *
    152     * @return a Loader
    153     */
    154    @Override
    155    public abstract Loader<T> getLoader();
    156
    157    /**
    158     * Get the size of a possibly configured cache
    159     *
    160     * @return the size of the cache in bytes
    161     */
    162    @Override
    163    public int getCacheSize()
    164    {
    165        return getLoader().getCacheSize();
    166    }
    167}