package alma.acs.logging.adapters; import java.util.HashMap; import java.util.Map; import java.util.logging.Logger; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogConfigurationException; import org.apache.commons.logging.impl.Jdk14Logger; import org.apache.commons.logging.impl.LogFactoryImpl; import alma.acs.logging.ClientLogManager; /** * Frameworks that use Apache Commons Logging should get this logger factory enabled * via system property <code>org.apache.commons.logging.LogFactory</code> * (see {@link org.apache.commons.logging.LogFactory#FACTORY_PROPERTY}). * <p> * Some frameworks will get recognized by the callstack, and for those logger * requests this factory will return an apache logger that is backed by an ACS-enabled JDK logger. * Frameworks that are not recognized will get a normal apache logger. * Currently this factory supports and maps: * <ul> * <li>Apache SCXML ("org.apache.commons.scxml" packages), logger name "scxml[@processName]" * </ul> * <p> * The alternative to recognizing frameworks, at the expense of creating and checking the call stack, * would be to create a different ACS logger for every requested logger. * This would conflict with the concept of ACS that logger names should represent components or other * pieces of code, and not the names of implementation classes that request the loggers. * * @author hsommer * @since ACS 10.2 */ public class CommonsLoggingFactory extends LogFactoryImpl { /** * SCXML logger name base. */ public static final String SCXML_LOGGER_NAME_PREFIX = "scxml"; private final Map<String, Log> loggerMap = new HashMap<String, Log>(); @Override protected synchronized Log newInstance(String name) throws LogConfigurationException { // System.out.println("CommonsLoggingFactoryForACS#newInstance called for name=" + name); // Check which framework is requesting the apache commons logger String loggerNameBase = null; StackTraceElement[] stackTrace = (new Exception()).getStackTrace(); for (StackTraceElement stackTraceElement : stackTrace) { if (stackTraceElement.getClassName().contains("org.apache.commons.scxml")) { loggerNameBase = SCXML_LOGGER_NAME_PREFIX; break; } // TODO: add check for other frameworks that use apache logging commons, once we have those } // Give up if we did not recognize the client framework if (loggerNameBase == null) { return super.newInstance(name); } // Check if we already have a logger for the client framework, and create it if needed. Log myLog = loggerMap.get(loggerNameBase); if (myLog == null) { final String loggerNameBaseFinal = loggerNameBase; myLog = new Jdk14Logger(loggerNameBase) { @Override public Logger getLogger() { // note that getLoggerForCorba implements a hack that assigns WARNING log levels // to some known framework loggers, in the absence of other specific log configuration. return ClientLogManager.getAcsLogManager().getLoggerForCorba(loggerNameBaseFinal, true); } }; loggerMap.put(loggerNameBase, myLog); } return myLog; } }