package osgi.logger.provider; import java.util.LinkedHashMap; import java.util.Map; import java.util.logging.Handler; import java.util.logging.Level; import java.util.logging.LogRecord; import java.util.regex.Pattern; import org.osgi.service.log.LogService; import osgi.enroute.logger.api.LoggerAdmin.Control; /** * Logging is so much fun! Everybody should have their own logging API! * <p> * Anyway, this class links into the (quite horrible) Java Util Logging API and * forwards the messages to the OSGi Log Service. */ class JavaUtilLoggingHandler extends Handler { /* * Loggers have a name. So we maintain a cache of the last 1000 loggers */ private final Map<String,AbstractLogger> loggers = new LinkedHashMap<String,AbstractLogger>() { private static final long serialVersionUID = 1L; protected boolean removeEldestEntry( Map.Entry<String,AbstractLogger> eldest) { if (size() > 1000) { eldest.getValue().close(); } return false; } }; /* * Java util logging is a bit confusing and horribly designed. The Logger * class is quite messed up with the reporting (slf4j is much better in that * way). This publish method has already passed any filters (which are * applied on local Loggers but can be inherited). Anyway, this method * has passed the hurdles and needs to be queued. */ @Override public void publish(LogRecord record) { AbstractLogger l; synchronized (loggers) { // // Try to find the name in the cache. If not found, create a new one. // l = loggers.get(record.getLoggerName()); if (l == null) { l = new AbstractLogger(LoggerDispatcher.classContext.getCallerBundle(), record.getLoggerName()); loggers.put(record.getLoggerName(), l); } Level level = record.getLevel(); // // Translate the JUL to the OSGi log levels // if (level == Level.INFO) { if (l.isInfoEnabled()) message(l, LogService.LOG_INFO, record); return; } if (level == Level.SEVERE) { if (l.isErrorEnabled()) message(l, LogService.LOG_ERROR, record); return; } if (level == Level.WARNING) { if (l.isWarnEnabled()) message(l, LogService.LOG_WARNING, record); return; } // // All other levels we assume are trace levels // if (l.isTraceEnabled()) message(l, LoggerAdminImpl.LOG_TRACE, record); } } static Object[] EMPTY = new Object[0]; /* * convert what we have to an OSGi record */ private void message(AbstractLogger l, int level, LogRecord record) { Object[] parameters = record.getParameters(); if (parameters == null) parameters = EMPTY; l.message(level, record.getMessage(), parameters); } /* Duh ... */ @Override public void flush() {} /* * Wow, a life cycle method ... we just close all our loggers. */ @Override public void close() throws SecurityException { synchronized (loggers) { for (AbstractLogger l : loggers.values()) { l.close(); } loggers.clear(); } } /* * TODO Not sure if this is needed */ void update(Map<Pattern,Control> controls) { } }