| /******************************************************************************* |
| * Copyright (c) 2006, 2012 Cognos Incorporated, IBM Corporation and others |
| * All rights reserved. This program and the accompanying materials are made |
| * available under the terms of the Eclipse Public License v1.0 which |
| * accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| ******************************************************************************/ |
| package org.eclipse.osgi.internal.log; |
| |
| import java.util.regex.Matcher; |
| import java.util.regex.Pattern; |
| import org.eclipse.equinox.log.Logger; |
| import org.osgi.framework.Bundle; |
| import org.osgi.framework.ServiceReference; |
| import org.osgi.service.log.*; |
| import org.osgi.service.log.admin.LoggerContext; |
| |
| public class LoggerImpl implements Logger { |
| static final String THIS_PACKAGE_NAME = LoggerImpl.class.getName().substring(0, LoggerImpl.class.getName().length() - LoggerImpl.class.getSimpleName().length()); |
| static final Object[] EMPTY = new Object[0]; |
| protected final ExtendedLogServiceImpl logServiceImpl; |
| protected final String name; |
| |
| private LogLevel enabledLevel = LogLevel.TRACE; |
| |
| public LoggerImpl(ExtendedLogServiceImpl logServiceImpl, String name, LoggerContext loggerContext) { |
| this.logServiceImpl = logServiceImpl; |
| this.name = name; |
| applyLoggerContext(loggerContext); |
| } |
| |
| public String getName() { |
| return name; |
| } |
| |
| public boolean isLoggable(int level) { |
| return logServiceImpl.isLoggable(name, level); |
| } |
| |
| public void log(int level, String message) { |
| log(null, level, message, null); |
| } |
| |
| public void log(int level, String message, Throwable exception) { |
| log(null, level, message, exception); |
| } |
| |
| @SuppressWarnings("rawtypes") |
| public void log(ServiceReference sr, int level, String message) { |
| log(sr, level, message, null); |
| } |
| |
| @SuppressWarnings("rawtypes") |
| public void log(ServiceReference sr, int level, String message, Throwable exception) { |
| log(sr, null, level, message, exception); |
| } |
| |
| public void log(Object context, int level, String message) { |
| log(context, level, message, null); |
| } |
| |
| public void log(Object context, int level, String message, Throwable exception) { |
| log(context, null, level, message, exception); |
| } |
| |
| private void log(Object context, LogLevel logLevelEnum, int level, String message, Throwable exception) { |
| log(logServiceImpl.getBundle(), context, logLevelEnum, level, message, exception); |
| } |
| |
| void log(Bundle entryBundle, Object context, LogLevel logLevelEnum, int level, String message, Throwable exception) { |
| if (logLevelEnum == null) { |
| logLevelEnum = getLogLevel(level); |
| } |
| if (enabledLevel.implies(logLevelEnum)) { |
| logServiceImpl.getFactory().log(entryBundle, name, getLocation(), context, logLevelEnum, level, message, exception); |
| } |
| } |
| |
| @SuppressWarnings("deprecation") |
| private LogLevel getLogLevel(int level) { |
| switch (level) { |
| case LogService.LOG_DEBUG : |
| return LogLevel.DEBUG; |
| case LogService.LOG_ERROR : |
| return LogLevel.ERROR; |
| case LogService.LOG_INFO : |
| return LogLevel.INFO; |
| case LogService.LOG_WARNING : |
| return LogLevel.WARN; |
| default : |
| return LogLevel.TRACE; |
| } |
| } |
| |
| @Override |
| public boolean isTraceEnabled() { |
| return enabledLevel.implies(LogLevel.TRACE); |
| } |
| |
| @Override |
| public void trace(String message) { |
| trace(message, EMPTY); |
| } |
| |
| @Override |
| public void trace(String format, Object arg) { |
| trace(format, new Object[] {arg}); |
| } |
| |
| @Override |
| public void trace(String format, Object arg1, Object arg2) { |
| trace(format, new Object[] {arg1, arg2}); |
| } |
| |
| @Override |
| public void trace(String format, Object... arguments) { |
| log(LogLevel.TRACE, format, arguments); |
| } |
| |
| @Override |
| public boolean isDebugEnabled() { |
| return enabledLevel.implies(LogLevel.DEBUG); |
| } |
| |
| @Override |
| public void debug(String message) { |
| debug(message, EMPTY); |
| } |
| |
| @Override |
| public void debug(String format, Object arg) { |
| debug(format, new Object[] {arg}); |
| } |
| |
| @Override |
| public void debug(String format, Object arg1, Object arg2) { |
| debug(format, new Object[] {arg1, arg2}); |
| } |
| |
| @Override |
| public void debug(String format, Object... arguments) { |
| log(LogLevel.DEBUG, format, arguments); |
| } |
| |
| @Override |
| public boolean isInfoEnabled() { |
| return enabledLevel.implies(LogLevel.INFO); |
| } |
| |
| @Override |
| public void info(String message) { |
| info(message, EMPTY); |
| } |
| |
| @Override |
| public void info(String format, Object arg) { |
| info(format, new Object[] {arg}); |
| } |
| |
| @Override |
| public void info(String format, Object arg1, Object arg2) { |
| info(format, new Object[] {arg1, arg2}); |
| } |
| |
| @Override |
| public void info(String format, Object... arguments) { |
| log(LogLevel.INFO, format, arguments); |
| } |
| |
| @Override |
| public boolean isWarnEnabled() { |
| return enabledLevel.implies(LogLevel.WARN); |
| } |
| |
| @Override |
| public void warn(String message) { |
| warn(message, EMPTY); |
| } |
| |
| @Override |
| public void warn(String format, Object arg) { |
| warn(format, new Object[] {arg}); |
| } |
| |
| @Override |
| public void warn(String format, Object arg1, Object arg2) { |
| warn(format, new Object[] {arg1, arg2}); |
| } |
| |
| @Override |
| public void warn(String format, Object... arguments) { |
| log(LogLevel.WARN, format, arguments); |
| } |
| |
| @Override |
| public boolean isErrorEnabled() { |
| return enabledLevel.implies(LogLevel.ERROR); |
| } |
| |
| @Override |
| public void error(String message) { |
| error(message, EMPTY); |
| } |
| |
| @Override |
| public void error(String format, Object arg) { |
| error(format, new Object[] {arg}); |
| } |
| |
| @Override |
| public void error(String format, Object arg1, Object arg2) { |
| error(format, new Object[] {arg1, arg2}); |
| } |
| |
| @Override |
| public void error(String format, Object... arguments) { |
| log(LogLevel.ERROR, format, arguments); |
| } |
| |
| @Override |
| public void audit(String message) { |
| audit(message, EMPTY); |
| } |
| |
| @Override |
| public void audit(String format, Object arg) { |
| audit(format, new Object[] {arg}); |
| } |
| |
| @Override |
| public void audit(String format, Object arg1, Object arg2) { |
| audit(format, new Object[] {arg1, arg2}); |
| } |
| |
| @Override |
| public void audit(String format, Object... arguments) { |
| log(LogLevel.AUDIT, format, arguments); |
| } |
| |
| @Override |
| public <E extends Exception> void trace(LoggerConsumer<E> consumer) throws E { |
| if (isTraceEnabled()) { |
| consumer.accept(this); |
| } |
| } |
| |
| @Override |
| public <E extends Exception> void debug(LoggerConsumer<E> consumer) throws E { |
| if (isDebugEnabled()) { |
| consumer.accept(this); |
| } |
| } |
| |
| @Override |
| public <E extends Exception> void info(LoggerConsumer<E> consumer) throws E { |
| if (isInfoEnabled()) { |
| consumer.accept(this); |
| } |
| } |
| |
| @Override |
| public <E extends Exception> void warn(LoggerConsumer<E> consumer) throws E { |
| if (isWarnEnabled()) { |
| consumer.accept(this); |
| } |
| } |
| |
| @Override |
| public <E extends Exception> void error(LoggerConsumer<E> consumer) throws E { |
| if (isErrorEnabled()) { |
| consumer.accept(this); |
| } |
| } |
| |
| private static final Pattern pattern = Pattern.compile("(\\\\?)(\\\\?)(\\{\\})"); //$NON-NLS-1$ |
| |
| private void log(LogLevel level, String format, Object... arguments) { |
| if (!enabledLevel.implies(level)) { |
| return; |
| } |
| StackTraceElement location = getLocation(); |
| Arguments processedArguments = new Arguments(arguments); |
| String message = processedArguments.isEmpty() ? format : formatMessage(format, processedArguments); |
| logServiceImpl.getFactory().log(logServiceImpl.getBundle(), name, location, processedArguments.serviceReference(), level, level.ordinal(), message.toString(), processedArguments.throwable()); |
| } |
| |
| private StackTraceElement getLocation() { |
| StackTraceElement[] elements = Thread.currentThread().getStackTrace(); |
| if (elements.length == 0) { |
| return null; |
| } |
| for (int i = 1; i < elements.length; i++) { |
| if (!elements[i].getClassName().startsWith(THIS_PACKAGE_NAME)) { |
| return elements[i]; |
| } |
| } |
| return elements[1]; |
| } |
| |
| String formatMessage(String format, Arguments processedArguments) { |
| Matcher matcher = pattern.matcher(format); |
| char[] chars = format.toCharArray(); |
| int offset = 0; |
| StringBuilder message = new StringBuilder(format.length() * 2); |
| for (Object argument : processedArguments.arguments()) { |
| // By design, the message will continue to be formatted for as long as arguments remain. |
| // Once all arguments have been processed, formatting stops. This means some escape characters |
| // and place holders may remain unconsumed. This matches SLF4J behavior. |
| while (matcher.find()) { |
| if (matcher.group(2).isEmpty()) { |
| if (matcher.group(1).isEmpty()) { |
| // {} Handle curly brackets as normal. |
| offset = append(message, matcher, chars, offset, matcher.start(3) - offset, argument); |
| break; |
| } |
| // \{} Ignore curly brackets. Consume backslash. |
| offset = append(message, matcher, chars, offset, matcher.start(3) - offset - 1, matcher.group(3)); |
| } else { |
| // \\{} Handle curly brackets as normal. Consume one backslash. |
| offset = append(message, matcher, chars, offset, matcher.start(3) - offset - 1, argument); |
| break; |
| } |
| } |
| } |
| message.append(chars, offset, chars.length - offset); |
| return message.toString(); |
| } |
| |
| private static int append(StringBuilder builder, Matcher matcher, char[] chars, int offset, int length, Object argument) { |
| builder.append(chars, offset, length); |
| builder.append(argument); |
| return matcher.end(3); |
| } |
| |
| void applyLoggerContext(LoggerContext loggerContext) { |
| enabledLevel = loggerContext == null ? LogLevel.WARN : loggerContext.getEffectiveLogLevel(name); |
| } |
| } |