blob: f9eafe383d2cae7377c2ff088a401ddaa17578bc [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2019 Xored Software Inc and others.
* 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:
* Xored Software Inc - initial API and implementation and/or initial documentation
*******************************************************************************/
package org.eclipse.rcptt.launching.ext;
import static java.util.Arrays.asList;
import static org.eclipse.rcptt.internal.launching.ext.AJConstants.OSGI_FRAMEWORK_EXTENSIONS;
import static org.eclipse.rcptt.internal.launching.ext.Q7ExtLaunchingPlugin.log;
import static org.eclipse.rcptt.internal.launching.ext.Q7ExtLaunchingPlugin.status;
import static org.eclipse.rcptt.launching.ext.Q7LaunchDelegateUtils.id;
import static org.eclipse.rcptt.launching.ext.Q7LaunchDelegateUtils.setDelegateFields;
import static org.eclipse.rcptt.launching.ext.StartLevelSupport.getStartInfo;
import static org.eclipse.rcptt.util.Versions.isGreater;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.variables.IStringVariableManager;
import org.eclipse.core.variables.VariablesPlugin;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
import org.eclipse.jdt.launching.IVMInstall;
import org.eclipse.jdt.launching.IVMInstallType;
import org.eclipse.jdt.launching.JavaRuntime;
import org.eclipse.pde.core.plugin.IPluginModelBase;
import org.eclipse.pde.core.target.ITargetDefinition;
import org.eclipse.pde.core.target.ITargetLocation;
import org.eclipse.pde.core.target.TargetBundle;
import org.eclipse.pde.internal.build.IPDEBuildConstants;
import org.eclipse.pde.internal.core.PDEState;
import org.eclipse.pde.internal.core.target.IUBundleContainer;
import org.eclipse.pde.internal.core.target.ProfileBundleContainer;
import org.eclipse.pde.internal.launching.PDEMessages;
import org.eclipse.pde.internal.launching.launcher.LaunchArgumentsHelper;
import org.eclipse.pde.internal.launching.launcher.LauncherUtils;
import org.eclipse.pde.internal.launching.launcher.VMHelper;
import org.eclipse.pde.launching.EclipseApplicationLaunchConfiguration;
import org.eclipse.pde.launching.IPDELauncherConstants;
import org.eclipse.rcptt.internal.launching.aut.LaunchInfoCache;
import org.eclipse.rcptt.internal.launching.aut.LaunchInfoCache.CachedInfo;
import org.eclipse.rcptt.internal.launching.ext.AJConstants;
import org.eclipse.rcptt.internal.launching.ext.IBundlePoolConstansts;
import org.eclipse.rcptt.internal.launching.ext.JDTUtils;
import org.eclipse.rcptt.internal.launching.ext.OSArchitecture;
import org.eclipse.rcptt.internal.launching.ext.Q7ExtLaunchMonitor;
import org.eclipse.rcptt.internal.launching.ext.Q7ExtLaunchingPlugin;
import org.eclipse.rcptt.internal.launching.ext.Q7TargetPlatformManager;
import org.eclipse.rcptt.internal.launching.ext.UpdateVMArgs;
import org.eclipse.rcptt.launching.IQ7Launch;
import org.eclipse.rcptt.launching.common.Q7LaunchingCommon;
import org.eclipse.rcptt.launching.events.AutEventManager;
import org.eclipse.rcptt.launching.internal.target.Q7Target;
import org.eclipse.rcptt.launching.internal.target.TargetPlatformHelper;
import org.eclipse.rcptt.launching.target.ITargetPlatformHelper;
import org.eclipse.rcptt.launching.target.TargetPlatformManager;
import org.eclipse.rcptt.tesla.core.TeslaLimits;
import org.eclipse.rcptt.util.FileUtil;
import org.osgi.framework.Version;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.MoreObjects;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
@SuppressWarnings("restriction")
public class Q7ExternalLaunchDelegate extends
EclipseApplicationLaunchConfiguration {
private static final String ATTR_D32 = "-d32";
private static final String Q7_LAUNCHING_AUT = "RCPTT: Launching AUT: ";
private static final String SECURE_STORAGE_FILE_NAME = "secure_storage";
private ILaunch launch;
@Override
public void launch(ILaunchConfiguration configuration, String mode,
ILaunch launch, IProgressMonitor monitor) throws CoreException {
this.launch = launch;
SubMonitor subm = SubMonitor.convert(monitor, 2000);
Q7ExtLaunchMonitor waiter = new Q7ExtLaunchMonitor(launch);
try {
super.launch(configuration, mode, launch, subm.newChild(1000));
waiter.wait(subm.newChild(1000), TeslaLimits.getAUTStartupTimeout() / 1000);
} catch (CoreException e) {
Q7ExtLaunchingPlugin.getDefault().log(
"RCPTT: Failed to Launch AUT: " + configuration.getName()
+ " cause " + e.getMessage(),
e);
waiter.handle(e);
// no need to throw exception in case of cancel
if (!e.getStatus().matches(IStatus.CANCEL)) {
throw e;
}
} catch (RuntimeException e) {
Q7ExtLaunchingPlugin.getDefault().log(
"RCPTT: Failed to Launch AUT: " + configuration.getName()
+ " cause " + e.getMessage(),
e);
waiter.handle(e);
throw e;
} finally {
waiter.dispose();
}
monitor.done();
}
@Override
protected void manageLaunch(ILaunch launch) {
// remove base PDE launch management
}
@Override
protected boolean saveBeforeLaunch(ILaunchConfiguration configuration,
String mode, IProgressMonitor monitor) throws CoreException {
if (isHeadless(configuration)) {
return true;
}
return super.saveBeforeLaunch(configuration, mode, monitor);
}
@Override
public boolean finalLaunchCheck(ILaunchConfiguration configuration,
String mode, IProgressMonitor monitor) throws CoreException {
if (isHeadless(configuration)) {
return true;
}
return super.finalLaunchCheck(configuration, mode, monitor);
}
@Override
public boolean preLaunchCheck(ILaunchConfiguration configuration,
String mode, IProgressMonitor monitor) throws CoreException {
if (monitor.isCanceled()) {
return false;
}
monitor.beginTask("", 4);
if (!isHeadless(configuration)
&& !super.preLaunchCheck(configuration, mode,
new SubProgressMonitor(monitor, 1))) {
monitor.done();
return false;
}
waitForClearBundlePool(monitor);
final CachedInfo info = LaunchInfoCache.getInfo(configuration);
if (info.target != null) {
monitor.done();
return true;
}
final ITargetPlatformHelper target = Q7TargetPlatformManager.getTarget(configuration,
SubMonitor.convert(monitor, 2));
if (monitor.isCanceled()) {
removeTargetPlatform(configuration);
return false;
}
info.target = target;
final MultiStatus error = new MultiStatus(Q7ExtLaunchingPlugin.PLUGIN_ID, 0,
"Target platform initialization failed for "
+ configuration.getName(),
null);
error.add(target.getStatus());
if (!error.isOK()) {
if (monitor.isCanceled()) {
removeTargetPlatform(configuration);
return false;
}
Q7ExtLaunchingPlugin.log(error);
removeTargetPlatform(configuration);
throw new CoreException(error);
}
boolean haveAUT = false;
OSArchitecture configArch = null;
StringBuilder detectMsg = new StringBuilder();
OSArchitecture architecture = ((configArch == null) ? ((ITargetPlatformHelper) info.target)
.detectArchitecture(true, detectMsg) : configArch);
Q7ExtLaunchingPlugin.getDefault().info(
Q7_LAUNCHING_AUT + configuration.getName()
+ ": Detected AUT architecture is "
+ architecture.name() + "." + detectMsg.toString());
IVMInstall install = VMHelper.getVMInstall(configuration);
OSArchitecture jvmArch = JDTUtils.detect(install);
Q7ExtLaunchingPlugin.getDefault().info(
Q7_LAUNCHING_AUT + configuration.getName()
+ ": Selected JVM is "
+ install.getInstallLocation().toString()
+ " detected architecture is " + jvmArch.name());
boolean canRun32bit = false;
if (jvmArch.equals(architecture)
|| (jvmArch.equals(OSArchitecture.x86_64) && (canRun32bit = JDTUtils
.canRun32bit(install)))) {
haveAUT = true;
}
if (!haveAUT
&& architecture != OSArchitecture.Unknown
&& target.detectArchitecture(false, new StringBuilder()) == OSArchitecture.Unknown) {
Q7ExtLaunchingPlugin
.getDefault()
.info("Cannot determine AUT architecture, sticking to architecture of selected JVM, which is "
+ jvmArch.name());
haveAUT = true;
}
Q7ExtLaunchingPlugin
.getDefault()
.info(Q7_LAUNCHING_AUT
+ configuration.getName()
+ ": JVM and AUT architectures are compatible: "
+ haveAUT
+ "."
+ (jvmArch.equals(OSArchitecture.x86_64) ? " JVM is 64bit and support running 32bit: "
+ canRun32bit
: ""));
if (!haveAUT) {
// Let's search for configuration and update JVM if possible.
haveAUT = updateJVM(configuration, architecture,
((ITargetPlatformHelper) info.target));
if (!haveAUT) {
// try to register current JVM, it may help
JDTUtils.registerCurrentJVM();
haveAUT = updateJVM(configuration, architecture,
((ITargetPlatformHelper) info.target));
}
if (haveAUT) {
Q7ExtLaunchingPlugin
.getDefault()
.info(Q7_LAUNCHING_AUT
+ configuration.getName()
+ "JVM configuration is updated to compatible one: "
+ VMHelper.getVMInstall(configuration)
.getInstallLocation());
}
}
if (!haveAUT) {
String errorMessage = "The "
+ configuration.getName()
+ " requires "
+ ((OSArchitecture.x86.equals(architecture)) ? "32 bit"
: "64 bit")
+ " Java VM which cannot be found.";
Q7ExtLaunchingPlugin.getDefault().log(errorMessage, null);
removeTargetPlatform(configuration);
throw new CoreException(new Status(IStatus.ERROR,
Q7ExtLaunchingPlugin.PLUGIN_ID, errorMessage, null));
}
monitor.done();
return true;
}
private void removeTargetPlatform(ILaunchConfiguration configuration)
throws CoreException {
String targetPlatformName = Q7TargetPlatformManager.getTargetPlatformName(configuration);
Q7TargetPlatformManager.delete(targetPlatformName);
LaunchInfoCache.remove(configuration);
TargetPlatformManager.deleteTargetPlatform(targetPlatformName);
}
private static boolean isHeadless(ILaunchConfiguration configuration)
throws CoreException {
return configuration
.getAttribute(IQ7Launch.ATTR_HEADLESS_LAUNCH, false);
}
private void waitForClearBundlePool(IProgressMonitor monitor) {
try {
Job.getJobManager().join(
IBundlePoolConstansts.CLEAN_BUNDLE_POOL_JOB,
new SubProgressMonitor(monitor, 1));
} catch (Exception e1) {
Q7ExtLaunchingPlugin.getDefault().log(
"Failed to wait for bundle pool clear job", e1);
}
}
private static boolean updateJVM(ILaunchConfiguration configuration,
OSArchitecture architecture, ITargetPlatformHelper target) throws CoreException {
IVMInstall jvmInstall = null;
OSArchitecture jvmArch = OSArchitecture.Unknown;
IVMInstallType[] types = JavaRuntime.getVMInstallTypes();
boolean haveArch = false;
for (IVMInstallType ivmInstallType : types) {
IVMInstall[] installs = ivmInstallType.getVMInstalls();
for (IVMInstall ivmInstall : installs) {
jvmArch = JDTUtils.detect(ivmInstall);
if (jvmArch.equals(architecture)
|| (jvmArch.equals(OSArchitecture.x86_64) && JDTUtils
.canRun32bit(ivmInstall))) {
jvmInstall = ivmInstall;
haveArch = true;
break;
}
}
}
if (haveArch) {
ILaunchConfigurationWorkingCopy workingCopy = configuration
.getWorkingCopy();
String vmArgs = workingCopy.getAttribute(
IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS,
Q7LaunchDelegateUtils.getJoinedVMArgs(target, null));
OSArchitecture configArch;
String archAttrValue = configuration.getAttribute(
Q7LaunchingCommon.ATTR_ARCH, "");
if (archAttrValue.isEmpty())
configArch = null;
else
configArch = OSArchitecture.valueOf(archAttrValue);
OSArchitecture autArch = configArch == null ? target
.detectArchitecture(true, null) : configArch;
// there is no -d32 on Windows
if (!autArch.equals(jvmArch)
&& Platform.getOS().equals(Platform.OS_MACOSX)) {
if (vmArgs != null && !vmArgs.contains(ATTR_D32)) {
vmArgs += " " + ATTR_D32;
} else {
vmArgs = ATTR_D32;
}
}
if (vmArgs != null && vmArgs.length() > 0) {
vmArgs = UpdateVMArgs.updateAttr(vmArgs);
workingCopy
.setAttribute(
IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS,
vmArgs);
}
workingCopy
.setAttribute(
IJavaLaunchConfigurationConstants.ATTR_JRE_CONTAINER_PATH,
String.format(
"org.eclipse.jdt.launching.JRE_CONTAINER/%s/%s",
jvmInstall.getVMInstallType().getId(),
jvmInstall.getName()));
String programArgs = workingCopy
.getAttribute(
IJavaLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS,
LaunchArgumentsHelper
.getInitialProgramArguments().trim());
if (programArgs.contains("${target.arch}")) {
programArgs = programArgs.replace("${target.arch}",
autArch.name());
} else {
if (programArgs.contains("-arch")) {
int pos = programArgs.indexOf("-arch ") + 6;
int len = 6;
int pos2 = programArgs.indexOf("x86_64", pos);
if (pos2 == -1) {
len = 3;
pos2 = programArgs.indexOf("x86", pos);
}
if (pos2 != -1) {
programArgs = programArgs.substring(0, pos)
+ autArch.name()
+ programArgs.substring(pos2 + len,
programArgs.length());
}
} else {
programArgs = programArgs + " -arch " + autArch.name();
}
}
if (programArgs.length() > 0) {
workingCopy
.setAttribute(
IJavaLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS,
programArgs);
}
workingCopy.doSave();
return true;
}
return false;
}
private static String getSubstitutedString(String text)
throws CoreException {
if (text == null)
return ""; //$NON-NLS-1$
IStringVariableManager mgr = VariablesPlugin.getDefault()
.getStringVariableManager();
return mgr.performStringSubstitution(text);
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private String[] constructClasspath(ILaunchConfiguration configuration)
throws CoreException {
CachedInfo info = LaunchInfoCache.getInfo(configuration);
ITargetPlatformHelper target = (ITargetPlatformHelper) info.target;
String jarPath = target
.getEquinoxStartupPath(IPDEBuildConstants.BUNDLE_EQUINOX_LAUNCHER);
if (jarPath == null)
return null;
ArrayList entries = new ArrayList();
entries.add(jarPath);
String bootstrap = configuration.getAttribute(
IPDELauncherConstants.BOOTSTRAP_ENTRIES, ""); //$NON-NLS-1$
StringTokenizer tok = new StringTokenizer(
getSubstitutedString(bootstrap), ","); //$NON-NLS-1$
while (tok.hasMoreTokens())
entries.add(tok.nextToken().trim());
return (String[]) entries.toArray(new String[entries.size()]);
}
@Override
public String[] getClasspath(ILaunchConfiguration configuration)
throws CoreException {
String[] classpath = constructClasspath(configuration);
if (classpath == null) {
String message = PDEMessages.WorkbenchLauncherConfigurationDelegate_noStartup;
throw new CoreException(LauncherUtils.createErrorStatus(message));
}
return classpath;
}
@Override
public String[] getProgramArguments(ILaunchConfiguration configuration)
throws CoreException {
CachedInfo info = LaunchInfoCache.getInfo(configuration);
final ITargetPlatformHelper target = (ITargetPlatformHelper) info.target;
if (info.programArgs != null) {
return info.programArgs;
}
ArrayList<String> programArgs = new ArrayList<String>();
programArgs.addAll(asList(super.getProgramArguments(configuration)));
try {
// Correct osgi.install.area property key
File config = new File(getConfigDir(configuration), "config.ini");
Properties props = new Properties();
BufferedInputStream in = new BufferedInputStream(
new FileInputStream(config));
props.load(in);
in.close();
File location = target.getQ7Target().getInstallLocation();
if (location != null) {
props.setProperty("osgi.install.area",
location.getAbsolutePath());
}
props.setProperty(
"osgi.bundles",
Q7LaunchDelegateUtils
.computeOSGiBundles(getBundlesToLaunch(info).latestVersionsOnly));
props.remove("osgi.framework");
// Append all other properties from original config file
OriginalOrderProperties properties = target.getConfigIniProperties();
properties.setBeginAdd(true);
properties.putAll(props);
BufferedOutputStream out = new BufferedOutputStream(
new FileOutputStream(config));
properties.store(out, "Configuration File");
out.close();
} catch (IOException e) {
throw new CoreException(Q7ExtLaunchingPlugin.status(e));
}
String override = configuration.getAttribute(
IQ7Launch.OVERRIDE_SECURE_STORAGE, (String) null);
if (override == null || "true".equals(override)) {
// Override existing parameter
programArgs.add("-eclipse.keyring");
programArgs.add(getConfigDir(configuration).toString()
+ IPath.SEPARATOR + SECURE_STORAGE_FILE_NAME);
}
IVMInstall install = VMHelper.getVMInstall(configuration);
programArgs.add("-vm");
programArgs.add(install.getInstallLocation().toString());
info.programArgs = programArgs.toArray(new String[programArgs.size()]);
Q7ExtLaunchingPlugin.getDefault().info(
Q7_LAUNCHING_AUT + configuration.getName()
+ ": AUT command line arguments is set to: "
+ Arrays.toString(info.programArgs));
return info.programArgs;
}
@Override
public String[] getVMArguments(ILaunchConfiguration config)
throws CoreException {
CachedInfo info = LaunchInfoCache.getInfo(config);
if (info.vmArgs != null) {
return info.vmArgs;
}
List<String> args = new ArrayList<String>(Arrays.asList(super.getVMArguments(config)));
// Filter some PDE parameters
Iterables.removeIf(args, new Predicate<String>() {
public boolean apply(String input) {
if (input.contains("-Declipse.pde.launch=true")) {
return true;
}
return false;
}
});
args.add("-Dq7id=" + launch.getAttribute(IQ7Launch.ATTR_AUT_ID));
args.add("-Dq7EclPort=" + AutEventManager.INSTANCE.getPort());
TargetPlatformHelper target = (TargetPlatformHelper) ((ITargetPlatformHelper) info.target);
IPluginModelBase hook = target.getWeavingHook();
if (hook == null) {
throw new CoreException(Q7ExtLaunchingPlugin.status("No "
+ AJConstants.HOOK + " plugin"));
}
// Append all other properties from original config file
OriginalOrderProperties properties = target.getConfigIniProperties();
args = UpdateVMArgs.addHook(args, hook, properties.getProperty(OSGI_FRAMEWORK_EXTENSIONS));
args.add("-Declipse.vmargs=" + Joiner.on("\n").join(args) + "\n");
info.vmArgs = args.toArray(new String[args.size()]);
Q7ExtLaunchingPlugin.getDefault().info(
Q7_LAUNCHING_AUT + config.getName()
+ ": AUT JVM arguments is set to : "
+ Arrays.toString(info.vmArgs));
return info.vmArgs;
}
@Override
protected void preLaunchCheck(final ILaunchConfiguration configuration,
ILaunch launch, IProgressMonitor monitor) throws CoreException {
SubMonitor subm = SubMonitor.convert(monitor, 100);
super.preLaunchCheck(configuration, launch, subm.newChild(50));
if (monitor.isCanceled()) {
return;
}
CachedInfo info = LaunchInfoCache.getInfo(configuration);
ITargetPlatformHelper target = (ITargetPlatformHelper) info.target;
BundlesToLaunch bundlesToLaunch = collectBundlesCheck(target.getQ7Target(), target.getTarget(), subm.newChild(50), configuration);
setBundlesToLaunch(info, bundlesToLaunch);
removeDuplicatedModels(bundlesToLaunch.fModels, target.getQ7Target());
setDelegateFields(this, bundlesToLaunch.fModels, bundlesToLaunch.fAllBundles);
// Copy all additional configuration area folders into PDE new
// configuration location.
copyConfiguratonFiles(configuration, info);
monitor.done();
}
public static void removeDuplicatedModels(Map<IPluginModelBase, String> fModels, Q7Target target) {
String path = target.getInstallLocation().getAbsolutePath();
List<IPluginModelBase> keysForRemove = new ArrayList<IPluginModelBase>();
Map<UniquePluginModel, IPluginModelBase> cache = new HashMap<UniquePluginModel, IPluginModelBase>();
for (Entry<IPluginModelBase, String> entry : fModels.entrySet()) {
IPluginModelBase model = entry.getKey();
UniquePluginModel uniqueModel = new UniquePluginModel(model);
IPluginModelBase secondModel = cache.get(uniqueModel);
if (secondModel != null) {
if (secondModel.getInstallLocation().contains(path)) {
keysForRemove.add(secondModel);
} else {
keysForRemove.add(model);
}
} else {
cache.put(uniqueModel, model);
}
}
for (IPluginModelBase key : keysForRemove) {
fModels.remove(key);
}
}
public static class BundlesToLaunchCollector {
private void addInstallationBundle(TargetBundle bundle,
BundleStart hint) {
for (IPluginModelBase base : getModels(bundle)) {
addInstallationBundle(base, hint);
}
}
public void addInstallationBundle(IPluginModelBase base,
BundleStart hint) {
String id = id(base);
idsToSkip.add(id);
put(base, getStartInfo(base, hint));
}
private void addPluginBundle(TargetBundle bundle) {
for (IPluginModelBase base : getModels(bundle)) {
String id = id(base);
if (idsToSkip.contains(id)) {
continue;
}
put(base, getStartInfo(base, BundleStart.DEFAULT));
}
}
public void addExtraBundle(TargetBundle bundle) {
for (IPluginModelBase base : getModels(bundle)) {
put(base, getStartInfo(base, BundleStart.DEFAULT));
}
}
public BundlesToLaunch getResult() {
return new BundlesToLaunch(rejectedBundles, plugins, latestVersions);
}
private void put(IPluginModelBase plugin, BundleStart start) {
/**
* Check for aspectj special plugins, they should be one version
* only.
**/
final String id = id(plugin);
if (id.equals(AJConstants.AJ_HOOK) || id.equals(AJConstants.AJ_RT)
|| id.equals(AJConstants.HOOK)) {
// remove previous bundles with specified id
Iterables.removeIf(plugins.entrySet(), isEqualsId(id));
latestVersions.remove(id);
}
plugins.put(plugin, start);
IPluginModelBase existing = latestVersions.get(id);
if (existing == null
|| isGreater(version(plugin), version(existing))) {
latestVersions.put(id, plugin);
}
}
private Predicate<Entry<IPluginModelBase, BundleStart>> isEqualsId(
final String id) {
return new Predicate<Map.Entry<IPluginModelBase, BundleStart>>() {
public boolean apply(Entry<IPluginModelBase, BundleStart> input) {
if (id.equals(id(input.getKey()))) {
return true;
}
return false;
}
};
}
private final Set<String> idsToSkip = new HashSet<String>();
private final Set<String> rejectedBundles = new LinkedHashSet<String>();
private final Map<IPluginModelBase, BundleStart> plugins = new HashMap<IPluginModelBase, BundleStart>();
private final Map<String, IPluginModelBase> latestVersions = new HashMap<String, IPluginModelBase>();
}
public static boolean isQ7BundleContainer(ITargetLocation container) {
if (!(container instanceof IUBundleContainer))
return false;
URI[] uris = ((IUBundleContainer) container).getRepositories();
for (URI uri : uris) {
if (!uri.getScheme().equals("platform")
|| !uri.getPath().startsWith("/plugin/org.eclipse.rcptt")) {
return false;
}
}
return true;
}
public static boolean isAutConfigSimpleconfiguratorSet(Q7Target target) {
return target.getInstall().configIniBundles().containsKey(TargetPlatformHelper.SIMPLECONFIGURATOR);
}
public static void setBundlesLevels(Q7Target target, Map<String, String> levelMap) {
final ProfileBundleContainer profileBundleContainer = target.getInstall().container;
if (profileBundleContainer != null) {
for (TargetBundle bundle : target.getInstall().getBundles()) {
String bundleLevels = levelMap.get(bundle.getBundleInfo().getSymbolicName());
if (bundleLevels != null) {
try {
String[] strings = bundleLevels.split(":");
int level = Integer.parseInt(strings[0]);
boolean started = Boolean.parseBoolean(strings[1]);
bundle.getBundleInfo().setStartLevel(level);
bundle.getBundleInfo().setMarkedAsStarted(started);
} catch (Exception e) {
// ignore parsing exception
}
}
}
} else {
log(status("Profile Bundle Container is EMPTY.")); //$NON-NLS-1$
}
}
public static BundlesToLaunch collectBundlesCheck(Q7Target target, ITargetDefinition targetDefinition, IProgressMonitor monitor,
ILaunchConfiguration configuration) {
if (target.getInstall() != null && isAutConfigSimpleconfiguratorSet(target)) {
final CachedInfo info = LaunchInfoCache.getInfo(configuration);
TargetPlatformHelper targetHelper = (TargetPlatformHelper) ((ITargetPlatformHelper) info.target);
Map<String, String> levelMap = targetHelper.getRunlevelsMap();
setBundlesLevels(target, levelMap);
}
return collectBundles(target, targetDefinition, monitor);
}
public static BundlesToLaunch collectBundles(Q7Target target, ITargetDefinition targetDefinition, IProgressMonitor monitor) {
BundlesToLaunchCollector collector = new BundlesToLaunchCollector();
SubMonitor subm = SubMonitor.convert(monitor, "Collecting bundles", 3000);
SubMonitor install = subm.newChild(1000);
if (target.getInstall() != null) {
Map<String, BundleStart> bundlesFromConfig = target.getInstall().configIniBundles();
TargetBundle[] installationBundles = target.getInstall().getBundles();
install.beginTask("Scanning " + target.getInstall().getInstallLocation(), installationBundles.length);
for (TargetBundle bundle : target.getInstall().getBundles()) {
BundleStart hint = MoreObjects.firstNonNull(bundlesFromConfig.get(bundle
.getBundleInfo().getSymbolicName()),
BundleStart.fromBundle(bundle.getBundleInfo()));
collector.addInstallationBundle(bundle, hint);
install.worked(1);
}
}
install.done();
final SubMonitor plugins = subm.newChild(1000);
TargetBundle[] bundles = targetDefinition.getAllBundles();
for (TargetBundle bundle : bundles) {
collector.addPluginBundle(bundle);
plugins.worked(1);
}
plugins.done();
return new BundlesToLaunch(collector.rejectedBundles,
collector.plugins, collector.latestVersions);
}
/**
* Represents result of collection of bundles to launch
*
* @author ivaninozemtsev
*
*/
public static class BundlesToLaunch {
public BundlesToLaunch(Set<String> rejectedBundles,
Map<IPluginModelBase, BundleStart> plugins,
final Map<String, IPluginModelBase> latestVersions) {
this.resolvedBundles = plugins;
this.latestVersionsOnly = Maps.filterKeys(resolvedBundles,
new Predicate<IPluginModelBase>() {
public boolean apply(IPluginModelBase input) {
// II: reference equality intentionally
return latestVersions.get(id(input)) == input;
}
});
fAllBundles = new HashMap<String, IPluginModelBase>(latestVersions);
fModels = new HashMap<IPluginModelBase, String>(Maps.transformValues(
resolvedBundles, new Function<BundleStart, String>() {
public String apply(BundleStart input) {
return input.toModelString();
}
}));
}
public final Map<IPluginModelBase, BundleStart> resolvedBundles;
public final Map<IPluginModelBase, BundleStart> latestVersionsOnly;
public final Map<IPluginModelBase, String> fModels;
public final Map<String, IPluginModelBase> fAllBundles;
}
private static final String KEY_BUNDLES_TO_LAUNCH = "bundlesToLaunch";
public static void setBundlesToLaunch(CachedInfo info,
BundlesToLaunch bundles) {
info.data.put(KEY_BUNDLES_TO_LAUNCH, bundles);
}
public static BundlesToLaunch getBundlesToLaunch(CachedInfo info) {
return (BundlesToLaunch) info.data.get(KEY_BUNDLES_TO_LAUNCH);
}
private static IPluginModelBase[] getModels(TargetBundle bundle) {
try {
return new PDEState(new URL[] { new URL(String.format("file://%s",
bundle.getBundleInfo().getLocation().getPath())) }, true, true,
new NullProgressMonitor()).getTargetModels();
} catch (MalformedURLException e) {
log(status("Problem in resolving AUT bundle " + bundle, e));
return new IPluginModelBase[0];
}
}
private static Version version(IPluginModelBase plugin) {
try {
return new Version(plugin.getPluginBase().getVersion());
} catch (IllegalArgumentException e) {
return Version.emptyVersion;
}
}
private void copyConfiguratonFiles(
final ILaunchConfiguration configuration, CachedInfo info) throws CoreException {
String targetPlatformPath = ((ITargetPlatformHelper) info.target).getUserArea();
if(targetPlatformPath == null)
targetPlatformPath = ((ITargetPlatformHelper) info.target)
.getTargetPlatformProfilePath();
File configFolder = new File(targetPlatformPath, "configuration"); //$NON-NLS-1$
if (!configFolder.exists())
return;
Set<String> filter = new HashSet<String>(Arrays.asList(new String(
".p2;" + //
"org.eclipse.core.runtime;" //
+ "org.eclipse.equinox.app;" //
+ "org.eclipse.equinox.simpleconfigurator;" //
+ "org.eclipse.equinox.source;" //
+ "org.eclipse.osgi;" //
+ "org.eclipse.ui.intro.universal;" //
+ "org.eclipse.update;" //
+ "config.ini;" //
+ ".settings;" //
+ "org.eclipse.help.base"//
).split(";")));
File target = getConfigDir(configuration);
File[] listFiles = configFolder.listFiles();
for (File file : listFiles) {
if (!filter.contains(file.getName())) {
if (file.isDirectory()) {
FileUtil.copyFiles(file, new File(target, file.getName()));
} else {
FileUtil.copyFiles(file, target);
}
}
}
}
public static class UniquePluginModel {
private String name;
private Version version;
public UniquePluginModel(IPluginModelBase model) {
version = model.getBundleDescription().getVersion();
name = model.getBundleDescription().getName();
}
@Override
public int hashCode() {
final int prime = 31;
int hashCode = 1;
hashCode = prime * hashCode + (name == null ? 0 : name.hashCode());
hashCode = prime * hashCode + (version == null ? 0 : version.hashCode());
return 0;
}
@Override
public boolean equals(Object object) {
if (object == null)
return false;
if (object == this)
return true;
if (!(object instanceof UniquePluginModel))
return false;
UniquePluginModel uniquePluginModel = (UniquePluginModel) object;
if (uniquePluginModel.name.equals(this.name)
&& uniquePluginModel.version.equals(this.version)) {
return true;
}
return false;
}
}
}