? src/org/netbeans/mdr/storagemodel/AttributeIOHelper.java Index: src/org/netbeans/mdr/NBMDRepositoryImpl.java =================================================================== RCS file: /cvs/mdr/src/org/netbeans/mdr/NBMDRepositoryImpl.java,v retrieving revision 1.8 diff -d -u -b -B -r1.8 NBMDRepositoryImpl.java --- src/org/netbeans/mdr/NBMDRepositoryImpl.java 16 Feb 2002 00:53:08 -0000 1.8 +++ src/org/netbeans/mdr/NBMDRepositoryImpl.java 4 Mar 2002 07:47:55 -0000 @@ -276,8 +276,13 @@ private void boot() { Log.out.println( "Booting repository ..." ); Log.out.indent(); + mdrStorage.setBooting(true); + try { installFakeMof(); installPureMof(); + } finally { + mdrStorage.setBooting(false); + } Log.out.unindent(); } Index: src/org/netbeans/mdr/handlers/EnumImpl.java =================================================================== RCS file: /cvs/mdr/src/org/netbeans/mdr/handlers/EnumImpl.java,v retrieving revision 1.4 diff -d -u -b -B -r1.4 EnumImpl.java --- src/org/netbeans/mdr/handlers/EnumImpl.java 24 Feb 2002 16:24:38 -0000 1.4 +++ src/org/netbeans/mdr/handlers/EnumImpl.java 4 Mar 2002 07:47:55 -0000 @@ -16,9 +16,13 @@ import java.lang.reflect.*; import java.io.*; +import javax.jmi.model.Classifier; +import javax.jmi.model.EnumerationType; +import javax.jmi.model.TypedElement; import javax.jmi.reflect.*; import org.netbeans.mdr.util.*; +import org.netbeans.mdr.persistence.StorageException; import org.netbeans.mdr.storagemodel.*; /** @@ -27,11 +31,12 @@ * @version */ public abstract class EnumImpl extends ImplClass implements RefEnum { + private static final String ENUMIMPL_SUFFIX = "Enum"; + private static final Hashtable enumCache = new Hashtable(50); + private final String label; private final List qualifiedName; - private static final Hashtable enumCache = new Hashtable(50); - private static Class getEnumClass(ClassLoader loader, Class ifc) throws IllegalArgumentException { check(loader, ifc); Map cache = getLoaderCache(loader); @@ -40,8 +45,10 @@ if (result == null) { try { - byte[] enumClassFile = EnumGenerator.generateEnum(className, ifc); - result = defineClass(loader, className, enumClassFile); + String rawName = ifc.getName() + ENUMIMPL_SUFFIX; + result = loader.loadClass(rawName); + } catch (ClassNotFoundException ex) { + throw new IllegalArgumentException("Invalid inteface: " + ifc); } finally { releaseCache(cache, result, className); } @@ -49,16 +56,7 @@ return result; } -/* - public static RefEnum newInstance(Descriptor.DataType dataType, int value) { - try { - return newInstance(Class.forName(dataType.getIfcName()), value, (String) dataType.getMembers().get(value), dataType.getTypeName()); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - throw new DebugException(e.toString()); - } - } -*/ + public static RefEnum newInstance(DatatypeDescriptor dataType, String label) { try { return newInstance(BaseObjectHandler.resolveInterface(dataType.getIfcName()), label, dataType.getTypeName()); @@ -77,21 +75,15 @@ Class cl = getEnumClass(loader, ifc); try { - Constructor cons = cl.getConstructor(new Class[] {String.class, List.class}); - enum = (RefEnum) cons.newInstance(new Object[] {label, qualifiedName}); + Field f = cl.getField(label.toUpperCase()); + enum = (RefEnum) f.get(null); enumCache.put(enumKey, enum); - } catch (NoSuchMethodException e) { + } catch (NoSuchFieldException e) { e.printStackTrace(); throw new DebugException(e.toString()); } catch (IllegalAccessException e) { e.printStackTrace(); throw new DebugException(e.toString()); - } catch (InstantiationException e) { - e.printStackTrace(); - throw new DebugException(e.toString()); - } catch (InvocationTargetException e) { - e.printStackTrace(); - throw new DebugException(e.toString()); } } @@ -131,29 +123,199 @@ return label.equals(other.toString()); } - public static RefEnum decode(InputStream inputStream, StorableBaseObject storable) throws IOException { - if (storable == null) Thread.dumpStack(); - String className = (String) IOUtils.read(inputStream); - List qualifiedName = (List) IOUtils.read(inputStream); - String label = (String) IOUtils.read(inputStream); + /** + * Maps enumeration's interface name to an integer index within the package + */ + private static Map enumerationMap = new HashMap(17); - Class clazz; + /** + * The first-level index is the enumeration index within the package. + * The second-level arrays are indexed by literal positions within + * the enumeration. + */ + private static List enumValues = new ArrayList(15); + + /** + * Maps enumeration instances (labels) to integer indices + */ + private static Map identityToValueMap = new HashMap(23); + + /** + * Another map of enum instances to integer values, this time + * keyed by the enum instance itself, so equals() from JMI spec is + * used. + */ + private static Map enumToValueMap = new HashMap(23); + + /** + * A little performance hack: we don't want allocate identity key every + * time a value of an enum needs to be looked up. Access to this field must + * be SYNCHRONIZED! + */ + private static IdentityKey sharedEnumKey; + + /** + * Registers an enumeration type with the package. It only puts the + * enumeration into a map and assings it an integer number to have fast + * access to values later. + * @param typeIndex index of typename in the MDR storage. + */ + public static int addEnumerationType(String typeName) { + int index; + synchronized (enumerationMap) { + index = enumerationMap.size(); + + Integer old = (Integer)enumerationMap.put(typeName, new Integer(index)); + if (old != null) { + enumerationMap.put(typeName, old); + index = old.intValue(); + } else { + enumValues.add(null); + } + } + return index; + } + + /** + * Initializes an enumeration for the given typeIndex (= interface FQN). + * If the enumeration was not seen yet, typedMetaMOFID is used to get + * the metaclass of the element, then the enumeration type. MOF reflective + * APIs are used to compute the translation tables. + * + * @param typeIndex index of the interface typename, key to the cache. + * @param typedMetaMOFID MOFID of a TypedElement, which uses the enumeration. + * @return handle to the enumeration to be used as a quick reference. + */ + public static int initEnumeration(String typeName, MdrStorage storage, + String typedMetaMOFID) { + Integer ivalue = (Integer)enumerationMap.get(typeName); + int index; + + if (ivalue == null) { + index = addEnumerationType(typeName); + } else { + index = ivalue.intValue(); + } + + RefEnum[] vals; + + synchronized (enumValues) { + vals = (RefEnum[])enumValues.get(index); + if (vals != null) + return index; + } try { - clazz = Class.forName(className); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - throw new DebugException(); + RefBaseObject te = BaseObjectHandler.getHandler(storage.getObject(typedMetaMOFID)); + Classifier c = ((TypedElement)te).getType(); + + // c can be BootMOF instance; in that case, it won't contain reliable information: + String typeMOFID = c.refMofId(); + /* + StorableObject sto = (StorableObject)storage.getObject(typeMOFID); + StorableClass stoProxy = sto.getClassProxy(); + StorableClass.AttributeDescriptor desc = stoProxy.getAttrDesc(0); + if (desc.getType() == Object.class) { + // It IS BootMOF => Go away. + return -1; } + */ + EnumerationType t = (EnumerationType)c; - return newInstance(clazz, label, qualifiedName); + // Try to acquire the Enum's implementation class + Class enumImpl = BaseObjectHandler.resolveInterface(typeName + ENUMIMPL_SUFFIX); + if (enumImpl == null) { + throw new DebugException("Cannot get enum class for " + typeName); + } + List labels = t.getLabels(); + vals = new RefEnum[labels.size()]; + int i = 0; + for (Iterator it = labels.iterator(); it.hasNext(); i++) { + String lab = (String)it.next(); + java.lang.reflect.Field f = enumImpl.getField(lab.toUpperCase()); + RefEnum v = (RefEnum)f.get(null); + vals[i] = v; + Integer ival = new Integer(i + 1); + identityToValueMap.put(new IdentityKey(v), ival); + enumToValueMap.put(v, ival); + } + } catch (ClassNotFoundException ex) { + } catch (NoSuchFieldException ex) { + } catch (IllegalAccessException ex) { + } catch (StorageException ex) { + } + if (sharedEnumKey == null) { + sharedEnumKey = new IdentityKey(); + } + synchronized (enumValues) { + enumValues.set(index, vals); + } + return index; } - public void write(OutputStream outputStream, MdrStorage storage) throws IOException { - if (storage == null) Thread.dumpStack(); - String className = this.getClass().getName().substring(0, this.getClass().getName().length() - getClassNameSuffix().length()); - IOUtils.write(outputStream, className); - IOUtils.write(outputStream, qualifiedName); - IOUtils.write(outputStream, label); + /** + * Maps the passed enum instance to a one-based label code. Null instance + * will be always mapped to 0. + * @param enumValue a value of the enumerated type + * @return encoded value. + */ + public static int encodeEnumInstance(RefEnum enumValue) { + if (enumValue == null) + return 0; + synchronized (sharedEnumKey) { + sharedEnumKey.setEnum(enumValue); + Object o = identityToValueMap.get(sharedEnumKey); + if (o == null) { + o = enumToValueMap.get(enumValue); + if (o == null) { + throw new IllegalArgumentException("Unknown enumeration label: " + + enumValue.getClass().getName() + ":" + enumValue.toString()); + } + } + return ((Integer)o).intValue(); + } + } + + /** + * Decodes a value of an enumerated type to a RefEnum instance. + * The method requires that the enum was previously properly initialized + * by calling {@link #initEnumeration}. + * The method always maps value 0 to null + * @param enumHandle handle returned by {@link #initEnumeration} call + * @param value int code of the label. + */ + public static RefEnum decodeEnumInstance(int enumHandle, int value) { + if (value == 0) + return null; + return ((RefEnum[])enumValues.get(enumHandle))[value -1]; + } + + /** + * This class is hack around ugly equals() mandated by the JMI spec. + * If/after JMI spec changes to a less stupid formula, this class may + * be removed and RefEnums may be put into the hashmap directly. + */ + private static final class IdentityKey { + private RefEnum enumValue; + private int hashCode; + + IdentityKey() {} + + IdentityKey(RefEnum en) { + setEnum(en); + } + + void setEnum(RefEnum en) { + this.enumValue = en; + this.hashCode = en.hashCode(); + } + + public boolean equals(Object o) { + return (o instanceof IdentityKey) && ((IdentityKey)o).enumValue == this.enumValue; + } + + public int hashCode() { + return hashCode; + } } } Index: src/org/netbeans/mdr/storagemodel/AttrImmutableList.java =================================================================== RCS file: /cvs/mdr/src/org/netbeans/mdr/storagemodel/AttrImmutableList.java,v retrieving revision 1.4 diff -d -u -b -B -r1.4 AttrImmutableList.java --- src/org/netbeans/mdr/storagemodel/AttrImmutableList.java 24 Feb 2002 16:24:38 -0000 1.4 +++ src/org/netbeans/mdr/storagemodel/AttrImmutableList.java 4 Mar 2002 07:47:56 -0000 @@ -22,6 +22,8 @@ import org.netbeans.mdr.util.IOUtils; /** + * [svata] This class is a candidate to be package private -- as soon as + * referencies to it are removed from util.IOUtils class. * * @author mm109185 */ @@ -296,6 +298,18 @@ public void write(OutputStream stream) throws IOException { IOUtils.writeInt(stream, attrIndex); IOUtils.write(stream, innerList); + } + + final void read(InputStream in, StorableFeatured owner, StorableClass.AttributeDescriptor desc, + int index) throws IOException, StorageException { + this.mdrObject = owner; + this.attrIndex = index; + this.innerList = AttributeIOHelper.readList(in, owner, desc); + } + + final void write(OutputStream out, StorableClass.AttributeDescriptor desc, StorableFeatured owner) + throws IOException { + AttributeIOHelper.writeList(out, innerList, owner, desc); } protected class AttrIterator implements ListIterator { Index: src/org/netbeans/mdr/storagemodel/MdrStorage.java =================================================================== RCS file: /cvs/mdr/src/org/netbeans/mdr/storagemodel/MdrStorage.java,v retrieving revision 1.10 diff -d -u -b -B -r1.10 MdrStorage.java --- src/org/netbeans/mdr/storagemodel/MdrStorage.java 24 Feb 2002 16:24:38 -0000 1.10 +++ src/org/netbeans/mdr/storagemodel/MdrStorage.java 4 Mar 2002 07:47:57 -0000 @@ -90,6 +90,11 @@ /** name of storage file */ private final String storageFile; + /** + * Determines whether the storage is ready or not. + */ + private boolean booting; + // mutexes private final RWMutex repositoryMutex = new RWMutex(); public RWMutex getRepositoryMutex() { @@ -208,6 +213,18 @@ instances.put(storage, this); return result; + } + + /** + * Announce that this storage is being booted. Only the storage which holds + * the MOF metamodel should be called with `true' as argument. + */ + public void setBooting(boolean flag) { + this.booting = flag; + } + + public boolean isBooting() { + return this.booting; } /** Commits changes to the storage. Index: src/org/netbeans/mdr/storagemodel/StorableClass.java =================================================================== RCS file: /cvs/mdr/src/org/netbeans/mdr/storagemodel/StorableClass.java,v retrieving revision 1.8 diff -d -u -b -B -r1.8 StorableClass.java --- src/org/netbeans/mdr/storagemodel/StorableClass.java 24 Feb 2002 16:24:38 -0000 1.8 +++ src/org/netbeans/mdr/storagemodel/StorableClass.java 4 Mar 2002 07:47:57 -0000 @@ -15,6 +15,8 @@ import java.util.*; import java.io.IOException; +import javax.jmi.reflect.RefEnum; + import org.netbeans.mdr.util.*; import org.netbeans.mdr.persistence.*; import org.netbeans.mdr.handlers.*; @@ -26,7 +28,6 @@ * @version 0.2 */ public class StorableClass extends StorableFeatured { - private AttributeDescriptor attrDescs[]; private List superclasses; private List subclasses; @@ -40,8 +41,21 @@ // transient variables private final Hashtable refCache = new Hashtable(); - private List attributeDescs = null; - private List attributes = null; + + /** + * Names of all attributes of this classproxy's instances, collected from + * the metaclass and its superclasses. Order of the names match exactly + * order of attribute descriptors in the attributeDecs array and the + * array of attr values in instances. + */ + private List attributes; + + /** + * Collected attribute descriptors from this classproxy's metaclass and + * its superclasses. They're stored as array because of convenient fast access + * by index. + */ + private AttributeDescriptor[] attributeDescs; // mutexes private final Object attrMutex = new Object(); @@ -57,7 +71,7 @@ for (int i = 0; i < attrDescs.length; i++) { attrDescs[i].replaceValues(table); } - + AttributeIOHelper.finalizeClassProxy(this, this.attrDescs); objectChanged(); } @@ -90,6 +104,9 @@ this.singletonClass = isSingleton; this.abstractClass = isAbstract; + // asks the IOHelper to precompute some things into the attributes + AttributeIOHelper.finalizeClassProxy(this, this.attrDescs); + getMdrStorage().addObject(this); initFinished = true; } @@ -147,7 +164,7 @@ objectChanged(); } - public int getAttrIndex(String attributeName) throws StorageException { + public final int getAttrIndex(String attributeName) throws StorageException { checkAttributes(); int result = attributes.indexOf(attributeName); @@ -170,14 +187,19 @@ return result; } - public int getAttrCount() throws StorageException { + public final int getAttrCount() throws StorageException { checkAttributes(); - return attributeDescs.size(); + return attributeDescs.length; } - protected AttributeDescriptor getAttrDesc(int attrIndex) throws StorageException { + protected final AttributeDescriptor getAttrDesc(int attrIndex) throws StorageException { checkAttributes(); - return (AttributeDescriptor) attributeDescs.get(attrIndex); + return attributeDescs[attrIndex]; + } + + final AttributeDescriptor[] getAttrDescriptors() throws StorageException { + checkAttributes(); + return attributeDescs; } public ReferenceDescriptor getReferenceDescriptor(String referenceName) throws StorageException { @@ -206,8 +228,10 @@ if (attributes == null) { //System.out.println("collecting attributes for: " + getMofId()); attributes = new ArrayList(); - attributeDescs = new ArrayList(); - collectAttributes(attributes, attributeDescs, new HashSet()); + List attribDescs = new ArrayList(); + collectAttributes(attributes, attribDescs, new HashSet()); + this.attributeDescs = (AttributeDescriptor[])attribDescs.toArray( + new AttributeDescriptor[attribDescs.size()]); } } } @@ -345,7 +369,7 @@ if (attrDescs == null) { IOUtils.write(outputStream, null); } else { - IOUtils.writeInt(outputStream, attrDescs.length); + IOUtils.write(outputStream, new Integer(attrDescs.length)); for (int i = 0; i < attrDescs.length; i++) { IOUtils.write(outputStream, attrDescs[i], getMdrStorage()); } @@ -410,6 +434,7 @@ classSuperclass = (String) IOUtils.read(inputStream); instanceSuperclass = (String) IOUtils.read(inputStream); + AttributeIOHelper.readResolveHelper(this, attrDescs); } catch (IOException e) { e.printStackTrace(); throw new DebugException("IOException: " + e); @@ -460,6 +485,15 @@ private String mofId; private final String name; private final boolean indexed; + /** + * Hint used by the marshalling code. + */ + private int serialCode; + + /** + * Runtime ID of the enumeration in the immediate package + */ + private transient int enumerationID; private final transient MdrStorage mdrStorage; private transient Class type = null; @@ -469,6 +503,14 @@ this.type = type; } + public AttributeDescriptor(MdrStorage storage, String mofId, String name, int typeIndex, + int minSize, int maxSize, boolean isUnique, boolean isChangeable, boolean isIndexed, + int serialCode) { + this(storage, mofId, name, typeIndex, minSize, maxSize, isUnique, isChangeable, + isIndexed); + this.serialCode = serialCode; + } + public AttributeDescriptor(MdrStorage storage, String mofId, String name, int typeIndex, int minSize, int maxSize, boolean isUnique, boolean isChangeable, boolean isIndexed) { this.mdrStorage = storage; this.typeIndex = typeIndex; @@ -496,6 +538,22 @@ } } return type; + } + + public void setEnumerationID(int id) { + this.enumerationID = id; + } + + public int getEnumerationID() { + return this.enumerationID; + } + + public void setSerialCode(int code) { + this.serialCode = code; + } + + public int getSerialCode() { + return serialCode; } public int getTypeIndex() { Index: src/org/netbeans/mdr/storagemodel/StorableFeatured.java =================================================================== RCS file: /cvs/mdr/src/org/netbeans/mdr/storagemodel/StorableFeatured.java,v retrieving revision 1.5 diff -d -u -b -B -r1.5 StorableFeatured.java --- src/org/netbeans/mdr/storagemodel/StorableFeatured.java 24 Feb 2002 16:24:38 -0000 1.5 +++ src/org/netbeans/mdr/storagemodel/StorableFeatured.java 4 Mar 2002 07:47:57 -0000 @@ -180,14 +180,10 @@ super.write(outputStream); try { - if (values == null) { - IOUtils.write(outputStream, null); - } else { - IOUtils.writeInt(outputStream, values.length); - for (int i = 0; i < values.length; i++) { - IOUtils.write(outputStream, values[i], getMdrStorage()); - } - } + AttributeIOHelper.writeAttributeValues(outputStream, this, values); + } catch (StorageException ex) { + ex.printStackTrace(); + throw new DebugException(); } catch (java.io.IOException e) { e.printStackTrace(); throw new DebugException(); @@ -201,14 +197,8 @@ super.read (inputStream); try { - Integer objCount = (Integer) IOUtils.read(inputStream); - if (objCount != null) { - int count = objCount.intValue(); - values = new Object[count]; - for (int i = 0; i < count; i++) { - values[i] = IOUtils.read(inputStream, this, getClassProxy().getAttrDesc(i).getType().getName()); - } - } + values = AttributeIOHelper.readAttributeValues(inputStream, + getClassProxy()); } catch (StorageException e) { e.printStackTrace(); throw new DebugException("IOException: " + e); Index: src/org/netbeans/mdr/storagemodel/StorableObject.java =================================================================== RCS file: /cvs/mdr/src/org/netbeans/mdr/storagemodel/StorableObject.java,v retrieving revision 1.7 diff -d -u -b -B -r1.7 StorableObject.java --- src/org/netbeans/mdr/storagemodel/StorableObject.java 21 Feb 2002 13:04:15 -0000 1.7 +++ src/org/netbeans/mdr/storagemodel/StorableObject.java 4 Mar 2002 07:47:57 -0000 @@ -197,8 +197,8 @@ */ public void write(java.io.OutputStream outputStream) { try { - IOUtils.write(outputStream, classProxyId); - IOUtils.write(outputStream, attribComposite); + IOUtils.writeString(outputStream, classProxyId); + IOUtils.writeString(outputStream, attribComposite); } catch (java.io.IOException e) { e.printStackTrace(); } @@ -210,8 +210,8 @@ */ public void read(java.io.InputStream inputStream) { try { - classProxyId = (String) IOUtils.read(inputStream); - attribComposite = (String) IOUtils.read(inputStream); + classProxyId = IOUtils.readString(inputStream); + attribComposite = IOUtils.readString(inputStream); // init value of "meta" (not serialized in case of StorableObject) } catch (java.io.IOException e) { e.printStackTrace(Log.out); Index: src/org/netbeans/mdr/util/IOUtils.java =================================================================== RCS file: /cvs/mdr/src/org/netbeans/mdr/util/IOUtils.java,v retrieving revision 1.3 diff -d -u -b -B -r1.3 IOUtils.java --- src/org/netbeans/mdr/util/IOUtils.java 24 Feb 2002 16:24:39 -0000 1.3 +++ src/org/netbeans/mdr/util/IOUtils.java 4 Mar 2002 07:47:58 -0000 @@ -49,6 +49,7 @@ private static final int T_SHORT = 15; private static final int T_BYTE = 16; private static final int T_OBJECT = 17; + private static final int T_LONG = 18; private static final String ENUMIMPL_SUFFIX = "Enum"; @@ -60,38 +61,60 @@ write(outputStream, object, null); } + /** + * Writes an integer to the output stream. It tries to optimize for space a little: + * small values are stored just as one byte. Values <= 0xffff are stored as + * 3 bytes, little-endian and other values as 5 bytes, little-endian + */ public static void writeInt(OutputStream outputStream, int val) throws IOException { - if ((int) ((byte) val & 0xFF) == val) { - outputStream.write(T_BYTE); + if ((int) ((byte) val & 0x7F) == val) { outputStream.write((byte)val); - } else if ((int) ((byte) (val >> 8) & 0xFF) == val >> 8) { - outputStream.write(T_SHORT); + } else if ((int) ((byte) (val >>> 8) & 0xFF) == val >>> 8) { + outputStream.write(T_SHORT | 0x80); outputStream.write((byte)(val & 0xff)); - outputStream.write((byte)((val & 0xff00) >> 8)); + outputStream.write((byte)((val & 0xff00) >>> 8)); } else { - outputStream.write(T_INTEGER); + outputStream.write(T_INTEGER | 0x80); outputStream.write((byte)(val & 0xff)); - outputStream.write((byte)((val & 0xff00) >> 8)); - outputStream.write((byte)((val & 0xff0000) >> 16)); + outputStream.write((byte)((val & 0xff00) >>> 8)); + outputStream.write((byte)((val & 0xff0000) >>> 16)); val = (val >> 24) & 0xff; outputStream.write((byte)val); } } + public static void writeLong(OutputStream outputStream, long val) throws IOException { + if ((int) ((byte) val & 0x7F) == val) { + outputStream.write((byte)val); + } else if ((int) ((byte) (val >>> 24) & 0xFF) == val >>> 24) { + outputStream.write(T_INTEGER | 0x80); + outputStream.write((byte)(val & 0xff)); + outputStream.write((byte)((val & 0xff00) >>> 8)); + outputStream.write((byte)((val & 0xff0000) >>> 16)); + outputStream.write((byte)((val >>> 24) & 0xff)); + } else { + outputStream.write(T_LONG | 0x80); + outputStream.write((byte)(val & 0xff)); + outputStream.write((byte)((val & 0xff00) >>> 8)); + outputStream.write((byte)((val >>> 16) & 0xff)); + outputStream.write((byte)((val >>> 24) & 0xff)); + outputStream.write((byte)((val >>> 32) & 0xff)); + outputStream.write((byte)((val >>> 48) & 0xff)); + outputStream.write((byte)((val >>> 56) & 0xff)); + } + } + public static void writeBoolean(OutputStream outputStream, boolean val) throws IOException { - outputStream.write(T_BOOLEAN); outputStream.write(val ? 1 : 0); } - public static void write(OutputStream outputStream, Object object, MdrStorage storage) throws IOException { - if (object == null) { - outputStream.write(T_NULL); - - } else if (object instanceof String) { - String val = (String) object; - outputStream.write(T_STRING); + public static void writeString(OutputStream outputStream, String val) throws IOException { + if (val == null) { + writeInt(outputStream, 0); + return; + } int len = val.length(); - writeInt(outputStream, len); + writeInt(outputStream, len + 1); for (int i = 0; i < len; i++) { char ch = val.charAt(i); if (ch <= 0x7f) { @@ -105,10 +128,21 @@ outputStream.write((byte) (0x80 | (ch & 0x3f))); } } + } + + public static void write(OutputStream outputStream, Object object, MdrStorage storage) throws IOException { + if (object == null) { + outputStream.write(T_NULL); + + } else if (object instanceof String) { + outputStream.write(T_STRING); + writeString(outputStream, (String)object); } else if (object instanceof Integer) { int val = ((Integer)object).intValue(); + outputStream.write(T_INTEGER); writeInt(outputStream, val); } else if (object instanceof Boolean) { + outputStream.write(T_BOOLEAN); writeBoolean(outputStream, ((Boolean) object).booleanValue()); } else if (object instanceof Map) { @@ -160,7 +194,7 @@ writeBoolean(outputStream, desc.isUnique()); writeBoolean(outputStream, desc.isChangeable()); writeBoolean(outputStream, desc.isIndexed()); - + writeInt(outputStream, desc.getSerialCode()); } else if (object instanceof StorableClass.ReferenceDescriptor) { outputStream.write(T_MOF_REFERENCE); write(outputStream, ((StorableClass.ReferenceDescriptor) object).getAssociationId()); @@ -193,7 +227,6 @@ } public static boolean readBoolean(InputStream is) throws IOException { - if (is.read() != T_BOOLEAN) throw new DebugException("Not a boolean value."); return (is.read() == 1); } @@ -201,18 +234,17 @@ return readInt(is, is.read()); } - public static int readInt(InputStream inputStream, int type) throws IOException { + static int readInt(InputStream inputStream, int type) throws IOException { + if (type <= 0x7f) + return type; switch (type) { - case T_BYTE: { - return inputStream.read(); - } - case T_SHORT: { + case T_SHORT | 0x80: { int ch1, ch2; ch1 = inputStream.read(); ch2 = inputStream.read(); return (ch2 << 8) | ch1; } - case T_INTEGER: { + case T_INTEGER | 0x80: { int ch1, ch2, ch3, ch4; ch1 = inputStream.read(); ch2 = inputStream.read(); @@ -225,14 +257,44 @@ } } - public static Object read(InputStream inputStream, StorableBaseObject storable, String className) throws IOException { - int type; - switch (type = inputStream.read()) { - case T_NULL: { - return null; - } case T_STRING: { + public static long readLong(InputStream inputStream) throws IOException { + int t = inputStream.read(); + if (t <= 0x7f) + return t; + switch (t) { + case T_INTEGER | 0x80: { + int ch1, ch2, ch3, ch4; + ch1 = inputStream.read(); + ch2 = inputStream.read(); + ch3 = inputStream.read(); + ch4 = inputStream.read(); + return (ch4 << 24) + (ch3 << 16) + (ch2 << 8) + ch1; + } + case T_LONG | 0x80: { + int ch1, ch2, ch3, ch4; + long v; + + ch1 = inputStream.read(); + ch2 = inputStream.read(); + ch3 = inputStream.read(); + ch4 = inputStream.read(); + v = (ch4 << 24) + (ch3 << 16) + (ch2 << 8) + ch1; + ch1 = inputStream.read(); + ch2 = inputStream.read(); + ch3 = inputStream.read(); + ch4 = inputStream.read(); + return v << 32 + ((ch4 << 24) + (ch3 << 16) + (ch2 << 8) + ch1); + } + default: + throw new IOException("Unknown int format: " + t); + } + } + + public static String readString(InputStream inputStream) throws IOException { int length = readInt(inputStream); if (length == 0) + return null; + else if (--length == 0) return ""; StringBuffer sb = new StringBuffer(length); do { @@ -249,10 +311,20 @@ } while (--length > 0); return new String(sb); } + + public static Object read(InputStream inputStream, StorableBaseObject storable, String className) throws IOException { + int type; + switch (type = inputStream.read()) { + case T_NULL: + return null; + case T_STRING: + return readString(inputStream); case T_BYTE: case T_SHORT: case T_INTEGER: - return new Integer(readInt(inputStream, type)); + return new Integer(readInt(inputStream)); + case T_LONG: + return new Long(readLong(inputStream)); case T_BOOLEAN: { return new Boolean(inputStream.read() == 1); } case T_MAP: { @@ -296,7 +368,7 @@ } } case T_MOF_ATTRIBUTE: { if (storable == null) Thread.dumpStack(); - return new StorableClass.AttributeDescriptor(storable.getMdrStorage(), (String) read(inputStream), (String) read(inputStream), readInt(inputStream), readInt(inputStream), readInt(inputStream), readBoolean(inputStream), readBoolean(inputStream), readBoolean(inputStream)); + return new StorableClass.AttributeDescriptor(storable.getMdrStorage(), (String) read(inputStream), (String) read(inputStream), readInt(inputStream), readInt(inputStream), readInt(inputStream), readBoolean(inputStream), readBoolean(inputStream), readBoolean(inputStream), readInt(inputStream)); } case T_MOF_REFERENCE: { if (storable == null) Thread.dumpStack(); return ((StorableClass) storable).new ReferenceDescriptor((String) read(inputStream, storable), (String) read(inputStream, storable));