You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by gu...@apache.org on 2013/01/07 17:41:00 UTC

svn commit: r1429888 - in /felix/trunk/ipojo/manipulator/bnd-ipojo-plugin/src: main/java/org/apache/felix/ipojo/bnd/ test/java/org/apache/felix/ipojo/bnd/ test/resources/

Author: guillaume
Date: Mon Jan  7 16:41:00 2013
New Revision: 1429888

URL: http://svn.apache.org/viewvc?rev=1429888&view=rev
Log:
FELIX-3827 - Bnd iPOJO Plugin, error when manipulating embed jars/bundles

* Deal with components embed in Bundle-Classpath
* Added a property (include-embed-bundles) to activate that behavior
* If embed dependency is already manipulated, its already generated IPOJO-Component
  header is merged within the bnd generated Manifest
* If embed contains annotated iPOJO classes, but has not been manipulated, 
  components are manipulated and the generated byte code is placed in the
  generated bundle (we don't touch the embed dependency)

Added:
    felix/trunk/ipojo/manipulator/bnd-ipojo-plugin/src/main/java/org/apache/felix/ipojo/bnd/Manifests.java
    felix/trunk/ipojo/manipulator/bnd-ipojo-plugin/src/test/java/org/apache/felix/ipojo/bnd/BndJarResourceStoreTestCase.java
    felix/trunk/ipojo/manipulator/bnd-ipojo-plugin/src/test/java/org/apache/felix/ipojo/bnd/EmptyComponent.java
    felix/trunk/ipojo/manipulator/bnd-ipojo-plugin/src/test/resources/EMBED-MANIFEST-EMPTY.MF
    felix/trunk/ipojo/manipulator/bnd-ipojo-plugin/src/test/resources/EMBED-MANIFEST.MF
    felix/trunk/ipojo/manipulator/bnd-ipojo-plugin/src/test/resources/metadata-test-component.xml
Modified:
    felix/trunk/ipojo/manipulator/bnd-ipojo-plugin/src/main/java/org/apache/felix/ipojo/bnd/BndJarResourceStore.java
    felix/trunk/ipojo/manipulator/bnd-ipojo-plugin/src/main/java/org/apache/felix/ipojo/bnd/PojoizationPlugin.java
    felix/trunk/ipojo/manipulator/bnd-ipojo-plugin/src/main/java/org/apache/felix/ipojo/bnd/ResourceMetadataProvider.java

Modified: felix/trunk/ipojo/manipulator/bnd-ipojo-plugin/src/main/java/org/apache/felix/ipojo/bnd/BndJarResourceStore.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/manipulator/bnd-ipojo-plugin/src/main/java/org/apache/felix/ipojo/bnd/BndJarResourceStore.java?rev=1429888&r1=1429887&r2=1429888&view=diff
==============================================================================
--- felix/trunk/ipojo/manipulator/bnd-ipojo-plugin/src/main/java/org/apache/felix/ipojo/bnd/BndJarResourceStore.java (original)
+++ felix/trunk/ipojo/manipulator/bnd-ipojo-plugin/src/main/java/org/apache/felix/ipojo/bnd/BndJarResourceStore.java Mon Jan  7 16:41:00 2013
@@ -34,7 +34,16 @@ import org.apache.felix.ipojo.metadata.E
 
 import java.io.IOException;
 import java.io.InputStream;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.jar.Attributes;
+import java.util.jar.Manifest;
 
 public class BndJarResourceStore implements ResourceStore {
 
@@ -44,6 +53,7 @@ public class BndJarResourceStore impleme
     private MetadataRenderer m_renderer = new MetadataRenderer();
 
     private List<Element> m_metadata;
+    private boolean m_includeEmbedComponents;
 
     public BndJarResourceStore(Analyzer analyzer, Reporter reporter) {
         m_metadata = new ArrayList<Element>();
@@ -52,7 +62,13 @@ public class BndJarResourceStore impleme
     }
 
     public byte[] read(String path) throws IOException {
+
+        // Find the resource either in the global jar or in one of the embed dependencies
         Resource resource = m_analyzer.getJar().getResource(path);
+        if (resource == null) {
+            Jar embed = findJar(path);
+            resource = embed.getResource(path);
+        }
         InputStream is = null;
         try {
             is = resource.openInputStream();
@@ -65,6 +81,7 @@ public class BndJarResourceStore impleme
     public void accept(ResourceVisitor visitor) {
 
         try {
+            // TODO make this configurable (react to other annotations)
             // Only visit classes annotated with @Component or @Handler
             String annotations = Component.class.getPackage().getName() + ".*";
 
@@ -72,6 +89,8 @@ public class BndJarResourceStore impleme
                     Clazz.QUERY.ANNOTATION.name(), annotations,
                     Clazz.QUERY.NAMED.name(), "*");
 
+            classes = filter(classes);
+
             // Iterates over discovered resources
             for (Clazz clazz : classes) {
                 visitor.visit(clazz.getPath());
@@ -81,6 +100,61 @@ public class BndJarResourceStore impleme
         }
     }
 
+    private Collection<Clazz> filter(Collection<Clazz> classes) throws Exception {
+        Set<Clazz> manipulable = new HashSet<Clazz>();
+        for (Clazz clazz : classes) {
+
+            // If it is i the main jar, simply use it
+            if (m_analyzer.getJar().getResource(clazz.getPath()) != null) {
+                manipulable.add(clazz);
+                continue;
+            }
+
+            if (m_includeEmbedComponents) {
+                // Otherwise ...
+                // Try to see if it is in an embed dependencies
+                Jar jar = findJar(clazz.getPath());
+                if (jar == null) {
+                    m_reporter.error("Resource for class %s not found in classpath", clazz.getFQN());
+                    continue;
+                }
+
+                // Is it a Bundle ?
+                if (jar.getBsn() != null) {
+                    // OSGi Bundle case
+
+                    // Check if the bundle was manipulated before
+                    Attributes attr = jar.getManifest().getMainAttributes();
+                    if (Manifests.getComponents(attr) != null) {
+                        // Bundle has been previously manipulated
+                        // TODO We should ignore the resource since it was already manipulated
+                        // TODO But we should also merge its IPOJO-Components header
+                    } else {
+                        // Bundle was not manipulated
+                        manipulable.add(clazz);
+                    }
+
+                } else  {
+                    // Simple Jar file with iPOJO annotations
+                    m_reporter.warning("Class %s found in a non-Bundle archive %s", clazz.getFQN(), jar.getName());
+                    continue;
+                }
+            } else {
+                m_reporter.warning("Embed components are excluded, Component %s will not be manipulated", clazz.getFQN());
+            }
+        }
+        return manipulable;
+    }
+
+    private Jar findJar(String path) {
+        for (Jar jar : m_analyzer.getClasspath()) {
+            if (jar.getResource(path) != null) {
+                return jar;
+            }
+        }
+        return null;
+    }
+
     public void open() throws IOException {
         // nothing to do
     }
@@ -105,8 +179,27 @@ public class BndJarResourceStore impleme
     }
 
     public void close() throws IOException {
+
         // Write the iPOJO header (including manipulation metadata)
         StringBuilder builder = new StringBuilder();
+
+        if (m_includeEmbedComponents) {
+            // Incorporate metadata of embed dependencies (if any)
+            for (Jar jar : m_analyzer.getClasspath()) {
+                try {
+                    Manifest manifest = jar.getManifest();
+                    Attributes main = manifest.getMainAttributes();
+                    String components = Manifests.getComponents(main);
+                    if (components != null) {
+                        m_reporter.progress("Merging components from %s", jar.getName());
+                        builder.append(components);
+                    }
+                } catch (Exception e) {
+                    m_reporter.warning("Cannot open MANIFEST of %s", jar.getName());
+                }
+            }
+        }
+
         for (Element metadata : m_metadata) {
             builder.append(m_renderer.render(metadata));
         }
@@ -138,4 +231,8 @@ public class BndJarResourceStore impleme
 
 
     }
+
+    public void setIncludeEmbedComponents(boolean excludeEmbedComponents) {
+        m_includeEmbedComponents = excludeEmbedComponents;
+    }
 }

Added: felix/trunk/ipojo/manipulator/bnd-ipojo-plugin/src/main/java/org/apache/felix/ipojo/bnd/Manifests.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/manipulator/bnd-ipojo-plugin/src/main/java/org/apache/felix/ipojo/bnd/Manifests.java?rev=1429888&view=auto
==============================================================================
--- felix/trunk/ipojo/manipulator/bnd-ipojo-plugin/src/main/java/org/apache/felix/ipojo/bnd/Manifests.java (added)
+++ felix/trunk/ipojo/manipulator/bnd-ipojo-plugin/src/main/java/org/apache/felix/ipojo/bnd/Manifests.java Mon Jan  7 16:41:00 2013
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.bnd;
+
+import aQute.lib.osgi.Analyzer;
+import aQute.lib.osgi.Jar;
+
+import java.util.jar.Attributes;
+
+/**
+ * A {@code Manifests} is a utility class for extracting data from Bundle's Manifest.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class Manifests {
+    private Manifests() {}
+
+    public static String getComponents(Attributes main) {
+        String value = main.getValue("iPOJO-Components");
+        if (value == null) {
+            value = main.getValue("IPOJO-Components");
+        }
+
+        return value;
+    }
+
+    public static boolean hasEmbedComponents(Analyzer analyzer) throws Exception {
+        for (Jar jar : analyzer.getClasspath()) {
+            // Check if the bundle was manipulated before
+            Attributes attr = jar.getManifest().getMainAttributes();
+            if (getComponents(attr) != null) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+
+}

Modified: felix/trunk/ipojo/manipulator/bnd-ipojo-plugin/src/main/java/org/apache/felix/ipojo/bnd/PojoizationPlugin.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/manipulator/bnd-ipojo-plugin/src/main/java/org/apache/felix/ipojo/bnd/PojoizationPlugin.java?rev=1429888&r1=1429887&r2=1429888&view=diff
==============================================================================
--- felix/trunk/ipojo/manipulator/bnd-ipojo-plugin/src/main/java/org/apache/felix/ipojo/bnd/PojoizationPlugin.java (original)
+++ felix/trunk/ipojo/manipulator/bnd-ipojo-plugin/src/main/java/org/apache/felix/ipojo/bnd/PojoizationPlugin.java Mon Jan  7 16:41:00 2013
@@ -18,11 +18,6 @@
  */
 package org.apache.felix.ipojo.bnd;
 
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
 import aQute.bnd.service.AnalyzerPlugin;
 import aQute.bnd.service.Plugin;
 import aQute.lib.osgi.Analyzer;
@@ -39,6 +34,13 @@ import org.apache.felix.ipojo.manipulato
 import org.apache.felix.ipojo.manipulator.visitor.writer.ManipulatedResourcesWriter;
 import org.apache.felix.ipojo.metadata.Element;
 
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import static org.apache.felix.ipojo.bnd.Manifests.hasEmbedComponents;
+
 /**
  * A {@code BndIpojoPlugin} is ...
  *
@@ -48,12 +50,15 @@ public class PojoizationPlugin implement
 
     private static final String PROPERTY_METADATA = "metadata";
     private static final String PROPERTY_USE_LOCAL_SCHEMAS = "use-local-schemas";
+    private static final String PROPERTY_INCLUDE_EMBED_BUNDLES = "include-embed-bundles";
 
     private static final String DEFAULT_METADATA = "META-INF/metadata.xml";
     private static final boolean DEFAULT_USE_LOCAL_SCHEMAS = false;
+    private static final boolean DEFAULT_INCLUDE_EMBED_BUNDLES = false;
 
     private String m_metadata = DEFAULT_METADATA;
     private boolean m_useLocalSchemas = DEFAULT_USE_LOCAL_SCHEMAS;
+    private boolean m_includeEmbedBundles = DEFAULT_INCLUDE_EMBED_BUNDLES;
 
     private Reporter m_reporter;
 
@@ -68,6 +73,11 @@ public class PojoizationPlugin implement
         if (configuration.containsKey(PROPERTY_USE_LOCAL_SCHEMAS)) {
             m_useLocalSchemas = true;
         }
+
+        // Process embed bundles ?
+        if (configuration.containsKey(PROPERTY_INCLUDE_EMBED_BUNDLES)) {
+            m_includeEmbedBundles = true;
+        }
     }
 
     public void setReporter(Reporter reporter) {
@@ -83,6 +93,7 @@ public class PojoizationPlugin implement
 
         // Build ResourceStore
         BndJarResourceStore store = new BndJarResourceStore(analyzer, this.m_reporter);
+        store.setIncludeEmbedComponents(m_includeEmbedBundles);
 
         // Build MetadataProvider
         CompositeMetadataProvider provider = new CompositeMetadataProvider(reporter);
@@ -105,7 +116,7 @@ public class PojoizationPlugin implement
         provider.addMetadataProvider(new AnnotationMetadataProvider(store, reporter));
 
         CacheableMetadataProvider cache = new CacheableMetadataProvider(provider);
-        if (cache.getMetadatas().isEmpty()) {
+        if (cache.getMetadatas().isEmpty() && !hasEmbedComponents(analyzer)) {
             return false;
         }
 
@@ -128,6 +139,12 @@ public class PojoizationPlugin implement
         return false;
     }
 
+    private boolean hasEmbedComponents(Analyzer analyzer) throws Exception {
+        // We want to process components from embed jars ?
+        return m_includeEmbedBundles && Manifests.hasEmbedComponents(analyzer);
+
+    }
+
     private List<Element> findElements(List<Element> metadatas, String name) {
         List<Element> found = new ArrayList<Element>();
         for (Element element : metadatas) {

Modified: felix/trunk/ipojo/manipulator/bnd-ipojo-plugin/src/main/java/org/apache/felix/ipojo/bnd/ResourceMetadataProvider.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/manipulator/bnd-ipojo-plugin/src/main/java/org/apache/felix/ipojo/bnd/ResourceMetadataProvider.java?rev=1429888&r1=1429887&r2=1429888&view=diff
==============================================================================
--- felix/trunk/ipojo/manipulator/bnd-ipojo-plugin/src/main/java/org/apache/felix/ipojo/bnd/ResourceMetadataProvider.java (original)
+++ felix/trunk/ipojo/manipulator/bnd-ipojo-plugin/src/main/java/org/apache/felix/ipojo/bnd/ResourceMetadataProvider.java Mon Jan  7 16:41:00 2013
@@ -18,17 +18,17 @@
  */
 package org.apache.felix.ipojo.bnd;
 
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.List;
-
 import aQute.lib.osgi.Resource;
 import org.apache.felix.ipojo.manipulator.MetadataProvider;
 import org.apache.felix.ipojo.manipulator.Reporter;
 import org.apache.felix.ipojo.manipulator.metadata.StreamMetadataProvider;
 import org.apache.felix.ipojo.metadata.Element;
 
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * A {@code ResourceMetadataProvider} is ...
  *
@@ -60,8 +60,8 @@ public class ResourceMetadataProvider im
             try {
                 stream = m_resource.openInputStream();
             } catch (Exception e) {
-                m_reporter.error(e.getMessage());
-                throw new IOException("Cannot read metadata");
+                m_reporter.error("%s", e.getMessage());
+                throw new IOException("Cannot read metadata", e);
             }
             StreamMetadataProvider provider = new StreamMetadataProvider(stream, m_reporter);
             provider.setValidateUsingLocalSchemas(m_validateUsingLocalSchemas);

Added: felix/trunk/ipojo/manipulator/bnd-ipojo-plugin/src/test/java/org/apache/felix/ipojo/bnd/BndJarResourceStoreTestCase.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/manipulator/bnd-ipojo-plugin/src/test/java/org/apache/felix/ipojo/bnd/BndJarResourceStoreTestCase.java?rev=1429888&view=auto
==============================================================================
--- felix/trunk/ipojo/manipulator/bnd-ipojo-plugin/src/test/java/org/apache/felix/ipojo/bnd/BndJarResourceStoreTestCase.java (added)
+++ felix/trunk/ipojo/manipulator/bnd-ipojo-plugin/src/test/java/org/apache/felix/ipojo/bnd/BndJarResourceStoreTestCase.java Mon Jan  7 16:41:00 2013
@@ -0,0 +1,172 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.bnd;
+
+import aQute.lib.osgi.Analyzer;
+import aQute.lib.osgi.Clazz;
+import aQute.lib.osgi.Jar;
+import aQute.lib.osgi.Resource;
+import aQute.lib.osgi.URLResource;
+import aQute.libg.reporter.Reporter;
+import junit.framework.TestCase;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.Spy;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.verify;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: guillaume
+ * Date: 04/01/13
+ * Time: 15:33
+ * To change this template use File | Settings | File Templates.
+ */
+public class BndJarResourceStoreTestCase extends TestCase {
+    @Mock
+    private Reporter reporter;
+
+    @Spy
+    private Analyzer analyzer = new Analyzer();
+
+    @Spy
+    private Jar dot = new Jar("root.jar");
+
+    @Spy
+    private Jar embed = new Jar("embed.jar");
+
+    @Override
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    public void testAnalysisWithOnlyEmbedComponents() throws Exception {
+        PojoizationPlugin plugin = new PojoizationPlugin();
+
+        Map<String, String> props = new HashMap<String, String>();
+        props.put("include-embed-bundles", "true");
+
+        Resource resource = new URLResource(getClass().getResource("/EMBED-MANIFEST.MF"));
+        doReturn(dot).when(analyzer).getJar();
+        doReturn(resource).when(embed).getResource(eq("META-INF/MANIFEST.MF"));
+        analyzer.setClasspath(new Jar[] {embed});
+
+        plugin.setReporter(reporter);
+        plugin.setProperties(props);
+
+        plugin.analyzeJar(analyzer);
+
+        assertContains("instance { $component=\"org.apache.felix.ipojo.IPOJOURLHandler\" }",
+                analyzer.getProperty("IPOJO-Components"));
+    }
+
+    public void testAnalysisWithExcludedEmbedComponents() throws Exception {
+        PojoizationPlugin plugin = new PojoizationPlugin();
+
+        Map<String, String> props = new HashMap<String, String>();
+
+        Resource resource = new URLResource(getClass().getResource("/EMBED-MANIFEST.MF"));
+        doReturn(dot).when(analyzer).getJar();
+        doReturn(resource).when(embed).getResource(eq("META-INF/MANIFEST.MF"));
+        analyzer.setClasspath(new Jar[] {embed});
+
+        plugin.setReporter(reporter);
+        plugin.setProperties(props);
+
+        plugin.analyzeJar(analyzer);
+
+        assertNull(analyzer.getProperty("IPOJO-Components"));
+    }
+
+
+    public void testAnalysisWithBothLocalAndEmbedComponents() throws Exception {
+        PojoizationPlugin plugin = new PojoizationPlugin();
+
+        Map<String, String> props = new HashMap<String, String>();
+        props.put("include-embed-bundles", "true");
+
+        Resource resource = new URLResource(getClass().getResource("/EMBED-MANIFEST.MF"));
+        Resource resource2 = new URLResource(getClass().getResource("/metadata-components-only.xml"));
+        doReturn(dot).when(analyzer).getJar();
+        doReturn(resource).when(embed).getResource(eq("META-INF/MANIFEST.MF"));
+        doReturn(resource2).when(dot).getResource(eq("META-INF/metadata.xml"));
+        analyzer.setClasspath(new Jar[]{embed});
+
+        plugin.setReporter(reporter);
+        plugin.setProperties(props);
+
+        plugin.analyzeJar(analyzer);
+
+        assertContains("instance { $component=\"org.apache.felix.ipojo.IPOJOURLHandler\" }",
+                analyzer.getProperty("IPOJO-Components"));
+        assertContains("component { $class=\"com.acme.Thermometer\" }",
+                analyzer.getProperty("IPOJO-Components"));
+    }
+
+
+    public void testAnalysisWithLocallyDefinedComponentAndEmbedResource() throws Exception {
+        PojoizationPlugin plugin = new PojoizationPlugin();
+
+        Map<String, String> props = new HashMap<String, String>();
+        props.put("include-embed-bundles", "true");
+        String path = EmptyComponent.class.getName().replace('.', '/').concat(".class");
+
+        Resource resource2 = new URLResource(getClass().getResource("/metadata-test-component.xml"));
+        doReturn(dot).when(analyzer).getJar();
+        doReturn(resource2).when(dot).getResource(eq("META-INF/metadata.xml"));
+
+        Collection<Clazz> classes = new ArrayList<Clazz>();
+        Resource typeResource = new URLResource(getClass().getResource("EmptyComponent.class"));
+        Clazz clazz = new Clazz(path, typeResource);
+        clazz.parseClassFile();
+        classes.add(clazz);
+        doReturn(classes).when(analyzer).getClasses(Matchers.<String[]>anyVararg());
+
+        Resource resource = new URLResource(getClass().getResource("/EMBED-MANIFEST-EMPTY.MF"));
+        doReturn(resource).when(embed).getResource(eq("META-INF/MANIFEST.MF"));
+        doReturn(typeResource).when(embed).getResource(path);
+        doReturn("aaa").when(embed).getBsn();
+
+        analyzer.setClasspath(new Jar[] {embed});
+
+        plugin.setReporter(reporter);
+        plugin.setProperties(props);
+
+        plugin.analyzeJar(analyzer);
+
+        assertContains("component { $classname=\"org.apache.felix.ipojo.bnd.EmptyComponent\" manipulation { method { $name=\"$init\" }}}",
+                analyzer.getProperty("IPOJO-Components"));
+        verify(dot).putResource(eq(path), any(Resource.class));
+    }
+
+    private void assertContains(String expected, String actual) {
+        assertTrue(actual.contains(expected));
+    }
+
+}

Added: felix/trunk/ipojo/manipulator/bnd-ipojo-plugin/src/test/java/org/apache/felix/ipojo/bnd/EmptyComponent.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/manipulator/bnd-ipojo-plugin/src/test/java/org/apache/felix/ipojo/bnd/EmptyComponent.java?rev=1429888&view=auto
==============================================================================
--- felix/trunk/ipojo/manipulator/bnd-ipojo-plugin/src/test/java/org/apache/felix/ipojo/bnd/EmptyComponent.java (added)
+++ felix/trunk/ipojo/manipulator/bnd-ipojo-plugin/src/test/java/org/apache/felix/ipojo/bnd/EmptyComponent.java Mon Jan  7 16:41:00 2013
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.bnd;
+
+/**
+* Created with IntelliJ IDEA.
+* User: guillaume
+* Date: 07/01/13
+* Time: 11:31
+* To change this template use File | Settings | File Templates.
+*/
+public class EmptyComponent {
+
+}

Added: felix/trunk/ipojo/manipulator/bnd-ipojo-plugin/src/test/resources/EMBED-MANIFEST-EMPTY.MF
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/manipulator/bnd-ipojo-plugin/src/test/resources/EMBED-MANIFEST-EMPTY.MF?rev=1429888&view=auto
==============================================================================
--- felix/trunk/ipojo/manipulator/bnd-ipojo-plugin/src/test/resources/EMBED-MANIFEST-EMPTY.MF (added)
+++ felix/trunk/ipojo/manipulator/bnd-ipojo-plugin/src/test/resources/EMBED-MANIFEST-EMPTY.MF Mon Jan  7 16:41:00 2013
@@ -0,0 +1,6 @@
+Manifest-Version: 1.0
+Bundle-Name: Embed
+Bundle-Vendor: The Apache Software Foundation
+Bundle-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: org.apache.felix.ipojo.test

Added: felix/trunk/ipojo/manipulator/bnd-ipojo-plugin/src/test/resources/EMBED-MANIFEST.MF
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/manipulator/bnd-ipojo-plugin/src/test/resources/EMBED-MANIFEST.MF?rev=1429888&view=auto
==============================================================================
--- felix/trunk/ipojo/manipulator/bnd-ipojo-plugin/src/test/resources/EMBED-MANIFEST.MF (added)
+++ felix/trunk/ipojo/manipulator/bnd-ipojo-plugin/src/test/resources/EMBED-MANIFEST.MF Mon Jan  7 16:41:00 2013
@@ -0,0 +1,21 @@
+Manifest-Version: 1.0
+Bundle-Name: Embed
+Bundle-Vendor: The Apache Software Foundation
+Bundle-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: org.apache.felix.ipojo.test
+IPOJO-Components: instance { $component="org.apache.felix.ipojo.IPOJOU
+ RLHandler" }component { $immediate="true" $classname="org.apache.feli
+ x.ipojo.IPOJOURLHandler" $public="false" callback { $transition="inva
+ lidate" $method="stop" }provides { property { $mandatory="false" $nam
+ e="url.handler.protocol" $value="ipojo" $type="java.lang.String" }}ma
+ nipulation { $super="org.osgi.service.url.AbstractURLStreamHandlerSer
+ vice" field { $name="m_context" $type="org.osgi.framework.BundleConte
+ xt" }field { $name="m_temp" $type="java.io.File" }method { $arguments
+ ="{org.osgi.framework.BundleContext}" $name="$init" }method { $name="
+ stop" }method { $arguments="{java.net.URL}" $name="openConnection" $r
+ eturn="java.net.URLConnection" }method { $arguments="{java.net.URL,ja
+ va.io.File}" $name="save" }method { $arguments="{java.io.InputStream,
+ java.io.File}" $name="save" }method { $arguments="{java.util.jar.JarF
+ ile}" $name="findMetadata" $return="java.io.File" }interface { $name=
+ "org.osgi.service.url.URLStreamHandlerService" }}}

Added: felix/trunk/ipojo/manipulator/bnd-ipojo-plugin/src/test/resources/metadata-test-component.xml
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/manipulator/bnd-ipojo-plugin/src/test/resources/metadata-test-component.xml?rev=1429888&view=auto
==============================================================================
--- felix/trunk/ipojo/manipulator/bnd-ipojo-plugin/src/test/resources/metadata-test-component.xml (added)
+++ felix/trunk/ipojo/manipulator/bnd-ipojo-plugin/src/test/resources/metadata-test-component.xml Mon Jan  7 16:41:00 2013
@@ -0,0 +1,22 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you under the Apache License, Version 2.0 (the
+  ~ "License"); you may not use this file except in compliance
+  ~ with the License.  You may obtain a copy of the License at
+  ~
+  ~   http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied.  See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
+  -->
+
+<ipojo>
+  <component classname="org.apache.felix.ipojo.bnd.EmptyComponent"/>
+</ipojo>