View Javadoc

1   /* 
2    * Copyright (c) 2007, Fraunhofer-Gesellschaft
3    * All rights reserved.
4    * 
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions are
7    * met:
8    * 
9    * (1) Redistributions of source code must retain the above copyright
10   *     notice, this list of conditions and the disclaimer at the end.
11   *     Redistributions in binary form must reproduce the above copyright
12   *     notice, this list of conditions and the following disclaimer in
13   *     the documentation and/or other materials provided with the
14   *     distribution.
15   * 
16   * (2) Neither the name of Fraunhofer nor the names of its
17   *     contributors may be used to endorse or promote products derived
18   *     from this software without specific prior written permission.
19   * 
20   * DISCLAIMER
21   * 
22   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25   * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26   * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30   * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33   *  
34   */
35  package org.ogf.graap.wsag.api.configuration;
36  
37  import java.io.File;
38  import java.io.FileNotFoundException;
39  import java.io.IOException;
40  import java.io.InputStream;
41  import java.net.URL;
42  import java.text.MessageFormat;
43  import java.util.Properties;
44  
45  import org.apache.commons.discovery.log.SimpleLog;
46  import org.apache.commons.discovery.resource.ClassLoaders;
47  import org.apache.commons.discovery.tools.DefaultClassHolder;
48  import org.apache.commons.discovery.tools.DiscoverClass;
49  import org.apache.commons.discovery.tools.DiscoverSingleton;
50  import org.apache.commons.discovery.tools.PropertiesHolder;
51  import org.apache.commons.discovery.tools.ResourceUtils;
52  import org.apache.commons.discovery.tools.SPInterface;
53  import org.apache.log4j.Logger;
54  import org.apache.xmlbeans.XmlException;
55  import org.ogf.graap.wsag.api.logging.LogMessage;
56  import org.ogf.graap.wsag4j.types.configuration.ConfigurationDocument;
57  import org.ogf.graap.wsag4j.types.configuration.ConfigurationType;
58  
59  /**
60   * MSSConfiguration This class provides basic configuration mechanisms for WSAG4J components.
61   * 
62   * @author Oliver Waeldrich
63   */
64  public class WSAG4JConfiguration
65  {
66  
67      private static final Logger LOG = Logger.getLogger( WSAG4JConfiguration.class );
68  
69      private static WSAG4JConfigurationEnvironment instance = null;
70  
71      /*
72       * convenience methods
73       */
74      private static synchronized WSAG4JConfigurationEnvironment getEnvironment()
75      {
76  
77          SimpleLog.setLevel( SimpleLog.LOG_LEVEL_INFO );
78  
79          if ( instance == null )
80          {
81  
82              SPInterface mssConfigSP = getWSAG4JSPI();
83              PropertiesHolder pHolder = new PropertiesHolder( WSAG4JEnvironment.DEFAULT_CONFIGURATION_FILE );
84              DefaultClassHolder cHolder = new DefaultClassHolder( WSAG4JEnvironment.class.getName() );
85  
86              instance =
87                  (WSAG4JConfigurationEnvironment) DiscoverSingleton.find( null, mssConfigSP, pHolder, cHolder );
88          }
89  
90          return instance;
91      }
92  
93      private static SPInterface getWSAG4JSPI()
94      {
95          // get the library classloaders for discovery
96          ClassLoaders loaders =
97              ClassLoaders.getLibLoaders( WSAG4JConfigurationEnvironment.class, DiscoverClass.class, true );
98  
99          // load the properties file via the classloaders
100         Properties properties =
101             ResourceUtils.loadProperties( WSAG4JConfigurationEnvironment.class,
102                 WSAG4JEnvironment.DEFAULT_CONFIGURATION_FILE, loaders );
103 
104         if ( properties == null )
105         {
106             properties = new Properties();
107         }
108 
109         // find the path of the application configuration
110         String cPath =
111             properties.getProperty( WSAG4JEnvironment.DEFAULT_CONFIGURATION_PATH_KEY,
112                 WSAG4JEnvironment.DEFAULT_CONFIGURATION_PATH );
113 
114         // instantiate new SPI with the configuration path
115         // the configuration path is passed to the MSSConfigurationEnvironment
116         // class on instantiation of the class by the discovery framework
117         SPInterface mssConfigSP =
118             new SPInterface( WSAG4JConfigurationEnvironment.class, new Class[] { String.class },
119                 new Object[] { cPath } );
120 
121         return mssConfigSP;
122     }
123 
124     /**
125      * @return the configuration path for this module
126      */
127     public static String getConfigurationPath()
128     {
129         return getEnvironment().getConfigurationPath();
130     }
131 
132     /**
133      * Finds an implementation for a given interface.
134      * 
135      * @param interfaceDef
136      *            the interface definition to find an implementation for
137      * @param configFile
138      *            the configuration file that specifies the appropriate implementation
139      * @param defaultImpl
140      *            the default implementation to use
141      * @return The instance of the implementation class
142      */
143     public static Object findImplementation( Class<?> interfaceDef, String configFile, String defaultImpl )
144     {
145         DiscoverClass discovery = new DiscoverClass();
146         try
147         {
148             try
149             {
150                 Properties properties = new Properties();
151 
152                 InputStream resource = findResource( configFile );
153                 properties.load( resource );
154 
155                 Class<?> theClass = discovery.find( interfaceDef, properties, defaultImpl );
156 
157                 return theClass.newInstance();
158             }
159             catch ( IOException e )
160             {
161                 String message = "Could not load resource {0}. Try default discovery.";
162                 LOG.debug( LogMessage.getMessage( message, configFile ) );
163 
164                 Class<?> theClass = discovery.find( interfaceDef, configFile, defaultImpl );
165 
166                 return theClass.newInstance();
167             }
168         }
169         catch ( InstantiationException e )
170         {
171             final String message = "Could not instantiate class for interface {0}.";
172             LOG.debug( LogMessage.getMessage( message, interfaceDef.getName() ), e );
173         }
174         catch ( IllegalAccessException e )
175         {
176             final String message = "Could not instantiate class for interface {0}.";
177             LOG.debug( LogMessage.getMessage( message, interfaceDef.getName() ), e );
178         }
179 
180         return null;
181     }
182 
183     /**
184      * Finds a singleton implementation for a given interface.
185      * 
186      * @param interfaceDef
187      *            the interface definition to find an implementation for
188      * @param configFile
189      *            the configuration file that specifies the appropriate implementation
190      * @param defaultImpl
191      *            the default implementation to use
192      * @return The instance of the implementation class
193      */
194     public static Object findSingeltonImplementation( Class<?> interfaceDef, String configFile,
195                                                       String defaultImpl )
196     {
197         try
198         {
199             Properties properties = new Properties();
200 
201             InputStream resource = findResource( configFile );
202             properties.load( resource );
203 
204             return DiscoverSingleton.find( interfaceDef, properties, defaultImpl );
205         }
206         catch ( IOException e )
207         {
208             final String message = "Could not load resource {0}. Try default discovery.";
209             LOG.debug( LogMessage.getMessage( message, configFile ) );
210             LOG.trace( e );
211 
212             return DiscoverSingleton.find( interfaceDef, configFile, defaultImpl );
213         }
214     }
215 
216     /**
217      * @param resourceName
218      *            The name of the requested resource.
219      * @return The requested resource as <code>InputStream</code>.
220      * @throws IOException
221      *             there was an error reading the resource
222      */
223     public static InputStream findResource( String resourceName ) throws IOException
224     {
225         return findResource( getEnvironment().getConfigurationPath(), resourceName );
226     }
227 
228     /**
229      * @param path
230      *            The path to the requested resource. If the resource is not found at the specified location
231      *            discovery will be performed.
232      * @param resourceName
233      *            The name of the requested resource.
234      * @return The requested resource as an InputStream.
235      * @throws IOException
236      *             there was an error reading the resource
237      */
238     public static InputStream findResource( String path, String resourceName ) throws IOException
239     {
240         return findResourceURL( path, resourceName ).openStream();
241     }
242 
243     /**
244      * @param resourceName
245      *            The name of the requested resource.
246      * @return The URL of the requested resource.
247      * @throws IOException
248      *             there was an error reading the resource
249      */
250     public static URL findResourceURL( String resourceName ) throws IOException
251     {
252         return findResourceURL( getEnvironment().getConfigurationPath(), resourceName );
253     }
254 
255     /**
256      * @param path
257      *            The path to the requested resource. If the resource is not found at the specified location
258      *            discovery will be performed.
259      * @param resourceName
260      *            The name of the requested resource.
261      * @return The URL of the requested resource.
262      * @throws IOException
263      *             there was an error reading the resource
264      */
265     public static URL findResourceURL( String path, String resourceName ) throws IOException
266     {
267         if ( path == null )
268         {
269             path = "";
270         }
271 
272         if ( resourceName == null )
273         {
274             throw new IOException( "Could not find resource. No resource name specified (null)." );
275         }
276 
277         File file = null;
278 
279         // first try to find the resource in the specified directory
280         // global configuration files should be kept outside the application
281         // in order to easy update the application
282         file = new File( path, resourceName );
283         if ( file.exists() )
284         {
285             try
286             {
287                 Object[] filler = new Object[] { resourceName, path };
288                 String message = MessageFormat.format( "Found resource {0} in directory {1}.", filler );
289 
290                 if ( LOG.isTraceEnabled() )
291                 {
292                     LOG.trace( message );
293                 }
294 
295                 return file.toURL();
296             }
297             catch ( IOException e )
298             {
299                 Object[] filler = new Object[] { resourceName };
300                 String message = MessageFormat.format( "Could not read resource {0}.", filler );
301                 LOG.error( message, e );
302             }
303         }
304 
305         // then try to load the resource by its absolute name
306         file = new File( resourceName );
307         if ( file.exists() )
308         {
309             try
310             {
311                 if ( LOG.isTraceEnabled() )
312                 {
313                     LOG.trace( MessageFormat.format( "Found resource [{0}].", new Object[] { resourceName } ) );
314                 }
315 
316                 return file.toURL();
317             }
318             catch ( IOException e )
319             {
320                 LOG.error(
321                     MessageFormat.format( "Could not read resource {0}.", new Object[] { resourceName } ), e );
322             }
323         }
324 
325         // then by its fully qualified resource name
326         String qualifiedResourceName = path + System.getProperty( "file.separator" ) + resourceName;
327 
328         // special case for empty path on Windows systems
329         if ( path.equals( "" ) )
330         {
331             qualifiedResourceName = "/" + resourceName;
332         }
333 
334         URL resourceUrl = WSAG4JConfiguration.class.getResource( qualifiedResourceName );
335         if ( resourceUrl != null )
336         {
337             if ( LOG.isTraceEnabled() )
338             {
339                 LOG.trace( MessageFormat.format(
340                     "Found resource {0} by the classloader [external name: {1}]", new Object[] {
341                         qualifiedResourceName, resourceUrl.toExternalForm() } ) );
342             }
343 
344             return resourceUrl;
345         }
346 
347         // last try to find the resource by the classloader
348         // this is the default behavior
349         if ( resourceName.startsWith( "/" ) || resourceName.startsWith( "\\" ) )
350         {
351             resourceUrl = WSAG4JConfiguration.class.getResource( resourceName );
352         }
353         else
354         {
355             // we don't want to load the resource relative from MSSConfiguration
356             resourceUrl = WSAG4JConfiguration.class.getResource( "/" + resourceName );
357         }
358 
359         if ( resourceUrl != null )
360         {
361             if ( LOG.isTraceEnabled() )
362             {
363                 LOG.trace( MessageFormat.format(
364                     "Found resource {0} by the classloader [external name: {1}]", new Object[] {
365                         resourceName, resourceUrl.toExternalForm() } ) );
366             }
367 
368             return resourceUrl;
369         }
370 
371         LOG.error( LogMessage.getMessage( "The resource {0} was not found.", resourceName ) );
372         LOG.error( LogMessage.getMessage( "Tried the following directories: [{0}] [{1}]", path,
373             System.getProperty( "java.class.path" ) ) );
374 
375         throw new FileNotFoundException( LogMessage.format(
376             "The resource [{0}] was not found at the system.", resourceName ) );
377     }
378 
379     /**
380      * @param fileName
381      *            The file name of the requested XML configuration file.
382      * @return The XML configuration file as an {@link org.apache.xmlbeans.XmlObject}.
383      * @throws IOException
384      *             the configuration file could not be read or a related error occurred
385      */
386     public static ConfigurationType findWSAG4JConfiguration( String fileName ) throws IOException
387     {
388         try
389         {
390 
391             InputStream resourceInput = findResource( fileName );
392 
393             ConfigurationType result = null;
394 
395             if ( resourceInput != null )
396             {
397                 try
398                 {
399                     result = ConfigurationDocument.Factory.parse( resourceInput ).getConfiguration();
400                 }
401                 catch ( IOException e )
402                 {
403                     String msgText = "Error reading the configuration file {0}. Error: {1}";
404                     String message = LogMessage.format( msgText, fileName, e.getMessage() );
405 
406                     LOG.error( message );
407                     throw new IOException( message );
408 
409                 }
410                 catch ( XmlException e )
411                 {
412                     String msgText = "Error reading the configuration file {0}. Description: {1}";
413                     String message = LogMessage.format( msgText, fileName, e.getMessage() );
414 
415                     LOG.error( message );
416                     throw new IOException( message );
417                 }
418             }
419 
420             return result;
421         }
422         catch ( Exception ex )
423         {
424             String msgText = "Error loading configuration file [{0}]. Message: {1}";
425             String message = LogMessage.format( msgText, fileName, ex.getMessage() );
426             LOG.error( message );
427 
428             return null;
429         }
430     }
431 
432 }