/* * Copyright (c) 2007, Fraunhofer-Gesellschaft * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * (1) Redistributions of source code must retain the above copyright * notice, this list of conditions and the disclaimer at the end. * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * (2) Neither the name of Fraunhofer nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * DISCLAIMER * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ package org.ogf.graap.wsag.api.configuration; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.text.MessageFormat; import java.util.Properties; import org.apache.commons.discovery.log.SimpleLog; import org.apache.commons.discovery.resource.ClassLoaders; import org.apache.commons.discovery.tools.DefaultClassHolder; import org.apache.commons.discovery.tools.DiscoverClass; import org.apache.commons.discovery.tools.DiscoverSingleton; import org.apache.commons.discovery.tools.PropertiesHolder; import org.apache.commons.discovery.tools.ResourceUtils; import org.apache.commons.discovery.tools.SPInterface; import org.apache.log4j.Logger; import org.ogf.graap.wsag.api.logging.LogMessage; /** * MSSConfiguration This class provides basic configuration mechanisms for WSAG4J components. * * @author Oliver Waeldrich */ public class WSAG4JConfiguration { private static final Logger LOG = Logger.getLogger( WSAG4JConfiguration.class ); private static WSAG4JConfigurationEnvironment instance = null; /* * convenience methods */ private static synchronized WSAG4JConfigurationEnvironment getEnvironment() { SimpleLog.setLevel( SimpleLog.LOG_LEVEL_INFO ); if ( instance == null ) { SPInterface mssConfigSP = getWSAG4JSPI(); PropertiesHolder pHolder = new PropertiesHolder( WSAG4JEnvironment.DEFAULT_CONFIGURATION_FILE ); DefaultClassHolder cHolder = new DefaultClassHolder( WSAG4JEnvironment.class.getName() ); instance = (WSAG4JConfigurationEnvironment) DiscoverSingleton.find( null, mssConfigSP, pHolder, cHolder ); } return instance; } private static SPInterface getWSAG4JSPI() { // get the library classloaders for discovery ClassLoaders loaders = ClassLoaders.getLibLoaders( WSAG4JConfigurationEnvironment.class, DiscoverClass.class, true ); // load the properties file via the classloaders Properties properties = ResourceUtils.loadProperties( WSAG4JConfigurationEnvironment.class, WSAG4JEnvironment.DEFAULT_CONFIGURATION_FILE, loaders ); if ( properties == null ) { properties = new Properties(); } // find the path of the application configuration String cPath = properties.getProperty( WSAG4JEnvironment.DEFAULT_CONFIGURATION_PATH_KEY, WSAG4JEnvironment.DEFAULT_CONFIGURATION_PATH ); // instantiate new SPI with the configuration path // the configuration path is passed to the MSSConfigurationEnvironment // class on instantiation of the class by the discovery framework SPInterface mssConfigSP = new SPInterface( WSAG4JConfigurationEnvironment.class, new Class[] { String.class }, new Object[] { cPath } ); return mssConfigSP; } /** * @return the configuration path for this module */ public static String getConfigurationPath() { return getEnvironment().getConfigurationPath(); } /** * Finds an implementation for a given interface. * * @param interfaceDef * the interface definition to find an implementation for * @param configFile * the configuration file that specifies the appropriate implementation * @param defaultImpl * the default implementation to use * @return The instance of the implementation class */ public static Object findImplementation( Class<?> interfaceDef, String configFile, String defaultImpl ) { DiscoverClass discovery = new DiscoverClass(); try { try { Properties properties = new Properties(); InputStream resource = findResource( configFile ); properties.load( resource ); Class<?> theClass = discovery.find( interfaceDef, properties, defaultImpl ); return theClass.newInstance(); } catch ( IOException e ) { String message = "Could not load resource {0}. Try default discovery."; LOG.debug( LogMessage.getMessage( message, configFile ) ); Class<?> theClass = discovery.find( interfaceDef, configFile, defaultImpl ); return theClass.newInstance(); } } catch ( InstantiationException e ) { final String message = "Could not instantiate class for interface {0}."; LOG.debug( LogMessage.getMessage( message, interfaceDef.getName() ), e ); } catch ( IllegalAccessException e ) { final String message = "Could not instantiate class for interface {0}."; LOG.debug( LogMessage.getMessage( message, interfaceDef.getName() ), e ); } return null; } /** * Finds a singleton implementation for a given interface. * * @param interfaceDef * the interface definition to find an implementation for * @param configFile * the configuration file that specifies the appropriate implementation * @param defaultImpl * the default implementation to use * @return The instance of the implementation class */ public static Object findSingeltonImplementation( Class<?> interfaceDef, String configFile, String defaultImpl ) { try { Properties properties = new Properties(); InputStream resource = findResource( configFile ); properties.load( resource ); return DiscoverSingleton.find( interfaceDef, properties, defaultImpl ); } catch ( IOException e ) { final String message = "Could not load resource {0}. Try default discovery."; LOG.debug( LogMessage.getMessage( message, configFile ) ); LOG.trace( e ); return DiscoverSingleton.find( interfaceDef, configFile, defaultImpl ); } } /** * @param resourceName * The name of the requested resource. * @return The requested resource as <code>InputStream</code>. * @throws IOException * there was an error reading the resource */ public static InputStream findResource( String resourceName ) throws IOException { return findResource( getEnvironment().getConfigurationPath(), resourceName ); } /** * @param path * The path to the requested resource. If the resource is not found at the specified location * discovery will be performed. * @param resourceName * The name of the requested resource. * @return The requested resource as an InputStream. * @throws IOException * there was an error reading the resource */ public static InputStream findResource( String path, String resourceName ) throws IOException { return findResourceURL( path, resourceName ).openStream(); } /** * @param resourceName * The name of the requested resource. * @return The URL of the requested resource. * @throws IOException * there was an error reading the resource */ public static URL findResourceURL( String resourceName ) throws IOException { return findResourceURL( getEnvironment().getConfigurationPath(), resourceName ); } /** * @param path * The path to the requested resource. If the resource is not found at the specified location * discovery will be performed. * @param resourceName * The name of the requested resource. * @return The URL of the requested resource. * @throws IOException * there was an error reading the resource */ public static URL findResourceURL( String path, String resourceName ) throws IOException { if ( path == null ) { path = ""; } if ( resourceName == null ) { throw new IOException( "Could not find resource. No resource name specified (null)." ); } File file = null; // first try to find the resource in the specified directory // global configuration files should be kept outside the application // in order to easy update the application file = new File( path, resourceName ); if ( file.exists() ) { try { LogMessage message = LogMessage.getMessage( "Found resource {0} in directory {1}.", resourceName, path ); if ( LOG.isTraceEnabled() ) { LOG.trace( message ); } return file.toURI().toURL(); } catch ( IOException e ) { LogMessage message = LogMessage.getMessage( "Could not read resource {0}.", resourceName ); LOG.error( message, e ); } } // then try to load the resource by its absolute name file = new File( resourceName ); if ( file.exists() ) { try { LOG.trace( LogMessage.getMessage( "Found resource [{0}].", new Object[] { resourceName } ) ); return file.toURI().toURL(); } catch ( IOException e ) { LOG.error( MessageFormat.format( "Could not read resource {0}.", new Object[] { resourceName } ), e ); } } // then by its fully qualified resource name String qualifiedResourceName = path + System.getProperty( "file.separator" ) + resourceName; // special case for empty path on Windows systems if ( path.equals( "" ) ) { qualifiedResourceName = "/" + resourceName; } URL resourceUrl = WSAG4JConfiguration.class.getResource( qualifiedResourceName ); if ( resourceUrl != null ) { LOG.trace( LogMessage.getMessage( "Found resource {0} by the classloader [external name: {1}]", qualifiedResourceName, resourceUrl.toExternalForm() ) ); return resourceUrl; } // last try to find the resource by the classloader // this is the default behavior if ( resourceName.startsWith( "/" ) || resourceName.startsWith( "\\" ) ) { resourceUrl = WSAG4JConfiguration.class.getResource( resourceName ); } else { // we don't want to load the resource relative from MSSConfiguration resourceUrl = WSAG4JConfiguration.class.getResource( "/" + resourceName ); } if ( resourceUrl != null ) { LOG.trace( LogMessage.getMessage( "Found resource {0} by the classloader [external name: {1}]", resourceName, resourceUrl.toExternalForm() ) ); return resourceUrl; } LOG.trace( LogMessage.getMessage( "The resource {0} was not found.", resourceName ) ); LOG.trace( LogMessage.getMessage( "Tried the following directories: [{0}] [{1}]", path, System.getProperty( "java.class.path" ) ) ); throw new FileNotFoundException( LogMessage.format( "The resource [{0}] was not found at the system.", resourceName ) ); } }