org.richfaces.skin.SkinFactory.java Source code

Java tutorial

Introduction

Here is the source code for org.richfaces.skin.SkinFactory.java

Source

/**
 * License Agreement.
 *
 * Rich Faces - Natural Ajax for Java Server Faces (JSF)
 *
 * Copyright (C) 2007 Exadel, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1 as published by the Free Software Foundation.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
 */

package org.richfaces.skin;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import javax.faces.FacesException;
import javax.faces.context.FacesContext;

import org.ajax4jsf.Messages;
import org.ajax4jsf.resource.util.URLToStreamHelper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Base factory class ( implement Singleton design pattern ). Produce self
 * instance to build current skin configuration. At present, realised as lazy
 * creation factory. TODO - select point to initialize.
 * 
 * @author asmirnov@exadel.com (latest modification by $Author: alexsmirnov $)
 * @version $Revision: 1.1.2.1 $ $Date: 2007/01/09 18:59:43 $
 * 
 */
public abstract class SkinFactory {

    /**
     * static instance variable.
     */
    private static Map<ClassLoader, SkinFactory> instances = Collections
            .synchronizedMap(new HashMap<ClassLoader, SkinFactory>());

    private static final Log log = LogFactory.getLog(SkinFactory.class);

    public static void reset() {
        instances = Collections.synchronizedMap(new HashMap<ClassLoader, SkinFactory>());
    }

    /**
     * Initialize skin factory. TODO - make call from init() method of any
     * servlet or custom faces element method ??? If exist resource
     * META-INF/services/org.richfaces.skin.SkinFactory , create
     * instance of class by name from first line of this file. If such class
     * have constructor with {@link SkinFactory} parameter, instantiate it with
     * instance of default factory ( as usual in JSF ). If any error occurs in
     * instantiate custom factory, return default.
     */
    public static final SkinFactory getInstance() {
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        SkinFactory instance = (SkinFactory) instances.get(loader);
        if (instance == null) {
            // Pluggable factories.
            InputStream input = null; // loader.getResourceAsStream(SERVICE_RESOURCE);
            input = URLToStreamHelper.urlToStreamSafe(loader.getResource(SERVICE_RESOURCE));
            // have services file.
            if (input != null) {
                try {
                    BufferedReader reader = new BufferedReader(new InputStreamReader(input));
                    String factoryClassName = reader.readLine();
                    if (log.isDebugEnabled()) {
                        log.debug(Messages.getMessage(Messages.SET_SKIN_FACTORY_INFO, factoryClassName));
                    }
                    instance = instantiateSkinFactory(factoryClassName, loader);
                } catch (Exception e) {
                    log.warn(Messages.getMessage(Messages.CREATING_SKIN_FACTORY_ERROR), e);
                } finally {
                    try {
                        input.close();
                    } catch (IOException e) {
                        // can be ignored
                    }

                }
            }
            if (instance == null) {
                // instantiate default implementation of SkinFactory - org.richfaces.skin.SkinFactoryImpl,
                // placed in the richfaces-impl.jar
                instance = instantiateSkinFactory(DEFAULT_SKIN_FACTORY_IMPL_CLASS, loader);
            }
            instances.put(loader, instance);
        }

        return instance;
    }

    /**
     * Create new instance of class with given name with the help of given <code>ClassLoader</code>.
     * Instantiated class should extend <code>SkinFactory</code> base class.
     * @param factoryClassName - class name of SkinFactory
     * @param classLoader - class loader
     * @return - instantiated <code>SkinFactory</code>
     * @throws FacesException - FacesException is thrown when instantiation fails;
     *                          causing exception is wrapped into <code>FacesException</code>  
     */
    private static SkinFactory instantiateSkinFactory(String factoryClassName, ClassLoader classLoader)
            throws FacesException {
        SkinFactory instance = null;
        try {
            Class<?> clazz = Class.forName(factoryClassName, false, classLoader);
            try {
                // try construct factory chain.
                Constructor<?> factoryConstructor = clazz.getConstructor(new Class[] { SkinFactory.class });
                instance = (SkinFactory) factoryConstructor.newInstance(new Object[] { instance });
            } catch (NoSuchMethodException e) {
                // no chain constructor - attempt default.
                instance = (SkinFactory) clazz.newInstance();
            }
        } catch (InvocationTargetException ite) {
            log.error(Messages.getMessage(Messages.CREATING_SKIN_FACTORY_ERROR), ite);
            throw new FacesException("Exception when creating instance of [" + SkinFactory.class.getName() + "]",
                    ite);
        } catch (InstantiationException ie) {
            log.error(Messages.getMessage(Messages.CREATING_SKIN_FACTORY_ERROR), ie);
            throw new FacesException("Exception when creating instance of [" + SkinFactory.class.getName() + "]",
                    ie);
        } catch (IllegalAccessException iae) {
            log.error(Messages.getMessage(Messages.CREATING_SKIN_FACTORY_ERROR), iae);
            throw new FacesException("Exception when creating instance of [" + SkinFactory.class.getName() + "]",
                    iae);
        } catch (ClassNotFoundException cnfe) {
            log.error(Messages.getMessage(Messages.CREATING_SKIN_FACTORY_ERROR), cnfe);
            throw new FacesException("Exception when creating instance of [" + SkinFactory.class.getName() + "]",
                    cnfe);
        }

        return instance;
    }

    /**
     * Get default {@link Skin} implementation.
     * 
     * @param context
     * @return
     */
    public abstract Skin getDefaultSkin(FacesContext context);

    /**
     * Get current {@link Skin} implementation.
     * @param context
     * @return
     */
    public abstract Skin getSkin(FacesContext context);

    //   public abstract SkinConfiguration getSkinConfiguration(FacesContext context);

    /**
     * Resource Uri for file with name of class for application-wide SkinFactory same as SPI definitions for common Java SAX, Jsf etc. factories
     */
    public static final String SERVICE_RESOURCE = "META-INF/services/" + SkinFactory.class.getName();

    /**
     * Name of web application init parameter for current skin . Can be simple
     * String for non-modified name, or EL-expression for calculate current
     * skin. If EL evaluated to <code>String</code> - used as skin name, if to
     * instance of {@link Skin } - used this instance. by default -
     * "org.exadel.chameleon.SKIN"
     */
    public static final String SKIN_PARAMETER = "org.richfaces.SKIN";

    public static final String BASE_SKIN_PARAMETER = "org.richfaces.BASE_SKIN";

    /**
     * Full class name of default implementation of the SkinFactory class 
     */
    public static final String DEFAULT_SKIN_FACTORY_IMPL_CLASS = "org.richfaces.skin.SkinFactoryImpl";

    /**
     * Get base {@link Skin} implementation
     * @param facesContext
     * @return
     */
    public abstract Skin getBaseSkin(FacesContext facesContext);

    /**
     * @param facesContext
     * @param name
     * @return
     */
    public abstract Theme getTheme(FacesContext facesContext, String name);

}