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.Hashtable;
021    import java.util.Map;
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     * <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
046    public 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    }