View Javadoc

1   /**
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2009, QOS.ch. All rights reserved.
4    *
5    * This program and the accompanying materials are dual-licensed under
6    * either the terms of the Eclipse Public License v1.0 as published by
7    * the Eclipse Foundation
8    *
9    *   or (per the licensee's choosing)
10   *
11   * under the terms of the GNU Lesser General Public License version 2.1
12   * as published by the Free Software Foundation.
13   */
14  package ch.qos.logback.core;
15  
16  import java.util.List;
17  
18  import ch.qos.logback.core.filter.Filter;
19  import ch.qos.logback.core.spi.ContextAwareBase;
20  import ch.qos.logback.core.spi.FilterAttachableImpl;
21  import ch.qos.logback.core.spi.FilterReply;
22  import ch.qos.logback.core.status.WarnStatus;
23  
24  /**
25   * Sets a skeleton implementation for appenders.
26   * 
27   * <p> For more information about this appender, please refer to the online
28   * manual at http://logback.qos.ch/manual/appenders.html#AppenderBase
29   * 
30   * @author Ceki G&uuml;lc&uuml;
31   */
32  abstract public class AppenderBase<E> extends ContextAwareBase implements
33      Appender<E> {
34  
35    /**
36     * The layout variable does not need to be set depending on the appender. Some
37     * appenders do not need a layout.
38     */
39    protected Layout<E> layout;
40  
41    protected boolean started = false;
42  
43    /**
44     * The guard prevents an appender from repeatedly calling its own doAppend
45     * method.
46     */
47    private boolean guard = false;
48  
49    /**
50     * Appenders are named.
51     */
52    protected String name;
53  
54    private FilterAttachableImpl<E> fai = new FilterAttachableImpl<E>();
55  
56    public String getName() {
57      return name;
58    }
59  
60    private int statusRepeatCount = 0;
61    private int exceptionCount = 0;
62  
63    static final int ALLOWED_REPEATS = 5;
64  
65    public synchronized void doAppend(E eventObject) {
66      // WARNING: The guard check MUST be the first statement in the
67      // doAppend() method.
68  
69      // prevent re-entry.
70      if (guard) {
71        return;
72      }
73  
74      try {
75        guard = true;
76  
77        if (!this.started) {
78          if (statusRepeatCount++ < ALLOWED_REPEATS) {
79            addStatus(new WarnStatus(
80                "Attempted to append to non started appender [" + name + "].",
81                this));
82          }
83          return;
84        }
85  
86        if (getFilterChainDecision(eventObject) == FilterReply.DENY) {
87          return;
88        }
89  
90        // ok, we now invoke derived class' implementation of append
91        this.append(eventObject);
92  
93      } catch (Exception e) {
94        if (exceptionCount++ < ALLOWED_REPEATS) {
95          addError("Appender [" + name + "] failed to append.", e);
96        }
97      } finally {
98        guard = false;
99      }
100   }
101 
102   abstract protected void append(E eventObject);
103 
104   /**
105    * Set the name of this appender.
106    */
107   public void setName(String name) {
108     this.name = name;
109   }
110 
111   public void start() {
112     started = true;
113   }
114 
115   public void stop() {
116     started = false;
117   }
118 
119   public boolean isStarted() {
120     return started;
121   }
122 
123   public String toString() {
124     return this.getClass().getName() + "[" + name + "]";
125   }
126 
127   public void addFilter(Filter<E> newFilter) {
128     fai.addFilter(newFilter);
129   }
130 
131   public Filter getFirstFilter() {
132     return fai.getFirstFilter();
133   }
134 
135   public void clearAllFilters() {
136     fai.clearAllFilters();
137   }
138 
139   public List<Filter<E>> getCopyOfAttachedFiltersList() {
140     return fai.getCopyOfAttachedFiltersList();
141   }
142 
143   public FilterReply getFilterChainDecision(E event) {
144     return fai.getFilterChainDecision(event);
145   }
146 
147   /**
148    * Returns the layout of this appender. The returned value may be null if this
149    * appender does not have a layout.
150    */
151   public Layout<E> getLayout() {
152     return layout;
153   }
154 
155   /**
156    * Set the layout for this appender. Note that some appenders have their own
157    * (fixed) layouts or do not use any.
158    */
159   public void setLayout(Layout<E> layout) {
160     this.layout = layout;
161   }
162 }