156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson/* 256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * Copyright (C) 2010 Google Inc. 356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * 456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * Licensed under the Apache License, Version 2.0 (the "License"); 556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * you may not use this file except in compliance with the License. 656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * You may obtain a copy of the License at 756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * 856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * http://www.apache.org/licenses/LICENSE-2.0 956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * 1056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * Unless required by applicable law or agreed to in writing, software 1156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * distributed under the License is distributed on an "AS IS" BASIS, 1256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * See the License for the specific language governing permissions and 1456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * limitations under the License. 1556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson */ 1656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 1756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonpackage org.clearsilver; 1856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 1956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport java.lang.reflect.Constructor; 2056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport java.util.concurrent.locks.ReadWriteLock; 2156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport java.util.concurrent.locks.ReentrantReadWriteLock; 2256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport java.util.logging.Level; 2356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonimport java.util.logging.Logger; 2456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 2556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson/** 2656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * This class holds static methods for getting and setting the CS and HDF 2756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * factory used throughout the Java Clearsilver Framework. 2856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * Clients are <strong>strongly encouraged</strong> to not use this class, and 2956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * instead directly inject {@link ClearsilverFactory} into the classes that 3056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * need to create {@link HDF} and {@link CS} instances. 3156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * For now, projects should set the {@link ClearsilverFactory} in FactoryLoader 3256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * and use the singleton accessor {@link #getClearsilverFactory()} if proper 3356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * dependency injection is not easy to implement. 3456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * <p> 3556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * Allows the default implementation to be the original JNI version without 3656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * requiring users that don't want to use the JNI version to have to link 3756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * it in. The ClearsilverFactory object to use can be either passed into the 3856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * {@link #setClearsilverFactory} method or the class name can be specified 3956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * in the Java property {@code org.clearsilver.defaultClearsilverFactory}. 4056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson */ 4156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodsonpublic final class FactoryLoader { 4256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson private static final Logger logger = 4356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson Logger.getLogger(FactoryLoader.class.getName()); 4456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 4556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson private static final String DEFAULT_CS_FACTORY_CLASS_PROPERTY_NAME = 4656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson "org.clearsilver.defaultClearsilverFactory"; 4756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson private static final String DEFAULT_CS_FACTORY_CLASS_NAME = 4856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson "org.clearsilver.jni.JniClearsilverFactory"; 4956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 5056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson // ClearsilverFactory to be used when constructing objects. Allows 5156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson // applications to subclass the CS and HDF objects used in Java Clearsilver 5256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson private static ClearsilverFactory clearsilverFactory = null; 5356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 5456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson // Read/Write lock for global factory pointer. 5556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson private static final ReadWriteLock factoryLock = new ReentrantReadWriteLock(); 5656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 5756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson // Getters and setters 5856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson /** 5956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * Get the {@link org.clearsilver.ClearsilverFactory} object to be used by 6056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * disparate parts of the application. 6156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson */ 6256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public static ClearsilverFactory getClearsilverFactory() { 6356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson factoryLock.readLock().lock(); 6456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (clearsilverFactory == null) { 6556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson factoryLock.readLock().unlock(); 6656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson factoryLock.writeLock().lock(); 6756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson try { 6856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson if (clearsilverFactory == null) { 6956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson clearsilverFactory = newDefaultClearsilverFactory(); 7056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 7156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson factoryLock.readLock().lock(); 7256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } finally { 7356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson factoryLock.writeLock().unlock(); 7456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 7556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 7656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson ClearsilverFactory returned = clearsilverFactory; 7756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson factoryLock.readLock().unlock(); 7856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return returned; 7956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 8056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 8156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson /** 8256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * Set the {@link org.clearsilver.ClearsilverFactory} to be used by 8356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * the application. If parameter is {@code null}, then the default factory 8456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * implementation will be used the next time {@link #getClearsilverFactory()} 8556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * is called. 8656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * 8756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson * @return the previous factory (may return {@code null}) 8856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson */ 8956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson public static ClearsilverFactory setClearsilverFactory( 9056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson ClearsilverFactory clearsilverFactory) { 9156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson factoryLock.writeLock().lock(); 9256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson try { 9356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson ClearsilverFactory previousFactory = FactoryLoader.clearsilverFactory; 9456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson FactoryLoader.clearsilverFactory = clearsilverFactory; 9556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return previousFactory; 9656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } finally { 9756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson factoryLock.writeLock().unlock(); 9856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 9956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 10056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 10156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson private static ClearsilverFactory newDefaultClearsilverFactory() { 10256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson String factoryClassName = 10356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson System.getProperty(DEFAULT_CS_FACTORY_CLASS_PROPERTY_NAME, 10456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson DEFAULT_CS_FACTORY_CLASS_NAME); 10556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson try { 10656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); 10756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson Class<ClearsilverFactory> clazz = 10856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson loadClass(factoryClassName, classLoader); 10956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson Constructor<ClearsilverFactory> constructor = clazz.getConstructor(); 11056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return constructor.newInstance(); 11156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } catch (Exception e) { 11256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson String errMsg = "Unable to load default ClearsilverFactory class: \"" + 11356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson factoryClassName + "\""; 11456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson logger.log(Level.SEVERE, errMsg, e); 11556ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson throw new RuntimeException(errMsg, e); 11656ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 11756ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 11856ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson 11956ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson private static Class<ClearsilverFactory> loadClass(String className, 12056ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson ClassLoader classLoader) throws ClassNotFoundException { 12156ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson return (Class<ClearsilverFactory>) Class.forName(className, true, 12256ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson classLoader); 12356ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson } 12456ed4167b942ec265f9cee70ac4d71d10b3835ceBen Dodson} 125