diff --git a/com.archimatetool.editor/src/com/archimatetool/editor/LoggingSupport.java b/com.archimatetool.editor/src/com/archimatetool/editor/FileLogger.java similarity index 70% rename from com.archimatetool.editor/src/com/archimatetool/editor/LoggingSupport.java rename to com.archimatetool.editor/src/com/archimatetool/editor/FileLogger.java index 2ccdb5fdf..8788a3abf 100644 --- a/com.archimatetool.editor/src/com/archimatetool/editor/LoggingSupport.java +++ b/com.archimatetool.editor/src/com/archimatetool/editor/FileLogger.java @@ -13,7 +13,10 @@ import java.net.URL; import java.time.ZoneId; import java.time.ZonedDateTime; +import java.util.HashMap; +import java.util.Map; import java.util.logging.FileHandler; +import java.util.logging.Level; import java.util.logging.LogManager; import java.util.logging.LogRecord; import java.util.logging.Logger; @@ -22,28 +25,55 @@ import org.eclipse.ui.PlatformUI; /** - * Logging Support + * File Logging Support * * Uses java.util.logging to log to a localised file for a given plug-in. * *

Example Usage:

-   LoggingSupport loggingSupport = new LoggingSupport("com.archimatetool.myplugin",
-                                            getBundle().getEntry("logging.properties"),
-                                            new File(getLoggingFolder(), "log-%g.txt"));
-   loggingSupport.start();
-   // Use the logger...
-   loggingSupport.stop();
+   FileLogger.create("com.archimatetool.myplugin",
+                      getBundle().getEntry("logging.properties"),
+                      new File(getLoggingFolder(), "log-%g.txt"));
    
* * @author Phillip Beauvoir */ @SuppressWarnings("nls") -public class LoggingSupport { +public class FileLogger { private static final int MAX_BYTES = 1024 * 1024 * 10; // 10 mb files private static final int FILE_COUNT = 3; // Max files to use + /** + * Registered loggers + */ + private static Map loggers = new HashMap<>(); + + /** + * Create and start Java Logging to file + * + * @param rootPackageName root package name that will be used for the root logger + * @param propertiesFile bundle location of logging.properties file (can be null) + * @param fileNamePattern absolute file name pattern of the logging file to write to + */ + public static FileLogger create(String rootPackageName, URL propertiesFile, File fileNamePattern) throws SecurityException, IOException { + FileLogger logger = loggers.get(rootPackageName); + + if(logger == null) { + logger = new FileLogger(rootPackageName, propertiesFile, fileNamePattern); + loggers.put(rootPackageName, logger); + } + + return logger; + } + + /** + * Return a previsously created FileLogger, or null if it hasn't been created yet or has been closed + */ + public static FileLogger get(String rootPackageName) { + return loggers.get(rootPackageName); + } + /** * Use our own extension of SimpleFormatter because we don't want to set a global, singleton format * with property "java.util.logging.SimpleFormatter.format" as this will be global and will set it for other SimpleFormatter usages. @@ -101,45 +131,20 @@ public String format(LogRecord record) { } private String rootPackageName; - private URL propertiesFile; - private File fileNamePattern; - private Logger rootLogger; private FileHandler fileHandler; - /** - * @param rootPackageName root package name that will be used for the root logger - * @param propertiesFile bundle location of logging.properties file (can be null) - * @param fileNamePattern absolute file name pattern of the logging file - */ - public LoggingSupport(String rootPackageName, URL propertiesFile, File fileNamePattern) { + private FileLogger() { + } + + private FileLogger(String rootPackageName, URL propertiesFile, File fileNamePattern) throws SecurityException, IOException { this.rootPackageName = rootPackageName; - this.propertiesFile = propertiesFile; - this.fileNamePattern = fileNamePattern; - // The root logger is the root class package name of the bundle + // The root logger is the root class package name of the plug-in rootLogger = Logger.getLogger(rootPackageName); // Don't use parent handlers so there's no logging to console rootLogger.setUseParentHandlers(false); - } - - /** - * Get a Logger for its name - * We use this proxy method rather than the direct call to ensure that the root logger is initialised - */ - public Logger getLogger(String name) { - return Logger.getLogger(name); - } - - /** - * Initialise the file handler for logging to file - */ - public void start() throws SecurityException, IOException { - // Don't use file logging if running headless (unit tests) - if(!PlatformUI.isWorkbenchRunning()) { - return; - } // Read logging properties file, if any if(propertiesFile != null) { @@ -147,11 +152,18 @@ public void start() throws SecurityException, IOException { LogManager.getLogManager().updateConfiguration(is, null); } } + + // Don't use file logging if running headless (unit tests) + if(!PlatformUI.isWorkbenchRunning()) { + return; + } // Parent folder must exist for logging file and lock file - fileNamePattern.getParentFile().mkdirs(); + if(fileNamePattern.getParentFile() != null) { + fileNamePattern.getParentFile().mkdirs(); + } - // Set file handler on root logger + // Set file handler and format on the root logger fileHandler = new FileHandler(fileNamePattern.getAbsolutePath(), MAX_BYTES, FILE_COUNT, true); // 10mb String format = LogManager.getLogManager().getProperty(rootPackageName + ".format"); fileHandler.setFormatter(new ExtSimpleFormatter(format)); @@ -160,12 +172,28 @@ public void start() throws SecurityException, IOException { } /** - * Close the file handler + * Set the root logger to level + */ + public void setLevel(Level newLevel) { + if(rootLogger != null) { + rootLogger.setLevel(newLevel); + } + } + + /** + * Close the logger and stop logging. The logger will be unregistered and calls to get(packagename) will return null. */ - public void stop() { + public void close() { if(fileHandler != null) { fileHandler.close(); - fileHandler = null; } + + if(rootLogger != null) { + rootLogger.removeHandler(fileHandler); + } + + fileHandler = null; + rootLogger = null; + loggers.remove(rootPackageName); } }