View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.discovery.log;
18  
19  import java.lang.reflect.Method;
20  import java.util.Enumeration;
21  import java.util.Hashtable;
22  
23  import org.apache.commons.discovery.DiscoveryException;
24  import org.apache.commons.discovery.tools.ClassUtils;
25  import org.apache.commons.logging.Log;
26  import org.apache.commons.logging.LogFactory;
27  
28  
29  /***
30   * <p>Simple implementation of Log that sends all enabled log messages,
31   * for all defined loggers, to System.err.
32   * </p>
33   * 
34   * <p>Hacked from commons-logging SimpleLog for use in discovery.
35   * This is intended to be enough of a Log implementation to bootstrap
36   * Discovery.
37   * </p>
38   * 
39   * <p>One property: <code>org.apache.commons.discovery.log.level</code>.
40   * valid values: all, trace, debug, info, warn, error, fatal, off.
41   * </p>
42   * 
43   * @author Richard A. Sitze
44   * @author <a href="mailto:sanders@apache.org">Scott Sanders</a>
45   * @author Rod Waldhoff
46   * @author Robert Burrell Donkin
47   *
48   * @version $Id: DiscoveryLogFactory.java 480374 2006-11-29 03:33:25Z niallp $
49   */
50  public class DiscoveryLogFactory {
51      private static LogFactory logFactory = null;
52      private static final Hashtable  classRegistry = new Hashtable();
53      private static final Class[] setLogParamClasses = new Class[] { Log.class };
54  
55      /***
56       * Above fields must be initialied before this one..
57       */
58      private static Log log = DiscoveryLogFactory._newLog(DiscoveryLogFactory.class);
59  
60      /***
61       */    
62      public static Log newLog(Class clazz) {
63          /***
64           * Required to implement 'public static void setLog(Log)'
65           */
66          try {
67              Method setLog = ClassUtils.findPublicStaticMethod(clazz,
68                                                                void.class,
69                                                                "setLog",
70                                                                setLogParamClasses);
71              
72              if (setLog == null) {
73                  String msg = "Internal Error: " + clazz.getName() + " required to implement 'public static void setLog(Log)'";
74                  log.fatal(msg);
75                  throw new DiscoveryException(msg);
76              }
77          } catch (SecurityException se) {
78              String msg = "Required Security Permissions not present";
79              log.fatal(msg, se);
80              throw new DiscoveryException(msg, se);
81          }
82  
83          if (log.isDebugEnabled())
84              log.debug("Class meets requirements: " + clazz.getName());
85  
86          return _newLog(clazz);
87      }
88  
89      /***
90       * This method MUST not invoke any logging..
91       */
92      public static Log _newLog(Class clazz) {
93          classRegistry.put(clazz, clazz);
94  
95          return (logFactory == null)
96                 ? new SimpleLog(clazz.getName())
97                 : logFactory.getInstance(clazz.getName());
98      }
99      
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 }