Package org.red5.logging

Source Code of org.red5.logging.LoggingContextSelector

/*
* RED5 Open Source Flash Server - http://code.google.com/p/red5/
*
* Copyright 2006-2014 by respective authors (see below). All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.red5.logging;

import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.Semaphore;

import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.joran.JoranConfigurator;
import ch.qos.logback.classic.selector.ContextSelector;
import ch.qos.logback.classic.util.ContextInitializer;
import ch.qos.logback.core.joran.spi.JoranException;
import ch.qos.logback.core.util.Loader;
import ch.qos.logback.core.util.StatusPrinter;

/**
* A class that allows the LoggerFactory to access an web context based LoggerContext.
*
* Add this java option -Dlogback.ContextSelector=org.red5.logging.LoggingContextSelector
*
* @author Paul Gregoire (mondain@gmail.com)
*/
public class LoggingContextSelector implements ContextSelector {

  private static boolean debug = false;
 
  private static final ConcurrentMap<String, LoggerContext> contextMap = new ConcurrentHashMap<String, LoggerContext>(6, 0.9f, 1);

  private static final Semaphore lock = new Semaphore(1, true);

  private final ThreadLocal<LoggerContext> threadLocal = new ThreadLocal<LoggerContext>();

  private final LoggerContext defaultContext;

  private volatile String contextName;

  private volatile String contextConfigFile;
 
  static {
    debug = System.getProperty("logback.debug") == null ? false : Boolean.valueOf(System.getProperty("logback.debug"));
  }

  public LoggingContextSelector(LoggerContext context) {
    if (debug) {
      System.out.printf("Setting default logging context: %s\n", context.getName());
    }
    defaultContext = context;
  }

  public LoggerContext getLoggerContext() {
    if (debug) {
      System.out.println("getLoggerContext request");   
    }
    // First check if ThreadLocal has been set already
    LoggerContext lc = threadLocal.get();
    if (lc != null) {
      if (debug) {
        System.out.printf("Thread local found: %s\n", lc.getName());
      }
      return lc;
    }
    if (contextName == null) {
      if (debug) {
        System.out.println("Context name was null, returning default");
      }
      // We return the default context
      return defaultContext;
    } else {
      LoggerContext loggerContext = null;
      try {
        // use a semaphore to protect against the .001% times when this gets hit too quickly
        lock.acquire();
        // Let's see if we already know such a context
        loggerContext = contextMap.get(contextName);
        //System.out.printf("Logger context for %s is %s\n", contextName, loggerContext);
        if (loggerContext == null) {
          // We have to create a new LoggerContext
          loggerContext = new LoggerContext();
          loggerContext.setName(contextName);
          // allow override using logbacks system prop
          String overrideProperty = System.getProperty("logback.configurationFile");
          if (overrideProperty == null) {
            contextConfigFile = String.format("logback-%s.xml", contextName);
          } else {
            contextConfigFile = String.format(overrideProperty, contextName);
          }
          if (debug) {
            System.out.printf("Context logger config file: %s\n", contextConfigFile);
          }
          ClassLoader classloader = Thread.currentThread().getContextClassLoader();
          //System.out.printf("Thread context cl: %s\n", classloader);
          //ClassLoader classloader2 = Loader.class.getClassLoader();
          //System.out.printf("Loader tcl: %s\n", classloader2);
          //URL url = Loader.getResourceBySelfClassLoader(contextConfigFile);
          URL url = Loader.getResource(contextConfigFile, classloader);
          if (url != null) {
            try {
              JoranConfigurator configurator = new JoranConfigurator();
              loggerContext.reset();
              configurator.setContext(loggerContext);
              configurator.doConfigure(url);
            } catch (JoranException e) {
              StatusPrinter.print(loggerContext);
            }
          } else {
            try {
              ContextInitializer ctxInit = new ContextInitializer(loggerContext);
              ctxInit.autoConfig();
            } catch (JoranException je) {
              StatusPrinter.print(loggerContext);
            }
          }
          if (debug) {
            System.out.printf("Adding logger context: %s to map for context: %s\n", loggerContext.getName(), contextName);
          }
          contextMap.put(contextName, loggerContext);
        }
      } catch (InterruptedException e) {
        e.printStackTrace();
      } finally {
        lock.release();
      }
      return loggerContext;
    }
  }

  public LoggerContext getLoggerContext(String name) {
    if (debug) {
      System.out.printf("getLoggerContext request for %s in context map %s\n", name, contextMap.containsKey(name));
    }
    return contextMap.get(name);
  }

  public LoggerContext getDefaultLoggerContext() {
    return defaultContext;
  }

  public void attachLoggerContext(String contextName, LoggerContext loggerContext) {
    contextMap.put(contextName, loggerContext);
  }

  public LoggerContext detachLoggerContext(String loggerContextName) {
    return contextMap.remove(loggerContextName);
  }

  public List<String> getContextNames() {
    List<String> list = new ArrayList<String>();
    list.addAll(contextMap.keySet());
    return list;
  }

  public void setContextName(String contextName) {
    this.contextName = contextName;
  }

  public void setContextConfigFile(String contextConfigFile) {
    this.contextConfigFile = contextConfigFile;
  }

  /**
   * Returns the number of managed contexts Used for testing purposes
   *
   * @return the number of managed contexts
   */
  public int getCount() {
    return contextMap.size();
  }

  /**
   * These methods are used by the LoggerContextFilter.
   *
   * They provide a way to tell the selector which context to use, thus saving
   * the cost of a JNDI call at each new request.
   *
   * @param context logging context
   */
  public void setLocalContext(LoggerContext context) {
    threadLocal.set(context);
  }

  public void removeLocalContext() {
    threadLocal.remove();
  }

}
TOP

Related Classes of org.red5.logging.LoggingContextSelector

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.