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