package org.ant4eclipse.ant.pde;
import java.io.File;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.ant4eclipse.ant.pde.analysis.TestClassAnalyser;
import org.ant4eclipse.ant.platform.ExecuteLauncherTask;
import org.ant4eclipse.ant.platform.core.MacroExecutionValues;
import org.ant4eclipse.lib.core.logging.A4ELogging;
import org.ant4eclipse.lib.core.osgi.BundleLayoutResolver;
import org.ant4eclipse.lib.core.service.ServiceRegistryAccess;
import org.ant4eclipse.lib.core.util.StringMap;
import org.ant4eclipse.lib.jdt.model.jre.JavaRuntime;
import org.ant4eclipse.lib.jdt.model.jre.JavaRuntimeRegistry;
import org.ant4eclipse.lib.jdt.model.project.JavaProjectRole;
import org.ant4eclipse.lib.pde.internal.tools.BundleDependenciesResolver;
import org.ant4eclipse.lib.pde.internal.tools.BundleDependenciesResolver.BundleDependency;
import org.ant4eclipse.lib.pde.internal.tools.UnresolvedBundleException;
import org.ant4eclipse.lib.pde.model.launcher.EquinoxLaunchConfigurationWrapper;
import org.ant4eclipse.lib.pde.model.pluginproject.BundleSource;
import org.ant4eclipse.lib.pde.model.pluginproject.PluginProjectRole;
import org.ant4eclipse.lib.pde.tools.TargetPlatform;
import org.ant4eclipse.lib.platform.model.launcher.LaunchConfiguration;
import org.apache.tools.ant.BuildException;
import org.eclipse.osgi.service.resolver.BundleDescription;
/**
* <p>
* Executes a PDE JUnit Launch Configuration (type="org.eclipse.pde.ui.EquinoxLauncher")
* </p>
* <p>
* TODOS:
* <ul>
* <li>Support for 'All workspace and enabled target plug-ins'</li>
* <li>If the test bundle is a fragment bundle, the host must be set as test bundle</li>
* <li></li>
* </ul>
* </p>
*
* @author Nils Hartmann (nils@nilshartmann.net)
* @author Gerd Wütherich (gerd@gerd-wuetherich.de)
*/
public class ExecutePdeJunitLauncherTask extends ExecuteLauncherTask implements TargetPlatformAwareComponent {
/** the target platform delegate */
private TargetPlatformAwareDelegate _targetPlatformAwareDelegate;
/** the 'bundles.info' string builder */
private StringBuilder _bundlesInfo;
/** the 'osgi.bundles' string builder */
private StringBuilder _osgiBundles;
/** the 'dev.properties' string builder */
private StringBuilder _devProperties;
/**
* <p>
* Creates a new instance of type {@link ExecutePdeJunitLauncherTask}.
* </p>
*/
public ExecutePdeJunitLauncherTask() {
super("executePdeJunitLauncher");
// create the delegate
this._targetPlatformAwareDelegate = new TargetPlatformAwareDelegate();
}
/**
* {@inheritDoc}
*/
public String getPlatformConfigurationId() {
return this._targetPlatformAwareDelegate.getPlatformConfigurationId();
}
/**
* {@inheritDoc}
*/
public final String getTargetPlatformId() {
return this._targetPlatformAwareDelegate.getTargetPlatformId();
}
/**
* {@inheritDoc}
*/
public boolean isPlatformConfigurationIdSet() {
return this._targetPlatformAwareDelegate.isPlatformConfigurationIdSet();
}
/**
* {@inheritDoc}
*/
public final boolean isTargetPlatformIdSet() {
return this._targetPlatformAwareDelegate.isTargetPlatformIdSet();
}
/**
* {@inheritDoc}
*/
public void setPlatformConfigurationId(String platformConfigurationId) {
this._targetPlatformAwareDelegate.setPlatformConfigurationId(platformConfigurationId);
}
/**
* {@inheritDoc}
*/
public final void setTargetPlatformId(String targetPlatformId) {
this._targetPlatformAwareDelegate.setTargetPlatformId(targetPlatformId);
}
/**
* {@inheritDoc}
*/
public final void requireTargetPlatformIdSet() {
this._targetPlatformAwareDelegate.requireTargetPlatformIdSet();
}
/**
* {@inheritDoc}
*/
@Override
protected void ensureSupportedLaunchConfiguration(LaunchConfiguration launchConfiguration) {
super.ensureSupportedLaunchConfiguration(launchConfiguration);
// makes sure the selected launch configuration is a PDE-Launch Configuration
if (!EquinoxLaunchConfigurationWrapper.isPdeJunitLaunchConfiguration(launchConfiguration)) {
throw new BuildException("The launch configuration you've specified must be a Equinox launch configuration");
}
}
/**
* {@inheritDoc}
*/
@Override
protected void preconditions() throws BuildException {
super.preconditions();
//
this._targetPlatformAwareDelegate.requireTargetPlatformIdSet();
}
/**
* {@inheritDoc}
*/
@Override
protected MacroExecutionValues provideDefaultMacroExecutionValues(MacroExecutionValues values) {
final MacroExecutionValues defaultValues = super.provideDefaultMacroExecutionValues(values);
// add JRE-Location to scoped properties
JavaRuntime javaRuntime = getJavaRuntime();
defaultValues.getProperties().put("jre.location", javaRuntime.getLocation().getAbsolutePath());
StringMap jrtProperties = javaRuntime.getJavaProfile().getProperties();
defaultValues.getProperties().put("org.osgi.framework.system.packages",
jrtProperties.get("org.osgi.framework.system.packages"));
defaultValues.getProperties().put("org.osgi.framework.bootdelegation",
jrtProperties.get("org.osgi.framework.bootdelegation"));
defaultValues.getProperties().put("org.osgi.framework.executionenvironment",
jrtProperties.get("org.osgi.framework.executionenvironment"));
// compute the bundle information
computeBundlesInfo();
defaultValues.getProperties().put("bundles.info", this._bundlesInfo.toString());
defaultValues.getProperties().put("osgi.bundles", this._osgiBundles.toString());
defaultValues.getProperties().put("dev.properties", this._devProperties.toString());
// set the osgi framework
BundleDescription osgiFramework = this._targetPlatformAwareDelegate.getTargetPlatform(getWorkspace())
.getResolvedBundle("org.eclipse.osgi", null);
if (osgiFramework == null) {
throw new RuntimeException("Bundle 'org.eclipse.osgi' is missing.");
}
defaultValues.getProperties().put("osgi.framework", osgiFramework.getLocation());
// set the test plug-in name and location
PluginProjectRole pluginProjectRole = getEclipseProject().getRole(PluginProjectRole.class);
BundleDescription bundleDescription = pluginProjectRole.getBundleDescription();
bundleDescription = this._targetPlatformAwareDelegate.getTargetPlatform(getWorkspace()).getResolvedBundle(
bundleDescription.getSymbolicName(), bundleDescription.getVersion());
BundleDescription bundleHost;
try {
bundleHost = BundleDependenciesResolver.getHost(bundleDescription);
} catch (UnresolvedBundleException e1) {
throw new RuntimeException("Bundle not resolved: " + e1.getMessage());
}
defaultValues.getProperties().put("testplugin.bundlehost.name", bundleHost.getSymbolicName());
defaultValues.getProperties().put("testplugin.name", bundleDescription.getSymbolicName());
defaultValues.getProperties().put("testplugin.location", bundleDescription.getLocation());
// find contained test classes
defaultValues.getProperties().put("test.classes",
new TestClassAnalyser(getEclipseProject()).getTestClassesAsString());
// compute the 'pde.test.utils' class path
try {
BundleDescription b = this._targetPlatformAwareDelegate.getTargetPlatform(getWorkspace()).getResolvedBundle(
"pde.test.utils", null);
StringBuilder collectorClassPath = new StringBuilder();
for (BundleDependency dependency : new BundleDependenciesResolver().resolveBundleClasspath(b)) {
buildClassPath(dependency.getHost(), collectorClassPath);
}
buildClassPath(b, collectorClassPath);
defaultValues.getProperties().put("collectorCP", collectorClassPath.toString());
} catch (UnresolvedBundleException e) {
e.printStackTrace();
}
//
return defaultValues;
}
/**
* <p>
* </p>
*
* @param bundleDescription
* @param classpath
*/
private void buildClassPath(BundleDescription bundleDescription, StringBuilder classpath) {
// get the layout resolver
BundleLayoutResolver resolver = BundleDependenciesResolver.getBundleLayoutResolver(bundleDescription);
// add all entries
File[] entries = resolver.resolveBundleClasspathEntries();
for (File file : entries) {
classpath.append(file.getAbsolutePath());
classpath.append(File.pathSeparatorChar);
}
}
/**
* <p>
* </p>
*/
private void computeBundlesInfo() {
// initialize result
this._bundlesInfo = new StringBuilder();
this._osgiBundles = new StringBuilder();
this._devProperties = new StringBuilder();
this._devProperties.append("@ignoredot@=true\n");
// compute contained bundles
computeBundles(getLaunchConfiguration().getAttribute("selected_workspace_plugins"), true);
computeBundles(getLaunchConfiguration().getAttribute("selected_target_plugins"), false);
// add additional bundles
BundleDescription b = this._targetPlatformAwareDelegate.getTargetPlatform(getWorkspace()).getResolvedBundle(
"org.eclipse.pde.junit.runtime", null);
handle(b.getSymbolicName(), "4", "false", false);
b = this._targetPlatformAwareDelegate.getTargetPlatform(getWorkspace()).getResolvedBundle(
"org.eclipse.jdt.junit4.runtime", null);
handle(b.getSymbolicName(), "4", "false", false);
try {
List<BundleDependency> dependencies = new BundleDependenciesResolver().resolveBundleClasspath(b);
for (BundleDependency bundleDependency : dependencies) {
// TODO: fragments
handle(bundleDependency.getHost().getSymbolicName(), "4", "false", false);
}
} catch (UnresolvedBundleException e) {
e.printStackTrace();
}
}
/**
* <p>
* </p>
*
* @param bundleList
* @param takeBundlesFromWorkspace
*/
private void computeBundles(String bundleList, boolean takeBundlesFromWorkspace) {
String[] workspacePlugins = bundleList.split(",");
for (String workspacePlugin : workspacePlugins) {
Pattern pattern = Pattern.compile("(.*)@(.*):(.*)");
Matcher matcher = pattern.matcher(workspacePlugin);
matcher.matches();
handle(matcher.group(1), matcher.group(2), matcher.group(3), takeBundlesFromWorkspace);
}
}
/**
* <p>
* </p>
*
* @param symName
* @param startLevel
* @param autoStart
* @param workspaceBundles
*/
private void handle(String symName, String startLevel, String autoStart, boolean workspaceBundles) {
//
if (symName.indexOf('*') != -1) {
symName = symName.split("\\*")[0];
}
//
TargetPlatform targetPlatform = this._targetPlatformAwareDelegate.getTargetPlatform(getWorkspace());
BundleDescription description = workspaceBundles ? targetPlatform.getBundleDescriptionFromWorkspace(symName)
: targetPlatform.getBundleDescriptionFromBinaryBundles(symName);
//
if (description == null) {
A4ELogging.warn("Bundle '%s' does not exist!", symName);
}
//
if (description.getBundleId() != 0) {
//
BundleSource bundleSource = (BundleSource) description.getUserObject();
//
if (bundleSource.isEclipseProject()) {
//
JavaProjectRole javaProjectRole = bundleSource.getAsEclipseProject().getRole(JavaProjectRole.class);
PluginProjectRole pluginProjectRole = bundleSource.getAsEclipseProject().getRole(PluginProjectRole.class);
//
this._devProperties.append(pluginProjectRole.getBundleDescription().getSymbolicName());
this._devProperties.append("=");
this._devProperties.append(javaProjectRole.getDefaultOutputFolder());
this._devProperties.append("\n");
}
this._bundlesInfo.append(String.format("%s,%s,file:/%s,4,%s\n", description.getSymbolicName(),
description.getVersion(), description.getLocation(), autoStart.equals("true")));
this._osgiBundles.append(String.format("reference\\:file\\:%s", description.getLocation().replace("\\", "/")));
if (autoStart.equals("true")) {
this._osgiBundles.append("@start");
}
this._osgiBundles.append(",");
}
}
/**
* <p>
* Returns the Java Runtime for the current launch configuration.
* </p>
*
* @return
*/
protected JavaRuntime getJavaRuntime() {
// get the java runtime registry
JavaRuntimeRegistry javaRuntimeRegistry = ServiceRegistryAccess.instance().getService(JavaRuntimeRegistry.class);
// get the vm path
String vmPath = getLaunchConfiguration().getAttribute("org.eclipse.jdt.launching.JRE_CONTAINER");
if (vmPath == null) {
return javaRuntimeRegistry.getDefaultJavaRuntime();
}
// return the runtime
return javaRuntimeRegistry.getJavaRuntimeForPath(vmPath);
}
}