Commit the patch attached to the Felix-1036 issue (FileInstaller spawns multiple watchers for same directory)

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@767421 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/fileinstall/src/main/java/org/apache/felix/fileinstall/ConfigurationKey.java b/fileinstall/src/main/java/org/apache/felix/fileinstall/ConfigurationKey.java
deleted file mode 100644
index f8a4bc0..0000000
--- a/fileinstall/src/main/java/org/apache/felix/fileinstall/ConfigurationKey.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.fileinstall;
-
-public class ConfigurationKey
-{
-    private String factoryId;
-    private String pid;
-
-    public ConfigurationKey(String factoryId, String pid)
-    {
-        this.factoryId = factoryId;
-        this.pid = pid;
-    }
-
-    public int hashCode()
-    {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + ((factoryId == null) ? 0 : factoryId.hashCode());
-        result = prime * result + ((pid == null) ? 0 : pid.hashCode());
-        return result;
-    }
-
-    public boolean equals(Object obj)
-    {
-        if (this == obj)
-        {
-            return true;
-        }
-        if (obj == null)
-        {
-            return false;
-        }
-        if (getClass() != obj.getClass())
-        {
-            return false;
-        }
-        ConfigurationKey other = (ConfigurationKey) obj;
-        if (factoryId == null)
-        {
-            if (other.factoryId != null)
-            {
-                return false;
-            }
-        }
-        else if (!factoryId.equals(other.factoryId))
-        {
-            return false;
-        }
-        if (pid == null)
-        {
-            if (other.pid != null)
-            {
-                return false;
-            }
-        }
-        else if (!pid.equals(other.pid))
-        {
-            return false;
-        }
-        return true;
-    }
-}
\ No newline at end of file
diff --git a/fileinstall/src/main/java/org/apache/felix/fileinstall/DirectoryWatcher.java b/fileinstall/src/main/java/org/apache/felix/fileinstall/DirectoryWatcher.java
index 6eadf1f..60f4ec9 100644
--- a/fileinstall/src/main/java/org/apache/felix/fileinstall/DirectoryWatcher.java
+++ b/fileinstall/src/main/java/org/apache/felix/fileinstall/DirectoryWatcher.java
@@ -54,7 +54,7 @@
  */
 public class DirectoryWatcher extends Thread
 {
-    final static String ALIAS_KEY = "_alias_factory_pid";
+	public final static String FILENAME = "felix.fileinstall.filename";
     public final static String POLL = "felix.fileinstall.poll";
     public final static String DIR = "felix.fileinstall.dir";
     public final static String DEBUG = "felix.fileinstall.debug";
@@ -66,6 +66,8 @@
     boolean startBundles = true; // by default, we start bundles.
     BundleContext context;
     boolean reported;
+    String originatingFileName;
+    
     Map/* <String, Jar> */ currentManagedBundles = new HashMap();
 
     // Represents jars that could not be installed
@@ -74,15 +76,14 @@
     // Represents jars that could not be installed
     Set/* <Bundle> */ startupFailures = new HashSet();
     
-    Map /*<ConfigurationKey, Configuration>*/ configurations = new HashMap();
-
     public DirectoryWatcher(Dictionary properties, BundleContext context)
     {
         super(properties.toString());
         this.context = context;
         poll = getLong(properties, POLL, poll);
         debug = getLong(properties, DEBUG, -1);
-
+        originatingFileName = ( String ) properties.get( FILENAME );
+        
         String dir = (String) properties.get(DIR);
         if (dir == null)
         {
@@ -229,6 +230,7 @@
         String pid[] = parsePid(f.getName());
         Hashtable ht = new Hashtable();
         ht.putAll(p);
+        ht.put(FILENAME, f.getName());
         Configuration config = getConfiguration(pid[0], pid[1]);
         if (config.getBundleLocation() != null)
         {
@@ -251,7 +253,6 @@
         String pid[] = parsePid(f.getName());
         Configuration config = getConfiguration(pid[0], pid[1]);
         config.delete();
-        configurations.remove(new ConfigurationKey(pid[0], pid[1]));
         return true;
     }
 
@@ -280,28 +281,45 @@
     Configuration getConfiguration(String pid, String factoryPid)
         throws Exception
     {
-    	ConfigurationKey ck = new ConfigurationKey(pid, factoryPid);
-    	if (configurations.containsKey(ck))
-    	{
-    		return (Configuration) configurations.get(ck);
-    	}
-    	else
-    	{
-    		ConfigurationAdmin cm = (ConfigurationAdmin) FileInstall.cmTracker.getService();
-    		Configuration newConfiguration = null;
-    		if (factoryPid!=null)
-    		{
-    			newConfiguration = cm.createFactoryConfiguration(pid, null);
-    		}
-    		else
-    		{
-    			newConfiguration = cm.getConfiguration(pid, null);
-    		}
-    		configurations.put(ck, newConfiguration);
-    		return newConfiguration;
-    	}
+	    Configuration oldConfiguration = findExistingConfiguration( pid, factoryPid );
+        if ( oldConfiguration != null )
+        {
+            log( "Updating configuration from " + pid + ( factoryPid == null ? "" : "-" + factoryPid ) + ".cfg", null );
+            return oldConfiguration;
+        }
+        else
+        {
+            ConfigurationAdmin cm = ( ConfigurationAdmin ) FileInstall.cmTracker.getService();
+            Configuration newConfiguration = null;
+            if ( factoryPid != null )
+            {
+                newConfiguration = cm.createFactoryConfiguration( pid, null );
+            }
+            else
+            {
+                newConfiguration = cm.getConfiguration( pid, null );
+            }
+            return newConfiguration;
+        }
     }
     
+    Configuration findExistingConfiguration( String pid, String factoryPid ) throws Exception
+    {
+        String suffix = factoryPid == null ? ".cfg" : "-" + factoryPid + ".cfg";
+
+        ConfigurationAdmin cm = ( ConfigurationAdmin ) FileInstall.cmTracker.getService();
+        String filter = "(" + FILENAME + "=" + pid + suffix + ")";
+        Configuration[] configurations = cm.listConfigurations( filter );
+        if ( configurations != null && configurations.length > 0 )
+        {
+            return configurations[0];
+        }
+        else
+        {
+            return null;
+        }
+    }
+
     /**
      * This is the core of this class.
      * Install bundles that were discovered, uninstall bundles that are gone
diff --git a/fileinstall/src/test/java/org/apache/felix/fileinstall/DirectoryWatcherTest.java b/fileinstall/src/test/java/org/apache/felix/fileinstall/DirectoryWatcherTest.java
index f6ca3ce..062cdae 100644
--- a/fileinstall/src/test/java/org/apache/felix/fileinstall/DirectoryWatcherTest.java
+++ b/fileinstall/src/test/java/org/apache/felix/fileinstall/DirectoryWatcherTest.java
@@ -176,6 +176,9 @@
     public void testGetNewFactoryConfiguration() throws Exception
     {
         mockConfigurationControl.replay();
+        mockConfigurationAdmin.listConfigurations( null );
+        mockConfigurationAdminControl.setMatcher( MockControl.ALWAYS_MATCHER );
+        mockConfigurationAdminControl.setReturnValue( null );
         mockConfigurationAdmin.createFactoryConfiguration( "pid", null );
         mockConfigurationAdminControl.setReturnValue( mockConfiguration );
         mockConfigurationAdminControl.replay();
@@ -198,6 +201,9 @@
     public void testGetExistentFactoryConfiguration() throws Exception
     {
         mockConfigurationControl.replay();
+        mockConfigurationAdmin.listConfigurations( null );
+        mockConfigurationAdminControl.setMatcher( MockControl.ALWAYS_MATCHER );
+        mockConfigurationAdminControl.setReturnValue( null );
         mockConfigurationAdmin.createFactoryConfiguration( "pid", null );
         mockConfigurationAdminControl.setReturnValue( mockConfiguration );
         mockConfigurationAdminControl.replay();
@@ -220,6 +226,9 @@
     public void testGetExistentNoFactoryConfiguration() throws Exception
     {
         mockConfigurationControl.replay();
+        mockConfigurationAdmin.listConfigurations( null );
+        mockConfigurationAdminControl.setMatcher( MockControl.ALWAYS_MATCHER );
+        mockConfigurationAdminControl.setReturnValue( null );
         mockConfigurationAdmin.getConfiguration( "pid", null );
         mockConfigurationAdminControl.setReturnValue( mockConfiguration );
         mockConfigurationAdminControl.replay();
@@ -243,6 +252,9 @@
     {
         mockConfiguration.delete();
         mockConfigurationControl.replay();
+        mockConfigurationAdmin.listConfigurations( null );
+        mockConfigurationAdminControl.setMatcher( MockControl.ALWAYS_MATCHER );
+        mockConfigurationAdminControl.setReturnValue( null );
         mockConfigurationAdmin.getConfiguration( "pid", null );
         mockConfigurationAdminControl.setReturnValue( mockConfiguration );
         mockConfigurationAdminControl.replay();
@@ -281,6 +293,9 @@
             }
         } );
         mockConfigurationControl.replay();
+        mockConfigurationAdmin.listConfigurations( null );
+        mockConfigurationAdminControl.setMatcher( MockControl.ALWAYS_MATCHER );
+        mockConfigurationAdminControl.setReturnValue( null );
         mockConfigurationAdmin.getConfiguration( "firstcfg", null );
         mockConfigurationAdminControl.setReturnValue( mockConfiguration );
         mockConfigurationAdminControl.replay();