001: package org.apache.ojb.broker.util.configuration.impl;
002:
003: /* Copyright 2002-2005 The Apache Software Foundation
004: *
005: * Licensed under the Apache License, Version 2.0 (the "License");
006: * you may not use this file except in compliance with the License.
007: * 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:
018: import org.apache.ojb.broker.metadata.MetadataException;
019: import org.apache.ojb.broker.util.configuration.Configuration;
020: import org.apache.ojb.broker.util.logging.Logger;
021: import org.apache.ojb.broker.util.logging.LoggerFactory;
022: import org.apache.ojb.broker.util.ClassHelper;
023:
024: import java.io.File;
025: import java.io.FileNotFoundException;
026: import java.io.InputStream;
027: import java.net.URL;
028: import java.net.URLConnection;
029: import java.util.Properties;
030: import java.util.StringTokenizer;
031:
032: /**
033: * Configuration Base Class that
034: * keeps a Properties based configuration persistent in a file.
035: * This class provides only basic infrastructure for loading etc.
036: *
037: * @author Thomas Mahler
038: * @version $Id: ConfigurationAbstractImpl.java,v 1.15.2.4 2005/12/21 22:28:15 tomdz Exp $
039: */
040: public abstract class ConfigurationAbstractImpl implements
041: Configuration {
042: /**the logger used in this class.*/
043: private Logger logger = LoggerFactory.getBootLogger();
044:
045: /**the name of the properties file*/
046: protected String filename;
047:
048: /**the properties object holding the configuration data*/
049: protected Properties properties;
050:
051: /**
052: * Contains all legal values for boolean configuration entries that represent
053: * <code>true</code>.
054: */
055: private String[] trueValues = { "true", "yes", "1" };
056: /**
057: * Contains all legal values for boolean configuration entries that represent
058: * <code>false</code>.
059: */
060: private String[] falseValues = { "false", "no", "0" };
061:
062: /**
063: * The constructor loads the configuration from file
064: */
065: public ConfigurationAbstractImpl() {
066: load();
067: }
068:
069: /**
070: * Returns the string value for the specified key. If no value for this key
071: * is found in the configuration <code>defaultValue</code> is returned.
072: *
073: * @param key the key
074: * @param defaultValue the default value
075: * @return the value for the key, or <code>defaultValue</code>
076: */
077: public String getString(String key, String defaultValue) {
078: String ret = properties.getProperty(key);
079: if (ret == null) {
080: if (defaultValue == null) {
081: logger.info("No value for key '" + key + "'");
082: } else {
083: logger
084: .debug("No value for key \"" + key
085: + "\", using default \"" + defaultValue
086: + "\".");
087: properties.put(key, defaultValue);
088: }
089:
090: ret = defaultValue;
091: }
092:
093: return ret;
094: }
095:
096: /**
097: * Gets an array of Strings from the value of the specified key, seperated
098: * by any key from <code>seperators</code>. If no value for this key
099: * is found the array contained in <code>defaultValue</code> is returned.
100: *
101: * @param key the key
102: * @param defaultValue the default Value
103: * @param seperators the seprators to be used
104: * @return the strings for the key, or the strings contained in <code>defaultValue</code>
105: *
106: * @see StringTokenizer
107: */
108: public String[] getStrings(String key, String defaultValue,
109: String seperators) {
110: StringTokenizer st = new StringTokenizer(getString(key,
111: defaultValue), seperators);
112: String[] ret = new String[st.countTokens()];
113: for (int i = 0; i < ret.length; i++) {
114: ret[i] = st.nextToken();
115: }
116: return ret;
117: }
118:
119: /**
120: * Gets an array of Strings from the value of the specified key, seperated
121: * by ";". If no value for this key
122: * is found the array contained in <code>defaultValue</code> is returned.
123: *
124: * @param key the key
125: * @param defaultValue the default Value
126: * @return the strings for the key, or the strings contained in <code>defaultValue</code>
127: */
128: public String[] getStrings(String key, String defaultValue) {
129: return getStrings(key, defaultValue, ";");
130: }
131:
132: /**
133: * Returns the integer value for the specified key. If no value for this key
134: * is found in the configuration or the value is not an legal integer
135: * <code>defaultValue</code> is returned.
136: *
137: * @param key the key
138: * @param defaultValue the default Value
139: * @return the value for the key, or <code>defaultValue</code>
140: */
141: public int getInteger(String key, int defaultValue) {
142: int ret;
143: try {
144: String tmp = properties.getProperty(key);
145: if (tmp == null) {
146: properties.put(key, String.valueOf(defaultValue));
147: logger.debug("No value for key \"" + key
148: + "\", using default " + defaultValue + ".");
149: return defaultValue;
150: }
151: ret = Integer.parseInt(tmp);
152: } catch (NumberFormatException e) {
153: Object wrongValue = properties.put(key, String
154: .valueOf(defaultValue));
155: logger.warn("Value \"" + wrongValue
156: + "\" is illegal for key \"" + key
157: + "\" (should be an integer, using default value "
158: + defaultValue + ")");
159: ret = defaultValue;
160: }
161: return ret;
162: }
163:
164: public long getLong(String key, long defaultValue) {
165: long ret;
166: try {
167: String tmp = properties.getProperty(key);
168: if (tmp == null) {
169: properties.put(key, String.valueOf(defaultValue));
170: logger.debug("No value for key \"" + key
171: + "\", using default " + defaultValue + ".");
172: return defaultValue;
173: }
174: ret = Long.parseLong(tmp);
175: } catch (NumberFormatException e) {
176: Object wrongValue = properties.put(key, String
177: .valueOf(defaultValue));
178: logger.warn("Value \"" + wrongValue
179: + "\" is illegal for key \"" + key
180: + "\" (should be an integer, using default value "
181: + defaultValue + ")");
182: ret = defaultValue;
183: }
184: return ret;
185: }
186:
187: public byte getByte(String key, byte defaultValue) {
188: byte ret;
189: try {
190: String tmp = properties.getProperty(key);
191: if (tmp == null) {
192: properties.put(key, String.valueOf(defaultValue));
193: logger.debug("No value for key \"" + key
194: + "\", using default " + defaultValue + ".");
195: return defaultValue;
196: }
197: ret = Byte.parseByte(tmp);
198: } catch (NumberFormatException e) {
199: Object wrongValue = properties.put(key, String
200: .valueOf(defaultValue));
201: logger.warn("Value \"" + wrongValue
202: + "\" is illegal for key \"" + key
203: + "\" (should be an integer, using default value "
204: + defaultValue + ")");
205: ret = defaultValue;
206: }
207: return ret;
208: }
209:
210: /**
211: * Returns the boolean value for the specified key. If no value for this key
212: * is found in the configuration or the value is not an legal boolean
213: * <code>defaultValue</code> is returned.
214: *
215: * @see #trueValues
216: * @see #falseValues
217: *
218: * @param key the key
219: * @param defaultValue the default Value
220: * @return the value for the key, or <code>defaultValue</code>
221: */
222: public boolean getBoolean(String key, boolean defaultValue) {
223: String tmp = properties.getProperty(key);
224:
225: if (tmp == null) {
226: logger.debug("No value for key \"" + key
227: + "\", using default " + defaultValue + ".");
228: properties.put(key, String.valueOf(defaultValue));
229: return defaultValue;
230: }
231:
232: for (int i = 0; i < trueValues.length; i++) {
233: if (tmp.equalsIgnoreCase(trueValues[i])) {
234: return true;
235: }
236: }
237:
238: for (int i = 0; i < falseValues.length; i++) {
239: if (tmp.equalsIgnoreCase(falseValues[i])) {
240: return false;
241: }
242: }
243:
244: logger.warn("Value \"" + tmp + "\" is illegal for key \"" + key
245: + "\" (should be a boolean, using default value "
246: + defaultValue + ")");
247: return defaultValue;
248: }
249:
250: /**
251: * Returns the class specified by the value for the specified key. If no
252: * value for this key is found in the configuration, no class of this name
253: * can be found or the specified class is not assignable to each
254: * class/interface in <code>assignables defaultValue</code> is returned.
255: *
256: * @param key the key
257: * @param defaultValue the default Value
258: * @param assignables classes and/or interfaces the specified class must
259: * extend/implement.
260: * @return the value for the key, or <code>defaultValue</code>
261: */
262: public Class getClass(String key, Class defaultValue,
263: Class[] assignables) {
264: String className = properties.getProperty(key);
265:
266: if (className == null) {
267: if (defaultValue == null) {
268: logger.info("No value for key '" + key + "'");
269: return null;
270: } else {
271: className = defaultValue.getName();
272: properties.put(key, className);
273: logger.debug("No value for key \"" + key
274: + "\", using default " + className + ".");
275: return defaultValue;
276: }
277: }
278:
279: Class clazz = null;
280: try {
281: clazz = ClassHelper.getClass(className);
282: } catch (ClassNotFoundException e) {
283: clazz = defaultValue;
284: logger.warn("Value \"" + className
285: + "\" is illegal for key \"" + key
286: + "\" (should be a class, using default value "
287: + defaultValue + ")", e);
288: }
289:
290: for (int i = 0; i < assignables.length; i++) {
291: Class assignable = assignables[i];
292: if (!assignable.isAssignableFrom(clazz)) {
293: String extendsOrImplements;
294: if (assignable.isInterface()) {
295: extendsOrImplements = "implement the interface ";
296: } else {
297: extendsOrImplements = "extend the class ";
298:
299: }
300: logger.error("The specified class \"" + className
301: + "\" does not " + extendsOrImplements
302: + assignables[i].getName()
303: + ", which is a requirement for the key \""
304: + key + "\". Using default class "
305: + defaultValue);
306: clazz = defaultValue;
307: }
308:
309: }
310:
311: return clazz;
312: }
313:
314: /**
315: * Returns the class specified by the value for the specified key. If no
316: * value for this key is found in the configuration, no class of this name
317: * can be found or the specified class is not assignable <code>assignable
318: * defaultValue</code> is returned.
319: *
320: * @param key the key
321: * @param defaultValue the default Value
322: * @param assignable a classe and/or interface the specified class must
323: * extend/implement.
324: * @return the value for the key, or <code>defaultValue</code>
325: */
326: public Class getClass(String key, Class defaultValue,
327: Class assignable) {
328: return getClass(key, defaultValue, new Class[] { assignable });
329: }
330:
331: /**
332: * Returns the class specified by the value for the specified key. If no
333: * value for this key is found in the configuration or no class of this name
334: * can be found <code>defaultValue</code> is returned.
335: *
336: * @param key the key
337: * @param defaultValue the default Value
338: * @return the value for the key, or <code>defaultValue</code>
339: */
340: public Class getClass(String key, Class defaultValue) {
341: return getClass(key, defaultValue, new Class[0]);
342: }
343:
344: /**
345: * Loads the Configuration from the properties file.
346: *
347: * Loads the properties file, or uses defaults on failure.
348: *
349: * @see org.apache.ojb.broker.util.configuration.impl.ConfigurationAbstractImpl#setFilename(java.lang.String)
350: *
351: */
352: protected void load() {
353: properties = new Properties();
354:
355: String filename = getFilename();
356:
357: try {
358: URL url = ClassHelper.getResource(filename);
359:
360: if (url == null) {
361: url = (new File(filename)).toURL();
362: }
363:
364: logger.info("Loading OJB's properties: " + url);
365:
366: URLConnection conn = url.openConnection();
367: conn.setUseCaches(false);
368: conn.connect();
369: InputStream strIn = conn.getInputStream();
370: properties.load(strIn);
371: strIn.close();
372: } catch (FileNotFoundException ex) {
373: // [tomdz] If the filename is explicitly reset (null or empty string) then we'll
374: // output an info message because the user did this on purpose
375: // Otherwise, we'll output a warning
376: if ((filename == null) || (filename.length() == 0)) {
377: logger
378: .info("Starting OJB without a properties file. OJB is using default settings instead.");
379: } else {
380: logger.warn("Could not load properties file '"
381: + filename + "'. Using default settings!", ex);
382: }
383: // [tomdz] There seems to be no use of this setting ?
384: //properties.put("valid", "false");
385: } catch (Exception ex) {
386: throw new MetadataException(
387: "An error happend while loading the properties file '"
388: + filename + "'", ex);
389: }
390: }
391:
392: private String getFilename() {
393: if (filename == null) {
394: filename = this .getClass().getName() + ".properties";
395: }
396: return filename;
397: }
398:
399: protected void setFilename(String name) {
400: filename = name;
401: }
402:
403: /**
404: * @see Configuration#setLogger(Logger)
405: */
406: public void setLogger(Logger loggerInstance) {
407: logger = loggerInstance;
408: }
409:
410: }
|