View Javadoc

1   /*
2    * Copyright 2008-2010 Digital Enterprise Research Institute (DERI)
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  
17  package org.deri.any23.configuration;
18  
19  import org.slf4j.Logger;
20  import org.slf4j.LoggerFactory;
21  
22  import java.io.IOException;
23  import java.util.Properties;
24  
25  /**
26   * Default implementation of {@link Configuration}.
27   * The default property values are read from the
28   * <i>/default-configuration.properties</i> properties file
29   * in classpath.
30   *
31   * @author Michele Mostarda (michele.mostarda@gmail.com)
32   */
33  public class DefaultConfiguration implements Configuration {
34  
35      /**
36       * Default configuration file.
37       */
38      public static final String DEFAULT_CONFIG_FILE = "/default-configuration.properties";
39  
40      public static final String FLAG_PROPERTY_ON  = "on";
41  
42      public static final String FLAG_PROPERTY_OFF = "off";
43  
44      protected static final Logger logger = LoggerFactory.getLogger(DefaultConfiguration.class);
45  
46      protected static final DefaultConfiguration singleton = new DefaultConfiguration();
47  
48      protected final Properties properties;
49  
50      /**
51       * @return the singleton configuration instance.
52       *         Such instance is unmodifiable.
53       */
54      public static synchronized DefaultConfiguration singleton() {
55          return singleton;
56      }
57  
58      /**
59       * @return a copy of the singleton instance. such instance is modifiable.
60       */
61      public static synchronized ModifiableConfiguration copy() {
62          final Properties propertiesCopy = (Properties) singleton.properties.clone();
63          return new DefaultModifiableConfiguration(propertiesCopy);
64      }
65  
66      private static Properties loadDefaultProperties() {
67          final Properties properties = new Properties();
68          try {
69              properties.load( DefaultConfiguration.class.getResourceAsStream(DEFAULT_CONFIG_FILE) );
70          } catch (IOException ioe) {
71              throw new IllegalStateException("Error while loading default configuration.", ioe);
72          }
73          return properties;
74      }
75  
76      protected DefaultConfiguration(Properties properties) {
77          this.properties = properties;
78      }
79  
80      private DefaultConfiguration() {
81          this( loadDefaultProperties() );
82      }
83  
84      public synchronized String[] getProperties() {
85          return properties.keySet().toArray( new String[properties.size()] );
86      }
87  
88      public synchronized boolean defineProperty(String propertyName) {
89          return properties.containsKey(propertyName);
90      }
91  
92      public synchronized String getProperty(String propertyName, String defaultValue) {
93          final String value = getPropertyValue(propertyName);
94          if(value == null) {
95              return defaultValue;
96          }
97          return value;
98      }
99  
100     public synchronized String getPropertyOrFail(String propertyName) {
101         final String propertyValue = getPropertyValue(propertyName);
102         if(propertyValue == null) {
103             throw new IllegalArgumentException("The property '" + propertyName + "' is expected to be declared.");
104         }
105         if(  propertyValue.trim().length() == 0) {
106             throw new IllegalArgumentException(
107                     "Invalid value '" + propertyValue + "' for property '" + propertyName + "'"
108             );
109         }
110         return propertyValue;
111     }
112 
113     public synchronized int getPropertyIntOrFail(String propertyName) {
114         final String value = getPropertyOrFail(propertyName);
115         final String trimValue = value.trim();
116         try {
117             return Integer.parseInt(trimValue);
118         } catch (NumberFormatException nfe) {
119             throw new NumberFormatException("The retrieved property is not a valid Integer: '" + trimValue + "'");
120         }
121     }
122 
123     public synchronized boolean getFlagProperty(final String propertyName) {
124         final String value = getPropertyOrFail(propertyName);
125         if(value == null) {
126             return false;
127         }
128         if(FLAG_PROPERTY_ON.equals(value)) {
129             return true;
130         }
131         if(FLAG_PROPERTY_OFF.equals(value)) {
132             return false;
133         }
134         throw new IllegalArgumentException(
135                 String.format(
136                     "Invalid value [%s] for flag property [%s]. Supported values are %s|%s",
137                     value, propertyName, FLAG_PROPERTY_ON, FLAG_PROPERTY_OFF
138                 )
139         );
140     }
141 
142     public synchronized String getConfigurationDump() {
143         final String[] defaultProperties = getProperties();
144         final StringBuilder sb = new StringBuilder();
145         sb.append("\n======================= Configuration Properties =======================\n");
146         for (String defaultProperty : defaultProperties) {
147             sb.append(defaultProperty).append('=').append(getPropertyValue(defaultProperty)).append('\n');
148         }
149         sb.append("========================================================================\n");
150         return sb.toString();
151     }
152 
153     private String getPropertyValue(String propertyName) {
154         if( ! defineProperty(propertyName) ) {
155             if(logger.isDebugEnabled()) {
156                 logger.debug(
157                         String.format(
158                                 "Property '%s' is not declared in default configuration file [%s]",
159                                 propertyName,
160                                 DEFAULT_CONFIG_FILE
161                         )
162                 );
163             }
164             return null;
165         }
166         final String systemValue = System.getProperties().getProperty(propertyName);
167         if(systemValue == null) {
168             return properties.getProperty(propertyName);
169         }
170         return systemValue;
171     }
172 
173 }