Fixed spec compliance issues around getting a service reference from an
invalid registration and throwing an exception when there are duplicate
property keys. (FELIX-798)


git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@709481 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/framework/src/main/java/org/apache/felix/framework/ServiceRegistrationImpl.java b/framework/src/main/java/org/apache/felix/framework/ServiceRegistrationImpl.java
index db50540..c338830 100644
--- a/framework/src/main/java/org/apache/felix/framework/ServiceRegistrationImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/ServiceRegistrationImpl.java
@@ -1,4 +1,4 @@
-/* 
+/*
  * 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
@@ -41,7 +41,7 @@
     // Service factory interface.
     private ServiceFactory m_factory = null;
     // Associated property dictionary.
-    private Map m_propMap =  new StringMap(false);
+    private volatile Map m_propMap = new StringMap(false);
     // Re-usable service reference.
     private ServiceReferenceImpl m_ref = null;
     // Flag indicating that we are unregistering.
@@ -82,6 +82,12 @@
 
     public ServiceReference getReference()
     {
+        // Make sure registration is valid.
+        if (!isValid())
+        {
+            throw new IllegalStateException(
+                "The service registration is no longer valid.");
+        }
         return m_ref;
     }
 
@@ -150,21 +156,10 @@
         return m_propMap.get(key);
     }
 
-    private transient ArrayList m_list = new ArrayList();
-
     protected String[] getPropertyKeys()
     {
-        synchronized (m_propMap)
-        {
-            m_list.clear();
-            Iterator i = m_propMap.entrySet().iterator();
-            while (i.hasNext())
-            {
-                Map.Entry entry = (Map.Entry) i.next();
-                m_list.add(entry.getKey());
-            }
-            return (String[]) m_list.toArray(new String[m_list.size()]);
-        }
+        Set s = m_propMap.keySet();
+        return (String[]) s.toArray(new String[s.size()]);
     }
 
     protected Bundle[] getUsingBundles()
@@ -193,7 +188,8 @@
             catch (Exception ex)
             {
                 m_registry.getLogger().log(
-                    Logger.LOG_ERROR, "ServiceRegistrationImpl: Error getting service.", ex);
+                    Logger.LOG_ERROR,
+                    "ServiceRegistrationImpl: Error getting service.", ex);
                 return null;
             }
         }
@@ -231,24 +227,33 @@
 
     private void initializeProperties(Dictionary dict)
     {
-        synchronized (m_propMap)
+        // Create a case-insensitive map for the properties.
+        Map props = new StringMap(false);
+
+        if (dict != null)
         {
-            m_propMap.clear();
-    
-            if (dict != null)
+            // Make sure there are no duplicate keys.
+            Enumeration keys = dict.keys();
+            while (keys.hasMoreElements())
             {
-                Enumeration keys = dict.keys();
-                while (keys.hasMoreElements())
+                Object key = keys.nextElement();
+                if (props.get(key) == null)
                 {
-                    Object key = keys.nextElement();
-                    m_propMap.put(key, dict.get(key));
+                    props.put(key, dict.get(key));
+                }
+                else
+                {
+                    throw new IllegalArgumentException("Duplicate service property: " + key);
                 }
             }
-    
-            // Add the framework assigned properties.
-            m_propMap.put(Constants.OBJECTCLASS, m_classes);
-            m_propMap.put(Constants.SERVICE_ID, m_serviceId);
         }
+
+        // Add the framework assigned properties.
+        props.put(Constants.OBJECTCLASS, m_classes);
+        props.put(Constants.SERVICE_ID, m_serviceId);
+
+        // Update the service property map.
+        m_propMap = props;
     }
 
     private Object getFactoryUnchecked(Bundle bundle)