Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'bundles/org.eclipse.equinox.framework/impl/org/eclipse/osgi/container/ModuleDataBase.java')
-rw-r--r--bundles/org.eclipse.equinox.framework/impl/org/eclipse/osgi/container/ModuleDataBase.java373
1 files changed, 363 insertions, 10 deletions
diff --git a/bundles/org.eclipse.equinox.framework/impl/org/eclipse/osgi/container/ModuleDataBase.java b/bundles/org.eclipse.equinox.framework/impl/org/eclipse/osgi/container/ModuleDataBase.java
index 81d98b651..894b67326 100644
--- a/bundles/org.eclipse.equinox.framework/impl/org/eclipse/osgi/container/ModuleDataBase.java
+++ b/bundles/org.eclipse.equinox.framework/impl/org/eclipse/osgi/container/ModuleDataBase.java
@@ -11,9 +11,14 @@
package org.eclipse.osgi.container;
import java.io.*;
+import java.net.URI;
+import java.net.URISyntaxException;
import java.util.*;
import java.util.concurrent.atomic.AtomicLong;
+import org.eclipse.osgi.framework.util.ObjectPool;
import org.osgi.framework.Version;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Requirement;
/**
* A database for storing modules, their revisions and wiring states. The
@@ -54,12 +59,12 @@ public abstract class ModuleDataBase {
/**
* Holds the next id to be assigned to a module when it is installed
*/
- private final AtomicLong nextId;
+ final AtomicLong nextId;
/**
* Holds the current timestamp of this database.
*/
- private final AtomicLong timeStamp;
+ final AtomicLong timeStamp;
/**
* Monitors read and write access to this database
@@ -88,7 +93,7 @@ public abstract class ModuleDataBase {
if (this.container != null)
throw new IllegalStateException("The container is already set."); //$NON-NLS-1$
if (container.moduleDataBase != this) {
- throw new IllegalArgumentException("Container is already using a different database.");
+ throw new IllegalArgumentException("Container is already using a different database."); //$NON-NLS-1$
}
this.container = container;
}
@@ -146,18 +151,22 @@ public abstract class ModuleDataBase {
* @return the installed module
*/
final Module install(String location, ModuleRevisionBuilder builder) {
+ Module module = load(location, builder, getNextIdAndIncrement());
+ incrementTimestamp();
+ return module;
+ }
+
+ final Module load(String location, ModuleRevisionBuilder builder, long id) {
if (container == null)
throw new IllegalStateException("Container is not set."); //$NON-NLS-1$
if (modulesByLocations.get(location) != null)
throw new IllegalArgumentException("Location is already used."); //$NON-NLS-1$
- long id = getNextIdAndIncrement();
Module module = createModule(location, id);
ModuleRevision newRevision = builder.buildRevision(id, location, module, container);
modulesByLocations.put(location, module);
modulesById.put(id, module);
addToRevisionByName(newRevision);
addCapabilities(newRevision);
- incrementTimestamp();
return module;
}
@@ -439,27 +448,371 @@ public abstract class ModuleDataBase {
protected abstract Module createModule(String location, long id);
protected void write(DataOutputStream out, boolean persistWirings) throws IOException {
- Persistence.write(this, out, persistWirings);
+ lockRead(false);
+ try {
+ Persistence.write(this, out, persistWirings);
+ } finally {
+ unlockRead(false);
+ }
}
protected void load(DataInputStream in) throws IOException {
- Persistence.load(this, in);
+ lockWrite();
+ try {
+ Persistence.load(this, in);
+ } finally {
+ unlockWrite();
+ }
}
private static class Persistence {
private static final int VERSION = 1;
+ private static final byte NULL = 0;
+ private static final byte OBJECT = 1;
+ private static final byte INDEX = 2;
+ private static final byte LONG_STRING = 3;
+ private static final String UTF_8 = "UTF-8"; //$NON-NLS-1$
+
+ private static final byte VALUE_STRING = 0;
+ private static final byte VALUE_STRING_ARRAY = 1;
+ private static final byte VAlUE_BOOLEAN = 2;
+ private static final byte VALUE_INTEGER = 3;
+ private static final byte VALUE_LONG = 4;
+ private static final byte VALUE_DOUBLE = 5;
+ private static final byte VALUE_VERSION = 6;
+ private static final byte VALUE_URI = 7;
+ private static final byte VALUE_LIST = 8;
public static void write(ModuleDataBase moduleDataBase, DataOutputStream out, boolean persistWirings) throws IOException {
- out.write(VERSION);
+ out.writeInt(VERSION);
+ out.writeLong(moduleDataBase.getTimestamp());
out.writeLong(moduleDataBase.getNextId());
- Collection<Module> modules = moduleDataBase.getModules();
+ List<Module> modules = moduleDataBase.getModules();
+ out.writeInt(modules.size());
+ for (Module module : modules) {
+ writeModule(module, out);
+ }
}
public static void load(ModuleDataBase moduleDataBase, DataInputStream in) throws IOException {
int version = in.readInt();
if (version < VERSION)
- throw new UnsupportedOperationException("Perstence version is not correct for loading: " + version + " expecting: " + VERSION);
+ throw new UnsupportedOperationException("Perstence version is not correct for loading: " + version + " expecting: " + VERSION); //$NON-NLS-1$ //$NON-NLS-2$
+ moduleDataBase.timeStamp.set(in.readLong());
+ moduleDataBase.nextId.set(in.readLong());
+ int numModules = in.readInt();
+
+ for (int i = 0; i < numModules; i++) {
+ readModule(moduleDataBase, in);
+ }
+ }
+
+ private static void writeModule(Module module, DataOutputStream out) throws IOException {
+ ModuleRevision current = module.getCurrentRevision();
+ if (current == null)
+ return;
+ ModuleRevisions revisions = module.getRevisions();
+
+ writeString(revisions.getLocation(), out);
+ out.writeLong(revisions.getId());
+ writeString(current.getSymbolicName(), out);
+ writeVersion(current.getVersion(), out);
+ out.writeInt(current.getTypes());
+
+ List<Capability> capabilities = current.getCapabilities(null);
+ out.writeInt(capabilities.size());
+ for (Capability capability : capabilities) {
+ writeGenericInfo(capability.getNamespace(), capability.getAttributes(), capability.getDirectives(), out);
+ }
+
+ List<Requirement> requirements = current.getRequirements(null);
+ out.writeInt(requirements.size());
+ for (Requirement requirement : requirements) {
+ writeGenericInfo(requirement.getNamespace(), requirement.getAttributes(), requirement.getDirectives(), out);
+ }
+ }
+
+ private static void readModule(ModuleDataBase moduleDataBase, DataInputStream in) throws IOException {
+ ModuleRevisionBuilder builder = new ModuleRevisionBuilder();
+ String location = readString(in);
+ long id = in.readLong();
+ builder.setSymbolicName(readString(in));
+ builder.setVersion(readVersion(in));
+ builder.setTypes(in.readInt());
+
+ int numCapabilities = in.readInt();
+ for (int i = 0; i < numCapabilities; i++) {
+ readGenericInfo(true, in, builder);
+ }
+
+ int numRequirements = in.readInt();
+ for (int i = 0; i < numRequirements; i++) {
+ readGenericInfo(false, in, builder);
+ }
+ moduleDataBase.load(location, builder, id);
+ }
+
+ private static void writeGenericInfo(String namespace, Map<String, ?> attributes, Map<String, String> directives, DataOutputStream out) throws IOException {
+ writeString(namespace, out);
+ writeMap(attributes, out);
+ writeMap(directives, out);
+ }
+
+ @SuppressWarnings("unchecked")
+ private static void readGenericInfo(boolean isCapability, DataInputStream in, ModuleRevisionBuilder builder) throws IOException {
+ String namespace = readString(in);
+ Map<String, Object> attributes = readMap(in);
+ Map<String, ?> directives = readMap(in);
+ if (isCapability) {
+ builder.addCapability(namespace, (Map<String, String>) directives, attributes);
+ } else {
+ builder.addRequirement(namespace, (Map<String, String>) directives, attributes);
+ }
+
}
+ private static void writeMap(Map<String, ?> source, DataOutputStream out) 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);
+ writeString(key, out);
+ if (value instanceof String) {
+ out.writeByte(VALUE_STRING);
+ writeString((String) value, out);
+ } else if (value instanceof String[]) {
+ out.writeByte(VALUE_STRING_ARRAY);
+ writeStringArray(out, (String[]) value);
+ } else if (value instanceof Boolean) {
+ out.writeByte(VAlUE_BOOLEAN);
+ out.writeBoolean(((Boolean) value).booleanValue());
+ } else if (value instanceof Integer) {
+ out.writeByte(VALUE_INTEGER);
+ out.writeInt(((Integer) value).intValue());
+ } else if (value instanceof Long) {
+ out.writeByte(VALUE_LONG);
+ out.writeLong(((Long) value).longValue());
+ } else if (value instanceof Double) {
+ out.writeByte(VALUE_DOUBLE);
+ out.writeDouble(((Double) value).doubleValue());
+ } else if (value instanceof Version) {
+ out.writeByte(VALUE_VERSION);
+ writeVersion((Version) value, out);
+ } else if (value instanceof URI) {
+ out.writeByte(VALUE_URI);
+ writeString(value.toString(), out);
+ } else if (value instanceof List) {
+ out.writeByte(VALUE_LIST);
+ writeList(out, (List<?>) value);
+ }
+ }
+ }
+ }
+
+ private static Map<String, Object> readMap(DataInputStream in) throws IOException {
+ int count = in.readInt();
+ HashMap<String, Object> result = new HashMap<String, Object>(count);
+ for (int i = 0; i < count; i++) {
+ String key = readString(in);
+ Object value = null;
+ byte type = in.readByte();
+ if (type == VALUE_STRING)
+ value = readString(in);
+ else if (type == VALUE_STRING_ARRAY)
+ value = readStringArray(in);
+ else if (type == VAlUE_BOOLEAN)
+ value = in.readBoolean() ? Boolean.TRUE : Boolean.FALSE;
+ else if (type == VALUE_INTEGER)
+ value = new Integer(in.readInt());
+ else if (type == VALUE_LONG)
+ value = new Long(in.readLong());
+ else if (type == VALUE_DOUBLE)
+ value = new Double(in.readDouble());
+ else if (type == VALUE_VERSION)
+ value = readVersion(in);
+ else if (type == VALUE_URI)
+ try {
+ value = new URI(readString(in));
+ } catch (URISyntaxException e) {
+ value = null;
+ }
+ else if (type == VALUE_LIST)
+ value = readList(in);
+
+ result.put(key, value);
+ }
+ return result;
+ }
+
+ private static void writeStringArray(DataOutputStream out, String[] value) throws IOException {
+ if (value == null) {
+ out.writeInt(0);
+ } else {
+ out.writeInt(value.length);
+ for (int i = 0; i < value.length; i++)
+ writeString(value[i], out);
+ }
+
+ }
+
+ private static String[] readStringArray(DataInputStream in) throws IOException {
+ int count = in.readInt();
+ if (count == 0)
+ return null;
+ String[] result = new String[count];
+ for (int i = 0; i < count; i++)
+ result[i] = readString(in);
+ return result;
+ }
+
+ private static void writeList(DataOutputStream out, List<?> list) throws IOException {
+ if (list.isEmpty()) {
+ out.writeInt(0);
+ return;
+ }
+ byte type = getListType(list);
+ if (type < 0) {
+ out.writeInt(0);
+ return; // don't understand the list type
+ }
+ out.writeInt(list.size());
+ out.writeByte(type);
+ for (Object value : list) {
+ switch (type) {
+ case VALUE_STRING :
+ writeString((String) value, out);
+ break;
+ case VALUE_INTEGER :
+ out.writeInt(((Integer) value).intValue());
+ break;
+ case VALUE_LONG :
+ out.writeLong(((Long) value).longValue());
+ break;
+ case VALUE_DOUBLE :
+ out.writeDouble(((Double) value).doubleValue());
+ break;
+ case VALUE_VERSION :
+ writeVersion((Version) value, out);
+ break;
+ default :
+ break;
+ }
+ }
+ }
+
+ private static byte getListType(List<?> list) {
+ if (list.size() == 0)
+ return -1;
+ Object type = list.get(0);
+ if (type instanceof String)
+ return VALUE_STRING;
+ if (type instanceof Integer)
+ return VALUE_INTEGER;
+ if (type instanceof Long)
+ return VALUE_LONG;
+ if (type instanceof Double)
+ return VALUE_DOUBLE;
+ if (type instanceof Version)
+ return VALUE_VERSION;
+ return -2;
+ }
+
+ private static List<?> readList(DataInputStream in) throws IOException {
+
+ int size = in.readInt();
+ if (size == 0)
+ return new ArrayList<Object>(0);
+ byte listType = in.readByte();
+ List<Object> list = new ArrayList<Object>(size);
+ for (int i = 0; i < size; i++) {
+ switch (listType) {
+ case VALUE_STRING :
+ list.add(readString(in));
+ break;
+ case VALUE_INTEGER :
+ list.add(new Integer(in.readInt()));
+ break;
+ case VALUE_LONG :
+ list.add(new Long(in.readLong()));
+ break;
+ case VALUE_DOUBLE :
+ list.add(new Double(in.readDouble()));
+ break;
+ case VALUE_VERSION :
+ list.add(readVersion(in));
+ break;
+ default :
+ throw new IOException("Invalid type: " + listType); //$NON-NLS-1$
+ }
+ }
+ return list;
+ }
+
+ private static void writeVersion(Version version, DataOutputStream out) throws IOException {
+ if (version == null || version.equals(Version.emptyVersion)) {
+ out.writeByte(NULL);
+ return;
+ }
+ out.writeByte(OBJECT);
+ out.writeInt(version.getMajor());
+ out.writeInt(version.getMinor());
+ out.writeInt(version.getMicro());
+ writeQualifier(version.getQualifier(), out);
+ }
+
+ private static void writeQualifier(String string, DataOutputStream out) throws IOException {
+ if (string != null && string.length() == 0)
+ string = null;
+ writeString(string, out);
+ }
+
+ private static Version readVersion(DataInputStream in) throws IOException {
+ byte tag = in.readByte();
+ if (tag == NULL)
+ return Version.emptyVersion;
+ int majorComponent = in.readInt();
+ int minorComponent = in.readInt();
+ int serviceComponent = in.readInt();
+ String qualifierComponent = readString(in);
+ return (Version) ObjectPool.intern(new Version(majorComponent, minorComponent, serviceComponent, qualifierComponent));
+ }
+
+ private static void writeString(String string, DataOutputStream out) throws IOException {
+ if (string == null)
+ out.writeByte(NULL);
+ else {
+ byte[] data = string.getBytes(UTF_8);
+
+ if (data.length > 65535) {
+ out.writeByte(LONG_STRING);
+ out.writeInt(data.length);
+ out.write(data);
+ } else {
+ out.writeByte(OBJECT);
+ out.writeUTF(string);
+ }
+ }
+ }
+
+ static private String readString(DataInputStream in) throws IOException {
+ byte type = in.readByte();
+ if (type == NULL)
+ return null;
+
+ if (type == LONG_STRING) {
+ int length = in.readInt();
+ byte[] data = new byte[length];
+ in.readFully(data);
+ String string = new String(data, UTF_8);
+
+ return (String) ObjectPool.intern(string);
+ }
+
+ return (String) ObjectPool.intern(in.readUTF());
+ }
}
}

Back to the top