Skip to content

Commit

Permalink
[ARQ-2016] Improve the ability to add custom extensions for the conta…
Browse files Browse the repository at this point in the history
…iners
  • Loading branch information
cgoncas authored and Thomas Diesler committed May 22, 2017
1 parent 338333b commit a663171
Show file tree
Hide file tree
Showing 26 changed files with 832 additions and 498 deletions.
112 changes: 28 additions & 84 deletions bundle/pom.xml
Expand Up @@ -12,7 +12,7 @@
<!-- Artifact Configuration -->
<artifactId>arquillian-osgi-bundle</artifactId>
<name>Arquillian OSGi :: Bundle</name>
<packaging>bundle</packaging>
<packaging>jar</packaging>

<!-- Dependencies -->
<dependencies>
Expand Down Expand Up @@ -55,98 +55,42 @@
<artifactId>org.osgi.core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.osgi.metadata</groupId>
<artifactId>jbosgi-metadata</artifactId>
<version>4.0.0.CR1</version>
</dependency>
<dependency>
<groupId>biz.aQute.bnd</groupId>
<artifactId>biz.aQute.bndlib</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.12</version>
</dependency>
<dependency>
<groupId>org.jboss.osgi.vfs</groupId>
<artifactId>jbosgi-vfs</artifactId>
<version>2.0.0.Final</version>
</dependency>
<dependency>
<groupId>org.jboss.osgi.vfs</groupId>
<artifactId>jbosgi-vfs</artifactId>
<version>2.0.0.Final</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<artifactId>maven-checkstyle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Bundle-Activator>org.jboss.arquillian.osgi.ArquillianBundleActivator</Bundle-Activator>
<Export-Package />
<Import-Package>
!org.jboss.arquillian.config.*,
!org.jboss.shrinkwrap.descriptor.api,
javax.activation,
javax.management*,
javax.naming,
org.osgi.framework;version="[1.5,2.0)",
org.osgi.framework.startlevel;version="[1.0,2.0)",
org.osgi.service.packageadmin;version="[1.2,2.0)",
org.osgi.service.startlevel;version="[1.1,2.0)",
org.osgi.util.tracker;version="[1.4,2.0)",
</Import-Package>
<Private-Package>
org.jboss.arquillian.osgi,
</Private-Package>
<Embed-Transitive>true</Embed-Transitive>
<Embed-Dependency>
arquillian-core-api;inline=false,
arquillian-core-impl-base;inline=false,
arquillian-core-spi;inline=false,
arquillian-test-api;inline=false,
arquillian-test-impl-base;inline=false,
arquillian-test-spi;inline=false,
arquillian-container-impl-base;inline=false,
arquillian-container-spi;inline=false,
arquillian-container-test-api;inline=false,
arquillian-container-test-impl-base;inline=false,
arquillian-container-test-spi;inline=false,
arquillian-junit-core;inline=false,
arquillian-junit-container;inline=false,
arquillian-testenricher-osgi;inline=false,
arquillian-protocol-jmx;inline=false,
shrinkwrap-api;inline=false,
shrinkwrap-impl-base;inline=false,
shrinkwrap-spi;inline=false,
hamcrest-core;inline=false,
junit;inline=false,
</Embed-Dependency>
<_exportcontents>
org.jboss.arquillian.container.test.api;version=${version.jboss.arquillian.core},
org.jboss.arquillian.test.api;version=${version.jboss.arquillian.core},
org.jboss.arquillian.container.test.api;version=${version.jboss.arquillian.core},
org.jboss.arquillian.junit;version=${version.jboss.arquillian.core},
org.jboss.arquillian.osgi;version=${project.version},
org.jboss.shrinkwrap.api;version=${version.jboss.shrinkwrap},
org.jboss.shrinkwrap.api.asset;version=${version.jboss.shrinkwrap},
org.jboss.shrinkwrap.api.container;version=${version.jboss.shrinkwrap},
org.jboss.shrinkwrap.api.exporter;version=${version.jboss.shrinkwrap},
org.jboss.shrinkwrap.api.formatter;version=${version.jboss.shrinkwrap},
org.jboss.shrinkwrap.api.importer;version=${version.jboss.shrinkwrap},
org.jboss.shrinkwrap.api.serialization;version=${version.jboss.shrinkwrap},
org.jboss.shrinkwrap.api.spec;version=${version.jboss.shrinkwrap},
org.jboss.shrinkwrap.api.importer;version=${version.jboss.shrinkwrap},
org.jboss.shrinkwrap.api.formatter;version=${version.jboss.shrinkwrap},
org.jboss.shrinkwrap.api.exporter;version=${version.jboss.shrinkwrap},
org.jboss.shrinkwrap.api.container;version=${version.jboss.shrinkwrap},
org.junit.runner;version=${version.junit},
org.junit.runner.manipulation;version=${version.junit},
org.junit.runners.model;version=${version.junit},
org.junit;version=${version.junit},
org.junit.rules;version=${version.junit},
org.hamcrest;version=${version.hamcrest-core},
org.hamcrest.core;version=${version.hamcrest-core}
</_exportcontents>
</instructions>
<configLocation>${basedir}/../checkstyle.xml</configLocation>
</configuration>
</plugin>
</plugins>

<!-- PluginManagement -->
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.1.0</version>
<extensions>true</extensions>
</plugin>
</plugins>
</pluginManagement>
</build>


Expand Down
Expand Up @@ -25,24 +25,24 @@
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;

import org.jboss.arquillian.container.test.api.OperateOnDeployment;
import org.jboss.arquillian.osgi.bundle.ArquillianFragmentGenerator;
import org.jboss.arquillian.protocol.jmx.JMXTestRunner;
import org.jboss.arquillian.protocol.jmx.JMXTestRunner.TestClassLoader;
import org.jboss.arquillian.testenricher.osgi.BundleAssociation;
import org.jboss.arquillian.testenricher.osgi.BundleContextAssociation;
import org.osgi.framework.Bundle;
import org.osgi.framework.Constants;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleReference;
import org.osgi.framework.namespace.HostNamespace;
import org.osgi.framework.wiring.BundleWire;
import org.osgi.framework.wiring.BundleWiring;
import org.osgi.framework.wiring.FrameworkWiring;

/**
* This is the Arquillian {@link BundleActivator}.
Expand All @@ -57,49 +57,16 @@ public class ArquillianBundleActivator implements BundleActivator {
private static Logger log = Logger.getLogger(ArquillianBundleActivator.class.getName());

private JMXTestRunner testRunner;
private long arqBundleId;

public void start(final BundleContext context) throws Exception {

arqBundleId = context.getBundle().getBundleId();

final BundleContext syscontext = context.getBundle(0).getBundleContext();
final TestClassLoader testClassLoader = new TestClassLoader() {

@Override
public Class<?> loadTestClass(String className) throws ClassNotFoundException {
String namePath = className.replace('.', '/') + ".class";

// Get all installed bundles and remove some
List<Bundle> bundles = new ArrayList<Bundle>(Arrays.asList(syscontext.getBundles()));
Iterator<Bundle> iterator = bundles.iterator();
while(iterator.hasNext()) {
Bundle aux = iterator.next();
if (aux.getBundleId() <= arqBundleId || aux.getState() == Bundle.UNINSTALLED) {
iterator.remove();
}
}

// Load the the test class from the bundle that contains the entry
for (Bundle aux : bundles) {
if (aux.getEntry(namePath) != null) {
return aux.loadClass(className);
}
}

// Load the the test class from bundle that defines a Bundle-ClassPath
for (Bundle aux : bundles) {
String bundlecp = aux.getHeaders().get(Constants.BUNDLE_CLASSPATH);
if (bundlecp != null) {
try {
return aux.loadClass(className);
} catch (ClassNotFoundException ex) {
// ignore
}
}
}

throw new ClassNotFoundException("Test '" + className + "' not found in: " + bundles);
return context.getBundle().loadClass(className);
}
};

Expand All @@ -108,7 +75,21 @@ public Class<?> loadTestClass(String className) throws ClassNotFoundException {
testRunner = new JMXTestRunner(testClassLoader) {
@Override
public byte[] runTestMethod(String className, String methodName) {
return super.runTestMethod(className, methodName);
Thread thread = Thread.currentThread();

ClassLoader contextClassLoader = thread.getContextClassLoader();

try {
Bundle bundle = context.getBundle();

thread.setContextClassLoader(
bundle.adapt(BundleWiring.class).getClassLoader());

return super.runTestMethod(className, methodName);
}
finally {
thread.setContextClassLoader(contextClassLoader);
}
}

@Override
Expand All @@ -119,7 +100,15 @@ public byte[] runTestMethod(String className, String methodName, Map<String, Str
} catch (ClassNotFoundException ex) {
throw new IllegalStateException(ex);
}
BundleAssociation.setBundle(getTestBundle(syscontext, testClass, methodName));
Bundle fragmentBundle = getFragmentBundle(context);

Bundle testBundle = getTestBundle(syscontext, fragmentBundle.getHeaders().get(ArquillianFragmentGenerator.TEST_BUNDLE_SYMBOLIC_NAME), testClass, methodName);

FrameworkWiring adapt = syscontext.getBundle().adapt(FrameworkWiring.class);

adapt.resolveBundles(Arrays.asList(testBundle));

BundleAssociation.setBundle(testBundle);
BundleContextAssociation.setBundleContext(syscontext);
return super.runTestMethod(className, methodName, protocolProps);
}
Expand Down Expand Up @@ -153,19 +142,54 @@ private MBeanServer findOrCreateMBeanServer() {
return mbeanServer;
}

private Bundle getTestBundle(BundleContext syscontext, Class<?> testClass, String methodName) {
Bundle bundle = ((BundleReference) testClass.getClassLoader()).getBundle();
private Bundle getFragmentBundle(BundleContext context) {
BundleWiring bundleWiring = context.getBundle().adapt(BundleWiring.class );

List<Bundle> fragmentBundles = new ArrayList<Bundle>();

if (bundleWiring != null) {
List<BundleWire> providedWires = bundleWiring.getProvidedWires(HostNamespace.HOST_NAMESPACE);

for (BundleWire providedWire : providedWires) {
fragmentBundles.add(providedWire.getRequirerWiring().getRevision().getBundle());
}
}

if (fragmentBundles.isEmpty()) {
throw new RuntimeException("There are not fragment associated with the context");
}

if (fragmentBundles.size() > 1) {
throw new RuntimeException("There are more than one fragment for the Arquilian Bundle");
}

return fragmentBundles.get(0);

}

private Bundle getTestBundle(BundleContext syscontext, String testBundleSymbolicName, Class<?> testClass, String methodName) {
Bundle testBundle = null;

for (Bundle aux : syscontext.getBundles()) {
if (aux.getSymbolicName().equals(testBundleSymbolicName)) {
testBundle = aux;

break;
}
}

for (Method method : testClass.getMethods()) {
OperateOnDeployment opon = method.getAnnotation(OperateOnDeployment.class);
if (opon != null && methodName.equals(method.getName())) {
for (Bundle aux : syscontext.getBundles()) {
if (aux.getLocation().equals(opon.value())) {
bundle = aux;
testBundle = aux;
break;
}
}
}
}
return bundle;

return testBundle;
}
}

This file was deleted.

0 comments on commit a663171

Please sign in to comment.