KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > avalon > excalibur > logger > factory > FileTargetFactory


1 /*
2  * Copyright (C) The Apache Software Foundation. All rights reserved.
3  *
4  * This software is published under the terms of the Apache Software License
5  * version 1.1, a copy of which has been included with this distribution in
6  * the LICENSE.txt file.
7  */

8 package org.apache.avalon.excalibur.logger.factory;
9
10 import org.apache.avalon.excalibur.logger.LogTargetFactory;
11
12 import org.apache.avalon.framework.configuration.Configuration;
13 import org.apache.avalon.framework.configuration.Configurable;
14 import org.apache.avalon.framework.configuration.ConfigurationException;
15 import org.apache.avalon.framework.context.Contextualizable;
16 import org.apache.avalon.framework.context.Context;
17 import org.apache.avalon.framework.context.ContextException;
18
19 import org.apache.log.LogTarget;
20 import org.apache.log.format.ExtendedPatternFormatter;
21 import org.apache.log.format.Formatter;
22 import org.apache.log.format.PatternFormatter;
23 import org.apache.log.format.RawFormatter;
24 import org.apache.log.output.io.FileTarget;
25 import org.apache.log.output.io.rotate.RotatingFileTarget;
26 import org.apache.log.output.io.rotate.RotateStrategy;
27 import org.apache.log.output.io.rotate.OrRotateStrategy;
28 import org.apache.log.output.io.rotate.RotateStrategyBySize;
29 import org.apache.log.output.io.rotate.RotateStrategyByTime;
30 import org.apache.log.output.io.rotate.FileStrategy;
31 import org.apache.log.output.io.rotate.RevolvingFileStrategy;
32 import org.apache.log.output.io.rotate.UniqueFileStrategy;
33
34 import java.io.File JavaDoc;
35 import java.io.IOException JavaDoc;
36 import java.util.StringTokenizer JavaDoc;
37
38 /**
39  * FileTargetFactory class.
40  *
41  * This factory is able to create different FileLogTargets according to the following
42  * configuration syntax:
43  *
44  * <pre>
45  * &lt;file id="foo"&gt;
46  * &lt;filename&gt;${context-key}/real-name/...&lt;/filename&gt;
47  * &lt;format type="raw|pattern|extended"&gt;pattern to be used if needed&lt;/format&gt;
48  * &lt;append&gt;true|false&lt;/append&gt;
49  * &lt;rotation type="revolving" init="5" max="10"&gt;
50  *
51  * or
52  *
53  * &lt;rotation type="unique" pattern="yyyy-MM-dd-hh-mm-ss" suffix=".log"&gt;
54  * &lt;or&gt;
55  * &lt;size&gt;10000000&lt;/size&gt;
56  * &lt;time&gt;24:00:00&lt;/time&gt;
57  * &lt;time&gt;12:00:00&lt;/time&gt;
58  * &lt;/or&gt;
59  * &lt;/rotate&gt;
60  * &lt;/file&gt;
61  * </pre>
62  *
63  * <p>Some explanations about the Elements used in the configuration:</p>
64  * <dl>
65  * <dt>&lt;filename&gt;</dt>
66  * <dd>
67  * This denotes the name of the file to log to. It can be constructed
68  * out of entries in the passed Context object as ${context-key}.
69  * This element is required.
70  * </dd>
71  * <dt>&lt;format&gt;</dt>
72  * <dd>
73  * The type attribute of the pattern element denotes the type of
74  * Formatter to be used and according to it the pattern to use for.
75  * This elements defaults to:
76  * <p>
77  * %7.7{priority} %5.5{time} [%8.8{category}] (%{context}): %{message}\\n%{throwable}
78  * </p>
79  * </dd>
80  * <dt>&lt;append&gt;<dt>
81  * <dd>
82  * If the log file should be deleted every time the logger is creates
83  * (normally at the start of the applcation) or not and thus the log
84  * entries will be appended. This elements defaults to false.
85  * </dd>
86  * <dt>&lt;rotation&gt;</dt>
87  * <dd>
88  * This is an optional element.
89  * The type attribute determines which FileStrategy to user
90  * (revolving=RevolvingFileStrategy, unique=UniqueFileStrategy).
91  * The required init and max attribute are used to determine the initial and
92  * maximum rotation to use on a type="revolving" attribute.
93  * The optional pattern and suffix attribute are used to form filenames on
94  * a type="unique" attribute.
95  * </dd>
96  * <dt>&lt;or&gt;</dt>
97  * <dd>uses the OrRotateStrategy to combine the children</dd>
98  * <dt>&lt;size&gt;</dt>
99  * <dd>
100  * The number of bytes if no suffix used or kilo bytes (1024) if suffixed with
101  * 'k' or mega bytes (1024k) if suffixed with 'm' when a file rotation should
102  * occur. It doesn't make sense to specify more than one.
103  * </dd>
104  * <dt>&lt;time&gt;</dt>
105  * <dd>
106  * The time as HH:MM:SS when a rotation should occur. If you like to rotate
107  * a logfile more than once a day put an &lt;or&gt; element immediately after the
108  * &lt;rotation&gt; element and specify the times (and one size, too) inside the
109  * &lt;or&gt; element.
110  * </dd>
111  * </dl>
112  *
113  * @author <a HREF="mailto:giacomo@apache,org">Giacomo Pati</a>
114  * @version CVS $Revision: 1.8 $ $Date: 2001/12/19 23:34:50 $
115  * @since 4.0
116  */

117 public class FileTargetFactory
118     extends AbstractTargetFactory
119 {
120
121     /**
122      * Create a LogTarget based on a Configuration
123      */

124     public final LogTarget createTarget( final Configuration configuration )
125         throws ConfigurationException
126     {
127         final Configuration conf_filename = configuration.getChild( "filename" );
128         final String JavaDoc filename = getFilename( conf_filename.getValue() );
129         
130         final Configuration conf_rotation = configuration.getChild( "rotation", false );
131         
132         final Configuration conf_format = configuration.getChild( "format" );
133
134         final Configuration conf_append = configuration.getChild( "append" );
135         final boolean append = conf_append.getValueAsBoolean( false );
136         
137         final LogTarget logtarget;
138         
139         final File JavaDoc file = new File JavaDoc( filename );
140         final Formatter formatter = getFormatter( conf_format );
141                       
142         try
143         {
144             if( null == conf_rotation )
145             {
146                 logtarget = new FileTarget( file, append, formatter );
147             }
148             else
149             {
150                 final Configuration conf_strategy = conf_rotation.getChildren()[0];
151                 final RotateStrategy rotateStrategy = getRotateStrategy( conf_strategy );
152                 final FileStrategy fileStrategy = getFileStrategy( conf_rotation, file );
153                 
154                 logtarget =
155                     new RotatingFileTarget( formatter, rotateStrategy, fileStrategy );
156             }
157         }
158         catch( final IOException JavaDoc ioe )
159         {
160             throw new ConfigurationException( "cannot create FileTarget", ioe );
161         }
162
163         return logtarget;
164     }
165
166     private final static long SECOND = 1000;
167     private final static long MINUTE = 60*SECOND;
168     private final static long HOUR = 60*MINUTE;
169     private final static long DAY = 24*HOUR;
170
171     private final static long KILOBYTE = 1000;
172     private final static long MEGABYTE = 1000*KILOBYTE;
173
174     private RotateStrategy getRotateStrategy( final Configuration conf )
175     {
176         final String JavaDoc type = conf.getName();
177         
178         if( "or".equals( type ) )
179         {
180             final Configuration[] configurations = conf.getChildren();
181             final int size = configurations.length;
182             
183             final RotateStrategy[] strategies = new RotateStrategy[size];
184             for( int i = 0; i < size; i++ )
185             {
186                 strategies[i] = getRotateStrategy( configurations[i] );
187             }
188             
189             return new OrRotateStrategy( strategies );
190         }
191         
192         if( "size".equals( type ) )
193         {
194             final String JavaDoc value = conf.getValue( "2m" );
195             
196             final int count = value.length();
197             final char end = value.charAt( count-1 );
198             final long no;
199             final long size;
200             
201             switch( end )
202             {
203                 case 'm':no = Long.parseLong( value.substring( 0, count-1 ) );
204                          size = no * MEGABYTE;
205                          break;
206                 case 'k':no = Long.parseLong( value.substring( 0, count-1 ) );
207                          size = no * KILOBYTE;
208                          break;
209                 default: size = Long.parseLong( value );
210             }
211             
212             return new RotateStrategyBySize( size );
213         }
214         
215         // default rotate strategy
216
final String JavaDoc value = conf.getValue( "24:00:00" );
217
218         // interpret a string like: ddd:hh:mm:ss ...
219
final StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc( value, ":" );
220         final int count = tokenizer.countTokens();
221         long time = 0;
222         for( int i = count; i > 0; i-- )
223         {
224             final long no = Long.parseLong( tokenizer.nextToken() );
225             if( 4 == i )
226             {
227                 time += no * DAY;
228             }
229             if( 3 == i )
230             {
231                 time += no * HOUR;
232             }
233             if( 2 == i )
234             {
235                 time += no * MINUTE;
236             }
237             if( 1 == i )
238             {
239                 time += no * SECOND;
240             }
241         }
242
243         return new RotateStrategyByTime( time );
244     }
245     
246     protected FileStrategy getFileStrategy( final Configuration conf, final File JavaDoc file )
247     {
248         final String JavaDoc type = conf.getAttribute( "type", "unique" );
249         
250         if( "revolving".equals( type ) )
251         {
252             final int initialRotation =
253                 conf.getAttributeAsInteger( "init", 5 );
254             final int maxRotation =
255                 conf.getAttributeAsInteger( "max", 10 );
256             
257             return new RevolvingFileStrategy( file, initialRotation, maxRotation );
258         }
259         
260         // default file strategy
261
final String JavaDoc pattern = conf.getAttribute( "pattern", null );
262         final String JavaDoc suffix = conf.getAttribute( "suffix", null );
263         if( pattern == null)
264         {
265             return new UniqueFileStrategy( file );
266         }
267         else
268         {
269             if( suffix == null )
270             {
271                 return new UniqueFileStrategy( file, pattern );
272             }
273             else
274             {
275                 return new UniqueFileStrategy( file, pattern, suffix );
276             }
277         }
278     }
279
280     protected Formatter getFormatter( final Configuration conf )
281     {
282         Formatter formatter = null;
283
284         if ( null != conf )
285         {
286             final FormatterFactory formatterFactory = new FormatterFactory();
287             formatter = formatterFactory.createFormatter( conf );
288         }
289         
290         return formatter;
291     }
292
293     /**
294      * Process the file name
295      *
296      * This method scans the file name passed for occurrences of
297      * ${foo}. Those strings get replaced by values from the Context object
298      * indexted by the name (here foo).
299      *
300      * @param rawFilename The filename with substitutable placeholders
301      * @return The processed file name
302      * @exception ConfigurationException if substitutable values are not in the
303      * Context object.
304      */

305     protected final String JavaDoc getFilename( String JavaDoc rawFilename )
306         throws ConfigurationException
307     {
308         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
309         int i = 0;
310         int j = -1;
311         while( ( j = rawFilename.indexOf( "${", i ) ) > -1 )
312         {
313             if( i < j )
314             {
315                 sb.append( rawFilename.substring( i, j ) );
316             }
317             int k = rawFilename.indexOf( '}', j );
318             final String JavaDoc ctx_name = rawFilename.substring( j + 2, k );
319             final Object JavaDoc ctx;
320             try
321             {
322                 ctx = m_context.get( ctx_name );
323             }
324             catch( final ContextException ce )
325             {
326                 throw new ConfigurationException( "missing entry '" + ctx_name + "' in Context" );
327             }
328             sb.append( ctx.toString() );
329             i = k + 1;
330         }
331         if( i < rawFilename.length() )
332         {
333             sb.append( rawFilename.substring( i, rawFilename.length() ) );
334         }
335         return sb.toString();
336     }
337 }
338
339
Popular Tags