blob: 88e85ba4f509a843b44ba07fd3cf3241e90edade [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2003, 2013 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* 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<Object, Integer>();
private final List<Object> forcedWrite = new ArrayList<Object>();
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<String, Object>(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());
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());
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);
}
}