KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > avalon > excalibur > logger > util > LoggerSwitch


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

19 package org.apache.avalon.excalibur.logger.util;
20
21 import org.apache.avalon.framework.logger.Logger;
22 import org.apache.avalon.framework.logger.NullLogger;
23
24 /**
25  * A proxy logger that switches between two underlying loggers
26  * with recursive invocation detection.
27  * <p>
28  * This class is intended to be used by o.a.a.e.logger.AbstractLoggerManager.
29  * all the logger switching is done in it during the "warm-up" phase
30  * (constructor, enableLogging, contextualize, configure, start).
31  * All these operations are held our on a single thread and the
32  * object is not exposed to other threads untill (in strict synchronization
33  * sense) it has been fully configured. That's why there is no synchronization
34  * in this class. If the switching was to occur in a mulitythreaded
35  * fasion we would have to synchronize access to m_fallback and m_preferred.
36  *
37  * @author <a HREF="mailto:dev@avalon.apache.org">Avalon Development Team</a>
38  */

39
40 public class LoggerSwitch
41 {
42     protected final static Logger SHARED_NULL = new NullLogger();
43
44     private final static class BooleanThreadLocal extends ThreadLocal JavaDoc
45     {
46         public Object JavaDoc initialValue() { return Boolean.FALSE; }
47         public boolean value() { return ((Boolean JavaDoc)this.get()).booleanValue(); }
48     }
49
50     private static class SwitchingLogger implements Logger
51     {
52         Logger m_fallback;
53         Logger m_preferred;
54
55         BooleanThreadLocal m_recursionOnPreferred = new BooleanThreadLocal();
56         BooleanThreadLocal m_recursionOnFallback = new BooleanThreadLocal();
57
58         SwitchingLogger( final Logger fallback, final Logger preferred )
59         {
60             m_fallback = fallback != null ? fallback : SHARED_NULL;
61             m_preferred = preferred;
62         }
63
64         void setFallback( final Logger fallback )
65         {
66             m_fallback = fallback != null ? fallback : SHARED_NULL;
67         }
68
69         void setPreferred( final Logger preferred )
70         {
71             m_preferred = preferred;
72         }
73
74         /**
75          * Retrieve m_preferred or if that is null m_fallback.
76          * Safeguard against recursion. That is possible if
77          * try to log something via a Logger that is failing
78          * and trying to log its own error via itself.
79          */

80         private Logger getLogger()
81         {
82             if ( m_recursionOnFallback.value() )
83             {
84                 throw new IllegalStateException JavaDoc( "infinite recursion" );
85             }
86             else if ( m_recursionOnPreferred.value() || m_preferred == null )
87             {
88                 m_recursionOnFallback.set( Boolean.TRUE );
89                 return m_fallback;
90             }
91             else
92             {
93                 m_recursionOnPreferred.set( Boolean.TRUE );
94                 return m_preferred;
95             }
96         }
97
98         private Logger getLoggerLight()
99         {
100             return m_preferred != null ? m_preferred : m_fallback;
101         }
102
103         private void releaseLogger()
104         {
105             if ( m_recursionOnFallback.value() )
106             {
107                 m_recursionOnFallback.set( Boolean.FALSE );
108             }
109             else if ( m_recursionOnPreferred.value() )
110             {
111                 m_recursionOnPreferred.set( Boolean.FALSE );
112             }
113             else
114             {
115                 throw new IllegalStateException JavaDoc( "no recursion" );
116             }
117         }
118
119         public void debug( final String JavaDoc message )
120         {
121             final Logger logger = getLogger();
122             try
123             {
124                 logger.debug( message );
125             }
126             finally
127             {
128                 releaseLogger();
129             }
130         }
131     
132         public void debug( final String JavaDoc message, final Throwable JavaDoc throwable )
133         {
134             final Logger logger = getLogger();
135             try
136             {
137                 logger.debug( message, throwable );
138             }
139             finally
140             {
141                 releaseLogger();
142             }
143         }
144     
145         /**
146          * This and similar method may probably be optimized in the
147          * future by caching the boolean in our instance variables.
148          * Each time setPreferred() or setFallback() is called they
149          * will be cached. Maybe in the future. :-)
150          */

151         public boolean isDebugEnabled()
152         {
153             final Logger logger = getLoggerLight();
154             return logger.isDebugEnabled();
155         }
156
157     
158         public void info( final String JavaDoc message )
159         {
160             final Logger logger = getLogger();
161             try
162             {
163                 logger.info( message );
164             }
165             finally
166             {
167                 releaseLogger();
168             }
169         }
170     
171         public void info( final String JavaDoc message, final Throwable JavaDoc throwable )
172         {
173             final Logger logger = getLogger();
174             try
175             {
176                 logger.info( message, throwable );
177             }
178             finally
179             {
180                 releaseLogger();
181             }
182         }
183     
184         public boolean isInfoEnabled()
185         {
186             final Logger logger = getLoggerLight();
187             return logger.isInfoEnabled();
188         }
189     
190         public void warn( final String JavaDoc message )
191         {
192             final Logger logger = getLogger();
193             try
194             {
195                 logger.warn( message );
196             }
197             finally
198             {
199                 releaseLogger();
200             }
201         }
202     
203         public void warn( final String JavaDoc message, final Throwable JavaDoc throwable )
204         {
205             final Logger logger = getLogger();
206             try
207             {
208                 logger.warn( message, throwable );
209             }
210             finally
211             {
212                 releaseLogger();
213             }
214         }
215     
216         public boolean isWarnEnabled()
217         {
218             final Logger logger = getLoggerLight();
219             return logger.isWarnEnabled();
220         }
221     
222         public void error( final String JavaDoc message )
223         {
224             final Logger logger = getLogger();
225             try
226             {
227                 logger.error( message );
228             }
229             finally
230             {
231                 releaseLogger();
232             }
233         }
234     
235         public void error( final String JavaDoc message, final Throwable JavaDoc throwable )
236         {
237             final Logger logger = getLogger();
238             try
239             {
240                 logger.error( message, throwable );
241             }
242             finally
243             {
244                 releaseLogger();
245             }
246         }
247     
248         public boolean isErrorEnabled()
249         {
250             final Logger logger = getLoggerLight();
251             return logger.isErrorEnabled();
252         }
253     
254         public void fatalError( final String JavaDoc message )
255         {
256             final Logger logger = getLogger();
257             try
258             {
259                 logger.fatalError( message );
260             }
261             finally
262             {
263                 releaseLogger();
264             }
265         }
266     
267         public void fatalError( final String JavaDoc message, final Throwable JavaDoc throwable )
268         {
269             final Logger logger = getLogger();
270             try
271             {
272                 logger.fatalError( message, throwable );
273             }
274             finally
275             {
276                 releaseLogger();
277             }
278         }
279     
280         public boolean isFatalErrorEnabled()
281         {
282             final Logger logger = getLoggerLight();
283             return logger.isFatalErrorEnabled();
284         }
285     
286         public Logger getChildLogger( final String JavaDoc name ) { return this; }
287
288     }
289
290     private SwitchingLogger m_switch;
291
292     /**
293      * We create a logger with no methods for changing
294      * m_fallback and m_preferred for security reasons.
295      * All the control is done by the parent class
296      * that does not implement Logger itself.
297      */

298     public Logger get()
299     {
300         return m_switch;
301     }
302
303     public LoggerSwitch( final Logger fallback )
304     {
305         this( fallback, null );
306     }
307
308     public LoggerSwitch( final Logger fallback, final Logger preferred )
309     {
310         m_switch = new SwitchingLogger( fallback, preferred );
311     }
312
313     public void setFallback( final Logger fallback )
314     {
315         m_switch.setFallback( fallback );
316     }
317
318     public void setPreferred( final Logger preferred )
319     {
320         m_switch.setPreferred( preferred );
321     }
322 }
323
Popular Tags