blob: 7c5d0ccd8577db043b640cf631d4225d88688d40 [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.commons.classloader.it;
import static org.junit.Assert.*;
import static org.ops4j.pax.exam.Constants.*;
import static org.ops4j.pax.exam.CoreOptions.*;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import javax.inject.Inject;
import org.apache.sling.commons.classloader.DynamicClassLoaderManager;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.CoreOptions;
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.JUnit4TestRunner;
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;
@RunWith(JUnit4TestRunner.class)
public class DynamicClassLoaderIT {
// 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";
@Inject
protected BundleContext bundleContext;
protected ClassLoader dynamicClassLoader;
protected ServiceReference classLoaderManagerReference;
/**
* Helper method to get a service of the given type
*/
@SuppressWarnings("unchecked")
protected <T> T getService(Class<T> clazz) {
final ServiceReference ref = bundleContext.getServiceReference(clazz.getName());
assertNotNull("getService(" + clazz.getName() + ") must find ServiceReference", ref);
final T result = (T)(bundleContext.getService(ref));
assertNotNull("getService(" + clazz.getName() + ") must find service", result);
return result;
}
protected ClassLoader getDynamicClassLoader() {
if ( classLoaderManagerReference == null || classLoaderManagerReference.getBundle() == null ) {
dynamicClassLoader = null;
classLoaderManagerReference = bundleContext.getServiceReference(DynamicClassLoaderManager.class.getName());
}
if ( dynamicClassLoader == null && classLoaderManagerReference != null ) {
final DynamicClassLoaderManager dclm = (DynamicClassLoaderManager) bundleContext.getService(classLoaderManagerReference);
if ( dclm != null ) {
dynamicClassLoader = dclm.getDynamicClassLoader();
}
}
return dynamicClassLoader;
}
@ProbeBuilder
public TestProbeBuilder extendProbe(TestProbeBuilder builder) {
builder.setHeader(Constants.IMPORT_PACKAGE, "org.osgi.framework,org.apache.sling.commons.classloader");
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;
}
@Configuration
public static Option[] configuration() {
final String bundleFileName = System.getProperty( BUNDLE_JAR_SYS_PROP );
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(
provision(
CoreOptions.bundle( bundleFile.toURI().toString() ),
mavenBundle( "org.ops4j.pax.tinybundles", "tinybundles", "1.0.0" ),
mavenBundle("org.apache.sling", "org.apache.sling.commons.log", "2.1.2"),
mavenBundle("org.apache.felix", "org.apache.felix.eventadmin", "1.2.14"),
mavenBundle("org.ops4j.pax.url", "pax-url-mvn", "1.3.5")
),
// 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")
);
}
@Test
public void testPackageAdminClassLoader() throws Exception {
// check class loader
assertNotNull(getDynamicClassLoader());
final URL url = new URL(mavenBundle("org.apache.sling", "org.apache.sling.commons.osgi", "2.1.0").getURL());
final InputStream is = url.openStream();
Bundle osgiBundle = null;
try {
osgiBundle = this.bundleContext.installBundle(url.toExternalForm(), is);
} finally {
try { is.close(); } catch ( final IOException ignore) {}
}
assertNotNull(osgiBundle);
assertEquals(Bundle.INSTALLED, osgiBundle.getState());
final String className = "org.apache.sling.commons.osgi.PropertiesUtil";
// try to load class when bundle is in state install: should fail
try {
getDynamicClassLoader().loadClass(className);
fail("Class should not be available");
} catch (final ClassNotFoundException expected) {
// expected
}
// force resolving of the bundle
osgiBundle.getResource("/something");
assertEquals(Bundle.RESOLVED, osgiBundle.getState());
// try to load class when bundle is in state resolve: should fail
try {
getDynamicClassLoader().loadClass(className);
fail("Class should not be available");
} catch (final ClassNotFoundException expected) {
// expected
}
// start bundle
osgiBundle.start();
assertEquals(Bundle.ACTIVE, osgiBundle.getState());
// try to load class when bundle is in state activate: should work
try {
getDynamicClassLoader().loadClass(className);
} catch (final ClassNotFoundException expected) {
fail("Class should be available");
}
}
/**
* 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;
}
}
}