/*******************************************************************************
 * Copyright (c) 2003, 2016 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.*;
import org.eclipse.osgi.framework.util.KeyedElement;
import org.eclipse.osgi.service.resolver.*;
import org.osgi.framework.*;
import org.osgi.framework.wiring.*;
import org.osgi.resource.*;

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;
		}
	}

	protected void setExportPackages(ExportPackageDescription[] exportPackages) {
		synchronized (this.monitor) {
			checkLazyData();
			lazyData.exportPackages = exportPackages;
			if (exportPackages != null) {
				for (int i = 0; i < exportPackages.length; i++) {
					((ExportPackageDescriptionImpl) exportPackages[i]).setExporter(this);
				}
			}
		}
	}

	protected void setImportPackages(ImportPackageSpecification[] importPackages) {
		synchronized (this.monitor) {
			checkLazyData();
			lazyData.importPackages = importPackages;
			if (importPackages != null) {
				for (int i = 0; i < importPackages.length; i++) {
					((ImportPackageSpecificationImpl) importPackages[i]).setBundle(this);
					if (ImportPackageSpecification.RESOLUTION_DYNAMIC.equals(importPackages[i].getDirective(Constants.RESOLUTION_DIRECTIVE)))
						stateBits |= HAS_DYNAMICIMPORT;
				}
			}
		}
	}

	protected void setRequiredBundles(BundleSpecification[] requiredBundles) {
		synchronized (this.monitor) {
			checkLazyData();
			lazyData.requiredBundles = requiredBundles;
			if (requiredBundles != null)
				for (int i = 0; i < requiredBundles.length; i++) {
					((VersionConstraintImpl) requiredBundles[i]).setBundle(this);
				}
		}
	}

	protected void setGenericCapabilities(GenericDescription[] genericCapabilities) {
		synchronized (this.monitor) {
			checkLazyData();
			lazyData.genericCapabilities = genericCapabilities;
			if (genericCapabilities != null)
				for (int i = 0; i < genericCapabilities.length; i++)
					((GenericDescriptionImpl) genericCapabilities[i]).setSupplier(this);
		}
	}

	protected void setGenericRequires(GenericSpecification[] genericRequires) {
		synchronized (this.monitor) {
			checkLazyData();
			lazyData.genericRequires = genericRequires;
			if (genericRequires != null)
				for (int i = 0; i < genericRequires.length; i++)
					((VersionConstraintImpl) genericRequires[i]).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 (int i = 0; i < suppliers.length; i++)
						((NativeCodeDescriptionImpl) suppliers[i]).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;
			if (selectedExports != null) {
				for (int i = 0; i < selectedExports.length; i++) {
					((ExportPackageDescriptionImpl) selectedExports[i]).setExporter(this);
				}
			}
		}
	}

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

	protected void setSubstitutedExports(ExportPackageDescription[] substitutedExports) {
		synchronized (this.monitor) {
			checkLazyData();
			lazyData.substitutedExports = substitutedExports;
		}
	}

	protected void setResolvedImports(ExportPackageDescription[] resolvedImports) {
		synchronized (this.monitor) {
			checkLazyData();
			lazyData.resolvedImports = resolvedImports;
		}
	}

	protected void setResolvedRequires(BundleDescription[] resolvedRequires) {
		synchronized (this.monitor) {
			checkLazyData();
			lazyData.resolvedRequires = resolvedRequires;
		}
	}

	protected void setResolvedCapabilities(GenericDescription[] resolvedCapabilities) {
		synchronized (this.monitor) {
			checkLazyData();
			lazyData.resolvedCapabilities = resolvedCapabilities;
		}
	}

	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 new Long(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 (int i = 0; i < newDependencies.length; i++) {
				addDependency((BaseDescriptionImpl) newDependencies[i], 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));
	}
}
