/*
* Copyright (c) 1998-2011 Caucho Technology -- all rights reserved
*
* This file is part of Resin(R) Open Source
*
* Each copy or derived work must preserve the copyright notice and this
* notice unmodified.
*
* Resin Open Source is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* Resin Open Source 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, or any warranty
* of NON-INFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with Resin Open Source; if not, write to the
*
* Free Software Foundation, Inc.
* 59 Temple Place, Suite 330
* Boston, MA 02111-1307 USA
*
* @author Scott Ferguson
*/
package javax.faces;
import java.lang.reflect.*;
import java.util.*;
import java.util.logging.*;
import javax.faces.application.*;
import javax.faces.context.*;
import javax.faces.lifecycle.*;
import javax.faces.render.*;
public final class FactoryFinder
{
private static final Logger log
= Logger.getLogger(FactoryFinder.class.getName());
public static final String APPLICATION_FACTORY
= "javax.faces.application.ApplicationFactory";
public static final String FACES_CONTEXT_FACTORY
= "javax.faces.context.FacesContextFactory";
public static final String LIFECYCLE_FACTORY
= "javax.faces.lifecycle.LifecycleFactory";
public static final String RENDER_KIT_FACTORY
= "javax.faces.render.RenderKitFactory";
private static final HashMap<String,Class> _factoryClassMap
= new HashMap<String,Class>();
private static final
WeakHashMap<ClassLoader,HashMap<String,String>> _factoryNameMap
= new WeakHashMap<ClassLoader,HashMap<String,String>>();
private static final
WeakHashMap<ClassLoader,HashMap<String,Object>> _factoryMap
= new WeakHashMap<ClassLoader,HashMap<String,Object>>();
FactoryFinder(){
}
public static Object getFactory(String factoryName)
{
if (factoryName == null)
throw new NullPointerException();
Class factoryClass = _factoryClassMap.get(factoryName);
if (factoryClass == null)
throw new IllegalArgumentException(factoryName + " is an unknown JSF factory");
Thread thread = Thread.currentThread();
ClassLoader loader = thread.getContextClassLoader();
synchronized (_factoryNameMap) {
HashMap<String,Object> objMap = _factoryMap.get(loader);
if (objMap != null) {
Object factory = objMap.get(factoryName);
if (factory != null)
return factory;
}
String className = null;
HashMap<String,String> nameMap = _factoryNameMap.get(loader);
if (nameMap != null) {
className = nameMap.get(factoryName);
}
Object factory = null;
if (className != null)
factory = createFactory(className, factoryClass, factory, loader);
if (factory == null)
throw new FacesException("No factory found for " + factoryName);
if (objMap == null) {
objMap = new HashMap<String,Object>();
_factoryMap.put(loader, objMap);
}
objMap.put(factoryName, factory);
return factory;
}
}
public static void setFactory(String factoryName, String implName)
{
if (log.isLoggable(Level.FINER))
log.finer("FactoryFinder[] setting '" + factoryName + "' to implementation '" + implName + "'");
Class factoryClass = _factoryClassMap.get(factoryName);
if (factoryClass == null)
throw new IllegalArgumentException(factoryName + " is an unknown JSF factory");
Thread thread = Thread.currentThread();
ClassLoader loader = thread.getContextClassLoader();
synchronized (_factoryNameMap) {
HashMap<String,Object> objectMap = _factoryMap.get(loader);
if (objectMap == null) {
objectMap = new HashMap<String,Object>();
_factoryMap.put(loader, objectMap);
}
Object oldFactory = objectMap.get(factoryName);
if (oldFactory == null)
oldFactory = _factoryMap.get(factoryName);
HashMap<String,String> map = _factoryNameMap.get(loader);
if (map == null) {
map = new HashMap<String,String>();
_factoryNameMap.put(loader, map);
}
map.put(factoryName, implName);
Object factory = createFactory(implName, factoryClass, oldFactory,
loader);
if (factory == null)
throw new FacesException("No factory found for " + factoryName);
objectMap.put(factoryName, factory);
}
}
public static void releaseFactories()
throws FacesException
{
ClassLoader loader = Thread.currentThread().getContextClassLoader();
synchronized (_factoryNameMap) {
_factoryMap.remove(loader);
_factoryNameMap.remove(loader);
}
}
private static Object createFactory(String className,
Class factoryClass,
Object previous,
ClassLoader loader)
throws FacesException
{
if (className == null)
return previous;
try {
Class cl = Class.forName(className, false, loader);
if (! factoryClass.isAssignableFrom(cl))
throw new FacesException(className + " is not assignable to " + factoryClass.getName());
Constructor ctor0 = null;
Constructor ctor1 = null;
try {
ctor0 = cl.getConstructor(new Class[] { });
} catch (Exception e) {
log.log(Level.FINEST, e.toString(), e);
}
try {
ctor1 = cl.getConstructor(new Class[] { factoryClass });
} catch (Exception e) {
log.log(Level.FINEST, e.toString(), e);
}
Object obj;
if (ctor1 == null)
obj = cl.newInstance();
else if (previous != null)
obj = ctor1.newInstance(previous);
else if (ctor0 != null)
obj = cl.newInstance();
else
obj = ctor1.newInstance(new Object[1]);
return obj;
} catch (ClassNotFoundException e) {
throw new FacesException(e);
} catch (InstantiationException e) {
throw new FacesException(e);
} catch (InvocationTargetException e) {
throw new FacesException(e);
} catch (IllegalAccessException e) {
throw new FacesException(e);
}
}
static {
_factoryClassMap.put(APPLICATION_FACTORY, ApplicationFactory.class);
_factoryClassMap.put(FACES_CONTEXT_FACTORY, FacesContextFactory.class);
_factoryClassMap.put(LIFECYCLE_FACTORY, LifecycleFactory.class);
_factoryClassMap.put(RENDER_KIT_FACTORY, RenderKitFactory.class);
}
}