View Javadoc

1   /*
2    * Copyright 2004-2005 Dan Washusen
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.reactive.configuration;
18  
19  import org.springframework.core.io.Resource;
20  import org.springframework.core.io.ClassPathResource;
21  import org.springframework.core.io.FileSystemResource;
22  import org.springframework.beans.factory.InitializingBean;
23  import org.springframework.beans.factory.BeanInitializationException;
24  import org.springframework.util.PropertiesPersister;
25  import org.springframework.util.DefaultPropertiesPersister;
26  import org.igfay.jfig.*;
27  import org.reactive.beans.factory.config.PlaceholderEvaluator;
28  import org.reactive.beans.factory.config.Placeholder;
29  import org.reactive.beans.factory.config.InvalidPlaceholderException;
30  import org.reactive.beans.factory.config.DefaultPlaceholder;
31  import org.reactive.beans.factory.config.properties.PropertiesPlaceholderEvaluator;
32  import org.apache.commons.logging.Log;
33  import org.apache.commons.logging.LogFactory;
34  
35  import java.io.InputStream;
36  import java.io.IOException;
37  import java.io.InputStreamReader;
38  import java.util.Properties;
39  import java.util.Enumeration;
40  
41  /***
42   * This class merges properties from several sources into one Properties object.
43   *
44   * <p>An example of the bean factory configuration required for Commons Configuration</p>
45   * <pre>
46   * TODO: Add example XML
47   * </pre>
48   *
49   * <p>
50   * Note: This class is basically Spring's org.springframework.beans.factory.config.PropertyResourceConfigurer
51   * by Juergen Hoeller with a few things moved to other classes.
52   * </p>
53   *
54   * @author Dan Washusen
55   * @version $Id: PropertiesConfigurationFactory.java,v 1.1 2004/12/30 23:28:28 dan_washusen Exp $
56   * @since 31.12.2004
57   */
58  public class PropertiesConfigurationFactory
59          implements InitializingBean {
60      protected final Log logger = LogFactory.getLog(PropertiesConfigurationFactory.class);
61  
62  	private Properties properties;
63  
64  	private Resource[] locations;
65  
66  	private String fileEncoding;
67  
68  	private PropertiesPersister propertiesPersister = new DefaultPropertiesPersister();
69  
70  	private boolean ignoreResourceNotFound = false;
71  
72      private Properties mergedProperties;
73  
74  	/***
75  	 * Set local properties, e.g. via the "props" tag in XML bean definitions.
76  	 * These can be considered defaults, to be overridden by properties
77  	 * loaded from files.
78  	 * @see #setLocation
79  	 * @see #setLocations
80  	 */
81  	public void setProperties(Properties properties) {
82  		this.properties = properties;
83  	}
84  
85  	/***
86  	 * Set a location of a properties file to be loaded.
87  	 * @see #setLocations
88  	 */
89  	public void setLocation(Resource location) {
90  		this.locations = new Resource[] {location};
91  	}
92  
93  	/***
94  	 * Set locations of properties files to be loaded.
95  	 * @see #setLocation
96  	 */
97  	public void setLocations(Resource[] locations) {
98  		this.locations = locations;
99  	}
100 
101 	/***
102 	 * Set the encoding to use for parsing properties files.
103 	 * Default is none, using java.util.Properties' default encoding.
104 	 * @see org.springframework.util.PropertiesPersister#load
105 	 */
106 	public void setFileEncoding(String encoding) {
107 		this.fileEncoding = encoding;
108 	}
109 
110 	/***
111 	 * Set the PropertiesPersister to use for parsing properties files.
112 	 * The default is DefaultPropertiesPersister.
113 	 * @see org.springframework.util.DefaultPropertiesPersister
114 	 */
115 	public void setPropertiesPersister(PropertiesPersister propertiesPersister) {
116 		this.propertiesPersister = propertiesPersister;
117 	}
118 
119 	/***
120 	 * Set if failure to find the property resource should be ignored.
121 	 * True is appropriate if the properties file is completely optional.
122 	 * Default is false.
123 	 */
124 	public void setIgnoreResourceNotFound(boolean ignoreResourceNotFound) {
125 		this.ignoreResourceNotFound = ignoreResourceNotFound;
126 	}
127 
128     /***
129      * Merges the properties provided by {@link #setLocations(org.springframework.core.io.Resource[])} and
130      * {@link #setProperties(java.util.Properties)} after all properties have been set by the bean factory.
131      * @throws Exception If an IO error occurs while attempting to read a properties file from disk
132      */
133     public void afterPropertiesSet()
134             throws Exception {
135         this.mergedProperties = new Properties();
136 
137 		if (this.properties != null) {
138 			// use propertyNames enumeration to also catch default properties
139 			for (Enumeration en = this.properties.propertyNames(); en.hasMoreElements();) {
140 				String key = (String) en.nextElement();
141 				mergedProperties.setProperty(key, this.properties.getProperty(key));
142 			}
143 		}
144 
145 		if (this.locations != null) {
146 			for (int i = 0; i < this.locations.length; i++) {
147 				Resource location = this.locations[i];
148 				if (logger.isInfoEnabled()) {
149 					logger.info("Loading properties from " + location + "");
150 				}
151 				try {
152 					InputStream is = location.getInputStream();
153 					try {
154 						if (this.fileEncoding != null) {
155 							this.propertiesPersister.load(mergedProperties, new InputStreamReader(is, this.fileEncoding));
156 						}
157 						else {
158 							this.propertiesPersister.load(mergedProperties, is);
159 						}
160 					}
161 					finally {
162 						is.close();
163 					}
164 				}
165 				catch (IOException ex) {
166 					String msg = "Could not load properties from " + location;
167 					if (this.ignoreResourceNotFound) {
168 						if (logger.isWarnEnabled()) {
169 							logger.warn(msg + ": " + ex.getMessage());
170 						}
171 					}
172 					else {
173 						throw new BeanInitializationException(msg, ex);
174 					}
175 				}
176 			}
177 		}
178     }
179 
180     /***
181      * Returns the merge properties, the result of merging the properties specified by {@link #setLocation(org.springframework.core.io.Resource)},
182      * {@link #setLocations(org.springframework.core.io.Resource[])} and {@link #setProperties(java.util.Properties)}.
183      * @return The merged properties
184      */
185     public Properties getMergedProperties() {
186         return mergedProperties;
187     }
188 
189     /***
190      * A convenience method that returns the merged properties.
191      * @return The merged properties
192      */
193     public Properties getConfiguration() {
194         return getMergedProperties();
195     }
196 }