001/**
002 * Logback: the reliable, generic, fast and flexible logging framework.
003 * Copyright (C) 1999-2015, QOS.ch. All rights reserved.
004 *
005 * This program and the accompanying materials are dual-licensed under
006 * either the terms of the Eclipse Public License v1.0 as published by
007 * the Eclipse Foundation
008 *
009 *   or (per the licensee's choosing)
010 *
011 * under the terms of the GNU Lesser General Public License version 2.1
012 * as published by the Free Software Foundation.
013 */
014package ch.qos.logback.classic.util;
015
016import java.lang.reflect.Constructor;
017import java.lang.reflect.InvocationTargetException;
018
019import ch.qos.logback.classic.ClassicConstants;
020import ch.qos.logback.classic.LoggerContext;
021import ch.qos.logback.classic.selector.ContextJNDISelector;
022import ch.qos.logback.classic.selector.ContextSelector;
023import ch.qos.logback.classic.selector.DefaultContextSelector;
024import ch.qos.logback.core.util.Loader;
025import ch.qos.logback.core.util.OptionHelper;
026
027/**
028 * Holds the context selector for use in the current environment.
029 * 
030 * @author Ceki Gülcü
031 * @since 0.9.19
032 */
033public class ContextSelectorStaticBinder {
034
035    static ContextSelectorStaticBinder singleton = new ContextSelectorStaticBinder();
036
037    ContextSelector contextSelector;
038    Object key;
039
040    public static ContextSelectorStaticBinder getSingleton() {
041        return singleton;
042    }
043
044    /**
045     * FOR INTERNAL USE. This method is intended for use by StaticLoggerBinder.
046     * 
047     * @param defaultLoggerContext
048     * @throws ClassNotFoundException
049     * @throws NoSuchMethodException
050     * @throws InstantiationException
051     * @throws IllegalAccessException
052     * @throws InvocationTargetException
053     */
054    public void init(LoggerContext defaultLoggerContext, Object key) throws ClassNotFoundException,
055            NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
056        if (this.key == null) {
057            this.key = key;
058        } else if (this.key != key) {
059            throw new IllegalAccessException("Only certain classes can access this method.");
060        }
061
062        String contextSelectorStr = OptionHelper.getSystemProperty(ClassicConstants.LOGBACK_CONTEXT_SELECTOR);
063        if (contextSelectorStr == null) {
064            contextSelector = new DefaultContextSelector(defaultLoggerContext);
065        } else if (contextSelectorStr.equals("JNDI")) {
066            // if jndi is specified, let's use the appropriate class
067            contextSelector = new ContextJNDISelector(defaultLoggerContext);
068        } else {
069            contextSelector = dynamicalContextSelector(defaultLoggerContext, contextSelectorStr);
070        }
071    }
072
073    /**
074     * Instantiate the context selector class designated by the user. The selector
075     * must have a constructor taking a LoggerContext instance as an argument.
076     * 
077     * @param defaultLoggerContext
078     * @param contextSelectorStr
079     * @return an instance of the designated context selector class
080     * @throws ClassNotFoundException
081     * @throws SecurityException
082     * @throws NoSuchMethodException
083     * @throws IllegalArgumentException
084     * @throws InstantiationException
085     * @throws IllegalAccessException
086     * @throws InvocationTargetException
087     */
088    static ContextSelector dynamicalContextSelector(LoggerContext defaultLoggerContext, String contextSelectorStr)
089            throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException,
090            InstantiationException, IllegalAccessException, InvocationTargetException {
091        Class<?> contextSelectorClass = Loader.loadClass(contextSelectorStr);
092        Constructor<?> cons = contextSelectorClass.getConstructor(new Class[] { LoggerContext.class });
093        return (ContextSelector) cons.newInstance(defaultLoggerContext);
094    }
095
096    public ContextSelector getContextSelector() {
097        return contextSelector;
098    }
099
100}