001: package org.apache.velocity.runtime.log;
002:
003: /*
004: * Licensed to the Apache Software Foundation (ASF) under one
005: * or more contributor license agreements. See the NOTICE file
006: * distributed with this work for additional information
007: * regarding copyright ownership. The ASF licenses this file
008: * to you under the Apache License, Version 2.0 (the
009: * "License"); you may not use this file except in compliance
010: * with the License. You may obtain a copy of the License at
011: *
012: * http://www.apache.org/licenses/LICENSE-2.0
013: *
014: * Unless required by applicable law or agreed to in writing,
015: * software distributed under the License is distributed on an
016: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017: * KIND, either express or implied. See the License for the
018: * specific language governing permissions and limitations
019: * under the License.
020: */
021:
022: import java.io.IOException;
023: import java.lang.reflect.Field;
024: import org.apache.log4j.Level;
025: import org.apache.log4j.Logger;
026: import org.apache.log4j.PatternLayout;
027: import org.apache.log4j.RollingFileAppender;
028: import org.apache.velocity.runtime.RuntimeConstants;
029: import org.apache.velocity.runtime.RuntimeServices;
030: import org.apache.velocity.util.ExceptionUtils;
031:
032: /**
033: * Implementation of a simple log4j system that will either latch onto
034: * an existing category, or just do a simple rolling file log.
035: *
036: * @author <a href="mailto:geirm@apache.org>Geir Magnusson Jr.</a>
037: * @author <a href="mailto:dlr@finemaltcoding.com>Daniel L. Rall</a>
038: * @author <a href="mailto:nbubna@apache.org>Nathan Bubna</a>
039: * @version $Id: Log4JLogChute.java 463298 2006-10-12 16:10:32Z henning $
040: * @since Velocity 1.5
041: */
042: public class Log4JLogChute implements LogChute {
043: /**
044: *
045: */
046: public static final String RUNTIME_LOG_LOG4J_LOGGER = "runtime.log.logsystem.log4j.logger";
047:
048: private RuntimeServices rsvc = null;
049: private boolean hasTrace = false;
050: private RollingFileAppender appender = null;
051:
052: /**
053: * <a href="http://jakarta.apache.org/log4j/">Log4J</a> logging API.
054: */
055: protected Logger logger = null;
056:
057: /**
058: * @see org.apache.velocity.runtime.log.LogChute#init(org.apache.velocity.runtime.RuntimeServices)
059: */
060: public void init(RuntimeServices rs) throws Exception {
061: rsvc = rs;
062:
063: /* first see if there is a category specified and just use that - it allows
064: * the application to make us use an existing logger
065: */
066: String name = (String) rsvc
067: .getProperty(RUNTIME_LOG_LOG4J_LOGGER);
068: if (name != null) {
069: logger = Logger.getLogger(name);
070: log(DEBUG_ID, "Log4JLogChute using logger '" + name + '\'');
071: } else {
072: // create a logger with this class name to avoid conflicts
073: logger = Logger.getLogger(this .getClass().getName());
074:
075: // if we have a file property, then create a separate
076: // rolling file log for velocity messages only
077: String file = rsvc.getString(RuntimeConstants.RUNTIME_LOG);
078: if (file != null && file.length() > 0) {
079: initAppender(file);
080: }
081: }
082:
083: /* Ok, now let's see if this version of log4j supports the trace level. */
084: try {
085: Field traceLevel = Level.class.getField("TRACE");
086: // we'll never get here in pre 1.2.12 log4j
087: hasTrace = true;
088: } catch (NoSuchFieldException e) {
089: log(DEBUG_ID,
090: "The version of log4j being used does not support the \"trace\" level.");
091: }
092: }
093:
094: // This tries to create a file appender for the specified file name.
095: private void initAppender(String file) throws Exception {
096: try {
097: // to add the appender
098: PatternLayout layout = new PatternLayout("%d - %m%n");
099: this .appender = new RollingFileAppender(layout, file, true);
100:
101: // if we successfully created the file appender,
102: // configure it and set the logger to use only it
103: appender.setMaxBackupIndex(1);
104: appender.setMaximumFileSize(100000);
105:
106: // don't inherit appenders from higher in the logger heirarchy
107: logger.setAdditivity(false);
108: // this impl checks levels (by default don't include trace level)
109: logger.setLevel(Level.DEBUG);
110: logger.addAppender(appender);
111: log(DEBUG_ID, "Log4JLogChute initialized using file '"
112: + file + '\'');
113: } catch (IOException ioe) {
114: rsvc.getLog().warn(
115: "Could not create file appender '" + file + '\'',
116: ioe);
117: throw ExceptionUtils.createRuntimeException(
118: "Error configuring Log4JLogChute : ", ioe);
119: }
120: }
121:
122: /**
123: * logs messages
124: *
125: * @param level severity level
126: * @param message complete error message
127: */
128: public void log(int level, String message) {
129: switch (level) {
130: case LogChute.WARN_ID:
131: logger.warn(message);
132: break;
133: case LogChute.INFO_ID:
134: logger.info(message);
135: break;
136: case LogChute.DEBUG_ID:
137: logger.debug(message);
138: break;
139: case LogChute.TRACE_ID:
140: if (hasTrace) {
141: logger.trace(message);
142: } else {
143: logger.debug(message);
144: }
145: break;
146: case LogChute.ERROR_ID:
147: logger.error(message);
148: break;
149: default:
150: logger.debug(message);
151: break;
152: }
153: }
154:
155: /**
156: * @see org.apache.velocity.runtime.log.LogChute#log(int, java.lang.String, java.lang.Throwable)
157: */
158: public void log(int level, String message, Throwable t) {
159: switch (level) {
160: case LogChute.WARN_ID:
161: logger.warn(message, t);
162: break;
163: case LogChute.INFO_ID:
164: logger.info(message, t);
165: break;
166: case LogChute.DEBUG_ID:
167: logger.debug(message, t);
168: break;
169: case LogChute.TRACE_ID:
170: if (hasTrace) {
171: logger.trace(message, t);
172: } else {
173: logger.debug(message, t);
174: }
175: break;
176: case LogChute.ERROR_ID:
177: logger.error(message, t);
178: break;
179: default:
180: logger.debug(message, t);
181: break;
182: }
183: }
184:
185: /**
186: * @see org.apache.velocity.runtime.log.LogChute#isLevelEnabled(int)
187: */
188: public boolean isLevelEnabled(int level) {
189: switch (level) {
190: case LogChute.DEBUG_ID:
191: return logger.isDebugEnabled();
192: case LogChute.INFO_ID:
193: return logger.isInfoEnabled();
194: case LogChute.TRACE_ID:
195: if (hasTrace) {
196: return logger.isTraceEnabled();
197: } else {
198: return logger.isDebugEnabled();
199: }
200: case LogChute.WARN_ID:
201: return logger.isEnabledFor(Level.WARN);
202: case LogChute.ERROR_ID:
203: // can't be disabled in log4j
204: return logger.isEnabledFor(Level.ERROR);
205: default:
206: return true;
207: }
208: }
209:
210: /**
211: * Also do a shutdown if the object is destroy()'d.
212: * @throws Throwable
213: */
214: protected void finalize() throws Throwable {
215: shutdown();
216: }
217:
218: /** Close all destinations*/
219: public void shutdown() {
220: if (appender != null) {
221: logger.removeAppender(appender);
222: appender.close();
223: appender = null;
224: }
225: }
226:
227: }
|