    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.logging.log4j.jul;
    018
    019    import java.util.Collections;
    020    import java.util.Enumeration;
    021    import java.util.logging.Logger;
    022
    023    import org.apache.logging.log4j.LoggingException;
    024    import org.apache.logging.log4j.status.StatusLogger;
    025    import org.apache.logging.log4j.util.LoaderUtil;
    026    import org.apache.logging.log4j.util.PropertiesUtil;
    027
    028    /**
    029     * Log4j implementation of {@link java.util.logging.LogManager}. Note that the system property
    030     * {@code java.util.logging.manager} must be set to {@code org.apache.logging.log4j.jul.LogManager} in order to use
    031     * this adaptor. This LogManager requires the {@code log4j-api} library to be available. If {@code log4j-core} is
    032     * also available, then more features of {@link java.util.logging.Logger} are supported.
    033     *
    034     * <p>To override the default {@link AbstractLoggerAdapter} that is used, specify the Log4j property
    035     * {@code log4j.jul.LoggerAdapter} and set it to the fully qualified class name of a custom
    036     * implementation. All implementations must have a default constructor.</p>
    037     *
    038     * @since 2.1
    039     */
    040    public class LogManager extends java.util.logging.LogManager {
    041
    042        private static final org.apache.logging.log4j.Logger LOGGER = StatusLogger.getLogger();
    043        private final AbstractLoggerAdapter loggerAdapter;
    044
    045        public LogManager() {
    046            super();
    047            AbstractLoggerAdapter adapter = null;
    048            final String overrideAdaptorClassName =
    049                PropertiesUtil.getProperties().getStringProperty(Constants.LOGGER_ADAPTOR_PROPERTY);
    050            if (overrideAdaptorClassName != null) {
    051                try {
    052                    LOGGER.info("Trying to use LoggerAdaptor [{}] specified by Log4j property.", overrideAdaptorClassName);
    053                    adapter = LoaderUtil.newCheckedInstanceOf(overrideAdaptorClassName, AbstractLoggerAdapter.class);
    054                } catch (final Exception e) {
    055                    LOGGER.error("Specified LoggerAdapter [{}] is incompatible.", overrideAdaptorClassName, e);
    056                }
    057            }
    058            if (adapter == null) {
    059                // default adapter
    060                String adapterClassName;
    061                try {
    062                    // find out if log4j-core is available
    063                    LoaderUtil.loadClass(Constants.CORE_LOGGER_CLASS_NAME);
    064                    adapterClassName = Constants.CORE_LOGGER_ADAPTER_CLASS_NAME;
    065                } catch (final ClassNotFoundException ignored) {
    066                    adapterClassName = Constants.API_LOGGER_ADAPTER_CLASS_NAME;
    067                }
    068                LOGGER.debug("Attempting to use {}", adapterClassName);
    069                try {
    070                    adapter = LoaderUtil.newCheckedInstanceOf(adapterClassName, AbstractLoggerAdapter.class);
    071                } catch (final Exception e) {
    072                    throw LOGGER.throwing(new LoggingException(e));
    073                }
    074            }
    075            loggerAdapter = adapter;
    076            LOGGER.info("Registered Log4j as the java.util.logging.LogManager.");
    077        }
    078
    079        @Override
    080        public boolean addLogger(final Logger logger) {
    081            // in order to prevent non-bridged loggers from being registered, we always return false to indicate that
    082            // the named logger should be obtained through getLogger(name)
    083            return false;
    084        }
    085
    086        @Override
    087        public Logger getLogger(final String name) {
    088            LOGGER.trace("Call to LogManager.getLogger({})", name);
    089            return loggerAdapter.getLogger(name);
    090        }
    091
    092        @Override
    093        public Enumeration<String> getLoggerNames() {
    094            return Collections.enumeration(loggerAdapter.getLoggersInContext(loggerAdapter.getContext()).keySet());
    095        }
    096
    097    }