View Javadoc

    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements. See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License. You may obtain a copy of the License at
    8    *
    9    *      http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17
    18  package org.apache.logging.log4j.core.osgi;
    19
    20  import java.util.concurrent.atomic.AtomicReference;
    21
    22  import org.apache.logging.log4j.Logger;
    23  import org.apache.logging.log4j.core.config.plugins.util.PluginRegistry;
    24  import org.apache.logging.log4j.core.util.Constants;
    25  import org.apache.logging.log4j.status.StatusLogger;
    26  import org.apache.logging.log4j.util.PropertiesUtil;
    27  import org.osgi.framework.Bundle;
    28  import org.osgi.framework.BundleActivator;
    29  import org.osgi.framework.BundleContext;
    30  import org.osgi.framework.BundleEvent;
    31  import org.osgi.framework.SynchronousBundleListener;
    32  import org.osgi.framework.wiring.BundleWiring;
    33
    34  /**
    35   * OSGi BundleActivator.
    36   */
    37  public final class Activator implements BundleActivator, SynchronousBundleListener {
    38
    39      private static final Logger LOGGER = StatusLogger.getLogger();
    40
    41      private final AtomicReference<BundleContext> context = new AtomicReference<BundleContext>();
    42
    43      @Override
    44      public void start(final BundleContext context) throws Exception {
    45          // allow the user to override the default ContextSelector (e.g., by using BasicContextSelector for a global cfg)
    46          if (PropertiesUtil.getProperties().getStringProperty(Constants.LOG4J_CONTEXT_SELECTOR) == null) {
    47              System.setProperty(Constants.LOG4J_CONTEXT_SELECTOR, BundleContextSelector.class.getName());
    48          }
    49          if (this.context.compareAndSet(null, context)) {
    50              context.addBundleListener(this);
    51              // done after the BundleListener as to not miss any new bundle installs in the interim
    52              scanInstalledBundlesForPlugins(context);
    53          }
    54      }
    55
    56      private static void scanInstalledBundlesForPlugins(final BundleContext context) {
    57          final Bundle[] bundles = context.getBundles();
    58          for (final Bundle bundle : bundles) {
    59              if (bundle.getState() == Bundle.ACTIVE) {
    60                  // TODO: bundle state can change during this
    61                  scanBundleForPlugins(bundle);
    62              }
    63          }
    64      }
    65
    66      private static void scanBundleForPlugins(final Bundle bundle) {
    67          LOGGER.trace("Scanning bundle [{}] for plugins.", bundle.getSymbolicName());
    68          PluginRegistry.getInstance().loadFromBundle(bundle.getBundleId(),
    69              bundle.adapt(BundleWiring.class).getClassLoader());
    70      }
    71
    72      private static void stopBundlePlugins(final Bundle bundle) {
    73          LOGGER.trace("Stopping bundle [{}] plugins.", bundle.getSymbolicName());
    74          // TODO: plugin lifecycle code
    75          PluginRegistry.getInstance().clearBundlePlugins(bundle.getBundleId());
    76      }
    77
    78      @Override
    79      public void stop(final BundleContext context) throws Exception {
    80          // not much can be done that isn't already automated by the framework
    81          this.context.compareAndSet(context, null);
    82          // TODO: shut down log4j
    83      }
    84
    85      @Override
    86      public void bundleChanged(final BundleEvent event) {
    87          switch (event.getType()) {
    88              // FIXME: STARTING instead of STARTED?
    89              case BundleEvent.STARTED:
    90                  scanBundleForPlugins(event.getBundle());
    91                  break;
    92
    93              case BundleEvent.STOPPING:
    94                  stopBundlePlugins(event.getBundle());
    95                  break;
    96
    97              default:
    98                  break;
    99          }
    100     }
    101 }