001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.commons.discovery.log;
018
019 import java.lang.reflect.Method;
020 import java.util.Enumeration;
021 import java.util.Hashtable;
022
023 import org.apache.commons.discovery.DiscoveryException;
024 import org.apache.commons.discovery.tools.ClassUtils;
025 import org.apache.commons.logging.Log;
026 import org.apache.commons.logging.LogFactory;
027
028
029 /**
030 * <p>Simple implementation of Log that sends all enabled log messages,
031 * for all defined loggers, to System.err.
032 * </p>
033 *
034 * <p>Hacked from commons-logging SimpleLog for use in discovery.
035 * This is intended to be enough of a Log implementation to bootstrap
036 * Discovery.
037 * </p>
038 *
039 * <p>One property: <code>org.apache.commons.discovery.log.level</code>.
040 * valid values: all, trace, debug, info, warn, error, fatal, off.
041 * </p>
042 *
043 * @author Richard A. Sitze
044 * @author <a href="mailto:sanders@apache.org">Scott Sanders</a>
045 * @author Rod Waldhoff
046 * @author Robert Burrell Donkin
047 *
048 * @version $Id: DiscoveryLogFactory.java 480374 2006-11-29 03:33:25Z niallp $
049 */
050 public class DiscoveryLogFactory {
051 private static LogFactory logFactory = null;
052 private static final Hashtable classRegistry = new Hashtable();
053 private static final Class[] setLogParamClasses = new Class[] { Log.class };
054
055 /**
056 * Above fields must be initialied before this one..
057 */
058 private static Log log = DiscoveryLogFactory._newLog(DiscoveryLogFactory.class);
059
060 /**
061 */
062 public static Log newLog(Class clazz) {
063 /**
064 * Required to implement 'public static void setLog(Log)'
065 */
066 try {
067 Method setLog = ClassUtils.findPublicStaticMethod(clazz,
068 void.class,
069 "setLog",
070 setLogParamClasses);
071
072 if (setLog == null) {
073 String msg = "Internal Error: " + clazz.getName() + " required to implement 'public static void setLog(Log)'";
074 log.fatal(msg);
075 throw new DiscoveryException(msg);
076 }
077 } catch (SecurityException se) {
078 String msg = "Required Security Permissions not present";
079 log.fatal(msg, se);
080 throw new DiscoveryException(msg, se);
081 }
082
083 if (log.isDebugEnabled())
084 log.debug("Class meets requirements: " + clazz.getName());
085
086 return _newLog(clazz);
087 }
088
089 /**
090 * This method MUST not invoke any logging..
091 */
092 public static Log _newLog(Class clazz) {
093 classRegistry.put(clazz, clazz);
094
095 return (logFactory == null)
096 ? new SimpleLog(clazz.getName())
097 : logFactory.getInstance(clazz.getName());
098 }
099
100 public static void setLog(Log _log) {
101 log = _log;
102 }
103
104 /**
105 * Set logFactory, works ONLY on first call.
106 */
107 public static void setFactory(LogFactory factory) {
108 if (logFactory == null) {
109 // for future generations.. if any
110 logFactory = factory;
111
112 // now, go back and reset loggers for all current classes..
113 Enumeration elements = classRegistry.elements();
114 while (elements.hasMoreElements()) {
115 Class clazz = (Class)elements.nextElement();
116
117 if (log.isDebugEnabled())
118 log.debug("Reset Log for: " + clazz.getName());
119
120 Method setLog = null;
121
122 // invoke 'setLog(Log)'.. we already know it's 'public static',
123 // have verified parameters, and return type..
124 try {
125 setLog = clazz.getMethod("setLog", setLogParamClasses);
126 } catch(Exception e) {
127 String msg = "Internal Error: pre-check for " + clazz.getName() + " failed?!";
128 log.fatal(msg, e);
129 throw new DiscoveryException(msg, e);
130 }
131
132 Object[] setLogParam = new Object[] { factory.getInstance(clazz.getName()) };
133
134 try {
135 setLog.invoke(null, setLogParam);
136 } catch(Exception e) {
137 String msg = "Internal Error: setLog failed for " + clazz.getName();
138 log.fatal(msg, e);
139 throw new DiscoveryException(msg, e);
140 }
141 }
142 }
143 }
144 }