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        @SuppressWarnings("unchecked")
087        public Class<? extends LoggerContextFactory> loadLoggerContextFactory() {
088            if (className == null) {
089                return null;
090            }
091            try {
092                final Class<?> clazz = classLoader.loadClass(className);
093                if (LoggerContextFactory.class.isAssignableFrom(clazz)) {
094                    return (Class<? extends LoggerContextFactory>) clazz;
095                }
096            } catch (final Exception e) {
097                LOGGER.error("Unable to create class {} specified in {}", className, url.toString(), e);
098            }
099            return null;
100        }
101    
102        /**
103         * Gets the class name of the {@link org.apache.logging.log4j.spi.ThreadContextMap} implementation of this
104         * Provider.
105         *
106         * @return the class name of a ThreadContextMap implementation
107         */
108        public String getThreadContextMap() {
109            return threadContextMap;
110        }
111    
112        /**
113         * Loads the {@link org.apache.logging.log4j.spi.ThreadContextMap} class specified by this Provider.
114         *
115         * @return the ThreadContextMap implementation class or {@code null} if there was an error loading it
116         */
117        @SuppressWarnings("unchecked")
118        public Class<? extends ThreadContextMap> loadThreadContextMap() {
119            if (threadContextMap == null) {
120                return null;
121            }
122            try {
123                final Class<?> clazz = classLoader.loadClass(threadContextMap);
124                if (ThreadContextMap.class.isAssignableFrom(clazz)) {
125                    return (Class<? extends ThreadContextMap>) clazz;
126                }
127            } catch (final Exception e) {
128                LOGGER.error("Unable to create class {} specified in {}", threadContextMap, url.toString(), e);
129            }
130            return null;
131        }
132    
133        /**
134         * Gets the URL containing this Provider's Log4j details.
135         *
136         * @return the URL corresponding to the Provider {@code META-INF/log4j-provider.properties} file
137         */
138        public URL getUrl() {
139            return url;
140        }
141    }