View Javadoc

1   /**
2    * Logback: the generic, reliable, fast and flexible logging framework.
3    * 
4    * Copyright (C) 2000-2008, QOS.ch
5    * 
6    * This library is free software, you can redistribute it and/or modify it under
7    * the terms of the GNU Lesser General Public License as published by the Free
8    * Software Foundation.
9    */
10  package ch.qos.logback.core;
11  
12  import java.util.List;
13  
14  import ch.qos.logback.core.filter.Filter;
15  import ch.qos.logback.core.spi.ContextAwareBase;
16  import ch.qos.logback.core.spi.FilterAttachableImpl;
17  import ch.qos.logback.core.spi.FilterReply;
18  import ch.qos.logback.core.status.WarnStatus;
19  
20  /**
21   * Similar to AppenderBase except that derived appenders need to handle 
22   * thread synchronization on their own.
23   * 
24   * @author Ceki Gülcü
25   * @author Ralph Goers
26   */
27  abstract public class UnsynchronizedAppenderBase<E> extends ContextAwareBase implements
28      Appender<E> {
29  
30    protected Layout<E> layout;
31    
32    protected boolean started = false;
33  
34    // using a ThreadLocal instead of a boolean add 75 nanoseconds per
35    // doAppend invocation. This is tolerable as doAppend takes at least a few microseconds
36    // on a real appender
37    /**
38     * The guard prevents an appender from repeatedly calling its own doAppend
39     * method.
40     */
41    private ThreadLocal<Boolean> guard = new ThreadLocal<Boolean>() {
42      protected Boolean initialValue() {
43        return false;
44      }
45    };
46  
47    /**
48     * Appenders are named.
49     */
50    protected String name;
51  
52    private FilterAttachableImpl<E> fai = new FilterAttachableImpl<E>();
53  
54    public String getName() {
55      return name;
56    }
57  
58    private int statusRepeatCount = 0;
59    private int exceptionCount = 0;
60  
61    static final int ALLOWED_REPEATS = 5;
62  
63    public void doAppend(E eventObject) {
64      // WARNING: The guard check MUST be the first statement in the
65      // doAppend() method.
66  
67      // prevent re-entry.
68      if (guard.get()) {
69        return;
70      }
71  
72      try {
73        guard.set(true);
74  
75        if (!this.started) {
76          if (statusRepeatCount++ < ALLOWED_REPEATS) {
77            addStatus(new WarnStatus(
78                "Attempted to append to non started appender [" + name + "].",
79                this));
80          }
81          return;
82        }
83  
84        if (getFilterChainDecision(eventObject) == FilterReply.DENY) {
85          return;
86        }
87  
88        // ok, we now invoke derived class' implementation of append
89        this.append(eventObject);
90  
91      } catch (Exception e) {
92        if (exceptionCount++ < ALLOWED_REPEATS) {
93          addError("Appender [" + name + "] failed to append.", e);
94        }
95      } finally {
96        guard.set(false);
97      }
98    }
99  
100   abstract protected void append(E eventObject);
101 
102   /**
103    * Set the name of this appender.
104    */
105   public void setName(String name) {
106     this.name = name;
107   }
108 
109   public void start() {
110     started = true;
111   }
112 
113   public void stop() {
114     started = false;
115   }
116 
117   public boolean isStarted() {
118     return started;
119   }
120 
121   public String toString() {
122     return this.getClass().getName() + "[" + name + "]";
123   }
124 
125   public void addFilter(Filter<E> newFilter) {
126     fai.addFilter(newFilter);
127   }
128 
129   public Filter getFirstFilter() {
130     return fai.getFirstFilter();
131   }
132 
133   public void clearAllFilters() {
134     fai.clearAllFilters();
135   }
136 
137   public List<Filter<E>> getCopyOfAttachedFiltersList() {
138     return fai.getCopyOfAttachedFiltersList();
139   }
140 
141   
142   public FilterReply getFilterChainDecision(E event) {
143     return fai.getFilterChainDecision(event);
144   }
145 
146   public Layout<E> getLayout() {
147     return layout;
148   }
149 
150   public void setLayout(Layout<E> layout) {
151     this.layout = layout;
152   }
153 }