blob: b1394226ce17de43123ff296cf4821da4e16774d [file] [log] [blame]
/* Copyright 2017, 2018 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.xmlbeans.impl.common;
/**
* A logger interface that strives to make it as easy as possible for
* developers to write log calls, while simultaneously making those
* calls as cheap as possible by performing lazy evaluation of the log
* message.<p>
*/
public abstract class XBLogger {
public static final int DEBUG = 1;
public static final int INFO = 3;
public static final int WARN = 5;
public static final int ERROR = 7;
public static final int FATAL = 9;
/** Short strings for numeric log level. Use level as array index. */
protected static final String LEVEL_STRINGS_SHORT[] = {"?", "D", "?", "I", "?", "W", "?", "E", "?", "F", "?"};
/** Long strings for numeric log level. Use level as array index. */
protected static final String LEVEL_STRINGS[] = {"?0?", "DEBUG", "?2?", "INFO", "?4?", "WARN", "?6?", "ERROR", "?8?", "FATAL", "?10+?"};
/**
* package scope so it cannot be instantiated outside of the util
* package. You need a XBLogger? Go to the XBLogFactory for one
*/
XBLogger() {
// no fields to initialize
}
abstract public void initialize(String cat);
/**
* Log a message
*
* @param level One of DEBUG, INFO, WARN, ERROR, FATAL
* @param obj1 The object to log. This is converted to a string.
*/
abstract protected void _log(int level, Object obj1);
/**
* Log a message
*
* @param level One of DEBUG, INFO, WARN, ERROR, FATAL
* @param obj1 The object to log. This is converted to a string.
* @param exception An exception to be logged
*/
abstract protected void _log(int level, Object obj1, final Throwable exception);
/**
* Check if a logger is enabled to log at the specified level
* This allows code to avoid building strings or evaluating functions in
* the arguments to log.
*
* An example:
* <code><pre>
* if (logger.check(XBLogger.INFO)) {
* logger.log(XBLogger.INFO, "Avoid concatenating " + " strings and evaluating " + functions());
* }
* </pre></code>
*
* @param level One of DEBUG, INFO, WARN, ERROR, FATAL
*/
abstract public boolean check(int level);
/**
* Log a message. Lazily appends Object parameters together.
* If the last parameter is a {@link Throwable} it is logged specially.
*
* @param level One of DEBUG, INFO, WARN, ERROR, FATAL
* @param objs the objects to place in the message
*/
public void log(int level, Object... objs) {
if (!check(level)) return;
StringBuilder sb = new StringBuilder(32);
Throwable lastEx = null;
for (int i=0; i<objs.length; i++) {
if (i == objs.length-1 && objs[i] instanceof Throwable) {
lastEx = (Throwable)objs[i];
} else {
sb.append(objs[i]);
}
}
String msg = sb.toString();
msg = msg.replaceAll("[\r\n]+", " "); // log forging escape
// somehow this ambiguity works and doesn't lead to a loop,
// but it's confusing ...
if (lastEx == null) {
_log(level, msg);
} else {
_log(level, msg, lastEx);
}
}
}