001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License version 2
011: * as published by the Free Software Foundation.
012: *
013: * Resin Open Source is distributed in the hope that it will be useful,
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
016: * of NON-INFRINGEMENT. See the GNU General Public License for more
017: * details.
018: *
019: * You should have received a copy of the GNU General Public License
020: * along with Resin Open Source; if not, write to the
021: *
022: * Free Software Foundation, Inc.
023: * 59 Temple Place, Suite 330
024: * Boston, MA 02111-1307 USA
025: *
026: * @author Scott Ferguson
027: */
028:
029: package javax.faces;
030:
031: import java.lang.reflect.*;
032: import java.io.*;
033: import java.util.*;
034: import java.util.logging.*;
035:
036: import javax.faces.application.*;
037: import javax.faces.context.*;
038: import javax.faces.lifecycle.*;
039: import javax.faces.render.*;
040:
041: public class FactoryFinder {
042: private static final Logger log = Logger
043: .getLogger(FactoryFinder.class.getName());
044:
045: public static final String APPLICATION_FACTORY = "javax.faces.application.ApplicationFactory";
046: public static final String FACES_CONTEXT_FACTORY = "javax.faces.context.FacesContextFactory";
047: public static final String LIFECYCLE_FACTORY = "javax.faces.lifecycle.LifecycleFactory";
048: public static final String RENDER_KIT_FACTORY = "javax.faces.render.RenderKitFactory";
049:
050: private static final HashMap<String, Class> _factoryClassMap = new HashMap<String, Class>();
051:
052: private static final WeakHashMap<ClassLoader, HashMap<String, String>> _factoryNameMap = new WeakHashMap<ClassLoader, HashMap<String, String>>();
053:
054: private static final WeakHashMap<ClassLoader, HashMap<String, Object>> _factoryMap = new WeakHashMap<ClassLoader, HashMap<String, Object>>();
055:
056: public static Object getFactory(String factoryName) {
057: if (factoryName == null)
058: throw new NullPointerException();
059:
060: Class factoryClass = _factoryClassMap.get(factoryName);
061:
062: if (factoryClass == null)
063: throw new IllegalArgumentException(factoryName
064: + " is an unknown JSF factory");
065:
066: Thread thread = Thread.currentThread();
067: ClassLoader loader = thread.getContextClassLoader();
068:
069: synchronized (_factoryNameMap) {
070: HashMap<String, Object> objMap = _factoryMap.get(loader);
071:
072: if (objMap != null) {
073: Object factory = objMap.get(factoryName);
074:
075: if (factory != null)
076: return factory;
077: }
078:
079: String className = null;
080:
081: HashMap<String, String> nameMap = _factoryNameMap
082: .get(loader);
083: if (nameMap != null) {
084: className = nameMap.get(factoryName);
085: }
086:
087: if (className == null)
088: className = getDefaultFactory(factoryName);
089:
090: Object factory = null;
091: if (className != null)
092: factory = createFactory(className, factoryClass,
093: factory, loader);
094:
095: if (factory == null)
096: throw new FacesException("No factory found for "
097: + factoryName);
098:
099: if (objMap == null) {
100: objMap = new HashMap<String, Object>();
101: _factoryMap.put(loader, objMap);
102: }
103:
104: objMap.put(factoryName, factory);
105:
106: return factory;
107: }
108: }
109:
110: public static void setFactory(String factoryName, String implName) {
111: if (log.isLoggable(Level.FINER))
112: log.finer("FactoryFinder[] setting '" + factoryName
113: + "' to implementation '" + implName + "'");
114:
115: Class factoryClass = _factoryClassMap.get(factoryName);
116:
117: if (factoryClass == null)
118: throw new IllegalArgumentException(factoryName
119: + " is an unknown JSF factory");
120:
121: Thread thread = Thread.currentThread();
122: ClassLoader loader = thread.getContextClassLoader();
123:
124: synchronized (_factoryNameMap) {
125: HashMap<String, Object> objectMap = _factoryMap.get(loader);
126:
127: if (objectMap == null) {
128: objectMap = new HashMap<String, Object>();
129: _factoryMap.put(loader, objectMap);
130: }
131:
132: Object oldFactory = objectMap.get(factoryName);
133:
134: if (oldFactory == null)
135: oldFactory = _factoryMap.get(factoryName);
136:
137: HashMap<String, String> map = _factoryNameMap.get(loader);
138:
139: if (map == null) {
140: map = new HashMap<String, String>();
141: _factoryNameMap.put(loader, map);
142: }
143:
144: map.put(factoryName, implName);
145:
146: Object factory = createFactory(implName, factoryClass,
147: oldFactory, loader);
148:
149: if (factory == null)
150: throw new FacesException("No factory found for "
151: + factoryName);
152:
153: objectMap.put(factoryName, factory);
154: }
155: }
156:
157: public static void releaseFactories() throws FacesException {
158: ClassLoader loader = Thread.currentThread()
159: .getContextClassLoader();
160:
161: synchronized (_factoryNameMap) {
162: _factoryMap.remove(loader);
163: _factoryNameMap.remove(loader);
164: }
165: }
166:
167: private static String getDefaultFactory(String factoryName) {
168: return null;
169: /*
170: if (APPLICATION_FACTORY.equals(factoryName))
171: return "com.caucho.jsf.application.ApplicationFactoryImpl";
172: else if (FACES_CONTEXT_FACTORY.equals(factoryName))
173: return "com.caucho.jsf.context.FacesContextFactoryImpl";
174: else if (LIFECYCLE_FACTORY.equals(factoryName))
175: return "com.caucho.jsf.lifecycle.LifecycleFactoryImpl";
176: else if (RENDER_KIT_FACTORY.equals(factoryName))
177: return "com.caucho.jsf.render.RenderKitFactoryImpl";
178: else
179: return null;
180: */
181: }
182:
183: private static Object createFactory(String className,
184: Class factoryClass, Object previous, ClassLoader loader)
185: throws FacesException {
186: if (className == null)
187: return previous;
188:
189: try {
190: Class cl = Class.forName(className, false, loader);
191:
192: if (!factoryClass.isAssignableFrom(cl))
193: throw new FacesException(className
194: + " is not assignable to "
195: + factoryClass.getName());
196:
197: Constructor ctor0 = null;
198: Constructor ctor1 = null;
199:
200: try {
201: ctor0 = cl.getConstructor(new Class[] {});
202: } catch (Exception e) {
203: log.log(Level.FINEST, e.toString(), e);
204: }
205:
206: try {
207: ctor1 = cl.getConstructor(new Class[] { factoryClass });
208: } catch (Exception e) {
209: log.log(Level.FINEST, e.toString(), e);
210: }
211:
212: Object obj;
213:
214: if (ctor1 == null)
215: obj = cl.newInstance();
216: else if (previous != null)
217: obj = ctor1.newInstance(previous);
218: else if (ctor0 != null)
219: obj = cl.newInstance();
220: else
221: obj = ctor1.newInstance(new Object[1]);
222:
223: return obj;
224: } catch (ClassNotFoundException e) {
225: throw new FacesException(e);
226: } catch (InstantiationException e) {
227: throw new FacesException(e);
228: } catch (InvocationTargetException e) {
229: throw new FacesException(e);
230: } catch (IllegalAccessException e) {
231: throw new FacesException(e);
232: }
233: }
234:
235: static {
236: _factoryClassMap.put(APPLICATION_FACTORY,
237: ApplicationFactory.class);
238: _factoryClassMap.put(FACES_CONTEXT_FACTORY,
239: FacesContextFactory.class);
240: _factoryClassMap.put(LIFECYCLE_FACTORY, LifecycleFactory.class);
241: _factoryClassMap
242: .put(RENDER_KIT_FACTORY, RenderKitFactory.class);
243: }
244: }
|