/*
* Copyright (C) 2008 Universidade Federal de Campina Grande
*
* This file is part of OurGrid.
*
* OurGrid is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.ourgrid.common.config;
import static java.io.File.separator;
import static org.ourgrid.common.interfaces.Constants.LINE_SEPARATOR;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Map;
import java.util.Properties;
import java.util.Scanner;
import java.util.Set;
import java.util.Map.Entry;
import org.ourgrid.common.util.CommonUtils;
import org.ourgrid.common.util.JavaFileUtil;
import org.ourgrid.reqtrace.Req;
/**
* Description: This class provides access to the ourgrid's configuration model
* Each module that needs specific configuration properties should extend this
* class and sets its own properties.
*/
public abstract class Configuration implements Serializable {
private static final long serialVersionUID = 1L;
public static final String VERSION_FILE = "/resources/VERSION";
public static final OurgridVersion VERSION = getVersionFromFile();
public final OurgridVersion version = VERSION;
private static Configuration singleInstance = null;
public static final String PROP_LOGFILE = "logfile";
public static final String PROP_LOG_PROPERTIES_FILE = "logProperties";
public static final String MGROOT = "MGROOT";
public static final String OGROOT = "OGROOT";
private Properties currentProperties = new Properties( System.getProperties() );
private boolean usingDefaultProperties = false;
protected Configuration() {
}
@Req({"REQ068a","REQ095"})
public static final synchronized Configuration getInstance() {
if ( Configuration.singleInstance == null ) {
throw new Error( "You need to create a configuration!" );
}
return Configuration.singleInstance;
}
/**
* Creates, if not already created, the unique configuration instance.
*
* @param configurationType The configuration type to be created.
* @return The unique configuration instance.
*/
public static final synchronized Configuration getInstance( String configurationType ) {
if ( Configuration.singleInstance == null ) {
Configuration.singleInstance = Configuration.getConfigurationInstance( configurationType );
}
return Configuration.singleInstance;
}
/**
* Sets the singleton instance to null. Used only by test classes.
*/
public static final synchronized void reset() {
Configuration.singleInstance = null;
}
/**
* Gets the value of a given property.
*
* @param key The property name without the module specific prefix.
* @return The property value or null if the property was no setted.
*/
public final String getProperty( String key ) {
String trimmedKey = key.trim();
String property = (String) currentProperties.get(trimmedKey);
if (property != null) {
return property.trim();
}
int indexOfSeparator = trimmedKey.indexOf('.');
if (indexOfSeparator >= 0) {
property = (String) currentProperties.get(
trimmedKey.substring(indexOfSeparator + 1));
if (property != null) {
return property.trim();
}
}
return property;
}
/**
* Sets the value of a given property.
*
* @param key The property name without the module specific prefix.
* @param value The property value.
*/
@Req("REQ010")
public final void setProperty( String key, String value ) {
currentProperties.put(key.trim(), value.trim());
}
/**
* Verify if the property passed is enabled.
*
* @param propertyKey the key name of the property.
* @return true if property is yes, false otherwise.
*/
public final boolean isEnabled( String propertyKey ) {
String property = getProperty( propertyKey );
return property != null && property.equalsIgnoreCase( "yes" );
}
/**
* This method reads properties from a file.
*
* @param file The property file to be loaded.
*/
@Req("REQ010")
protected void loadPropertiesFromFile( String file ) {
/** Get an abstraction for the properties file */
File propertiesFile = new File( file );
/* load the properties file, if it exists */
try {
currentProperties.load( new FileInputStream( propertiesFile ) );
} catch ( IOException e ) {
usingDefaultProperties = true;
}
}
public boolean isUsingDefaultProperties() {
return usingDefaultProperties;
}
/**
* Gets an instance of a <code>Configuration</code> subclass by reflection
* and throws an <code>ConfigurationInstantiationRunTimeException</code>
* if any error occurs.
*
* @param configurationClassName The fully qualified
* <code>Configuration</code> subclass name.
* @return An <code>Configuration</code> subclass instance.
*/
@Req("REQ010")
private static Configuration getConfigurationInstance( String configurationClassName ) {
try {
Class<?> configurationClassDefinition = Class.forName( configurationClassName );
Constructor<?> constructor = configurationClassDefinition.getConstructor( new Class[ 0 ] );
return (Configuration) constructor.newInstance( new Object[ 0 ] );
} catch ( Exception e ) {
throw new ConfigurationInstantiationRunTimeException();
}
}
/**
* @return local host name.
*/
public final String getHostname() {
String hostname = "localhost";
try {
hostname = InetAddress.getLocalHost().getCanonicalHostName();
} catch ( UnknownHostException e ) {
// Using default peer name.
}
return hostname;
}
/**
* This method provides the absolute path to the log file.
*
* @return The absolute path where the log file is located
*/
@Req({"REQ001", "REQ003", "REQ010"})
public String getLogPath() {
String logfile = getProperty( PROP_LOGFILE );
if ( JavaFileUtil.isAbsolutePath( logfile ) ) {
return (new File( logfile )).getAbsolutePath();
}
return getConfDir() + separator + logfile;
}
@Req({"REQ001", "REQ003", "REQ010"})
public String getLogPropertiesPath() {
String logfile = getProperty( PROP_LOG_PROPERTIES_FILE );
if ( JavaFileUtil.isAbsolutePath( logfile ) ) {
return (new File( logfile )).getAbsolutePath();
}
return getConfDir() + separator + logfile;
}
public OurgridVersion getVersion() {
return this.version;
}
// /**
// * Returns the module specific prefix used to identify it's own properties.
// * For example, the Broker properties prefix is "mg." , the OurGrid's one is
// * "peer." .
// *
// * @return The module specific property prefix.
// */
// protected abstract String getPrefix();
/**
* Gets the module configuration rootdir.
*
* @return The module configuration rootdir path.
*/
@Req({"REQ001", "REQ003", "REQ010"})
public abstract String getConfDir();
/**
* Creates the unique configuration instance.
*
* @param configurationType The configuration type to be created.
* @return The unique configuration instance.
*/
public static Configuration createInstance( String configurationType ) {
reset();
return getInstance( configurationType );
}
protected Properties getCurrentProperties() {
return this.currentProperties;
}
@Override
public int hashCode() {
final int PRIME = 31;
int result = 1;
result = PRIME * result + this.currentProperties.hashCode();
result = PRIME * result + this.version.hashCode();
return result;
}
@Override
public boolean equals( Object obj ) {
if ( this == obj )
return true;
if ( obj == null )
return false;
if ( getClass() != obj.getClass() )
return false;
final Configuration other = (Configuration) obj;
if ( !this.currentProperties.equals( other.currentProperties ) )
return false;
if ( !this.version.equals( other.version ) )
return false;
return true;
}
public double parseDoubleProperty( String propName ) throws InvalidConfigurationPropertyException {
final String val = getProperty( propName );
try {
return Double.parseDouble( val );
} catch ( NumberFormatException e ) {
throw new InvalidConfigurationPropertyException( propName, val, e );
}
}
public int parseIntegerProperty( String propName ) throws InvalidConfigurationPropertyException {
final String val = getProperty( propName );
try {
return Integer.parseInt( val );
} catch ( NumberFormatException e ) {
throw new InvalidConfigurationPropertyException( propName, val, e );
}
}
public long parseLongProperty( String propName ) throws InvalidConfigurationPropertyException {
final String val = getProperty( propName );
try {
return Long.parseLong( val );
} catch ( NumberFormatException e ) {
throw new InvalidConfigurationPropertyException( propName, val, e );
}
}
@Override
public String toString() {
StringBuilder conf = new StringBuilder();
conf.append( "\tVersion: " ).append( VERSION ).append( LINE_SEPARATOR );
conf.append( "\tConfiguration directory: " );
conf.append( getConfDir() );
conf.append( LINE_SEPARATOR );
return conf.toString();
}
public Map<String, Object> toMap() {
Map<String, Object> result = CommonUtils.createSerializableMap();
Set<Entry<Object, Object>> properties = currentProperties.entrySet();
for (Entry<Object, Object> entry : properties) {
result.put((String)entry.getKey(), entry.getValue());
}
return result;
}
private static OurgridVersion getVersionFromFile() {
Scanner scn = new Scanner(Configuration.class.getResourceAsStream(VERSION_FILE));
String version = scn.next();
scn.close();
return OurgridVersion.parse(version);
}
}