001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.cocoon.util;
018:
019: import org.apache.excalibur.source.SourceResolver;
020: import org.apache.excalibur.source.Source;
021: import org.apache.excalibur.source.TraversableSource;
022: import org.apache.avalon.framework.logger.Logger;
023:
024: import java.util.List;
025: import java.util.ArrayList;
026: import java.util.Properties;
027: import java.util.Iterator;
028: import java.util.Map;
029: import java.util.Collections;
030: import java.io.File;
031: import java.io.FileInputStream;
032: import java.io.IOException;
033: import java.io.InputStream;
034:
035: /**
036: * This object holds the property settings for Cocoon. This interface is loosely based on the Settings interface
037: * introduced in 2.2 but is note equivalent to it as it is only meant to hold configuration properties.
038: *
039: * @version $Id: PropertySettings.java 433543 2006-08-22 06:22:54Z crossley $
040: */
041: public class PropertySettings implements Settings {
042:
043: /** The list of properties used to configure Cocoon. */
044: private Map properties = new java.util.HashMap();
045:
046: /** Parameter map for the context protocol */
047: protected static final Map CONTEXT_PARAMETERS = Collections
048: .singletonMap("force-traversable", Boolean.TRUE);
049:
050: /**
051: * Initialize the settings for Cocoon.
052: * This method reads several property files and merges the result. If there
053: * is more than one definition for a property, the last one wins.
054: * The property files are read in the following order:
055: * 1) context://WEB-INF/properties/*.properties
056: * Default values for the core and each block - the order in which the files are read is not guaranteed.
057: * 2) context://WEB-INF/properties/[RUNNING_MODE]/*.properties
058: * Default values for the running mode - the order in which the files are read is not guaranteed.
059: * 3) Property providers (ToBeDocumented)
060: * 4) The environment (CLI, Servlet etc.) adds own properties (e.g. from web.xml)
061: * 5) Additional property file specified by the "org.apache.cocoon.settings" system property or
062: * if the property is not found, the file ".cocoon/settings.properties" is tried to be read from
063: * the user directory.
064: * 6) System properties
065: *
066: */
067: public PropertySettings(SourceResolver resolver, Logger logger) {
068:
069: // now read all properties from the properties directory
070: readProperties("context://WEB-INF/properties", resolver);
071:
072: // read additional properties file
073:
074: String additionalPropertyFile = properties
075: .containsKey(Settings.PROPERTY_USER_SETTINGS) ? (String) properties
076: .get(Settings.PROPERTY_USER_SETTINGS)
077: : System.getProperty(Settings.PROPERTY_USER_SETTINGS);
078:
079: // if there is no property defining the addition file, we try it in the home directory
080: if (additionalPropertyFile == null) {
081: additionalPropertyFile = System.getProperty("user.home")
082: + File.separator + ".cocoon/settings.properties";
083: final File testFile = new File(additionalPropertyFile);
084: if (!testFile.exists()) {
085: additionalPropertyFile = null;
086: }
087: }
088: if (additionalPropertyFile != null) {
089: logger.debug("Reading user settings from '"
090: + additionalPropertyFile + "'");
091: final Properties p = new Properties();
092: try {
093: FileInputStream fis = new FileInputStream(
094: additionalPropertyFile);
095: p.load(fis);
096: fis.close();
097: } catch (IOException ignore) {
098: logger.warn("Unable to read '" + additionalPropertyFile
099: + "'.", ignore);
100: logger.warn("Continuing initialization.");
101: }
102: properties.putAll(p);
103: }
104: // now overwrite with system properties
105: properties.putAll(System.getProperties());
106:
107: if (logger.isDebugEnabled()) {
108: Iterator iter = properties.keySet().iterator();
109: logger.debug("Cocoon Properties:");
110: while (iter.hasNext()) {
111: String key = (String) iter.next();
112: logger.debug("Key: " + key + " Value: "
113: + properties.get(key));
114: }
115: }
116: }
117:
118: /**
119: * Read all property files from the given directory and apply them to the settings.
120: */
121: private void readProperties(String directoryName,
122: SourceResolver resolver) {
123: Source directory = null;
124: try {
125: directory = resolver.resolveURI(directoryName, null,
126: CONTEXT_PARAMETERS);
127: if (directory.exists()
128: && directory instanceof TraversableSource) {
129: final Iterator c = ((TraversableSource) directory)
130: .getChildren().iterator();
131: while (c.hasNext()) {
132: final Source src = (Source) c.next();
133: if (src.getURI().endsWith(".properties")) {
134: Properties props = new Properties();
135: final InputStream propsIS = src
136: .getInputStream();
137: props.load(propsIS);
138: propsIS.close();
139: properties.putAll(props);
140: }
141: }
142: }
143: } catch (IOException ignore) {
144:
145: } finally {
146: resolver.release(directory);
147: }
148: }
149:
150: /**
151: * @see org.apache.cocoon.util.Settings#getProperty(java.lang.String)
152: */
153: public String getProperty(String name) {
154: return this .getProperty(name, null);
155: }
156:
157: /**
158: * @see org.apache.cocoon.util.Settings#getProperty(java.lang.String, java.lang.String)
159: */
160: public String getProperty(String key, String defaultValue) {
161: if (key == null) {
162: return defaultValue;
163: }
164: String value = (String) properties.get(key);
165:
166: if (value == null) {
167: value = defaultValue;
168: }
169: return value;
170: }
171:
172: /**
173: * @see org.apache.cocoon.util.Settings#getProperties(java.lang.String)
174: */
175: public List getProperties(String keyPrefix) {
176: final List props = new ArrayList();
177: final Iterator kI = this .properties.keySet().iterator();
178: while (kI.hasNext()) {
179: final String name = (String) kI.next();
180: if (name.startsWith(keyPrefix) && !props.contains(name)) {
181: props.add(name);
182: }
183: }
184: return props;
185: }
186:
187: /**
188: * @see org.apache.cocoon.util.Settings#getProperties()
189: */
190: public List getProperties() {
191: final List props = new ArrayList();
192: props.addAll(this .properties.keySet());
193:
194: return props;
195: }
196:
197: public int size() {
198: return this.properties.size();
199: }
200: }
|