/*******************************************************************************
 * 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
 *     Rob Harrop - SpringSource Inc. (bug 247522)
 *******************************************************************************/
package org.eclipse.osgi.internal.resolver;

import java.io.*;
import java.util.*;
import org.eclipse.osgi.service.resolver.*;
import org.eclipse.osgi.service.resolver.VersionRange;
import org.osgi.framework.*;

/**
 * This class is <strong>not</strong> thread safe. Instances must not be
 * shared across multiple threads.
 */
class StateWriter {

	// objectTable will be a hashmap of objects. The objects will be things
	// like BundleDescription, ExportPackageDescription, Version etc.. The integer
	// index value will be used in the cache to allow cross-references in the
	// cached state.
	private final Map<Object, Integer> objectTable = new HashMap<>();

	private final List<Object> forcedWrite = new ArrayList<>();

	private int addToObjectTable(Object object) {
		Integer cur = objectTable.get(object);
		if (cur != null)
			return cur.intValue();
		objectTable.put(object, new Integer(objectTable.size()));
		// return the index of the object just added (i.e. size - 1)
		return (objectTable.size() - 1);
	}

	private int getFromObjectTable(Object object) {
		if (objectTable != null) {
			Object objectResult = objectTable.get(object);
			if (objectResult != null) {
				return ((Integer) objectResult).intValue();
			}
		}
		return -1;
	}

	private boolean writePrefix(Object object, DataOutputStream out) throws IOException {
		if (writeIndex(object, out))
			return true;
		// add this object to the object table first
		int index = addToObjectTable(object);
		out.writeByte(StateReader.OBJECT);
		out.writeInt(index);
		return false;
	}

	private void writeStateDeprecated(StateImpl state, DataOutputStream out) throws IOException {
		out.write(StateReader.STATE_CACHE_VERSION);
		if (writePrefix(state, out))
			return;
		out.writeLong(state.getTimeStamp());
		// write the platform property keys
		String[] platformPropKeys = state.getPlatformPropertyKeys();
		writePlatformProp(platformPropKeys, out);
		Dictionary<Object, Object>[] propSet = state.getPlatformProperties();
		out.writeInt(propSet.length);
		for (int i = 0; i < propSet.length; i++) {
			Dictionary<Object, Object> props = propSet[i];
			out.writeInt(platformPropKeys.length);
			for (int j = 0; j < platformPropKeys.length; j++)
				writePlatformProp(props.get(platformPropKeys[j]), out);
		}
		BundleDescription[] bundles = state.getBundles();
		StateHelperImpl.getInstance().sortBundles(bundles);
		out.writeInt(bundles.length);
		if (bundles.length == 0)
			return;
		for (int i = 0; i < bundles.length; i++)
			writeBundleDescription(bundles[i], out, false);
		out.writeBoolean(state.isResolved());
		// save the lazy data offset
		out.writeInt(out.size());
		for (int i = 0; i < bundles.length; i++)
			writeBundleDescriptionLazyData(bundles[i], out);
	}

	public void saveState(StateImpl state, File stateFile, File lazyFile) throws IOException {
		DataOutputStream outLazy = null;
		DataOutputStream outState = null;
		FileOutputStream fosLazy = null;
		FileOutputStream fosState = null;
		synchronized (state.monitor) {
			try {
				BundleDescription[] bundles = state.getBundles();
				StateHelperImpl.getInstance().sortBundles(bundles);
				// need to prime the object table with all bundles
				// this allows us to write only indexes to bundles in the lazy data
				for (int i = 0; i < bundles.length; i++) {
					addToObjectTable(bundles[i]);
					if (bundles[i].getHost() != null)
						addToObjectTable(bundles[i].getHost());
				}
				// first write the lazy data to get the offsets and sizes to the lazy data
				fosLazy = new FileOutputStream(lazyFile);
				outLazy = new DataOutputStream(new BufferedOutputStream(fosLazy));
				for (int i = 0; i < bundles.length; i++)
					writeBundleDescriptionLazyData(bundles[i], outLazy);
				// now write the state data
				fosState = new FileOutputStream(stateFile);
				outState = new DataOutputStream(new BufferedOutputStream(fosState));
				outState.write(StateReader.STATE_CACHE_VERSION);
				if (writePrefix(state, outState))
					return;
				outState.writeLong(state.getTimeStamp());
				// write the platform property keys
				String[] platformPropKeys = state.getPlatformPropertyKeys();
				writePlatformProp(platformPropKeys, outState);
				// write the platform property values
				Dictionary<Object, Object>[] propSet = state.getPlatformProperties();
				outState.writeInt(propSet.length);
				for (int i = 0; i < propSet.length; i++) {
					Dictionary<Object, Object> props = propSet[i];
					outState.writeInt(platformPropKeys.length);
					for (int j = 0; j < platformPropKeys.length; j++)
						writePlatformProp(props.get(platformPropKeys[j]), outState);
				}
				outState.writeInt(bundles.length);
				for (int i = 0; i < bundles.length; i++)
					// write out each bundle with the force flag set to make sure
					// the data is written at least once in the non-lazy state data
					writeBundleDescription(bundles[i], outState, true);
				// write the DisabledInfos
				DisabledInfo[] infos = state.getDisabledInfos();
				outState.writeInt(infos.length);
				for (int i = 0; i < infos.length; i++)
					writeDisabledInfo(infos[i], outState);
				outState.writeBoolean(state.isResolved());
			} finally {
				if (outLazy != null) {
					try {
						outLazy.flush();
						fosLazy.getFD().sync();
					} catch (IOException e) {
						// do nothing, we tried
					}
					try {
						outLazy.close();
					} catch (IOException e) {
						// do nothing
					}
				}
				if (outState != null) {
					try {
						outState.flush();
						fosState.getFD().sync();
					} catch (IOException e) {
						// do nothing, we tried
					}
					try {
						outState.close();
					} catch (IOException e) {
						// do nothing
					}
				}
			}
		}
	}

	private void writePlatformProp(Object obj, DataOutputStream out) throws IOException {
		if (!(obj instanceof String) && !(obj instanceof String[]))
			out.writeByte(StateReader.NULL);
		else {
			out.writeByte(StateReader.OBJECT);
			if (obj instanceof String) {
				out.writeInt(1);
				writeStringOrNull((String) obj, out);
			} else {
				String[] props = (String[]) obj;
				out.writeInt(props.length);
				for (int i = 0; i < props.length; i++)
					writeStringOrNull(props[i], out);
			}
		}
	}

	/*
	 * The force flag is used when writing the non-lazy state data.  This forces the data to be
	 * written once even if the object exists in the object table.
	 * This is needed because we want to write the lazy data first but we only want
	 * to include indexes to the actual bundles in the lazy data.  To do this we
	 * prime the object table with all the bundles first.  Then we write the
	 * lazy data.  Finally we write the non-lazy data and force a write of the
	 * bundles data once even if the bundle is in the object table.
	 */
	private void writeBundleDescription(BundleDescription bundle, DataOutputStream out, boolean force) throws IOException {
		if (force && !forcedWrite.contains(bundle)) {
			int index = addToObjectTable(bundle);
			out.writeByte(StateReader.OBJECT);
			out.writeInt(index);
			forcedWrite.add(bundle);
		} else if (writePrefix(bundle, out))
			return;
		// first write out non-lazy loaded data
		out.writeLong(bundle.getBundleId()); // ID must be the first thing
		writeBaseDescription(bundle, out);
		out.writeInt(((BundleDescriptionImpl) bundle).getLazyDataOffset());
		out.writeInt(((BundleDescriptionImpl) bundle).getLazyDataSize());
		out.writeBoolean(bundle.isResolved());
		out.writeBoolean(bundle.isSingleton());
		out.writeBoolean(bundle.hasDynamicImports());
		out.writeBoolean(bundle.attachFragments());
		out.writeBoolean(bundle.dynamicFragments());
		writeList(out, (String[]) ((BundleDescriptionImpl) bundle).getDirective(Constants.MANDATORY_DIRECTIVE));
		writeMap(out, bundle.getAttributes());
		writeMap(out, ((BundleDescriptionImpl) bundle).getArbitraryDirectives());
		writeHostSpec((HostSpecificationImpl) bundle.getHost(), out, force);

		List<BundleDescription> dependencies = ((BundleDescriptionImpl) bundle).getBundleDependencies();
		out.writeInt(dependencies.size());
		for (Iterator<BundleDescription> iter = dependencies.iterator(); iter.hasNext();)
			writeBundleDescription(iter.next(), out, force);
		// the rest is lazy loaded data
	}

	private void writeBundleDescriptionLazyData(BundleDescription bundle, DataOutputStream out) throws IOException {
		int dataStart = out.size(); // save the offset of lazy data start
		int index = getFromObjectTable(bundle);
		((BundleDescriptionImpl) bundle).setLazyDataOffset(out.size());
		out.writeInt(index);

		writeStringOrNull(bundle.getLocation(), out);
		writeStringOrNull(bundle.getPlatformFilter(), out);

		ExportPackageDescription[] exports = bundle.getExportPackages();
		out.writeInt(exports.length);
		for (int i = 0; i < exports.length; i++)
			writeExportPackageDesc((ExportPackageDescriptionImpl) exports[i], out);

		ImportPackageSpecification[] imports = bundle.getImportPackages();
		out.writeInt(imports.length);
		for (int i = 0; i < imports.length; i++)
			writeImportPackageSpec((ImportPackageSpecificationImpl) imports[i], out);

		BundleSpecification[] requiredBundles = bundle.getRequiredBundles();
		out.writeInt(requiredBundles.length);
		for (int i = 0; i < requiredBundles.length; i++)
			writeBundleSpec((BundleSpecificationImpl) requiredBundles[i], out);

		ExportPackageDescription[] selectedExports = bundle.getSelectedExports();
		if (selectedExports == null) {
			out.writeInt(0);
		} else {
			out.writeInt(selectedExports.length);
			for (int i = 0; i < selectedExports.length; i++)
				writeExportPackageDesc((ExportPackageDescriptionImpl) selectedExports[i], out);
		}

		ExportPackageDescription[] substitutedExports = bundle.getSubstitutedExports();
		if (substitutedExports == null) {
			out.writeInt(0);
		} else {
			out.writeInt(substitutedExports.length);
			for (int i = 0; i < substitutedExports.length; i++)
				writeExportPackageDesc((ExportPackageDescriptionImpl) substitutedExports[i], out);
		}

		ExportPackageDescription[] resolvedImports = bundle.getResolvedImports();
		if (resolvedImports == null) {
			out.writeInt(0);
		} else {
			out.writeInt(resolvedImports.length);
			for (int i = 0; i < resolvedImports.length; i++)
				writeExportPackageDesc((ExportPackageDescriptionImpl) resolvedImports[i], out);
		}

		BundleDescription[] resolvedRequires = bundle.getResolvedRequires();
		if (resolvedRequires == null) {
			out.writeInt(0);
		} else {
			out.writeInt(resolvedRequires.length);
			for (int i = 0; i < resolvedRequires.length; i++)
				writeBundleDescription(resolvedRequires[i], out, false);
		}

		String[] ees = bundle.getExecutionEnvironments();
		out.writeInt(ees.length);
		for (int i = 0; i < ees.length; i++)
			writeStringOrNull(ees[i], out);

		Map<String, Long> dynamicStamps = ((BundleDescriptionImpl) bundle).getDynamicStamps();
		if (dynamicStamps == null)
			out.writeInt(0);
		else {
			out.writeInt(dynamicStamps.size());
			for (Iterator<String> pkgs = dynamicStamps.keySet().iterator(); pkgs.hasNext();) {
				String pkg = pkgs.next();
				writeStringOrNull(pkg, out);
				out.writeLong(dynamicStamps.get(pkg).longValue());
			}
		}

		GenericDescription[] genericCapabilities = bundle.getGenericCapabilities();
		if (genericCapabilities == null)
			out.writeInt(0);
		else {
			out.writeInt(genericCapabilities.length);
			for (int i = 0; i < genericCapabilities.length; i++)
				writeGenericDescription(genericCapabilities[i], out);
		}

		GenericSpecification[] genericRequires = bundle.getGenericRequires();
		if (genericRequires == null)
			out.writeInt(0);
		else {
			out.writeInt(genericRequires.length);
			for (int i = 0; i < genericRequires.length; i++)
				writeGenericSpecification((GenericSpecificationImpl) genericRequires[i], out);
		}

		GenericDescription[] selectedCapabilities = bundle.getSelectedGenericCapabilities();
		if (selectedCapabilities == null)
			out.writeInt(0);
		else {
			out.writeInt(selectedCapabilities.length);
			for (int i = 0; i < selectedCapabilities.length; i++)
				writeGenericDescription(selectedCapabilities[i], out);
		}

		GenericDescription[] resolvedCapabilities = bundle.getResolvedGenericRequires();
		if (resolvedCapabilities == null)
			out.writeInt(0);
		else {
			out.writeInt(resolvedCapabilities.length);
			for (int i = 0; i < resolvedCapabilities.length; i++)
				writeGenericDescription(resolvedCapabilities[i], out);
		}

		writeNativeCode(bundle.getNativeCodeSpecification(), out);

		writeMap(out, ((BundleDescriptionImpl) bundle).getWiresInternal());
		// save the size of the lazy data
		((BundleDescriptionImpl) bundle).setLazyDataSize(out.size() - dataStart);
	}

	private void writeDisabledInfo(DisabledInfo disabledInfo, DataOutputStream out) throws IOException {
		writeStringOrNull(disabledInfo.getPolicyName(), out);
		writeStringOrNull(disabledInfo.getMessage(), out);
		writeBundleDescription(disabledInfo.getBundle(), out, false);
	}

	private void writeBundleSpec(BundleSpecificationImpl bundle, DataOutputStream out) throws IOException {
		if (writePrefix(bundle, out))
			return;
		writeVersionConstraint(bundle, out);
		writeBundleDescription((BundleDescription) bundle.getSupplier(), out, false);
		out.writeBoolean(bundle.isExported());
		out.writeBoolean(bundle.isOptional());
		writeMap(out, bundle.getAttributes());
		writeMap(out, bundle.getArbitraryDirectives());
	}

	private void writeExportPackageDesc(ExportPackageDescriptionImpl exportPackageDesc, DataOutputStream out) throws IOException {
		if (writePrefix(exportPackageDesc, out))
			return;
		writeBaseDescription(exportPackageDesc, out);
		writeBundleDescription(exportPackageDesc.getExporter(), out, false);
		writeMap(out, exportPackageDesc.getAttributes());
		writeMap(out, exportPackageDesc.getDirectives());
		writeMap(out, exportPackageDesc.getArbitraryDirectives());
		writeExportPackageDesc((ExportPackageDescriptionImpl) exportPackageDesc.getFragmentDeclaration(), out);
	}

	private void writeGenericDescription(GenericDescription description, DataOutputStream out) throws IOException {
		if (writePrefix(description, out))
			return;
		writeBaseDescription(description, out);
		writeBundleDescription(description.getSupplier(), out, false);
		writeStringOrNull(description.getType() == GenericDescription.DEFAULT_TYPE ? null : description.getType(), out);
		Dictionary<String, Object> attrs = description.getAttributes();
		Map<String, Object> mapAttrs = new HashMap<>(attrs.size());
		for (Enumeration<String> keys = attrs.keys(); keys.hasMoreElements();) {
			String key = keys.nextElement();
			mapAttrs.put(key, attrs.get(key));
		}
		writeMap(out, mapAttrs);
		Map<String, String> directives = description.getDeclaredDirectives();
		writeMap(out, directives);
		writeGenericDescription((GenericDescription) ((BaseDescriptionImpl) description).getFragmentDeclaration(), out);
	}

	private void writeGenericSpecification(GenericSpecificationImpl specification, DataOutputStream out) throws IOException {
		if (writePrefix(specification, out))
			return;
		writeVersionConstraint(specification, out);
		writeStringOrNull(specification.getType() == GenericDescription.DEFAULT_TYPE ? null : specification.getType(), out);
		GenericDescription[] suppliers = specification.getSuppliers();
		out.writeInt(suppliers == null ? 0 : suppliers.length);
		if (suppliers != null)
			for (int i = 0; i < suppliers.length; i++)
				writeGenericDescription(suppliers[i], out);
		out.writeInt(specification.getResolution());
		writeStringOrNull(specification.getMatchingFilter(), out);
		writeMap(out, specification.getAttributes());
		writeMap(out, specification.getArbitraryDirectives());
	}

	private void writeNativeCode(NativeCodeSpecification nativeCodeSpecification, DataOutputStream out) throws IOException {
		if (nativeCodeSpecification == null) {
			out.writeBoolean(false);
			return;
		}
		out.writeBoolean(true);
		out.writeBoolean(nativeCodeSpecification.isOptional());
		NativeCodeDescription[] nativeDescs = nativeCodeSpecification.getPossibleSuppliers();
		int numDescs = nativeDescs == null ? 0 : nativeDescs.length;
		out.writeInt(numDescs);
		int supplierIndex = -1;
		for (int i = 0; i < numDescs; i++) {
			if (nativeDescs[i] == nativeCodeSpecification.getSupplier())
				supplierIndex = i;
			writeNativeCodeDescription(nativeDescs[i], out);
		}
		out.writeInt(supplierIndex);
	}

	private void writeNativeCodeDescription(NativeCodeDescription nativeCodeDescription, DataOutputStream out) throws IOException {
		writeBaseDescription(nativeCodeDescription, out);
		writeBundleDescription(nativeCodeDescription.getSupplier(), out, false);
		Filter filter = nativeCodeDescription.getFilter();
		writeStringOrNull(filter == null ? null : filter.toString(), out);
		writeStringArray(nativeCodeDescription.getLanguages(), out);
		writeStringArray(nativeCodeDescription.getNativePaths(), out);
		writeStringArray(nativeCodeDescription.getOSNames(), out);
		writeVersionRanges(nativeCodeDescription.getOSVersions(), out);
		writeStringArray(nativeCodeDescription.getProcessors(), out);
		out.writeBoolean(nativeCodeDescription.hasInvalidNativePaths());
	}

	private void writeVersionRanges(VersionRange[] ranges, DataOutputStream out) throws IOException {
		out.writeInt(ranges == null ? 0 : ranges.length);
		if (ranges == null)
			return;
		for (int i = 0; i < ranges.length; i++)
			writeVersionRange(ranges[i], out);
	}

	private void writeStringArray(String[] strings, DataOutputStream out) throws IOException {
		out.writeInt(strings == null ? 0 : strings.length);
		if (strings == null)
			return;
		for (int i = 0; i < strings.length; i++)
			writeStringOrNull(strings[i], out);
	}

	private void writeMap(DataOutputStream out, Map<String, ?> source) throws IOException {
		if (source == null) {
			out.writeInt(0);
		} else {
			out.writeInt(source.size());
			Iterator<String> iter = source.keySet().iterator();
			while (iter.hasNext()) {
				String key = iter.next();
				Object value = source.get(key);
				writeStringOrNull(key, out);
				if (value instanceof String) {
					out.writeByte(0);
					writeStringOrNull((String) value, out);
				} else if (value instanceof String[]) {
					out.writeByte(1);
					writeList(out, (String[]) value);
				} else if (value instanceof Boolean) {
					out.writeByte(2);
					out.writeBoolean(((Boolean) value).booleanValue());
				} else if (value instanceof Integer) {
					out.writeByte(3);
					out.writeInt(((Integer) value).intValue());
				} else if (value instanceof Long) {
					out.writeByte(4);
					out.writeLong(((Long) value).longValue());
				} else if (value instanceof Double) {
					out.writeByte(5);
					out.writeDouble(((Double) value).doubleValue());
				} else if (value instanceof Version) {
					out.writeByte(6);
					writeVersion((Version) value, out);
				} else if ("java.net.URI".equals(value.getClass().getName())) { //$NON-NLS-1$
					out.writeByte(7);
					writeStringOrNull(value.toString(), out);
				} else if (value instanceof List) {
					writeList(out, (List<?>) value);
				}
			}
		}
	}

	private void writeList(DataOutputStream out, List<?> list) throws IOException {
		byte type = getListType(list);
		if (type == -2)
			return; // don't understand the list type
		out.writeByte(8);
		out.writeByte(type);
		out.writeInt(list.size());
		for (Object value : list) {
			switch (type) {
				case 0 :
					writeStringOrNull((String) value, out);
					break;
				case 3 :
					out.writeInt(((Integer) value).intValue());
					break;
				case 4 :
					out.writeLong(((Long) value).longValue());
					break;
				case 5 :
					out.writeDouble(((Double) value).doubleValue());
					break;
				case 6 :
					writeVersion((Version) value, out);
					break;
				case 7 :
					writeStateWire((StateWire) value, out);
				default :
					break;
			}
		}
	}

	private void writeStateWire(StateWire wire, DataOutputStream out) throws IOException {
		VersionConstraint requirement = wire.getDeclaredRequirement();
		if (requirement instanceof ImportPackageSpecificationImpl) {
			out.writeByte(0);
			writeImportPackageSpec((ImportPackageSpecificationImpl) requirement, out);
		} else if (requirement instanceof BundleSpecificationImpl) {
			out.writeByte(1);
			writeBundleSpec((BundleSpecificationImpl) requirement, out);
		} else if (requirement instanceof HostSpecificationImpl) {
			out.writeByte(2);
			writeHostSpec((HostSpecificationImpl) requirement, out, false);
		} else if (requirement instanceof GenericSpecificationImpl) {
			out.writeByte(3);
			writeGenericSpecification((GenericSpecificationImpl) requirement, out);
		} else
			throw new IllegalArgumentException("Unknown requiement type: " + requirement.getClass()); //$NON-NLS-1$

		BaseDescription capability = wire.getDeclaredCapability();
		if (capability instanceof BundleDescription)
			writeBundleDescription((BundleDescription) capability, out, false);
		else if (capability instanceof ExportPackageDescriptionImpl)
			writeExportPackageDesc((ExportPackageDescriptionImpl) capability, out);
		else if (capability instanceof GenericDescription)
			writeGenericDescription((GenericDescription) capability, out);
		else
			throw new IllegalArgumentException("Unknown capability type: " + requirement.getClass()); //$NON-NLS-1$

		writeBundleDescription(wire.getRequirementHost(), out, false);
		writeBundleDescription(wire.getCapabilityHost(), out, false);
	}

	private byte getListType(List<?> list) {
		if (list.size() == 0)
			return -1;
		Object type = list.get(0);
		if (type instanceof String)
			return 0;
		if (type instanceof Integer)
			return 3;
		if (type instanceof Long)
			return 4;
		if (type instanceof Double)
			return 5;
		if (type instanceof Version)
			return 6;
		if (type instanceof StateWire)
			return 7;
		return -2;
	}

	private void writeList(DataOutputStream out, String[] list) throws IOException {
		if (list == null) {
			out.writeInt(0);
		} else {
			out.writeInt(list.length);
			for (int i = 0; i < list.length; i++)
				writeStringOrNull(list[i], out);
		}
	}

	private void writeBaseDescription(BaseDescription rootDesc, DataOutputStream out) throws IOException {
		writeStringOrNull(rootDesc.getName(), out);
		writeVersion(rootDesc.getVersion(), out);
	}

	private void writeImportPackageSpec(ImportPackageSpecificationImpl importPackageSpec, DataOutputStream out) throws IOException {
		if (writePrefix(importPackageSpec, out))
			return;
		writeVersionConstraint(importPackageSpec, out);
		// TODO this is a hack until the state dynamic loading is cleaned up
		// we should only write the supplier if we are resolved
		if (importPackageSpec.getBundle().isResolved())
			writeExportPackageDesc((ExportPackageDescriptionImpl) importPackageSpec.getSupplier(), out);
		else
			out.writeByte(StateReader.NULL);

		writeStringOrNull(importPackageSpec.getBundleSymbolicName(), out);
		writeVersionRange(importPackageSpec.getBundleVersionRange(), out);
		writeMap(out, importPackageSpec.getAttributes());
		writeMap(out, importPackageSpec.getDirectives());
		writeMap(out, importPackageSpec.getArbitraryDirectives());
	}

	private void writeHostSpec(HostSpecificationImpl host, DataOutputStream out, boolean force) throws IOException {
		if (host != null && force && !forcedWrite.contains(host)) {
			int index = addToObjectTable(host);
			out.writeByte(StateReader.OBJECT);
			out.writeInt(index);
			forcedWrite.add(host);
		} else if (writePrefix(host, out))
			return;
		writeVersionConstraint(host, out);
		BundleDescription[] hosts = host.getHosts();
		if (hosts == null) {
			out.writeInt(0);
			return;
		}
		out.writeInt(hosts.length);
		for (int i = 0; i < hosts.length; i++)
			writeBundleDescription(hosts[i], out, force);
		writeMap(out, host.getAttributes());
		writeMap(out, host.getArbitraryDirectives());
	}

	// called by writers for VersionConstraintImpl subclasses
	private void writeVersionConstraint(VersionConstraint constraint, DataOutputStream out) throws IOException {
		writeStringOrNull(constraint.getName(), out);
		writeVersionRange(constraint.getVersionRange(), out);
	}

	private void writeVersion(Version version, DataOutputStream out) throws IOException {
		if (version == null || version.equals(Version.emptyVersion)) {
			out.writeByte(StateReader.NULL);
			return;
		}
		out.writeByte(StateReader.OBJECT);
		out.writeInt(version.getMajor());
		out.writeInt(version.getMinor());
		out.writeInt(version.getMicro());
		writeQualifier(version.getQualifier(), out);
	}

	private void writeVersionRange(VersionRange versionRange, DataOutputStream out) throws IOException {
		if (versionRange == null || versionRange.equals(VersionRange.emptyRange)) {
			out.writeByte(StateReader.NULL);
			return;
		}
		out.writeByte(StateReader.OBJECT);
		writeVersion(versionRange.getMinimum(), out);
		out.writeBoolean(versionRange.getIncludeMinimum());
		writeVersion(versionRange.getMaximum(), out);
		out.writeBoolean(versionRange.getIncludeMaximum());
	}

	private boolean writeIndex(Object object, DataOutputStream out) throws IOException {
		if (object == null) {
			out.writeByte(StateReader.NULL);
			return true;
		}
		int index = getFromObjectTable(object);
		if (index == -1)
			return false;
		out.writeByte(StateReader.INDEX);
		out.writeInt(index);
		return true;
	}

	public void saveStateDeprecated(StateImpl state, DataOutputStream output) throws IOException {
		synchronized (state.monitor) {
			try {
				writeStateDeprecated(state, output);
			} finally {
				output.close();
			}
		}
	}

	private void writeStringOrNull(String string, DataOutputStream out) throws IOException {
		if (string == null)
			out.writeByte(StateReader.NULL);
		else {
			byte[] data = string.getBytes(StateReader.UTF_8);

			if (data.length > 65535) {
				out.writeByte(StateReader.LONG_STRING);
				out.writeInt(data.length);
				out.write(data);
			} else {
				out.writeByte(StateReader.OBJECT);
				out.writeUTF(string);
			}
		}
	}

	private void writeQualifier(String string, DataOutputStream out) throws IOException {
		if (string != null && string.length() == 0)
			string = null;
		writeStringOrNull(string, out);
	}
}
