blob: 56e88b5b1f465da73ec5f70d55ac20bbb28b685e [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.felix.scr.impl.logger;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.MessageFormat;
import org.apache.felix.scr.impl.logger.InternalLogger.Level;
import org.apache.felix.scr.impl.manager.ScrConfiguration;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.service.log.Logger;
/**
* Implements a SCR based log manager. This class was needed to not change the
* whole codebase. It looks very similar to the old logging but leverages the
* {@link LogManager}. This class implements the existing behavior and the
* {@link ExtLogManager} implements the extension behavior. The {@link #scr()}
* method makes this distinction based on the configuration.
*/
public class ScrLogManager extends LogManager
{
private final Bundle bundle;
private final ScrConfiguration config;
/**
* Get a new log manager based on the configuration.
*
* @param context
* the bundle context of the SCR bundle
* @param config
* the SCR configuration
* @return a proper ScrLogManager
*/
public static ScrLogger scr(BundleContext context, ScrConfiguration config)
{
ScrLogManager manager;
if (config.isLogExtension())
manager = new ExtLogManager(context, config);
else
manager = new ScrLogManager(context, config);
manager.open();
return manager.scr();
}
ScrLogManager(BundleContext context, ScrConfiguration config)
{
super(context);
this.config = config;
this.bundle = context.getBundle();
}
/**
* This logger is used for the main code of SCR. This will use the SCR
* bundle & the {@link Logger#ROOT_LOGGER_NAME}
*
* @return an Scr Logger.
*/
public ScrLogger scr()
{
ScrLoggerFacade scrl = super.getLogger(bundle, Logger.ROOT_LOGGER_NAME,
ScrLoggerFacade.class);
scrl.setPrefix(getBundleIdentifier(bundle));
return scrl;
}
/**
* This logger is used for the logging on a per bundle basis. This will use
* the target bundle & the {@link Logger#ROOT_LOGGER_NAME}
*
* @param bundle
* the target bundle
* @return a logger suitable to log bundle entries
*/
public BundleLogger bundle(Bundle bundle)
{
ScrLoggerFacade logger = getLogger(bundle, Logger.ROOT_LOGGER_NAME,
ScrLoggerFacade.class);
logger.setPrefix(getBundleIdentifier(bundle));
return logger;
}
/**
* This logger is used for the logging on a per bundle basis. This will use
* the target bundle & the implementation class as logger name.
*
* @param bundle
* the target bundle
* @return a logger suitable to log bundle entries
*/
public ComponentLogger component(Bundle bundle, String implementationClass,
String name)
{
// assert bundle != null;
// assert bundle.getSymbolicName() != null : "scr requires recent
// bundles";
// assert implementationClass != null;
// assert name != null;
ScrLoggerFacade facade = getLogger(bundle, implementationClass,
ScrLoggerFacade.class);
facade.setComponentId(-1);
return (ComponentLogger) facade;
}
class ScrLoggerFacade extends LoggerFacade implements InternalLogger, ScrLogger, BundleLogger, ComponentLogger
{
ScrLoggerFacade(LogDomain logDomain, String name)
{
super(logDomain, name);
}
@Override
public void setComponentId(long id)
{
setPrefix(componentPrefix(this, id));
}
public boolean isLogEnabled(Level level)
{
// assert !closed.get();
Object checkLogger = getLogger();
if (checkLogger != null)
{
Logger logger = (Logger) checkLogger;
switch (level)
{
case AUDIT:
return true;
case ERROR:
return logger.isErrorEnabled();
case WARN:
return logger.isWarnEnabled();
case INFO:
return logger.isInfoEnabled();
case TRACE:
return logger.isTraceEnabled();
case DEBUG:
default:
return logger.isDebugEnabled();
}
}
else
{
return getLogLevel().implies(level);
}
}
@Override
public void log(Level level, String format, Throwable ex, Object... arguments)
{
if (isLogEnabled(level))
log0(level, format(format, arguments), ex);
}
@Override
public void log(Level level, String message, Throwable ex)
{
if (isLogEnabled(level))
log0(level, message, ex);
}
void log0(Level level, String message, Throwable ex)
{
if (prefix != null && prefix.length() > 0)
{
message = prefix.concat(" ").concat(message);
}
Object checkLogger = getLogger();
if (checkLogger != null)
{
Logger logger = (Logger) checkLogger;
if (ex == null)
{
switch (level)
{
case AUDIT:
logger.audit(message);
break;
case ERROR:
logger.error(message);
break;
case WARN:
logger.warn(message);
break;
case INFO:
logger.info(message);
break;
case TRACE:
logger.trace(message);
break;
case DEBUG:
default:
logger.debug(message);
}
}
else
{
switch (level)
{
case AUDIT:
logger.audit(message, ex);
break;
case ERROR:
logger.error(message, ex);
break;
case WARN:
logger.warn(message, ex);
break;
case INFO:
logger.info(message, ex);
break;
case TRACE:
logger.trace(message, ex);
break;
case DEBUG:
default:
logger.debug(message, ex);
}
}
}
else
{
StringWriter buf = new StringWriter();
String l = String.format("%-5s", level);
buf.append(l).append(" : ").append(message);
if (ex != null)
{
try (PrintWriter pw = new PrintWriter(buf))
{
pw.println();
ex.printStackTrace(pw);
}
}
@SuppressWarnings("resource")
PrintStream out = level.err() ? System.err : System.out;
out.println(buf);
}
}
void setPrefix(String prefix)
{
this.prefix = prefix;
}
@Override
public ComponentLogger component(Bundle bundle, String implementationClassName,
String name)
{
// assert !closed.get();
return ScrLogManager.this.component(bundle, implementationClassName, name);
}
@Override
public BundleLogger bundle(Bundle bundle)
{
// assert !closed.get();
return ScrLogManager.this.bundle(bundle);
}
@Override
public void close()
{
// assert !closed.get();
ScrLogManager.this.close();
}
};
LoggerFacade createLoggerFacade(LogDomain logDomain, String name)
{
// assert !closed.get();
return new ScrLoggerFacade(logDomain, name);
}
Level getLogLevel()
{
return config.getLogLevel();
}
String getBundleIdentifier(final Bundle bundle)
{
final StringBuilder sb = new StringBuilder("bundle ");
if (bundle.getSymbolicName() != null)
{
sb.append(bundle.getSymbolicName());
sb.append(':');
sb.append(bundle.getVersion());
sb.append(" (");
sb.append(bundle.getBundleId());
sb.append(")");
}
else
{
sb.append(bundle.getBundleId());
}
return sb.toString();
}
String componentPrefix(ScrLoggerFacade slf, long id)
{
if (id >= 0)
{
return getBundleIdentifier(slf.getBundle()) + "[" + slf.getName() + "(" + id
+ ")] :";
}
else
{
return getBundleIdentifier(slf.getBundle()) + "[" + slf.getName() + "] :";
}
}
String format(final String pattern, final Object... arguments)
{
if (arguments == null || arguments.length == 0)
{
return pattern;
}
else
{
for (int i = 0; i < arguments.length; i++)
{
if (arguments[i] instanceof Bundle)
{
arguments[i] = getBundleIdentifier((Bundle) arguments[i]);
}
}
return MessageFormat.format(pattern, arguments);
}
}
}