/*******************************************************************************
 * Copyright (c) 2003, 2020 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
 *     Danail Nachev -  ProSyst - bug 218625
 *     Rob Harrop - SpringSource Inc. (bug 247522 and 255520)
 *******************************************************************************/
package org.eclipse.osgi.internal.resolver;

import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.osgi.framework.util.KeyedElement;
import org.eclipse.osgi.service.resolver.BaseDescription;
import org.eclipse.osgi.service.resolver.BundleDescription;
import org.eclipse.osgi.service.resolver.BundleSpecification;
import org.eclipse.osgi.service.resolver.ExportPackageDescription;
import org.eclipse.osgi.service.resolver.GenericDescription;
import org.eclipse.osgi.service.resolver.GenericSpecification;
import org.eclipse.osgi.service.resolver.HostSpecification;
import org.eclipse.osgi.service.resolver.ImportPackageSpecification;
import org.eclipse.osgi.service.resolver.NativeCodeDescription;
import org.eclipse.osgi.service.resolver.NativeCodeSpecification;
import org.eclipse.osgi.service.resolver.State;
import org.eclipse.osgi.service.resolver.StateWire;
import org.eclipse.osgi.service.resolver.VersionConstraint;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleReference;
import org.osgi.framework.Constants;
import org.osgi.framework.wiring.BundleCapability;
import org.osgi.framework.wiring.BundleRequirement;
import org.osgi.framework.wiring.BundleRevision;
import org.osgi.framework.wiring.BundleWire;
import org.osgi.framework.wiring.BundleWiring;
import org.osgi.resource.Capability;
import org.osgi.resource.Requirement;
import org.osgi.resource.Wire;

public final class BundleDescriptionImpl extends BaseDescriptionImpl implements BundleDescription, KeyedElement {
	static final String[] EMPTY_STRING = new String[0];
	static final ImportPackageSpecification[] EMPTY_IMPORTS = new ImportPackageSpecification[0];
	static final BundleSpecification[] EMPTY_BUNDLESPECS = new BundleSpecification[0];
	static final ExportPackageDescription[] EMPTY_EXPORTS = new ExportPackageDescription[0];
	static final BundleDescription[] EMPTY_BUNDLEDESCS = new BundleDescription[0];
	static final GenericSpecification[] EMPTY_GENERICSPECS = new GenericSpecification[0];
	static final GenericDescription[] EMPTY_GENERICDESCS = new GenericDescription[0];
	static final RuntimePermission GET_CLASSLOADER_PERM = new RuntimePermission("getClassLoader"); //$NON-NLS-1$

	static final int RESOLVED = 0x01;
	static final int SINGLETON = 0x02;
	static final int REMOVAL_PENDING = 0x04;
	static final int FULLY_LOADED = 0x08;
	static final int LAZY_LOADED = 0x10;
	static final int HAS_DYNAMICIMPORT = 0x20;
	static final int ATTACH_FRAGMENTS = 0x40;
	static final int DYNAMIC_FRAGMENTS = 0x80;

	// set to fully loaded and allow dynamic fragments by default
	private volatile int stateBits = FULLY_LOADED | ATTACH_FRAGMENTS | DYNAMIC_FRAGMENTS;

	private volatile long bundleId = -1;
	volatile HostSpecification host; //null if the bundle is not a fragment. volatile to allow unsynchronized checks for null
	private volatile StateImpl containingState;

	private volatile int lazyDataOffset = -1;
	private volatile int lazyDataSize = -1;

	private List<BundleDescription> dependencies;
	private List<BundleDescription> dependents;
	private String[] mandatory;
	private Map<String, Object> attributes;
	private Map<String, String> arbitraryDirectives;

	private volatile LazyData lazyData;
	private volatile int equinox_ee = -1;

	private DescriptionWiring bundleWiring;

	public BundleDescriptionImpl() {
		//
	}

	public long getBundleId() {
		return bundleId;
	}

	public String getSymbolicName() {
		return getName();
	}

	public BundleDescription getSupplier() {
		return this;
	}

	public String getLocation() {
		LazyData currentData = loadLazyData();
		synchronized (this.monitor) {
			return currentData.location;
		}
	}

	public String getPlatformFilter() {
		LazyData currentData = loadLazyData();
		synchronized (this.monitor) {
			return currentData.platformFilter;
		}
	}

	public String[] getExecutionEnvironments() {
		LazyData currentData = loadLazyData();
		synchronized (this.monitor) {
			if (currentData.executionEnvironments == null)
				return EMPTY_STRING;
			return currentData.executionEnvironments;
		}
	}

	public ImportPackageSpecification[] getImportPackages() {
		LazyData currentData = loadLazyData();
		synchronized (this.monitor) {
			if (currentData.importPackages == null)
				return EMPTY_IMPORTS;
			return currentData.importPackages;
		}
	}

	public ImportPackageSpecification[] getAddedDynamicImportPackages() {
		LazyData currentData = loadLazyData();
		synchronized (this.monitor) {
			if (currentData.addedDynamicImports == null)
				return EMPTY_IMPORTS;
			return currentData.addedDynamicImports.toArray(new ImportPackageSpecification[currentData.addedDynamicImports.size()]);
		}
	}

	public BundleSpecification[] getRequiredBundles() {
		LazyData currentData = loadLazyData();
		synchronized (this.monitor) {
			if (currentData.requiredBundles == null)
				return EMPTY_BUNDLESPECS;
			return currentData.requiredBundles;
		}
	}

	public GenericSpecification[] getGenericRequires() {
		LazyData currentData = loadLazyData();
		synchronized (this.monitor) {
			if (currentData.genericRequires == null)
				return EMPTY_GENERICSPECS;
			return currentData.genericRequires;
		}
	}

	public GenericDescription[] getGenericCapabilities() {
		LazyData currentData = loadLazyData();
		synchronized (this.monitor) {
			if (currentData.genericCapabilities == null)
				return EMPTY_GENERICDESCS;
			return currentData.genericCapabilities;
		}
	}

	public NativeCodeSpecification getNativeCodeSpecification() {
		LazyData currentData = loadLazyData();
		synchronized (this.monitor) {
			return currentData.nativeCode;
		}
	}

	public ExportPackageDescription[] getExportPackages() {
		LazyData currentData = loadLazyData();
		synchronized (this.monitor) {
			return currentData.exportPackages == null ? EMPTY_EXPORTS : currentData.exportPackages;
		}
	}

	public boolean isResolved() {
		return (stateBits & RESOLVED) != 0;
	}

	public State getContainingState() {
		return containingState;
	}

	public BundleDescription[] getFragments() {
		if (host != null)
			return EMPTY_BUNDLEDESCS;
		StateImpl currentState = (StateImpl) getContainingState();
		if (currentState == null)
			throw new IllegalStateException("BundleDescription does not belong to a state."); //$NON-NLS-1$
		return currentState.getFragments(this);
	}

	public HostSpecification getHost() {
		return host;
	}

	public boolean isSingleton() {
		return (stateBits & SINGLETON) != 0;
	}

	public boolean isRemovalPending() {
		return (stateBits & REMOVAL_PENDING) != 0;
	}

	public boolean hasDynamicImports() {
		return (stateBits & HAS_DYNAMICIMPORT) != 0;
	}

	public boolean attachFragments() {
		return (stateBits & ATTACH_FRAGMENTS) != 0;
	}

	public boolean dynamicFragments() {
		return (stateBits & DYNAMIC_FRAGMENTS) != 0;
	}

	public ExportPackageDescription[] getSelectedExports() {
		LazyData currentData = loadLazyData();
		synchronized (this.monitor) {
			if (currentData.selectedExports == null)
				return EMPTY_EXPORTS;
			return currentData.selectedExports;
		}
	}

	public GenericDescription[] getSelectedGenericCapabilities() {
		LazyData currentData = loadLazyData();
		synchronized (this.monitor) {
			if (currentData.selectedCapabilities == null)
				return EMPTY_GENERICDESCS;
			return currentData.selectedCapabilities;
		}
	}

	public ExportPackageDescription[] getSubstitutedExports() {
		LazyData currentData = loadLazyData();
		synchronized (this.monitor) {
			if (currentData.substitutedExports == null)
				return EMPTY_EXPORTS;
			return currentData.substitutedExports;
		}
	}

	public BundleDescription[] getResolvedRequires() {
		LazyData currentData = loadLazyData();
		synchronized (this.monitor) {
			if (currentData.resolvedRequires == null)
				return EMPTY_BUNDLEDESCS;
			return currentData.resolvedRequires;
		}
	}

	public ExportPackageDescription[] getResolvedImports() {
		LazyData currentData = loadLazyData();
		synchronized (this.monitor) {
			if (currentData.resolvedImports == null)
				return EMPTY_EXPORTS;
			return currentData.resolvedImports;
		}
	}

	public GenericDescription[] getResolvedGenericRequires() {
		LazyData currentData = loadLazyData();
		synchronized (this.monitor) {
			if (currentData.resolvedCapabilities == null)
				return EMPTY_GENERICDESCS;
			return currentData.resolvedCapabilities;
		}
	}

	public Map<String, List<StateWire>> getWires() {
		LazyData currentData = loadLazyData();
		synchronized (this.monitor) {
			if (currentData.stateWires == null) {
				currentData.stateWires = new HashMap<>(0);
			}
			return currentData.stateWires;
		}
	}

	Map<String, List<StateWire>> getWiresInternal() {
		LazyData currentData = loadLazyData();
		synchronized (this.monitor) {
			return currentData.stateWires;
		}
	}

	protected void setBundleId(long bundleId) {
		this.bundleId = bundleId;
	}

	protected void setSymbolicName(String symbolicName) {
		setName(symbolicName);
	}

	protected void setLocation(String location) {
		synchronized (this.monitor) {
			checkLazyData();
			lazyData.location = location;
		}
	}

	protected void setPlatformFilter(String platformFilter) {
		synchronized (this.monitor) {
			checkLazyData();
			lazyData.platformFilter = platformFilter;
		}
	}

	protected void setExecutionEnvironments(String[] executionEnvironments) {
		synchronized (this.monitor) {
			checkLazyData();
			lazyData.executionEnvironments = executionEnvironments == null || executionEnvironments.length > 0 ? executionEnvironments : EMPTY_STRING;
		}
	}

	protected void setExportPackages(ExportPackageDescription[] exportPackages) {
		synchronized (this.monitor) {
			checkLazyData();
			lazyData.exportPackages = exportPackages == null || exportPackages.length > 0 ? exportPackages : EMPTY_EXPORTS;
			if (exportPackages != null) {
				for (ExportPackageDescription exportPackage : exportPackages) {
					((ExportPackageDescriptionImpl) exportPackage).setExporter(this);
				}
			}
		}
	}

	protected void setImportPackages(ImportPackageSpecification[] importPackages) {
		synchronized (this.monitor) {
			checkLazyData();
			lazyData.importPackages = importPackages == null || importPackages.length > 0 ? importPackages : EMPTY_IMPORTS;
			if (importPackages != null) {
				for (ImportPackageSpecification importPackage : importPackages) {
					((ImportPackageSpecificationImpl) importPackage).setBundle(this);
					if (ImportPackageSpecification.RESOLUTION_DYNAMIC.equals(importPackage.getDirective(Constants.RESOLUTION_DIRECTIVE))) {
						stateBits |= HAS_DYNAMICIMPORT;
					}
				}
			}
		}
	}

	protected void setRequiredBundles(BundleSpecification[] requiredBundles) {
		synchronized (this.monitor) {
			checkLazyData();
			lazyData.requiredBundles = requiredBundles == null || requiredBundles.length > 0 ? requiredBundles : EMPTY_BUNDLESPECS;
			if (requiredBundles != null)
				for (BundleSpecification requiredBundle : requiredBundles) {
					((VersionConstraintImpl) requiredBundle).setBundle(this);
				}
		}
	}

	protected void setGenericCapabilities(GenericDescription[] genericCapabilities) {
		synchronized (this.monitor) {
			checkLazyData();
			lazyData.genericCapabilities = genericCapabilities == null || genericCapabilities.length > 0 ? genericCapabilities : EMPTY_GENERICDESCS;
			if (genericCapabilities != null)
				for (GenericDescription genericCapability : genericCapabilities) {
					((GenericDescriptionImpl) genericCapability).setSupplier(this);
				}
		}
	}

	protected void setGenericRequires(GenericSpecification[] genericRequires) {
		synchronized (this.monitor) {
			checkLazyData();
			lazyData.genericRequires = genericRequires == null || genericRequires.length > 0 ? genericRequires : EMPTY_GENERICSPECS;
			if (genericRequires != null)
				for (GenericSpecification genericRequire : genericRequires) {
					((VersionConstraintImpl) genericRequire).setBundle(this);
				}
		}
	}

	protected void setNativeCodeSpecification(NativeCodeSpecification nativeCode) {
		synchronized (this.monitor) {
			checkLazyData();
			lazyData.nativeCode = nativeCode;
			if (nativeCode != null) {
				((NativeCodeSpecificationImpl) nativeCode).setBundle(this);
				NativeCodeDescription[] suppliers = nativeCode.getPossibleSuppliers();
				if (suppliers != null)
					for (NativeCodeDescription supplier : suppliers) {
						((NativeCodeDescriptionImpl) supplier).setSupplier(this);
					}
			}
		}
	}

	protected int getStateBits() {
		return stateBits;
	}

	protected void setStateBit(int stateBit, boolean on) {
		synchronized (this.monitor) {
			if (on) {
				stateBits |= stateBit;
			} else {
				stateBits &= ~stateBit;
				if (stateBit == RESOLVED) {
					if (bundleWiring != null)
						bundleWiring.invalidate();
					bundleWiring = null;
				}
			}
		}
	}

	protected void setContainingState(State value) {
		synchronized (this.monitor) {
			containingState = (StateImpl) value;
			if (containingState != null && containingState.getReader() != null) {
				if (containingState.getReader().isLazyLoaded())
					stateBits |= LAZY_LOADED;
				else
					stateBits &= ~LAZY_LOADED;
			} else {
				stateBits &= ~LAZY_LOADED;
			}
		}
	}

	protected void setHost(HostSpecification host) {
		synchronized (this.monitor) {
			this.host = host;
			if (host != null) {
				((VersionConstraintImpl) host).setBundle(this);
			}
		}
	}

	protected void setLazyLoaded(boolean lazyLoad) {
		loadLazyData();
		synchronized (this.monitor) {
			if (lazyLoad)
				stateBits |= LAZY_LOADED;
			else
				stateBits &= ~LAZY_LOADED;
		}
	}

	protected void setSelectedExports(ExportPackageDescription[] selectedExports) {
		synchronized (this.monitor) {
			checkLazyData();
			lazyData.selectedExports = selectedExports == null || selectedExports.length > 0 ? selectedExports : EMPTY_EXPORTS;
			if (selectedExports != null) {
				for (ExportPackageDescription selectedExport : selectedExports) {
					((ExportPackageDescriptionImpl) selectedExport).setExporter(this);
				}
			}
		}
	}

	protected void setSelectedCapabilities(GenericDescription[] selectedCapabilities) {
		synchronized (this.monitor) {
			checkLazyData();
			lazyData.selectedCapabilities = selectedCapabilities == null || selectedCapabilities.length > 0 ? selectedCapabilities : EMPTY_GENERICDESCS;
			if (selectedCapabilities != null) {
				for (GenericDescription capability : selectedCapabilities) {
					((GenericDescriptionImpl) capability).setSupplier(this);
				}
			}
		}
	}

	protected void setSubstitutedExports(ExportPackageDescription[] substitutedExports) {
		synchronized (this.monitor) {
			checkLazyData();
			lazyData.substitutedExports = substitutedExports != null && substitutedExports.length > 0 ? substitutedExports : EMPTY_EXPORTS;
		}
	}

	protected void setResolvedImports(ExportPackageDescription[] resolvedImports) {
		synchronized (this.monitor) {
			checkLazyData();
			lazyData.resolvedImports = resolvedImports == null || resolvedImports.length > 0 ? resolvedImports : EMPTY_EXPORTS;
		}
	}

	protected void setResolvedRequires(BundleDescription[] resolvedRequires) {
		synchronized (this.monitor) {
			checkLazyData();
			lazyData.resolvedRequires = resolvedRequires == null || resolvedRequires.length > 0 ? resolvedRequires : EMPTY_BUNDLEDESCS;
		}
	}

	protected void setResolvedCapabilities(GenericDescription[] resolvedCapabilities) {
		synchronized (this.monitor) {
			checkLazyData();
			lazyData.resolvedCapabilities = resolvedCapabilities == null || resolvedCapabilities.length > 0 ? resolvedCapabilities : EMPTY_GENERICDESCS;
		}
	}

	protected void setStateWires(Map<String, List<StateWire>> stateWires) {
		synchronized (this.monitor) {
			checkLazyData();
			lazyData.stateWires = stateWires;
		}
	}

	void clearAddedDynamicImportPackages() {
		synchronized (this.monitor) {
			checkLazyData();
			lazyData.addedDynamicImports = null;
		}
	}

	@Override
	public String toString() {
		if (getSymbolicName() == null)
			return "[" + getBundleId() + "]"; //$NON-NLS-1$ //$NON-NLS-2$
		return getSymbolicName() + "_" + getVersion(); //$NON-NLS-1$
	}

	public Object getKey() {
		return Long.valueOf(bundleId);
	}

	public boolean compare(KeyedElement other) {
		if (!(other instanceof BundleDescriptionImpl))
			return false;
		BundleDescriptionImpl otherBundleDescription = (BundleDescriptionImpl) other;
		return bundleId == otherBundleDescription.bundleId;
	}

	public int getKeyHashCode() {
		return (int) (bundleId ^ (bundleId >>> 32));
	}

	/* TODO Determine if we need more than just Object ID type of hashcode.
	 public int hashCode() {
	 if (getSymbolicName() == null)
	 return (int) (bundleId % Integer.MAX_VALUE);
	 return (int) ((bundleId * (getSymbolicName().hashCode())) % Integer.MAX_VALUE);
	 }
	 */

	protected void removeDependencies() {
		synchronized (this.monitor) {
			if (dependencies == null)
				return;
			Iterator<BundleDescription> iter = dependencies.iterator();
			while (iter.hasNext()) {
				((BundleDescriptionImpl) iter.next()).removeDependent(this);
			}
			dependencies = null;
		}
	}

	protected void addDependencies(BaseDescription[] newDependencies, boolean checkDups) {
		synchronized (this.monitor) {
			if (newDependencies == null)
				return;
			if (!checkDups && dependencies == null)
				dependencies = new ArrayList<>(newDependencies.length);
			for (BaseDescription newDependency : newDependencies) {
				addDependency((BaseDescriptionImpl) newDependency, checkDups);
			}
		}
	}

	protected void addDependency(BaseDescriptionImpl dependency, boolean checkDups) {
		synchronized (this.monitor) {
			BundleDescriptionImpl bundle = (BundleDescriptionImpl) dependency.getSupplier();
			if (bundle == this)
				return;
			if (dependencies == null)
				dependencies = new ArrayList<>(10);
			if (!checkDups || !dependencies.contains(bundle)) {
				bundle.addDependent(this);
				dependencies.add(bundle);
			}
		}
	}

	/*
	 * Gets all the bundle dependencies as a result of import-package or require-bundle.
	 * Self and fragment bundles are removed.
	 */
	List<BundleDescription> getBundleDependencies() {
		synchronized (this.monitor) {
			if (dependencies == null)
				return new ArrayList<>(0);
			ArrayList<BundleDescription> required = new ArrayList<>(dependencies.size());
			for (Iterator<BundleDescription> iter = dependencies.iterator(); iter.hasNext();) {
				BundleDescription dep = iter.next();
				if (dep != this && dep.getHost() == null)
					required.add(dep);
			}
			return required;
		}
	}

	protected void addDependent(BundleDescription dependent) {
		synchronized (this.monitor) {
			if (dependents == null)
				dependents = new ArrayList<>(10);
			// no need to check for duplicates here; this is only called in addDepenency which already checks for dups.
			dependents.add(dependent);
		}
	}

	protected void removeDependent(BundleDescription dependent) {
		synchronized (this.monitor) {
			if (dependents == null)
				return;
			dependents.remove(dependent);
		}
	}

	public BundleDescription[] getDependents() {
		synchronized (this.monitor) {
			if (dependents == null)
				return EMPTY_BUNDLEDESCS;
			return dependents.toArray(new BundleDescription[dependents.size()]);
		}
	}

	boolean hasDependents() {
		synchronized (this.monitor) {
			return dependents == null ? false : dependents.size() > 0;
		}
	}

	void setFullyLoaded(boolean fullyLoaded) {
		synchronized (this.monitor) {
			if (fullyLoaded) {
				stateBits |= FULLY_LOADED;
			} else {
				stateBits &= ~FULLY_LOADED;
			}
		}
	}

	boolean isFullyLoaded() {
		return (stateBits & FULLY_LOADED) != 0;
	}

	void setLazyDataOffset(int lazyDataOffset) {
		this.lazyDataOffset = lazyDataOffset;
	}

	int getLazyDataOffset() {
		return this.lazyDataOffset;
	}

	void setLazyDataSize(int lazyDataSize) {
		this.lazyDataSize = lazyDataSize;
	}

	int getLazyDataSize() {
		return this.lazyDataSize;
	}

	// DO NOT call while holding this.monitor
	private LazyData loadLazyData() {
		// TODO add back if ee min 1.2 adds holdsLock method
		//if (Thread.holdsLock(this.monitor)) {
		//	throw new IllegalStateException("Should not call fullyLoad() holding monitor."); //$NON-NLS-1$
		//}
		if ((stateBits & LAZY_LOADED) == 0)
			return this.lazyData;

		StateImpl currentState = (StateImpl) getContainingState();
		StateReader reader = currentState == null ? null : currentState.getReader();
		if (reader == null)
			throw new IllegalStateException("No valid reader for the bundle description"); //$NON-NLS-1$

		synchronized (currentState.monitor) {
			if (isFullyLoaded()) {
				reader.setAccessedFlag(true); // set reader accessed flag
				return this.lazyData;
			}
			try {
				reader.fullyLoad(this);
				return this.lazyData;
			} catch (IOException e) {
				throw new RuntimeException(e.getMessage(), e); // TODO not sure what to do here!!
			}
		}
	}

	void addDynamicResolvedImport(ExportPackageDescriptionImpl result) {
		synchronized (this.monitor) {
			// mark the dependency
			addDependency(result, true);
			// add the export to the list of the resolvedImports
			checkLazyData();
			if (lazyData.resolvedImports == null) {
				lazyData.resolvedImports = new ExportPackageDescription[] {result};
				return;
			}
			ExportPackageDescription[] newImports = new ExportPackageDescription[lazyData.resolvedImports.length + 1];
			System.arraycopy(lazyData.resolvedImports, 0, newImports, 0, lazyData.resolvedImports.length);
			newImports[newImports.length - 1] = result;
			lazyData.resolvedImports = newImports;
		}
	}

	void addDynamicImportPackages(ImportPackageSpecification[] dynamicImport) {
		LazyData currentData = loadLazyData();
		synchronized (this.monitor) {
			if (currentData.addedDynamicImports == null)
				currentData.addedDynamicImports = new ArrayList<>();
			for (ImportPackageSpecification addImport : dynamicImport) {
				if (!ImportPackageSpecification.RESOLUTION_DYNAMIC.equals(addImport.getDirective(Constants.RESOLUTION_DIRECTIVE)))
					throw new IllegalArgumentException("Import must be a dynamic import."); //$NON-NLS-1$
			}
			adding: for (ImportPackageSpecification addImport : dynamicImport) {
				for (ImportPackageSpecification currentImport : currentData.addedDynamicImports) {
					if (equalImports(addImport, currentImport))
						continue adding;
				}
				((ImportPackageSpecificationImpl) addImport).setBundle(this);
				currentData.addedDynamicImports.add(addImport);
			}
		}
	}

	private boolean equalImports(ImportPackageSpecification addImport, ImportPackageSpecification currentImport) {
		if (!isEqual(addImport.getName(), currentImport.getName()))
			return false;
		if (!isEqual(addImport.getVersionRange(), currentImport.getVersionRange()))
			return false;
		if (!isEqual(addImport.getBundleSymbolicName(), currentImport.getBundleSymbolicName()))
			return false;
		if (!isEqual(addImport.getBundleVersionRange(), currentImport.getBundleVersionRange()))
			return false;
		return isEqual(addImport.getAttributes(), currentImport.getAttributes());
	}

	private boolean isEqual(Object o1, Object o2) {
		return (o1 == null) ? o2 == null : o1.equals(o2);
	}

	void unload() {
		StateImpl currentState = (StateImpl) getContainingState();
		StateReader reader = currentState == null ? null : currentState.getReader();
		if (reader == null)
			throw new IllegalStateException("BundleDescription does not belong to a reader."); //$NON-NLS-1$
		synchronized (currentState.monitor) {
			if ((stateBits & LAZY_LOADED) == 0)
				return;
			if (!isFullyLoaded())
				return;
			synchronized (this.monitor) {
				setFullyLoaded(false);
				lazyData = null;
			}
		}
	}

	void setDynamicStamps(Map<String, Long> dynamicStamps) {
		synchronized (this.monitor) {
			checkLazyData();
			lazyData.dynamicStamps = dynamicStamps;
		}
	}

	void setDynamicStamp(String requestedPackage, Long timestamp) {
		synchronized (this.monitor) {
			checkLazyData();
			if (lazyData.dynamicStamps == null) {
				if (timestamp == null)
					return;
				lazyData.dynamicStamps = new HashMap<>();
			}
			if (timestamp == null)
				lazyData.dynamicStamps.remove(requestedPackage);
			else
				lazyData.dynamicStamps.put(requestedPackage, timestamp);
		}
	}

	long getDynamicStamp(String requestedPackage) {
		LazyData currentData = loadLazyData();
		synchronized (this.monitor) {
			Long stamp = currentData.dynamicStamps == null ? null : (Long) currentData.dynamicStamps.get(requestedPackage);
			return stamp == null ? 0 : stamp.longValue();
		}
	}

	Map<String, Long> getDynamicStamps() {
		LazyData currentData = loadLazyData();
		synchronized (this.monitor) {
			return currentData.dynamicStamps;
		}
	}

	public void setEquinoxEE(int equinox_ee) {
		this.equinox_ee = equinox_ee;
	}

	public int getEquinoxEE() {
		return equinox_ee;
	}

	private void checkLazyData() {
		if (lazyData == null)
			lazyData = new LazyData();
	}

	final class LazyData {
		String location;
		String platformFilter;

		BundleSpecification[] requiredBundles;
		ExportPackageDescription[] exportPackages;
		ImportPackageSpecification[] importPackages;
		GenericDescription[] genericCapabilities;
		GenericSpecification[] genericRequires;
		NativeCodeSpecification nativeCode;

		ExportPackageDescription[] selectedExports;
		GenericDescription[] selectedCapabilities;
		BundleDescription[] resolvedRequires;
		ExportPackageDescription[] resolvedImports;
		GenericDescription[] resolvedCapabilities;
		ExportPackageDescription[] substitutedExports;
		String[] executionEnvironments;

		Map<String, Long> dynamicStamps;
		Map<String, List<StateWire>> stateWires;
		// Note that this is not persisted in the state cache
		List<ImportPackageSpecification> addedDynamicImports;
	}

	public Map<String, Object> getAttributes() {
		synchronized (this.monitor) {
			return attributes;
		}
	}

	@SuppressWarnings("unchecked")
	void setAttributes(Map<String, ?> attributes) {
		synchronized (this.monitor) {
			this.attributes = (Map<String, Object>) attributes;
		}
	}

	Object getDirective(String key) {
		synchronized (this.monitor) {
			if (Constants.MANDATORY_DIRECTIVE.equals(key))
				return mandatory;
			if (Constants.SINGLETON_DIRECTIVE.equals(key))
				return isSingleton() ? Boolean.TRUE : Boolean.FALSE;
			if (Constants.FRAGMENT_ATTACHMENT_DIRECTIVE.equals(key)) {
				if (!attachFragments())
					return Constants.FRAGMENT_ATTACHMENT_NEVER;
				if (dynamicFragments())
					return Constants.FRAGMENT_ATTACHMENT_ALWAYS;
				return Constants.FRAGMENT_ATTACHMENT_RESOLVETIME;
			}
		}
		return null;
	}

	void setDirective(String key, Object value) {
		// only pay attention to mandatory directive for now; others are set with setState method
		if (Constants.MANDATORY_DIRECTIVE.equals(key))
			mandatory = (String[]) value;
	}

	@SuppressWarnings("unchecked")
	void setArbitraryDirectives(Map<String, ?> directives) {
		synchronized (this.monitor) {
			this.arbitraryDirectives = (Map<String, String>) directives;
		}
	}

	Map<String, String> getArbitraryDirectives() {
		synchronized (this.monitor) {
			return arbitraryDirectives;
		}
	}

	public Map<String, String> getDeclaredDirectives() {
		Map<String, String> result = new HashMap<>(2);
		Map<String, String> arbitrary = getArbitraryDirectives();
		if (arbitrary != null)
			result.putAll(arbitrary);
		if (!attachFragments()) {
			result.put(Constants.FRAGMENT_ATTACHMENT_DIRECTIVE, Constants.FRAGMENT_ATTACHMENT_NEVER);
		} else {
			if (dynamicFragments())
				result.put(Constants.FRAGMENT_ATTACHMENT_DIRECTIVE, Constants.FRAGMENT_ATTACHMENT_ALWAYS);
			else
				result.put(Constants.FRAGMENT_ATTACHMENT_DIRECTIVE, Constants.FRAGMENT_ATTACHMENT_RESOLVETIME);
		}
		if (isSingleton())
			result.put(Constants.SINGLETON_DIRECTIVE, Boolean.TRUE.toString());
		String[] mandatoryDirective = (String[]) getDirective(Constants.MANDATORY_DIRECTIVE);
		if (mandatoryDirective != null)
			result.put(Constants.MANDATORY_DIRECTIVE, ExportPackageDescriptionImpl.toString(mandatoryDirective));
		return Collections.unmodifiableMap(result);
	}

	public Map<String, Object> getDeclaredAttributes() {
		Map<String, Object> result = new HashMap<>(1);
		synchronized (this.monitor) {
			if (attributes != null)
				result.putAll(attributes);
		}
		result.put(BundleRevision.BUNDLE_NAMESPACE, getName());
		result.put(Constants.BUNDLE_VERSION_ATTRIBUTE, getVersion());
		return Collections.unmodifiableMap(result);
	}

	public List<BundleRequirement> getDeclaredRequirements(String namespace) {
		List<BundleRequirement> result = new ArrayList<>();
		if (namespace == null || BundleRevision.BUNDLE_NAMESPACE.equals(namespace)) {
			BundleSpecification[] requires = getRequiredBundles();
			for (BundleSpecification require : requires) {
				result.add(require.getRequirement());
			}
		}
		if (host != null && (namespace == null || BundleRevision.HOST_NAMESPACE.equals(namespace))) {
			result.add(host.getRequirement());
		}
		if (namespace == null || BundleRevision.PACKAGE_NAMESPACE.equals(namespace)) {
			ImportPackageSpecification[] imports = getImportPackages();
			for (ImportPackageSpecification importPkg : imports)
				result.add(importPkg.getRequirement());
		}
		GenericSpecification[] genericSpecifications = getGenericRequires();
		for (GenericSpecification requirement : genericSpecifications) {
			if (namespace == null || namespace.equals(requirement.getType()))
				result.add(requirement.getRequirement());
		}
		return Collections.unmodifiableList(result);
	}

	public List<BundleCapability> getDeclaredCapabilities(String namespace) {
		List<BundleCapability> result = new ArrayList<>();
		if (host == null) {
			if (getSymbolicName() != null) {
				if (namespace == null || BundleRevision.BUNDLE_NAMESPACE.equals(namespace)) {
					result.add(BundleDescriptionImpl.this.getCapability());
				}
				if (attachFragments() && (namespace == null || BundleRevision.HOST_NAMESPACE.equals(namespace))) {
					result.add(BundleDescriptionImpl.this.getCapability(BundleRevision.HOST_NAMESPACE));
				}
			}

		} else {
			// may need to have a osgi.wiring.fragment capability
		}
		if (namespace == null || BundleRevision.PACKAGE_NAMESPACE.equals(namespace)) {
			ExportPackageDescription[] exports = getExportPackages();
			for (ExportPackageDescription exportPkg : exports)
				result.add(exportPkg.getCapability());
		}
		GenericDescription[] genericCapabilities = getGenericCapabilities();
		for (GenericDescription capabilitiy : genericCapabilities) {
			if (namespace == null || namespace.equals(capabilitiy.getType()))
				result.add(capabilitiy.getCapability());
		}
		return Collections.unmodifiableList(result);
	}

	public int getTypes() {
		return getHost() != null ? BundleRevision.TYPE_FRAGMENT : 0;
	}

	public Bundle getBundle() {
		Object ref = getUserObject();
		if (ref instanceof BundleReference)
			return ((BundleReference) ref).getBundle();
		return null;
	}

	@Override
	String getInternalNameSpace() {
		return BundleRevision.BUNDLE_NAMESPACE;
	}

	public BundleWiring getWiring() {
		synchronized (this.monitor) {
			if (bundleWiring != null || !isResolved())
				return bundleWiring;
			return bundleWiring = new DescriptionWiring();
		}
	}

	static class BundleWireImpl implements BundleWire {
		private final BundleCapability capability;
		private final BundleWiring provider;
		private final BundleRequirement requirement;
		private final BundleWiring requirer;

		public BundleWireImpl(StateWire wire) {
			VersionConstraint declaredRequirement = wire.getDeclaredRequirement();
			if (declaredRequirement instanceof HostSpecification)
				this.capability = ((BaseDescriptionImpl) wire.getDeclaredCapability()).getCapability(BundleRevision.HOST_NAMESPACE);
			else
				this.capability = wire.getDeclaredCapability().getCapability();
			this.provider = wire.getCapabilityHost().getWiring();
			this.requirement = declaredRequirement.getRequirement();
			this.requirer = wire.getRequirementHost().getWiring();
		}

		public BundleCapability getCapability() {
			return capability;
		}

		public BundleRequirement getRequirement() {
			return requirement;
		}

		public BundleWiring getProviderWiring() {
			return provider;
		}

		public BundleWiring getRequirerWiring() {
			return requirer;
		}

		@Override
		public int hashCode() {
			int hashcode = 31 + capability.hashCode();
			hashcode = hashcode * 31 + requirement.hashCode();
			hashcode = hashcode * 31 + provider.hashCode();
			hashcode = hashcode * 31 + requirer.hashCode();
			return hashcode;
		}

		@Override
		public boolean equals(Object obj) {
			if (!(obj instanceof BundleWireImpl))
				return false;
			BundleWireImpl other = (BundleWireImpl) obj;
			return capability.equals(other.getCapability()) && requirement.equals(other.getRequirement()) && provider.equals(other.getProviderWiring()) && requirer.equals(other.getRequirerWiring());
		}

		@Override
		public String toString() {
			return getRequirement() + " -> " + getCapability(); //$NON-NLS-1$
		}

		public BundleRevision getProvider() {
			return provider.getRevision();
		}

		public BundleRevision getRequirer() {
			return requirer.getRevision();
		}
	}

	/**
	 * Coerce the generic type of a list from List<BundleWire>
	 * to List<Wire>
	 * @param l List to be coerced.
	 * @return l coerced to List<Wire>
	 */
	@SuppressWarnings("unchecked")
	static List<Wire> asListWire(List<? extends Wire> l) {
		return (List<Wire>) l;
	}

	/**
	 * Coerce the generic type of a list from List<BundleCapability>
	 * to List<Capability>
	 * @param l List to be coerced.
	 * @return l coerced to List<Capability>
	 */
	@SuppressWarnings("unchecked")
	static List<Capability> asListCapability(List<? extends Capability> l) {
		return (List<Capability>) l;
	}

	/**
	 * Coerce the generic type of a list from List<BundleRequirement>
	 * to List<Requirement>
	 * @param l List to be coerced.
	 * @return l coerced to List<Requirement>
	 */
	@SuppressWarnings("unchecked")
	static List<Requirement> asListRequirement(List<? extends Requirement> l) {
		return (List<Requirement>) l;
	}

	// Note that description wiring are identity equality based
	class DescriptionWiring implements BundleWiring {
		private volatile boolean valid = true;

		public Bundle getBundle() {
			return BundleDescriptionImpl.this.getBundle();
		}

		public boolean isInUse() {
			return valid && (isCurrent() || BundleDescriptionImpl.this.hasDependents());
		}

		void invalidate() {
			valid = false;
		}

		public boolean isCurrent() {
			return valid && !BundleDescriptionImpl.this.isRemovalPending();
		}

		public List<BundleCapability> getCapabilities(String namespace) {
			if (!isInUse())
				return null;
			List<BundleCapability> result = new ArrayList<>();
			GenericDescription[] genericCapabilities = getSelectedGenericCapabilities();
			for (GenericDescription capabilitiy : genericCapabilities) {
				if (namespace == null || namespace.equals(capabilitiy.getType()))
					result.add(capabilitiy.getCapability());
			}
			if (host != null)
				return result;
			if (getSymbolicName() != null) {
				if (namespace == null || BundleRevision.BUNDLE_NAMESPACE.equals(namespace)) {
					result.add(BundleDescriptionImpl.this.getCapability());
				}
				if (attachFragments() && (namespace == null || BundleRevision.HOST_NAMESPACE.equals(namespace))) {
					result.add(BundleDescriptionImpl.this.getCapability(BundleRevision.HOST_NAMESPACE));
				}
			}
			if (namespace == null || BundleRevision.PACKAGE_NAMESPACE.equals(namespace)) {
				ExportPackageDescription[] exports = getSelectedExports();
				for (ExportPackageDescription exportPkg : exports)
					result.add(exportPkg.getCapability());
			}
			return result;
		}

		public List<Capability> getResourceCapabilities(String namespace) {
			return asListCapability(getCapabilities(namespace));
		}

		public List<BundleRequirement> getRequirements(String namespace) {
			List<BundleWire> requiredWires = getRequiredWires(namespace);
			if (requiredWires == null)
				// happens if not in use
				return null;
			List<BundleRequirement> requirements = new ArrayList<>(requiredWires.size());
			for (BundleWire wire : requiredWires) {
				if (!requirements.contains(wire.getRequirement()))
					requirements.add(wire.getRequirement());
			}
			// get dynamic imports
			if (getHost() == null && (namespace == null || BundleRevision.PACKAGE_NAMESPACE.equals(namespace))) {
				// TODO need to handle fragments that add dynamic imports
				if (hasDynamicImports()) {
					ImportPackageSpecification[] imports = getImportPackages();
					for (ImportPackageSpecification impPackage : imports) {
						if (ImportPackageSpecification.RESOLUTION_DYNAMIC.equals(impPackage.getDirective(Constants.RESOLUTION_DIRECTIVE))) {
							BundleRequirement req = impPackage.getRequirement();
							if (!requirements.contains(req))
								requirements.add(req);
						}
					}
				}
				ImportPackageSpecification[] addedDynamic = getAddedDynamicImportPackages();
				for (ImportPackageSpecification dynamicImport : addedDynamic) {
					BundleRequirement req = dynamicImport.getRequirement();
					if (!requirements.contains(req))
						requirements.add(req);
				}
			}
			return requirements;
		}

		public List<Requirement> getResourceRequirements(String namespace) {
			return asListRequirement(getRequirements(namespace));
		}

		public List<BundleWire> getProvidedWires(String namespace) {
			if (!isInUse())
				return null;
			BundleDescription[] dependentBundles = getDependents();
			List<BundleWire> unorderedResult = new ArrayList<>();
			for (BundleDescription dependent : dependentBundles) {
				List<BundleWire> dependentWires = dependent.getWiring().getRequiredWires(namespace);
				if (dependentWires != null)
					for (BundleWire bundleWire : dependentWires) {
						if (bundleWire.getProviderWiring() == this)
							unorderedResult.add(bundleWire);
					}
			}
			List<BundleWire> orderedResult = new ArrayList<>(unorderedResult.size());
			List<BundleCapability> capabilities = getCapabilities(namespace);
			for (BundleCapability capability : capabilities) {
				for (Iterator<BundleWire> wires = unorderedResult.iterator(); wires.hasNext();) {
					BundleWire wire = wires.next();
					if (wire.getCapability().equals(capability)) {
						wires.remove();
						orderedResult.add(wire);
					}
				}
			}
			return orderedResult;
		}

		public List<Wire> getProvidedResourceWires(String namespace) {
			return asListWire(getProvidedWires(namespace));
		}

		public List<BundleWire> getRequiredWires(String namespace) {
			if (!isInUse())
				return null;
			List<BundleWire> result = Collections.<BundleWire> emptyList();
			Map<String, List<StateWire>> wireMap = getWires();
			if (namespace == null) {
				result = new ArrayList<>();
				for (List<StateWire> wires : wireMap.values()) {
					for (StateWire wire : wires) {
						result.add(new BundleWireImpl(wire));
					}
				}
				return result;
			}
			List<StateWire> wires = wireMap.get(namespace);
			if (wires == null)
				return result;
			result = new ArrayList<>(wires.size());
			for (StateWire wire : wires) {
				result.add(new BundleWireImpl(wire));
			}
			return result;
		}

		public List<Wire> getRequiredResourceWires(String namespace) {
			return asListWire(getRequiredWires(namespace));
		}

		public BundleRevision getRevision() {
			return BundleDescriptionImpl.this;
		}

		public BundleRevision getResource() {
			return getRevision();
		}

		public ClassLoader getClassLoader() {
			throw new UnsupportedOperationException();
		}

		public List<URL> findEntries(String path, String filePattern, int options) {
			return null;
		}

		public Collection<String> listResources(String path, String filePattern, int options) {
			return null;
		}

		@Override
		public String toString() {
			return BundleDescriptionImpl.this.toString();
		}
	}

	public List<Capability> getCapabilities(String namespace) {
		return asListCapability(getDeclaredCapabilities(namespace));
	}

	public List<Requirement> getRequirements(String namespace) {
		return asListRequirement(getDeclaredRequirements(namespace));
	}
}
