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 */
017package org.apache.commons.discovery.log;
018
019import java.lang.reflect.Method;
020import java.util.Hashtable;
021import java.util.Map;
022
023import org.apache.commons.discovery.DiscoveryException;
024import org.apache.commons.discovery.tools.ClassUtils;
025import org.apache.commons.logging.Log;
026import org.apache.commons.logging.LogFactory;
027
028/**
029 * <p>Simple implementation of Log that sends all enabled log messages,
030 * for all defined loggers, to System.err.
031 * </p>
032 *
033 * <p>Hacked from commons-logging SimpleLog for use in discovery.
034 * This is intended to be enough of a Log implementation to bootstrap
035 * Discovery.
036 * </p>
037 *
038 * <p>One property: <code>org.apache.commons.discovery.log.level</code>.
039 * valid values: all, trace, debug, info, warn, error, fatal, off.
040 * </p>
041 *
042 * @deprecated Starting from commons-discovery-05, Log is totally delegated to commons-logging
043 * @version $Id: DiscoveryLogFactory.java 1089255 2011-04-05 21:51:05Z simonetripodi $
044 */
045@Deprecated
046public class DiscoveryLogFactory {
047
048    private static LogFactory logFactory = null;
049
050    private static final Map<Class<?>, Class<?>>  classRegistry = new Hashtable<Class<?>, Class<?>>();
051
052    private static final Class<?>[] setLogParamClasses = new Class<?>[] { Log.class };
053
054    /**
055     * Above fields must be initialied before this one..
056     */
057    private static Log log = DiscoveryLogFactory._newLog(DiscoveryLogFactory.class);
058
059    /**
060     * Creates a new {@code Log} instance for the input class.
061     *
062     * @param clazz The class the log has to be created for
063     * @return The input class logger
064     */
065    public static Log newLog(Class<?> clazz) {
066        /**
067         * Required to implement 'public static void setLog(Log)'
068         */
069        try {
070            Method setLog = ClassUtils.findPublicStaticMethod(clazz,
071                                                              void.class,
072                                                              "setLog",
073                                                              setLogParamClasses);
074
075            if (setLog == null) {
076                String msg = "Internal Error: "
077                    + clazz.getName()
078                    + " required to implement 'public static void setLog(Log)'";
079                log.fatal(msg);
080                throw new DiscoveryException(msg);
081            }
082        } catch (SecurityException se) {
083            String msg = "Required Security Permissions not present";
084            log.fatal(msg, se);
085            throw new DiscoveryException(msg, se);
086        }
087
088        if (log.isDebugEnabled()) {
089            log.debug("Class meets requirements: " + clazz.getName());
090        }
091
092        return _newLog(clazz);
093    }
094
095    /**
096     * This method MUST not invoke any logging..
097     *
098     * @param clazz The class the log has to be created for
099     * @return The input class logger
100     */
101    public static Log _newLog(Class<?> clazz) {
102        classRegistry.put(clazz, clazz);
103
104        return (logFactory == null)
105               ? new SimpleLog(clazz.getName())
106               : logFactory.getInstance(clazz.getName());
107    }
108
109    /**
110     * Sets the {@code Log} for this class.
111     *
112     * @param _log This class {@code Log}
113     */
114    public static void setLog(Log _log) {
115        log = _log;
116    }
117
118    /**
119     * Set logFactory, works ONLY on first call.
120     *
121     * @param factory The log factory
122     */
123    public static void setFactory(LogFactory factory) {
124        if (logFactory == null) {
125            // for future generations.. if any
126            logFactory = factory;
127
128            // now, go back and reset loggers for all current classes..
129            for (Class<?> clazz : classRegistry.values()) {
130
131                if (log.isDebugEnabled()) {
132                    log.debug("Reset Log for: " + clazz.getName());
133                }
134
135                Method setLog = null;
136
137                // invoke 'setLog(Log)'.. we already know it's 'public static',
138                // have verified parameters, and return type..
139                try {
140                    setLog = clazz.getMethod("setLog", setLogParamClasses);
141                } catch(Exception e) {
142                    String msg = "Internal Error: pre-check for " + clazz.getName() + " failed?!";
143                    log.fatal(msg, e);
144                    throw new DiscoveryException(msg, e);
145                }
146
147                Object[] setLogParam = new Object[] { factory.getInstance(clazz.getName()) };
148
149                try {
150                    setLog.invoke(null, setLogParam);
151                } catch(Exception e) {
152                    String msg = "Internal Error: setLog failed for " + clazz.getName();
153                    log.fatal(msg, e);
154                    throw new DiscoveryException(msg, e);
155                }
156            }
157        }
158    }
159
160}