package org.springframework.roo.support.logging; import java.util.ArrayList; import java.util.List; import java.util.logging.ConsoleHandler; import java.util.logging.Formatter; import java.util.logging.Handler; import java.util.logging.Level; import java.util.logging.LogRecord; import java.util.logging.Logger; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.Validate; /** * Utility methods for dealing with {@link Handler} objects. * * @author Ben Alex * @since 1.0 */ public final class HandlerUtils { /** * Forces all {@link Handler} instances registered in the presented * {@link Logger} to be flushed. * * @param logger to flush (required) * @return the number of {@link Handler}s flushed (may be 0 or above) */ public static int flushAllHandlers(final Logger logger) { Validate.notNull(logger, "Logger is required"); int flushed = 0; final Handler[] handlers = logger.getHandlers(); if (handlers != null && handlers.length > 0) { for (final Handler h : handlers) { flushed++; h.flush(); } } return flushed; } /** * Obtains a {@link Logger} that guarantees to set the {@link Level} to * {@link Level#FINE} if it is part of org.springframework.roo. * Unfortunately this is needed due to a regression in JDK 1.6.0_18 as per * issue ROO-539. * * @param clazz to retrieve the logger for (required) * @return the logger, which will at least of {@link Level#FINE} if no level * was specified */ public static Logger getLogger(final Class<?> clazz) { Validate.notNull(clazz, "Class required"); final Logger logger = Logger.getLogger(clazz.getName()); if (logger.getLevel() == null && clazz.getName().startsWith("org.springframework.roo")) { logger.setLevel(Level.FINE); } return logger; } /** * Registers the presented target {@link Handler} against any * {@link DeferredLogHandler} encountered in the presented {@link Logger}. * <p> * Generally this method is used on {@link Logger} instances that have * previously been presented to the * {@link #wrapWithDeferredLogHandler(Logger, Level)} method. * <p> * The method will return a count of how many {@link DeferredLogHandler} * instances it detected. Note that no attempt is made to distinguish * between instances already possessing the intended target {@link Handler} * or those already possessing any target {@link Handler} at all. This * method always overwrites the target {@link Handler} and the returned * count represents how many overwrites took place. * * @param logger to introspect for {@link DeferredLogHandler} instances * (required) * @param target to set as the target {@link Handler} * @return number of {@link DeferredLogHandler} instances detected and * updated (may be 0 if none found) */ public static int registerTargetHandler(final Logger logger, final Handler target) { Validate.notNull(logger, "Logger is required"); Validate.notNull(target, "Target handler is required"); int replaced = 0; final Handler[] handlers = logger.getHandlers(); if (handlers != null && handlers.length > 0) { for (final Handler h : handlers) { if (h instanceof DeferredLogHandler) { replaced++; final DeferredLogHandler defLogger = (DeferredLogHandler) h; defLogger.setTargetHandler(target); } } } return replaced; } /** * Replaces each {@link Handler} defined against the presented * {@link Logger} with {@link DeferredLogHandler}. * <p> * This is useful for ensuring any {@link Handler} defaults defined by the * user are preserved and treated as the {@link DeferredLogHandler} * "fallback" {@link Handler} if the indicated severity {@link Level} is * encountered. * <p> * This method will create a {@link ConsoleHandler} if the presented * {@link Logger} has no current {@link Handler}. * * @param logger to introspect and replace the {@link Handler}s for * (required) * @param fallbackSeverity to trigger fallback mode (required) * @return the number of {@link DeferredLogHandler}s now registered against * the {@link Logger} (guaranteed to be 1 or above) */ public static int wrapWithDeferredLogHandler(final Logger logger, final Level fallbackSeverity) { Validate.notNull(logger, "Logger is required"); Validate.notNull(fallbackSeverity, "Fallback severity is required"); final List<DeferredLogHandler> newHandlers = new ArrayList<DeferredLogHandler>(); // Create DeferredLogHandlers for each Handler in presented Logger final Handler[] handlers = logger.getHandlers(); if (handlers != null && handlers.length > 0) { for (final Handler h : handlers) { logger.removeHandler(h); newHandlers.add(new DeferredLogHandler(h, fallbackSeverity)); } } // Create a default DeferredLogHandler if no Handler was defined in the // presented Logger if (newHandlers.isEmpty()) { final ConsoleHandler consoleHandler = new ConsoleHandler(); consoleHandler.setFormatter(new Formatter() { @Override public String format(final LogRecord record) { return record.getMessage() + IOUtils.LINE_SEPARATOR; } }); newHandlers.add(new DeferredLogHandler(consoleHandler, fallbackSeverity)); } // Add the new DeferredLogHandlers to the presented Logger for (final DeferredLogHandler h : newHandlers) { logger.addHandler(h); } return newHandlers.size(); } /** * Constructor is private to prevent instantiation * * @since 1.2.0 */ private HandlerUtils() {} }