blob: 262e1d75cbfa294867f56e3cab0207f2ebfacce9 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.felix.ipojo.test.online;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import org.apache.felix.ipojo.ComponentInstance;
import org.apache.felix.ipojo.architecture.Architecture;
import org.apache.felix.ipojo.architecture.InstanceDescription;
import org.apache.felix.ipojo.test.online.components.Consumer;
import org.apache.felix.ipojo.test.online.components.MyProvider;
import org.apache.felix.ipojo.test.online.services.Hello;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.io.StreamUtils;
import org.ops4j.pax.exam.Configuration;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.junit.PaxExam;
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.ops4j.pax.tinybundles.core.TinyBundles;
import org.osgi.framework.*;
import org.osgi.service.url.URLStreamHandlerService;
import org.ow2.chameleon.testing.helpers.OSGiHelper;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import static org.ops4j.pax.exam.CoreOptions.*;
import static org.ops4j.pax.exam.MavenUtils.asInProject;
@RunWith(PaxExam.class)
@ExamReactorStrategy(PerClass.class)
public class OnlineManipulatorTest {
private static File TMP = new File("target/tmp-bundle");
@Inject
BundleContext context;
private OSGiHelper helper;
@Configuration
public Option[] configure() throws IOException {
Logger root = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
root.setLevel(Level.INFO);
String providerWithMetadata = providerWithMetadata();
String providerWithMetadataInMetaInf = providerWithMetadataInMetaInf();
String providerWithoutMetadata = providerWithoutMetadata();
String consumerWithMetadata = consumerWithMetadata();
String consumerWithoutMetadata = consumerWithoutMetadata();
return options(
cleanCaches(),
mavenBundle("org.apache.felix", "org.apache.felix.ipojo").versionAsInProject(),
mavenBundle("org.ow2.chameleon.testing", "osgi-helpers").versionAsInProject(),
mavenBundle("org.apache.felix","org.apache.felix.ipojo.manipulator.online").versionAsInProject(),
junitBundles(),
provision(
TinyBundles.bundle()
.add(Hello.class)
.set(Constants.BUNDLE_SYMBOLICNAME, "ServiceInterface")
.set(Constants.EXPORT_PACKAGE, "org.apache.felix.ipojo.test.online.services")
.build()
),
systemProperty("providerWithMetadata").value(providerWithMetadata),
systemProperty("providerWithMetadataInMetaInf").value(providerWithMetadataInMetaInf),
systemProperty("providerWithoutMetadata").value(providerWithoutMetadata),
systemProperty("consumerWithMetadata").value(consumerWithMetadata),
systemProperty("consumerWithoutMetadata").value(consumerWithoutMetadata),
systemProperty("org.knopflerfish.osgi.registerserviceurlhandler").value("true")
);
}
@Before
public void before() {
helper = new OSGiHelper(context);
waitForStability(context);
helper.waitForService(URLStreamHandlerService.class, null, 1000);
Assert.assertEquals("Check online manipulator bundle state",
helper.getBundle("org.apache.felix.ipojo.manipulator.online").getState(),
Bundle.ACTIVE);
URLStreamHandlerService svc = helper.getServiceObject(URLStreamHandlerService.class, null);
Assert.assertNotNull("URL Stream handler exported", svc);
System.out.println(svc);
}
@After
public void after() {
helper.dispose();
}
private static File getTemporaryFile(String name) throws IOException {
if (!TMP.exists()) {
TMP.mkdirs();
TMP.deleteOnExit();
}
File file = File.createTempFile(name, ".jar", TMP);
//File file = new File(TMP, name + ".jar");
if (file.exists()) {
file.delete();
}
file.deleteOnExit();
return file;
}
@Test
public void installProviderWithMetadata1() throws Exception {
String url = context.getProperty("providerWithMetadata");
Assert.assertNotNull(url);
Bundle bundle = context.installBundle("ipojo:" + url);
bundle.start();
assertBundle("Provider");
helper.waitForService(Hello.class.getName(), null, 5000);
assertValidity();
Assert.assertNotNull(context.getServiceReference(Hello.class.getName()));
bundle.uninstall();
}
@Test
public void installProviderWithMetadata2() throws BundleException, InvalidSyntaxException, IOException {
String url = context.getProperty("providerWithMetadataInMetaInf");
Assert.assertNotNull(url);
System.out.println("prefixed url : " + "ipojo:" + url);
Bundle bundle = context.installBundle("ipojo:" + url);
bundle.start();
assertBundle("Provider");
helper.waitForService(Hello.class.getName(), null, 5000);
assertValidity();
Assert.assertNotNull(context.getServiceReference(Hello.class.getName()));
bundle.uninstall();
}
@Test
public void installProviderWithoutMetadata() throws BundleException, InvalidSyntaxException, IOException {
String url = context.getProperty("providerWithoutMetadata");
Assert.assertNotNull(url);
Bundle bundle = context.installBundle("ipojo:" + url);
bundle.start();
assertBundle("Provider");
helper.waitForService(Hello.class.getName(), null, 5000);
assertValidity();
Assert.assertNotNull(context.getServiceReference(Hello.class.getName()));
bundle.uninstall();
}
@Test
public void installConsumerWithMetadata() throws BundleException, InvalidSyntaxException, IOException {
String url = context.getProperty("providerWithoutMetadata");
Assert.assertNotNull(url);
Bundle bundle = context.installBundle("ipojo:" + url);
bundle.start();
assertBundle("Provider");
String url2 = context.getProperty("consumerWithMetadata");
Assert.assertNotNull(url);
Bundle bundle2 = context.installBundle("ipojo:" + url2);
bundle2.start();
assertBundle("Consumer");
helper.waitForService(Hello.class.getName(), null, 5000);
// Wait for activation.
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
assertValidity();
Assert.assertNotNull(context.getServiceReference(Hello.class.getName()));
bundle.uninstall();
bundle2.uninstall();
}
@Test
public void installConsumerWithoutMetadata() throws BundleException, InvalidSyntaxException, IOException {
String url = context.getProperty("providerWithMetadataInMetaInf");
Assert.assertNotNull(url);
Bundle bundle = context.installBundle("ipojo:" + url);
bundle.start();
assertBundle("Provider");
helper.waitForService(Hello.class.getName(), null, 5000);
String url2 = context.getProperty("consumerWithoutMetadata");
Assert.assertNotNull(url);
Bundle bundle2 = context.installBundle("ipojo:" + url2);
bundle2.start();
assertBundle("Consumer");
// Wait for activation.
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
assertValidity();
Assert.assertNotNull(context.getServiceReference(Hello.class.getName()));
bundle.uninstall();
bundle2.uninstall();
}
/**
* Gets a regular bundle containing metadata file
*
* @return the url of the bundle
* @throws java.io.IOException
*/
public static String providerWithMetadata() throws IOException {
InputStream is = TinyBundles.bundle()
.add("metadata.xml", OnlineManipulatorTest.class.getClassLoader().getResource("provider.xml"))
.add(MyProvider.class)
.set(Constants.BUNDLE_SYMBOLICNAME, "Provider")
.set(Constants.IMPORT_PACKAGE, "org.apache.felix.ipojo.test.online.services")
.build();
File out = getTemporaryFile("providerWithMetadata");
StreamUtils.copyStream(is, new FileOutputStream(out), true);
return out.toURI().toURL().toExternalForm();
}
/**
* Gets a regular bundle containing metadata file in the META-INF directory
*
* @return the url of the bundle
* @throws java.io.IOException
*/
public static String providerWithMetadataInMetaInf() throws IOException {
InputStream is = TinyBundles.bundle()
.add("META-INF/metadata.xml", OnlineManipulatorTest.class.getClassLoader().getResource("provider.xml"))
.add(MyProvider.class)
.set(Constants.BUNDLE_SYMBOLICNAME, "Provider")
.set(Constants.IMPORT_PACKAGE, "org.apache.felix.ipojo.test.online.services")
.build();
File out = getTemporaryFile("providerWithMetadataInMetaInf");
StreamUtils.copyStream(is, new FileOutputStream(out), true);
return out.toURI().toURL().toExternalForm();
}
/**
* Gets a provider bundle which does not contain the metadata file.
*
* @return the url of the bundle + metadata
* @throws java.io.IOException
*/
public static String providerWithoutMetadata() throws IOException {
InputStream is = TinyBundles.bundle()
//.addResource("metadata.xml", this.getClass().getClassLoader().getResource("provider.xml"))
.add(MyProvider.class)
.set(Constants.BUNDLE_SYMBOLICNAME, "Provider")
.set(Constants.IMPORT_PACKAGE, "org.apache.felix.ipojo.test.online.services")
.build();
File out = getTemporaryFile("providerWithoutMetadata");
StreamUtils.copyStream(is, new FileOutputStream(out), true);
String url = out.toURI().toURL().toExternalForm();
return url + "!" + OnlineManipulatorTest.class.getClassLoader().getResource("provider.xml");
}
/**
* Gets a consumer bundle using annotation containing the instance
* declaration in the metadata.
*
* @return the url of the bundle
* @throws java.io.IOException
*/
public static String consumerWithMetadata() throws IOException {
InputStream is = TinyBundles.bundle()
.add("metadata.xml", OnlineManipulatorTest.class.getClassLoader().getResource("consumer.xml"))
.add(Consumer.class)
.set(Constants.BUNDLE_SYMBOLICNAME, "Consumer")
.set(Constants.IMPORT_PACKAGE, "org.apache.felix.ipojo.test.online.services")
.build();
File out = getTemporaryFile("consumerWithMetadata");
StreamUtils.copyStream(is, new FileOutputStream(out), true);
return out.toURI().toURL().toExternalForm();
}
/**
* Gets a consumer bundle using annotation that does not contain
* metadata
*
* @return the url of the bundle + metadata
* @throws java.io.IOException
*/
public static String consumerWithoutMetadata() throws IOException {
InputStream is = TinyBundles.bundle()
.add(Consumer.class)
.set(Constants.BUNDLE_SYMBOLICNAME, "Consumer")
.set(Constants.IMPORT_PACKAGE, "org.apache.felix.ipojo.test.online.services")
.build();
File out = getTemporaryFile("consumerWithoutMetadata");
StreamUtils.copyStream(is, new FileOutputStream(out), true);
String url = out.toURI().toURL().toExternalForm();
return url + "!" + OnlineManipulatorTest.class.getClassLoader().getResource("consumer.xml");
}
public void dumpServices() throws InvalidSyntaxException {
ServiceReference[] refs = context.getAllServiceReferences(null, null);
System.out.println(" === Services === ");
for (ServiceReference ref : refs) {
String[] itf = (String[]) ref.getProperty(Constants.OBJECTCLASS);
System.out.println(itf[0]);
}
System.out.println("====");
}
public void dumpBundles() throws InvalidSyntaxException {
Bundle[] bundles = context.getBundles();
System.out.println(" === Bundles === ");
for (Bundle bundle : bundles) {
String sn = bundle.getSymbolicName();
System.out.println(sn);
}
System.out.println("====");
}
private void assertBundle(String sn) {
for (Bundle bundle : context.getBundles()) {
if (bundle.getSymbolicName().equals(sn)
&& bundle.getState() == Bundle.ACTIVE) {
return;
}
}
Assert.fail("Cannot find the bundle " + sn);
}
private void assertValidity() {
try {
ServiceReference[] refs = context.getServiceReferences(Architecture.class.getName(), null);
Assert.assertNotNull(refs);
for (ServiceReference ref : refs) {
InstanceDescription id = ((Architecture) context.getService(ref)).getInstanceDescription();
int state = id.getState();
Assert.assertEquals("State of " + id.getName(), ComponentInstance.VALID, state);
}
} catch (InvalidSyntaxException e) {
Assert.fail(e.getMessage());
}
}
/**
* 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(200);
} 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(1000);
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;
}
}