blob: 2d98b9298e9de6f02f42916e837c8812a6ca9e02 [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.log;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.concurrent.atomic.AtomicLong;
import org.osgi.framework.Bundle;
import org.osgi.framework.ServiceReference;
import org.osgi.service.log.LogEntry;
import org.osgi.service.log.LogLevel;
import org.osgi.service.log.LogService;
/**
* Implementation of the OSGi {@link LogEntry} interface. See section 101
* of the OSGi service compendium.
* <p>
* Provides methods to access the information contained in an individual Log
* Service log entry.
* <p>
* A LogEntry object may be acquired from the
* {@link org.osgi.service.log.LogReaderService#getLog()} method or by
* registering a {@link org.osgi.service.log.LogListener} object.
* @see org.osgi.service.log.LogReaderService#getLog()
* @see org.osgi.service.log.LogListener
*/
final class LogEntryImpl implements LogEntry
{
/** The sequence number generator. */
private static final AtomicLong m_sequenceGenerator = new AtomicLong();
/** The name of the logger used to create the LogEntry. */
private final String m_name;
/** The bundle that created the LogEntry object. */
private final Bundle m_bundle;
/** The exception associated with this LogEntry object. */
private final Throwable m_exception;
/** The severity level of this LogEntry object. */
private final LogLevel m_level;
private final int m_legacyLevel;
/** The message associated with this LogEntry object. */
private final String m_message;
/** The service reference associated with this LogEntry object. */
private final ServiceReference<?> m_serviceReference;
/** The system time in milliseconds when this LogEntry object was created. */
private final long m_time;
/** The sequence of the LogEntry. */
private final long m_sequence;
/** The information about the Thread which logged the message. */
private final String m_threadInfo;
/** The StackTraceElement where the message was originally logged. */
private final StackTraceElement m_stackTraceElement;
private volatile String _toString;
/**
* Create a new instance.
* @param name the name of the logger used to create the LogEntry
* @param bundle the bundle that created the LogEntry object
* @param sr the service reference to associate with this LogEntry object
* @param level the severity level for this LogEntry object
* @param message the message to associate with this LogEntry object
* @param exception the exception to associate with this LogEntry object
*/
LogEntryImpl(
final String name,
final Bundle bundle,
final ServiceReference<?> sr,
final LogLevel level,
final String message,
final Throwable exception,
final StackTraceElement stackTraceElement)
{
this.m_name = name;
this.m_bundle = bundle;
this.m_exception = LogException.getException(exception);
this.m_level = level;
this.m_legacyLevel = level.ordinal();
this.m_message = message;
this.m_serviceReference = sr;
this.m_time = System.currentTimeMillis();
this.m_sequence = m_sequenceGenerator.getAndIncrement();
this.m_threadInfo = Thread.currentThread().getName();
this.m_stackTraceElement = stackTraceElement;
}
@SuppressWarnings("deprecation")
LogEntryImpl(
final String name,
final Bundle bundle,
final ServiceReference<?> sr,
final int legacyLevel,
final String message,
final Throwable exception,
final StackTraceElement stackTraceElement)
{
this.m_name = name;
this.m_bundle = bundle;
this.m_exception = LogException.getException(exception);
LogLevel level = LogLevel.TRACE;
switch (legacyLevel) {
case LogService.LOG_ERROR:
level = LogLevel.ERROR;
break;
case LogService.LOG_WARNING:
level = LogLevel.WARN;
break;
case LogService.LOG_INFO:
level = LogLevel.INFO;
break;
case LogService.LOG_DEBUG:
level = LogLevel.DEBUG;
}
this.m_level = level;
this.m_legacyLevel = ((level == LogLevel.TRACE) ? legacyLevel : level.ordinal());
this.m_message = message;
this.m_serviceReference = sr;
this.m_time = System.currentTimeMillis();
this.m_sequence = m_sequenceGenerator.getAndIncrement();
this.m_threadInfo = Thread.currentThread().getName();
this.m_stackTraceElement = stackTraceElement;
}
/**
* Returns the bundle that created this LogEntry object.
* @return the bundle that created this LogEntry object;<code>null</code> if no
* bundle is associated with this LogEntry object
*/
public Bundle getBundle()
{
return m_bundle;
}
/**
* Returns the {@link ServiceReference} object for the service associated with
* this LogEntry object.
* @return the {@link ServiceReference} object for the service associated with
* this LogEntry object; <code>null</code> if no {@link ServiceReference} object
* was provided
*/
public ServiceReference<?> getServiceReference()
{
return m_serviceReference;
}
/**
* Returns the severity level of this LogEntry object.
* <p>
* This is one of the severity levels defined by the
* {@link org.osgi.service.logLogService} interface.
* @return severity level of this LogEntry object.
* @see org.osgi.service.LogService#LOG_ERROR
* @see org.osgi.service.LogService#LOG_WARNING
* @see org.osgi.service.LogService#LOG_INFO
* @see org.osgi.service.LogService#LOG_DEBUG
*/
public int getLevel()
{
if (m_legacyLevel != m_level.ordinal()) {
return m_legacyLevel;
}
return m_level.ordinal();
}
/**
* Returns the human readable message associated with this LogEntry object.
* @return a string containing the message associated with this LogEntry object
*/
public String getMessage()
{
return m_message;
}
/**
* Returns the exception object associated with this LogEntry object.
* <p>
* The returned exception may not be the original exception. To avoid
* references to a bundle defined exception class, thus preventing an
* uninstalled bundle from being garbage collected, this LogService will
* return an exception object of an implementation defined
* {@link Throwable} sub-class.
* This exception will maintain as much information as possible from the
* original exception object such as the message and stack trace.
* @return throwable object of the exception associated with this LogEntry;
* <code>null</code> if no exception is associated with this LogEntry object
*/
public Throwable getException()
{
return m_exception;
}
/**
* Returns the value of {@link System#currentTimeMillis()} at the time this
* LogEntry object was created.
* @return the system time in milliseconds when this LogEntry object was created
* @see System#currentTimeMillis()
*/
public long getTime()
{
return m_time;
}
@Override
public LogLevel getLogLevel() {
return m_level;
}
@Override
public String getLoggerName() {
return m_name;
}
@Override
public long getSequence() {
return m_sequence;
}
@Override
public String getThreadInfo() {
return m_threadInfo;
}
@Override
public StackTraceElement getLocation() {
return m_stackTraceElement;
}
@Override
public String toString() {
if (_toString == null) {
_toString = m_time + "#" + m_sequence + " [" + m_threadInfo + "] " + m_level +
" (" + m_legacyLevel + ") [" + m_bundle.getBundleId() + ":" + m_name + "] " +
m_stackTraceElement.getClassName() + ":" +
m_stackTraceElement.getLineNumber() + " > " + m_message +
(m_exception != null ? "\n" + exceptionString(m_exception) : "");
}
return _toString;
}
String exceptionString(Throwable t) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
t.printStackTrace(pw);
return sw.toString();
}
}