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