001: /*
002: * Copyright 2006-2007, Unitils.org
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.unitils.core;
017:
018: import org.apache.commons.logging.Log;
019: import org.apache.commons.logging.LogFactory;
020: import static org.unitils.thirdparty.org.apache.commons.io.IOUtils.closeQuietly;
021: import static org.unitils.util.PropertyUtils.getString;
022:
023: import java.io.File;
024: import java.io.FileInputStream;
025: import java.io.InputStream;
026: import java.util.Properties;
027:
028: /**
029: * Utility that loads the configuration of unitils.
030: * <p/>
031: * Unitils settings can be defined in 3 files:<ul>
032: * <li><b>unitils-default.properties</b> - a fixed file packaged in the unitils jar that contains all predefined defaults.
033: * This file should normally not be modified.</li>
034: * <li><b>unitils.properties</b> - a file somewhere in the classpath or user.home dir that contains all custom configuration
035: * settings. Settings in this file will override the default settings. This is where you should put your project
036: * specific configuration</li>
037: * <li><b>unitils-local.properties</b> - a file somewhere in the classpath or user.home that contains machine/user local
038: * configuration. Eg the database schema specific to the local user could be defined here. Settings in this file
039: * will override the unitil default and custom settings.</li>
040: * </ul>
041: * The name of the custom settings file (unitils.properties) is defined by the {@link #PROPKEY_CUSTOM_CONFIGURATION}
042: * property in the default settings. The name of the local settings file (unitils-local.propeties) is defined
043: * by the {@link #PROPKEY_LOCAL_CONFIGURATION} in the custom or default settings. If these properties are set to
044: * null or empty, the corresponding property file will not be loaded.
045: * <p/>
046: * A runtime exception is thrown when the default properties cannot be loaded.
047: * A warning is logged when the custom propreties cannot be loaded.
048: * A debug message is logged when the local properties cannot be loaded.
049: *
050: * @author Tim Ducheyne
051: * @author Filip Neven
052: */
053: public class ConfigurationLoader {
054:
055: /**
056: * Name of the fixed configuration file that contains all defaults
057: */
058: public static final String DEFAULT_PROPERTIES_FILE_NAME = "unitils-default.properties";
059:
060: /**
061: * Property in the defaults configuration file that contains the name of the custom configuration file
062: */
063: public static final String PROPKEY_CUSTOM_CONFIGURATION = "unitils.configuration.customFileName";
064:
065: /**
066: * Property in the defaults and/or custom configuration file that contains the name of
067: * the user local configuration file
068: */
069: public static final String PROPKEY_LOCAL_CONFIGURATION = "unitils.configuration.localFileName";
070:
071: /* The logger instance for this class */
072: private static Log logger = LogFactory
073: .getLog(ConfigurationLoader.class);
074:
075: /**
076: * Creates and loads all configuration settings.
077: *
078: * @return the settings, not null
079: */
080: public Properties loadConfiguration() {
081: return loadConfiguration(null);
082: }
083:
084: /**
085: * Creates and loads all configuration settings.
086: *
087: * @param customConfigurationFileName The name of the custom configuration file.
088: * May be null: if so, the fileName is retrieved from the default properties.
089: *
090: * @return the settings, not null
091: */
092: public Properties loadConfiguration(
093: String customConfigurationFileName) {
094: Properties defaultProperties = createDefaultProperties();
095: Properties customProperties = createCustomProperties(
096: defaultProperties, customConfigurationFileName);
097: Properties localProperties = createLocalProperties(
098: defaultProperties, customProperties);
099:
100: Properties result = new Properties();
101: result.putAll(defaultProperties);
102: if (customProperties != null) {
103: result.putAll(customProperties);
104: }
105: if (localProperties != null) {
106: result.putAll(localProperties);
107: }
108: return result;
109: }
110:
111: /**
112: * Creates and loads the default configuration settings from the {@link #DEFAULT_PROPERTIES_FILE_NAME} file.
113: *
114: * @return the defaults, not null
115: * @throws RuntimeException if the file cannot be found or loaded
116: */
117: protected Properties createDefaultProperties() {
118: InputStream inputStream = null;
119: try {
120: Properties properties = new Properties();
121: inputStream = getClass().getClassLoader()
122: .getResourceAsStream(DEFAULT_PROPERTIES_FILE_NAME);
123: if (inputStream == null) {
124: throw new UnitilsException("Main configuration file: "
125: + DEFAULT_PROPERTIES_FILE_NAME + " not found.");
126: }
127: properties.load(inputStream);
128: logger
129: .info("Loaded main configuration file "
130: + DEFAULT_PROPERTIES_FILE_NAME
131: + " from classpath.");
132: return properties;
133:
134: } catch (Exception e) {
135: throw new UnitilsException(
136: "Unable to load main configuration file: "
137: + DEFAULT_PROPERTIES_FILE_NAME, e);
138: } finally {
139: closeQuietly(inputStream);
140: }
141: }
142:
143: /**
144: * Creates and loads the custom configuration settings. The name of the settings file is defined by the
145: * {@link #PROPKEY_CUSTOM_CONFIGURATION} property in the given default configuration.
146: *
147: * @param defaultProperties the default settings, not null
148: * @param customConfigurationFileName TODO
149: * @return the custom settings, null if not found or not loaded
150: */
151: protected Properties createCustomProperties(
152: Properties defaultProperties,
153: String customConfigurationFileName) {
154: if (customConfigurationFileName == null) {
155: customConfigurationFileName = getString(
156: PROPKEY_CUSTOM_CONFIGURATION, null,
157: defaultProperties);
158: }
159: if (customConfigurationFileName == null) {
160: // loading of local settings disabled
161: return null;
162: }
163:
164: InputStream inputStream = null;
165: try {
166: Properties properties = new Properties();
167: inputStream = getClass().getClassLoader()
168: .getResourceAsStream(customConfigurationFileName);
169: if (inputStream == null) {
170: logger.info("No custom configuration file "
171: + customConfigurationFileName + " found.");
172: return null;
173: }
174: properties.load(inputStream);
175: logger.info("Loaded custom configuration file "
176: + customConfigurationFileName + " from classpath.");
177: return properties;
178:
179: } catch (Exception e) {
180: throw new UnitilsException(
181: "Unable to load custom configuration file: "
182: + customConfigurationFileName, e);
183: } finally {
184: closeQuietly(inputStream);
185: }
186: }
187:
188: /**
189: * Creates and loads the local configuration settings. The name of the settings file is defined by the
190: * {@link #PROPKEY_LOCAL_CONFIGURATION} property in the given custom or default configuration.
191: *
192: * @param defaultProperties the default properties, not null
193: * @param customProperties the custom properties, can be null
194: * @return the local properties, null if not found or not loaded
195: */
196: protected Properties createLocalProperties(
197: Properties defaultProperties, Properties customProperties) {
198: String localPropertiesFileName = null;
199: if (customProperties != null) {
200: // try custom settings
201: localPropertiesFileName = getString(
202: PROPKEY_LOCAL_CONFIGURATION, null, customProperties);
203: }
204: if (localPropertiesFileName == null) {
205: // not found in custom settings, try defaults
206: localPropertiesFileName = getString(
207: PROPKEY_LOCAL_CONFIGURATION, null,
208: defaultProperties);
209: }
210: if (localPropertiesFileName == null) {
211: // loading of local settings disabled
212: return null;
213: }
214:
215: InputStream inputStream = null;
216: try {
217: Properties properties = new Properties();
218:
219: // try loading from the user home folder
220: String userHomeDir = System.getProperty("user.home");
221: File localPropertiesFile = new File(userHomeDir,
222: localPropertiesFileName);
223: if (localPropertiesFile.exists()) {
224: inputStream = new FileInputStream(localPropertiesFile);
225: properties.load(inputStream);
226: logger.info("Loaded local configuration file "
227: + localPropertiesFileName + " from "
228: + localPropertiesFile);
229: return properties;
230: }
231:
232: // try loading from classpath
233: inputStream = getClass().getClassLoader()
234: .getResourceAsStream(localPropertiesFileName);
235: if (inputStream == null) {
236: logger.info("No local configuration file "
237: + localPropertiesFileName + " found.");
238: return null;
239: }
240: properties.load(inputStream);
241: logger.info("Loaded local configuration file "
242: + localPropertiesFileName + " from classpath.");
243: return properties;
244:
245: } catch (Exception e) {
246: throw new UnitilsException(
247: "Unable to load local configuration file: "
248: + localPropertiesFileName, e);
249: } finally {
250: closeQuietly(inputStream);
251: }
252: }
253:
254: }
|