package org.ant4eclipse.ant.pde; import static org.ant4eclipse.lib.core.Assure.notNull; import static org.ant4eclipse.lib.core.logging.A4ELogging.warn; import org.ant4eclipse.ant.core.FileListHelper; import org.ant4eclipse.ant.platform.ExecuteLauncherTask; import org.ant4eclipse.ant.platform.core.MacroExecutionValues; import org.ant4eclipse.ant.platform.core.delegate.MacroExecutionValuesProvider; import org.ant4eclipse.lib.core.service.ServiceRegistryAccess; import org.ant4eclipse.lib.core.util.StringMap; import org.ant4eclipse.lib.core.util.Utilities; import org.ant4eclipse.lib.jdt.model.jre.JavaRuntime; import org.ant4eclipse.lib.jdt.model.jre.JavaRuntimeRegistry; import org.ant4eclipse.lib.pde.model.launcher.EquinoxLaunchConfigurationWrapper; import org.ant4eclipse.lib.pde.model.launcher.SelectedLaunchConfigurationBundle; import org.ant4eclipse.lib.pde.model.pluginproject.BundleSource; import org.ant4eclipse.lib.platform.model.launcher.LaunchConfiguration; import org.ant4eclipse.lib.platform.model.resource.EclipseProject; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.taskdefs.MacroDef; import org.eclipse.osgi.service.resolver.BundleDescription; import org.osgi.framework.Version; import java.io.File; /** * Executes a Equinox Launch Configuration (type="org.eclipse.pde.ui.EquinoxLauncher") * * @author Nils Hartmann (nils@nilshartmann.net) */ public class ExecuteEquinoxLauncherTask extends ExecuteLauncherTask implements TargetPlatformAwareComponent { /** * The forEachBundle scope that is invoked for each bundle that is selected either from the workspace or the target * platform */ public static final String SCOPE_FOR_EACH_SELECTED_BUNDLE = "forEachSelectedBundle"; /** - */ private TargetPlatformAwareDelegate _targetPlatformAwareDelegate; /** * Create new instance */ public ExecuteEquinoxLauncherTask() { super("executeEquinoxLauncher"); 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(); } /** * Makes sure the selected launch configuration is a PDE-Launch Configuration */ @Override protected void ensureSupportedLaunchConfiguration(LaunchConfiguration launchConfiguration) { super.ensureSupportedLaunchConfiguration(launchConfiguration); if (!EquinoxLaunchConfigurationWrapper.isEquinoxLaunchConfiguration(launchConfiguration)) { throw new BuildException("The launch configuration you've specified must be a Equinox launch configuration"); } } @Override public Object createDynamicElement(String name) throws BuildException { // handle 'forEachSelectedBundle' element if (SCOPE_FOR_EACH_SELECTED_BUNDLE.equalsIgnoreCase(name)) { return createScopedMacroDefinition(SCOPE_FOR_EACH_SELECTED_BUNDLE); } // all other scopes: not handled here, try super class return super.createDynamicElement(name); } /** * Make sure all preconditions are fulfilled before executing the task */ @Override protected void preconditions() throws BuildException { super.preconditions(); this._targetPlatformAwareDelegate.requireTargetPlatformIdSet(); } /** * Execute the scoped macro definitions */ @Override protected void doExecute(String scope, MacroDef macroDef) { if (SCOPE_FOR_EACH_SELECTED_BUNDLE.equals(scope)) { executeForEachSelectedBundleScopedMacroDef(macroDef); } else { super.doExecute(scope, macroDef); } } /** * Run the 'forEachSelectedBundle' macro * * @param macroDef */ private void executeForEachSelectedBundleScopedMacroDef(MacroDef macroDef) { // Step 1: read the launchconfiguration file final LaunchConfiguration launchConfiguration = getLaunchConfiguration(); // Step 2: Create a EquinoxLaunchConfigurationWrapper to access Equinox-specific settings in launch config EquinoxLaunchConfigurationWrapper wrapper = new EquinoxLaunchConfigurationWrapper(launchConfiguration); // Step 3: Get all selected workspace bundles final SelectedLaunchConfigurationBundle[] selectedWorkspaceBundles = wrapper.getSelectedWorkspaceBundles(); // Step 3a: run the macro for each workspace bundle for (SelectedLaunchConfigurationBundle selectedWorkspaceBundle : selectedWorkspaceBundles) { executeMacroInstance(macroDef, createBundleMacroExecuteValuesProvider(wrapper, selectedWorkspaceBundle, true)); } // Step 4: Get all selected bundles from target platform final SelectedLaunchConfigurationBundle[] selectedTargetBundles = wrapper.getSelectedTargetBundles(); // Step 4a: Run the macro for each selected target platform bundle for (SelectedLaunchConfigurationBundle selectedTargetBundle : selectedTargetBundles) { executeMacroInstance(macroDef, createBundleMacroExecuteValuesProvider(wrapper, selectedTargetBundle, false)); } } /** * Creates a {@link MacroExecutionValuesProvider} for the given selected bundle. * * <p> * The providered that is returned contains all properties and references that should passed to the macro * * @param wrapper * @param selectedBundle * @param workspaceBundle * @return */ protected MacroExecutionValuesProvider createBundleMacroExecuteValuesProvider( final EquinoxLaunchConfigurationWrapper wrapper, final SelectedLaunchConfigurationBundle selectedBundle, final boolean workspaceBundle) { notNull("wrapper", wrapper); notNull("launchConfigurationBundleInfo", selectedBundle); final BundleDescription bundleDescription = getResolvedBundle(selectedBundle); return new MacroExecutionValuesProvider() { public MacroExecutionValues provideMacroExecutionValues(MacroExecutionValues values) { values = provideDefaultMacroExecutionValues(values); final StringMap properties = values.getProperties(); properties.put("selectedBundle.symbolicName", selectedBundle.getBundleSymbolicName()); String version = selectedBundle.hasVersion() ? selectedBundle.getVersion() : ""; properties.put("selectedBundle.version", version); properties.put("selectedBundle.startLevel", selectedBundle.getStartLevel()); properties.put("selectedBundle.autoStart", selectedBundle.getAutoStart()); properties.put("selectedBundle.workspaceBundle", Boolean.toString(workspaceBundle)); properties.put("selectedBundle.targetBundle", Boolean.toString(!workspaceBundle)); final String resolvedStartLevel = wrapper.getResolvedStartLevel(selectedBundle); properties.put("selectedBundle.resolvedStartLevel", resolvedStartLevel); final String resolvedAutoStart = wrapper.getResolvedAutoStart(selectedBundle); properties.put("selectedBundle.resolvedAutoStart", resolvedAutoStart); // set the "bundle start parameter" as expected in osgi.bundles property String bundleStart = ""; if (Utilities.hasText(resolvedStartLevel)) { bundleStart = "@" + resolvedStartLevel; } if (Utilities.hasText(resolvedAutoStart)) { if (Utilities.hasText(bundleStart)) { bundleStart += ":" + resolvedAutoStart; } else { bundleStart = "@" + resolvedAutoStart; } } properties.put("selectedBundle.startParameter", bundleStart); if (bundleDescription != null) { BundleSource bundlesource = (BundleSource) bundleDescription.getUserObject(); properties.put("resolvedBundle.version", bundleDescription.getVersion().toString()); properties.put("resolvedBundle.isSystemBundle", Boolean.toString(bundleDescription.getBundleId() == 0)); if (bundlesource.isEclipseProject()) { // Plug-in is a source project contained in the workspace EclipseProject project = bundlesource.getAsEclipseProject(); File location = project.getFolder(); properties.put("resolvedBundle.isSource", "true"); properties.put("resolvedBundle.file", location.getAbsolutePath()); properties.put("resolvedBundle.fileName", location.getName()); properties.put("resolvedBundle.projectName", project.getSpecifiedName()); } else { // Bundle comes from the target platform File location = bundlesource.getAsFile(); properties.put("resolvedBundle.isSource", "false"); properties.put("resolvedBundle.file", location.getAbsolutePath()); properties.put("resolvedBundle.fileName", location.getName()); values.getReferences().put("resolvedBundle.fileList", FileListHelper.getFileList(location)); } } return values; } }; } /** * Returns the resolved bundle from the target platform * * @param launchConfigurationBundleInfo * @return the {@link BundleDescription} for the selected bundle or null if the bundle could not be resolved */ protected BundleDescription getResolvedBundle(SelectedLaunchConfigurationBundle launchConfigurationBundleInfo) { String bundleSymbolicName = launchConfigurationBundleInfo.getBundleSymbolicName(); Version osgiVersion = (launchConfigurationBundleInfo.hasVersion() ? new Version(launchConfigurationBundleInfo .getVersion()) : null); BundleDescription bundleDescription = this._targetPlatformAwareDelegate.getTargetPlatform(getWorkspace()) .getResolvedBundle(bundleSymbolicName, osgiVersion); if (bundleDescription == null) { warn("Bundle '%s' with version '%s' not found in target platform", bundleSymbolicName, osgiVersion); } return bundleDescription; } @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()); return defaultValues; } /** * Returns the Java Runtime for the current launch configuration * * @return */ protected JavaRuntime getJavaRuntime() { LaunchConfiguration launchConfiguration = getLaunchConfiguration(); JavaRuntimeRegistry javaRuntimeRegistry = ServiceRegistryAccess.instance().getService(JavaRuntimeRegistry.class); String vmPath = launchConfiguration.getAttribute("org.eclipse.jdt.launching.JRE_CONTAINER"); if (vmPath == null) { return javaRuntimeRegistry.getDefaultJavaRuntime(); } JavaRuntime javaRuntime = javaRuntimeRegistry.getJavaRuntimeForPath(vmPath); return javaRuntime; } }