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 DefaultConfigurationration.html#DefaultConfiguration">DefaultConfiguration singleton = new DefaultConfiguration();
48  
49      protected final Properties properties;
50  
51      protected DefaultConfiguration(Properties properties) {
52          this.properties = properties;
53      }
54  
55      private DefaultConfiguration() {
56          this( loadDefaultProperties() );
57      }
58  
59      /**
60       * @return the singleton configuration instance.
61       *         Such instance is unmodifiable.
62       */
63      public static synchronized DefaultConfiguration singleton() {
64          return singleton;
65      }
66  
67      /**
68       * @return a copy of the singleton instance. such instance is modifiable.
69       */
70      public static synchronized ModifiableConfiguration copy() {
71          final Properties propertiesCopy = (Properties) singleton.properties.clone();
72          return new DefaultModifiableConfiguration(propertiesCopy);
73      }
74  
75      private static Properties loadDefaultProperties() {
76          final Properties properties = new Properties();
77          try {
78              properties.load( DefaultConfiguration.class.getResourceAsStream(DEFAULT_CONFIG_FILE) );
79          } catch (IOException ioe) {
80              throw new IllegalStateException("Error while loading default configuration.", ioe);
81          }
82          return properties;
83      }
84  
85      @Override
86      public synchronized String[] getProperties() {
87          return properties.keySet().toArray( new String[properties.size()] );
88      }
89  
90      @Override
91      public synchronized boolean defineProperty(String propertyName) {
92          return properties.containsKey(propertyName);
93      }
94  
95      @Override
96      public synchronized String getProperty(String propertyName, String defaultValue) {
97          final String value = getPropertyValue(propertyName);
98          if(value == null) {
99              return defaultValue;
100         }
101         return value;
102     }
103 
104     @Override
105     public synchronized String getPropertyOrFail(String propertyName) {
106         final String propertyValue = getPropertyValue(propertyName);
107         if(propertyValue == null) {
108             throw new IllegalArgumentException("The property '" + propertyName + "' is expected to be declared.");
109         }
110         if(  propertyValue.trim().length() == 0) {
111             throw new IllegalArgumentException(
112                     "Invalid value '" + propertyValue + "' for property '" + propertyName + "'"
113             );
114         }
115         return propertyValue;
116     }
117 
118     @Override
119     public synchronized int getPropertyIntOrFail(String propertyName) {
120         final String value = getPropertyOrFail(propertyName);
121         final String trimValue = value.trim();
122         try {
123             return Integer.parseInt(trimValue);
124         } catch (NumberFormatException nfe) {
125             throw new NumberFormatException("The retrieved property is not a valid Integer: '" + trimValue + "'");
126         }
127     }
128 
129     @Override
130     public synchronized boolean getFlagProperty(final String propertyName) {
131         final String value = getPropertyOrFail(propertyName);
132         if(value == null) {
133             return false;
134         }
135         if(FLAG_PROPERTY_ON.equals(value)) {
136             return true;
137         }
138         if(FLAG_PROPERTY_OFF.equals(value)) {
139             return false;
140         }
141         throw new IllegalArgumentException(
142                 String.format(
143                     "Invalid value [%s] for flag property [%s]. Supported values are %s|%s",
144                     value, propertyName, FLAG_PROPERTY_ON, FLAG_PROPERTY_OFF
145                 )
146         );
147     }
148 
149     @Override
150     public synchronized String getConfigurationDump() {
151         final String[] defaultProperties = getProperties();
152         final StringBuilder sb = new StringBuilder();
153         sb.append("\n======================= Configuration Properties =======================\n");
154         for (String defaultProperty : defaultProperties) {
155             sb.append(defaultProperty).append('=').append(getPropertyValue(defaultProperty)).append('\n');
156         }
157         sb.append("========================================================================\n");
158         return sb.toString();
159     }
160 
161     private String getPropertyValue(String propertyName) {
162         if( ! defineProperty(propertyName) ) {
163             if(logger.isDebugEnabled()) {
164                 logger.debug(
165                         String.format(
166                                 "Property '%s' is not declared in default configuration file [%s]",
167                                 propertyName,
168                                 DEFAULT_CONFIG_FILE
169                         )
170                 );
171             }
172             return null;
173         }
174         final String systemValue = System.getProperties().getProperty(propertyName);
175         if(systemValue == null) {
176             return properties.getProperty(propertyName);
177         }
178         return systemValue;
179     }
180 
181 }