Package osgi.logger.provider

Source Code of osgi.logger.provider.LoggerAdminImpl

package osgi.logger.provider;

import java.io.PrintStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;

import org.osgi.framework.BundleContext;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.service.log.LogService;

import osgi.enroute.debug.api.Debug;
import osgi.enroute.logger.api.Level;
import osgi.enroute.logger.api.LoggerAdmin;
import osgi.logger.provider.LoggerDispatcher.Eval;
import aQute.bnd.annotation.component.Activate;
import aQute.bnd.annotation.component.Component;
import aQute.bnd.annotation.component.ConfigurationPolicy;
import aQute.bnd.annotation.component.Deactivate;
import aQute.bnd.annotation.component.Reference;
import aQute.bnd.annotation.metatype.Configurable;
import aQute.libg.glob.Glob;

/**
* This is the Logger Admin component. It registers a {@link LoggerAdmin}
* service.
*/
@Component(
    immediate = true,
    servicefactory = false,
    designate = Configuration.class,
    provide = LoggerAdmin.class,
    configurationPolicy = ConfigurationPolicy.optional,
    properties = {
        Debug.COMMAND_SCOPE + "=logger", Debug.COMMAND_FUNCTION + "=add|remove|settings"
    })
public class LoggerAdminImpl extends Thread implements LoggerAdmin, Eval {

  final static int              LOG_TRACE    = LogService.LOG_DEBUG + 1;

  boolean                    traces;
  PrintStream                  out        = System.err;
  final List<ServiceReference<LogService>>  logReferences  = new CopyOnWriteArrayList<>();
  final List<LogService>            logs      = new CopyOnWriteArrayList<>();
  final Map<Pattern,Control>          controls    = new ConcurrentHashMap<>();
  Control                    control      = new Control();
  Settings                  settings    = new Settings();
  JavaUtilLoggingHandler            javaUtilLogging;
  final CountDownLatch            latch      = new CountDownLatch(1);

  public LoggerAdminImpl() {
    super("OSGi :: Logger Admin");
    setDaemon(true);
  }

  /*
   * Activate the component
   */
  @Activate
  public void activate(Map<String,Object> config) throws Exception {
    assert config != null;

    Configuration c = Configurable.createConfigurable(Configuration.class, config);

    //
    // Check if we need java util logging
    //

    if (c.javaUtilLogging()) {
      java.util.logging.Logger.getLogger("").addHandler(javaUtilLogging = new JavaUtilLoggingHandler());
    }

    control.level = c.level() == null ? Level.WARN : c.level();
    control.thread = null;
    control.pattern = null;
    control.stackTraces = c.traces();
    control.where = c.where();

    //
    // Make us the admin ...
    //
    assert LoggerDispatcher.dispatcher.admin == null;

    LoggerDispatcher.dispatcher.admin = this;

    this.setPriority(Thread.MIN_PRIORITY);

    start();
  }

  @Deactivate
  public void deactivate() throws Exception {
    if (javaUtilLogging != null) {
      java.util.logging.Logger.getLogger("").removeHandler(javaUtilLogging);
    }
    //
    // Stop our thread
    //
    interrupt();
  }

  /*
   * This is the queue flusher. We read from the queue and send it to the OSGi
   * Log Services registered. We quit this method when we get an interrupt.
   */
  public void run() {
    try {
      LoggerDispatcher.dispatcher.evaluate(this);

      //
      // Poll the queue until we get an interrupt
      //

      while (!isInterrupted())
        try {

          //
          // We wait util we get at least 1 log service. In the mean
          // time we buffer the messages anyway. This is one time
          // only.
          //

          latch.await(10, TimeUnit.SECONDS);

          Entry take = LoggerDispatcher.dispatcher.queue.take();

          //
          // If there are no log services we print to the
          // console
          //

          List<LogService> logs = getLogs(take);
          if (logs.isEmpty()) {
            System.err.println(take);
            continue;
          }

          //
          // We push to all log services registered since the deployer
          // can always set the x.target property to limit the
          // applicable log services
          //

          for (LogService log : logs) {

            try {

              int n = take.exception == null ? 0 : 1;
              n += take.reference == null ? 0 : 2;

              switch (n) {
                case 0 :
                  log.log(take.level, take.message);
                  break;

                case 1 :
                  log.log(take.level, take.message, take.exception);
                  break;

                case 2 :
                  log.log(take.reference, take.level, take.message);
                  break;

                case 3 :
                  log.log(take.reference, take.level, take.message, take.exception);
                  break;
              }

            }
            catch (Exception e) {
              //
              // Hmm, not much we can do here ...
              // Since we're the logging subsystem
              //
              e.printStackTrace();
            }
          }
        }
        catch (InterruptedException e) {
          interrupt();
          return;
        }
    }
    catch (Exception e) {
      //
      // Hmm, not much we can do here ...
      //
      e.printStackTrace();
    }
    finally {}
  }

  private List<LogService> getLogs(Entry take) throws InvalidSyntaxException {
    if (take.source == null)
      return logs;

    List<LogService> logs = new ArrayList<>();
    BundleContext ctx = take.source.getBundleContext();
    if ( ctx == null)
      return this.logs;
   
    for (ServiceReference<LogService> ref : ctx.getServiceReferences(LogService.class, null)) {
      LogService service = ctx.getService(ref);
      if (service != null)
        logs.add(service);
    }
    return logs;
  }

  /*
   * We're an Eval, so we can iterate over the registered loggers. The default
   * we supply is to reset the loggers so they have to refetch their
   * configurations.
   */
  public void eval(AbstractLogger msf) {
    msf.reset();
  }

  /*
   * Called by an Abstract Logger when it is initing.
   */
  Control getControl(String identifier) {
    for (java.util.Map.Entry<Pattern,Control> p : controls.entrySet()) {
      if (p.getKey().matcher(identifier).matches())
        return p.getValue();
    }
    return control;
  }

  /*
   * List the information about the selected loggers (known to the system).
   */
  @Override
  public List<Info> list(String glob) throws Exception {
    final List<Info> infos = new ArrayList<>();
    final Pattern p = glob == null ? null : Glob.toPattern(glob);
    ;

    LoggerDispatcher.dispatcher.evaluate(new Eval() {

      @Override
      public void eval(AbstractLogger msf) {
        if (p == null || p.matcher(msf.name).find()) {
          Info info = new Info();
          info.bundleId = msf.bundle.getBundleId();
          info.level = msf.level;
          info.name = msf.name;
          infos.add(info);
        }
      }
    });
    return infos;
  }

  /*
   * Get the current settings
   */
  @Override
  public Settings getSettings() throws Exception {
    return settings;
  }

  /*
   * Set the current settings and update the current loggers
   */
  @Override
  public void setSettings(Settings settings) throws Exception {
    Map<Pattern,Control> controls = new HashMap<>();

    for (Control c : settings.controls) {
      try {
        Pattern p = Glob.toPattern(c.pattern);
        controls.put(p, c);
      }
      catch (Exception ee) {
        error("Invalid filter " + c.pattern, ee);
        return;
      }
    }
    synchronized (this.controls) {
      this.controls.clear();
      this.controls.putAll(controls);
    }
    LoggerDispatcher.dispatcher.evaluate(this);
    if (javaUtilLogging != null) {
      javaUtilLogging.update(controls);
    }
  }

  private void error(String string, Exception ee) {
    System.err.println(string);
  }

  /**
   * Shell command to add a new setting
   *
   * @param pattern
   *            the pattern to add
   * @param level
   *            the level to report on
   * @param options
   *            set of options: stacktrace, where
   * @return the Control added
   */
  public Control add(Glob pattern, Level level, String... options) throws Exception {
    Settings settings = getSettings();
    Control control = new Control();
    control.level = level;
    control.pattern = pattern.toString();
    for (String option : options) {
      switch (option) {
        case "stacktrace" :
          control.stackTraces = true;
          break;

        case "where" :
          control.where = true;
          break;

        default :
          System.err.println("Unknown option " + option);
          break;
      }
    }
    settings.controls.add(control);
    setSettings(settings);
    return control;
  }

  /**
   * Shell command to remove a control
   *
   * @param pattern
   *            the pattern to remove (will remove all controls with that
   *            exact pattern)
   * @return the controls removed
   */
  public List<Control> remove(Glob pattern) throws Exception {
    Settings settings = getSettings();
    List<Control> deleted = new ArrayList<>();

    for (Iterator<Control> i = settings.controls.iterator(); i.hasNext();) {
      Control c = i.next();
      if (c.pattern.equals(pattern.toString())) {
        i.remove();
        deleted.add(c);
      }
    }
    setSettings(settings);
    return deleted;
  }

  /*
   * Get the log services
   */
  @Reference(type = '*', service = LogService.class)
  void addLog(ServiceReference<LogService> log) {
    latch.countDown();
    logReferences.add(log);
  }

  /*
   * Remove the log services
   */
  void removeLog(ServiceReference<LogService> log) {
    logReferences.remove(log);
  }

  /*
   * Get the log services
   */
  @Reference(type = '*')
  void addLogService(LogService log) {
    latch.countDown();
    logs.add(log);
  }

  /*
   * Remove the log services
   */
  void removeLogService(LogService log) {
    logs.remove(log);
  }
}
TOP

Related Classes of osgi.logger.provider.LoggerAdminImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.