001: package org.jacorb.config;
002:
003: /*
004: * JacORB - a free Java ORB
005: *
006: * Copyright (C) 1997-2004 Gerald Brose.
007: *
008: * This library is free software; you can redistribute it and/or
009: * modify it under the terms of the GNU Library General Public
010: * License as published by the Free Software Foundation; either
011: * version 2 of the License, or (at your option) any later version.
012: *
013: * This library is distributed in the hope that it will be useful,
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
016: * Library General Public License for more details.
017: *
018: * You should have received a copy of the GNU Library General Public
019: * License along with this library; if not, write to the Free
020: * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
021: */
022:
023: import org.apache.avalon.framework.configuration.Configurable;
024: import org.apache.avalon.framework.configuration.ConfigurationException;
025: import org.apache.avalon.framework.logger.*;
026:
027: import java.io.*;
028: import java.text.DateFormat;
029: import java.text.SimpleDateFormat;
030: import java.util.*;
031:
032: import org.jacorb.orb.ORB;
033: import org.jacorb.util.ObjectUtil;
034:
035: /**
036: * @author Gerald Brose
037: * @version $Id: JacORBConfiguration.java,v 1.18 2006/11/24 14:13:34 alphonse.bendt Exp $
038: */
039:
040: public class JacORBConfiguration extends
041: org.apache.avalon.framework.configuration.DefaultConfiguration
042: implements Configuration {
043: private static final String CONFIG_LOG_VERBOSITY = "jacorb.config.log.verbosity";
044: private static final String fileSuffix = ".properties";
045: private static final String COMMON_PROPS = "orb" + fileSuffix;
046:
047: private static final String TRUE = "true";
048: private static final String ON = "on";
049: private static final String EMPTY_STR = "";
050:
051: private static final int DEFAULT_LOG_LEVEL = 0;
052:
053: private final ORB orb;
054:
055: /** root logger instance for this configuration */
056: private Logger logger = null;
057:
058: /** logger factory used to create loggers */
059: private LoggerFactory loggerFactory = null;
060:
061: /** default class name for logger factory */
062: private static final String loggerFactoryClzName = "org.jacorb.config.LogKitLoggerFactory";
063:
064: /**
065: * Factory method
066: */
067: public static Configuration getConfiguration(Properties props,
068: ORB orb, boolean isApplet) throws ConfigurationException {
069: // determine the ORBId, if set, so we can locate the corresponding
070: // configuration
071: String orbID = "jacorb"; // default id
072: String myOrbID = null;
073: if (!isApplet) {
074: try {
075: myOrbID = System.getProperty("ORBid");
076: } catch (SecurityException e) {
077: isApplet = true;
078: println("Could not access system property 'ORBid' - will use default...");
079: }
080: }
081:
082: if (props != null) {
083: // props override system properties
084: String tmp = (String) props.get("ORBid");
085: if (tmp != null) {
086: myOrbID = tmp;
087: }
088: }
089:
090: if (myOrbID != null) {
091: // check for legal values
092: if (myOrbID.equals("orb") || myOrbID.equals("jacorb")) {
093: throw new ConfigurationException("Illegal orbID, <"
094: + myOrbID + "> is reserved");
095: }
096: orbID = myOrbID;
097: }
098:
099: return new JacORBConfiguration(orbID, props, orb, isApplet);
100: }
101:
102: /**
103: * Create a configuration using the properties passed
104: * into ORB.init()
105: */
106:
107: private JacORBConfiguration(String name, Properties orbProperties,
108: ORB orb, boolean isApplet) throws ConfigurationException {
109: super (name);
110: this .orb = orb;
111:
112: if (isApplet) {
113: initApplet(name, orbProperties);
114: } else {
115: init(name, orbProperties);
116: }
117:
118: initLogging();
119: }
120:
121: private static void println(String mesg) {
122: System.out.println(mesg); // NOPMD
123: }
124:
125: private static void printErr(String mesg) {
126: System.err.println(mesg); // NOPMD
127: }
128:
129: /**
130: * loads properties from files.
131: *
132: * Properties are loaded in the following order, with later
133: * properties overriding earlier ones: 1) System properties
134: * (incl. command line), to get properties that affect further
135: * property loading 2) orb.properties file 3) specific
136: * configuration file for the ORB (if any) 4) System properties
137: * again, so that command line args take precedence over the above
138: * 5) the ORB properties set in the client code and passed in
139: * through ORB.init().
140: * (Note that these will thus always take effect!)
141: *
142: * @param name the name for the ORB instance, may not be null.
143: */
144:
145: private void init(String name, Properties orbProperties)
146: throws ConfigurationException {
147: if (name == null) {
148: throw new ConfigurationException(
149: "Illegal null value for ORB name!");
150: }
151:
152: String separator = System.getProperty("file.separator");
153: String home = System.getProperty("user.home");
154: String lib = System.getProperty("java.home");
155: boolean loaded = false;
156:
157: // 1) load system properties to grab any command line properties
158: // that will influence further property loading
159: setAttributes(System.getProperties());
160:
161: int logLevel = getAttributeAsInteger(CONFIG_LOG_VERBOSITY,
162: DEFAULT_LOG_LEVEL);
163:
164: // 2) look for orb.properties
165: // look for common properties files in java.home/lib first
166: Properties commonProps = loadPropertiesFromFile(lib + separator
167: + "lib" + separator + COMMON_PROPS);
168:
169: if (commonProps != null) {
170: setAttributes(commonProps);
171: // we don't have proper logging at this stage yet, so we can only
172: // log to the console, but we check if that is explicitly disallowed
173: logLevel = getAttributeAsInteger(CONFIG_LOG_VERBOSITY,
174: DEFAULT_LOG_LEVEL);
175: loaded = true;
176:
177: if (logLevel > 2) {
178: println("[ base configuration loaded from file " + lib
179: + separator + "lib" + separator + COMMON_PROPS
180: + " ]");
181: }
182: }
183:
184: // look for common properties files in user.home next
185: commonProps = loadPropertiesFromFile(home + separator
186: + COMMON_PROPS);
187:
188: if (commonProps != null) {
189: setAttributes(commonProps);
190: loaded = true;
191:
192: logLevel = getAttributeAsInteger(CONFIG_LOG_VERBOSITY,
193: DEFAULT_LOG_LEVEL);
194: if (logLevel > 2) {
195: println("[ base configuration loaded from file " + home
196: + separator + COMMON_PROPS + " ]");
197: }
198: }
199:
200: // look for common properties files on the classpath next
201: commonProps = loadPropertiesFromClassPath(COMMON_PROPS);
202:
203: if (commonProps != null) {
204: loaded = true;
205: setAttributes(commonProps);
206: logLevel = getAttributeAsInteger(CONFIG_LOG_VERBOSITY,
207: DEFAULT_LOG_LEVEL);
208: if (logLevel > 2) {
209: println("[ base configuration loaded from classpath "
210: + COMMON_PROPS + " ]");
211: }
212: }
213:
214: // 3) look for specific properties file
215: String configDir = getAttribute("jacorb.config.dir", "");
216:
217: if (configDir.length() == 0) {
218: configDir = getAttribute("jacorb.home", "");
219: }
220:
221: if (configDir.length() != 0) {
222: configDir += separator + "etc";
223: } else {
224: logLevel = getAttributeAsInteger(CONFIG_LOG_VERBOSITY,
225: DEFAULT_LOG_LEVEL);
226: if (logLevel > 0) {
227: printErr("[ jacorb.home unset! Will use '.' ]");
228: }
229: configDir = ".";
230: }
231:
232: String propFileName = configDir + separator + name + fileSuffix;
233:
234: // now load properties file from file system
235: Properties orbConfig = loadPropertiesFromFile(propFileName);
236:
237: if (orbConfig != null) {
238: setAttributes(orbConfig);
239: loaded = true;
240:
241: logLevel = getAttributeAsInteger(CONFIG_LOG_VERBOSITY,
242: DEFAULT_LOG_LEVEL);
243: if (logLevel > 2) {
244: println("[ configuration " + name
245: + " loaded from file " + propFileName + " ]");
246: }
247: } else {
248: logLevel = getAttributeAsInteger(CONFIG_LOG_VERBOSITY,
249: DEFAULT_LOG_LEVEL);
250: if (logLevel > 0) {
251: printErr("[ File " + propFileName
252: + " for configuration " + name + " not found ]");
253: }
254: }
255:
256: // now load properties file from classpath
257: orbConfig = loadPropertiesFromClassPath(name + fileSuffix);
258: if (orbConfig != null) {
259: setAttributes(orbConfig);
260: loaded = true;
261:
262: logLevel = getAttributeAsInteger(CONFIG_LOG_VERBOSITY,
263: DEFAULT_LOG_LEVEL);
264: if (logLevel > 2) {
265: println("[ configuration " + name
266: + " loaded from classpath]");
267: }
268: }
269:
270: // 4) look for additional custom properties files
271: List customPropFileNames = getAttributeList("custom.props");
272:
273: if (!customPropFileNames.isEmpty()) {
274: for (Iterator iter = customPropFileNames.iterator(); iter
275: .hasNext();) {
276: String fileName = ((String) iter.next());
277: Properties customProps = loadPropertiesFromFile(fileName);
278: if (customProps != null) {
279: setAttributes(customProps);
280: loaded = true;
281:
282: logLevel = getAttributeAsInteger(
283: CONFIG_LOG_VERBOSITY, DEFAULT_LOG_LEVEL);
284: if (logLevel > 2) {
285: println("[ custom properties loaded from file "
286: + fileName + " ]");
287: }
288: } else {
289: if (logLevel > 0) {
290: printErr("[ custom properties not found in "
291: + fileName + " ]");
292: }
293: }
294: }
295: }
296:
297: // 5) load system properties again, so that
298: // command line args override properties from files
299: setAttributes(System.getProperties());
300:
301: // 6) load properties passed to ORB.init(), these will override any
302: // settings in config files or system properties!
303: if (orbProperties != null) {
304: loaded = true;
305: setAttributes(orbProperties);
306: }
307:
308: if (!loaded && logLevel > 0) {
309: // print a warning....
310: println("[ No configuration properties found for configuration "
311: + name + " ]");
312: }
313:
314: }
315:
316: /**
317: * loads properties via classloader.
318: *
319: * Properties are loaded in the following order, with later properties
320: * overriding earlier ones: 1) Properties from ORB.init(), to get
321: * properties that affect further property loading 2) orb.properties 3)
322: * specific configuration file for the ORB (if any) 4) the ORB properties
323: * set in the client code and passed in through ORB.init(). (Note that
324: * these will thus always take effect!)
325: *
326: * @param name the name for the ORB instance, may not be null.
327: */
328:
329: private void initApplet(String name, Properties orbProperties)
330: throws ConfigurationException {
331: if (name == null) {
332: throw new ConfigurationException(
333: "Illegal null value for ORB name!");
334: }
335: boolean loaded = false;
336:
337: // 1) load system properties to grab any command line properties
338: // that will influence further property loading
339: if (orbProperties != null) {
340: setAttributes(orbProperties);
341: }
342:
343: int logLevel = getAttributeAsInteger(CONFIG_LOG_VERBOSITY,
344: DEFAULT_LOG_LEVEL);
345:
346: // 2) look for orb.properties
347: // look for common properties files on the classpath next
348: Properties commonProps = loadPropertiesFromClassPath(COMMON_PROPS);
349:
350: if (commonProps != null) {
351: loaded = true;
352: setAttributes(commonProps);
353: logLevel = getAttributeAsInteger(CONFIG_LOG_VERBOSITY,
354: DEFAULT_LOG_LEVEL);
355: if (logLevel > 2) {
356: println("[ base configuration loaded from classpath "
357: + COMMON_PROPS + " ]");
358: }
359: }
360:
361: // 3) look for specific properties file
362: String propFileName = name + fileSuffix;
363: Properties orbConfig = loadPropertiesFromClassPath(propFileName);
364:
365: if (orbConfig != null) {
366: setAttributes(orbConfig);
367: loaded = true;
368:
369: logLevel = getAttributeAsInteger(CONFIG_LOG_VERBOSITY,
370: DEFAULT_LOG_LEVEL);
371: if (logLevel > 2) {
372: println("[ configuration " + name
373: + " loaded from classpath " + propFileName
374: + " ]");
375: }
376: } else {
377: logLevel = getAttributeAsInteger(CONFIG_LOG_VERBOSITY,
378: DEFAULT_LOG_LEVEL);
379: if (logLevel > 0) {
380: printErr("[ File " + propFileName
381: + " for configuration " + name
382: + " not found in classpath]");
383: }
384: }
385:
386: // 4) look for additional custom properties files
387: List customPropFileNames = getAttributeList("custom.props");
388:
389: if (!customPropFileNames.isEmpty()) {
390: for (Iterator iter = customPropFileNames.iterator(); iter
391: .hasNext();) {
392: String fileName = ((String) iter.next());
393: Properties customProps = loadPropertiesFromClassPath(fileName);
394: if (customProps != null) {
395: setAttributes(customProps);
396: loaded = true;
397:
398: logLevel = getAttributeAsInteger(
399: CONFIG_LOG_VERBOSITY, DEFAULT_LOG_LEVEL);
400: if (logLevel > 2) {
401: println("[ custom properties loaded from classpath "
402: + fileName + " ]");
403: }
404: } else {
405: if (logLevel > 0) {
406: printErr("[ custom properties " + fileName
407: + "not found in classpath ]");
408: }
409: }
410: }
411: }
412:
413: // 5) load properties passed to ORB.init(), these will override any
414: // settings in config files or system properties!
415: if (orbProperties != null) {
416: loaded = true;
417: setAttributes(orbProperties);
418: }
419:
420: if (!loaded) {
421: // print a warning....
422: println("[ No configuration properties found for configuration "
423: + name + " ]");
424: }
425: }
426:
427: /**
428: * set attributes of this configuration using properties
429: */
430:
431: void setAttributes(Properties properties) {
432: for (Iterator iter = properties.keySet().iterator(); iter
433: .hasNext();) {
434: Object obj = iter.next();
435: // Some lunatics illegally put non String objects into System props
436: // as keys / values - we check for both and ignore them.
437: if (!(obj instanceof String)) {
438: continue;
439: }
440:
441: String key = (String) obj;
442: Object value = properties.get(key);
443: if (value instanceof String || value == null) {
444: setAttribute(key, (String) value);
445: }
446: }
447: }
448:
449: /**
450: * Loads properties from a file
451: * @param fileName the name of a properties file
452: * @return a properties object or null, if fileName not found
453: */
454:
455: private static Properties loadPropertiesFromFile(String fileName) {
456: try {
457: InputStream stream = new FileInputStream(fileName);
458: try {
459: Properties result = new Properties();
460: result.load(stream);
461: return result;
462: } finally {
463: stream.close();
464: }
465: } catch (java.io.FileNotFoundException e) {
466: // It's okay to ignore this silently: There was just no
467: // config file there, so the caller is going to look elsewhere.
468: return null;
469: } catch (java.io.IOException e) {
470: // This is probably a more severe problem with the config file.
471: // Write to the terminal, because we have no logging yet.
472: println("could not read config file: " + fileName);
473: e.printStackTrace();
474: return null;
475: }
476: }
477:
478: /**
479: * load properties file from classpath
480: * @param name the name of the properties file.
481: * @return a properties object or null, if name not found
482: */
483:
484: private static Properties loadPropertiesFromClassPath(String name) {
485: Properties result = null;
486: try {
487: final ClassLoader clazzLoader;
488:
489: if (Thread.currentThread().getContextClassLoader() != null) {
490: clazzLoader = Thread.currentThread()
491: .getContextClassLoader();
492: } else {
493: clazzLoader = JacORBConfiguration.class
494: .getClassLoader();
495: }
496:
497: java.net.URL url = clazzLoader.getResource(name);
498: if (url != null) {
499: result = new Properties();
500: final InputStream stream = url.openStream();
501: try {
502: result.load(stream);
503: } finally {
504: stream.close();
505: }
506: }
507: } catch (FileNotFoundException ex) {
508: // It's okay to ignore this silently: the caller will just look
509: // elsewhere.
510: } catch (java.io.IOException ioe) {
511: // This is a more severe problem: write to the terminal, because
512: // we have no logging yet.
513: println("could not read config file: " + name);
514: ioe.printStackTrace();
515: }
516: return result;
517: }
518:
519: /**
520: * Set up JacORB logging. Will create logger factory and root
521: * logger object according to configuration parameters. The value
522: * of the property <tt>jacorb.log.loggerFactory</tt> determines the
523: * logger factory class name that is used to create the root logger.
524: *
525: * @since 2.0 beta 3
526: */
527: private void initLogging() {
528: final DateFormat dateFormatter = new SimpleDateFormat(
529: "yyyyMdHm");
530:
531: String logFileName = getAttribute("jacorb.logfile", "");
532:
533: int maxLogSize = getAttributeAsInteger(
534: "jacorb.logfile.maxLogSize", 0);
535:
536: if (!logFileName.equals("")) {
537: if (orb == null) // this is the case for the singleton ORB
538: {
539: final String singletonLogFile = getAttribute(
540: "jacorb.logfile.singleton", "");
541: if (singletonLogFile.equals("")) {
542: // setting to "" effectively disables logging for the singleton orb.
543: logFileName = "";
544: } else {
545: // If it ends with implname File can't handle it so do it manually.
546: if (logFileName.endsWith("$implname")) {
547: logFileName = logFileName.substring(0,
548: logFileName.indexOf("$implname") - 1);
549: logFileName += File.separatorChar
550: + singletonLogFile
551: + dateFormatter.format(new Date())
552: + ".log";
553: } else {
554: final File file = new File(logFileName);
555: final String parent = file.getParent();
556:
557: if (parent != null) {
558: logFileName += singletonLogFile
559: + dateFormatter.format(new Date())
560: + ".log";
561: } else {
562: logFileName = singletonLogFile
563: + dateFormatter.format(new Date())
564: + ".log";
565: }
566: }
567: }
568: } else if (logFileName.endsWith("$implname")) {
569: // Convert $implname postfix to implementation name
570: logFileName = logFileName.substring(0, logFileName
571: .length() - 9);
572:
573: final String serverId = new String(orb.getServerId());
574: String implName = getAttribute("jacorb.implname",
575: serverId);
576: logFileName += implName + ".log";
577: }
578: }
579:
580: String clzName = getAttribute("jacorb.log.loggerFactory", "");
581: Class loggerFactoryClz = null;
582:
583: try {
584: if (!clzName.equals("")) {
585: loggerFactoryClz = org.jacorb.util.ObjectUtil
586: .classForName(clzName);
587: } else {
588: loggerFactoryClz = org.jacorb.util.ObjectUtil
589: .classForName(loggerFactoryClzName);
590: }
591: loggerFactory = (LoggerFactory) loggerFactoryClz
592: .newInstance();
593: loggerFactory.configure(this );
594: } catch (Exception e) {
595: e.printStackTrace();
596: }
597:
598: if (loggerFactory == null) {
599: printErr("Configuration Error, could not create logger!");
600: }
601: if (!logFileName.equals("")) {
602: try {
603: loggerFactory
604: .setDefaultLogFile(logFileName, maxLogSize);
605: logger = loggerFactory.getNamedLogger("jacorb",
606: logFileName, maxLogSize);
607: } catch (IOException e) {
608: logger = loggerFactory.getNamedRootLogger("jacorb");
609: if (logger.isErrorEnabled()) {
610: logger
611: .error("Could not create logger with file target: "
612: + logFileName
613: + ", falling back to console log!");
614: }
615: }
616: } else {
617: logger = loggerFactory.getNamedRootLogger("jacorb");
618: }
619: }
620:
621: /**
622: * @return the ORB for which this configuration was created
623: */
624:
625: public ORB getORB() {
626: return orb;
627: }
628:
629: /**
630: * @param name the name of the logger, which also functions
631: * as a log category
632: * @return a Logger for a given name
633: */
634:
635: public Logger getNamedLogger(String name) {
636: return loggerFactory.getNamedLogger(name);
637: }
638:
639: public String getLoggerName(Class clz) {
640: final String clazzName = clz.getName();
641: final String packageName = clazzName.substring(0, clazzName
642: .lastIndexOf('.'));
643:
644: if (packageName != null && packageName.startsWith("org.jacorb")) {
645: return packageName.substring(4);
646: }
647: return packageName;
648: }
649:
650: /**
651: * For a property that has a list of comma-separated values,
652: * this method returns these values as a list of Strings.
653: * If the property is not set, an empty list is returned.
654: */
655:
656: public List getAttributeList(String key) {
657: List result = new ArrayList();
658: String value = null;
659:
660: try {
661: value = getAttribute(key);
662: } catch (ConfigurationException ce) {
663: // ignore
664: }
665:
666: if (value != null) {
667: StringTokenizer tok = new StringTokenizer(value, ",");
668: while (tok.hasMoreTokens()) {
669: result.add(tok.nextToken().trim());
670: }
671: }
672: return result;
673: }
674:
675: /**
676: * Create an object from the given property. The class's default
677: * constructor will be used.
678: *
679: * @return an object of the class of the keys value, or null, if
680: * no class name is found for the key
681: * @throws ConfigurationException if object creation fails.
682: */
683:
684: public Object getAttributeAsObject(String key)
685: throws ConfigurationException {
686: String className = getAttribute(key, null);
687:
688: if (className != null && className.length() > 0) {
689: return newInstance(key, className);
690: }
691:
692: return null;
693: }
694:
695: private Object newInstance(String key, String className)
696: throws ConfigurationException {
697: try {
698: Class clazz = ObjectUtil.classForName(className);
699:
700: final Object instance = clazz.newInstance();
701:
702: if (instance instanceof Configurable) {
703: ((Configurable) instance).configure(this );
704: }
705: return instance;
706: } catch (Exception e) {
707: throw new ConfigurationException(
708: "Unable to build class from key >" + key + "<: "
709: + e);
710: }
711: }
712:
713: public Object getAttributeAsObject(String key, String defaultValue)
714: throws ConfigurationException {
715: Object result = getAttributeAsObject(key);
716:
717: if (result == null) {
718: return newInstance("default", defaultValue);
719: }
720:
721: return result;
722: }
723:
724: public boolean getAttributeAsBoolean(String key)
725: throws ConfigurationException {
726: String value = getAttribute(key);
727:
728: if (value != null && value.length() > 0) {
729: value = value.trim().toLowerCase();
730: return ON.equals(value) || TRUE.equals(value);
731: }
732:
733: return false;
734: }
735:
736: public boolean getAttributeAsBoolean(String key,
737: boolean defaultValue) {
738: String value = getAttribute(key, EMPTY_STR);
739:
740: if (value.length() > 0) {
741: value = value.trim().toLowerCase();
742: return ON.equals(value) || TRUE.equals(value);
743: }
744:
745: return defaultValue;
746: }
747:
748: public List getAttributeNamesWithPrefix(String prefix) {
749: final List attributesWithPrefix = new ArrayList();
750:
751: final String[] allAttributes = getAttributeNames();
752:
753: for (int x = 0; x < allAttributes.length; ++x) {
754: if (allAttributes[x].startsWith(prefix)) {
755: attributesWithPrefix.add(allAttributes[x]);
756: }
757: }
758:
759: return Collections.unmodifiableList(attributesWithPrefix);
760: }
761: }
|