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.loader; 023 024import de.novanic.eventservice.client.config.ConfigurationException; 025import de.novanic.eventservice.config.EventServiceConfiguration; 026import de.novanic.eventservice.config.RemoteEventServiceConfiguration; 027import de.novanic.eventservice.config.ConfigParameter; 028import de.novanic.eventservice.logger.ServerLogger; 029import de.novanic.eventservice.logger.ServerLoggerFactory; 030 031import java.util.Properties; 032import java.util.Scanner; 033import java.io.InputStream; 034import java.io.IOException; 035 036/** 037 * PropertyConfigurationLoader is used by {@link de.novanic.eventservice.config.EventServiceConfigurationFactory} 038 * to load the {@link de.novanic.eventservice.config.EventServiceConfiguration} with a properties file. 039 * The default name of the properties is "eventservice.properties". For that file will be searched if not other defined. 040 * 041 * @author sstrohschein 042 * <br>Date: 23.10.2008 043 * <br>Time: 14:37:13 044 */ 045public class PropertyConfigurationLoader implements ConfigurationLoader 046{ 047 private static final ServerLogger LOG = ServerLoggerFactory.getServerLogger(PropertyConfigurationLoader.class.getName()); 048 private static final String DEFAULT_PROPERTY_NAME = "eventservice.properties"; 049 050 private final String myPropertyName; 051 052 /** 053 * Creates a {@link PropertyConfigurationLoader} with the default properties ("eventservice.properties"). 054 */ 055 public PropertyConfigurationLoader() { 056 this(null); 057 } 058 059 /** 060 * Creates a {@link PropertyConfigurationLoader} with a properties file. 061 * @param aPropertyName properties file to load (the location must be attached to the classpath) 062 */ 063 public PropertyConfigurationLoader(String aPropertyName) { 064 if(aPropertyName != null) { 065 myPropertyName = aPropertyName; 066 } else { 067 myPropertyName = DEFAULT_PROPERTY_NAME; 068 } 069 } 070 071 /** 072 * Checks if the configuration is available and can be loaded. If no configuration is available, the load method 073 * {@link ConfigurationLoader#load()} shouldn't called. In the case of {@link PropertyConfigurationLoader} the method 074 * returns true when the location of the properties file is attached to the classpath. 075 * @return true when available, otherwise false 076 */ 077 public boolean isAvailable() { 078 return getPropertiesStream() != null; 079 } 080 081 /** 082 * Loads the configuration with the loader. 083 * @return {@link de.novanic.eventservice.config.EventServiceConfiguration} the loaded configuration or NULL if the 084 * properties file couldn't found with the classpath. 085 * @throws ConfigurationException occurs when the configuration can't be loaded or if it contains unreadable values. 086 */ 087 public EventServiceConfiguration load() { 088 InputStream thePropertiesInputStream = getPropertiesStream(); 089 if(thePropertiesInputStream != null) { 090 try { 091 Properties theProperties = new Properties(); 092 theProperties.load(thePropertiesInputStream); 093 return load(theProperties); 094 } catch(IOException e) { 095 throw new ConfigurationException("Error on loading \"" + myPropertyName + "\"!", e); 096 } finally { 097 try { 098 thePropertiesInputStream.close(); 099 } catch(IOException e) { 100 LOG.error("Error on closing stream of \"" + myPropertyName + "\"!", e); 101 } 102 } 103 } 104 return null; 105 } 106 107 /** 108 * Returns the properties file as a stream ({@link java.io.InputStream}). 109 * @return properties file as a stream ({@link java.io.InputStream}) 110 */ 111 private InputStream getPropertiesStream() { 112 return Thread.currentThread().getContextClassLoader().getResourceAsStream(myPropertyName); 113 } 114 115 /** 116 * Loads the {@link de.novanic.eventservice.config.EventServiceConfiguration} with the values of the properties file. 117 * @param aProperties properties to initialize the {@link de.novanic.eventservice.config.EventServiceConfiguration} 118 * @return initialized {@link de.novanic.eventservice.config.EventServiceConfiguration} 119 * @throws ConfigurationException thrown when the values aren't parsable to an integer 120 */ 121 private EventServiceConfiguration load(Properties aProperties) { 122 final Integer theMaxWaitingTime = getIntValue(getPropertyValue(aProperties, ConfigParameter.FQ_MAX_WAITING_TIME_TAG, ConfigParameter.MAX_WAITING_TIME_TAG)); 123 final Integer theMinWaitingTime = getIntValue(getPropertyValue(aProperties, ConfigParameter.FQ_MIN_WAITING_TIME_TAG, ConfigParameter.MIN_WAITING_TIME_TAG)); 124 final Integer theTimeoutTime = getIntValue(getPropertyValue(aProperties, ConfigParameter.FQ_TIMEOUT_TIME_TAG, ConfigParameter.TIMEOUT_TIME_TAG)); 125 final Integer theReconnectAttemptCount = getIntValue(getPropertyValue(aProperties, ConfigParameter.FQ_RECONNECT_ATTEMPT_COUNT_TAG, ConfigParameter.RECONNECT_ATTEMPT_COUNT_TAG)); 126 final String theConnectionIdGenerator = getPropertyValue(aProperties, ConfigParameter.FQ_CONNECTION_ID_GENERATOR, ConfigParameter.CONNECTION_ID_GENERATOR); 127 final String theConnectionStrategyClientConnector = getPropertyValue(aProperties, ConfigParameter.FQ_CONNECTION_STRATEGY_CLIENT_CONNECTOR, ConfigParameter.CONNECTION_STRATEGY_CLIENT_CONNECTOR); 128 final String theConnectionStrategyServerConnector = getPropertyValue(aProperties, ConfigParameter.FQ_CONNECTION_STRATEGY_SERVER_CONNECTOR, ConfigParameter.CONNECTION_STRATEGY_SERVER_CONNECTOR); 129 final String theConnectionStrategyEncoding = getPropertyValue(aProperties, ConfigParameter.FQ_CONNECTION_STRATEGY_ENCODING, ConfigParameter.CONNECTION_STRATEGY_ENCODING); 130 final Integer theMaxEvents = getIntValue(getPropertyValue(aProperties, ConfigParameter.FQ_MAX_EVENTS, ConfigParameter.MAX_EVENTS)); 131 132 return new RemoteEventServiceConfiguration(getConfigDescription(), theMinWaitingTime, theMaxWaitingTime, theTimeoutTime, 133 theReconnectAttemptCount, 134 theConnectionIdGenerator, theConnectionStrategyClientConnector, theConnectionStrategyServerConnector, theConnectionStrategyEncoding, 135 theMaxEvents); 136 } 137 138 /** 139 * Parses the integer value from a {@link String}. 140 * @param aString {@link String} to parse the integer values 141 * @return integer value which is contained in the {@link String} 142 * @throws de.novanic.eventservice.client.config.ConfigurationException thrown when the {@link String} values isn't parsable to an integer value 143 */ 144 private Integer getIntValue(String aString) { 145 if(aString != null) { 146 Scanner theScanner = new Scanner(aString); 147 if(theScanner.hasNextInt()) { 148 return theScanner.nextInt(); 149 } else { 150 throw new ConfigurationException("Error on processing configuration \"" + myPropertyName + "\"! " + 151 "The value \"" + aString + "\" couldn't parsed to an integer!"); 152 } 153 } 154 return null; 155 } 156 157 /** 158 * Returns the description of the configuration (could for example contain the config file name). 159 * @return configuration description 160 */ 161 private String getConfigDescription() { 162 StringBuilder theConfigDescriptionBuffer = new StringBuilder(15 + myPropertyName.length()); 163 theConfigDescriptionBuffer.append("Properties \""); 164 theConfigDescriptionBuffer.append(myPropertyName); 165 theConfigDescriptionBuffer.append('\"'); 166 return theConfigDescriptionBuffer.toString(); 167 } 168 169 /** 170 * Returns the best property value. The specified properties are checked in sequence and the value of the first available property is returned. 171 * @param aProperties properties 172 * @param aConfigParameters properties in sequence to check 173 * @return return the value of the best / first available property 174 */ 175 private String getPropertyValue(Properties aProperties, ConfigParameter... aConfigParameters) { 176 for(ConfigParameter theConfigParameter: aConfigParameters) { 177 String theValue = aProperties.getProperty(theConfigParameter.declaration()); 178 if(theValue != null) { 179 return theValue; 180 } 181 } 182 return null; 183 } 184 185 public boolean equals(Object anObject) { 186 if(this == anObject) { 187 return true; 188 } 189 if(anObject == null || getClass() != anObject.getClass()) { 190 return false; 191 } 192 PropertyConfigurationLoader theOtherLoader = (PropertyConfigurationLoader)anObject; 193 return myPropertyName.equals(theOtherLoader.myPropertyName); 194 } 195 196 public int hashCode() { 197 return myPropertyName.hashCode(); 198 } 199}