KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > log4j > AppenderSkeleton


1 /*
2  * Copyright 1999-2005 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.apache.log4j;
18
19 import org.apache.log4j.Layout;
20 import org.apache.log4j.spi.Filter;
21 import org.apache.log4j.spi.ErrorHandler;
22 import org.apache.log4j.spi.OptionHandler;
23 import org.apache.log4j.spi.LoggingEvent;
24 import org.apache.log4j.helpers.OnlyOnceErrorHandler;
25 import org.apache.log4j.helpers.LogLog;
26
27
28 /**
29  * Abstract superclass of the other appenders in the package.
30  *
31  * This class provides the code for common functionality, such as
32  * support for threshold filtering and support for general filters.
33  *
34  * @since 0.8.1
35  * @author Ceki Gülcü
36  * */

37 public abstract class AppenderSkeleton implements Appender, OptionHandler {
38
39   /** The layout variable does not need to be set if the appender
40       implementation has its own layout. */

41   protected Layout layout;
42
43   /** Appenders are named. */
44   protected String JavaDoc name;
45
46   /**
47      There is no level threshold filtering by default. */

48   protected Priority threshold;
49
50   /**
51       It is assumed and enforced that errorHandler is never null.
52   */

53   protected ErrorHandler errorHandler = new OnlyOnceErrorHandler();
54
55   /** The first filter in the filter chain. Set to <code>null</code>
56       initially. */

57   protected Filter headFilter;
58   /** The last filter in the filter chain. */
59   protected Filter tailFilter;
60
61   /**
62      Is this appender closed?
63    */

64   protected boolean closed = false;
65
66
67   /**
68      Derived appenders should override this method if option structure
69      requires it. */

70   public
71   void activateOptions() {
72   }
73
74
75   /**
76      Add a filter to end of the filter list.
77
78      @since 0.9.0
79    */

80   public
81   void addFilter(Filter newFilter) {
82     if(headFilter == null) {
83       headFilter = tailFilter = newFilter;
84     } else {
85       tailFilter.next = newFilter;
86       tailFilter = newFilter;
87     }
88   }
89
90   /**
91      Subclasses of <code>AppenderSkeleton</code> should implement this
92      method to perform actual logging. See also {@link #doAppend
93      AppenderSkeleton.doAppend} method.
94
95      @since 0.9.0
96   */

97   abstract
98   protected
99   void append(LoggingEvent event);
100
101
102   /**
103      Clear the filters chain.
104      
105      @since 0.9.0 */

106   public
107   void clearFilters() {
108     headFilter = tailFilter = null;
109   }
110
111   /**
112      Finalize this appender by calling the derived class'
113      <code>close</code> method.
114
115      @since 0.8.4 */

116   public
117   void finalize() {
118     // An appender might be closed then garbage collected. There is no
119
// point in closing twice.
120
if(this.closed)
121       return;
122
123     LogLog.debug("Finalizing appender named ["+name+"].");
124     close();
125   }
126
127
128   /**
129       Return the currently set {@link ErrorHandler} for this
130       Appender.
131
132       @since 0.9.0 */

133   public
134   ErrorHandler getErrorHandler() {
135     return this.errorHandler;
136   }
137
138
139   /**
140      Returns the head Filter.
141      
142      @since 1.1
143   */

144   public
145   Filter getFilter() {
146     return headFilter;
147   }
148
149   /**
150       Return the first filter in the filter chain for this
151       Appender. The return value may be <code>null</code> if no is
152       filter is set.
153       
154   */

155   public
156   final
157   Filter getFirstFilter() {
158     return headFilter;
159   }
160
161   /**
162      Returns the layout of this appender. The value may be null.
163   */

164   public
165   Layout getLayout() {
166     return layout;
167   }
168
169
170   /**
171      Returns the name of this FileAppender.
172    */

173   public
174   final
175   String JavaDoc getName() {
176     return this.name;
177   }
178
179   /**
180      Returns this appenders threshold level. See the {@link
181      #setThreshold} method for the meaning of this option.
182      
183      @since 1.1 */

184   public
185   Priority getThreshold() {
186     return threshold;
187   }
188
189
190   /**
191      Check whether the message level is below the appender's
192      threshold. If there is no threshold set, then the return value is
193      always <code>true</code>.
194
195   */

196   public
197   boolean isAsSevereAsThreshold(Priority priority) {
198     return ((threshold == null) || priority.isGreaterOrEqual(threshold));
199   }
200
201
202   /**
203     * This method performs threshold checks and invokes filters before
204     * delegating actual logging to the subclasses specific {@link
205     * AppenderSkeleton#append} method.
206     * */

207   public
208   synchronized
209   void doAppend(LoggingEvent event) {
210     if(closed) {
211       LogLog.error("Attempted to append to closed appender named ["+name+"].");
212       return;
213     }
214     
215     if(!isAsSevereAsThreshold(event.getLevel())) {
216       return;
217     }
218
219     Filter f = this.headFilter;
220     
221     FILTER_LOOP:
222     while(f != null) {
223       switch(f.decide(event)) {
224       case Filter.DENY: return;
225       case Filter.ACCEPT: break FILTER_LOOP;
226       case Filter.NEUTRAL: f = f.next;
227       }
228     }
229     
230     this.append(event);
231   }
232
233   /**
234       Set the {@link ErrorHandler} for this Appender.
235       @since 0.9.0
236   */

237   public
238   synchronized
239   void setErrorHandler(ErrorHandler eh) {
240     if(eh == null) {
241       // We do not throw exception here since the cause is probably a
242
// bad config file.
243
LogLog.warn("You have tried to set a null error-handler.");
244     } else {
245       this.errorHandler = eh;
246     }
247   }
248
249   /**
250      Set the layout for this appender. Note that some appenders have
251      their own (fixed) layouts or do not use one. For example, the
252      {@link org.apache.log4j.net.SocketAppender} ignores the layout set
253      here.
254   */

255   public
256   void setLayout(Layout layout) {
257     this.layout = layout;
258   }
259
260   
261   /**
262      Set the name of this Appender.
263    */

264   public
265   void setName(String JavaDoc name) {
266     this.name = name;
267   }
268
269
270   /**
271      Set the threshold level. All log events with lower level
272      than the threshold level are ignored by the appender.
273      
274      <p>In configuration files this option is specified by setting the
275      value of the <b>Threshold</b> option to a level
276      string, such as "DEBUG", "INFO" and so on.
277      
278      @since 0.8.3 */

279   public
280   void setThreshold(Priority threshold) {
281     this.threshold = threshold;
282   }
283 }
284
Popular Tags