View Javadoc

1   package org.apache.onami.configuration;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import static com.google.inject.name.Names.named;
23  import static java.lang.String.format;
24  import static org.apache.onami.configuration.PropertiesIterator.newPropertiesIterator;
25  
26  import java.io.File;
27  import java.net.MalformedURLException;
28  import java.net.URI;
29  import java.net.URL;
30  import java.util.Iterator;
31  import java.util.LinkedList;
32  import java.util.List;
33  import java.util.Map;
34  import java.util.Map.Entry;
35  import java.util.Properties;
36  
37  import org.apache.onami.configuration.binder.PropertyValueBindingBuilder;
38  import org.apache.onami.configuration.binder.XMLPropertiesFormatBindingBuilder;
39  
40  import com.google.inject.AbstractModule;
41  import com.google.inject.ProvisionException;
42  
43  /**
44   * The ConfigurationModule simplifies the task of loading configurations in Google Guice.
45   */
46  public abstract class ConfigurationModule
47      extends AbstractModule
48  {
49  
50      /**
51       * The environment variable prefix, {@code env.}
52       */
53      private static final String ENV_PREFIX = "env.";
54  
55      /**
56       * The {@code classpath} URL scheme constant
57       */
58      private static final String CLASSPATH_SCHEME = "classpath";
59  
60      private List<PropertiesURLReader> readers;
61  
62      @Override
63      protected final void configure()
64      {
65          if ( readers != null )
66          {
67              throw new IllegalStateException( "Re-entry not allowed" );
68          }
69  
70          readers = new LinkedList<PropertiesURLReader>();
71  
72          bindConfigurations();
73  
74          try
75          {
76              for ( PropertiesURLReader reader : readers )
77              {
78                  try
79                  {
80                      bindProperties( reader.readConfiguration() );
81                  }
82                  catch ( Exception e )
83                  {
84                      addError( "An error occurred while reading properties from '%s': %s", reader.getUrl(),
85                                e.getMessage() );
86                  }
87              }
88          }
89          finally
90          {
91              readers = null;
92          }
93      }
94  
95      /**
96       *
97       */
98      protected abstract void bindConfigurations();
99  
100     /**
101      * Binds to a property with the given name.
102      *
103      * @param name The property name
104      * @return The property value binder
105      */
106     protected PropertyValueBindingBuilder bindProperty( final String name )
107     {
108         checkNotNull( name, "Property name cannot be null." );
109 
110         return new PropertyValueBindingBuilder()
111         {
112 
113             public void toValue( final String value )
114             {
115                 checkNotNull( value, "Null value not admitted for property '%s's", name );
116 
117                 bindConstant().annotatedWith( named( name ) ).to( value );
118             }
119 
120         };
121     }
122 
123     /**
124      *
125      * @param properties
126      * @return
127      */
128     protected void bindProperties( Properties properties )
129     {
130         checkNotNull( properties, "Parameter 'properties' must be not null" );
131 
132         bindProperties( newPropertiesIterator( properties ) );
133     }
134 
135     /**
136      *
137      * @param properties
138      */
139     protected void bindProperties( Iterable<Entry<String, String>> properties )
140     {
141         checkNotNull( properties, "Parameter 'properties' must be not null" );
142 
143         bindProperties( properties.iterator() );
144     }
145 
146     /**
147      *
148      * @param properties
149      */
150     protected void bindProperties( Iterator<Entry<String, String>> properties )
151     {
152         checkNotNull( properties, "Parameter 'properties' must be not null" );
153 
154         while ( properties.hasNext() )
155         {
156             Entry<String, String> property = properties.next();
157             bindProperty( property.getKey() ).toValue( property.getValue() );
158         }
159     }
160 
161     /**
162      * Add the Environment Variables properties, prefixed by {@code env.}.
163      */
164     protected void bindSystemProperties()
165     {
166         bindProperties( System.getProperties() );
167     }
168 
169     /**
170      *
171      * @param properties
172      * @return
173      */
174     protected void bindProperties( Map<String, String> properties )
175     {
176         checkNotNull( properties, "Parameter 'properties' must be not null" );
177 
178         bindProperties( newPropertiesIterator( properties ) );
179     }
180 
181     /**
182      * Add the System Variables properties.
183      */
184     protected void bindEnvironmentVariables()
185     {
186         bindProperties( newPropertiesIterator( ENV_PREFIX, System.getenv() ) );
187     }
188 
189     /**
190      *
191      *
192      * @param propertiesResource
193      * @return
194      */
195     protected XMLPropertiesFormatBindingBuilder bindProperties( final File propertiesResource )
196     {
197         checkNotNull( propertiesResource, "Parameter 'propertiesResource' must be not null" );
198 
199         return bindProperties( propertiesResource.toURI() );
200     }
201 
202     /**
203      *
204      *
205      * @param propertiesResource
206      * @return
207      */
208     protected XMLPropertiesFormatBindingBuilder bindProperties( final URI propertiesResource )
209     {
210         checkNotNull( propertiesResource, "Parameter 'propertiesResource' must be not null" );
211 
212         if ( CLASSPATH_SCHEME.equals( propertiesResource.getScheme() ) )
213         {
214             String path = propertiesResource.getPath();
215             if ( propertiesResource.getHost() != null )
216             {
217                 path = propertiesResource.getHost() + path;
218             }
219             return bindProperties( path );
220         }
221 
222         try
223         {
224             return bindProperties( propertiesResource.toURL() );
225         }
226         catch ( MalformedURLException e )
227         {
228             throw new ProvisionException( format( "URI '%s' not supported: %s", propertiesResource, e.getMessage() ) );
229         }
230     }
231 
232     /**
233      *
234      * @param classPathResource
235      * @return
236      */
237     protected XMLPropertiesFormatBindingBuilder bindProperties( final String classPathResource )
238     {
239         return bindProperties( classPathResource, getClass().getClassLoader() );
240     }
241 
242     /**
243      *
244      * @param classPathResource
245      * @param classLoader
246      * @return
247      */
248     protected XMLPropertiesFormatBindingBuilder bindProperties( final String classPathResource,
249                                                                 final ClassLoader classLoader )
250     {
251         checkNotNull( classPathResource, "Parameter 'classPathResource' must be not null" );
252         checkNotNull( classLoader, "Parameter 'classLoader' must be not null" );
253 
254         String resourceURL = classPathResource;
255         if ( '/' == classPathResource.charAt( 0 ) )
256         {
257             resourceURL = classPathResource.substring( 1 );
258         }
259 
260         URL url = classLoader.getResource( resourceURL );
261         checkNotNull( url,
262                       "ClassPath resource '%s' not found, make sure it is in the ClassPath or you're using the right ClassLoader",
263                       classPathResource );
264 
265         return bindProperties( url );
266     }
267 
268     /**
269      *
270      * @param propertiesResource
271      * @return
272      */
273     protected XMLPropertiesFormatBindingBuilder bindProperties( final URL propertiesResource )
274     {
275         checkNotNull( propertiesResource, "parameter 'propertiesResource' must not be null" );
276 
277         PropertiesURLReader reader = new PropertiesURLReader( propertiesResource );
278         readers.add( reader );
279         return reader;
280     }
281 
282     private static void checkNotNull( Object object, String messageFormat, Object...args )
283     {
284         if ( object == null )
285         {
286             throw new IllegalArgumentException( format( messageFormat, args ) );
287         }
288     }
289 
290 }