001: package org.apache.ojb.broker.util.logging;
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 java.util.HashMap;
019: import java.util.Map;
020:
021: import org.apache.ojb.broker.util.ClassHelper;
022: import org.apache.commons.lang.SystemUtils;
023:
024: /**
025: * The factory class <code>LoggerFactory</code> can be used
026: * to create <code>Logger</code> instances.
027: * The <code>Logger</code>-implementation class served
028: * by the factory is configured by settings in the
029: * OJB.properties file.
030: *
031: * @author Thomas Mahler
032: * @author <a href="leandro@ibnetwork.com.br">Leandro Rodrigo Saad Cruz</a>
033: * @version $Id: LoggerFactoryImpl.java,v 1.18.2.6 2005/12/21 22:28:16 tomdz Exp $
034: * @see <a href="http://jakarta.apache.org/log4j/docs/index.html">jakarta-log4j</a>
035: */
036: public class LoggerFactoryImpl {
037: public static final String BOOT_LOG_LEVEL_STR = "OJB.bootLogLevel";
038: protected static final String BOOT_STR = "BOOT";
039: protected static final String DEFAULT_STR = "DEFAULT";
040: protected static final LoggerFactoryImpl INSTANCE = new LoggerFactoryImpl();
041:
042: private Logger defaultLogger = null;
043:
044: private Logger bootLogger = null;
045:
046: private boolean bootLoggerIsReassigned = false;
047:
048: /** Used for caching logger instances */
049: private Map cache = new HashMap();
050: /** The configuration */
051: private LoggingConfiguration conf;
052:
053: // yes. it's a singleton !
054: private LoggerFactoryImpl() {
055: }
056:
057: public static LoggerFactoryImpl getInstance() {
058: return INSTANCE;
059: }
060:
061: private LoggingConfiguration getConfiguration() {
062: if (conf == null) {
063: // this will load the configuration
064: conf = new LoggingConfiguration();
065: }
066: return conf;
067: }
068:
069: /**
070: * returns a minimal logger that needs no configuration
071: * and can thus be safely used during OJB boot phase
072: * (i.e. when OJB.properties have not been loaded).
073: *
074: * @return Logger the OJB BootLogger
075: */
076: public Logger getBootLogger() {
077: if (bootLogger == null) {
078: // create a StringBuffer based Logger for boot log operations
079: bootLogger = createStringBufferLogger_Boot();
080: }
081: return bootLogger;
082: }
083:
084: /**
085: * returns the default logger. This Logger can
086: * be used when it is not appropriate to use a
087: * dedicated fresh Logger instance.
088: *
089: * @return default Logger
090: */
091: public Logger getDefaultLogger() {
092: if (defaultLogger == null) {
093: defaultLogger = getLogger(DEFAULT_STR);
094: }
095: return defaultLogger;
096: }
097:
098: /**
099: * returns a Logger. The Logger is named
100: * after the full qualified name of input parameter clazz
101: *
102: * @param clazz the Class which name is to be used as name
103: * @return Logger the returned Logger
104: */
105: public Logger getLogger(Class clazz) {
106: return getLogger(clazz.getName());
107: }
108:
109: /**
110: * returns a Logger.
111: *
112: * @param loggerName the name of the Logger
113: * @return Logger the returned Logger
114: */
115: public Logger getLogger(String loggerName) {
116: Logger logger;
117: //lookup in the cache first
118: logger = (Logger) cache.get(loggerName);
119:
120: if (logger == null) {
121: try {
122: // get the configuration (not from the configurator because this is independent)
123: logger = createLoggerInstance(loggerName);
124: if (getBootLogger().isDebugEnabled()) {
125: getBootLogger()
126: .debug(
127: "Using logger class '"
128: + (getConfiguration() != null ? getConfiguration()
129: .getLoggerClass()
130: : null) + "' for "
131: + loggerName);
132: }
133: // configure the logger
134: getBootLogger().debug(
135: "Initializing logger instance " + loggerName);
136: logger.configure(conf);
137: } catch (Throwable t) {
138: // do reassign check and signal logger creation failure
139: reassignBootLogger(true);
140: logger = getBootLogger();
141: getBootLogger().error(
142: "["
143: + this .getClass().getName()
144: + "] Could not initialize logger "
145: + (conf != null ? conf.getLoggerClass()
146: : null), t);
147: }
148: //cache it so we can get it faster the next time
149: cache.put(loggerName, logger);
150: // do reassign check
151: reassignBootLogger(false);
152: }
153: return logger;
154: }
155:
156: /**
157: * Creates a new Logger instance for the specified name.
158: */
159: private Logger createLoggerInstance(String loggerName)
160: throws Exception {
161: Class loggerClass = getConfiguration().getLoggerClass();
162: Logger log = (Logger) ClassHelper.newInstance(loggerClass,
163: String.class, loggerName);
164: log.configure(getConfiguration());
165: return log;
166: }
167:
168: /**
169: *
170: * @param forceError
171: */
172: protected synchronized void reassignBootLogger(boolean forceError) {
173: // if the boot logger was already reassigned do nothing
174: if (!bootLoggerIsReassigned) {
175: Logger newBootLogger = null;
176: String name = getBootLogger().getName();
177: try {
178: // 1. try to use a Logger instance based on the configuration files
179: newBootLogger = createLoggerInstance(name);
180: } catch (Exception e) {/*ignore*/
181: }
182: if (newBootLogger == null) {
183: // 2. if no logging library can be found, use OJB's console logger
184: newBootLogger = createPoorMansLogger_Boot();
185: }
186: if (getBootLogger() instanceof StringBufferLoggerImpl) {
187: /*
188: if the StringBuffer based Logger was used for OJB bootstrap process
189: get the logging statement string and log it on the "real" Logger instance
190: */
191: StringBufferLoggerImpl strLogger = (StringBufferLoggerImpl) getBootLogger();
192: String bootMessage = strLogger.flushLogBuffer();
193: String eol = SystemUtils.LINE_SEPARATOR;
194: if (forceError || strLogger.isErrorLog()) {
195: newBootLogger.error("-- boot log messages -->"
196: + eol + bootMessage);
197: } else {
198: newBootLogger.info("-- boot log messages -->" + eol
199: + bootMessage);
200: }
201: }
202: bootLogger = newBootLogger;
203: bootLoggerIsReassigned = true;
204: }
205: }
206:
207: protected Logger createPoorMansLogger_Boot() {
208: Logger bootLogger = new PoorMansLoggerImpl(BOOT_STR);
209: // allow user to set boot log level via system property
210: String level = System.getProperty(BOOT_LOG_LEVEL_STR,
211: LoggingConfiguration.OJB_DEFAULT_BOOT_LOG_LEVEL);
212: ((PoorMansLoggerImpl) bootLogger).setLevel(level);
213: return bootLogger;
214: }
215:
216: protected Logger createStringBufferLogger_Boot() {
217: Logger bootLogger = new StringBufferLoggerImpl(BOOT_STR);
218: // allow user to set boot log level via system property
219: String level = System.getProperty(BOOT_LOG_LEVEL_STR,
220: LoggingConfiguration.OJB_DEFAULT_BOOT_LOG_LEVEL);
221: ((PoorMansLoggerImpl) bootLogger).setLevel(level);
222: return bootLogger;
223: }
224: }
|