blob: e19000679e32ade25187987869bdf3b6ee3cde9d [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2003, 2004 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.osgi.internal.resolver;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.osgi.service.resolver.*;
class StateWriter {
// TODO not sure this comment applies anymore
// objectTable will be a hashmap of objects. The objects will be things
// like a plugin descriptor, extension, extension point, etc. The integer
// index value will be used in the cache to allow cross-references in the
// cached registry.
protected Map objectTable = new HashMap();
public static final byte NULL = 0;
public static final byte OBJECT = 1;
public static final byte INDEX = 2;
private int addToObjectTable(Object object) {
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
addToObjectTable(object);
out.writeByte(OBJECT);
return false;
}
private void writeState(StateImpl state, DataOutputStream out) throws IOException {
out.write(StateReader.STATE_CACHE_VERSION);
if (writePrefix(state, out))
return;
out.writeLong(state.getTimeStamp());
BundleDescription[] bundles = state.getBundles();
out.writeInt(bundles.length);
if (bundles.length == 0)
return;
for (int i = 0; i < bundles.length; i++)
writeBundleDescription((BundleDescriptionImpl) bundles[i], out);
out.writeBoolean(state.isResolved());
if (!state.isResolved())
return;
BundleDescription[] resolvedBundles = state.getResolvedBundles();
out.writeInt(resolvedBundles.length);
for (int i = 0; i < resolvedBundles.length; i++)
writeBundleDescription((BundleDescriptionImpl) resolvedBundles[i], out);
}
private void writeBundleDescription(BundleDescriptionImpl bundle, DataOutputStream out) throws IOException {
if (writePrefix(bundle, out))
return;
out.writeLong(bundle.getBundleId());
writeStringOrNull(bundle.getUniqueId(), out);
writeStringOrNull(bundle.getLocation(), out);
out.writeInt(bundle.getState());
writeVersion(bundle.getVersion(), out);
writeHostSpec((HostSpecificationImpl) bundle.getHost(), out);
PackageSpecification[] packages = bundle.getPackages();
out.writeInt(packages.length);
for (int i = 0; i < packages.length; i++)
writePackageSpec((PackageSpecificationImpl) packages[i], out);
String[] providedPackages = bundle.getProvidedPackages();
out.writeInt(providedPackages.length);
for (int i = 0; i < providedPackages.length; i++)
out.writeUTF(providedPackages[i]);
BundleSpecification[] requiredBundles = bundle.getRequiredBundles();
out.writeInt(requiredBundles.length);
for (int i = 0; i < requiredBundles.length; i++)
writeBundleSpec((BundleSpecificationImpl) requiredBundles[i], out);
out.writeBoolean(bundle.isSingleton());
}
private void writeBundleSpec(BundleSpecificationImpl bundle, DataOutputStream out) throws IOException {
writeVersionConstraint(bundle, out);
out.writeBoolean(bundle.isExported());
out.writeBoolean(bundle.isOptional());
}
private void writePackageSpec(PackageSpecificationImpl packageSpec, DataOutputStream out) throws IOException {
writeVersionConstraint(packageSpec, out);
out.writeBoolean(packageSpec.isExported());
}
private void writeHostSpec(HostSpecificationImpl host, DataOutputStream out) throws IOException {
if (host == null) {
out.writeByte(NULL);
return;
}
out.writeByte(OBJECT);
writeVersionConstraint(host, out);
out.writeBoolean(host.reloadHost());
}
// called by writers for VersionConstraintImpl subclasses
private void writeVersionConstraint(VersionConstraintImpl version, DataOutputStream out) throws IOException {
writeStringOrNull(version.getName(), out);
writeVersion(version.getVersionSpecification(), out);
out.writeByte(version.getMatchingRule());
writeVersion(version.getActualVersion(), out);
writeBundleDescription((BundleDescriptionImpl) version.getSupplier(), out);
}
private void writeVersion(Version version, DataOutputStream out) throws IOException {
// TODO: should assess whether avoiding sharing versions would be good
if (writePrefix(version, out))
return;
out.writeInt(version.getMajorComponent());
out.writeInt(version.getMinorComponent());
out.writeInt(version.getMicroComponent());
writeStringOrNull(version.getQualifierComponent(), out);
}
private boolean writeIndex(Object object, DataOutputStream out) throws IOException {
if (object == null) {
out.writeByte(NULL);
return true;
}
int index = getFromObjectTable(object);
if (index == -1)
return false;
out.writeByte(INDEX);
out.writeInt(index);
return true;
}
public void saveState(StateImpl state, DataOutputStream output) throws IOException {
try {
writeState(state, output);
} finally {
output.close();
}
}
private void writeStringOrNull(String string, DataOutputStream out) throws IOException {
if (string == null)
out.writeByte(NULL);
else {
out.writeByte(OBJECT);
out.writeUTF(string);
}
}
}