Commit online-manipulator tests.

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@767445 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/ipojo/tests/online-manipulator/src/test/java/org/apache/felix/org/apache/felix/ipojo/online/manipulator/test/OSGiHelper.java b/ipojo/tests/online-manipulator/src/test/java/org/apache/felix/org/apache/felix/ipojo/online/manipulator/test/OSGiHelper.java
new file mode 100644
index 0000000..276b6c7
--- /dev/null
+++ b/ipojo/tests/online-manipulator/src/test/java/org/apache/felix/org/apache/felix/ipojo/online/manipulator/test/OSGiHelper.java
@@ -0,0 +1,456 @@
+package org.apache.felix.org.apache.felix.ipojo.online.manipulator.test;
+
+import static org.junit.Assert.fail;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.packageadmin.PackageAdmin;
+
+
+public class OSGiHelper {
+    
+    /**
+     * The bundle context.
+     */
+    private BundleContext context;
+    
+    /**
+     * List of get references.
+     */
+    private List<ServiceReference> m_references = new ArrayList<ServiceReference>();
+    
+    public OSGiHelper(BundleContext context) {
+        this.context = context;
+    }
+    
+    public void dispose() {
+        // Unget services
+        for (int i = 0; i < m_references.size(); i++) {
+            context.ungetService((ServiceReference) m_references.get(i));
+        }
+        m_references.clear();
+    }
+    
+    /**
+     * Gets the Bundle Context.
+     * @return the bundle context.
+     */
+    public BundleContext getContext() {
+        return context;
+    }
+    
+    /**
+     * Returns the service object of a service provided by the specified bundle,
+     * offering the specified interface and matching the given filter.
+     * 
+     * @param bundle the bundle from which the service is searched.
+     * @param itf the interface provided by the searched service.
+     * @param filter an additional filter (can be {@code null}).
+     * @return the service object provided by the specified bundle, offering the
+     *         specified interface and matching the given filter.
+     */
+    public static Object getServiceObject(Bundle bundle, String itf,
+            String filter) {
+        ServiceReference ref = getServiceReference(bundle, itf, filter);
+        if (ref != null) {
+            return bundle.getBundleContext().getService(ref);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Returns the service objects of the services provided by the specified
+     * bundle, offering the specified interface and matching the given filter.
+     * 
+     * @param bundle the bundle from which services are searched.
+     * @param itf the interface provided by the searched services.
+     * @param filter an additional filter (can be {@code null}).
+     * @return the service objects provided by the specified bundle, offering
+     *         the specified interface and matching the given filter.
+     */
+    public static Object[] getServiceObjects(Bundle bundle, String itf,
+            String filter) {
+        ServiceReference[] refs = getServiceReferences(bundle, itf, filter);
+        if (refs != null) {
+            Object[] list = new Object[refs.length];
+            for (int i = 0; i < refs.length; i++) {
+                list[i] = bundle.getBundleContext().getService(refs[i]);
+            }
+            return list;
+        } else {
+            return new Object[0];
+        }
+    }
+
+    /**
+     * Returns the service reference of a service provided by the specified
+     * bundle, offering the specified interface and matching the given filter.
+     * 
+     * @param bundle the bundle from which the service is searched.
+     * @param itf the interface provided by the searched service.
+     * @param filter an additional filter (can be {@code null}).
+     * @return a service reference provided by the specified bundle, offering
+     *         the specified interface and matching the given filter. If no
+     *         service is found, {@code null} is returned.
+     */
+    public static ServiceReference getServiceReference(Bundle bundle,
+            String itf, String filter) {
+        ServiceReference[] refs = getServiceReferences(bundle, itf, filter);
+        if (refs.length != 0) {
+            return refs[0];
+        } else {
+            // No service found
+            return null;
+        }
+    }
+
+    /**
+     * Checks if the service is available.
+     * @param itf the service interface
+     * @return <code>true</code> if the service is available, <code>false</code>
+     *         otherwise.
+     */
+    public boolean isServiceAvailable(String itf) {
+        ServiceReference ref = getServiceReference(itf, null);
+        return ref != null;
+    }
+
+    /**
+     * Checks if the service is available.
+     * @param itf the service interface
+     * @param pid the service pid
+     * @return <code>true</code> if the service is available, <code>false</code>
+     *         otherwise.
+     */
+    public boolean isServiceAvailableByPID(String itf, String pid) {
+        ServiceReference ref = getServiceReferenceByPID(itf, pid);
+        return ref != null;
+    }
+
+    /**
+     * Returns the service reference of the service provided by the specified
+     * bundle, offering the specified interface and having the given persistent
+     * ID.
+     * 
+     * @param bundle the bundle from which the service is searched.
+     * @param itf the interface provided by the searched service.
+     * @param pid the persistent ID of the searched service.
+     * @return a service provided by the specified bundle, offering the
+     *         specified interface and having the given persistent ID.
+     */
+    public static ServiceReference getServiceReferenceByPID(Bundle bundle,
+            String itf, String pid) {
+        String filter = "(" + "service.pid" + "=" + pid + ")";
+        ServiceReference[] refs = getServiceReferences(bundle, itf, filter);
+        if (refs == null) {
+            return null;
+        } else if (refs.length == 1) {
+            return refs[0];
+        } else {
+            throw new IllegalStateException(
+                    "A service lookup by PID returned several providers ("
+                            + refs.length + ")" + " for " + itf + " with pid="
+                            + pid);
+        }
+    }
+
+    /**
+     * Returns the service reference of all the services provided in the
+     * specified bundle, offering the specified interface and matching the given
+     * filter.
+     * 
+     * @param bundle the bundle from which services are searched.
+     * @param itf the interface provided by the searched services.
+     * @param filter an additional filter (can be {@code null}).
+     * @return all the service references provided in the specified bundle,
+     *         offering the specified interface and matching the given filter.
+     *         If no service matches, an empty array is returned.
+     */
+    public static ServiceReference[] getServiceReferences(Bundle bundle,
+            String itf, String filter) {
+        ServiceReference[] refs = null;
+        try {
+            // Get all the service references
+            refs = bundle.getBundleContext().getServiceReferences(itf, filter);
+        } catch (InvalidSyntaxException e) {
+            throw new IllegalArgumentException(
+                    "Cannot get service references: " + e.getMessage());
+        }
+        if (refs == null) {
+            return new ServiceReference[0];
+        } else {
+            return refs;
+        }
+    }
+
+    /**
+     * Returns the service object of a service provided by the local bundle,
+     * offering the specified interface and matching the given filter.
+     * 
+     * @param itf the interface provided by the searched service.
+     * @param filter an additional filter (can be {@code null}).
+     * @return the service object provided by the local bundle, offering the
+     *         specified interface and matching the given filter.
+     */
+    public Object getServiceObject(String itf, String filter) {
+        ServiceReference ref = getServiceReference(itf, filter);
+        if (ref != null) {
+            m_references.add(ref);
+            return context.getService(ref);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Returns the service object associated with this service reference.
+     * 
+     * @param ref service reference
+     * @return the service object.
+     */
+    public Object getServiceObject(ServiceReference ref) {
+        if (ref != null) {
+            m_references.add(ref);
+            return context.getService(ref);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Returns the service objects of the services provided by the local bundle,
+     * offering the specified interface and matching the given filter.
+     * 
+     * @param itf the interface provided by the searched services.
+     * @param filter an additional filter (can be {@code null}).
+     * @return the service objects provided by the local bundle, offering the
+     *         specified interface and matching the given filter.
+     */
+    public Object[] getServiceObjects(String itf, String filter) {
+        ServiceReference[] refs = getServiceReferences(itf, filter);
+        if (refs != null) {
+            Object[] list = new Object[refs.length];
+            for (int i = 0; i < refs.length; i++) {
+                m_references.add(refs[i]);
+                list[i] = context.getService(refs[i]);
+            }
+            return list;
+        } else {
+            return new Object[0];
+        }
+    }
+
+    /**
+     * Returns the service reference of a service provided by the local bundle,
+     * offering the specified interface and matching the given filter.
+     * 
+     * @param itf the interface provided by the searched service.
+     * @param filter an additional filter (can be {@code null}).
+     * @return a service reference provided by the local bundle, offering the
+     *         specified interface and matching the given filter. If no service
+     *         is found, {@code null} is returned.
+     */
+    public ServiceReference getServiceReference(String itf, String filter) {
+        return getServiceReference(context.getBundle(), itf, filter);
+    }
+
+    /**
+     * Returns the service reference of a service provided offering the
+     * specified interface.
+     * 
+     * @param itf the interface provided by the searched service.
+     * @return a service reference provided by the local bundle, offering the
+     *         specified interface and matching the given filter. If no service
+     *         is found, {@code null} is returned.
+     */
+    public ServiceReference getServiceReference(String itf) {
+        return getServiceReference(context.getBundle(), itf, null);
+    }
+
+    /**
+     * Returns the service reference of the service provided by the local
+     * bundle, offering the specified interface and having the given persistent
+     * ID.
+     * 
+     * @param itf the interface provided by the searched service.
+     * @param pid the persistent ID of the searched service.
+     * @return a service provided by the local bundle, offering the specified
+     *         interface and having the given persistent ID.
+     */
+    public ServiceReference getServiceReferenceByPID(String itf, String pid) {
+        return getServiceReferenceByPID(context.getBundle(), itf, pid);
+    }
+
+    /**
+     * Returns the service reference of all the services provided in the local
+     * bundle, offering the specified interface and matching the given filter.
+     * 
+     * @param itf the interface provided by the searched services.
+     * @param filter an additional filter (can be {@code null}).
+     * @return all the service references provided in the local bundle, offering
+     *         the specified interface and matching the given filter. If no
+     *         service matches, an empty array is returned.
+     */
+    public ServiceReference[] getServiceReferences(String itf, String filter) {
+        return getServiceReferences(context.getBundle(), itf, filter);
+    }
+    
+    /**
+     * Gets the package admin exposed by the framework.
+     * Fails if the package admin is not available. 
+     * @return the package admin service.
+     */
+    public PackageAdmin getPackageAdmin() {
+        PackageAdmin pa = (PackageAdmin) getServiceObject(PackageAdmin.class.getName(), null);
+        if (pa == null) {
+            fail("No package admin available");
+        }
+        return pa;
+    }
+    
+    /**
+     * Refresh the packages.
+     * Fails if the package admin service is not available.
+     */
+    public void refresh() {
+        getPackageAdmin().refreshPackages(null);
+    }
+    
+    /**
+     * Waits for a service. Fails on timeout.
+     * If timeout is set to 0, it sets the timeout to 10s.
+     * @param itf the service interface
+     * @param filter  the filter
+     * @param timeout the timeout
+     */
+    public void waitForService(String itf, String filter, long timeout) {
+        if (timeout == 0) {
+            timeout = 10000; // Default 10 secondes.
+        }
+        ServiceReference[] refs = getServiceReferences(itf, filter);
+        long begin = System.currentTimeMillis();
+        if (refs.length != 0) {
+            return;
+        } else {
+            while(refs.length == 0) {
+                try {
+                    Thread.sleep(5);
+                } catch (InterruptedException e) {
+                    // Interrupted
+                }
+                long now = System.currentTimeMillis();
+                
+                if ((now - begin) > timeout) {
+                    fail("Timeout ... no services matching with the request after " + timeout + "ms");
+                }
+                refs = getServiceReferences(itf, filter);
+            }
+        }
+    }
+    
+    
+    /**
+     * Installs a bundle.
+     * Fails if the bundle cannot be installed.
+     * Be aware that you have to uninstall the bundle yourself.
+     * @param url bundle url
+     * @return the installed bundle
+     */
+    public Bundle installBundle(String url) {
+        try {
+            return context.installBundle(url);
+        } catch (BundleException e) {
+            fail("Cannot install the bundle " + url + " : " + e.getMessage());
+        }
+        return null; // Can not happen
+    }
+    
+    /**
+     * Installs a bundle.
+     * Fails if the bundle cannot be installed.
+     * Be aware that you have to uninstall the bundle yourself.
+     * @param url bundle url
+     * @param stream input stream containing the bundle
+     * @return the installed bundle
+     */
+    public Bundle installBundle(String url, InputStream stream) {
+        try {
+            return context.installBundle(url, stream);
+        } catch (BundleException e) {
+            fail("Cannot install the bundle " + url + " : " + e.getMessage());
+        }
+        return null; // Can not happen
+    }
+    
+    /**
+     * Installs and starts a bundle.
+     * Fails if the bundle cannot be installed or an error occurs
+     * during startup. Be aware that you have to uninstall the bundle
+     * yourself.
+     * @param url the bundle url
+     * @return the Bundle object.
+     */
+    public Bundle installAndStart(String url) {
+        Bundle bundle = installBundle(url);
+        try {
+            bundle.start();
+        } catch (BundleException e) {
+           fail("Cannot start the bundle " + url + " : " + e.getMessage());
+        }
+        return bundle;
+    }
+    
+    /**
+     * Installs and starts a bundle.
+     * Fails if the bundle cannot be installed or an error occurs
+     * during startup. Be aware that you have to uninstall the bundle
+     * yourself.
+     * @param url the bundle url
+     * @param stream input stream containing the bundle
+     * @return the Bundle object.
+     */
+    public Bundle installAndStart(String url, InputStream stream) {
+        Bundle bundle = installBundle(url, stream);
+        try {
+            bundle.start();
+        } catch (BundleException e) {
+           fail("Cannot start the bundle " + url + " : " + e.getMessage());
+        }
+        return bundle;
+    }
+    
+    /**
+     * Get the bundle by its id.
+     * @param bundleId the bundle id.
+     * @return the bundle with the given id.
+     */
+    public Bundle getBundle(long bundleId) {
+        return context.getBundle(bundleId);
+    }
+    
+    /**
+     * Gets a bundle by its symbolic name.
+     * Fails if no bundle matches.
+     * @param name the symbolic name of the bundle
+     * @return the bundle object.
+     */
+    public Bundle getBundle(String name) {
+        Bundle[] bundles = context.getBundles();
+        for (int i = 0; i < bundles.length; i++) {
+            if (name.equals(bundles[i].getSymbolicName())) {
+                return bundles[i];
+            }
+        }
+        fail("No bundles with the given symbolic name " + name);
+        return null; // should not happen
+    }
+
+}
diff --git a/ipojo/tests/online-manipulator/src/test/java/org/apache/felix/org/apache/felix/ipojo/online/manipulator/test/OnlineManipulatorTest.java b/ipojo/tests/online-manipulator/src/test/java/org/apache/felix/org/apache/felix/ipojo/online/manipulator/test/OnlineManipulatorTest.java
new file mode 100644
index 0000000..63c42b0
--- /dev/null
+++ b/ipojo/tests/online-manipulator/src/test/java/org/apache/felix/org/apache/felix/ipojo/online/manipulator/test/OnlineManipulatorTest.java
@@ -0,0 +1,363 @@
+package org.apache.felix.org.apache.felix.ipojo.online.manipulator.test;
+
+
+import static org.ops4j.pax.exam.CoreOptions.equinox;
+import static org.ops4j.pax.exam.CoreOptions.felix;
+import static org.ops4j.pax.exam.CoreOptions.frameworks;
+import static org.ops4j.pax.exam.CoreOptions.knopflerfish;
+import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
+import static org.ops4j.pax.exam.CoreOptions.options;
+import static org.ops4j.pax.exam.CoreOptions.provision;
+import static org.ops4j.pax.exam.CoreOptions.systemProperty;
+import static org.ops4j.pax.tinybundles.core.TinyBundles.asFile;
+import static org.ops4j.pax.tinybundles.core.TinyBundles.asURL;
+import static org.ops4j.pax.tinybundles.core.TinyBundles.newBundle;
+import static org.ops4j.pax.tinybundles.core.TinyBundles.with;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.felix.ipojo.ComponentInstance;
+import org.apache.felix.ipojo.architecture.Architecture;
+import org.apache.felix.ipojo.architecture.InstanceDescription;
+import org.apache.felix.org.apache.felix.ipojo.online.manipulator.test.impl.Consumer;
+import org.apache.felix.org.apache.felix.ipojo.online.manipulator.test.impl.MyProvider;
+import org.apache.felix.org.apache.felix.ipojo.online.manipulator.test.service.Hello;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Inject;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.Configuration;
+import org.ops4j.pax.exam.junit.JUnit4TestRunner;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+
+
+@RunWith( JUnit4TestRunner.class )
+public class OnlineManipulatorTest {
+    
+    
+    private static File TMP = new File("target/tmp-bundle");
+    
+    @Inject
+    BundleContext context;
+
+    private OSGiHelper helper;
+
+    
+    /*
+     * <groupId>org.apache.felix</groupId>
+  <artifactId>org.apache.felix.ipojo.online.manipulator</artifactId>
+  <version>1.3.0-SNAPSHOT</version>
+ 
+     */
+    
+    @Configuration
+    public static Option[] configure() throws IOException
+    {
+        
+        
+
+        String providerWithMetadata = providerWithMetadata();
+        String providerWithMetadataInMetaInf = providerWithMetadataInMetaInf();
+        String providerWithoutMetadata = providerWithoutMetadata();
+        String consumerWithMetadata =  consumerWithMetadata();
+        String consumerWithoutMetadata = consumerWithoutMetadata();
+        
+        return options(
+                frameworks(
+                        felix(),
+                        equinox()
+                    ),
+            provision(
+                mavenBundle()
+                    .groupId( "org.ops4j.pax.tinybundles" )
+                    .artifactId( "pax-tinybundles-core" )
+                    .version( "0.5.0-SNAPSHOT" )),
+            provision( 
+                    mavenBundle()
+                    .groupId("org.apache.felix")
+                    .artifactId("org.apache.felix.ipojo")
+                    .version("1.3.0-SNAPSHOT")
+            ),
+            
+            provision(
+                    mavenBundle()
+                    .groupId("org.apache.felix")
+                    .artifactId("org.apache.felix.ipojo.online.manipulator")
+                    .version("1.3.0-SNAPSHOT")
+                    ),
+            provision(
+                            newBundle()
+                                .addClass( Hello.class )
+                                .prepare()
+                               .set(Constants.BUNDLE_SYMBOLICNAME,"ServiceInterface")
+                               .set(Constants.EXPORT_PACKAGE, "org.apache.felix.org.apache.felix.ipojo.online.manipulator.test.service")
+                                .build( asURL() ).toExternalForm()
+                        ),
+           systemProperty( "providerWithMetadata" ).value( providerWithMetadata ),
+           systemProperty( "providerWithMetadataInMetaInf" ).value( providerWithMetadataInMetaInf ),
+           systemProperty( "providerWithoutMetadata" ).value( providerWithoutMetadata ),
+           systemProperty( "consumerWithMetadata").value(consumerWithMetadata),
+           systemProperty( "consumerWithoutMetadata").value(consumerWithoutMetadata)
+           );
+        
+       
+
+
+    }
+    
+    @Before
+    public void before() {
+        helper = new OSGiHelper(context);
+    }
+    
+    @After
+    public void after() {
+        helper.dispose();
+    }
+    
+    private static File getTemporaryFile(String name) throws IOException {
+        if (! TMP.exists()) {
+            TMP.mkdirs();
+            TMP.deleteOnExit();
+        }
+        File file = File.createTempFile(name, ".jar", TMP);
+        //File file = new File(TMP, name + ".jar");
+        if (file.exists()) {
+            file.delete();
+        }
+        file.deleteOnExit();
+        return file;  
+    }
+    
+    @Test
+    public void installProviderWithMetadata1() throws BundleException, InvalidSyntaxException, IOException {
+        String url = context.getProperty("providerWithMetadata");
+        Assert.assertNotNull(url);
+        context.installBundle("ipojo:"+url).start();
+        
+        assertBundle("Provider");
+        helper.waitForService(Hello.class.getName(), null, 5000);
+        assertValidity();
+        Assert.assertNotNull(context.getServiceReference(Hello.class.getName()));
+    }
+    
+   
+
+    @Test
+    public void installProviderWithMetadata2() throws BundleException, InvalidSyntaxException, IOException {
+        String url = context.getProperty("providerWithMetadataInMetaInf");
+        Assert.assertNotNull(url);
+        context.installBundle("ipojo:"+url).start();
+        assertBundle("Provider");
+        helper.waitForService(Hello.class.getName(), null, 5000);
+        assertValidity();
+        Assert.assertNotNull(context.getServiceReference(Hello.class.getName()));
+    }
+    
+    @Test
+    public void installProviderWithoutMetadata() throws BundleException, InvalidSyntaxException, IOException {
+        String url = context.getProperty("providerWithoutMetadata");
+        Assert.assertNotNull(url);
+        context.installBundle("ipojo:"+url).start();
+        assertBundle("Provider");
+        helper.waitForService(Hello.class.getName(), null, 5000);
+        assertValidity();
+        Assert.assertNotNull(context.getServiceReference(Hello.class.getName()));
+    }
+    
+    @Test
+    public void installConsumerWithMetadata() throws BundleException, InvalidSyntaxException, IOException {
+        String url = context.getProperty("providerWithoutMetadata");
+        Assert.assertNotNull(url);
+        context.installBundle("ipojo:"+url).start();
+        assertBundle("Provider");
+        
+        String url2 = context.getProperty("consumerWithMetadata");
+        Assert.assertNotNull(url);
+        context.installBundle("ipojo:"+url2).start();
+        assertBundle("Consumer");
+        helper.waitForService(Hello.class.getName(), null, 5000);
+        // Wait for activation.
+        try {
+            Thread.sleep(2000);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+        assertValidity();
+        Assert.assertNotNull(context.getServiceReference(Hello.class.getName()));
+    }
+    
+    @Test
+    public void installConsumerWithoutMetadata() throws BundleException, InvalidSyntaxException, IOException {
+        String url = context.getProperty("providerWithMetadataInMetaInf");
+        Assert.assertNotNull(url);
+        context.installBundle("ipojo:"+url).start();
+        assertBundle("Provider");
+        helper.waitForService(Hello.class.getName(), null, 5000);
+
+        String url2 = context.getProperty("consumerWithoutMetadata");
+        Assert.assertNotNull(url);
+        context.installBundle("ipojo:"+url2).start();
+        assertBundle("Consumer");
+        // Wait for activation.
+        try {
+            Thread.sleep(2000);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }  
+        assertValidity();
+        Assert.assertNotNull(context.getServiceReference(Hello.class.getName()));
+    }
+    
+    /**
+     * Gets a regular bundle containing metadata file
+     * @return the url of the bundle
+     * @throws IOException 
+     */
+    public static String providerWithMetadata() throws IOException {
+        return newBundle()
+        .addResource("metadata.xml", OnlineManipulatorTest.class.getClassLoader().getResource("provider.xml"))
+        .addClass(MyProvider.class)
+        .prepare( 
+            with()
+                .set(Constants.BUNDLE_SYMBOLICNAME,"Provider")
+                .set(Constants.IMPORT_PACKAGE, "org.apache.felix.org.apache.felix.ipojo.online.manipulator.test.service")
+            )
+              .build( asFile(getTemporaryFile("providerWithMetadata")) ).toURL().toExternalForm();
+    }
+    
+    /**
+     * Gets a regular bundle containing metadata file in the META-INF directory
+     * @return the url of the bundle
+     * @throws IOException 
+     */
+    public static String providerWithMetadataInMetaInf() throws IOException {
+        return newBundle()
+        .addResource("META-INF/metadata.xml", OnlineManipulatorTest.class.getClassLoader().getResource("provider.xml"))
+        .addClass(MyProvider.class)
+        .prepare( 
+            with()
+                .set(Constants.BUNDLE_SYMBOLICNAME,"Provider")
+                .set(Constants.IMPORT_PACKAGE, "org.apache.felix.org.apache.felix.ipojo.online.manipulator.test.service")
+            )
+              .build( asFile(getTemporaryFile("providerWithMetadataInMetaInf")) ).toURL().toExternalForm();
+    }
+    
+    /**
+     * Gets a provider bundle which does not contain the metadata file.
+     * @return the url of the bundle + metadata
+     * @throws IOException 
+     */
+    public static String providerWithoutMetadata() throws IOException {
+        String url = newBundle()
+        //.addResource("metadata.xml", this.getClass().getClassLoader().getResource("provider.xml"))
+        .addClass(MyProvider.class)
+        .prepare( 
+            with()
+                .set(Constants.BUNDLE_SYMBOLICNAME,"Provider")
+                .set(Constants.IMPORT_PACKAGE, "org.apache.felix.org.apache.felix.ipojo.online.manipulator.test.service")
+            )
+              .build( asFile(getTemporaryFile("providerWithoutMetadata")) ).toURL().toExternalForm();
+        
+        return url + "!" +OnlineManipulatorTest.class.getClassLoader().getResource("provider.xml");
+    }
+    
+    /**
+     * Gets a consumer bundle using annotation containing the instance
+     * declaration in the metadata.
+     * @return the url of the bundle
+     * @throws IOException 
+     */
+    public static String consumerWithMetadata() throws IOException {
+        return newBundle()
+            .addResource("metadata.xml", OnlineManipulatorTest.class.getClassLoader().getResource("consumer.xml"))
+            .addClass(Consumer.class)
+
+        .prepare(
+                with()
+                        .set(Constants.BUNDLE_SYMBOLICNAME, "Consumer")
+                .set(Constants.IMPORT_PACKAGE, "org.apache.felix.org.apache.felix.ipojo.online.manipulator.test.service")
+                )
+                .build( asFile(getTemporaryFile("consumerWithMetadata")) ).toURL().toExternalForm();
+       
+    }
+    
+    /**
+     * Gets a consumer bundle using annotation that does not contain
+     * metadata
+     * @return the url of the bundle + metadata
+     * @throws IOException 
+     */
+    public static String consumerWithoutMetadata() throws IOException {
+        String url = newBundle()
+        .addClass(Consumer.class)
+        .prepare(
+                with()
+                        .set(Constants.BUNDLE_SYMBOLICNAME, "Consumer")
+                .set(Constants.IMPORT_PACKAGE, "org.apache.felix.org.apache.felix.ipojo.online.manipulator.test.service")
+                )
+                .build( asFile(getTemporaryFile("consumerWithoutMetadata")) ).toURL().toExternalForm();
+        
+        return url + "!" + OnlineManipulatorTest.class.getClassLoader().getResource("consumer.xml");
+    }
+    
+    
+    
+    public void dumpServices() throws InvalidSyntaxException {
+        ServiceReference[] refs = context.getAllServiceReferences(null, null);
+        System.out.println(" === Services === ");
+        for (ServiceReference ref : refs) {
+            String[] itf = (String[]) ref.getProperty(Constants.OBJECTCLASS);
+            System.out.println(itf[0]);
+        }
+        System.out.println("====");
+    }
+    
+    public void dumpBundles() throws InvalidSyntaxException {
+        Bundle[] bundles = context.getBundles();
+        System.out.println(" === Bundles === ");
+        for (Bundle bundle : bundles) {
+            String sn  =  bundle.getSymbolicName();
+            System.out.println(sn);
+        }
+        System.out.println("====");
+    }
+    
+    private void assertBundle(String sn) {
+        for (Bundle bundle :context.getBundles()) {
+            if (bundle.getSymbolicName().equals(sn)
+                    && bundle.getState() == Bundle.ACTIVE) {
+                return;
+            }
+                
+        }
+        Assert.fail("Cannot find the bundle " + sn);
+    }
+    
+    private void assertValidity() {
+        try {
+            ServiceReference[] refs = context.getServiceReferences(Architecture.class.getName(), null);
+            Assert.assertNotNull(refs);
+            for (int i = 0; i < refs.length; i++) {
+                InstanceDescription id = ((Architecture) context.getService(refs[i])).getInstanceDescription();
+                int state = id.getState();
+                Assert.assertEquals("State of " + id.getName(), ComponentInstance.VALID, state);
+            }
+        } catch (InvalidSyntaxException e) {
+            Assert.fail(e.getMessage());
+        }
+            
+    }
+    
+  
+
+}
diff --git a/ipojo/tests/online-manipulator/src/test/java/org/apache/felix/org/apache/felix/ipojo/online/manipulator/test/impl/Consumer.java b/ipojo/tests/online-manipulator/src/test/java/org/apache/felix/org/apache/felix/ipojo/online/manipulator/test/impl/Consumer.java
new file mode 100644
index 0000000..1f83497
--- /dev/null
+++ b/ipojo/tests/online-manipulator/src/test/java/org/apache/felix/org/apache/felix/ipojo/online/manipulator/test/impl/Consumer.java
@@ -0,0 +1,17 @@
+package org.apache.felix.org.apache.felix.ipojo.online.manipulator.test.impl;
+
+import org.apache.felix.ipojo.annotations.Component;
+import org.apache.felix.ipojo.annotations.Requires;
+import org.apache.felix.org.apache.felix.ipojo.online.manipulator.test.service.Hello;
+
+@Component
+public class Consumer {
+    
+    @Requires
+    private Hello hello;
+    
+    public Consumer() {
+        System.out.println(hello.sayHello());
+    }
+
+}
diff --git a/ipojo/tests/online-manipulator/src/test/java/org/apache/felix/org/apache/felix/ipojo/online/manipulator/test/impl/MyProvider.java b/ipojo/tests/online-manipulator/src/test/java/org/apache/felix/org/apache/felix/ipojo/online/manipulator/test/impl/MyProvider.java
new file mode 100644
index 0000000..592132a
--- /dev/null
+++ b/ipojo/tests/online-manipulator/src/test/java/org/apache/felix/org/apache/felix/ipojo/online/manipulator/test/impl/MyProvider.java
@@ -0,0 +1,11 @@
+package org.apache.felix.org.apache.felix.ipojo.online.manipulator.test.impl;
+
+import org.apache.felix.org.apache.felix.ipojo.online.manipulator.test.service.Hello;
+
+public class MyProvider implements Hello {
+    
+    public String sayHello() {
+        return "Hello";
+    }
+
+}
diff --git a/ipojo/tests/online-manipulator/src/test/java/org/apache/felix/org/apache/felix/ipojo/online/manipulator/test/service/Hello.java b/ipojo/tests/online-manipulator/src/test/java/org/apache/felix/org/apache/felix/ipojo/online/manipulator/test/service/Hello.java
new file mode 100644
index 0000000..83de144
--- /dev/null
+++ b/ipojo/tests/online-manipulator/src/test/java/org/apache/felix/org/apache/felix/ipojo/online/manipulator/test/service/Hello.java
@@ -0,0 +1,7 @@
+package org.apache.felix.org.apache.felix.ipojo.online.manipulator.test.service;
+
+public interface Hello {
+    
+    public String sayHello();
+
+}
diff --git a/ipojo/tests/pom.xml b/ipojo/tests/pom.xml
index 0354f23..1aa72ed 100644
--- a/ipojo/tests/pom.xml
+++ b/ipojo/tests/pom.xml
@@ -50,6 +50,7 @@
 	<module>handler/eventadmin</module>

 	<module>core/configadmin</module>

 	<module>api</module>

+	<module>online-manipulator</module>

    </modules>

    

    <profiles>