    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.spi;
    018
    019    import java.net.URL;
    020    import java.util.Properties;
    021
    022    import org.apache.logging.log4j.Logger;
    023    import org.apache.logging.log4j.status.StatusLogger;
    024
    025    /**
    026     * Model class for a Log4j 2 provider. The properties in this class correspond to the properties used in a
    027     * {@code META-INF/log4j-provider.properties} file. Note that this class is automatically created by Log4j and should
    028     * not be used by providers.
    029     */
    030    public class Provider {
    031        private static final Integer DEFAULT_PRIORITY = Integer.valueOf(-1);
    032        /**
    033         * Property name to set for a Log4j 2 provider to specify the priority of this implementation.
    034         */
    035        public static final String FACTORY_PRIORITY = "FactoryPriority";
    036        /**
    037         * Property name to set to the implementation of {@link org.apache.logging.log4j.spi.ThreadContextMap}.
    038         */
    039        public static final String THREAD_CONTEXT_MAP = "ThreadContextMap";
    040        /**
    041         * Property name to set to the implementation of {@link org.apache.logging.log4j.spi.LoggerContextFactory}.
    042         */
    043        public static final String LOGGER_CONTEXT_FACTORY = "LoggerContextFactory";
    044
    045        private static final Logger LOGGER = StatusLogger.getLogger();
    046
    047        private final Integer priority;
    048        private final String className;
    049        private final String threadContextMap;
    050        private final URL url;
    051        private final ClassLoader classLoader;
    052
    053        public Provider(final Properties props, final URL url, final ClassLoader classLoader) {
    054            this.url = url;
    055            this.classLoader = classLoader;
    056            final String weight = props.getProperty(FACTORY_PRIORITY);
    057            priority = weight == null ? DEFAULT_PRIORITY : Integer.valueOf(weight);
    058            className = props.getProperty(LOGGER_CONTEXT_FACTORY);
    059            threadContextMap = props.getProperty(THREAD_CONTEXT_MAP);
    060        }
    061
    062        /**
    063         * Gets the priority (natural ordering) of this Provider.
    064         *
    065         * @return the priority of this Provider
    066         */
    067        public Integer getPriority() {
    068            return priority;
    069        }
    070
    071        /**
    072         * Gets the class name of the {@link org.apache.logging.log4j.spi.LoggerContextFactory} implementation of this
    073         * Provider.
    074         *
    075         * @return the class name of a LoggerContextFactory implementation
    076         */
    077        public String getClassName() {
    078            return className;
    079        }
    080
    081        /**
    082         * Loads the {@link org.apache.logging.log4j.spi.LoggerContextFactory} class specified by this Provider.
    083         *
    084         * @return the LoggerContextFactory implementation class or {@code null} if there was an error loading it
    085         */
    086        public Class<? extends LoggerContextFactory> loadLoggerContextFactory() {
    087            if (className == null) {
    088                return null;
    089            }
    090            try {
    091                final Class<?> clazz = classLoader.loadClass(className);
    092                if (LoggerContextFactory.class.isAssignableFrom(clazz)) {
    093                    return clazz.asSubclass(LoggerContextFactory.class);
    094                }
    095            } catch (final Exception e) {
    096                LOGGER.error("Unable to create class {} specified in {}", className, url.toString(), e);
    097            }
    098            return null;
    099        }
    100
    101        /**
    102         * Gets the class name of the {@link org.apache.logging.log4j.spi.ThreadContextMap} implementation of this
    103         * Provider.
    104         *
    105         * @return the class name of a ThreadContextMap implementation
    106         */
    107        public String getThreadContextMap() {
    108            return threadContextMap;
    109        }
    110
    111        /**
    112         * Loads the {@link org.apache.logging.log4j.spi.ThreadContextMap} class specified by this Provider.
    113         *
    114         * @return the ThreadContextMap implementation class or {@code null} if there was an error loading it
    115         */
    116        public Class<? extends ThreadContextMap> loadThreadContextMap() {
    117            if (threadContextMap == null) {
    118                return null;
    119            }
    120            try {
    121                final Class<?> clazz = classLoader.loadClass(threadContextMap);
    122                if (ThreadContextMap.class.isAssignableFrom(clazz)) {
    123                    return clazz.asSubclass(ThreadContextMap.class);
    124                }
    125            } catch (final Exception e) {
    126                LOGGER.error("Unable to create class {} specified in {}", threadContextMap, url.toString(), e);
    127            }
    128            return null;
    129        }
    130
    131        /**
    132         * Gets the URL containing this Provider's Log4j details.
    133         *
    134         * @return the URL corresponding to the Provider {@code META-INF/log4j-provider.properties} file
    135         */
    136        public URL getUrl() {
    137            return url;
    138        }
    139    }