001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. 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: package org.apache.cocoon.util;
018:
019: import org.apache.avalon.framework.logger.ConsoleLogger;
020: import org.apache.avalon.framework.logger.Logger;
021: import org.apache.commons.lang.enums.Enum;
022: import org.apache.commons.lang.enums.ValuedEnum;
023:
024: /**
025: * This class provides a special static "deprecation" logger.
026: * All deprecated code should use this logger to log messages into the
027: * deprecation logger. This makes it easier for users to find out if they're
028: * using deprecated stuff.
029: * <p>
030: * Additionally, it is possible to set the forbidden level of deprecation messages (default
031: * is to forbid ERROR, i.e. allow up to WARN). Messages equal to or above the forbidden level
032: * will lead to throwing a {@link DeprecationException}. Setting the forbidden level to
033: * FATAL_ERROR allows running legacy applications using deprecated features (tolerant mode), and
034: * setting the forbidden level to DEBUG will run in strict mode, forbidding all deprecations.
035: * <p>
036: * Note that according to the above, issuing a fatalError log always raises an exception, and
037: * can therefore be used when detecting old features that have been totally removed.
038: *
039: * @version $Id: Deprecation.java 479306 2006-11-26 07:49:17Z antonio $
040: */
041: public class Deprecation {
042:
043: /**
044: * The deprecation logger.
045: */
046: public static final Logger logger = new LoggerWrapper(
047: new ConsoleLogger());
048:
049: private static final int DEBUG_VALUE = 0;
050: private static final int INFO_VALUE = 1;
051: private static final int WARN_VALUE = 2;
052: private static final int ERROR_VALUE = 3;
053: private static final int FATAL_VALUE = 3;
054: private static final int FATAL_ERROR_VALUE = 4;
055:
056: /**
057: * Debug deprecation messages indicate features that are no more considered "current"
058: * or "best practice", but for which no removal is currently foreseen.
059: */
060: public static final LogLevel DEBUG = new LogLevel("DEBUG",
061: DEBUG_VALUE);
062:
063: /**
064: * Info deprecation messages indicate features that are no more considered "current"
065: * or "best practice", and that will probably be removed in future releases.
066: */
067: public static final LogLevel INFO = new LogLevel("INFO", INFO_VALUE);
068:
069: /**
070: * Warning deprecation messages indicate features that will be removed in the next major
071: * version (e.g. 2.1.x --> 2.2.0). Such features should not be used if the application is
072: * planned to be migrated to newer Cocoon versions.
073: */
074: public static final LogLevel WARN = new LogLevel("WARN", WARN_VALUE);
075:
076: /**
077: * Error deprecation messages indicate features that will be removed in the next minor
078: * version (e.g. 2.1.6 --> 2.1.7). Although still functional, users are stronly invited to
079: * not use them.
080: */
081: public static final LogLevel ERROR = new LogLevel("ERROR",
082: ERROR_VALUE);
083:
084: /**
085: * Fatal error deprecation messages indicate features that used to exist but have been removed
086: * in the current version. Logging such a message always throws a {@link DeprecationException}.
087: */
088: public static final LogLevel FATAL_ERROR = new LogLevel(
089: "FATAL_ERROR", FATAL_ERROR_VALUE);
090:
091: public static final class LogLevel extends ValuedEnum {
092: private LogLevel(String text, int value) {
093: super (text, value);
094: }
095:
096: public static LogLevel getLevel(String level) {
097: return (LogLevel) Enum.getEnum(LogLevel.class, level);
098: }
099: }
100:
101: public static void setLogger(Logger newLogger) {
102: // Note: the "logger" attribute is not of type LoggerWrapper so that it appears
103: // as a standard Logger in the javadocs.
104: ((LoggerWrapper) logger).setLogger(newLogger);
105: }
106:
107: public static void setForbiddenLevel(LogLevel level) {
108: // If null, reset to the default level
109: if (level == null) {
110: level = ERROR;
111: }
112: ((LoggerWrapper) logger).setForbiddenLevel(level);
113: }
114:
115: /**
116: * Wraps a logger, and throws an DeprecatedException if the message level is
117: * higher than the allowed one.
118: */
119: private static class LoggerWrapper implements Logger {
120:
121: private Logger realLogger;
122: // up to warn is allowed
123: private int forbiddenLevel = ERROR_VALUE;
124:
125: public LoggerWrapper(Logger logger) {
126: this .realLogger = logger;
127: }
128:
129: public void setLogger(Logger logger) {
130: // Unwrap a wrapped logger
131: while (logger instanceof LoggerWrapper) {
132: logger = ((LoggerWrapper) logger).realLogger;
133: }
134: this .realLogger = logger;
135: }
136:
137: public void setForbiddenLevel(LogLevel level) {
138: this .forbiddenLevel = level.getValue();
139: }
140:
141: private void throwException(int level, String message) {
142: if (level >= this .forbiddenLevel) {
143: throw new DeprecationException(message);
144: }
145: }
146:
147: private boolean isThrowingException(int level) {
148: return level >= this .forbiddenLevel;
149: }
150:
151: public void debug(String message) {
152: realLogger.debug(message);
153: throwException(DEBUG_VALUE, message);
154: }
155:
156: public void debug(String message, Throwable thr) {
157: realLogger.debug(message, thr);
158: throwException(DEBUG_VALUE, message);
159: }
160:
161: public void info(String message) {
162: realLogger.info(message);
163: throwException(INFO_VALUE, message);
164: }
165:
166: public void info(String message, Throwable thr) {
167: realLogger.info(message, thr);
168: throwException(INFO_VALUE, message);
169: }
170:
171: public void warn(String message) {
172: realLogger.warn(message);
173: throwException(WARN_VALUE, message);
174: }
175:
176: public void warn(String message, Throwable thr) {
177: realLogger.warn(message, thr);
178: throwException(WARN_VALUE, message);
179: }
180:
181: public void error(String message) {
182: realLogger.error(message);
183: throwException(ERROR_VALUE, message);
184: }
185:
186: public void error(String message, Throwable thr) {
187: realLogger.error(message, thr);
188: throwException(ERROR_VALUE, message);
189: }
190:
191: public void fatalError(String message) {
192: realLogger.fatalError(message);
193: throwException(FATAL_VALUE, message);
194: }
195:
196: public void fatalError(String message, Throwable thr) {
197: realLogger.fatalError(message, thr);
198: throwException(FATAL_VALUE, message);
199: }
200:
201: public boolean isDebugEnabled() {
202: // Enable level also if it is set to throw an exception, so that
203: // logging the message occurs, and then throws it.
204: return isThrowingException(DEBUG_VALUE)
205: || realLogger.isDebugEnabled();
206: }
207:
208: public boolean isInfoEnabled() {
209: return isThrowingException(INFO_VALUE)
210: || realLogger.isInfoEnabled();
211: }
212:
213: public boolean isWarnEnabled() {
214: return isThrowingException(WARN_VALUE)
215: || realLogger.isWarnEnabled();
216: }
217:
218: public boolean isErrorEnabled() {
219: return isThrowingException(ERROR_VALUE)
220: || realLogger.isErrorEnabled();
221: }
222:
223: public boolean isFatalErrorEnabled() {
224: return true;
225: }
226:
227: public Logger getChildLogger(String message) {
228: return realLogger.getChildLogger(message);
229: }
230: }
231: }
|