001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2006, Geotools Project Managment Committee (PMC)
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2.1 of the License, or (at your option) any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: */
016: package org.geotools.util;
017:
018: // J2SE dependencies
019: import java.util.Map;
020: import java.util.HashMap;
021: import java.util.logging.Level;
022: import java.util.logging.Logger;
023: import java.util.logging.Handler;
024: import java.util.logging.LogRecord;
025: import java.util.logging.Formatter;
026: import java.util.logging.SimpleFormatter;
027:
028: // Apache dependencies
029: import org.apache.commons.logging.Log;
030: import org.apache.commons.logging.LogFactory;
031: import org.apache.commons.logging.impl.Jdk14Logger;
032:
033: // Geotools dependencies
034: import org.geotools.resources.i18n.Logging;
035: import org.geotools.resources.i18n.LoggingKeys;
036:
037: /**
038: * An adapter that redirect all Java logging events to the Apache's commons logging framework.
039: * This adapter is installed when the {@link #install} method is invoked.
040: *
041: * @since 2.4
042: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/metadata/src/main/java/org/geotools/util/CommonHandler.java $
043: * @version $Id: CommonHandler.java 27848 2007-11-12 13:10:32Z desruisseaux $
044: * @author Martin Desruisseaux
045: * @author Saul Farber
046: *
047: * @see Logging
048: *
049: * @deprecated No replacement. See the new {@link org.geotools.util.logging} package instead.
050: */
051: final class CommonHandler extends Handler {
052: /**
053: * The Apache's log created up to date.
054: */
055: private final Map/*<String,Log>*/loggers = new HashMap();
056:
057: /**
058: * The logger the handler is forwarding for.
059: */
060: private final Log logger;
061:
062: /**
063: * Creates a new handler.
064: *
065: * @param name The name of the root logger.
066: * @param logger The value of {@code LogFactory.getLog(name)}.
067: */
068: private CommonHandler(final String name, final Log logger) {
069: /*
070: * NOTE: We add the log now instead of waiting for the 'getLog' method because the
071: * setting for the root logger (as performed by the 'install' method) is different
072: * than the setting performed by the 'getLog' method for child loggers.
073: */
074: loggers.put(name, logger);
075: this .logger = logger;
076: setFormatter(new SimpleFormatter());
077: }
078:
079: /**
080: * Install or re-install the {@code CommonHandler} for the {@linkplain Logger logger} of the
081: * specified name and its childs. The parent logger name is typically {@code "org.geotools"},
082: * but could also be {@code ""} if events from other packages (including the log records from
083: * J2SE itself) should be redirected as well.
084: * <p>
085: * This method should be invoked again when the logging configuration change. For example
086: * if the <cite>Log4J</cite> configuration is dynamically changed at runtime, then this
087: * method should be invoked again.
088: * <p>
089: * If this method determines that <cite>commons-logging</cite> would redirect all log events
090: * to the java logging system, then this method do nothing and return {@code false}.
091: * <p>
092: * Note that this method throws an {@linkplain java.lang.Error error} if the Apache
093: * commons-logging package is not found on the classpath. For a safer alternative,
094: * consider invoking {@link Logging#redirectToCommonsLogging} instead.
095: *
096: * @param name The logger name, usually {@code ""} or {@code "org.geotools"}.
097: * @return {@code true} if the adapter has been installed or re-installed, or
098: * {@code false} if this method did nothing.
099: * @throws NoClassDefFoundError if the Apache commons-logging package was not found on the
100: * classpath.
101: *
102: * @see Logging#redirectToCommonsLogging
103: */
104: public static synchronized boolean install(final String name)
105: throws NoClassDefFoundError {
106: final Log log = LogFactory.getLog(name);
107: if (log instanceof Jdk14Logger) {
108: return false;
109: }
110: final Logger root = Logger.getLogger(name);
111: /*
112: * Log to the Java logger before to redirect it,
113: * so user can known where his logging are gone...
114: */
115: root.log(Logging.format(Level.CONFIG,
116: LoggingKeys.REDIRECTED_TO_COMMONS_LOGGING));
117: /*
118: * Now process to the installation.
119: */
120: removeAllHandlers(root);
121: root.addHandler(new CommonHandler(name, log));
122: root.setLevel(Level.ALL);
123: root.setUseParentHandlers(false);
124: return true;
125: }
126:
127: /**
128: * Remove all handlers from the specified logger.
129: */
130: private static void removeAllHandlers(final Logger logger) {
131: final Handler[] handlers = logger.getHandlers();
132: for (int i = 0; i < handlers.length; i++) {
133: logger.removeHandler(handlers[i]);
134: }
135: }
136:
137: /**
138: * Returns the logger (from the commons-logging package) of the specified name.
139: * This method try to preserve acceptable performances in two ways:
140: * <p>
141: * <ul>
142: * <li>The {@linkplain Log commons-logging loggers} are cached using the name as the key.</li>
143: * <li>The {@linkplain Logger#setLevel Java logger level} are set according the
144: * commons-logging level.</li>
145: * </ul>
146: */
147: private Log getLog(final String name) {
148: synchronized (loggers) {
149: Log log = (Log) loggers.get(name);
150: if (log == null) {
151: log = LogFactory.getLog(name);
152: assert !(log instanceof Jdk14Logger);
153: loggers.put(name, log);
154: final Level level;
155: if (log.isTraceEnabled()) {
156: level = Level.FINEST;
157: } else if (log.isDebugEnabled()) {
158: level = Level.FINER;
159: } else if (log.isInfoEnabled()) {
160: level = Level.CONFIG;
161: } else if (log.isWarnEnabled()) {
162: level = Level.WARNING;
163: } else if (log.isErrorEnabled()) {
164: level = Level.SEVERE;
165: } else if (log.isFatalEnabled()) {
166: level = Level.SEVERE;
167: } else {
168: level = Level.OFF;
169: }
170: final Logger logger = Logger.getLogger(name);
171: removeAllHandlers(logger);
172: logger.setUseParentHandlers(true);
173: logger.setLevel(level);
174: }
175: return log;
176: }
177: }
178:
179: /**
180: * Send the specified record to Apache's commons-logging framework.
181: */
182: public void publish(final LogRecord record) {
183: final String name = record.getLoggerName();
184: final Log log = (name != null) ? getLog(name) : logger;
185: final int level = record.getLevel().intValue();
186: final String message = getFormatter().formatMessage(record);
187: final Throwable throwable = record.getThrown();
188:
189: if (level == Level.OFF.intValue()) {
190: return;
191: } else if (level >= Level.SEVERE.intValue()) {
192: if (throwable != null) {
193: log.error(message, throwable);
194: } else {
195: log.error(message);
196: }
197: } else if (level >= Level.WARNING.intValue()) {
198: if (throwable != null) {
199: log.warn(message, throwable);
200: } else {
201: log.warn(message);
202: }
203: } else if (level >= Level.CONFIG.intValue()) {
204: if (throwable != null) {
205: log.info(message, throwable);
206: } else {
207: log.info(message);
208: }
209: } else if (level >= Level.FINER.intValue()) {
210: if (throwable != null) {
211: log.debug(message, throwable);
212: } else {
213: log.debug(message);
214: }
215: } else {
216: if (throwable != null) {
217: log.trace(message, throwable);
218: } else {
219: log.trace(message);
220: }
221: }
222: }
223:
224: /**
225: * Flush this handler. The default implementation does nothing.
226: */
227: public void flush() {
228: }
229:
230: /**
231: * Closes this handler. The default implementation just invokes {@link #flush}.
232: */
233: public void close() {
234: flush();
235: }
236: }
|