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 }