FELIX-4454 Online manipulator should be able to take advantage of Stereotypes
* Use the new manipulator-bom
* Moved AnnotationLiteral into the spi package (seems more logical to group class usable from modules)
* Changed the Module API a bit (module still have to implement the configure() method, but the container do not call that method itself (avoid multiple invocations leading to duplicate bindings))
* Introduced ModuleProvider interface for Pojoization to normalize the way modules are given to the manipulator
* Refactored a bit the 'ipojo:' UrlHandler (use of annotation + logservice)
* Provided a dedicated ResourceStore that search for annotation bytecode in all available bundles
* Added IT tests to ensure that services modules are accessible and that annotation bytecode is usable
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1575999 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/ipojo/manipulator/manipulator-it/online-manipulator-it/src/main/java/org/apache/felix/ipojo/test/online/components/FrenchHelloService.java b/ipojo/manipulator/manipulator-it/online-manipulator-it/src/main/java/org/apache/felix/ipojo/test/online/components/FrenchHelloService.java
new file mode 100644
index 0000000..289f3e9
--- /dev/null
+++ b/ipojo/manipulator/manipulator-it/online-manipulator-it/src/main/java/org/apache/felix/ipojo/test/online/components/FrenchHelloService.java
@@ -0,0 +1,40 @@
+/*
+ * 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.test.online.components;
+
+import org.apache.felix.ipojo.annotations.Instantiate;
+import org.apache.felix.ipojo.annotations.Provides;
+import org.apache.felix.ipojo.test.online.module.Type;
+import org.apache.felix.ipojo.test.online.services.Hello;
+
+/**
+ * User: guillaume
+ * Date: 27/02/2014
+ * Time: 14:33
+ */
+@Type
+@Instantiate
+@Provides
+public class FrenchHelloService implements Hello {
+ @Override
+ public String sayHello() {
+ return "Bonjour";
+ }
+}
diff --git a/ipojo/manipulator/manipulator-it/online-manipulator-it/src/main/java/org/apache/felix/ipojo/test/online/components/GermanHelloService.java b/ipojo/manipulator/manipulator-it/online-manipulator-it/src/main/java/org/apache/felix/ipojo/test/online/components/GermanHelloService.java
new file mode 100644
index 0000000..a4cd6d5
--- /dev/null
+++ b/ipojo/manipulator/manipulator-it/online-manipulator-it/src/main/java/org/apache/felix/ipojo/test/online/components/GermanHelloService.java
@@ -0,0 +1,40 @@
+/*
+ * 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.test.online.components;
+
+import org.apache.felix.ipojo.annotations.Instantiate;
+import org.apache.felix.ipojo.annotations.Provides;
+import org.apache.felix.ipojo.test.online.module.Type2;
+import org.apache.felix.ipojo.test.online.services.Hello;
+
+/**
+ * User: guillaume
+ * Date: 27/02/2014
+ * Time: 14:33
+ */
+@Type2
+@Instantiate
+@Provides
+public class GermanHelloService implements Hello {
+ @Override
+ public String sayHello() {
+ return "Hallo";
+ }
+}
diff --git a/ipojo/manipulator/manipulator-it/online-manipulator-it/src/main/java/org/apache/felix/ipojo/test/online/module/Activator.java b/ipojo/manipulator/manipulator-it/online-manipulator-it/src/main/java/org/apache/felix/ipojo/test/online/module/Activator.java
new file mode 100644
index 0000000..8bf3d80
--- /dev/null
+++ b/ipojo/manipulator/manipulator-it/online-manipulator-it/src/main/java/org/apache/felix/ipojo/test/online/module/Activator.java
@@ -0,0 +1,45 @@
+/*
+ * 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.test.online.module;
+
+import org.apache.felix.ipojo.manipulator.spi.Module;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+
+/**
+ * User: guillaume
+ * Date: 27/02/2014
+ * Time: 14:31
+ */
+public class Activator implements BundleActivator {
+
+ private ServiceRegistration<Module> registration;
+
+ @Override
+ public void start(final BundleContext context) throws Exception {
+ registration = context.registerService(Module.class, new TypeModule(), null);
+ }
+
+ @Override
+ public void stop(final BundleContext context) throws Exception {
+ registration.unregister();
+ }
+}
diff --git a/ipojo/manipulator/manipulator-it/online-manipulator-it/src/main/java/org/apache/felix/ipojo/test/online/module/Type.java b/ipojo/manipulator/manipulator-it/online-manipulator-it/src/main/java/org/apache/felix/ipojo/test/online/module/Type.java
new file mode 100644
index 0000000..2329851
--- /dev/null
+++ b/ipojo/manipulator/manipulator-it/online-manipulator-it/src/main/java/org/apache/felix/ipojo/test/online/module/Type.java
@@ -0,0 +1,36 @@
+/*
+ * 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.test.online.module;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.apache.felix.ipojo.annotations.Component;
+import org.apache.felix.ipojo.annotations.Stereotype;
+
+/**
+ * Stereotype defined in a Module
+ */
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Type {
+}
diff --git a/ipojo/manipulator/manipulator-it/online-manipulator-it/src/main/java/org/apache/felix/ipojo/test/online/module/Type2.java b/ipojo/manipulator/manipulator-it/online-manipulator-it/src/main/java/org/apache/felix/ipojo/test/online/module/Type2.java
new file mode 100644
index 0000000..36992ab
--- /dev/null
+++ b/ipojo/manipulator/manipulator-it/online-manipulator-it/src/main/java/org/apache/felix/ipojo/test/online/module/Type2.java
@@ -0,0 +1,38 @@
+/*
+ * 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.test.online.module;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.apache.felix.ipojo.annotations.Component;
+import org.apache.felix.ipojo.annotations.Stereotype;
+
+/**
+ * Annotated stereotype
+ */
+@Stereotype
+@Component
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Type2 {
+}
diff --git a/ipojo/manipulator/manipulator-it/online-manipulator-it/src/main/java/org/apache/felix/ipojo/test/online/module/TypeModule.java b/ipojo/manipulator/manipulator-it/online-manipulator-it/src/main/java/org/apache/felix/ipojo/test/online/module/TypeModule.java
new file mode 100644
index 0000000..43db0db
--- /dev/null
+++ b/ipojo/manipulator/manipulator-it/online-manipulator-it/src/main/java/org/apache/felix/ipojo/test/online/module/TypeModule.java
@@ -0,0 +1,84 @@
+/*
+ * 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.test.online.module;
+
+import java.lang.annotation.Annotation;
+
+import org.apache.felix.ipojo.annotations.Component;
+import org.apache.felix.ipojo.annotations.Instantiate;
+import org.apache.felix.ipojo.manipulator.spi.AnnotationLiteral;
+import org.apache.felix.ipojo.manipulator.spi.AbsBindingModule;
+
+/**
+ * User: guillaume
+ * Date: 27/02/2014
+ * Time: 14:26
+ */
+public class TypeModule extends AbsBindingModule {
+ @Override
+ public void configure() {
+ // @Type is equivalent to @Component
+ bindStereotype(Type.class)
+ .with(new ComponentLiteral());
+ }
+
+ private static class ComponentLiteral extends AnnotationLiteral<Component> implements Component {
+
+ public boolean public_factory() {
+ return true;
+ }
+
+ public boolean publicFactory() {
+ return true;
+ }
+
+ public String name() {
+ return "";
+ }
+
+ public boolean architecture() {
+ return false;
+ }
+
+ public boolean immediate() {
+ return false;
+ }
+
+ public boolean propagation() {
+ return true;
+ }
+
+ public String managedservice() {
+ return "";
+ }
+
+ public String factory_method() {
+ return "";
+ }
+
+ public String factoryMethod() {
+ return "";
+ }
+
+ public String version() {
+ return "";
+ }
+ }
+}
diff --git a/ipojo/manipulator/manipulator-it/online-manipulator-it/src/test/java/org/apache/felix/ipojo/test/online/OnlineManipulatorTest.java b/ipojo/manipulator/manipulator-it/online-manipulator-it/src/test/java/org/apache/felix/ipojo/test/online/OnlineManipulatorTest.java
index 5690f05..474ccc4 100644
--- a/ipojo/manipulator/manipulator-it/online-manipulator-it/src/test/java/org/apache/felix/ipojo/test/online/OnlineManipulatorTest.java
+++ b/ipojo/manipulator/manipulator-it/online-manipulator-it/src/test/java/org/apache/felix/ipojo/test/online/OnlineManipulatorTest.java
@@ -26,8 +26,14 @@
import org.apache.felix.ipojo.architecture.Architecture;
import org.apache.felix.ipojo.architecture.InstanceDescription;
import org.apache.felix.ipojo.test.online.components.Consumer;
+import org.apache.felix.ipojo.test.online.components.FrenchHelloService;
+import org.apache.felix.ipojo.test.online.components.GermanHelloService;
import org.apache.felix.ipojo.test.online.components.MyProvider;
import org.apache.felix.ipojo.test.online.components.MyProviderWithAnnotations;
+import org.apache.felix.ipojo.test.online.module.Activator;
+import org.apache.felix.ipojo.test.online.module.Type;
+import org.apache.felix.ipojo.test.online.module.Type2;
+import org.apache.felix.ipojo.test.online.module.TypeModule;
import org.apache.felix.ipojo.test.online.services.Hello;
import org.junit.After;
import org.junit.Assert;
@@ -78,6 +84,8 @@
String providerWithoutMetadata = providerWithoutMetadata();
String consumerWithMetadata = consumerWithMetadata();
String consumerWithoutMetadata = consumerWithoutMetadata();
+ String providerUsingModules = providerUsingModules();
+ String providerUsingAnnotatedStereotype = providerUsingAnnotatedStereotype();
return options(
cleanCaches(),
@@ -91,7 +99,8 @@
.add(Hello.class)
.set(Constants.BUNDLE_SYMBOLICNAME, "ServiceInterface")
.set(Constants.EXPORT_PACKAGE, "org.apache.felix.ipojo.test.online.services")
- .build()
+ .build(),
+ moduleBundle()
),
systemProperty("providerWithMetadata").value(providerWithMetadata),
@@ -100,12 +109,30 @@
systemProperty("providerUsingAnnotations").value(providerUsingAnnotation()),
systemProperty("consumerWithMetadata").value(consumerWithMetadata),
systemProperty("consumerWithoutMetadata").value(consumerWithoutMetadata),
+ systemProperty("providerUsingModules").value(providerUsingModules),
+ systemProperty("providerUsingAnnotatedStereotype").value(providerUsingAnnotatedStereotype),
systemProperty("org.knopflerfish.osgi.registerserviceurlhandler").value("true")
);
}
+ private InputStream moduleBundle() {
+ return TinyBundles.bundle()
+ .add(Activator.class)
+ .add(Type.class)
+ .add(Type2.class)
+ .add(TypeModule.class)
+ .set(Constants.BUNDLE_ACTIVATOR, Activator.class.getName())
+ .set(Constants.BUNDLE_SYMBOLICNAME, "Manipulator Module")
+ .set(Constants.IMPORT_PACKAGE,
+ "org.osgi.framework," +
+ "org.apache.felix.ipojo.manipulator.spi," +
+ "org.apache.felix.ipojo.annotations")
+ .set(Constants.EXPORT_PACKAGE, "org.apache.felix.ipojo.test.online.module")
+ .build();
+ }
+
@Before
public void before() {
helper = new OSGiHelper(context);
@@ -257,6 +284,38 @@
bundle2.uninstall();
}
+ @Test
+ public void testManipulatorModuleRegisteredAsServicesAreLoaded() throws Exception {
+
+ String url = context.getProperty("providerUsingModules");
+ Assert.assertNotNull(url);
+ Bundle bundle = context.installBundle("ipojo:" + url);
+ bundle.start();
+ assertBundle("ProviderUsingModules");
+
+ helper.waitForService(Hello.class.getName(), null, 5000);
+ Assert.assertNotNull(context.getServiceReference(Hello.class.getName()));
+
+ bundle.uninstall();
+
+ }
+
+ @Test
+ public void testAnnotatedStereotypes() throws Exception {
+
+ String url = context.getProperty("providerUsingAnnotatedStereotype");
+ Assert.assertNotNull(url);
+ Bundle bundle = context.installBundle("ipojo:" + url);
+ bundle.start();
+ assertBundle("ProviderUsingAnnotatedStereotype");
+
+ helper.waitForService(Hello.class.getName(), null, 5000);
+ Assert.assertNotNull(context.getServiceReference(Hello.class.getName()));
+
+ bundle.uninstall();
+
+ }
+
/**
* Gets a regular bundle containing metadata file
*
@@ -358,6 +417,37 @@
}
/**
+ * Gets a consumer bundle using annotation containing the instance
+ * declaration in the metadata.
+ *
+ * @return the url of the bundle
+ * @throws java.io.IOException
+ */
+ public static String providerUsingModules() throws IOException {
+ InputStream is = TinyBundles.bundle()
+ .add(FrenchHelloService.class)
+ .set(Constants.BUNDLE_SYMBOLICNAME, "ProviderUsingModules")
+ .set(Constants.IMPORT_PACKAGE, "org.apache.felix.ipojo.test.online.services")
+ .build();
+
+ File out = getTemporaryFile("providerUsingModules");
+ StreamUtils.copyStream(is, new FileOutputStream(out), true);
+ return out.toURI().toURL().toExternalForm();
+ }
+
+ public static String providerUsingAnnotatedStereotype() throws IOException {
+ InputStream is = TinyBundles.bundle()
+ .add(GermanHelloService.class)
+ .set(Constants.BUNDLE_SYMBOLICNAME, "ProviderUsingAnnotatedStereotype")
+ .set(Constants.IMPORT_PACKAGE, "org.apache.felix.ipojo.test.online.services")
+ .build();
+
+ File out = getTemporaryFile("providerUsingAnnotatedStereotype");
+ StreamUtils.copyStream(is, new FileOutputStream(out), true);
+ return out.toURI().toURL().toExternalForm();
+ }
+
+ /**
* Gets a consumer bundle using annotation that does not contain
* metadata
*
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/Pojoization.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/Pojoization.java
index c2a3356..6239b4c 100644
--- a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/Pojoization.java
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/Pojoization.java
@@ -33,6 +33,9 @@
import org.apache.felix.ipojo.manipulator.metadata.StreamMetadataProvider;
import org.apache.felix.ipojo.manipulator.render.MetadataRenderer;
import org.apache.felix.ipojo.manipulator.reporter.SystemReporter;
+import org.apache.felix.ipojo.manipulator.spi.ModuleProvider;
+import org.apache.felix.ipojo.manipulator.spi.provider.CoreModuleProvider;
+import org.apache.felix.ipojo.manipulator.spi.provider.ServiceLoaderModuleProvider;
import org.apache.felix.ipojo.manipulator.store.DirectoryResourceStore;
import org.apache.felix.ipojo.manipulator.store.JarFileResourceStore;
import org.apache.felix.ipojo.manipulator.store.builder.DefaultManifestBuilder;
@@ -67,14 +70,25 @@
/**
* Reporter for error reporting.
*/
- private Reporter m_reporter;
+ private final Reporter m_reporter;
+
+ private final ModuleProvider m_moduleProvider;
public Pojoization() {
this(new SystemReporter());
}
+ public Pojoization(ModuleProvider provider) {
+ this(new SystemReporter(), provider);
+ }
+
public Pojoization(Reporter reporter) {
+ this(reporter, new ServiceLoaderModuleProvider());
+ }
+
+ public Pojoization(Reporter reporter, final ModuleProvider moduleProvider) {
m_reporter = reporter;
+ m_moduleProvider = moduleProvider;
m_reporter.info("Apache Felix iPOJO Manipulator - " + Constants.getVersion());
}
@@ -284,7 +298,7 @@
composite.addMetadataProvider(metadata);
if (!m_ignoreAnnotations) {
- composite.addMetadataProvider(new AnnotationMetadataProvider(store, m_reporter));
+ composite.addMetadataProvider(new AnnotationMetadataProvider(store, m_moduleProvider, m_reporter));
}
// Get metadata
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/AnnotationMetadataProvider.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/AnnotationMetadataProvider.java
index 67de673..218cf10 100644
--- a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/AnnotationMetadataProvider.java
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/AnnotationMetadataProvider.java
@@ -24,11 +24,13 @@
import java.util.List;
import org.apache.felix.ipojo.manipulator.MetadataProvider;
+import org.apache.felix.ipojo.manipulator.spi.ModuleProvider;
import org.apache.felix.ipojo.manipulator.Reporter;
import org.apache.felix.ipojo.manipulator.ResourceStore;
import org.apache.felix.ipojo.manipulator.ResourceVisitor;
import org.apache.felix.ipojo.manipulator.metadata.annotation.ClassMetadataCollector;
import org.apache.felix.ipojo.manipulator.metadata.annotation.registry.BindingRegistry;
+import org.apache.felix.ipojo.manipulator.spi.provider.CoreModuleProvider;
import org.apache.felix.ipojo.metadata.Element;
import org.objectweb.asm.ClassReader;
@@ -48,7 +50,13 @@
public AnnotationMetadataProvider(final ResourceStore store,
final Reporter reporter) {
- this(store, newBindingRegistry(reporter, store), reporter);
+ this(store, new CoreModuleProvider(), reporter);
+ }
+
+ public AnnotationMetadataProvider(final ResourceStore store,
+ final ModuleProvider provider,
+ final Reporter reporter) {
+ this(store, newBindingRegistry(reporter, store, provider), reporter);
}
public AnnotationMetadataProvider(final ResourceStore store,
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/util/Bindings.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/util/Bindings.java
index 2a74b87..5da9928 100644
--- a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/util/Bindings.java
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/util/Bindings.java
@@ -19,6 +19,7 @@
package org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.util;
+import org.apache.felix.ipojo.manipulator.spi.ModuleProvider;
import org.apache.felix.ipojo.manipulator.Reporter;
import org.apache.felix.ipojo.manipulator.ResourceStore;
import org.apache.felix.ipojo.manipulator.metadata.annotation.registry.DefaultBindingRegistry;
@@ -28,16 +29,14 @@
import org.apache.felix.ipojo.manipulator.metadata.annotation.registry.BindingRegistry;
import org.apache.felix.ipojo.manipulator.spi.Module;
-import java.util.ServiceLoader;
-
-import static org.apache.felix.ipojo.manipulator.spi.helper.Predicates.or;
-
/**
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public class Bindings {
- public static BindingRegistry newBindingRegistry(Reporter reporter, ResourceStore store) {
+ public static BindingRegistry newBindingRegistry(final Reporter reporter,
+ final ResourceStore store,
+ final ModuleProvider provider) {
// Build the registry by aggregation of the features we want
// TODO We can enable/disable the legacy support easily here
@@ -46,18 +45,12 @@
registry = new LegacyGenericBindingRegistry(registry, reporter);
registry = new IgnoreAllBindingRegistry(registry, reporter);
- ServiceLoader<Module> loader = ServiceLoader.load(Module.class, classloader());
-
// Build each Module and add its contributed Bindings in the registry
- for (Module module : loader) {
- module.configure();
+ for (Module module : provider.findModules()) {
+ module.load();
registry.addBindings(module);
}
return registry;
}
-
- private static ClassLoader classloader() {
- return Bindings.class.getClassLoader();
- }
}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/AbsBindingModule.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/AbsBindingModule.java
index c188e5e..6f46672 100644
--- a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/AbsBindingModule.java
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/AbsBindingModule.java
@@ -27,7 +27,6 @@
import java.util.List;
import org.apache.felix.ipojo.manipulator.metadata.annotation.model.AnnotationType;
-import org.apache.felix.ipojo.manipulator.metadata.annotation.model.literal.AnnotationLiteral;
import org.apache.felix.ipojo.manipulator.metadata.annotation.model.literal.AnnotationPlayback;
import org.apache.felix.ipojo.manipulator.metadata.annotation.registry.Binding;
import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.generic.GenericVisitorFactory;
@@ -47,7 +46,22 @@
/**
* Build bindings.
*/
- private List<Binding> bindings = new ArrayList<Binding>();
+ private final List<Binding> bindings = new ArrayList<Binding>();
+
+ private boolean loaded = false;
+
+ public synchronized void load() {
+ if (!loaded) {
+ configure();
+ loaded = true;
+ }
+ }
+
+ /**
+ * Configure the bindings provided by this module.
+ */
+ protected abstract void configure();
+
public Iterator<Binding> iterator() {
return bindings.iterator();
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/literal/AnnotationLiteral.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/AnnotationLiteral.java
similarity index 84%
rename from ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/literal/AnnotationLiteral.java
rename to ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/AnnotationLiteral.java
index 6da7dac..52ab4e4 100644
--- a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/literal/AnnotationLiteral.java
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/AnnotationLiteral.java
@@ -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
@@ -17,7 +17,7 @@
* under the License.
*/
-package org.apache.felix.ipojo.manipulator.metadata.annotation.model.literal;
+package org.apache.felix.ipojo.manipulator.spi;
import static java.lang.String.format;
@@ -26,9 +26,16 @@
import java.lang.reflect.Type;
/**
- * User: guillaume
- * Date: 28/06/13
- * Time: 11:39
+ * Base annotation literal class to be extended when declaring stereotype bindings in a programmatic way.
+ * Usage example:
+ * <pre>
+ * public class InstantiateLiteral extends AnnotationLiteral<Instantiate> implements Instantiate {
+ * public String name() {
+ * return "";
+ * }
+ * }
+ * </pre>
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public abstract class AnnotationLiteral<T extends Annotation> implements Annotation {
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/Module.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/Module.java
index e5f4b5c..433bcb9 100644
--- a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/Module.java
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/Module.java
@@ -30,7 +30,8 @@
public interface Module extends Iterable<Binding> {
/**
- * Configure the bindings provided by this module.
+ * Load the bindings provided by this module (only once).
+ * @since 1.12
*/
- void configure();
+ void load();
}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/ModuleProvider.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/ModuleProvider.java
new file mode 100644
index 0000000..e2298c3
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/ModuleProvider.java
@@ -0,0 +1,38 @@
+/*
+ * 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.manipulator.spi;
+
+import org.apache.felix.ipojo.manipulator.spi.Module;
+
+/**
+ * Discover {@link org.apache.felix.ipojo.manipulator.spi.Module}s available in the "environment".
+ * Environment is dependent of the implementation.
+ * @since 1.12
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public interface ModuleProvider {
+
+ /**
+ * Discover a set of modules at a given time.
+ * Returned modules could disappear in the future.
+ * @return discovered modules (should <bold>NEVER</bold> returns {@literal null})
+ */
+ Iterable<Module> findModules();
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/provider/CompositeModuleProvider.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/provider/CompositeModuleProvider.java
new file mode 100644
index 0000000..c1ae728
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/provider/CompositeModuleProvider.java
@@ -0,0 +1,55 @@
+/*
+ * 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.manipulator.spi.provider;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.felix.ipojo.manipulator.spi.ModuleProvider;
+import org.apache.felix.ipojo.manipulator.spi.Module;
+
+/**
+ * Encapsulate other ModuleProviders in a single instance.
+ * @since 1.12
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class CompositeModuleProvider implements ModuleProvider {
+
+ private final Iterable<ModuleProvider> providers;
+
+ public CompositeModuleProvider(ModuleProvider... providers) {
+ this(Arrays.asList(providers));
+ }
+
+ public CompositeModuleProvider(final Iterable<ModuleProvider> providers) {
+ this.providers = providers;
+ }
+
+ public Iterable<Module> findModules() {
+ List<Module> modules = new ArrayList<Module>();
+ for (ModuleProvider provider : providers) {
+ for (Module module : provider.findModules()) {
+ modules.add(module);
+ }
+ }
+ return modules;
+ }
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/provider/CoreModuleProvider.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/provider/CoreModuleProvider.java
new file mode 100644
index 0000000..218d9b3
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/provider/CoreModuleProvider.java
@@ -0,0 +1,33 @@
+/*
+ * 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.manipulator.spi.provider;
+
+import org.apache.felix.ipojo.manipulator.metadata.annotation.module.DefaultBindingModule;
+
+/**
+ * Hardcoded provider for default core manipulation module.
+ * @since 1.12
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class CoreModuleProvider extends DefaultModuleProvider {
+ public CoreModuleProvider() {
+ super(new DefaultBindingModule());
+ }
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/provider/DefaultModuleProvider.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/provider/DefaultModuleProvider.java
new file mode 100644
index 0000000..bb2fdef
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/provider/DefaultModuleProvider.java
@@ -0,0 +1,53 @@
+/*
+ * 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.manipulator.spi.provider;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+import org.apache.felix.ipojo.manipulator.spi.ModuleProvider;
+import org.apache.felix.ipojo.manipulator.spi.Module;
+
+/**
+ * Return the given collection of {@link org.apache.felix.ipojo.manipulator.spi.Module}s.
+ * @since 1.12
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class DefaultModuleProvider implements ModuleProvider {
+
+ private final Iterable<Module> modules;
+
+ public DefaultModuleProvider() {
+ this(Collections.<Module>emptyList());
+ }
+
+ public DefaultModuleProvider(Module... modules) {
+ this(Arrays.asList(modules));
+ }
+
+ public DefaultModuleProvider(final Iterable<Module> modules) {
+ this.modules = modules;
+ }
+
+ public Iterable<Module> findModules() {
+ return modules;
+ }
+
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/provider/ServiceLoaderModuleProvider.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/provider/ServiceLoaderModuleProvider.java
new file mode 100644
index 0000000..ea44ac0
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/provider/ServiceLoaderModuleProvider.java
@@ -0,0 +1,52 @@
+/*
+ * 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.manipulator.spi.provider;
+
+import java.util.ServiceLoader;
+
+import org.apache.felix.ipojo.manipulator.spi.ModuleProvider;
+import org.apache.felix.ipojo.manipulator.spi.Module;
+
+/**
+ * Find {@link org.apache.felix.ipojo.manipulator.spi.Module}s using the {@link java.util.ServiceLoader} mechanisms.
+ * @since 1.12
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ServiceLoaderModuleProvider implements ModuleProvider {
+
+ private final ClassLoader loader;
+
+ public ServiceLoaderModuleProvider() {
+ this(ServiceLoaderModuleProvider.class);
+ }
+
+ public ServiceLoaderModuleProvider(final Class<?> type) {
+ this(type.getClassLoader());
+ }
+
+ public ServiceLoaderModuleProvider(ClassLoader loader) {
+ this.loader = loader;
+ }
+
+ public Iterable<Module> findModules() {
+ return ServiceLoader.load(Module.class, loader);
+ }
+
+}
diff --git a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/SelectionTestCase.java b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/SelectionTestCase.java
index 06c337d..8ae37f9 100644
--- a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/SelectionTestCase.java
+++ b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/SelectionTestCase.java
@@ -78,7 +78,7 @@
public void testSelectionOnClassNodeOnly() throws Exception {
AbsBindingModule module = new MonoBindingModule(OnTypeOnly.class);
- module.configure();
+ module.load();
registry.addBindings(module);
// Verifications
@@ -91,7 +91,7 @@
public void testSelectionOnFieldNodeOnly() throws Exception {
AbsBindingModule module = new MonoBindingModule(OnFieldOnly.class);
- module.configure();
+ module.load();
registry.addBindings(module);
// Verifications
@@ -105,7 +105,7 @@
public void testSelectionOnMethodNodeOnly() throws Exception {
AbsBindingModule module = new MonoBindingModule(OnMethodOnly.class);
- module.configure();
+ module.load();
registry.addBindings(module);
// Verifications
@@ -119,7 +119,7 @@
public void testSelectionOnMethodParameterOnly() throws Exception {
AbsBindingModule module = new MonoBindingModule(OnParameterOnly.class);
- module.configure();
+ module.load();
registry.addBindings(module);
// Verifications
@@ -133,7 +133,7 @@
public void testSelectionOBothMethodAndParameter() throws Exception {
AbsBindingModule module = new MonoBindingModule(OnBothMethodAndParameter.class);
- module.configure();
+ module.load();
registry.addBindings(module);
// Verifications
diff --git a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/spi/AbsBindingModuleTestCase.java b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/spi/AbsBindingModuleTestCase.java
index f6f6ebe..3374522 100644
--- a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/spi/AbsBindingModuleTestCase.java
+++ b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/spi/AbsBindingModuleTestCase.java
@@ -22,10 +22,8 @@
import junit.framework.TestCase;
import org.apache.felix.ipojo.annotations.Component;
-import org.apache.felix.ipojo.annotations.HandlerBinding;
import org.apache.felix.ipojo.annotations.Provides;
import org.apache.felix.ipojo.annotations.Requires;
-import org.apache.felix.ipojo.manipulator.metadata.annotation.model.literal.AnnotationLiteral;
import org.apache.felix.ipojo.manipulator.metadata.annotation.registry.Binding;
import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.generic.GenericVisitorFactory;
import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.ignore.NullBinding;
@@ -36,7 +34,6 @@
import static org.apache.felix.ipojo.manipulator.spi.helper.Predicates.on;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.only;
import static org.objectweb.asm.Type.getType;
/**
diff --git a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/literal/AnnotationLiteralTestCase.java b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/spi/AnnotationLiteralTestCase.java
similarity index 86%
rename from ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/literal/AnnotationLiteralTestCase.java
rename to ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/spi/AnnotationLiteralTestCase.java
index 9d6360d..54f2ab8 100644
--- a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/model/literal/AnnotationLiteralTestCase.java
+++ b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/spi/AnnotationLiteralTestCase.java
@@ -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
@@ -17,9 +17,9 @@
* under the License.
*/
-package org.apache.felix.ipojo.manipulator.metadata.annotation.model.literal;
+package org.apache.felix.ipojo.manipulator.spi;
-import org.apache.felix.ipojo.manipulator.metadata.annotation.model.literal.AnnotationLiteral;
+import org.apache.felix.ipojo.manipulator.spi.AnnotationLiteral;
import junit.framework.TestCase;
diff --git a/ipojo/manipulator/online-manipulator/pom.xml b/ipojo/manipulator/online-manipulator/pom.xml
index 3c61c15..07e9a56 100644
--- a/ipojo/manipulator/online-manipulator/pom.xml
+++ b/ipojo/manipulator/online-manipulator/pom.xml
@@ -55,23 +55,18 @@
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.ipojo.metadata</artifactId>
- <version>1.6.0</version>
</dependency>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.ipojo.manipulator</artifactId>
- <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.ipojo.annotations</artifactId>
</dependency>
<dependency>
<groupId>asm</groupId>
<artifactId>asm-all</artifactId>
- <version>3.3.1</version>
- <exclusions>
- <exclusion>
- <groupId>asm</groupId>
- <artifactId>asm-tree</artifactId>
- </exclusion>
- </exclusions>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
@@ -80,6 +75,19 @@
<scope>test</scope>
</dependency>
</dependencies>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>ipojo-manipulator-bom</artifactId>
+ <version>${project.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
<build>
<resources>
<resource>
@@ -138,9 +146,6 @@
<goals>
<goal>ipojo-bundle</goal>
</goals>
- <configuration>
- <ignoreAnnotations>true</ignoreAnnotations>
- </configuration>
</execution>
</executions>
</plugin>
diff --git a/ipojo/manipulator/online-manipulator/src/main/java/org/apache/felix/ipojo/online/manipulator/BundleAwareJarFileResourceStore.java b/ipojo/manipulator/online-manipulator/src/main/java/org/apache/felix/ipojo/online/manipulator/BundleAwareJarFileResourceStore.java
new file mode 100644
index 0000000..0b8f612
--- /dev/null
+++ b/ipojo/manipulator/online-manipulator/src/main/java/org/apache/felix/ipojo/online/manipulator/BundleAwareJarFileResourceStore.java
@@ -0,0 +1,91 @@
+/*
+ * 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.online.manipulator;
+
+import static java.lang.String.format;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.util.List;
+import java.util.jar.JarFile;
+
+import org.apache.felix.ipojo.manipulator.render.MetadataRenderer;
+import org.apache.felix.ipojo.manipulator.store.JarFileResourceStore;
+import org.apache.felix.ipojo.manipulator.store.builder.DefaultManifestBuilder;
+import org.apache.felix.ipojo.manipulator.util.Streams;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.wiring.BundleWiring;
+
+/**
+ * User: guillaume
+ * Date: 28/02/2014
+ * Time: 19:16
+ */
+public class BundleAwareJarFileResourceStore extends JarFileResourceStore {
+
+ private final BundleContext bundleContext;
+
+ /**
+ * @param source original Bundle
+ * @param target File where the updated Bundle will be outputted
+ * @throws java.io.IOException if there is an error retrieving the Manifest from the original JarFile
+ */
+ public BundleAwareJarFileResourceStore(final JarFile source,
+ final File target,
+ final BundleContext bundleContext) throws IOException {
+ super(source, target);
+ this.bundleContext = bundleContext;
+ DefaultManifestBuilder manifestBuilder = new DefaultManifestBuilder();
+ manifestBuilder.setMetadataRenderer(new MetadataRenderer());
+ setManifestBuilder(manifestBuilder);
+ }
+
+ @Override
+ public byte[] read(final String path) throws IOException {
+ try {
+ return super.read(path);
+ } catch (IOException e) {
+ // An IOException is thrown when no resource can be found
+ // We swallow this exception and try to load the resource from the installed bundles
+ }
+
+ String directory = path.substring(0, path.lastIndexOf('/'));
+ String filename = path.substring(path.lastIndexOf('/') + 1);
+
+ for (Bundle bundle : bundleContext.getBundles()) {
+
+ BundleWiring wiring = bundle.adapt(BundleWiring.class);
+ List<URL> entries = wiring.findEntries(directory, filename, 0);
+ for (URL url : entries) {
+ try {
+ return Streams.readBytes(url.openStream());
+ } catch (IOException e) {
+ // Ignore and move to the next source
+ e.printStackTrace();
+ }
+ }
+
+ }
+
+ throw new IOException(format("Could not find %s in currently available bundles", path));
+ }
+}
diff --git a/ipojo/manipulator/online-manipulator/src/main/java/org/apache/felix/ipojo/online/manipulator/Files.java b/ipojo/manipulator/online-manipulator/src/main/java/org/apache/felix/ipojo/online/manipulator/Files.java
new file mode 100644
index 0000000..f645651
--- /dev/null
+++ b/ipojo/manipulator/online-manipulator/src/main/java/org/apache/felix/ipojo/online/manipulator/Files.java
@@ -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.online.manipulator;
+
+import static org.apache.felix.ipojo.manipulator.util.Streams.close;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+/**
+ * User: guillaume
+ * Date: 04/03/2014
+ * Time: 15:33
+ */
+public class Files {
+
+ public static void dump(URL url, File target) throws IOException {
+ dump(url.openStream(), target);
+ }
+
+ public static void dump(InputStream stream, File target) throws IOException {
+ BufferedInputStream in = new BufferedInputStream(stream);
+ FileOutputStream file = new FileOutputStream(target);
+ BufferedOutputStream out = new BufferedOutputStream(file);
+ int i;
+ while ((i = in.read()) != -1) {
+ out.write(i);
+ }
+ out.flush();
+ close(in, out);
+ }
+}
diff --git a/ipojo/manipulator/online-manipulator/src/main/java/org/apache/felix/ipojo/online/manipulator/IPOJOURLHandler.java b/ipojo/manipulator/online-manipulator/src/main/java/org/apache/felix/ipojo/online/manipulator/IPOJOURLHandler.java
index bd16ebf..403581c 100644
--- a/ipojo/manipulator/online-manipulator/src/main/java/org/apache/felix/ipojo/online/manipulator/IPOJOURLHandler.java
+++ b/ipojo/manipulator/online-manipulator/src/main/java/org/apache/felix/ipojo/online/manipulator/IPOJOURLHandler.java
@@ -18,53 +18,123 @@
*/
package org.apache.felix.ipojo.online.manipulator;
+import static java.lang.String.format;
+import static org.apache.felix.ipojo.online.manipulator.Files.dump;
+import static org.osgi.service.log.LogService.LOG_DEBUG;
+import static org.osgi.service.log.LogService.LOG_WARNING;
+import static org.osgi.service.url.URLConstants.URL_HANDLER_PROTOCOL;
+
+import org.apache.felix.ipojo.annotations.Bind;
+import org.apache.felix.ipojo.annotations.Component;
+import org.apache.felix.ipojo.annotations.Instantiate;
+import org.apache.felix.ipojo.annotations.Invalidate;
+import org.apache.felix.ipojo.annotations.Provides;
+import org.apache.felix.ipojo.annotations.Requires;
+import org.apache.felix.ipojo.annotations.StaticServiceProperty;
+import org.apache.felix.ipojo.annotations.Unbind;
+import org.apache.felix.ipojo.manipulator.ManipulationVisitor;
+import org.apache.felix.ipojo.manipulator.Reporter;
+import org.apache.felix.ipojo.manipulator.ResourceStore;
+import org.apache.felix.ipojo.manipulator.metadata.CompositeMetadataProvider;
+import org.apache.felix.ipojo.manipulator.metadata.FileMetadataProvider;
+import org.apache.felix.ipojo.manipulator.reporter.SystemReporter;
+import org.apache.felix.ipojo.manipulator.spi.ModuleProvider;
import org.apache.felix.ipojo.manipulator.Pojoization;
+import org.apache.felix.ipojo.manipulator.spi.Module;
+import org.apache.felix.ipojo.manipulator.spi.provider.CompositeModuleProvider;
+import org.apache.felix.ipojo.manipulator.spi.provider.CoreModuleProvider;
+import org.apache.felix.ipojo.manipulator.spi.provider.DefaultModuleProvider;
+import org.apache.felix.ipojo.manipulator.visitor.check.CheckFieldConsistencyVisitor;
+import org.apache.felix.ipojo.manipulator.visitor.writer.ManipulatedResourcesWriter;
import org.osgi.framework.BundleContext;
+import org.osgi.service.log.LogService;
+import org.osgi.service.url.AbstractURLStreamHandlerService;
import org.osgi.service.url.URLStreamHandlerService;
import java.io.File;
-import java.io.FileOutputStream;
import java.io.IOException;
-import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
+import java.util.ArrayList;
+import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
/**
* iPOJO URL Handler allowing installation time manipulation.
- * When a bundle is installed with the <code>ipojo:</code> URL
- * prefix, the bundle is downloaded and manipulated by this
- * handler.
- * The metadata.xml file can either be provided inside the bundle (root,
- * or in META-INF) or given in the URL:
- * ipojo:URL_BUNDLE!URL_METADATA.
+ *
+ * When a bundle is installed with the {@literal ipojo} URL prefix, the referred bundle is
+ * manipulated by this handler.
+
+ * The {@literal metadata.xml} file can either be provided:
+ * <ul>
+ * <li>Inside the bundle, this handler will look for {@literal /metadata.xml} (at the root of the bundle)
+ * or in {@literal /META-INF/metadata.xml}</li>
+ * <li>Through the URL using the following URL format: {@literal ipojo:URL_BUNDLE!URL_METADATA}, notice
+ * the {@literal !} used as separator</li>
+ * </ul>
+ *
+ * Examples of valid iPojo's URLs:
+ * <pre>
+ * ipojo:file:///tmp/bundle.jar
+ * ipojo:/http://www.example.org/bundle.jar
+ * ipojo://mvn://com.acme/bundle/1.0.0 (with Maven Pax Url support installed)
+ * ipojo:file:///tmp/bundle.jar!file:///tmp2/metadata.xml
+ * </pre>
+ *
+ * Notice that trailing {@literal '/'} (or {@literal '//'}) after {@literal ipojo:} are optional.
*
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
-public class IPOJOURLHandler
- extends org.osgi.service.url.AbstractURLStreamHandlerService implements URLStreamHandlerService {
+@Component(publicFactory = false,
+ immediate = true)
+@Provides(specifications = URLStreamHandlerService.class,
+ properties = @StaticServiceProperty(name = URL_HANDLER_PROTOCOL,
+ value = "ipojo",
+ type = "java.lang.String"))
+@Instantiate
+public class IPOJOURLHandler extends AbstractURLStreamHandlerService {
+
+ public static final String IPOJO_SCHEME = "ipojo:";
+
+ private final BundleContext m_context;
/**
- * The bundle context.
+ * The directory storing manipulated bundles.
*/
- private BundleContext m_context;
- /**
- * The directory storing bundles.
- */
- private File m_temp;
+ private final File m_temp;
+
+ private List<Module> m_modules = new ArrayList<Module>();
+
+ //@Requires(optional = true, defaultimplementation = SystemLogService.class)
+ // TODO Change this once NPE is fixed
+ private LogService logger = new SystemLogService();
+
+ @Bind(optional = true, aggregate = true)
+ public void bindModule(Module module) {
+ m_modules.add(module);
+ }
+
+ @Unbind
+ public void unbindModule(Module module) {
+ m_modules.remove(module);
+ }
/**
* Creates a IPOJOURLHandler.
* Gets the bundle context and create the working
* directory.
*
- * @param bc the bundle context
+ * @param bundleContext the bundle context
*/
- public IPOJOURLHandler(BundleContext bc) {
- m_context = bc;
- m_temp = m_context.getDataFile("temp");
+ public IPOJOURLHandler(BundleContext bundleContext) {
+ this(bundleContext, bundleContext.getDataFile("temp"));
+ }
+
+ public IPOJOURLHandler(BundleContext context, File work) {
+ m_context = context;
+ m_temp = work;
if (!m_temp.exists()) {
m_temp.mkdir();
}
@@ -74,6 +144,7 @@
* Stops the URL handler:
* Deletes the working directory.
*/
+ @Invalidate
public void stop() {
File[] files = m_temp.listFiles();
if (files != null) {
@@ -95,119 +166,116 @@
* @see org.osgi.service.url.AbstractURLStreamHandlerService#openConnection(java.net.URL)
*/
public URLConnection openConnection(URL url) throws IOException {
- System.out.println("Processing URL : " + url);
+ logger.log(LOG_DEBUG, format("Processing URL %s", url));
+ String full = removeScheme(url);
- // Parse the url:
- String full = url.toExternalForm();
- // Remote ipojo://
- if (full.startsWith("ipojo:")) {
- full = full.substring(6);
- }
- // Remove '/' or '//'
- while (full.startsWith("/")) {
- full = full.substring(1);
- }
-
- full = full.trim();
-
- // Now full is like : URL,URL or URL
+ // Now full is like : URL!URL or URL
String[] urls = full.split("!");
URL bundleURL = null;
URL metadataURL = null;
if (urls.length == 1) {
// URL form
- System.out.println("Extracted URL : " + urls[0]);
bundleURL = new URL(urls[0]);
} else if (urls.length == 2) {
- // URL,URL form
+ // URL!URL form
bundleURL = new URL(urls[0]);
metadataURL = new URL(urls[1]);
} else {
throw new MalformedURLException("The iPOJO url is not formatted correctly, ipojo:bundle_url[!metadata_url] expected");
}
- File bundle = File.createTempFile("ipojo_", ".jar", m_temp);
- save(bundleURL, bundle);
+ logger.log(LOG_DEBUG, format("Extracted URL %s", url));
+
+ // Dump the referenced bundle on disk
+ File original = File.createTempFile("original-", ".jar", m_temp);
+ dump(bundleURL.openStream(), original);
+
+ JarFile jf = new JarFile(original);
+
File metadata = null;
if (metadataURL != null) {
- metadata = File.createTempFile("ipojo_", ".xml", m_temp);
- save(metadataURL, metadata);
+ metadata = File.createTempFile("ipojo-", ".xml", m_temp);
+ dump(metadataURL, metadata);
} else {
// Check that the metadata are in the jar file
- JarFile jar = new JarFile(bundle);
- metadata = findMetadata(jar);
+ metadata = findMetadata(jf);
+ }
+
+ Reporter reporter = new SystemReporter();
+ File out = File.createTempFile("ipojo-", ".jar", m_temp);
+
+ ResourceStore store = new BundleAwareJarFileResourceStore(jf, out, m_context);
+
+ CompositeMetadataProvider composite = new CompositeMetadataProvider(reporter);
+ if (metadata != null) {
+ FileMetadataProvider provider = new FileMetadataProvider(metadata, reporter);
+ composite.addMetadataProvider(provider);
}
// Pojoization
- Pojoization pojoizator = new Pojoization();
- File out = new File(m_temp, bundle.getName() + "-ipojo.jar");
+ Pojoization pojoizator = new Pojoization(createModuleProvider());
try {
- pojoizator.pojoization(bundle, out, metadata);
+ pojoizator.pojoization(store, composite, createVisitor(store, reporter));
} catch (Exception e) {
if (!pojoizator.getErrors().isEmpty()) {
- throw new IOException("Errors occurred during the manipulation : " + pojoizator.getErrors());
+ throw new IOException("Errors occurred during the manipulation : " + pojoizator.getErrors(), e);
}
e.printStackTrace();
- throw new RuntimeException(e.getMessage());
+ throw new IOException("Cannot manipulate the Url: " + url, e);
}
if (!pojoizator.getErrors().isEmpty()) {
throw new IOException("Errors occurred during the manipulation : " + pojoizator.getErrors());
}
if (!pojoizator.getWarnings().isEmpty()) {
- System.err.println("Warnings occurred during the manipulation : " + pojoizator.getWarnings());
+ logger.log(LOG_WARNING, format("Warnings occurred during the manipulation %s", pojoizator.getWarnings()));
}
- System.out.println("Manipulation done : " + out.exists());
+ logger.log(LOG_DEBUG, format("Manipulation done %s", out.exists()));
// Cleanup
- bundle.delete();
if (metadata != null) {
metadata.delete();
}
+ original.delete();
out.deleteOnExit();
+
// Returns the URL Connection
return out.toURI().toURL().openConnection();
}
- /**
- * Downloads the content pointed by the given url to
- * the given file.
- *
- * @param url the url
- * @param file the file
- * @throws java.io.IOException occurs if the content cannot be read
- * and save inside the file
- */
- private void save(URL url, File file) throws IOException {
- InputStream is = url.openStream();
- save(is, file);
+ private String removeScheme(final URL url) {
+ String full = url.toExternalForm();
+ // Remove ipojo:
+ if (full.startsWith(IPOJO_SCHEME)) {
+ full = full.substring(IPOJO_SCHEME.length());
+ }
+ // Remove '/' or '//'
+ while (full.startsWith("/")) {
+ full = full.substring(1);
+ }
+
+ return full.trim();
}
- /**
- * Saves the content of the input stream to the given file.
- *
- * @param is the input stream to read
- * @param file the file
- * @throws java.io.IOException occurs if the content cannot be read
- * and save inside the file
- */
- private void save(InputStream is, File file) throws IOException {
- FileOutputStream writer = new FileOutputStream(file);
- int cc = 0;
- do {
- int i = is.read();
- if (i == -1) {
- break;
- }
- cc++;
- writer.write(i);
- } while (true);
- System.out.println(cc + " bytes copied");
- is.close();
- writer.close();
+ private ManipulationVisitor createVisitor(ResourceStore store, Reporter reporter) {
+ ManipulatedResourcesWriter writer = new ManipulatedResourcesWriter();
+ writer.setReporter(reporter);
+ writer.setResourceStore(store);
+
+ CheckFieldConsistencyVisitor checkFieldConsistencyVisitor = new CheckFieldConsistencyVisitor(writer);
+ checkFieldConsistencyVisitor.setReporter(reporter);
+ return checkFieldConsistencyVisitor;
+ }
+
+
+ private ModuleProvider createModuleProvider() {
+ return new CompositeModuleProvider(
+ new CoreModuleProvider(),
+ new DefaultModuleProvider(m_modules)
+ );
}
/**
@@ -219,7 +287,7 @@
* </ol>
*
* @param jar the jar file
- * @return the founded file or <code>null</code> if not found.
+ * @return the found file or <code>null</code> if not found.
* @throws java.io.IOException occurs when the Jar file cannot be read.
*/
private File findMetadata(JarFile jar) throws IOException {
@@ -229,13 +297,13 @@
}
if (je == null) {
- System.out.println("Metadata file not found, use annotations only.");
+ logger.log(LOG_DEBUG, "Metadata file not found, use annotations only.");
return null; // Not Found, use annotation only
} else {
- System.out.println("Metadata file found: " + je.getName());
- File metadata = File.createTempFile("ipojo_", ".xml", m_temp);
- save(jar.getInputStream(je), metadata);
- System.out.println("Metadata file saved to " + metadata.getAbsolutePath());
+ logger.log(LOG_DEBUG, format("Metadata file found at %s", je.getName()));
+ File metadata = File.createTempFile("ipojo-", ".xml", m_temp);
+ dump(jar.getInputStream(je), metadata);
+ logger.log(LOG_DEBUG, format("Metadata file saved at %s", metadata));
return metadata;
}
diff --git a/ipojo/manipulator/online-manipulator/src/main/java/org/apache/felix/ipojo/online/manipulator/SystemLogService.java b/ipojo/manipulator/online-manipulator/src/main/java/org/apache/felix/ipojo/online/manipulator/SystemLogService.java
new file mode 100644
index 0000000..f147d84
--- /dev/null
+++ b/ipojo/manipulator/online-manipulator/src/main/java/org/apache/felix/ipojo/online/manipulator/SystemLogService.java
@@ -0,0 +1,83 @@
+/*
+ * 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.online.manipulator;
+
+import static java.lang.String.format;
+
+import java.io.PrintStream;
+
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.log.LogService;
+
+/**
+* Default implementation based on System.out
+*/
+public class SystemLogService implements LogService {
+
+ public void log(final int level, final String message) {
+ log(null, level, message, null);
+ }
+
+ public void log(final int level, final String message, final Throwable throwable) {
+ log(null, level, message, throwable);
+ }
+
+ public void log(final ServiceReference reference, final int level, final String message) {
+ log(null, level, message, null);
+ }
+
+ public void log(final ServiceReference reference, final int level, final String message, final Throwable throwable) {
+ PrintStream stream = System.out;
+ if (level >= LogService.LOG_WARNING) {
+ stream = System.err;
+ }
+
+ String formatted = format("%s %s", asString(level), message);
+
+ if (reference != null) {
+ formatted = format("[%s] %s", reference.getBundle().getSymbolicName(), formatted);
+ }
+
+ // Print the message
+ stream.println(formatted);
+ if (throwable != null) {
+ throwable.printStackTrace(stream);
+ }
+ }
+
+ private static String asString(final int level) {
+ String levelStr = "?";
+ switch (level) {
+ case LOG_DEBUG:
+ levelStr = "D";
+ break;
+ case LOG_INFO:
+ levelStr = "I";
+ break;
+ case LOG_WARNING:
+ levelStr = "W";
+ break;
+ case LOG_ERROR:
+ levelStr = "E";
+ break;
+ }
+ return levelStr;
+ }
+}
diff --git a/ipojo/manipulator/online-manipulator/src/main/resources/META-INF/services/org.apache.felix.ipojo.manipulator.spi.Module b/ipojo/manipulator/online-manipulator/src/main/resources/META-INF/services/org.apache.felix.ipojo.manipulator.spi.Module
deleted file mode 100644
index d3b15f9..0000000
--- a/ipojo/manipulator/online-manipulator/src/main/resources/META-INF/services/org.apache.felix.ipojo.manipulator.spi.Module
+++ /dev/null
@@ -1 +0,0 @@
-org.apache.felix.ipojo.manipulator.metadata.annotation.module.DefaultBindingModule
\ No newline at end of file
diff --git a/ipojo/manipulator/online-manipulator/src/main/resources/metadata.xml b/ipojo/manipulator/online-manipulator/src/main/resources/metadata.xml
deleted file mode 100644
index 771b2d5..0000000
--- a/ipojo/manipulator/online-manipulator/src/main/resources/metadata.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<!--
- 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 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="org.apache.felix.ipojo http://felix.apache.org/ipojo/schemas/CURRENT/core.xsd"
- xmlns="org.apache.felix.ipojo">
-
- <component classname="org.apache.felix.ipojo.online.manipulator.IPOJOURLHandler"
- public="false"
- immediate="true">
- <provides>
- <property name="url.handler.protocol" type="java.lang.String" value="ipojo"/>
- </provides>
- <callback transition="invalidate" method="stop"/>
- </component>
- <instance component="org.apache.felix.ipojo.online.manipulator.IPOJOURLHandler"/>
-</ipojo>
\ No newline at end of file