/*******************************************************************************
 * Copyright (c) 2010, 2018 EclipseSource 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:
 *     EclipseSource Inc. - initial API and implementation
 *     IBM Corporation - ongoing enhancements
 *     Manumitting Technologies Inc - Bug 437726
 *     Lars Vogel <Lars.Vogel@vogella.com> - Bug 477527
 *******************************************************************************/
package org.eclipse.pde.internal.core.target;

import java.io.File;
import java.net.URI;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.preferences.IPreferencesService;
import org.eclipse.equinox.internal.p2.director.PermissiveSlicer;
import org.eclipse.equinox.internal.p2.engine.*;
import org.eclipse.equinox.internal.p2.engine.phases.*;
import org.eclipse.equinox.internal.p2.garbagecollector.GarbageCollector;
import org.eclipse.equinox.p2.core.*;
import org.eclipse.equinox.p2.engine.*;
import org.eclipse.equinox.p2.engine.query.IUProfilePropertyQuery;
import org.eclipse.equinox.p2.engine.spi.ProvisioningAction;
import org.eclipse.equinox.p2.metadata.*;
import org.eclipse.equinox.p2.metadata.MetadataFactory.InstallableUnitDescription;
import org.eclipse.equinox.p2.metadata.Version;
import org.eclipse.equinox.p2.planner.IPlanner;
import org.eclipse.equinox.p2.planner.IProfileChangeRequest;
import org.eclipse.equinox.p2.query.*;
import org.eclipse.equinox.p2.repository.*;
import org.eclipse.equinox.p2.repository.artifact.*;
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository;
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager;
import org.eclipse.pde.core.target.*;
import org.eclipse.pde.internal.core.PDECore;
import org.osgi.framework.*;

public class P2TargetUtils {

	private static final String SOURCE_IU_ID = "org.eclipse.pde.core.target.source.bundles"; //$NON-NLS-1$

	/**
	 * URI to the local directory where the p2 agent keeps its information.
	 */
	public static URI AGENT_LOCATION;
	static {
		try {
			AGENT_LOCATION = URIUtil.fromString("file:" + PDECore.getDefault().getStateLocation().append(".p2")); //$NON-NLS-1$//$NON-NLS-2$
		} catch (Exception e) {
			// should never happen
		}
	}

	/**
	 * Path to the local directory where the local bundle pool is stored for p2 profile
	 * based targets.
	 */
	public static final IPath BUNDLE_POOL = PDECore.getDefault().getStateLocation().append(".bundle_pool"); //$NON-NLS-1$

	/**
	 * Path to the local directory where install folders are created for p2 profile
	 * based targets.
	 */
	static final IPath INSTALL_FOLDERS = PDECore.getDefault().getStateLocation().append(".install_folders"); //$NON-NLS-1$

	/**
	 * Prefix for all profiles ID's associated with target definitions
	 */
	static final String PROFILE_ID_PREFIX = "TARGET_DEFINITION:"; //$NON-NLS-1$

	/**
	 * Installable unit property to mark IU's that have been installed in a profile by
	 * a bundle container (rather than as a secondary/required IU).
	 */
	static final String PROP_INSTALLED_IU = PDECore.PLUGIN_ID + ".installed_iu"; //$NON-NLS-1$

	/**
	 * Profile property that keeps track of provisioning mode for the target
	 * (slice versus plan).
	 */
	static final String PROP_PROVISION_MODE = PDECore.PLUGIN_ID + ".provision_mode"; //$NON-NLS-1$

	/**
	 * Profile property that keeps track of provisioning mode for the target
	 * (all environments/true versus false).
	 */
	static final String PROP_ALL_ENVIRONMENTS = PDECore.PLUGIN_ID + ".all_environments"; //$NON-NLS-1$

	/**
	 * Profile property that keeps track of the target sequence number
	 */
	static final String PROP_SEQUENCE_NUMBER = PDECore.PLUGIN_ID + ".sequence"; //$NON-NLS-1$

	/**
	 * Profile property that tracks whether or not source to be auto-included
	 */
	static final String PROP_AUTO_INCLUDE_SOURCE = PDECore.PLUGIN_ID + ".autoIncludeSource"; //$NON-NLS-1$

	/**
	 * Profile property that tracks whether or not the configuration phase should be executed when installing
	 */
	static final String PROP_INCLUDE_CONFIGURE_PHASE = PDECore.PLUGIN_ID + ".includeConfigure"; //$NON-NLS-1$

	/**
	 * Table mapping {@link ITargetDefinition} to synchronizer (P2TargetUtils) instance.
	 */
	private static Map<ITargetDefinition, P2TargetUtils> synchronizers = new HashMap<>();

	/**
	 * Table mapping of  ITargetDefinition and IFileArtifactRepository
	 */
	public static Map<ITargetDefinition, IFileArtifactRepository> fgTargetArtifactRepo = new ConcurrentHashMap<>();

	/**
	 * Table mapping IArtifactKey to table map of IFileArtifactRepository and IFileArtifactRepository
	 */
	public static Map<IArtifactKey, Map<IFileArtifactRepository, File>> fgArtifactKeyRepoFile = new ConcurrentHashMap<>();

	/**
	 * The profile to be synchronized
	 */
	private IProfile fProfile;

	/**
	 * Whether this container must have all required IUs of the selected IUs available and included
	 * in the target to resolve successfully.  If this option is true, the planner will be used to resolve
	 * otherwise the slicer is used.  The planner can describe any missing requirements as errors.
	 * <p>
	 * <code>true</code> by default
	 * </p>
	 */
	private boolean fIncludeAllRequired = true;

	/**
	 * Whether this container should download and include environment (platform) specific units for all
	 * available platforms (vs only the current target definition's environment settings).  Only supported
	 * by the slicer so {@link IUBundleContainer#INCLUDE_REQUIRED} must be turned off for this setting to be used.
	 * <p>
	 * <code>false</code> by default
	 * </p>
	 */
	private boolean fIncludeMultipleEnvironments = false;

	/**
	 * Whether this container should download and include source bundles for the selected units if the associated
	 * source is available in the repository.
	 * <p>
	 * <code>false</code> by default
	 * </p>
	 */
	private boolean fIncludeSource = false;

	/**
	 * Whether this container should execute the configure phase when installing the IUs
	 * <p>
	 * <code>false</code> by default
	 * </p>
	 */
	private boolean fIncludeConfigurePhase = false;

	/**
	 * Deletes any profiles associated with target definitions that no longer exist
	 * and returns a list of profile identifiers that were deleted.
	 */
	public static List<String> cleanOrphanedTargetDefinitionProfiles() throws CoreException {
		List<String> list = new ArrayList<>();
		IProfileRegistry registry = getProfileRegistry();
		ITargetPlatformService tps = PDECore.getDefault().acquireService(ITargetPlatformService.class);
		if (registry != null && tps != null) {
			IProfile[] profiles = registry.getProfiles();
			for (IProfile profile : profiles) {
				String id = profile.getProfileId();
				if (id.startsWith(PROFILE_ID_PREFIX)) {
					String memento = id.substring(PROFILE_ID_PREFIX.length());
					ITargetHandle handle = tps.getTarget(memento);
					if (!handle.exists()) {
						deleteProfile(handle);
						list.add(id);
					}
				}
			}
		}
		return list;
	}

	/**
	 * Recursively deletes folder and files.
	 *
	 * @param folder
	 */
	private static void delete(File folder) {
		File[] files = folder.listFiles();
		for (File file : files) {
			if (file.isDirectory()) {
				delete(file);
			}
			file.delete();
		}
		folder.delete();
	}

	/**
	 * Deletes the profile associated with this target handle, if any. Returns
	 * <code>true</code> if a profile existed and was deleted, otherwise <code>false</code>.
	 *
	 * @throws CoreException if unable to delete the profile
	 */
	public static void deleteProfile(ITargetHandle handle) throws CoreException {
		IProfileRegistry registry = getProfileRegistry();
		if (registry != null) {
			IProfile profile = registry.getProfile(getProfileId(handle));
			if (profile != null) {
				String location = profile.getProperty(IProfile.PROP_INSTALL_FOLDER);
				registry.removeProfile(getProfileId(handle));
				if (location != null && location.length() > 0) {
					File folder = new File(location);
					if (folder.exists()) {
						delete(folder);
					}
				}
			}
		}
	}

	@SuppressWarnings("restriction")
	public static void forceCheckTarget(final ITargetDefinition target) {
		final P2TargetUtils result = getSynchronizer(target);
		if (result != null && result.fProfile != null && result.fProfile instanceof Profile) {
			((Profile) result.fProfile).setProperty(PROP_SEQUENCE_NUMBER, "-1"); //$NON-NLS-1$
		}
	}

	/**
	 * Performs garbage collection based on remaining profiles. Should be called to avoid
	 * having PDE's bundle pool area grow unbounded.
	 */
	public static void garbageCollect() {
		try {
			IProfile[] profiles = getProfileRegistry().getProfiles();
			for (IProfile profile : profiles) {
				if (profile.getProfileId().startsWith(PROFILE_ID_PREFIX)) {
					getGarbageCollector().runGC(profile);
				}
			}
		} catch (CoreException e) {
			// XXX likely should log something here.
			return;
		}
	}

	/**
	 * Generates the environment properties string for this target definition's p2 profile.
	 *
	 * @return environment properties
	 */
	private String generateEnvironmentProperties(ITargetDefinition target) {
		// TODO: are there constants for these keys?
		StringBuilder env = new StringBuilder();
		String ws = target.getWS();
		if (ws == null) {
			ws = Platform.getWS();
		}
		env.append("osgi.ws="); //$NON-NLS-1$
		env.append(ws);
		env.append(","); //$NON-NLS-1$
		String os = target.getOS();
		if (os == null) {
			os = Platform.getOS();
		}
		env.append("osgi.os="); //$NON-NLS-1$
		env.append(os);
		env.append(","); //$NON-NLS-1$
		String arch = target.getArch();
		if (arch == null) {
			arch = Platform.getOSArch();
		}
		env.append("osgi.arch="); //$NON-NLS-1$
		env.append(arch);
		return env.toString();
	}

	/**
	 * Generates the NL property for this target definition's p2 profile.
	 *
	 * @return NL profile property
	 */
	private String generateNLProperty(ITargetDefinition target) {
		String nl = target.getNL();
		if (nl == null) {
			nl = Platform.getNL();
		}
		return nl;
	}

	public static IProvisioningAgent getAgent() throws CoreException {
		//Is there already an agent for this location?
		String filter = "(locationURI=" + String.valueOf(AGENT_LOCATION) + ")"; //$NON-NLS-1$//$NON-NLS-2$
		ServiceReference<?>[] serviceReferences = null;
		BundleContext context = PDECore.getDefault().getBundleContext();
		try {
			serviceReferences = context.getServiceReferences(IProvisioningAgent.SERVICE_NAME, filter);
			if (serviceReferences != null) {
				return (IProvisioningAgent) context.getService(serviceReferences[0]);
			}
		} catch (InvalidSyntaxException e) {
			// ignore
		} finally {
			if (serviceReferences != null)
				context.ungetService(serviceReferences[0]);
		}

		IProvisioningAgentProvider provider = PDECore.getDefault().acquireService(IProvisioningAgentProvider.class);
		try {
			if (provider == null) {
				throw new CoreException(new Status(IStatus.ERROR, PDECore.PLUGIN_ID, Messages.IUBundleContainer_7));
			}
			IProvisioningAgent agent = provider.createAgent(AGENT_LOCATION);
			if (agent == null) {
				throw new CoreException(new Status(IStatus.ERROR, PDECore.PLUGIN_ID, Messages.IUBundleContainer_7));
			}
			// turn off the garbage collector for the PDE agent.  GC is managed on a coarser grain
			GarbageCollector garbageCollector = (GarbageCollector) agent.getService(GarbageCollector.class.getName());
			if (garbageCollector != null) {
				garbageCollector.stop();
			}
			return agent;
		} catch (ProvisionException e) {
			throw new CoreException(new Status(IStatus.ERROR, PDECore.PLUGIN_ID, Messages.IUBundleContainer_7, e));
		}
	}

	/**
	 * Returns the global p2 provisioning agent.  This is useful when looking to inherit or use
	 * some settings from the global p2 world.
	 *
	 * @return the global p2 provisioning agent
	 * @throws CoreException
	 */
	public static IProvisioningAgent getGlobalAgent() throws CoreException {
		IProvisioningAgent agent = PDECore.getDefault().acquireService(IProvisioningAgent.class);
		if (agent == null)
			throw new CoreException(new Status(IStatus.ERROR, PDECore.PLUGIN_ID, Messages.IUBundleContainer_11));
		return agent;
	}

	/**
	 * Returns the provisioning agent location service.
	 *
	 * @return provisioning agent location service
	 * @throws CoreException if none
	 */
	public static IAgentLocation getAgentLocation() throws CoreException {
		IAgentLocation result = (IAgentLocation) getAgent().getService(IAgentLocation.SERVICE_NAME);
		if (result == null)
			throw new CoreException(new Status(IStatus.ERROR, PDECore.PLUGIN_ID, Messages.IUBundleContainer_10));
		return result;
	}

	/**
	 * Returns the provisioning engine service.
	 *
	 * @return provisioning engine
	 * @throws CoreException if none
	 */
	public static IArtifactRepositoryManager getArtifactRepositoryManager() throws CoreException {
		IArtifactRepositoryManager manager = (IArtifactRepositoryManager) getAgent().getService(IArtifactRepositoryManager.class.getName());
		if (manager == null) {
			throw new CoreException(new Status(IStatus.ERROR, PDECore.PLUGIN_ID, Messages.IUBundleContainer_3));
		}
		return manager;
	}

	/**
	 * Returns the local bundle pool (repository) where bundles are stored
	 *
	 * @return local file artifact repository
	 * @throws CoreException
	 */
	public static IFileArtifactRepository getBundlePool() throws CoreException {
		URI uri = BUNDLE_POOL.toFile().toURI();
		IArtifactRepositoryManager manager = getArtifactRepositoryManager();
		try {
			if (manager.contains(uri))
				return (IFileArtifactRepository) manager.loadRepository(uri, null);
		} catch (CoreException e) {
			// could not load or there wasn't one, fall through to create
		}
		String repoName = "PDE Target Bundle Pool"; //$NON-NLS-1$
		IArtifactRepository result = manager.createRepository(uri, repoName, IArtifactRepositoryManager.TYPE_SIMPLE_REPOSITORY, null);
		return (IFileArtifactRepository) result;
	}

	/**
	 * Returns the provisioning engine service.
	 *
	 * @return provisioning engine
	 * @throws CoreException if none
	 */
	public static IEngine getEngine() throws CoreException {
		IEngine engine = (IEngine) getAgent().getService(IEngine.class.getName());
		if (engine == null) {
			throw new CoreException(new Status(IStatus.ERROR, PDECore.PLUGIN_ID, Messages.IUBundleContainer_4));
		}
		return engine;
	}

	/**
	 * Returns the p2 garbage collector
	 *
	 * @return p2 garbage collector
	 * @throws CoreException if none
	 */
	public static GarbageCollector getGarbageCollector() throws CoreException {
		GarbageCollector engine = (GarbageCollector) getAgent().getService(GarbageCollector.class.getName());
		if (engine == null) {
			throw new CoreException(new Status(IStatus.ERROR, PDECore.PLUGIN_ID, Messages.IUBundleContainer_9));
		}
		return engine;
	}

	/**
	 * Returns the provisioning planner.
	 *
	 * @return provisioning planner
	 * @throws CoreException if none
	 */
	public static IPlanner getPlanner() throws CoreException {
		IPlanner planner = (IPlanner) getAgent().getService(IPlanner.class.getName());
		if (planner == null) {
			throw new CoreException(new Status(IStatus.ERROR, PDECore.PLUGIN_ID, Messages.IUBundleContainer_5));
		}
		return planner;
	}

	/**
	 * Returns the preferences service.
	 *
	 * @return preferences service or null if none
	 */
	public static IPreferencesService getPreferences() {
		return PDECore.getDefault().acquireService(IPreferencesService.class);
	}

	/**
	 * Returns whether the contents of the profile matches the expected contents of the target definition
	 *
	 * @return whether or not the profile and target definitions match
	 * @throws CoreException in unable to retrieve profile
	 */
	private boolean checkProfile(ITargetDefinition target) throws CoreException {
		// make sure we have a profile to validate
		if (fProfile == null) {
			return false;
		}

		// check that the target and profiles are in sync. If they are then life is good.
		// If they are not equal, there is still a chance that everything is ok.
		String profileNumber = fProfile.getProperty(PROP_SEQUENCE_NUMBER);
		if (Integer.toString(((TargetDefinition) target).getSequenceNumber()).equals(profileNumber)) {
			return true;
		}

		// check if all environments setting is the same
		boolean all = false;
		String value = fProfile.getProperty(PROP_ALL_ENVIRONMENTS);
		if (value != null) {
			all = Boolean.valueOf(value).booleanValue();
			if (!Boolean.toString(getIncludeAllEnvironments()).equals(value)) {
				return false;
			}
		}

		// ensure environment & NL settings are still the same (else we need a new profile)
		String property = null;
		if (!all) {
			property = generateEnvironmentProperties(target);
			value = fProfile.getProperty(IProfile.PROP_ENVIRONMENTS);
			if (!property.equals(value)) {
				return false;
			}
		}
		property = generateNLProperty(target);
		value = fProfile.getProperty(IProfile.PROP_NL);
		if (!property.equals(value)) {
			return false;
		}

		// check provisioning mode: slice versus plan
		if (!getProvisionMode(target).equals(fProfile.getProperty(PROP_PROVISION_MODE))) {
			return false;
		}

		// check that the include source flag matches what the profile represents
		if (getIncludeSource() != Boolean.valueOf(fProfile.getProperty(PROP_AUTO_INCLUDE_SOURCE)).booleanValue()) {
			return false;
		}

		if (getIncludeConfigurePhase() != Boolean.valueOf(fProfile.getProperty(PROP_INCLUDE_CONFIGURE_PHASE)).booleanValue()) {
			return false;
		}

		// check top level IU's. If any have been removed from the containers that are
		// still in the profile, we need to recreate (rather than uninstall)
		IUProfilePropertyQuery propertyQuery = new IUProfilePropertyQuery(PROP_INSTALLED_IU, Boolean.toString(true));
		IQueryResult<?> queryResult = fProfile.query(propertyQuery, null);
		Iterator<?> iterator = queryResult.iterator();
		Set<NameVersionDescriptor> installedIUs = new HashSet<>();
		while (iterator.hasNext()) {
			IInstallableUnit unit = (IInstallableUnit) iterator.next();
			installedIUs.add(new NameVersionDescriptor(unit.getId(), unit.getVersion().toString()));
		}
		ITargetLocation[] containers = target.getTargetLocations();
		if (containers == null) {
			return installedIUs.isEmpty();
		}
		for (ITargetLocation container : containers) {
			if (container instanceof IUBundleContainer) {
				IUBundleContainer bc = (IUBundleContainer) container;
				String[] ids = bc.getIds();
				Version[] versions = bc.getVersions();
				for (int j = 0; j < versions.length; j++) {
					// if there is something in a container but not in the profile, recreate
					if (!installedIUs.remove(new NameVersionDescriptor(ids[j], versions[j].toString()))) {
						return false;
					}
				}
			}
		}
		if (!installedIUs.isEmpty()) {
			return false;
		}

		// Phew! seems like the profile checks out.
		return true;
	}

	/**
	 * Sets whether all required units must be available to resolve this container.  When <code>true</code>
	 * the resolve operation will use the planner to determine the complete set of IUs required to
	 * make the selected IUs runnable.  If any dependencies are missing, the resolve operation will return an
	 * error explaining what problems exist.  When <code>false</code> the resolve operation will use the slicer
	 * to determine what units to include.  Any required units that are not available in the repositories will
	 * be ignored.
	 * <p>
	 * Since there is only one profile per target and the planner and slicer resolve methods are incompatible.
	 * </p>
	 * @param value whether all required units must be available to resolve this container
	 */
	public void setIncludeAllRequired(boolean value) {
		fIncludeAllRequired = value;
	}

	/**
	 * Returns whether all required units must be available to resolve this container.  When <code>true</code>
	 * the resolve operation will use the planner to determine the complete set of IUs required to
	 * make the selected IUs runnable.  If any dependencies are missing, the resolve operation will return an
	 * error explaining what problems exist.  When <code>false</code> the resolve operation will use the slicer
	 * to determine what units to include.  Any required units that are not available in the repositories will
	 * be ignored.
	 *
	 * @return whether all required units must be available to resolve this container
	 */
	public boolean getIncludeAllRequired() {
		return fIncludeAllRequired;
	}

	/**
	 * Sets whether all environment (platform) specific installable units should
	 * be included in this container when it is resolved.  This feature is not supported
	 * by the planner so will only have an effect if the include all required setting
	 * is turned off ({@link #getIncludeAllRequired()}).
	 * <p>
	 * There is only one profile per target and this setting can only be set for the
	 * entire target definition.
	 * </p>
	 * @param value whether environment specific units should be included
	 */
	public void setIncludeAllEnvironments(boolean value) {
		fIncludeMultipleEnvironments = value;
	}

	/**
	 * Returns whether all environment (platform) specific installable units should
	 * be included in this container when it is resolved.  This feature is not supported
	 * by the planner so will only have an effect if the include all required setting
	 * is turned off ({@link #getIncludeAllRequired()}).
	 *
	 * @return whether environment specific units should be included
	 */
	public boolean getIncludeAllEnvironments() {
		return fIncludeMultipleEnvironments;
	}

	/**
	 * Set whether or not the source bundles corresponding to any binary bundles should
	 * be automatically included in the target.
	 *
	 * @param value whether or not to include source
	 */
	public void setIncludeSource(boolean value) {
		fIncludeSource = value;
	}

	/**
	 * Returns whether or not source bundles corresponding to selected binary bundles
	 * are automatically included in the target.
	 *
	 * @return whether or not source is included automatically
	 */
	public boolean getIncludeSource() {
		return fIncludeSource;
	}

	/**
	 * Set whether or not the configuration phase should be executed when installing the IUs
	 *
	 * @param value whether or not to execute configuration phase
	 */
	public void setIncludeConfigurePhase(boolean value) {
		fIncludeConfigurePhase = value;
	}

	/**
	 * Returns whether or not the configuration phase should be executed when installing the IUs
	 *
	 * @return whether or not to execute configuration phase
	 */
	public boolean getIncludeConfigurePhase() {
		return fIncludeConfigurePhase;
	}

	/**
	 * Return whether or not the given target has a matching profile that is in sync
	 * @param target the target to check
	 * @return whether or not the target has been resolved at the p2 level
	 */
	public static boolean isResolved(ITargetDefinition target) {
		P2TargetUtils synchronizer = getSynchronizer(target);
		if (synchronizer == null)
			return false;
		try {
			return synchronizer.checkProfile(target);
		} catch (CoreException e) {
			return false;
		}
	}

	/**
	 * Return whether or not the given target's matching profile  is in sync
	 * @param target the target to check
	 * @return whether or not the target has been resolved at the p2 level
	 */
	public static boolean isProfileValid(ITargetDefinition target) {
		P2TargetUtils synchronizer = getSynchronizer(target);
		if (synchronizer == null)
			return false;
		try {
			synchronizer.updateProfileFromRegistry(target);
			return synchronizer.checkProfile(target);
		} catch (CoreException e) {
			return false;
		}
	}


	private void updateProfileFromRegistry(ITargetDefinition target) {
		if (fProfile == null) {
			try {
				fProfile = getProfileRegistry().getProfile(getProfileId(target));
			} catch (CoreException e) {
			}
		}
	}

	/**
	 * Get the synchronizer to use for the given target.  If there is already one on a
	 * container in the target, use that one.  Otherwise, create a new one.  Either way,
	 * ensure that all other IU containers in the target are using the same synchronizer.
	 * <p>
	 * The synchronizer is an instance of {@link P2TargetUtils} that has access to the
	 * profile and other p2 bits for the target.
	 * </p>
	 *
	 * @param target the target for which we are getting the synchronizer
	 * @return the discovered or created synchronizer
	 */
	static synchronized P2TargetUtils getSynchronizer(ITargetDefinition target) {
		P2TargetUtils result = synchronizers.get(target);
		if (result != null)
			return result;

		result = new P2TargetUtils();
		synchronizers.put(target, result);
		return result;
	}

	/**
	 * Return the set of IUs in all IU containers associated with this synchronizer.
	 * This is a helper method so we don't have to expose the profile itself.
	 *
	 * @param target the target definition to query
	 * @param monitor the progress monitor to use
	 * @return the set of associated IUs
	 * @throws CoreException if there is a problem discovering the IUs
	 */
	public static IQueryResult<?> getIUs(ITargetDefinition target, IProgressMonitor monitor) throws CoreException {
		P2TargetUtils synchronizer = getSynchronizer(target);
		if (synchronizer == null)
			return null;
		synchronizer.synchronize(target, monitor);
		return synchronizer.getProfile().query(QueryUtil.createIUAnyQuery(), null);
	}

	/**
	 * Synchronize the profile and the target definition managed by this synchronizer.  On return the profile will
	 * be resolved and correctly match the given target.  The IUBundleContainers associated with
	 * the target will be notified of any changes in the underlying p2 profile and given an
	 * opportunity to update themselves accordingly.
	 *
	 * NOTE: this is a potentially *very* heavyweight operation.
	 *
	 * NOTE: this method is synchronized as it is effectively a "test and set" caching method. Two
	 * threads getting the profile at the same time should not execute concurrently or the profiles
	 * will get out of sync.
	 *
	 * @throws CoreException if there was a problem synchronizing
	 */
	public synchronized void synchronize(ITargetDefinition target, IProgressMonitor monitor) throws CoreException {
		SubMonitor progress = SubMonitor.convert(monitor, 100);

		// Happiness if we have a profile and it checks out or if we can load one and it checks out.
		if (fProfile == null)
			fProfile = getProfileRegistry().getProfile(getProfileId(target));
		if (fProfile != null && checkProfile(target)) {
			// always push the changes to the target because there can be many target objects
			// for the same synchronizer (doh!)
			notify(target, progress.split(25));
			return;
		}

		// Either no profile was found or it was stale.  Delete the current profile and recreate.
		// This keeps the internal agent data clean and does not cost us much.
		deleteProfile(target.getHandle());
		createProfile(target);

		if (progress.isCanceled())
			return;
		progress.setWorkRemaining(75);

		try {
			// Now resolve the profile and refresh the relate IU containers
			if (getIncludeAllRequired())
				resolveWithPlanner(target, progress.split(60));
			else
				resolveWithSlicer(target, progress.split(60));

			// If we are updating a profile then delete the old snapshot on success.
			notify(target, progress.split(15));
		} catch (CoreException e) {
			// There was at least one problem getting the contents, delete the profile so we don't cache in a bad state, Bug 439034
			// TODO ALL we really want to delete is the sequence property, so that checkProfile will compare settings and contents
			deleteProfile(target.getHandle());
			throw e;
		}
	}

	private void createProfile(ITargetDefinition target) throws CoreException, ProvisionException {
		// create a new profile
		IProfileRegistry registry = getProfileRegistry();
		if (registry == null) {
			throw new CoreException(new Status(IStatus.ERROR, PDECore.PLUGIN_ID, Messages.AbstractTargetHandle_0));
		}
		Map<String, String> properties = new HashMap<>();
		properties.put(IProfile.PROP_INSTALL_FOLDER, INSTALL_FOLDERS.append(Long.toString(LocalTargetHandle.nextTimeStamp())).toOSString());
		properties.put(IProfile.PROP_CACHE, BUNDLE_POOL.toOSString());
		properties.put(IProfile.PROP_INSTALL_FEATURES, Boolean.TRUE.toString());
		properties.put(IProfile.PROP_ENVIRONMENTS, generateEnvironmentProperties(target));
		properties.put(IProfile.PROP_NL, generateNLProperty(target));
		properties.put(PROP_SEQUENCE_NUMBER, Integer.toString(((TargetDefinition) target).getSequenceNumber()));
		properties.put(PROP_PROVISION_MODE, getProvisionMode(target));
		properties.put(PROP_ALL_ENVIRONMENTS, Boolean.toString(getIncludeAllEnvironments()));
		properties.put(PROP_AUTO_INCLUDE_SOURCE, Boolean.toString(getIncludeSource()));
		properties.put(PROP_INCLUDE_CONFIGURE_PHASE, Boolean.toString(getIncludeConfigurePhase()));
		fProfile = registry.addProfile(getProfileId(target), properties);
	}

	/**
	 * Signal the relevant bundle containers that the given profile has changed.
	 */
	private void notify(ITargetDefinition target, IProgressMonitor monitor) {
		// flush the target caches first since some of them are used in rebuilding
		// the container caches (e.g., featureModels)
		((TargetDefinition) target).flushCaches(P2TargetUtils.BUNDLE_POOL.toOSString());
		// Now proactively recompute all the related container caches.
		ITargetLocation[] containers = target.getTargetLocations();
		if (containers != null) {
			for (ITargetLocation container : containers) {
				if (container instanceof IUBundleContainer) {
					((IUBundleContainer) container).synchronizerChanged(target);
				}
			}
		}
	}

	/**
	 * Returns the profile identifier for this target handle. There is one profile
	 * per target definition.
	 *
	 * @return profile identifier
	 * @throws CoreException in unable to generate identifier
	 */
	private static String getProfileId(ITargetHandle handle) throws CoreException {
		StringBuilder buffer = new StringBuilder();
		buffer.append(PROFILE_ID_PREFIX);
		// Memento strings can be very long and exceed max filename lengths, trim down to 200 + prefix + hashcode
		String memento = handle.getMemento();
		if (memento.length() > 200) {
			buffer.append(memento.substring(memento.length() - 200));
			buffer.append(memento.hashCode());
		} else {
			buffer.append(memento);
		}
		return buffer.toString();
	}

	/**
	 * Returns the profile identifier for this target handle. There is one profile
	 * per target definition.
	 *
	 * @return definition the target to lookup
	 */
	public static String getProfileId(ITargetDefinition definition) {
		try {
			return getProfileId(definition.getHandle());
		} catch (CoreException e) {
			// gotta make sure that this never happens.  all we're doing here is computing a string.
			return null;
		}
	}

	/**
	 * Returns the profile registry or <code>null</code>
	 *
	 * @return profile registry or <code>null</code>
	 * @throws CoreException
	 */
	public static IProfileRegistry getProfileRegistry() throws CoreException {
		IProfileRegistry result = (IProfileRegistry) getAgent().getService(IProfileRegistry.SERVICE_NAME);
		if (result == null) {
			throw new CoreException(new Status(IStatus.ERROR, PDECore.PLUGIN_ID, Messages.IUBundleContainer_8));
		}
		return result;
	}

	/**
	 * Returns the mode used to provision this target - slice versus plan or <code>null</code> if
	 * this target has no software sites.
	 *
	 * @return provisioning mode or <code>null</code>
	 */
	private String getProvisionMode(ITargetDefinition target) {
		return getIncludeAllRequired() ? TargetDefinitionPersistenceHelper.MODE_PLANNER : TargetDefinitionPersistenceHelper.MODE_SLICER;
	}

	/**
	 * Returns the metadata repository manager.
	 *
	 * @return metadata repository manager
	 * @throws CoreException if none
	 */
	public static IMetadataRepositoryManager getRepoManager() throws CoreException {
		IMetadataRepositoryManager manager = (IMetadataRepositoryManager) getAgent().getService(IMetadataRepositoryManager.SERVICE_NAME);
		if (manager == null) {
			throw new CoreException(new Status(IStatus.ERROR, PDECore.PLUGIN_ID, Messages.IUBundleContainer_2));
		}
		return manager;
	}

	/**
	 * Return a queryable on the metadata defined in the given repo locations
	 *
	 * @param repos the repos to lookup
	 * @param monitor the progress monitor
	 * @return the set of metadata repositories found
	 * @throws CoreException if there is a problem getting the repositories
	 */
	static IQueryable<IInstallableUnit> getQueryableMetadata(URI[] repos, IProgressMonitor monitor) throws CoreException {
		IMetadataRepositoryManager manager = getRepoManager();
		if (repos == null) {
			repos = manager.getKnownRepositories(IRepositoryManager.REPOSITORIES_ALL);
		}

		int repoCount = repos.length;
		SubMonitor subMonitor = SubMonitor.convert(monitor, repoCount);


		List<IMetadataRepository> result = new ArrayList<>(repoCount);
		MultiStatus repoStatus = new MultiStatus(PDECore.PLUGIN_ID, 0, Messages.IUBundleContainer_ProblemsLoadingRepositories, null);
		for (int i = 0; i < repoCount; ++i) {
			try {
				result.add(manager.loadRepository(repos[i], subMonitor.split(1)));
			} catch (ProvisionException e) {
				repoStatus.add(e.getStatus());
			}
		}

		if (result.size() != repos.length) {
			throw new CoreException(repoStatus);
		}
		if (result.size() == 1) {
			return result.get(0);
		}
		return QueryUtil.compoundQueryable(result);
	}

	/**
	 * Used to resolve the contents of this container if the user is including all required software.  The p2 planner is used
	 * to determine the complete set of IUs required to run the selected software.  If all requirements are met, the bundles
	 * are downloaded from the repository into the bundle pool and added to the target definition.
	 *
	 * @param monitor for reporting progress
	 * @throws CoreException if there is a problem with the requirements or there is a problem downloading
	 */
	private void resolveWithPlanner(ITargetDefinition target, IProgressMonitor monitor) throws CoreException {
		SubMonitor subMonitor = SubMonitor.convert(monitor, Messages.IUBundleContainer_0, 220);

		// Get the root IUs for every relevant container in the target definition
		IInstallableUnit[] units = getRootIUs(target, subMonitor.split(20));

		// create the provisioning plan
		IPlanner planner = getPlanner();
		IProfileChangeRequest request = planner.createChangeRequest(fProfile);
		// first remove everything that was explicitly installed.  Then add it back.  This has the net effect of
		// removing everything that is no longer needed.
		computeRemovals(fProfile, request, getIncludeSource());
		request.addAll(Arrays.asList(units));
		for (IInstallableUnit unit : units) {
			request.setInstallableUnitProfileProperty(unit, PROP_INSTALLED_IU, Boolean.toString(true));
		}

		ProvisioningContext context = new ProvisioningContext(getAgent());
		context.setMetadataRepositories(getMetadataRepositories(target));
		context.setArtifactRepositories(getArtifactRepositories(target));

		IProvisioningPlan plan = planner.getProvisioningPlan(request, context, subMonitor.split(20));
		IStatus status = plan.getStatus();
		if (!status.isOK()) {
			throw new CoreException(status);
		}
		setPlanProperties(plan, target, TargetDefinitionPersistenceHelper.MODE_PLANNER);
		IProvisioningPlan installerPlan = plan.getInstallerPlan();
		if (installerPlan != null) {
			// this plan requires an update to the installer first, log the fact and attempt
			// to continue, we don't want to update the running SDK while provisioning a target
			PDECore.log(new Status(IStatus.INFO, PDECore.PLUGIN_ID, Messages.IUBundleContainer_6));
		}
		subMonitor.split(10);

		// execute the provisioning plan
		IPhaseSet phases = createPhaseSet();
		IEngine engine = getEngine();
		IStatus result = engine.perform(plan, phases, subMonitor.split(100));
		if (result.getSeverity() == IStatus.ERROR || result.getSeverity() == IStatus.CANCEL) {
			throw new CoreException(result);
		}

		// Now that we have a plan with all the binary and explicit bundles, do a second pass and add
		// in all the source.
		try {
			planInSourceBundles(fProfile, context, subMonitor.split(60));
		} catch (CoreException e) {
			// XXX Review required: is adding in the source critical or optional?
			// We failed adding in the source so remove the intermediate profile and rethrow
			getProfileRegistry().removeProfile(fProfile.getProfileId(), fProfile.getTimestamp());
			throw e;
		}
	}

	private void setPlanProperties(IProvisioningPlan plan, ITargetDefinition definition, String mode) {
		plan.setProfileProperty(PROP_PROVISION_MODE, mode);
		plan.setProfileProperty(PROP_ALL_ENVIRONMENTS, Boolean.toString(getIncludeAllEnvironments()));
		plan.setProfileProperty(PROP_AUTO_INCLUDE_SOURCE, Boolean.toString(getIncludeSource()));
		plan.setProfileProperty(PROP_INCLUDE_CONFIGURE_PHASE, Boolean.toString(getIncludeConfigurePhase()));
		plan.setProfileProperty(PROP_SEQUENCE_NUMBER, Integer.toString(((TargetDefinition) definition).getSequenceNumber()));
	}

	/**
	 * @return the phase set to execute, includes the configuration phase if {@link #getIncludeConfigurePhase()} is <code>true<code>
	 */
	private IPhaseSet createPhaseSet() {
		ArrayList<Phase> phases = new ArrayList<>(4);
		phases.add(new Collect(100));
		phases.add(new Property(1));
		phases.add(new Uninstall(50, true));
		phases.add(new Install(50));
		phases.add(new CollectNativesPhase(100));
		if (getIncludeConfigurePhase()) {
			phases.add(new Configure(100));
		}

		return new PhaseSet(phases.toArray(new Phase[phases.size()]));
	}

	/**
	 * Update the given change request to remove anything that was explicitly installed
	 * including the internal source IU.
	 */
	private void computeRemovals(IProfile profile, IProfileChangeRequest request, boolean includeSource) {
		// if include source is off then ensure that the source IU is removed.
		if (!includeSource) {
			IInstallableUnit sourceIU = getCurrentSourceIU(profile);
			if (sourceIU != null)
				request.remove(sourceIU);
		}
		// remove everything that is marked as roots.  The plan will have the new roots added in anyway.
		IQuery<IInstallableUnit> query = new IUProfilePropertyQuery(PROP_INSTALLED_IU, Boolean.toString(true));
		IQueryResult<IInstallableUnit> installedIUs = profile.query(query, null);
		request.removeAll(installedIUs.toSet());
	}

	// run a second pass of the planner to add in the source bundles for everything that's
	// in the current profile.
	private void planInSourceBundles(IProfile fProfile, ProvisioningContext context, IProgressMonitor monitor) throws CoreException {
		SubMonitor subMonitor = SubMonitor.convert(monitor, Messages.P2TargetUtils_ProvisioningSourceTask, 100);

		// create an IU that optionally and greedily requires the related source bundles.
		// Completely replace any source IU that may already be in place
		IInstallableUnit currentSourceIU = getCurrentSourceIU(fProfile);

		// determine the new version number.  start at 1
		Version sourceVersion = Version.createOSGi(1, 0, 0);
		if (currentSourceIU != null) {
			Integer major = (Integer) currentSourceIU.getVersion().getSegment(0);
			sourceVersion = Version.createOSGi(major.intValue() + 1, 0, 0);
		}
		IInstallableUnit sourceIU = createSourceIU(fProfile, sourceVersion);

		// call the planner again to add in the new source IU and all available source bundles
		IPlanner planner = getPlanner();
		IProfileChangeRequest request = planner.createChangeRequest(fProfile);
		if (currentSourceIU != null)
			request.remove(currentSourceIU);
		request.add(sourceIU);
		IProvisioningPlan plan = planner.getProvisioningPlan(request, context, subMonitor.split(25));
		IStatus status = plan.getStatus();
		if (!status.isOK()) {
			throw new CoreException(status);
		}
		if (subMonitor.isCanceled()) {
			return;
		}

		// execute the provisioning plan
		long oldTimestamp = fProfile.getTimestamp();
		IPhaseSet phases = PhaseSetFactory.createDefaultPhaseSetExcluding(new String[] {PhaseSetFactory.PHASE_CHECK_TRUST, PhaseSetFactory.PHASE_CONFIGURE, PhaseSetFactory.PHASE_UNCONFIGURE, PhaseSetFactory.PHASE_UNINSTALL});
		IEngine engine = getEngine();
		plan.setProfileProperty(PROP_PROVISION_MODE, TargetDefinitionPersistenceHelper.MODE_PLANNER);
		plan.setProfileProperty(PROP_ALL_ENVIRONMENTS, Boolean.toString(false));
		IStatus result = engine.perform(plan, phases, subMonitor.split(75));

		if (subMonitor.isCanceled()) {
			return;
		}
		if (!result.isOK()) {
			throw new CoreException(result);
		}

		// remove the old (intermediate) profile version now we have a new one with source.
		getProfileRegistry().removeProfile(fProfile.getProfileId(), oldTimestamp);
	}

	// Create and return an IU that has optional and greedy requirements on all source bundles
	// related to bundle IUs in the given queryable.
	private IInstallableUnit createSourceIU(IQueryable<IInstallableUnit> queryable, Version iuVersion) {
		// compute the set of source bundles we could possibly need for the bundles in the profile
		IRequirement bundleRequirement = MetadataFactory.createRequirement("org.eclipse.equinox.p2.eclipse.type", "bundle", null, null, false, false, false); //$NON-NLS-1$ //$NON-NLS-2$
		IQueryResult<IInstallableUnit> profileIUs = queryable.query(QueryUtil.createIUAnyQuery(), null);
		ArrayList<IRequirement> requirements = new ArrayList<>();
		for (IInstallableUnit profileIU : profileIUs) {
			if (profileIU.satisfies(bundleRequirement)) {
				String id = profileIU.getId() + ".source"; //$NON-NLS-1$
				Version version = profileIU.getVersion();
				// use fully qualified name to avoid conflict with other VersionRange class
				org.eclipse.equinox.p2.metadata.VersionRange range = new org.eclipse.equinox.p2.metadata.VersionRange(version, true, version, true);
				IRequirement sourceRequirement = MetadataFactory.createRequirement("osgi.bundle", id, range, null, true, false, true); //$NON-NLS-1$
				requirements.add(sourceRequirement);
			}
		}

		InstallableUnitDescription sourceDescription = new MetadataFactory.InstallableUnitDescription();
		sourceDescription.setSingleton(true);
		sourceDescription.setId(SOURCE_IU_ID);
		sourceDescription.setVersion(iuVersion);
		sourceDescription.addRequirements(requirements);
		IProvidedCapability capability = MetadataFactory.createProvidedCapability(IInstallableUnit.NAMESPACE_IU_ID, SOURCE_IU_ID, iuVersion);
		sourceDescription.setCapabilities(new IProvidedCapability[] {capability});
		return MetadataFactory.createInstallableUnit(sourceDescription);
	}

	// Lookup and return (if any) the source IU in the given queryable.
	private IInstallableUnit getCurrentSourceIU(IQueryable<IInstallableUnit> queryable) {
		IQuery<IInstallableUnit> query = QueryUtil.createIUQuery(SOURCE_IU_ID);
		IQueryResult<IInstallableUnit> list = queryable.query(query, null);
		IInstallableUnit currentSourceIU = null;
		if (!list.isEmpty())
			currentSourceIU = list.iterator().next();
		return currentSourceIU;
	}

	/**
	 * Used to resolve the contents of this container when the user has chosen to manage the dependencies in the target
	 * themselves.  The selected IUs and any required software that can be found will be retrieved from the repositories
	 * and added to the target.  Any missing required software will be ignored.
	 *
	 * @param monitor for reporting progress
	 * @throws CoreException if there is a problem interacting with the repositories
	 */
	private void resolveWithSlicer(ITargetDefinition target, IProgressMonitor monitor) throws CoreException {
		SubMonitor subMonitor = SubMonitor.convert(monitor, Messages.IUBundleContainer_0, 110);

		// resolve IUs
		IInstallableUnit[] units = getRootIUs(target, subMonitor.split(40));

		URI[] repositories = getMetadataRepositories(target);
		int repoCount = repositories.length;
		if (repoCount == 0) {
			return;
		}
		IQueryable<IInstallableUnit> allMetadata = getQueryableMetadata(repositories, subMonitor.split(5));

		// do an initial slice to add everything the user requested
		IQueryResult<IInstallableUnit> queryResult = slice(units, allMetadata, target, subMonitor.split(5));
		if (queryResult == null || queryResult.isEmpty()) {
			return;
		}

		// If we are including source then create a source IU to bring in the relevant source
		// bundles and run the slicer again.
		if (getIncludeSource()) {
			// Build an IU that represents all the source bundles and slice again to add them in if available
			IInstallableUnit sourceIU = createSourceIU(queryResult, Version.createOSGi(1, 0, 0));
			IInstallableUnit[] units2 = new IInstallableUnit[units.length + 1];
			System.arraycopy(units, 0, units2, 0, units.length);
			units2[units.length] = sourceIU;

			queryResult = slice(units2, allMetadata, target, subMonitor.split(5));
			if (queryResult == null || queryResult.isEmpty()) {
				return;
			}
		}

		IEngine engine = getEngine();
		ProvisioningContext context = new ProvisioningContext(getAgent());
		context.setMetadataRepositories(repositories);
		context.setArtifactRepositories(getArtifactRepositories(target));
		IProvisioningPlan plan = engine.createPlan(fProfile, context);
		setPlanProperties(plan, target, TargetDefinitionPersistenceHelper.MODE_SLICER);

		Set<IInstallableUnit> newSet = queryResult.toSet();
		Iterator<IInstallableUnit> itor = newSet.iterator();
		while (itor.hasNext()) {
			plan.addInstallableUnit(itor.next());
		}
		for (IInstallableUnit unit : units) {
			plan.setInstallableUnitProfileProperty(unit, PROP_INSTALLED_IU, Boolean.toString(true));
		}

		// remove all units that are in the current profile but not in the new slice
		Set<?> toRemove = fProfile.query(QueryUtil.ALL_UNITS, null).toSet();
		toRemove.removeAll(newSet);
		for (Object name : toRemove) {
			plan.removeInstallableUnit((IInstallableUnit) name);
		}

		subMonitor.split(5);

		// execute the provisioning plan
		IPhaseSet phases = createPhaseSet();
		IStatus result = engine.perform(plan, phases, subMonitor.split(50));
		if (result.getSeverity() == IStatus.ERROR || result.getSeverity() == IStatus.CANCEL) {
			throw new CoreException(result);
		}
	}

	/**
	 * Sets up a slice operation to download the set of installable units that are both required
	 * by the provided root IUs and available in the repositories specified in the metadata.
	 *
	 * @param units The set of root IUs to search for dependencies of in the repositories
	 * @param allMetadata metadata describing the repositories where the slicer can search
	 * @param definition the target definition this operation is being executed for
	 * @param monitor progress monitor, done will not be called
	 * @return the result of the slice operation
	 * @throws CoreException if a problem occurs during the slice operation that should stop this location from resolving
	 */
	private IQueryResult<IInstallableUnit> slice(IInstallableUnit[] units, IQueryable<IInstallableUnit> allMetadata, ITargetDefinition definition, IProgressMonitor monitor) throws CoreException {
		SubMonitor subMonitor = SubMonitor.convert(monitor, 100);
		// slice IUs and all prerequisites
		PermissiveSlicer slicer = null;
		if (getIncludeAllEnvironments()) {
			slicer = new PermissiveSlicer(allMetadata, new HashMap<String, String>(), true, false, true, true, false);
		} else {
			Map<String, String> props = new HashMap<>();
			props.put("osgi.os", definition.getOS() != null ? definition.getOS() : Platform.getOS()); //$NON-NLS-1$
			props.put("osgi.ws", definition.getWS() != null ? definition.getWS() : Platform.getWS()); //$NON-NLS-1$
			props.put("osgi.arch", definition.getArch() != null ? definition.getArch() : Platform.getOSArch()); //$NON-NLS-1$
			props.put("osgi.nl", definition.getNL() != null ? definition.getNL() : Platform.getNL()); //$NON-NLS-1$
			props.put(IProfile.PROP_INSTALL_FEATURES, Boolean.TRUE.toString());
			slicer = new PermissiveSlicer(allMetadata, props, true, false, false, true, false);
		}
		IQueryable<IInstallableUnit> slice = slicer.slice(units, subMonitor.split(50));
		IStatus sliceStatus = slicer.getStatus();
		// If the slicer encounters an error, stop the operation
		if (sliceStatus.getSeverity() == IStatus.ERROR) {
			throw new CoreException(sliceStatus);
		}

		// Collect the IUs from the sliced
		IQueryResult<IInstallableUnit> queryResult = null;
		if (slice != null)
			queryResult = slice.query(QueryUtil.createIUAnyQuery(), subMonitor.split(50));

		// If the slicer encounters a non-error status, only report it if the slice returned no IU results
		// It would be better to inform the user, but we do not want to stop the location from resolving (bug 350772)
		if (!sliceStatus.isOK()) {
			if (queryResult != null && !queryResult.iterator().hasNext()) {
				throw new CoreException(sliceStatus);
			}
		}

		return queryResult;
	}

	/**
	 * Returns the artifact repositories to consider when getting artifacts.  Returns a default set of
	 * repositories if current repository settings are <code>null</code>).
	 *
	 * @return URI's of repositories to use when getting artifacts
	 * @exception CoreException
	 */
	private URI[] getArtifactRepositories(ITargetDefinition target) throws CoreException {
		Set<URI> result = new HashSet<>();
		ITargetLocation[] containers = target.getTargetLocations();
		if (containers == null) {
			containers = new ITargetLocation[0];
		}
		IArtifactRepositoryManager manager = getArtifactRepositoryManager();
		for (ITargetLocation container : containers) {
			if (container instanceof IUBundleContainer) {
				URI[] repos = ((IUBundleContainer) container).getRepositories();
				if (repos == null) {
					repos = manager.getKnownRepositories(IRepositoryManager.REPOSITORIES_ALL);
				}
				result.addAll(Arrays.asList(repos));
			}
		}
		if (useAdditionalLocalArtifacts()) {
			// get all the artifact repos we know in the manager currently
			result.addAll(Arrays.asList(manager.getKnownRepositories(IRepositoryManager.REPOSITORIES_ALL)));

			// Add in the IDE profile bundle pool and all known workspaces
			findProfileRepos(result);
			findWorkspaceRepos(result);
		}
		return result.toArray(new URI[result.size()]);
	}

	/**
	 * return whether or not to use local artifact repositories when provisioning the target
	 */
	private boolean useAdditionalLocalArtifacts() {
		// XXX consider using a preference here or another strategy if users are able to spec
		// what local repos are to be considered.
		return true;
	}

	/**
	 * Add the artifact repos from the PDE target bundle pools from all known repos.  For example, the list
	 * of "recent workspaces" maintained by the IDE is a good source.
	 *
	 * @param additionalRepos the set to which additional repos are added.
	 */
	private void findWorkspaceRepos(Set<URI> additionalRepos) {
		IPreferencesService prefs = getPreferences();
		if (prefs == null)
			return;
		String recent = prefs.getString("org.eclipse.ui.ide", "RECENT_WORKSPACES", null, null); //$NON-NLS-1$ //$NON-NLS-2$
		if (recent == null)
			return;
		String[] recents = recent.split("\n"); //$NON-NLS-1$
		for (String recentWorkspace : recents) {
			File bundlePool = new File(recentWorkspace + "/.metadata/.plugins/org.eclipse.pde.core/.bundle_pool"); //$NON-NLS-1$
			if (bundlePool.exists()) {
				additionalRepos.add(bundlePool.toURI().normalize());
			}
		}
	}

	/**
	 * Look through the current p2 profile (_SELF_) and add the artifact repos that make up its
	 * bundle pool, dropins location, ...  This helps in the cases that you are targeting stuff that
	 * makes up your current IDE.
	 *
	 * @param additionalRepos the set to which additional repos are added.
	 */
	private void findProfileRepos(Set<URI> additionalRepos) {
		try {
			// NOTE: be sure to use the global p2 agent here as we are looking for SELF.
			IProfileRegistry profileRegistry = (IProfileRegistry) getGlobalAgent().getService(IProfileRegistry.SERVICE_NAME);
			if (profileRegistry == null)
				return;
			IProfile self = profileRegistry.getProfile(IProfileRegistry.SELF);
			if (self == null)
				return;

			IAgentLocation location = (IAgentLocation) getGlobalAgent().getService(IAgentLocation.SERVICE_NAME);
			URI dataArea = location.getDataArea("org.eclipse.equinox.p2.engine"); //$NON-NLS-1$
			dataArea = URIUtil.append(dataArea, "profileRegistry/" + self.getProfileId() + ".profile"); //$NON-NLS-1$//$NON-NLS-2$
			ProfileMetadataRepository profileRepo = new ProfileMetadataRepository(getGlobalAgent(), dataArea, null);
			Collection<?> repos = profileRepo.getReferences();
			for (Object element : repos) {
				if (element instanceof IRepositoryReference) {
					IRepositoryReference reference = (IRepositoryReference) element;
					if (reference.getType() == IRepository.TYPE_ARTIFACT && reference.getLocation() != null)
						additionalRepos.add(reference.getLocation());
				}
			}
		} catch (CoreException e) {
			// if there is a problem, move on.  Could log something here
			return;
		}
	}

	/**
	 * Returns the IU's for the given target related to the given containers
	 *
	 * @param definition the definition to filter with
	 * @param monitor
	 * @return the discovered IUs
	 * @exception CoreException if unable to retrieve IU's
	 */
	private IInstallableUnit[] getRootIUs(ITargetDefinition definition, IProgressMonitor monitor) throws CoreException {

		HashSet<IInstallableUnit> result = new HashSet<>();
		ITargetLocation[] containers = definition.getTargetLocations();
		if (containers == null) {
			return new IInstallableUnit[0];
		}
		SubMonitor subMonitor = SubMonitor.convert(monitor, Messages.IUBundleContainer_0, containers.length * 10);
		MultiStatus status = new MultiStatus(PDECore.PLUGIN_ID, 0, Messages.IUBundleContainer_ProblemsLoadingRepositories, null);
		for (ITargetLocation container : containers) {
			if (container instanceof IUBundleContainer) {
				try {
					IUBundleContainer iuContainer = (IUBundleContainer) container;
					Collections.addAll(result, iuContainer.getRootIUs(definition, subMonitor.split(10)));
				} catch (CoreException e) {
					status.add(e.getStatus());
				}
			}
		}
		if (!status.isOK()) {
			throw new CoreException(status);
		}
		return result.toArray(new IInstallableUnit[result.size()]);
	}

	/**
	 * Returns the repositories to consider when resolving IU's (will return default set of
	 * repositories if current repository settings are <code>null</code>).
	 *
	 * @return URI's of repositories to use when resolving bundles
	 * @exception CoreException
	 */
	private URI[] getMetadataRepositories(ITargetDefinition target) throws CoreException {
		Set<URI> result = new HashSet<>();
		ITargetLocation[] containers = target.getTargetLocations();
		if (containers == null) {
			containers = new ITargetLocation[0];
		}
		IMetadataRepositoryManager manager = getRepoManager();
		for (ITargetLocation container : containers) {
			if (container instanceof IUBundleContainer) {
				URI[] repos = ((IUBundleContainer) container).getRepositories();
				if (repos == null) {
					repos = manager.getKnownRepositories(IRepositoryManager.REPOSITORIES_ALL);
				}
				result.addAll(Arrays.asList(repos));
			}
		}
		return result.toArray(new URI[result.size()]);
	}

	private static final String NATIVE_ARTIFACTS = "nativeArtifacts"; //$NON-NLS-1$
	private static final String NATIVE_TYPE = "org.eclipse.equinox.p2.native"; //$NON-NLS-1$
	private static final String PARM_OPERAND = "operand"; //$NON-NLS-1$

	protected static class CollectNativesAction extends ProvisioningAction {
		@Override
		public IStatus execute(Map<String, Object> parameters) {
			InstallableUnitOperand operand = (InstallableUnitOperand) parameters.get(PARM_OPERAND);
			IInstallableUnit installableUnit = operand.second();
			if (installableUnit == null)
				return Status.OK_STATUS;

			IArtifactRepositoryManager manager;
			try {
				Collection<?> toDownload = installableUnit.getArtifacts();
				if (toDownload == null)
					return Status.OK_STATUS;

				@SuppressWarnings("unchecked")
				List<IArtifactRequest> artifactRequests = (List<IArtifactRequest>) parameters.get(NATIVE_ARTIFACTS);
				IArtifactRepository destinationArtifactRepository = getBundlePool();
				manager = getArtifactRepositoryManager();
				for (Object name : toDownload) {
					IArtifactKey keyToDownload = (IArtifactKey) name;
					IArtifactRequest request = manager.createMirrorRequest(keyToDownload, destinationArtifactRepository, null, null);
					artifactRequests.add(request);
				}
			} catch (CoreException e) {
				return e.getStatus();
			}
			return Status.OK_STATUS;
		}

		@Override
		public IStatus undo(Map<String, Object> parameters) {
			// nothing to do for now
			return Status.OK_STATUS;
		}
	}

	protected static class CollectNativesPhase extends InstallableUnitPhase {
		public CollectNativesPhase(int weight) {
			super(NATIVE_ARTIFACTS, weight);
		}

		@Override
		protected List<ProvisioningAction> getActions(InstallableUnitOperand operand) {
			IInstallableUnit unit = operand.second();
			if (unit != null && unit.getTouchpointType().getId().equals(NATIVE_TYPE)) {
				ArrayList<ProvisioningAction> list = new ArrayList<>(1);
				list.add(new CollectNativesAction());
				return list;
			}
			return null;
		}

		@Override
		protected IStatus initializePhase(IProgressMonitor monitor, IProfile profile, Map<String, Object> parameters) {
			parameters.put(NATIVE_ARTIFACTS, new ArrayList<>());
			parameters.put(PARM_PROFILE, profile);
			return null;
		}

		@Override
		protected IStatus completePhase(IProgressMonitor monitor, IProfile profile, Map<String, Object> parameters) {
			@SuppressWarnings("unchecked")
			List<IArtifactRequest> artifactRequests = (List<IArtifactRequest>) parameters.get(NATIVE_ARTIFACTS);
			ProvisioningContext context = (ProvisioningContext) parameters.get(PARM_CONTEXT);
			IProvisioningAgent agent = (IProvisioningAgent) parameters.get(PARM_AGENT);
			DownloadManager dm = new DownloadManager(context, agent);
			for (IArtifactRequest iArtifactRequest : artifactRequests) {
				dm.add(iArtifactRequest);
			}
			return dm.start(monitor);
		}
	}

	/**
	 * @return the profile associated with this synchronizer
	 */
	IProfile getProfile() {
		return fProfile;
	}

}
