The version of Apache log4j used by SoundHelix.
Clone
HTTPS:
git clone https://vervis.peers.community/repos/aEp6o
SSH:
git clone USERNAME@vervis.peers.community:aEp6o
Branches
Tags
- 1.3alpha-7
- CHAINSAW_2_SANDBOX_MERGE
- CORE_VERSION
- LEVEL_REPLACES_PRIORITY
- PREALPHA_1_3_AS_OF_2004_05_12
- PRE_CHAINSAW_MODEL_CONVERSION
- PRE_UGLI_MOVE
- TAG_CHAINSAW2_MOVE
- log4j-1.2.17
- log4j-1.2.17-rc1
- v1.3alpha8
- v1.3alpha8-temp
- v1_2_1
- v1_2_10-recalled
- v1_2_11
- v1_2_11_rc1
- v1_2_11rc3
- v1_2_12
- v1_2_12_rc1
- v1_2_12_rc2
- v1_2_12_rc3
- v1_2_12_rc4
- v1_2_12_rc5
- v1_2_12_rc6
- v1_2_13
- v1_2_13_rc1
- v1_2_13_rc2
- v1_2_13_site_update
- v1_2_14
- v1_2_14_maven
- v1_2_14_rc1
- v1_2_14_site_update
- v1_2_15
- v1_2_15_rc1
- v1_2_15_rc2
- v1_2_15_rc3
- v1_2_15_rc4
- v1_2_15_rc5
- v1_2_15_rc6
- v1_2_16
- v1_2_16_rc1
- v1_2_16_rc2
- v1_2_17
- v1_2_17-rc1
- v1_2_17_rc1
- v1_2_17_rc2
- v1_2_17_rc3
- v1_2_2
- v1_2_3
- v1_2_4
- v1_2_6
- v1_2_7
- v1_2_9
- v1_2_alpha0
- v1_2_alpha7
- v1_2beta1
- v1_2final
- v1_3alpha_1
- v1_3alpha_6
- v_1_0
- v_1_0_1
- v_1_0_4
- v_1_1
- v_1_1_1
- v_1_1_2
- v_1_1_3
- v_1_1_b1
- v_1_1b2
- v_1_1b3
- v_1_1b5
- v_1_1b6
- v_1_1b7
- v_1_2beta3
LoggingEvent.java
/*
* Copyright 1999,2004 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.log4j.spi;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.Hashtable;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.MDC;
import org.apache.log4j.NDC;
import org.apache.log4j.helpers.Loader;
import org.apache.log4j.spi.location.LocationInfo;
// Contributors: Nelson Minar <nelson@monkey.org>
// Wolf Siberski
// Anders Kristensen <akristensen@dynamicsoft.com>
/**
* The internal representation of logging events. When an affirmative decision
* is made to log then a <code>LoggingEvent</code> instance is created. This
* instance is passed around to the different log4j components.
*
* <p>
* This class is of concern to those wishing to extend log4j.
* </p>
*
* <p>Writers of log4j components such as appenders and receivers should be
* aware of that some of the LoggingEvent fields are initialized lazily.
* Therefore, an appender wishing to output data to be later correctly read
* by a receiver, must initialize "lazy" fields prior to writing them out.
* See the {@link #prepareForDeferredProcessing()} method for the exact list.</p>
*
* <p>Moreover, in the absence of certain fields, receivers must set the
* values of null fields to a default non-null value. For example, in the
* absence of the locationInfo data, the locationInfo field should be
* set to {@link org.apache.log4j.spi.location.LocationInfo#NA_LOCATION_INFO
* LocationInfo.NA_LOCATION_INFO}.
*
*
* @author Ceki Gülcü
* @author James P. Cakalic
*/
public class LoggingEvent
implements java.io.Serializable {
private static long startTime = System.currentTimeMillis();
// Serialization
static final long serialVersionUID = -868428216207166145L;
static final Integer[] PARAM_ARRAY = new Integer[1];
static final String TO_LEVEL = "toLevel";
static final Class[] TO_LEVEL_PARAMS = new Class[] { int.class };
static final Hashtable methodCache = new Hashtable(3); // use a tiny table
/**
* LoggingEvent are stamped with a {@link #sequenceNumber}. The
* <code>sequenceCount</code> static variable keeps track of the current count.
*
* The count starts at 1 (one).
*
* @since 1.3
*/
static long sequenceCount = 1;
/**
* Fully qualified name of the calling category class. This field does not
* survive serialization.
*
* <p>Note that the getLocationInfo() method relies on this fact.
*/
transient String fqnOfLoggerClass;
/**
* The category of the logging event. This field is not serialized for
* performance reasons.
*
* <p>
* It is set by the LoggingEvent constructor or set by a remote entity after
* deserialization.
* </p>
*
* @deprecated This field will be marked as private or be completely removed
* in future releases. Please do not use it.
*/
private transient Logger logger;
/**
* The LoggerRepository in which this event was created.
*
* @since 1.3
*/
private transient LoggerRepository loggerRepository;
// The logger name.
//
// the 'logger name' variable name ("categoryName") must remain the same
// as prior versions in order to maintain serialization compatibility with
// log4j 1.2.8
private String categoryName;
/**
* Level of logging event. Level cannot be serializable because it is a
* flyweight. Due to its special seralization it cannot be declared final
* either.
*
* <p>
* This field should not be accessed directly. You shoud use the {@link
* #getLevel} method instead.
* </p>
*
*/
private transient Level level;
/**
* The nested diagnostic context (NDC) of logging event.
*/
private String ndc;
/**
* <p>The properties map is specific for this event.</p>
*
* <p>When serialized, it contains a copy of MDC properties as well
* as LoggerRepository properties.
* </p>
*
* <p>It survives serialization.</p>
* @since 1.3
*/
private Map properties;
/**
* Have we tried to do an NDC lookup? If we did, there is no need to do it
* again. Note that its value is always false when serialized. Thus, a
* receiving SocketNode will never use it's own (incorrect) NDC. See also
* writeObject method.
*/
private boolean ndcLookupRequired = true;
/**
* The application supplied message of logging event.
*/
private transient Object message;
/**
* The application supplied message rendered through the log4j objet
* rendering mechanism.
*/
private String renderedMessage;
/**
* The name of thread in which this logging event was generated.
*/
private String threadName;
/**
* This variable contains information about this event's throwable
*/
private ThrowableInformation throwableInfo;
/**
* The number of milliseconds elapsed from 1/1/1970 until logging event was
* created.
*/
private long timeStamp;
/**
*
* Each logging event bears a sequence number.
*
* @since 1.3
*/
long sequenceNumber;
/**
* Location information for the caller.
*/
private LocationInfo locationInfo;
/**
* @return The current sequenceCount for this JVM.
*/
public static long getSequenceCount() {
return sequenceCount;
}
/**
* The no-argument constructor for LoggingEvent. This method is the recommended
* constructor for creating LoggingEvent instances.
*
* @since 1.3
*/
public LoggingEvent() {
}
/**
* Instantiate a LoggingEvent from the supplied parameters.
*
* <p>Note that many of the LoggingEvent fields are initialized when actually
* needed. For more information please refer to the comments for the
* LoggingEvent class at the top of this page.
* </p>
*
* @param logger The logger of this event.
* @param level The level of this event.
* @param message The message of this event.
* @param throwable The throwable of this event.
*/
public LoggingEvent(String fqnOfLoggerClass, Logger logger, Level level, Object message, Throwable throwable) {
this.fqnOfLoggerClass = fqnOfLoggerClass;
this.logger = logger;
this.categoryName = logger.getName();
this.level = level;
this.message = message;
if (throwable != null) {
this.throwableInfo = new ThrowableInformation(throwable);
}
timeStamp = System.currentTimeMillis();
synchronized(LoggingEvent.class) {
sequenceNumber = sequenceCount++;
}
}
/**
* Instantiate a LoggingEvent from the supplied parameters.
*
* <p>Note that many of the LoggingEvent fields are initialized lazily. For
* more information please refer to the comments for the LoggingEvent class
* at the top of this page.
* </p>
*
* @param fqnOfCategoryClass The category of this event.
* @param logger The logger
* @param timeStamp the timestamp of this logging event
* @param level The level of this event.
* @param message The message of this event.
* @param throwable The throwable of this event.
* @deprecated Please use the no argument constructor and the setter methods
* instead.
*/
public LoggingEvent(String fqnOfCategoryClass, Logger logger, long timeStamp, Level level, Object message,
Throwable throwable) {
this.fqnOfLoggerClass = fqnOfCategoryClass;
this.logger = logger;
this.categoryName = logger.getName();
this.level = level;
this.message = message;
if (throwable != null) {
this.throwableInfo = new ThrowableInformation(throwable);
}
this.timeStamp = timeStamp;
synchronized(LoggingEvent.class) {
sequenceNumber = sequenceCount++;
}
}
/**
* Two events are considerd equal if they refer to the same instance, or if
* both their timestamps and sequence numbers match.
*/
public boolean equals(Object rObject) {
if (this == rObject) {
return true;
}
if (! (rObject instanceof LoggingEvent)) {
return false;
}
LoggingEvent rEvent = (LoggingEvent)rObject;
if (timeStamp != rEvent.timeStamp) {
return false;
}
if (sequenceNumber != rEvent.sequenceNumber) {
return false;
}
// at this point, the probability of the two events being equal is
// extremely high. The next few test is optimized to take advantage of
// this knowlege. (We only compare string lengths instead of invoking
// string.equals which is much slower when the two string are equal.
if(categoryName != null && rEvent.categoryName != null) {
if(categoryName.length() != rEvent.categoryName.length()) {
return false;
}
} else if(categoryName != rEvent.categoryName) {
// of categoryNames is null while the other is not, they can't possibly
// be equal
return false;
}
// If timestamp, sequenceNumber and categoryName length are equal than the
// events are assumed to be equal.
return true;
}
/**
* The hashcode is computed as XOR of the lower 32 bits of sequenceNumber and
* bits 21 to 53 of timeStamp;
*/
public int hashCode() {
// 2^20 millis corresponds to 17 minutes
return (int)((timeStamp >> 20) ^ (sequenceNumber & 0xFFFFFFFF));
}
/**
* Check for the existence of location information without creating it (a byproduct of calling
* getLocationInformation).
*/
public boolean locationInformationExists() {
return (locationInfo != null);
}
/**
* Get the location information for this logging event. If location
* information is null at the time of its invocation, this method extracts
* location information. The collected information is cached for future use.
*
* <p>Note that after serialisation, it is impossible to correctly extract
* location information. In that case null is returned.</p>
*/
public LocationInfo getLocationInformation() {
// we rely on the fact that fqnOfLoggerClass does not survive
// serialization
if (locationInfo == null && fqnOfLoggerClass != null) {
locationInfo = new LocationInfo(new Throwable(), fqnOfLoggerClass);
}
return locationInfo;
}
/**
* Set the location information for this logging event.
* @since 1.3
*/
public void setLocationInformation(LocationInfo li) {
if (locationInfo != null) {
throw new IllegalStateException("LocationInformation has been already set.");
}
locationInfo = li;
}
/**
* Return the level of this event.
*/
public Level getLevel() {
return (Level)level;
}
/**
* Set the level of this event. The level can be set at most once.
*
* @param level The level to set.
* @throws IllegalStateException if the level has been already set.
* @since 1.3
*/
public void setLevel(Level level) {
if (this.level != null) {
throw new IllegalStateException("The level has been already set for this event.");
}
this.level = level;
}
/**
* Returns the logger of this event. May be null because events after
* serialization do not have a logger.
*
* @since 1.3
**/
public Logger getLogger() {
return logger;
}
/**
* Set the logger of this event. Calling this method also sets the <code>loggerName</code>
* for the event. The logger can be set at most once.
*
* Moreover, if the loggerName has been already set, this method will throw
* an {@link IllegalStateException}.
*
* @throws IllegalStateException
*/
public void setLogger(Logger logger) {
if (this.logger != null) {
throw new IllegalStateException("logger has been already set to [" + this.logger.getName() + "].");
}
if (this.categoryName != null) {
throw new IllegalStateException("loggerName has been already set to [" + this.categoryName + "], logger "
+ logger.getName() + "] is invalid");
}
this.logger = logger;
this.categoryName = logger.getName();
}
/**
* Return the name of the logger.
*/
public String getLoggerName() {
return categoryName;
}
/**
* Set the loggerName for this event. The loggerName can be set at most once.
*
* @param loggerName The loggerName to set.
* @throws IllegalStateException if loggerName is already set
* @since 1.3
*/
public void setLoggerName(String loggerName)
throws IllegalStateException {
if (this.categoryName != null) {
throw new IllegalStateException("loggerName has been already set to [" + this.categoryName + "].");
} else {
this.categoryName = loggerName;
}
}
/**
* Return the message for this logging event.
*
* <p>
* Before serialization, the returned object is the message passed by the
* user to generate the logging event. After serialization, the returned
* value equals the String form of the message possibly after object
* rendering.
* </p>
*
* @since 1.1
*/
public Object getMessage() {
if (message != null) {
return message;
} else {
return getRenderedMessage();
}
}
/**
* Set the message for this event. The
* @param message The message to set.
* @since 1.3
*/
public void setMessage(Object message) {
if (this.message != null) {
throw new IllegalStateException("The message for this event has been set alredy.");
}
// After serialisation, message will be null and renderedMessage will be non-null.
if (this.renderedMessage != null) {
throw new IllegalStateException("The message cannot be set if the renderedMessage has been set.");
}
this.message = message;
}
/**
* This method returns the NDC for this event. It will return the correct
* content even if the event was generated in a different thread or even on
* a different machine. The {@link NDC#get} method should <em>never</em> be
* called directly.
*/
public String getNDC() {
if (ndcLookupRequired) {
ndcLookupRequired = false;
ndc = NDC.get();
}
return ndc;
}
/**
* This method sets the NDC string for this event.
* @throws IllegalStateException if ndc had been already set.
* @since 1.3
*/
public void setNDC(String ndcString) {
if (this.ndc != null) {
throw new IllegalStateException("The ndc has been already set.");
}
ndcLookupRequired = false;
ndc = ndcString;
}
/**
* If the properties field is null, this method creates a new properties map
* containing a copy of MDC context and a copy of the properites in
* LoggerRepository generating this event. If properties is non-null,
* this method does nothing.
*
* @since 1.3
*/
public void initializeProperties() {
if(properties == null) {
properties = new TreeMap();
Map mdcMap = MDC.getContext();
if (mdcMap != null) {
properties.putAll(mdcMap);
}
if (logger != null) {
properties.putAll(logger.getLoggerRepository().getProperties());
}
}
}
/**
* Return a property for this event. The return value can be null.
*
* <p>The property is searched first in the properties map specific for this
* event, then in the MDC, then in the logger repository containing the logger
* of this event.
* @since 1.3
*/
public String getProperty(String key) {
String value = null;
if (properties != null) {
value = (String)properties.get(key);
if (value != null) {
return value;
}
}
// if the key was not found in this even't properties, try the MDC
value = MDC.get(key);
if (value != null) {
return value;
}
// if still not found try, the properties in the logger repository
if (logger != null) {
value = logger.getLoggerRepository().getProperty(key);
}
return value;
}
/**
* Returns the set of of the key values in the properties
* for the event.
*
* The returned set is unmodifiable by the caller.
*
* @return Set an unmodifiable set of the property keys.
* @since 1.3
*/
public Set getPropertyKeySet() {
initializeProperties();
return Collections.unmodifiableSet(properties.keySet());
}
/**
* Returns the rendered version of the message according to the renderers
* registered in the logger repository.
*
* Only the rendered version survives serialization.
*
*/
public String getRenderedMessage() {
if ((renderedMessage == null) && (message != null)) {
if (message instanceof String) {
renderedMessage = (String)message;
} else {
// The logger has a back-reference to the repository containing it
LoggerRepository repository = logger.getLoggerRepository();
if (repository instanceof RendererSupport) {
RendererSupport rs = (RendererSupport)repository;
renderedMessage = rs.getRendererMap().findAndRender(message);
} else {
renderedMessage = message.toString();
}
}
}
return renderedMessage;
}
/**
*
* @param renderedMessage The renderedMessage to set.
* @throws IllegalStateException if renderedMessage has been already set.
* @since 1.3
*/
public void setRenderedMessage(String renderedMessage)
throws IllegalStateException {
if (this.renderedMessage != null) {
throw new IllegalStateException("renderedMessage has been already set.");
}
this.renderedMessage = renderedMessage;
}
/**
* Returns the time when the application started, in milliseconds elapsed
* since 01.01.1970.
*/
public static long getStartTime() {
return startTime;
}
/**
*
* @since 1.3
*/
public long getSequenceNumber() {
return sequenceNumber;
}
/**
*
* @since 1.3
*/
public void setSequenceNumber(long sequenceNumber) {
this.sequenceNumber = sequenceNumber;
}
public String getThreadName() {
if (threadName == null) {
threadName = (Thread.currentThread()).getName();
}
return threadName;
}
/**
* @param threadName The threadName to set.
* @throws IllegalStateException If threadName has been already set.
*/
public void setThreadName(String threadName)
throws IllegalStateException {
if (this.threadName != null) {
throw new IllegalStateException("threadName has been already set");
}
this.threadName = threadName;
}
/**
* Returns the throwable information contained within this event. May be
* <code>null</code> if there is no such information.
*
* <p>
* Note that the {@link Throwable} object contained within a {@link
* ThrowableInformation} does not survive serialization.
* </p>
*
* @since 1.1
*/
public ThrowableInformation getThrowableInformation() {
return throwableInfo;
}
/**
* Return this event's throwable's string[] representaion.
*/
public String[] getThrowableStrRep() {
if (throwableInfo == null) {
return null;
} else {
return throwableInfo.getThrowableStrRep();
}
}
/**
* Set this event's throwable information.
* @since 1.3
*/
public void setThrowableInformation(ThrowableInformation ti) {
if (throwableInfo != null) {
throw new IllegalStateException("ThrowableInformation has been already set.");
} else {
throwableInfo = ti;
}
}
private void readLevel(ObjectInputStream ois)
throws java.io.IOException, ClassNotFoundException {
int p = ois.readInt();
try {
String className = (String)ois.readObject();
if (className == null) {
level = Level.toLevel(p);
} else {
Method m = (Method)methodCache.get(className);
if (m == null) {
Class clazz = Loader.loadClass(className);
// Note that we use Class.getDeclaredMethod instead of
// Class.getMethod. This assumes that the Level subclass
// implements the toLevel(int) method which is a
// requirement. Actually, it does not make sense for Level
// subclasses NOT to implement this method. Also note that
// only Level can be subclassed and not Priority.
m = clazz.getDeclaredMethod(TO_LEVEL, TO_LEVEL_PARAMS);
methodCache.put(className, m);
}
PARAM_ARRAY[0] = new Integer(p);
level = (Level)m.invoke(null, PARAM_ARRAY);
}
} catch (Exception e) {
//LogLog.warn("Level deserialization failed, reverting to default.", e);
level = Level.toLevel(p);
}
}
private void readObject(ObjectInputStream ois)
throws java.io.IOException, ClassNotFoundException {
ois.defaultReadObject();
readLevel(ois);
// Make sure that location info instance is set.
if (locationInfo == null) {
locationInfo = LocationInfo.NA_LOCATION_INFO;
}
}
/**
* @return Returns the properties specific for this event. The returned
* value can be null.
* @since 1.3
*/
public Map getProperties() {
return properties;
}
/**
* @param properties The properties to set.
*/
public void setProperties(Hashtable properties) {
this.properties = properties;
}
/**
* Set a string property using a key and a string value. since 1.3
*/
public void setProperty(String key, String value) {
if (properties == null) {
// create a copy of MDC and repository properties
initializeProperties();
}
if (value != null) {
properties.put(key, value);
} else {
properties.remove(key);
}
}
/**
* This method should be called prior to serializing an event. It should also
* be called when using asynchronous logging, before writing the event on
* a database, or as an XML element.
*
*
* @since 1.3
*/
public void prepareForDeferredProcessing() {
// Aside from returning the current thread name the wgetThreadName
// method sets the threadName variable.
this.getThreadName();
// This sets the renders the message in case it wasn't up to now.
this.getRenderedMessage();
// This call has a side effect of setting this.ndc and
// setting ndcLookupRequired to false if not already false.
this.getNDC();
// This call has a side effect of creating a copy of MDC context information
// as well as a copy the properties for the containing LoggerRepository.
if(properties == null) {
initializeProperties();
}
// This sets the throwable sting representation of the event throwable.
this.getThrowableStrRep();
}
private void writeObject(ObjectOutputStream oos)
throws java.io.IOException {
prepareForDeferredProcessing();
oos.defaultWriteObject();
// serialize this event's level
writeLevel(oos);
}
private void writeLevel(ObjectOutputStream oos)
throws java.io.IOException {
oos.writeInt(level.toInt());
Class clazz = level.getClass();
if (clazz == Level.class) {
oos.writeObject(null);
} else {
// writing directly the Class object would be nicer, except that
// serialized a Class object can not be read back by JDK
// 1.1.x. We have to resort to this hack instead.
oos.writeObject(clazz.getName());
}
}
/**
* Getter for the event's time stamp. The time stamp is calculated starting
* from 1970-01-01 GMT.
*
* @since 1.3
*/
public long getTimeStamp() {
return timeStamp;
}
/**
* Setter for the even'ts time stamp.
* See also {@link #getTimeStamp}.
* @since 1.3
*/
public void setTimeStamp(long timeStamp) {
this.timeStamp = timeStamp;
}
/**
* Get the fully qualified name of the calling logger sub-class/wrapper.
* @since 1.3
*/
public String getFQNOfLoggerClass() {
return fqnOfLoggerClass;
}
/**
* Set the fully qualified name of the calling logger sub-class/wrapper.
*
* @since 1.3
* @param fqnOfLoggerClass
*/
public void setFQNOfLoggerClass(String fqnOfLoggerClass) {
this.fqnOfLoggerClass = fqnOfLoggerClass;
}
}