diff --git a/org.apache.felix.wireadmin/pom.xml b/org.apache.felix.wireadmin/pom.xml
new file mode 100644
index 0000000..4080b91
--- /dev/null
+++ b/org.apache.felix.wireadmin/pom.xml
@@ -0,0 +1,51 @@
+<project>
+  <parent>
+    <groupId>org.apache.felix</groupId>
+    <artifactId>felix</artifactId>
+    <version>0.8.0-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <packaging>osgi-bundle</packaging>
+  <name>Apache Felix WireAdmin</name>
+  <artifactId>org.apache.felix.wireadmin</artifactId>
+  <dependencies>
+    <dependency>
+      <groupId>${pom.groupId}</groupId>
+      <artifactId>org.osgi.core</artifactId>
+      <version>${pom.version}</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>${pom.groupId}</groupId>
+      <artifactId>org.osgi.compendium</artifactId>
+      <version>${pom.version}</version>
+      <scope>provided</scope>
+    </dependency>
+  </dependencies>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix.plugins</groupId>
+        <artifactId>maven-osgi-plugin</artifactId>
+        <version>${pom.version}</version>
+        <extensions>true</extensions>
+        <configuration>
+          <osgiManifest>
+            <bundleName>WireAdmin</bundleName>
+            <bundleVendor>Apache Software Foundation</bundleVendor>
+            <bundleDescription>
+              Implementation of the WireAdmin Service.
+            </bundleDescription>
+            <bundleActivator>
+              org.apache.felix.wireadmin.Activator
+            </bundleActivator>
+            <bundleSymbolicName>org.apache.felix.wireadmin</bundleSymbolicName>
+            <importPackage>
+              org.osgi.service.wireadmin; specification-version=1.0.0
+            </importPackage>
+          </osgiManifest>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/org.apache.felix.wireadmin/src/main/java/org/apache/felix/wireadmin/Activator.java b/org.apache.felix.wireadmin/src/main/java/org/apache/felix/wireadmin/Activator.java
new file mode 100644
index 0000000..d0e17cb
--- /dev/null
+++ b/org.apache.felix.wireadmin/src/main/java/org/apache/felix/wireadmin/Activator.java
@@ -0,0 +1,125 @@
+/*
+ *   Copyright 2006 The Apache Software Foundation
+ *
+ *   Licensed 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.wireadmin;
+
+import java.util.Dictionary;
+import java.util.Properties;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.wireadmin.WireAdmin;
+import org.osgi.service.wireadmin.WireConstants;
+import org.osgi.service.wireadmin.WireAdminListener;
+import org.osgi.service.wireadmin.WireAdminEvent;
+/**
+ * The activator
+ *
+ * @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+ */
+public class Activator implements BundleActivator {
+
+	private final static String WIREADMIN_PID="org.apache.felix.wireadmin";
+	private ServiceRegistration m_reg=null;
+	private WireAdminImpl m_wai=null;
+	
+	/**
+	 * Called upon starting of the bundle.
+	 *
+	 * @param   context  The bundle context passed by the framework
+	 * @exception   Exception
+	 */
+	public void start(BundleContext bundleContext) throws BundleException {
+		
+        m_wai= new WireAdminImpl(bundleContext);
+
+        // Register the service
+        Dictionary properties=new Properties();
+		properties.put(WireConstants.WIREADMIN_PID,WIREADMIN_PID);
+		m_reg = bundleContext.registerService(WireAdmin.class.getName(),m_wai,properties);
+
+        // Event dispatching does not start until the reference is set        
+        m_wai.setServiceReference(m_reg.getReference());
+
+        if(bundleContext.getProperty("fr.imag.adele.wireadmin.traceEvt") != null)
+        {
+            String value = bundleContext.getProperty("fr.imag.adele.wireadmin.traceEvt");
+            if(value.equals("true"))
+            {
+                Dictionary props=new Properties();
+                props.put(WireConstants.WIREADMIN_EVENTS,new Integer(0x80|0x40|0x20|0x10|0x08|0x04|0x02|0x01));
+                properties.put(WireConstants.WIREADMIN_PID,WIREADMIN_PID);
+                bundleContext.registerService(WireAdminListener.class.getName(),new eventTracer(),props);
+            }
+        }
+	}
+
+    /**
+     * Called upon stopping the bundle.
+     *
+     * @param   context  The bundle context passed by the framework
+     * @exception   Exception
+     */
+	public void stop(BundleContext bundleContext) throws BundleException 
+    {   
+        m_wai.releaseAll();
+        m_wai = null;
+	}
+
+    class eventTracer implements WireAdminListener
+    {
+        public void wireAdminEvent(WireAdminEvent evt)
+        {
+            int type = evt.getType();
+            if((type & WireAdminEvent.WIRE_CREATED)!=0)
+            {
+                WireAdminImpl.traceln("Received event WIRE_CREATED");
+            }
+            if((type & WireAdminEvent.WIRE_CONNECTED)!=0)
+            {
+                WireAdminImpl.traceln("Received event WIRE_CONNECTED");
+            }
+            if((type & WireAdminEvent.WIRE_UPDATED)!=0)
+            {
+                WireAdminImpl.traceln("Received event WIRE_UPDATED");
+            }
+            if((type & WireAdminEvent.WIRE_TRACE)!=0)
+            {
+                WireAdminImpl.traceln("Received event WIRE_TRACE");
+            }
+            if((type & WireAdminEvent.WIRE_DISCONNECTED)!=0)
+            {
+                WireAdminImpl.traceln("Received event WIRE_DISCONNECTED");
+            }
+            if((type & WireAdminEvent.WIRE_DELETED)!=0)
+            {
+                WireAdminImpl.traceln("Received event WIRE_DELETED");
+            }
+            if((type & WireAdminEvent.PRODUCER_EXCEPTION)!=0)
+            {
+                WireAdminImpl.traceln("Received event PRODUCER_EXCEPTION");
+                evt.getThrowable().printStackTrace();
+            }
+            if((type & WireAdminEvent.CONSUMER_EXCEPTION)!=0)
+            {
+                WireAdminImpl.traceln("Received event CONSUMER_EXCEPTION");
+                evt.getThrowable().printStackTrace();
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/org.apache.felix.wireadmin/src/main/java/org/apache/felix/wireadmin/EventManager.java b/org.apache.felix.wireadmin/src/main/java/org/apache/felix/wireadmin/EventManager.java
new file mode 100644
index 0000000..2fe530e
--- /dev/null
+++ b/org.apache.felix.wireadmin/src/main/java/org/apache/felix/wireadmin/EventManager.java
@@ -0,0 +1,266 @@
+/*
+ *   Copyright 2006 The Apache Software Foundation
+ *
+ *   Licensed 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.wireadmin;
+
+import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.BundleContext;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import org.osgi.service.wireadmin.WireAdminEvent;
+import org.osgi.service.wireadmin.WireAdminListener;
+import org.osgi.service.wireadmin.WireConstants;
+
+/**
+ * Class that tracks listeners and manages event dispatching 
+ * 
+ * @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+ */
+class EventManager implements ServiceListener
+{
+    // <ServiceReference,WireAdminListener>
+    private Map m_wireAdminListeners = new HashMap();
+
+    // The bundle context
+    private BundleContext m_bundleContext;
+    
+    // Asynchronous dispatcher
+    private AsyncDispatcher m_eventDispatcher = new AsyncDispatcher();
+       
+    // Service reference from the WireAdmin service
+    private ServiceReference m_ref;
+    
+    /**
+     * The constructor receives the bundle context and a service reference
+     * corresponding to the wire admin service
+     * 
+     * @param ctxt
+     * @param ref
+     */
+    EventManager(BundleContext ctxt)
+    {
+        m_bundleContext = ctxt;
+        ServiceReference [] serviceRefs = null;
+        
+        try
+        {
+            m_bundleContext.addServiceListener(this,"(objectClass=org.osgi.service.wireadmin.WireAdminListener)");
+            serviceRefs = m_bundleContext.getServiceReferences(WireAdminListener.class.getName(),null);
+        }
+        catch(Exception ex)
+        {
+            // Exception never thrown since filter is correct
+        }        
+
+        if(serviceRefs != null)
+        {
+            // lock the producers Map to avoid concurrent modifications due
+            // to service events
+            synchronized(m_wireAdminListeners)
+            {
+                for(int i=0;i<serviceRefs.length;i++)
+                {
+                    ServiceReference currentRef=(ServiceReference)serviceRefs[i];
+                    
+                    m_wireAdminListeners.put(currentRef,m_bundleContext.getService(currentRef));
+                }
+            }
+        }        
+    }
+    
+    /**
+     * When the service reference is set the event dispatching thread is
+     * started. This is necessary since events require m_ref to be set
+     * 
+     * @param ref <tt>ServiceReference</tt> to the wire admin service.
+     */
+    void setServiceReference(ServiceReference ref)
+    {
+        m_ref = ref;
+
+        // Activate thread that does asynchronous calls to
+        // the producersConnected and consummersConnected methods
+        new Thread(m_eventDispatcher).start();
+    }
+    
+    /**
+     * Stop the event manager
+     *
+     */
+    void stop()
+    {
+        m_eventDispatcher.stop();
+    }
+    
+    /**
+     * Tracks Listener changes
+     */
+    public void serviceChanged(ServiceEvent e) 
+    {
+        ServiceReference serviceRef = e.getServiceReference();
+        switch (e.getType()) 
+        {
+            case ServiceEvent.REGISTERED:
+                synchronized(m_wireAdminListeners)
+                {
+                    m_wireAdminListeners.put(serviceRef,m_bundleContext.getService(serviceRef));
+                }
+                break;
+            case ServiceEvent.UNREGISTERING:
+            synchronized(m_wireAdminListeners)
+                {
+                    m_wireAdminListeners.remove(serviceRef);
+                }
+                break;
+            case ServiceEvent.MODIFIED:
+                // Not necessary
+                break;
+        }
+    }
+    
+    /**
+     * Fire an event
+     * 
+     * @param eventType (see WireAdminEvent)
+     * @param wire the wire
+     */
+    void fireEvent(int eventType,WireImpl wire) 
+    {
+        fireEvent(eventType, wire, null);
+    }
+
+    /**
+     * Fire an event that contains an exception
+     * 
+     * @param eventType
+     * @param wire
+     * @param exception
+     */
+    void fireEvent(int eventType,WireImpl wire, Throwable exception) 
+    {
+        WireAdminEvent evt = new WireAdminEvent(m_ref,eventType,wire,exception);
+        m_eventDispatcher.queueEvent(evt);
+    }
+
+    /**
+     * p. 345 "A WireAdminEvent object can be sent asynchronously but must be
+     * ordered for each WireAdminListener service"
+     * But the API doc says "WireAdminEvent objects are delivered asynchronously 
+     * to all registered WireAdminListener service objects which specify an 
+     * interest in the WireAdminEvent type."
+     * We choose asynchronous delivery to be safe
+     *
+    **/
+    class AsyncDispatcher implements Runnable
+    {
+        private boolean m_stop = false;
+        private boolean m_empty = true;
+
+        private List m_eventStack = new ArrayList();
+
+        public void run()
+        {
+            while (m_stop == false || (m_stop == true && m_empty == false))
+            {
+                WireAdminEvent nextEvent = null;
+
+                synchronized (m_eventStack)
+                {
+                    while (m_eventStack.size() == 0)
+                    {
+                        try
+                        {
+                            m_eventStack.wait();
+                        } 
+                        catch (InterruptedException ex)
+                        {
+                            // Ignore.
+                        }
+                    }
+                    nextEvent = (WireAdminEvent) m_eventStack.remove(0);
+                    
+                    if(m_eventStack.size()==0)
+                    {
+                        // This allows the queue to be flushed upon termination
+                        m_empty = true;
+                    }
+                }
+                
+                synchronized (m_wireAdminListeners)
+                {
+                    Iterator listenerIt = m_wireAdminListeners.keySet().iterator();
+                    while(listenerIt.hasNext())
+                    {
+                        ServiceReference listenerRef = (ServiceReference)listenerIt.next();
+                        WireAdminListener listener = (WireAdminListener)m_wireAdminListeners.get(listenerRef);
+                        
+                        try
+                        {
+                            Integer evtsInteger = (Integer) listenerRef.getProperty(WireConstants.WIREADMIN_EVENTS);
+                            if(evtsInteger != null)
+                            {
+                                int events = evtsInteger.intValue();
+                                if((nextEvent.getType()&events)!=0)
+                                {
+                                    listener.wireAdminEvent(nextEvent);
+                                }                            
+                            }
+                            else
+                            {
+                                WireAdminImpl.trace(new Exception("Listener with no WIREADMIN_EVENTS"+listenerRef));
+                            }
+                        }
+                        catch(ClassCastException ex)
+                        {
+                            WireAdminImpl.trace("Listener returned WIREADMIN_EVENTS of wrong type:"+ex);
+                        }
+                    }
+                }
+            }
+        }
+
+        /**
+         * Queue an event on the stack
+         * 
+         * @param evt the event
+         */
+        public void queueEvent(WireAdminEvent evt)
+        {
+            synchronized (m_eventStack)
+            {
+                m_eventStack.add(evt);
+                m_empty = false;
+                m_eventStack.notify();
+            }
+        }
+
+        /**
+         * stop the dispatcher
+         *
+         */
+        void stop()
+        {
+            m_stop = true;
+        }
+    }
+}
\ No newline at end of file
diff --git a/org.apache.felix.wireadmin/src/main/java/org/apache/felix/wireadmin/WireAdminImpl.java b/org.apache.felix.wireadmin/src/main/java/org/apache/felix/wireadmin/WireAdminImpl.java
new file mode 100644
index 0000000..eaf95fd
--- /dev/null
+++ b/org.apache.felix.wireadmin/src/main/java/org/apache/felix/wireadmin/WireAdminImpl.java
@@ -0,0 +1,1034 @@
+/*
+ *   Copyright 2006 The Apache Software Foundation
+ *
+ *   Licensed 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.wireadmin;
+
+import java.io.PrintStream;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Enumeration;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Filter;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.wireadmin.Consumer;
+import org.osgi.service.wireadmin.Producer;
+import org.osgi.service.wireadmin.Wire;
+import org.osgi.service.wireadmin.WireAdmin;
+import org.osgi.service.wireadmin.WireConstants;
+import org.osgi.service.wireadmin.WireAdminEvent;
+
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileNotFoundException;
+
+/**
+ * Wire Administration service.
+ *
+ * <p>This service can be used to create <tt>Wire</tt> objects connecting
+ * a Producer service and a Consumer service.
+ * <tt>Wire</tt> objects also have wire properties that may be specified
+ * when a <tt>Wire</tt> object is created. The Producer and Consumer
+ * services may use the <tt>Wire</tt> object's properties to manage or control their
+ * interaction.
+ * The use of <tt>Wire</tt> object's properties by a Producer or Consumer
+ * services is optional.
+ *
+ * <p>Security Considerations.
+ * A bundle must have <tt>ServicePermission[GET,WireAdmin]</tt> to get the Wire Admin service to
+ * create, modify, find, and delete <tt>Wire</tt> objects.
+ *
+ * @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+ */
+public class WireAdminImpl implements WireAdmin, ServiceListener {
+
+	private BundleContext m_bundleContext;
+
+    // A Map containing a service reference associated to a producer and a List
+    // of wire objects	
+    private Map m_consumers = new HashMap(); /* ServiceReferences, List */
+	
+    private Map m_producers = new HashMap(); /* ServiceReferences, List */
+
+	private List m_wires; // List containing the wires
+
+	//private BindingController wireAdminListenersBindingController;
+
+    // Filter corresponding to a consumer service
+	private Filter m_consumerFilter;
+    
+    //  Filter corresponding to a producer service
+	private Filter m_producerFilter;
+
+    // EventManager
+    private EventManager m_eventManager;
+
+	private static int m_wireCount = 0;
+    
+    private AsyncMethodCaller m_asyncMethodCaller = new AsyncMethodCaller();        //m_eventDispatcher.stop();
+    
+    private static PrintStream m_traceout = null;
+    
+    private static PrintStream m_errorout = System.err;
+
+	/**
+     * Constructor with package visibility
+     * 
+	 * @param bundleContext the bundle context
+	 */
+	WireAdminImpl(BundleContext bundleContext) 
+    {
+		m_bundleContext = bundleContext;
+        
+        if(bundleContext.getProperty("fr.imag.adele.wireadmin.trace") != null)
+        {
+            String value = bundleContext.getProperty("fr.imag.adele.wireadmin.trace");
+            if(value.equals("true"))
+            {
+                m_traceout = System.out;
+            }
+        }
+        // Create the event manager (the event manager will start its own thread)       
+        m_eventManager = new EventManager(m_bundleContext);
+        
+		try 
+        {
+			m_producerFilter = m_bundleContext.createFilter(
+					"(objectClass=org.osgi.service.wireadmin.Producer)");
+			m_consumerFilter = m_bundleContext.createFilter(
+					"(objectClass=org.osgi.service.wireadmin.Consumer)");
+		} 
+        catch (InvalidSyntaxException e) 
+        {
+			// never thrown since LDAP expressions are correct
+		}
+
+        // Recover persistent wires
+        getPersistentWires();
+
+        // Activate thread that does asynchronous calls to
+        // the producersConnected and consummersConnected methods
+        new Thread(m_asyncMethodCaller).start();
+
+        // Gets all producers and consumers that are present at the
+        // moment the wire admin is created
+        try 
+        {
+            // Registration for events must be done first, as some service
+            // can be registered during initialization
+            
+            m_bundleContext.addServiceListener(this,"(|"+m_producerFilter.toString()+m_consumerFilter.toString()+")");
+
+            // Replacement for the two following lines which work under OSCAR, 
+            // but not work under IBM's SMF
+            //m_bundleContext.addServiceListener(this,m_consumerFilter.toString());
+            //m_bundleContext.addServiceListener(this,m_producerFilter.toString());
+            
+            // Get all producers
+            ServiceReference[] producerRefs = m_bundleContext.getServiceReferences(Producer.class.getName(),null);
+            
+            if(producerRefs!=null)
+            {
+                // lock the producers Map to avoid concurrent modifications due
+                // to service events
+                synchronized(m_producers)
+                {
+                    for(int i=0;i<producerRefs.length;i++)
+                    {
+                        ServiceReference currentRef=(ServiceReference)producerRefs[i];
+                        
+                        Iterator wireIt = m_wires.iterator();
+                        while(wireIt.hasNext())
+                        {
+                            WireImpl currentWire = (WireImpl) wireIt.next();
+                            if(currentWire.getProducerPID().equals(currentRef.getProperty(Constants.SERVICE_PID)))
+                            {
+                                currentWire.bindProducer(currentRef);
+                            }
+                        }
+                        m_producers.put(currentRef,new ArrayList());
+                    }
+                }
+            }
+
+            // Get all the consumers
+            ServiceReference[] consumerRefs = m_bundleContext.getServiceReferences(Consumer.class.getName(),null);
+            
+            if(consumerRefs!=null)
+            {
+                for(int i=0;i<consumerRefs.length;i++)
+                {
+                    // lock the consumers to avoid concurrent modifications due
+                    // to service events
+                    synchronized(m_consumers)
+                    {
+                        ServiceReference currentRef=(ServiceReference)consumerRefs[i];
+
+                        Iterator wireIt = m_wires.iterator();
+                        while(wireIt.hasNext())
+                        {
+                            WireImpl currentWire = (WireImpl) wireIt.next();
+                            if(currentWire.getConsumerPID().equals(currentRef.getProperty(Constants.SERVICE_PID)))
+                            {
+                                currentWire.bindConsumer(currentRef);
+                            }
+                        }
+                        m_consumers.put(currentRef,new ArrayList());
+                    }
+                }
+            }
+        } 
+        catch (InvalidSyntaxException e) 
+        {
+            trace(e);
+        }
+
+        // Iterate over all the wires, when a wire is connected
+        // add it to the list of wires associated to a particular
+        // producer or consumer
+        synchronized(m_wires)
+        {
+            Iterator wireIterator = m_wires.iterator();
+            while(wireIterator.hasNext())
+            {
+                WireImpl currentWire = (WireImpl) wireIterator.next();
+                if(currentWire.isConnected())
+                {                
+                    // p. 327 "If both Producer and consumer services are registered
+                    // with the framework, they are connected by the WireAdmin service"
+                    List wires = (List) m_producers.get(currentWire.getProducerServiceRef());
+                    wires.add(currentWire);
+                    m_asyncMethodCaller.consumersConnected(currentWire.getProducer(),(Wire[])wires.toArray(new Wire[wires.size()]));
+                    
+                    wires = (List) m_consumers.get(currentWire.getConsumerServiceRef());
+                    wires.add(currentWire);
+                    m_asyncMethodCaller.producersConnected(currentWire.getConsumer(),(Wire[])wires.toArray(new Wire[wires.size()]));
+                }            
+            }
+        }       
+	}
+    
+    /**
+     * Pass the service reference to the event dispatcher
+     * 
+     * @param ref the service reference
+     */
+    void setServiceReference(ServiceReference ref)
+    {
+        m_eventManager.setServiceReference(ref);
+    }
+
+	/**
+	 * Create a new <tt>Wire</tt> object that connects a Producer
+	 * service to a Consumer service.
+	 *
+	 * The Producer service and Consumer service do not
+	 * have to be registered when the <tt>Wire</tt> object is created.
+	 *
+	 * <p>The <tt>Wire</tt> configuration data must be persistently stored.
+	 * All <tt>Wire</tt> connections are reestablished when the
+	 * <tt>WireAdmin</tt> service is registered.
+	 * A <tt>Wire</tt> can be permanently removed by using the
+	 * {@link #deleteWire} method.
+	 *
+	 * <p>The <tt>Wire</tt> object's properties must have case
+	 * insensitive <tt>String</tt> objects as keys (like the Framework).
+	 * However, the case of the key must be preserved.
+	 * The type of the value of the property must be one of the following:
+	 *
+	 * <pre>
+	 * type        = basetype
+	 *  | vector | arrays
+	 *
+	 * basetype = String | Integer | Long
+	 *  | Float | Double | Byte
+	 *  | Short | Character
+	 *  | Boolean
+	 *
+	 * primitive   = long | int | short
+	 *  | char | byte | double | float
+	 *
+	 * arrays   = primitive '[]' | basetype '[]'
+	 *
+	 * vector   = Vector of basetype
+	 * </pre>
+	 *
+	 * <p>The <tt>WireAdmin</tt> service must automatically add the
+	 * following <tt>Wire</tt> properties:
+	 * <ul>
+	 * <li>
+	 * {@link WireConstants#WIREADMIN_PID} set to the value of the <tt>Wire</tt> object's
+	 * persistent identity (PID). This value is generated by the
+	 * Wire Admin service when a <tt>Wire</tt> object is created.
+	 * </li>
+	 * <li>
+	 * {@link WireConstants#WIREADMIN_PRODUCER_PID} set to the value of
+	 * Producer service's PID.
+	 * </li>
+	 * <li>
+	 * {@link WireConstants#WIREADMIN_CONSUMER_PID} set to the value of
+	 * Consumer service's PID.
+	 * </li>
+	 * </ul>
+	 * If the <tt>properties</tt> argument
+	 * already contains any of these keys, then the supplied values
+	 * are replaced with the values assigned by the Wire Admin service.
+	 *
+	 * <p>The Wire Admin service must broadcast a <tt>WireAdminEvent</tt> of type
+	 * {@link WireAdminEvent#WIRE_CREATED}
+	 * after the new <tt>Wire</tt> object becomes available from {@link #getWires}.
+	 *
+	 * @param producerPID The <tt>service.pid</tt> of the Producer service
+	 * to be connected to the <tt>Wire</tt> object.
+	 * @param consumerPID The <tt>service.pid</tt> of the Consumer service
+	 * to be connected to the <tt>Wire</tt> object.
+	 * @param properties The <tt>Wire</tt> object's properties. This argument may be <tt>null</tt>
+	 * if the caller does not wish to define any <tt>Wire</tt> object's properties.
+	 * @return The <tt>Wire</tt> object for this connection.
+	 * @throws java.lang.IllegalArgumentException If
+	 * <tt>properties</tt> contains case variants of the same key name.
+	 */
+	public Wire createWire(String producerPID, String consumerPID, Dictionary props) 
+    {
+        ServiceReference producerServiceRef = null;
+        ServiceReference consumerServiceRef = null;
+
+        Dictionary properties;
+        
+        if(props == null)
+        {
+        	properties = new Hashtable();
+        }
+        else
+        {
+        	//Clone the dictionary
+        	properties = cloneProperties(props);
+        }
+
+        // Addition of mandatory properties
+        properties.put(WireConstants.WIREADMIN_CONSUMER_PID, consumerPID);
+        properties.put(WireConstants.WIREADMIN_PRODUCER_PID, producerPID);
+        properties.put(WireConstants.WIREADMIN_PID, generateWirePID());
+
+        // p.327 "Wire objects can be created when the producer or consumer
+        // service is not registered
+        WireImpl wire = new WireImpl(producerPID, consumerPID, properties);
+
+        // Initialize the wire
+        wire.initialize(m_bundleContext,m_eventManager);
+
+        // Add the wire to the list 
+        synchronized(m_wires)
+        {
+            m_wires.add(wire);            
+        }
+
+        // p. 357 "The Wire Admin service must broadcast a WireAdminEvent of 
+        // type WireAdminEvent.WIRE_CREATED  after the new Wire object becomes 
+        // available from getWires(java.lang.String)."
+        m_eventManager.fireEvent(WireAdminEvent.WIRE_CREATED,wire);
+
+        synchronized (m_producers)
+        {
+            Iterator producerIterator = m_producers.keySet().iterator();
+            while(producerIterator.hasNext())
+            {
+                producerServiceRef = (ServiceReference) producerIterator.next();
+                if (producerServiceRef.getProperty(Constants.SERVICE_PID).equals(producerPID)) 
+                {
+                    wire.bindProducer(producerServiceRef);                    
+                    break;
+                }
+            }
+        }        
+        
+        synchronized (m_consumers)
+        {
+            Iterator consumerIterator = m_consumers.keySet().iterator();
+            while(consumerIterator.hasNext())
+            {
+                consumerServiceRef = (ServiceReference) consumerIterator.next();
+                if (consumerServiceRef.getProperty(Constants.SERVICE_PID).equals(consumerPID)) 
+                {
+                    wire.bindConsumer(consumerServiceRef);
+                    break;
+                }
+                
+            }
+        }
+        
+        
+        // p.327 If both Producer and Consumer services are registered, they are 
+        // connected by the wire admin service. 
+        if(wire.isConnected())
+        {
+            List wires = (List) m_producers.get(producerServiceRef);
+            wires.add(wire);
+            m_asyncMethodCaller.consumersConnected(wire.getProducer(),(Wire[])wires.toArray(new Wire[wires.size()]));
+
+            wires = (List) m_consumers.get(consumerServiceRef);
+            wires.add(wire);
+            m_asyncMethodCaller.producersConnected(wire.getConsumer(),(Wire[])wires.toArray(new Wire[wires.size()]));
+        }
+
+        // Newly created wires are immediately persisted to avoid information
+        // loss in case of crashes.  (spec not clear about this)        
+        persistWires();
+
+        return wire;
+    }
+
+	/**
+	 * Delete a <tt>Wire</tt> object.
+	 *
+	 * <p>The <tt>Wire</tt> object representing a connection between
+	 * a Producer service and a Consumer service must be
+	 * removed.
+	 * The persistently stored configuration data for the <tt>Wire</tt> object
+	 * must destroyed. The <tt>Wire</tt> object's method {@link Wire#isValid} will return <tt>false</tt>
+	 * after it is deleted.
+	 *
+	 * <p>The Wire Admin service must broadcast a <tt>WireAdminEvent</tt> of type
+	 * {@link WireAdminEvent#WIRE_DELETED}
+	 * after the <tt>Wire</tt> object becomes invalid.
+	 *
+	 * @param wire The <tt>Wire</tt> object which is to be deleted.
+	 */
+	public void deleteWire(Wire wire) 
+    {
+        if(m_wires.contains(wire))
+        {
+            WireImpl wireImpl = (WireImpl) wire;
+            m_wires.remove(wire);
+            if(wireImpl.isConnected())
+            {
+                List wires = (List) m_producers.get(wireImpl.getProducerServiceRef());
+                wires.remove(wireImpl);
+                m_asyncMethodCaller.consumersConnected(wireImpl.getProducer(),(Wire[])wires.toArray(new Wire[wires.size()]));
+
+                wires = (List) m_consumers.get(wireImpl.getConsumerServiceRef());
+                wires.remove(wireImpl);
+                m_asyncMethodCaller.producersConnected(wireImpl.getConsumer(),(Wire[])wires.toArray(new Wire[wires.size()]));
+            }
+            
+            wireImpl.invalidate();
+
+            // fire an event
+            m_eventManager.fireEvent(WireAdminEvent.WIRE_DELETED,wireImpl);
+            
+            // Persist state to avoid losses in case of crashes (spec not clear about this).        
+            persistWires();
+        }
+        else
+        {
+            traceln("WireAdminImpl: Cannot delete a wire that is not managed by this service");
+        }
+
+	}
+
+	/**
+	 * Update the properties of a <tt>Wire</tt> object.
+	 *
+	 * The persistently stored configuration data for the <tt>Wire</tt> object
+	 * is updated with the new properties and then the Consumer and Producer
+	 * services will be called at the respective {@link Consumer#producersConnected}
+	 * and {@link Producer#consumersConnected} methods.
+	 *
+	 * <p>The Wire Admin service must broadcast a <tt>WireAdminEvent</tt> of type
+	 * {@link WireAdminEvent#WIRE_UPDATED}
+	 * after the updated properties are available from the <tt>Wire</tt> object.
+	 *
+	 * @param wire The <tt>Wire</tt> object which is to be updated.
+	 * @param properties The new <tt>Wire</tt> object's properties or <tt>null</tt> if no properties are required.
+	 */
+	public void updateWire(Wire wire, Dictionary props) 
+    {
+        if(m_wires.contains(wire) == false)
+        {
+            traceln("WireAdminImpl: Cannot update a wire that is not managed by this service");
+            return;
+        }
+        
+        // Clone the dictionary
+        Dictionary properties = cloneProperties(props);
+
+        // Put again the mandatory properties, in case they are not set
+        properties.put(WireConstants.WIREADMIN_CONSUMER_PID,wire.getProperties().get(WireConstants.WIREADMIN_CONSUMER_PID));
+        properties.put(WireConstants.WIREADMIN_PRODUCER_PID,wire.getProperties().get(WireConstants.WIREADMIN_PRODUCER_PID));
+        properties.put(WireConstants.WIREADMIN_PID,wire.getProperties().get(WireConstants.WIREADMIN_PID));
+        
+        WireImpl wireImpl = (WireImpl) wire;
+        
+        wireImpl.updateProperties(properties);
+        
+        // Call methods on Consumer and Producer
+        if(wireImpl.isConnected())
+        {
+            List wires = (List) m_producers.get(wireImpl.getProducerServiceRef());
+            m_asyncMethodCaller.consumersConnected(wireImpl.getProducer(),(Wire[])wires.toArray(new Wire[wires.size()]));
+
+            wires = (List) m_consumers.get(wireImpl.getConsumerServiceRef());
+            m_asyncMethodCaller.producersConnected(wireImpl.getConsumer(),(Wire[])wires.toArray(new Wire[wires.size()]));
+        }
+
+        // fire an event
+        m_eventManager.fireEvent(WireAdminEvent.WIRE_UPDATED,wireImpl);
+	}
+
+	/**
+	 * Return the <tt>Wire</tt> objects that match the given <tt>filter</tt>.
+	 *
+	 * <p>The list of available <tt>Wire</tt> objects is matched against the
+	 * specified <tt>filter</tt>. <tt>Wire</tt> objects which match the
+	 * <tt>filter</tt> must be returned. These <tt>Wire</tt> objects are not necessarily
+	 * connected. The Wire Admin service should not return
+	 * invalid <tt>Wire</tt> objects, but it is possible that a <tt>Wire</tt>
+	 * object is deleted after it was placed in the list.
+	 *
+	 * <p>The filter matches against the <tt>Wire</tt> object's properties including
+	 * {@link WireConstants#WIREADMIN_PRODUCER_PID}, {@link WireConstants#WIREADMIN_CONSUMER_PID}
+	 * and {@link WireConstants#WIREADMIN_PID}.
+	 *
+	 * @param filter Filter string to select <tt>Wire</tt> objects
+	 * or <tt>null</tt> to select all <tt>Wire</tt> objects.
+	 * @return An array of <tt>Wire</tt> objects which match the <tt>filter</tt>
+	 * or <tt>null</tt> if no <tt>Wire</tt> objects match the <tt>filter</tt>.
+	 * @throws org.osgi.framework.InvalidSyntaxException If the specified <tt>filter</tt>
+	 * has an invalid syntax.
+	 * @see org.osgi.framework.Filter
+	 */
+	public Wire[] getWires(String filter) throws InvalidSyntaxException 
+    {
+		List res = null;
+		if (filter == null) 
+        {
+            return (Wire [])m_wires.toArray(new Wire[m_wires.size()]);
+		} 
+        else 
+        {
+			Filter tempFilter = m_bundleContext.createFilter(filter);
+			Iterator iter = m_wires.iterator();
+			while (iter.hasNext()) 
+            {
+				WireImpl currentWire = (WireImpl) iter.next();
+				if (tempFilter.match(currentWire.getProperties())) 
+                {
+					if (res == null)
+                    {
+						res = new ArrayList();
+                    }
+					res.add(currentWire);
+				}
+			}
+		}
+		if (res == null) 
+        {
+			return null;
+		} 
+        else 
+        {
+            return (Wire [])res.toArray(new Wire[res.size()]);
+		}
+	}
+
+    /**
+     * listens Producer and Consumer services changes
+     * @see org.osgi.framework.ServiceListener#serviceChanged(org.osgi.framework.ServiceEvent)
+     */
+    public void serviceChanged(ServiceEvent e) 
+    {
+		ServiceReference serviceRef = e.getServiceReference();
+		// A consumer service changed
+		if (m_consumerFilter.match(serviceRef)) 
+        {
+			switch (e.getType()) 
+            {
+                case ServiceEvent.REGISTERED :
+                    traceln("consumer registered");
+                    
+                    List wires = new ArrayList();
+
+                    synchronized(m_consumers)
+                    {
+                        m_consumers.put(serviceRef,wires);
+                    }
+                    synchronized(m_wires)
+                    {
+                        Iterator wireIt = m_wires.iterator();
+                        boolean called = false;
+                        // Iterate over all existing wires
+                        while(wireIt.hasNext())
+                        {
+                            WireImpl currentWire = (WireImpl) wireIt.next();
+
+                            if(currentWire.getConsumerPID().equals(serviceRef.getProperty(Constants.SERVICE_PID)))
+                            {
+                                // This wire is associated to the newly arrived consumer
+                                currentWire.bindConsumer(serviceRef);
+                                if(currentWire.isConnected())
+                                {
+                                    // The wire has been connected, both producer and consumer
+                                    // must be updated
+                                    wires.add(currentWire);
+                                    called = true;
+                                    m_asyncMethodCaller.producersConnected(currentWire.getConsumer(),(Wire[])wires.toArray(new Wire[wires.size()]));
+                                    List producerWires = (List) m_producers.get(currentWire.getProducerServiceRef());
+                                    producerWires.add(currentWire);
+                                    m_asyncMethodCaller.consumersConnected(currentWire.getProducer(),(Wire[])producerWires.toArray(new Wire[producerWires.size()]));                                    
+                                }
+                            }
+                        }
+                        if(!called)
+                        {
+                            // P. 329 "If the Consumer service has no Wire objects attached when it
+                            // is registered, the WireAdmin service must always call producersConnected(null)
+                            m_asyncMethodCaller.producersConnected((Consumer) m_bundleContext.getService(serviceRef),null);
+                        }
+                    }
+                    break;
+                case ServiceEvent.UNREGISTERING :
+                    traceln("consumer unregistering");
+                    
+                    synchronized(m_consumers)
+                    {
+                        m_consumers.remove(serviceRef);
+                    }
+                    synchronized(m_wires)
+                    {
+                        Iterator wireIt = m_wires.iterator();
+                        while(wireIt.hasNext())
+                        {
+                            WireImpl currentWire = (WireImpl) wireIt.next();
+                            if(currentWire.getConsumerPID().equals(serviceRef.getProperty(Constants.SERVICE_PID)))
+                            {
+                                // p. 328 "When a Consumer or Producer service is unregistered
+                                // from the OSGi framework, the other object in the association
+                                // is informed that the Wire object is no longer valid"
+
+                                if(currentWire.isConnected())
+                                {
+                                    currentWire.unbindConsumer();                               
+                                    List producerWires = (List) m_producers.get(currentWire.getProducerServiceRef());
+                                    producerWires.remove(currentWire);
+                                    m_asyncMethodCaller.consumersConnected(currentWire.getProducer(),(Wire[])producerWires.toArray(new Wire[producerWires.size()]));
+                                }
+                                else
+                                {
+                                    currentWire.unbindConsumer();    
+                                }
+                            }
+                        }
+                    }
+                    break;
+                case ServiceEvent.MODIFIED :
+                    // TODO Respond to consumer service modification
+                    traceln("consumer service modified");
+                    break;
+
+            }
+        }
+        // Removed else to manage services which are both producers AND consumers
+		if (m_producerFilter.match(serviceRef)) 
+        {
+            switch (e.getType()) 
+            {
+                case ServiceEvent.REGISTERED :
+                    traceln("producer registered");
+                    
+                    List wires = new ArrayList();
+
+                    synchronized(m_producers)
+                    {
+                        m_producers.put(serviceRef,wires);
+                    }
+                    synchronized(m_wires)
+                    {
+                        Iterator wireIt = m_wires.iterator();
+                        boolean called = false;
+                        // Iterate over all existing wires
+                        while(wireIt.hasNext())
+                        {
+                            WireImpl currentWire = (WireImpl) wireIt.next();
+                            if(currentWire.getProducerPID().equals(serviceRef.getProperty(Constants.SERVICE_PID)))
+                            {
+                                // This wire is associated to the newly arrived producer
+                                currentWire.bindProducer(serviceRef);
+                                if(currentWire.isConnected())
+                                {
+                                    // The wire has been connected, both producer and consumer
+                                    // must be updated
+                                    wires.add(currentWire);
+                                    called = true;
+                                    m_asyncMethodCaller.consumersConnected(currentWire.getProducer(),(Wire[])wires.toArray(new Wire[wires.size()]));
+                                    List consumerWires = (List) m_consumers.get(currentWire.getConsumerServiceRef());
+                                    consumerWires.add(currentWire);
+                                    m_asyncMethodCaller.producersConnected(currentWire.getConsumer(),(Wire[])consumerWires.toArray(new Wire[consumerWires.size()]));                                    
+                                }
+                            }
+                        }
+                        if(!called)
+                        {
+                            // P. 329 "If the Producer service has no Wire objects attached when it
+                            // is registered, the WireAdmin service must always call consumersConnected(null)
+                            m_asyncMethodCaller.consumersConnected((Producer) m_bundleContext.getService(serviceRef),null);
+                        }
+                    }
+                    break;
+                case ServiceEvent.UNREGISTERING :
+                    traceln("Producer unregistering");
+                    
+                    synchronized(m_producers)
+                    {
+                        m_producers.remove(serviceRef);
+                    }
+                    synchronized(m_wires)
+                    {
+                        Iterator wireIt = m_wires.iterator();
+                        while(wireIt.hasNext())
+                        {
+                            WireImpl currentWire = (WireImpl) wireIt.next();
+                            if(currentWire.getProducerPID().equals(serviceRef.getProperty(Constants.SERVICE_PID)))
+                            {
+                                // p. 328 "When a Consumer or Producer service is unregistered
+                                // from the OSGi framework, the other object in the association
+                                // is informed that the Wire object is no longer valid"
+
+                                if(currentWire.isConnected())
+                                {
+                                    currentWire.unbindProducer();                               
+                                    List consumerWires = (List) m_consumers.get(currentWire.getConsumerServiceRef());
+                                    consumerWires.remove(currentWire);
+                                    m_asyncMethodCaller.producersConnected(currentWire.getConsumer(),(Wire[])consumerWires.toArray(new Wire[consumerWires.size()]));
+                                }
+                                else
+                                {
+                                    currentWire.unbindProducer();    
+                                }
+                            }
+                        }
+                    }
+                    break;
+                case ServiceEvent.MODIFIED :
+                    // TODO Respond to producer service modification
+                    traceln("producer service modified");
+                    break;
+            }
+        }        
+    }
+
+
+	/**
+	 * release all references before stop
+	 */
+	synchronized void releaseAll() 
+    {
+        Iterator wireIt = m_wires.iterator();
+        while(wireIt.hasNext())
+        {
+            WireImpl currentWire = (WireImpl) wireIt.next();
+            currentWire.invalidate();
+        }
+        
+        Iterator producerIt = m_producers.keySet().iterator();        
+        while (producerIt.hasNext())
+        {
+            ServiceReference producerRef = (ServiceReference) producerIt.next();
+            ((Producer)m_bundleContext.getService(producerRef)).consumersConnected(null);            
+        }
+        
+        Iterator consumerIt = m_consumers.keySet().iterator();        
+        while (consumerIt.hasNext())
+        {
+            ServiceReference consumerRef = (ServiceReference) consumerIt.next();
+            ((Consumer)m_bundleContext.getService(consumerRef)).producersConnected(null);            
+        }
+
+        // Stop the thread
+        m_asyncMethodCaller.stop();
+        
+        // Notify the event manager so that it stops its thread
+        m_eventManager.stop();
+        
+        persistWires();
+
+	}
+
+    /**
+     * This method generates a PID. The pid is generated from the bundle id,
+     * a hash code from the current time and a counter.
+     * 
+     * @return a wire PID
+     */
+    private String generateWirePID()
+    {
+        Date d = new Date();
+        String PID="wire."+m_bundleContext.getBundle().getBundleId()+d.hashCode()+m_wireCount;
+        m_wireCount ++;
+        
+        // Maybe the counter should go above 9?
+        if(m_wireCount>9)
+        {
+            m_wireCount = 0;
+        }
+        return PID;
+    }
+    
+    /**
+     * Recover persistent wires 
+     *
+     */
+    private void getPersistentWires()
+    {
+        
+        try
+        {
+            ObjectInputStream ois = new ObjectInputStream(new FileInputStream(m_bundleContext.getDataFile("wires.ser")));
+            m_wires = (ArrayList) ois.readObject();
+            ois.close();
+            if(m_wires!=null)
+            {
+                traceln("Deserialized "+m_wires.size()+" wires");
+                Iterator wireIt = m_wires.iterator();
+                while(wireIt.hasNext())
+                {
+                    WireImpl currentWire = (WireImpl) wireIt.next();
+                    currentWire.initialize(m_bundleContext,m_eventManager);     
+                }
+            }
+            else
+            {
+                traceln("Couldn't Deserialize wires");
+                m_wires = new ArrayList();
+            }
+        }
+        catch(FileNotFoundException ex)
+        {
+            // do not show anything as this exception is thrown every
+            // time the wire admin service is launched for the first
+            // time
+            m_wires = new ArrayList();
+        }
+        catch(Exception ex)
+        {
+            trace(ex);
+            m_wires = new ArrayList();
+        }
+    }
+    
+    /**
+     * Persist existing wires
+     *
+     */
+    private void persistWires()
+    {
+        try
+        {
+            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(m_bundleContext.getDataFile("wires.ser")));
+            oos.writeObject(m_wires);
+            oos.close();
+            traceln("Serialized "+m_wires.size()+" wires");
+        }
+        catch(Exception ex)
+        {
+            trace(ex);
+        }
+    }
+
+    /**
+     * print an error 
+     * @param message message to error 
+     */
+    static void error(String message)
+    {
+        if (m_errorout != null) 
+        {
+            m_errorout.println(message);
+        }
+    }
+
+	/**
+	 * print a trace 
+	 * @param message message to trace
+	 */
+	static void traceln(String message)
+    {
+		if (m_traceout != null) 
+        {
+			trace(message);
+			trace("\n");
+		}
+	}
+
+	/**
+	 * print a trace 
+	 * @param message message to trace
+	 */
+	static void trace(String message)
+    {
+		if (m_traceout != null) 
+        {
+			m_traceout.print(message);
+		}
+	}
+	/**
+	 * print a trace 
+	 * @param e exception to trace
+	 */
+	static void trace(Exception e) 
+    {
+		if (m_traceout != null) 
+        {
+			e.printStackTrace(m_traceout);
+		}
+	}
+
+	/**
+	 * Clone a dictionary
+	 * 
+	 * @param dictionary The dictionary to clone
+	 * @return a copy of the dicionary
+	 */
+    private Dictionary cloneProperties(Dictionary dictionary){
+        Dictionary properties=new Hashtable();
+        
+        if (dictionary == null) {
+            properties = new Hashtable();
+        } else {
+            Enumeration enumeration=dictionary.keys();
+            while(enumeration.hasMoreElements()){
+                Object key=enumeration.nextElement();
+                Object value=dictionary.get(key);
+                properties.put(key,value);
+            }
+        }
+        
+        return properties;
+    }
+	
+    /**
+     * This class enables calls to Producer.consumersConnected and Consumer.producersConnected
+     * to be done asynchronously
+     * 
+     * p.333 "The WireAdmin service can call the consumersConnected or producersConnected
+     * methods during the registration of the consumer of producer service"
+     *
+    **/
+    class AsyncMethodCaller implements Runnable
+    {
+        private boolean m_stop = false;
+
+        private List m_methodCallStack = new ArrayList();
+
+        public void run()
+        {
+            while (!m_stop)
+            {
+                Object nextTarget[] = null;
+
+                synchronized (m_methodCallStack)
+                {
+                    while (m_methodCallStack.size() == 0)
+                    {
+                        try
+                        {
+                            m_methodCallStack.wait();
+                        } 
+                        catch (InterruptedException ex)
+                        {
+                            // Ignore.
+                        }
+                    }
+                    nextTarget = (Object[]) m_methodCallStack.remove(0);
+                }
+                
+                if(nextTarget[0] instanceof Producer)
+                {
+                    try
+                    {
+                        ((Producer)nextTarget[0]).consumersConnected((Wire[])nextTarget[1]);
+                    }
+                    catch(Exception ex)
+                    {
+                        trace(ex);
+                    }
+                }
+                // Removed else because nextTarget can be both producer and consumer                
+                if(nextTarget[0] instanceof Consumer)
+                {
+                    try
+                    {
+                        ((Consumer)nextTarget[0]).producersConnected((Wire[])nextTarget[1]);
+                    }
+                    catch(Exception ex)
+                    {
+                        trace(ex);
+                    }
+                }
+            }
+        }
+
+        /**
+         * Place a call to Consumer.producersConnected on the stack
+         * 
+         * @param c the consumer
+         * @param wires the wires
+         */
+        public void producersConnected(Consumer c,Wire []wires)
+        {
+            synchronized (m_methodCallStack)
+            {
+                m_methodCallStack.add(new Object[]{c,wires});
+                m_methodCallStack.notify();
+            }
+        }
+
+        /**
+         * Place a call to Producer.consumersConnected on the stack
+         * 
+         * @param p the producer
+         * @param wires the wires
+         */
+        public void consumersConnected(Producer p,Wire []wires)
+        {
+            synchronized (m_methodCallStack)
+            {
+                m_methodCallStack.add(new Object[]{p,wires});
+                m_methodCallStack.notify();
+            }
+        }
+
+        /**
+         * stop the dispatcher
+         *
+         */
+        void stop()
+        {
+            m_stop = true;
+        }
+    }
+}
\ No newline at end of file
diff --git a/org.apache.felix.wireadmin/src/main/java/org/apache/felix/wireadmin/WireImpl.java b/org.apache.felix.wireadmin/src/main/java/org/apache/felix/wireadmin/WireImpl.java
new file mode 100644
index 0000000..e587a68
--- /dev/null
+++ b/org.apache.felix.wireadmin/src/main/java/org/apache/felix/wireadmin/WireImpl.java
@@ -0,0 +1,952 @@
+/*
+ *   Copyright 2006 The Apache Software Foundation
+ *
+ *   Licensed 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.wireadmin;
+
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.Vector;
+import java.util.Date;
+
+import org.osgi.framework.Filter;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+
+import org.osgi.service.wireadmin.Consumer;
+import org.osgi.service.wireadmin.Producer;
+import org.osgi.service.wireadmin.Wire;
+import org.osgi.service.wireadmin.WireConstants;
+import org.osgi.service.wireadmin.WireAdminEvent;
+
+/**
+ * A connection between a Producer service and a Consumer service.
+ *
+ * <p>A <tt>Wire</tt> object connects a Producer service
+ * to a Consumer service.
+ * Both the Producer and Consumer services are identified
+ * by their unique <tt>service.pid</tt> values.
+ * The Producer and Consumer services may communicate with
+ * each other via <tt>Wire</tt> objects that connect them.
+ * The Producer service may send updated values to the
+ * Consumer service by calling the {@link #update} method.
+ * The Consumer service may request an updated value from the
+ * Producer service by calling the {@link #poll} method.
+ *
+ * <p>A Producer service and a Consumer service may be
+ * connected through multiple <tt>Wire</tt> objects.
+ *
+ * <p>Security Considerations. <tt>Wire</tt> objects are available to
+ * Producer and Consumer services connected to a given
+ * <tt>Wire</tt> object and to bundles which can access the <tt>WireAdmin</tt> service.
+ * A bundle must have <tt>ServicePermission[GET,WireAdmin]</tt> to get the <tt>WireAdmin</tt> service to
+ * access all <tt>Wire</tt> objects.
+ * A bundle registering a Producer service or a Consumer service
+ * must have the appropriate <tt>ServicePermission[REGISTER,Consumer|Producer]</tt> to register the service and
+ * will be passed <tt>Wire</tt> objects when the service object's
+ * <tt>consumersConnected</tt> or <tt>producersConnected</tt> method is called.
+ *
+ * <p>Scope. Each Wire object can have a scope set with the <tt>setScope</tt> method. This
+ * method should be called by a Consumer service when it assumes a Producer service that is
+ * composite (supports multiple information items). The names in the scope must be
+ * verified by the <tt>Wire</tt> object before it is used in communication. The semantics of the
+ * names depend on the Producer service and must not be interpreted by the Wire Admin service.
+ *
+ * @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a> * 
+ */
+public class WireImpl implements Wire, java.io.Serializable 
+{
+	static final long serialVersionUID = -3637966367104019136L;
+	
+    // Persistent attributes
+    
+    // p. 327 "The Wire admin object contains a Persistend Identity (PID) for
+    // a consumer service and a PID for a producer service" These properties
+    // are also contained in the dictionary, but they are stored to optimize
+    // access. 
+    private String m_producerPID;
+    private String m_consumerPID;
+
+    private Dictionary m_properties;
+    
+    // Transient attributes
+
+	transient private boolean m_isValid = true;
+    transient private boolean m_isConnected = false;
+    transient private Filter m_filter = null;
+    
+    transient private ServiceReference m_producerServiceRef;
+    transient private Producer m_producer;
+    transient private boolean m_producerIsComposite = false;
+    transient private String [] m_producerScope = null;
+    
+    transient private ServiceReference m_consumerServiceRef;	
+	transient private Consumer m_consumer;
+    transient private boolean m_consumerIsComposite = false;
+    transient private String [] m_consumerScope = null;
+    
+    transient private BundleContext m_bundleContext;
+    transient private EventManager m_eventManager;
+	transient private Object m_lastValue;
+	transient private String[] m_scope;
+    
+    transient private long m_lastUpdate;    
+    transient private boolean m_isFirstUpdate;
+    transient FilterDictionary m_dictionary;
+    
+    /**
+     * Constructor with package visibility
+     * 
+     * @param producerPID
+     * @param consumerPID
+     * @param properties
+     */
+	WireImpl(String producerPID, String consumerPID, Dictionary properties)
+    {
+		m_producerPID = producerPID;
+		m_consumerPID = consumerPID;
+		m_properties = properties;
+		
+		// set the scope which is the intersection of strings in the WIREADMIN_PRODUCER_SCOPE properties and the strings in the WIREADMIN_CONSUMER_SCOPE
+		m_scope = null;
+	}
+    
+    /**
+     * Method called after construction and after deserialization
+     * 
+     * @param ctxt
+     * @param eventManager
+     */
+    void initialize(BundleContext ctxt, EventManager eventManager)
+    {
+        m_isValid = true;
+        m_isConnected = false;
+
+        m_bundleContext = ctxt;
+        m_eventManager = eventManager;
+        
+        m_lastValue = null;
+        
+        m_lastUpdate = 0;
+        
+        m_isFirstUpdate = true;
+        
+        /*
+        if(m_date == null)
+        {
+            m_date = new Date();
+        }
+        */
+        m_dictionary = new FilterDictionary();
+    }
+
+	/**
+	 * Return the state of this <tt>Wire</tt> object.
+	 *
+	 * <p>A connected <tt>Wire</tt> must always be disconnected before
+	 * becoming invalid.
+	 *
+	 * @return <tt>false</tt> if this <tt>Wire</tt> object is invalid because it
+	 * has been deleted via {@link WireAdmin#deleteWire};
+	 * <tt>true</tt> otherwise.
+	 */
+	public boolean isValid() 
+    {
+		return m_isValid;
+	}
+
+	/**
+	 * Return the connection state of this <tt>Wire</tt> object.
+	 *
+	 * <p>A <tt>Wire</tt> is connected after the Wire Admin service receives
+	 * notification that the Producer service and
+	 * the Consumer service for this <tt>Wire</tt> object are both registered.
+	 * This method will return <tt>true</tt> prior to notifying the Producer
+	 * and Consumer services via calls
+	 * to their respective <tt>consumersConnected</tt> and <tt>producersConnected</tt>
+	 * methods.
+	 * <p>A <tt>WireAdminEvent</tt> of type {@link WireAdminEvent#WIRE_CONNECTED}
+	 * must be broadcast by the Wire Admin service when
+	 * the <tt>Wire</tt> becomes connected.
+	 *
+	 * <p>A <tt>Wire</tt> object
+	 * is disconnected when either the Consumer or Producer
+	 * service is unregistered or the <tt>Wire</tt> object is deleted.
+	 * <p>A <tt>WireAdminEvent</tt> of type {@link WireAdminEvent#WIRE_DISCONNECTED}
+	 * must be broadcast by the Wire Admin service when
+	 * the <tt>Wire</tt> becomes disconnected.
+	 *
+	 * @return <tt>true</tt> if both the Producer and Consumer
+	 * for this <tt>Wire</tt> object are connected to the <tt>Wire</tt> object;
+	 * <tt>false</tt> otherwise.
+	 */
+	public boolean isConnected() 
+    {
+		return m_isConnected;
+	}
+
+	/**
+	 * Return the list of data types understood by the
+	 * Consumer service connected to this <tt>Wire</tt> object. Note that
+	 * subclasses of the classes in this list are acceptable data types as well.
+	 *
+	 * <p>The list is the value of the {@link WireConstants#WIREADMIN_CONSUMER_FLAVORS}
+	 * service property of the
+	 * Consumer service object connected to this object. If no such
+	 * property was registered or the type of the property value is not
+	 * <tt>Class[]</tt>, this method must return <tt>null</tt>.
+	 *
+	 * @return An array containing the list of classes understood by the
+	 * Consumer service or <tt>null</tt> if
+	 * the <tt>Wire</tt> is not connected,
+	 * or the consumer did not register a {@link WireConstants#WIREADMIN_CONSUMER_FLAVORS} property
+	 * or the value of the property is not of type <tt>Class[]</tt>.
+	 */
+
+	public Class[] getFlavors() 
+    {
+        if(isConnected())
+        {
+            try
+            {
+                return (Class [])m_consumerServiceRef.getProperty(WireConstants.WIREADMIN_CONSUMER_FLAVORS);
+            }
+            catch(ClassCastException ex)
+            {
+                return null;
+            }
+        }
+        else
+        {
+            return null;
+
+        }
+	}
+
+	/**
+	 * Update the value.
+	 *
+	 * <p>This methods is called by the Producer service to
+	 * notify the Consumer service connected to this <tt>Wire</tt> object
+	 * of an updated value.
+	 * <p>If the properties of this <tt>Wire</tt> object contain a
+	 * {@link WireConstants#WIREADMIN_FILTER} property,
+	 * then filtering is performed.
+	 * If the Producer service connected to this <tt>Wire</tt>
+	 * object was registered with the service
+	 * property {@link WireConstants#WIREADMIN_PRODUCER_FILTERS}, the
+	 * Producer service will perform the filtering according to the rules specified
+	 * for the filter. Otherwise, this <tt>Wire</tt> object
+	 * will perform the filtering of the value.
+	 * <p>If no filtering is done, or the filter indicates the updated value should
+	 * be delivered to the Consumer service, then
+	 * this <tt>Wire</tt> object must call
+	 * the {@link Consumer#updated} method with the updated value.
+	 * If this <tt>Wire</tt> object is not connected, then the Consumer
+	 * service must not be called and the value is ignored.<p>
+	 * If the value is an <tt>Envelope</tt> object, and the scope name is not permitted, then the
+	 * <tt>Wire</tt> object must ignore this call and not transfer the object to the Consumer
+	 * service.
+	 *
+	 * <p>A <tt>WireAdminEvent</tt> of type {@link WireAdminEvent#WIRE_TRACE}
+	 * must be broadcast by the Wire Admin service after
+	 * the Consumer service has been successfully called.
+	 *
+	 * @param value The updated value. The value should be an instance of
+	 * one of the types returned by {@link #getFlavors}.
+	 * @see WireConstants#WIREADMIN_FILTER
+	 */
+	public void update(Object value) 
+    {
+        // TODO Implement Access Control (p. 338)
+		if (isConnected())
+        {       
+            if(m_producerIsComposite == true)
+            {
+                // TODO Implement update for composite producers
+                WireAdminImpl.traceln("WireImpl.update: update for composite producers not yet implemented");
+                return;
+            }
+            else // not a composite (Note: p. 341 "Filtering for composite producer services is not supported")
+            {
+                //long time = m_date.getTime();
+                long time = new Date().getTime();
+                
+                // We ignore filtering the first time...
+                if(m_isFirstUpdate == false && m_filter != null)
+                {
+                    // If the Producer service was registered with the WIREADMIN_PRODUCER_FILTERS  
+                    // service property indicating that the Producer service will perform the data 
+                    // filtering then the Wire object will not perform data filtering. Otherwise, 
+                    // the Wire object must perform basic filtering.
+                    try
+                    {
+                        m_dictionary.reset(value,time);
+                        if(!m_filter.match(m_dictionary))
+                        {
+                            WireAdminImpl.traceln("### Update rejected ("+m_properties.get(WireConstants.WIREADMIN_PID)+") filter evaluated to false:"+m_filter);
+                            WireAdminImpl.traceln("  WIREVALUE_CURRENT.class"+m_dictionary.get(WireConstants.WIREVALUE_CURRENT).getClass().getName());
+                            WireAdminImpl.traceln("  WIREVALUE_CURRENT="+m_dictionary.get(WireConstants.WIREVALUE_CURRENT));
+                            WireAdminImpl.traceln("  WIREVALUE_PREVIOUS="+m_dictionary.get(WireConstants.WIREVALUE_PREVIOUS));
+                            WireAdminImpl.traceln("  WIREVALUE_DELTA_ABSOLUTE="+m_dictionary.get(WireConstants.WIREVALUE_DELTA_ABSOLUTE));
+                            WireAdminImpl.traceln("  WIREVALUE_DELTA_RELATIVE="+m_dictionary.get(WireConstants.WIREVALUE_DELTA_RELATIVE));
+                            WireAdminImpl.traceln("  WIREVALUE_ELAPSED="+m_dictionary.get(WireConstants.WIREVALUE_ELAPSED));
+                            return;
+                        }
+                    }
+                    catch(Exception ex)
+                    {
+                        // Could happen...
+                        WireAdminImpl.trace(ex);
+                    }
+    
+                }
+                try
+                {
+        			m_consumer.updated(this, value);
+                    if(m_isFirstUpdate == true)
+                    {
+                        m_isFirstUpdate = false;
+                    }
+                    m_lastUpdate = time;
+                    m_lastValue = value;
+                    // Fire event
+                    m_eventManager.fireEvent(WireAdminEvent.WIRE_TRACE,this);
+                }
+                catch(Exception ex)
+                {
+                    m_eventManager.fireEvent(WireAdminEvent.CONSUMER_EXCEPTION,this,ex);
+                }
+            }
+        }
+	}
+
+	/**
+	 * Poll for an updated value.
+	 *
+	 * <p>This methods is normally called by the Consumer service to
+	 * request an updated value from the Producer service
+	 * connected to this <tt>Wire</tt> object.
+	 * This <tt>Wire</tt> object will call
+	 * the {@link Producer#polled} method to obtain an updated value.
+	 * If this <tt>Wire</tt> object is not connected, then the Producer
+	 * service must not be called.<p>
+	 *
+	 * If this <tt>Wire</tt> object has a scope, then this method
+	 * must return an array of <tt>Envelope</tt> objects. The objects returned must
+	 * match the scope of this object. The <tt>Wire</tt> object must remove
+	 * all <tt>Envelope</tt> objects with a scope name that is not in the <tt>Wire</tt> object's scope.
+	 * Thus, the list of objects returned
+	 * must only contain <tt>Envelope</tt> objects with a permitted scope name. If the
+	 * array becomes empty, <tt>null</tt> must be returned.
+	 *
+	 * <p>A <tt>WireAdminEvent</tt> of type {@link WireAdminEvent#WIRE_TRACE}
+	 * must be broadcast by the Wire Admin service after
+	 * the Producer service has been successfully called.
+	 *
+	 * @return A value whose type should be one of the types
+	 * returned by {@link #getFlavors}, <tt>Envelope[]</tt>, or <tt>null</tt> if
+	 * the <tt>Wire</tt> object is not connected,
+	 * the Producer service threw an exception, or
+	 * the Producer service returned a value which is not an instance of
+	 * one of the types returned by {@link #getFlavors}.
+	 */
+	public Object poll() {
+        // p.330 "Update filtering must not apply to polling"
+		if (isConnected()) 
+        {
+            try
+            {
+    			Object value = m_producer.polled(this);
+                Class []flavors = getFlavors();
+                
+                boolean valueOk = false;
+                
+                // Test if the value is ok with respect to the flavors understood by
+                // the consumer
+                for(int i=0; i<flavors.length; i++)
+                {
+                    Class currentClass = flavors[i];
+                    if(currentClass.isInstance(value))
+                    {
+                        valueOk = true;
+                    }                    
+                }
+                if(valueOk)
+                {
+                    m_eventManager.fireEvent(WireAdminEvent.WIRE_TRACE,this);
+                    m_lastValue = value;
+        			return m_lastValue;
+                }
+                else
+                {
+                    WireAdminImpl.traceln("WireImpl.poll: value returned by producer is not undestood by consumer");
+                    return null;
+                }
+            }
+            catch(Exception ex)
+            {
+                m_eventManager.fireEvent(WireAdminEvent.PRODUCER_EXCEPTION,this,ex);
+                return null;
+            }
+		} 
+        else
+        {
+            // p. 333 "If the poll() method on the wire object is called and the
+            // producer is unregistered it must return a null value"
+			return null;
+        }
+	}
+
+	/**
+	 * Return the last value sent through this <tt>Wire</tt> object.
+	 *
+	 * <p>The returned value is the most recent, valid value passed to the
+	 * {@link #update} method or returned by the {@link #poll} method
+	 * of this object. If filtering is performed by this <tt>Wire</tt> object,
+	 * this methods returns the last value provided by the Producer service. This
+	 * value may be an <tt>Envelope[]</tt> when the Producer service
+	 * uses scoping. If the return value is an Envelope object (or array), it
+	 * must be verified that the Consumer service has the proper WirePermission to see it.
+	 *
+	 * @return The last value passed though this <tt>Wire</tt> object
+	 * or <tt>null</tt> if no valid values have been passed or the Consumer service has no permission.
+	 */
+	public Object getLastValue() 
+    {
+		return m_lastValue;
+	}
+
+	/**
+	 * Return the wire properties for this <tt>Wire</tt> object.
+	 *
+	 * @return The properties for this <tt>Wire</tt> object.
+	 * The returned <tt>Dictionary</tt> must be read only.
+	 */
+	public Dictionary getProperties() 
+    {
+		return m_properties;
+	}
+
+	/**
+	 * Return the calculated scope of this <tt>Wire</tt> object.
+	 *
+	 * The purpose of the <tt>Wire</tt> object's scope is to allow a Producer
+	 * and/or Consumer service to produce/consume different types
+	 * over a single <tt>Wire</tt> object (this was deemed necessary for efficiency
+	 * reasons). Both the Consumer service and the
+	 * Producer service must set an array of scope names (their scope) with
+	 * the service registration property <tt>WIREADMIN_PRODUCER_SCOPE</tt>, or <tt>WIREADMIN_CONSUMER_SCOPE</tt> when they can
+	 * produce multiple types. If a Producer service can produce different types, it should set this property
+	 * to the array of scope names it can produce, the Consumer service
+	 * must set the array of scope names it can consume. The scope of a <tt>Wire</tt>
+	 * object is defined as the intersection of permitted scope names of the
+	 * Producer service and Consumer service.
+	 * <p>If neither the Consumer, or the Producer service registers scope names with its
+	 * service registration, then the <tt>Wire</tt> object's scope must be <tt>null</tt>.
+	 * <p>The <tt>Wire</tt> object's scope must not change when a Producer or Consumer services
+	 * modifies its scope.
+	 * <p>A scope name is permitted for a Producer service when the registering bundle has
+	 * <tt>WirePermission[PRODUCE]</tt>, and for a Consumer service when
+	 * the registering bundle has <tt>WirePermission[CONSUME]</tt>.<p>
+	 * If either Consumer service or Producer service has not set a <tt>WIREADMIN_*_SCOPE</tt> property, then
+	 * the returned value must be <tt>null</tt>.<p>
+	 * If the scope is set, the <tt>Wire</tt> object must enforce the scope names when <tt>Envelope</tt> objects are
+	 * used as a parameter to update or returned from the <tt>poll</tt> method. The <tt>Wire</tt> object must then
+	 * remove all <tt>Envelope</tt> objects with a scope name that is not permitted.
+	 *
+	 * @return A list of permitted scope names or null if the Produce or Consumer service has set no scope names.
+	 */
+	public String[] getScope() 
+    {
+		return m_scope;
+	}
+
+	/**
+	 * Return true if the given name is in this <tt>Wire</tt> object's scope.
+	 *
+	 * @param name The scope name
+	 * @return true if the name is listed in the permitted scope names
+	 */
+	public boolean hasScope(String name) 
+    {
+		if (m_scope != null) 
+        {
+			for (int i = 0; i < m_scope.length; i++) 
+            {
+				if (name.equals(m_scope[i])) 
+                {
+					return true;
+				}
+			}
+		}
+		return false;
+	}
+
+	/**
+	 * @see java.lang.Object#toString()
+	 */
+	public String toString() 
+    {
+		return super.toString()
+			+ ":["
+			+ getProperties().get(WireConstants.WIREADMIN_PID)
+			+ ","
+			+ getProperties().get(WireConstants.WIREADMIN_PRODUCER_PID)
+			+ ","
+			+ getProperties().get(WireConstants.WIREADMIN_CONSUMER_PID)
+			+ "]";
+	}
+
+    /**
+     * Bind the consumer.
+     * 
+     * @param consumer A <tt>ServiceReference</tt> corresponding to the consumer service
+     */
+    void bindConsumer(ServiceReference consumerRef)
+    {
+        if(m_consumerServiceRef != null)
+        {
+            WireAdminImpl.traceln("WireImpl: consumer already bound!");
+            return;
+        }
+        
+        // Pid must be present
+        if(consumerRef.getProperty(Constants.SERVICE_PID) == null)
+        {
+            WireAdminImpl.traceln("WireImpl: Consumer service has no PID "+consumerRef);
+            return;
+        }
+        
+        // Flavors must be present
+        if(consumerRef.getProperty(WireConstants.WIREADMIN_CONSUMER_FLAVORS) == null)
+        {
+            WireAdminImpl.traceln("WireImpl: Consumer service has no WIREADMIN_CONSUMER_FLAVORS "+consumerRef);
+            return;
+        }
+
+        // Is this a composite?
+        if(consumerRef.getProperty(WireConstants.WIREADMIN_CONSUMER_COMPOSITE) != null)
+        {
+            m_consumerIsComposite = true;
+            m_consumerScope = (String []) consumerRef.getProperty(WireConstants.WIREADMIN_CONSUMER_SCOPE);
+
+        }
+
+        m_consumerServiceRef = consumerRef;
+        m_consumer = (Consumer) m_bundleContext.getService(consumerRef);
+        
+        if(m_producer != null)
+        {
+            if(m_producerIsComposite)
+            {
+                if(matchComposites() == false)
+                {
+                    WireAdminImpl.traceln("WireImpl.bindConsumer : warning composite identities do not match");
+                }
+            }
+            m_isConnected = true;
+            m_eventManager.fireEvent(WireAdminEvent.WIRE_CONNECTED,this);
+        }
+    }
+    
+    /**
+     * Unbind the consumer
+     *
+     */
+    void unbindConsumer()
+    {
+    	// This test is made because knopflerfish doesn't support ungetService(null);
+    	if(m_consumerServiceRef != null)
+    	{
+	        m_bundleContext.ungetService(m_consumerServiceRef);
+	        if(m_isConnected)
+	        {
+	            m_isConnected = false;
+	            m_eventManager.fireEvent(WireAdminEvent.WIRE_DISCONNECTED,this);
+	        }
+	        m_consumer = null;
+	        m_consumerServiceRef = null;
+    	}
+    }
+    
+    /**
+     * Bind the producer
+     * 
+     * @param producer A <tt>ServiceReference</tt> corresponding to the producer service
+     */
+    void bindProducer(ServiceReference producerRef)
+    {
+        if(m_producerServiceRef != null)
+        {
+            WireAdminImpl.traceln("WireImpl: producer already bound!");
+            return;
+        }
+        
+        // Pid must be present
+        if(producerRef.getProperty(Constants.SERVICE_PID) == null)
+        {
+            WireAdminImpl.traceln("WireImpl.bindProducer: Producer service has no PID "+producerRef);
+            return;
+        }
+
+        // Flavors must be present
+        if(producerRef.getProperty(WireConstants.WIREADMIN_PRODUCER_FLAVORS) == null)
+        {
+            WireAdminImpl.traceln("WireImpl: Consumer service has no WIREADMIN_PRODUCER_FLAVORS "+producerRef);
+            return;
+        }
+
+        // Is this a composite?
+        if(producerRef.getProperty(WireConstants.WIREADMIN_PRODUCER_COMPOSITE) != null)
+        {
+            m_producerIsComposite = true;
+            m_producerScope = (String []) producerRef.getProperty(WireConstants.WIREADMIN_PRODUCER_SCOPE);
+        }
+
+        m_producerServiceRef = producerRef;
+        m_producer = (Producer) m_bundleContext.getService(producerRef);
+        
+        // p. 329 " If this property (wireadmin.producer.filters) is not set,
+        // the Wire object must filter according to the description in CompositeObjects"
+        if(producerRef.getProperty(WireConstants.WIREADMIN_PRODUCER_FILTERS) == null)
+        {
+            String filter = (String) m_properties.get(WireConstants.WIREADMIN_FILTER);
+            if(filter != null)
+            {
+                try
+                {
+                    m_filter = m_bundleContext.createFilter(filter);
+                }
+                catch(InvalidSyntaxException ex)
+                {
+                    WireAdminImpl.traceln("WireImpl.bindProducer: Ignoring filter with invalid syntax "+filter);                    
+                }
+            }
+        }
+        
+        if(m_consumer != null)
+        {
+            if(m_consumerIsComposite)
+            {
+                if(matchComposites() == false)
+                {
+                    WireAdminImpl.traceln("WireImpl.bindProducer : warning composite identities do not match");
+                }
+            }
+            m_isConnected = true;
+            // fire the corresponding event
+            m_eventManager.fireEvent(WireAdminEvent.WIRE_CONNECTED,this);
+        }
+    }
+    
+    /**
+     * Unbind the producer
+     *
+     */
+    void unbindProducer()
+    {
+    	if(m_producerServiceRef != null)
+    	{
+	        m_bundleContext.ungetService(m_producerServiceRef);
+	        if(m_isConnected)
+	        {
+	            m_isConnected = false;
+	            // fire the corresponding event
+	            m_eventManager.fireEvent(WireAdminEvent.WIRE_DISCONNECTED,this);
+	        }
+	        m_producer = null;
+	        m_producerServiceRef = null;
+    	}
+    }
+
+    /**
+     * Check if composites match. Match occurs when "at least one equal composite identity is
+     * listed on both the Producer and Consmer composite identity service property" (p. 336)
+     * 
+     * @return <tt>true</tt> if they match, <tt>false</tt>otherwise
+     */    
+    private boolean matchComposites()
+    {
+        String [] producerIdentities = (String []) m_producerServiceRef.getProperty(WireConstants.WIREADMIN_PRODUCER_COMPOSITE);
+        String [] consumerIdentities = (String []) m_producerServiceRef.getProperty(WireConstants.WIREADMIN_PRODUCER_COMPOSITE);
+        
+        boolean match = false;
+        
+        // confirm matching
+        
+        for(int i = 0; i< producerIdentities.length; i++)
+        {
+            String currentProducerIdentity = producerIdentities [i]; 
+            for(int j = 0; j < consumerIdentities.length; j++)
+            {
+                String currentConsumerIdentity = consumerIdentities [j];
+                if (currentProducerIdentity.equals(currentConsumerIdentity))
+                {
+                    match = true;
+                    break;
+                }
+            }
+        }
+        
+        // setup wire scope
+        
+        if (m_consumerScope != null && m_producerScope != null)
+        {
+            // p. 337 "It is allowed to register with a wildcard, indicating that all scopenames
+            // are supported. In that case, the WIREADMIN_SCOPE_ALL ({"*"}) should be registered as the
+            // scope of the serivce. The WireObject's scope is then fully defined by the
+            // other service connected to the wire object
+            if(m_consumerScope.length == 1 && m_consumerScope[0].equals("*"))
+            {
+                m_scope = m_producerScope;
+            }
+            else if(m_producerScope.length == 1 && m_producerScope[0].equals("*"))
+            {
+                m_scope = m_consumerScope;
+            }
+            else
+            {
+                /*
+                // TODO Implement wire scope creation based on producer, consumer and wire permissions (p. 338)
+
+                ServiceReference ref = m_bundleContext.getServiceReference(PermissionAdmin.class.getName());
+                if(ref != null)
+                {
+                    PermissionAdmin permAdmin = (PermissionAdmin) m_bundleContext.getService(ref);
+                    PermissionInfo [] producerPermissions = permAdmin.getPermissions(m_producerServiceRef.getBundle().getLocation());
+                    PermissionInfo [] consumerPermissions = permAdmin.getPermissions(m_consumerServiceRef.getBundle().getLocation()); 
+                }
+                */
+            }
+        }
+        else
+        {
+            // p. 337 "Not registering this property (WIREADMIN_CONSUMER_SCOPE or WIREADMIN_PRODUCER_SCOPE)
+            // by the Consumer or the Producer service indicates to the WireAdmin service that any
+            // Wire object connected to that service must return null for the Wire.getScope() method"
+            m_scope = null;
+        }
+        
+        return match;
+    }
+
+    /**
+     * Called to invalidate the wire
+     *
+     */
+    void invalidate()
+    {
+    	if(m_isValid)
+    	{
+	        unbindProducer();
+	        unbindConsumer();
+	        m_isValid=false;
+    	}
+    }
+    
+    /**
+     * Update the properties
+     * 
+     * @param properties new properties
+     */
+    void updateProperties(Dictionary properties)
+    {
+        m_properties = properties;
+    }
+
+    /**
+     * Return the service reference corresponding to the producer
+     * 
+     * @return a <tt>ServiceReference</tt> corresponding to the producer
+     */
+    ServiceReference getProducerServiceRef()
+    {
+        return m_producerServiceRef;
+    }
+
+    /**
+     * Return the producer service object
+     * 
+     * @return An <tt>Object</tt> corresponding to the producer
+     */
+    Producer getProducer()
+    {
+        return m_producer;
+    }
+
+    /**
+     * return the producer PID
+     * 
+     * @return
+     */
+    String getProducerPID()
+    {
+        return m_producerPID;
+    }
+
+    /**
+     * Return the service reference corresponding to the consumer
+     * 
+     * @return a <tt>ServiceReference</tt> corresponding to the consumer
+     */
+    ServiceReference getConsumerServiceRef()
+    {
+        return m_consumerServiceRef;
+    }
+
+    /**
+     * Returns the consumer service object
+     * 
+     * @return An <tt>Object</tt> corresponding to the consumer
+     */
+    Consumer getConsumer()
+    {
+        return m_consumer;
+    }
+
+    /**
+     * return the consumer PID
+     * 
+     * @return
+     */
+    String getConsumerPID()
+    {
+        return m_consumerPID;
+    }
+    
+    /**
+     * This inner class implements a dictionary that is used to filter out values
+     * during calls to update. This design choice was favored to avoid constructing
+     * a new dictionary for every call to update and to avoid doing unnecessary
+     * calculations.
+     */
+    class FilterDictionary extends Dictionary
+    {
+        private Object m_value;
+        private long m_time;
+        
+        /**
+         * Must be called prior to evaluating the filter
+         * 
+         * @param value
+         * @param time
+         */
+        void reset(Object value, long time)
+        {
+            m_value = value;
+            m_time = time;
+        }
+        
+        /**
+         * 
+         */
+        public Object get(Object key)
+        {
+            if(key.equals(WireConstants.WIREVALUE_CURRENT))
+            {
+                return m_value;
+            }
+            else if(key.equals(WireConstants.WIREVALUE_PREVIOUS))
+            {
+                return m_lastValue;
+            }
+            else if(m_value instanceof Number && key.equals(WireConstants.WIREVALUE_DELTA_ABSOLUTE))
+            {
+                return null;
+            }
+            else if(m_value instanceof Number && key.equals(WireConstants.WIREVALUE_DELTA_RELATIVE))
+            {
+                return null;
+            }
+            else if(key.equals(WireConstants.WIREVALUE_ELAPSED))
+            {
+                if(m_lastUpdate == 0)
+                {
+                    return new Long(0);    
+                }
+                else
+                {
+                    long delay = m_time - m_lastUpdate;
+                    //System.out.println("### delay = "+(delay));
+                    return new Long(delay);
+                }
+            }
+            else
+            {
+            	WireAdminImpl.traceln("### key not found:"+key);
+                return null;
+            }
+        }
+
+        /**
+         * Never empty
+         */
+        public boolean isEmpty()
+        {
+            return false;       
+        }
+        
+        /**
+         * Remove not supported
+         */
+        public Object remove(Object obj)
+        {
+            return null;
+        }
+        
+        /**
+         * Size is static
+         */
+        public int size()
+        {
+            return 5;
+        }
+        
+        /**
+         * Put not supported
+         */
+        public Object put(Object key, Object value)
+        {
+            return null;
+        }
+        
+        /**
+         * 
+         */
+        public Enumeration keys()
+        {
+        	Vector keys=new Vector();
+        	
+        	keys.addElement(WireConstants.WIREVALUE_ELAPSED);
+        	keys.addElement(WireConstants.WIREVALUE_CURRENT);
+        	keys.addElement(WireConstants.WIREVALUE_PREVIOUS);
+        	keys.addElement(WireConstants.WIREVALUE_DELTA_ABSOLUTE);
+        	keys.addElement(WireConstants.WIREVALUE_DELTA_RELATIVE);
+        	
+        	return keys.elements();
+        }
+        
+        /**
+         * Not supported
+         */
+        public Enumeration elements()
+        {
+            return null;
+        }
+    }
+}
\ No newline at end of file
