changeset 779:c7bd4f6cf1b7

partially backported singletons logic, logs and test cleanup/fixes, adapted/fixed CacheLRUWrapperTest
author Jiri Vanek <jvanek@redhat.com>
date Fri, 20 Dec 2013 13:25:38 +0100
parents 28cc32272dba
children 28ac9a016c80
files ChangeLog netx/net/sourceforge/jnlp/cache/CacheLRUWrapper.java netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java tests/netx/unit/net/sourceforge/jnlp/cache/CacheLRUWrapperTest.java
diffstat 4 files changed, 89 insertions(+), 36 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Wed Dec 18 16:23:00 2013 +0100
+++ b/ChangeLog	Fri Dec 20 13:25:38 2013 +0100
@@ -1,3 +1,16 @@
+2013-12-20  Jiri Vanek  <jvanek@redhat.com>
+
+	backported singletons logic, logs and test cleanup/fixes
+	adapted/fixed CacheLRUWrapperTest
+	* netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java:
+	config singleton made properly synchronized via Holder pattern
+	(DeploymentConfigurationHolder).
+	* netx/net/sourceforge/jnlp/cache/CacheLRUWrapper.java: (cacheDir) and 
+	(cacheOrder) made package private for testing purposes. 
+	* tests/netx/unit/net/sourceforge/jnlp/cache/CacheLRUWrapperTest.java:
+	True testing cache file is now prepared, tested, and removed. 
+	the CacheLRUWrapper is using this testing repo.
+
 2013-12-17  Jiri Vanek  <jvanek@redhat.com>
 
 	JNLPRuntime.config changed to proper singleton.
--- a/netx/net/sourceforge/jnlp/cache/CacheLRUWrapper.java	Wed Dec 18 16:23:00 2013 +0100
+++ b/netx/net/sourceforge/jnlp/cache/CacheLRUWrapper.java	Fri Dec 20 13:25:38 2013 +0100
@@ -72,15 +72,16 @@
 
     /* location of cache directory */
     private final String setCachePath = JNLPRuntime.getConfiguration().getProperty(DeploymentConfiguration.KEY_USER_CACHE_DIR);
-    private final String cacheDir = new File(setCachePath != null ? setCachePath : System.getProperty("java.io.tmpdir")).getPath();
+    String cacheDir = new File(setCachePath != null ? setCachePath : System.getProperty("java.io.tmpdir")).getPath();
 
     /*
      * back-end of how LRU is implemented This file is to keep track of the most
      * recently used items. The items are to be kept with key = (current time
      * accessed) followed by folder of item. value = path to file.
      */
-    private PropertiesFile cacheOrder = new PropertiesFile(
-            new File(cacheDir + File.separator + "recently_used"));
+    PropertiesFile cacheOrder = new PropertiesFile(
+            new File(cacheDir + File.separator + CACHE_INDEX_FILE_NAME));
+    public static final String CACHE_INDEX_FILE_NAME = "recently_used";
 
     private CacheLRUWrapper(){
         File f = cacheOrder.getStoreFile();
--- a/netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java	Wed Dec 18 16:23:00 2013 +0100
+++ b/netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java	Fri Dec 20 13:25:38 2013 +0100
@@ -81,7 +81,7 @@
  * @version $Revision: 1.19 $
  */
 public class JNLPRuntime {
-    
+
     static {
         loadResources();
     }
@@ -89,8 +89,6 @@
     /** the localized resource strings */
     private static ResourceBundle resources;
 
-    private static DeploymentConfiguration config;
-
     /** the security manager */
     private static JNLPSecurityManager security;
 
@@ -377,26 +375,41 @@
         }
     }
 
+   
+    /**
+     * see https://en.wikipedia.org/wiki/Double-checked_locking#Usage_in_Java
+     * for cases how not to do lazy initialization
+     * and https://en.wikipedia.org/wiki/Initialization_on_demand_holder_idiom
+     * for ITW approach
+     */
+    private static class DeploymentConfigurationHolder {
+
+        private static final DeploymentConfiguration INSTANCE = initConfiguration();
+
+        private static DeploymentConfiguration initConfiguration() {
+            DeploymentConfiguration config = new DeploymentConfiguration();
+            try {
+                config.load();
+                config.copyTo(System.getProperties());
+            } catch (ConfigurationException ex) {
+                ex.printStackTrace();
+                //mark this exceptionas we can die on it later
+                config.setLoadingException(ex);
+            } finally {
+                //noop, 1.5+ starts consumer here
+            }
+            return config;
+        }
+    }
+
     /**
      * Gets the Configuration associated with this runtime
+     *
      * @return a {@link DeploymentConfiguration} object that can be queried to
      * find relevant configuration settings
      */
-    public synchronized static DeploymentConfiguration getConfiguration() {
-        if (config == null){
-            config = new DeploymentConfiguration();
-            try{
-                config.load();
-                config.copyTo(System.getProperties());
-            }catch(ConfigurationException ex){
-                if (JNLPRuntime.isDebug()) {
-                    ex.printStackTrace();
-                }
-                //mark this exceptionas we can die on it later
-                config.setLoadingException(ex);
-            }
-        }
-        return config;
+    public static DeploymentConfiguration getConfiguration() {
+        return DeploymentConfigurationHolder.INSTANCE;
     }
 
     /**
--- a/tests/netx/unit/net/sourceforge/jnlp/cache/CacheLRUWrapperTest.java	Wed Dec 18 16:23:00 2013 +0100
+++ b/tests/netx/unit/net/sourceforge/jnlp/cache/CacheLRUWrapperTest.java	Fri Dec 20 13:25:38 2013 +0100
@@ -42,31 +42,46 @@
 import java.io.File;
 import net.sourceforge.jnlp.ServerAccess;
 
-import net.sourceforge.jnlp.config.DeploymentConfiguration;
-import net.sourceforge.jnlp.runtime.JNLPRuntime;
+import net.sourceforge.jnlp.util.PropertiesFile;
+import org.junit.AfterClass;
 
 import org.junit.BeforeClass;
 import org.junit.Test;
 
 public class CacheLRUWrapperTest {
 
-    private final CacheLRUWrapper clw = CacheLRUWrapper.getInstance();
-    private final String cacheDir = new File(JNLPRuntime.getConfiguration()
-            .getProperty(DeploymentConfiguration.KEY_USER_CACHE_DIR)).getPath();
-
+    private static final CacheLRUWrapper clw = CacheLRUWrapper.getInstance();
+    private static String cacheDirBackup;
+    private static PropertiesFile cacheOrderBackup;
     // does no DeploymentConfiguration exist for this file name? 
-    private final String cacheIndexFileName = "recently_used";
+    private static  final String cacheIndexFileName = CacheLRUWrapper.CACHE_INDEX_FILE_NAME + "_testing";
 
     private final int noEntriesCacheFile = 1000;
 
     @BeforeClass
     static public void setupJNLPRuntimeConfig() {
-        JNLPRuntime.getConfiguration().setProperty(DeploymentConfiguration.KEY_USER_CACHE_DIR, System.getProperty("java.io.tmpdir"));
+        cacheDirBackup = clw.cacheDir;
+        cacheOrderBackup = clw.cacheOrder;
+        clw.cacheDir=System.getProperty("java.io.tmpdir");
+        clw.cacheOrder = new PropertiesFile( new File(clw.cacheDir + File.separator + cacheIndexFileName));
+        
+    }
+    
+    @AfterClass
+    static public void restoreJNLPRuntimeConfig() {
+        clw.cacheDir = cacheDirBackup;
+        clw.cacheOrder = cacheOrderBackup;
     }
     
     @Test
     public void testLoadStoreTiming() throws InterruptedException {
 
+        final File cacheIndexFile = new File(clw.cacheDir + File.separator + cacheIndexFileName);
+        cacheIndexFile.delete();
+        //ensure it exists, so we can lock
+        clw.store();
+        try{
+        
         int noLoops = 1000;
 
         long time[] = new long[noLoops];
@@ -95,15 +110,17 @@
 
         // wait more than 100 microseconds for noLoops = 1000 and noEntries=1000 is bad
         assertTrue("load() must not take longer than 100 µs, but took in avg " + avg/1000 + "µs", avg < 100 * 1000);
-
-        clw.unlock();
+        } finally {
+            clw.unlock();
+            cacheIndexFile.delete();
+        }
     }
 
     private void fillCacheIndexFile(int noEntries) {
 
         // fill cache index file
         for(int i = 0; i < noEntries; i++) {
-            String path = cacheDir + File.separatorChar + i + File.separatorChar + "test" + i + ".jar";
+            String path = clw.cacheDir + File.separatorChar + i + File.separatorChar + "test" + i + ".jar";
             String key = clw.generateKey(path);
             clw.addEntry(key, path);
         }
@@ -112,18 +129,24 @@
     @Test
     public void testModTimestampAfterStore() throws InterruptedException {
 
-        final File cacheIndexFile = new File(cacheDir + File.separator + cacheIndexFileName);
-
+        final File cacheIndexFile = new File(clw.cacheDir + File.separator + cacheIndexFileName);
+        cacheIndexFile.delete();
+        //ensure it exists, so we can lock
+        clw.store();
+        try{
         clw.lock();
         
         // 1. clear cache entries + store
+        clw.addEntry("aa", "bb");
+        clw.store();
         long lmBefore = cacheIndexFile.lastModified();
+        Thread.sleep(1010);
         clearCacheIndexFile();
         long lmAfter = cacheIndexFile.lastModified();
         assertTrue("modification timestamp hasn't changed! Before = " + lmBefore + " After = " + lmAfter, lmBefore < lmAfter);
 
         // FIXME: wait a second, because of file modification timestamp only provides accuracy on seconds.
-        Thread.sleep(1000);
+        Thread.sleep(1010);
 
         // 2. load cache file
         lmBefore = cacheIndexFile.lastModified();
@@ -138,7 +161,10 @@
         lmAfter = cacheIndexFile.lastModified();
         assertTrue("modification timestamp hasn't changed! Before = " + lmBefore + " After = " + lmAfter, lmBefore < lmAfter);
 
-        clw.unlock();
+        } finally {
+            cacheIndexFile.delete();
+            clw.unlock();
+        }
     }
     
     private void clearCacheIndexFile() {