// // Copyright 2010 Cinch Logic Pty Ltd. // // http://www.chililog.com // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package org.chililog.server.common; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.Enumeration; import java.util.Properties; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.WordUtils; /** * <p> * SystemProperties provides strongly typed access to our system properties. * </p> * * <h3>Example</h3> * * <code> * SystemProperties.getInstance().getJavaHome(); * </code> * * <h3>Property Loading</h3> * * We use convention to load the properties. * <ol> * <li>We search for all fields with upper case letters in their names. For example, <code>APP_NAME<code>.</li> * <li>We search for the corresponding field cache variable. The field name is converted to camel case and prefixed with * underscore. For example, <code>_appName</code></li> * <li>Next, we search for a load method to parse the entry in the property file. The field name is converted to camel * case and prefixed with "load". For example, <code>loadAppName</code></li> * <li>If the method is found, it is called and the result is used to set the cache variable identified in step #2.</li> * </ol> * * @author vibul * @since 1.0 */ public class SystemProperties { private static Log4JLogger _logger = Log4JLogger.getLogger(SystemProperties.class); /** * Returns the singleton instance for this class */ public static SystemProperties getInstance() { return SingletonHolder.INSTANCE; } /** * SingletonHolder is loaded on the first execution of Singleton.getInstance() or the first access to * SingletonHolder.INSTANCE, not before. * * @see http://en.wikipedia.org/wiki/Singleton_pattern */ private static class SingletonHolder { public static final SystemProperties INSTANCE = new SystemProperties(); } /** * <p> * Singleton constructor that parses and loads the required system properties. * </p> * * <p> * If there are any errors, the JVM is terminated. Without valid system properties, we will fall over elsewhere so * might as well terminate here. * </p> */ private SystemProperties() { try { loadProperties(); } catch (Exception e) { _logger.error(e, "Error loading system properties: " + e.getMessage()); System.exit(1); } } /** * <p> * Loads/Reloads the properties. This method is NOT thread-safe and should only be called for unit-testing. * </p> * * <p> * Use reflection to simulate the likes of: * <code>_chiliLogConfigDirectory = loadChiliLogConfigDirectory(properties);</code> * </p> * * @throws Exception */ public void loadProperties() throws Exception { Class<SystemProperties> cls = SystemProperties.class; for (Field f : cls.getDeclaredFields()) { // Look for field names like CHILILOG_CONFIG_DIRECTORY String propertyNameFieldName = f.getName(); if (!propertyNameFieldName.matches("^[A-Z0-9_]+$")) { continue; } // Build cache field (_chiliLogConfigDirectory) and method (loadChiliLogConfigDirectory) names String baseName = WordUtils.capitalizeFully(propertyNameFieldName, new char[] { '_' }); baseName = baseName.replace("Chililog", "ChiliLog").replace("_", ""); String cacheMethodName = "load" + baseName; String cacheFieldName = "_" + StringUtils.uncapitalize(baseName); // If field not exist, then skip Field cacheField = null; try { cacheField = cls.getDeclaredField(cacheFieldName); } catch (NoSuchFieldException e) { continue; } // Get and set the value Method m = cls.getDeclaredMethod(cacheMethodName, (Class[]) null); Object cacheValue = m.invoke(null, (Object[]) null); cacheField.set(this, cacheValue); } return; } /** * @return The Java home directory */ public String getJavaHome() { return _javaHome; } public static final String JAVA_HOME = "java.home"; private String _javaHome = null; static String loadJavaHome() { return System.getProperty(JAVA_HOME); } /** * @return The Java vendor */ public String getJavaVender() { return _javaVender; } public static final String JAVA_VENDER = "java.vender"; private String _javaVender = null; static String loadJavaVender() { return System.getProperty(JAVA_VENDER); } /** * @return The Java version */ public String getJavaVersion() { return _javaVersion; } public static final String JAVA_VERSION = "java.version"; private String _javaVersion = null; static String loadJavaVersion() { return System.getProperty(JAVA_VERSION); } /** * @return The operating system name */ public String getOsName() { return _osName; } public static final String OS_NAME = "os.name"; private String _osName = null; static String loadOsName() { return System.getProperty(OS_NAME); } /** * @return The operating system architecture */ public String getOsArchitecture() { return _osArchitecture; } public static final String OS_ARCHITECTURE = "os.arch"; private String _osArchitecture = null; static String loadOsArchitecture() { return System.getProperty(OS_ARCHITECTURE); } /** * @return The operating system version */ public String getOsVersion() { return _osVersion; } public static final String OS_VERSION = "os.version"; private String _osVersion = null; static String loadOsVersion() { return System.getProperty(OS_VERSION); } /** * String representation of the values are have parsed */ public String toString() { StringBuilder sb = new StringBuilder(); // Get all system properties Properties props = System.getProperties(); // Enumerate all system properties Enumeration<?> e = props.propertyNames(); for (; e.hasMoreElements();) { String name = (String) e.nextElement(); String value = (String) props.get(name); sb.append(name); sb.append(" = "); sb.append(value); sb.append("\n"); } return sb.toString(); } }