blob: aaa8ab2d443f2aaca5d77d1a55d5b69421670206 [file] [log] [blame]
/******************************************************************************
* Copyright (c) 2006, 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
* and Apache License v2.0 which accompanies this distribution.
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0
* is available at http://www.opensource.org/licenses/apache2.0.php.
* You may elect to redistribute this code under either of these licenses.
*
* Contributors:
* VMware Inc.
*****************************************************************************/
package org.eclipse.gemini.blueprint.iandt;
import java.io.File;
import java.io.FilePermission;
import java.lang.reflect.ReflectPermission;
import java.security.AllPermission;
import java.security.Permission;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.PropertyPermission;
import java.util.jar.Manifest;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.BundlePermission;
import org.osgi.framework.Constants;
import org.osgi.framework.PackagePermission;
import org.osgi.framework.ServicePermission;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.SynchronousBundleListener;
import org.osgi.service.permissionadmin.PermissionAdmin;
import org.osgi.service.permissionadmin.PermissionInfo;
import org.springframework.core.io.Resource;
import org.eclipse.gemini.blueprint.test.AbstractConfigurableBundleCreatorTests;
import org.eclipse.gemini.blueprint.test.platform.OsgiPlatform;
import org.eclipse.gemini.blueprint.test.provisioning.ArtifactLocator;
import org.eclipse.gemini.blueprint.util.OsgiStringUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
/**
* Base test class used for improving performance of integration tests by
* creating bundles only with the classes within a package as opposed to all
* resources available in the target folder.
*
* <p/>
* Additionally, the class checks for the presence Clover if a certain property
* is set and uses a special setup to use the instrumented jars instead of the
* naked ones.
*
* @author Costin Leau
*
*/
public abstract class BaseIntegrationTest extends AbstractConfigurableBundleCreatorTests {
private class CloverClassifiedArtifactLocator implements ArtifactLocator {
private final ArtifactLocator delegate;
public CloverClassifiedArtifactLocator(ArtifactLocator delegate) {
this.delegate = delegate;
}
public Resource locateArtifact(String group, String id, String version, String type) {
return parse(id + "-" + version, delegate.locateArtifact(group, id, version, type));
}
public Resource locateArtifact(String group, String id, String version) {
return parse(id + "-" + version, delegate.locateArtifact(group, id, version));
}
private Resource parse(String id, Resource resource) {
if (id.indexOf(SPRING_DM_PREFIX) > -1) {
try {
String relativePath = "";
// check if it's a relative file
if (StringUtils.cleanPath(resource.getURI().toString()).indexOf("/target/") > -1) {
relativePath = "clover" + File.separator;
}
relativePath = relativePath + id + "-clover.jar";
Resource res = resource.createRelative(relativePath);
BaseIntegrationTest.this.logger.info("Using clover instrumented jar " + res.getDescription());
return res;
}
catch (Exception ex) {
throw (RuntimeException) new IllegalStateException(
"Trying to find Clover instrumented class but none is available; disable clover or build the instrumented artifacts").initCause(ex);
}
}
return resource;
}
}
private class PermissionManager implements SynchronousBundleListener {
private final PermissionAdmin pa;
/**
* Constructs a new <code>PermissionManager</code> instance.
*
* @param bc
*/
private PermissionManager(BundleContext bc) {
ServiceReference ref = bc.getServiceReference(PermissionAdmin.class.getName());
if (ref != null) {
logger.trace("Found permission admin " + ref);
pa = (PermissionAdmin) bc.getService(ref);
bc.addBundleListener(this);
logger.trace("Default permissions are " + ObjectUtils.nullSafeToString(pa.getDefaultPermissions()));
logger.warn("Security turned ON");
}
else {
logger.warn("Security turned OFF");
pa = null;
}
}
public void bundleChanged(BundleEvent event) {
if (event.getType() == BundleEvent.INSTALLED) {
Bundle bnd = event.getBundle();
String location = bnd.getLocation();
// iandt bundles
if (location.indexOf("iandt") > -1 || location.indexOf("integration-tests") > -1) {
logger.trace("Discovered I&T test...");
List perms = getIAndTPermissions();
// define permission info
PermissionInfo[] pi = getPIFromPermissions(perms);
logger.info("About to set permissions " + perms + " for I&T bundle "
+ OsgiStringUtils.nullSafeNameAndSymName(bnd) + "@" + location);
pa.setPermissions(location, pi);
}
// on the fly test
else if (location.indexOf("onTheFly") > -1) {
logger.trace("Discovered on the fly test...");
List<Permission> perms = getTestPermissions();
// define permission info
PermissionInfo[] pi = getPIFromPermissions(perms);
logger.info("About to set permissions " + perms + " for OnTheFly bundle "
+ OsgiStringUtils.nullSafeNameAndSymName(bnd) + "@" + location);
pa.setPermissions(location, pi);
}
// logging bundle
else if (bnd.getSymbolicName().indexOf("log4j.osgi") > -1) {
logger.trace("Setting permissions on log4j bundle " + OsgiStringUtils.nullSafeNameAndSymName(bnd));
List<Permission> perms = new ArrayList<Permission>();
// defaults
perms.add(new AllPermission());
PermissionInfo[] defaultPerm = pa.getDefaultPermissions();
if (defaultPerm != null)
CollectionUtils.mergeArrayIntoCollection(defaultPerm, perms);
pa.setPermissions(location, getPIFromPermissions(perms));
}
}
}
private PermissionInfo[] getPIFromPermissions(List perms) {
PermissionInfo[] pi = new PermissionInfo[perms.size()];
int index = 0;
for (Iterator iterator = perms.iterator(); iterator.hasNext();) {
Permission perm = (Permission) iterator.next();
pi[index++] = new PermissionInfo(perm.getClass().getName(), perm.getName(), perm.getActions());
}
return pi;
}
}
private static final String CLOVER_PROPERTY = "org.eclipse.gemini.blueprint.integration.testing.clover";
private static final String CLOVER_PKG = "com_cenqua_clover";
private static final String SPRING_DM_PREFIX = "spring-osgi";
protected String[] getBundleContentPattern() {
String pkg = getClass().getPackage().getName().replace('.', '/').concat("/");
String[] patterns = new String[] { BaseIntegrationTest.class.getName().replace('.', '/').concat("*.class"),
pkg + "**/*" };
return patterns;
}
protected void preProcessBundleContext(BundleContext context) throws Exception {
super.preProcessBundleContext(context);
if (isCloverEnabled()) {
logger.warn("Test coverage instrumentation (Clover) enabled");
}
}
private boolean isCloverEnabled() {
return Boolean.getBoolean(CLOVER_PROPERTY);
}
protected ArtifactLocator getLocator() {
ArtifactLocator defaultLocator = super.getLocator();
// redirect to the clover artifacts
if (isCloverEnabled()) {
return new CloverClassifiedArtifactLocator(defaultLocator);
}
return defaultLocator;
}
protected List getBootDelegationPackages() {
List bootPkgs = super.getBootDelegationPackages();
if (isCloverEnabled()) {
bootPkgs.add(CLOVER_PKG);
}
return bootPkgs;
}
protected Manifest getManifest() {
String permissionPackage = "org.osgi.service.permissionadmin";
Manifest mf = super.getManifest();
// make permission admin packages optional
String impPackage = mf.getMainAttributes().getValue(Constants.IMPORT_PACKAGE);
int startIndex = impPackage.indexOf(permissionPackage);
String newImpPackage = impPackage;
if (startIndex >= 0) {
newImpPackage = impPackage.substring(0, startIndex) + permissionPackage + ";resolution:=optional"
+ impPackage.substring(startIndex + permissionPackage.length());
}
mf.getMainAttributes().putValue(Constants.IMPORT_PACKAGE, newImpPackage);
return mf;
}
/**
* Returns the list of permissions for the running test.
*
* @return
*/
protected List<Permission> getTestPermissions() {
List<Permission> perms = new ArrayList<Permission>();
perms.add(new PackagePermission("*", PackagePermission.EXPORT));
perms.add(new PackagePermission("*", PackagePermission.IMPORT));
perms.add(new BundlePermission("*", BundlePermission.HOST));
perms.add(new BundlePermission("*", BundlePermission.PROVIDE));
perms.add(new BundlePermission("*", BundlePermission.REQUIRE));
perms.add(new ServicePermission("*", ServicePermission.REGISTER));
perms.add(new ServicePermission("*", ServicePermission.GET));
perms.add(new PropertyPermission("*", "read,write"));
// required by Spring
perms.add(new RuntimePermission("*", "accessDeclaredMembers"));
perms.add(new ReflectPermission("*", "suppressAccessChecks"));
// logging permission
perms.add(new FilePermission("-", "write"));
perms.add(new FilePermission("-", "read"));
return perms;
}
protected List<Permission> getIAndTPermissions() {
List<Permission> perms = new ArrayList<Permission>();
// export package
perms.add(new PackagePermission("*", PackagePermission.EXPORT));
perms.add(new PackagePermission("*", PackagePermission.IMPORT));
perms.add(new BundlePermission("*", BundlePermission.FRAGMENT));
perms.add(new BundlePermission("*", BundlePermission.PROVIDE));
perms.add(new ServicePermission("*", ServicePermission.REGISTER));
perms.add(new ServicePermission("*", ServicePermission.GET));
perms.add(new PropertyPermission("*", "read,write"));
// required by Spring
perms.add(new RuntimePermission("*", "accessDeclaredMembers"));
perms.add(new ReflectPermission("*", "suppressAccessChecks"));
// logging permission
perms.add(new FilePermission("-", "write"));
perms.add(new FilePermission("-", "read"));
return perms;
}
@Override
protected OsgiPlatform createPlatform() {
OsgiPlatform platform = super.createPlatform();
platform.getConfigurationProperties().setProperty("org.osgi.framework.storage.clean", "onFirstInit");
platform.getConfigurationProperties().setProperty("felix.fragment.validation", "warning");
// KF 3.1 settings
//platform.getConfigurationProperties().setProperty("org.knopflerfish.framework.all_signed", "false");
//platform.getConfigurationProperties().setProperty("org.knopflerfish.framework.debug.classloader", "true");
//platform.getConfigurationProperties().setProperty("org.knopflerfish.framework.bundlestorage", "file");
return platform;
}
}