// Copyright (c) 2002 SPY internetworking <dustin@spy.net> package net.spy.log; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; /** * Factory to get logger instances. * The system property <code>net.spy.log.LoggerImpl</code> should point to * an implementation of net.spy.log.Logger to use. * * <p> * Depending on how and where this was compiled, a sun logger (jdk 1.4) * and/or <a href="http://jakarta.apache.org/log4j/docs/">log4j</a> logger * implementation may be included. Both are included with the official * distribution. * </p> * * @see AbstractLogger */ public final class LoggerFactory extends Object { private static LoggerFactory instance=null; private final ConcurrentMap<String, Logger> instances; private Constructor<? extends Logger> instanceConstructor; /** * Get an instance of LoggerFactory. */ private LoggerFactory() { super(); instances=new ConcurrentHashMap<String, Logger>(); } private static void init() { if(instance == null) { instance=new LoggerFactory(); } } /** * Get a logger by class. * * @param clazz the class for which we want the logger. * @return a Logger instance */ public static Logger getLogger(Class<?> clazz) { return(getLogger(clazz.getName())); } /** * Get a logger by name. * * @param name the name for which we want the logger * @return a Logger instance */ public static Logger getLogger(String name) { if(name == null) { throw new NullPointerException("Logger name may not be null."); } init(); return(instance.internalGetLogger(name)); } // Get an instance of Logger from internal mechanisms. private Logger internalGetLogger(String name) { assert name != null : "Name was null"; Logger rv=instances.get(name); if (rv==null) { Logger newLogger=null; try { newLogger=getNewInstance(name); } catch(Exception e) { throw new RuntimeException("Problem getting logger", e); } Logger tmp=instances.putIfAbsent(name, newLogger); // Return either the new logger we've just made, or one that was // created while we were waiting rv = tmp == null ? newLogger : tmp; } return(rv); } private Logger getNewInstance(String name) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { if(instanceConstructor==null) { getConstructor(); } Object[] args={name}; Logger rv=instanceConstructor.newInstance(args); return (rv); } // Find the appropriate constructor @SuppressWarnings("unchecked") private void getConstructor() { Class<? extends Logger> c=DefaultLogger.class; String className=System.getProperty("net.spy.log.LoggerImpl"); if(className!=null) { try { c=(Class<? extends Logger>) Class.forName(className); } catch(NoClassDefFoundError e) { System.err.println("Warning: " + className + " not found while initializing" + " net.spy.log.LoggerFactory"); e.printStackTrace(); c=DefaultLogger.class; } catch(ClassNotFoundException e) { System.err.println("Warning: " + className + " not found while initializing" + " net.spy.log.LoggerFactory"); e.printStackTrace(); c=DefaultLogger.class; } } // Find the best constructor try { // Try to find a constructor that takes a single string Class[] args={String.class}; instanceConstructor=c.getConstructor(args); } catch(NoSuchMethodException e) { try { // Try to find an empty constructor Class[] args={}; instanceConstructor=c.getConstructor(args); } catch(NoSuchMethodException e2) { System.err.println("Warning: " + className + " has no appropriate constructor, using defaults."); // Try to find a constructor that takes a single string try { Class[] args={String.class}; instanceConstructor= DefaultLogger.class.getConstructor(args); } catch(NoSuchMethodException e3) { // This shouldn't happen. throw new NoSuchMethodError( "There used to be a constructor that takes a single " + "String on " + DefaultLogger.class + ", but I can't " + "find one now."); } // SOL } // No empty constructor } // No constructor that takes a string } // getConstructor }