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        @Override
082        public LoggerContext getContext(final String fqcn, final ClassLoader loader, final boolean currentContext) {
083            final LoggerContext ctx = selector.getContext(fqcn, loader, currentContext);
084            if (ctx.getStatus() == LoggerContext.Status.INITIALIZED) {
085                ctx.start();
086            }
087            return ctx;
088        }
089    
090        /**
091         * Load the LoggerContext using the ContextSelector.
092         * @param fqcn The fully qualified class name of the caller.
093         * @param loader The ClassLoader to use or null.
094         * @param currentContext If true returns the current Context, if false returns the Context appropriate
095         * for the caller if a more appropriate Context can be determined.
096         * @param configLocation The location of the configuration for the LoggerContext.
097         * @return The LoggerContext.
098         */
099        @Override
100        public LoggerContext getContext(final String fqcn, final ClassLoader loader, final boolean currentContext,
101                URI configLocation) {
102            final LoggerContext ctx = selector.getContext(fqcn, loader, currentContext, configLocation);
103            if (ctx.getStatus() == LoggerContext.Status.INITIALIZED) {
104                ctx.start();
105            }
106            return ctx;
107        }
108    
109    
110        /**
111         * Removes knowledge of a LoggerContext.
112         * 
113         * @param context The context to remove.
114         */
115        @Override
116        public void removeContext(org.apache.logging.log4j.spi.LoggerContext context) {
117            if (context instanceof LoggerContext) {
118                selector.removeContext((LoggerContext) context);
119            }
120        }
121    }