Improve iPOJO to manage synchronization when a POJO uses service objects.

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@565748 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/ipojo/core/pom.xml b/ipojo/core/pom.xml
index c210e8f..848f73f 100644
--- a/ipojo/core/pom.xml
+++ b/ipojo/core/pom.xml
@@ -61,7 +61,7 @@
               	org.apache.felix.ipojo.handlers.lifecycle.callback,
               	org.objectweb.asm,
               	org.objectweb.asm.commons,
-              	org.objectweb.asm.tree <!-- to remove -->
+              	org.objectweb.asm.tree  <!-- to remove -->
             </Private-Package>
             <Export-Package>
               org.apache.felix.ipojo; version="0.7.3", 
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/Extender.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/Extender.java
index 0b80e0e..dd8fabd 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/Extender.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/Extender.java
@@ -193,6 +193,7 @@
             InstanceCreator creator = (InstanceCreator) m_creators.get(e2.nextElement());

             creator.stop();

         }

+        m_creators = null;

     }

     

     /**

diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java
index b1e3c80..31e7642 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java
@@ -138,7 +138,7 @@
         }
 
         // ComponentInfo initialization
-        m_componentDesc = new ComponentDescription(m_factory.getName(), m_className);
+        m_componentDesc = new ComponentDescription(m_factory.getName(), m_className, m_context.getBundle().getBundleId());
 
         // Add the name
         m_name = (String) configuration.get("name");
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/architecture/ComponentDescription.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/architecture/ComponentDescription.java
index 12234a9..e1f5515 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/architecture/ComponentDescription.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/architecture/ComponentDescription.java
@@ -47,16 +47,23 @@
      * Get the name of this component type.
      */
     private String m_name;
+    
+    /**
+     * Bundle Id of the bundle containing this type.
+     */
+    private long m_bundleId;
 
     /**
      * Constructor.
      * 
      * @param name : name of the component type (factory name).
      * @param className : implementation class.
+     * @param bundle : bundle id.
      */
-    public ComponentDescription(String name, String className) {
+    public ComponentDescription(String name, String className, long bundle) {
         m_name = name;
         m_className = className;
+        m_bundleId = bundle;
     }
 
     /**
@@ -152,6 +159,7 @@
         Element desc = new Element("Factory", "");
         
         desc.addAttribute(new Attribute("name", m_name));
+        desc.addAttribute(new Attribute("bundle", "" + m_bundleId));
         
         if (m_className != null) {
             desc.addAttribute(new Attribute("Implementation-Class", m_className));
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/Dependency.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/Dependency.java
index 26e23b1..649f4b6 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/Dependency.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/Dependency.java
@@ -103,13 +103,6 @@
     private int m_policy = PolicyServiceContext.LOCAL_AND_GLOBAL; 
 
     /**
-     * Array of Service Objects. When cardinality = 1 : just the first element
-     * is returned When cardinality = ?..n : all the array is returned
-     * m_services : Array
-     */
-    private Object[] m_services = new Object[0];
-
-    /**
      * Array of service references.
      * m_ref : Array
      */
@@ -127,12 +120,6 @@
     private int m_state;
 
     /**
-     * True if the reference list change after the creation of a service object
-     * array.
-     */
-    private boolean m_change;
-
-    /**
      * Class of the dependency. 
      * Useful to create in the case of multiple dependency
      */
@@ -147,6 +134,12 @@
      * Service Context in which resolving the dependency.
      */
     private ServiceContext m_serviceContext;
+    
+    
+    /**
+     * Thread Local.
+     */
+    private ServiceUsage m_usage = new ServiceUsage();
 
     /**
      * Dependency constructor. After the creation the dependency is not started.
@@ -244,20 +237,17 @@
     }
 
     /**
-     * Build the List [service reference] of used services.
+     * Build the Set [service reference] of used services.
      * @return the used service.
      */
     public List getUsedServices() {
-        List list = new ArrayList();
-        if (m_isAggregate) {
-            list.addAll(m_usedReferences);
-            return list;
-        } else {
-            if (m_usedReferences.size() != 0 && m_services.length != 0) {
-                list.add(m_usedReferences.get(0));
-            } 
+        List set = new ArrayList();
+        for (int i = 0; i < m_usedReferences.size(); i++) {
+            if (! set.contains(m_usedReferences.get(i))) {
+                set.add(m_usedReferences.get(i));
+            }
         }
-        return list;
+        return set;
     }
 
     /**
@@ -278,105 +268,63 @@
      */
     protected Object get() {
         try {
-            // 1 : Test if there is any change in the reference list :
-            if (!m_change) {
-                if (!m_isAggregate) {
-                    if (m_services.length > 0) {
-                        return m_services[0];
+            // Initialize the thread local object is not already touched.
+            if (m_usage.getObjects().isEmpty()) {
+                if (isAggregate()) {
+                    m_usage.getReferences().addAll(m_references);
+                    for (int i = 0; i < m_references.size(); i++) {
+                        m_usage.getObjects().add(getService((ServiceReference) m_references.get(i)));
                     }
                 } else {
-                    return m_services;
+                    if (!m_references.isEmpty()) {
+                        m_usage.getReferences().add(m_references.get(0));
+                        m_usage.getObjects().add(getService((ServiceReference) m_references.get(0)));
+                    } else {
+                        // Add a nullable object
+                        // Load the nullable class
+                        String className = m_specification + "Nullable";
+                        Class nullableClazz = m_handler.getNullableClass(className);
+
+                        if (nullableClazz == null) {
+                            m_handler.getInstanceManager().getFactory().getLogger().log(
+                                    Logger.INFO,
+                                    "[" + m_handler.getInstanceManager().getClassName()
+                                            + "] Cannot load the nullable class to return a dependency object for "
+                                            + m_field + " -> " + m_specification);
+                            return null;
+                        }
+
+                        // The nullable class is loaded, create the object and add it
+                        Object instance = nullableClazz.newInstance();
+                        m_usage.getObjects().add(instance);
+                    }
                 }
+                m_usage.setStackLevel(1);
             }
 
-            // 2 : Else there is a change in the list -> recompute the
-            // m_services array
-            m_handler.getInstanceManager().getFactory().getLogger().log(Logger.INFO,
-                    "[" + m_handler.getInstanceManager().getClassName() + "] Create a service array of " + m_clazz.getName());
-            
-
-            buildServiceObjectArray();
-
-            m_change = false;
-            // m_handler.getInstanceManager().getFactory().getLogger().log(Logger.INFO,
-            // "[" + m_handler.getInstanceManager().getClassName() + "] Create
-            // an array with the size " + m_services.length);
-
-            // 3 : The service object list is populated, I return either the
-            // first service object, either the array.
-            // Return null or an empty array if no service are found.
             if (!m_isAggregate) {
-                if (m_services.length > 0) {
-                    return m_services[0];
-                } else {
-                    // Load the nullable class
-                    // String[] segment =
-                    // m_metadata.getServiceSpecification().split("[.]");
-                    // String className = "org.apache.felix.ipojo." +
-                    // segment[segment.length - 1] + "Nullable";
-                    String className = m_specification + "Nullable";
-                    // m_handler.getInstanceManager().getFactory().getLogger().log(Logger.INFO,
-                    // "[" + m_handler.getInstanceManager().getClassName() + "]
-                    // Try to load the nullable class for " +
-                    // getMetadata().getServiceSpecification() + " -> " +
-                    // className);
-                    Class nullableClazz = m_handler.getNullableClass(className);
-
-                    if (nullableClazz == null) {
-                        m_handler.getInstanceManager().getFactory().getLogger().log(
-                                Logger.INFO,
-                                "[" + m_handler.getInstanceManager().getClassName() + "] Cannot load the nullable class to return a dependency object for "
-                                        + m_field + " -> " + m_specification);
-                        return null;
-                    }
-
-                    // The nullable class is loaded, create the object and
-                    // return it
-                    Object instance = nullableClazz.newInstance();
-                    // m_handler.getInstanceManager().getFactory().getLogger().log(Logger.INFO,
-                    // "[" + m_handler.getInstanceManager().getClassName() + "]
-                    // Nullable object created for " +
-                    // getMetadata().getServiceSpecification() + " -> " +
-                    // instance);
-                    return instance;
-                }
+                return m_usage.getObjects().get(0);
             } else { // Multiple dependency
-                return m_services;
+                return (Object[]) m_usage.getObjects().toArray((Object[]) Array.newInstance(m_clazz, 0));
             }
+
         } catch (Exception e) {
             // There is a problem in the dependency resolving (like in stopping
             // method)
-            if (!m_isAggregate) {
-                m_handler.getInstanceManager().getFactory().getLogger().log(Logger.ERROR,
-                        "[" + m_handler.getInstanceManager().getClassName() + "] Return null, an exception was throwed in the get method", e);
+            if (!m_isAggregate) { 
+                m_handler.getInstanceManager().getFactory().getLogger().log(Logger.ERROR, "[" + m_handler.getInstanceManager().getClassName() + "] Return null, an exception was throwed in the get method", e);
                 return null;
             } else {
-                m_handler.getInstanceManager().getFactory().getLogger().log(Logger.ERROR,
-                        "[" + m_handler.getInstanceManager().getClassName() + "] Return an empty array, an exception was throwed in the get method", e);
+                m_handler.getInstanceManager().getFactory().getLogger().log(
+                        Logger.ERROR,
+                        "[" + m_handler.getInstanceManager().getClassName()
+                                + "] Return an empty array, an exception was throwed in the get method", e);
                 return Array.newInstance(m_clazz, 0);
             }
         }
     }
 
     /**
-     * Create the service object array according to the resolving policy.
-     */
-    private void buildServiceObjectArray() {
-        if (m_isAggregate) {
-            m_services = (Object[]) Array.newInstance(m_clazz, m_references.size());
-            for (int i = 0; i < m_references.size(); i++) {
-                m_services[i] = getService((ServiceReference) m_references.get(i));
-            }
-        } else {
-            if (m_references.size() == 0) {
-                m_services = new Object[0];
-            } else {
-                m_services = new Object[] { getService((ServiceReference) m_references.get(0)) };
-            }
-        }
-    }
-
-    /**
      * Method called when a service event occurs.
      * 
      * @see org.osgi.framework.ServiceListener#serviceChanged(org.osgi.framework.ServiceEvent)
@@ -428,7 +376,6 @@
         if (isSatisfied()) {
             m_state = RESOLVED;
             if (m_isAggregate || ! m_references.isEmpty()) {
-                m_change = true;
                 callBindMethod(ref);
             }
         }
@@ -437,7 +384,6 @@
 
     /**
      * Method called when a service goes away.
-     * 
      * @param ref : the leaving service reference
      */
     private void departureManagement(ServiceReference ref) {
@@ -447,10 +393,11 @@
             callUnbindMethod(ref);
             // Unget the service reference
             ungetService(ref);
+            m_usedReferences.remove(ref);
             hasChanged = true;
         }
 
-        // Remove from the list (remove on both to be sure.
+        // Remove from the list.
         m_references.remove(ref);
 
         // Is the state valid or invalid
@@ -463,15 +410,10 @@
         // Is there any change ?
         if (!m_isAggregate) {
             if (hasChanged) {
-                m_change = true;
                 if (!m_references.isEmpty()) {
                     callBindMethod((ServiceReference) m_references.get(0));
                 }
-            } else {
-                m_change = false;
             }
-        } else {
-            m_change = true;
         }
 
         m_handler.checkContext();
@@ -529,7 +471,6 @@
      * @param ref : service reference to unget
      */
     private void ungetService(ServiceReference ref) {
-        m_usedReferences.remove(ref);
         m_serviceContext.ungetService(ref);
     }
 
@@ -671,7 +612,6 @@
          
             m_filter = m_handler.getInstanceManager().getContext().createFilter(filter); // Store the filter
             m_handler.getInstanceManager().getFactory().getLogger().log(Logger.INFO, "[" + m_handler.getInstanceManager().getClassName() + "] Create a filter from : " + filter);
-            m_change = true;
         } catch (InvalidSyntaxException e1) {
             m_handler.getInstanceManager().getFactory().getLogger().log(Logger.ERROR,
                     "[" + m_handler.getInstanceManager().getClassName() + "] A filter is malformed : " + filter + " - " + e1.getMessage());
@@ -719,7 +659,6 @@
         m_references.clear();
         m_usedReferences.clear();
         m_clazz = null;
-        m_services = new Object[0];
     }
 
     /**
@@ -768,4 +707,36 @@
         return m_isServiceLevelRequirement;
     }
 
+    /**
+     * Method called when a thread enters in a method.
+     * @param method : method id.
+     */
+    public void entry(String method) {
+        if (! m_usage.getObjects().isEmpty()) {
+            int level = m_usage.getStackLevel();
+            m_usage.setStackLevel(level++);
+        }
+    }
+    
+    /**
+     * Method called when a thread exits a method.
+     * @param method : the method id.
+     */
+    public void exit(String method) {
+        if (! m_usage.getObjects().isEmpty()) {
+            int level = m_usage.getStackLevel();
+            level = level - 1;
+            if (level == 0) {
+                // Exit the method flow => Release all object
+                m_usage.getObjects().clear();
+                List refs = m_usage.getReferences();
+                for (int i = 0; i < refs.size(); i++) {
+                    ServiceReference ref = (ServiceReference) refs.get(i);
+                    ungetService(ref);
+                }
+                refs.clear();
+            }
+        }
+    }
+
 }
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyDescription.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyDescription.java
index 280ff7c..f9dea1b 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyDescription.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyDescription.java
@@ -55,7 +55,7 @@
     private String m_filter;
 
     /**
-     * List[service reference] of the used service.
+     * Set[service reference] of the used service.
      */
     private List m_usedServices = new ArrayList();
 
@@ -111,7 +111,7 @@
     public void setServiceReferences(List sr) { m_serviceReferences = sr; }
 
     /**
-     * Get the used service list.
+     * Get the used service set.
      * @return the list [service reference] containing the used services
      */
     public List getUsedServices() { return m_usedServices; }
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandler.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandler.java
index e5c1d28..7c7f2a3 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandler.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandler.java
@@ -318,7 +318,7 @@
         }
 
         if (deps.length > 0) {
-            m_manager.register(this, (FieldMetadata[]) fl.toArray(new FieldMetadata[0]), null);
+            m_manager.register(this, (FieldMetadata[]) fl.toArray(new FieldMetadata[0]), manipulation.getMethods());
         }
     }
 
@@ -392,6 +392,33 @@
         // Else return the value
         return value;
     }
+    
+    /**
+     * Method Entry callback.
+     * @param methodId : method Id.
+     * @see org.apache.felix.ipojo.Handler#entryCallback(java.lang.String)
+     */
+    public void entryCallback(String methodId) {
+        for (int i = 0; i < m_dependencies.length; i++) {
+            Dependency dep = m_dependencies[i];
+            dep.entry(methodId);
+        }
+    }
+    
+    /**
+     * Method Exit callback.
+     * @param methodId : method id.
+     * @param returnedObj : returned object.
+     * @see org.apache.felix.ipojo.Handler#exitCallback(java.lang.String, java.lang.Object)
+     */
+    public void exitCallback(String methodId, Object returnedObj) {
+        for (int i = 0; i < m_dependencies.length; i++) {
+            Dependency dep = m_dependencies[i];
+            dep.exit(methodId);
+        }
+    }
+    
+    
 
     /**
      * Check the handler validity.
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandlerDescription.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandlerDescription.java
index 6c1bd85..f3905da 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandlerDescription.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandlerDescription.java
@@ -18,6 +18,7 @@
  */
 package org.apache.felix.ipojo.handlers.dependency;
 
+import java.util.Iterator;
 import java.util.List;
 
 import org.apache.felix.ipojo.architecture.HandlerDescription;
@@ -89,7 +90,10 @@
             }
             Element dep = new Element("Requires", "");
             dep.addAttribute(new Attribute("Specification", m_dependencies[i].getInterface()));
-            dep.addAttribute(new Attribute("Filter", m_dependencies[i].getFilter()));
+            
+            if (!m_dependencies[i].getFilter().equals("")) {
+                dep.addAttribute(new Attribute("Filter", m_dependencies[i].getFilter()));
+            }
             
             if (m_dependencies[i].isOptional()) {
                 dep.addAttribute(new Attribute("Optional", "true"));
@@ -104,18 +108,19 @@
             }
             
             dep.addAttribute(new Attribute("State", state));
-            Element usages = new Element("Usages", "");
-            List list = m_dependencies[i].getUsedServices();
-            for (int j = 0; j < list.size(); j++) {
-                Element use = new Element("Use", "");
-                ServiceReference ref = (ServiceReference) list.get(i);
-                use.addAttribute(new Attribute("service.id", (String) ref.getProperty(Constants.SERVICE_ID)));
+            List set = m_dependencies[i].getUsedServices();
+            Iterator it = set.iterator();
+            while (it.hasNext()) {
+                Element use = new Element("Uses", "");
+                ServiceReference ref = (ServiceReference) it.next();
+                use.addAttribute(new Attribute("service.id", ref.getProperty(Constants.SERVICE_ID).toString()));
                 String pid = (String) ref.getProperty(Constants.SERVICE_PID);
                 if (pid != null) {
                     use.addAttribute(new Attribute("service.pid", pid));
                 }
-                usages.addElement(use);
+                dep.addElement(use);
             }
+            
             deps.addElement(dep);
         }
         return deps;
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/ServiceUsage.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/ServiceUsage.java
new file mode 100644
index 0000000..822910b
--- /dev/null
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/ServiceUsage.java
@@ -0,0 +1,97 @@
+/* 

+ * 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.ipojo.handlers.dependency;

+

+import java.util.ArrayList;

+import java.util.List;

+

+/**

+ * Object managing thread local copy of required services.

+ * 

+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>

+ */

+public class ServiceUsage extends ThreadLocal {

+    

+    /**

+     * Structure contained in the Thread Local.

+     */

+    private class Usage {

+        /**

+         * Stack Size.

+         */

+        Integer m_stack = new Integer(0);

+        /**

+         * List of used service references.

+         */

+        List m_refs = new ArrayList();

+        /**

+         * List of used objects.

+         */

+        List m_objects = new ArrayList();

+    }

+    

+    /**

+     * Initialize the cached object.

+     * @return an empty Usage object.

+     * @see java.lang.ThreadLocal#initialValue()

+     */

+    public Object initialValue() {

+        return new Usage();

+    }

+    

+    /**

+     * Get the list of stored references.

+     * @return the list of stored references.

+     */

+    public List getReferences() {

+        Usage use = (Usage) super.get();

+        return use.m_refs;

+    }

+    

+    /**

+     * Get the lost of stored object.

+     * @return the list of stored service objects.

+     */

+    public List getObjects() {

+        Usage use = (Usage) super.get();

+        return use.m_objects;

+    }

+    

+    /**

+     * Get the stack level.

+     * @return the stack level.

+     */

+    public int getStackLevel() {

+        Usage use = (Usage) super.get();

+        return use.m_stack.intValue();

+    }

+    

+    /**

+     * Set the stack level.

+     * @param level : the new stack level.

+     */

+    public void setStackLevel(int level) {

+        Usage use = (Usage) super.get();

+        use.m_stack = new Integer(level);

+    }

+    

+    

+    

+

+}

diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedServiceHandlerDescription.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedServiceHandlerDescription.java
index 2fd6641..bd08f40 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedServiceHandlerDescription.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedServiceHandlerDescription.java
@@ -23,6 +23,7 @@
 import org.apache.felix.ipojo.architecture.HandlerDescription;
 import org.apache.felix.ipojo.metadata.Attribute;
 import org.apache.felix.ipojo.metadata.Element;
+import org.osgi.framework.Constants;
 
 /**
  * Provided Service Handler Description.
@@ -83,10 +84,6 @@
         Element services = super.getHandlerInfo();
         for (int i = 0; i < m_providedServices.length; i++) {
             Element service = new Element("provides", "");
-            String state = "unregistered";
-            if (m_providedServices[i].getState() == ProvidedService.REGISTERED) {
-                state = "registered";
-            }
             String spec = "[";
             for (int j = 0; j < m_providedServices[i].getServiceSpecification().length; j++) {
                 if (j == 0) {
@@ -97,7 +94,14 @@
             }
             spec += "]";
             service.addAttribute(new Attribute("specifications", spec));
-            service.addAttribute(new Attribute("state", state));
+
+            if (m_providedServices[i].getState() == ProvidedService.REGISTERED) {
+                service.addAttribute(new Attribute("state", "registered"));
+                service.addAttribute(new Attribute("service.id", m_providedServices[i].getServiceReference().getProperty(Constants.SERVICE_ID).toString()));
+            } else {
+                service.addAttribute(new Attribute("state", "unregistered"));
+            }
+            
             Iterator it = m_providedServices[i].getProperties().keySet().iterator();
             while (it.hasNext()) {
                 Element prop = new Element("property", "");