Fix FELIX-4040, reimplement configuration admin support
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1477027 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/ipojo/runtime/core-it/src/it/ipojo-core-configuration-admin-test/pom.xml b/ipojo/runtime/core-it/src/it/ipojo-core-configuration-admin-test/pom.xml
new file mode 100644
index 0000000..bb52beb
--- /dev/null
+++ b/ipojo/runtime/core-it/src/it/ipojo-core-configuration-admin-test/pom.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <parent>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.ipojo.runtime.core-it</artifactId>
+ <version>1.9.0-SNAPSHOT</version>
+ <relativePath>../../../pom.xml</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>ipojo-core-configuration-admin-test</artifactId>
+ <name>${project.artifactId}</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.configadmin</artifactId>
+ <version>1.2.8</version>
+ </dependency>
+ </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/ipojo/runtime/core-it/src/it/ipojo-core-configuration-admin-test/src/main/java/org/apache/felix/ipojo/runtime/core/components/ConfigurableFooProvider.java b/ipojo/runtime/core-it/src/it/ipojo-core-configuration-admin-test/src/main/java/org/apache/felix/ipojo/runtime/core/components/ConfigurableFooProvider.java
new file mode 100644
index 0000000..f0df68f
--- /dev/null
+++ b/ipojo/runtime/core-it/src/it/ipojo-core-configuration-admin-test/src/main/java/org/apache/felix/ipojo/runtime/core/components/ConfigurableFooProvider.java
@@ -0,0 +1,72 @@
+/*
+ * 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.components;
+
+import org.apache.felix.ipojo.runtime.core.services.FooService;
+
+import java.util.Properties;
+
+public class ConfigurableFooProvider implements FooService {
+
+ private String message; // Configurable property
+ private int invokeCount = 0;
+
+ public void setMessage(String message) {
+ System.err.println("=== Set message to " + message);
+ this.message = message;
+ invokeCount++;
+ }
+
+ public boolean foo() {
+ return true;
+ }
+
+ public Properties fooProps() {
+ Properties props = new Properties();
+ if (message == null) {
+ props.put("message", "NULL");
+ } else {
+ props.put("message", message);
+ }
+ props.put("count", new Integer(invokeCount));
+ return props;
+ }
+
+ public boolean getBoolean() {
+ return false;
+ }
+
+ public double getDouble() {
+ return invokeCount;
+ }
+
+ public int getInt() {
+ return invokeCount;
+ }
+
+ public long getLong() {
+ return invokeCount;
+ }
+
+ public Boolean getObject() {
+ return null;
+ }
+
+}
diff --git a/ipojo/runtime/core-it/src/it/ipojo-core-configuration-admin-test/src/main/java/org/apache/felix/ipojo/runtime/core/services/CheckService.java b/ipojo/runtime/core-it/src/it/ipojo-core-configuration-admin-test/src/main/java/org/apache/felix/ipojo/runtime/core/services/CheckService.java
new file mode 100644
index 0000000..c3d38ec
--- /dev/null
+++ b/ipojo/runtime/core-it/src/it/ipojo-core-configuration-admin-test/src/main/java/org/apache/felix/ipojo/runtime/core/services/CheckService.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.ipojo.runtime.core.services;
+
+import java.util.Properties;
+
+public interface CheckService {
+
+ public static final String foo = "foo";
+
+ public boolean check();
+
+ public Properties getProps();
+
+}
diff --git a/ipojo/runtime/core-it/src/it/ipojo-core-configuration-admin-test/src/main/java/org/apache/felix/ipojo/runtime/core/services/FooService.java b/ipojo/runtime/core-it/src/it/ipojo-core-configuration-admin-test/src/main/java/org/apache/felix/ipojo/runtime/core/services/FooService.java
new file mode 100644
index 0000000..716115f
--- /dev/null
+++ b/ipojo/runtime/core-it/src/it/ipojo-core-configuration-admin-test/src/main/java/org/apache/felix/ipojo/runtime/core/services/FooService.java
@@ -0,0 +1,39 @@
+/*
+ * 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.services;
+
+import java.util.Properties;
+
+public interface FooService {
+
+ boolean foo();
+
+ Properties fooProps();
+
+ Boolean getObject();
+
+ boolean getBoolean();
+
+ int getInt();
+
+ long getLong();
+
+ double getDouble();
+
+}
diff --git a/ipojo/runtime/core-it/src/it/ipojo-core-configuration-admin-test/src/main/resources/metadata.xml b/ipojo/runtime/core-it/src/it/ipojo-core-configuration-admin-test/src/main/resources/metadata.xml
new file mode 100644
index 0000000..6affd5b
--- /dev/null
+++ b/ipojo/runtime/core-it/src/it/ipojo-core-configuration-admin-test/src/main/resources/metadata.xml
@@ -0,0 +1,41 @@
+<!--
+ ~ 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/SNAPSHOT/core.xsd"
+ xmlns="org.apache.felix.ipojo">
+ <component classname="org.apache.felix.ipojo.runtime.core.components.ConfigurableFooProvider"
+ name="CA-ConfigurableProvider">
+ <provides/>
+ <properties>
+ <property name="message" method="setMessage"/>
+ </properties>
+ </component>
+
+ <component classname="org.apache.felix.ipojo.runtime.core.components.ConfigurableFooProvider"
+ immediate="true"
+ name="CA-ImmConfigurableProvider">
+ <provides/>
+ <properties>
+ <property name="message" method="setMessage"/>
+ </properties>
+ </component>
+
+
+</ipojo>
diff --git a/ipojo/runtime/core-it/src/it/ipojo-core-configuration-admin-test/src/test/java/org/apache/felix/ipojo/runtime/core/Common.java b/ipojo/runtime/core-it/src/it/ipojo-core-configuration-admin-test/src/test/java/org/apache/felix/ipojo/runtime/core/Common.java
new file mode 100644
index 0000000..551970a
--- /dev/null
+++ b/ipojo/runtime/core-it/src/it/ipojo-core-configuration-admin-test/src/test/java/org/apache/felix/ipojo/runtime/core/Common.java
@@ -0,0 +1,248 @@
+/*
+ * 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 ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.Logger;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.filefilter.TrueFileFilter;
+import org.apache.felix.ipojo.runtime.core.components.*;
+import org.apache.felix.ipojo.runtime.core.services.CheckService;
+import org.apache.felix.ipojo.runtime.core.services.FooService;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+import org.ops4j.pax.exam.options.CompositeOption;
+import org.ops4j.pax.exam.options.DefaultCompositeOption;
+import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
+import org.ops4j.pax.exam.spi.reactors.PerClass;
+import org.ops4j.pax.tinybundles.core.TinyBundle;
+import org.ops4j.pax.tinybundles.core.TinyBundles;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+import org.ow2.chameleon.testing.helpers.IPOJOHelper;
+import org.ow2.chameleon.testing.helpers.OSGiHelper;
+import org.ow2.chameleon.testing.tinybundles.ipojo.IPOJOStrategy;
+import org.slf4j.LoggerFactory;
+
+import javax.inject.Inject;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import static org.ops4j.pax.exam.CoreOptions.*;
+
+/**
+ * Bootstrap the test from this project
+ */
+@RunWith(PaxExam.class)
+@ExamReactorStrategy(PerClass.class)
+public class Common {
+
+ public static long UPDATE_WAIT_TIME = 2000;
+
+ @Inject
+ BundleContext bc;
+
+ OSGiHelper osgiHelper;
+ IPOJOHelper ipojoHelper;
+
+ @Configuration
+ public Option[] config() throws MalformedURLException {
+ Logger root = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
+ root.setLevel(Level.INFO);
+
+ return options(
+ ipojoBundles(),
+ junitBundles(),
+ testedBundle(),
+ systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value("WARN")
+ );
+ }
+
+ @Before
+ public void commonSetUp() {
+ osgiHelper = new OSGiHelper(bc);
+ ipojoHelper = new IPOJOHelper(bc);
+
+ // Dump OSGi Framework information
+ String vendor = (String) osgiHelper.getBundle(0).getHeaders().get(Constants.BUNDLE_VENDOR);
+ if (vendor == null) {
+ vendor = (String) osgiHelper.getBundle(0).getHeaders().get(Constants.BUNDLE_SYMBOLICNAME);
+ }
+ String version = (String) osgiHelper.getBundle(0).getHeaders().get(Constants.BUNDLE_VERSION);
+ System.out.println("OSGi Framework : " + vendor + " - " + version);
+
+ waitForStability(bc);
+ }
+
+ public Bundle getTestBundle() {
+ return osgiHelper.getBundle("test.bundle");
+ }
+
+ @After
+ public void commonTearDown() {
+ ipojoHelper.dispose();
+ osgiHelper.dispose();
+ }
+
+ public CompositeOption ipojoBundles() {
+ return new DefaultCompositeOption(
+ mavenBundle("org.apache.felix", "org.apache.felix.ipojo").versionAsInProject(),
+ mavenBundle("org.ow2.chameleon.testing", "osgi-helpers").versionAsInProject(),
+ mavenBundle("org.apache.felix", "org.apache.felix.configadmin").versionAsInProject());
+ }
+
+ public Option testedBundle() throws MalformedURLException {
+ File out = new File("target/tested/bundle.jar");
+
+ TinyBundle tested = TinyBundles.bundle();
+
+ // We look inside target/classes to find the class and resources
+ File classes = new File("target/classes");
+ Collection<File> files = FileUtils.listFilesAndDirs(classes, TrueFileFilter.INSTANCE, TrueFileFilter.INSTANCE);
+ List<File> services = new ArrayList<File>();
+ for (File file : files) {
+ if (file.isDirectory()) {
+ // By convention we export of .services and .service package
+ if (file.getName().endsWith("services") || file.getName().endsWith("service")) {
+ services.add(file);
+ }
+ } else {
+ // We need to compute the path
+ String path = file.getAbsolutePath().substring(classes.getAbsolutePath().length() +1);
+ tested.add(path, file.toURI().toURL());
+ System.out.println(file.getName() + " added to " + path);
+ }
+ }
+
+ String export = "";
+ for (File file : services) {
+ if (export.length() > 0) { export += ", "; }
+ String path = file.getAbsolutePath().substring(classes.getAbsolutePath().length() +1);
+ String packageName = path.replace('/', '.');
+ export += packageName;
+ }
+
+ System.out.println("Exported packages : " + export);
+
+ InputStream inputStream = tested
+ .set(Constants.BUNDLE_SYMBOLICNAME, "test.bundle")
+ .set(Constants.IMPORT_PACKAGE, "*")
+ .set(Constants.EXPORT_PACKAGE, export)
+ .build(IPOJOStrategy.withiPOJO(new File("src/main/resources")));
+
+ try {
+ org.apache.commons.io.FileUtils.copyInputStreamToFile(inputStream, out);
+ return bundle(out.toURI().toURL().toExternalForm());
+ } catch (MalformedURLException e) {
+ throw new RuntimeException("Cannot compute the url of the manipulated bundle");
+ } catch (IOException e) {
+ throw new RuntimeException("Cannot write of the manipulated bundle");
+ }
+ }
+
+ /**
+ * Waits for stability:
+ * <ul>
+ * <li>all bundles are activated
+ * <li>service count is stable
+ * </ul>
+ * If the stability can't be reached after a specified time,
+ * the method throws a {@link IllegalStateException}.
+ *
+ * @param context the bundle context
+ * @throws IllegalStateException when the stability can't be reach after a several attempts.
+ */
+ private void waitForStability(BundleContext context) throws IllegalStateException {
+ // Wait for bundle initialization.
+ boolean bundleStability = getBundleStability(context);
+ int count = 0;
+ while (!bundleStability && count < 500) {
+ try {
+ Thread.sleep(5);
+ } catch (InterruptedException e) {
+ // Interrupted
+ }
+ count++;
+ bundleStability = getBundleStability(context);
+ }
+
+ if (count == 500) {
+ System.err.println("Bundle stability isn't reached after 500 tries");
+ throw new IllegalStateException("Cannot reach the bundle stability");
+ }
+
+ boolean serviceStability = false;
+ count = 0;
+ int count1 = 0;
+ int count2 = 0;
+ while (!serviceStability && count < 500) {
+ try {
+ ServiceReference[] refs = context.getServiceReferences((String) null, null);
+ count1 = refs.length;
+ Thread.sleep(500);
+ refs = context.getServiceReferences((String) null, null);
+ count2 = refs.length;
+ serviceStability = count1 == count2;
+ } catch (Exception e) {
+ System.err.println(e);
+ serviceStability = false;
+ // Nothing to do, while recheck the condition
+ }
+ count++;
+ }
+
+ if (count == 500) {
+ System.err.println("Service stability isn't reached after 500 tries (" + count1 + " != " + count2);
+ throw new IllegalStateException("Cannot reach the service stability");
+ }
+ }
+
+ /**
+ * Are bundle stables.
+ *
+ * @param bc the bundle context
+ * @return <code>true</code> if every bundles are activated.
+ */
+ private boolean getBundleStability(BundleContext bc) {
+ boolean stability = true;
+ Bundle[] bundles = bc.getBundles();
+ for (Bundle bundle : bundles) {
+ stability = stability && (bundle.getState() == Bundle.ACTIVE);
+ }
+ return stability;
+ }
+
+ public boolean isKF() {
+ return bc.getClass().toString().contains("knopflerfish");
+ }
+
+
+}
diff --git a/ipojo/runtime/core-it/src/it/ipojo-core-configuration-admin-test/src/test/java/org/apache/felix/ipojo/runtime/core/ConfigurationMonitor.java b/ipojo/runtime/core-it/src/it/ipojo-core-configuration-admin-test/src/test/java/org/apache/felix/ipojo/runtime/core/ConfigurationMonitor.java
new file mode 100644
index 0000000..8f761cb
--- /dev/null
+++ b/ipojo/runtime/core-it/src/it/ipojo-core-configuration-admin-test/src/test/java/org/apache/felix/ipojo/runtime/core/ConfigurationMonitor.java
@@ -0,0 +1,74 @@
+/*
+ * 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.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.cm.ConfigurationEvent;
+import org.osgi.service.cm.ConfigurationListener;
+
+public class ConfigurationMonitor implements ConfigurationListener {
+
+ private String waitForEvent;
+ private boolean detected;
+ private ServiceRegistration reg;
+
+ public synchronized void configurationEvent(ConfigurationEvent arg0) {
+ System.out.println(arg0.getPid() + " reconfiguration received");
+ if (waitForEvent != null) {
+ if (arg0.getPid().equals(waitForEvent)) {
+ this.detected = true;
+ }
+ }
+ }
+
+ public ConfigurationMonitor(BundleContext bc) {
+ reg = bc.registerService(ConfigurationListener.class.getName(), this, null);
+ }
+
+ public void stop() {
+ reg.unregister();
+ reg = null;
+ }
+
+ public void waitForEvent(String pid, String mes) {
+ waitForEvent = pid;
+ detected = false;
+ long begin = System.currentTimeMillis();
+ long duration = 0;
+ while( ! this.detected) {
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException e) {
+ // Interrupted
+ }
+ long end = System.currentTimeMillis();
+ duration = end - begin;
+ if (duration > 10000) {
+ Assert.fail(mes + " -> Timeout when waiting for a reconfiguration of " + pid);
+ }
+ }
+ System.out.println("Reconfiguration detected of " + pid);
+ waitForEvent = null;
+ detected = false;
+ }
+
+}
diff --git a/ipojo/runtime/core-it/src/it/ipojo-core-configuration-admin-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestManagedServiceFactoryTestForImmediate.java b/ipojo/runtime/core-it/src/it/ipojo-core-configuration-admin-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestManagedServiceFactoryTestForImmediate.java
new file mode 100644
index 0000000..72097b1
--- /dev/null
+++ b/ipojo/runtime/core-it/src/it/ipojo-core-configuration-admin-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestManagedServiceFactoryTestForImmediate.java
@@ -0,0 +1,404 @@
+/*
+ * 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 org.apache.felix.ipojo.ComponentFactory;
+import org.apache.felix.ipojo.PrimitiveInstanceDescription;
+import org.apache.felix.ipojo.architecture.Architecture;
+import org.apache.felix.ipojo.runtime.core.services.FooService;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+import java.io.IOException;
+import java.util.Dictionary;
+import java.util.Properties;
+
+import static junit.framework.Assert.assertEquals;
+import static org.junit.Assert.*;
+
+public class TestManagedServiceFactoryTestForImmediate extends Common {
+
+ private ComponentFactory factory;
+ private ConfigurationAdmin admin;
+
+ @Before
+ public void setUp() {
+ factory = (ComponentFactory) ipojoHelper.getFactory("CA-ImmConfigurableProvider");
+ admin = (ConfigurationAdmin) osgiHelper.getServiceObject(ConfigurationAdmin.class.getName(), null);
+ assertNotNull("Check configuration admin availability", admin);
+ try {
+ Configuration[] configurations = admin.listConfigurations("(service.factoryPid=CA-ImmConfigurableProvider)");
+ for (int i = 0; configurations != null && i < configurations.length; i++) {
+ configurations[i].delete();
+ }
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (InvalidSyntaxException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ @After
+ public void tearDown() {
+ try {
+ Configuration[] configurations = admin.listConfigurations("(service.factoryPid=CA-ImmConfigurableProvider)");
+ for (int i = 0; configurations != null && i < configurations.length; i++) {
+ configurations[i].delete();
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (InvalidSyntaxException e) {
+ e.printStackTrace();
+ }
+ admin = null;
+
+
+ }
+
+ @Test
+ public void testCreationAndReconfiguration() {
+ Configuration configuration = null;
+ try {
+ configuration = admin.createFactoryConfiguration("CA-ImmConfigurableProvider", "?");
+ } catch (IOException e) {
+ fail(e.getMessage());
+ }
+ Dictionary props = configuration.getProperties();
+ if (props == null) {
+ props = new Properties();
+ }
+ props.put("message", "message");
+
+ try {
+ configuration.update(props);
+ } catch (IOException e) {
+ fail(e.getMessage());
+ }
+
+ String pid = configuration.getPid();
+
+ // Wait for the processing of the first configuration.
+ try {
+ Thread.sleep(UPDATE_WAIT_TIME);
+ } catch (InterruptedException e1) {
+ fail(e1.getMessage());
+ }
+
+ // The instance should be created, wait for the architecture service
+ osgiHelper.waitForService(Architecture.class.getName(), "(architecture.instance=" + pid + ")", 1000);
+ Architecture architecture = (Architecture) osgiHelper.getServiceObject(Architecture.class.getName(), "(architecture.instance=" + pid + ")");
+
+ assertEquals("Check object", 1, ((PrimitiveInstanceDescription) architecture.getInstanceDescription()).getCreatedObjects().length);
+
+ FooService fs = (FooService) osgiHelper.getServiceObject(FooService.class.getName(), "(instance.name=" + pid + ")");
+ Properties p = fs.fooProps();
+ String mes = p.getProperty("message");
+ int count = (Integer) p.get("count");
+ //architecture = (Architecture) osgiHelper.getServiceObject( Architecture.class.getName(), "(architecture.instance="+pid+")");
+
+ assertEquals("Assert Message", "message", mes);
+ assertEquals("Assert count", 1, count);
+ assertEquals("Check 1 object", 1, ((PrimitiveInstanceDescription) architecture.getInstanceDescription()).getCreatedObjects().length);
+
+ props.put("message", "message2");
+ try {
+ configuration.update(props);
+ // Update the configuration ...
+ Thread.sleep(UPDATE_WAIT_TIME);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ fs = (FooService) osgiHelper.getServiceObject(FooService.class.getName(), "(instance.name=" + pid + ")");
+ p = fs.fooProps();
+ mes = p.getProperty("message");
+ count = (Integer) p.get("count");
+ //architecture = (Architecture) osgiHelper.getServiceObject( Architecture.class.getName(), "(architecture.instance="+pid+")");
+
+ assertEquals("Assert Message", "message2", mes);
+ assertEquals("Assert count", 2, count);
+ assertEquals("Check 1 object", 1, ((PrimitiveInstanceDescription) architecture.getInstanceDescription()).getCreatedObjects().length);
+
+ try {
+ configuration.delete();
+ Thread.sleep(UPDATE_WAIT_TIME);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ ServiceReference ref = osgiHelper.getServiceReference(FooService.class.getName(), "(instance.name=" + pid + ")");
+ assertNull("Check unavailability", ref);
+ }
+
+ @Test
+ public void testCreationAndReconfiguration2() {
+ //The reconfiguration happens before the service invocation
+ Configuration configuration = null;
+ try {
+ configuration = admin.createFactoryConfiguration("CA-ImmConfigurableProvider", "?");
+ } catch (IOException e) {
+ fail(e.getMessage());
+ }
+ Dictionary props = configuration.getProperties();
+ if (props == null) {
+ props = new Properties();
+ }
+ props.put("message", "message");
+
+ try {
+ configuration.update(props);
+ } catch (IOException e) {
+ fail(e.getMessage());
+ }
+
+ String pid = configuration.getPid();
+ System.out.println("PID : " + pid);
+
+ // Wait for the processing of the first configuration.
+ try {
+ Thread.sleep(UPDATE_WAIT_TIME);
+ } catch (InterruptedException e1) {
+ fail(e1.getMessage());
+ }
+
+ // The instance should be created, wait for the architecture service
+ osgiHelper.waitForService(Architecture.class.getName(), "(architecture.instance=" + pid + ")", 1000);
+ Architecture architecture = (Architecture) osgiHelper.getServiceObject(Architecture.class.getName(), "(architecture.instance=" + pid + ")");
+
+ assertEquals("Check object", 1, ((PrimitiveInstanceDescription) architecture.getInstanceDescription()).getCreatedObjects().length);
+
+ props.put("message", "message2");
+ try {
+ configuration.update(props);
+ // Update the configuration ...
+ Thread.sleep(UPDATE_WAIT_TIME);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ //architecture = (Architecture) osgiHelper.getServiceObject( Architecture.class.getName(), "(architecture.instance="+pid+")");
+
+ assertEquals("Check object -2", 1, ((PrimitiveInstanceDescription) architecture.getInstanceDescription()).getCreatedObjects().length);
+
+ //Invoke
+ FooService fs = (FooService) osgiHelper.getServiceObject(FooService.class.getName(), "(instance.name=" + pid + ")");
+ Properties p = fs.fooProps();
+ String mes = p.getProperty("message");
+ int count = ((Integer) p.get("count")).intValue();
+ // architecture = (Architecture) osgiHelper.getServiceObject( Architecture.class.getName(), "(architecture.instance="+pid+")");
+
+ assertEquals("Assert Message", "message2", mes);
+ assertEquals("Assert count", 2, count);
+ assertEquals("Check 1 object", 1, ((PrimitiveInstanceDescription) architecture.getInstanceDescription()).getCreatedObjects().length);
+
+ try {
+ configuration.delete();
+ Thread.sleep(UPDATE_WAIT_TIME);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ ServiceReference ref = osgiHelper.getServiceReference(FooService.class.getName(), "(instance.name=" + pid + ")");
+ assertNull("Check unavailability", ref);
+ }
+
+ @Test
+ public void testDelayedCreationAndReconfiguration() {
+ factory.stop();
+ Configuration configuration = null;
+ try {
+ configuration = admin.createFactoryConfiguration("CA-ImmConfigurableProvider", "?");
+ } catch (IOException e) {
+ fail(e.getMessage());
+ }
+ Dictionary props = configuration.getProperties();
+ if (props == null) {
+ props = new Properties();
+ }
+ props.put("message", "message");
+
+ try {
+ configuration.update(props);
+ } catch (IOException e) {
+ fail(e.getMessage());
+ }
+
+ String pid = configuration.getPid();
+
+ // Wait for the processing of the first configuration.
+ try {
+ Thread.sleep(UPDATE_WAIT_TIME);
+ } catch (InterruptedException e1) {
+ fail(e1.getMessage());
+ }
+
+ assertNull("check no instance", osgiHelper.getServiceObject(Architecture.class.getName(), "(architecture.instance=" + pid + ")"));
+
+ factory.start();
+
+
+ // Wait for the processing of the first configuration.
+ try {
+ Thread.sleep(UPDATE_WAIT_TIME);
+ } catch (InterruptedException e1) {
+ fail(e1.getMessage());
+ }
+
+
+ // The instance should be created, wait for the architecture service
+ osgiHelper.waitForService(Architecture.class.getName(), "(architecture.instance=" + pid + ")", 1000);
+ Architecture architecture = (Architecture) osgiHelper.getServiceObject(Architecture.class.getName(), "(architecture.instance=" + pid + ")");
+
+ assertEquals("Check object", 1, ((PrimitiveInstanceDescription) architecture.getInstanceDescription()).getCreatedObjects().length);
+
+ FooService fs = (FooService) osgiHelper.getServiceObject(FooService.class.getName(), "(instance.name=" + pid + ")");
+ Properties p = fs.fooProps();
+ String mes = p.getProperty("message");
+ int count = (Integer) p.get("count");
+ //architecture = (Architecture) osgiHelper.getServiceObject( Architecture.class.getName(), "(architecture.instance="+pid+")");
+
+ assertEquals("Assert Message", "message", mes);
+ assertEquals("Assert count", 1, count);
+ assertEquals("Check 1 object", 1, ((PrimitiveInstanceDescription) architecture.getInstanceDescription()).getCreatedObjects().length);
+
+ props.put("message", "message2");
+ try {
+ configuration.update(props);
+ // Update the configuration ...
+ Thread.sleep(UPDATE_WAIT_TIME);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ fs = (FooService) osgiHelper.getServiceObject(FooService.class.getName(), "(instance.name=" + pid + ")");
+ p = fs.fooProps();
+ mes = p.getProperty("message");
+ count = (Integer) p.get("count");
+ // architecture = (Architecture) osgiHelper.getServiceObject( Architecture.class.getName(), "(architecture.instance="+pid+")");
+
+ assertEquals("Assert Message", "message2", mes);
+ //assertEquals("Assert count", 2, count);
+ // This test was removed as the result can be 3.
+ assertEquals("Check 1 object", 1, ((PrimitiveInstanceDescription) architecture.getInstanceDescription()).getCreatedObjects().length);
+
+ try {
+ configuration.delete();
+ Thread.sleep(UPDATE_WAIT_TIME);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ ServiceReference ref = osgiHelper.getServiceReference(FooService.class.getName(), "(instance.name=" + pid + ")");
+ assertNull("Check unavailability", ref);
+ }
+
+ @Test
+ public void testDelayedCreationAndReconfiguration2() {
+ factory.stop();
+ //The reconfiguration happens before the service invocation
+ Configuration configuration = null;
+ try {
+ configuration = admin.createFactoryConfiguration("CA-ImmConfigurableProvider", "?");
+ } catch (IOException e) {
+ fail(e.getMessage());
+ }
+ Dictionary props = configuration.getProperties();
+ if (props == null) {
+ props = new Properties();
+ }
+ props.put("message", "message");
+
+ try {
+ configuration.update(props);
+ } catch (IOException e) {
+ fail(e.getMessage());
+ }
+
+ String pid = configuration.getPid();
+
+ // Wait for the processing of the first configuration.
+ try {
+ Thread.sleep(UPDATE_WAIT_TIME);
+ } catch (InterruptedException e1) {
+ fail(e1.getMessage());
+ }
+
+ assertNull("check no instance", osgiHelper.getServiceObject(Architecture.class.getName(), "(architecture.instance=" + pid + ")"));
+
+ factory.start();
+
+ // Wait for the processing of the first configuration.
+ try {
+ Thread.sleep(UPDATE_WAIT_TIME);
+ } catch (InterruptedException e1) {
+ fail(e1.getMessage());
+ }
+
+
+ // The instance should be created, wait for the architecture service
+ osgiHelper.waitForService(Architecture.class.getName(), "(architecture.instance=" + pid + ")", 1000);
+ Architecture architecture = (Architecture) osgiHelper.getServiceObject(Architecture.class.getName(), "(architecture.instance=" + pid + ")");
+
+ assertEquals("Check object", 1, ((PrimitiveInstanceDescription) architecture.getInstanceDescription()).getCreatedObjects().length);
+
+ props.put("message", "message2");
+ try {
+ configuration.update(props);
+ // Update the configuration ...
+ Thread.sleep(UPDATE_WAIT_TIME);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ //architecture = (Architecture) osgiHelper.getServiceObject( Architecture.class.getName(), "(architecture.instance="+pid+")");
+
+ assertEquals("Check object -1", 1, ((PrimitiveInstanceDescription) architecture.getInstanceDescription()).getCreatedObjects().length);
+
+ //Invoke
+ FooService fs = (FooService) osgiHelper.getServiceObject(FooService.class.getName(), "(instance.name=" + pid + ")");
+ Properties p = fs.fooProps();
+ String mes = p.getProperty("message");
+ int count = (Integer) p.get("count");
+ // architecture = (Architecture) osgiHelper.getServiceObject( Architecture.class.getName(), "(architecture.instance="+pid+")");
+
+ assertEquals("Assert Message", "message2", mes);
+ assertEquals("Assert count", 2, count);
+ assertEquals("Check 1 object", 1, ((PrimitiveInstanceDescription) architecture.getInstanceDescription()).getCreatedObjects().length);
+
+ try {
+ configuration.delete();
+ Thread.sleep(UPDATE_WAIT_TIME);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ ServiceReference ref = osgiHelper.getServiceReference(FooService.class.getName(), "(instance.name=" + pid + ")");
+ assertNull("Check unavailability", ref);
+ }
+
+
+}
diff --git a/ipojo/runtime/core-it/src/it/ipojo-core-configuration-admin-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestManagedServiceFactoryTestForServices.java b/ipojo/runtime/core-it/src/it/ipojo-core-configuration-admin-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestManagedServiceFactoryTestForServices.java
new file mode 100644
index 0000000..b2cb1c5
--- /dev/null
+++ b/ipojo/runtime/core-it/src/it/ipojo-core-configuration-admin-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestManagedServiceFactoryTestForServices.java
@@ -0,0 +1,406 @@
+/*
+ * 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 org.apache.felix.ipojo.ComponentFactory;
+import org.apache.felix.ipojo.PrimitiveInstanceDescription;
+import org.apache.felix.ipojo.architecture.Architecture;
+import org.apache.felix.ipojo.runtime.core.services.FooService;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+import java.io.IOException;
+import java.util.Dictionary;
+import java.util.Properties;
+
+import static junit.framework.Assert.assertEquals;
+import static org.junit.Assert.*;
+
+public class TestManagedServiceFactoryTestForServices extends Common {
+
+ private ComponentFactory factory;
+ private ConfigurationAdmin admin;
+
+ @Before
+ public void setUp() {
+ factory = (ComponentFactory) ipojoHelper.getFactory("CA-ConfigurableProvider");
+ admin = (ConfigurationAdmin) osgiHelper.getServiceObject(ConfigurationAdmin.class.getName(), null);
+ assertNotNull("Check configuration admin availability", admin);
+ try {
+ Configuration[] configurations = admin.listConfigurations("(service.factoryPid=CA-ConfigurableProvider)");
+ for (int i = 0; configurations != null && i < configurations.length; i++) {
+ configurations[i].delete();
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (InvalidSyntaxException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @After
+ public void tearDown() {
+ try {
+ Configuration[] configurations = admin.listConfigurations("(service.factoryPid=CA-ConfigurableProvider)");
+ for (int i = 0; configurations != null && i < configurations.length; i++) {
+ configurations[i].delete();
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (InvalidSyntaxException e) {
+ e.printStackTrace();
+ }
+ admin = null;
+
+
+ }
+
+ @Test
+ public void testMSFCreationAndReconfiguration() {
+ Configuration configuration = null;
+ try {
+ configuration = admin.createFactoryConfiguration("CA-ConfigurableProvider", "?");
+ } catch (IOException e) {
+ fail(e.getMessage());
+ }
+ Dictionary props = configuration.getProperties();
+ if (props == null) {
+ props = new Properties();
+ }
+ props.put("message", "message");
+
+ try {
+ configuration.update(props);
+ } catch (IOException e) {
+ fail(e.getMessage());
+ }
+
+ String pid = configuration.getPid();
+ System.out.println("PID : " + pid);
+
+ // The instance should be created, wait for the architecture service
+ osgiHelper.waitForService(Architecture.class.getName(), "(architecture.instance=" + pid + ")", 1000);
+ Architecture architecture = (Architecture) osgiHelper.getServiceObject(Architecture.class.getName(), "(architecture.instance=" + pid + ")");
+
+ assertEquals("Check no object", 0, ((PrimitiveInstanceDescription) architecture.getInstanceDescription()).getCreatedObjects().length);
+
+ osgiHelper.waitForService(FooService.class.getName(), "(instance.name=" + pid + ")", 1000);
+
+ ServiceReference refx = osgiHelper.getServiceReference(FooService.class.getName(), "(instance.name=" + pid + ")");
+ assertNotNull("Check refx", refx);
+ FooService fs = (FooService) osgiHelper.getServiceObject(FooService.class.getName(), "(instance.name=" + pid + ")");
+ assertNotNull("Check fs", fs);
+
+ Properties p = fs.fooProps();
+ String mes = p.getProperty("message");
+ int count = (Integer) p.get("count");
+ //architecture = (Architecture) osgiHelper.getServiceObject( Architecture.class.getName(), "(architecture.instance="+pid+")");
+
+ assertEquals("Assert Message", "message", mes);
+ assertEquals("Assert count", 1, count);
+ assertEquals("Check 1 object", 1, ((PrimitiveInstanceDescription) architecture.getInstanceDescription()).getCreatedObjects().length);
+
+
+ // Wait for the processing of the first configuration.
+ try {
+ Thread.sleep(UPDATE_WAIT_TIME);
+ } catch (InterruptedException e1) {
+ fail(e1.getMessage());
+ }
+
+
+ Dictionary p2 = configuration.getProperties();
+ p2.put("message", "message2");
+ try {
+ System.err.println("The configuration will be updated with message2");
+
+ configuration.update(p2);
+ // Update the configuration ...
+ Thread.sleep(UPDATE_WAIT_TIME);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ System.err.println("The configuration should be updated with message2");
+
+ fs = (FooService) osgiHelper.getServiceObject(FooService.class.getName(), "(instance.name=" + pid + ")");
+ p = fs.fooProps();
+ mes = p.getProperty("message");
+ count = (Integer) p.get("count");
+ //architecture = (Architecture) osgiHelper.getServiceObject( Architecture.class.getName(), "(architecture.instance="+pid+")");
+
+ assertEquals("Assert Message", "message2", mes);
+ assertEquals("Assert count", 2, count);
+ assertEquals("Check 1 object", 1, ((PrimitiveInstanceDescription) architecture.getInstanceDescription()).getCreatedObjects().length);
+
+ try {
+ configuration.delete();
+ Thread.sleep(UPDATE_WAIT_TIME);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ ServiceReference ref = osgiHelper.getServiceReference(FooService.class.getName(), "(instance.name=" + pid + ")");
+ assertNull("Check unavailability", ref);
+ }
+
+ @Test
+ public void testMSFCreationAndReconfiguration2() {
+ //The reconfiguration happens before the service invocation
+ Configuration configuration = null;
+ try {
+ configuration = admin.createFactoryConfiguration("CA-ConfigurableProvider", "?");
+ } catch (IOException e) {
+ fail(e.getMessage());
+ }
+ Dictionary props = configuration.getProperties();
+ if (props == null) {
+ props = new Properties();
+ }
+ props.put("message", "message");
+
+ try {
+ configuration.update(props);
+ } catch (IOException e) {
+ fail(e.getMessage());
+ }
+
+ String pid = configuration.getPid();
+
+ // The instance should be created, wait for the architecture service
+ osgiHelper.waitForService(Architecture.class.getName(), "(architecture.instance=" + pid + ")", 1000);
+ Architecture architecture = (Architecture) osgiHelper.getServiceObject(Architecture.class.getName(), "(architecture.instance=" + pid + ")");
+
+ assertEquals("Check no object", 0, ((PrimitiveInstanceDescription) architecture.getInstanceDescription()).getCreatedObjects().length);
+
+ // Wait for the processing of the first configuration.
+ try {
+ Thread.sleep(UPDATE_WAIT_TIME);
+ } catch (InterruptedException e1) {
+ fail(e1.getMessage());
+ }
+
+ props.put("message", "message2");
+ try {
+ configuration.update(props);
+ // Update the configuration ...
+ Thread.sleep(UPDATE_WAIT_TIME);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ // architecture = (Architecture) osgiHelper.getServiceObject( Architecture.class.getName(), "(architecture.instance="+pid+")");
+
+ assertEquals("Check no object -2", 0, ((PrimitiveInstanceDescription) architecture.getInstanceDescription()).getCreatedObjects().length);
+
+ //Invoke
+ FooService fs = (FooService) osgiHelper.getServiceObject(FooService.class.getName(), "(instance.name=" + pid + ")");
+ Properties p = fs.fooProps();
+ String mes = p.getProperty("message");
+ int count = (Integer) p.get("count");
+ //architecture = (Architecture) osgiHelper.getServiceObject( Architecture.class.getName(), "(architecture.instance="+pid+")");
+
+ assertEquals("Assert Message", "message2", mes);
+ assertEquals("Assert count", 1, count);
+ assertEquals("Check 1 object", 1, ((PrimitiveInstanceDescription) architecture.getInstanceDescription()).getCreatedObjects().length);
+
+ try {
+ configuration.delete();
+ Thread.sleep(UPDATE_WAIT_TIME);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ ServiceReference ref = osgiHelper.getServiceReference(FooService.class.getName(), "(instance.name=" + pid + ")");
+ assertNull("Check unavailability", ref);
+ }
+
+ @Test
+ public void testDelayedCreationAndReconfiguration() {
+ factory.stop();
+ Configuration configuration = null;
+ try {
+ configuration = admin.createFactoryConfiguration("CA-ConfigurableProvider", "?");
+ } catch (IOException e) {
+ fail(e.getMessage());
+ }
+ Dictionary props = configuration.getProperties();
+ if (props == null) {
+ props = new Properties();
+ }
+ props.put("message", "message");
+
+ try {
+ configuration.update(props);
+ } catch (IOException e) {
+ fail(e.getMessage());
+ }
+
+ String pid = configuration.getPid();
+
+ assertNull("check no instance", osgiHelper.getServiceObject(Architecture.class.getName(), "(architecture.instance=" + pid + ")"));
+
+ factory.start();
+
+
+ // The instance should be created, wait for the architecture service
+ osgiHelper.waitForService(Architecture.class.getName(), "(architecture.instance=" + pid + ")", 1000);
+ Architecture architecture = (Architecture) osgiHelper.getServiceObject(Architecture.class.getName(), "(architecture.instance=" + pid + ")");
+
+ assertEquals("Check no object", 0, ((PrimitiveInstanceDescription) architecture.getInstanceDescription()).getCreatedObjects().length);
+
+ osgiHelper.waitForService(FooService.class.getName(), "(instance.name=" + pid + ")", 1000);
+ FooService fs = (FooService) osgiHelper.getServiceObject(FooService.class.getName(), "(instance.name=" + pid + ")");
+
+ Properties p = fs.fooProps();
+ String mes = p.getProperty("message");
+ int count = (Integer) p.get("count");
+ // architecture = (Architecture) osgiHelper.getServiceObject( Architecture.class.getName(), "(architecture.instance="+pid+")");
+
+ assertEquals("Assert Message", "message", mes);
+ assertEquals("Assert count", 1, count);
+ assertEquals("Check 1 object", 1, ((PrimitiveInstanceDescription) architecture.getInstanceDescription()).getCreatedObjects().length);
+
+ // Wait for the processing of the first configuration.
+ try {
+ Thread.sleep(UPDATE_WAIT_TIME);
+ } catch (InterruptedException e1) {
+ fail(e1.getMessage());
+ }
+
+ System.out.println("===");
+
+ props.put("message", "message2");
+ try {
+ configuration.update(props);
+ // Update the configuration ...
+ Thread.sleep(UPDATE_WAIT_TIME);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ System.out.println("===");
+
+ fs = (FooService) osgiHelper.getServiceObject(FooService.class.getName(), "(instance.name=" + pid + ")");
+ p = fs.fooProps();
+ mes = p.getProperty("message");
+ count = (Integer) p.get("count");
+ // architecture = (Architecture) osgiHelper.getServiceObject( Architecture.class.getName(), "(architecture.instance="+pid+")");
+
+ assertEquals("Assert Message", "message2", mes);
+ assertEquals("Assert count", 2, count);
+ assertEquals("Check 1 object", 1, ((PrimitiveInstanceDescription) architecture.getInstanceDescription()).getCreatedObjects().length);
+
+ try {
+ configuration.delete();
+ Thread.sleep(UPDATE_WAIT_TIME);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ ServiceReference ref = osgiHelper.getServiceReference(FooService.class.getName(), "(instance.name=" + pid + ")");
+ assertNull("Check unavailability", ref);
+ }
+
+ @Test
+ public void testDelayedCreationAndReconfiguration2() {
+ factory.stop();
+ //The reconfiguration happens before the service invocation
+ Configuration configuration = null;
+ try {
+ configuration = admin.createFactoryConfiguration("CA-ConfigurableProvider", "?");
+ } catch (IOException e) {
+ fail(e.getMessage());
+ }
+ Dictionary props = configuration.getProperties();
+ if (props == null) {
+ props = new Properties();
+ }
+ props.put("message", "message");
+
+ try {
+ configuration.update(props);
+ } catch (IOException e) {
+ fail(e.getMessage());
+ }
+
+ String pid = configuration.getPid();
+ System.out.println("PID : " + pid);
+
+ assertNull("check no instance", osgiHelper.getServiceObject(Architecture.class.getName(), "(architecture.instance=" + pid + ")"));
+
+ factory.start();
+
+
+ // The instance should be created, wait for the architecture service
+ osgiHelper.waitForService(Architecture.class.getName(), "(architecture.instance=" + pid + ")", 1000);
+ Architecture architecture = (Architecture) osgiHelper.getServiceObject(Architecture.class.getName(), "(architecture.instance=" + pid + ")");
+
+ assertEquals("Check no object", 0, ((PrimitiveInstanceDescription) architecture.getInstanceDescription()).getCreatedObjects().length);
+
+ // Wait for the processing of the first configuration.
+ try {
+ Thread.sleep(UPDATE_WAIT_TIME);
+ } catch (InterruptedException e1) {
+ fail(e1.getMessage());
+ }
+
+ props.put("message", "message2");
+ try {
+ configuration.update(props);
+ // Update the configuration ...
+ Thread.sleep(UPDATE_WAIT_TIME);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ //architecture = (Architecture) osgiHelper.getServiceObject( Architecture.class.getName(), "(architecture.instance="+pid+")");
+
+ assertEquals("Check no object -2", 0, ((PrimitiveInstanceDescription) architecture.getInstanceDescription()).getCreatedObjects().length);
+
+ //Invoke
+ FooService fs = (FooService) osgiHelper.getServiceObject(FooService.class.getName(), "(instance.name=" + pid + ")");
+ Properties p = fs.fooProps();
+ String mes = p.getProperty("message");
+ int count = (Integer) p.get("count");
+ // architecture = (Architecture) osgiHelper.getServiceObject( Architecture.class.getName(), "(architecture.instance="+pid+")");
+
+ assertEquals("Assert Message", "message2", mes);
+ assertEquals("Assert count", 1, count);
+ assertEquals("Check 1 object", 1, ((PrimitiveInstanceDescription) architecture.getInstanceDescription()).getCreatedObjects().length);
+
+ try {
+ configuration.delete();
+ Thread.sleep(UPDATE_WAIT_TIME);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ ServiceReference ref = osgiHelper.getServiceReference(FooService.class.getName(), "(instance.name=" + pid + ")");
+ assertNull("Check unavailability", ref);
+ }
+
+
+}
diff --git a/ipojo/runtime/core-it/src/it/ipojo-core-configuration-admin-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestManagedServiceTestForImmediate.java b/ipojo/runtime/core-it/src/it/ipojo-core-configuration-admin-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestManagedServiceTestForImmediate.java
new file mode 100644
index 0000000..c116ab1
--- /dev/null
+++ b/ipojo/runtime/core-it/src/it/ipojo-core-configuration-admin-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestManagedServiceTestForImmediate.java
@@ -0,0 +1,398 @@
+/*
+ * 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 org.apache.felix.ipojo.ComponentFactory;
+import org.apache.felix.ipojo.ComponentInstance;
+import org.apache.felix.ipojo.PrimitiveInstanceDescription;
+import org.apache.felix.ipojo.architecture.Architecture;
+import org.apache.felix.ipojo.runtime.core.services.FooService;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+import java.io.IOException;
+import java.util.Dictionary;
+import java.util.Properties;
+
+import static junit.framework.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+public class TestManagedServiceTestForImmediate extends Common {
+
+ private String factNameImm = "CA-ImmConfigurableProvider";
+ private String msp = "foo";
+
+ private ComponentFactory factImm;
+
+ private ConfigurationAdmin admin;
+
+ ConfigurationMonitor listener;
+
+ @Before
+ public void setUp() throws InterruptedException {
+ factImm = (ComponentFactory) ipojoHelper.getFactory(factNameImm);
+ admin = (ConfigurationAdmin) osgiHelper.getServiceObject(ConfigurationAdmin.class.getName(), null);
+ assertNotNull("Check configuration admin availability", admin);
+ cleanConfigurationAdmin();
+ listener = new ConfigurationMonitor(bc);
+ }
+
+ @After
+ public void tearDown() {
+ listener.stop();
+ cleanConfigurationAdmin();
+ admin = null;
+ }
+
+ private void cleanConfigurationAdmin() {
+ try {
+ Configuration[] configurations = admin.listConfigurations("(service.pid=" + msp + ")");
+ for (int i = 0; configurations != null && i < configurations.length; i++) {
+ configurations[i].delete();
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (InvalidSyntaxException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Test
+ public void testFactoryCreationAndReconfigurationUsingManagedService() {
+ Properties props = new Properties();
+ props.put("managed.service.pid", msp); // Exposes a ManagedService.
+ props.put("message", "message");
+ ComponentInstance instance = null;
+ try {
+ instance = factImm.createComponentInstance(props);
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+
+ ServiceReference ref = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), instance.getInstanceName());
+ assertEquals("Check 1 object", 1, ((PrimitiveInstanceDescription) instance.getInstanceDescription()).getCreatedObjects().length);
+ assertNotNull("FS availability", ref);
+
+ FooService fs = (FooService) bc.getService(ref);
+ Properties p = fs.fooProps();
+ String mes = p.getProperty("message");
+ int count = (Integer) p.get("count");
+ assertEquals("Check 1 object", 1, ((PrimitiveInstanceDescription) instance.getInstanceDescription()).getCreatedObjects().length);
+ assertEquals("Check message", "message", mes);
+ assertEquals("Check count", 1, count);
+
+ //Update
+ Configuration configuration;
+ try {
+ configuration = admin.getConfiguration(msp, getTestBundle().getLocation());
+ Dictionary prc = configuration.getProperties();
+ if (prc == null) {
+ prc = new Properties();
+ }
+ prc.put("message", "message2");
+ configuration.update(prc);
+ System.err.println("updated ? ");
+ //Thread.sleep(UPDATE_WAIT_TIME);
+ listener.waitForEvent(configuration.getPid(), "1");
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ ref = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), instance.getInstanceName());
+ assertEquals("Check 1 object", 1, ((PrimitiveInstanceDescription) instance.getInstanceDescription()).getCreatedObjects().length);
+ assertNotNull("FS availability", ref);
+
+ fs = (FooService) bc.getService(ref);
+ p = fs.fooProps();
+ mes = p.getProperty("message");
+ count = (Integer) p.get("count");
+ assertEquals("Check 1 object", 1, ((PrimitiveInstanceDescription) instance.getInstanceDescription()).getCreatedObjects().length);
+ assertEquals("Check message", "message2", mes);
+ assertEquals("Check count", 2, count);
+
+ instance.dispose();
+ cleanConfigurationAdmin();
+ }
+
+ /**
+ * Creates an instance using a factory configuration.
+ * The configuration specifies the managed.service.pid property
+ * Reconfiguration is applied using the exposed managed service.
+ */
+ @Test
+ public void testCreationUsingFactoryConfigurationSettingTheManagedServicePid() {
+ Configuration conf = null;
+ try {
+ //TODO test multi-location:?
+ conf = admin.createFactoryConfiguration(factNameImm, getTestBundle().getLocation());
+ Dictionary props = conf.getProperties();
+ if (props == null) {
+ props = new Properties();
+ }
+ props.put("managed.service.pid", msp);
+ props.put("message", "message");
+ conf.update(props);
+ Thread.sleep(UPDATE_WAIT_TIME); // Wait for the creation.
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+
+ Architecture arch = (Architecture) osgiHelper.getServiceObject(org.apache.felix.ipojo.architecture.Architecture.class.getName(), "(architecture.instance=" + conf.getPid() + ")");
+
+ ServiceReference ref = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), conf.getPid());
+ assertEquals("Check 1 object", 1, ((PrimitiveInstanceDescription) arch.getInstanceDescription()).getCreatedObjects().length);
+ assertNotNull("FS availability", ref);
+
+ // arch = (Architecture) osgiHelper.getServiceObject( org.apache.felix.ipojo.architecture.Architecture.class.getName(), "(architecture.instance=" + conf.getPid() + ")");
+ FooService fs = (FooService) bc.getService(ref);
+ Properties p = fs.fooProps();
+ String mes = p.getProperty("message");
+ int count = ((Integer) p.get("count")).intValue();
+ assertEquals("Check 1 object", 1, ((PrimitiveInstanceDescription) arch.getInstanceDescription()).getCreatedObjects().length);
+ assertEquals("Check message", "message", mes);
+ assertEquals("Check count", 1, count);
+
+ //Update
+ Configuration configuration;
+ try {
+ configuration = admin.getConfiguration(msp, getTestBundle().getLocation());
+ Dictionary prc = configuration.getProperties();
+ if (prc == null) {
+ prc = new Properties();
+ }
+ prc.put("message", "message2");
+ configuration.update(prc);
+ //Thread.sleep(UPDATE_WAIT_TIME);
+ listener.waitForEvent(configuration.getPid(), "1");
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ // arch = (Architecture) osgiHelper.getServiceObject( org.apache.felix.ipojo.architecture.Architecture.class.getName(), "(architecture.instance=" + conf.getPid() + ")");
+ ref = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), conf.getPid());
+ assertEquals("Check 1 object", 1, ((PrimitiveInstanceDescription) arch.getInstanceDescription()).getCreatedObjects().length);
+ assertNotNull("FS availability", ref);
+
+ // arch = (Architecture) osgiHelper.getServiceObject( org.apache.felix.ipojo.architecture.Architecture.class.getName(), "(architecture.instance=" + conf.getPid() + ")");
+ fs = (FooService) bc.getService(ref);
+ p = fs.fooProps();
+ mes = p.getProperty("message");
+ count = ((Integer) p.get("count")).intValue();
+ assertEquals("Check 1 object", 1, ((PrimitiveInstanceDescription) arch.getInstanceDescription()).getCreatedObjects().length);
+ if (mes.equals("message")) {
+ System.out.println("Warning, configuration not yet applied");
+ assertEquals("Check count - W", 1, count);
+ } else {
+ assertEquals("Check message", "message2", mes);
+ assertEquals("Check count", 2, count);
+ }
+
+ try {
+ conf.delete();
+ } catch (IOException e) {
+ fail(e.getMessage());
+ }
+
+ }
+
+ @Test
+ public void testCreationAndReconfiguration2() {
+ // The configuration exists before the instance creation.
+
+ //Update
+ Configuration configuration = null;
+ try {
+ configuration = admin.getConfiguration(msp, getTestBundle().getLocation());
+ Dictionary prc = configuration.getProperties();
+ if (prc == null) {
+ prc = new Properties();
+ }
+ prc.put("message", "message2");
+ configuration.update(prc);
+ Thread.sleep(UPDATE_WAIT_TIME);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ Properties props = new Properties();
+ props.put("managed.service.pid", msp);
+ props.put("message", "message");
+ ComponentInstance instance = null;
+ try {
+ instance = factImm.createComponentInstance(props);
+ Thread.sleep(UPDATE_WAIT_TIME);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ ServiceReference ref = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), instance.getInstanceName());
+ assertEquals("Check 1 object", 1, ((PrimitiveInstanceDescription) instance.getInstanceDescription()).getCreatedObjects().length);
+ assertNotNull("FS availability", ref);
+
+ FooService fs = (FooService) bc.getService(ref);
+ Properties p = fs.fooProps();
+ String mes = p.getProperty("message");
+ // int count1 = ((Integer) p.get("count")).intValue();
+ assertEquals("Check 1 object", 1, ((PrimitiveInstanceDescription) instance.getInstanceDescription()).getCreatedObjects().length);
+ assertEquals("Check message - 1 (" + mes + ")", "message2", mes); // Already reconfigured.
+ // assertEquals("Check count", 2, count); // Two : 1) "message" on immediate, "message2" on the reconfiguration,
+ // not necessary as the property can be set before the immediate instance creation
+
+ instance.dispose();
+
+ //Reconfiguration
+ try {
+ configuration = admin.getConfiguration(msp, getTestBundle().getLocation());
+ Dictionary prc = configuration.getProperties();
+ if (prc == null) {
+ prc = new Properties();
+ }
+ prc.put("message", "message3");
+ configuration.update(prc);
+ listener.waitForEvent(msp, "1");
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ // Recreation of the instance.
+ props = new Properties();
+ props.put("managed.service.pid", msp);
+ props.put("message", "message");
+ instance = null;
+ try {
+ instance = factImm.createComponentInstance(props);
+ Thread.sleep(UPDATE_WAIT_TIME * 2);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+ ref = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), instance.getInstanceName());
+ assertEquals("Check 1 object", 1, ((PrimitiveInstanceDescription) instance.getInstanceDescription()).getCreatedObjects().length);
+ assertNotNull("FS availability", ref);
+
+ fs = (FooService) bc.getService(ref);
+ p = fs.fooProps();
+ mes = p.getProperty("message");
+ // int count = ((Integer) p.get("count")).intValue();
+ assertEquals("Check 1 object", 1, ((PrimitiveInstanceDescription) instance.getInstanceDescription()).getCreatedObjects().length);
+ assertEquals("Check message already reconfigured", "message3", mes); // Already reconfigured.
+ //assertEquals("Check count", count1 + 1, count); // message before the reconfiguration, message3 after the reconfiguration
+
+ instance.dispose();
+
+
+ }
+
+ @Test
+ public void testCreationAndReconfiguration3() {
+ // The configuration exists before the instance creation.
+
+ //Update
+ Configuration configuration;
+ try {
+ configuration = admin.getConfiguration(msp, getTestBundle().getLocation());
+ Dictionary prc = configuration.getProperties();
+ if (prc == null) {
+ prc = new Properties();
+ }
+ prc.put("message", "message2");
+ configuration.update(prc);
+ listener.waitForEvent(msp, "1");
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ Properties props = new Properties();
+ props.put("managed.service.pid", msp);
+ props.put("message", "message");
+ ComponentInstance instance = null;
+ try {
+ instance = factImm.createComponentInstance(props);
+ Thread.sleep(UPDATE_WAIT_TIME);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ ServiceReference ref = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), instance.getInstanceName());
+ assertEquals("Check 1 object", 1, ((PrimitiveInstanceDescription) instance.getInstanceDescription()).getCreatedObjects().length);
+ assertNotNull("FS availability", ref);
+
+ FooService fs = (FooService) bc.getService(ref);
+ Properties p = fs.fooProps();
+ String mes = p.getProperty("message");
+ // int count = ((Integer) p.get("count")).intValue();
+ assertEquals("Check 1 object", 1, ((PrimitiveInstanceDescription) instance.getInstanceDescription()).getCreatedObjects().length);
+ assertEquals("Check message", "message2", mes); // Already reconfigured.
+ //assertEquals("Check count", 1, count);
+
+ //Reconfiguration
+ try {
+ configuration = admin.getConfiguration(msp);
+ Dictionary prc = configuration.getProperties();
+ if (prc == null) {
+ prc = new Properties();
+ }
+ prc.put("message", "message3");
+ configuration.update(prc);
+ //Thread.sleep(UPDATE_WAIT_TIME);
+ listener.waitForEvent(msp, "1");
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ instance.dispose();
+
+ // Recreation of the instance.
+ props = new Properties();
+ props.put("managed.service.pid", msp);
+ props.put("message", "message");
+ instance = null;
+ try {
+ instance = factImm.createComponentInstance(props);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ ref = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), instance.getInstanceName());
+ assertEquals("Check 1 object", 1, ((PrimitiveInstanceDescription) instance.getInstanceDescription()).getCreatedObjects().length);
+ assertNotNull("FS availability", ref);
+
+ fs = (FooService) bc.getService(ref);
+ p = fs.fooProps();
+ mes = p.getProperty("message");
+ // count = ((Integer) p.get("count")).intValue();
+ assertEquals("Check 1 object", 1, ((PrimitiveInstanceDescription) instance.getInstanceDescription()).getCreatedObjects().length);
+ assertEquals("Check message", "message3", mes); // Already reconfigured.
+ // assertEquals("Check count", 1, count);
+
+ instance.dispose();
+
+
+ }
+
+
+}
diff --git a/ipojo/runtime/core-it/src/it/ipojo-core-configuration-admin-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestManagedServiceTestForService.java b/ipojo/runtime/core-it/src/it/ipojo-core-configuration-admin-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestManagedServiceTestForService.java
new file mode 100644
index 0000000..68eb29d
--- /dev/null
+++ b/ipojo/runtime/core-it/src/it/ipojo-core-configuration-admin-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestManagedServiceTestForService.java
@@ -0,0 +1,393 @@
+/*
+ * 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 org.apache.felix.ipojo.ComponentFactory;
+import org.apache.felix.ipojo.ComponentInstance;
+import org.apache.felix.ipojo.PrimitiveInstanceDescription;
+import org.apache.felix.ipojo.architecture.Architecture;
+import org.apache.felix.ipojo.runtime.core.services.FooService;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+import java.io.IOException;
+import java.util.Dictionary;
+import java.util.Properties;
+
+import static junit.framework.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+public class TestManagedServiceTestForService extends Common {
+
+ private String factNameSvc = "CA-ConfigurableProvider";
+ private String msp = "foo";
+
+ private ComponentFactory factSvc;
+
+ private ConfigurationAdmin admin;
+
+ ConfigurationMonitor listener;
+
+ @Before
+ public void setUp() {
+ factSvc = (ComponentFactory) ipojoHelper.getFactory(factNameSvc);
+ admin = (ConfigurationAdmin) osgiHelper.getServiceObject(ConfigurationAdmin.class.getName(), null);
+ assertNotNull("Check configuration admin availability", admin);
+ cleanConfigurationAdmin();
+ listener = new ConfigurationMonitor(bc);
+ }
+
+ @After
+ public void tearDown() {
+ listener.stop();
+ cleanConfigurationAdmin();
+ admin = null;
+ }
+
+ private void cleanConfigurationAdmin() {
+ try {
+ Configuration[] configurations = admin.listConfigurations("(service.pid=" + msp + ")");
+ for (int i = 0; configurations != null && i < configurations.length; i++) {
+ configurations[i].delete();
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (InvalidSyntaxException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Test
+ public void testCreationUsingFactoryAndReconfigurationUsingManagedService() {
+ Properties props = new Properties();
+ props.put("managed.service.pid", msp);
+ props.put("message", "message");
+ ComponentInstance instance = null;
+ try {
+ instance = factSvc.createComponentInstance(props);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ ServiceReference ref = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), instance.getInstanceName());
+ assertEquals("Check no object", 0, ((PrimitiveInstanceDescription) instance.getInstanceDescription()).getCreatedObjects().length);
+ assertNotNull("FS availability", ref);
+
+ FooService fs = (FooService) bc.getService(ref);
+ Properties p = fs.fooProps();
+ String mes = p.getProperty("message");
+ int count = (Integer) p.get("count");
+ assertEquals("Check 1 object", 1, ((PrimitiveInstanceDescription) instance.getInstanceDescription()).getCreatedObjects().length);
+ assertEquals("Check message", "message", mes);
+ assertEquals("Check count", 1, count);
+
+ //Update
+ Configuration configuration;
+ try {
+ configuration = admin.getConfiguration(msp, getTestBundle().getLocation());
+ Dictionary prc = configuration.getProperties();
+ if (prc == null) {
+ prc = new Properties();
+ }
+ prc.put("message", "message2");
+ configuration.update(prc);
+ Thread.sleep(UPDATE_WAIT_TIME);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ ref = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), instance.getInstanceName());
+ assertEquals("Check 1 object", 1, ((PrimitiveInstanceDescription) instance.getInstanceDescription()).getCreatedObjects().length);
+ assertNotNull("FS availability", ref);
+
+ fs = (FooService) bc.getService(ref);
+ p = fs.fooProps();
+ mes = p.getProperty("message");
+ count = (Integer) p.get("count");
+ assertEquals("Check 1 object", 1, ((PrimitiveInstanceDescription) instance.getInstanceDescription()).getCreatedObjects().length);
+ if (mes.equals("message")) {
+ System.out.println("Warning, configuration not yet applied");
+ assertEquals("Check count - W", 1, count);
+ } else {
+ assertEquals("Check message", "message2", mes);
+ assertEquals("Check count", 2, count);
+ }
+
+ instance.dispose();
+
+ }
+
+ @Test
+ public void testCreationUsingMSFAndReconfigurationUsingManagedService() {
+ Configuration conf = null;
+ try {
+ conf = admin.createFactoryConfiguration(factNameSvc, getTestBundle().getLocation());
+ Dictionary props = conf.getProperties();
+ if (props == null) {
+ props = new Properties();
+ }
+ props.put("managed.service.pid", msp);
+ props.put("message", "message");
+ conf.update(props);
+ Thread.sleep(UPDATE_WAIT_TIME); // Wait for the creation.
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ Architecture arch = (Architecture) osgiHelper.getServiceObject(org.apache.felix.ipojo.architecture.Architecture.class.getName(), "(architecture.instance=" + conf.getPid() + ")");
+
+ ServiceReference ref = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), conf.getPid());
+ assertEquals("Check no object", 0, ((PrimitiveInstanceDescription) arch.getInstanceDescription()).getCreatedObjects().length);
+ assertNotNull("FS availability", ref);
+
+ // arch = (Architecture) osgiHelper.getServiceObject( org.apache.felix.ipojo.architecture.Architecture.class.getName(), "(architecture.instance=" + conf.getPid() + ")");
+ FooService fs = (FooService) bc.getService(ref);
+ Properties p = fs.fooProps();
+ String mes = p.getProperty("message");
+ int count = (Integer) p.get("count");
+ assertEquals("Check 1 object", 1, ((PrimitiveInstanceDescription) arch.getInstanceDescription()).getCreatedObjects().length);
+ assertEquals("Check message", "message", mes);
+ assertEquals("Check count", 1, count);
+
+ //Update
+ Configuration configuration;
+ try {
+ configuration = admin.getConfiguration(msp, getTestBundle().getLocation());
+ Dictionary prc = configuration.getProperties();
+ if (prc == null) {
+ prc = new Properties();
+ }
+ prc.put("message", "message2");
+ configuration.update(prc);
+ Thread.sleep(UPDATE_WAIT_TIME);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ // arch = (Architecture) osgiHelper.getServiceObject( org.apache.felix.ipojo.architecture.Architecture.class.getName(), "(architecture.instance=" + conf.getPid() + ")");
+ ref = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), conf.getPid());
+ assertEquals("Check 1 object", 1, ((PrimitiveInstanceDescription) arch.getInstanceDescription()).getCreatedObjects().length);
+ assertNotNull("FS availability", ref);
+
+ // arch = (Architecture) osgiHelper.getServiceObject( org.apache.felix.ipojo.architecture.Architecture.class.getName(), "(architecture.instance=" + conf.getPid() + ")");
+ fs = (FooService) bc.getService(ref);
+ p = fs.fooProps();
+ mes = p.getProperty("message");
+ count = (Integer) p.get("count");
+ assertEquals("Check 1 object", 1, ((PrimitiveInstanceDescription) arch.getInstanceDescription()).getCreatedObjects().length);
+ if (mes.equals("message")) {
+ System.out.println("Warning, configuration not yet applied");
+ assertEquals("Check count - W", 1, count);
+ } else {
+ assertEquals("Check message", "message2", mes);
+ assertEquals("Check count", 2, count);
+ }
+
+ try {
+ conf.delete();
+ } catch (IOException e) {
+ fail(e.getMessage());
+ }
+
+ }
+
+ @Test
+ public void testConfigurationPushedBeforeInstantiationUsingFactory() {
+ // The configuration exists before the instance creation.
+
+ //Update
+ Configuration configuration;
+ try {
+ configuration = admin.getConfiguration(msp, getTestBundle().getLocation());
+ Dictionary prc = configuration.getProperties();
+ if (prc == null) {
+ prc = new Properties();
+ }
+ prc.put("message", "message2");
+ configuration.update(prc);
+ //listener.waitForEvent(msp, "1");
+ Thread.sleep(UPDATE_WAIT_TIME);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ Properties props = new Properties();
+ props.put("managed.service.pid", msp);
+ props.put("message", "message");
+ ComponentInstance instance = null;
+ try {
+ instance = factSvc.createComponentInstance(props);
+ Thread.sleep(UPDATE_WAIT_TIME);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ ServiceReference ref = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), instance.getInstanceName());
+ assertEquals("Check no object", 0, ((PrimitiveInstanceDescription) instance.getInstanceDescription()).getCreatedObjects().length);
+ assertNotNull("FS availability", ref);
+
+ FooService fs = (FooService) bc.getService(ref);
+ Properties p = fs.fooProps();
+ String mes = p.getProperty("message");
+ int count = (Integer) p.get("count");
+ assertEquals("Check 1 object", 1, ((PrimitiveInstanceDescription) instance.getInstanceDescription()).getCreatedObjects().length);
+ assertEquals("Check message", "message2", mes); // Already reconfigured.
+ assertEquals("Check count", 1, count);
+
+ instance.dispose();
+
+ //Reconfiguration
+ try {
+ configuration = admin.getConfiguration(msp, getTestBundle().getLocation());
+ Dictionary prc = configuration.getProperties();
+ if (prc == null) {
+ prc = new Properties();
+ }
+ prc.put("message", "message3");
+ configuration.update(prc);
+ listener.waitForEvent(msp, "2");
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ // Recreation of the instance.
+ props = new Properties();
+ props.put("managed.service.pid", msp);
+ props.put("message", "message");
+ instance = null;
+ try {
+ instance = factSvc.createComponentInstance(props);
+ Thread.sleep(UPDATE_WAIT_TIME);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ ref = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), instance.getInstanceName());
+ assertEquals("Check no object", 0, ((PrimitiveInstanceDescription) instance.getInstanceDescription()).getCreatedObjects().length);
+ assertNotNull("FS availability", ref);
+
+ fs = (FooService) bc.getService(ref);
+ p = fs.fooProps();
+ mes = p.getProperty("message");
+ count = (Integer) p.get("count");
+ assertEquals("Check 1 object", 1, ((PrimitiveInstanceDescription) instance.getInstanceDescription()).getCreatedObjects().length);
+ assertEquals("Check message", "message3", mes); // Already reconfigured.
+ assertEquals("Check count", 1, count);
+
+ instance.dispose();
+
+
+ }
+
+ @Test
+ public void testConfigurationPushedBeforeInstantiationUsingFactoryAndReconfiguration() {
+ // The configuration exists before the instance creation.
+
+ //Update
+ Configuration configuration;
+ try {
+ configuration = admin.getConfiguration(msp, getTestBundle().getLocation());
+ Dictionary prc = configuration.getProperties();
+ if (prc == null) {
+ prc = new Properties();
+ }
+ prc.put("message", "message2");
+ configuration.update(prc);
+ Thread.sleep(UPDATE_WAIT_TIME);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ Properties props = new Properties();
+ props.put("managed.service.pid", msp);
+ props.put("message", "message");
+ ComponentInstance instance = null;
+ try {
+ instance = factSvc.createComponentInstance(props);
+ Thread.sleep(UPDATE_WAIT_TIME);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ ServiceReference ref = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), instance.getInstanceName());
+ assertEquals("Check no object", 0, ((PrimitiveInstanceDescription) instance.getInstanceDescription()).getCreatedObjects().length);
+ assertNotNull("FS availability", ref);
+
+ FooService fs = (FooService) bc.getService(ref);
+ Properties p = fs.fooProps();
+ String mes = p.getProperty("message");
+ int count = (Integer) p.get("count");
+ assertEquals("Check 1 object", 1, ((PrimitiveInstanceDescription) instance.getInstanceDescription()).getCreatedObjects().length);
+ assertEquals("Check message", "message2", mes); // Already reconfigured.
+ assertEquals("Check count", 1, count);
+
+ //Reconfiguration
+ try {
+ configuration = admin.getConfiguration(msp, getTestBundle().getLocation());
+ Dictionary prc = configuration.getProperties();
+ if (prc == null) {
+ prc = new Properties();
+ }
+ prc.put("message", "message3");
+ configuration.update(prc);
+ Thread.sleep(UPDATE_WAIT_TIME);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ instance.dispose();
+
+ // Recreation of the instance.
+ props = new Properties();
+ props.put("managed.service.pid", msp);
+ props.put("message", "message");
+ instance = null;
+ try {
+ instance = factSvc.createComponentInstance(props);
+ Thread.sleep(UPDATE_WAIT_TIME);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ ref = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), instance.getInstanceName());
+ assertEquals("Check no object", 0, ((PrimitiveInstanceDescription) instance.getInstanceDescription()).getCreatedObjects().length);
+ assertNotNull("FS availability", ref);
+
+ fs = (FooService) bc.getService(ref);
+ p = fs.fooProps();
+ mes = p.getProperty("message");
+ count = (Integer) p.get("count");
+ assertEquals("Check 1 object", 1, ((PrimitiveInstanceDescription) instance.getInstanceDescription()).getCreatedObjects().length);
+ assertEquals("Check message", "message3", mes); // Already reconfigured.
+ assertEquals("Check count", 1, count);
+
+ instance.dispose();
+
+
+ }
+
+
+}
diff --git a/ipojo/runtime/core-it/src/it/ipojo-core-configuration-test/src/test/java/org/apache/felix/ipojo/runtime/core/Common.java b/ipojo/runtime/core-it/src/it/ipojo-core-configuration-test/src/test/java/org/apache/felix/ipojo/runtime/core/Common.java
index f0fe02f..a39d105 100644
--- a/ipojo/runtime/core-it/src/it/ipojo-core-configuration-test/src/test/java/org/apache/felix/ipojo/runtime/core/Common.java
+++ b/ipojo/runtime/core-it/src/it/ipojo-core-configuration-test/src/test/java/org/apache/felix/ipojo/runtime/core/Common.java
@@ -109,7 +109,12 @@
public CompositeOption ipojoBundles() {
return new DefaultCompositeOption(
mavenBundle("org.apache.felix", "org.apache.felix.ipojo").versionAsInProject(),
- mavenBundle("org.ow2.chameleon.testing", "osgi-helpers").versionAsInProject());
+ mavenBundle("org.ow2.chameleon.testing", "osgi-helpers").versionAsInProject(),
+ mavenBundle("org.apache.felix", "org.apache.felix.configadmin").versionAsInProject());
+ }
+
+ public Bundle getTestBundle() {
+ return osgiHelper.getBundle("test.bundle");
}
public Option testedBundle() throws MalformedURLException {
diff --git a/ipojo/runtime/core-it/src/it/ipojo-core-configuration-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestDynamicallyConfigurableProperties.java b/ipojo/runtime/core-it/src/it/ipojo-core-configuration-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestDynamicallyConfigurablePropertiesUsingConfigAdmin.java
similarity index 74%
rename from ipojo/runtime/core-it/src/it/ipojo-core-configuration-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestDynamicallyConfigurableProperties.java
rename to ipojo/runtime/core-it/src/it/ipojo-core-configuration-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestDynamicallyConfigurablePropertiesUsingConfigAdmin.java
index f00c1f8..84ebf4a 100644
--- a/ipojo/runtime/core-it/src/it/ipojo-core-configuration-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestDynamicallyConfigurableProperties.java
+++ b/ipojo/runtime/core-it/src/it/ipojo-core-configuration-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestDynamicallyConfigurablePropertiesUsingConfigAdmin.java
@@ -23,10 +23,16 @@
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
+import org.ops4j.pax.exam.spi.reactors.PerClass;
+import org.ops4j.pax.exam.spi.reactors.PerMethod;
import org.osgi.framework.ServiceReference;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ManagedServiceFactory;
+import java.io.IOException;
import java.util.Hashtable;
import java.util.Properties;
@@ -34,7 +40,12 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
-public class TestDynamicallyConfigurableProperties extends Common {
+/**
+ * iPOJO does not expose the ManagedServiceFactory anymore, we must use the configuration admin.
+ * To avoid conflicts with persisted configuration, we run one framework per tests
+ */
+@ExamReactorStrategy(PerMethod.class)
+public class TestDynamicallyConfigurablePropertiesUsingConfigAdmin extends Common {
ComponentInstance instance, instance2;
@@ -64,7 +75,7 @@
}
@Test
- public void testStatic() {
+ public void testStatic() throws IOException, InterruptedException {
ServiceReference fooRef = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), instance.getInstanceName());
assertNotNull("Check FS availability", fooRef);
String fooP = (String) fooRef.getProperty("foo");
@@ -74,21 +85,23 @@
assertEquals("Check bar equality -1", barP, new Integer(2));
assertEquals("Check baz equality -1", bazP, "baz");
- ServiceReference msRef = ipojoHelper.getServiceReferenceByName(ManagedServiceFactory.class.getName(), instance.getFactory().getName());
- assertNotNull("Check ManagedServiceFactory availability", msRef);
+ ConfigurationAdmin admin = osgiHelper.getServiceObject(ConfigurationAdmin.class);
+ assertNotNull("Check Configuration Admin availability", admin);
+ Configuration configuration = admin.getConfiguration(instance.getInstanceName(),
+ getTestBundle().getLocation());
// Configuration of baz
Properties conf = new Properties();
conf.put("baz", "zab");
conf.put("bar", new Integer(2));
conf.put("foo", "foo");
- ManagedServiceFactory ms = (ManagedServiceFactory) osgiHelper.getContext().getService(msRef);
- try {
- ms.updated(instance.getInstanceName(), conf);
- } catch (ConfigurationException e) {
- fail("Configuration Exception : " + e);
- }
+ conf.put("instance.name", instance.getInstanceName());
+
+ configuration.update(conf);
+
+ // Asynchronous dispatching of the configuration
+ Thread.sleep(200);
// Recheck props
fooRef = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), instance.getInstanceName());
@@ -98,12 +111,11 @@
assertEquals("Check foo equality -2", fooP, "foo");
assertEquals("Check bar equality -2", barP, new Integer(2));
assertEquals("Check baz equality -2", bazP, "zab");
- osgiHelper.getContext().ungetService(msRef);
}
@Test
- public void testStaticNoValue() {
+ public void testStaticNoValue() throws IOException, InterruptedException {
ServiceReference fooRef = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), instance2.getInstanceName());
assertNotNull("Check FS availability", fooRef);
Object fooP = fooRef.getProperty("foo");
@@ -113,21 +125,21 @@
assertEquals("Check bar equality -1", barP, null);
assertEquals("Check baz equality -1", bazP, null);
- ServiceReference msRef = ipojoHelper.getServiceReferenceByName(ManagedServiceFactory.class.getName(), instance2.getFactory().getName());
- assertNotNull("Check ManagedServiceFactory availability", msRef);
+ ConfigurationAdmin admin = osgiHelper.getServiceObject(ConfigurationAdmin.class);
+ assertNotNull("Check Configuration Admin availability", admin);
+ Configuration configuration = admin.getConfiguration(instance2.getInstanceName(),
+ getTestBundle().getLocation());
// Configuration of baz
Properties conf = new Properties();
conf.put("baz", "zab");
conf.put("bar", new Integer(2));
conf.put("foo", "foo");
- ManagedServiceFactory ms = (ManagedServiceFactory) osgiHelper.getContext().getService(msRef);
- try {
- ms.updated(instance2.getInstanceName(), conf);
- } catch (ConfigurationException e) {
- fail("Configuration Exception : " + e);
- }
+
+ // Asynchronous dispatching of the configuration
+ configuration.update(conf);
+ Thread.sleep(200);
// Recheck props
fooRef = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), instance2.getInstanceName());
@@ -137,11 +149,10 @@
assertEquals("Check foo equality -2", fooP, "foo");
assertEquals("Check bar equality -2", barP, new Integer(2));
assertEquals("Check baz equality -2", bazP, "zab");
- osgiHelper.getContext().ungetService(msRef);
}
@Test
- public void testDynamic() {
+ public void testDynamic() throws IOException, InterruptedException {
ServiceReference fooRef = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), instance.getInstanceName());
assertNotNull("Check FS availability", fooRef);
@@ -153,20 +164,21 @@
assertEquals("Check bar equality", barP, new Integer(2));
assertEquals("Check baz equality", bazP, "baz");
- ServiceReference msRef = ipojoHelper.getServiceReferenceByName(ManagedServiceFactory.class.getName(), instance.getFactory().getName());
- assertNotNull("Check ManagedServiceFactory availability", msRef);
+ ConfigurationAdmin admin = osgiHelper.getServiceObject(ConfigurationAdmin.class);
+ assertNotNull("Check Configuration Admin availability", admin);
+
+ Configuration configuration = admin.getConfiguration(instance.getInstanceName(),
+ getTestBundle().getLocation());
// Configuration of baz
Properties conf = new Properties();
conf.put("baz", "zab");
conf.put("foo", "oof");
conf.put("bar", new Integer(0));
- ManagedServiceFactory ms = (ManagedServiceFactory) osgiHelper.getContext().getService(msRef);
- try {
- ms.updated(instance.getInstanceName(), conf);
- } catch (ConfigurationException e) {
- fail("Configuration Exception : " + e);
- }
+
+ // Asynchronous dispatching of the configuration
+ configuration.update(conf);
+ Thread.sleep(200);
// Recheck props
fooRef = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), instance.getInstanceName());
@@ -188,11 +200,10 @@
assertEquals("Check bar field equality", barP, new Integer(0));
osgiHelper.getContext().ungetService(fooRef);
- osgiHelper.getContext().ungetService(msRef);
}
@Test
- public void testDynamicNoValue() {
+ public void testDynamicNoValue() throws IOException, InterruptedException {
ServiceReference fooRef = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), instance2.getInstanceName());
assertNotNull("Check FS availability", fooRef);
@@ -203,20 +214,21 @@
assertEquals("Check bar equality -1", barP, null);
assertEquals("Check baz equality -1", bazP, null);
- ServiceReference msRef = ipojoHelper.getServiceReferenceByName(ManagedServiceFactory.class.getName(), instance2.getFactory().getName());
- assertNotNull("Check ManagedServiceFactory availability", msRef);
+ ConfigurationAdmin admin = osgiHelper.getServiceObject(ConfigurationAdmin.class);
+ assertNotNull("Check Configuration Admin availability", admin);
+
+ Configuration configuration = admin.getConfiguration(instance2.getInstanceName(),
+ getTestBundle().getLocation());
// Configuration of baz
Properties conf = new Properties();
conf.put("baz", "zab");
conf.put("foo", "oof");
conf.put("bar", new Integer(0));
- ManagedServiceFactory ms = (ManagedServiceFactory) osgiHelper.getContext().getService(msRef);
- try {
- ms.updated(instance2.getInstanceName(), conf);
- } catch (ConfigurationException e) {
- fail("Configuration Exception : " + e);
- }
+
+ // Asynchronous dispatching of the configuration
+ configuration.update(conf);
+ Thread.sleep(200);
// Recheck props
fooRef = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), instance2.getInstanceName());
@@ -238,12 +250,12 @@
assertEquals("Check bar field equality", barP, new Integer(0));
osgiHelper.getContext().ungetService(fooRef);
- osgiHelper.getContext().ungetService(msRef);
}
@Test
- public void testDynamicString() {
- ServiceReference fooRef = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), instance.getInstanceName());
+ public void testDynamicString() throws IOException, InterruptedException {
+ ServiceReference fooRef = ipojoHelper.getServiceReferenceByName(FooService.class.getName(),
+ instance.getInstanceName());
assertNotNull("Check FS availability", fooRef);
String fooP = (String) fooRef.getProperty("foo");
@@ -254,20 +266,21 @@
assertEquals("Check bar equality", barP, new Integer(2));
assertEquals("Check baz equality", bazP, "baz");
- ServiceReference msRef = ipojoHelper.getServiceReferenceByName(ManagedServiceFactory.class.getName(), instance.getFactory().getName());
- assertNotNull("Check ManagedServiceFactory availability", msRef);
+ ConfigurationAdmin admin = osgiHelper.getServiceObject(ConfigurationAdmin.class);
+ assertNotNull("Check Configuration Admin availability", admin);
+
+ Configuration configuration = admin.getConfiguration(instance.getInstanceName(),
+ getTestBundle().getLocation());
// Configuration of baz
Properties conf = new Properties();
conf.put("baz", "zab");
conf.put("foo", "oof");
conf.put("bar", "0");
- ManagedServiceFactory ms = (ManagedServiceFactory) osgiHelper.getContext().getService(msRef);
- try {
- ms.updated(instance.getInstanceName(), conf);
- } catch (ConfigurationException e) {
- fail("Configuration Exception : " + e);
- }
+
+ // Asynchronous dispatching of the configuration
+ configuration.update(conf);
+ Thread.sleep(200);
// Recheck props
fooRef = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), instance.getInstanceName());
@@ -289,11 +302,10 @@
assertEquals("Check bar field equality", barP, new Integer(0));
osgiHelper.getContext().ungetService(fooRef);
- osgiHelper.getContext().ungetService(msRef);
}
@Test
- public void testPropagation() {
+ public void testPropagation() throws IOException, InterruptedException {
ServiceReference fooRef = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), instance.getInstanceName());
assertNotNull("Check FS availability", fooRef);
@@ -305,8 +317,11 @@
assertEquals("Check bar equality", barP, new Integer(2));
assertEquals("Check baz equality", bazP, "baz");
- ServiceReference msRef = ipojoHelper.getServiceReferenceByName(ManagedServiceFactory.class.getName(), instance.getFactory().getName());
- assertNotNull("Check ManagedServiceFactory availability", msRef);
+ ConfigurationAdmin admin = osgiHelper.getServiceObject(ConfigurationAdmin.class);
+ assertNotNull("Check Configuration Admin availability", admin);
+
+ Configuration configuration = admin.getConfiguration(instance.getInstanceName(),
+ getTestBundle().getLocation());
// Configuration of baz
Properties conf = new Properties();
@@ -315,12 +330,10 @@
conf.put("bar", new Integer(2));
conf.put("propagated1", "propagated");
conf.put("propagated2", new Integer(1));
- ManagedServiceFactory ms = (ManagedServiceFactory) osgiHelper.getContext().getService(msRef);
- try {
- ms.updated(instance.getInstanceName(), conf);
- } catch (ConfigurationException e) {
- fail("Configuration Exception : " + e);
- }
+
+ // Asynchronous dispatching of the configuration
+ configuration.update(conf);
+ Thread.sleep(200);
// Recheck props
fooRef = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), instance.getInstanceName());
@@ -337,12 +350,10 @@
assertEquals("Check baz equality", bazP, "zab");
assertEquals("Check propagated1 equality", prop1, "propagated");
assertEquals("Check propagated2 equality", prop2, new Integer(1));
-
- osgiHelper.getContext().ungetService(msRef);
}
@Test
- public void testPropagationNoValue() {
+ public void testPropagationNoValue() throws IOException, InterruptedException {
ServiceReference fooRef = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), instance2.getInstanceName());
assertNotNull("Check FS availability", fooRef);
@@ -353,8 +364,11 @@
assertEquals("Check bar equality -1", barP, null);
assertEquals("Check baz equality -1", bazP, null);
- ServiceReference msRef = ipojoHelper.getServiceReferenceByName(ManagedServiceFactory.class.getName(), instance2.getFactory().getName());
- assertNotNull("Check ManagedServiceFactory availability", msRef);
+ ConfigurationAdmin admin = osgiHelper.getServiceObject(ConfigurationAdmin.class);
+ assertNotNull("Check Configuration Admin availability", admin);
+
+ Configuration configuration = admin.getConfiguration(instance2.getInstanceName(),
+ getTestBundle().getLocation());
// Configuration of baz
Properties conf = new Properties();
@@ -363,12 +377,10 @@
conf.put("bar", new Integer(2));
conf.put("propagated1", "propagated");
conf.put("propagated2", new Integer(1));
- ManagedServiceFactory ms = (ManagedServiceFactory) osgiHelper.getContext().getService(msRef);
- try {
- ms.updated(instance2.getInstanceName(), conf);
- } catch (ConfigurationException e) {
- fail("Configuration Exception : " + e);
- }
+
+ // Asynchronous dispatching of the configuration
+ configuration.update(conf);
+ Thread.sleep(200);
// Recheck props
fooRef = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), instance2.getInstanceName());
@@ -385,8 +397,6 @@
assertEquals("Check baz equality", bazP, "zab");
assertEquals("Check propagated1 equality", prop1, "propagated");
assertEquals("Check propagated2 equality", prop2, new Integer(1));
-
- osgiHelper.getContext().ungetService(msRef);
}
}
diff --git a/ipojo/runtime/core-it/src/it/ipojo-core-configuration-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestUpdatedMethodAndManagedServiceFactory.java b/ipojo/runtime/core-it/src/it/ipojo-core-configuration-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestUpdatedMethodAndConfigAdmin.java
similarity index 79%
rename from ipojo/runtime/core-it/src/it/ipojo-core-configuration-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestUpdatedMethodAndManagedServiceFactory.java
rename to ipojo/runtime/core-it/src/it/ipojo-core-configuration-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestUpdatedMethodAndConfigAdmin.java
index 3bcb886..b0e3d0e 100644
--- a/ipojo/runtime/core-it/src/it/ipojo-core-configuration-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestUpdatedMethodAndManagedServiceFactory.java
+++ b/ipojo/runtime/core-it/src/it/ipojo-core-configuration-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestUpdatedMethodAndConfigAdmin.java
@@ -24,12 +24,17 @@
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
+import org.ops4j.pax.exam.spi.reactors.PerMethod;
import org.osgi.framework.ServiceReference;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ManagedServiceFactory;
import org.ow2.chameleon.testing.helpers.IPOJOHelper;
import org.ow2.chameleon.testing.helpers.OSGiHelper;
+import java.io.IOException;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.Properties;
@@ -37,14 +42,11 @@
import static junit.framework.Assert.*;
-public class TestUpdatedMethodAndManagedServiceFactory extends Common {
-
-
+@ExamReactorStrategy(PerMethod.class)
+public class TestUpdatedMethodAndConfigAdmin extends Common {
ComponentInstance instance, instance2;
-
-
@Before
public void setUp() {
osgiHelper = new OSGiHelper(bc);
@@ -74,7 +76,7 @@
}
@Test
- public void testStatic() {
+ public void testStatic() throws IOException, InterruptedException {
ServiceReference fooRef = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), instance.getInstanceName());
assertNotNull("Check FS availability", fooRef);
@@ -85,21 +87,21 @@
assertEquals("Check bar equality -1", barP, new Integer(2));
assertEquals("Check baz equality -1", bazP, "baz");
- ServiceReference msRef = ipojoHelper.getServiceReferenceByName(ManagedServiceFactory.class.getName(), instance.getFactory().getName());
- assertNotNull("Check ManagedServiceFactory availability", msRef);
+ ConfigurationAdmin admin = osgiHelper.getServiceObject(ConfigurationAdmin.class);
+ assertNotNull("Check Configuration Admin availability", admin);
+ Configuration configuration = admin.getConfiguration(instance.getInstanceName(),
+ getTestBundle().getLocation());
// Configuration of baz
Properties conf = new Properties();
conf.put("baz", "zab");
conf.put("bar", new Integer(2));
conf.put("foo", "foo");
- ManagedServiceFactory ms = (ManagedServiceFactory) osgiHelper.getServiceObject(msRef);
- try {
- ms.updated(instance.getInstanceName(), conf);
- } catch (ConfigurationException e) {
- fail("Configuration Exception : " + e);
- }
+
+ // Asynchronous dispatching of the configuration
+ configuration.update(conf);
+ Thread.sleep(200);
// Recheck props
fooRef = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), instance.getInstanceName());
@@ -121,7 +123,7 @@
}
@Test
- public void testStaticNoValue() {
+ public void testStaticNoValue() throws IOException, InterruptedException {
ServiceReference fooRef = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), instance2.getInstanceName());
assertNotNull("Check FS availability", fooRef);
Object fooP = fooRef.getProperty("foo");
@@ -131,21 +133,21 @@
assertEquals("Check bar equality -1", barP, null);
assertEquals("Check baz equality -1", bazP, null);
- ServiceReference msRef = ipojoHelper.getServiceReferenceByName(ManagedServiceFactory.class.getName(), instance2.getFactory().getName());
- assertNotNull("Check ManagedServiceFactory availability", msRef);
+ ConfigurationAdmin admin = osgiHelper.getServiceObject(ConfigurationAdmin.class);
+ assertNotNull("Check Configuration Admin availability", admin);
+ Configuration configuration = admin.getConfiguration(instance2.getInstanceName(),
+ getTestBundle().getLocation());
// Configuration of baz
Properties conf = new Properties();
conf.put("baz", "zab");
conf.put("bar", new Integer(2));
conf.put("foo", "foo");
- ManagedServiceFactory ms = (ManagedServiceFactory) osgiHelper.getServiceObject(msRef);
- try {
- ms.updated(instance2.getInstanceName(), conf);
- } catch (ConfigurationException e) {
- fail("Configuration Exception : " + e);
- }
+
+ // Asynchronous dispatching of the configuration
+ configuration.update(conf);
+ Thread.sleep(200);
// Recheck props
fooRef = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), instance2.getInstanceName());
@@ -166,7 +168,7 @@
}
@Test
- public void testDynamic() {
+ public void testDynamic() throws IOException, InterruptedException {
ServiceReference fooRef = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), instance.getInstanceName());
assertNotNull("Check FS availability", fooRef);
@@ -178,20 +180,21 @@
assertEquals("Check bar equality", barP, new Integer(2));
assertEquals("Check baz equality", bazP, "baz");
- ServiceReference msRef = ipojoHelper.getServiceReferenceByName(ManagedServiceFactory.class.getName(), instance.getFactory().getName());
- assertNotNull("Check ManagedServiceFactory availability", msRef);
+ ConfigurationAdmin admin = osgiHelper.getServiceObject(ConfigurationAdmin.class);
+ assertNotNull("Check Configuration Admin availability", admin);
+
+ Configuration configuration = admin.getConfiguration(instance.getInstanceName(),
+ getTestBundle().getLocation());
// Configuration of baz
Properties conf = new Properties();
conf.put("baz", "zab");
conf.put("foo", "oof");
conf.put("bar", new Integer(0));
- ManagedServiceFactory ms = (ManagedServiceFactory) osgiHelper.getServiceObject(msRef);
- try {
- ms.updated(instance.getInstanceName(), conf);
- } catch (ConfigurationException e) {
- fail("Configuration Exception : " + e);
- }
+
+ // Asynchronous dispatching of the configuration
+ configuration.update(conf);
+ Thread.sleep(200);
// Recheck props
fooRef = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), instance.getInstanceName());
@@ -220,7 +223,7 @@
}
@Test
- public void testDynamicNoValue() {
+ public void testDynamicNoValue() throws IOException, InterruptedException {
ServiceReference fooRef = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), instance2.getInstanceName());
assertNotNull("Check FS availability", fooRef);
@@ -231,20 +234,21 @@
assertEquals("Check bar equality -1", barP, null);
assertEquals("Check baz equality -1", bazP, null);
- ServiceReference msRef = ipojoHelper.getServiceReferenceByName(ManagedServiceFactory.class.getName(), instance2.getFactory().getName());
- assertNotNull("Check ManagedServiceFactory availability", msRef);
+ ConfigurationAdmin admin = osgiHelper.getServiceObject(ConfigurationAdmin.class);
+ assertNotNull("Check Configuration Admin availability", admin);
+
+ Configuration configuration = admin.getConfiguration(instance2.getInstanceName(),
+ getTestBundle().getLocation());
// Configuration of baz
Properties conf = new Properties();
conf.put("baz", "zab");
conf.put("foo", "oof");
conf.put("bar", new Integer(0));
- ManagedServiceFactory ms = (ManagedServiceFactory) osgiHelper.getServiceObject(msRef);
- try {
- ms.updated(instance2.getInstanceName(), conf);
- } catch (ConfigurationException e) {
- fail("Configuration Exception : " + e);
- }
+
+ // Asynchronous dispatching of the configuration
+ configuration.update(conf);
+ Thread.sleep(200);
// Recheck props
fooRef = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), instance2.getInstanceName());
@@ -275,7 +279,7 @@
@Test
- public void testDynamicString() {
+ public void testDynamicString() throws IOException, InterruptedException {
ServiceReference fooRef = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), instance.getInstanceName());
assertNotNull("Check FS availability", fooRef);
@@ -287,20 +291,21 @@
assertEquals("Check bar equality", barP, new Integer(2));
assertEquals("Check baz equality", bazP, "baz");
- ServiceReference msRef = ipojoHelper.getServiceReferenceByName(ManagedServiceFactory.class.getName(), instance.getFactory().getName());
- assertNotNull("Check ManagedServiceFactory availability", msRef);
+ ConfigurationAdmin admin = osgiHelper.getServiceObject(ConfigurationAdmin.class);
+ assertNotNull("Check Configuration Admin availability", admin);
+
+ Configuration configuration = admin.getConfiguration(instance.getInstanceName(),
+ getTestBundle().getLocation());
// Configuration of baz
Properties conf = new Properties();
conf.put("baz", "zab");
conf.put("foo", "oof");
conf.put("bar", "0");
- ManagedServiceFactory ms = (ManagedServiceFactory) osgiHelper.getServiceObject(msRef);
- try {
- ms.updated(instance.getInstanceName(), conf);
- } catch (ConfigurationException e) {
- fail("Configuration Exception : " + e);
- }
+
+ // Asynchronous dispatching of the configuration
+ configuration.update(conf);
+ Thread.sleep(200);
// Recheck props
fooRef = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), instance.getInstanceName());
diff --git a/ipojo/runtime/core-it/src/it/ipojo-core-configuration-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestUpdatedNoArgMethodAndManagedServiceFactory.java b/ipojo/runtime/core-it/src/it/ipojo-core-configuration-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestUpdatedNoArgMethodAndConfigAdmin.java
similarity index 77%
rename from ipojo/runtime/core-it/src/it/ipojo-core-configuration-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestUpdatedNoArgMethodAndManagedServiceFactory.java
rename to ipojo/runtime/core-it/src/it/ipojo-core-configuration-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestUpdatedNoArgMethodAndConfigAdmin.java
index 642f0bf..dcb4d12 100644
--- a/ipojo/runtime/core-it/src/it/ipojo-core-configuration-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestUpdatedNoArgMethodAndManagedServiceFactory.java
+++ b/ipojo/runtime/core-it/src/it/ipojo-core-configuration-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestUpdatedNoArgMethodAndConfigAdmin.java
@@ -24,19 +24,24 @@
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
+import org.ops4j.pax.exam.spi.reactors.PerMethod;
import org.osgi.framework.ServiceReference;
-import org.osgi.service.cm.ConfigurationException;
-import org.osgi.service.cm.ManagedServiceFactory;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
import org.ow2.chameleon.testing.helpers.IPOJOHelper;
import org.ow2.chameleon.testing.helpers.OSGiHelper;
+import java.io.IOException;
import java.util.Hashtable;
import java.util.Properties;
-import static org.junit.Assert.*;
+import static junit.framework.Assert.assertNotNull;
+import static org.junit.Assert.assertEquals;
-public class TestUpdatedNoArgMethodAndManagedServiceFactory extends Common {
+@ExamReactorStrategy(PerMethod.class)
+public class TestUpdatedNoArgMethodAndConfigAdmin extends Common {
@@ -72,7 +77,7 @@
}
@Test
- public void testStatic() {
+ public void testStatic() throws IOException, InterruptedException {
ServiceReference fooRef = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), instance.getInstanceName());
assertNotNull("Check FS availability", fooRef);
@@ -83,21 +88,21 @@
assertEquals("Check bar equality -1", barP, new Integer(2));
assertEquals("Check baz equality -1", bazP, "baz");
- ServiceReference msRef = ipojoHelper.getServiceReferenceByName(ManagedServiceFactory.class.getName(), instance.getFactory().getName());
- assertNotNull("Check ManagedServiceFactory availability", msRef);
+ ConfigurationAdmin admin = osgiHelper.getServiceObject(ConfigurationAdmin.class);
+ assertNotNull("Check Configuration Admin availability", admin);
+ Configuration configuration = admin.getConfiguration(instance.getInstanceName(),
+ getTestBundle().getLocation());
// Configuration of baz
Properties conf = new Properties();
conf.put("baz", "zab");
conf.put("bar", new Integer(2));
conf.put("foo", "foo");
- ManagedServiceFactory ms = (ManagedServiceFactory) osgiHelper.getServiceObject(msRef);
- try {
- ms.updated(instance.getInstanceName(), conf);
- } catch (ConfigurationException e) {
- fail("Configuration Exception : " + e);
- }
+
+ // Asynchronous dispatching of the configuration
+ configuration.update(conf);
+ Thread.sleep(200);
// Recheck props
fooRef = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), instance.getInstanceName());
@@ -117,7 +122,7 @@
}
@Test
- public void testStaticNoValue() {
+ public void testStaticNoValue() throws InterruptedException, IOException {
ServiceReference fooRef = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), instance2.getInstanceName());
assertNotNull("Check FS availability", fooRef);
Object fooP = fooRef.getProperty("foo");
@@ -127,21 +132,21 @@
assertEquals("Check bar equality -1", barP, null);
assertEquals("Check baz equality -1", bazP, null);
- ServiceReference msRef = ipojoHelper.getServiceReferenceByName(ManagedServiceFactory.class.getName(), instance2.getFactory().getName());
- assertNotNull("Check ManagedServiceFactory availability", msRef);
+ ConfigurationAdmin admin = osgiHelper.getServiceObject(ConfigurationAdmin.class);
+ assertNotNull("Check Configuration Admin availability", admin);
+ Configuration configuration = admin.getConfiguration(instance2.getInstanceName(),
+ getTestBundle().getLocation());
// Configuration of baz
Properties conf = new Properties();
conf.put("baz", "zab");
conf.put("bar", new Integer(2));
conf.put("foo", "foo");
- ManagedServiceFactory ms = (ManagedServiceFactory) osgiHelper.getServiceObject(msRef);
- try {
- ms.updated(instance2.getInstanceName(), conf);
- } catch (ConfigurationException e) {
- fail("Configuration Exception : " + e);
- }
+
+ // Asynchronous dispatching of the configuration
+ configuration.update(conf);
+ Thread.sleep(200);
// Recheck props
fooRef = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), instance2.getInstanceName());
@@ -160,7 +165,7 @@
}
@Test
- public void testDynamic() {
+ public void testDynamic() throws InterruptedException, IOException {
ServiceReference fooRef = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), instance.getInstanceName());
assertNotNull("Check FS availability", fooRef);
@@ -172,20 +177,21 @@
assertEquals("Check bar equality", barP, new Integer(2));
assertEquals("Check baz equality", bazP, "baz");
- ServiceReference msRef = ipojoHelper.getServiceReferenceByName(ManagedServiceFactory.class.getName(), instance.getFactory().getName());
- assertNotNull("Check ManagedServiceFactory availability", msRef);
+ ConfigurationAdmin admin = osgiHelper.getServiceObject(ConfigurationAdmin.class);
+ assertNotNull("Check Configuration Admin availability", admin);
+
+ Configuration configuration = admin.getConfiguration(instance.getInstanceName(),
+ getTestBundle().getLocation());
// Configuration of baz
Properties conf = new Properties();
conf.put("baz", "zab");
conf.put("foo", "oof");
conf.put("bar", new Integer(0));
- ManagedServiceFactory ms = (ManagedServiceFactory) osgiHelper.getServiceObject(msRef);
- try {
- ms.updated(instance.getInstanceName(), conf);
- } catch (ConfigurationException e) {
- fail("Configuration Exception : " + e);
- }
+
+ // Asynchronous dispatching of the configuration
+ configuration.update(conf);
+ Thread.sleep(200);
// Recheck props
fooRef = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), instance.getInstanceName());
@@ -212,7 +218,7 @@
}
@Test
- public void testDynamicNoValue() {
+ public void testDynamicNoValue() throws IOException, InterruptedException {
ServiceReference fooRef = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), instance2.getInstanceName());
assertNotNull("Check FS availability", fooRef);
@@ -223,20 +229,21 @@
assertEquals("Check bar equality -1", barP, null);
assertEquals("Check baz equality -1", bazP, null);
- ServiceReference msRef = ipojoHelper.getServiceReferenceByName(ManagedServiceFactory.class.getName(), instance2.getFactory().getName());
- assertNotNull("Check ManagedServiceFactory availability", msRef);
+ ConfigurationAdmin admin = osgiHelper.getServiceObject(ConfigurationAdmin.class);
+ assertNotNull("Check Configuration Admin availability", admin);
+
+ Configuration configuration = admin.getConfiguration(instance2.getInstanceName(),
+ getTestBundle().getLocation());
// Configuration of baz
Properties conf = new Properties();
conf.put("baz", "zab");
conf.put("foo", "oof");
conf.put("bar", new Integer(0));
- ManagedServiceFactory ms = (ManagedServiceFactory) osgiHelper.getServiceObject(msRef);
- try {
- ms.updated(instance2.getInstanceName(), conf);
- } catch (ConfigurationException e) {
- fail("Configuration Exception : " + e);
- }
+
+ // Asynchronous dispatching of the configuration
+ configuration.update(conf);
+ Thread.sleep(200);
// Recheck props
fooRef = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), instance2.getInstanceName());
@@ -264,7 +271,7 @@
@Test
- public void testDynamicString() {
+ public void testDynamicString() throws InterruptedException, IOException {
ServiceReference fooRef = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), instance.getInstanceName());
assertNotNull("Check FS availability", fooRef);
@@ -276,20 +283,21 @@
assertEquals("Check bar equality", barP, new Integer(2));
assertEquals("Check baz equality", bazP, "baz");
- ServiceReference msRef = ipojoHelper.getServiceReferenceByName(ManagedServiceFactory.class.getName(), instance.getFactory().getName());
- assertNotNull("Check ManagedServiceFactory availability", msRef);
+ ConfigurationAdmin admin = osgiHelper.getServiceObject(ConfigurationAdmin.class);
+ assertNotNull("Check Configuration Admin availability", admin);
+
+ Configuration configuration = admin.getConfiguration(instance.getInstanceName(),
+ getTestBundle().getLocation());
// Configuration of baz
Properties conf = new Properties();
conf.put("baz", "zab");
conf.put("foo", "oof");
conf.put("bar", "0");
- ManagedServiceFactory ms = (ManagedServiceFactory) osgiHelper.getServiceObject(msRef);
- try {
- ms.updated(instance.getInstanceName(), conf);
- } catch (ConfigurationException e) {
- fail("Configuration Exception : " + e);
- }
+
+ // Asynchronous dispatching of the configuration
+ configuration.update(conf);
+ Thread.sleep(200);
// Recheck props
fooRef = ipojoHelper.getServiceReferenceByName(FooService.class.getName(), instance.getInstanceName());
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/ComponentFactory.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/ComponentFactory.java
index 12e99ba..cf7199d 100644
--- a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/ComponentFactory.java
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/ComponentFactory.java
@@ -32,15 +32,13 @@
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
-import java.net.URL;
import java.security.ProtectionDomain;
import java.util.*;
/**
* The component factory manages component instance objects. This management
* consists to create and manage component instances build with the current
- * component factory. This class could export Factory and ManagedServiceFactory
- * services.
+ * component factory. If the factory is public a {@see Factory} service is exposed.
*
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
* @see IPojoFactory
@@ -182,16 +180,10 @@
} catch (ConfigurationException e) {
// An exception occurs while executing the configure or start
// methods.
- if (instance != null) {
- instance.dispose();
- instance = null;
- }
+ instance.dispose();
throw e;
} catch (Throwable e) { // All others exception are handled here.
- if (instance != null) {
- instance.dispose();
- instance = null;
- }
+ instance.dispose();
m_logger.log(Logger.ERROR, e.getMessage(), e);
throw new ConfigurationException(e.getMessage());
}
@@ -202,7 +194,7 @@
* Defines a class.
* This method needs to be synchronized to avoid that the classloader
* is created twice.
- * This method delegate the <code>define</code> method invocation to the
+ * This method delegates the <code>define</code> method invocation to the
* factory classloader.
*
* @param name the qualified name of the class
@@ -210,32 +202,18 @@
* @param domain the protection domain of the class
* @return the defined class object
*/
- public synchronized Class defineClass(String name, byte[] clazz, ProtectionDomain domain) {
+ public synchronized Class<? extends Object> defineClass(String name, byte[] clazz, ProtectionDomain domain) {
if (!m_useFactoryClassloader) {
m_logger.log(Log.WARNING, "A class definition was required even without the factory classloader enabled");
}
if (m_classLoader == null) {
- m_classLoader = new FactoryClassloader();
+ m_classLoader = new FactoryClassloader(this);
}
return m_classLoader.defineClass(name, clazz, domain);
}
/**
- * Returns the URL of a resource.
- * This methods delegates the invocation to the
- * {@link Bundle#getResource(String)} method.
- *
- * @param resName the resource name
- * @return the URL of the resource
- */
- public URL getResource(String resName) {
- //No synchronization needed, the context is immutable and
- //the call is managed by the underlying framework.
- return m_context.getBundle().getResource(resName);
- }
-
- /**
* Loads a class. This method checks if the class
* to load is the implementation class or not.
* If it is, the factory classloader is used, else
@@ -260,9 +238,7 @@
* This method is not called when holding the monitor lock.
*/
public void starting() {
- if (m_tracker != null) {
- return; // Already started
- } else {
+ if (m_tracker == null) {
if (m_requiredHandlers.size() != 0) {
try {
String filter = "(&(" + Handler.HANDLER_TYPE_PROPERTY + "=" + PrimitiveHandler.HANDLER_TYPE + ")" + "(factory.state=1)" + ")";
@@ -274,6 +250,7 @@
}
}
}
+ // Else, the tracking has already started.
}
/**
@@ -314,10 +291,9 @@
* @return the required handler list.
*/
public List getRequiredHandlerList() {
- List list = new ArrayList();
+ List<RequiredHandler> list = new ArrayList<RequiredHandler>();
Element[] elems = m_componentMetadata.getElements();
- for (int i = 0; i < elems.length; i++) {
- Element current = elems[i];
+ for (Element current : elems) {
if (!"manipulation".equals(current.getName())) { // Remove the manipulation element
RequiredHandler req = new RequiredHandler(current.getName(), current.getNameSpace());
if (!list.contains(req)) {
@@ -359,8 +335,8 @@
String v = System.getProperty(HANDLER_AUTO_PRIMITIVE);
if (v != null && v.length() != 0) {
String[] hs = ParseUtils.split(v, ",");
- for (int i = 0; i < hs.length; i++) {
- String h = hs[i].trim();
+ for (String h1 : hs) {
+ String h = h1.trim();
String[] segments = ParseUtils.split(h, ":");
RequiredHandler rq = null;
if (segments.length == 2) { // External handler
@@ -378,7 +354,6 @@
}
}
-
return list;
}
@@ -434,8 +409,8 @@
*/
public synchronized void removedService(ServiceReference reference, Object service) {
// Look for the implied reference and invalid the handler identifier
- for (int i = 0; i < m_requiredHandlers.size(); i++) {
- RequiredHandler req = (RequiredHandler) m_requiredHandlers.get(i);
+ for (Object m_requiredHandler : m_requiredHandlers) {
+ RequiredHandler req = (RequiredHandler) m_requiredHandler;
if (reference.equals(req.getReference())) {
req.unRef(); // This method will unget the service.
computeFactoryState();
@@ -480,251 +455,4 @@
return m_classLoader;
}
- /**
- * this class defines the classloader attached to a factory.
- * This class loader is used to load the implementation (e.g. manipulated)
- * class.
- *
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- * @see ClassLoader
- */
- private class FactoryClassloader extends ClassLoader {
-
- /**
- * The map of defined classes [Name, Class Object].
- */
- private final Map m_definedClasses = new HashMap();
-
- /**
- * The defineClass method.
- *
- * @param name name of the class
- * @param clazz the byte array of the class
- * @param domain the protection domain
- * @return the defined class.
- */
- public Class defineClass(String name, byte[] clazz, ProtectionDomain domain) {
- if (m_definedClasses.containsKey(name)) {
- return (Class) m_definedClasses.get(name);
- }
- Class clas = super.defineClass(name, clazz, 0, clazz.length, domain);
- m_definedClasses.put(name, clas);
- return clas;
- }
-
- /**
- * Returns the URL of the required resource.
- *
- * @param arg the name of the resource to find.
- * @return the URL of the resource.
- * @see java.lang.ClassLoader#getResource(java.lang.String)
- */
- public URL getResource(String arg) {
- return m_context.getBundle().getResource(arg);
- }
-
- /**
- * Loads the given class.
- *
- * @param name the name of the class
- * @param resolve should be the class resolve now ?
- * @return the loaded class object
- * @throws ClassNotFoundException if the class to load is not found
- * @see java.lang.ClassLoader#loadClass(java.lang.String, boolean)
- * @see java.lang.ClassLoader#loadClass(String, boolean)
- */
- protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException {
- return m_context.getBundle().loadClass(name);
- }
- }
-
- /**
- * This class defines the description of primitive (non-composite) component
- * types. An instance of this class will be returned when invoking the
- * {@link ComponentFactory#getComponentDescription()} method.
- *
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
- private final class PrimitiveTypeDescription extends ComponentTypeDescription {
-
- /*
- * Set to keep component's all super-class class-names.
- */
- private Set m_superClasses = new HashSet();
- /*
- * Set to keep component's all interface class-names.
- */
- private Set m_interfaces = new HashSet();
-
- /**
- * Creates a PrimitiveTypeDescription object.
- *
- * @param factory the factory attached to this component type description.
- */
- public PrimitiveTypeDescription(IPojoFactory factory) {
- super(factory);
-
- try {
- // The inspection can be done only for primitive components
- if (m_classname != null) {
- // Read inherited classes and interfaces into given Sets.
- new InheritanceInspector(getPojoMetadata(), getBundleContext().getBundle()).
- computeInterfacesAndSuperClasses(m_interfaces, m_superClasses);
- }
- } catch (ClassNotFoundException e) {
- m_interfaces.clear();
- m_superClasses.clear();
- }
-
- }
-
- /**
- * Computes the properties to publish.
- * The <code>component.class</code> property contains the implementation class name.
- *
- * @return the dictionary of properties to publish
- * @see org.apache.felix.ipojo.architecture.ComponentTypeDescription#getPropertiesToPublish()
- */
- public Dictionary getPropertiesToPublish() {
- Dictionary dict = super.getPropertiesToPublish();
- if (m_classname != null) {
- dict.put("component.class", m_classname);
- }
- return dict;
- }
-
- /**
- * Adds the "implementation-class" attribute to the type description.
- *
- * @return the component type description.
- * @see org.apache.felix.ipojo.architecture.ComponentTypeDescription#getDescription()
- */
- public Element getDescription() {
- Element elem = super.getDescription();
- elem.addAttribute(new Attribute("Implementation-Class", m_classname));
-
- /* Adding interfaces and super-classes of component into description */
- Element inheritance = new Element("Inherited", "");
-
- inheritance.addAttribute(new Attribute("Interfaces", m_interfaces.toString()));
- inheritance.addAttribute(new Attribute("SuperClasses", m_superClasses.toString()));
-
- elem.addElement(inheritance);
-
- return elem;
- }
-
- /**
- * This class is used to collect interfaces and super-classes of given component in specified Sets.
- *
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
- private final class InheritanceInspector {
- /*
- * PojoMetadata of target Component.
- */
- private PojoMetadata m_pojoMetadata;
- /*
- * Bundle exposing target component.
- */
- private Bundle m_bundle;
-
-
- /**
- * Creates a TypeCollector object
- *
- * @param pojoMetadata PojoMetadata describing Component.
- * @param bundle Bundle which has been exposed the intended Component.
- */
- public InheritanceInspector(PojoMetadata pojoMetadata, Bundle bundle) {
- m_pojoMetadata = pojoMetadata;
- m_bundle = bundle;
- }
-
- /**
- * Collect interfaces implemented by the POJO into given Sets.
- *
- * @param interfaces : the set of implemented interfaces
- * @param classes : the set of extended classes
- * @throws ClassNotFoundException : occurs when an interface cannot be loaded.
- */
- public void computeInterfacesAndSuperClasses(Set interfaces, Set classes) throws ClassNotFoundException {
- String[] immediateInterfaces = m_pojoMetadata.getInterfaces();
- String parentClass = m_pojoMetadata.getSuperClass();
-
- // First iterate on found specification in manipulation metadata
- for (int i = 0; i < immediateInterfaces.length; i++) {
- interfaces.add(immediateInterfaces[i]);
- // Iterate on interfaces implemented by the current interface
- Class clazz = m_bundle.loadClass(immediateInterfaces[i]);
- collectInterfaces(clazz, interfaces, m_bundle);
- }
-
- // Look for parent class.
- if (parentClass != null) {
- Class clazz = m_bundle.loadClass(parentClass);
- collectInterfacesFromClass(clazz, interfaces, m_bundle);
- classes.add(parentClass);
- collectParentClassesFromClass(clazz, classes, m_bundle);
- }
-
- // Removing Object Class from the inherited classes list.
- classes.remove(Object.class.getName());
- }
-
- /**
- * Look for inherited interfaces.
- *
- * @param clazz : interface name to explore (class object)
- * @param acc : set (accumulator)
- * @param bundle : bundle
- * @throws ClassNotFoundException : occurs when an interface cannot be loaded.
- */
- private void collectInterfaces(Class clazz, Set acc, Bundle bundle) throws ClassNotFoundException {
- Class[] clazzes = clazz.getInterfaces();
- for (int i = 0; i < clazzes.length; i++) {
- acc.add(clazzes[i].getName());
- collectInterfaces(clazzes[i], acc, bundle);
- }
- }
-
- /**
- * Collect interfaces for the given class.
- * This method explores super class to.
- *
- * @param clazz : class object.
- * @param acc : set of implemented interface (accumulator)
- * @param bundle : bundle.
- * @throws ClassNotFoundException : occurs if an interface cannot be load.
- */
- private void collectInterfacesFromClass(Class clazz, Set acc, Bundle bundle) throws ClassNotFoundException {
- Class[] clazzes = clazz.getInterfaces();
- for (int i = 0; i < clazzes.length; i++) {
- acc.add(clazzes[i].getName());
- collectInterfaces(clazzes[i], acc, bundle);
- }
- // Iterate on parent classes
- Class sup = clazz.getSuperclass();
- if (sup != null) {
- collectInterfacesFromClass(sup, acc, bundle);
- }
- }
-
- /**
- * Collect parent classes for the given class.
- *
- * @param clazz : class object.
- * @param acc : set of extended classes (accumulator)
- * @param bundle : bundle.
- * @throws ClassNotFoundException : occurs if an interface cannot be load.
- */
- private void collectParentClassesFromClass(Class clazz, Set acc, Bundle bundle) throws ClassNotFoundException {
- Class parent = clazz.getSuperclass();
- if (parent != null) {
- acc.add(parent.getName());
- collectParentClassesFromClass(parent, acc, bundle);
- }
- }
- }
- }
}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/ConfigurationTracker.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/ConfigurationTracker.java
new file mode 100644
index 0000000..df3b34b
--- /dev/null
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/ConfigurationTracker.java
@@ -0,0 +1,332 @@
+/*
+ * 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;
+
+import org.apache.felix.ipojo.extender.internal.Extender;
+import org.apache.felix.ipojo.util.Log;
+import org.apache.felix.ipojo.util.Logger;
+import org.apache.felix.ipojo.util.ServiceLocator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.cm.*;
+import org.osgi.service.cm.ConfigurationException;
+
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * An object tracking configuration from the configuration admin. It delegates to the underlying factories or
+ * component instance the action.
+ * <p/>
+ * This class implements a Configuration Listener, so events are received asynchronously.
+ */
+public class ConfigurationTracker implements ConfigurationListener {
+
+ /**
+ * The tracker instance.
+ */
+ private static ConfigurationTracker m_singleton;
+ private final ServiceRegistration<ConfigurationListener> m_registration;
+ private final BundleContext m_context;
+ private final Logger m_logger;
+ private Map<String, IPojoFactory> m_factories = new HashMap<String, IPojoFactory>();
+
+ public ConfigurationTracker() {
+ m_context = Extender.getIPOJOBundleContext();
+ m_logger = new Logger(m_context, "iPOJO Configuration Admin listener", Log.INFO);
+ // register as listener for configurations
+ Dictionary<String, Object> props = new Hashtable<String, Object>();
+ props.put(Constants.SERVICE_DESCRIPTION, "iPOJO Configuration Admin Listener");
+ props.put(Constants.SERVICE_VENDOR, "The Apache Software Foundation");
+ m_registration = m_context.registerService(ConfigurationListener.class, this, props);
+ }
+
+ public static void initialize() {
+ synchronized (ConfigurationTracker.class) {
+ if (m_singleton == null) {
+ m_singleton = new ConfigurationTracker();
+ }
+ }
+ }
+
+ public static void shutdown() {
+ m_singleton.dispose();
+ }
+
+ public static ConfigurationTracker get() {
+ return m_singleton;
+ }
+
+ /**
+ * This method must be called by the iPOJO System itself, and only once.
+ */
+ public synchronized void dispose() {
+ if (m_registration != null) {
+ m_registration.unregister();
+ }
+ m_factories.clear();
+ }
+
+ public synchronized void registerFactory(IPojoFactory factory) {
+ m_factories.put(factory.getFactoryName(), factory);
+
+ ServiceLocator<ConfigurationAdmin> locator = new ServiceLocator<ConfigurationAdmin>(ConfigurationAdmin
+ .class, m_context);
+ final ConfigurationAdmin admin = locator.get();
+ if (admin == null) {
+ return;
+ }
+
+ List<Configuration> configurations = findFactoryConfiguration(admin, factory);
+ for (Configuration configuration : configurations) {
+ try {
+ factory.updated(configuration.getPid(), configuration.getProperties());
+ } catch (ConfigurationException e) {
+ m_logger.log(Log.ERROR, "Cannot reconfigure instance " + configuration.getPid() + " from " +
+ configuration.getFactoryPid() + " with the configuration : " + configuration.getProperties(),
+ e);
+ }
+ }
+ }
+
+ public synchronized void instanceCreated(IPojoFactory factory, ComponentInstance instance) {
+ ServiceLocator<ConfigurationAdmin> locator = new ServiceLocator<ConfigurationAdmin>(ConfigurationAdmin
+ .class, m_context);
+ final ConfigurationAdmin admin = locator.get();
+ if (admin == null) {
+ return;
+ }
+
+ Configuration configuration = findSingletonConfiguration(admin, instance.getInstanceName());
+ if (configuration != null) {
+ Hashtable<String, Object> conf = copyConfiguration(configuration);
+ if (!conf.containsKey(Factory.INSTANCE_NAME_PROPERTY)) {
+ conf.put(Factory.INSTANCE_NAME_PROPERTY, configuration.getPid());
+ }
+ try {
+ instance.getFactory().reconfigure(conf);
+ } catch (UnacceptableConfiguration unacceptableConfiguration) {
+ m_logger.log(Log.ERROR, "Cannot reconfigure the instance " + configuration.getPid() + " - the " +
+ "configuration is unacceptable", unacceptableConfiguration);
+ } catch (MissingHandlerException e) {
+ m_logger.log(Log.ERROR, "Cannot reconfigure the instance " + configuration.getPid() + " - factory is " +
+ "invalid", e);
+ }
+ }
+ }
+
+ public synchronized void unregisterFactory(IPojoFactory factory) {
+ m_factories.remove(factory.getFactoryName());
+ }
+
+ public void configurationEvent(ConfigurationEvent event) {
+ String pid = event.getPid();
+ String factoryPid = event.getFactoryPid();
+
+ if (factoryPid == null) {
+ ComponentInstance instance = retrieveInstance(pid);
+ if (instance != null) {
+ manageConfigurationEventForSingleton(instance, event);
+ }
+ } else {
+ IPojoFactory factory = retrieveFactory(factoryPid);
+ if (factory != null) {
+ manageConfigurationEventForFactory(factory, event);
+ }
+ // Else the factory is unknown, do nothing.
+ }
+
+ }
+
+ private void manageConfigurationEventForFactory(final IPojoFactory factory, final ConfigurationEvent event) {
+ ServiceLocator<ConfigurationAdmin> locator = new ServiceLocator<ConfigurationAdmin>(ConfigurationAdmin
+ .class, m_context);
+
+ switch (event.getType()) {
+ case ConfigurationEvent.CM_DELETED:
+ factory.deleted(event.getPid());
+ break;
+ case ConfigurationEvent.CM_UPDATED:
+ final ConfigurationAdmin admin = locator.get();
+ if (admin == null) {
+ break;
+ }
+ final Configuration config = getConfiguration(admin, event.getPid(),
+ factory.getBundleContext().getBundle().getLocation());
+ if (config != null) {
+ try {
+ factory.updated(event.getPid(), config.getProperties());
+ } catch (org.osgi.service.cm.ConfigurationException e) {
+ m_logger.log(Log.ERROR, "Cannot reconfigure instance " + event.getPid() + " with the new " +
+ "configuration " + config.getProperties(), e);
+ }
+ }
+ default:
+ // To nothing.
+ }
+
+ locator.unget();
+ }
+
+ private void manageConfigurationEventForSingleton(final ComponentInstance instance,
+ final ConfigurationEvent event) {
+ ServiceLocator<ConfigurationAdmin> locator = new ServiceLocator<ConfigurationAdmin>(ConfigurationAdmin
+ .class, m_context);
+
+ switch (event.getType()) {
+ case ConfigurationEvent.CM_DELETED:
+ instance.dispose();
+ break;
+ case ConfigurationEvent.CM_UPDATED:
+ final ConfigurationAdmin admin = locator.get();
+ if (admin == null) {
+ break;
+ }
+ final Configuration config = getConfiguration(admin, event.getPid(),
+ instance.getFactory().getBundleContext().getBundle().getLocation());
+ if (config != null) {
+ Hashtable<String, Object> conf = copyConfiguration(config);
+ if (!conf.containsKey(Factory.INSTANCE_NAME_PROPERTY)) {
+ conf.put(Factory.INSTANCE_NAME_PROPERTY, event.getPid());
+ }
+ try {
+ instance.getFactory().reconfigure(conf);
+ } catch (UnacceptableConfiguration unacceptableConfiguration) {
+ m_logger.log(Log.ERROR, "Cannot reconfigure the instance " + event.getPid() + " - the " +
+ "configuration is unacceptable", unacceptableConfiguration);
+ } catch (MissingHandlerException e) {
+ m_logger.log(Log.ERROR, "Cannot reconfigure the instance " + event.getPid() + " - factory is " +
+ "invalid", e);
+ }
+ }
+ default:
+ // To nothing.
+ }
+
+ locator.unget();
+ }
+
+ private Hashtable<String, Object> copyConfiguration(Configuration config) {
+ Hashtable<String, Object> conf = new Hashtable<String, Object>();
+ // Copy configuration
+ Enumeration keys = config.getProperties().keys();
+ while (keys.hasMoreElements()) {
+ String key = (String) keys.nextElement();
+ conf.put(key, config.getProperties().get(key));
+ }
+ return conf;
+ }
+
+ private IPojoFactory retrieveFactory(String factoryPid) {
+ synchronized (this) {
+ return m_factories.get(factoryPid);
+ }
+ }
+
+ private ComponentInstance retrieveInstance(String instanceName) {
+ Collection<IPojoFactory> factories;
+ synchronized (this) {
+ factories = m_factories.values();
+ }
+ for (IPojoFactory factory : factories) {
+ ComponentInstance instance = factory.getInstanceByName(instanceName);
+ if (instance != null) {
+ return instance;
+ }
+ }
+ return null;
+ }
+
+ private Configuration getConfiguration(final ConfigurationAdmin admin, final String pid,
+ final String bundleLocation) {
+ if (admin == null) {
+ return null;
+ }
+
+ try {
+ // Even if it is possible, we don't build the filter with bundle.location to detect the case where the
+ // configuration exists but can't be managed by iPOJO.
+ final Configuration cfg = admin.getConfiguration(pid);
+
+ if (bundleLocation.equals(cfg.getBundleLocation())) {
+ return cfg;
+ }
+
+ // Multi-location with only ?
+ if (cfg.getBundleLocation().equals("?")) {
+ return cfg;
+ }
+
+ // Multi-location specifying the pid
+ if (cfg.getBundleLocation().startsWith("?")) {
+ String sn = cfg.getBundleLocation().substring(1); // Remove ?
+ if (sn.equals(pid)) {
+ return cfg;
+ }
+ }
+
+ // configuration belongs to another bundle, cannot be used here
+ m_logger.log(Log.ERROR, "Cannot use configuration pid=" + pid + " for bundle "
+ + bundleLocation + " because it belongs to bundle " + cfg.getBundleLocation());
+ } catch (IOException ioe) {
+ m_logger.log(Log.WARNING, "Failed reading configuration for pid=" + pid, ioe);
+ }
+
+ return null;
+ }
+
+ public List<Configuration> findFactoryConfiguration(final ConfigurationAdmin admin, final IPojoFactory factory) {
+ final String filter = "(service.factoryPid=" + factory.getFactoryName() + ")";
+ return findConfigurations(admin, filter);
+ }
+
+ public Configuration findSingletonConfiguration(final ConfigurationAdmin admin, final String pid) {
+ final String filter = "(service.pid=" + pid + ")";
+ List<Configuration> list = findConfigurations(admin, filter);
+ if (list.isEmpty()) {
+ return null;
+ } else {
+ return list.get(0);
+ }
+ }
+
+ private List<Configuration> findConfigurations(final ConfigurationAdmin admin, final String filter) {
+ List<Configuration> configurations = Collections.emptyList();
+ if (admin == null) {
+ return configurations;
+ }
+
+ try {
+ Configuration[] list = admin.listConfigurations(filter);
+ if (list == null) {
+ return configurations;
+ } else {
+ return Arrays.asList(list);
+ }
+ } catch (InvalidSyntaxException e) {
+ m_logger.log(Log.ERROR, "Invalid Configuration selection filter " + filter, e);
+ } catch (IOException e) {
+ m_logger.log(Log.ERROR, "Error when retrieving configurations for filter=" + filter, e);
+ }
+ return configurations;
+ }
+}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/FactoryClassloader.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/FactoryClassloader.java
new file mode 100644
index 0000000..eb1d5d7
--- /dev/null
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/FactoryClassloader.java
@@ -0,0 +1,88 @@
+/*
+ * 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;
+
+import java.net.URL;
+import java.security.ProtectionDomain;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * This class defines the classloader attached to a factory.
+ * This class loader is used to load the implementation (e.g. manipulated)
+ * class.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ * @see ClassLoader
+ */
+class FactoryClassloader extends ClassLoader {
+
+ /**
+ * The map of defined classes [Name, Class Object].
+ */
+ private final Map<String, Class<?>> m_definedClasses = new HashMap<String, Class<?>>();
+ private ComponentFactory factory;
+
+ public FactoryClassloader(ComponentFactory factory) {
+ this.factory = factory;
+ }
+
+ /**
+ * The defineClass method.
+ *
+ * @param name name of the class
+ * @param clazz the byte array of the class
+ * @param domain the protection domain
+ * @return the defined class.
+ */
+ public Class<?> defineClass(String name, byte[] clazz, ProtectionDomain domain) {
+ if (m_definedClasses.containsKey(name)) {
+ return m_definedClasses.get(name);
+ }
+ Class clas = super.defineClass(name, clazz, 0, clazz.length, domain);
+ m_definedClasses.put(name, clas);
+ return clas;
+ }
+
+ /**
+ * Returns the URL of the required resource.
+ *
+ * @param arg the name of the resource to find.
+ * @return the URL of the resource.
+ * @see ClassLoader#getResource(String)
+ */
+ public URL getResource(String arg) {
+ return factory.m_context.getBundle().getResource(arg);
+ }
+
+ /**
+ * Loads the given class.
+ *
+ * @param name the name of the class
+ * @param resolve should be the class resolve now ?
+ * @return the loaded class object
+ * @throws ClassNotFoundException if the class to load is not found
+ * @see ClassLoader#loadClass(String, boolean)
+ * @see ClassLoader#loadClass(String, boolean)
+ */
+ protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException {
+ return factory.m_context.getBundle().loadClass(name);
+ }
+}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/IPojoFactory.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/IPojoFactory.java
index 85cb3f1..a5b34a2 100644
--- a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/IPojoFactory.java
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/IPojoFactory.java
@@ -35,8 +35,10 @@
/**
* This class defines common mechanisms of iPOJO component factories
* (i.e. component type).
- * This class implements both the Factory and ManagedServiceFactory
- * services.
+ *
+ * The factory is also tracking Factory configuration from the configuration admin to created / delete and update
+ * instances from this factory.
+ *
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public abstract class IPojoFactory implements Factory, ManagedServiceFactory {
@@ -49,7 +51,7 @@
* The list of the managed instance name.
* This list is shared by all factories and is used to assert name uniqueness.
*/
- protected static final List INSTANCE_NAME = Collections.synchronizedList(new ArrayList());
+ protected static final List<String> INSTANCE_NAME = Collections.synchronizedList(new ArrayList<String>());
/**
* The component type description exposed by the {@link Factory} service.
@@ -60,7 +62,7 @@
* The list of the managed instance managers.
* The key of this map is the name (i.e. instance names) of the created instance
*/
- protected final Map m_componentInstances = new HashMap();
+ protected final Map<String, ComponentInstance> m_componentInstances = new HashMap<String, ComponentInstance>();
/**
* The component type metadata.
@@ -82,13 +84,13 @@
/**
* The list of required handlers.
*/
- protected List m_requiredHandlers = new ArrayList();
+ protected List<RequiredHandler> m_requiredHandlers = new ArrayList<RequiredHandler>();
/**
* The list of factory state listeners.
* @see FactoryStateListener
*/
- protected List m_listeners = new ArrayList(1);
+ protected List<FactoryStateListener> m_listeners = new ArrayList<FactoryStateListener>(1);
/**
* The logger for the factory.
@@ -202,7 +204,7 @@
* Each sub-type must override this method.
* @return the required handler list
*/
- public abstract List getRequiredHandlerList();
+ public abstract List<RequiredHandler> getRequiredHandlerList();
/**
* Creates an instance.
@@ -292,14 +294,15 @@
// Here we are sure to be valid until the end of the method.
HandlerManager[] handlers = new HandlerManager[m_requiredHandlers.size()];
for (int i = 0; i < handlers.length; i++) {
- RequiredHandler req = (RequiredHandler) m_requiredHandlers.get(i);
- handlers[i] = getHandler(req, serviceContext);
+ handlers[i] = getHandler(m_requiredHandlers.get(i), serviceContext);
}
try {
ComponentInstance instance = createInstance(configuration, context, handlers);
m_componentInstances.put(name, instance);
m_logger.log(Logger.INFO, "Instance " + name + " from factory " + m_factoryName + " created");
+ // Register the instance on the ConfigurationTracker to be updated if needed.
+ ConfigurationTracker.get().instanceCreated(this, instance);
return instance;
} catch (ConfigurationException e) {
INSTANCE_NAME.remove(name);
@@ -361,10 +364,9 @@
* @return the list of missing handlers.
* @see org.apache.felix.ipojo.Factory#getMissingHandlers()
*/
- public List getMissingHandlers() {
- List list = new ArrayList();
- for (int i = 0; i < m_requiredHandlers.size(); i++) {
- RequiredHandler req = (RequiredHandler) m_requiredHandlers.get(i);
+ public List<String> getMissingHandlers() {
+ List<String> list = new ArrayList<String>();
+ for (RequiredHandler req : m_requiredHandlers) {
if (req.getReference() == null) {
list.add(req.getFullName());
}
@@ -389,10 +391,9 @@
* @return the list of required handlers.
* @see org.apache.felix.ipojo.Factory#getRequiredHandlers()
*/
- public synchronized List getRequiredHandlers() {
- List list = new ArrayList();
- for (int i = 0; i < m_requiredHandlers.size(); i++) {
- RequiredHandler req = (RequiredHandler) m_requiredHandlers.get(i);
+ public synchronized List<String> getRequiredHandlers() {
+ List<String> list = new ArrayList<String>();
+ for (RequiredHandler req : m_requiredHandlers) {
list.add(req.getFullName());
}
return list;
@@ -409,6 +410,17 @@
}
/**
+ * Gets a component instance created by the current factory.
+ * @param name the instance name
+ * @return the component instance, {@literal null} if not found
+ */
+ public ComponentInstance getInstanceByName(String name) {
+ synchronized (this) {
+ return m_componentInstances.get(name);
+ }
+ }
+
+ /**
* Checks if the configuration is acceptable.
* @param conf the configuration to test.
* @return <code>true</code> if the configuration is acceptable.
@@ -435,7 +447,8 @@
* @throws UnacceptableConfiguration if the configuration is unacceptable.
* @throws MissingHandlerException if an handler is missing.
*/
- public void checkAcceptability(Dictionary conf) throws UnacceptableConfiguration, MissingHandlerException {
+ public void checkAcceptability(Dictionary<String, ?> conf) throws UnacceptableConfiguration,
+ MissingHandlerException {
PropertyDescription[] props;
synchronized (this) {
if (m_state == Factory.INVALID) {
@@ -447,14 +460,15 @@
// Check that the configuration does not override immutable properties.
- for (int i = 0; i < props.length; i++) {
+ for (PropertyDescription prop : props) {
// Is the property immutable
- if (props[i].isImmutable() && conf.get(props[i].getName()) != null) {
- throw new UnacceptableConfiguration("The property " + props[i] + " cannot be overide : immutable property"); // The instance configuration tries to override an immutable property.
+ if (prop.isImmutable() && conf.get(prop.getName()) != null) {
+ throw new UnacceptableConfiguration("The property " + prop + " cannot be overridden : immutable " +
+ "property"); // The instance configuration tries to override an immutable property.
}
// Is the property required ?
- if (props[i].isMandatory() && props[i].getValue() == null && conf.get(props[i].getName()) == null) {
- throw new UnacceptableConfiguration("The mandatory property " + props[i].getName() + " is missing"); // The property must be set.
+ if (prop.isMandatory() && prop.getValue() == null && conf.get(prop.getName()) == null) {
+ throw new UnacceptableConfiguration("The mandatory property " + prop.getName() + " is missing"); // The property must be set.
}
}
}
@@ -480,7 +494,7 @@
name = (String) properties.get("name");
}
- ComponentInstance instance = (ComponentInstance) m_componentInstances.get(name);
+ ComponentInstance instance = m_componentInstances.get(name);
if (instance == null) { // The instance does not exists.
return;
}
@@ -520,13 +534,16 @@
m_sr.unregister();
m_sr = null;
}
+
+ ConfigurationTracker.get().unregisterFactory(this);
+
stopping(); // Method called when holding the lock.
int oldState = m_state; // Create a variable to store the old state. Using a variable is important as
// after the next instruction, the getState() method must return INVALID.
m_state = INVALID; // Set here to avoid to create instances during the stops.
- Set col = m_componentInstances.keySet();
- Iterator it = col.iterator();
+ Set<String> col = m_componentInstances.keySet();
+ Iterator<String> it = col.iterator();
instances = new ComponentInstance[col.size()]; // Stack confinement
int index = 0;
while (it.hasNext()) {
@@ -535,23 +552,23 @@
}
if (oldState == VALID) { // Check if the old state was valid.
- for (int i = 0; i < m_listeners.size(); i++) {
- ((FactoryStateListener) m_listeners.get(i)).stateChanged(this, INVALID);
+ for (FactoryStateListener listener : m_listeners) {
+ listener.stateChanged(this, INVALID);
}
}
// Dispose created instances.
- for (int i = 0; i < instances.length; i++) {
- ComponentInstance instance = instances[i];
+ for (ComponentInstance instance : instances) {
if (instance.getState() != ComponentInstance.DISPOSED) {
instance.dispose();
}
}
// Release each handler
- for (int i = 0; i < m_requiredHandlers.size(); i++) {
- ((RequiredHandler) m_requiredHandlers.get(i)).unRef();
+ for (RequiredHandler req : m_requiredHandlers) {
+ req.unRef();
}
+
m_described = false;
m_componentDesc = null;
m_componentInstances.clear();
@@ -601,13 +618,17 @@
if (m_isPublic) {
// Exposition of the factory service
if (m_componentDesc == null) {
- System.out.println("Description of " + m_factoryName + " " + m_componentDesc);
+ m_logger.log(Logger.ERROR, "Unexpected state, the description of " + m_factoryName + " is null");
+ return;
}
BundleContext bc = SecurityHelper.selectContextToRegisterServices(m_componentDesc.getFactoryInterfacesToPublish(),
m_context, getIPOJOBundleContext());
m_sr =
bc.registerService(m_componentDesc.getFactoryInterfacesToPublish(), this, m_componentDesc
.getPropertiesToPublish());
+
+ // Register the factory on the ConfigurationTracker
+ ConfigurationTracker.get().registerFactory(this);
}
m_logger.log(Logger.INFO, "Factory " + m_factoryName + " started");
@@ -637,11 +658,12 @@
* @param properties the new configuration of the instance
* @throws org.osgi.service.cm.ConfigurationException if the configuration is not consistent for this component type
* @see org.osgi.service.cm.ManagedServiceFactory#updated(java.lang.String, java.util.Dictionary)
+ * TODO this method should disappear.
*/
public void updated(String name, Dictionary properties) throws org.osgi.service.cm.ConfigurationException {
ComponentInstance instance;
synchronized (this) {
- instance = (ComponentInstance) m_componentInstances.get(name);
+ instance = m_componentInstances.get(name);
}
if (instance == null) {
@@ -677,6 +699,7 @@
* Deletes an instance.
* @param name the name of the instance to delete
* @see org.osgi.service.cm.ManagedServiceFactory#deleted(java.lang.String)
+ * todo this method should disappear.
*/
public synchronized void deleted(String name) {
INSTANCE_NAME.remove(name);
@@ -707,9 +730,7 @@
* This method is called with the lock.
*/
protected void computeDescription() {
- for (int i = 0; i < m_requiredHandlers.size(); i++) {
- RequiredHandler req = (RequiredHandler) m_requiredHandlers.get(i);
-
+ for (RequiredHandler req : m_requiredHandlers) {
if (getHandler(req, null) == null) {
// TODO this does not really looks good.
m_logger.log(Logger.ERROR, "Cannot extract handler object from " + m_factoryName + " " + req
@@ -720,7 +741,7 @@
handler.setFactory(this);
handler.initializeComponentFactory(m_componentDesc, m_componentMetadata);
((Pojo) handler).getComponentInstance().dispose();
- } catch (org.apache.felix.ipojo.ConfigurationException e) {
+ } catch (ConfigurationException e) {
((Pojo) handler).getComponentInstance().dispose();
m_logger.log(Logger.ERROR, e.getMessage());
stop();
@@ -739,8 +760,7 @@
*/
protected void computeFactoryState() {
boolean isValid = true;
- for (int i = 0; i < m_requiredHandlers.size(); i++) {
- RequiredHandler req = (RequiredHandler) m_requiredHandlers.get(i);
+ for (RequiredHandler req : m_requiredHandlers) {
if (req.getReference() == null) {
isValid = false;
break;
@@ -760,25 +780,24 @@
if (m_sr != null) {
m_sr.setProperties(m_componentDesc.getPropertiesToPublish());
}
- for (int i = 0; i < m_listeners.size(); i++) {
- ((FactoryStateListener) m_listeners.get(i)).stateChanged(this, VALID);
+ for (FactoryStateListener listener : m_listeners) {
+ listener.stateChanged(this, VALID);
}
- return;
}
} else {
if (m_state == VALID) {
m_state = INVALID;
// Notify listeners.
- for (int i = 0; i < m_listeners.size(); i++) {
- ((FactoryStateListener) m_listeners.get(i)).stateChanged(this, INVALID);
+ for (FactoryStateListener listener : m_listeners) {
+ listener.stateChanged(this, INVALID);
}
// Dispose created instances.
- Set col = m_componentInstances.keySet();
- String[] keys = (String[]) col.toArray(new String[col.size()]);
- for (int i = 0; i < keys.length; i++) {
- ComponentInstance instance = (ComponentInstance) m_componentInstances.get(keys[i]);
+ // We must create a copy to avoid concurrent exceptions
+ Set<? extends String> keys = new HashSet<String>(m_componentInstances.keySet());
+ for (String key : keys) {
+ ComponentInstance instance = m_componentInstances.get(key);
if (instance.getState() != ComponentInstance.DISPOSED) {
instance.dispose();
}
@@ -790,8 +809,6 @@
if (m_sr != null) {
m_sr.setProperties(m_componentDesc.getPropertiesToPublish());
}
-
- return;
}
}
}
@@ -803,7 +820,7 @@
* @param ref the service reference.
* @return <code>true</code> if the service reference can fulfill the handler requirement
*/
- protected boolean match(RequiredHandler req, ServiceReference ref) {
+ protected boolean match(RequiredHandler req, ServiceReference<? extends Object> ref) {
String name = (String) ref.getProperty(Handler.HANDLER_NAME_PROPERTY);
String namespace = (String) ref.getProperty(Handler.HANDLER_NAMESPACE_PROPERTY);
if (HandlerFactory.IPOJO_NAMESPACE.equals(namespace)) {
@@ -927,7 +944,7 @@
return null;
}
if (m_factory == null) {
- m_factory = (HandlerFactory) m_context.getService(getReference());
+ m_factory = m_context.getService(getReference());
}
return m_factory;
}
@@ -952,7 +969,7 @@
return m_namespace;
}
- public ServiceReference getReference() {
+ public ServiceReference<? extends HandlerFactory> getReference() {
return m_reference;
}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/PrimitiveTypeDescription.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/PrimitiveTypeDescription.java
new file mode 100644
index 0000000..6e61112
--- /dev/null
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/PrimitiveTypeDescription.java
@@ -0,0 +1,228 @@
+/*
+ * 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;
+
+import org.apache.felix.ipojo.architecture.ComponentTypeDescription;
+import org.apache.felix.ipojo.metadata.Attribute;
+import org.apache.felix.ipojo.metadata.Element;
+import org.apache.felix.ipojo.parser.PojoMetadata;
+import org.osgi.framework.Bundle;
+
+import java.util.Dictionary;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * This class defines the description of primitive (non-composite) component
+ * types. An instance of this class will be returned when invoking the
+ * {@link org.apache.felix.ipojo.ComponentFactory#getComponentDescription()} method.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+final class PrimitiveTypeDescription extends ComponentTypeDescription {
+
+ /**
+ * Set to keep component's all super-class class-names.
+ */
+ private Set<String> m_superClasses = new HashSet<String>();
+
+ /**
+ * Set to keep component's all interface class-names.
+ */
+ private Set<String> m_interfaces = new HashSet<String>();
+
+ /**
+ * The described component factory.
+ */
+ private ComponentFactory m_factory;
+
+ /**
+ * Creates a PrimitiveTypeDescription object.
+ *
+ * @param factory the m_factory attached to this component type description.
+ */
+ public PrimitiveTypeDescription(ComponentFactory factory) {
+ super(factory);
+ this.m_factory = factory;
+
+ try {
+ // The inspection can be done only for primitive components
+ if (factory.getClassName() != null) {
+ // Read inherited classes and interfaces into given Sets.
+ new InheritanceInspector(factory.getPojoMetadata(), getBundleContext().getBundle()).
+ computeInterfacesAndSuperClasses(m_interfaces, m_superClasses);
+ }
+ } catch (ClassNotFoundException e) {
+ m_interfaces.clear();
+ m_superClasses.clear();
+ }
+
+ }
+
+ /**
+ * Computes the properties to publish.
+ * The <code>component.class</code> property contains the implementation class name.
+ *
+ * @return the dictionary of properties to publish
+ * @see org.apache.felix.ipojo.architecture.ComponentTypeDescription#getPropertiesToPublish()
+ */
+ public Dictionary<String, Object> getPropertiesToPublish() {
+ Dictionary<String, Object> dict = super.getPropertiesToPublish();
+ if (m_factory.getClassName() != null) {
+ dict.put("component.class", m_factory.getClassName());
+ }
+ return dict;
+ }
+
+ /**
+ * Adds the "implementation-class" attribute to the type description.
+ *
+ * @return the component type description.
+ * @see org.apache.felix.ipojo.architecture.ComponentTypeDescription#getDescription()
+ */
+ public Element getDescription() {
+ Element elem = super.getDescription();
+ elem.addAttribute(new Attribute("Implementation-Class", m_factory.getClassName()));
+
+ /* Adding interfaces and super-classes of component into description */
+ Element inheritance = new Element("Inherited", "");
+
+ inheritance.addAttribute(new Attribute("Interfaces", m_interfaces.toString()));
+ inheritance.addAttribute(new Attribute("SuperClasses", m_superClasses.toString()));
+
+ elem.addElement(inheritance);
+
+ return elem;
+ }
+
+ /**
+ * This class is used to collect interfaces and super-classes of given component in specified Sets.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+ private final class InheritanceInspector {
+ /*
+ * PojoMetadata of target Component.
+ */
+ private PojoMetadata m_pojoMetadata;
+ /*
+ * Bundle exposing target component.
+ */
+ private Bundle m_bundle;
+
+
+ /**
+ * Creates a TypeCollector object
+ *
+ * @param pojoMetadata PojoMetadata describing Component.
+ * @param bundle Bundle which has been exposed the intended Component.
+ */
+ public InheritanceInspector(PojoMetadata pojoMetadata, Bundle bundle) {
+ m_pojoMetadata = pojoMetadata;
+ m_bundle = bundle;
+ }
+
+ /**
+ * Collect interfaces implemented by the POJO into given Sets.
+ *
+ * @param interfaces : the set of implemented interfaces
+ * @param classes : the set of extended classes
+ * @throws ClassNotFoundException : occurs when an interface cannot be loaded.
+ */
+ public void computeInterfacesAndSuperClasses(Set<String> interfaces, Set<String> classes) throws ClassNotFoundException {
+ String[] immediateInterfaces = m_pojoMetadata.getInterfaces();
+ String parentClass = m_pojoMetadata.getSuperClass();
+
+ // First iterate on found specification in manipulation metadata
+ for (String immediateInterface : immediateInterfaces) {
+ interfaces.add(immediateInterface);
+ // Iterate on interfaces implemented by the current interface
+ Class<?> clazz = m_bundle.loadClass(immediateInterface);
+ collectInterfaces(clazz, interfaces, m_bundle);
+ }
+
+ // Look for parent class.
+ if (parentClass != null) {
+ Class clazz = m_bundle.loadClass(parentClass);
+ collectInterfacesFromClass(clazz, interfaces, m_bundle);
+ classes.add(parentClass);
+ collectParentClassesFromClass(clazz, classes, m_bundle);
+ }
+
+ // Removing Object Class from the inherited classes list.
+ classes.remove(Object.class.getName());
+ }
+
+ /**
+ * Look for inherited interfaces.
+ *
+ * @param clazz : interface name to explore (class object)
+ * @param acc : set (accumulator)
+ * @param bundle : bundle
+ * @throws ClassNotFoundException : occurs when an interface cannot be loaded.
+ */
+ private void collectInterfaces(Class<?> clazz, Set<String> acc, Bundle bundle) throws ClassNotFoundException {
+ Class[] clazzes = clazz.getInterfaces();
+ for (Class clazze : clazzes) {
+ acc.add(clazze.getName());
+ collectInterfaces(clazze, acc, bundle);
+ }
+ }
+
+ /**
+ * Collect interfaces for the given class.
+ * This method explores super class to.
+ *
+ * @param clazz : class object.
+ * @param acc : set of implemented interface (accumulator)
+ * @param bundle : bundle.
+ * @throws ClassNotFoundException : occurs if an interface cannot be load.
+ */
+ private void collectInterfacesFromClass(Class<?> clazz, Set<String> acc,
+ Bundle bundle) throws ClassNotFoundException {
+ Class[] clazzes = clazz.getInterfaces();
+ for (Class clazze : clazzes) {
+ acc.add(clazze.getName());
+ collectInterfaces(clazze, acc, bundle);
+ }
+ // Iterate on parent classes
+ Class sup = clazz.getSuperclass();
+ if (sup != null) {
+ collectInterfacesFromClass(sup, acc, bundle);
+ }
+ }
+
+ /**
+ * Collect parent classes for the given class.
+ *
+ * @param clazz : class object.
+ * @param acc : set of extended classes (accumulator)
+ * @param bundle : bundle.
+ * @throws ClassNotFoundException : occurs if an interface cannot be load.
+ */
+ private void collectParentClassesFromClass(Class<?> clazz, Set<String> acc, Bundle bundle) throws ClassNotFoundException {
+ Class<?> parent = clazz.getSuperclass();
+ if (parent != null) {
+ acc.add(parent.getName());
+ collectParentClassesFromClass(parent, acc, bundle);
+ }
+ }
+ }
+}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/architecture/ComponentTypeDescription.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/architecture/ComponentTypeDescription.java
index a2d02d6..d1193fb 100644
--- a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/architecture/ComponentTypeDescription.java
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/architecture/ComponentTypeDescription.java
@@ -18,11 +18,6 @@
*/
package org.apache.felix.ipojo.architecture;
-import java.util.Dictionary;
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.Properties;
-
import org.apache.felix.ipojo.Factory;
import org.apache.felix.ipojo.IPojoFactory;
import org.apache.felix.ipojo.metadata.Attribute;
@@ -31,34 +26,37 @@
import org.osgi.framework.Constants;
import org.osgi.service.cm.ManagedServiceFactory;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
/**
* Component Type description.
+ *
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public class ComponentTypeDescription {
/**
+ * Represented factory.
+ */
+ private final IPojoFactory m_factory;
+ /**
* Provided service by the component type.
*/
private String[] m_providedServiceSpecification = new String[0];
-
/**
* Configuration Properties accepted by the component type.
*/
private PropertyDescription[] m_properties = new PropertyDescription[0];
-
/*
* Used by custom handlers to keep and retrieve custom info.
*/
private Dictionary m_handlerInfoSlot = new Hashtable();
/**
- * Represented factory.
- */
- private final IPojoFactory m_factory;
-
- /**
* Constructor.
+ *
* @param factory : represented factory.
*/
public ComponentTypeDescription(IPojoFactory factory) {
@@ -67,6 +65,7 @@
/**
* Gets the attached factory.
+ *
* @return the factory
*/
public IPojoFactory getFactory() {
@@ -75,6 +74,7 @@
/**
* Gets a printable form of the current component type description.
+ *
* @return printable form of the component type description
* @see java.lang.Object#toString()
*/
@@ -84,6 +84,7 @@
/**
* Gets the implementation class of this component type.
+ *
* @return the component type implementation class name.
* @deprecated
*/
@@ -93,8 +94,9 @@
/**
* Gets the component type version.
+ *
* @return the component type version or
- * <code>null</code> if not set.
+ * <code>null</code> if not set.
*/
public String getVersion() {
return m_factory.getVersion();
@@ -102,6 +104,7 @@
/**
* Gets component-type properties.
+ *
* @return the list of configuration properties accepted by the component type type.
*/
public PropertyDescription[] getProperties() {
@@ -110,7 +113,8 @@
/**
* Adds a String property in the component type.
- * @param name : property name.
+ *
+ * @param name : property name.
* @param value : property value.
*/
public void addProperty(String name, String value) {
@@ -119,8 +123,9 @@
/**
* Adds a String property in the component type.
- * @param name : property name.
- * @param value : property value.
+ *
+ * @param name : property name.
+ * @param value : property value.
* @param immutable : the property is immutable.
*/
public void addProperty(String name, String value, boolean immutable) {
@@ -130,6 +135,7 @@
/**
* Adds a configuration properties to the component type.
+ *
* @param pd : the property to add
*/
public void addProperty(PropertyDescription pd) { //NOPMD remove the instance name of the 'name' property.
@@ -138,7 +144,9 @@
// Check if the property is not already in the array
for (int i = 0; i < m_properties.length; i++) {
PropertyDescription desc = m_properties[i];
- if (desc.getName().equals(name)) { return; }
+ if (desc.getName().equals(name)) {
+ return;
+ }
}
PropertyDescription[] newProps = new PropertyDescription[m_properties.length + 1];
@@ -146,35 +154,32 @@
newProps[m_properties.length] = pd;
m_properties = newProps;
}
-
+
/**
* Adds the HandlerInfo for specified handler.
- * @param handlerNs Handler's namespace
+ *
+ * @param handlerNs Handler's namespace
* @param handlerName Handler's name
- * @param info HandlerInfo associated with the given custom handler.
+ * @param info HandlerInfo associated with the given custom handler.
*/
- public void setHandlerInfo(String handlerNs, String handlerName, CustomHandlerInfo info)
- {
- String fullHandlerName = handlerNs + ":" + handlerName;
-
- if(info == null)
- {
- m_handlerInfoSlot.remove(fullHandlerName);
- }
- else
- {
- m_handlerInfoSlot.put(fullHandlerName, info);
- }
+ public void setHandlerInfo(String handlerNs, String handlerName, CustomHandlerInfo info) {
+ String fullHandlerName = handlerNs + ":" + handlerName;
+
+ if (info == null) {
+ m_handlerInfoSlot.remove(fullHandlerName);
+ } else {
+ m_handlerInfoSlot.put(fullHandlerName, info);
+ }
}
-
- public CustomHandlerInfo getHandlerInfo(String handlerNs, String handlerName)
- {
- String fullHandlerName = handlerNs + ":" + handlerName;
- return (CustomHandlerInfo)m_handlerInfoSlot.get(fullHandlerName);
+
+ public CustomHandlerInfo getHandlerInfo(String handlerNs, String handlerName) {
+ String fullHandlerName = handlerNs + ":" + handlerName;
+ return (CustomHandlerInfo) m_handlerInfoSlot.get(fullHandlerName);
}
/**
* Gets the list of provided service offered by instances of this type.
+ *
* @return the list of the provided service.
*/
public String[] getprovidedServiceSpecification() {
@@ -183,6 +188,7 @@
/**
* Adds a provided service to the component type.
+ *
* @param serviceSpecification : the provided service to add (interface name)
*/
public void addProvidedServiceSpecification(String serviceSpecification) {
@@ -194,6 +200,7 @@
/**
* Returns the component-type name.
+ *
* @return the name of this component type
*/
public String getName() {
@@ -203,10 +210,11 @@
/**
* Computes the default service properties to publish :
* factory.name, service.pid, component.providedServiceSpecification, component.properties, component.description, factory.State.
+ *
* @return : the dictionary of properties to publish.
*/
- public Dictionary getPropertiesToPublish() {
- Properties props = new Properties();
+ public Dictionary<String, Object> getPropertiesToPublish() {
+ Hashtable<String, Object> props = new Hashtable<String, Object>();
props.put("factory.name", m_factory.getName());
props.put(Constants.SERVICE_PID, m_factory.getName()); // Service PID is required for the integration in the configuration admin.
@@ -222,14 +230,14 @@
props.put("component.description", this);
// add every immutable property
- for (int i = 0; i < m_properties.length; i++) {
- if (m_properties[i].isImmutable() && m_properties[i].getValue() != null) {
- props.put(m_properties[i].getName(), m_properties[i].getObjectValue(m_factory.getBundleContext()));
+ for (PropertyDescription m_property : m_properties) {
+ if (m_property.isImmutable() && m_property.getValue() != null) {
+ props.put(m_property.getName(), m_property.getObjectValue(m_factory.getBundleContext()));
}
}
// Add factory state
- props.put("factory.state", new Integer(m_factory.getState()));
+ props.put("factory.state", m_factory.getState());
return props;
@@ -238,14 +246,16 @@
/**
* Gets the interfaces published by the factory.
* By default publish both {@link Factory} and {@link ManagedServiceFactory}.
+ *
* @return : the list of interface published by the factory.
*/
public String[] getFactoryInterfacesToPublish() {
- return new String[] {Factory.class.getName(), ManagedServiceFactory.class.getName()};
+ return new String[]{Factory.class.getName()};
}
/**
* Gets the component type description.
+ *
* @return : the description
*/
public Element getDescription() {
@@ -253,8 +263,8 @@
desc.addAttribute(new Attribute("name", m_factory.getName()));
desc.addAttribute(
- new Attribute("bundle",
- Long.toString(m_factory.getBundleContext().getBundle().getBundleId())));
+ new Attribute("bundle",
+ Long.toString(m_factory.getBundleContext().getBundle().getBundleId())));
String state = "valid";
if (m_factory.getState() == Factory.INVALID) {
@@ -280,24 +290,22 @@
Element prop = new Element("property", "");
prop.addAttribute(new Attribute("name", m_properties[i].getName()));
prop.addAttribute(new Attribute("type", m_properties[i].getType()));
- if (m_properties[i].isMandatory() && m_properties[i].getValue() == null) {
+ if (m_properties[i].isMandatory() && m_properties[i].getValue() == null) {
prop.addAttribute(new Attribute("value", "REQUIRED"));
} else {
prop.addAttribute(new Attribute("value", m_properties[i].getValue()));
}
desc.addElement(prop);
}
-
- if(m_handlerInfoSlot.size() > 0)
- {
- Enumeration keys = m_handlerInfoSlot.keys();
-
- while(keys.hasMoreElements())
- {
- String fullHandlerName = (String) keys.nextElement();
-
- CustomHandlerInfo handlerInfo = (CustomHandlerInfo)m_handlerInfoSlot.get(fullHandlerName);
- desc.addElement( handlerInfo.getDescription() );
+
+ if (m_handlerInfoSlot.size() > 0) {
+ Enumeration keys = m_handlerInfoSlot.keys();
+
+ while (keys.hasMoreElements()) {
+ String fullHandlerName = (String) keys.nextElement();
+
+ CustomHandlerInfo handlerInfo = (CustomHandlerInfo) m_handlerInfoSlot.get(fullHandlerName);
+ desc.addElement(handlerInfo.getDescription());
}
}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/configuration/Instance.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/configuration/Instance.java
index e4994e3..8e9d90c 100644
--- a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/configuration/Instance.java
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/configuration/Instance.java
@@ -19,7 +19,6 @@
package org.apache.felix.ipojo.configuration;
-import org.apache.felix.ipojo.ComponentInstance;
import org.apache.felix.ipojo.Factory;
import java.util.*;
@@ -49,6 +48,10 @@
return new Pair<K, T>(k, v);
}
+ public static <K, T> Pair<K, T> entry(K k, T v) {
+ return new Pair<K, T>(k, v);
+ }
+
public String factory() {
return factory;
}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/Extender.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/Extender.java
index af074ab..561623c 100644
--- a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/Extender.java
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/Extender.java
@@ -19,6 +19,7 @@
package org.apache.felix.ipojo.extender.internal;
+import org.apache.felix.ipojo.ConfigurationTracker;
import org.apache.felix.ipojo.EventDispatcher;
import org.apache.felix.ipojo.extender.internal.linker.DeclarationLinker;
import org.apache.felix.ipojo.extender.internal.processor.*;
@@ -115,6 +116,9 @@
EventDispatcher.create(context);
}
+ // Initialize ConfigurationTracker
+ ConfigurationTracker.initialize();
+
BundleProcessor extensionBundleProcessor = new ExtensionBundleProcessor(m_logger);
BundleProcessor componentsProcessor = new ComponentsBundleProcessor(m_logger);
BundleProcessor configurationProcessor = new ConfigurationProcessor(m_logger);
@@ -169,6 +173,9 @@
public void stop(BundleContext context) throws Exception {
context.removeBundleListener(this);
+ //Shutdown ConfigurationTracker
+ ConfigurationTracker.shutdown();
+
m_processor.stop();
if (DISPATCHER_ENABLED) {
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/util/ServiceLocator.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/util/ServiceLocator.java
new file mode 100644
index 0000000..bd970d4
--- /dev/null
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/util/ServiceLocator.java
@@ -0,0 +1,61 @@
+/*
+ * 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 org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * A simple utility class to retrive services from the service registry.
+ */
+public class ServiceLocator<T> {
+
+ private final BundleContext m_context;
+ private final Class<T> m_clazz;
+
+ private ServiceReference<T> m_reference;
+ private T m_service;
+
+ public ServiceLocator(Class<T> clazz, BundleContext context) {
+ m_clazz = clazz;
+ m_context = context;
+ }
+
+ public synchronized T get() {
+ if (m_service != null) {
+ return m_service;
+ }
+
+ m_reference = m_context.getServiceReference(m_clazz);
+ if (m_reference == null) {
+ return null;
+ }
+ m_service = m_context.getService(m_reference);
+
+ return m_service;
+ }
+
+ public synchronized void unget() {
+ m_service = null;
+ if (m_reference != null) {
+ m_context.ungetService(m_reference);
+ m_reference = null;
+ }
+ }
+}