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}.
28   * The default property values are read from the
29   * <i>/default-configuration.properties</i> properties file
30   * in classpath.
31   *
32   * @author Michele Mostarda (michele.mostarda@gmail.com)
33   */
34  public class DefaultConfiguration implements Configuration {
35  
36      /**
37       * Default configuration file.
38       */
39      public static final String DEFAULT_CONFIG_FILE = "/default-configuration.properties";
40  
41      public static final String FLAG_PROPERTY_ON  = "on";
42  
43      public static final String FLAG_PROPERTY_OFF = "off";
44  
45      protected static final Logger logger = LoggerFactory.getLogger(DefaultConfiguration.class);
46  
47      protected static final DefaultConfiguration singleton = new DefaultConfiguration();
48  
49      protected final Properties properties;
50  
51      /**
52       * @return the singleton configuration instance.
53       *         Such instance is unmodifiable.
54       */
55      public static synchronized DefaultConfiguration singleton() {
56          return singleton;
57      }
58  
59      /**
60       * @return a copy of the singleton instance. such instance is modifiable.
61       */
62      public static synchronized ModifiableConfiguration copy() {
63          final Properties propertiesCopy = (Properties) singleton.properties.clone();
64          return new DefaultModifiableConfiguration(propertiesCopy);
65      }
66  
67      private static Properties loadDefaultProperties() {
68          final Properties properties = new Properties();
69          try {
70              properties.load( DefaultConfiguration.class.getResourceAsStream(DEFAULT_CONFIG_FILE) );
71          } catch (IOException ioe) {
72              throw new IllegalStateException("Error while loading default configuration.", ioe);
73          }
74          return properties;
75      }
76  
77      protected DefaultConfiguration(Properties properties) {
78          this.properties = properties;
79      }
80  
81      private DefaultConfiguration() {
82          this( loadDefaultProperties() );
83      }
84  
85      public synchronized String[] getProperties() {
86          return properties.keySet().toArray( new String[properties.size()] );
87      }
88  
89      public synchronized boolean defineProperty(String propertyName) {
90          return properties.containsKey(propertyName);
91      }
92  
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     public synchronized String getPropertyOrFail(String propertyName) {
102         final String propertyValue = getPropertyValue(propertyName);
103         if(propertyValue == null) {
104             throw new IllegalArgumentException("The property '" + propertyName + "' is expected to be declared.");
105         }
106         if(  propertyValue.trim().length() == 0) {
107             throw new IllegalArgumentException(
108                     "Invalid value '" + propertyValue + "' for property '" + propertyName + "'"
109             );
110         }
111         return propertyValue;
112     }
113 
114     public synchronized int getPropertyIntOrFail(String propertyName) {
115         final String value = getPropertyOrFail(propertyName);
116         final String trimValue = value.trim();
117         try {
118             return Integer.parseInt(trimValue);
119         } catch (NumberFormatException nfe) {
120             throw new NumberFormatException("The retrieved property is not a valid Integer: '" + trimValue + "'");
121         }
122     }
123 
124     public synchronized boolean getFlagProperty(final String propertyName) {
125         final String value = getPropertyOrFail(propertyName);
126         if(value == null) {
127             return false;
128         }
129         if(FLAG_PROPERTY_ON.equals(value)) {
130             return true;
131         }
132         if(FLAG_PROPERTY_OFF.equals(value)) {
133             return false;
134         }
135         throw new IllegalArgumentException(
136                 String.format(
137                     "Invalid value [%s] for flag property [%s]. Supported values are %s|%s",
138                     value, propertyName, FLAG_PROPERTY_ON, FLAG_PROPERTY_OFF
139                 )
140         );
141     }
142 
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(
158                         String.format(
159                                 "Property '%s' is not declared in default configuration file [%s]",
160                                 propertyName,
161                                 DEFAULT_CONFIG_FILE
162                         )
163                 );
164             }
165             return null;
166         }
167         final String systemValue = System.getProperties().getProperty(propertyName);
168         if(systemValue == null) {
169             return properties.getProperty(propertyName);
170         }
171         return systemValue;
172     }
173 
174 }