/*******************************************************************************
 *  Copyright (c) 2004, 2019 IBM Corporation and others.
 *
 *  This program and the accompanying materials
 *  are made available under the terms of the Eclipse Public License 2.0
 *  which accompanies this distribution, and is available at
 *  https://www.eclipse.org/legal/epl-2.0/
 *
 *  SPDX-License-Identifier: EPL-2.0
 * 
 *  Contributors:
 *      IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.pde.internal.build.site;

import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.util.*;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.eclipse.core.runtime.*;
import org.eclipse.osgi.service.resolver.*;
import org.eclipse.osgi.service.resolver.VersionRange;
import org.eclipse.osgi.util.ManifestElement;
import org.eclipse.osgi.util.NLS;
import org.eclipse.pde.internal.build.*;
import org.osgi.framework.*;

// This class provides a higher level API on the state
public class PDEState implements IPDEBuildConstants, IBuildPropertiesConstants {
	private static final String[] MANIFEST_ENTRIES = {Constants.BUNDLE_LOCALIZATION, Constants.BUNDLE_NAME, Constants.BUNDLE_VENDOR, ECLIPSE_BUNDLE_SHAPE, ECLIPSE_SOURCE_BUNDLE, ECLIPSE_SOURCE_REF};
	private static int LAST_SUPPORTED_JDK = 13;
	private StateObjectFactory factory;
	protected State state;
	private long id;
	private Properties repositoryVersions;
	private Properties sourceReferences;
	private HashMap<Long, String[]> bundleClasspaths;
	private ProfileManager profileManager;
	private Map<Long, String> patchBundles;
	private List<BundleDescription> addedBundle;
	private List<BundleDescription> unqualifiedBundles; //All the bundle description objects that have .qualifier in them 
	private Properties platformProperties;
	private List<BundleDescription> sortedBundles = null;
	private final Set<Dictionary<String, String>> convertedManifests;
	private long lastSortingDate = 0L;
	private String[] eeSources;

	protected long getNextId() {
		return ++id;
	}

	public PDEState(PDEUIStateWrapper initialState) {
		this();
		state = initialState.getState();
		factory = state.getFactory();
		id = initialState.getNextId();
		bundleClasspaths = initialState.getClasspaths();
		patchBundles = initialState.getPatchData();
		addedBundle = new ArrayList<>();
		unqualifiedBundles = new ArrayList<>();
		//forceQualifiers();
	}

	public PDEState() {
		factory = Platform.getPlatformAdmin().getFactory();
		state = factory.createState(false);
		state.setResolver(Platform.getPlatformAdmin().createResolver());
		id = 0;
		bundleClasspaths = new HashMap<>();
		patchBundles = new HashMap<>();
		convertedManifests = new HashSet<>(2);
		loadPluginTagFile();
		loadSourceReferences();
	}

	public StateObjectFactory getFactory() {
		return factory;
	}

	public boolean addBundleDescription(BundleDescription toAdd) {
		return state.addBundle(toAdd);
	}

	//Add a bundle to the state, updating the version number 
	public boolean addBundle(Dictionary<String, String> enhancedManifest, File bundleLocation) {
		String oldVersion = updateVersionNumber(enhancedManifest);
		try {
			BundleDescription descriptor;
			descriptor = factory.createBundleDescription(state, enhancedManifest, bundleLocation.getAbsolutePath(), getNextId());
			bundleClasspaths.put(Long.valueOf(descriptor.getBundleId()), BundleHelper.getClasspath(enhancedManifest));
			String patchValue = fillPatchData(enhancedManifest);
			if (patchValue != null)
				patchBundles.put(Long.valueOf(descriptor.getBundleId()), patchValue);
			rememberQualifierTagPresence(descriptor);
			rememberManifestConversion(descriptor, enhancedManifest);
			rememberManifestEntries(descriptor, enhancedManifest, MANIFEST_ENTRIES);
			rememberSourceReference(descriptor, oldVersion);
			if (addBundleDescription(descriptor) == true && addedBundle != null)
				addedBundle.add(descriptor);
		} catch (BundleException e) {
			IStatus status = new Status(IStatus.WARNING, IPDEBuildConstants.PI_PDEBUILD, EXCEPTION_STATE_PROBLEM, NLS.bind(Messages.exception_stateAddition, BundleHelper.getManifestHeader(enhancedManifest, Constants.BUNDLE_NAME)), e);
			BundleHelper.getDefault().getLog().log(status);
			return false;
		}
		return true;
	}

	private void rememberQualifierTagPresence(BundleDescription descriptor) {
		Properties bundleProperties = null;
		bundleProperties = (Properties) descriptor.getUserObject();
		if (bundleProperties == null) {
			bundleProperties = new Properties();
			descriptor.setUserObject(bundleProperties);
		}
		bundleProperties.setProperty(PROPERTY_QUALIFIER, "marker"); //$NON-NLS-1$
	}

	private void rememberSourceReference(BundleDescription descriptor, String oldVersion) {
		if (sourceReferences == null)
			return;

		String key = QualifierReplacer.getQualifierKey(descriptor.getSymbolicName(), oldVersion);
		if (key == null || !sourceReferences.containsKey(key))
			key = descriptor.getSymbolicName() + ',' + Version.emptyVersion.toString();
		if (sourceReferences.containsKey(key)) {
			Properties bundleProperties = (Properties) descriptor.getUserObject();
			if (bundleProperties == null) {
				bundleProperties = new Properties();
				descriptor.setUserObject(bundleProperties);
			}
			bundleProperties.setProperty(PROPERTY_SOURCE_REFERENCE, sourceReferences.getProperty(key));
		}
	}

	private void rememberManifestEntries(BundleDescription descriptor, Dictionary<String, String> manifest, String[] entries) {
		if (entries == null || entries.length == 0)
			return;

		Properties properties = (Properties) descriptor.getUserObject();
		if (properties == null) {
			properties = new Properties();
			descriptor.setUserObject(properties);
		}

		for (int i = 0; i < entries.length; i++) {
			String entry = BundleHelper.getManifestHeader(manifest, entries[i]);
			if (entry != null) {
				properties.put(entries[i], entry);
			}
		}
	}

	private void rememberManifestConversion(BundleDescription descriptor, Dictionary<String, String> manifest) {
		if (convertedManifests == null || !convertedManifests.contains(manifest))
			return;

		convertedManifests.remove(manifest);
		Properties bundleProperties = (Properties) descriptor.getUserObject();
		if (bundleProperties == null) {
			bundleProperties = new Properties();
			descriptor.setUserObject(bundleProperties);
		}
		bundleProperties.setProperty(PROPERTY_CONVERTED_MANIFEST, "marker"); //$NON-NLS-1$
	}

	private void mapVersionReplacedBundle(BundleDescription oldBundle, BundleDescription newBundle) {
		Properties bundleProperties = null;
		bundleProperties = (Properties) oldBundle.getUserObject();
		if (bundleProperties == null) {
			bundleProperties = new Properties();
			oldBundle.setUserObject(bundleProperties);
		}
		bundleProperties.setProperty(PROPERTY_VERSION_REPLACEMENT, String.valueOf(newBundle.getBundleId()));
	}

	private String fillPatchData(Dictionary<String, String> manifest) {
		if (BundleHelper.getManifestHeader(manifest, EXTENSIBLE_API) != null) {
			return EXTENSIBLE_API + ": true"; //$NON-NLS-1$
		}

		if (BundleHelper.getManifestHeader(manifest, PATCH_FRAGMENT) != null) {
			return PATCH_FRAGMENT + ": true"; //$NON-NLS-1$
		}
		return null;
	}

	private void loadPluginTagFile() {
		repositoryVersions = new Properties();
		try (InputStream input = new BufferedInputStream(new FileInputStream(AbstractScriptGenerator.getWorkingDirectory() + '/' + DEFAULT_PLUGIN_REPOTAG_FILENAME_DESCRIPTOR))) {
			repositoryVersions.load(input);
		} catch (IOException e) {
			//Ignore
		}
	}

	private void loadSourceReferences() {
		sourceReferences = new Properties();
		try (InputStream input = new BufferedInputStream(new FileInputStream(AbstractScriptGenerator.getWorkingDirectory() + '/' + DEFAULT_SOURCE_REFERENCES_FILENAME_DESCRIPTOR))) {
			sourceReferences.load(input);
		} catch (IOException e) {
			//Ignore
		}
	}

	public boolean addBundle(File bundleLocation) {
		Dictionary<String, String> manifest;
		manifest = loadManifest(bundleLocation);
		if (manifest == null) {
			return addFlexibleRoot(bundleLocation);
		}
		try {
			hasQualifier(bundleLocation, manifest);
		} catch (BundleException e) {
			//should not happen since we know the header
		}
		return addBundle(manifest, bundleLocation);
	}

	private boolean addFlexibleRoot(File bundleLocation) {
		if (!new File(bundleLocation, PDE_CORE_PREFS).exists())
			return false;

		try {
			Properties properties = AbstractScriptGenerator.readProperties(bundleLocation.getAbsolutePath(), PDE_CORE_PREFS, IStatus.OK);
			String root = properties.getProperty(BUNDLE_ROOT_PATH);
			if (root != null)
				return addBundle(new File(bundleLocation, root));
		} catch (CoreException e) {
			//ignore
		}
		return false;
	}

	private String updateVersionNumber(Dictionary<String, String> manifest) {
		String newVersion = null;
		String oldVersion = null;
		try {
			String symbolicName = BundleHelper.getManifestHeader(manifest, Constants.BUNDLE_SYMBOLICNAME);
			if (symbolicName == null)
				return null;

			symbolicName = ManifestElement.parseHeader(Constants.BUNDLE_SYMBOLICNAME, symbolicName)[0].getValue();
			oldVersion = BundleHelper.getManifestHeader(manifest, Constants.BUNDLE_VERSION);
			newVersion = QualifierReplacer.replaceQualifierInVersion(oldVersion, symbolicName, manifest.get(PROPERTY_QUALIFIER), repositoryVersions);
		} catch (BundleException e) {
			//ignore
		}
		if (newVersion != null)
			manifest.put(Constants.BUNDLE_VERSION, newVersion);
		return oldVersion;
	}

	/**
	 * @param bundleLocation
	 * @param manifest
	 * @throws BundleException
	 */
	private void hasQualifier(File bundleLocation, Dictionary<String, String> manifest) throws BundleException {
		ManifestElement[] versionInfo = ManifestElement.parseHeader(Constants.BUNDLE_VERSION, BundleHelper.getManifestHeader(manifest, Constants.BUNDLE_VERSION));
		if (versionInfo != null) {
			if (versionInfo[0].getValue().endsWith(PROPERTY_QUALIFIER)) {
				manifest.put(PROPERTY_QUALIFIER, getQualifierPropery(bundleLocation.getAbsolutePath()));
			}
		}
	}

	private String getQualifierPropery(String bundleLocation) {
		String qualifierInfo = null;
		try {
			qualifierInfo = AbstractScriptGenerator.readProperties(bundleLocation, IPDEBuildConstants.PROPERTIES_FILE, IStatus.INFO).getProperty(PROPERTY_QUALIFIER);
		} catch (CoreException e) {
			//ignore
		}
		if (qualifierInfo == null)
			qualifierInfo = PROPERTY_CONTEXT;
		return qualifierInfo;
	}

	//Return a dictionary representing a manifest. The data may result from plugin.xml conversion  
	private Dictionary<String, String> basicLoadManifest(File bundleLocation) {
		InputStream manifestStream = null;
		ZipFile jarFile = null;
		try {
			if ("jar".equalsIgnoreCase(new Path(bundleLocation.getName()).getFileExtension()) && bundleLocation.isFile()) { //$NON-NLS-1$
				jarFile = new ZipFile(bundleLocation, ZipFile.OPEN_READ);
				ZipEntry manifestEntry = jarFile.getEntry(JarFile.MANIFEST_NAME);
				if (manifestEntry != null) {
					manifestStream = jarFile.getInputStream(manifestEntry);
				}
			} else {
				manifestStream = new BufferedInputStream(new FileInputStream(new File(bundleLocation, JarFile.MANIFEST_NAME)));
			}
		} catch (IOException e) {
			//ignore
		}

		//It is not a manifest, but a plugin or a fragment
		if (manifestStream == null)
			return null;

		try {
			Hashtable<String, String> result = new Hashtable<>();
			result.putAll(ManifestElement.parseBundleManifest(manifestStream, null));
			return result;
		} catch (IOException ioe) {
			return null;
		} catch (BundleException e) {
			return null;
		} finally {
			try {
				manifestStream.close();
			} catch (IOException e1) {
				//Ignore
			}
			try {
				if (jarFile != null)
					jarFile.close();
			} catch (IOException e2) {
				//Ignore
			}
		}
	}

	private boolean enforceSymbolicName(File bundleLocation, Dictionary<String, String> initialManifest) {
		if (BundleHelper.getManifestHeader(initialManifest, Constants.BUNDLE_SYMBOLICNAME) != null)
			return true;

		return false;
	}

	private void enforceClasspath(Dictionary<String, String> manifest) {
		String classpath = BundleHelper.getManifestHeader(manifest, Constants.BUNDLE_CLASSPATH);
		if (classpath == null)
			manifest.put(Constants.BUNDLE_CLASSPATH, "."); //$NON-NLS-1$
	}

	private void enforceVersion(Dictionary<String, String> manifest) {
		String version = BundleHelper.getManifestHeader(manifest, Constants.BUNDLE_VERSION);
		if (version == null)
			manifest.put(Constants.BUNDLE_VERSION, "0.0.0"); //$NON-NLS-1$
	}

	private Dictionary<String, String> loadManifest(File bundleLocation) {
		Dictionary<String, String> manifest = basicLoadManifest(bundleLocation);
		if (manifest == null)
			return null;

		// require a Bundle-SymbolicName
		if (!enforceSymbolicName(bundleLocation, manifest))
			return null;
		enforceVersion(manifest);
		enforceClasspath(manifest);
		return manifest;
	}

	public void addBundles(Collection<File> bundles) {
		for (Iterator<File> iter = bundles.iterator(); iter.hasNext();) {
			File bundle = iter.next();
			addBundle(bundle);
		}
	}

	public void resolveState() {
		List<Config> configs = AbstractScriptGenerator.getConfigInfos();
		ArrayList<Dictionary<String, Object>> properties = new ArrayList<>(); //Collection of dictionaries
		Dictionary<String, Object> prop;

		// initialize profileManager and get the JRE profiles
		String[] javaProfiles = getJavaProfiles();
		String systemPackages = null;
		String ee = null;

		for (Iterator<Config> iter = configs.iterator(); iter.hasNext();) {
			Config aConfig = iter.next();
			prop = new Hashtable<>();
			if (AbstractScriptGenerator.getPropertyAsBoolean(RESOLVER_DEV_MODE))
				prop.put(PROPERTY_RESOLVER_MODE, VALUE_DEVELOPMENT);
			String os = aConfig.getOs();
			String ws = aConfig.getWs();
			String arch = aConfig.getArch();
			if (Config.ANY.equalsIgnoreCase(os))
				prop.put(OSGI_OS, CatchAllValue.singleton);
			else
				prop.put(OSGI_OS, os);

			if (Config.ANY.equalsIgnoreCase(ws))
				prop.put(OSGI_WS, CatchAllValue.singleton);
			else
				prop.put(OSGI_WS, ws);

			if (Config.ANY.equalsIgnoreCase(arch))
				prop.put(OSGI_ARCH, CatchAllValue.singleton);
			else
				prop.put(OSGI_ARCH, arch);

			// check the user-specified platform properties
			if (platformProperties != null) {
				for (Enumeration<Object> e = platformProperties.keys(); e.hasMoreElements();) {
					String key = (String) e.nextElement();
					prop.put(key, platformProperties.get(key));
				}
			}

			properties.add(prop);
		}

		Properties profileProps = null;
		boolean added = false;
		String eeJava9 = null;
		//javaProfiles are sorted, go in reverse order, and if when we hit 0 we haven't added any yet, 
		//then add that last profile so we have something.
		for (int j = javaProfiles.length - 1; j >= 0; j--) {
			// add a property set for each EE that is defined in the build.
			profileProps = profileManager.getProfileProperties(javaProfiles[j]);
			if (profileProps != null) {
				String profileName = profileProps.getProperty(ProfileManager.PROFILE_NAME);
				if (AbstractScriptGenerator.getImmutableAntProperty(profileName) != null || (j == 0 && !added)) {
					systemPackages = profileProps.getProperty(ProfileManager.SYSTEM_PACKAGES);
					ee = profileProps.getProperty(Constants.FRAMEWORK_EXECUTIONENVIRONMENT);

					prop = new Hashtable<>();
					prop.put(ProfileManager.SYSTEM_PACKAGES, systemPackages);
					if (profileName.equals("JavaSE-9")) { //$NON-NLS-1$
						eeJava9 = ee;
					}
					prop.put(Constants.FRAMEWORK_EXECUTIONENVIRONMENT, ee);
					properties.add(prop);
					added = true;
				}
			}
		}
		// from java 10 and beyond 
		ArrayList<String> eeJava10AndBeyond = new ArrayList<>();
		for (int i = 10; i <= LAST_SUPPORTED_JDK; i++) {
			eeJava10AndBeyond.add("JavaSE-" + i);//$NON-NLS-1$		
		}
		prop = new Hashtable<>();
		String previousEE = eeJava9;
		for (String execEnvID : eeJava10AndBeyond) {
			prop = new Hashtable<>();
			Properties javaProfilePropertiesForVMPackage = getJavaProfilePropertiesForVMPackage(execEnvID);
			if (javaProfilePropertiesForVMPackage != null) {
				systemPackages = javaProfilePropertiesForVMPackage.getProperty(Constants.FRAMEWORK_SYSTEMPACKAGES);
			}
			String currentEE = previousEE + "," + execEnvID; //$NON-NLS-1$
			if (systemPackages == null) {
				previousEE = currentEE;
				continue;
			}
			prop.put(ProfileManager.SYSTEM_PACKAGES, systemPackages);
			prop.put(Constants.FRAMEWORK_EXECUTIONENVIRONMENT, currentEE);
			previousEE = currentEE;
			properties.add(prop);
		}

		Dictionary<String, Object>[] stateProperties = properties.toArray(new Dictionary[properties.size()]);
		state.setPlatformProperties(stateProperties);
		state.resolve(false);

		if (unqualifiedBundles != null) {
			forceQualifiers();
		}
	}

	public State getState() {
		return state;
	}

	public BundleDescription[] getDependentBundles(String bundleId, Version version) {
		BundleDescription root = state.getBundle(bundleId, version);
		return getDependentBundles(root);
	}

	/**
	 * This methods return the bundleDescriptions to which imports have been
	 * bound to.
	 * 
	 * @param root
	 */
	public static BundleDescription[] getImportedBundles(BundleDescription root) {
		if (root == null)
			return new BundleDescription[0];
		ExportPackageDescription[] packages = root.getResolvedImports();
		ArrayList<BundleDescription> resolvedImports = new ArrayList<>(packages.length);
		for (int i = 0; i < packages.length; i++)
			if (!root.getLocation().equals(packages[i].getExporter().getLocation()) && !resolvedImports.contains(packages[i].getExporter()))
				resolvedImports.add(packages[i].getExporter());
		return resolvedImports.toArray(new BundleDescription[resolvedImports.size()]);
	}

	/**
	 * This methods return the bundleDescriptions to which required bundles
	 * have been bound to.
	 * 
	 * @param root
	 */
	public static BundleDescription[] getRequiredBundles(BundleDescription root) {
		if (root == null)
			return new BundleDescription[0];
		return root.getResolvedRequires();
	}

	public BundleDescription getResolvedBundle(String bundleId, String version) {
		return getBundle(bundleId, version, true);
	}

	public BundleDescription getBundle(String bundleId, String version, boolean resolved) {
		if (IPDEBuildConstants.GENERIC_VERSION_NUMBER.equals(version) || version == null) {
			BundleDescription bundle = getResolvedBundle(bundleId);
			if (bundle == null && !resolved)
				bundle = getState().getBundle(bundleId, null);
			return bundle;
		}
		Version parsedVersion = Version.parseVersion(version);
		BundleDescription description = getState().getBundle(bundleId, parsedVersion);
		if (description != null && (!resolved || description.isResolved()))
			return description;

		if (parsedVersion.getQualifier().indexOf(IBuildPropertiesConstants.PROPERTY_QUALIFIER) > -1) {
			BundleDescription[] bundles = sortByVersion(getState().getBundles(bundleId));
			VersionRange qualifierRange = Utils.createVersionRange(version);
			//bundles are sorted, start at the high end
			for (int i = bundles.length - 1; i >= 0; i--) {
				if (qualifierRange.isIncluded(bundles[i].getVersion()) && (!resolved || bundles[i].isResolved()))
					return bundles[i];
			}
		}
		return null;
	}

	/**
	 * Sort the BundleDescription[] by Version, lowest to highest.
	 * (It is likely they are already close to this order)
	 * @param bundles
	 * @return sorted BundleDescription []
	 */
	private BundleDescription[] sortByVersion(BundleDescription[] bundles) {
		if (bundles.length > 1) {
			Arrays.sort(bundles, new Comparator<BundleDescription>() {
				@Override
				public int compare(BundleDescription o1, BundleDescription o2) {
					return o1.getVersion().compareTo(o2.getVersion());
				}
			});
		}
		return bundles;
	}

	public BundleDescription getResolvedBundle(String bundleId) {
		BundleDescription[] description = sortByVersion(getState().getBundles(bundleId));
		if (description == null)
			return null;
		//bundles are sorted, start at the high end
		for (int i = description.length - 1; i >= 0; i--) {
			if (description[i].isResolved())
				return description[i];
		}
		return null;
	}

	public static BundleDescription[] getDependentBundles(BundleDescription root) {
		BundleDescription[] imported = getImportedBundles(root);
		BundleDescription[] required = getRequiredBundles(root);
		BundleDescription[] dependents = new BundleDescription[imported.length + required.length];
		System.arraycopy(imported, 0, dependents, 0, imported.length);
		System.arraycopy(required, 0, dependents, imported.length, required.length);
		return dependents;
	}

	public static BundleDescription[] getDependentBundlesWithFragments(BundleDescription root) {
		BundleDescription[] imported = getImportedBundles(root);
		BundleDescription[] importedByFragments = getImportedByFragments(root);
		BundleDescription[] required = getRequiredBundles(root);
		BundleDescription[] requiredByFragments = getRequiredByFragments(root);
		BundleDescription[] dependents = new BundleDescription[imported.length + importedByFragments.length + required.length + requiredByFragments.length];
		System.arraycopy(imported, 0, dependents, 0, imported.length);
		System.arraycopy(importedByFragments, 0, dependents, imported.length, importedByFragments.length);
		System.arraycopy(required, 0, dependents, imported.length + importedByFragments.length, required.length);
		System.arraycopy(requiredByFragments, 0, dependents, imported.length + importedByFragments.length + required.length, requiredByFragments.length);
		return dependents;
	}

	public static BundleDescription[] getImportedByFragments(BundleDescription root) {
		BundleDescription[] fragments = root.getFragments();
		List<BundleDescription> importedByFragments = new ArrayList<>();
		for (int i = 0; i < fragments.length; i++) {
			if (!fragments[i].isResolved())
				continue;
			merge(importedByFragments, getImportedBundles(fragments[i]));
		}
		BundleDescription[] result = new BundleDescription[importedByFragments.size()];
		return importedByFragments.toArray(result);
	}

	public static BundleDescription[] getRequiredByFragments(BundleDescription root) {
		BundleDescription[] fragments = root.getFragments();
		List<BundleDescription> importedByFragments = new ArrayList<>();
		for (int i = 0; i < fragments.length; i++) {
			if (!fragments[i].isResolved())
				continue;
			merge(importedByFragments, getRequiredBundles(fragments[i]));
		}
		BundleDescription[] result = new BundleDescription[importedByFragments.size()];
		return importedByFragments.toArray(result);
	}

	public static void merge(List<BundleDescription> source, BundleDescription[] toAdd) {
		for (int i = 0; i < toAdd.length; i++) {
			if (!source.contains(toAdd[i]))
				source.add(toAdd[i]);
		}
	}

	public Properties loadPropertyFileIn(Map<String, String> toMerge, File location) {
		Properties result = new Properties();
		result.putAll(toMerge);
		try (InputStream propertyStream = new BufferedInputStream(new FileInputStream(new File(location, PROPERTIES_FILE)))) {
			result.load(propertyStream);
		} catch (IOException e) {
			//ignore because compiled plug-ins do not have such files
		}
		return result;
	}

	public HashMap<Long, String[]> getExtraData() {
		return bundleClasspaths;
	}

	public Map<Long, String> getPatchData() {
		return patchBundles;
	}

	public List<BundleDescription> getSortedBundles() {
		if (lastSortingDate != getState().getTimeStamp()) {
			lastSortingDate = getState().getTimeStamp();
			BundleDescription[] toSort = getState().getResolvedBundles();
			Platform.getPlatformAdmin().getStateHelper().sortBundles(toSort);
			sortedBundles = Arrays.asList(toSort);
		}
		return sortedBundles;
	}

	public void cleanupOriginalState() {
		if (addedBundle == null && unqualifiedBundles == null)
			return;

		for (Iterator<BundleDescription> iter = addedBundle.iterator(); iter.hasNext();) {
			BundleDescription added = iter.next();
			state.removeBundle(added);
		}
		addedBundle.clear();

		for (Iterator<BundleDescription> iter = unqualifiedBundles.iterator(); iter.hasNext();) {
			BundleDescription toAddBack = iter.next();
			state.removeBundle(toAddBack.getBundleId());
			addBundleDescription(toAddBack);
		}
		unqualifiedBundles.clear();

		BundleDescription[] allBundles = state.getBundles();
		for (int i = 0; i < allBundles.length; i++) {
			allBundles[i].setUserObject(null);
		}
		state.resolve();
	}

	private File getOSGiLocation() {
		BundleDescription osgiBundle = state.getBundle(BUNDLE_OSGI, null);
		if (osgiBundle == null)
			return null;
		return new File(osgiBundle.getLocation());
	}

	private String[] getJavaProfiles() {
		return getProfileManager().getJavaProfiles();
	}

	//Replace the version numbers that ends with .qualifier
	private void forceQualifiers() {
		BundleDescription[] resolvedBundles = state.getResolvedBundles(); //We only get the resolved bundles since, changing the qualifier should not change the resolution state 
		for (int i = 0; i < resolvedBundles.length; i++) {
			if (resolvedBundles[i].getVersion().getQualifier().endsWith(PROPERTY_QUALIFIER)) {
				BundleDescription b = resolvedBundles[i];
				unqualifiedBundles.add(state.removeBundle(b.getBundleId())); //We keep the removed bundle so we can reinsert it in the state when we are done
				String newVersion = QualifierReplacer.replaceQualifierInVersion(b.getVersion().toString(), b.getSymbolicName(), getQualifierPropery(b.getLocation()), null);

				//Here it is important to reuse the same bundle id than the bundle we are removing so that we don't loose the information about the classpath
				BundleDescription newBundle = state.getFactory().createBundleDescription(b.getBundleId(), b.getSymbolicName(), new Version(newVersion), b.getLocation(), b.getRequiredBundles(), b.getHost(), b.getImportPackages(), b.getExportPackages(), b.isSingleton(), b.attachFragments(), b.dynamicFragments(), b.getPlatformFilter(), b.getExecutionEnvironments(), b.getGenericRequires(), b.getGenericCapabilities(), b.getNativeCodeSpecification());
				addBundleDescription(newBundle);
				rememberQualifierTagPresence(newBundle);
				mapVersionReplacedBundle(b, newBundle);
			}
		}
		state.resolve();
	}

	/*
	 * If this bundle had its qualifier version replaced, return the replacement bundle description
	 * return the original bundle if no replacement occurred
	 */
	public BundleDescription getVersionReplacement(BundleDescription bundle) {
		Properties props = (Properties) bundle.getUserObject();
		if (props == null)
			return bundle;
		String idString = props.getProperty(PROPERTY_VERSION_REPLACEMENT);
		if (idString == null)
			return bundle;
		try {
			long newId = Long.parseLong(idString);
			BundleDescription newBundle = state.getBundle(newId);
			if (newBundle != null)
				return newBundle;
		} catch (NumberFormatException e) {
			// fall through
		}
		return bundle;
	}

	public void setPlatformProperties(Properties platformProperties) {
		this.platformProperties = platformProperties;
	}

	public void setEESources(String[] eeSources) {
		this.eeSources = eeSources;
	}

	public ProfileManager getProfileManager() {
		if (profileManager == null) {
			File osgi = getOSGiLocation();
			String[] sources = null;
			if (osgi != null) {
				if (eeSources != null) {
					sources = new String[eeSources.length + 1];
					sources[0] = osgi.getAbsolutePath();
					System.arraycopy(eeSources, 0, sources, 1, eeSources.length);
				} else {
					sources = new String[] {osgi.getAbsolutePath()};
				}
				profileManager = new ProfileManager(sources, false);
			} else {
				profileManager = new ProfileManager(eeSources, true);
			}
		}
		return profileManager;
	}

	private static Properties getJavaProfilePropertiesForVMPackage(String ee) {
		Bundle apitoolsBundle = Platform.getBundle("org.eclipse.pde.api.tools"); //$NON-NLS-1$
		if (apitoolsBundle == null) {
			return null;
		}
		URL systemPackageProfile = apitoolsBundle.getEntry("system_packages" + '/' + ee.replace('/', '_') + "-systempackages.profile"); //$NON-NLS-1$ //$NON-NLS-2$
		if (systemPackageProfile != null) {
			return getPropertiesFromURL(systemPackageProfile);

		}
		return null;
	}

	private static Properties getPropertiesFromURL(URL profileURL) {
		InputStream is = null;
		try {
			profileURL = FileLocator.resolve(profileURL);
			URLConnection openConnection = profileURL.openConnection();
			openConnection.setUseCaches(false);
			is = openConnection.getInputStream();
			if (is != null) {
				Properties profile = new Properties();
				profile.load(is);
				return profile;
			}
		} catch (IOException e) {
			// nothing to do
		} finally {
			try {
				if (is != null) {
					is.close();
				}
			} catch (IOException e) {
				// nothing to do
			}
		}
		return null;
	}
}
