blob: 771e1a0dfab1274e97507c7360c19f92f0a3a523 [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.sling.test;
import static org.ops4j.pax.exam.Constants.START_LEVEL_SYSTEM_BUNDLES;
import static org.ops4j.pax.exam.CoreOptions.bundle;
import static org.ops4j.pax.exam.CoreOptions.composite;
import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
import static org.ops4j.pax.exam.CoreOptions.options;
import static org.ops4j.pax.exam.CoreOptions.provision;
import static org.ops4j.pax.exam.CoreOptions.systemProperty;
import static org.ops4j.pax.exam.CoreOptions.wrappedBundle;
import java.io.File;
import java.io.FilenameFilter;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Dictionary;
import java.util.Enumeration;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.TestProbeBuilder;
import org.ops4j.pax.exam.junit.Configuration;
import org.ops4j.pax.exam.junit.ProbeBuilder;
import org.ops4j.pax.exam.options.AbstractDelegateProvisionOption;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
/**
* Spin the cache up in a container to verify we have a working system.
* Parts shamelessly borrowed from the Integration Test class in commons.classloader.
*/
public abstract class AbstractOSGiRunner {
// the name of the system property providing the bundle file to be installed
// and tested
private static final String BUNDLE_JAR_SYS_PROP = "project.bundle.file";
@ProbeBuilder
public TestProbeBuilder _extendProbe(TestProbeBuilder builder) {
System.err.println("Parent Builder");
String imports = getImports();
if ( !imports.startsWith(",")) {
imports = ","+imports;
}
builder.setHeader(Constants.IMPORT_PACKAGE, "org.osgi.framework,org.apache.sling.test"+imports);
builder.setHeader(Constants.DYNAMICIMPORT_PACKAGE, "org.ops4j.pax.exam,org.junit,javax.inject,org.ops4j.pax.exam.options");
builder.setHeader("Bundle-ManifestVersion", "2");
return builder;
}
/**
* @return the artifact name to assist determining the correct jar to load from target/
*/
protected abstract String getArtifactName();
/**
* @return a string of additional imports to the builder
*/
protected String getImports() {
return "";
}
protected Option[] getOptions() {
return options();
}
@Configuration
public Option[] configuration() {
String bundleFileName = getBundleFileName();
final File bundleFile = new File(bundleFileName);
if (!bundleFile.canRead()) {
throw new IllegalArgumentException("Cannot read from bundle file "
+ bundleFileName + " specified in the "
+ BUNDLE_JAR_SYS_PROP + " system property");
}
return options(
composite(getOptions()),
provision(
// url resolution for pax
mavenBundle("org.ops4j.pax.url", "pax-url-mvn", "1.3.5"),
// to support declarative services
mavenBundle("org.apache.felix", "org.apache.felix.scr", "1.6.0"),
// bound to need servlet api
mavenBundle("org.apache.felix", "javax.servlet","1.0.0"),
// standard items.
mavenBundle("commons-collections", "commons-collections", "3.2.1"), // 3.2.1 is a bundle, 3.2 is not
mavenBundle("commons-io", "commons-io", "1.4"),
// export ourselves
wrappedBundle(mavenBundle("org.apache.sling","org.apache.sling.commons.cache.container-test")).exports(AbstractOSGiRunner.class.getPackage().getName()),
// add the project thats being tested.
bundle(bundleFile.toURI().toString())
),
// below is instead of normal Pax Exam junitBundles() to deal
// with build server issue
new DirectURLJUnitBundlesOption(),
systemProperty("pax.exam.invoker").value("junit"),
bundle("link:classpath:META-INF/links/org.ops4j.pax.exam.invoker.junit.link")
);
}
private String getBundleFileName() {
String bundleFileName = System.getProperty(BUNDLE_JAR_SYS_PROP);
if (bundleFileName == null) {
// are we in an IDE, can we guess the jar name.
File target = new File("target");
final String artifactName = getArtifactName();
System.err.println("Listing files in "+target.getAbsolutePath()+" looking for "+artifactName);
File[] jars = target.listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) {
if (!name.endsWith(".jar")) {
return false;
}
if (name.endsWith("sources.jar")) {
return false;
}
return name
.startsWith(artifactName);
}
});
if (jars.length > 0) {
bundleFileName = jars[0].getAbsolutePath();
}
}
return bundleFileName;
}
protected void check() {
try {
Class<?> t = this.getClass().getClassLoader().loadClass("javax.transaction.TransactionManager");
System.err.println("Loaded Class "+t+" from classloader "+t.getClassLoader());
ClassLoader cl = t.getClassLoader();
if ( cl instanceof URLClassLoader ) {
URLClassLoader u = (URLClassLoader) cl;
for ( URL url : u.getURLs() ) {
System.err.println("Classloadr url"+url);
}
}
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
/**
* Try and load a class from each bundle in turn.
* @param bundleContext
* @param classname
*/
protected void findClassHome(BundleContext bundleContext, String classname) {
System.err.println("Bundle is "+bundleContext);
for ( Bundle b : bundleContext.getBundles()) {
System.err.println("Bundle is "+bundleContext);
if ( classname != null ) {
try{
Class<?> t = b.loadClass(classname);
ClassLoader cl = t.getClassLoader();
System.err.println("Loaded "+t+" "+cl);
} catch ( Exception e ) {
}
}
}
}
/**
* List all the bundles showing services and headers.
* @param bundleContext
*/
protected void listBundles(BundleContext bundleContext) {
System.err.println("Bundle is "+bundleContext);
for ( Bundle b : bundleContext.getBundles()) {
System.err.println("Bundle is "+bundleContext);
Dictionary<String, String> headers = b.getHeaders();
for( Enumeration<String> e = headers.keys(); e.hasMoreElements();) {
String key = e.nextElement();
System.err.println(" Header "+key+" "+headers.get(key));
}
ServiceReference[] srs = b.getRegisteredServices();
if (srs != null ) {
for ( ServiceReference sr: srs) {
System.err.println(" Service "+bundleContext);
}
}
}
}
/**
* This code is taken from commons.classloader.it.DynamicClassLoaderIT Clone
* of Pax Exam's JunitBundlesOption which uses a direct URL to the
* SpringSource JUnit bundle to avoid some weird repository issues on the
* Apache build server.
*/
private static class DirectURLJUnitBundlesOption extends
AbstractDelegateProvisionOption<DirectURLJUnitBundlesOption> {
/**
* Constructor.
*/
public DirectURLJUnitBundlesOption() {
super(
bundle("http://repository.springsource.com/ivy/bundles/external/org.junit/com.springsource.org.junit/4.9.0/com.springsource.org.junit-4.9.0.jar"));
noUpdate();
startLevel(START_LEVEL_SYSTEM_BUNDLES);
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return String.format("DirectURLJUnitBundlesOption{url=%s}",
getURL());
}
/**
* {@inheritDoc}
*/
protected DirectURLJUnitBundlesOption itself() {
return this;
}
}
}