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