001/* 002 * GWTEventService 003 * Copyright (c) 2011 and beyond, strawbill UG (haftungsbeschränkt) 004 * 005 * This is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU Lesser General Public License as 007 * published by the Free Software Foundation; either version 3 of 008 * the License, or (at your option) any later version. 009 * Other licensing for GWTEventService may also be possible on request. 010 * Please view the license.txt of the project for more information. 011 * 012 * This software is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * You should have received a copy of the GNU Lesser General Public 018 * License along with this software; if not, write to the Free 019 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 020 * 02110-1301 USA, or see the FSF site: http://www.fsf.org. 021 */ 022package de.novanic.eventservice.config; 023 024import de.novanic.eventservice.client.config.ConfigurationException; 025import de.novanic.eventservice.service.connection.id.ConnectionIdGenerator; 026import de.novanic.eventservice.service.connection.strategy.connector.ConnectionStrategyServerConnector; 027 028import java.lang.reflect.Constructor; 029import java.lang.reflect.InvocationTargetException; 030 031/** 032 * The {@link de.novanic.eventservice.config.ConfigurationDependentFactory} can create instances from a configuration 033 * which can be configured with a class name (for example {@link de.novanic.eventservice.config.ConfigParameter#CONNECTION_ID_GENERATOR}. 034 * The created instances are hold as a singleton. 035 * 036 * @author sstrohschein 037 * <br>Date: 05.04.2010 038 * <br>Time: 13:55:51 039 */ 040public final class ConfigurationDependentFactory 041{ 042 private static EventServiceConfiguration myConfiguration; 043 044 private ConnectionIdGenerator myConnectionIdGenerator; 045 private ConnectionStrategyServerConnector myConnectionStrategyServerConnector; 046 047 /** 048 * Initializes the {@link de.novanic.eventservice.config.ConfigurationDependentFactory}. That constructor is only called one time, 049 * because the factory is created as a singleton. 050 */ 051 private ConfigurationDependentFactory() {} 052 053 /** 054 * Factory-Holder class to ensure thread-safe lazy-loading with IODH. 055 */ 056 private static class ConfigurationDependentFactoryHolder { 057 private static ConfigurationDependentFactory INSTANCE = new ConfigurationDependentFactory(); 058 } 059 060 /** 061 * This method should be used to create an instance of {@link de.novanic.eventservice.config.ConfigurationDependentFactory}. 062 * {@link de.novanic.eventservice.config.ConfigurationDependentFactory} is a singleton, so this method returns always the same instance of 063 * {@link de.novanic.eventservice.config.ConfigurationDependentFactory}. This method initializes the factory with a configuration and should be 064 * called before {@link ConfigurationDependentFactory#getInstance()} is used, because it has to be initialized with 065 * with a configuration at first. 066 * @return {@link de.novanic.eventservice.config.ConfigurationDependentFactory} (singleton) 067 */ 068 public static ConfigurationDependentFactory getInstance(EventServiceConfiguration aConfiguration) { 069 if(aConfiguration == null) { 070 throw new ConfigurationException(ConfigurationDependentFactory.class.getName() + " was initialized without a configuration!"); 071 } 072 if(myConfiguration == null) { 073 myConfiguration = aConfiguration; 074 } 075 return ConfigurationDependentFactoryHolder.INSTANCE; 076 } 077 078 /** 079 * This method returns the {@link de.novanic.eventservice.config.ConfigurationDependentFactory} as a singleton. It has to be initialized 080 * with a configuration at first. Therefore the method {@link de.novanic.eventservice.config.ConfigurationDependentFactory#getInstance(EventServiceConfiguration)} should 081 * be used at first. 082 * @return {@link de.novanic.eventservice.config.ConfigurationDependentFactory} (singleton) 083 */ 084 public static ConfigurationDependentFactory getInstance() { 085 if(myConfiguration == null) { 086 throw new ConfigurationException(ConfigurationDependentFactory.class.getName() + " has to be initialized with a configuration before!"); 087 } 088 return ConfigurationDependentFactoryHolder.INSTANCE; 089 } 090 091 /** 092 * Returns the configured {@link de.novanic.eventservice.service.connection.id.ConnectionIdGenerator}. 093 * @see de.novanic.eventservice.config.ConfigParameter#CONNECTION_ID_GENERATOR 094 * @return the configured {@link de.novanic.eventservice.service.connection.id.ConnectionIdGenerator} 095 */ 096 public ConnectionIdGenerator getConnectionIdGenerator() { 097 if(myConnectionIdGenerator == null) { 098 synchronized(this) { 099 if(myConnectionIdGenerator == null) { 100 try { 101 myConnectionIdGenerator = createObject(myConfiguration.getConnectionIdGeneratorClassName()); 102 } catch(ClassCastException e) { 103 throw new ConfigurationException(myConfiguration.getConnectionIdGeneratorClassName() + " should have another type!", e); 104 } 105 } 106 } 107 } 108 return myConnectionIdGenerator; 109 } 110 111 /** 112 * Returns the server side part / connector of the configured connection strategy. 113 * @see de.novanic.eventservice.config.ConfigParameter#CONNECTION_STRATEGY_SERVER_CONNECTOR 114 * @return server side part / connector of the configured connection strategy 115 */ 116 public ConnectionStrategyServerConnector getConnectionStrategyServerConnector() { 117 if(myConnectionStrategyServerConnector == null) { 118 synchronized(this) { 119 if(myConnectionStrategyServerConnector == null) { 120 try { 121 myConnectionStrategyServerConnector = createObject(myConfiguration.getConnectionStrategyServerConnectorClassName()); 122 } catch(ClassCastException e) { 123 throw new ConfigurationException(myConfiguration.getConnectionStrategyServerConnectorClassName() + " should have another type!", e); 124 } 125 } 126 } 127 } 128 return myConnectionStrategyServerConnector; 129 } 130 131 /** 132 * Creates and initializes an object of a specific type. 133 */ 134 @SuppressWarnings("unchecked") 135 private static <T> T createObject(String aClassName) { 136 //when no class is configured, no object is created 137 if(aClassName == null) { 138 return null; 139 } 140 141 try { 142 final Class theConnectionIdGeneratorClass = Class.forName(aClassName); 143 144 Constructor<T> theDefaultConstructor = null; 145 for(Constructor<T> theConstructor: theConnectionIdGeneratorClass.getDeclaredConstructors()) { 146 Class<?>[] theParameterTypes = theConstructor.getParameterTypes(); 147 switch(theParameterTypes.length) { 148 case 0: 149 theDefaultConstructor = theConstructor; 150 break; 151 case 1: 152 if(theParameterTypes[0].equals(EventServiceConfiguration.class)) { 153 return theConstructor.newInstance(myConfiguration); 154 } 155 } 156 } 157 158 if(theDefaultConstructor == null) { 159 throw new ConfigurationException("The class \"" + theConnectionIdGeneratorClass + "\" has no default constructor and no constructor which requires a single configuration! At least one of both is needed!"); 160 } 161 return theDefaultConstructor.newInstance(); 162 } catch(ClassNotFoundException e) { 163 throw new ConfigurationException(aClassName + " couldn't be instantiated!", e); 164 } catch(InstantiationException e) { 165 throw new ConfigurationException(aClassName + " couldn't be instantiated!", e); 166 } catch(IllegalAccessException e) { 167 throw new ConfigurationException(aClassName + " couldn't be instantiated!", e); 168 } catch(InvocationTargetException e) { 169 throw new ConfigurationException(aClassName + " couldn't be instantiated!", e); 170 } 171 } 172 173 /** 174 * Returns the configuration which was specified with the initialization of the {@link de.novanic.eventservice.config.ConfigurationDependentFactory}. 175 * @see {@link ConfigurationDependentFactory#getInstance(EventServiceConfiguration)} 176 * @return configuration which was specified with the initialization of the {@link de.novanic.eventservice.config.ConfigurationDependentFactory} 177 */ 178 public static EventServiceConfiguration getConfiguration() { 179 return myConfiguration; 180 } 181 182 public static void reset() { 183 myConfiguration = null; 184 ConfigurationDependentFactoryHolder.INSTANCE.myConnectionIdGenerator = null; 185 ConfigurationDependentFactoryHolder.INSTANCE.myConnectionStrategyServerConnector = null; 186 } 187}