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.config.loader.ConfigurationLoader; 026import de.novanic.eventservice.config.loader.PropertyConfigurationLoader; 027import de.novanic.eventservice.config.loader.DefaultConfigurationLoader; 028import de.novanic.eventservice.config.level.ConfigLevel; 029import de.novanic.eventservice.config.level.ConfigLevelFactory; 030 031import java.util.*; 032import java.util.concurrent.ConcurrentLinkedQueue; 033 034/** 035 * EventServiceConfigurationFactory can be used to create an instance of {@link EventServiceConfiguration}. There a 036 * various {@link de.novanic.eventservice.config.loader.ConfigurationLoader} strategies to initilize the configuration. 037 * {@link de.novanic.eventservice.config.loader.DefaultConfigurationLoader} is used at last, when no configuration could 038 * be found. 039 * 040 * <br><br> 041 * There are three pre-registered ConfigurationLoaders at various levels. 042 * <br> 1) Level {@link de.novanic.eventservice.config.level.ConfigLevelFactory#DEFAULT} (5000) - {@link de.novanic.eventservice.config.loader.PropertyConfigurationLoader} 043 * <br> 2) Level {@link de.novanic.eventservice.config.level.ConfigLevelFactory#DEFAULT} (5000) - {@link de.novanic.eventservice.config.loader.WebDescriptorConfigurationLoader} 044 * <br> 3) Level {@link de.novanic.eventservice.config.level.ConfigLevelFactory#HIGHEST} (10000) - {@link de.novanic.eventservice.config.loader.DefaultConfigurationLoader} 045 * <br> 046 * <br> That means when a property file is in the classpath, the property file is used for the configuration. When no property file is available, 047 * the web-descriptor is used. When no servlet-parameters are registered in the web-descriptor, the default configuration is used. 048 * To manipulate that sequence and to register custom configuration loaders {@link EventServiceConfigurationFactory#addConfigurationLoader(de.novanic.eventservice.config.level.ConfigLevel, de.novanic.eventservice.config.loader.ConfigurationLoader)} 049 * and other modifier methods of that class can be used. 050 * 051 * @author sstrohschein 052 * <br>Date: 23.10.2008 053 * <br>Time: 14:36:49 054 */ 055public class EventServiceConfigurationFactory 056{ 057 private final Map<ConfigLevel, Queue<ConfigurationLoader>> myConfigurationLoaders; 058 059 /** 060 * The EventServiceConfigurationFactory should be created via the getInstance method. 061 * @see EventServiceConfigurationFactory#getInstance() 062 */ 063 private EventServiceConfigurationFactory() { 064 myConfigurationLoaders = new TreeMap<ConfigLevel, Queue<ConfigurationLoader>>(); 065 initConfigurationLoaders(); 066 } 067 068 /** 069 * Factory-Holder class to ensure thread-safe lazy-loading with IODH. 070 */ 071 private static class EventServiceConfigurationFactoryHolder { 072 private static EventServiceConfigurationFactory INSTANCE = new EventServiceConfigurationFactory(); 073 } 074 075 /** 076 * This method should be used to create an instance of EventServiceConfigurationFactory. 077 * EventServiceConfigurationFactory is a singleton, so this method returns always the same instance of EventServiceConfigurationFactory. 078 * @return EventServiceConfigurationFactory (singleton) 079 */ 080 public static EventServiceConfigurationFactory getInstance() { 081 return EventServiceConfigurationFactoryHolder.INSTANCE; 082 } 083 084 /** 085 * Loads the {@link de.novanic.eventservice.config.EventServiceConfiguration} with various 086 * {@link de.novanic.eventservice.config.loader.ConfigurationLoader} strategies. 087 * @param aPropertyName properties file if another properties file is preferred as the default properties file" 088 * (see description of {@link de.novanic.eventservice.config.loader.PropertyConfigurationLoader}). 089 * The returned configurations get enriched with default values when the parameters / options aren't configured. 090 * @return the configuration ({@link de.novanic.eventservice.config.EventServiceConfiguration}) 091 * @throws ConfigurationException thrown when a configuration is available, but can't be loaded 092 */ 093 public EventServiceConfiguration loadEventServiceConfiguration(String aPropertyName) { 094 replaceConfigurationLoader(ConfigLevelFactory.DEFAULT, new PropertyConfigurationLoader(aPropertyName)); 095 initConfigurationLoaders(); 096 return loadEventServiceConfiguration(); 097 } 098 099 /** 100 * Loads the {@link de.novanic.eventservice.config.EventServiceConfiguration} with various 101 * {@link de.novanic.eventservice.config.loader.ConfigurationLoader} strategies. The returned configurations 102 * get enriched with default values when the parameters / options aren't configured. 103 * @return the configuration ({@link de.novanic.eventservice.config.EventServiceConfiguration}) 104 * @throws de.novanic.eventservice.client.config.ConfigurationException thrown when a configuration is available, but can't be loaded 105 */ 106 public EventServiceConfiguration loadEventServiceConfiguration() { 107 for(Queue<ConfigurationLoader> theConfigLoaders: myConfigurationLoaders.values()) { 108 for(ConfigurationLoader theConfigLoader: theConfigLoaders) { 109 if(theConfigLoader.isAvailable()) { 110 return enrich(theConfigLoader.load()); 111 } 112 } 113 } 114 //can not occur, because the DefaultConfigurationLoader is attached and always available 115 throw new ConfigurationException("No configuration is available!"); 116 } 117 118 /** 119 * Adds a custom {@link de.novanic.eventservice.config.loader.ConfigurationLoader} (in the queue before the default 120 * configuration loaders). 121 * @param aConfigurationLoader custom {@link de.novanic.eventservice.config.loader.ConfigurationLoader} 122 */ 123 public void addCustomConfigurationLoader(ConfigurationLoader aConfigurationLoader) { 124 addConfigurationLoader(ConfigLevelFactory.LOWEST, aConfigurationLoader); 125 } 126 127 /** 128 * Adds a {@link de.novanic.eventservice.config.loader.ConfigurationLoader} (in the queue before the default 129 * configuration loaders). 130 * @param aLevel {@link de.novanic.eventservice.config.level.ConfigLevel} to specify the priority/level for the {@link de.novanic.eventservice.config.loader.ConfigurationLoader} 131 * @param aConfigurationLoader custom {@link de.novanic.eventservice.config.loader.ConfigurationLoader} 132 */ 133 public void addConfigurationLoader(ConfigLevel aLevel, ConfigurationLoader aConfigurationLoader) { 134 Queue<ConfigurationLoader> theConfigLoaders = myConfigurationLoaders.get(aLevel); 135 if(theConfigLoaders == null) { 136 theConfigLoaders = new ConcurrentLinkedQueue<ConfigurationLoader>(); 137 myConfigurationLoaders.put(aLevel, theConfigLoaders); 138 } 139 theConfigLoaders.add(aConfigurationLoader); 140 } 141 142 /** 143 * Removes a {@link de.novanic.eventservice.config.loader.ConfigurationLoader}. 144 * @param aConfigurationLoader {@link de.novanic.eventservice.config.loader.ConfigurationLoader} to remove from the queue 145 */ 146 public void removeConfigurationLoader(ConfigurationLoader aConfigurationLoader) { 147 for(Queue<ConfigurationLoader> theConfigLoaders: myConfigurationLoaders.values()) { 148 theConfigLoaders.remove(aConfigurationLoader); 149 } 150 } 151 152 /** 153 * Replaces a configuration loader at the specified configuration level. 154 * @param aLevel configuration level to search the {@link de.novanic.eventservice.config.loader.ConfigurationLoader} 155 * @param aConfigurationLoader {@link de.novanic.eventservice.config.loader.ConfigurationLoader} to add 156 */ 157 public void replaceConfigurationLoader(ConfigLevel aLevel, ConfigurationLoader aConfigurationLoader) { 158 removeConfigurationLoader(aConfigurationLoader); 159 addConfigurationLoader(aLevel, aConfigurationLoader); 160 } 161 162 /** 163 * Initializes and registers the pre-definied ConfigurationLoaders ({@link de.novanic.eventservice.config.loader.ConfigurationLoader}). 164 * See the class description of {@link de.novanic.eventservice.config.EventServiceConfigurationFactory} for more information. 165 */ 166 private void initConfigurationLoaders() { 167 replaceConfigurationLoader(ConfigLevelFactory.DEFAULT, new PropertyConfigurationLoader()); 168 replaceConfigurationLoader(ConfigLevelFactory.HIGHEST, new DefaultConfigurationLoader()); 169 } 170 171 /** 172 * The configuration will be enriched with default values, when no values are contained for the parameters. 173 * @param aConfiguration configuration to enrich 174 * @return the enriched configuration 175 */ 176 private EventServiceConfiguration enrich(EventServiceConfiguration aConfiguration) { 177 final EventServiceConfiguration theDefaultConfiguration = new DefaultConfigurationLoader().load(); 178 final Map<ConfigParameter, Object> theDefaultConfigMap = theDefaultConfiguration.getConfigMap(); 179 180 for(Map.Entry<ConfigParameter, Object> theConfigEntry: aConfiguration.getConfigMap().entrySet()) { 181 Object theValue = theConfigEntry.getValue(); 182 if(theValue == null) { 183 theConfigEntry.setValue(theDefaultConfigMap.get(theConfigEntry.getKey())); 184 } 185 } 186 187 return aConfiguration; 188 } 189}