001 package org.hackystat.sensorbase.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 sensorbase.properties file. 012 * @author Philip Johnson 013 */ 014 public class ServerProperties { 015 016 /** The admin email key. */ 017 public static final String ADMIN_EMAIL_KEY = "sensorbase.admin.email"; 018 /** The admin password. */ 019 public static final String ADMIN_PASSWORD_KEY = "sensorbase.admin.password"; 020 /** The context root key. */ 021 public static final String CONTEXT_ROOT_KEY = "sensorbase.context.root"; 022 /** The database directory key. */ 023 public static final String DB_DIR_KEY = "sensorbase.db.dir"; 024 /** The database implementation class. */ 025 public static final String DB_IMPL_KEY = "sensorbase.db.impl"; 026 /** The hostname key. */ 027 public static final String HOSTNAME_KEY = "sensorbase.hostname"; 028 /** The logging level key. */ 029 public static final String LOGGING_LEVEL_KEY = "sensorbase.logging.level"; 030 /** The Restlet Logging key. */ 031 public static final String RESTLET_LOGGING_KEY = "sensorbase.restlet.logging"; 032 /** The SMTP host key. */ 033 public static final String SMTP_HOST_KEY = "sensorbase.smtp.host"; 034 /** The sensorbase port key. */ 035 public static final String PORT_KEY = "sensorbase.port"; 036 /** The XML directory key. */ 037 public static final String XML_DIR_KEY = "sensorbase.xml.dir"; 038 /** The test installation key. */ 039 public static final String TEST_INSTALL_KEY = "sensorbase.test.install"; 040 /** The test domain key. */ 041 public static final String TEST_DOMAIN_KEY = "sensorbase.test.domain"; 042 /** The sensorbase port key during testing. */ 043 public static final String TEST_PORT_KEY = "sensorbase.test.port"; 044 /** The sensorbase db dir during testing. */ 045 public static final String TEST_DB_DIR_KEY = "sensorbase.test.db.dir"; 046 /** The test admin email key. */ 047 public static final String TEST_ADMIN_EMAIL_KEY = "sensorbase.test.admin.email"; 048 /** The test admin password. */ 049 public static final String TEST_ADMIN_PASSWORD_KEY = "sensorbase.test.admin.password"; 050 /** The test hostname. */ 051 public static final String TEST_HOSTNAME_KEY = "sensorbase.test.hostname"; 052 /** Whether to compress on startup. */ 053 public static final String COMPRESS_ON_STARTUP_KEY = "sensorbase.db.startup.compress"; 054 /** Whether to re-index on startup. */ 055 public static final String REINDEX_ON_STARTUP_KEY = "sensorbase.db.startup.reindex"; 056 /** SMTP Server User name. */ 057 public static final String SMTP_SERVER_USER = "sensorbase.smtp.user"; 058 /** The admin email key. */ 059 public static final String SMTP_SERVER_PASS = "sensorbase.smtp.pass"; 060 061 062 /** Where we store the properties. */ 063 private Properties properties; 064 065 private static String FALSE = "false"; 066 067 /** 068 * Creates a new ServerProperties instance. 069 * Prints an error to the console if problems occur on loading. 070 */ 071 public ServerProperties() { 072 try { 073 initializeProperties(); 074 } 075 catch (Exception e) { 076 System.out.println("Error initializing server properties."); 077 } 078 } 079 080 /** 081 * Reads in the properties in ~/.hackystat/sensorbase.properties if this file exists, 082 * and provides default values for all properties not mentioned in this file. 083 * Will also add any pre-existing System properties that start with "sensorbase.". 084 * @throws Exception if errors occur. 085 */ 086 private void initializeProperties () throws Exception { 087 String userHome = System.getProperty("user.home"); 088 String userDir = System.getProperty("user.dir"); 089 String hackyHome = userHome + "/.hackystat"; 090 String sensorBaseHome = hackyHome + "/sensorbase"; 091 String propFile = userHome + "/.hackystat/sensorbase/sensorbase.properties"; 092 String defaultAdmin = "admin@hackystat.org"; 093 this.properties = new Properties(); 094 // Set defaults for 'standard' operation. These will override any previously 095 properties.setProperty(ADMIN_EMAIL_KEY, defaultAdmin); 096 properties.setProperty(ADMIN_PASSWORD_KEY, defaultAdmin); 097 properties.setProperty(CONTEXT_ROOT_KEY, "sensorbase"); 098 properties.setProperty(DB_DIR_KEY, sensorBaseHome + "/db"); 099 properties.setProperty(DB_IMPL_KEY, "org.hackystat.sensorbase.db.derby.DerbyImplementation"); 100 properties.setProperty(HOSTNAME_KEY, "localhost"); 101 properties.setProperty(LOGGING_LEVEL_KEY, "INFO"); 102 properties.setProperty(RESTLET_LOGGING_KEY, FALSE); 103 properties.setProperty(SMTP_HOST_KEY, "mail.hawaii.edu"); 104 properties.setProperty(PORT_KEY, "9876"); 105 properties.setProperty(XML_DIR_KEY, userDir + "/xml"); 106 properties.setProperty(TEST_DOMAIN_KEY, "hackystat.org"); 107 properties.setProperty(TEST_INSTALL_KEY, FALSE); 108 properties.setProperty(TEST_ADMIN_EMAIL_KEY, defaultAdmin); 109 properties.setProperty(TEST_ADMIN_PASSWORD_KEY, defaultAdmin); 110 properties.setProperty(TEST_DB_DIR_KEY, sensorBaseHome + "/testdb"); 111 properties.setProperty(TEST_PORT_KEY, "9976"); 112 properties.setProperty(TEST_HOSTNAME_KEY, "localhost"); 113 properties.setProperty(COMPRESS_ON_STARTUP_KEY, FALSE); 114 properties.setProperty(REINDEX_ON_STARTUP_KEY, FALSE); 115 116 FileInputStream stream = null; 117 try { 118 stream = new FileInputStream(propFile); 119 properties.load(stream); 120 System.out.println("Loading SensorBase properties from: " + propFile); 121 } 122 catch (IOException e) { 123 System.out.println(propFile + " not found. Using default sensorbase properties."); 124 } 125 finally { 126 if (stream != null) { 127 stream.close(); 128 } 129 } 130 addSensorBaseSystemProperties(this.properties); 131 trimProperties(properties); 132 133 // Now add to System properties. Since the Mailer class expects to find this stuff on the 134 // System Properties, we will add everything to it. In general, however, clients should not 135 // use the System Properties to get at these values, since that precludes running several 136 // SensorBases in a single JVM. And just is generally bogus. 137 Properties systemProperties = System.getProperties(); 138 systemProperties.putAll(properties); 139 System.setProperties(systemProperties); 140 } 141 142 /** 143 * Finds any System properties whose key begins with "sensorbase.", and adds those 144 * key-value pairs to the passed Properties object. 145 * @param properties The properties instance to be updated with the SensorBase system 146 * properties. 147 */ 148 private void addSensorBaseSystemProperties(Properties properties) { 149 Properties systemProperties = System.getProperties(); 150 for (Map.Entry<Object, Object> entry : systemProperties.entrySet()) { 151 String sysPropName = (String)entry.getKey(); 152 if (sysPropName.startsWith("sensorbase.")) { 153 String sysPropValue = (String)entry.getValue(); 154 properties.setProperty(sysPropName, sysPropValue); 155 } 156 } 157 } 158 159 /** 160 * Sets the following properties to their "test" equivalents. 161 * <ul> 162 * <li> ADMIN_EMAIL_KEY 163 * <li> ADMIN_PASSWORD_KEY 164 * <li> HOSTNAME_KEY 165 * <li> DB_DIR_KEY 166 * <li> PORT_KEY 167 * <li> XML_DIR_KEY (if HACKYSTAT_SENSORBASE_HOME is in System properties). 168 * </ul> 169 * Also sets TEST_INSTALL_KEY to true. 170 */ 171 public void setTestProperties() { 172 properties.setProperty(ADMIN_EMAIL_KEY, properties.getProperty(TEST_ADMIN_EMAIL_KEY)); 173 properties.setProperty(ADMIN_PASSWORD_KEY, properties.getProperty(TEST_ADMIN_PASSWORD_KEY)); 174 properties.setProperty(HOSTNAME_KEY, properties.getProperty(TEST_HOSTNAME_KEY)); 175 properties.setProperty(DB_DIR_KEY, properties.getProperty(TEST_DB_DIR_KEY)); 176 properties.setProperty(PORT_KEY, properties.getProperty(TEST_PORT_KEY)); 177 properties.setProperty(TEST_INSTALL_KEY, "true"); 178 // Change the XML dir location if HACKYSTAT_SENSORBASE_HOME exists. 179 String sensorbaseHome = System.getProperty("HACKYSTAT_SENSORBASE_HOME"); 180 if (sensorbaseHome != null) { 181 File file = new File(sensorbaseHome, "xml"); 182 if (file.exists()) { 183 properties.setProperty(XML_DIR_KEY, file.getAbsolutePath()); 184 } 185 else { 186 System.out.println("Bad HACKYSTAT_SENSORBASE_HOME: " + sensorbaseHome); 187 } 188 } 189 // Change the db implementation class if DB_IMPL_KEY is in system properties. 190 String dbImpl = System.getProperty(DB_IMPL_KEY); 191 if (dbImpl != null) { 192 properties.setProperty(DB_IMPL_KEY, dbImpl); 193 } 194 trimProperties(properties); 195 // update the system properties object to reflect these new values. 196 Properties systemProperties = System.getProperties(); 197 systemProperties.putAll(properties); 198 System.setProperties(systemProperties); 199 } 200 201 /** 202 * Returns a string containing all current properties in alphabetical order. 203 * @return A string with the properties. 204 */ 205 public String echoProperties() { 206 String cr = System.getProperty("line.separator"); 207 String eq = " = "; 208 String pad = " "; 209 // Adding them to a treemap has the effect of alphabetizing them. 210 TreeMap<String, String> alphaProps = new TreeMap<String, String>(); 211 for (Map.Entry<Object, Object> entry : this.properties.entrySet()) { 212 String propName = (String)entry.getKey(); 213 String propValue = (String)entry.getValue(); 214 alphaProps.put(propName, propValue); 215 } 216 StringBuffer buff = new StringBuffer(25); 217 buff.append("SensorBase Properties:").append(cr); 218 for (String key : alphaProps.keySet()) { 219 buff.append(pad).append(key).append(eq).append(get(key)).append(cr); 220 } 221 return buff.toString(); 222 } 223 224 /** 225 * Returns the value of the Server Property specified by the key. 226 * @param key Should be one of the public static final strings in this class. 227 * @return The value of the key, or null if not found. 228 */ 229 public String get(String key) { 230 return this.properties.getProperty(key); 231 } 232 233 /** 234 * Ensures that the there is no leading or trailing whitespace in the property values. 235 * The fact that we need to do this indicates a bug in Java's Properties implementation to me. 236 * @param properties The properties. 237 */ 238 private void trimProperties(Properties properties) { 239 // Have to do this iteration in a Java 5 compatible manner. no stringPropertyNames(). 240 for (Map.Entry<Object, Object> entry : properties.entrySet()) { 241 String propName = (String)entry.getKey(); 242 properties.setProperty(propName, properties.getProperty(propName).trim()); 243 } 244 } 245 246 /** 247 * Returns the fully qualified host name, such as "http://localhost:9876/sensorbase/". 248 * @return The fully qualified host name. 249 */ 250 public String getFullHost() { 251 return "http://" + get(HOSTNAME_KEY) + ":" + get(PORT_KEY) + "/" + get(CONTEXT_ROOT_KEY) + "/"; 252 } 253 254 /** 255 * True if the sensorbase.properties file indicates that the user wishes to compress the db 256 * on startup. 257 * @return True if compress on startup. 258 */ 259 public boolean compressOnStartup () { 260 return this.properties.getProperty(COMPRESS_ON_STARTUP_KEY).equalsIgnoreCase("true"); 261 } 262 263 /** 264 * True if the sensorbase.properties file indicates the user wants to reindex on startup. 265 * @return True if reindex on startup. 266 */ 267 public boolean reindexOnStartup () { 268 return this.properties.getProperty(REINDEX_ON_STARTUP_KEY).equalsIgnoreCase("true"); 269 } 270 }