001 package org.hackystat.dailyprojectdata.server; 002 003 import java.io.FileInputStream; 004 import java.io.IOException; 005 import java.util.Map; 006 import java.util.Properties; 007 import java.util.TreeMap; 008 009 /** 010 * Provides access to the values stored in the dailyprojectdata.properties file. 011 * @author Philip Johnson 012 */ 013 public class ServerProperties { 014 015 /** The sensorbase fully qualified host name, such as http://localhost:9876/sensorbase. */ 016 public static final String SENSORBASE_FULLHOST_KEY = "dailyprojectdata.sensorbase.host"; 017 /** The dailyprojectdata hostname key. */ 018 public static final String HOSTNAME_KEY = "dailyprojectdata.hostname"; 019 /** The dailyprojectdata context root. */ 020 public static final String CONTEXT_ROOT_KEY = "dailyprojectdata.context.root"; 021 /** The logging level key. */ 022 public static final String LOGGING_LEVEL_KEY = "dailyprojectdata.logging.level"; 023 /** The dailyprojectdata port key. */ 024 public static final String PORT_KEY = "dailyprojectdata.port"; 025 /** The XML directory key. */ 026 public static final String XML_DIR_KEY = "dailyprojectdata.xml.dir"; 027 /** The Restlet Logging key. */ 028 public static final String RESTLET_LOGGING_KEY = "dailyprojectdata.restlet.logging"; 029 /** The dpd port key during testing. */ 030 public static final String TEST_PORT_KEY = "dailyprojectdata.test.port"; 031 /** The test installation key. */ 032 public static final String TEST_INSTALL_KEY = "dailyprojectdata.test.install"; 033 /** The test installation key. */ 034 public static final String TEST_HOSTNAME_KEY = "dailyprojectdata.test.hostname"; 035 /** The test installation key. */ 036 public static final String TEST_SENSORBASE_FULLHOST_KEY = "dailyprojectdata.test.sensorbase.host"; 037 /** Indicates whether SensorBaseClient caching is enabled. */ 038 public static final String CACHE_ENABLED = "dailyprojectdata.cache.enabled"; 039 /** The maxLife in days for each instance in each SensorBaseClient cache. */ 040 public static final String CACHE_MAX_LIFE = "dailyprojectdata.cache.max.life"; 041 /** The total capacity of each SensorBaseClient cache. */ 042 public static final String CACHE_CAPACITY = "dailyprojectdata.cache.capacity"; 043 /** Whether or not the front side cache is enabled. */ 044 public static final String FRONTSIDECACHE_ENABLED = "dailyprojectdata.cache.frontside.enabled"; 045 046 private String falseString = "false"; // for PMD. 047 048 049 050 /** Where we store the properties. */ 051 private Properties properties; 052 053 /** 054 * Creates a new ServerProperties instance. 055 * Prints an error to the console if problems occur on loading. 056 */ 057 public ServerProperties() { 058 try { 059 initializeProperties(); 060 } 061 catch (Exception e) { 062 System.out.println("Error initializing server properties: " + e.getMessage()); 063 } 064 } 065 066 /** 067 * Reads in the properties in ~/.hackystat/dailyprojectdata/dailyprojectdata.properties 068 * if this file exists, and provides default values for all properties. 069 * @throws Exception if errors occur. 070 */ 071 private void initializeProperties () throws Exception { 072 String userHome = System.getProperty("user.home"); 073 String userDir = System.getProperty("user.dir"); 074 String propFile = userHome + "/.hackystat/dailyprojectdata/dailyprojectdata.properties"; 075 this.properties = new Properties(); 076 // Set defaults 077 properties.setProperty(SENSORBASE_FULLHOST_KEY, "http://localhost:9876/sensorbase/"); 078 properties.setProperty(HOSTNAME_KEY, "localhost"); 079 properties.setProperty(PORT_KEY, "9877"); 080 properties.setProperty(CONTEXT_ROOT_KEY, "dailyprojectdata"); 081 properties.setProperty(LOGGING_LEVEL_KEY, "INFO"); 082 properties.setProperty(RESTLET_LOGGING_KEY, falseString); 083 properties.setProperty(XML_DIR_KEY, userDir + "/xml"); 084 properties.setProperty(TEST_PORT_KEY, "9977"); 085 properties.setProperty(TEST_HOSTNAME_KEY, "localhost"); 086 properties.setProperty(TEST_SENSORBASE_FULLHOST_KEY, "http://localhost:9976/sensorbase"); 087 properties.setProperty(TEST_INSTALL_KEY, falseString); 088 properties.setProperty(CACHE_ENABLED, "true"); 089 properties.setProperty(FRONTSIDECACHE_ENABLED, "true"); 090 properties.setProperty(CACHE_MAX_LIFE, "365"); 091 properties.setProperty(CACHE_CAPACITY, "500000"); 092 FileInputStream stream = null; 093 try { 094 stream = new FileInputStream(propFile); 095 System.out.println("Loading DailyProjectData properties from: " + propFile); 096 properties.load(stream); 097 } 098 catch (IOException e) { 099 System.out.println(propFile + " not found. Using default dailyprojectdata properties."); 100 } 101 finally { 102 if (stream != null) { 103 stream.close(); 104 } 105 } 106 107 trimProperties(properties); 108 // make sure that SENSORBASE_HOST always has a final slash. 109 String sensorBaseHost = (String) properties.get(SENSORBASE_FULLHOST_KEY); 110 if (!sensorBaseHost.endsWith("/")) { 111 properties.put(SENSORBASE_FULLHOST_KEY, sensorBaseHost + "/"); 112 } 113 } 114 115 /** 116 * Sets the following properties' values to their "test" equivalent. 117 * <ul> 118 * <li> HOSTNAME_KEY 119 * <li> PORT_KEY 120 * <li> SENSORBASE_FULLHOST_KEY 121 * </ul> 122 * Also sets TEST_INSTALL_KEY's value to "true". 123 */ 124 public void setTestProperties() { 125 properties.setProperty(HOSTNAME_KEY, properties.getProperty(TEST_HOSTNAME_KEY)); 126 properties.setProperty(PORT_KEY, properties.getProperty(TEST_PORT_KEY)); 127 properties.setProperty(SENSORBASE_FULLHOST_KEY, 128 properties.getProperty(TEST_SENSORBASE_FULLHOST_KEY)); 129 properties.setProperty(TEST_INSTALL_KEY, "true"); 130 properties.setProperty(CACHE_ENABLED, falseString); 131 properties.setProperty(FRONTSIDECACHE_ENABLED, falseString); 132 trimProperties(properties); 133 } 134 135 /** 136 * Returns the value of the Server Property specified by the key. 137 * @param key Should be one of the public static final strings in this class. 138 * @return The value of the key, or null if not found. 139 */ 140 public String get(String key) { 141 return this.properties.getProperty(key); 142 } 143 144 /** 145 * Ensures that the there is no leading or trailing whitespace in the property values. 146 * The fact that we need to do this indicates a bug in Java's Properties implementation to me. 147 * @param properties The properties. 148 */ 149 private void trimProperties(Properties properties) { 150 // Have to do this iteration in a Java 5 compatible manner. no stringPropertyNames(). 151 for (Map.Entry<Object, Object> entry : properties.entrySet()) { 152 String propName = (String)entry.getKey(); 153 properties.setProperty(propName, properties.getProperty(propName).trim()); 154 } 155 } 156 157 /** 158 * Returns the fully qualified host name, such as "http://localhost:9877/dailyprojectdata/". 159 * @return The fully qualified host name. 160 */ 161 public String getFullHost() { 162 return "http://" + get(HOSTNAME_KEY) + ":" + get(PORT_KEY) + "/" + get(CONTEXT_ROOT_KEY) + "/"; 163 } 164 165 /** 166 * Returns true if caching is enabled in this service. 167 * @return True if caching enabled. 168 */ 169 public boolean isCacheEnabled() { 170 return "True".equalsIgnoreCase(this.properties.getProperty(CACHE_ENABLED)); 171 } 172 173 /** 174 * Returns true if front side caching is enabled in this service. 175 * @return True if caching enabled. 176 */ 177 public boolean isFrontSideCacheEnabled() { 178 return "True".equalsIgnoreCase(this.properties.getProperty(FRONTSIDECACHE_ENABLED)); 179 } 180 181 /** 182 * Returns the caching max life as a double. 183 * If the property has an illegal value, then return the default. 184 * @return The max life of each instance in the cache. 185 */ 186 public double getCacheMaxLife() { 187 String maxLifeString = this.properties.getProperty(CACHE_MAX_LIFE); 188 double maxLife = 0; 189 try { 190 maxLife = Double.valueOf(maxLifeString); 191 } 192 catch (Exception e) { 193 System.out.println("Illegal cache max life: " + maxLifeString + ". Using default."); 194 maxLife = 365D; 195 } 196 return maxLife; 197 } 198 199 /** 200 * Returns the in-memory capacity for each cache. 201 * If the property has an illegal value, then return the default. 202 * @return The in-memory capacity. 203 */ 204 public long getCacheCapacity() { 205 String capacityString = this.properties.getProperty(CACHE_CAPACITY); 206 long capacity = 0; 207 try { 208 capacity = Long.valueOf(capacityString); 209 } 210 catch (Exception e) { 211 System.out.println("Illegal cache capacity: " + capacityString + ". Using default."); 212 capacity = 500000L; 213 } 214 return capacity; 215 } 216 217 /** 218 * Returns a string containing all current properties in alphabetical order. 219 * @return A string with the properties. 220 */ 221 public String echoProperties() { 222 String cr = System.getProperty("line.separator"); 223 String eq = " = "; 224 String pad = " "; 225 // Adding them to a treemap has the effect of alphabetizing them. 226 TreeMap<String, String> alphaProps = new TreeMap<String, String>(); 227 for (Map.Entry<Object, Object> entry : this.properties.entrySet()) { 228 String propName = (String)entry.getKey(); 229 String propValue = (String)entry.getValue(); 230 alphaProps.put(propName, propValue); 231 } 232 StringBuffer buff = new StringBuffer(30); 233 buff.append("DailyProjectData Properties:").append(cr); 234 for (String key : alphaProps.keySet()) { 235 buff.append(pad).append(key).append(eq).append(get(key)).append(cr); 236 } 237 return buff.toString(); 238 } 239 240 }