KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > codehaus > loom > components > logger > DefaultLogManager


1 /* ====================================================================
2  * Loom Software License, version 1.1
3  *
4  * Copyright (c) 2003, Loom Group. All rights reserved.
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in
14  * the documentation and/or other materials provided with the
15  * distribution.
16  *
17  * 3. Neither the name of the Loom Group nor the name "Loom" nor
18  * the names of its contributors may be used to endorse or promote
19  * products derived from this software without specific prior
20  * written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  *
35  * ====================================================================
36  *
37  * Loom includes code from the Apache Software Foundation
38  *
39  * ====================================================================
40  * The Apache Software License, Version 1.1
41  *
42  * Copyright (c) 1997-2003 The Apache Software Foundation. All rights
43  * reserved.
44  *
45  * Redistribution and use in source and binary forms, with or without
46  * modification, are permitted provided that the following conditions
47  * are met:
48  *
49  * 1. Redistributions of source code must retain the above copyright
50  * notice, this list of conditions and the following disclaimer.
51  *
52  * 2. Redistributions in binary form must reproduce the above copyright
53  * notice, this list of conditions and the following disclaimer in
54  * the documentation and/or other materials provided with the
55  * distribution.
56  *
57  * 3. The end-user documentation included with the redistribution,
58  * if any, must include the following acknowledgment:
59  * "This product includes software developed by the
60  * Apache Software Foundation (http://www.apache.org/)."
61  * Alternately, this acknowledgment may appear in the software
62  * itself, if and wherever such third-party acknowledgments
63  * normally appear.
64  *
65  * 4. The names "Jakarta", "Avalon", and "Apache Software Foundation"
66  * must not be used to endorse or promote products derived from this
67  * software without prior written permission. For written
68  * permission, please contact apache@apache.org.
69  *
70  * 5. Products derived from this software may not be called "Apache",
71  * nor may "Apache" appear in their name, without prior written
72  * permission of the Apache Software Foundation.
73  *
74  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
75  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
76  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
77  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
78  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
79  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
80  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
81  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
82  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
83  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
84  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
85  * SUCH DAMAGE.
86  */

87 package org.codehaus.loom.components.logger;
88
89 import java.io.File JavaDoc;
90 import java.util.HashMap JavaDoc;
91 import java.util.Iterator JavaDoc;
92 import java.util.Map JavaDoc;
93 import java.util.Properties JavaDoc;
94 import javax.xml.parsers.DocumentBuilder JavaDoc;
95 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
96 import org.apache.avalon.framework.configuration.Configuration;
97 import org.apache.avalon.framework.container.ContainerUtil;
98 import org.apache.avalon.framework.context.Context;
99 import org.apache.avalon.framework.context.DefaultContext;
100 import org.apache.avalon.framework.logger.Logger;
101 import org.apache.avalon.phoenix.BlockContext;
102 import org.codehaus.loom.components.util.ResourceUtil;
103 import org.codehaus.loom.interfaces.LogManager;
104 import org.codehaus.spice.alchemist.logger.LoggerAlchemist;
105 import org.codehaus.spice.alchemist.configuration.ConfigurationAlchemist;
106 import org.codehaus.spice.configkit.PropertyExpander;
107 import org.codehaus.spice.configkit.ResolverFactory;
108 import org.codehaus.spice.loggerstore.LoggerStore;
109 import org.codehaus.spice.loggerstore.LoggerStoreFactory;
110 import org.codehaus.spice.loggerstore.factories.DOMLog4JLoggerStoreFactory;
111 import org.codehaus.spice.loggerstore.factories.InitialLoggerStoreFactory;
112 import org.codehaus.spice.loggerstore.factories.Jdk14LoggerStoreFactory;
113 import org.codehaus.spice.loggerstore.factories.LogKitLoggerStoreFactory;
114 import org.codehaus.spice.loggerstore.factories.PropertyLog4JLoggerStoreFactory;
115 import org.codehaus.spice.loggerstore.factories.SimpleLogKitLoggerStoreFactory;
116 import org.codehaus.spice.salt.i18n.ResourceManager;
117 import org.codehaus.spice.salt.i18n.Resources;
118 import org.codehaus.dna.AbstractLogEnabled;
119 import org.codehaus.dna.Composable;
120 import org.codehaus.dna.MissingResourceException;
121 import org.codehaus.dna.ResourceLocator;
122 import org.codehaus.dna.impl.ConfigurationUtil;
123 import org.w3c.dom.Document JavaDoc;
124 import org.w3c.dom.Element JavaDoc;
125 import org.w3c.dom.Node JavaDoc;
126 import org.w3c.dom.NodeList JavaDoc;
127 import org.xml.sax.EntityResolver JavaDoc;
128
129 /**
130  * Interface that is used to manage Log objects for a Sar.
131  *
132  * @author Peter Donald
133  */

134 public class DefaultLogManager
135     extends AbstractLogEnabled
136     implements LogManager, Composable
137 {
138     private static final Resources REZ =
139         ResourceManager.getPackageResources( DefaultLogManager.class );
140
141     private final PropertyExpander m_expander = new PropertyExpander();
142
143     private final InitialLoggerStoreFactory m_factory = new InitialLoggerStoreFactory();
144
145     /** Hold the value of loom.home */
146     private File JavaDoc m_loomHome;
147
148     /**
149      * @dna.dependency type="File" qualifier="home"
150      */

151     public void compose( ResourceLocator locator )
152         throws MissingResourceException
153     {
154         m_loomHome = (File JavaDoc)locator.lookup( File JavaDoc.class.getName() + "/home" );
155     }
156
157     private Map JavaDoc createLoggerManagerContext( final Map JavaDoc appContext )
158     {
159         final HashMap JavaDoc data = new HashMap JavaDoc();
160         data.putAll( appContext );
161         data.put( "loom.home", m_loomHome );
162         return data;
163     }
164
165     /**
166      * Normalises file paths by replacing File.separatorChar with '/' and
167      * storing the path in the map in place of the File object which would be
168      * converted back to using the File.separatorChar
169      *
170      * @param data the Map containing the File objects
171      * @return the Map with the normalised File paths
172      */

173     private Map JavaDoc normaliseFilePaths( final Map JavaDoc data )
174     {
175         final Map JavaDoc map = new HashMap JavaDoc();
176         map.putAll( data );
177         for( Iterator JavaDoc i = data.keySet().iterator(); i.hasNext(); )
178         {
179             final Object JavaDoc key = i.next();
180             final Object JavaDoc value = data.get( key );
181             if( value instanceof File JavaDoc )
182             {
183                 final File JavaDoc file = (File JavaDoc)value;
184                 final String JavaDoc newPath = normalisePath( file.getPath() );
185                 // replace File object value with its path
186
map.put( key, newPath );
187             }
188         }
189         return map;
190     }
191
192     /**
193      * Normalises file path by replacing File.separatorChar with '/'
194      *
195      * @param path the file path is to be normalised
196      * @return the normalised file path
197      */

198     private String JavaDoc normalisePath( final String JavaDoc path )
199     {
200         return path.replace( File.separatorChar, '/' );
201     }
202
203     /**
204      * Create a Logger hierarchy for specified application.
205      *
206      * @param logs the configuration data for logging
207      * @param context the context in which to create loggers
208      * @return the Log hierarchy
209      * @throws Exception if unable to create Loggers
210      */

211     public LoggerStore
212         createHierarchy( final org.codehaus.dna.Configuration logs,
213                          final File JavaDoc homeDirectory,
214                          final File JavaDoc workDirectory,
215                          final Map JavaDoc context )
216         throws Exception JavaDoc
217     {
218         final Map JavaDoc map = createLoggerManagerContext( context );
219         // normalise file paths to circumvent backslash replacement
220
final Map JavaDoc normalisedMap = normaliseFilePaths( map );
221         if( null == logs )
222         {
223             LoggerStore store = null;
224             store = scanForLoggerConfig( "SAR-INF/log4j.properties",
225                                          PropertyLog4JLoggerStoreFactory.class.getName(),
226                                          homeDirectory,
227                                          workDirectory,
228                                          normalisedMap );
229             if( null != store )
230             {
231                 return store;
232             }
233             store = scanForLoggerConfig( "SAR-INF/log4j.xml",
234                                          DOMLog4JLoggerStoreFactory.class.getName(),
235                                          homeDirectory,
236                                          workDirectory,
237                                          normalisedMap );
238             if( null != store )
239             {
240                 return store;
241             }
242             store = scanForLoggerConfig( "SAR-INF/logging.properties",
243                                          Jdk14LoggerStoreFactory.class.getName(),
244                                          homeDirectory,
245                                          workDirectory,
246                                          normalisedMap );
247             if( null != store )
248             {
249                 return store;
250             }
251             store = scanForLoggerConfig( "SAR-INF/excalibur-logger.xml",
252                                          LogKitLoggerStoreFactory.class.getName(),
253                                          homeDirectory,
254                                          workDirectory,
255                                          normalisedMap );
256             if( null != store )
257             {
258                 return store;
259             }
260
261             //TODO: Set up a default LoggerStore at this point
262
final String JavaDoc message = "Unable to locate any logging configuration";
263             throw new IllegalStateException JavaDoc( message );
264         }
265         else
266         {
267             final String JavaDoc version = logs.getAttribute( "version", "1.0" );
268             if( getLogger().isDebugEnabled() )
269             {
270                 final String JavaDoc message =
271                     REZ.format( "logger-create",
272                                 context.get( BlockContext.APP_NAME ),
273                                 version );
274                 getLogger().debug( message );
275             }
276
277             Logger logger = LoggerAlchemist.toAvalonLogger( getLogger() );
278             if( version.equals( "1.0" ) )
279             {
280                 final LoggerStoreFactory loggerManager = new SimpleLogKitLoggerStoreFactory();
281                 ContainerUtil.enableLogging( loggerManager, logger );
282                 final HashMap JavaDoc config = new HashMap JavaDoc();
283                 config.put( Logger.class.getName(), logger );
284                 // use the original context map as SimpleLogKitManager requires
285
// the File object in the context
286
config.put( Context.class.getName(),
287                             new DefaultContext( map ) );
288                 config.put( Configuration.class.getName(),
289                             ConfigurationAlchemist.toAvalonConfiguration( logs ) );
290                 return loggerManager.createLoggerStore( config );
291             }
292             else if( version.equals( "1.1" ) )
293             {
294                 final LoggerStoreFactory loggerManager = new LogKitLoggerStoreFactory();
295                 ContainerUtil.enableLogging( loggerManager, logger );
296                 final HashMap JavaDoc config = new HashMap JavaDoc();
297                 config.put( Logger.class.getName(), logger );
298                 config.put( Context.class.getName(),
299                             new DefaultContext( normalisedMap ) );
300                 config.put( Configuration.class.getName(),
301                             ConfigurationAlchemist.toAvalonConfiguration( logs ) );
302                 return loggerManager.createLoggerStore( config );
303             }
304             else if( version.equals( "log4j" ) )
305             {
306                 final LoggerStoreFactory loggerManager = new DOMLog4JLoggerStoreFactory();
307                 ContainerUtil.enableLogging( loggerManager, logger );
308                 final HashMap JavaDoc config = new HashMap JavaDoc();
309                 final Element JavaDoc element = buildLog4JConfiguration( logs );
310                 m_expander.expandValues( element, normalisedMap );
311                 config.put( Element JavaDoc.class.getName(), element );
312                 return loggerManager.createLoggerStore( config );
313             }
314             else
315             {
316                 final String JavaDoc message =
317                     "Unknown logger version '" +
318                     version +
319                     "' in environment.xml";
320                 throw new IllegalStateException JavaDoc( message );
321             }
322         }
323     }
324
325     private Element JavaDoc
326         buildLog4JConfiguration( final org.codehaus.dna.Configuration logs )
327     {
328         final Element JavaDoc element = ConfigurationUtil.toElement( logs );
329         final Document JavaDoc document = element.getOwnerDocument();
330         final Element JavaDoc newElement = document.createElement(
331             "log4j:configuration" );
332         final NodeList JavaDoc childNodes = element.getChildNodes();
333         final int length = childNodes.getLength();
334         for( int i = 0; i < length; i++ )
335         {
336             final Node JavaDoc node = childNodes.item( i );
337             final Node JavaDoc newNode = node.cloneNode( true );
338             newElement.appendChild( newNode );
339         }
340
341         document.appendChild( newElement );
342         return newElement;
343     }
344
345     private LoggerStore scanForLoggerConfig( final String JavaDoc location,
346                                              final String JavaDoc classname,
347                                              final File JavaDoc homeDirectory,
348                                              final File JavaDoc workDirectory,
349                                              final Map JavaDoc context )
350         throws Exception JavaDoc
351     {
352         final boolean isPropertiesFile = location.endsWith( "properties" );
353         final File JavaDoc file =
354             ResourceUtil.getFileForResource( location,
355                                              homeDirectory,
356                                              workDirectory );
357         LoggerStore store = null;
358         if( null != file )
359         {
360             final HashMap JavaDoc config = new HashMap JavaDoc();
361             if( isPropertiesFile )
362             {
363                 final Properties JavaDoc properties = new Properties JavaDoc();
364                 properties.load( file.toURL().openStream() );
365                 final Properties JavaDoc newProperties =
366                     m_expander.expandValues( properties, context );
367                 config.put( Properties JavaDoc.class.getName(), newProperties );
368             }
369             //TODO: Remove next line as it is an ugly hack!
370
else if( !location.equals( "SAR-INF/excalibur-logger.xml" ) )
371             {
372                 final DocumentBuilderFactory JavaDoc factory = DocumentBuilderFactory.newInstance();
373                 final DocumentBuilder JavaDoc builder = factory.newDocumentBuilder();
374
375                 //TODO: Need to set up config files for entity resolver
376
final EntityResolver JavaDoc resolver =
377                     ResolverFactory.createResolver(
378                         getClass().getClassLoader() );
379                 builder.setEntityResolver( resolver );
380                 final Document JavaDoc document = builder.parse( file );
381                 final Element JavaDoc element = document.getDocumentElement();
382                 m_expander.expandValues( element, context );
383                 config.put( Element JavaDoc.class.getName(), element );
384             }
385             else
386             {
387                 config.put( LoggerStoreFactory.URL_LOCATION, file.toURL() );
388             }
389             config.put( InitialLoggerStoreFactory.INITIAL_FACTORY, classname );
390             store = m_factory.createLoggerStore( config );
391         }
392         return store;
393     }
394 }
395
Popular Tags