changeset 1268:33bca916e032

Added to enable and write logs directly to file without java.util.logging
author Jiri Vanek <jvanek@redhat.com>
date Tue, 27 Oct 2015 11:02:45 +0100
parents 3049b4003737
children 8bbb1c9daa4d
files ChangeLog netx/net/sourceforge/jnlp/config/Defaults.java netx/net/sourceforge/jnlp/config/DeploymentConfiguration.java netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java netx/net/sourceforge/jnlp/util/logging/FileLog.java netx/net/sourceforge/jnlp/util/logging/LogConfig.java netx/net/sourceforge/jnlp/util/logging/OutputController.java netx/net/sourceforge/jnlp/util/logging/SingleStreamLogger.java netx/net/sourceforge/jnlp/util/logging/filelogs/LogBasedFileLog.java netx/net/sourceforge/jnlp/util/logging/filelogs/WriterBasedFileLog.java tests/netx/unit/net/sourceforge/jnlp/util/logging/FileLogTest.java tests/netx/unit/net/sourceforge/jnlp/util/logging/OutputControllerTest.java tests/netx/unit/net/sourceforge/jnlp/util/logging/WriterBasedFileLogTest.java
diffstat 13 files changed, 520 insertions(+), 136 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Thu Oct 15 15:09:37 2015 +0200
+++ b/ChangeLog	Tue Oct 27 11:02:45 2015 +0100
@@ -1,3 +1,30 @@
+2015-10-15  Jiri Vanek  <jvanek@redhat.com>
+
+	Added to enable and write logs directly to	file without java.util.logging
+	* netx/net/sourceforge/jnlp/config/Defaults.java: (defaults) added new key
+	KEY_ENABLE_LEGACY_LOGBASEDFILELOG, by default true
+	* netx/net/sourceforge/jnlp/config/DeploymentConfiguration.java: defined
+	KEY_ENABLE_LEGACY_LOGBASEDFILELOG for deployment.log.file.legacylog
+	* netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java: (exit) catch new exception
+	* netx/net/sourceforge/jnlp/util/logging/FileLog.java: removed all logic.
+	Now serve onl as factory provider of FileLog implementation
+	* netx/net/sourceforge/jnlp/util/logging/LogConfig.java: fixed indentation, made 
+	aware about LOGBASEDFILELOG
+	* netx/net/sourceforge/jnlp/util/logging/OutputController.java: adapted to
+	autocloseable SingleStreamLogger
+	* netx/net/sourceforge/jnlp/util/logging/SingleStreamLogger.java: this interface
+	now extends	AutoCloseable
+	* netx/net/sourceforge/jnlp/util/logging/filelogs/LogBasedFileLog.java: copy 
+	of original FileLog. Writing to file is done via java.util.loggiing engine
+	* netx/net/sourceforge/jnlp/util/logging/filelogs/WriterBasedFileLog.java:
+	writing to file is done by simple buffered writer
+	* tests/netx/unit/net/sourceforge/jnlp/util/logging/FileLogTest.java: now tests
+	LogBasedFileLog
+	* tests/netx/unit/net/sourceforge/jnlp/util/logging/OutputControllerTest.java:
+	now tests WriterBasedFileLog instead of FileLog
+	* tests/netx/unit/net/sourceforge/jnlp/util/logging/WriterBasedFileLogTest.java:
+	Similar set of tests as are in FileLogTest but for WriterBasedFileLog
+
 2015-10-15  Jiri Vanek  <jvanek@redhat.com>
 
 	Broken file logging now dont crash itw
--- a/netx/net/sourceforge/jnlp/config/Defaults.java	Thu Oct 15 15:09:37 2015 +0200
+++ b/netx/net/sourceforge/jnlp/config/Defaults.java	Tue Oct 27 11:02:45 2015 +0100
@@ -339,6 +339,11 @@
                         BasicValueValidators.getBooleanValidator(),
                         String.valueOf(false)
                 },
+                 {
+                        DeploymentConfiguration.KEY_ENABLE_LEGACY_LOGBASEDFILELOG,
+                        BasicValueValidators.getBooleanValidator(),
+                        String.valueOf(true)
+                },
                 {
                         DeploymentConfiguration.KEY_ENABLE_LOGGING_TOSTREAMS,
                         BasicValueValidators.getBooleanValidator(),
@@ -430,4 +435,4 @@
 
         return result;
     }
-}
\ No newline at end of file
+}
--- a/netx/net/sourceforge/jnlp/config/DeploymentConfiguration.java	Thu Oct 15 15:09:37 2015 +0200
+++ b/netx/net/sourceforge/jnlp/config/DeploymentConfiguration.java	Tue Oct 27 11:02:45 2015 +0100
@@ -178,6 +178,7 @@
     public static final String KEY_ENABLE_LOGGING = "deployment.log"; //same as verbose or ICEDTEAPLUGIN_DEBUG=true
     public static final String KEY_ENABLE_LOGGING_HEADERS = "deployment.log.headers"; //will add header OutputContorll.getHeader To all messages
     public static final String KEY_ENABLE_LOGGING_TOFILE = "deployment.log.file";
+    public static final String KEY_ENABLE_LEGACY_LOGBASEDFILELOG = "deployment.log.file.legacylog";    
     public static final String KEY_ENABLE_LOGGING_TOSTREAMS = "deployment.log.stdstreams";
     public static final String KEY_ENABLE_LOGGING_TOSYSTEMLOG = "deployment.log.system";
     
--- a/netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java	Thu Oct 15 15:09:37 2015 +0200
+++ b/netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java	Tue Oct 27 11:02:45 2015 +0100
@@ -880,7 +880,11 @@
     }
 
     public static void exit(int i) {
-        OutputController.getLogger().close();
+        try {
+            OutputController.getLogger().close();
+        } catch (Exception ex) {
+            //to late
+        }
         System.exit(i);
     }
 
--- a/netx/net/sourceforge/jnlp/util/logging/FileLog.java	Thu Oct 15 15:09:37 2015 +0200
+++ b/netx/net/sourceforge/jnlp/util/logging/FileLog.java	Tue Oct 27 11:02:45 2015 +0100
@@ -36,22 +36,21 @@
  exception statement from your version. */
 package net.sourceforge.jnlp.util.logging;
 
-import java.io.File;
-import java.io.IOException;
 import java.text.SimpleDateFormat;
 import java.util.Date;
-import java.util.logging.FileHandler;
-import java.util.logging.Formatter;
-import java.util.logging.Level;
-import java.util.logging.LogRecord;
-import java.util.logging.Logger;
-import net.sourceforge.jnlp.util.FileUtils;
+import net.sourceforge.jnlp.util.docprovider.TextsProvider;
+import net.sourceforge.jnlp.util.logging.filelogs.LogBasedFileLog;
+import net.sourceforge.jnlp.util.logging.filelogs.WriterBasedFileLog;
 import net.sourceforge.jnlp.util.logging.headers.Header;
 
 /**
- * This class writes log information to file.
+ * This class is utility and factory around file logs.
  */
-public final class FileLog implements SingleStreamLogger {
+public final class FileLog  {
+
+    public static Header getHeadlineHeader() {
+        return new Header(OutputController.Level.WARNING_ALL, Thread.currentThread().getStackTrace(), Thread.currentThread(), false);
+    }
     
     private static final class SingleStreamLoggerImpl implements SingleStreamLogger {
 
@@ -69,18 +68,20 @@
         }
     }
 
-    private static SimpleDateFormat fileLogNameFormatter = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss.S");
+    public static final SimpleDateFormat fileLogNameFormatter = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss.S");
     /**"Tue Nov 19 09:43:50 CET 2013"*/
-    private static SimpleDateFormat pluginSharedFormatter = new SimpleDateFormat("EEE MMM dd HH:mm:ss ZZZ yyyy");
+    public static final SimpleDateFormat pluginSharedFormatter = new SimpleDateFormat("EEE MMM dd HH:mm:ss ZZZ yyyy");
+    public static final String defaultloggerName = TextsProvider.ITW + " file-logger";
 
-    private final Logger impl;
-    private final FileHandler fh;
-    private static final String defaultloggerName = "IcedTea-Web file-logger";
-
+    
       public static SingleStreamLogger createFileLog() {
         SingleStreamLogger s;
         try {
-            s = new FileLog();
+            if (LogConfig.getLogConfig().isLegacyLogBasedFileLog()){
+                s = new LogBasedFileLog(defaultloggerName, getFileName(), false);
+            } else {
+                s = new WriterBasedFileLog(defaultloggerName, getFileName(), false);
+            }
         } catch (Exception ex) {
             //we do not wont to block whole logging just because initialization error in "new FileLog()"
             OutputController.getLogger().log(ex);
@@ -88,58 +89,13 @@
         }
         return s;
     }
-    
-    private FileLog() {
-        this(false);
+
+    private static String getFileName() {
+        return LogConfig.getLogConfig().getIcedteaLogDir() + "itw-javantx-" + getStamp() + ".log";
     }
     
-    private FileLog(boolean append) {
-        this(defaultloggerName, LogConfig.getLogConfig().getIcedteaLogDir() + "itw-javantx-" + getStamp() + ".log", append);
-    }
-
-    // testing constructor 
-    FileLog(String fileName, boolean append) {
-        this(fileName, fileName, append);
-    }
-
-    private FileLog(String loggerName, String fileName, boolean append) {
-        try {
-           File futureFile = new File(fileName);
-           if (!futureFile.exists()) {
-               FileUtils.createRestrictedFile(futureFile, true);
-           }
-           fh = new FileHandler(fileName, append);
-           fh.setFormatter(new Formatter() {
-               @Override
-               public String format(LogRecord record) {
-                   return record.getMessage() + "\n";
-               }
-           });
-           impl = Logger.getLogger(loggerName);
-           impl.setLevel(Level.ALL);
-           impl.addHandler(fh);
-           log(new Header(OutputController.Level.WARNING_ALL, Thread.currentThread().getStackTrace(), Thread.currentThread(), false).toString());
-       } catch (IOException e) {
-           throw new RuntimeException(e);
-       }
-    }
-
-    /**
-     * Log the String to file.
-     *
-     * @param s {@link Exception} that was thrown.
-     */
-    @Override
-    public synchronized void log(String s) {
-        impl.log(Level.FINE, s);
-    }
-    
-    @Override
-    public void close() {
-        fh.close();
-    }
-
-    private static String getStamp() {
+  
+    public static String getStamp() {
         return fileLogNameFormatter.format(new Date());
     }
 
--- a/netx/net/sourceforge/jnlp/util/logging/LogConfig.java	Thu Oct 15 15:09:37 2015 +0200
+++ b/netx/net/sourceforge/jnlp/util/logging/LogConfig.java	Tue Oct 27 11:02:45 2015 +0100
@@ -54,30 +54,32 @@
     private boolean logToFile;
     private boolean logToStreams;
     private boolean logToSysLog;
-    
+    private boolean legacyLogaAsedFileLog;
+
     private LogConfig() {
-            DeploymentConfiguration config = JNLPRuntime.getConfiguration();
-            // Check whether logging and tracing is enabled.
-            enableLogging = Boolean.parseBoolean(config.getProperty(DeploymentConfiguration.KEY_ENABLE_LOGGING));
-            //enagle disable headers
-            enableHeaders = Boolean.parseBoolean(config.getProperty(DeploymentConfiguration.KEY_ENABLE_LOGGING_HEADERS));
-            //enable/disable individual channels
-            logToFile = Boolean.parseBoolean(config.getProperty(DeploymentConfiguration.KEY_ENABLE_LOGGING_TOFILE));
-            logToStreams = Boolean.parseBoolean(config.getProperty(DeploymentConfiguration.KEY_ENABLE_LOGGING_TOSTREAMS));
-            logToSysLog = Boolean.parseBoolean(config.getProperty(DeploymentConfiguration.KEY_ENABLE_LOGGING_TOSYSTEMLOG));
+        DeploymentConfiguration config = JNLPRuntime.getConfiguration();
+        // Check whether logging and tracing is enabled.
+        enableLogging = Boolean.parseBoolean(config.getProperty(DeploymentConfiguration.KEY_ENABLE_LOGGING));
+        //enagle disable headers
+        enableHeaders = Boolean.parseBoolean(config.getProperty(DeploymentConfiguration.KEY_ENABLE_LOGGING_HEADERS));
+        //enable/disable individual channels
+        logToFile = Boolean.parseBoolean(config.getProperty(DeploymentConfiguration.KEY_ENABLE_LOGGING_TOFILE));
+        logToStreams = Boolean.parseBoolean(config.getProperty(DeploymentConfiguration.KEY_ENABLE_LOGGING_TOSTREAMS));
+        logToSysLog = Boolean.parseBoolean(config.getProperty(DeploymentConfiguration.KEY_ENABLE_LOGGING_TOSYSTEMLOG));
+        legacyLogaAsedFileLog = Boolean.parseBoolean(config.getProperty(DeploymentConfiguration.KEY_ENABLE_LEGACY_LOGBASEDFILELOG));
 
-            // Get log directory, create it if it doesn't exist. If unable to create and doesn't exist, don't log.
-            icedteaLogDir = PathsAndFiles.LOG_DIR.getFullPath();
-            if (icedteaLogDir != null) {
-                File f = new File(icedteaLogDir);
-                if (f.isDirectory() || f.mkdirs()) {
-                    icedteaLogDir += File.separator;
-                } else {
-                    enableLogging = false;
-                }
+        // Get log directory, create it if it doesn't exist. If unable to create and doesn't exist, don't log.
+        icedteaLogDir = PathsAndFiles.LOG_DIR.getFullPath();
+        if (icedteaLogDir != null) {
+            File f = new File(icedteaLogDir);
+            if (f.isDirectory() || f.mkdirs()) {
+                icedteaLogDir += File.separator;
             } else {
                 enableLogging = false;
             }
+        } else {
+            enableLogging = false;
+        }
     }
 
     private static class LogConfigHolder {
@@ -91,9 +93,11 @@
         return LogConfigHolder.INSTANCE;
     }
 
-    /** For testing only: throw away the previous config */
+    /**
+     * For testing only: throw away the previous config
+     */
     static synchronized void resetLogConfig() {
-            LogConfigHolder.INSTANCE = new LogConfig();
+        LogConfigHolder.INSTANCE = new LogConfig();
     }
 
     public String getIcedteaLogDir() {
@@ -119,11 +123,8 @@
     public boolean isEnableHeaders() {
         return enableHeaders;
     }
-    
-    
-    
+
     //package private setters for testing
-
     void setEnableHeaders(boolean enableHeaders) {
         this.enableHeaders = enableHeaders;
     }
@@ -151,5 +152,13 @@
     boolean isLogToConsole() {
         return JavaConsole.isEnabled();
     }
-    
+
+    boolean isLegacyLogBasedFileLog() {
+        return legacyLogaAsedFileLog;
+    }
+
+    boolean setLegacyLogBasedFileLog(boolean b) {
+        return legacyLogaAsedFileLog = b;
+    }
+
 }
--- a/netx/net/sourceforge/jnlp/util/logging/OutputController.java	Thu Oct 15 15:09:37 2015 +0200
+++ b/netx/net/sourceforge/jnlp/util/logging/OutputController.java	Tue Oct 27 11:02:45 2015 +0100
@@ -134,7 +134,7 @@
         }
     }
     
-    public void close() {
+    public void close() throws Exception {
         flush();
         if (LogConfig.getLogConfig().isLogToFile()){
             getFileLog().close();
@@ -395,7 +395,7 @@
         this.errLog = errLog;
     }
 
-    void setFileLog(FileLog fileLog) {
+    void setFileLog(SingleStreamLogger fileLog) {
         FileLogHolder.INSTANCE = fileLog;
     }
 
--- a/netx/net/sourceforge/jnlp/util/logging/SingleStreamLogger.java	Thu Oct 15 15:09:37 2015 +0200
+++ b/netx/net/sourceforge/jnlp/util/logging/SingleStreamLogger.java	Tue Oct 27 11:02:45 2015 +0100
@@ -36,11 +36,11 @@
 
 package net.sourceforge.jnlp.util.logging;
 
-public interface SingleStreamLogger {
-     
-     
-      public  void log(String s);
-      public void close();
+public interface SingleStreamLogger extends AutoCloseable {
 
+    public void log(String s);
+
+    @Override
+    public void close() throws Exception;
 
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/netx/net/sourceforge/jnlp/util/logging/filelogs/LogBasedFileLog.java	Tue Oct 27 11:02:45 2015 +0100
@@ -0,0 +1,101 @@
+/*
+ Copyright (C) 2011, 2013 Red Hat, Inc.
+
+ This file is part of IcedTea.
+
+ IcedTea is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ IcedTea is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with IcedTea; see the file COPYING.  If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library.  Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module.  An independent module is a module which is not derived from
+ or based on this library.  If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so.  If you do not wish to do so, delete this
+ exception statement from your version. */
+package net.sourceforge.jnlp.util.logging.filelogs;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.logging.FileHandler;
+import java.util.logging.Formatter;
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+import java.util.logging.Logger;
+import net.sourceforge.jnlp.util.FileUtils;
+import net.sourceforge.jnlp.util.logging.FileLog;
+import net.sourceforge.jnlp.util.logging.SingleStreamLogger;
+
+/**
+ * This class writes log information to file.
+ */
+public final class LogBasedFileLog implements SingleStreamLogger {
+
+    //really instance bounded
+    private final Logger impl;
+    private final FileHandler fh;
+
+    // testing constructor 
+    public LogBasedFileLog(String fileName, boolean append) {
+        this(fileName, fileName, append);
+    }
+
+    public LogBasedFileLog(String loggerName, String fileName, boolean append) {
+        try {
+            File futureFile = new File(fileName);
+            if (!futureFile.exists()) {
+                FileUtils.createRestrictedFile(futureFile, true);
+            }
+            fh = new FileHandler(fileName, append);
+            fh.setFormatter(new Formatter() {
+                @Override
+                public String format(LogRecord record) {
+                    return record.getMessage() + "\n";
+                }
+            });
+            impl = Logger.getLogger(loggerName);
+            impl.setLevel(Level.ALL);
+            impl.addHandler(fh);
+            log(FileLog.getHeadlineHeader().toString() + " log-based impl.");
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Log the String to file.
+     *
+     * @param s {@link Exception} that was thrown.
+     */
+    @Override
+    public synchronized void log(String s) {
+        impl.log(Level.FINE, s);
+    }
+
+    @Override
+    public void close() {
+        fh.close();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/netx/net/sourceforge/jnlp/util/logging/filelogs/WriterBasedFileLog.java	Tue Oct 27 11:02:45 2015 +0100
@@ -0,0 +1,100 @@
+/*
+ Copyright (C) 2011, 2013 Red Hat, Inc.
+
+ This file is part of IcedTea.
+
+ IcedTea is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ IcedTea is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with IcedTea; see the file COPYING.  If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library.  Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module.  An independent module is a module which is not derived from
+ or based on this library.  If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so.  If you do not wish to do so, delete this
+ exception statement from your version. */
+package net.sourceforge.jnlp.util.logging.filelogs;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import net.sourceforge.jnlp.util.FileUtils;
+import net.sourceforge.jnlp.util.logging.FileLog;
+import net.sourceforge.jnlp.util.logging.SingleStreamLogger;
+
+/**
+ * This class writes log information to file.
+ */
+public final class WriterBasedFileLog implements SingleStreamLogger {
+
+    private final BufferedWriter bw;
+
+    public WriterBasedFileLog(String fileName, boolean append) {
+        this(fileName, fileName, append);
+    }
+
+    public WriterBasedFileLog(String loggerName, String fileName, boolean append) {
+        try {
+            File futureFile = new File(fileName);
+            if (!futureFile.exists()) {
+                FileUtils.createRestrictedFile(futureFile, true);
+            }
+            bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File(fileName), append), "UTF-8"));
+            log(FileLog.getHeadlineHeader().toString() + " writer-based impl.");
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Log the String to file.
+     *
+     * @param s {@link Exception} that was thrown.
+     */
+    @Override
+    public synchronized void log(String s) {
+        try {
+            bw.write(s);
+            if (!s.endsWith("\n")) {
+                bw.newLine();
+            }
+            bw.flush();
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public void close() throws IOException {
+        try {
+            bw.flush();
+        } finally {
+            bw.close();
+        }
+
+    }
+
+}
--- a/tests/netx/unit/net/sourceforge/jnlp/util/logging/FileLogTest.java	Thu Oct 15 15:09:37 2015 +0200
+++ b/tests/netx/unit/net/sourceforge/jnlp/util/logging/FileLogTest.java	Tue Oct 27 11:02:45 2015 +0100
@@ -40,6 +40,7 @@
 import java.io.IOException;
 import net.sourceforge.jnlp.closinglisteners.RulesFolowingClosingListener;
 import net.sourceforge.jnlp.util.StreamUtils;
+import net.sourceforge.jnlp.util.logging.filelogs.LogBasedFileLog;
 import org.junit.AfterClass;
 import org.junit.Assert;
 import org.junit.BeforeClass;
@@ -47,13 +48,13 @@
 
 public class FileLogTest {
 
-    private static File[] loggingTargets = new File[12];
-    private static String line1 = "I'm logged line one";
-    private static String line2 = "I'm logged line two";
-    private static String line3 = "I'm logged line three";
-    private static RulesFolowingClosingListener.ContainsRule r1 = new RulesFolowingClosingListener.ContainsRule(line1);
-    private static RulesFolowingClosingListener.ContainsRule r2 = new RulesFolowingClosingListener.ContainsRule(line2);
-    private static RulesFolowingClosingListener.ContainsRule r3 = new RulesFolowingClosingListener.ContainsRule(line3);
+    private static final File[] loggingTargets = new File[12];
+    private static final String line1 = "I'm logged line one";
+    private static final String line2 = "I'm logged line two";
+    private static final String line3 = "I'm logged line three";
+    private static final RulesFolowingClosingListener.ContainsRule r1 = new RulesFolowingClosingListener.ContainsRule(line1);
+    private static final RulesFolowingClosingListener.ContainsRule r2 = new RulesFolowingClosingListener.ContainsRule(line2);
+    private static final RulesFolowingClosingListener.ContainsRule r3 = new RulesFolowingClosingListener.ContainsRule(line3);
 
     @BeforeClass
     public static void prepareTmpFiles() throws IOException {
@@ -78,7 +79,7 @@
     @Test
     public void isAppendingLoggerLoggingOnNotExisitngFile() throws Exception {
         int i = 0;
-        FileLog l = new FileLog(loggingTargets[i].getAbsolutePath(), true);
+        LogBasedFileLog l = new LogBasedFileLog(loggingTargets[i].getAbsolutePath(), true);
         l.log(line1);
         String s = StreamUtils.readStreamAsString(new FileInputStream(loggingTargets[i]), true);
         Assert.assertTrue(r1.evaluate(s));
@@ -87,7 +88,7 @@
     @Test
     public void isRewritingLoggerLoggingOnNotExisitngFile() throws Exception {
         int i = 1;
-        FileLog l = new FileLog(loggingTargets[i].getAbsolutePath(), false);
+        LogBasedFileLog l = new LogBasedFileLog(loggingTargets[i].getAbsolutePath(), false);
         l.log(line1);
         String s = StreamUtils.readStreamAsString(new FileInputStream(loggingTargets[i]), true);
         Assert.assertTrue(r1.evaluate(s));
@@ -96,12 +97,12 @@
     @Test
     public void isRewritingLoggerRewritingOnNotExisitngFile() throws Exception {
         int i = 2;
-        FileLog l1 = new FileLog(loggingTargets[i].getAbsolutePath(), false);
+        LogBasedFileLog l1 = new LogBasedFileLog(loggingTargets[i].getAbsolutePath(), false);
         l1.log(line2);
         String s1 = StreamUtils.readStreamAsString(new FileInputStream(loggingTargets[i]), true);
         Assert.assertTrue(r2.evaluate(s1));
         l1.close();
-        FileLog l2 = new FileLog(loggingTargets[i].getAbsolutePath(), false);
+        LogBasedFileLog l2 = new LogBasedFileLog(loggingTargets[i].getAbsolutePath(), false);
         l2.log(line3);
         String s2 = StreamUtils.readStreamAsString(new FileInputStream(loggingTargets[i]), true);
         Assert.assertFalse(r2.evaluate(s2));
@@ -112,12 +113,12 @@
     @Test
     public void isAppendingLoggerAppendingOnNotExisitngFile() throws Exception {
         int i = 4;
-        FileLog l1 = new FileLog(loggingTargets[i].getAbsolutePath(), true);
+        LogBasedFileLog l1 = new LogBasedFileLog(loggingTargets[i].getAbsolutePath(), true);
         l1.log(line2);
         String s1 = StreamUtils.readStreamAsString(new FileInputStream(loggingTargets[i]), true);
         Assert.assertTrue(r2.evaluate(s1));
         l1.close();
-        FileLog l2 = new FileLog(loggingTargets[i].getAbsolutePath(), true);
+        LogBasedFileLog l2 = new LogBasedFileLog(loggingTargets[i].getAbsolutePath(), true);
         l2.log(line3);
         String s2 = StreamUtils.readStreamAsString(new FileInputStream(loggingTargets[i]), true);
         Assert.assertTrue(r2.evaluate(s2));
@@ -129,7 +130,7 @@
     @Test
     public void isAppendingLoggerLoggingOnExisitngFile() throws Exception {
         int i = 6;
-        FileLog l = new FileLog(loggingTargets[i].getAbsolutePath(), true);
+        LogBasedFileLog l = new LogBasedFileLog(loggingTargets[i].getAbsolutePath(), true);
         l.log(line1);
         String s = StreamUtils.readStreamAsString(new FileInputStream(loggingTargets[i]), true);
         Assert.assertTrue(r1.evaluate(s));
@@ -138,7 +139,7 @@
     @Test
     public void isRewritingLoggerLoggingOnExisitngFile() throws Exception {
         int i = 7;
-        FileLog l = new FileLog(loggingTargets[i].getAbsolutePath(), false);
+        LogBasedFileLog l = new LogBasedFileLog(loggingTargets[i].getAbsolutePath(), false);
         l.log(line1);
         String s = StreamUtils.readStreamAsString(new FileInputStream(loggingTargets[i]), true);
         Assert.assertTrue(r1.evaluate(s));
@@ -147,12 +148,12 @@
     @Test
     public void isRewritingLoggerRewritingOnExisitngFile() throws Exception {
         int i = 8;
-        FileLog l1 = new FileLog(loggingTargets[i].getAbsolutePath(), false);
+        LogBasedFileLog l1 = new LogBasedFileLog(loggingTargets[i].getAbsolutePath(), false);
         l1.log(line2);
         String s1 = StreamUtils.readStreamAsString(new FileInputStream(loggingTargets[i]), true);
         Assert.assertTrue(r2.evaluate(s1));
         l1.close();
-        FileLog l2 = new FileLog(loggingTargets[i].getAbsolutePath(), false);
+        LogBasedFileLog l2 = new LogBasedFileLog(loggingTargets[i].getAbsolutePath(), false);
         l2.log(line3);
         String s2 = StreamUtils.readStreamAsString(new FileInputStream(loggingTargets[i]), true);
         Assert.assertFalse(r2.evaluate(s2));
@@ -163,12 +164,12 @@
     @Test
     public void isAppendingLoggerAppendingOnExisitngFile() throws Exception {
         int i = 10;
-        FileLog l1 = new FileLog(loggingTargets[i].getAbsolutePath(), true);
+        LogBasedFileLog l1 = new LogBasedFileLog(loggingTargets[i].getAbsolutePath(), true);
         l1.log(line2);
         String s1 = StreamUtils.readStreamAsString(new FileInputStream(loggingTargets[i]), true);
         Assert.assertTrue(r2.evaluate(s1));
         l1.close();
-        FileLog l2 = new FileLog(loggingTargets[i].getAbsolutePath(), true);
+        LogBasedFileLog l2 = new LogBasedFileLog(loggingTargets[i].getAbsolutePath(), true);
         l2.log(line3);
         String s2 = StreamUtils.readStreamAsString(new FileInputStream(loggingTargets[i]), true);
         Assert.assertTrue(r2.evaluate(s2));
--- a/tests/netx/unit/net/sourceforge/jnlp/util/logging/OutputControllerTest.java	Thu Oct 15 15:09:37 2015 +0200
+++ b/tests/netx/unit/net/sourceforge/jnlp/util/logging/OutputControllerTest.java	Tue Oct 27 11:02:45 2015 +0100
@@ -42,6 +42,7 @@
 import java.util.Random;
 import net.sourceforge.jnlp.closinglisteners.RulesFolowingClosingListener;
 import net.sourceforge.jnlp.util.StreamUtils;
+import net.sourceforge.jnlp.util.logging.filelogs.WriterBasedFileLog;
 import org.junit.Assert;
 import org.junit.After;
 import org.junit.Before;
@@ -49,18 +50,18 @@
 
 public class OutputControllerTest {
 
-    private static String line1 = "I'm logged line one";
-    private static String line2 = "I'm logged line two";
-    private static String line3 = "I'm logged line three";
-    private static String line4 = "I'm logged line four";
-    private static String line5 = "I'm logged line five";
-    private static String line6 = "I'm logged line six";
-    private static RulesFolowingClosingListener.ContainsRule r1 = new RulesFolowingClosingListener.ContainsRule(line1);
-    private static RulesFolowingClosingListener.ContainsRule r2 = new RulesFolowingClosingListener.ContainsRule(line2);
-    private static RulesFolowingClosingListener.ContainsRule r3 = new RulesFolowingClosingListener.ContainsRule(line3);
-    private static RulesFolowingClosingListener.ContainsRule r4 = new RulesFolowingClosingListener.ContainsRule(line4);
-    private static RulesFolowingClosingListener.ContainsRule r5 = new RulesFolowingClosingListener.ContainsRule(line5);
-    private static RulesFolowingClosingListener.ContainsRule r6 = new RulesFolowingClosingListener.ContainsRule(line6);
+    private static final String line1 = "I'm logged line one";
+    private static final String line2 = "I'm logged line two";
+    private static final String line3 = "I'm logged line three";
+    private static final String line4 = "I'm logged line four";
+    private static final String line5 = "I'm logged line five";
+    private static final String line6 = "I'm logged line six";
+    private static final RulesFolowingClosingListener.ContainsRule r1 = new RulesFolowingClosingListener.ContainsRule(line1);
+    private static final RulesFolowingClosingListener.ContainsRule r2 = new RulesFolowingClosingListener.ContainsRule(line2);
+    private static final RulesFolowingClosingListener.ContainsRule r3 = new RulesFolowingClosingListener.ContainsRule(line3);
+    private static final RulesFolowingClosingListener.ContainsRule r4 = new RulesFolowingClosingListener.ContainsRule(line4);
+    private static final RulesFolowingClosingListener.ContainsRule r5 = new RulesFolowingClosingListener.ContainsRule(line5);
+    private static final RulesFolowingClosingListener.ContainsRule r6 = new RulesFolowingClosingListener.ContainsRule(line6);
 
     private static class AccessiblePrintStream extends PrintStream {
 
@@ -201,7 +202,7 @@
 
                     File f = File.createTempFile("replacedFilelogger", "itwTest");
                     f.deleteOnExit();
-                    oc.setFileLog(new FileLog(f.getAbsolutePath(), false));
+                    oc.setFileLog(new WriterBasedFileLog(f.getAbsolutePath(), false));
                     LogConfig.getLogConfig().setLogToFile(true);
 
                     ThreadGroup tg = new ThreadGroup("TerribleGroup");
@@ -322,7 +323,7 @@
         File f2 = File.createTempFile("replacedFilelogger", "itwTest");
         f1.deleteOnExit();
         f2.deleteOnExit();
-        oc.setFileLog(new FileLog(f1.getAbsolutePath(), false));
+        oc.setFileLog(new WriterBasedFileLog(f1.getAbsolutePath(), false));
         LogConfig.getLogConfig().setLogToFile(true);
         oc.log(OutputController.Level.MESSAGE_ALL, line1);
         oc.log(OutputController.Level.ERROR_ALL, line2);
@@ -338,7 +339,7 @@
         Assert.assertTrue(r3.evaluate(s1));
         Assert.assertFalse(r3.evaluate(s2));
 
-        oc.setFileLog(new FileLog(f2.getAbsolutePath(), false));
+        oc.setFileLog(new WriterBasedFileLog(f2.getAbsolutePath(), false));
         oc.log(OutputController.Level.ERROR_ALL, line5);
         oc.log(OutputController.Level.MESSAGE_ALL, line5);
         oc.flush();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/netx/unit/net/sourceforge/jnlp/util/logging/WriterBasedFileLogTest.java	Tue Oct 27 11:02:45 2015 +0100
@@ -0,0 +1,179 @@
+/*Copyright (C) 2013 Red Hat, Inc.
+
+ This file is part of IcedTea.
+
+ IcedTea is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, version 2.
+
+ IcedTea is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with IcedTea; see the file COPYING.  If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library.  Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module.  An independent module is a module which is not derived from
+ or based on this library.  If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so.  If you do not wish to do so, delete this
+ exception statement from your version.
+ */
+package net.sourceforge.jnlp.util.logging;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import net.sourceforge.jnlp.closinglisteners.RulesFolowingClosingListener;
+import net.sourceforge.jnlp.util.StreamUtils;
+import net.sourceforge.jnlp.util.logging.filelogs.WriterBasedFileLog;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class WriterBasedFileLogTest {
+
+    private static final File[] loggingTargets = new File[12];
+    private static final String line1 = "I'm logged line one";
+    private static final String line2 = "I'm logged line two";
+    private static final String line3 = "I'm logged line three";
+    private static final RulesFolowingClosingListener.ContainsRule r1 = new RulesFolowingClosingListener.ContainsRule(line1);
+    private static final RulesFolowingClosingListener.ContainsRule r2 = new RulesFolowingClosingListener.ContainsRule(line2);
+    private static final RulesFolowingClosingListener.ContainsRule r3 = new RulesFolowingClosingListener.ContainsRule(line3);
+
+    @BeforeClass
+    public static void prepareTmpFiles() throws IOException {
+        for (int i = 0; i < loggingTargets.length; i++) {
+            loggingTargets[i] = File.createTempFile("WriterBasedFileLogger", "iteTest");
+            loggingTargets[i].deleteOnExit();
+        }
+        //delete first half of the files, logger should handle both casses
+        for (int i = 0; i < loggingTargets.length / 2; i++) {
+            loggingTargets[i].delete();
+        }
+
+    }
+
+    @AfterClass
+    public static void cleanTmpFiles() throws IOException {
+        for (int i = 0; i < loggingTargets.length; i++) {
+            loggingTargets[i].delete();
+        }
+    }
+
+    @Test
+    public void isAppendingLoggerLoggingOnNotExisitngFile() throws Exception {
+        int i = 0;
+        WriterBasedFileLog l = new WriterBasedFileLog(loggingTargets[i].getAbsolutePath(), true);
+        l.log(line1);
+        String s = StreamUtils.readStreamAsString(new FileInputStream(loggingTargets[i]), true);
+        Assert.assertTrue(r1.evaluate(s));
+    }
+
+    @Test
+    public void isRewritingLoggerLoggingOnNotExisitngFile() throws Exception {
+        int i = 1;
+        WriterBasedFileLog l = new WriterBasedFileLog(loggingTargets[i].getAbsolutePath(), false);
+        l.log(line1);
+        String s = StreamUtils.readStreamAsString(new FileInputStream(loggingTargets[i]), true);
+        Assert.assertTrue(r1.evaluate(s));
+    }
+
+    @Test
+    public void isRewritingLoggerRewritingOnNotExisitngFile() throws Exception {
+        int i = 2;
+        WriterBasedFileLog l1 = new WriterBasedFileLog(loggingTargets[i].getAbsolutePath(), false);
+        l1.log(line2);
+        String s1 = StreamUtils.readStreamAsString(new FileInputStream(loggingTargets[i]), true);
+        Assert.assertTrue(r2.evaluate(s1));
+        l1.close();
+        WriterBasedFileLog l2 = new WriterBasedFileLog(loggingTargets[i].getAbsolutePath(), false);
+        l2.log(line3);
+        String s2 = StreamUtils.readStreamAsString(new FileInputStream(loggingTargets[i]), true);
+        Assert.assertFalse(r2.evaluate(s2));
+        Assert.assertTrue(r3.evaluate(s2));
+
+    }
+
+    @Test
+    public void isAppendingLoggerAppendingOnNotExisitngFile() throws Exception {
+        int i = 4;
+        WriterBasedFileLog l1 = new WriterBasedFileLog(loggingTargets[i].getAbsolutePath(), true);
+        l1.log(line2);
+        String s1 = StreamUtils.readStreamAsString(new FileInputStream(loggingTargets[i]), true);
+        Assert.assertTrue(r2.evaluate(s1));
+        l1.close();
+        WriterBasedFileLog l2 = new WriterBasedFileLog(loggingTargets[i].getAbsolutePath(), true);
+        l2.log(line3);
+        String s2 = StreamUtils.readStreamAsString(new FileInputStream(loggingTargets[i]), true);
+        Assert.assertTrue(r2.evaluate(s2));
+        Assert.assertTrue(r3.evaluate(s2));
+
+    }
+
+    //************
+    @Test
+    public void isAppendingLoggerLoggingOnExisitngFile() throws Exception {
+        int i = 6;
+        WriterBasedFileLog l = new WriterBasedFileLog(loggingTargets[i].getAbsolutePath(), true);
+        l.log(line1);
+        String s = StreamUtils.readStreamAsString(new FileInputStream(loggingTargets[i]), true);
+        Assert.assertTrue(r1.evaluate(s));
+    }
+
+    @Test
+    public void isRewritingLoggerLoggingOnExisitngFile() throws Exception {
+        int i = 7;
+        WriterBasedFileLog l = new WriterBasedFileLog(loggingTargets[i].getAbsolutePath(), false);
+        l.log(line1);
+        String s = StreamUtils.readStreamAsString(new FileInputStream(loggingTargets[i]), true);
+        Assert.assertTrue(r1.evaluate(s));
+    }
+
+    @Test
+    public void isRewritingLoggerRewritingOnExisitngFile() throws Exception {
+        int i = 8;
+        WriterBasedFileLog l1 = new WriterBasedFileLog(loggingTargets[i].getAbsolutePath(), false);
+        l1.log(line2);
+        String s1 = StreamUtils.readStreamAsString(new FileInputStream(loggingTargets[i]), true);
+        Assert.assertTrue(r2.evaluate(s1));
+        l1.close();
+        WriterBasedFileLog l2 = new WriterBasedFileLog(loggingTargets[i].getAbsolutePath(), false);
+        l2.log(line3);
+        String s2 = StreamUtils.readStreamAsString(new FileInputStream(loggingTargets[i]), true);
+        Assert.assertFalse(r2.evaluate(s2));
+        Assert.assertTrue(r3.evaluate(s2));
+
+    }
+
+    @Test
+    public void isAppendingLoggerAppendingOnExisitngFile() throws Exception {
+        int i = 10;
+        WriterBasedFileLog l1 = new WriterBasedFileLog(loggingTargets[i].getAbsolutePath(), true);
+        l1.log(line2);
+        String s1 = StreamUtils.readStreamAsString(new FileInputStream(loggingTargets[i]), true);
+        Assert.assertTrue(r2.evaluate(s1));
+        l1.close();
+        WriterBasedFileLog l2 = new WriterBasedFileLog(loggingTargets[i].getAbsolutePath(), true);
+        l2.log(line3);
+        String s2 = StreamUtils.readStreamAsString(new FileInputStream(loggingTargets[i]), true);
+        Assert.assertTrue(r2.evaluate(s2));
+        Assert.assertTrue(r3.evaluate(s2));
+
+    }
+}