blob: 3bc8b1976722fc2ff06c5828fea55b21102c0aca [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2022 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
* EclipseSource Corporation - ongoing enhancements
*******************************************************************************/
package org.eclipse.pde.launching;
import java.io.File;
import java.net.URL;
import java.util.*;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import org.eclipse.core.runtime.*;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.pde.core.plugin.*;
import org.eclipse.pde.internal.build.IPDEBuildConstants;
import org.eclipse.pde.internal.core.ClasspathHelper;
import org.eclipse.pde.internal.core.P2Utils;
import org.eclipse.pde.internal.core.util.CoreUtility;
import org.eclipse.pde.internal.launching.*;
import org.eclipse.pde.internal.launching.launcher.*;
/**
* A launch delegate for launching the Equinox framework
* <p>
* Clients may subclass and instantiate this class.
* </p>
* <p>
* This class originally existed in 3.2 as
* <code>org.eclipse.pde.ui.launcher.EquinoxLaunchConfiguration</code>.
* </p>
* @since 3.6
*/
public class EquinoxLaunchConfiguration extends AbstractPDELaunchConfiguration {
static {
RequirementHelper.registerLaunchTypeRequirements(IPDELauncherConstants.OSGI_CONFIGURATION_TYPE, lc -> {
OSGiFrameworkManager framworkManager = PDELaunchingPlugin.getDefault().getOSGiFrameworkManager();
String id = lc.getAttribute(IPDELauncherConstants.OSGI_FRAMEWORK_ID, framworkManager.getDefaultFramework());
if ("org.eclipse.pde.ui.EquinoxFramework".equals(id)) { //$NON-NLS-1$
return List.of(IPDEBuildConstants.BUNDLE_OSGI);
}
return Collections.emptyList();
});
}
// used to generate the dev classpath entries
// key is bundle ID, value is a List of models
protected Map<String, List<IPluginModelBase>> fAllBundles;
// key is a model, value is startLevel:autoStart
private Map<IPluginModelBase, String> fModels;
@Override
public String[] getProgramArguments(ILaunchConfiguration configuration) throws CoreException {
ArrayList<String> programArgs = new ArrayList<>();
programArgs.add("-dev"); //$NON-NLS-1$
programArgs.add(ClasspathHelper.getDevEntriesProperties(getConfigDir(configuration).toString() + "/dev.properties", fAllBundles)); //$NON-NLS-1$
saveConfigurationFile(configuration);
programArgs.add("-configuration"); //$NON-NLS-1$
programArgs.add("file:" + new Path(getConfigDir(configuration).getPath()).addTrailingSeparator().toString()); //$NON-NLS-1$
String[] args = super.getProgramArguments(configuration);
Collections.addAll(programArgs, args);
return programArgs.toArray(new String[programArgs.size()]);
}
private void saveConfigurationFile(ILaunchConfiguration configuration) throws CoreException {
Properties properties = new Properties();
properties.setProperty("osgi.install.area", "file:" + TargetPlatform.getLocation()); //$NON-NLS-1$ //$NON-NLS-2$
properties.setProperty("osgi.configuration.cascaded", "false"); //$NON-NLS-1$ //$NON-NLS-2$
properties.put("osgi.framework", LaunchConfigurationHelper.getBundleURL(IPDEBuildConstants.BUNDLE_OSGI, fAllBundles, false)); //$NON-NLS-1$
int start = configuration.getAttribute(IPDELauncherConstants.DEFAULT_START_LEVEL, 4);
properties.put("osgi.bundles.defaultStartLevel", Integer.toString(start)); //$NON-NLS-1$
boolean autostart = configuration.getAttribute(IPDELauncherConstants.DEFAULT_AUTO_START, true);
String bundles = null;
if (fAllBundles.containsKey(IPDEBuildConstants.BUNDLE_SIMPLE_CONFIGURATOR)) {
// If simple configurator is being used, we need to write out the bundles.txt instead of writing out the list in the config.ini
URL bundlesTxt = P2Utils.writeBundlesTxt(fModels, start, autostart, getConfigDir(configuration), null);
if (bundlesTxt != null) {
properties.setProperty("org.eclipse.equinox.simpleconfigurator.configUrl", bundlesTxt.toString()); //$NON-NLS-1$
}
StringBuilder buffer = new StringBuilder();
IPluginModelBase model = LaunchConfigurationHelper.getLatestModel(IPDEBuildConstants.BUNDLE_SIMPLE_CONFIGURATOR, fAllBundles);
buffer.append(LaunchConfigurationHelper.getBundleURL(model, true));
appendStartData(buffer, fModels.get(model), autostart);
bundles = buffer.toString();
} else {
bundles = getBundles(autostart);
}
if (bundles.length() > 0)
properties.put("osgi.bundles", bundles); //$NON-NLS-1$
if (!"3.3".equals(configuration.getAttribute(IPDEConstants.LAUNCHER_PDE_VERSION, ""))) { //$NON-NLS-1$ //$NON-NLS-2$
properties.put("eclipse.ignoreApp", "true"); //$NON-NLS-1$ //$NON-NLS-2$
properties.put("osgi.noShutdown", "true"); //$NON-NLS-1$ //$NON-NLS-2$
}
LaunchConfigurationHelper.save(new File(getConfigDir(configuration), "config.ini"), properties); //$NON-NLS-1$
}
private String getBundles(boolean defaultAuto) {
StringBuilder buffer = new StringBuilder();
for (Entry<IPluginModelBase, String> entry : fModels.entrySet()) {
IPluginModelBase model = entry.getKey();
String id = model.getPluginBase().getId();
if (!IPDEBuildConstants.BUNDLE_OSGI.equals(id)) {
if (buffer.length() > 0)
buffer.append(","); //$NON-NLS-1$
buffer.append(LaunchConfigurationHelper.getBundleURL(model, true));
// fragments must not be started or have a start level
if (model instanceof IFragmentModel)
continue;
String data = entry.getValue();
appendStartData(buffer, data, defaultAuto);
}
}
return buffer.toString();
}
/**
* Convenience method to parses the startData ("startLevel:autoStart"), convert it to the
* format expected by the OSGi bundles property, and append to a StringBuilder.
* @param buffer buffer to append the data to
* @param startData data to parse ("startLevel:autoStart")
* @param defaultAuto default auto start setting
*/
private void appendStartData(StringBuilder buffer, String startData, boolean defaultAuto) {
int index = startData.indexOf(':');
String level = index > 0 ? startData.substring(0, index) : "default"; //$NON-NLS-1$
String auto = index > 0 && index < startData.length() - 1 ? startData.substring(index + 1) : "default"; //$NON-NLS-1$
if ("default".equals(auto)) //$NON-NLS-1$
auto = Boolean.toString(defaultAuto);
if (!level.equals("default") || "true".equals(auto)) //$NON-NLS-1$ //$NON-NLS-2$
buffer.append("@"); //$NON-NLS-1$
if (!level.equals("default")) { //$NON-NLS-1$
buffer.append(level);
if ("true".equals(auto)) //$NON-NLS-1$
buffer.append(":"); //$NON-NLS-1$
}
if ("true".equals(auto)) { //$NON-NLS-1$
buffer.append("start"); //$NON-NLS-1$
}
}
@Override
protected void preLaunchCheck(ILaunchConfiguration configuration, ILaunch launch, IProgressMonitor monitor) throws CoreException {
fModels = BundleLauncherHelper.getMergedBundleMap(configuration, true);
if (!RequirementHelper.addApplicationLaunchRequirements(fModels, configuration)) {
throw new CoreException(Status.error(PDEMessages.EquinoxLaunchConfiguration_oldTarget));
}
fAllBundles = fModels.keySet().stream().collect(Collectors.groupingBy(m -> m.getPluginBase().getId(), HashMap::new, Collectors.toCollection(ArrayList::new)));
super.preLaunchCheck(configuration, launch, monitor);
}
@Override
protected void validatePluginDependencies(ILaunchConfiguration configuration, IProgressMonitor monitor) throws CoreException {
LaunchValidationOperation op = new LaunchValidationOperation(configuration, fModels.keySet());
LaunchPluginValidator.runValidationOperation(op, monitor);
}
/**
* Clears the configuration area if the area exists and that option is selected.
*
* @param configuration
* the launch configuration
* @param monitor
* the progress monitor
* @throws CoreException
* if unable to retrieve launch attribute values
* @since 3.3
*/
@Override
protected void clear(ILaunchConfiguration configuration, IProgressMonitor monitor) throws CoreException {
// clear config area, if necessary
if (configuration.getAttribute(IPDELauncherConstants.CONFIG_CLEAR_AREA, false))
CoreUtility.deleteContent(getConfigDir(configuration), monitor);
}
}