You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by cl...@apache.org on 2013/04/24 17:06:09 UTC

svn commit: r1471456 [2/2] - in /felix/trunk/ipojo/runtime: core-it/src/it/ipojo-core-configuration-processor-test/ core-it/src/it/ipojo-core-configuration-processor-test/src/ core-it/src/it/ipojo-core-configuration-processor-test/src/main/ core-it/src...

Added: felix/trunk/ipojo/runtime/core-it/src/it/ipojo-core-configuration-processor-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestConfigurationOfTwoInstances.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core-it/src/it/ipojo-core-configuration-processor-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestConfigurationOfTwoInstances.java?rev=1471456&view=auto
==============================================================================
--- felix/trunk/ipojo/runtime/core-it/src/it/ipojo-core-configuration-processor-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestConfigurationOfTwoInstances.java (added)
+++ felix/trunk/ipojo/runtime/core-it/src/it/ipojo-core-configuration-processor-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestConfigurationOfTwoInstances.java Wed Apr 24 15:06:07 2013
@@ -0,0 +1,95 @@
+/*
+ * 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.runtime.core;
+
+import junit.framework.Assert;
+import org.apache.felix.ipojo.architecture.Architecture;
+import org.apache.felix.ipojo.runtime.core.components.ConfigureTwoInstances;
+import org.apache.felix.ipojo.runtime.core.components.MyComponent;
+import org.apache.felix.ipojo.runtime.core.services.FooService;
+import org.junit.Test;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.OptionUtils;
+import org.ops4j.pax.tinybundles.core.TinyBundles;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+import org.ow2.chameleon.testing.tinybundles.ipojo.IPOJOStrategy;
+
+import java.io.IOException;
+import java.util.List;
+
+import static org.ops4j.pax.exam.CoreOptions.streamBundle;
+import static org.ops4j.pax.tinybundles.core.TinyBundles.withBnd;
+
+/**
+ * Check a @Configuration with 2 instances.
+ */
+public class TestConfigurationOfTwoInstances extends Common {
+
+    @Configuration
+    public Option[] config() throws IOException {
+        deployTestedBundle = false;
+        Option[] options = super.config();
+
+        // Build a service bundle
+        return OptionUtils.combine(options,
+                streamBundle(
+                        TinyBundles.bundle()
+                                .add(FooService.class)
+                                .set(Constants.BUNDLE_SYMBOLICNAME, "ServiceInterface")
+                                .set(Constants.EXPORT_PACKAGE, "org.apache.felix.ipojo.runtime.core.services")
+                                .build(withBnd())
+                ),
+                streamBundle(
+                        TinyBundles.bundle()
+                                .add(ConfigureTwoInstances.class)
+                                .add(MyComponent.class)
+                                .set(Constants.BUNDLE_SYMBOLICNAME, "MyComponent")
+                                .build(IPOJOStrategy.withiPOJO())
+                )
+        );
+    }
+
+    @Test
+    public void testConfiguration() {
+        if (isKF()) {
+            return; // Test disabled on KF
+        }
+
+        osgiHelper.waitForService(FooService.class, null, 10000);
+
+        // Check we have two instances
+        ServiceReference[] refs = osgiHelper.getServiceReferences(FooService.class, null);
+        Assert.assertEquals(refs.length, 2);
+
+        List<Architecture> arch = osgiHelper.getServiceObjects(Architecture.class, null);
+        for (Architecture a : arch) {
+            System.out.println("Instance " + a.getInstanceDescription().getName());
+        }
+
+        // Check name
+        Assert.assertNotNull(ipojoHelper.getServiceReferenceByName(FooService.class.getName(), "hello"));
+        Assert.assertNotNull(ipojoHelper.getServiceReferenceByName(FooService.class.getName(), "myInstance1"));
+
+    }
+
+
+}

Added: felix/trunk/ipojo/runtime/core-it/src/it/ipojo-core-configuration-processor-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestConfigurationWithInheritedInstance.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core-it/src/it/ipojo-core-configuration-processor-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestConfigurationWithInheritedInstance.java?rev=1471456&view=auto
==============================================================================
--- felix/trunk/ipojo/runtime/core-it/src/it/ipojo-core-configuration-processor-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestConfigurationWithInheritedInstance.java (added)
+++ felix/trunk/ipojo/runtime/core-it/src/it/ipojo-core-configuration-processor-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestConfigurationWithInheritedInstance.java Wed Apr 24 15:06:07 2013
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.runtime.core;
+
+import junit.framework.Assert;
+import org.apache.felix.ipojo.architecture.Architecture;
+import org.apache.felix.ipojo.runtime.core.components.ConfigureTwoInstancesWithInheritance;
+import org.apache.felix.ipojo.runtime.core.components.MyComponent;
+import org.apache.felix.ipojo.runtime.core.components.ParentConfiguration;
+import org.apache.felix.ipojo.runtime.core.services.FooService;
+import org.junit.Test;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.OptionUtils;
+import org.ops4j.pax.tinybundles.core.TinyBundles;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+import org.ow2.chameleon.testing.tinybundles.ipojo.IPOJOStrategy;
+
+import java.io.IOException;
+import java.util.List;
+
+import static org.ops4j.pax.exam.CoreOptions.streamBundle;
+import static org.ops4j.pax.tinybundles.core.TinyBundles.withBnd;
+
+/**
+ * Check a @Configuration inheriting an instance from a parent class.
+ */
+public class TestConfigurationWithInheritedInstance extends Common {
+
+    @Configuration
+    public Option[] config() throws IOException {
+        deployTestedBundle = false;
+        Option[] options = super.config();
+
+        // Build a service bundle
+        return OptionUtils.combine(options,
+                streamBundle(
+                        TinyBundles.bundle()
+                                .add(FooService.class)
+                                .set(Constants.BUNDLE_SYMBOLICNAME, "ServiceInterface")
+                                .set(Constants.EXPORT_PACKAGE, "org.apache.felix.ipojo.runtime.core.services")
+                                .build(withBnd())
+                ),
+                streamBundle(
+                        TinyBundles.bundle()
+                                .add(ConfigureTwoInstancesWithInheritance.class)
+                                .add(ParentConfiguration.class)
+                                .add(MyComponent.class)
+                                .set(Constants.BUNDLE_SYMBOLICNAME, "MyComponent")
+                                .build(IPOJOStrategy.withiPOJO())
+                )
+        );
+    }
+
+    @Test
+    public void testConfiguration() {
+        if (isKF()) {
+            return; // Test disabled on KF
+        }
+
+        osgiHelper.waitForService(FooService.class, null, 10000);
+
+        // Check we have two instances
+        ServiceReference[] refs = osgiHelper.getServiceReferences(FooService.class, null);
+        Assert.assertEquals(refs.length, 2);
+
+        List<Architecture> arch = osgiHelper.getServiceObjects(Architecture.class, null);
+        for (Architecture a : arch) {
+            System.out.println("Instance " + a.getInstanceDescription().getName());
+        }
+
+        // Check name
+        Assert.assertNotNull(ipojoHelper.getServiceReferenceByName(FooService.class.getName(), "hello"));
+        Assert.assertNotNull(ipojoHelper.getServiceReferenceByName(FooService.class.getName(), "myInstance1"));
+
+    }
+
+
+}

Added: felix/trunk/ipojo/runtime/core-it/src/it/ipojo-core-configuration-processor-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestConfigurationWithOverriddenInstance.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core-it/src/it/ipojo-core-configuration-processor-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestConfigurationWithOverriddenInstance.java?rev=1471456&view=auto
==============================================================================
--- felix/trunk/ipojo/runtime/core-it/src/it/ipojo-core-configuration-processor-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestConfigurationWithOverriddenInstance.java (added)
+++ felix/trunk/ipojo/runtime/core-it/src/it/ipojo-core-configuration-processor-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestConfigurationWithOverriddenInstance.java Wed Apr 24 15:06:07 2013
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.runtime.core;
+
+import junit.framework.Assert;
+import org.apache.felix.ipojo.architecture.Architecture;
+import org.apache.felix.ipojo.runtime.core.components.ConfigureTwoInstancesWithOverridding;
+import org.apache.felix.ipojo.runtime.core.components.MyComponent;
+import org.apache.felix.ipojo.runtime.core.components.ParentConfiguration;
+import org.apache.felix.ipojo.runtime.core.services.FooService;
+import org.junit.Test;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.OptionUtils;
+import org.ops4j.pax.tinybundles.core.TinyBundles;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+import org.ow2.chameleon.testing.tinybundles.ipojo.IPOJOStrategy;
+
+import java.io.IOException;
+import java.util.List;
+
+import static org.ops4j.pax.exam.CoreOptions.streamBundle;
+import static org.ops4j.pax.tinybundles.core.TinyBundles.withBnd;
+
+/**
+ * Check a @Configuration overriding instance declaration.
+ */
+public class TestConfigurationWithOverriddenInstance extends Common {
+
+    @Configuration
+    public Option[] config() throws IOException {
+        deployTestedBundle = false;
+        Option[] options = super.config();
+
+        // Build a service bundle
+        return OptionUtils.combine(options,
+                streamBundle(
+                        TinyBundles.bundle()
+                                .add(FooService.class)
+                                .set(Constants.BUNDLE_SYMBOLICNAME, "ServiceInterface")
+                                .set(Constants.EXPORT_PACKAGE, "org.apache.felix.ipojo.runtime.core.services")
+                                .build(withBnd())
+                ),
+                streamBundle(
+                        TinyBundles.bundle()
+                                .add(ConfigureTwoInstancesWithOverridding.class)
+                                .add(ParentConfiguration.class)
+                                .add(MyComponent.class)
+                                .set(Constants.BUNDLE_SYMBOLICNAME, "MyComponent")
+                                .build(IPOJOStrategy.withiPOJO())
+                )
+        );
+    }
+
+    @Test
+    public void testConfiguration() {
+        if (isKF()) {
+            return; // Test disabled on KF
+        }
+
+        osgiHelper.waitForService(FooService.class, null, 10000);
+
+        // Check we have two instances
+        ServiceReference[] refs = osgiHelper.getServiceReferences(FooService.class, null);
+        Assert.assertEquals(refs.length, 2);
+
+        List<Architecture> arch = osgiHelper.getServiceObjects(Architecture.class, null);
+        for (Architecture a : arch) {
+            System.out.println("Instance " + a.getInstanceDescription().getName());
+        }
+
+        // Check name
+        Assert.assertNotNull(ipojoHelper.getServiceReferenceByName(FooService.class.getName(), "hello-over"));
+        Assert.assertNotNull(ipojoHelper.getServiceReferenceByName(FooService.class.getName(), "myInstance1"));
+
+    }
+
+
+}

Added: felix/trunk/ipojo/runtime/core-it/src/it/ipojo-core-configuration-processor-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestEmptyConfiguration.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core-it/src/it/ipojo-core-configuration-processor-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestEmptyConfiguration.java?rev=1471456&view=auto
==============================================================================
--- felix/trunk/ipojo/runtime/core-it/src/it/ipojo-core-configuration-processor-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestEmptyConfiguration.java (added)
+++ felix/trunk/ipojo/runtime/core-it/src/it/ipojo-core-configuration-processor-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestEmptyConfiguration.java Wed Apr 24 15:06:07 2013
@@ -0,0 +1,76 @@
+/*
+ * 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.runtime.core;
+
+import junit.framework.Assert;
+import org.apache.felix.ipojo.runtime.core.components.ConfigureNothing;
+import org.apache.felix.ipojo.runtime.core.components.MyComponent;
+import org.apache.felix.ipojo.runtime.core.services.FooService;
+import org.junit.Test;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.OptionUtils;
+import org.ops4j.pax.tinybundles.core.TinyBundles;
+import org.osgi.framework.Constants;
+import org.ow2.chameleon.testing.tinybundles.ipojo.IPOJOStrategy;
+
+import java.io.IOException;
+
+import static org.ops4j.pax.exam.CoreOptions.streamBundle;
+import static org.ops4j.pax.tinybundles.core.TinyBundles.withBnd;
+
+/**
+ * Check an empty @Configuration
+ */
+public class TestEmptyConfiguration extends Common {
+
+    @Configuration
+    public Option[] config() throws IOException {
+        deployTestedBundle = false;
+        Option[] options = super.config();
+
+        // Build a service bundle
+        return OptionUtils.combine(options,
+                streamBundle(
+                        TinyBundles.bundle()
+                                .add(FooService.class)
+                                .set(Constants.BUNDLE_SYMBOLICNAME, "ServiceInterface")
+                                .set(Constants.EXPORT_PACKAGE, "org.apache.felix.ipojo.runtime.core.services")
+                                .build(withBnd())
+                ),
+                streamBundle(
+                        TinyBundles.bundle()
+                                .add(MyComponent.class)
+                                .add(ConfigureNothing.class)
+                                .set(Constants.BUNDLE_SYMBOLICNAME, "MyComponent")
+                                .build(IPOJOStrategy.withiPOJO())
+                )
+        );
+    }
+
+    @Test
+    public void testConfiguration() throws InterruptedException {
+        Thread.sleep(200);
+        // Check configuration
+        Assert.assertNull(osgiHelper.getServiceReference(FooService.class));
+    }
+
+
+}

Added: felix/trunk/ipojo/runtime/core-it/src/it/ipojo-core-configuration-processor-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestSeveralConfigurations.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core-it/src/it/ipojo-core-configuration-processor-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestSeveralConfigurations.java?rev=1471456&view=auto
==============================================================================
--- felix/trunk/ipojo/runtime/core-it/src/it/ipojo-core-configuration-processor-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestSeveralConfigurations.java (added)
+++ felix/trunk/ipojo/runtime/core-it/src/it/ipojo-core-configuration-processor-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestSeveralConfigurations.java Wed Apr 24 15:06:07 2013
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.runtime.core;
+
+import junit.framework.Assert;
+import org.apache.felix.ipojo.architecture.Architecture;
+import org.apache.felix.ipojo.runtime.core.components.ConfigureAnotherInstance;
+import org.apache.felix.ipojo.runtime.core.components.ConfigureOneInstance;
+import org.apache.felix.ipojo.runtime.core.components.MyComponent;
+import org.apache.felix.ipojo.runtime.core.services.FooService;
+import org.junit.Test;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.OptionUtils;
+import org.ops4j.pax.tinybundles.core.TinyBundles;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+import org.ow2.chameleon.testing.tinybundles.ipojo.IPOJOStrategy;
+
+import java.io.IOException;
+import java.util.List;
+
+import static org.ops4j.pax.exam.CoreOptions.streamBundle;
+import static org.ops4j.pax.tinybundles.core.TinyBundles.withBnd;
+
+/**
+ * Check several configuration @Configuration in the same bundle.
+ */
+public class TestSeveralConfigurations extends Common {
+
+    @Configuration
+    public Option[] config() throws IOException {
+        deployTestedBundle = false;
+        Option[] options = super.config();
+
+        // Build a service bundle
+        return OptionUtils.combine(options,
+                streamBundle(
+                        TinyBundles.bundle()
+                                .add(FooService.class)
+                                .set(Constants.BUNDLE_SYMBOLICNAME, "ServiceInterface")
+                                .set(Constants.EXPORT_PACKAGE, "org.apache.felix.ipojo.runtime.core.services")
+                                .build(withBnd())
+                ),
+                streamBundle(
+                        TinyBundles.bundle()
+                                .add(ConfigureOneInstance.class)
+                                .add(ConfigureAnotherInstance.class)
+                                .add(MyComponent.class)
+                                .set(Constants.BUNDLE_SYMBOLICNAME, "MyComponent")
+                                .build(IPOJOStrategy.withiPOJO())
+                )
+        );
+    }
+
+    @Test
+    public void testConfiguration() {
+        if (isKF()) {
+            return; // Test disabled on KF
+        }
+
+        osgiHelper.waitForService(FooService.class, null, 10000);
+
+        // Check we have two instances
+        ServiceReference[] refs = osgiHelper.getServiceReferences(FooService.class, null);
+        Assert.assertEquals(refs.length, 2);
+
+        List<Architecture> arch = osgiHelper.getServiceObjects(Architecture.class, null);
+        for (Architecture a : arch) {
+            System.out.println("Instance " + a.getInstanceDescription().getName());
+        }
+
+        // Check name
+        Assert.assertNotNull(ipojoHelper.getServiceReferenceByName(FooService.class.getName(), "anotherInstance"));
+        Assert.assertNotNull(ipojoHelper.getServiceReferenceByName(FooService.class.getName(), "myInstance"));
+
+    }
+
+
+}

Modified: felix/trunk/ipojo/runtime/core/pom.xml
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/pom.xml?rev=1471456&r1=1471455&r2=1471456&view=diff
==============================================================================
--- felix/trunk/ipojo/runtime/core/pom.xml (original)
+++ felix/trunk/ipojo/runtime/core/pom.xml Wed Apr 24 15:06:07 2013
@@ -116,11 +116,14 @@
                         </IPOJO-Extension>
                         <Import-Package>
                             org.osgi.framework;version=1.3, <!-- To support KF 2 -->
+                            org.osgi.framework.wiring;resolution:=optional,
                             org.osgi.service.cm,
                             org.osgi.service.log,
                             org.osgi.util.tracker;version=1.3,
                             !sun.io,
-                            !net.sourceforge.cobertura.* <!--  To support code coverage -->
+                            !net.sourceforge.cobertura.*, <!--  To support code coverage -->
+                            !org.objectweb.asm.signature,
+                            !org.objectweb.asm.tree
                         </Import-Package>
                         <Private-Package>
                             org.apache.felix.ipojo.handlers.architecture,
@@ -128,6 +131,7 @@
                             org.apache.felix.ipojo.handlers.lifecycle.controller,
                             org.apache.felix.ipojo.extender.internal*,
                             org.objectweb.asm;-split-package:=merge-last,
+                            org.objectweb.asm.commons;-split-package:=merge-last,
                             org.apache.felix.ipojo.metadata,
                             <!-- Compendium packages -->
                             org.osgi.service.cm,
@@ -135,6 +139,7 @@
                         </Private-Package>
                         <Export-Package>
                             org.apache.felix.ipojo; version="${ipojo.package.version}",
+                            org.apache.felix.ipojo.configuration; version="${ipojo.package.version}",
                             org.apache.felix.ipojo.metadata; version="${ipojo.package.version}",
                             org.apache.felix.ipojo.architecture; version="${ipojo.package.version}",
                             org.apache.felix.ipojo.extender;

Added: felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/configuration/Configuration.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/configuration/Configuration.java?rev=1471456&view=auto
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/configuration/Configuration.java (added)
+++ felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/configuration/Configuration.java Wed Apr 24 15:06:07 2013
@@ -0,0 +1,32 @@
+/*
+ * 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.configuration;
+
+/**
+ * A marker interface to detect configurations
+ */
+public @interface Configuration {
+
+    /**
+     * An optional name
+     * @return the optional configuration name
+     */
+    String value() default "";
+}

Added: felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/configuration/Instance.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/configuration/Instance.java?rev=1471456&view=auto
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/configuration/Instance.java (added)
+++ felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/configuration/Instance.java Wed Apr 24 15:06:07 2013
@@ -0,0 +1,173 @@
+/*
+ * 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.configuration;
+
+import org.apache.felix.ipojo.ComponentInstance;
+import org.apache.felix.ipojo.Factory;
+
+import java.util.*;
+
+/**
+ * Instance Builder
+ */
+public class Instance {
+
+    private String factory;
+    private String name;
+    private List<Property> configuration;
+
+    public static Instance instance() {
+        return new Instance();
+    }
+
+    public static <T> FluentList<T> list(T... items) {
+        return new FluentList<T>(items);
+    }
+
+    public static <K, T> FluentMap<K, T> map(Pair<K, T>... pairs) {
+        return new FluentMap<K, T>(pairs);
+    }
+
+    public static <K, T> Pair<K, T> pair(K k, T v) {
+        return new Pair<K, T>(k, v);
+    }
+
+    public String factory() {
+        return factory;
+    }
+
+    public String name() {
+        return name;
+    }
+
+    public Dictionary<String, Object> configuration() {
+        Hashtable<String, Object> configuration = new Hashtable<String, Object>();
+        for (Property property : this.configuration) {
+            configuration.put(property.name, property.value);
+        }
+
+        if (name != null) {
+            configuration.put(Factory.INSTANCE_NAME_PROPERTY, name);
+        }
+
+        return configuration;
+    }
+
+    public Instance of(String factory) {
+        this.factory = factory;
+        return this;
+    }
+
+    public Instance of(Class clazz) {
+        this.factory = clazz.getName();
+        return this;
+    }
+
+    public Instance named(String name) {
+        this.name = name;
+        return this;
+    }
+
+    public Instance.Property<Object> with(String property) {
+        if (this.configuration == null) {
+            this.configuration = new ArrayList<Property>();
+        }
+        Property<Object> prop = new Property<Object>(property);
+        this.configuration.add(prop);
+        return prop;
+    }
+
+    public Instance nameIfUnnamed(String name) {
+        if (this.name == null) {
+            this.name = name;
+        }
+        return this;
+    }
+
+    public static class FluentList<T> extends ArrayList<T> {
+
+        public FluentList() {
+            super(new ArrayList<T>());
+        }
+
+        public FluentList(T... items) {
+            this();
+            addAll(Arrays.asList(items));
+        }
+
+        public FluentList<T> with(T o) {
+            add(o);
+            return this;
+        }
+    }
+
+    public static class FluentMap<K,T> extends LinkedHashMap<K, T> {
+
+        public FluentMap() {
+            super(new LinkedHashMap<K, T>());
+        }
+
+        public FluentMap(Pair<? extends K, ? extends T>... pairs) {
+            this();
+            with(pairs);
+        }
+
+        public FluentMap<K, T> with(Pair<? extends K, ? extends T>... pairs) {
+            for (Pair<? extends K, ? extends T> pair : pairs) {
+                this.put(pair.key, pair.value);
+            }
+            return this;
+        }
+
+        public FluentMap<K, T> putAt(K k, T value) {
+            this.put(k, value);
+            return this;
+        }
+    }
+
+    public static class Pair<K, V> {
+        private final K key;
+        private final V value;
+
+        Pair(K key, V value) {
+            this.key = key;
+            this.value = value;
+        }
+    }
+
+    public class Property<T> {
+
+        private final String name;
+        private T value;
+
+        Property(String name) {
+            this.name = name;
+        }
+
+        public Instance setto(T value) {
+            this.value = value;
+            return Instance.this;
+        }
+
+        public T get() {
+            return value;
+        }
+    }
+}

Modified: felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/Extender.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/Extender.java?rev=1471456&r1=1471455&r2=1471456&view=diff
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/Extender.java (original)
+++ felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/Extender.java Wed Apr 24 15:06:07 2013
@@ -21,10 +21,7 @@ package org.apache.felix.ipojo.extender.
 
 import org.apache.felix.ipojo.EventDispatcher;
 import org.apache.felix.ipojo.extender.internal.linker.DeclarationLinker;
-import org.apache.felix.ipojo.extender.internal.processor.ChainedBundleProcessor;
-import org.apache.felix.ipojo.extender.internal.processor.ComponentsBundleProcessor;
-import org.apache.felix.ipojo.extender.internal.processor.ExtensionBundleProcessor;
-import org.apache.felix.ipojo.extender.internal.processor.QueuingActivationProcessor;
+import org.apache.felix.ipojo.extender.internal.processor.*;
 import org.apache.felix.ipojo.extender.internal.queue.ExecutorQueueService;
 import org.apache.felix.ipojo.extender.internal.queue.PrefixedThreadFactory;
 import org.apache.felix.ipojo.extender.internal.queue.SynchronousQueueService;
@@ -120,6 +117,7 @@ public class Extender implements BundleA
 
         BundleProcessor extensionBundleProcessor = new ExtensionBundleProcessor(m_logger);
         BundleProcessor componentsProcessor = new ComponentsBundleProcessor(m_logger);
+        BundleProcessor configurationProcessor = new ConfigurationProcessor(m_logger);
         if (SYNCHRONOUS_PROCESSING_ENABLED) {
             m_queueService = new EnforcedQueueService(
                     new HeaderPreferenceSelection(),
@@ -133,6 +131,7 @@ public class Extender implements BundleA
 
             extensionBundleProcessor = new QueuingActivationProcessor(extensionBundleProcessor, m_queueService);
             componentsProcessor = new QueuingActivationProcessor(componentsProcessor, m_queueService);
+            configurationProcessor = new QueuingActivationProcessor(configurationProcessor, m_queueService);
         }
         m_queueService.start();
 
@@ -140,7 +139,7 @@ public class Extender implements BundleA
         m_linker = new DeclarationLinker(context, m_queueService);
         m_linker.start();
 
-        m_processor = ChainedBundleProcessor.create(extensionBundleProcessor, componentsProcessor);
+        m_processor = ChainedBundleProcessor.create(extensionBundleProcessor, componentsProcessor, configurationProcessor);
 
         m_processor.start();
 

Added: felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/ConfigurationAnnotationScanner.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/ConfigurationAnnotationScanner.java?rev=1471456&view=auto
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/ConfigurationAnnotationScanner.java (added)
+++ felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/ConfigurationAnnotationScanner.java Wed Apr 24 15:06:07 2013
@@ -0,0 +1,67 @@
+/*
+ * 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.extender.internal.processor;
+
+import org.apache.felix.ipojo.configuration.Configuration;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.commons.EmptyVisitor;
+
+/**
+ * Class visitor detecting @Configuration annotation.
+ * <p/>
+ * After the visit, two state variables are set:
+ * {@literal isConfiguration} is set to true if the class contained the @Configuration annotation
+ * {@literal parent} is set to the parent class if and only if it's not a java.* class (which don't contain the
+ * Configuration annotation) and {@literal isConfiguration} is set to false
+ */
+public class ConfigurationAnnotationScanner extends EmptyVisitor implements Opcodes {
+
+    private static final String CONFIGURATION_ANNOTATION_DESCRIPTOR = Type.getType(Configuration.class)
+            .getDescriptor();
+    private boolean m_isConfiguration = false;
+    private String m_super;
+
+
+    @Override
+    public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
+        m_super = superName;  // This is the internal class name.
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(String desc, boolean vis) {
+        if (desc.equals(CONFIGURATION_ANNOTATION_DESCRIPTOR)) {
+            m_isConfiguration = true;
+        }
+        return null;
+    }
+
+    public boolean isConfiguration() {
+        return m_isConfiguration;
+    }
+
+    public String getParent() {
+        if (m_super == null  || m_super.startsWith("java/") || m_isConfiguration) {
+            return null;
+        }
+        return m_super.replace("/", ".");
+    }
+}

Copied: felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/ConfigurationProcessor.java (from r1465972, felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/ComponentsBundleProcessor.java)
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/ConfigurationProcessor.java?p2=felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/ConfigurationProcessor.java&p1=felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/ComponentsBundleProcessor.java&r1=1465972&r2=1471456&rev=1471456&view=diff
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/ComponentsBundleProcessor.java (original)
+++ felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/ConfigurationProcessor.java Wed Apr 24 15:06:07 2013
@@ -7,7 +7,7 @@
  * "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
+ * 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
@@ -19,60 +19,72 @@
 
 package org.apache.felix.ipojo.extender.internal.processor;
 
+import org.apache.felix.ipojo.configuration.Instance;
 import org.apache.felix.ipojo.extender.internal.BundleProcessor;
 import org.apache.felix.ipojo.extender.internal.declaration.DefaultInstanceDeclaration;
 import org.apache.felix.ipojo.extender.internal.declaration.DefaultTypeDeclaration;
-import org.apache.felix.ipojo.metadata.Element;
-import org.apache.felix.ipojo.parser.ManifestMetadataParser;
-import org.apache.felix.ipojo.parser.ParseException;
+import org.apache.felix.ipojo.util.InvocationResult;
 import org.apache.felix.ipojo.util.Log;
-import org.apache.felix.ipojo.util.Logger;
+import org.objectweb.asm.ClassReader;
 import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.wiring.BundleWiring;
 
 import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.net.URL;
 import java.util.*;
 
+import static org.apache.felix.ipojo.util.Reflection.fields;
+import static org.apache.felix.ipojo.util.Reflection.methods;
+
 /**
- * Processor handling the {@link #IPOJO_HEADER} and {@link #IPOJO_HEADER_ALT}
- * header from the bundle manifest.
+ * Processor looking for classes annotated with @Configuration and creating the corresponding instance declaration.
  */
-public class ComponentsBundleProcessor implements BundleProcessor {
-
-    /**
-     * iPOJO Component Type and Instance declaration header.
-     */
-    public static final String IPOJO_HEADER = "iPOJO-Components";
-
-    /**
-     * iPOJO Component Type and Instance declaration header
-     * (alternative).
-     * This header was introduced because of BND supporting only header
-     * starting with an uppercase.
-     */
-    public static final String IPOJO_HEADER_ALT = "IPOJO-Components";
-
-    /**
-     * The attribute used in instance configuration specifying the targeted component (i.e. factory).
-     */
-    public static final String COMPONENT_INSTANCE_ATTRIBUTE = "component";
+public class ConfigurationProcessor implements BundleProcessor {
 
     /**
      * The logger.
      */
     private final Log m_logger;
-
     /**
      * Registry storing the bundle to components and instances declared within this bundle.
+     * Only instances are expected.
      */
     private final Map<Bundle, ComponentsAndInstances> m_registry = new HashMap<Bundle, ComponentsAndInstances>();
+    private final boolean m_enabled;
 
     /**
-     * Creates the component bundle processor.
+     * Creates the configuration processor.
      *
      * @param logger the logger.
      */
-    public ComponentsBundleProcessor(Log logger) {
+    public ConfigurationProcessor(Log logger) {
+
         m_logger = logger;
+
+        // org.osgi.framework.wiring may not be available, in this case, disable us.
+        try {
+            this.getClass().getClassLoader().loadClass("org.osgi.framework.wiring.BundleWiring");
+        } catch (ClassNotFoundException e) {
+            m_logger.log(Log.ERROR, "The org.osgi.framework.wiring.BundleWiring class is not provided by the " +
+                    "framework, configuration processor disabled.");
+            m_enabled = false;
+            return;
+        }
+        // Check ok.
+        m_enabled = true;
+    }
+
+    public static String getClassNameFromResource(String resource) {
+        String res = resource;
+        if (resource.startsWith("/")) {
+            res = resource.substring(1); // Remove the first /
+        }
+        res = res.substring(0, res.length() - ".class".length()); // Remove the .class
+        return res.replace("/", ".");
     }
 
     /**
@@ -81,24 +93,28 @@ public class ComponentsBundleProcessor i
      * @param bundle the bundle
      */
     public void activate(Bundle bundle) {
-        Dictionary dict = bundle.getHeaders();
-        // Check bundle
-        String header = (String) dict.get(IPOJO_HEADER);
-        // Check the alternative header
-        if (header == null) {
-            header = (String) dict.get(IPOJO_HEADER_ALT);
-        }
+        if (! m_enabled) { return; }
 
-        if (header != null) {
-            try {
-                parse(bundle, header);
-            } catch (IOException e) {
-                m_logger.log(Logger.ERROR, "An exception occurs during the parsing of the bundle " + bundle.getBundleId(), e);
-            } catch (ParseException e) {
-                m_logger.log(Logger.ERROR, "A parse exception occurs during the parsing of the bundle " + bundle.getBundleId(), e);
-            }
+        // TODO - optimization, ignore all bundles that do not import org.apache.felix.ipojo.configuration
+
+        BundleWiring wiring = bundle.adapt(BundleWiring.class);
+        if (wiring == null) {
+            // Invalid state.
+            m_logger.log(Log.ERROR, "The bundle " + bundle.getBundleId() + " (" + bundle.getSymbolicName() + ") " +
+                    "cannot be adapted to BundleWiring, state: " + bundle.getState());
+            return;
         }
 
+        // Only lookup for local classes, parent classes will be analyzed on demand.
+        Collection<String> resources = wiring.listResources("/", "*.class",
+                BundleWiring.FINDENTRIES_RECURSE + BundleWiring.LISTRESOURCES_LOCAL);
+        if (resources == null) {
+            m_logger.log(Log.ERROR, "The bundle " + bundle.getBundleId() + " (" + bundle.getSymbolicName() + ") " +
+                    " does not have any classes to be analyzed");
+            return;
+        }
+        m_logger.log(Log.DEBUG, resources.size() + " classes found");
+        handleResources(bundle, resources, wiring.getClassLoader());
     }
 
     /**
@@ -107,6 +123,8 @@ public class ComponentsBundleProcessor i
      * @param bundle the bundle
      */
     public void deactivate(Bundle bundle) {
+        if (! m_enabled) { return; }
+
         ComponentsAndInstances cai = m_registry.remove(bundle);
         if (cai != null) {
             cai.stop();
@@ -129,64 +147,119 @@ public class ComponentsBundleProcessor i
         // Ignored, for a simple ordered shutdown, use ReverseBundleProcessor
     }
 
-    /**
-     * Parses the internal metadata (from the manifest
-     * (in the iPOJO-Components property)). This methods
-     * creates factories and add instances to the instance creator.
-     *
-     * @param bundle     the owner bundle.
-     * @param components The iPOJO Header String.
-     * @throws IOException    if the manifest can not be found
-     * @throws ParseException if the parsing process failed
-     */
-    private void parse(Bundle bundle, String components) throws IOException, ParseException {
-        ManifestMetadataParser parser = new ManifestMetadataParser();
-        parser.parseHeader(components);
+    private void handleResources(Bundle bundle, Collection<String> resources, ClassLoader classLoader) {
+        for (String resource : resources) {
+            handleResource(bundle, resource, classLoader);
+        }
+    }
 
-        // Get the component type declaration
-        Element[] metadata = parser.getComponentsMetadata();
-        for (int i = 0; i < metadata.length; i++) {
-            handleTypeDeclaration(bundle, metadata[i]);
+    private void handleResource(Bundle bundle, String resource, ClassLoader classLoader) {
+        URL url = classLoader.getResource(resource);
+        if (url == null) {
+            m_logger.log(Log.ERROR, "The resource " + resource + " cannot be loaded by " + bundle.getBundleId() + " " +
+                    "(" + bundle.getSymbolicName() + ")");
+            return;
         }
 
-        Dictionary[] instances = parser.getInstances();
-        for (int i = 0; instances != null && i < instances.length; i++) {
-            handleInstanceDeclaration(bundle, instances[i]);
+        try {
+            if (hasConfigurationAnnotation(bundle, url, classLoader)) {
+                instantiateAndDeclareInstances(bundle, resource, classLoader);
+            }
+        } catch (IOException e) {
+            m_logger.log(Log.ERROR, "The resource " + resource + " cannot be loaded by " + bundle.getBundleId() + " " +
+                    "(" + bundle.getSymbolicName() + ")", e);
         }
-    }
 
-    /**
-     * Extracts and builds the declaration attached to an instance.
-     *
-     * @param bundle   the bundle declaring the instance
-     * @param instance the instance configuration (parsed from the header)
-     */
-    private void handleInstanceDeclaration(Bundle bundle, Dictionary instance) {
+    }
 
-        String component = (String) instance.get(COMPONENT_INSTANCE_ATTRIBUTE);
-        //String v = (String) instance.get(Factory.FACTORY_VERSION_PROPERTY); //TODO CES to GSA, why this is commented ?
+    private void instantiateAndDeclareInstances(Bundle bundle, String resource, ClassLoader classLoader) {
+        String classname = getClassNameFromResource(resource);
+        List<Instance> instances = new ArrayList<Instance>();
+        try {
+            Class clazz = classLoader.loadClass(classname);
+            Object configuration = clazz.newInstance();
+
+            // Collect fields
+            Map<Field, Instance> fields =
+                    fields().ofType(Instance.class).in(configuration).map();
+            for (Map.Entry<Field, Instance> entry : fields.entrySet()) {
+                Instance instance = entry.getValue();
+                instance.nameIfUnnamed(entry.getKey().getName());
+                instances.add(instance);
+            }
 
-        DefaultInstanceDeclaration declaration = new DefaultInstanceDeclaration(bundle.getBundleContext(),
-                component, instance);
-        declaration.start();
+            // Collect methods with Bundle Context as argument
+            Map<Method, InvocationResult<Instance>> methods =
+                    methods().in(configuration).ofReturnType(Instance.class).withParameter(BundleContext.class)
+                            .map(bundle.getBundleContext());
+
+            // Collect methods without arguments
+            methods.putAll(methods().in(configuration).ofReturnType(Instance.class).map());
+
+            for (Map.Entry<Method, InvocationResult<Instance>> entry : methods.entrySet()) {
+                Instance instance = entry.getValue().get();
+                if (instance == null) {
+                    m_logger.log(Log.ERROR, "The Instance declaration creation failed because the method " + entry
+                            .getKey().getName() + " of class " + entry.getKey().getDeclaringClass() + " threw an " +
+                            "exception", entry.getValue().error());
+                } else {
+                    instance.nameIfUnnamed(entry.getKey().getName());
+                    instances.add(instance);
+                }
+            }
 
-        getComponentsAndInstances(bundle).m_instances.add(declaration);
+        } catch (ClassNotFoundException e) {
+            m_logger.log(Log.ERROR, "Cannot load class " + classname + " despite it was considered as a " +
+                    "configuration", e);
+            return;
+        } catch (InstantiationException e) {
+            m_logger.log(Log.ERROR, "Cannot instantiate class " + classname + " despite it was considered as a " +
+                    "configuration", e);
+            return;
+        } catch (IllegalAccessException e) {
+            m_logger.log(Log.ERROR, "Cannot instantiate class " + classname + " despite it was considered as a " +
+                    "configuration", e);
+            return;
+        }
 
+        m_logger.log(Log.WARNING, instances.size() + " instances found in class " + classname);
+        //Build and enqueue declaration
+        for (Instance instance : instances) {
+            DefaultInstanceDeclaration declaration = new DefaultInstanceDeclaration(bundle.getBundleContext(),
+                    instance.factory(), instance.configuration());
+            declaration.start();
+            getComponentsAndInstances(bundle).m_instances.add(declaration);
+        }
     }
 
-    /**
-     * Adds a component factory to the factory list.
-     *
-     * @param metadata the new component metadata.
-     * @param bundle   the bundle.
-     */
-    private void handleTypeDeclaration(Bundle bundle, Element metadata) {
-
-        DefaultTypeDeclaration declaration = new DefaultTypeDeclaration(bundle.getBundleContext(), metadata);
-        declaration.start();
-
-        getComponentsAndInstances(bundle).m_types.add(declaration);
-
+    private boolean hasConfigurationAnnotation(Bundle bundle, URL url, ClassLoader classLoader) throws IOException {
+        InputStream is = url.openStream();
+        try {
+            ClassReader reader = new ClassReader(is);
+            ConfigurationAnnotationScanner scanner = new ConfigurationAnnotationScanner();
+            reader.accept(scanner, 0);
+
+            // Only class with the @Configuration are considered, parent classes are not analyzed.
+            // Indeed, we have to detect when the parent must be considered independently,
+            // or when only the daughter needs too (to avoid creating the instances twice).
+
+            return scanner.isConfiguration();
+
+            // The following code would traverse the whole class hierarchy.
+//            if (scanner.isConfiguration()) {
+//                return true;
+//            } else if (scanner.getParent() != null) {
+//                URL parentUrl = classLoader.getResource("/" + scanner.getParent().replace(".", "/") + ".class");
+//                if (parentUrl == null) {
+//                    m_logger.log(Log.DEBUG, "Cannot load the parent class " + scanner.getParent() + " - stopping " +
+//                            "scan");
+//                    return false;
+//                }
+//                return hasConfigurationAnnotation(bundle, parentUrl, classLoader);
+//            }
+        } finally {
+            is.close();
+        }
     }
 
     /**

Added: felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/util/Fields.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/util/Fields.java?rev=1471456&view=auto
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/util/Fields.java (added)
+++ felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/util/Fields.java Wed Apr 24 15:06:07 2013
@@ -0,0 +1,134 @@
+/*
+ * 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.util;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+* Fluent API to retrieve fields of a given type.
+*/
+public class Fields<T> {
+
+    private Class<? extends T> type;
+    private Class<?> clazz;
+    private Object object;
+    private Map<String, Field> fields;
+
+    public Collection<T> get() {
+        return map().values();
+    }
+
+    public Map<Field, T> map(Object o) {
+        this.object = o;
+        return map();
+    }
+
+    public Map<Field, T> map() {
+        Collection<Field> set = retrieve();
+        Map<Field, T> results = new LinkedHashMap<Field, T>();
+        for (Field field : set) {
+            if (!field.isAccessible()) {
+                field.setAccessible(true);
+            }
+
+            try {
+                results.put(field, (T) field.get(object));
+            } catch (IllegalAccessException e) {
+                // Hopefully should not happen.
+            }
+        }
+        return results;
+    }
+
+    public Collection<T> get(Object o) {
+        this.object = o;
+        return get();
+    }
+
+    public Fields ofType(Class<? extends T> clazz) {
+        this.type = clazz;
+        return this;
+    }
+
+    public Fields in(Object o) {
+        this.object = o;
+        this.clazz = o.getClass();
+        return this;
+    }
+
+    public Fields in(Class<?> c) {
+        this.clazz = c;
+        return this;
+    }
+
+    private Collection<Field> retrieve() {
+        if (fields != null) {
+            return fields.values();
+        }
+
+        if (clazz == null) {
+            throw new NullPointerException("Cannot retrieve field, class not set");
+        }
+
+
+        fields = new LinkedHashMap<String, Field>();
+
+        // First the class itself
+        Field[] list = clazz.getDeclaredFields();
+        for (Field field : list) {
+            if (type == null || type.isAssignableFrom(field.getType())) {
+                fields.put(field.getName(), field);
+            }
+        }
+
+        // Traverse class hierarchy
+        if (clazz.getSuperclass() != null) {
+            traverse(fields, clazz.getSuperclass());
+        }
+
+        return fields.values();
+    }
+
+    private void traverse(Map<String, Field> fields, Class<?> clazz) {
+        // First the given class
+        Field[] list = clazz.getDeclaredFields();
+        for (Field field : list) {
+            if (type == null || type.isAssignableFrom(field.getType())) {
+                // Already defined by a daughter class
+                if (!fields.containsKey(field.getName())) {
+                    // Check visibility if must be either  public or protected.
+                    if (Modifier.isPublic(field.getModifiers()) || Modifier.isProtected(field.getModifiers())) {
+                        fields.put(field.getName(), field);
+                    }
+                }
+            }
+        }
+
+        // If we have a parent class, traverse it
+        if (clazz.getSuperclass() != null) {
+            traverse(fields, clazz.getSuperclass());
+        }
+    }
+
+}

Added: felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/util/InvocationResult.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/util/InvocationResult.java?rev=1471456&view=auto
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/util/InvocationResult.java (added)
+++ felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/util/InvocationResult.java Wed Apr 24 15:06:07 2013
@@ -0,0 +1,76 @@
+/*
+ * 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.util;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * Wraps the result of a method invocation
+ */
+public class InvocationResult<T> {
+
+    private final Method method;
+    private final Object target;
+    private final T result;
+    private final Throwable error;
+
+    public InvocationResult(Method method, Object target, T result, Throwable error) {
+        this.method = method;
+        this.target = target;
+        this.result = result;
+        this.error = error;
+    }
+
+    public Method getMethod() {
+        return method;
+    }
+
+    public Object getTarget() {
+        return target;
+    }
+
+    public Throwable error() {
+        return error;
+    }
+
+    public T get() {
+        return result;
+    }
+
+    public T getOrElse(T def) {
+        if (error == null) {
+            return def;
+        } else {
+            return result;
+        }
+    }
+
+    public static <T> InvocationResult<T> fromInvocation(Method method, Object target, Object[] args) {
+        try {
+            T result = (T) method.invoke(target, args);
+            return new InvocationResult<T>(method, target, result, null);
+        } catch (IllegalAccessException e) {
+            return new InvocationResult<T>(method, target, null, e);
+        } catch (InvocationTargetException e) {
+            return new InvocationResult<T>(method, target, null, e);
+        }
+    }
+}

Added: felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/util/Methods.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/util/Methods.java?rev=1471456&view=auto
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/util/Methods.java (added)
+++ felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/util/Methods.java Wed Apr 24 15:06:07 2013
@@ -0,0 +1,189 @@
+/*
+ * 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.util;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.*;
+
+/**
+ * Fluent API to retrieve methods.
+ */
+public class Methods<T> {
+
+    private Class<? extends T> returnType;
+    private List<Class<?>> argumentTypes = new ArrayList<Class<?>>();
+    private Class<?> clazz;
+    private Object object;
+    private List<Method> methods;
+
+    public Map<Method, InvocationResult<T>> map(Object... args) {
+        Collection<Method> set = retrieve();
+        Map<Method, InvocationResult<T>> results = new LinkedHashMap<Method, InvocationResult<T>>();
+        for (Method method : set) {
+            if (!method.isAccessible()) {
+                method.setAccessible(true);
+            }
+
+            results.put(method, InvocationResult.<T>fromInvocation(method, object, args));
+
+        }
+        return results;
+    }
+
+    public Collection<InvocationResult<T>> invoke(Object... args) {
+        return map(args).values();
+    }
+
+    public Methods ofReturnType(Class<? extends T> clazz) {
+        this.returnType = clazz;
+        return this;
+    }
+
+    public Methods withParameter(Class<?>... type) {
+        argumentTypes.addAll(Arrays.asList(type));
+        return this;
+    }
+
+    public Methods in(Object o) {
+        this.object = o;
+        this.clazz = o.getClass();
+        return this;
+    }
+
+    public Methods in(Class<?> c) {
+        this.clazz = c;
+        this.object = null;
+        return this;
+    }
+
+    private Collection<Method> retrieve() {
+        if (methods != null) {
+            return methods;
+        }
+
+        if (clazz == null) {
+            throw new NullPointerException("Cannot retrieve method, class not set");
+        }
+
+
+        methods = new ArrayList<Method>();
+
+        // First the class itself
+        Method[] list = clazz.getDeclaredMethods();
+        for (Method method : list) {
+            // Two criteria : the return type and the argument type
+            if (matchReturnType(method)
+                    && matchArgumentTypes(method)) {
+                // The method matches
+                methods.add(method);
+            }
+        }
+
+        // Traverse class hierarchy
+        if (clazz.getSuperclass() != null) {
+            traverse(methods, clazz.getSuperclass());
+        }
+
+        return methods;
+    }
+
+    private boolean matchReturnType(Method method) {
+        if (returnType == null) { // Void.
+            return method.getReturnType() == null;
+        }
+
+        return !(method.getReturnType() == null || !returnType.isAssignableFrom(method.getReturnType()));
+    }
+
+    private boolean matchArgumentTypes(Method method) {
+        // Fast check, the size must be the same.
+        if (argumentTypes.size() != method.getParameterTypes().length) {
+            return false;
+        }
+
+        // We have the same size.
+        for (int i = 0; i < argumentTypes.size(); i++) {
+            Class<?> argType = method.getParameterTypes()[i];
+            if (!argumentTypes.get(i).isAssignableFrom(argType)) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    private boolean matchInheritanceVisibility(Method method) {
+        return Modifier.isPublic(method.getModifiers()) || Modifier.isProtected(method.getModifiers());
+    }
+
+    private boolean matchNotOverridden(Method method, List<Method> methods) {
+        for (Method meth : methods) {
+            if (methodEquality(meth, method)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Compares this <code>Method</code> against the specified object.  Returns
+     * true if the objects are the same.  Two <code>Methods</code> are the same if
+     * they were declared by the same class and have the same name
+     * and formal parameter types and return type.
+     */
+    private boolean methodEquality(Method method1, Method method2) {
+        if (method1.getName().equals(method2.getName())) {
+            if (!method1.getReturnType().equals(method2.getReturnType())) {
+                return false;
+            }
+
+            Class[] params1 = method1.getParameterTypes();
+            Class[] params2 = method2.getParameterTypes();
+            if (params1.length == params2.length) {
+                for (int i = 0; i < params1.length; i++) {
+                    if (params1[i] != params2[i])
+                        return false;
+                }
+                return true;
+            }
+
+        }
+
+        return false;
+    }
+
+    private void traverse(List<Method> methods, Class<?> clazz) {
+        // First the given class
+        Method[] list = clazz.getDeclaredMethods();
+        for (Method method : list) {
+            if (matchReturnType(method) && matchArgumentTypes(method) && matchInheritanceVisibility(method)
+                    && matchNotOverridden(method, methods)) {
+                methods.add(method);
+            }
+        }
+
+        // If we have a parent class, traverse it
+        if (clazz.getSuperclass() != null) {
+            traverse(methods, clazz.getSuperclass());
+        }
+    }
+
+}

Added: felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/util/Reflection.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/util/Reflection.java?rev=1471456&view=auto
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/util/Reflection.java (added)
+++ felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/util/Reflection.java Wed Apr 24 15:06:07 2013
@@ -0,0 +1,35 @@
+/*
+ * 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.util;
+
+/**
+ * Class containing utility method helping reflection
+ */
+public class Reflection {
+
+    public static <T> Fields<T> fields() {
+        return new Fields<T>();
+    }
+
+    public static <T> Methods<T> methods() {
+        return new Methods<T>();
+    }
+
+}

Added: felix/trunk/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/configuration/InstanceDSLTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/configuration/InstanceDSLTest.java?rev=1471456&view=auto
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/configuration/InstanceDSLTest.java (added)
+++ felix/trunk/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/configuration/InstanceDSLTest.java Wed Apr 24 15:06:07 2013
@@ -0,0 +1,54 @@
+/*
+ * 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.configuration;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+import org.apache.felix.ipojo.extender.internal.processor.ConfigurationProcessor;
+
+import static org.apache.felix.ipojo.configuration.Instance.*;
+
+/**
+ * Check the instance DSL.
+ */
+public class InstanceDSLTest extends TestCase {
+
+
+    public void testInstance() {
+        instance().of("my.factory")
+                .with("simple").setto("simple");
+
+        instance()
+                .of("my.factory")
+                .with("simple").setto("simple")
+
+                .with("list").setto(list(1, 2, 3))
+                .with("list2").setto(list().with(1).with(2).with(3))
+
+                .with("map").setto(map().with(pair("entry", "value")))
+                .with("map").setto(map()
+                .with(pair("entry2", list("aaa", "bbb"))));
+    }
+
+    public void testClassnameExtraction() {
+        String cn = ConfigurationProcessor.getClassNameFromResource("/org/apache/felix/ipojo/Pojo.class");
+        Assert.assertEquals(cn, "org.apache.felix.ipojo.Pojo");
+    }
+}