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.core.impl;
018    
019    import java.net.URI;
020    
021    import org.apache.logging.log4j.core.LoggerContext;
022    import org.apache.logging.log4j.core.helpers.Constants;
023    import org.apache.logging.log4j.core.helpers.Loader;
024    import org.apache.logging.log4j.core.jmx.Server;
025    import org.apache.logging.log4j.core.selector.ClassLoaderContextSelector;
026    import org.apache.logging.log4j.core.selector.ContextSelector;
027    import org.apache.logging.log4j.spi.LoggerContextFactory;
028    import org.apache.logging.log4j.status.StatusLogger;
029    import org.apache.logging.log4j.util.PropertiesUtil;
030    
031    /**
032     * Factory to locate a ContextSelector and then load a LoggerContext.
033     */
034    public class Log4jContextFactory implements LoggerContextFactory {
035    
036        private static final StatusLogger LOGGER = StatusLogger.getLogger();
037    
038        private ContextSelector selector;
039    
040        /**
041         * Constructor that initializes the ContextSelector.
042         */
043        public Log4jContextFactory() {
044            final String sel = PropertiesUtil.getProperties().getStringProperty(Constants.LOG4J_CONTEXT_SELECTOR);
045            if (sel != null) {
046                try {
047                    final Class<?> clazz = Loader.loadClass(sel);
048                    if (clazz != null && ContextSelector.class.isAssignableFrom(clazz)) {
049                        selector = (ContextSelector) clazz.newInstance();
050                    }
051                } catch (final Exception ex) {
052                    LOGGER.error("Unable to create context " + sel, ex);
053                }
054            }
055            if (selector == null) {
056                selector = new ClassLoaderContextSelector();
057            }
058            try {
059                Server.registerMBeans(selector);
060            } catch (Exception ex) {
061                LOGGER.error("Could not start JMX", ex);
062            }
063        }
064    
065        /**
066         * Returns the ContextSelector.
067         * @return The ContextSelector.
068         */
069        public ContextSelector getSelector() {
070            return selector;
071        }
072    
073        /**
074         * Load the LoggerContext using the ContextSelector.
075         * @param fqcn The fully qualified class name of the caller.
076         * @param loader The ClassLoader to use or null.
077         * @param currentContext If true returns the current Context, if false returns the Context appropriate
078         * for the caller if a more appropriate Context can be determined.
079         * @return The LoggerContext.
080         */
081        public LoggerContext getContext(final String fqcn, final ClassLoader loader, final boolean currentContext) {
082            final LoggerContext ctx = selector.getContext(fqcn, loader, currentContext);
083            if (ctx.getStatus() == LoggerContext.Status.INITIALIZED) {
084                ctx.start();
085            }
086            return ctx;
087        }
088    
089        /**
090         * Load the LoggerContext using the ContextSelector.
091         * @param fqcn The fully qualified class name of the caller.
092         * @param loader The ClassLoader to use or null.
093         * @param currentContext If true returns the current Context, if false returns the Context appropriate
094         * for the caller if a more appropriate Context can be determined.
095         * @param configLocation The location of the configuration for the LoggerContext.
096         * @return The LoggerContext.
097         */
098        public LoggerContext getContext(final String fqcn, final ClassLoader loader, final boolean currentContext,
099                URI configLocation) {
100            final LoggerContext ctx = selector.getContext(fqcn, loader, currentContext, configLocation);
101            if (ctx.getStatus() == LoggerContext.Status.INITIALIZED) {
102                ctx.start();
103            }
104            return ctx;
105        }
106    }