blob: 70752a511bc75090be7edfbd5837f49165a4fecd [file] [log] [blame]
/*
* Copyright 2005 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cocoon.util;
import org.apache.avalon.framework.logger.ConsoleLogger;
import org.apache.avalon.framework.logger.Logger;
import org.apache.commons.lang.enums.ValuedEnum;
/**
* This class provides a special static "deprecation" logger.
* All deprecated code should use this logger to log messages into the
* deprecation logger. This makes it easier for users to find out if they're
* using deprecated stuff.
* <p>
* Additionally, it is possible to set the forbidden level of deprecation messages (default
* is to forbid ERROR, i.e. allow up to WARN). Messages equal to or above the forbidden level
* will lead to throwing a {@link DeprecationException}. Setting the forbidden level to
* FATAL_ERROR allows running legacy applications using deprecated features (tolerant mode), and
* setting the forbidden level to DEBUG will run in strict mode, forbidding all deprecations.
* <p>
* Note that according to the above, issuing a fatalError log always raises an exception, and
* can therefore be used when detecting old features that have been totally removed.
*
* @version $Id$
*/
public class Deprecation {
/**
* The deprecation logger.
*/
public static final Logger logger = new LoggerWrapper(new ConsoleLogger());
private static final int DEBUG_VALUE = 0;
private static final int INFO_VALUE = 1;
private static final int WARN_VALUE = 2;
private static final int ERROR_VALUE = 3;
private static final int FATAL_VALUE = 3;
private static final int FATAL_ERROR_VALUE = 4;
/**
* Debug deprecation messages indicate features that are no more considered "current"
* or "best practice", but for which no removal is currently foreseen.
*/
public static final LogLevel DEBUG = new LogLevel("DEBUG", DEBUG_VALUE);
/**
* Info deprecation messages indicate features that are no more considered "current"
* or "best practice", and that will probably be removed in future releases.
*/
public static final LogLevel INFO = new LogLevel("INFO", INFO_VALUE);
/**
* Warning deprecation messages indicate features that will be removed in the next major
* version (e.g. 2.1.x --> 2.2.0). Such features should not be used if the application is
* planned to be migrated to newer Cocoon versions.
*/
public static final LogLevel WARN = new LogLevel("WARN", WARN_VALUE);
/**
* Error deprecation messages indicate features that will be removed in the next minor
* version (e.g. 2.1.6 --> 2.1.7). Although still functional, users are stronly invited to
* not use them.
*/
public static final LogLevel ERROR = new LogLevel("ERROR", ERROR_VALUE);
/**
* Fatal error deprecation messages indicate features that used to exist but have been removed
* in the current version. Logging such a message always throws a {@link DeprecationException}.
*/
public static final LogLevel FATAL_ERROR = new LogLevel("FATAL_ERROR", FATAL_ERROR_VALUE);
public static final class LogLevel extends ValuedEnum {
private LogLevel(String text, int value) {
super(text, value);
}
public static LogLevel getLevel(String level) {
return (LogLevel)ValuedEnum.getEnum(LogLevel.class, level);
}
}
public static void setLogger(Logger newLogger) {
// Note: the "logger" attribute is not of type LoggerWrapper so that it appears
// as a standard Logger in the javadocs.
((LoggerWrapper)logger).setLogger(newLogger);
}
public static void setForbiddenLevel(LogLevel level) {
// If null, reset to the default level
if (level == null) {
level = ERROR;
}
((LoggerWrapper)logger).setForbiddenLevel(level);
}
/**
* Wraps a logger, and throws an DeprecatedException if the message level is
* higher than the allowed one.
*/
private static class LoggerWrapper implements Logger {
private Logger realLogger;
// up to warn is allowed
private int forbiddenLevel = ERROR_VALUE;
public LoggerWrapper(Logger logger) {
this.realLogger = logger;
}
public void setLogger(Logger logger) {
// Unwrap a wrapped logger
while(logger instanceof LoggerWrapper) {
logger = ((LoggerWrapper)logger).realLogger;
}
this.realLogger = logger;
}
public void setForbiddenLevel(LogLevel level) {
this.forbiddenLevel = level.getValue();
}
private void throwException(int level, String message) {
if (level >= this.forbiddenLevel) {
throw new DeprecationException(message);
}
}
private boolean isThrowingException(int level) {
return level >= this.forbiddenLevel;
}
public void debug(String message) {
realLogger.debug(message);
throwException(DEBUG_VALUE, message);
}
public void debug(String message, Throwable thr) {
realLogger.debug(message, thr);
throwException(DEBUG_VALUE, message);
}
public void info(String message) {
realLogger.info(message);
throwException(INFO_VALUE, message);
}
public void info(String message, Throwable thr) {
realLogger.info(message, thr);
throwException(INFO_VALUE, message);
}
public void warn(String message) {
realLogger.warn(message);
throwException(WARN_VALUE, message);
}
public void warn(String message, Throwable thr) {
realLogger.warn(message, thr);
throwException(WARN_VALUE, message);
}
public void error(String message) {
realLogger.error(message);
throwException(ERROR_VALUE, message);
}
public void error(String message, Throwable thr) {
realLogger.error(message, thr);
throwException(ERROR_VALUE, message);
}
public void fatalError(String message) {
realLogger.fatalError(message);
throwException(FATAL_VALUE, message);
}
public void fatalError(String message, Throwable thr) {
realLogger.fatalError(message, thr);
throwException(FATAL_VALUE, message);
}
public boolean isDebugEnabled() {
// Enable level also if it is set to throw an exception, so that
// logging the message occurs, and then throws it.
return isThrowingException(DEBUG_VALUE) || realLogger.isDebugEnabled();
}
public boolean isInfoEnabled() {
return isThrowingException(INFO_VALUE) || realLogger.isInfoEnabled();
}
public boolean isWarnEnabled() {
return isThrowingException(WARN_VALUE) || realLogger.isWarnEnabled();
}
public boolean isErrorEnabled() {
return isThrowingException(ERROR_VALUE) || realLogger.isErrorEnabled();
}
public boolean isFatalErrorEnabled() {
return true;
}
public Logger getChildLogger(String message) {
return realLogger.getChildLogger(message);
}
}
}