blob: 364f705a5c673b64ea4b2fe89fd068088fd3160f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008, 2010 VMware Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* VMware Inc. - initial contribution
*******************************************************************************/
package org.eclipse.virgo.test.framework.dmkernel;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Properties;
import org.eclipse.virgo.test.framework.BundleEntry;
import org.eclipse.virgo.test.framework.OsgiTestRunner;
import org.eclipse.virgo.test.framework.TestFrameworkUtils;
import org.eclipse.virgo.util.common.CollectionUtils;
import org.eclipse.virgo.util.common.PropertyPlaceholderResolver;
import org.junit.runners.model.InitializationError;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.startlevel.FrameworkStartLevel;
import javax.management.MalformedObjectNameException;
/**
* JUnit TestRunner for running OSGi integration tests on the dm Kernel.
* <p />
*
* <strong>Concurrent Semantics</strong><br />
*
* As thread-safe as OsgiTestRunner
*
*/
public class DmKernelTestRunner extends OsgiTestRunner {
private static final int DEFAULT_BUNDLE_START_LEVEL = 4;
private static final long DEFAULT_USER_REGION_START_WAIT_TIME = 60000;
private final long userRegionStartWaitTime;
public DmKernelTestRunner(Class<?> klass) throws InitializationError, MalformedObjectNameException {
this(klass, DEFAULT_USER_REGION_START_WAIT_TIME);
}
DmKernelTestRunner(Class<?> klass, long userRegionStartWaitTime) throws InitializationError, MalformedObjectNameException {
super(klass);
this.userRegionStartWaitTime = userRegionStartWaitTime;
}
@Override
protected BundleContext getTargetBundleContext(BundleContext bundleContext) {
Collection<ServiceReference<BundleContext>> serviceReferences = getUserRegionBundleContextServiceReferences(bundleContext);
if (serviceReferences != null) {
if (serviceReferences.size() != 1) {
throw new IllegalStateException("There must be exactly one user region bundle context in the service registry. "
+ serviceReferences.size() + " were found.");
} else {
BundleContext targetBundleContext = bundleContext.getService(serviceReferences.iterator().next());
if (targetBundleContext != null) {
return targetBundleContext;
}
}
}
throw new IllegalStateException("User region's bundle context was not available from the service registry within "
+ (this.userRegionStartWaitTime / 1000) + " seconds.");
}
/**
* Installs additional user region bundles based on {@link RegionBundleDependencies}
*/
@Override
protected void postProcessTargetBundleContext(BundleContext bundleContext, Properties frameworkConfigurationProperties) throws Exception {
/*
* Use the same default start level for user region bundles as the user region factory. Program the framework
* start level instance defensively to allow for stubs which don't understand adapt.
*/
FrameworkStartLevel frameworkStartLevel = bundleContext.getBundle(0).adapt(FrameworkStartLevel.class);
if (frameworkStartLevel != null) {
frameworkStartLevel.setInitialBundleStartLevel(DEFAULT_BUNDLE_START_LEVEL);
}
final Properties configurationProperties = new Properties(frameworkConfigurationProperties);
// This list is installed post installation of user region bundle that includes bundles listed in the
// user region configuration file as implemented in kernel RegionManager
Class<RegionBundleDependencies> annotationType = RegionBundleDependencies.class;
Class<?> annotationDeclaringClazz = TestFrameworkUtils.findAnnotationDeclaringClass(annotationType, getTestClass().getJavaClass());
if (annotationDeclaringClazz == null) {
// could not find an 'annotation declaring class' for annotation + annotationType + and targetType +
// startFromClazz
return;
}
final List<Bundle> bundlesToStart = new ArrayList<>();
List<BundleEntry> bundleEntries = new ArrayList<>();
while (annotationDeclaringClazz != null) {
RegionBundleDependencies dependencies = annotationDeclaringClazz.getAnnotation(annotationType);
BundleEntry[] entries = dependencies.entries();
bundleEntries.addAll(0, Arrays.asList(entries));
annotationDeclaringClazz = dependencies.inheritDependencies() ? TestFrameworkUtils.findAnnotationDeclaringClass(annotationType,
annotationDeclaringClazz.getSuperclass()) : null;
}
PropertyPlaceholderResolver resolver = new PropertyPlaceholderResolver();
if (!CollectionUtils.isEmpty(bundleEntries)) {
for (BundleEntry bundleEntry : bundleEntries) {
String path = bundleEntry.value();
boolean autoStart = bundleEntry.autoStart();
String formattedPath = resolver.resolve(path, configurationProperties);
Bundle bundle = bundleContext.installBundle(new URI(formattedPath).toString());
if (autoStart && !TestFrameworkUtils.isFragment(bundle)) {
bundlesToStart.add(bundle);
}
}
}
for (Bundle bundle : bundlesToStart) {
try {
bundle.start();
} catch (BundleException e) {
throw new BundleException("Failed to start bundle " + bundle.getSymbolicName() + " " + bundle.getVersion(), e);
}
}
}
private Collection<ServiceReference<BundleContext>> getUserRegionBundleContextServiceReferences(BundleContext bundleContext) {
long startTime = System.currentTimeMillis();
Collection<ServiceReference<BundleContext>> serviceReferences = doGetUserRegionBundleContextServiceReferences(bundleContext);
while (serviceReferences.size() == 0) {
if (System.currentTimeMillis() < (this.userRegionStartWaitTime + startTime)) {
try {
Thread.sleep(500);
serviceReferences = doGetUserRegionBundleContextServiceReferences(bundleContext);
} catch (InterruptedException ie) {
throw new RuntimeException(ie);
}
} else {
break;
}
}
return serviceReferences;
}
private Collection<ServiceReference<BundleContext>> doGetUserRegionBundleContextServiceReferences(BundleContext bundleContext) {
try {
return bundleContext.getServiceReferences(BundleContext.class, "(org.eclipse.virgo.kernel.regionContext=true)");
} catch (InvalidSyntaxException e) {
throw new RuntimeException("Unexpected InvalidSyntaxException when looking up the user region's BundleContext", e);
}
}
}