You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
305 lines
7.0 KiB
305 lines
7.0 KiB
/* |
|
* 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 com.fr.third.apache.log4j; |
|
|
|
import com.fr.third.apache.log4j.helpers.LogLog; |
|
import com.fr.third.apache.log4j.helpers.OnlyOnceErrorHandler; |
|
import com.fr.third.apache.log4j.net.SocketAppender; |
|
import com.fr.third.apache.log4j.spi.ErrorHandler; |
|
import com.fr.third.apache.log4j.spi.Filter; |
|
import com.fr.third.apache.log4j.spi.LoggingEvent; |
|
import com.fr.third.apache.log4j.spi.OptionHandler; |
|
|
|
|
|
/** |
|
* Abstract superclass of the other appenders in the package. |
|
* |
|
* This class provides the code for common functionality, such as |
|
* support for threshold filtering and support for general filters. |
|
* |
|
* @since 0.8.1 |
|
* @author Ceki Gülcü |
|
* */ |
|
public abstract class AppenderSkeleton implements Appender, OptionHandler { |
|
|
|
/** The layout variable does not need to be set if the appender |
|
implementation has its own layout. */ |
|
protected Layout layout; |
|
|
|
/** Appenders are named. */ |
|
protected String name; |
|
|
|
/** |
|
There is no level threshold filtering by default. */ |
|
protected Priority threshold; |
|
|
|
/** |
|
It is assumed and enforced that errorHandler is never null. |
|
*/ |
|
protected ErrorHandler errorHandler = new OnlyOnceErrorHandler(); |
|
|
|
/** The first filter in the filter chain. Set to <code>null</code> |
|
initially. */ |
|
protected Filter headFilter; |
|
/** The last filter in the filter chain. */ |
|
protected Filter tailFilter; |
|
|
|
/** |
|
Is this appender closed? |
|
*/ |
|
protected boolean closed = false; |
|
|
|
/** |
|
* Create new instance. |
|
*/ |
|
public AppenderSkeleton() { |
|
super(); |
|
} |
|
|
|
/** |
|
* Create new instance. |
|
* Provided for compatibility with log4j 1.3. |
|
* |
|
* @param isActive true if appender is ready for use upon construction. |
|
* Not used in log4j 1.2.x. |
|
* @since 1.2.15 |
|
*/ |
|
protected AppenderSkeleton(final boolean isActive) { |
|
super(); |
|
} |
|
|
|
|
|
|
|
/** |
|
Derived appenders should override this method if option structure |
|
requires it. */ |
|
public |
|
void activateOptions() { |
|
} |
|
|
|
|
|
/** |
|
Add a filter to end of the filter list. |
|
|
|
@since 0.9.0 |
|
*/ |
|
public |
|
void addFilter(Filter newFilter) { |
|
if(headFilter == null) { |
|
headFilter = tailFilter = newFilter; |
|
} else { |
|
tailFilter.setNext(newFilter); |
|
tailFilter = newFilter; |
|
} |
|
} |
|
|
|
/** |
|
Subclasses of <code>AppenderSkeleton</code> should implement this |
|
method to perform actual logging. See also {@link #doAppend |
|
AppenderSkeleton.doAppend} method. |
|
|
|
@since 0.9.0 |
|
*/ |
|
abstract |
|
protected |
|
void append(LoggingEvent event); |
|
|
|
|
|
/** |
|
Clear the filters chain. |
|
|
|
@since 0.9.0 */ |
|
public |
|
void clearFilters() { |
|
headFilter = tailFilter = null; |
|
} |
|
|
|
/** |
|
Finalize this appender by calling the derived class' |
|
<code>close</code> method. |
|
|
|
@since 0.8.4 */ |
|
public |
|
void finalize() { |
|
// An appender might be closed then garbage collected. There is no |
|
// point in closing twice. |
|
if(this.closed) |
|
return; |
|
|
|
LogLog.debug("Finalizing appender named ["+name+"]."); |
|
close(); |
|
} |
|
|
|
|
|
/** |
|
Return the currently set {@link ErrorHandler} for this |
|
Appender. |
|
|
|
@since 0.9.0 */ |
|
public |
|
ErrorHandler getErrorHandler() { |
|
return this.errorHandler; |
|
} |
|
|
|
|
|
/** |
|
Returns the head Filter. |
|
|
|
@since 1.1 |
|
*/ |
|
public |
|
Filter getFilter() { |
|
return headFilter; |
|
} |
|
|
|
/** |
|
Return the first filter in the filter chain for this |
|
Appender. The return value may be <code>null</code> if no is |
|
filter is set. |
|
|
|
*/ |
|
public |
|
final |
|
Filter getFirstFilter() { |
|
return headFilter; |
|
} |
|
|
|
/** |
|
Returns the layout of this appender. The value may be null. |
|
*/ |
|
public |
|
Layout getLayout() { |
|
return layout; |
|
} |
|
|
|
|
|
/** |
|
Returns the name of this appender. |
|
@return name, may be null. |
|
*/ |
|
public |
|
final |
|
String getName() { |
|
return this.name; |
|
} |
|
|
|
/** |
|
Returns this appenders threshold level. See the {@link |
|
#setThreshold} method for the meaning of this option. |
|
|
|
@since 1.1 */ |
|
public |
|
Priority getThreshold() { |
|
return threshold; |
|
} |
|
|
|
|
|
/** |
|
Check whether the message level is below the appender's |
|
threshold. If there is no threshold set, then the return value is |
|
always <code>true</code>. |
|
|
|
*/ |
|
public |
|
boolean isAsSevereAsThreshold(Priority priority) { |
|
return ((threshold == null) || priority.isGreaterOrEqual(threshold)); |
|
} |
|
|
|
|
|
/** |
|
* This method performs threshold checks and invokes filters before |
|
* delegating actual logging to the subclasses specific {@link |
|
* AppenderSkeleton#append} method. |
|
* */ |
|
public |
|
synchronized |
|
void doAppend(LoggingEvent event) { |
|
if(closed) { |
|
LogLog.error("Attempted to append to closed appender named ["+name+"]."); |
|
return; |
|
} |
|
|
|
if(!isAsSevereAsThreshold(event.getLevel())) { |
|
return; |
|
} |
|
|
|
Filter f = this.headFilter; |
|
|
|
FILTER_LOOP: |
|
while(f != null) { |
|
switch(f.decide(event)) { |
|
case Filter.DENY: return; |
|
case Filter.ACCEPT: break FILTER_LOOP; |
|
case Filter.NEUTRAL: f = f.getNext(); |
|
} |
|
} |
|
|
|
this.append(event); |
|
} |
|
|
|
/** |
|
Set the {@link ErrorHandler} for this Appender. |
|
@since 0.9.0 |
|
*/ |
|
public |
|
synchronized |
|
void setErrorHandler(ErrorHandler eh) { |
|
if(eh == null) { |
|
// We do not throw exception here since the cause is probably a |
|
// bad config file. |
|
LogLog.warn("You have tried to set a null error-handler."); |
|
} else { |
|
this.errorHandler = eh; |
|
} |
|
} |
|
|
|
/** |
|
Set the layout for this appender. Note that some appenders have |
|
their own (fixed) layouts or do not use one. For example, the |
|
{@link SocketAppender} ignores the layout set |
|
here. |
|
*/ |
|
public |
|
void setLayout(Layout layout) { |
|
this.layout = layout; |
|
} |
|
|
|
|
|
/** |
|
Set the name of this Appender. |
|
*/ |
|
public |
|
void setName(String name) { |
|
this.name = name; |
|
} |
|
|
|
|
|
/** |
|
Set the threshold level. All log events with lower level |
|
than the threshold level are ignored by the appender. |
|
|
|
<p>In configuration files this option is specified by setting the |
|
value of the <b>Threshold</b> option to a level |
|
string, such as "DEBUG", "INFO" and so on. |
|
|
|
@since 0.8.3 */ |
|
public |
|
void setThreshold(Priority threshold) { |
|
this.threshold = threshold; |
|
} |
|
}
|
|
|