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.util.List;
023: import java.util.ArrayList;
024: import java.util.Iterator;
025:
026: import org.apache.velocity.runtime.RuntimeServices;
027: import org.apache.velocity.runtime.RuntimeConstants;
028: import org.apache.velocity.util.ClassUtils;
029:
030: /**
031: * <p>
032: * This class is responsible for instantiating the correct LogChute
033: * </p>
034: *
035: * <p>
036: * The approach is :
037: * </p>
038: * <ul>
039: * <li>
040: * First try to see if the user is passing in a living object
041: * that is a LogChute, allowing the app to give its living
042: * custom loggers.
043: * </li>
044: * <li>
045: * Next, run through the (possible) list of classes specified
046: * specified as loggers, taking the first one that appears to
047: * work. This is how we support finding logkit, log4j or
048: * jdk logging, whichever is in the classpath and found first,
049: * as all three are listed as defaults.
050: * </li>
051: * <li>
052: * Finally, we turn to the System.err stream and print log messages
053: * to it if nothing else works.
054: * </li>
055: *
056: * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
057: * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
058: * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
059: * @author <a href="mailto:nbubna@apache.org">Nathan Bubna</a>
060: * @version $Id: LogManager.java 490011 2006-12-24 12:19:09Z henning $
061: */
062: public class LogManager {
063: // Creates a new logging system or returns an existing one
064: // specified by the application.
065: private static LogChute createLogChute(RuntimeServices rsvc)
066: throws Exception {
067: Log log = rsvc.getLog();
068:
069: /* If a LogChute or LogSystem instance was set as a configuration
070: * value, use that. This is any class the user specifies.
071: */
072: Object o = rsvc
073: .getProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM);
074: if (o != null) {
075: // first check for a LogChute
076: if (o instanceof LogChute) {
077: try {
078: ((LogChute) o).init(rsvc);
079: return (LogChute) o;
080: } catch (Exception e) {
081: log.error("Could not init runtime.log.logsystem "
082: + o, e);
083: }
084: }
085: // then check for a LogSystem
086: else if (o instanceof LogSystem) {
087: // inform the user about the deprecation
088: log
089: .info("LogSystem has been deprecated. Please use a LogChute implementation.");
090: try {
091: // wrap the LogSystem into a chute.
092: LogChute chute = new LogChuteSystem((LogSystem) o);
093: chute.init(rsvc);
094: return chute;
095: } catch (Exception e) {
096: log.error("Could not init runtime.log.logsystem "
097: + o, e);
098: }
099: } else {
100: log
101: .warn(o.getClass().getName()
102: + " object set as runtime.log.logsystem is not a valid log implementation.");
103: }
104: }
105:
106: /* otherwise, see if a class was specified. You can put multiple
107: * classes, and we use the first one we find.
108: *
109: * Note that the default value of this property contains the
110: * AvalonLogChute, the Log4JLogChute, and the JdkLogChute for
111: * convenience - so we use whichever we find first.
112: */
113: List classes = new ArrayList();
114: Object obj = rsvc
115: .getProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS);
116:
117: /*
118: * we might have a list, or not - so check
119: */
120: if (obj instanceof List) {
121: classes = (List) obj;
122: } else if (obj instanceof String) {
123: classes.add(obj);
124: }
125:
126: /*
127: * now run through the list, trying each. It's ok to
128: * fail with a class not found, as we do this to also
129: * search out a default simple file logger
130: */
131: for (Iterator ii = classes.iterator(); ii.hasNext();) {
132: String claz = (String) ii.next();
133: if (claz != null && claz.length() > 0) {
134: log.debug("Trying to use logger class " + claz);
135: try {
136: o = ClassUtils.getNewInstance(claz);
137: if (o instanceof LogChute) {
138: ((LogChute) o).init(rsvc);
139: log.debug("Using logger class " + claz);
140: return (LogChute) o;
141: } else if (o instanceof LogSystem) {
142: // inform the user about the deprecation
143: log
144: .info("LogSystem has been deprecated. Please use a LogChute implementation.");
145: LogChute chute = new LogChuteSystem(
146: (LogSystem) o);
147: chute.init(rsvc);
148: return chute;
149: } else {
150: log
151: .error("The specifid logger class "
152: + claz
153: + " isn't a valid LogChute implementation.");
154: }
155: } catch (NoClassDefFoundError ncdfe) {
156: // note these errors for anyone debugging the app
157: log
158: .debug(
159: "Couldn't find class "
160: + claz
161: + " or necessary supporting classes in classpath.",
162: ncdfe);
163: } catch (Exception e) {
164: // log init exception at slightly higher priority
165: log
166: .info(
167: "Failed to initialize an instance of "
168: + claz
169: + " with the current runtime configuration.",
170: e);
171: }
172: }
173: }
174:
175: /* If the above failed, that means either the user specified a
176: * logging class that we can't find, there weren't the necessary
177: * dependencies in the classpath for it, or there were the same
178: * problems for the default loggers, log4j and Java1.4+.
179: * Since we really don't know and we want to be sure the user knows
180: * that something went wrong with the logging, let's fall back to the
181: * surefire SystemLogChute. No panicking or failing to log!!
182: */
183: LogChute slc = new SystemLogChute();
184: slc.init(rsvc);
185: log.debug("Using SystemLogChute.");
186: return slc;
187: }
188:
189: /**
190: * Update the Log instance with the appropriate LogChute and other
191: * settings determined by the RuntimeServices.
192: * @param log
193: * @param rsvc
194: * @throws Exception
195: */
196: public static void updateLog(Log log, RuntimeServices rsvc)
197: throws Exception {
198: // create a new LogChute using the RuntimeServices
199: LogChute newLogChute = createLogChute(rsvc);
200: LogChute oldLogChute = log.getLogChute();
201:
202: // If the old LogChute was the pre-Init logger,
203: // dump its messages into the new system first.
204: if (oldLogChute instanceof HoldingLogChute) {
205: HoldingLogChute hlc = (HoldingLogChute) oldLogChute;
206: hlc.transferTo(newLogChute);
207: }
208:
209: // pass the new LogChute to the log
210: log.setLogChute(newLogChute);
211: }
212:
213: }
|