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    
018    package org.apache.logging.log4j.core.config.plugins.osgi;
019    
020    import org.apache.logging.log4j.LogManager;
021    import org.apache.logging.log4j.Logger;
022    import org.apache.logging.log4j.core.config.plugins.util.PluginManager;
023    import org.apache.logging.log4j.core.impl.Log4jContextFactory;
024    import org.apache.logging.log4j.core.util.BundleResourceLoader;
025    import org.apache.logging.log4j.simple.SimpleLoggerContextFactory;
026    import org.apache.logging.log4j.spi.LoggerContextFactory;
027    import org.apache.logging.log4j.status.StatusLogger;
028    import org.osgi.framework.Bundle;
029    import org.osgi.framework.BundleContext;
030    import org.osgi.framework.BundleEvent;
031    import org.osgi.framework.BundleListener;
032    
033    /**
034     * OSGi BundleActivator.
035     */
036    public final class Activator implements org.osgi.framework.BundleActivator {
037    
038        private static final Logger LOGGER = StatusLogger.getLogger();
039    
040        @Override
041        public void start(final BundleContext context) throws Exception {
042            registerLoggerContextFactory();
043            context.addBundleListener(new Listener());
044            // done after the BundleListener as to not miss any new bundle installs in the interim
045            scanInstalledBundlesForPlugins(context);
046        }
047    
048        private void registerLoggerContextFactory() {
049            final LoggerContextFactory current = LogManager.getFactory();
050            if (!(current instanceof Log4jContextFactory)) {
051                LOGGER.debug("Replacing LogManager LoggerContextFactory.");
052                LogManager.setFactory(new Log4jContextFactory());
053            }
054        }
055    
056        private void scanInstalledBundlesForPlugins(final BundleContext context) {
057            final Bundle[] bundles = context.getBundles();
058            for (final Bundle bundle : bundles) {
059                if (bundle.getState() == Bundle.ACTIVE) {
060                    // TODO: bundle state can change during this
061                    scanBundleForPlugins(bundle);
062                }
063            }
064        }
065    
066        private static void scanBundleForPlugins(final Bundle bundle) {
067            LOGGER.debug("Scanning bundle [{}] for plugins.", bundle.getSymbolicName());
068            PluginManager.loadPlugins(new BundleResourceLoader(bundle));
069        }
070    
071        @Override
072        public void stop(final BundleContext context) throws Exception {
073            unregisterLoggerContextFactory();
074        }
075    
076        private void unregisterLoggerContextFactory() {
077            LogManager.setFactory(new SimpleLoggerContextFactory());
078        }
079    
080        private static class Listener implements BundleListener {
081    
082            @Override
083            public void bundleChanged(final BundleEvent event) {
084                switch (event.getType()) {
085                    case BundleEvent.STARTED:
086                        scanBundleForPlugins(event.getBundle());
087                        break;
088    
089                    default:
090                        break;
091                }
092            }
093        }
094    }