/*******************************************************************************
 * Copyright (c) 2008, 2017 Code 9 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:
 *   Code 9 - initial API and implementation
 *   IBM - ongoing development
 *   SAP AG - make optional dependencies non-greedy by default; allow setting greedy through directive (bug 247099)
 *   Red Hat Inc. - Bug 460967 
 ******************************************************************************/
package org.eclipse.equinox.p2.publisher.eclipse;

import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;

import java.io.*;
import java.util.*;
import java.util.Map.Entry;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.eclipse.core.runtime.*;
import org.eclipse.equinox.frameworkadmin.BundleInfo;
import org.eclipse.equinox.internal.p2.core.helpers.LogHelper;
import org.eclipse.equinox.internal.p2.metadata.ArtifactKey;
import org.eclipse.equinox.internal.p2.publisher.Messages;
import org.eclipse.equinox.internal.p2.publisher.eclipse.GeneratorBundleInfo;
import org.eclipse.equinox.p2.metadata.*;
import org.eclipse.equinox.p2.metadata.MetadataFactory.InstallableUnitDescription;
import org.eclipse.equinox.p2.metadata.MetadataFactory.InstallableUnitFragmentDescription;
import org.eclipse.equinox.p2.metadata.VersionRange;
import org.eclipse.equinox.p2.metadata.expression.IMatchExpression;
import org.eclipse.equinox.p2.publisher.*;
import org.eclipse.equinox.p2.publisher.actions.*;
import org.eclipse.equinox.p2.query.IQueryResult;
import org.eclipse.equinox.p2.repository.artifact.IArtifactDescriptor;
import org.eclipse.equinox.p2.repository.artifact.IArtifactRepository;
import org.eclipse.equinox.spi.p2.publisher.LocalizationHelper;
import org.eclipse.equinox.spi.p2.publisher.PublisherHelper;
import org.eclipse.osgi.framework.util.Headers;
import org.eclipse.osgi.service.resolver.*;
import org.eclipse.osgi.util.ManifestElement;
import org.eclipse.osgi.util.NLS;
import org.eclipse.pde.internal.publishing.Activator;
import org.osgi.framework.BundleException;
import org.osgi.framework.Constants;
import org.osgi.framework.wiring.BundleRequirement;
import org.osgi.resource.Namespace;

/**
 * Publish IUs for all of the bundles in a given set of locations or described by a set of
 * bundle descriptions.  The locations can be actual locations of the bundles or folders
 * of bundles.
 *
 * This action consults the following types of advice:
 * </ul>
 * <li>{@link IAdditionalInstallableUnitAdvice }</li>
 * <li>{@link IBundleShapeAdvice}</li>
 * <li>{@link ICapabilityAdvice}</li>
 * <li>{@link IPropertyAdvice}</li>
 * <li>{@link ITouchpointAdvice}</li>
 * </ul>
 */
@SuppressWarnings("restriction")
public class BundlesAction extends AbstractPublisherAction {

	/**
	 * A capability name in the {@link PublisherHelper#NAMESPACE_ECLIPSE_TYPE} namespace
	 * representing and OSGi bundle resource
	 * @see IProvidedCapability#getName()
	 */
	public static final String TYPE_ECLIPSE_BUNDLE = "bundle"; //$NON-NLS-1$

	/**
	 * A capability name in the {@link PublisherHelper#NAMESPACE_ECLIPSE_TYPE} namespace
	 * representing a source bundle
	 * @see IProvidedCapability#getName()
	 */
	public static final String TYPE_ECLIPSE_SOURCE = "source"; //$NON-NLS-1$

	public static final String OSGI_BUNDLE_CLASSIFIER = "osgi.bundle"; //$NON-NLS-1$
	public static final String CAPABILITY_NS_OSGI_BUNDLE = "osgi.bundle"; //$NON-NLS-1$
	public static final String CAPABILITY_NS_OSGI_FRAGMENT = "osgi.fragment"; //$NON-NLS-1$

	public static final IProvidedCapability BUNDLE_CAPABILITY = MetadataFactory.createProvidedCapability(PublisherHelper.NAMESPACE_ECLIPSE_TYPE, TYPE_ECLIPSE_BUNDLE, Version.createOSGi(1, 0, 0));
	public static final IProvidedCapability SOURCE_BUNDLE_CAPABILITY = MetadataFactory.createProvidedCapability(PublisherHelper.NAMESPACE_ECLIPSE_TYPE, TYPE_ECLIPSE_SOURCE, Version.createOSGi(1, 0, 0));

	static final String DEFAULT_BUNDLE_LOCALIZATION = "OSGI-INF/l10n/bundle"; //$NON-NLS-1$

	private static final String[] BUNDLE_IU_PROPERTY_MAP = {Constants.BUNDLE_NAME, IInstallableUnit.PROP_NAME, Constants.BUNDLE_DESCRIPTION, IInstallableUnit.PROP_DESCRIPTION, Constants.BUNDLE_VENDOR, IInstallableUnit.PROP_PROVIDER, Constants.BUNDLE_CONTACTADDRESS, IInstallableUnit.PROP_CONTACT, Constants.BUNDLE_DOCURL, IInstallableUnit.PROP_DOC_URL, Constants.BUNDLE_UPDATELOCATION, IInstallableUnit.PROP_BUNDLE_LOCALIZATION, Constants.BUNDLE_LOCALIZATION, IInstallableUnit.PROP_BUNDLE_LOCALIZATION};
	public static final int BUNDLE_LOCALIZATION_INDEX = PublisherHelper.BUNDLE_LOCALIZED_PROPERTIES.length - 1;
	public static final String DIR = "dir"; //$NON-NLS-1$
	public static final String JAR = "jar"; //$NON-NLS-1$
	public static final String BUNDLE_SHAPE = "Eclipse-BundleShape"; //$NON-NLS-1$

	/**
	 * Manifest header directive for specifying how optional runtime 
	 * requirements shall be handled during installation.
	 * 
	 * @see #INSTALLATION_GREEDY
	 */
	public static final String INSTALLATION_DIRECTIVE = "x-installation"; //$NON-NLS-1$

	/** 
	 * Value for {@link #INSTALLATION_DIRECTIVE} indicating that an optional 
	 * requirement shall be installed unless this is prevented by other 
	 * mandatory requirements. Optional requirements without this directive 
	 * value are ignored during installation.
	 */
	public static final String INSTALLATION_GREEDY = "greedy"; //$NON-NLS-1$

	private File[] locations;
	private BundleDescription[] bundles;
	protected MultiStatus finalStatus;

	public static IArtifactKey createBundleArtifactKey(String bsn, String version) {
		return new ArtifactKey(OSGI_BUNDLE_CLASSIFIER, bsn, Version.parseVersion(version));
	}

	public static IInstallableUnit createBundleConfigurationUnit(String hostId, Version cuVersion, boolean isBundleFragment, GeneratorBundleInfo configInfo, String configurationFlavor, IMatchExpression<IInstallableUnit> filter) {
		if (configInfo == null)
			return null;

		InstallableUnitFragmentDescription cu = new InstallableUnitFragmentDescription();
		String configUnitId = configurationFlavor + hostId;
		cu.setId(configUnitId);
		cu.setVersion(cuVersion);

		//Indicate the IU to which this CU apply
		Version hostVersion = Version.parseVersion(configInfo.getVersion());
		VersionRange range = hostVersion == Version.emptyVersion ? VersionRange.emptyRange : new VersionRange(hostVersion, true, Version.MAX_VERSION, true);
		cu.setHost(new IRequirement[] { //
				MetadataFactory.createRequirement(CAPABILITY_NS_OSGI_BUNDLE, hostId, range, null, false, false, true), //
				MetadataFactory.createRequirement(PublisherHelper.NAMESPACE_ECLIPSE_TYPE, TYPE_ECLIPSE_BUNDLE, new VersionRange(Version.createOSGi(1, 0, 0), true, Version.createOSGi(2, 0, 0), false), null, false, false, false)});

		//Adds capabilities for fragment, self, and describing the flavor supported
		cu.setProperty(InstallableUnitDescription.PROP_TYPE_FRAGMENT, Boolean.TRUE.toString());
		cu.setCapabilities(new IProvidedCapability[] {PublisherHelper.createSelfCapability(configUnitId, cuVersion), MetadataFactory.createProvidedCapability(PublisherHelper.NAMESPACE_FLAVOR, configurationFlavor, Version.createOSGi(1, 0, 0))});

		Map<String, String> touchpointData = new HashMap<>();
		touchpointData.put("install", "installBundle(bundle:${artifact})"); //$NON-NLS-1$ //$NON-NLS-2$
		touchpointData.put("uninstall", "uninstallBundle(bundle:${artifact})"); //$NON-NLS-1$ //$NON-NLS-2$
		touchpointData.put("configure", createConfigScript(configInfo, isBundleFragment)); //$NON-NLS-1$
		touchpointData.put("unconfigure", createUnconfigScript(configInfo, isBundleFragment)); //$NON-NLS-1$
		cu.addTouchpointData(MetadataFactory.createTouchpointData(touchpointData));
		cu.setFilter(filter);
		return MetadataFactory.createInstallableUnit(cu);
	}

	public static IInstallableUnit createBundleIU(BundleDescription bd, IArtifactKey key, IPublisherInfo info) {
		return new BundlesAction(new BundleDescription[] {bd}).doCreateBundleIU(bd, key, info);
	}

	protected IInstallableUnit doCreateBundleIU(BundleDescription bd, IArtifactKey key, IPublisherInfo info) {
		@SuppressWarnings("unchecked")
		Map<String, String> manifest = (Map<String, String>) bd.getUserObject();

		Map<Locale, Map<String, String>> manifestLocalizations = null;
		if (manifest != null && bd.getLocation() != null) {
			manifestLocalizations = getManifestLocalizations(manifest, new File(bd.getLocation()));
		}

		InstallableUnitDescription iu = new MetadataFactory.InstallableUnitDescription();
		iu.setSingleton(bd.isSingleton());
		iu.setId(bd.getSymbolicName());
		iu.setVersion(PublisherHelper.fromOSGiVersion(bd.getVersion()));
		iu.setFilter(bd.getPlatformFilter());
		iu.setUpdateDescriptor(MetadataFactory.createUpdateDescriptor(bd.getSymbolicName(), computeUpdateRange(bd.getVersion()), IUpdateDescriptor.NORMAL, null));
		iu.setArtifacts(new IArtifactKey[] {key});
		iu.setTouchpointType(PublisherHelper.TOUCHPOINT_OSGI);

		boolean isFragment = (bd.getHost() != null);

		// Gather requirements here
		List<IRequirement> requirements = new ArrayList<>();

		// Process required fragment host
		if (isFragment) {
			requirements.add(MetadataFactory.createRequirement(CAPABILITY_NS_OSGI_BUNDLE, bd.getHost().getName(), PublisherHelper.fromOSGiVersionRange(bd.getHost().getVersionRange()), null, false, false));
		}

		// Process required bundles
		ManifestElement[] rawRequireBundleHeader = parseManifestHeader(Constants.REQUIRE_BUNDLE, manifest, bd.getLocation());
		for (BundleSpecification requiredBundle : bd.getRequiredBundles()) {
			addRequireBundleRequirement(requirements, requiredBundle, rawRequireBundleHeader);
		}

		// Process the import packages
		ManifestElement[] rawImportPackageHeader = parseManifestHeader(Constants.IMPORT_PACKAGE, manifest, bd.getLocation());
		for (ImportPackageSpecification importedPackage : bd.getImportPackages()) {
			if (!isDynamicImport(importedPackage)) {
				addImportPackageRequirement(requirements, importedPackage, rawImportPackageHeader);
			}
		}

		// Process generic requirements
		ManifestElement[] rawRequireCapHeader = parseManifestHeader(Constants.REQUIRE_CAPABILITY, manifest, bd.getLocation());
		for (GenericSpecification requiredCap : bd.getGenericRequires()) {
			addRequirement(requirements, requiredCap, rawRequireCapHeader);
		}

		iu.setRequirements(requirements.toArray(new IRequirement[requirements.size()]));

		// Create set of provided capabilities
		List<IProvidedCapability> providedCapabilities = new ArrayList<>();

		// Add identification capabilities
		providedCapabilities.add(PublisherHelper.createSelfCapability(bd.getSymbolicName(), PublisherHelper.fromOSGiVersion(bd.getVersion())));
		providedCapabilities.add(MetadataFactory.createProvidedCapability(CAPABILITY_NS_OSGI_BUNDLE, bd.getSymbolicName(), PublisherHelper.fromOSGiVersion(bd.getVersion())));

		// Process exported packages
		for (ExportPackageDescription packageExport : bd.getExportPackages()) {
			providedCapabilities.add(MetadataFactory.createProvidedCapability(PublisherHelper.CAPABILITY_NS_JAVA_PACKAGE, packageExport.getName(), PublisherHelper.fromOSGiVersion(packageExport.getVersion())));
		}

		// Process generic capabilities

		// TODO 
		// IProvidedCapability may have to be extended to contain the OSGi directives as well which may be needed for 
		// Bug 360659, Bug 525368. E.g. with IProvidedCapability.getDirectives()

		// TODO
		// It may be possible map the "osgi.identity" capability to elements of the IU like the id, the license, etc.
		// It may be better to derive it at runtime.

		int capNo = 0;
		for (GenericDescription genericCap : bd.getGenericCapabilities()) {
			addCapability(providedCapabilities, genericCap, iu, capNo);
			capNo++;
		}

		// Add capability to describe the type of bundle
		if (manifest != null && manifest.containsKey("Eclipse-SourceBundle")) { //$NON-NLS-1$
			providedCapabilities.add(SOURCE_BUNDLE_CAPABILITY);
		} else {
			providedCapabilities.add(BUNDLE_CAPABILITY);
		}

		// If needed add an additional capability to identify this as an OSGi fragment
		if (isFragment) {
			providedCapabilities.add(MetadataFactory.createProvidedCapability(CAPABILITY_NS_OSGI_FRAGMENT, bd.getHost().getName(), PublisherHelper.fromOSGiVersion(bd.getVersion())));
		}

		if (manifestLocalizations != null) {
			for (Entry<Locale, Map<String, String>> locEntry : manifestLocalizations.entrySet()) {
				Locale locale = locEntry.getKey();
				Map<String, String> translatedStrings = locEntry.getValue();
				for (Entry<String, String> entry : translatedStrings.entrySet()) {
					iu.setProperty(locale.toString() + '.' + entry.getKey(), entry.getValue());
				}
				providedCapabilities.add(PublisherHelper.makeTranslationCapability(bd.getSymbolicName(), locale));
			}
		}

		iu.setCapabilities(providedCapabilities.toArray(new IProvidedCapability[providedCapabilities.size()]));

		// Process advice
		processUpdateDescriptorAdvice(iu, info);
		processCapabilityAdvice(iu, info);

		// Set certain properties from the manifest header attributes as IU properties.
		// The values of these attributes may be localized (strings starting with '%')
		// with the translated values appearing in the localization IU fragments
		// associated with the bundle IU.
		if (manifest != null) {
			int i = 0;
			while (i < BUNDLE_IU_PROPERTY_MAP.length) {
				if (manifest.containsKey(BUNDLE_IU_PROPERTY_MAP[i])) {
					String value = manifest.get(BUNDLE_IU_PROPERTY_MAP[i]);
					if (value != null && value.length() > 0) {
						iu.setProperty(BUNDLE_IU_PROPERTY_MAP[i + 1], value);
					}
				}
				i += 2;
			}
		}

		// Define the immutable metadata for this IU. In this case immutable means
		// that this is something that will not impact the configuration.
		Map<String, String> touchpointData = new HashMap<>();
		touchpointData.put("manifest", toManifestString(manifest)); //$NON-NLS-1$
		if (isDir(bd, info)) {
			touchpointData.put("zipped", "true"); //$NON-NLS-1$ //$NON-NLS-2$
		}

		// Process more advice
		processTouchpointAdvice(iu, touchpointData, info);
		processInstallableUnitPropertiesAdvice(iu, info);

		return MetadataFactory.createInstallableUnit(iu);
	}

	protected void addImportPackageRequirement(List<IRequirement> reqsDeps, ImportPackageSpecification importSpec, ManifestElement[] rawImportPackageHeader) {
		VersionRange versionRange = PublisherHelper.fromOSGiVersionRange(importSpec.getVersionRange());
		final boolean optional = isOptional(importSpec);
		final boolean greedy;
		if (optional) {
			greedy = INSTALLATION_GREEDY.equals(getInstallationDirective(importSpec.getName(), rawImportPackageHeader));
		} else {
			greedy = true;
		}
		//TODO this needs to be refined to take into account all the attribute handled by imports
		reqsDeps.add(MetadataFactory.createRequirement(PublisherHelper.CAPABILITY_NS_JAVA_PACKAGE, importSpec.getName(), versionRange, null, optional, false, greedy));
	}

	protected void addRequireBundleRequirement(List<IRequirement> reqsDeps, BundleSpecification requiredBundle, ManifestElement[] rawRequireBundleHeader) {
		final boolean optional = requiredBundle.isOptional();
		final boolean greedy;
		if (optional) {
			greedy = INSTALLATION_GREEDY.equals(getInstallationDirective(requiredBundle.getName(), rawRequireBundleHeader));
		} else {
			greedy = true;
		}
		reqsDeps.add(MetadataFactory.createRequirement(CAPABILITY_NS_OSGI_BUNDLE, requiredBundle.getName(), PublisherHelper.fromOSGiVersionRange(requiredBundle.getVersionRange()), null, optional ? 0 : 1, 1, greedy));
	}

	// TODO Handle the "effective:=" directive somehow?
	protected void addRequirement(List<IRequirement> reqsDeps, GenericSpecification requireCapSpec, ManifestElement[] rawRequireCapabilities) {
		BundleRequirement req = requireCapSpec.getRequirement();

		String namespace = req.getNamespace();
		Map<String, String> directives = req.getDirectives();

		String capFilter = directives.get(Namespace.REQUIREMENT_FILTER_DIRECTIVE);
		boolean optional = directives.get(Namespace.REQUIREMENT_RESOLUTION_DIRECTIVE) == Namespace.RESOLUTION_OPTIONAL;
		boolean greedy = optional
				? INSTALLATION_GREEDY.equals(directives.get(INSTALLATION_DIRECTIVE))
				: true;

		IRequirement requireCap = MetadataFactory.createRequirement(namespace, capFilter, null, optional ? 0 : 1, 1, greedy);
		reqsDeps.add(requireCap);
	}

	protected void addCapability(List<IProvidedCapability> caps, GenericDescription provideCapDesc, InstallableUnitDescription iu, int capNo) {
		// Convert the values to String, Version, List of String or Version
		Map<String, Object> capAttrs = provideCapDesc.getDeclaredAttributes()
				.entrySet()
				.stream()
				.collect(toMap(Entry::getKey, e -> convertAttribute(e.getValue())));

		// Resolve the namespace
		String capNs = provideCapDesc.getType();

		// Resolve the mandatory p2 name
		// By convention OSGi capabilities have an attribute named like the capability namespace.
		// If this is not the case synthesize a unique name (e.g. "osgi.service" has an "objectClass" attribute instead).
		// TODO If present but not a String log a warning somehow that it is ignored? Or fail the publication?
		capAttrs.compute(
				capNs,
				(k, v) -> (v instanceof String) ? v : String.format("%s_%s-%s", iu.getId(), iu.getVersion(), capNo)); //$NON-NLS-1$

		// Resolve the mandatory p2 version
		// By convention versioned OSGi capabilities have a "version" attribute containing the OSGi Version object
		// If this is not the case use an empty version (e.g. "osgi.ee" has a list of versions).
		// TODO If present but not a Version log a warning somehow that it is ignored? Or fail the publication?
		capAttrs.compute(
				IProvidedCapability.PROPERTY_VERSION,
				(k, v) -> (v instanceof Version) ? v : Version.emptyVersion);

		caps.add(MetadataFactory.createProvidedCapability(capNs, capAttrs));
	}

	private Object convertAttribute(Object attr) {
		if (attr instanceof Collection<?>) {
			return ((Collection<?>) attr).stream().map(this::convertScalarAttribute).collect(toList());
		}
		return convertScalarAttribute(attr);
	}

	private Object convertScalarAttribute(Object attr) {
		if (attr instanceof org.osgi.framework.Version) {
			org.osgi.framework.Version osgiVer = (org.osgi.framework.Version) attr;
			return Version.createOSGi(osgiVer.getMajor(), osgiVer.getMinor(), osgiVer.getMicro(), osgiVer.getQualifier());
		}
		return attr.toString();
	}

	static VersionRange computeUpdateRange(org.osgi.framework.Version base) {
		VersionRange updateRange = null;
		if (!base.equals(org.osgi.framework.Version.emptyVersion)) {
			updateRange = new VersionRange(Version.emptyVersion, true, PublisherHelper.fromOSGiVersion(base), false);
		} else {
			updateRange = VersionRange.emptyRange;
		}
		return updateRange;
	}

	private IInstallableUnitFragment createHostLocalizationFragment(IInstallableUnit bundleIU, BundleDescription bd, String hostId, String[] hostBundleManifestValues) {
		Map<Locale, Map<String, String>> hostLocalizations = getHostLocalizations(new File(bd.getLocation()), hostBundleManifestValues);
		if (hostLocalizations == null || hostLocalizations.isEmpty())
			return null;
		return createLocalizationFragmentOfHost(bd, hostId, hostBundleManifestValues, hostLocalizations);
	}

	/*
	 * @param hostId
	 * @param bd
	 * @param locale
	 * @param localizedStrings
	 * @return installableUnitFragment
	 */
	private static IInstallableUnitFragment createLocalizationFragmentOfHost(BundleDescription bd, String hostId, String[] hostManifestValues, Map<Locale, Map<String, String>> hostLocalizations) {
		InstallableUnitFragmentDescription fragment = new MetadataFactory.InstallableUnitFragmentDescription();
		String fragmentId = makeHostLocalizationFragmentId(bd.getSymbolicName());
		fragment.setId(fragmentId);
		fragment.setVersion(PublisherHelper.fromOSGiVersion(bd.getVersion())); // TODO: is this a meaningful version?

		HostSpecification hostSpec = bd.getHost();
		IRequirement[] hostReqs = new IRequirement[] {MetadataFactory.createRequirement(IInstallableUnit.NAMESPACE_IU_ID, hostSpec.getName(), PublisherHelper.fromOSGiVersionRange(hostSpec.getVersionRange()), null, false, false, false)};
		fragment.setHost(hostReqs);

		fragment.setSingleton(true);
		fragment.setProperty(InstallableUnitDescription.PROP_TYPE_FRAGMENT, Boolean.TRUE.toString());

		// Create a provided capability for each locale and add the translated properties.
		ArrayList<IProvidedCapability> providedCapabilities = new ArrayList<>(hostLocalizations.keySet().size());
		providedCapabilities.add(PublisherHelper.createSelfCapability(fragmentId, fragment.getVersion()));
		for (Entry<Locale, Map<String, String>> localeEntry : hostLocalizations.entrySet()) {
			Locale locale = localeEntry.getKey();
			Map<String, String> translatedStrings = localeEntry.getValue();
			for (Entry<String, String> entry : translatedStrings.entrySet()) {
				fragment.setProperty(locale.toString() + '.' + entry.getKey(), entry.getValue());
			}
			providedCapabilities.add(PublisherHelper.makeTranslationCapability(hostId, locale));
		}
		fragment.setCapabilities(providedCapabilities.toArray(new IProvidedCapability[providedCapabilities.size()]));

		return MetadataFactory.createInstallableUnitFragment(fragment);
	}

	/**
	 * @param id
	 * @return the id for the iu fragment containing localized properties
	 * 		   for the fragment with the given id.
	 */
	private static String makeHostLocalizationFragmentId(String id) {
		return id + ".translated_host_properties"; //$NON-NLS-1$
	}

	private static String createConfigScript(GeneratorBundleInfo configInfo, boolean isBundleFragment) {
		if (configInfo == null)
			return ""; //$NON-NLS-1$

		String configScript = "";//$NON-NLS-1$
		if (!isBundleFragment && configInfo.getStartLevel() != BundleInfo.NO_LEVEL) {
			configScript += "setStartLevel(startLevel:" + configInfo.getStartLevel() + ");"; //$NON-NLS-1$ //$NON-NLS-2$
		}
		if (!isBundleFragment && configInfo.isMarkedAsStarted()) {
			configScript += "markStarted(started: true);"; //$NON-NLS-1$
		}

		if (configInfo.getSpecialConfigCommands() != null) {
			configScript += configInfo.getSpecialConfigCommands();
		}

		return configScript;
	}

	private static String createDefaultBundleConfigScript(GeneratorBundleInfo configInfo) {
		return createConfigScript(configInfo, false);
	}

	public static IInstallableUnit createDefaultBundleConfigurationUnit(GeneratorBundleInfo configInfo, GeneratorBundleInfo unconfigInfo, String configurationFlavor) {
		InstallableUnitFragmentDescription cu = new InstallableUnitFragmentDescription();
		String configUnitId = PublisherHelper.createDefaultConfigUnitId(OSGI_BUNDLE_CLASSIFIER, configurationFlavor);
		cu.setId(configUnitId);
		Version configUnitVersion = Version.createOSGi(1, 0, 0);
		cu.setVersion(configUnitVersion);

		// Add capabilities for fragment, self, and describing the flavor supported
		cu.setProperty(InstallableUnitDescription.PROP_TYPE_FRAGMENT, Boolean.TRUE.toString());
		cu.setCapabilities(new IProvidedCapability[] {PublisherHelper.createSelfCapability(configUnitId, configUnitVersion), MetadataFactory.createProvidedCapability(PublisherHelper.NAMESPACE_FLAVOR, configurationFlavor, Version.createOSGi(1, 0, 0))});

		// Create a required capability on bundles
		IRequirement[] reqs = new IRequirement[] {MetadataFactory.createRequirement(PublisherHelper.NAMESPACE_ECLIPSE_TYPE, TYPE_ECLIPSE_BUNDLE, VersionRange.emptyRange, null, false, true, false)};
		cu.setHost(reqs);
		Map<String, String> touchpointData = new HashMap<>();

		touchpointData.put("install", "installBundle(bundle:${artifact})"); //$NON-NLS-1$ //$NON-NLS-2$
		touchpointData.put("uninstall", "uninstallBundle(bundle:${artifact})"); //$NON-NLS-1$ //$NON-NLS-2$
		touchpointData.put("configure", createDefaultBundleConfigScript(configInfo)); //$NON-NLS-1$
		touchpointData.put("unconfigure", createDefaultBundleUnconfigScript(unconfigInfo)); //$NON-NLS-1$

		cu.addTouchpointData(MetadataFactory.createTouchpointData(touchpointData));
		return MetadataFactory.createInstallableUnit(cu);
	}

	private static String createDefaultBundleUnconfigScript(GeneratorBundleInfo unconfigInfo) {
		return createUnconfigScript(unconfigInfo, false);
	}

	private static String createUnconfigScript(GeneratorBundleInfo unconfigInfo, boolean isBundleFragment) {
		if (unconfigInfo == null)
			return ""; //$NON-NLS-1$
		String unconfigScript = "";//$NON-NLS-1$
		if (!isBundleFragment && unconfigInfo.getStartLevel() != BundleInfo.NO_LEVEL) {
			unconfigScript += "setStartLevel(startLevel:" + BundleInfo.NO_LEVEL + ");"; //$NON-NLS-1$ //$NON-NLS-2$
		}
		if (!isBundleFragment && unconfigInfo.isMarkedAsStarted()) {
			unconfigScript += "markStarted(started: false);"; //$NON-NLS-1$
		}

		if (unconfigInfo.getSpecialUnconfigCommands() != null) {
			unconfigScript += unconfigInfo.getSpecialUnconfigCommands();
		}
		return unconfigScript;
	}

	private static boolean isDynamicImport(ImportPackageSpecification importedPackage) {
		return importedPackage.getDirective(Constants.RESOLUTION_DIRECTIVE).equals(ImportPackageSpecification.RESOLUTION_DYNAMIC);
	}

	protected static boolean isOptional(ImportPackageSpecification importedPackage) {
		return importedPackage.getDirective(Constants.RESOLUTION_DIRECTIVE).equals(ImportPackageSpecification.RESOLUTION_OPTIONAL);
	}

	private static String toManifestString(Map<String, String> p) {
		if (p == null)
			return null;
		StringBuffer result = new StringBuffer();
		// See https://bugs.eclipse.org/329386. We are trying to reduce the size of the manifest data in
		// the eclipse touchpoint. We've removed the code that requires it but in order for old clients
		// to still be able to use recent repositories, we're going to keep around the manifest properties
		// they need.
		final String[] interestingKeys = new String[] {Constants.BUNDLE_SYMBOLICNAME, Constants.BUNDLE_VERSION, Constants.FRAGMENT_HOST};
		for (String key : interestingKeys) {
			String value = p.get(key);
			if (value != null)
				result.append(key).append(": ").append(value).append('\n'); //$NON-NLS-1$
		}
		return result.length() == 0 ? null : result.toString();
	}

	// Return a map from locale to property set for the manifest localizations
	// from the given bundle directory and given bundle localization path/name
	// manifest property value.
	private static Map<Locale, Map<String, String>> getManifestLocalizations(Map<String, String> manifest, File bundleLocation) {
		Map<Locale, Map<String, String>> localizations;
		Locale defaultLocale = null; // = Locale.ENGLISH; // TODO: get this from GeneratorInfo
		String[] bundleManifestValues = getManifestCachedValues(manifest);
		String bundleLocalization = bundleManifestValues[BUNDLE_LOCALIZATION_INDEX]; // Bundle localization is the last one in the list

		if ("jar".equalsIgnoreCase(new Path(bundleLocation.getName()).getFileExtension()) && //$NON-NLS-1$
				bundleLocation.isFile()) {
			localizations = LocalizationHelper.getJarPropertyLocalizations(bundleLocation, bundleLocalization, defaultLocale, bundleManifestValues);
			//localizations = getJarManifestLocalization(bundleLocation, bundleLocalization, defaultLocale, bundleManifestValues);
		} else {
			localizations = LocalizationHelper.getDirPropertyLocalizations(bundleLocation, bundleLocalization, defaultLocale, bundleManifestValues);
			// localizations = getDirManifestLocalization(bundleLocation, bundleLocalization, defaultLocale, bundleManifestValues);
		}

		return localizations;
	}

	public static String[] getExternalizedStrings(IInstallableUnit iu) {
		String[] result = new String[PublisherHelper.BUNDLE_LOCALIZED_PROPERTIES.length];
		int j = 0;
		for (int i = 1; i < BUNDLE_IU_PROPERTY_MAP.length - 1; i += 2) {
			if (iu.getProperty(BUNDLE_IU_PROPERTY_MAP[i]) != null && iu.getProperty(BUNDLE_IU_PROPERTY_MAP[i]).length() > 0 && iu.getProperty(BUNDLE_IU_PROPERTY_MAP[i]).charAt(0) == '%')
				result[j++] = iu.getProperty(BUNDLE_IU_PROPERTY_MAP[i]).substring(1);
			else
				j++;
		}
		// The last string is the location 
		result[BUNDLE_LOCALIZATION_INDEX] = iu.getProperty(IInstallableUnit.PROP_BUNDLE_LOCALIZATION);

		return result;
	}

	public static String[] getManifestCachedValues(Map<String, String> manifest) {
		String[] cachedValues = new String[PublisherHelper.BUNDLE_LOCALIZED_PROPERTIES.length];
		for (int j = 0; j < PublisherHelper.BUNDLE_LOCALIZED_PROPERTIES.length; j++) {
			String value = manifest.get(PublisherHelper.BUNDLE_LOCALIZED_PROPERTIES[j]);
			if (PublisherHelper.BUNDLE_LOCALIZED_PROPERTIES[j].equals(Constants.BUNDLE_LOCALIZATION)) {
				if (value == null)
					value = DEFAULT_BUNDLE_LOCALIZATION;
				cachedValues[j] = value;
			} else if (value != null && value.length() > 1 && value.charAt(0) == '%') {
				cachedValues[j] = value.substring(1);
			}
		}
		return cachedValues;
	}

	// Return a map from locale to property set for the manifest localizations
	// from the given bundle directory and given bundle localization path/name
	// manifest property value.
	public static Map<Locale, Map<String, String>> getHostLocalizations(File bundleLocation, String[] hostBundleManifestValues) {
		Map<Locale, Map<String, String>> localizations;
		Locale defaultLocale = null; // = Locale.ENGLISH; // TODO: get this from GeneratorInfo
		String hostBundleLocalization = hostBundleManifestValues[BUNDLE_LOCALIZATION_INDEX];
		if (hostBundleLocalization == null)
			return null;

		if ("jar".equalsIgnoreCase(new Path(bundleLocation.getName()).getFileExtension()) && //$NON-NLS-1$
				bundleLocation.isFile()) {
			localizations = LocalizationHelper.getJarPropertyLocalizations(bundleLocation, hostBundleLocalization, defaultLocale, hostBundleManifestValues);
			//localizations = getJarManifestLocalization(bundleLocation, hostBundleLocalization, defaultLocale, hostBundleManifestValues);
		} else {
			localizations = LocalizationHelper.getDirPropertyLocalizations(bundleLocation, hostBundleLocalization, defaultLocale, hostBundleManifestValues);
			// localizations = getDirManifestLocalization(bundleLocation, hostBundleLocalization, defaultLocale, hostBundleManifestValues);
		}

		return localizations;
	}

	public static BundleDescription createBundleDescription(Dictionary<String, String> enhancedManifest, File bundleLocation) {
		try {
			BundleDescription descriptor = StateObjectFactory.defaultFactory.createBundleDescription(null, enhancedManifest, bundleLocation == null ? null : bundleLocation.getAbsolutePath(), 1); //TODO Do we need to have a real bundle id
			descriptor.setUserObject(enhancedManifest);
			return descriptor;
		} catch (BundleException e) {
			String message = NLS.bind(Messages.exception_stateAddition, bundleLocation == null ? null : bundleLocation.getAbsoluteFile());
			IStatus status = new Status(IStatus.WARNING, Activator.ID, message, e);
			LogHelper.log(status);
			return null;
		}
	}

	/**
	 * @deprecated use {@link #createBundleDescription(File)} instead.
	 */
	@Deprecated
	public static BundleDescription createBundleDescriptionIgnoringExceptions(File bundleLocation) {
		try {
			return createBundleDescription(bundleLocation);
		} catch (IOException e) {
			logWarning(bundleLocation, e);
			return null;
		} catch (BundleException e) {
			logWarning(bundleLocation, e);
			return null;
		}
	}

	private static void logWarning(File bundleLocation, Throwable t) {
		String message = NLS.bind(Messages.exception_errorLoadingManifest, bundleLocation);
		LogHelper.log(new Status(IStatus.WARNING, Activator.ID, message, t));
	}

	public static BundleDescription createBundleDescription(File bundleLocation) throws IOException, BundleException {
		Dictionary<String, String> manifest = loadManifest(bundleLocation);
		if (manifest == null)
			return null;
		return createBundleDescription(manifest, bundleLocation);
	}

	/**
	 * @deprecated use {@link #loadManifest(File)} instead.
	 */
	@Deprecated
	public static Dictionary<String, String> loadManifestIgnoringExceptions(File bundleLocation) {
		try {
			return loadManifest(bundleLocation);
		} catch (IOException e) {
			logWarning(bundleLocation, e);
			return null;
		} catch (BundleException e) {
			logWarning(bundleLocation, e);
			return null;
		}
	}

	public static Dictionary<String, String> loadManifest(File bundleLocation) throws IOException, BundleException {
		Dictionary<String, String> manifest = basicLoadManifest(bundleLocation);
		if (manifest == null)
			return null;
		// if the bundle itself does not define its shape, infer the shape from the current form
		if (manifest.get(BUNDLE_SHAPE) == null)
			manifest.put(BUNDLE_SHAPE, bundleLocation.isDirectory() ? DIR : JAR);
		return manifest;
	}

	/**
	 * @deprecated use {@link #basicLoadManifest(File)} instead.
	 */
	@Deprecated
	public static Dictionary<String, String> basicLoadManifestIgnoringExceptions(File bundleLocation) {
		try {
			return basicLoadManifest(bundleLocation);
		} catch (IOException e) {
			logWarning(bundleLocation, e);
			return null;
		} catch (BundleException e) {
			logWarning(bundleLocation, e);
			return null;
		}
	}

	public static Dictionary<String, String> basicLoadManifest(File bundleLocation) throws IOException, BundleException {
		InputStream manifestStream = null;
		ZipFile jarFile = null;
		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 {
			File manifestFile = new File(bundleLocation, JarFile.MANIFEST_NAME);
			if (manifestFile.exists()) {
				manifestStream = new BufferedInputStream(new FileInputStream(manifestFile));
			}
		}
		Dictionary<String, String> manifest = null;
		try {
			if (manifestStream != null) {
				manifest = parseBundleManifestIntoModifyableDictionaryWithCaseInsensitiveKeys(manifestStream);
			}
		} finally {
			try {
				if (jarFile != null)
					jarFile.close();
			} catch (IOException e2) {
				//Ignore
			}
		}

		return manifest;

	}

	/**
	 * @return the same result as {@link Headers#parseManifest(InputStream)}, but with a modifiable {@link Headers} instance
	 */
	private static Headers<String, String> parseBundleManifestIntoModifyableDictionaryWithCaseInsensitiveKeys(InputStream manifestStream) throws IOException, BundleException {
		return (Headers<String, String>) ManifestElement.parseBundleManifest(manifestStream, new Headers<String, String>(10));
	}

	private static ManifestElement[] parseManifestHeader(String header, Map<String, String> manifest, String bundleLocation) {
		try {
			return ManifestElement.parseHeader(header, manifest.get(header));
		} catch (BundleException e) {
			String message = NLS.bind(Messages.exception_errorReadingManifest, bundleLocation, e.getMessage());
			LogHelper.log(new Status(IStatus.ERROR, Activator.ID, message, e));
			return null;
		}
	}

	private static String getInstallationDirective(String requirementId, ManifestElement[] correspondingBundleHeader) {
		for (ManifestElement manifestElement : correspondingBundleHeader) {
			String[] packages = manifestElement.getValueComponents();
			for (String pckg : packages) {
				if (requirementId.equals(pckg)) {
					return manifestElement.getDirective(INSTALLATION_DIRECTIVE);
				}
			}
		}
		// TODO this case indicates an internal error -> return assertion error status
		return null;
	}

	public BundlesAction(File[] locations) {
		this.locations = locations;
	}

	public BundlesAction(BundleDescription[] bundles) {
		this.bundles = bundles;
	}

	@Override
	public IStatus perform(IPublisherInfo publisherInfo, IPublisherResult results, IProgressMonitor monitor) {
		if (bundles == null && locations == null)
			throw new IllegalStateException(Messages.exception_noBundlesOrLocations);

		setPublisherInfo(publisherInfo);
		finalStatus = new MultiStatus(Activator.ID, IStatus.OK, Messages.message_bundlesPublisherMultistatus, null);

		try {
			if (bundles == null)
				bundles = getBundleDescriptions(expandLocations(locations), monitor);
			generateBundleIUs(bundles, publisherInfo, results, monitor);
			bundles = null;
		} catch (OperationCanceledException e) {
			return Status.CANCEL_STATUS;
		}
		if (!finalStatus.isOK()) {
			return finalStatus;
		}
		return Status.OK_STATUS;
	}

	protected void publishArtifact(IArtifactDescriptor descriptor, File base, File[] inclusions, IPublisherInfo publisherInfo) {
		IArtifactRepository destination = publisherInfo.getArtifactRepository();
		if (descriptor == null || destination == null)
			return;

		// publish the given files
		publishArtifact(descriptor, inclusions, null, publisherInfo, createRootPrefixComputer(base));
	}

	@Override
	protected void publishArtifact(IArtifactDescriptor descriptor, File jarFile, IPublisherInfo publisherInfo) {
		// no files to publish so this is done.
		if (jarFile == null || publisherInfo == null)
			return;

		// if the destination already contains the descriptor, there is nothing to do.
		IArtifactRepository destination = publisherInfo.getArtifactRepository();
		if (destination == null || destination.contains(descriptor))
			return;

		super.publishArtifact(descriptor, jarFile, publisherInfo);

		// if we are assimilating pack200 files then add the packed descriptor
		// into the repo assuming it does not already exist.
		boolean reuse = "true".equals(destination.getProperties().get(AbstractPublisherApplication.PUBLISH_PACK_FILES_AS_SIBLINGS)); //$NON-NLS-1$
		if (reuse && (publisherInfo.getArtifactOptions() & IPublisherInfo.A_PUBLISH) > 0) {
			File packFile = new Path(jarFile.getAbsolutePath()).addFileExtension("pack.gz").toFile(); //$NON-NLS-1$
			if (packFile.exists()) {
				IArtifactDescriptor ad200 = createPack200ArtifactDescriptor(descriptor.getArtifactKey(), packFile, descriptor.getProperty(IArtifactDescriptor.ARTIFACT_SIZE));
				publishArtifact(ad200, packFile, publisherInfo);
			}
		}
	}

	private File[] expandLocations(File[] list) {
		ArrayList<File> result = new ArrayList<>();
		expandLocations(list, result);
		return result.toArray(new File[result.size()]);
	}

	private void expandLocations(File[] list, ArrayList<File> result) {
		if (list == null)
			return;
		for (int i = 0; i < list.length; i++) {
			File location = list[i];
			if (location.isDirectory()) {
				// if the location is itself a bundle, just add it.  Otherwise r down
				if (new File(location, JarFile.MANIFEST_NAME).exists())
					result.add(location);
				else if (new File(location, "plugin.xml").exists() || new File(location, "fragment.xml").exists()) //$NON-NLS-1$ //$NON-NLS-2$
					result.add(location); //old style bundle without manifest
				else
					expandLocations(location.listFiles(), result);
			} else {
				result.add(location);
			}
		}
	}

	/**
	 * Publishes bundle IUs to the p2 metadata and artifact repositories. 
	 * 
	 * @param bundleDescriptions Equinox framework descriptions of the bundles to publish. 
	 * @param result Used to attach status for the publication operation.
	 * @param monitor Used to fire progress events.
	 * 
	 * @deprecated Use {@link #generateBundleIUs(BundleDescription[] bundleDescriptions, IPublisherInfo info, IPublisherResult result, IProgressMonitor monitor)} with
	 * {@link IPublisherInfo} set to <code>null</code>
	 */
	@Deprecated
	protected void generateBundleIUs(BundleDescription[] bundleDescriptions, IPublisherResult result, IProgressMonitor monitor) {
		generateBundleIUs(bundleDescriptions, null, result, monitor);
	}

	/**
	 * Publishes bundle IUs to the p2 metadata and artifact repositories. 
	 * 
	 * @param bundleDescriptions Equinox framework descriptions of the bundles to publish. 
	 * @param info Configuration and publication advice information.
	 * @param result Used to attach status for the publication operation.
	 * @param monitor Used to fire progress events.
	 */
	protected void generateBundleIUs(BundleDescription[] bundleDescriptions, IPublisherInfo info, IPublisherResult result, IProgressMonitor monitor) {
		// This assumes that hosts are processed before fragments because for each fragment the host
		// is queried for the strings that should be translated.
		for (BundleDescription bd : bundleDescriptions) {
			if (monitor.isCanceled()) {
				throw new OperationCanceledException();
			}

			if (bd == null || bd.getSymbolicName() == null || bd.getVersion() == null) {
				continue;
			}

			//First check to see if there is already an IU around for this
			IInstallableUnit bundleIU = queryForIU(result, bd.getSymbolicName(), PublisherHelper.fromOSGiVersion(bd.getVersion()));
			IArtifactKey bundleArtKey = createBundleArtifactKey(bd.getSymbolicName(), bd.getVersion().toString());
			if (bundleIU == null) {
				createAdviceFileAdvice(bd, info);
				// Create the bundle IU according to any shape advice we have
				bundleIU = doCreateBundleIU(bd, bundleArtKey, info);
			}

			File bundleLocation = new File(bd.getLocation());
			IArtifactDescriptor ad = PublisherHelper.createArtifactDescriptor(info, bundleArtKey, bundleLocation);
			processArtifactPropertiesAdvice(bundleIU, ad, info);

			// Publish according to the shape on disk
			if (bundleLocation.isDirectory()) {
				publishArtifact(ad, bundleLocation, bundleLocation.listFiles(), info);
			} else {
				publishArtifact(ad, bundleLocation, info);
			}

			IInstallableUnit fragment = null;
			if (isFragment(bd)) {
				String hostId = bd.getHost().getName();
				VersionRange hostVersionRange = PublisherHelper.fromOSGiVersionRange(bd.getHost().getVersionRange());

				IQueryResult<IInstallableUnit> hosts = queryForIUs(result, hostId, hostVersionRange);

				for (IInstallableUnit host : hosts) {
					String fragmentId = makeHostLocalizationFragmentId(bd.getSymbolicName());
					fragment = queryForIU(result, fragmentId, PublisherHelper.fromOSGiVersion(bd.getVersion()));
					if (fragment == null) {
						String[] externalizedStrings = getExternalizedStrings(host);
						fragment = createHostLocalizationFragment(bundleIU, bd, hostId, externalizedStrings);
					}
				}
			}

			result.addIU(bundleIU, IPublisherResult.ROOT);
			if (fragment != null) {
				result.addIU(fragment, IPublisherResult.NON_ROOT);
			}

			InstallableUnitDescription[] others = processAdditionalInstallableUnitsAdvice(bundleIU, info);
			for (int iuIndex = 0; others != null && iuIndex < others.length; iuIndex++) {
				result.addIU(MetadataFactory.createInstallableUnit(others[iuIndex]), IPublisherResult.ROOT);
			}
		}
	}

	/**
	 * Adds advice for any p2.inf file found in this bundle.
	 */
	protected void createAdviceFileAdvice(BundleDescription bundleDescription, IPublisherInfo publisherInfo) {
		String location = bundleDescription.getLocation();
		if (location == null)
			return;

		AdviceFileAdvice advice = new AdviceFileAdvice(bundleDescription.getSymbolicName(), PublisherHelper.fromOSGiVersion(bundleDescription.getVersion()), new Path(location), AdviceFileAdvice.BUNDLE_ADVICE_FILE);
		if (advice.containsAdvice())
			publisherInfo.addAdvice(advice);

	}

	private static boolean isDir(BundleDescription bundle, IPublisherInfo info) {
		Collection<IBundleShapeAdvice> advice = info.getAdvice(null, true, bundle.getSymbolicName(), PublisherHelper.fromOSGiVersion(bundle.getVersion()), IBundleShapeAdvice.class);
		// if the advice has a shape, use it
		if (advice != null && !advice.isEmpty()) {
			// we know there is some advice but if there is more than one, take the first.
			String shape = advice.iterator().next().getShape();
			if (shape != null)
				return shape.equals(IBundleShapeAdvice.DIR);
		}
		// otherwise go with whatever we figured out from the manifest or the shape on disk
		@SuppressWarnings("unchecked")
		Map<String, String> manifest = (Map<String, String>) bundle.getUserObject();
		String format = manifest.get(BUNDLE_SHAPE);
		return DIR.equals(format);
	}

	private boolean isFragment(BundleDescription bd) {
		return (bd.getHost() != null ? true : false);
	}

	protected BundleDescription[] getBundleDescriptions(File[] bundleLocations, IProgressMonitor monitor) {
		if (bundleLocations == null)
			return new BundleDescription[0];
		List<BundleDescription> result = new ArrayList<>(bundleLocations.length);
		for (int i = 0; i < bundleLocations.length; i++) {
			if (monitor.isCanceled())
				throw new OperationCanceledException();
			BundleDescription description = null;
			try {
				description = createBundleDescription(bundleLocations[i]);
			} catch (IOException e) {
				addPublishingErrorToFinalStatus(e, bundleLocations[i]);
			} catch (BundleException e) {
				addPublishingErrorToFinalStatus(e, bundleLocations[i]);
			}
			if (description != null) {
				result.add(description);
			}
		}
		return result.toArray(new BundleDescription[0]);
	}

	private void addPublishingErrorToFinalStatus(Throwable t, File bundleLocation) {
		finalStatus.add(new Status(IStatus.ERROR, Activator.ID, NLS.bind(Messages.exception_errorPublishingBundle, bundleLocation, t.getMessage()), t));
	}
}
