1  /*
     2   * Copyright the original author or authors.
     3   * 
     4   * Licensed under the MOZILLA PUBLIC LICENSE, Version 1.1 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   * 
     8   *      http://www.mozilla.org/MPL/MPL-1.1.html
     9   * 
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16   
    17  import org.as2lib.core.BasicClass;
    18  import org.as2lib.env.log.Logger;
    19  import org.as2lib.env.log.LoggerRepository;
    20  import org.as2lib.env.log.repository.LoggerFactory;
    21  
    22  /**
    23   * {@code DynamicLoggerRepository} is used to obtain loggers.
    24   *
    25   * <p>The actual class of these loggers is determined by you at runtime. You can
    26   * therefor either use the constructors logger class argument or the
    27   * {@link #setLoggerFactory} method.
    28   * 
    29   * <p>This repository is very performant. What it does is quite simple. It only
    30   * instantiates logger instances passing-in the given name, stores these instances
    31   * by name for retrieval later on and returns them.
    32   *
    33   * <p>When working with logger repositories you normally store them in the log
    34   * manager using the static {@link LogManager#setLoggerRepository} method. You can
    35   * then use the static {@link LogManager#getLogger} method to obtain loggers from
    36   * the set repository.
    37   *
    38   * <p>Example:
    39   * <code>
    40   *   // configuration: on system start-up
    41   *   var repository:LoggerRepository = new DynamicLoggerRepository(MyLogger);
    42   *   LogManager.setLoggerRepository(repository);
    43   *   // usage: in the org.mydomain.MyClass class
    44   *   var myLogger:Logger = LogManager.getLogger("org.mydomain.MyClass");
    45   *   if (myLogger.isWarningEnabled()) {
    46   *       myLogger.warning("Pay attention please!");
    47   *   }
    48   * </code>
    49   *
    50   * @author Simon Wacker
    51   */
    52  class org.as2lib.env.log.repository.DynamicLoggerRepository extends BasicClass implements LoggerRepository {
    53  	
    54  	/** Already received loggers. */
    55  	private var loggers:Object;
    56  	
    57  	/** Creates loggers. */
    58  	private var loggerFactory:LoggerFactory;
    59  	
    60  	/**
    61  	 * Constructs a new {@code DynamicLoggerRepository} instance.
    62  	 *
    63  	 * <p>If you do not pass a {@code loggerClass} you must set the logger factory via
    64  	 * the {@link #setLoggerFactory} method. Otherwise the logger returned by
    65  	 * {@link #getLogger} will always be {@code null}.
    66  	 *
    67  	 * <p>The logger is wrapped into a factory and the factory is set. The factory
    68  	 * then instantiates the logger class passing-in the name of the logger on calls
    69  	 * to {@link #getLogger}.
    70  	 *
    71  	 * <p>Already received loggers are cached by name. Thus there exists only one
    72  	 * logger instance per name.
    73  	 *
    74  	 * @param loggerClass (optional) the class to create loggers of
    75  	 */
    76  	public function DynamicLoggerRepository(loggerClass:Function) {
    77  		if (loggerClass) {
    78  			loggerFactory = getDynamicLoggerFactory(loggerClass);
    79  		}
    80  		loggers = new Object();
    81  	}
    82  	
    83  	/**
    84  	 * Returns a new dynamic logger factory.
    85  	 *
    86  	 * <p>This factory creates new instances of the passed-in {@code loggerClass}. It
    87  	 * passes the logger name as parameter to the constructor of the class on creation.
    88  	 *
    89  	 * @return a new dynamic logger factory
    90  	 */
    91  	private function getDynamicLoggerFactory(loggerClass:Function):LoggerFactory {
    92  		var result:LoggerFactory = getBlankLoggerFactory();
    93  		result.getLogger = function(loggerName:String):Logger {
    94  			return new loggerClass(loggerName);
    95  		};
    96  		return result;
    97  	}
    98  	
    99  	/**
   100  	 * Returns a blank logger factory.
   101  	 *
   102  	 * <p>That is a factory without implemented methods. All methods have still to be
   103  	 * set.
   104  	 *
   105  	 * @return a blank logger factory
   106  	 */
   107  	private function getBlankLoggerFactory(Void):LoggerFactory {
   108  		var result = new Object();
   109  		result.__proto__ = LoggerFactory["prototype"];
   110  		result.__constructor__ = LoggerFactory;
   111  		return result;
   112  	}
   113  	
   114  	/**
   115  	 * Returns the set logger factory.
   116  	 *
   117  	 * @return the set logger factory
   118  	 */
   119  	public function getLoggerFactory(Void):LoggerFactory {
   120  		return loggerFactory;
   121  	}
   122  	
   123  	/**
   124  	 * Sets a new logger factory.
   125  	 *
   126  	 * <p>This logger factory is used to create loggers for given names, that are
   127  	 * returned by the {@link #getLogger} method.
   128  	 *
   129  	 * @param loggerFactory the new logger factory
   130  	 */
   131  	public function setLoggerFactory(loggerFactory:LoggerFactory):Void {
   132  		this.loggerFactory = loggerFactory;
   133  	}
   134  	
   135  	/**
   136  	 * Returns a pre-configured logger for the passed-in {@code name}.
   137  	 *
   138  	 * <p>A new logger is created for names to which no logger has been assigned yet.
   139  	 * The new logger is configured with the {@code name}, either by the custom
   140  	 * factory or by the default one, which passes the {@code name} as parameter to
   141  	 * the constructor of the logger class. The logger is then cached by name and
   142  	 * returned for usage.
   143  	 *
   144  	 * <p>{@code null} will be returned if:
   145  	 * <ul>
   146  	 *   <li>No logger factory has been set.</li>
   147  	 *   <li>The set logger factory returns {@code null} or {@code undefined}.</li>
   148  	 * </ul>
   149  	 *ยด
   150  	 * @param name the name of the logger to return
   151  	 * @return the logger appropriate to the passed-in {@code name}
   152  	 */
   153  	public function getLogger(name:String):Logger {
   154  		if (loggers[name]) return loggers[name];
   155  		if (loggerFactory) {
   156  			var result:Logger = loggerFactory.getLogger(name);
   157  			loggers[name] = result;
   158  			return result;
   159  		}
   160  		return null;
   161  	}
   162  	
   163  }