View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *  http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.any23.configuration;
19  
20  import org.slf4j.Logger;
21  import org.slf4j.LoggerFactory;
22  
23  import java.io.IOException;
24  import java.util.Properties;
25  
26  /**
27   * Default implementation of {@link Configuration}. The default property values are read from the
28   * <i>/default-configuration.properties</i> properties file in classpath.
29   *
30   * @author Michele Mostarda (michele.mostarda@gmail.com)
31   */
32  public class DefaultConfiguration implements Configuration {
33  
34      /**
35       * Default configuration file.
36       */
37      public static final String DEFAULT_CONFIG_FILE = "/default-configuration.properties";
38  
39      public static final String FLAG_PROPERTY_ON = "on";
40  
41      public static final String FLAG_PROPERTY_OFF = "off";
42  
43      protected static final Logger logger = LoggerFactory.getLogger(DefaultConfiguration.class);
44  
45      protected static final DefaultConfigurationration.html#DefaultConfiguration">DefaultConfiguration singleton = new DefaultConfiguration();
46  
47      protected final Properties properties;
48  
49      protected DefaultConfiguration(Properties properties) {
50          this.properties = properties;
51      }
52  
53      private DefaultConfiguration() {
54          this(loadDefaultProperties());
55      }
56  
57      /**
58       * @return the singleton configuration instance. Such instance is unmodifiable.
59       */
60      public static synchronized DefaultConfiguration singleton() {
61          return singleton;
62      }
63  
64      /**
65       * @return a copy of the singleton instance. such instance is modifiable.
66       */
67      public static synchronized ModifiableConfiguration copy() {
68          final Properties propertiesCopy = (Properties) singleton.properties.clone();
69          return new DefaultModifiableConfiguration(propertiesCopy);
70      }
71  
72      private static Properties loadDefaultProperties() {
73          final Properties properties = new Properties();
74          try {
75              properties.load(DefaultConfiguration.class.getResourceAsStream(DEFAULT_CONFIG_FILE));
76          } catch (IOException ioe) {
77              throw new IllegalStateException("Error while loading default configuration.", ioe);
78          }
79          return properties;
80      }
81  
82      @Override
83      public synchronized String[] getProperties() {
84          return properties.keySet().toArray(new String[properties.size()]);
85      }
86  
87      @Override
88      public synchronized boolean defineProperty(String propertyName) {
89          return properties.containsKey(propertyName);
90      }
91  
92      @Override
93      public synchronized String getProperty(String propertyName, String defaultValue) {
94          final String value = getPropertyValue(propertyName);
95          if (value == null) {
96              return defaultValue;
97          }
98          return value;
99      }
100 
101     @Override
102     public synchronized String getPropertyOrFail(String propertyName) {
103         final String propertyValue = getPropertyValue(propertyName);
104         if (propertyValue == null) {
105             throw new IllegalArgumentException("The property '" + propertyName + "' is expected to be declared.");
106         }
107         if (propertyValue.trim().length() == 0) {
108             throw new IllegalArgumentException(
109                     "Invalid value '" + propertyValue + "' for property '" + propertyName + "'");
110         }
111         return propertyValue;
112     }
113 
114     @Override
115     public synchronized int getPropertyIntOrFail(String propertyName) {
116         final String value = getPropertyOrFail(propertyName);
117         final String trimValue = value.trim();
118         try {
119             return Integer.parseInt(trimValue);
120         } catch (NumberFormatException nfe) {
121             throw new NumberFormatException("The retrieved property is not a valid Integer: '" + trimValue + "'");
122         }
123     }
124 
125     @Override
126     public synchronized boolean getFlagProperty(final String propertyName) {
127         final String value = getPropertyOrFail(propertyName);
128         if (value == null) {
129             return false;
130         }
131         if (FLAG_PROPERTY_ON.equals(value)) {
132             return true;
133         }
134         if (FLAG_PROPERTY_OFF.equals(value)) {
135             return false;
136         }
137         throw new IllegalArgumentException(String.format(java.util.Locale.ROOT,
138                 "Invalid value [%s] for flag property [%s]. Supported values are %s|%s", value, propertyName,
139                 FLAG_PROPERTY_ON, FLAG_PROPERTY_OFF));
140     }
141 
142     @Override
143     public synchronized String getConfigurationDump() {
144         final String[] defaultProperties = getProperties();
145         final StringBuilder sb = new StringBuilder();
146         sb.append("\n======================= Configuration Properties =======================\n");
147         for (String defaultProperty : defaultProperties) {
148             sb.append(defaultProperty).append('=').append(getPropertyValue(defaultProperty)).append('\n');
149         }
150         sb.append("========================================================================\n");
151         return sb.toString();
152     }
153 
154     private String getPropertyValue(String propertyName) {
155         if (!defineProperty(propertyName)) {
156             if (logger.isDebugEnabled()) {
157                 logger.debug(String.format(java.util.Locale.ROOT,
158                         "Property '%s' is not declared in default configuration file [%s]", propertyName,
159                         DEFAULT_CONFIG_FILE));
160             }
161             return null;
162         }
163         final String systemValue = System.getProperties().getProperty(propertyName);
164         if (systemValue == null) {
165             return properties.getProperty(propertyName);
166         }
167         return systemValue;
168     }
169 
170 }