View Javadoc

1   /*
2    ~ Copyright 2006-2007 Nicolas De Loof.
3    ~
4    ~ Licensed under the Apache License, Version 2.0 (the "License");
5    ~ you may not use this file except in compliance with the License.
6    ~ You may obtain a copy of the License at
7    ~
8    ~      http://www.apache.org/licenses/LICENSE-2.0
9    ~
10   ~ Unless required by applicable law or agreed to in writing, software
11   ~ distributed under the License is distributed on an "AS IS" BASIS,
12   ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   ~ See the License for the specific language governing permissions and
14   ~ limitations under the License.
15   */
16  package org.jmonit.features;
17  
18  import java.io.InputStream;
19  import java.lang.reflect.Field;
20  import java.net.URL;
21  import java.util.Collection;
22  import java.util.Collections;
23  import java.util.Enumeration;
24  import java.util.Iterator;
25  import java.util.LinkedList;
26  import java.util.Map;
27  import java.util.Properties;
28  import java.util.Set;
29  import java.util.concurrent.ConcurrentHashMap;
30  
31  import org.jmonit.log.Log;
32  import org.jmonit.spi.Factory;
33  import org.jmonit.spi.PluginManager;
34  
35  /**
36   * Default implementation of <code>PluginManager</code>.
37   * 
38   * @author <a href="mailto:nicolas.deloof@gmail.com">Nicolas De Loof</a>
39   */
40  public class DefaultPluginManager
41      implements PluginManager
42  {
43  
44      /**
45       *
46       */
47      private static final String CONFIG = "jmonit.properties";
48  
49      /**
50       *
51       */
52      private static final String DEFAULT = "META-INF/jmonit/default.properties";
53  
54      /**
55       *
56       */
57      private static final String PLUGINS = "META-INF/jmonit/plugins.properties";
58  
59      /** logger */
60      private static Log log = Log.getLog( DefaultPluginManager.class );
61  
62      Map<Class, Factory> features = new ConcurrentHashMap<Class, Factory>();
63  
64      Map<String, Collection<Class>> featuresForGroup =
65          new ConcurrentHashMap<String, Collection<Class>>();
66  
67      /**
68       * Constructor
69       */
70      public DefaultPluginManager()
71      {
72          super();
73          try
74          {
75              readConfiguration();
76          }
77          catch ( Exception e )
78          {
79              log.error( "Failed to load jMonit configuration " + e );
80              System.err
81                  .println( "WARNING : Failed to load jMonit configuration : " + e.getMessage() );
82          }
83      }
84  
85      private ClassLoader getClassLoader()
86      {
87          ClassLoader cl = Thread.currentThread().getContextClassLoader();
88          if ( cl == null )
89          {
90              cl = getClass().getClassLoader();
91          }
92          return cl;
93      }
94  
95      protected void readFeatureGroupsConfiguration( Properties config )
96      {
97          for ( Map.Entry entry : config.entrySet() )
98          {
99              String key = (String) entry.getKey();
100             String value = (String) entry.getValue();
101             Collection<Class> features = featuresForGroup.get( key );
102             if ( features == null )
103             {
104                 features = new LinkedList<Class>();
105                 featuresForGroup.put( key, features );
106             }
107             String[] plugins = value.split( "," );
108             for ( String plugin : plugins )
109             {
110                 Class feature = getFeature( plugin );
111                 if ( feature == null )
112                 {
113                     log.error( "Unknown feature " + value + " requested for tag " + key );
114                     continue;
115                 }
116                 features.add( feature );
117                 log.info( value + " registered as a feature for monitor group " + key );
118             }
119         }
120     }
121 
122     protected void readConfiguration()
123         throws Exception
124     {
125         Properties props = new Properties();
126         Enumeration<URL> modules = getClassLoader().getResources( PLUGINS );
127         while ( modules.hasMoreElements() )
128         {
129             URL url = (URL) modules.nextElement();
130             props.load( url.openStream() );
131         }
132         registerFeatures( props );
133 
134         props.clear();
135 
136         InputStream config = getClassLoader().getResourceAsStream( DEFAULT );
137         if ( config != null )
138         {
139             props.load( config );
140         }
141         config = getClassLoader().getResourceAsStream( CONFIG );
142         if ( config != null )
143         {
144             props.load( config );
145         }
146         readFeatureGroupsConfiguration( props );
147     }
148 
149     protected void registerFeatures( Properties config )
150         throws Exception
151     {
152         Set keys = config.keySet();
153         for ( Iterator iterator = keys.iterator(); iterator.hasNext(); )
154         {
155             String key = (String) iterator.next();
156             try
157             {
158                 Class feature = Class.forName( key );
159                 Factory factory = null;
160                 String property = config.getProperty( key );
161                 int dash = property.indexOf( "#" );
162                 String field = null;
163                 if ( dash > 0 )
164                 {
165                     field = property.substring( dash + 1 ).trim();
166                     property = property.substring( 0, dash );
167                 }
168                 Class factoryClass = Class.forName( property );
169                 if ( field != null )
170                 {
171                     Field f = factoryClass.getField( field );
172                     if ( !Factory.class.isAssignableFrom( f.getType() ) )
173                     {
174                         log.error( property + " in class  " + factoryClass
175                             + " is not a plugin Factory" );
176                         log.error( key + " feature will be disabled" );
177                         continue;
178                     }
179                     factory = (Factory) f.get( factoryClass );
180                 }
181                 else
182                 {
183                     if ( !Factory.class.isAssignableFrom( factoryClass ) )
184                     {
185                         log.error( factoryClass + " is not a plugin Factory" );
186                         log.error( key + " feature will be disabled" );
187                         continue;
188                     }
189                     factory = (Factory) factoryClass.newInstance();
190                 }
191                 registerPlugin( factory, feature );
192             }
193             catch ( Exception e )
194             {
195                 log.error( "Fail to register " + key + " : " + e );
196             }
197         }
198     }
199 
200     /**
201      * {@inheritDoc}
202      * 
203      * @see org.jmonit.spi.PluginManager#registerPlugin(org.jmonit.spi.Factory,
204      * Class)
205      */
206     public void registerPlugin( Factory factory, Class role )
207     {
208         if ( log.isDebugEnabled() )
209         {
210             String name = factory.getClass().getName();
211             log.info( "register plugin factory " + name + " for feature " + role );
212         }
213         features.put( role, factory );
214     }
215 
216     /**
217      * {@inheritDoc}
218      * 
219      * @see org.jmonit.spi.PluginManager#getFactory(java.lang.Class)
220      */
221     public <T> Factory<T> getFactory( Class<T> feature )
222     {
223         return features.get( feature );
224     }
225 
226     /**
227      * {@inheritDoc}
228      * 
229      * @see org.jmonit.spi.PluginManager#getFeatures(java.lang.String)
230      */
231     public Collection<Class> getFeatures( String tag )
232     {
233         if ( tag == null )
234         {
235             return Collections.<Class> emptySet();
236         }
237         Collection<Class> features = featuresForGroup.get( tag );
238         return features != null ? features : Collections.<Class> emptySet();
239     }
240 
241     /**
242      * {@inheritDoc}
243      * 
244      * @see org.jmonit.spi.PluginManager#getFeature(java.lang.String)
245      */
246     public Class getFeature( String name )
247     {
248         if ( name != null )
249         {
250             // Request for a montior feature
251             try
252             {
253                 return Class.forName( "org.jmonit.features." + name );
254             }
255             catch ( ClassNotFoundException e )
256             {
257                 // Not a default feature. Maybe a custom one ?
258                 try
259                 {
260                     return Class.forName( name );
261                 }
262                 catch ( ClassNotFoundException ex )
263                 {
264                     log.error( "Unknown feature requested " + name );
265                     // Ignore
266                 }
267             }
268         }
269         return null;
270     }
271 }