/******************************************************************************* | |
* Copyright (c) 2009 IBM Corporation 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: | |
* IBM Corporation - initial API and implementation | |
*******************************************************************************/ | |
package org.eclipse.pde.internal.core.target.provisional; | |
import java.io.File; | |
import java.net.MalformedURLException; | |
import java.net.URL; | |
import java.util.*; | |
import org.eclipse.core.resources.WorkspaceJob; | |
import org.eclipse.core.runtime.*; | |
import org.eclipse.core.runtime.jobs.Job; | |
import org.eclipse.core.variables.IStringVariableManager; | |
import org.eclipse.core.variables.VariablesPlugin; | |
import org.eclipse.equinox.internal.provisional.frameworkadmin.BundleInfo; | |
import org.eclipse.jdt.launching.IVMInstall; | |
import org.eclipse.jdt.launching.JavaRuntime; | |
import org.eclipse.pde.core.plugin.IPluginModelBase; | |
import org.eclipse.pde.core.plugin.TargetPlatform; | |
import org.eclipse.pde.internal.core.*; | |
import org.eclipse.pde.internal.core.target.impl.*; | |
/** | |
* Sets the current target platform based on a target definition. | |
* | |
* @since 3.5 | |
*/ | |
public class LoadTargetDefinitionJob extends WorkspaceJob { | |
/** | |
* Target definition being loaded | |
*/ | |
private ITargetDefinition fTarget; | |
/** | |
* Whether a target definition was specified | |
*/ | |
private boolean fNone = false; | |
/** | |
* Constructs a new operation to load the specified target definition | |
* as the current target platform. When <code>null</code> is specified | |
* the target platform is empty and all other settings are default. | |
* | |
* @param target target definition or <code>null</code> if none | |
*/ | |
public LoadTargetDefinitionJob(ITargetDefinition target) { | |
super(Messages.LoadTargetDefinitionJob_0); | |
fTarget = target; | |
if (target == null) { | |
fNone = true; | |
ITargetPlatformService service = (ITargetPlatformService) PDECore.getDefault().acquireService(ITargetPlatformService.class.getName()); | |
fTarget = service.newTarget(); | |
} | |
} | |
/* (non-Javadoc) | |
* @see org.eclipse.core.resources.WorkspaceJob#runInWorkspace(org.eclipse.core.runtime.IProgressMonitor) | |
*/ | |
public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException { | |
try { | |
Preferences preferences = PDECore.getDefault().getPluginPreferences(); | |
monitor.beginTask(Messages.LoadTargetOperation_mainTaskName, 100); | |
loadEnvironment(preferences, new SubProgressMonitor(monitor, 5)); | |
loadArgs(preferences, new SubProgressMonitor(monitor, 5)); | |
loadJRE(preferences, new SubProgressMonitor(monitor, 15)); | |
loadImplicitPlugins(preferences, new SubProgressMonitor(monitor, 15)); | |
loadPlugins(preferences, new SubProgressMonitor(monitor, 60)); | |
loadAdditionalPreferences(preferences); | |
PDECore.getDefault().savePluginPreferences(); | |
} finally { | |
monitor.done(); | |
} | |
return Status.OK_STATUS; | |
} | |
/** | |
* Configures program and VM argument preferences based on the target | |
* definition. | |
* | |
* @param pref preference store | |
* @param monitor progress monitor | |
*/ | |
private void loadArgs(Preferences pref, IProgressMonitor monitor) { | |
monitor.beginTask(Messages.LoadTargetOperation_argsTaskName, 2); | |
String args = fTarget.getProgramArguments(); | |
pref.setValue(ICoreConstants.PROGRAM_ARGS, (args != null) ? args : ""); //$NON-NLS-1$ | |
monitor.worked(1); | |
args = fTarget.getVMArguments(); | |
pref.setValue(ICoreConstants.VM_ARGS, (args != null) ? args : ""); //$NON-NLS-1$ | |
monitor.done(); | |
} | |
/** | |
* Configures the environment preferences from the target definition. | |
* | |
* @param pref preference store | |
* @param monitor progress monitor | |
*/ | |
private void loadEnvironment(Preferences pref, IProgressMonitor monitor) { | |
monitor.beginTask(Messages.LoadTargetOperation_envTaskName, 1); | |
setEnvironmentPref(pref, ICoreConstants.ARCH, fTarget.getArch()); | |
setEnvironmentPref(pref, ICoreConstants.NL, fTarget.getNL()); | |
setEnvironmentPref(pref, ICoreConstants.OS, fTarget.getOS()); | |
setEnvironmentPref(pref, ICoreConstants.WS, fTarget.getWS()); | |
monitor.done(); | |
} | |
/** | |
* Sets the given preference to default when <code>null</code> or the | |
* specified value. | |
* | |
* @param pref preference store | |
* @param key preference key | |
* @param value preference value or <code>null</code> | |
*/ | |
private void setEnvironmentPref(Preferences pref, String key, String value) { | |
if (value == null) { | |
pref.setToDefault(key); | |
} else { | |
pref.setValue(key, value); | |
} | |
} | |
/** | |
* Sets the workspace default JRE based on the target's JRE container. | |
* | |
* @param pref | |
* @param monitor | |
*/ | |
private void loadJRE(Preferences pref, IProgressMonitor monitor) { | |
IPath container = fTarget.getJREContainer(); | |
monitor.beginTask(Messages.LoadTargetOperation_jreTaskName, 1); | |
if (container != null) { | |
IVMInstall jre = JavaRuntime.getVMInstall(container); | |
if (jre != null) { | |
IVMInstall def = JavaRuntime.getDefaultVMInstall(); | |
if (!jre.equals(def)) { | |
try { | |
JavaRuntime.setDefaultVMInstall(jre, null); | |
} catch (CoreException e) { | |
} | |
} | |
} | |
} | |
monitor.done(); | |
} | |
/** | |
* Sets implicit dependencies, if any | |
* | |
* @param pref preference store | |
* @param monitor progress monitor | |
*/ | |
private void loadImplicitPlugins(Preferences pref, IProgressMonitor monitor) { | |
BundleInfo[] infos = fTarget.getImplicitDependencies(); | |
if (infos != null) { | |
monitor.beginTask(Messages.LoadTargetOperation_implicitPluginsTaskName, infos.length + 1); | |
StringBuffer buffer = new StringBuffer(); | |
for (int i = 0; i < infos.length; i++) { | |
buffer.append(infos[i].getSymbolicName()).append(','); | |
monitor.worked(1); | |
} | |
if (infos.length > 0) | |
buffer.setLength(buffer.length() - 1); | |
pref.setValue(ICoreConstants.IMPLICIT_DEPENDENCIES, buffer.toString()); | |
} | |
monitor.done(); | |
} | |
/** | |
* Resolves the bundles in the target platform and sets them in the corresponding | |
* CHECKED_PLUGINS preference. Sets home and addition location preferences as well. | |
* | |
* @param pref | |
* @param monitor | |
* @throws CoreException | |
*/ | |
private void loadPlugins(Preferences pref, IProgressMonitor monitor) throws CoreException { | |
monitor.beginTask(Messages.LoadTargetOperation_loadPluginsTaskName, 100); | |
String currentPath = pref.getString(ICoreConstants.PLATFORM_PATH); | |
IBundleContainer[] containers = fTarget.getBundleContainers(); | |
// the first container is assumed to be the primary/home location | |
String path = null; | |
if (containers != null && containers.length > 0) { | |
path = ((AbstractBundleContainer) containers[0]).getLocation(true); | |
} | |
if (path == null) { | |
path = TargetPlatform.getDefaultLocation(); | |
} else { | |
try { | |
IStringVariableManager manager = VariablesPlugin.getDefault().getStringVariableManager(); | |
path = manager.performStringSubstitution(path); | |
} catch (CoreException e) { | |
return; | |
} | |
} | |
monitor.worked(10); | |
List additional = getAdditionalLocs(); | |
handleReload(path, additional, pref, new SubProgressMonitor(monitor, 85)); | |
// update preferences (Note: some preferences updated in handleReload()) | |
pref.setValue(ICoreConstants.PLATFORM_PATH, path); | |
String mode = new Path(path).equals(new Path(TargetPlatform.getDefaultLocation())) ? ICoreConstants.VALUE_USE_THIS : ICoreConstants.VALUE_USE_OTHER; | |
pref.setValue(ICoreConstants.TARGET_MODE, mode); | |
ListIterator li = additional.listIterator(); | |
StringBuffer buffer = new StringBuffer(); | |
while (li.hasNext()) | |
buffer.append(li.next()).append(","); //$NON-NLS-1$ | |
if (buffer.length() > 0) | |
buffer.setLength(buffer.length() - 1); | |
pref.setValue(ICoreConstants.ADDITIONAL_LOCATIONS, buffer.toString()); | |
String newValue = currentPath; | |
for (int i = 0; i < 4; i++) { | |
String value = pref.getString(ICoreConstants.SAVED_PLATFORM + i); | |
pref.setValue(ICoreConstants.SAVED_PLATFORM + i, newValue); | |
if (!value.equals(currentPath)) | |
newValue = value; | |
else | |
break; | |
} | |
monitor.done(); | |
} | |
/** | |
* Sets the TARGET_PROFILE preference which stores the ID of the target profile used | |
* (if based on an target extension) or the workspace location of the file that | |
* was used. For now we just clear it. | |
* <p> | |
* Sets the WORKSPACE_TARGET_HANDLE. | |
* </p> | |
* @param pref | |
*/ | |
private void loadAdditionalPreferences(Preferences pref) throws CoreException { | |
pref.setValue(ICoreConstants.TARGET_PROFILE, ""); //$NON-NLS-1$ | |
String memento = fTarget.getHandle().getMemento(); | |
if (fNone) { | |
memento = ""; //$NON-NLS-1$ | |
} | |
pref.setValue(ICoreConstants.WORKSPACE_TARGET_HANDLE, memento); | |
IBundleContainer[] containers = fTarget.getBundleContainers(); | |
boolean profile = false; | |
if (containers != null && containers.length > 0) { | |
profile = containers[0] instanceof ProfileBundleContainer; | |
} | |
pref.setValue(ICoreConstants.TARGET_PLATFORM_REALIZATION, profile); | |
} | |
/** | |
* Returns a list of additional locations of bundles. | |
* | |
* @return additional bundle locations | |
*/ | |
private List getAdditionalLocs() throws CoreException { | |
ArrayList additional = new ArrayList(); | |
// secondary containers are considered additional | |
IBundleContainer[] containers = fTarget.getBundleContainers(); | |
if (containers != null && containers.length > 1) { | |
for (int i = 1; i < containers.length; i++) { | |
additional.add(((AbstractBundleContainer) containers[i]).getLocation(true)); | |
} | |
} | |
return additional; | |
} | |
private void handleReload(String targetLocation, List additionalLocations, Preferences pref, IProgressMonitor monitor) throws CoreException { | |
SubMonitor subMon = SubMonitor.convert(monitor, Messages.LoadTargetOperation_reloadTaskName, 100); | |
try { | |
Set included = new HashSet(); | |
List infos = new ArrayList(); | |
if (!fTarget.isResolved()) { | |
fTarget.resolve(subMon.newChild(20)); | |
} else { | |
subMon.worked(20); | |
} | |
if (subMon.isCanceled()) { | |
// TODO Support cancellation? | |
} | |
IStatus status = fTarget.getBundleStatus(); | |
if (status == null) { | |
throw new CoreException(new Status(IStatus.ERROR, PDECore.PLUGIN_ID, Messages.LoadTargetDefinitionJob_1)); | |
} | |
if (!status.isOK()) { | |
// TODO Support prompting for differing levels of errors/warnings/info | |
throw new CoreException(status); | |
} | |
IResolvedBundle[] resolved = fTarget.getBundles(); | |
for (int i = 0; i < resolved.length; i++) { | |
infos.add(resolved[i].getBundleInfo()); | |
included.add(resolved[i].getBundleInfo()); | |
} | |
// Compute missing bundles (preference need to know disabled/missing bundles) | |
List missing = new ArrayList(); | |
IBundleContainer[] containers = fTarget.getBundleContainers(); | |
if (containers != null) { | |
for (int i = 0; i < containers.length; i++) { | |
IBundleContainer container = containers[i]; | |
BundleInfo[] restrictions = container.getIncludedBundles(); | |
if (restrictions != null) { | |
try { | |
container.setIncludedBundles(null); | |
IResolvedBundle[] all = container.getBundles(); | |
for (int j = 0; j < all.length; j++) { | |
IResolvedBundle bi = all[j]; | |
if (!included.contains(bi.getBundleInfo())) { | |
missing.add(bi.getBundleInfo()); | |
} | |
} | |
} finally { | |
container.setIncludedBundles(restrictions); | |
} | |
} | |
} | |
} | |
List paths = new ArrayList(infos.size() + missing.size()); | |
Iterator iterator = infos.iterator(); | |
while (iterator.hasNext()) { | |
BundleInfo info = (BundleInfo) iterator.next(); | |
try { | |
paths.add(new File(info.getLocation()).toURL()); | |
} catch (MalformedURLException e) { | |
throw new CoreException(new Status(IStatus.ERROR, PDECore.PLUGIN_ID, Messages.LoadTargetDefinitionJob_1, e)); | |
} | |
} | |
// generate URLs and save CHECKED_PLUGINS (which are missing), and add to master list of paths | |
StringBuffer checked = new StringBuffer(); | |
int i = 0; | |
iterator = missing.iterator(); | |
Set missingIds = new HashSet(missing.size()); | |
while (iterator.hasNext()) { | |
BundleInfo bi = (BundleInfo) iterator.next(); | |
missingIds.add(bi.getSymbolicName()); | |
try { | |
paths.add(new File(bi.getLocation()).toURL()); | |
} catch (MalformedURLException e) { | |
throw new CoreException(new Status(IStatus.ERROR, PDECore.PLUGIN_ID, Messages.LoadTargetDefinitionJob_1, e)); | |
} | |
if (i > 0) { | |
checked.append(" "); //$NON-NLS-1$ | |
} | |
checked.append(bi.getSymbolicName()); | |
i++; | |
} | |
URL[] urls = (URL[]) paths.toArray(new URL[paths.size()]); | |
PDEState state = new PDEState(urls, true, new SubProgressMonitor(monitor, 45)); | |
IPluginModelBase[] models = state.getTargetModels(); | |
for (i = 0; i < models.length; i++) { | |
models[i].setEnabled(!missingIds.contains(models[i].getPluginBase().getId())); | |
} | |
// save CHECKED_PLUGINS | |
if (urls.length == 0) { | |
pref.setValue(ICoreConstants.CHECKED_PLUGINS, ICoreConstants.VALUE_SAVED_NONE); | |
} else if (missing.size() == 0) { | |
pref.setValue(ICoreConstants.CHECKED_PLUGINS, ICoreConstants.VALUE_SAVED_ALL); | |
} else { | |
pref.setValue(ICoreConstants.CHECKED_PLUGINS, checked.toString()); | |
} | |
Job job = new TargetPlatformResetJob(state); | |
job.schedule(); | |
try { | |
job.join(); | |
} catch (InterruptedException e) { | |
// TODO Auto-generated catch block | |
} | |
} finally { | |
if (monitor != null) { | |
monitor.done(); | |
} | |
subMon.done(); | |
} | |
} | |
} |