/*******************************************************************************
 * Copyright (c) 2007, 2017 IBM Corporation and others.
 * All rights reserved.
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0 which accompanies this distribution,
 * and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 * IBM Corporation - initial implementation and ideas
 *     Sonatype, Inc. - ongoing development
 *     RedHat, Inc. - Bug 397216, Bug 460967
 ******************************************************************************/
package org.eclipse.equinox.internal.p2.reconciler.dropins;

import java.io.*;
import java.net.*;
import java.util.*;
import java.util.Map.Entry;
import org.eclipse.core.runtime.*;
import org.eclipse.equinox.internal.p2.core.helpers.*;
import org.eclipse.equinox.internal.p2.director.ProfileChangeRequest;
import org.eclipse.equinox.internal.p2.extensionlocation.Constants;
import org.eclipse.equinox.internal.provisional.configurator.Configurator;
import org.eclipse.equinox.internal.provisional.p2.directorywatcher.RepositoryListener;
import org.eclipse.equinox.p2.core.IProvisioningAgent;
import org.eclipse.equinox.p2.core.ProvisionException;
import org.eclipse.equinox.p2.engine.*;
import org.eclipse.equinox.p2.engine.query.IUProfilePropertyQuery;
import org.eclipse.equinox.p2.metadata.*;
import org.eclipse.equinox.p2.planner.IPlanner;
import org.eclipse.equinox.p2.planner.ProfileInclusionRules;
import org.eclipse.equinox.p2.query.*;
import org.eclipse.equinox.p2.repository.IRepository;
import org.eclipse.equinox.p2.repository.artifact.IArtifactRepository;
import org.eclipse.equinox.p2.repository.artifact.IFileArtifactRepository;
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository;
import org.eclipse.osgi.service.environment.EnvironmentInfo;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;

/**
 * Synchronizes a profile with a set of repositories.
 */
public class ProfileSynchronizer {
	private static final String RECONCILER_APPLICATION_ID = "org.eclipse.equinox.p2.reconciler.application"; //$NON-NLS-1$
	private static final String TIMESTAMPS_FILE_PREFIX = "timestamps"; //$NON-NLS-1$
	private static final String PROFILE_TIMESTAMP = "PROFILE"; //$NON-NLS-1$
	private static final String NO_TIMESTAMP = "-1"; //$NON-NLS-1$
	private static final String PROP_FROM_DROPINS = "org.eclipse.equinox.p2.reconciler.dropins"; //$NON-NLS-1$
	private static final String INCLUSION_RULES = "org.eclipse.equinox.p2.internal.inclusion.rules"; //$NON-NLS-1$
	private static final String INCLUSION_OPTIONAL = "OPTIONAL"; //$NON-NLS-1$
	private static final String INCLUSION_STRICT = "STRICT"; //$NON-NLS-1$

	private static final String CACHE_EXTENSIONS = "org.eclipse.equinox.p2.cache.extensions"; //$NON-NLS-1$
	private static final String PIPE = "|"; //$NON-NLS-1$
	private static final String EXPLANATION = "org.eclipse.equinox.p2.director.explain"; //$NON-NLS-1$

	static final String PROP_IGNORE_USER_CONFIGURATION = "eclipse.ignoreUserConfiguration"; //$NON-NLS-1$

	final IProfile profile;

	final Map<String, IMetadataRepository> repositoryMap;
	private Map<String, String> timestamps;
	private final IProvisioningAgent agent;

	/*
	 * Specialized profile change request so we can keep track of IUs which have moved
	 * locations on disk.
	 */
	static class ReconcilerProfileChangeRequest extends ProfileChangeRequest {
		List<IInstallableUnit> toMove = new ArrayList<>();

		public ReconcilerProfileChangeRequest(IProfile profile) {
			super(profile);
		}

		void moveAll(Collection<IInstallableUnit> list) {
			toMove.addAll(list);
		}

		Collection<IInstallableUnit> getMoves() {
			return toMove;
		}
	}

	/*
	 * Constructor for the class.
	 */
	public ProfileSynchronizer(IProvisioningAgent agent, IProfile profile, Collection<IMetadataRepository> repositories) {
		this.agent = agent;
		this.profile = profile;
		this.repositoryMap = new HashMap<>();
		for (IMetadataRepository repository : repositories) {
			repositoryMap.put(repository.getLocation().toString(), repository);
		}
	}

	/*
	 * Synchronize the profile with the list of metadata repositories.
	 * TODO fix progress monitoring (although in practice the user doesn't see it or have a chance to cancel)
	 */
	public IStatus synchronize(IProgressMonitor monitor) {
		readTimestamps();
		if (isUpToDate())
			return Status.OK_STATUS;

		ProvisioningContext context = getContext();
		context.setProperty(EXPLANATION, Boolean.valueOf(Tracing.DEBUG_RECONCILER).toString());

		String updatedCacheExtensions = synchronizeCacheExtensions();

		// figure out if we really have anything to install/uninstall.
		ReconcilerProfileChangeRequest request = createProfileChangeRequest(context);
		if (request == null) {
			if (updatedCacheExtensions == null)
				return Status.OK_STATUS;
			IStatus engineResult = setProperty(CACHE_EXTENSIONS, updatedCacheExtensions, context, null);
			if (engineResult.getSeverity() != IStatus.ERROR && engineResult.getSeverity() != IStatus.CANCEL)
				writeTimestamps();
			return engineResult;
		}
		if (updatedCacheExtensions != null)
			request.setProfileProperty(CACHE_EXTENSIONS, updatedCacheExtensions);

		// if some of the IUs move locations then construct a special plan and execute that first
		IStatus moveResult = performRemoveForMovedIUs(request, context, monitor);
		if (moveResult.getSeverity() == IStatus.ERROR || moveResult.getSeverity() == IStatus.CANCEL)
			return moveResult;

		if (!request.getRemovals().isEmpty()) {
			Collection<IRequirement> requirements = new ArrayList<>();
			for (IInstallableUnit unit : request.getRemovals()) {
				IRequirement req = MetadataFactory.createRequirement(IInstallableUnit.NAMESPACE_IU_ID, unit.getId(), new VersionRange(unit.getVersion(), true, unit.getVersion(), true), null, 0, 0, false);
				requirements.add(req);
			}
			request.addExtraRequirements(requirements);
		}

		// now create a plan for the rest of the work and execute it
		IStatus addRemoveResult = performAddRemove(request, context, monitor);
		if (addRemoveResult.getSeverity() == IStatus.ERROR || addRemoveResult.getSeverity() == IStatus.CANCEL)
			return addRemoveResult;

		// write out the new timestamps (for caching) and apply the configuration
		writeTimestamps();
		IStatus applyResult = applyConfiguration(false);

		// Mark the state update as hidden so it does not appear in the Installation History UI list
		// TODO We need to determine if it is ok to use this copy of the profile.
		// See https://bugs.eclipse.org/334670
		IProfileRegistry profileRegistry = agent.getService(IProfileRegistry.class);
		if (profileRegistry != null) {
			IStatus result = profileRegistry.setProfileStateProperty(profile.getProfileId(), profile.getTimestamp(), IProfile.STATE_PROP_HIDDEN, Boolean.TRUE.toString());
			if (!result.isOK()) {
				// we don't get here but if we do, we will ignore the problem and continue. We
				// still want the install operation to succeed. The consequence of this failure is the
				// profile state appears in the UI in the Install History page, which isn't horrible.
				LogHelper.log(result);
			}
		}

		return applyResult;
	}

	/*
	 * Return a list of the roots in the profile.
	 */
	private IQueryResult<IInstallableUnit> getStrictRoots() {
		return profile.query(new IUProfilePropertyQuery(INCLUSION_RULES, INCLUSION_STRICT), null);
	}

	/*
	 * Convert the profile change request into operands and have the engine execute them. There
	 * is fancy logic here in case we are trying to remove IUs which are depended on by something
	 * which is installed via the UI. Since the bundle has been removed from the file-system it is a forced
	 * removal so we have to uninstall the UI-installed IU.
	 */
	private IStatus performAddRemove(ReconcilerProfileChangeRequest request, ProvisioningContext context, IProgressMonitor monitor) {
		// if we have moves then we have previously removed them.
		// now we need to add them back (at the new location)
		for (IInstallableUnit iu : request.getMoves()) {
			request.add(iu);
			request.setInstallableUnitProfileProperty(iu, PROP_FROM_DROPINS, Boolean.TRUE.toString());
			request.setInstallableUnitInclusionRules(iu, ProfileInclusionRules.createOptionalInclusionRule(iu));
			request.setInstallableUnitProfileProperty(iu, IProfile.PROP_PROFILE_LOCKED_IU, Integer.toString(IProfile.LOCK_UNINSTALL));
		}

		Collection<IInstallableUnit> additions = request.getAdditions();
		Collection<IInstallableUnit> removals = request.getRemovals();
		// see if there is any work to do
		if (additions.isEmpty() && removals.isEmpty())
			return Status.OK_STATUS;

		// TODO See bug 270195. Eventually we will attempt to remove strictly installed IUs if their
		// dependent bundles have been deleted.
		boolean removeStrictRoots = false;
		if (removeStrictRoots)
			return performStrictRootRemoval(request, context, monitor);
		IProvisioningPlan plan = createProvisioningPlan(request, context, monitor);
		debug(request, plan);
		return executePlan(plan, context, monitor);
	}

	// TODO re-enable after resolving bug 270195.
	private IStatus performStrictRootRemoval(ReconcilerProfileChangeRequest request, ProvisioningContext context, IProgressMonitor monitor) {
		Collection<IInstallableUnit> removals = request.getRemovals();
		// if we don't have any removals then we don't have to worry about potentially
		// invalidating things we already have installed, removal of roots, etc so just
		// create a regular plan.
		if (removals.isEmpty()) {
			IProvisioningPlan plan = createProvisioningPlan(request, context, monitor);
			debug(request, plan);
			return executePlan(plan, context, monitor);
		}

		// We are now creating a backup of the original request that will be used to create the final plan (where no optional magic is used)
		ProfileChangeRequest finalRequest = request.clone();

		// otherwise collect the roots, pretend they are optional, and see
		// if the resulting plan affects them
		Set<IInstallableUnit> strictRoots = getStrictRoots().toUnmodifiableSet();
		Collection<IRequirement> forceNegation = new ArrayList<>(removals.size());
		for (IInstallableUnit iu : removals)
			forceNegation.add(createNegation(iu));
		request.addExtraRequirements(forceNegation);

		// set all the profile roots to be optional to see how they would be effected by the plan
		for (IInstallableUnit iu : strictRoots)
			request.setInstallableUnitProfileProperty(iu, INCLUSION_RULES, INCLUSION_OPTIONAL);

		// get the tentative plan back from the planner
		IProvisioningPlan plan = createProvisioningPlan(request, context, monitor);
		debug(request, plan);
		if (!plan.getStatus().isOK())
			return plan.getStatus();

		// Analyze the plan to see if any of the strict roots are being uninstalled.
		int removedRoots = 0;
		for (IInstallableUnit initialRoot : strictRoots) {
			// if the root wasn't uninstalled, then continue
			if (plan.getRemovals().query(QueryUtil.createIUQuery(initialRoot), null).isEmpty())
				continue;
			// otherwise add its removal to the change request, along with a negation and
			// change of strict to optional for their inclusion rule.
			finalRequest.remove(initialRoot);
			finalRequest.setInstallableUnitProfileProperty(initialRoot, INCLUSION_RULES, INCLUSION_OPTIONAL);
			IRequirement negation = createNegation(initialRoot);
			Collection<IRequirement> extra = new ArrayList<>();
			extra.add(negation);
			request.addExtraRequirements(extra);
			LogHelper.log(new Status(IStatus.INFO, Activator.ID, NLS.bind(Messages.remove_root, initialRoot.getId(), initialRoot.getVersion())));
			removedRoots++;
		}

		// Check for the case where all the strict roots are being removed.
		if (removedRoots == strictRoots.size())
			return new Status(IStatus.ERROR, Activator.ID, Messages.remove_all_roots);
		plan = createProvisioningPlan(finalRequest, context, monitor);
		if (!plan.getStatus().isOK()) {
			System.out.println("original request"); //$NON-NLS-1$
			System.out.println(request);
			System.out.println("final request"); //$NON-NLS-1$
			System.out.println(finalRequest);
			throw new IllegalStateException("The second plan is not resolvable."); //$NON-NLS-1$
		}

		// execute the plan and return the status
		return executePlan(plan, context, monitor);
	}

	/*
	 * If the request contains IUs to be moved then create and execute a plan which
	 * removes them. Otherwise just return.
	 */
	private IStatus performRemoveForMovedIUs(ReconcilerProfileChangeRequest request, ProvisioningContext context, IProgressMonitor monitor) {
		Collection<IInstallableUnit> moves = request.getMoves();
		if (moves.isEmpty())
			return Status.OK_STATUS;
		IEngine engine = agent.getService(IEngine.class);
		IProvisioningPlan plan = engine.createPlan(profile, context);
		for (IInstallableUnit unit : moves)
			plan.removeInstallableUnit(unit);
		return executePlan(plan, context, monitor);
	}

	/*
	 * Write out the timestamps of various repositories and folders/file to help
	 * us cache and detect cases where we don't have to perform a reconciliation.
	 */
	private void writeTimestamps() {
		timestamps.clear();
		timestamps.put(PROFILE_TIMESTAMP, Long.toString(profile.getTimestamp()));
		for (Entry<String, IMetadataRepository> entry : repositoryMap.entrySet()) {
			IMetadataRepository repository = entry.getValue();
			Map<String, String> props = repository.getProperties();
			String timestamp = null;
			if (props != null)
				timestamp = props.get(IRepository.PROP_TIMESTAMP);
			if (timestamp == null)
				timestamp = NO_TIMESTAMP;

			timestamps.put(entry.getKey(), timestamp);
		}

		try {
			File file = Activator.getContext().getDataFile(TIMESTAMPS_FILE_PREFIX + profile.getProfileId().hashCode());
			Activator.trace("Writing timestamp file to : " + file.getAbsolutePath()); //$NON-NLS-1$
			try (OutputStream os = new BufferedOutputStream(new FileOutputStream(file))) {
				CollectionUtils.storeProperties(timestamps, os, "Timestamps for " + profile.getProfileId()); //$NON-NLS-1$
				if (Tracing.DEBUG_RECONCILER) {
					for (String key : timestamps.keySet()) {
						Object value = timestamps.get(key);
						Activator.trace(key + '=' + value);
					}
				}
			}
		} catch (FileNotFoundException e) {
			//Ignore
		} catch (IOException e) {
			//Ignore
		}
	}

	/*
	 * Check timestamps and return true if the profile is considered to be up-to-date or
	 * false if we should perform a reconciliation.
	 */
	private boolean isUpToDate() {
		// the user might want to force a reconciliation
		if ("true".equals(Activator.getContext().getProperty("osgi.checkConfiguration"))) { //$NON-NLS-1$//$NON-NLS-2$
			Activator.trace("User requested forced reconciliation via \"osgi.checkConfiguration=true\" System property."); //$NON-NLS-1$
			Activator.trace("Performing reconciliation."); //$NON-NLS-1$
			return false;
		}

		String lastKnownProfileTimeStamp = timestamps.remove(PROFILE_TIMESTAMP);
		if (lastKnownProfileTimeStamp == null) {
			Activator.trace("Profile timestamp not found in cache."); //$NON-NLS-1$
			Activator.trace("Performing reconciliation."); //$NON-NLS-1$
			return false;
		}
		String currentProfileTimestamp = Long.toString(profile.getTimestamp());
		if (!lastKnownProfileTimeStamp.equals(currentProfileTimestamp)) {
			Activator.trace("Profile timestamps not equal, expected: " + lastKnownProfileTimeStamp + ", actual=" + currentProfileTimestamp); //$NON-NLS-1$ //$NON-NLS-2$
			Activator.trace("Performing reconciliation."); //$NON-NLS-1$
			return false;
		}

		//When we get here the timestamps map only contains information related to repos
		for (Entry<String, IMetadataRepository> entry : repositoryMap.entrySet()) {
			IMetadataRepository repository = entry.getValue();

			Map<String, String> props = repository.getProperties();
			String currentTimestamp = null;
			if (props != null)
				currentTimestamp = props.get(IRepository.PROP_TIMESTAMP);

			if (currentTimestamp == null)
				currentTimestamp = NO_TIMESTAMP;

			String key = entry.getKey();
			String lastKnownTimestamp = timestamps.remove(key);
			//A repo has been added
			if (lastKnownTimestamp == null) {
				Activator.trace("No cached timestamp found for: " + key); //$NON-NLS-1$
				Activator.trace("Performing reconciliation."); //$NON-NLS-1$
				return false;
			}
			if (!lastKnownTimestamp.equals(currentTimestamp)) {
				Activator.trace("Timestamps not equal for file: " + key + ", expected: " + lastKnownTimestamp + ", actual: " + currentTimestamp); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				Activator.trace("Performing reconciliation."); //$NON-NLS-1$
				return false;
			}
		}
		if (timestamps.size() == 0) {
			Activator.trace("Timestamps valid."); //$NON-NLS-1$
			Activator.trace("Skipping reconciliation."); //$NON-NLS-1$
			return true;
		}

		//A repo has been removed
		if (Tracing.DEBUG_RECONCILER) {
			Activator.trace("Extra values in timestamp file:"); //$NON-NLS-1$
			for (String string : timestamps.keySet())
				Activator.trace(string);
			Activator.trace("Performing reconciliation."); //$NON-NLS-1$
		}
		return false;
	}

	/*
	 * Read the values of the stored timestamps that we use for caching.
	 */
	private void readTimestamps() {
		if (Boolean.TRUE.toString().equalsIgnoreCase(System.getProperty(PROP_IGNORE_USER_CONFIGURATION))) {
			timestamps = new HashMap<>();
			Activator.trace("Master profile changed."); //$NON-NLS-1$
			Activator.trace("Performing reconciliation."); //$NON-NLS-1$
			return;
		}
		File file = Activator.getContext().getDataFile(TIMESTAMPS_FILE_PREFIX + profile.getProfileId().hashCode());
		try {
			try (InputStream is = new BufferedInputStream(new FileInputStream(file))) {
				timestamps = CollectionUtils.loadProperties(is);
			}
		} catch (FileNotFoundException e) {
			//Ignore
			timestamps = new HashMap<>();
			Activator.trace("Timestamp file does not exist."); //$NON-NLS-1$
			Activator.trace("Performing reconciliation."); //$NON-NLS-1$
		} catch (IOException e) {
			//Ignore
			timestamps = new HashMap<>();
			Activator.trace("Exception loading timestamp file: " + e.getMessage()); //$NON-NLS-1$
			Activator.trace("Performing reconciliation."); //$NON-NLS-1$
		}
	}

	private ProvisioningContext getContext() {
		ArrayList<URI> repoURLs = new ArrayList<>();
		for (String string : repositoryMap.keySet()) {
			try {
				repoURLs.add(new URI(string));
			} catch (URISyntaxException e) {
				//ignore
			}
		}
		ProvisioningContext result = new ProvisioningContext(agent);
		result.setMetadataRepositories(repoURLs.toArray(new URI[repoURLs.size()]));
		result.setArtifactRepositories(new URI[0]);
		return result;
	}

	private String synchronizeCacheExtensions() {
		List<String> currentExtensions = new ArrayList<>();
		StringBuilder buffer = new StringBuilder();

		List<String> repositories = new ArrayList<>(repositoryMap.keySet());
		URL installArea = Activator.getOSGiInstallArea();
		final String OSGiInstallArea;
		try {
			// The OSGi install area is an unencoded URL and repository locations are encoded URIs
			// so make them the same so we can compare them.
			// See https://bugs.eclipse.org/346565.
			OSGiInstallArea = URIUtil.toURI(installArea).toString() + Constants.EXTENSION_LOCATION;
			// Sort the repositories so the extension location at the OSGi install folder is first.
			// See https://bugs.eclipse.org/246310.
			Collections.sort(repositories, (left, right) -> {
				if (OSGiInstallArea.equals(left))
					return -1;
				if (OSGiInstallArea.equals(right))
					return 1;
				return left.compareTo(right);
			});
		} catch (URISyntaxException e) {
			// This shouldn't happen but if it does we will log the error and continue
			// with the repositories in the default order.
			LogHelper.log(new Status(IStatus.ERROR, Activator.ID, "Unable to convert OSGi install area: " + installArea + " into URI.", e)); //$NON-NLS-1$ //$NON-NLS-2$
		}
		for (Iterator<String> it = repositories.iterator(); it.hasNext();) {
			String repositoryId = it.next();
			try {
				IArtifactRepository repository = Activator.loadArtifactRepository(new URI(repositoryId), null);
				if (repository instanceof IFileArtifactRepository) {
					currentExtensions.add(escapePipe(repositoryId));
					buffer.append(repositoryId);
					if (it.hasNext())
						buffer.append(PIPE);
				}
			} catch (ProvisionException e) {
				// ignore
			} catch (URISyntaxException e) {
				// unexpected
				e.printStackTrace();
			}
		}
		String currentExtensionsProperty = (buffer.length() == 0) ? null : buffer.toString();

		List<String> previousExtensions = new ArrayList<>();
		String previousExtensionsProperty = profile.getProperty(CACHE_EXTENSIONS);
		if (previousExtensionsProperty != null) {
			StringTokenizer tokenizer = new StringTokenizer(previousExtensionsProperty, PIPE);
			while (tokenizer.hasMoreTokens()) {
				previousExtensions.add(tokenizer.nextToken());
			}
		}

		if (previousExtensions.size() == currentExtensions.size() && previousExtensions.containsAll(currentExtensions))
			return null;

		return currentExtensionsProperty;
	}

	/**
	 * Escapes the pipe ('|') character in a URI using the standard URI escape sequence.
	 * This is done because the pipe character is used as the delimiter between locations
	 * in the cache extensions profile property.
	 */
	private String escapePipe(String location) {
		String result = location;
		int pipeIndex;
		while ((pipeIndex = result.indexOf(',')) != -1)
			result = result.substring(0, pipeIndex) + "%7C" + result.substring(pipeIndex + 1); //$NON-NLS-1$
		return result;
	}

	/*
	 * Return a map of all the IUs in the profile
	 * Use a map here so we have a copy of the original IU from the profile... we will need it later.
	 */
	private Map<IInstallableUnit, IInstallableUnit> getProfileIUs() {
		IQueryResult<IInstallableUnit> profileQueryResult = profile.query(QueryUtil.createIUAnyQuery(), null);
		Map<IInstallableUnit, IInstallableUnit> result = new HashMap<>();
		for (IInstallableUnit iu : profileQueryResult) {
			result.put(iu, iu);
		}
		return result;
	}

	/*
	 * Return a map of all the IUs available in the profile. This takes the shared parents into consideration, if applicable.
	 * Use a map here so we have a copy of the original IU from the profile... we will need it later.
	 */
	private Map<IInstallableUnit, IInstallableUnit> getAvailableProfileIUs() {
		IQueryResult<IInstallableUnit> profileQueryResult = profile.available(QueryUtil.createIUAnyQuery(), null);
		Map<IInstallableUnit, IInstallableUnit> result = new HashMap<>();
		for (IInstallableUnit iu : profileQueryResult) {
			result.put(iu, iu);
		}
		return result;
	}

	/*
	 * Return the profile change requests that we need to execute in order to install everything from the
	 * dropins folder(s). (or uninstall things that have been removed) We use a collection here because if
	 * the user has moved bundles from the dropins to the plugins (for instance) then we need to uninstall
	 * the old bundle and then re-install the new one. This is because the IUs for the moved bundles are
	 * considered the same but they really differ in an IU property. (file location, which is not considered
	 * as part of equality)
	 */
	public ReconcilerProfileChangeRequest createProfileChangeRequest(ProvisioningContext context) {
		ReconcilerProfileChangeRequest request = new ReconcilerProfileChangeRequest(profile);

		boolean resolve = Boolean.parseBoolean(profile.getProperty("org.eclipse.equinox.p2.resolve")); //$NON-NLS-1$
		if (resolve)
			request.removeProfileProperty("org.eclipse.equinox.p2.resolve"); //$NON-NLS-1$

		List<IInstallableUnit> toRemove = new ArrayList<>();
		List<IInstallableUnit> toMove = new ArrayList<>();

		boolean foundIUsToAdd = false;
		Map<IInstallableUnit, IInstallableUnit> profileIUs = getProfileIUs();

		// we use IProfile.available(...) here so that we also gather any shared IUs
		Map<IInstallableUnit, IInstallableUnit> availableProfileIUs = getAvailableProfileIUs();

		// get all IUs from all our repos
		IQueryResult<IInstallableUnit> allIUs = getAllIUsFromRepos();
		for (Iterator<IInstallableUnit> iter = allIUs.iterator(); iter.hasNext();) {
			final IInstallableUnit iu = iter.next();
			IInstallableUnit existing = profileIUs.get(iu);
			// check to see if this IU has moved locations
			if (existing != null) {
				// if the IU is already installed in the profile then check to see if it was moved.
				String one = iu.getProperty(RepositoryListener.FILE_NAME);
				String two = existing.getProperty(RepositoryListener.FILE_NAME);
				// cheat here... since we always set the filename property for bundles in the dropins,
				// if the existing IU's filename is null then it isn't from the dropins. a better
				// (and more expensive) way to find this out is to do an IU profile property query.
				if (two == null) {
					// the IU is already installed so don't mark it as a dropin now - see bug 404619.
					iter.remove();
					continue;
				}
				// if we have an IU which has been moved, keep track of it.
				if (one != null && !one.equals(two)) {
					toMove.add(iu);
					continue;
				}
			}
			// even though we are adding all IUs below, we need to explicitly set the properties for
			// them as well. Do that here.
			if (QueryUtil.isGroup(iu))
				request.setInstallableUnitProfileProperty(iu, IProfile.PROP_PROFILE_ROOT_IU, Boolean.TRUE.toString());
			// mark all IUs with special property
			request.setInstallableUnitProfileProperty(iu, PROP_FROM_DROPINS, Boolean.TRUE.toString());
			request.setInstallableUnitInclusionRules(iu, ProfileInclusionRules.createOptionalInclusionRule(iu));
			request.setInstallableUnitProfileProperty(iu, IProfile.PROP_PROFILE_LOCKED_IU, Integer.toString(IProfile.LOCK_UNINSTALL));

			// as soon as we find something locally that needs to be installed, then
			// everything from the parent's dropins must be installed locally as well.
			if (!foundIUsToAdd && availableProfileIUs.get(iu) == null) {
				foundIUsToAdd = true;
			}
		}

		// get all IUs from profile with marked property (existing)
		IQueryResult<IInstallableUnit> dropinIUs = profile.query(new IUProfilePropertyQuery(PROP_FROM_DROPINS, Boolean.TRUE.toString()), null);
		Set<IInstallableUnit> all = allIUs.toUnmodifiableSet();
		for (IInstallableUnit iu : dropinIUs) {
			// the STRICT policy is set when we install things via the UI, we use it to differentiate between IUs installed
			// via the dropins and the UI. (dropins are considered optional) If an IU has both properties set it means that
			// it was initially installed via the dropins but then upgraded via the UI. (properties are copied from the old IU
			// to the new IU during an upgrade) In this case we want to remove the "from dropins" property so the upgrade
			// will stick.
			if ("STRICT".equals(profile.getInstallableUnitProperty(iu, "org.eclipse.equinox.p2.internal.inclusion.rules"))) { //$NON-NLS-1$//$NON-NLS-2$
				request.removeInstallableUnitProfileProperty(iu, PROP_FROM_DROPINS);
				request.removeInstallableUnitProfileProperty(iu, IProfile.PROP_PROFILE_LOCKED_IU);
				continue;
			}
			// if the IU from the profile is in the "all available" list, then it is already added
			// otherwise if it isn't in the repo then we have to remove it from the profile.
			if (!all.contains(iu))
				toRemove.add(iu);
		}

		if (!foundIUsToAdd && toRemove.isEmpty() && !resolve && toMove.isEmpty()) {
			if (Tracing.DEBUG_RECONCILER)
				Tracing.debug("[reconciler] Nothing to do."); //$NON-NLS-1$
			return null;
		}

		// everything from the drop-ins must be considered for addition/removal everytime so add all here
		request.addAll(all);
		request.removeAll(toRemove);
		request.moveAll(toMove);

		debug(request);
		return request;
	}

	/*
	 * Create and return a negated requirement saying that the given IU must not exist in the profile.
	 */
	private IRequirement createNegation(IInstallableUnit unit) {
		return MetadataFactory.createRequirement(IInstallableUnit.NAMESPACE_IU_ID, unit.getId(), //
				new VersionRange(unit.getVersion(), true, unit.getVersion(), true), null, 0, 0, false);
	}

	/*
	 * If in debug mode, print out information which tells us whether or not the given
	 * provisioning plan matches the request.
	 */
	private void debug(ReconcilerProfileChangeRequest request, IProvisioningPlan plan) {
		if (!Tracing.DEBUG_RECONCILER)
			return;
		final String PREFIX = "[reconciler] [plan] "; //$NON-NLS-1$
		// get the request
		List<IInstallableUnit> toAdd = new ArrayList<>(request.getAdditions());
		List<IInstallableUnit> toRemove = new ArrayList<>(request.getRemovals());
		List<IInstallableUnit> toMove = new ArrayList<>(request.getMoves());

		// remove from the request everything that is in the plan
		for (IInstallableUnit iu : plan.getRemovals().query(QueryUtil.createIUAnyQuery(), null)) {
			if (!toRemove.remove(iu)) {
				Tracing.debug(PREFIX + iu + " will be removed"); //$NON-NLS-1$
			}
		}
		for (IInstallableUnit iu : plan.getAdditions().query(QueryUtil.createIUAnyQuery(), null)) {
			if (!toAdd.remove(iu)) {
				Tracing.debug(PREFIX + iu + " will be added"); //$NON-NLS-1$
			}
		}
		// Move operations are treated as doing a remove/add. The removes have already happened
		// and at this point we are adding the moved IUs back at their new location. Remove the moved
		// IUs from the added list because this will just confuse the user.
		toAdd.removeAll(toMove);

		// if anything is left in the request, then something is wrong with the plan
		if (toAdd.size() == 0 && toRemove.size() == 0)
			Tracing.debug(PREFIX + "Plan matches the request."); //$NON-NLS-1$
		if (toAdd.size() != 0) {
			Tracing.debug(PREFIX + "Some units will not be installed, because they are already installed or there are dependency issues:"); //$NON-NLS-1$
			for (IInstallableUnit unit : toAdd)
				Tracing.debug(PREFIX + unit);
		}
		if (toRemove.size() != 0) {
			Tracing.debug(PREFIX + "Some units will not be uninstalled:"); //$NON-NLS-1$
			for (IInstallableUnit unit : toRemove)
				Tracing.debug(PREFIX + unit);
		}
	}

	/*
	 * If debugging is turned on, then print out the details for the given profile change request.
	 */
	private void debug(ReconcilerProfileChangeRequest request) {
		if (!Tracing.DEBUG_RECONCILER)
			return;
		final String PREFIX = "[reconciler] "; //$NON-NLS-1$
		Collection<IInstallableUnit> toAdd = request.getAdditions();
		if (toAdd == null || toAdd.size() == 0) {
			Tracing.debug(PREFIX + "No installable units to add."); //$NON-NLS-1$
		} else {
			for (IInstallableUnit add : toAdd) {
				Tracing.debug(PREFIX + "Adding IU: " + add.getId() + ' ' + add.getVersion()); //$NON-NLS-1$
			}
		}
		Map<IInstallableUnit, Map<String, String>> propsToAdd = request.getInstallableUnitProfilePropertiesToAdd();
		if (propsToAdd == null || propsToAdd.isEmpty()) {
			Tracing.debug(PREFIX + "No IU properties to add."); //$NON-NLS-1$
		} else {
			for (Entry<IInstallableUnit, Map<String, String>> entry : propsToAdd.entrySet()) {
				Tracing.debug(PREFIX + "Adding IU property: " + entry.getKey() + "->" + entry.getValue()); //$NON-NLS-1$ //$NON-NLS-2$
			}
		}

		Collection<IInstallableUnit> toRemove = request.getRemovals();
		if (toRemove == null || toRemove.size() == 0) {
			Tracing.debug(PREFIX + "No installable units to remove."); //$NON-NLS-1$
		} else {
			for (IInstallableUnit remove : toRemove) {
				Tracing.debug(PREFIX + "Removing IU: " + remove.getId() + ' ' + remove.getVersion()); //$NON-NLS-1$
			}
		}
		Map<IInstallableUnit, List<String>> propsToRemove = request.getInstallableUnitProfilePropertiesToRemove();
		if (propsToRemove == null || propsToRemove.isEmpty()) {
			Tracing.debug(PREFIX + "No IU properties to remove."); //$NON-NLS-1$
		} else {
			for (Entry<IInstallableUnit, List<String>> entry : propsToRemove.entrySet()) {
				Tracing.debug(PREFIX + "Removing IU property: " + entry.getKey() + "->" + entry.getValue()); //$NON-NLS-1$ //$NON-NLS-2$
			}
		}

		Collection<IInstallableUnit> toMove = request.getMoves();
		if (toMove == null || toMove.isEmpty()) {
			Tracing.debug(PREFIX + "No installable units to move."); //$NON-NLS-1$
		} else {
			for (IInstallableUnit move : toMove)
				Tracing.debug(PREFIX + "Moving IU: " + move.getId() + ' ' + move.getVersion()); //$NON-NLS-1$
		}

		Collection<IRequirement> extra = request.getExtraRequirements();
		if (extra == null || extra.isEmpty()) {
			Tracing.debug(PREFIX + "No extra requirements."); //$NON-NLS-1$
		} else {
			for (IRequirement requirement : extra)
				Tracing.debug(PREFIX + "Extra requirement: " + requirement); //$NON-NLS-1$
		}
	}

	/*
	 * Return all of the IUs available in all of our repos. This usually includes the dropins and plugins folders
	 * as well as any sites specified in the platform.xml file.
	 */
	private IQueryResult<IInstallableUnit> getAllIUsFromRepos() {
		// TODO: Should consider using a sequenced iterator here instead of collecting
		Collector<IInstallableUnit> allRepos = new Collector<>();
		for (IMetadataRepository repository : repositoryMap.values()) {
			allRepos.addAll(repository.query(QueryUtil.createIUAnyQuery(), null));
		}
		return allRepos;
	}

	/*
	 * Create and return a provisioning plan for the given change request.
	 */
	private IProvisioningPlan createProvisioningPlan(ProfileChangeRequest request, ProvisioningContext provisioningContext, IProgressMonitor monitor) {
		IPlanner planner = agent.getService(IPlanner.class);
		return planner.getProvisioningPlan(request, provisioningContext, monitor);
	}

	/*
	 * Call the engine to set the given property on the profile.
	 */
	private IStatus setProperty(String key, String value, ProvisioningContext provisioningContext, IProgressMonitor monitor) {
		IEngine engine = agent.getService(IEngine.class);
		IProvisioningPlan plan = engine.createPlan(profile, provisioningContext);
		plan.setProfileProperty(key, value);
		IPhaseSet phaseSet = PhaseSetFactory.createPhaseSetIncluding(new String[] {PhaseSetFactory.PHASE_PROPERTY});
		return engine.perform(plan, phaseSet, monitor);
	}

	/*
	 * Execute the given plan.
	 */
	private IStatus executePlan(IProvisioningPlan plan, ProvisioningContext provisioningContext, IProgressMonitor monitor) {
		IEngine engine = agent.getService(IEngine.class);
		IPhaseSet phaseSet = PhaseSetFactory.createDefaultPhaseSetExcluding(new String[] {PhaseSetFactory.PHASE_COLLECT, PhaseSetFactory.PHASE_CHECK_TRUST});

		if (plan.getInstallerPlan() != null) {
			IStatus installerPlanStatus = engine.perform(plan.getInstallerPlan(), phaseSet, monitor);
			if (!installerPlanStatus.isOK())
				return installerPlanStatus;

			applyConfiguration(true);
		}
		return engine.perform(plan, phaseSet, monitor);
	}

	/*
	 * Write out the configuration file.
	 */
	private IStatus applyConfiguration(boolean isInstaller) {
		if (!isInstaller && isReconciliationApplicationRunning())
			return Status.OK_STATUS;
		BundleContext context = Activator.getContext();
		ServiceReference<Configurator> reference = context.getServiceReference(Configurator.class);
		Configurator configurator = context.getService(reference);
		try {
			configurator.applyConfiguration();
		} catch (IOException e) {
			return new Status(IStatus.ERROR, Activator.ID, "Unexpected failure applying configuration", e); //$NON-NLS-1$
		} finally {
			context.ungetService(reference);
		}
		return Status.OK_STATUS;
	}

	static boolean isReconciliationApplicationRunning() {
		EnvironmentInfo info = ServiceHelper.getService(Activator.getContext(), EnvironmentInfo.class);
		if (info == null)
			return false;
		String[] args = info.getCommandLineArgs();
		if (args == null)
			return false;
		for (String arg : args) {
			if (arg != null && RECONCILER_APPLICATION_ID.equals(arg.trim()))
				return true;
		}
		return false;
	}
}
