You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by cl...@apache.org on 2007/08/14 15:42:20 UTC

svn commit: r565748 - in /felix/trunk/ipojo/core: ./ src/main/java/org/apache/felix/ipojo/ src/main/java/org/apache/felix/ipojo/architecture/ src/main/java/org/apache/felix/ipojo/handlers/dependency/ src/main/java/org/apache/felix/ipojo/handlers/provid...

Author: clement
Date: Tue Aug 14 06:42:19 2007
New Revision: 565748

URL: http://svn.apache.org/viewvc?view=rev&rev=565748
Log:
Improve iPOJO to manage synchronization when a POJO uses service objects.

Added:
    felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/ServiceUsage.java
Modified:
    felix/trunk/ipojo/core/pom.xml
    felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/Extender.java
    felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java
    felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/architecture/ComponentDescription.java
    felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/Dependency.java
    felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyDescription.java
    felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandler.java
    felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandlerDescription.java
    felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedServiceHandlerDescription.java

Modified: felix/trunk/ipojo/core/pom.xml
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/core/pom.xml?view=diff&rev=565748&r1=565747&r2=565748
==============================================================================
--- felix/trunk/ipojo/core/pom.xml (original)
+++ felix/trunk/ipojo/core/pom.xml Tue Aug 14 06:42:19 2007
@@ -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", 

Modified: felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/Extender.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/Extender.java?view=diff&rev=565748&r1=565747&r2=565748
==============================================================================
--- felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/Extender.java (original)
+++ felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/Extender.java Tue Aug 14 06:42:19 2007
@@ -193,6 +193,7 @@
             InstanceCreator creator = (InstanceCreator) m_creators.get(e2.nextElement());
             creator.stop();
         }
+        m_creators = null;
     }
     
     /**

Modified: felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java?view=diff&rev=565748&r1=565747&r2=565748
==============================================================================
--- felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java (original)
+++ felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java Tue Aug 14 06:42:19 2007
@@ -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");

Modified: felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/architecture/ComponentDescription.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/architecture/ComponentDescription.java?view=diff&rev=565748&r1=565747&r2=565748
==============================================================================
--- felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/architecture/ComponentDescription.java (original)
+++ felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/architecture/ComponentDescription.java Tue Aug 14 06:42:19 2007
@@ -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));

Modified: felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/Dependency.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/Dependency.java?view=diff&rev=565748&r1=565747&r2=565748
==============================================================================
--- felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/Dependency.java (original)
+++ felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/Dependency.java Tue Aug 14 06:42:19 2007
@@ -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;
-                }
-            }
-
-            // 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();
+                    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);
 
-            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;
+                        }
 
-                    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);
                     }
-
-                    // 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;
                 }
+                m_usage.setStackLevel(1);
+            }
+
+            if (!m_isAggregate) {
+                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];
     }
 
     /**
@@ -766,6 +705,38 @@
     
     public boolean isServiceLevelRequirement() {
         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();
+            }
+        }
     }
 
 }

Modified: felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyDescription.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyDescription.java?view=diff&rev=565748&r1=565747&r2=565748
==============================================================================
--- felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyDescription.java (original)
+++ felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyDescription.java Tue Aug 14 06:42:19 2007
@@ -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; }

Modified: felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandler.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandler.java?view=diff&rev=565748&r1=565747&r2=565748
==============================================================================
--- felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandler.java (original)
+++ felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandler.java Tue Aug 14 06:42:19 2007
@@ -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.

Modified: felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandlerDescription.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandlerDescription.java?view=diff&rev=565748&r1=565747&r2=565748
==============================================================================
--- felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandlerDescription.java (original)
+++ felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandlerDescription.java Tue Aug 14 06:42:19 2007
@@ -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;

Added: felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/ServiceUsage.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/ServiceUsage.java?view=auto&rev=565748
==============================================================================
--- felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/ServiceUsage.java (added)
+++ felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/ServiceUsage.java Tue Aug 14 06:42:19 2007
@@ -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);
+    }
+    
+    
+    
+
+}

Modified: felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedServiceHandlerDescription.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedServiceHandlerDescription.java?view=diff&rev=565748&r1=565747&r2=565748
==============================================================================
--- felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedServiceHandlerDescription.java (original)
+++ felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedServiceHandlerDescription.java Tue Aug 14 06:42:19 2007
@@ -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", "");