Package osgi.logger.provider

Source Code of osgi.logger.provider.AbstractLogger

package osgi.logger.provider;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import java.lang.reflect.Array;
import java.util.Formatter;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.osgi.framework.Bundle;
import org.osgi.framework.ServiceReference;
import org.osgi.service.log.LogService;
import org.slf4j.Marker;

import osgi.enroute.logger.api.Level;
import osgi.enroute.logger.api.LoggerAdmin.Control;

/**
* This is the base class for the class that must log information. It fully
* implements the slf4j Logger class and maps them to an {@link Entry} record
* which is then queued via the static (yuck) dispatcher.
*/
class AbstractLogger implements org.slf4j.Logger {

  /*
   * A pattern to discard classes in a stacktrace that we do not want to see
   */
  // final static Pattern CUSTOM_CLASSES = Pattern
  // .compile("(?!com\\.sun|sun|java\\.|osgi\\.enroute\\.logger\\.provider)(.+\\.)+(.*)");

  String        name;
  Bundle        bundle;

  volatile boolean  info;
  volatile boolean  trace;
  volatile boolean  debug;
  volatile boolean  warn;
  volatile boolean  error;
  volatile boolean  exceptions;
  volatile boolean  where;

  boolean        init;
  boolean        registered;
  Level        level;

  AbstractLogger(Bundle bundle, String name) {
    this.bundle = bundle;
    this.name = name;
    reset();
  }

  AbstractLogger() {
    reset();
  }

  /*
   * The init method is checked when a flag is set to true (done in reset()).
   * The init method will set all flags correctly based on defaults, or, if
   * there is a admin, from the settings in the admin. The init method returns
   * true if the given level must be logged. I think this is the fastest
   * possible way when you're not using a level. I.e. initially trace is set
   * to true. At the first trace, init(TRACE) is called but this in general
   * will set the trace flag to false. So the second time only the trace flag
   * is checked. In general, extra work is only done when we actually are
   * going to log a message.
   */
  private synchronized boolean init(Level level) {
    if (init)
      return true;

    init = true;

    //
    // We need to register once with the LoggerDispatcher
    // so the admin can reset us when there are new settings
    //

    if (!registered) {
      LoggerDispatcher.dispatcher.register(this);
      registered = true;
    }

    LoggerAdminImpl admin = LoggerDispatcher.dispatcher.admin;

    if (admin != null) {
      //
      // We have an admin. So we actually get our settins
      // from this admin.
      //
      Control control = admin.getControl(this.name);
      debug = control.level.ordinal() <= Level.DEBUG.ordinal();
      info = control.level.ordinal() <= Level.INFO.ordinal();
      trace = control.level.ordinal() <= Level.TRACE.ordinal();
      warn = control.level.ordinal() <= Level.WARN.ordinal();
      error = control.level.ordinal() <= Level.ERROR.ordinal();
      level = control.level;
    } else {
      //
      // Default Defaults if no admin present. There is a bit of a race
      // condition since at this admin could have become active and reset
      // us
      // However, this is pretty rare and should be corrected on the next
      // call
      //
      debug = false;
      info = false;
      trace = false;
      warn = true;
      error = true;
    }

    return isLevel(level);
  }

  /*
   * Next time this logger is used it will try to get its configuration again
   */
  synchronized void reset() {
    init = false;
    debug = true;
    info = true;
    trace = true;
    warn = true;
    error = true;
  }

  /*
   * Check if this level is set
   */
  private boolean isLevel(Level level) {
    switch (level) {
      case DEBUG :
        return debug;
      case ERROR :
        return error;
      case INFO :
        return info;

      case TRACE :
        return trace;
      case WARN :
        return warn;

      case R1 :
      case R2 :
      case R3 :
      case AUDIT :
      default :
        return true;

    }
  }

  /*
   * Return the name
   */
  @Override
  public String getName() {
    return name;
  }

  /*
   * The core routine. We've committed to logging so now we have to create a
   * logging message.
   */
  void message(int level, String format, Object... arguments) {
    try {
      //
      // Log4j is using {} as the %s ... :-(
      // so we replace it with the %s
      // TODO figure out markers
      //
      if (format.indexOf('{') >= 0) {
        format = format.replaceAll("\\{\\}", "%s");
      }

      //
      // We will log an entry to the queue
      //
      Entry entry = new Entry();
      entry.level = level;

      //
      // Adjust the arguments since arrays print badly and we can do
      // better for some other objects as well.
      //

      for (int i = 0; i < arguments.length; i++)
        if (arguments[i] != null) {

          if (entry.reference == null && arguments[i] instanceof ServiceReference< ? >) {
            entry.reference = (ServiceReference< ? >) arguments[i];
          } else if (entry.exception == null && arguments[i] instanceof Throwable) {
            entry.exception = (Throwable) arguments[i];
          } else if (!(arguments[i] instanceof String))
            arguments[i] = toString(arguments[i]);
        }

      //
      // Add a few more places so that errors in the format would refer to
      // non-existent args. Logging should not throw exceptions.
      //

      Object nargs[] = new Object[arguments.length + 10];
      System.arraycopy(arguments, 0, nargs, 0, arguments.length);

      final StringBuilder sb = new StringBuilder();
      try (Formatter formatter = new Formatter(sb)) {

        if (name != null) {
          sb.append(name).append(" :: ");
        }

        if (where) {
          where(sb, 4);
        }

        formatter.format(format, nargs);
        if (entry.exception != null && exceptions) {
          sb.append("\n");
          try (PrintWriter sw = getWriter(sb)) {
            entry.exception.printStackTrace(sw);
          }
        }
      }

      entry.message = sb.toString();
      entry.source = bundle;

      //
      // We will not block on the queue. So we attempt to put it in the
      // queue and if we do not succeed, print it to std err.
      //
      if (!LoggerDispatcher.dispatcher.queue.offer(entry)) {
        System.err.println("Overflowing log queue " + entry);
      }
    }
    catch (Exception e) {
      System.err.println("Shamefully have to admit the log service failed :-(" + e);
      e.printStackTrace();
    }
  }

  private PrintWriter getWriter(final StringBuilder sb) {
    return new PrintWriter(new Writer() {

      @Override
      public void write(char[] cbuf, int off, int len) throws IOException {
        for (int i = 0; i < len; i++)
          sb.append(cbuf[i + off]);
      }

      @Override
      public void flush() throws IOException {}

      @Override
      public void close() throws IOException {}

    });
  }

  /*
   * Create a more suitable text presentation for array objects
   * @param object
   * @return
   */
  private String toString(Object object) {
    if (object == null)
      return "null";

    if (object.getClass().isArray()) {
      StringBuilder sb = new StringBuilder();
      String del = "[";
      for (int i = 0; i < Array.getLength(object); i++) {
        sb.append(del).append(toString(Array.get(object, i)));
        del = ", ";
      }
      sb.append("]");
      return sb.toString();
    }
    return object.toString();
  }

  /*
   * Get the current location of where the error was reported.
   */
  protected void where(StringBuilder sb, int max) {
    try {
      throw new Exception();
    }
    catch (Exception e) {
      StackTraceElement[] stackTrace = e.getStackTrace();
      int n = 0;
      for (int i = 2; i < sb.length(); i++) {
        Matcher matcher = Pattern.compile(".*").matcher(stackTrace[i].getClassName());

        if (matcher.matches()) {
          String logMethod = stackTrace[i].getMethodName();
          String logClass = matcher.group(2);
          int line = stackTrace[i].getLineNumber();
          sb.append("[").append(logClass).append(".").append(logMethod);
          if (line != 0)
            sb.append(":").append(line);
          sb.append("] ");
          n++;
          if (n >= max)
            return;
        }
      }
    }
  }

  /**************************************************************************************************************/

  // The rest is the SLF4J dump ... what backward compatibility does to you
  // ... :-(

  @Override
  public void info(String format, Object... arguments) {
    if (info && init(Level.INFO))
      message(LogService.LOG_INFO, format, arguments);
  }

  @Override
  public void debug(String format, Object... arguments) {
    if (debug && init(Level.DEBUG))
      message(LogService.LOG_DEBUG, format, arguments);
  }

  @Override
  public void error(String format, Object... arguments) {
    if (error && init(Level.ERROR))
      message(LogService.LOG_ERROR, format, arguments);
  }

  @Override
  public void trace(String format, Object... arguments) {
    if (trace && init(Level.TRACE))
      message(LoggerAdminImpl.LOG_TRACE, format, arguments);
  }

  @Override
  public void warn(String format, Object... arguments) {
    if (warn && init(Level.WARN))
      message(LogService.LOG_WARNING, format, arguments);
  }

  @Override
  public boolean isInfoEnabled() {
    return info && init(Level.INFO);
  }

  @Override
  public boolean isDebugEnabled() {
    return debug && init(Level.DEBUG);
  }

  @Override
  public boolean isErrorEnabled() {
    return error && init(Level.ERROR);
  }

  @Override
  public boolean isTraceEnabled() {
    return trace && init(Level.TRACE);
  }

  @Override
  public boolean isWarnEnabled() {
    return warn && init(Level.WARN);
  }

  public void close() {
    LoggerDispatcher.dispatcher.unregister(this);
    init = registered = info = trace = error = warn = debug = false;
  }

  @Override
  public void debug(String string) {
    if (debug && init(Level.DEBUG))
      message(LogService.LOG_DEBUG, string);
  }

  @Override
  public void debug(String format, Object arguments) {
    if (debug && init(Level.DEBUG))
      message(LogService.LOG_DEBUG, format, arguments);
  }

  @Override
  public void debug(String string, Throwable t) {
    if (debug && init(Level.DEBUG))
      message(LogService.LOG_DEBUG, string, t);
  }

  @Override
  public void debug(Marker marker, String string) {
    if (debug && init(Level.DEBUG))
      message(LogService.LOG_DEBUG, string, marker);
  }

  @Override
  public void debug(String format, Object a, Object b) {
    if (debug && init(Level.DEBUG))
      message(LogService.LOG_DEBUG, format, a, b);
  }

  @Override
  public void debug(Marker marker, String format, Object a) {
    if (debug && init(Level.DEBUG))
      message(LogService.LOG_DEBUG, format, a, marker);
  }

  @Override
  public void debug(Marker marker, String format, Object... args) {
    if (debug && init(Level.DEBUG))
      message(LogService.LOG_DEBUG, format, args);
  }

  @Override
  public void debug(Marker marker, String format, Throwable t) {
    if (debug && init(Level.DEBUG))
      message(LogService.LOG_DEBUG, format, t);
  }

  @Override
  public void debug(Marker marker, String format, Object a, Object b) {
    if (debug && init(Level.DEBUG))
      message(LogService.LOG_DEBUG, format, a, b);
  }

  @Override
  public void error(String string) {
    if (error && init(Level.ERROR))
      message(LogService.LOG_ERROR, string);
  }

  @Override
  public void error(String format, Object arguments) {
    if (error && init(Level.ERROR))
      message(LogService.LOG_ERROR, format, arguments);
  }

  @Override
  public void error(String string, Throwable t) {
    if (error && init(Level.ERROR))
      message(LogService.LOG_ERROR, string, t);
  }

  @Override
  public void error(Marker marker, String string) {
    if (error && init(Level.ERROR))
      message(LogService.LOG_ERROR, string, marker);
  }

  @Override
  public void error(String format, Object a, Object b) {
    if (error && init(Level.ERROR))
      message(LogService.LOG_ERROR, format, a, b);
  }

  @Override
  public void error(Marker marker, String format, Object a) {
    if (error && init(Level.ERROR))
      message(LogService.LOG_ERROR, format, a, marker);
  }

  @Override
  public void error(Marker marker, String format, Object... args) {
    if (error && init(Level.ERROR))
      message(LogService.LOG_ERROR, format, args);
  }

  @Override
  public void error(Marker marker, String format, Throwable t) {
    if (error && init(Level.ERROR))
      message(LogService.LOG_ERROR, format, t);
  }

  @Override
  public void error(Marker marker, String format, Object a, Object b) {
    if (error && init(Level.ERROR))
      message(LogService.LOG_ERROR, format, a, b);
  }

  @Override
  public void info(String string) {
    if (info && init(Level.INFO))
      message(LogService.LOG_INFO, string);
  }

  @Override
  public void info(String format, Object arguments) {
    if (info && init(Level.INFO))
      message(LogService.LOG_INFO, format, arguments);
  }

  @Override
  public void info(String string, Throwable t) {
    if (info && init(Level.INFO))
      message(LogService.LOG_INFO, string, t);
  }

  @Override
  public void info(Marker marker, String string) {
    if (info && init(Level.INFO))
      message(LogService.LOG_INFO, string, marker);
  }

  @Override
  public void info(String format, Object a, Object b) {
    if (info && init(Level.INFO))
      message(LogService.LOG_INFO, format, a, b);
  }

  @Override
  public void info(Marker marker, String format, Object a) {
    if (info && init(Level.INFO))
      message(LogService.LOG_INFO, format, a, marker);
  }

  @Override
  public void info(Marker marker, String format, Object... args) {
    if (info && init(Level.INFO))
      message(LogService.LOG_INFO, format, args);
  }

  @Override
  public void info(Marker marker, String format, Throwable t) {
    if (info && init(Level.INFO))
      message(LogService.LOG_INFO, format, t);
  }

  @Override
  public void info(Marker marker, String format, Object a, Object b) {
    if (info && init(Level.INFO))
      message(LogService.LOG_INFO, format, a, b);
  }

  @Override
  public boolean isDebugEnabled(Marker arg0) {
    return debug && init(Level.DEBUG);
  }

  @Override
  public boolean isErrorEnabled(Marker arg0) {
    return error && init(Level.ERROR);
  }

  @Override
  public boolean isInfoEnabled(Marker arg0) {
    return info && init(Level.INFO);
  }

  @Override
  public boolean isTraceEnabled(Marker arg0) {
    return trace && init(Level.TRACE);
  }

  @Override
  public boolean isWarnEnabled(Marker arg0) {
    return warn && init(Level.WARN);
  }

  @Override
  public void warn(String string) {
    if (warn && init(Level.WARN))
      message(LogService.LOG_WARNING, string);
  }

  @Override
  public void warn(String format, Object arguments) {
    if (warn && init(Level.WARN))
      message(LogService.LOG_WARNING, format, arguments);
  }

  @Override
  public void warn(String string, Throwable t) {
    if (warn && init(Level.WARN))
      message(LogService.LOG_WARNING, string, t);
  }

  @Override
  public void warn(Marker marker, String string) {
    if (warn && init(Level.WARN))
      message(LogService.LOG_WARNING, string, marker);
  }

  @Override
  public void warn(String format, Object a, Object b) {
    if (warn && init(Level.WARN))
      message(LogService.LOG_WARNING, format, a, b);
  }

  @Override
  public void warn(Marker marker, String format, Object a) {
    if (warn && init(Level.WARN))
      message(LogService.LOG_WARNING, format, a, marker);
  }

  @Override
  public void warn(Marker marker, String format, Object... args) {
    if (warn && init(Level.WARN))
      message(LogService.LOG_WARNING, format, args);
  }

  @Override
  public void warn(Marker marker, String format, Throwable t) {
    if (warn && init(Level.WARN))
      message(LogService.LOG_WARNING, format, t);
  }

  @Override
  public void warn(Marker marker, String format, Object a, Object b) {
    if (warn && init(Level.WARN))
      message(LogService.LOG_WARNING, format, a, b);
  }

  @Override
  public void trace(String string) {
    if (trace && init(Level.TRACE))
      message(LoggerAdminImpl.LOG_TRACE, string);
  }

  @Override
  public void trace(String format, Object arguments) {
    if (trace && init(Level.TRACE))
      message(LoggerAdminImpl.LOG_TRACE, format, arguments);
  }

  @Override
  public void trace(String string, Throwable t) {
    if (trace && init(Level.TRACE))
      message(LoggerAdminImpl.LOG_TRACE, string, t);
  }

  @Override
  public void trace(Marker marker, String string) {
    if (trace && init(Level.TRACE))
      message(LoggerAdminImpl.LOG_TRACE, string, marker);
  }

  @Override
  public void trace(String format, Object a, Object b) {
    if (trace && init(Level.TRACE))
      message(LoggerAdminImpl.LOG_TRACE, format, a, b);
  }

  @Override
  public void trace(Marker marker, String format, Object a) {
    if (trace && init(Level.TRACE))
      message(LoggerAdminImpl.LOG_TRACE, format, a, marker);
  }

  @Override
  public void trace(Marker marker, String format, Object... args) {
    if (trace && init(Level.TRACE))
      message(LoggerAdminImpl.LOG_TRACE, format, args);
  }

  @Override
  public void trace(Marker marker, String format, Throwable t) {
    if (trace && init(Level.TRACE))
      message(LoggerAdminImpl.LOG_TRACE, format, t);
  }

  @Override
  public void trace(Marker marker, String format, Object a, Object b) {
    if (trace && init(Level.TRACE))
      message(LoggerAdminImpl.LOG_TRACE, format, a, b);
  }

  public void setBundle(Bundle bundle) {
    this.bundle = bundle;
    if (this.name == null) {
      String name = this.bundle.getSymbolicName();
      if (name == null)
        name = bundle.getBundleId() + "";
      if (bundle.getVersion() != null)
        name += ";" + bundle.getVersion();

      setName(name);
    }
  }

  public void setName(String name) {
    this.name = name;
  }

}
TOP

Related Classes of osgi.logger.provider.AbstractLogger

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.