View Javadoc

1   package org.apache.velocity.runtime.log;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.    
20   */
21  
22  import java.io.IOException;
23  import java.lang.reflect.Field;
24  import org.apache.log4j.Level;
25  import org.apache.log4j.Logger;
26  import org.apache.log4j.PatternLayout;
27  import org.apache.log4j.RollingFileAppender;
28  import org.apache.velocity.runtime.RuntimeConstants;
29  import org.apache.velocity.runtime.RuntimeServices;
30  import org.apache.velocity.util.ExceptionUtils;
31  
32  /**
33   * Implementation of a simple log4j system that will either latch onto
34   * an existing category, or just do a simple rolling file log.
35   *
36   * @author <a href="mailto:geirm@apache.org>Geir Magnusson Jr.</a>
37   * @author <a href="mailto:dlr@finemaltcoding.com>Daniel L. Rall</a>
38   * @author <a href="mailto:nbubna@apache.org>Nathan Bubna</a>
39   * @version $Id: Log4JLogChute.java 522566 2007-03-26 16:42:00Z nbubna $
40   * @since Velocity 1.5
41   */
42  public class Log4JLogChute implements LogChute
43  {
44      public static final String RUNTIME_LOG_LOG4J_LOGGER =
45              "runtime.log.logsystem.log4j.logger";
46      public static final String RUNTIME_LOG_LOG4J_LOGGER_LEVEL =
47              "runtime.log.logsystem.log4j.logger.level";
48  
49      private RuntimeServices rsvc = null;
50      private boolean hasTrace = false;
51      private RollingFileAppender appender = null;
52  
53      /**
54       * <a href="http://jakarta.apache.org/log4j/">Log4J</a> logging API.
55       */
56      protected Logger logger = null;
57  
58      /**
59       * @see org.apache.velocity.runtime.log.LogChute#init(org.apache.velocity.runtime.RuntimeServices)
60       */
61      public void init(RuntimeServices rs) throws Exception
62      {
63          rsvc = rs;
64  
65          /* first see if there is a category specified and just use that - it allows
66           * the application to make us use an existing logger
67           */
68          String name = (String)rsvc.getProperty(RUNTIME_LOG_LOG4J_LOGGER);
69          if (name != null)
70          {
71              logger = Logger.getLogger(name);
72              log(DEBUG_ID, "Log4JLogChute using logger '" + name + '\'');
73          }
74          else
75          {
76              // create a logger with this class name to avoid conflicts
77              logger = Logger.getLogger(this.getClass().getName());
78  
79              // if we have a file property, then create a separate
80              // rolling file log for velocity messages only
81              String file = rsvc.getString(RuntimeConstants.RUNTIME_LOG);
82              if (file != null && file.length() > 0)
83              {
84                  initAppender(file);
85              }
86          }
87  
88          /* get and set specified level for this logger, default to WARN */
89          String lvl = rsvc.getString(RUNTIME_LOG_LOG4J_LOGGER_LEVEL, "WARN");
90          Level level = Level.toLevel(lvl);
91          logger.setLevel(level);
92  
93          /* Ok, now let's see if this version of log4j supports the trace level. */
94          try
95          {
96              Field traceLevel = Level.class.getField("TRACE");
97              // we'll never get here in pre 1.2.12 log4j
98              hasTrace = true;
99          }
100         catch (NoSuchFieldException e)
101         {
102             log(DEBUG_ID,
103                 "The version of log4j being used does not support the \"trace\" level.");
104         }
105     }
106 
107     // This tries to create a file appender for the specified file name.
108     private void initAppender(String file) throws Exception
109     {
110         try
111         {
112             // to add the appender
113             PatternLayout layout = new PatternLayout("%d - %m%n");
114             this.appender = new RollingFileAppender(layout, file, true);
115 
116             // if we successfully created the file appender,
117             // configure it and set the logger to use only it
118             appender.setMaxBackupIndex(1);
119             appender.setMaximumFileSize(100000);
120 
121             // don't inherit appenders from higher in the logger heirarchy
122             logger.setAdditivity(false);
123             logger.addAppender(appender);
124             log(DEBUG_ID, "Log4JLogChute initialized using file '"+file+'\'');
125         }
126         catch (IOException ioe)
127         {
128             rsvc.getLog().warn("Could not create file appender '"+file+'\'', ioe);
129             throw ExceptionUtils.createRuntimeException("Error configuring Log4JLogChute : ", ioe);
130         }
131     }
132 
133     /**
134      *  logs messages
135      *
136      *  @param level severity level
137      *  @param message complete error message
138      */
139     public void log(int level, String message)
140     {
141         switch (level)
142         {
143             case LogChute.WARN_ID:
144                 logger.warn(message);
145                 break;
146             case LogChute.INFO_ID:
147                 logger.info(message);
148                 break;
149             case LogChute.DEBUG_ID:
150                 logger.debug(message);
151                 break;
152             case LogChute.TRACE_ID:
153                 if (hasTrace)
154                 {
155                     logger.trace(message);
156                 }
157                 else
158                 {
159                     logger.debug(message);
160                 }
161                 break;
162             case LogChute.ERROR_ID:
163                 logger.error(message);
164                 break;
165             default:
166                 logger.debug(message);
167                 break;
168         }
169     }
170 
171     /**
172      * @see org.apache.velocity.runtime.log.LogChute#log(int, java.lang.String, java.lang.Throwable)
173      */
174     public void log(int level, String message, Throwable t)
175     {
176         switch (level)
177         {
178             case LogChute.WARN_ID:
179                 logger.warn(message, t);
180                 break;
181             case LogChute.INFO_ID:
182                 logger.info(message, t);
183                 break;
184             case LogChute.DEBUG_ID:
185                 logger.debug(message, t);
186                 break;
187             case LogChute.TRACE_ID:
188                 if (hasTrace)
189                 {
190                     logger.trace(message, t);
191                 }
192                 else
193                 {
194                     logger.debug(message, t);
195                 }
196                 break;
197             case LogChute.ERROR_ID:
198                 logger.error(message, t);
199                 break;
200             default:
201                 logger.debug(message, t);
202                 break;
203         }
204     }
205 
206     /**
207      * @see org.apache.velocity.runtime.log.LogChute#isLevelEnabled(int)
208      */
209     public boolean isLevelEnabled(int level)
210     {
211         switch (level)
212         {
213             case LogChute.DEBUG_ID:
214                 return logger.isDebugEnabled();
215             case LogChute.INFO_ID:
216                 return logger.isInfoEnabled();
217             case LogChute.TRACE_ID:
218                 if (hasTrace)
219                 {
220                     return logger.isTraceEnabled();
221                 }
222                 else
223                 {
224                     return logger.isDebugEnabled();
225                 }
226             case LogChute.WARN_ID:
227                 return logger.isEnabledFor(Level.WARN);
228             case LogChute.ERROR_ID:
229                 // can't be disabled in log4j
230                 return logger.isEnabledFor(Level.ERROR);
231             default:
232                 return true;
233         }
234     }
235 
236     /**
237      * Also do a shutdown if the object is destroy()'d.
238      * @throws Throwable
239      */
240     protected void finalize() throws Throwable
241     {
242         shutdown();
243     }
244 
245     /** Close all destinations*/
246     public void shutdown()
247     {
248         if (appender != null)
249         {
250             logger.removeAppender(appender);
251             appender.close();
252             appender = null;
253         }
254     }
255 
256 }