summaryrefslogtreecommitdiff
path: root/java/src/IceInternal/BasicStream.java
diff options
context:
space:
mode:
authorBenoit Foucher <benoit@zeroc.com>2013-01-04 10:50:28 +0100
committerBenoit Foucher <benoit@zeroc.com>2013-01-04 10:50:28 +0100
commit8b4674dbca704b9ffb48cd9a4fee43211e774cce (patch)
treeac55936ef4ba7b52ed8835c011b7c59cf2d1d3ee /java/src/IceInternal/BasicStream.java
parentFixed(ICE-5147) - Fix python scripts to not raise strings anymore (diff)
downloadice-8b4674dbca704b9ffb48cd9a4fee43211e774cce.tar.bz2
ice-8b4674dbca704b9ffb48cd9a4fee43211e774cce.tar.xz
ice-8b4674dbca704b9ffb48cd9a4fee43211e774cce.zip
ICE-4938: Super compact enoding
Diffstat (limited to 'java/src/IceInternal/BasicStream.java')
-rw-r--r--java/src/IceInternal/BasicStream.java2130
1 files changed, 1210 insertions, 920 deletions
diff --git a/java/src/IceInternal/BasicStream.java b/java/src/IceInternal/BasicStream.java
index 8b781ebf7ac..c8e9f819605 100644
--- a/java/src/IceInternal/BasicStream.java
+++ b/java/src/IceInternal/BasicStream.java
@@ -186,56 +186,56 @@ public class BasicStream
startWriteObject(Ice.SlicedData data)
{
assert(_writeEncapsStack != null && _writeEncapsStack.encoder != null);
- _writeEncapsStack.encoder.startObject(data);
+ _writeEncapsStack.encoder.startInstance(SliceType.ObjectSlice, data);
}
public void
endWriteObject()
{
assert(_writeEncapsStack != null && _writeEncapsStack.encoder != null);
- _writeEncapsStack.encoder.endObject();
+ _writeEncapsStack.encoder.endInstance();
}
public void
startReadObject()
{
assert(_readEncapsStack != null && _readEncapsStack.decoder != null);
- _readEncapsStack.decoder.startObject();
+ _readEncapsStack.decoder.startInstance(SliceType.ObjectSlice);
}
public Ice.SlicedData
endReadObject(boolean preserve)
{
assert(_readEncapsStack != null && _readEncapsStack.decoder != null);
- return _readEncapsStack.decoder.endObject(preserve);
+ return _readEncapsStack.decoder.endInstance(preserve);
}
public void
startWriteException(Ice.SlicedData data)
{
assert(_writeEncapsStack != null && _writeEncapsStack.encoder != null);
- _writeEncapsStack.encoder.startException(data);
+ _writeEncapsStack.encoder.startInstance(SliceType.ExceptionSlice, data);
}
public void
endWriteException()
{
assert(_writeEncapsStack != null && _writeEncapsStack.encoder != null);
- _writeEncapsStack.encoder.endException();
+ _writeEncapsStack.encoder.endInstance();
}
public void
startReadException()
{
assert(_readEncapsStack != null && _readEncapsStack.decoder != null);
- _readEncapsStack.decoder.startException();
+ _readEncapsStack.decoder.startInstance(SliceType.ExceptionSlice);
}
public Ice.SlicedData
endReadException(boolean preserve)
{
assert(_readEncapsStack != null && _readEncapsStack.decoder != null);
- return _readEncapsStack.decoder.endException(preserve);
+ return _readEncapsStack.decoder.endInstance(preserve);
}
public void
@@ -288,11 +288,6 @@ public class BasicStream
{
assert(_writeEncapsStack != null);
- if(_writeEncapsStack.encoder != null)
- {
- _writeEncapsStack.encoder.writePendingObjects();
- }
-
// Size includes size and version.
int start = _writeEncapsStack.start;
int sz = _buf.size() - start;
@@ -389,33 +384,21 @@ public class BasicStream
{
assert(_readEncapsStack != null);
- if(_readEncapsStack.decoder != null)
- {
- _readEncapsStack.decoder.readPendingObjects();
- }
- else if(_buf.b.position() < _readEncapsStack.start + _readEncapsStack.sz && !_readEncapsStack.encoding_1_0)
+ if(!_readEncapsStack.encoding_1_0)
{
- //
- // Read remaining encapsulation optionals. This returns
- // true if the optionals end with the end marker. The end
- // marker indicates that there are more to read from the
- // encapsulation: object instances. In this case, don't
- // bother reading the objects, just skip to the end of the
- // encapsulation.
- //
- if(skipOpts())
+ skipOpts();
+ if(_buf.b.position() != _readEncapsStack.start + _readEncapsStack.sz)
{
- _buf.b.position(_readEncapsStack.start + _readEncapsStack.sz);
+ throw new Ice.EncapsulationException();
}
}
-
- if(_buf.b.position() != _readEncapsStack.start + _readEncapsStack.sz)
+ else if(_buf.b.position() != _readEncapsStack.start + _readEncapsStack.sz)
{
if(_buf.b.position() + 1 != _readEncapsStack.start + _readEncapsStack.sz)
{
throw new Ice.EncapsulationException();
}
-
+
//
// Ice version < 3.3 had a bug where user exceptions with
// class members could be encoded with a trailing byte
@@ -585,7 +568,6 @@ public class BasicStream
if(_readEncapsStack != null && _readEncapsStack.decoder != null)
{
_readEncapsStack.decoder.readPendingObjects();
- _readEncapsStack.decoder = null;
}
else if(_readEncapsStack != null ? _readEncapsStack.encoding_1_0 : _encoding.equals(Ice.Util.Encoding_1_0))
{
@@ -608,7 +590,6 @@ public class BasicStream
if(_writeEncapsStack != null && _writeEncapsStack.encoder != null)
{
_writeEncapsStack.encoder.writePendingObjects();
- _writeEncapsStack.encoder = null;
}
else if(_writeEncapsStack != null ? _writeEncapsStack.encoding_1_0 : _encoding.equals(Ice.Util.Encoding_1_0))
{
@@ -641,16 +622,6 @@ public class BasicStream
}
}
- public void
- writeSizeSeq(java.util.List<Integer> v)
- {
- writeSize(v.size());
- for(Integer n : v)
- {
- writeSize(n);
- }
- }
-
public int
readSize()
{
@@ -677,23 +648,6 @@ public class BasicStream
}
}
- public int[]
- readSizeSeq()
- {
- int sz = readSize();
- int[] v = new int[sz];
-
- if(sz > 0)
- {
- for(int n = 0; n < sz; ++n)
- {
- v[n] = readSize();
- }
- }
-
- return v;
- }
-
public int
readAndCheckSeqSize(int minSize)
{
@@ -2067,7 +2021,7 @@ public class BasicStream
public void
writeObject(int tag, Ice.Object v)
{
- if(writeOpt(tag, Ice.OptionalFormat.Size))
+ if(writeOpt(tag, Ice.OptionalFormat.Class))
{
writeObject(v);
}
@@ -2076,7 +2030,6 @@ public class BasicStream
public void
readObject(Patcher patcher)
{
- assert(patcher != null);
initReadEncaps();
_readEncapsStack.decoder.readObject(patcher);
}
@@ -2084,7 +2037,7 @@ public class BasicStream
public void
readObject(int tag, Ice.Optional<Ice.Object> v)
{
- if(readOpt(tag, Ice.OptionalFormat.Size))
+ if(readOpt(tag, Ice.OptionalFormat.Class))
{
Ice.OptionalObject opt = new Ice.OptionalObject(v, Ice.Object.class, Ice.ObjectImpl.ice_staticId());
readObject(opt);
@@ -2100,12 +2053,6 @@ public class BasicStream
{
initWriteEncaps();
_writeEncapsStack.encoder.writeUserException(e);
-
- //
- // Reset the encoder, the writing of the exception wrote
- // pending objects if any.
- //
- _writeEncapsStack.encoder = null;
}
public void
@@ -2113,15 +2060,7 @@ public class BasicStream
throws Ice.UserException
{
initReadEncaps();
- try
- {
- _readEncapsStack.decoder.throwException(factory);
- }
- catch(Ice.UserException ex)
- {
- _readEncapsStack.decoder = null;
- throw ex;
- }
+ _readEncapsStack.decoder.throwException(factory);
}
public void
@@ -2138,9 +2077,7 @@ public class BasicStream
return false; // Optional members aren't supported with the 1.0 encoding.
}
- int tag = 0;
- Ice.OptionalFormat format;
- do
+ while(true)
{
if(_buf.b.position() >= _readEncapsStack.start + _readEncapsStack.sz)
{
@@ -2149,38 +2086,38 @@ public class BasicStream
final byte b = readByte();
final int v = b < 0 ? (int)b + 256 : b;
- format = Ice.OptionalFormat.valueOf(v & 0x07); // First 3 bits.
- tag = v >> 3;
- if(tag == 31)
+ if(v == OPTIONAL_END_MARKER)
{
- tag = readSize();
+ _buf.b.position(_buf.b.position() - 1); // Rewind.
+ return false;
}
- }
- while(format != Ice.OptionalFormat.EndMarker && tag < readTag && skipOpt(format)); // Skip optional data members
- if(format == Ice.OptionalFormat.EndMarker || tag > readTag)
- {
- //
- // Rewind the stream to correctly read the next optional data
- // member tag & format next time.
- //
- int offset = tag < 31 ? 1 : (tag < 255 ? 2 : 6);
- _buf.b.position(_buf.b.position() - offset);
- return false; // No optional data members with the requested tag.
- }
+ Ice.OptionalFormat format = Ice.OptionalFormat.valueOf(v & 0x07); // First 3 bits.
+ int tag = v >> 3;
+ if(tag == 30)
+ {
+ tag = readSize();
+ }
- assert(readTag == tag);
- if(format != expectedFormat)
- {
- String msg = "invalid optional data member `" + tag + "': unexpected format";
- throw new Ice.MarshalException(msg);
+ if(tag > readTag)
+ {
+ int offset = tag < 30 ? 1 : (tag < 255 ? 2 : 6); // Rewind
+ _buf.b.position(_buf.b.position() - offset);
+ return false; // No optional data members with the requested tag.
+ }
+ else if(tag < readTag)
+ {
+ skipOpt(format); // Skip optional data members
+ }
+ else
+ {
+ if(format != expectedFormat)
+ {
+ throw new Ice.MarshalException("invalid optional data member `" + tag + "': unexpected format");
+ }
+ return true;
+ }
}
-
- //
- // We have an optional data member with the requested tag and
- // format.
- //
- return true;
}
public boolean
@@ -2192,95 +2129,95 @@ public class BasicStream
}
int v = format.value();
- if(tag < 31)
+ if(tag < 30)
{
v |= tag << 3;
writeByte((byte)v);
}
else
{
- v |= 0x0F8; // tag = 31
+ v |= 0x0F0; // tag = 30
writeByte((byte)v);
writeSize(tag);
}
return true;
}
- public boolean
+ public void
skipOpt(Ice.OptionalFormat format)
{
- int sz;
switch(format)
{
case F1:
{
- sz = 1;
+ skip(1);
break;
}
case F2:
{
- sz = 2;
+ skip(2);
break;
}
case F4:
{
- sz = 4;
+ skip(4);
break;
}
case F8:
{
- sz = 8;
+ skip(8);
break;
}
case Size:
{
skipSize();
- return true;
+ break;
}
case VSize:
{
- sz = readSize();
+ skip(readSize());
break;
}
case FSize:
{
- sz = readInt();
+ skip(readInt());
break;
}
- default:
+ case Class:
{
- return false;
+ readObject(null);
+ break;
}
}
- skip(sz);
- return true;
}
- public boolean
+ public void
skipOpts()
{
//
// Skip remaining un-read optional members.
//
- Ice.OptionalFormat format;
- do
+ while(true)
{
if(_buf.b.position() >= _readEncapsStack.start + _readEncapsStack.sz)
{
- return false; // End of encapsulation also indicates end of optionals.
+ return; // End of encapsulation also indicates end of optionals.
}
final byte b = readByte();
final int v = b < 0 ? (int)b + 256 : b;
- format = Ice.OptionalFormat.valueOf(v & 0x07); // Read first 3 bits.
- if((v >> 3) == 31)
+ if(v == OPTIONAL_END_MARKER)
+ {
+ return;
+ }
+
+ Ice.OptionalFormat format = Ice.OptionalFormat.valueOf(v & 0x07); // Read first 3 bits.
+ if((v >> 3) == 30)
{
skipSize();
}
+ skipOpt(format);
}
- while(skipOpt(format));
- assert(format == Ice.OptionalFormat.EndMarker);
- return true;
}
public void
@@ -2831,67 +2768,270 @@ public class BasicStream
private enum SliceType { NoSlice, ObjectSlice, ExceptionSlice }
- private static final class EncapsDecoder
+ abstract private static class EncapsDecoder
{
- EncapsDecoder(BasicStream stream, ReadEncaps encaps, boolean sliceObjects)
+ EncapsDecoder(BasicStream stream, ReadEncaps encaps, boolean sliceObjects, ObjectFactoryManager f)
{
_stream = stream;
_encaps = encaps;
_sliceObjects = sliceObjects;
- _traceSlicing = -1;
- _sliceType = SliceType.NoSlice;
+ _servantFactoryManager = f;
_typeIdIndex = 0;
- _compactId = -1;
- _slices = new java.util.ArrayList<Ice.SliceInfo>();
- _indirectionTables = new java.util.ArrayList<int[]>();
- _indirectPatchList = new java.util.ArrayList<IndirectPatchEntry>();
- _patchMap = new java.util.TreeMap<Integer, java.util.LinkedList<Patcher> >();
_unmarshaledMap = new java.util.TreeMap<Integer, Ice.Object>();
- _typeIdMap = new java.util.TreeMap<Integer, String>();
}
- void readObject(Patcher patcher)
+ abstract void readObject(Patcher patcher);
+ abstract void throwException(UserExceptionFactory factory)
+ throws Ice.UserException;
+
+ abstract void startInstance(SliceType type);
+ abstract Ice.SlicedData endInstance(boolean preserve);
+ abstract String startSlice();
+ abstract void endSlice();
+ abstract void skipSlice();
+
+ boolean
+ readOpt(int tag, Ice.OptionalFormat format)
{
- int index = 0;
- if(_encaps.encoding_1_0)
+ return false;
+ }
+
+ void
+ readPendingObjects()
+ {
+ }
+
+ protected String
+ readTypeId(boolean isIndex)
+ {
+ if(_typeIdMap == null) // Lazy initialization
{
- //
- // Object references are encoded as a negative integer in 1.0.
- //
- index = _stream.readInt();
- if(index > 0)
+ _typeIdMap = new java.util.TreeMap<Integer, String>();
+ }
+
+ if(isIndex)
+ {
+ int index = _stream.readSize();
+ String typeId = _typeIdMap.get(index);
+ if(typeId == null)
{
- throw new Ice.MarshalException("invalid object id");
+ throw new Ice.UnmarshalOutOfBoundsException();
}
- index = -index;
+ return typeId;
}
else
{
- //
- // Later versions use a size.
- //
- index = _stream.readSize();
- if(index < 0)
+ String typeId = _stream.readString();
+ _typeIdMap.put(++_typeIdIndex, typeId);
+ return typeId;
+ }
+ }
+
+ protected Ice.Object
+ newInstance(String typeId)
+ {
+ //
+ // Try to find a factory registered for the specific type.
+ //
+ Ice.ObjectFactory userFactory = _servantFactoryManager.find(typeId);
+ Ice.Object v = null;
+ if(userFactory != null)
+ {
+ v = userFactory.create(typeId);
+ }
+
+ //
+ // If that fails, invoke the default factory if one has been
+ // registered.
+ //
+ if(v == null)
+ {
+ userFactory = _servantFactoryManager.find("");
+ if(userFactory != null)
{
- throw new Ice.MarshalException("invalid object id");
+ v = userFactory.create(typeId);
}
}
+
+ //
+ // Last chance: try to instantiate the class dynamically.
+ //
+ if(v == null)
+ {
+ v = _stream.createObject(typeId);
+ }
- if(index == 0)
+ return v;
+ }
+
+ protected void
+ addPatchEntry(int index, Patcher patcher)
+ {
+ assert(index > 0);
+
+ //
+ // Check if already un-marshalled the object. If that's the case,
+ // just patch the object smart pointer and we're done.
+ //
+ Ice.Object obj = _unmarshaledMap.get(index);
+ if(obj != null)
{
- patcher.patch(null);
+ patcher.patch(obj);
+ return;
}
- else if(_sliceType != SliceType.NoSlice && (_sliceFlags & FLAG_HAS_INDIRECTION_TABLE) != 0)
+
+ if(_patchMap == null) // Lazy initialization
+ {
+ _patchMap = new java.util.TreeMap<Integer, java.util.LinkedList<Patcher> >();
+ }
+
+ //
+ // Add patch entry if the object isn't un-marshalled yet,
+ // the smart pointer will be patched when the instance is
+ // un-marshalled.
+ //
+ java.util.LinkedList<Patcher> l = _patchMap.get(index);
+ if(l == null)
{
//
- // Maintain a list of indirect references. Note that the indirect index
- // starts at 1, so we decrement it by one to derive an index into
- // the indirection table that we'll read at the end of the slice.
+ // We have no outstanding instances to be patched for this
+ // index, so make a new entry in the patch map.
//
- IndirectPatchEntry e = new IndirectPatchEntry();
- e.index = index - 1;
- e.patcher = patcher;
- _indirectPatchList.add(e);
+ l = new java.util.LinkedList<Patcher>();
+ _patchMap.put(index, l);
+ }
+
+ //
+ // Append a patch entry for this instance.
+ //
+ l.add(patcher);
+ }
+
+ protected void
+ unmarshal(int index, Ice.Object v)
+ {
+ //
+ // Add the object to the map of un-marshalled objects, this must
+ // be done before reading the objects (for circular references).
+ //
+ _unmarshaledMap.put(index, v);
+
+ //
+ // Read the object.
+ //
+ v.__read(_stream);
+
+ if(_patchMap != null)
+ {
+ //
+ // Patch all instances now that the object is un-marshalled.
+ //
+ java.util.LinkedList<Patcher> l = _patchMap.get(index);
+ if(l != null)
+ {
+ assert(l.size() > 0);
+
+ //
+ // Patch all pointers that refer to the instance.
+ //
+ for(Patcher p : l)
+ {
+ p.patch(v);
+ }
+
+ //
+ // Clear out the patch map for that index -- there is nothing left
+ // to patch for that index for the time being.
+ //
+ _patchMap.remove(index);
+ }
+ }
+
+ if((_patchMap == null || _patchMap.isEmpty()) && _objectList == null)
+ {
+ try
+ {
+ v.ice_postUnmarshal();
+ }
+ catch(java.lang.Exception ex)
+ {
+ String s = "exception raised by ice_postUnmarshal:\n" + Ex.toString(ex);
+ _stream.instance().initializationData().logger.warning(s);
+ }
+ }
+ else
+ {
+ if(_objectList == null) // Lazy initialization
+ {
+ _objectList = new java.util.ArrayList<Ice.Object>();
+ }
+ _objectList.add(v);
+
+ if(_patchMap == null || _patchMap.isEmpty())
+ {
+ //
+ // Iterate over the object list and invoke ice_postUnmarshal on
+ // each object. We must do this after all objects have been
+ // unmarshaled in order to ensure that any object data members
+ // have been properly patched.
+ //
+ for(Ice.Object p : _objectList)
+ {
+ try
+ {
+ p.ice_postUnmarshal();
+ }
+ catch(java.lang.Exception ex)
+ {
+ String s = "exception raised by ice_postUnmarshal:\n" + Ex.toString(ex);
+ _stream.instance().initializationData().logger.warning(s);
+ }
+ }
+ _objectList.clear();
+ }
+ }
+ }
+
+ protected final BasicStream _stream;
+ protected final ReadEncaps _encaps;
+ protected final boolean _sliceObjects;
+ protected ObjectFactoryManager _servantFactoryManager;
+
+ // Encapsulation attributes for object un-marshalling
+ protected java.util.TreeMap<Integer, java.util.LinkedList<Patcher> > _patchMap;
+
+ // Encapsulation attributes for object un-marshalling
+ private java.util.TreeMap<Integer, Ice.Object> _unmarshaledMap;
+ private java.util.TreeMap<Integer, String> _typeIdMap;
+ private int _typeIdIndex;
+ private java.util.List<Ice.Object> _objectList;
+ }
+
+ private static final class EncapsDecoder10 extends EncapsDecoder
+ {
+ EncapsDecoder10(BasicStream stream, ReadEncaps encaps, boolean sliceObjects, ObjectFactoryManager f)
+ {
+ super(stream, encaps, sliceObjects, f);
+ _sliceType = SliceType.NoSlice;
+ }
+
+ void readObject(Patcher patcher)
+ {
+ assert(patcher != null);
+
+ //
+ // Object references are encoded as a negative integer in 1.0.
+ //
+ int index = _stream.readInt();
+ if(index > 0)
+ {
+ throw new Ice.MarshalException("invalid object id");
+ }
+ index = -index;
+
+ if(index == 0)
+ {
+ patcher.patch(null);
}
else
{
@@ -2909,19 +3049,9 @@ public class BasicStream
// that indicates whether or not the exception has classes.
//
// This allows reading the pending objects even if some part of
- // the exception was sliced. With encoding > 1.0, we don't need
- // this, each slice indirect patch table indicates the presence of
- // objects.
+ // the exception was sliced.
//
- boolean usesClasses;
- if(_encaps.encoding_1_0)
- {
- usesClasses = _stream.readBool();
- }
- else
- {
- usesClasses = true; // Always call readPendingObjects.
- }
+ boolean usesClasses = _stream.readBool();
_sliceType = SliceType.ExceptionSlice;
_skipFirstSlice = false;
@@ -2971,37 +3101,9 @@ public class BasicStream
}
//
- // Performance sensitive, so we use lazy initialization for
- // tracing.
- //
- if(_traceSlicing == -1)
- {
- _traceSlicing = _stream.instance().traceLevels().slicing;
- _slicingCat = _stream.instance().traceLevels().slicingCat;
- }
- if(_traceSlicing > 0)
- {
- TraceUtil.traceSlicing("exception", _typeId, _slicingCat,
- _stream.instance().initializationData().logger);
- }
-
- //
// Slice off what we don't understand.
//
skipSlice();
-
- if((_sliceFlags & FLAG_IS_LAST_SLICE) != 0)
- {
- if(mostDerivedId.length() > 2 && mostDerivedId.charAt(0) == ':' && mostDerivedId.charAt(1) == ':')
- {
- throw new Ice.UnknownUserException(mostDerivedId.substring(2));
- }
- else
- {
- throw new Ice.UnknownUserException(mostDerivedId);
- }
- }
-
try
{
startSlice();
@@ -3014,172 +3116,402 @@ public class BasicStream
// next type ID, which raises UnmarshalOutOfBoundsException when the
// input buffer underflows.
//
- if(_encaps.encoding_1_0)
- {
- // Set the reason member to a more helpful message.
- ex.reason = "unknown exception type `" + mostDerivedId + "'";
- }
+ // Set the reason member to a more helpful message.
+ //
+ ex.reason = "unknown exception type `" + mostDerivedId + "'";
throw ex;
}
}
}
- void startObject()
+ void startInstance(SliceType sliceType)
{
- assert(_sliceType == SliceType.ObjectSlice);
+ assert(_sliceType == sliceType);
_skipFirstSlice = true;
}
- Ice.SlicedData endObject(boolean preserve)
+ Ice.SlicedData endInstance(boolean preserve)
{
- if(_encaps.encoding_1_0)
+ //
+ // Read the Ice::Object slice.
+ //
+ if(_sliceType == SliceType.ObjectSlice)
{
- //
- // Read the Ice::Object slice.
- //
startSlice();
-
- //
- // For compatibility with the old AFM.
- //
- int sz = _stream.readSize();
+ int sz = _stream.readSize(); // For compatibility with the old AFM.
if(sz != 0)
{
throw new Ice.MarshalException("invalid Object slice");
}
-
endSlice();
}
_sliceType = SliceType.NoSlice;
- Ice.SlicedData slicedData = null;
- if(preserve)
+ return null;
+ }
+
+ String startSlice()
+ {
+ //
+ // If first slice, don't read the header, it was already read in
+ // readInstance or throwException to find the factory.
+ //
+ if(_skipFirstSlice)
{
- slicedData = readSlicedData();
+ _skipFirstSlice = false;
+ return _typeId;
}
- _slices.clear();
- _indirectionTables.clear();
- return slicedData;
+
+ //
+ // For objects, first read the type ID boolean which indicates
+ // whether or not the type ID is encoded as a string or as an
+ // index. For exceptions, the type ID is always encoded as a
+ // string.
+ //
+ if(_sliceType == SliceType.ObjectSlice) // For exceptions, the type ID is always encoded as a string
+ {
+ boolean isIndex = _stream.readBool();
+ _typeId = readTypeId(isIndex);
+ }
+ else
+ {
+ _typeId = _stream.readString();
+ }
+
+ _sliceSize = _stream.readInt();
+ if(_sliceSize < 4)
+ {
+ throw new Ice.UnmarshalOutOfBoundsException();
+ }
+
+ return _typeId;
}
- void startException()
+ void endSlice()
{
- assert(_sliceType == SliceType.ExceptionSlice);
- _skipFirstSlice = true;
}
- Ice.SlicedData endException(boolean preserve)
+ void skipSlice()
{
- _sliceType = SliceType.NoSlice;
- Ice.SlicedData slicedData = null;
- if(preserve)
+ if(_stream.instance().traceLevels().slicing > 0)
{
- slicedData = readSlicedData();
+ Ice.Logger logger = _stream.instance().initializationData().logger;
+ if(_sliceType == SliceType.ObjectSlice)
+ {
+ TraceUtil.traceSlicing("object", _typeId, _stream.instance().traceLevels().slicingCat, logger);
+ }
+ else
+ {
+ TraceUtil.traceSlicing("exception", _typeId, _stream.instance().traceLevels().slicingCat, logger);
+ }
}
- _slices.clear();
- _indirectionTables.clear();
- return slicedData;
+
+ assert(_sliceSize >= 4);
+ _stream.skip(_sliceSize - 4);
}
- String startSlice()
+ void readPendingObjects()
+ {
+ int num;
+ do
+ {
+ num = _stream.readSize();
+ for(int k = num; k > 0; --k)
+ {
+ readInstance();
+ }
+ }
+ while(num > 0);
+
+ if(_patchMap != null && !_patchMap.isEmpty())
+ {
+ //
+ // If any entries remain in the patch map, the sender has sent an index for an object, but failed
+ // to supply the object.
+ //
+ throw new Ice.MarshalException("index for class received, but no instance");
+ }
+ }
+
+ private void readInstance()
{
+ int index = _stream.readInt();
+
+ if(index <= 0)
+ {
+ throw new Ice.MarshalException("invalid object id");
+ }
+
+ _sliceType = SliceType.ObjectSlice;
+ _skipFirstSlice = false;
+
//
- // If first slice, don't read the header, it was already read in
- // readInstance or throwException to find the factory.
+ // Read the first slice header.
//
- if(_skipFirstSlice)
+ startSlice();
+ final String mostDerivedId = _typeId;
+ Ice.Object v = null;
+ while(true)
{
- _skipFirstSlice = false;
- return _typeId;
+ //
+ // For the 1.0 encoding, the type ID for the base Object class
+ // marks the last slice.
+ //
+ if(_typeId.equals(Ice.ObjectImpl.ice_staticId()))
+ {
+ throw new Ice.NoObjectFactoryException("", mostDerivedId);
+ }
+
+ v = newInstance(_typeId);
+
+ //
+ // We found a factory, we get out of this loop.
+ //
+ if(v != null)
+ {
+ break;
+ }
+
+ //
+ // If object slicing is disabled, stop un-marshalling.
+ //
+ if(!_sliceObjects)
+ {
+ throw new Ice.NoObjectFactoryException("object slicing is disabled", _typeId);
+ }
+
+ //
+ // Slice off what we don't understand.
+ //
+ skipSlice();
+ startSlice(); // Read next Slice header for next iteration.
}
//
- // Read the slice flags. For the 1.0 encoding there's no flag but
- // just a boolean for object slices. The boolean indicates whether
- // or not the type ID is encoded as a string or as an index.
+ // Un-marshal the object and add-it to the map of un-marshaled objects.
//
- if(_encaps.encoding_1_0)
+ unmarshal(index, v);
+ }
+
+ // Object/exception attributes
+ private SliceType _sliceType;
+ private boolean _skipFirstSlice;
+
+ // Slice attributes
+ private int _sliceSize;
+ private String _typeId;
+ }
+
+ private static class EncapsDecoder11 extends EncapsDecoder
+ {
+ EncapsDecoder11(BasicStream stream, ReadEncaps encaps, boolean sliceObjects, ObjectFactoryManager f)
+ {
+ super(stream, encaps, sliceObjects, f);
+ _objectIdIndex = 1;
+ _current = null;
+ }
+
+ void readObject(Patcher patcher)
+ {
+ int index = _stream.readSize();
+ if(index < 0)
{
- _sliceFlags = FLAG_HAS_SLICE_SIZE;
- if(_sliceType == SliceType.ObjectSlice) // For exceptions, the type ID is always encoded as a string
+ throw new Ice.MarshalException("invalid object id");
+ }
+ else if(index == 0)
+ {
+ if(patcher != null)
{
- boolean isIndex = _stream.readBool();
- _sliceFlags |= isIndex ? FLAG_HAS_TYPE_ID_INDEX : FLAG_HAS_TYPE_ID_STRING;
+ patcher.patch(null);
+ }
+ }
+ else if(_current != null && (_current.sliceFlags & FLAG_HAS_INDIRECTION_TABLE) != 0)
+ {
+ //
+ // When reading an object within a slice and there's an
+ // indirect object table, always read an indirect reference
+ // that points to an object from the indirect object table
+ // marshaled at the end of the Slice.
+ //
+ // Maintain a list of indirect references. Note that the
+ // indirect index starts at 1, so we decrement it by one to
+ // derive an index into the indirection table that we'll read
+ // at the end of the slice.
+ //
+ if(patcher != null)
+ {
+ if(_current.indirectPatchList == null) // Lazy initialization
+ {
+ _current.indirectPatchList = new java.util.ArrayDeque<IndirectPatchEntry>();
+ }
+ IndirectPatchEntry e = new IndirectPatchEntry();
+ e.index = index - 1;
+ e.patcher = patcher;
+ _current.indirectPatchList.push(e);
}
}
else
{
- _sliceFlags = _stream.readByte();
+ readInstance(index, patcher);
}
+ }
+
+ void throwException(UserExceptionFactory factory)
+ throws Ice.UserException
+ {
+ assert(_current == null);
+
+ push(SliceType.ExceptionSlice);
//
- // Read the type ID, for object slices the type ID is encoded as a
- // string or as an index, for exceptions it's always encoded as a
- // string.
+ // Read the first slice header.
//
- if(_sliceType == SliceType.ObjectSlice)
+ startSlice();
+ final String mostDerivedId = _current.typeId;
+ while(true)
{
- if((_sliceFlags & FLAG_HAS_TYPE_ID_COMPACT) == FLAG_HAS_TYPE_ID_COMPACT) // Must be checked first!
+ Ice.UserException userEx = null;
+
+ //
+ // Use a factory if one was provided.
+ //
+ if(factory != null)
{
- _typeId = "";
- _compactId = _stream.readSize();
+ try
+ {
+ factory.createAndThrow(_current.typeId);
+ }
+ catch(Ice.UserException ex)
+ {
+ userEx = ex;
+ }
}
- else if((_sliceFlags & FLAG_HAS_TYPE_ID_INDEX) != 0)
+
+ if(userEx == null)
{
- int index = _stream.readSize();
- _typeId = _typeIdMap.get(index);
- if(_typeId == null)
+ userEx = _stream.createUserException(_current.typeId);
+ }
+
+ //
+ // We found the exception.
+ //
+ if(userEx != null)
+ {
+ userEx.__read(_stream);
+ throw userEx;
+
+ // Never reached.
+ }
+
+ //
+ // Slice off what we don't understand.
+ //
+ skipSlice();
+
+ if((_current.sliceFlags & FLAG_IS_LAST_SLICE) != 0)
+ {
+ if(mostDerivedId.startsWith("::"))
+ {
+ throw new Ice.UnknownUserException(mostDerivedId.substring(2));
+ }
+ else
{
- throw new Ice.UnmarshalOutOfBoundsException();
+ throw new Ice.UnknownUserException(mostDerivedId);
}
- _compactId = -1;
}
- else if((_sliceFlags & FLAG_HAS_TYPE_ID_STRING) != 0)
+
+ startSlice();
+ }
+ }
+
+ void startInstance(SliceType sliceType)
+ {
+ assert(_current.sliceType == sliceType);
+ _current.skipFirstSlice = true;
+ }
+
+ Ice.SlicedData endInstance(boolean preserve)
+ {
+ Ice.SlicedData slicedData = null;
+ if(preserve)
+ {
+ slicedData = readSlicedData();
+ }
+ if(_current.slices != null)
+ {
+ _current.slices.clear();
+ _current.indirectionTables.clear();
+ }
+ _current = _current.previous;
+ return slicedData;
+ }
+
+ String startSlice()
+ {
+ //
+ // If first slice, don't read the header, it was already read in
+ // readInstance or throwException to find the factory.
+ //
+ if(_current.skipFirstSlice)
+ {
+ _current.skipFirstSlice = false;
+ return _current.typeId;
+ }
+
+ _current.sliceFlags = _stream.readByte();
+
+ //
+ // Read the type ID, for object slices the type ID is encoded as a
+ // string or as an index, for exceptions it's always encoded as a
+ // string.
+ //
+ if(_current.sliceType == SliceType.ObjectSlice)
+ {
+ if((_current.sliceFlags & FLAG_HAS_TYPE_ID_COMPACT) == FLAG_HAS_TYPE_ID_COMPACT) // Must be checked 1st!
+ {
+ _current.typeId = "";
+ _current.compactId = _stream.readSize();
+ }
+ else if((_current.sliceFlags & (FLAG_HAS_TYPE_ID_INDEX | FLAG_HAS_TYPE_ID_STRING)) != 0)
{
- _typeId = _stream.readString();
- _compactId = -1;
- _typeIdMap.put(++_typeIdIndex, _typeId);
+ _current.typeId = readTypeId((_current.sliceFlags & FLAG_HAS_TYPE_ID_INDEX) != 0);
+ _current.compactId = -1;
}
else
{
- // Only the most derived slice encodes the type ID for the
- // compact format.
- _typeId = "";
- _compactId = -1;
+ // Only the most derived slice encodes the type ID for the compact format.
+ _current.typeId = "";
+ _current.compactId = -1;
}
}
else
{
- _typeId = _stream.readString();
- _compactId = -1;
+ _current.typeId = _stream.readString();
+ _current.compactId = -1;
}
//
// Read the slice size if necessary.
//
- if((_sliceFlags & FLAG_HAS_SLICE_SIZE) != 0)
+ if((_current.sliceFlags & FLAG_HAS_SLICE_SIZE) != 0)
{
- _sliceSize = _stream.readInt();
- if(_sliceSize < 4)
+ _current.sliceSize = _stream.readInt();
+ if(_current.sliceSize < 4)
{
throw new Ice.UnmarshalOutOfBoundsException();
}
}
else
{
- _sliceSize = 0;
+ _current.sliceSize = 0;
}
- //
- // Reset the indirect patch list for this new slice.
- //
- _indirectPatchList.clear();
- return _typeId;
+ return _current.typeId;
}
void endSlice()
{
- if((_sliceFlags & FLAG_HAS_OPTIONAL_MEMBERS) != 0)
+ if((_current.sliceFlags & FLAG_HAS_OPTIONAL_MEMBERS) != 0)
{
_stream.skipOpts();
}
@@ -3188,24 +3520,28 @@ public class BasicStream
// Read the indirection table if one is present and transform the
// indirect patch list into patch entries with direct references.
//
- if((_sliceFlags & FLAG_HAS_INDIRECTION_TABLE) != 0)
+ if((_current.sliceFlags & FLAG_HAS_INDIRECTION_TABLE) != 0)
{
//
// The table is written as a sequence<size> to conserve space.
//
- int[] indirectionTable = _stream.readSizeSeq();
-
+ int[] indirectionTable = new int[_stream.readAndCheckSeqSize(1)];
+ for(int i = 0; i < indirectionTable.length; ++i)
+ {
+ indirectionTable[i] = readInstance(_stream.readSize(), null);
+ }
+
//
// Sanity checks. If there are optional members, it's possible
// that not all object references were read if they are from
// unknown optional data members.
//
- if(indirectionTable.length == 0 && !_indirectPatchList.isEmpty())
+ if(indirectionTable.length == 0)
{
throw new Ice.MarshalException("empty indirection table");
}
- else if(indirectionTable.length > 0 && _indirectPatchList.isEmpty() &&
- (_sliceFlags & FLAG_HAS_OPTIONAL_MEMBERS) == 0)
+ if((_current.indirectPatchList == null || _current.indirectPatchList.isEmpty()) &&
+ (_current.sliceFlags & FLAG_HAS_OPTIONAL_MEMBERS) == 0)
{
throw new Ice.MarshalException("no references to indirection table");
}
@@ -3213,217 +3549,177 @@ public class BasicStream
//
// Convert indirect references into direct references.
//
- for(IndirectPatchEntry e : _indirectPatchList)
+ if(_current.indirectPatchList != null)
{
- assert(e.index >= 0);
- if(e.index >= indirectionTable.length)
+ for(IndirectPatchEntry e : _current.indirectPatchList)
{
- throw new Ice.MarshalException("indirection out of range");
- }
- final int id = indirectionTable[e.index];
- if(id <= 0)
- {
- //
- // Entries in the table must be positive, just like a regular object reference.
- //
- throw new Ice.MarshalException("invalid id in object indirection table");
+ assert(e.index >= 0);
+ if(e.index >= indirectionTable.length)
+ {
+ throw new Ice.MarshalException("indirection out of range");
+ }
+ addPatchEntry(indirectionTable[e.index], e.patcher);
}
- addPatchEntry(id, e.patcher);
+ _current.indirectPatchList.clear();
}
}
}
void skipSlice()
{
+ if(_stream.instance().traceLevels().slicing > 0)
+ {
+ Ice.Logger logger = _stream.instance().initializationData().logger;
+ String slicingCat = _stream.instance().traceLevels().slicingCat;
+ if(_current.sliceType == SliceType.ExceptionSlice)
+ {
+ TraceUtil.traceSlicing("exception", _current.typeId, slicingCat, logger);
+ }
+ else
+ {
+ TraceUtil.traceSlicing("object", _current.typeId, slicingCat, logger);
+ }
+ }
+
int start = _stream.pos();
- if((_sliceFlags & FLAG_HAS_SLICE_SIZE) != 0)
+ if((_current.sliceFlags & FLAG_HAS_SLICE_SIZE) != 0)
{
- assert(_sliceSize >= 4);
- _stream.skip(_sliceSize - 4);
+ assert(_current.sliceSize >= 4);
+ _stream.skip(_current.sliceSize - 4);
}
else
{
- if(_sliceType == SliceType.ObjectSlice)
+ if(_current.sliceType == SliceType.ObjectSlice)
{
throw new Ice.NoObjectFactoryException(
"compact format prevents slicing (the sender should use the sliced format instead)",
- _typeId);
+ _current.typeId);
}
else
{
- throw new Ice.UnknownUserException(_typeId.substring(2));
+ if(_current.typeId.startsWith("::"))
+ {
+ throw new Ice.UnknownUserException(_current.typeId.substring(2));
+ }
+ else
+ {
+ throw new Ice.UnknownUserException(_current.typeId);
+ }
}
}
- if(!_encaps.encoding_1_0)
+ //
+ // Preserve this slice.
+ //
+ Ice.SliceInfo info = new Ice.SliceInfo();
+ info.typeId = _current.typeId;
+ info.compactId = _current.compactId;
+ info.hasOptionalMembers = (_current.sliceFlags & FLAG_HAS_OPTIONAL_MEMBERS) != 0;
+ info.isLastSlice = (_current.sliceFlags & FLAG_IS_LAST_SLICE) != 0;
+ java.nio.ByteBuffer b = _stream.getBuffer().b;
+ final int end = b.position();
+ int dataEnd = end;
+ if(info.hasOptionalMembers)
{
//
- // Preserve this slice.
+ // Don't include the optional member end marker. It will be re-written by
+ // endSlice when the sliced data is re-written.
//
- Ice.SliceInfo info = new Ice.SliceInfo();
- info.typeId = _typeId;
- info.compactId = _compactId;
- info.hasOptionalMembers = (_sliceFlags & FLAG_HAS_OPTIONAL_MEMBERS) != 0;
- info.isLastSlice = (_sliceFlags & FLAG_IS_LAST_SLICE) != 0;
- java.nio.ByteBuffer b = _stream.getBuffer().b;
- final int end = b.position();
- int dataEnd = end;
- if(info.hasOptionalMembers)
- {
- //
- // Don't include the optional member end marker. It will be re-written by
- // endSlice when the sliced data is re-written.
- //
- --dataEnd;
- }
- info.bytes = new byte[dataEnd - start];
- b.position(start);
- b.get(info.bytes);
- b.position(end);
- _slices.add(info);
-
- if((_sliceFlags & FLAG_HAS_INDIRECTION_TABLE) != 0)
- {
- //
- // Read the indirection table, which is written as a sequence<size> to conserve space.
- //
- _indirectionTables.add(_stream.readSizeSeq());
- }
- else
- {
- _indirectionTables.add(new int[0]);
- }
+ --dataEnd;
}
- }
+ info.bytes = new byte[dataEnd - start];
+ b.position(start);
+ b.get(info.bytes);
+ b.position(end);
- boolean readOpt(int readTag, Ice.OptionalFormat expectedFormat)
- {
- if(_sliceType == SliceType.NoSlice)
- {
- return _stream.readOptImpl(readTag, expectedFormat);
- }
- else if((_sliceFlags & FLAG_HAS_OPTIONAL_MEMBERS) != 0)
+ if(_current.slices == null) // Lazy initialization
{
- return _stream.readOptImpl(readTag, expectedFormat);
+ _current.slices = new java.util.ArrayList<Ice.SliceInfo>();
+ _current.indirectionTables = new java.util.ArrayList<int[]>();
}
- return false;
- }
- void readPendingObjects()
- {
//
- // With the 1.0 encoding, we read pending objects if the marshaled
- // data uses classes. Otherwise, only read pending objects if some
- // non-nil references were read.
+ // Read the indirect object table. We read the instances or their
+ // IDs if the instance is a reference to an already un-marhsaled
+ // object.
+ //
+ // The SliceInfo object sequence is initialized only if
+ // readSlicedData is called.
//
- if(!_encaps.encoding_1_0)
- {
- if(_patchMap.isEmpty())
- {
- return;
- }
- else
- {
- //
- // Read unread encapsulation optionals before reading the
- // pending objects.
- //
- _stream.skipOpts();
- }
- }
- int num;
- java.util.ArrayList<Ice.Object> objectList = new java.util.ArrayList<Ice.Object>();
- do
+ if((_current.sliceFlags & FLAG_HAS_INDIRECTION_TABLE) != 0)
{
- num = _stream.readSize();
- for(int k = num; k > 0; --k)
+ int[] indirectionTable = new int[_stream.readAndCheckSeqSize(1)];
+ for(int i = 0; i < indirectionTable.length; ++i)
{
- objectList.add(readInstance());
- }
+ indirectionTable[i] = readInstance(_stream.readSize(), null);
+ }
+ _current.indirectionTables.add(indirectionTable);
}
- while(num > 0);
-
- if(!_patchMap.isEmpty())
+ else
{
- //
- // If any entries remain in the patch map, the sender has sent an index for an object, but failed
- // to supply the object.
- //
- throw new Ice.MarshalException("index for class received, but no instance");
+ _current.indirectionTables.add(null);
}
- //
- // Iterate over the object list and invoke ice_postUnmarshal on
- // each object. We must do this after all objects have been
- // unmarshaled in order to ensure that any object data members
- // have been properly patched.
- //
- for(Ice.Object p : objectList)
- {
- try
- {
- p.ice_postUnmarshal();
- }
- catch(java.lang.Exception ex)
- {
- String s = "exception raised by ice_postUnmarshal:\n" + Ex.toString(ex);
- _stream.instance().initializationData().logger.warning("exception raised by ice_postUnmarshal:\n");
- }
- }
+ _current.slices.add(info);
}
- private Ice.Object readInstance()
+ boolean readOpt(int readTag, Ice.OptionalFormat expectedFormat)
{
- int index;
- if(_encaps.encoding_1_0)
+ if(_current == null)
{
- index = _stream.readInt();
+ return _stream.readOptImpl(readTag, expectedFormat);
}
- else
+ else if((_current.sliceFlags & FLAG_HAS_OPTIONAL_MEMBERS) != 0)
{
- index = _stream.readSize();
+ return _stream.readOptImpl(readTag, expectedFormat);
}
+ return false;
+ }
- Ice.Object v = null;
- if(index <= 0)
+ private int readInstance(int index, Patcher patcher)
+ {
+ assert(index > 0);
+
+ if(index > 1)
{
- throw new Ice.MarshalException("invalid object id");
+ if(patcher != null)
+ {
+ addPatchEntry(index, patcher);
+ }
+ return index;
}
- _sliceType = SliceType.ObjectSlice;
- _skipFirstSlice = false;
+ push(SliceType.ObjectSlice);
+
+ //
+ // Get the object ID before we start reading slices. If some
+ // slices are skiped, the indirect object table are still read and
+ // might read other objects.
+ //
+ index = ++_objectIdIndex;
//
// Read the first slice header.
//
startSlice();
- final String mostDerivedId = _typeId;
- final ObjectFactoryManager servantFactoryManager = _stream.instance().servantFactoryManager();
+ final String mostDerivedId = _current.typeId;
+ Ice.Object v = null;
final Ice.CompactIdResolver compactIdResolver = _stream.instance().initializationData().compactIdResolver;
while(true)
{
- //
- // For the 1.0 encoding, the type ID for the base Object class
- // marks the last slice.
- //
- if(_typeId.equals(Ice.ObjectImpl.ice_staticId()))
- {
- throw new Ice.NoObjectFactoryException("", mostDerivedId);
- }
-
- if(_compactId >= 0)
+ if(_current.compactId >= 0)
{
//
// Translate a compact (numeric) type ID into a string type ID.
//
- _typeId = "";
+ _current.typeId = "";
if(compactIdResolver != null)
{
try
{
- _typeId = compactIdResolver.resolve(_compactId);
+ _current.typeId = compactIdResolver.resolve(_current.compactId);
}
catch(Ice.LocalException ex)
{
@@ -3431,46 +3727,19 @@ public class BasicStream
}
catch(Throwable ex)
{
- throw new Ice.MarshalException("exception in CompactIdResolver for ID " + _compactId, ex);
+ throw new Ice.MarshalException("exception in CompactIdResolver for ID " +
+ _current.compactId, ex);
}
}
- if(_typeId.length() == 0)
+ if(_current.typeId.length() == 0)
{
- _typeId = _stream.getTypeId(_compactId);
+ _current.typeId = _stream.getTypeId(_current.compactId);
}
}
- if(_typeId.length() > 0)
+ if(_current.typeId.length() > 0)
{
- //
- // Try to find a factory registered for the specific type.
- //
- Ice.ObjectFactory userFactory = servantFactoryManager.find(_typeId);
- if(userFactory != null)
- {
- v = userFactory.create(_typeId);
- }
-
- //
- // If that fails, invoke the default factory if one has been
- // registered.
- //
- if(v == null)
- {
- userFactory = servantFactoryManager.find("");
- if(userFactory != null)
- {
- v = userFactory.create(_typeId);
- }
- }
-
- //
- // Last chance: try to instantiate the class dynamically.
- //
- if(v == null)
- {
- v = _stream.createObject(_typeId);
- }
+ v = newInstance(_current.typeId);
//
// We found a factory, we get out of this loop.
@@ -3482,25 +3751,11 @@ public class BasicStream
}
//
- // Performance sensitive, so we use lazy initialization for tracing.
- //
- if(_traceSlicing == -1)
- {
- _traceSlicing = _stream.instance().traceLevels().slicing;
- _slicingCat = _stream.instance().traceLevels().slicingCat;
- }
- if(_traceSlicing > 0)
- {
- TraceUtil.traceSlicing("class", _typeId, _slicingCat,
- _stream.instance().initializationData().logger);
- }
-
- //
// If object slicing is disabled, stop un-marshalling.
//
if(!_sliceObjects)
{
- throw new Ice.NoObjectFactoryException("object slicing is disabled", _typeId);
+ throw new Ice.NoObjectFactoryException("object slicing is disabled", _current.typeId);
}
//
@@ -3512,9 +3767,19 @@ public class BasicStream
// If this is the last slice, keep the object as an opaque
// UnknownSlicedData object.
//
- if((_sliceFlags & FLAG_IS_LAST_SLICE) != 0)
+ if((_current.sliceFlags & FLAG_IS_LAST_SLICE) != 0)
{
- v = new Ice.UnknownSlicedObject(mostDerivedId);
+ //
+ // Provide a factory with an opportunity to supply the object.
+ // We pass the "::Ice::Object" ID to indicate that this is the
+ // last chance to preserve the object.
+ //
+ v = newInstance(Ice.ObjectImpl.ice_staticId());
+ if(v == null)
+ {
+ v = new Ice.UnknownSlicedObject(mostDerivedId);
+ }
+
break;
}
@@ -3522,83 +3787,29 @@ public class BasicStream
}
//
- // Add the object to the map of un-marshalled objects, this must
- // be done before reading the objects (for circular references).
+ // Un-marshal the object
//
- _unmarshaledMap.put(index, v);
+ unmarshal(index, v);
- //
- // Read the object.
- //
- v.__read(_stream);
-
- //
- // Patch all instances now that the object is un-marshalled.
- //
- java.util.LinkedList<Patcher> l = _patchMap.get(index);
- if(l != null)
+ if(_current == null && _patchMap != null && !_patchMap.isEmpty())
{
- assert(l.size() > 0);
-
- //
- // Patch all pointers that refer to the instance.
//
- for(Patcher p : l)
- {
- p.patch(v);
- }
-
- //
- // Clear out the patch map for that index -- there is nothing left
- // to patch for that index for the time being.
+ // If any entries remain in the patch map, the sender has sent an index for an object, but failed
+ // to supply the object.
//
- _patchMap.remove(index);
+ throw new Ice.MarshalException("index for class received, but no instance");
}
- return v;
- }
-
- private void addPatchEntry(int index, Patcher patcher)
- {
- assert(index > 0);
-
- //
- // Check if already un-marshalled the object. If that's the case,
- // just patch the object smart pointer and we're done.
- //
- Ice.Object obj = _unmarshaledMap.get(index);
- if(obj != null)
+ if(patcher != null)
{
- patcher.patch(obj);
- return;
+ patcher.patch(v);
}
-
- //
- // Add patch entry if the object isn't un-marshalled yet, the
- // smart pointer will be patched when the instance is
- // un-marshalled.
- //
-
- java.util.LinkedList<Patcher> l = _patchMap.get(index);
- if(l == null)
- {
- //
- // We have no outstanding instances to be patched for this
- // index, so make a new entry in the patch map.
- //
- l = new java.util.LinkedList<Patcher>();
- _patchMap.put(index, l);
- }
-
- //
- // Append a patch entry for this instance.
- //
- l.add(patcher);
+ return index;
}
private Ice.SlicedData readSlicedData()
{
- if(_slices.isEmpty()) // No preserved slices.
+ if(_current.slices == null) // No preserved slices.
{
return null;
}
@@ -3607,199 +3818,162 @@ public class BasicStream
// The _indirectionTables member holds the indirection table for each slice
// in _slices.
//
- assert(_slices.size() == _indirectionTables.size());
-
- for(int n = 0; n < _slices.size(); ++n)
+ assert(_current.slices.size() == _current.indirectionTables.size());
+ for(int n = 0; n < _current.slices.size(); ++n)
{
//
- // We use the "objects" list in SliceInfo to hold references to the target
- // objects. Note however that we may not have actually read these objects
- // yet, so they need to be treated just like we had read the object references
- // directly (i.e., we add them to the patch list).
- //
- // Another important note: the SlicedData object that we return here must
- // not be destroyed before readPendingObjects is called, otherwise the
- // patch references will refer to invalid addresses.
+ // We use the "objects" list in SliceInfo to hold references
+ // to the target objects. Note that the objects might not have
+ // been read yet in the case of a circular reference to an
+ // enclosing object.
//
- final int[] table = _indirectionTables.get(n);
- Ice.SliceInfo info = _slices.get(n);
- info.objects = new Ice.Object[table.length];
- for(int j = 0; j < table.length; ++j)
+ final int[] table = _current.indirectionTables.get(n);
+ Ice.SliceInfo info = _current.slices.get(n);
+ info.objects = new Ice.Object[table != null ? table.length : 0];
+ for(int j = 0; j < info.objects.length; ++j)
{
- if(table[j] <= 0)
- {
- throw new Ice.MarshalException("invalid id in object indirection table");
- }
- SequencePatcher patcher = new SequencePatcher(info.objects, Ice.Object.class,
- Ice.ObjectImpl.ice_staticId(), j);
- addPatchEntry(table[j], patcher);
+ addPatchEntry(table[j], new SequencePatcher(info.objects, Ice.Object.class,
+ Ice.ObjectImpl.ice_staticId(), j));
}
}
- Ice.SliceInfo[] arr = new Ice.SliceInfo[_slices.size()];
- _slices.toArray(arr);
+ Ice.SliceInfo[] arr = new Ice.SliceInfo[_current.slices.size()];
+ _current.slices.toArray(arr);
return new Ice.SlicedData(arr);
}
- private boolean skipOpt(int format)
+ private void push(SliceType sliceType)
{
- int sz;
- switch(format)
- {
- case MemberFormatF1:
+ if(_current == null)
{
- sz = 1;
- break;
+ _current = new InstanceData(null);
}
- case MemberFormatF2:
- {
- sz = 2;
- break;
- }
- case MemberFormatF4:
- {
- sz = 4;
- break;
- }
- case MemberFormatF8:
- {
- sz = 8;
- break;
- }
- case MemberFormatVSize:
- {
- sz = _stream.readSize();
- break;
- }
- case MemberFormatFSize:
- {
- sz = _stream.readInt();
- break;
- }
- default:
+ else
{
- return false;
- }
+ _current = _current.next == null ? new InstanceData(_current) : _current.next;
}
+ _current.sliceType = sliceType;
+ _current.skipFirstSlice = false;
+ }
- int pos = _stream.pos();
- if(pos + sz > _stream.size())
+ private static final class IndirectPatchEntry
+ {
+ int index;
+ Patcher patcher;
+ }
+
+ private static final class InstanceData
+ {
+ InstanceData(InstanceData previous)
{
- throw new Ice.UnmarshalOutOfBoundsException();
+ if(previous != null)
+ {
+ previous.next = this;
+ }
+ this.previous = previous;
+ this.next = null;
}
- _stream.pos(pos + sz);
- return true;
- }
- private final BasicStream _stream;
- private final ReadEncaps _encaps;
- private final boolean _sliceObjects;
+ // Instance attributes
+ SliceType sliceType;
+ boolean skipFirstSlice;
+ java.util.List<Ice.SliceInfo> slices; // Preserved slices.
+ java.util.List<int[]> indirectionTables;
+
+ // Slice attributes
+ byte sliceFlags;
+ int sliceSize;
+ String typeId;
+ int compactId;
+ java.util.Deque<IndirectPatchEntry> indirectPatchList;
+
+ final InstanceData previous;
+ InstanceData next;
+ };
+ private InstanceData _current;
- private int _traceSlicing;
- private String _slicingCat;
+ private int _objectIdIndex; // The ID of the next object to un-marshal.
+ };
- // Object/exception attributes
- private SliceType _sliceType;
- private boolean _skipFirstSlice;
- private java.util.ArrayList<Ice.SliceInfo> _slices; // Preserved slices.
- private java.util.ArrayList<int[]> _indirectionTables;
+ abstract private static class EncapsEncoder
+ {
+ protected EncapsEncoder(BasicStream stream, WriteEncaps encaps)
+ {
+ _stream = stream;
+ _encaps = encaps;
+ _typeIdIndex = 0;
+ _marshaledMap = new java.util.IdentityHashMap<Ice.Object, Integer>();
+ }
+
+ abstract void writeObject(Ice.Object v);
+ abstract void writeUserException(Ice.UserException v);
+
+ abstract void startInstance(SliceType type, Ice.SlicedData data);
+ abstract void endInstance();
+ abstract void startSlice(String typeId, int compactId, boolean last);
+ abstract void endSlice();
- // Slice attributes
- private byte _sliceFlags;
- private int _sliceSize;
- private String _typeId;
- private int _compactId;
+ boolean writeOpt(int tag, Ice.OptionalFormat format)
+ {
+ return false;
+ }
- private static final class IndirectPatchEntry
+ void writePendingObjects()
{
- int index;
- Patcher patcher;
}
- private java.util.ArrayList<IndirectPatchEntry> _indirectPatchList;
- // Encapsulation attributes for object un-marshalling
- private java.util.TreeMap<Integer, java.util.LinkedList<Patcher> > _patchMap;
- private java.util.TreeMap<Integer, Ice.Object> _unmarshaledMap;
- private java.util.TreeMap<Integer, String> _typeIdMap;
+ protected int registerTypeId(String typeId)
+ {
+ if(_typeIdMap == null) // Lazy initialization
+ {
+ _typeIdMap = new java.util.TreeMap<String, Integer>();
+ }
+
+ Integer p = _typeIdMap.get(typeId);
+ if(p != null)
+ {
+ return p;
+ }
+ else
+ {
+ _typeIdMap.put(typeId, ++_typeIdIndex);
+ return -1;
+ }
+ }
+
+ final protected BasicStream _stream;
+ final protected WriteEncaps _encaps;
+
+ // Encapsulation attributes for object marshalling.
+ final protected java.util.IdentityHashMap<Ice.Object, Integer> _marshaledMap;
+
+ // Encapsulation attributes for object marshalling.
+ private java.util.TreeMap<String, Integer> _typeIdMap;
private int _typeIdIndex;
- }
+ };
- private static final class EncapsEncoder
+ private static final class EncapsEncoder10 extends EncapsEncoder
{
- EncapsEncoder(BasicStream stream, WriteEncaps encaps)
+ EncapsEncoder10(BasicStream stream, WriteEncaps encaps)
{
- _stream = stream;
- _encaps = encaps;
+ super(stream, encaps);
_sliceType = SliceType.NoSlice;
_objectIdIndex = 0;
- _typeIdIndex = 0;
- _indirectionTable = new java.util.ArrayList<Integer>();
- _indirectionMap = new java.util.TreeMap<Integer, Integer>();
_toBeMarshaledMap = new java.util.IdentityHashMap<Ice.Object, Integer>();
- _marshaledMap = new java.util.IdentityHashMap<Ice.Object, Integer>();
- _typeIdMap = new java.util.TreeMap<String, Integer>();
}
void writeObject(Ice.Object v)
{
+ //
+ // Object references are encoded as a negative integer in 1.0.
+ //
if(v != null)
{
- //
- // Register the object.
- //
- int index = registerObject(v);
-
- if(_encaps.encoding_1_0)
- {
- //
- // Object references are encoded as a negative integer in 1.0.
- //
- _stream.writeInt(-index);
- }
- else if(_sliceType != SliceType.NoSlice && _encaps.format == Ice.FormatType.SlicedFormat)
- {
- //
- // An object reference that appears inside a slice of an
- // object or exception encoded as a positive non-zero
- // index into a per-slice indirection table.
- //
- // We use _indirectionMap to keep track of the object
- // references in the current slice; it maps the object
- // reference to the position in the indirection list. Note
- // that the position is offset by one (e.g., the first
- // position = 1).
- //
- Integer p = _indirectionMap.get(index);
- if(p == null)
- {
- _indirectionTable.add(index);
- int sz = _indirectionTable.size(); // Position + 1
- _indirectionMap.put(index, sz);
- _stream.writeSize(sz);
- }
- else
- {
- _stream.writeSize(p.intValue());
- }
- }
- else
- {
- _stream.writeSize(index);
- }
+ _stream.writeInt(-registerObject(v));
}
else
{
- //
- // Write nil reference.
- //
- if(_encaps.encoding_1_0)
- {
- _stream.writeInt(0);
- }
- else
- {
- _stream.writeSize(0);
- }
+ _stream.writeInt(0);
}
}
@@ -3811,40 +3985,26 @@ public class BasicStream
// classes.
//
// This allows reading the pending objects even if some part of
- // the exception was sliced. With encoding > 1.0, we don't need
- // this, each slice indirect patch table indicates the presence of
- // objects.
+ // the exception was sliced.
//
- boolean usesClasses;
- if(_encaps.encoding_1_0)
- {
- usesClasses = v.__usesClasses();
- _stream.writeBool(usesClasses);
- }
- else
- {
- usesClasses = true; // Always call writePendingObjects
- }
+ boolean usesClasses = v.__usesClasses();
+ _stream.writeBool(usesClasses);
v.__write(_stream);
if(usesClasses)
{
writePendingObjects();
}
}
-
- void startObject(Ice.SlicedData data)
+
+ void startInstance(SliceType sliceType, Ice.SlicedData sliceData)
{
- _sliceType = SliceType.ObjectSlice;
+ _sliceType = sliceType;
_firstSlice = true;
- if(data != null)
- {
- writeSlicedData(data);
- }
}
- void endObject()
+ void endInstance()
{
- if(_encaps.encoding_1_0)
+ if(_sliceType == SliceType.ObjectSlice)
{
//
// Write the Object slice.
@@ -3856,102 +4016,272 @@ public class BasicStream
_sliceType = SliceType.NoSlice;
}
- void startException(Ice.SlicedData data)
+ void startSlice(String typeId, int compactId, boolean last)
{
- _sliceType = SliceType.ExceptionSlice;
- _firstSlice = true;
- if(data != null)
+ //
+ // For object slices, encode a boolean to indicate how the type ID
+ // is encoded and the type ID either as a string or index. For
+ // exception slices, always encode the type ID as a string.
+ //
+ if(_sliceType == SliceType.ObjectSlice)
{
- writeSlicedData(data);
+ int index = registerTypeId(typeId);
+ if(index < 0)
+ {
+ _stream.writeBool(false);
+ _stream.writeString(typeId);
+ }
+ else
+ {
+ _stream.writeBool(true);
+ _stream.writeSize(index);
+ }
+ }
+ else
+ {
+ _stream.writeString(typeId);
}
+
+ _stream.writeInt(0); // Placeholder for the slice length.
+
+ _writeSlice = _stream.pos();
+ _firstSlice = false;
}
- void endException()
+ void endSlice()
{
- _sliceType = SliceType.NoSlice;
+ //
+ // Write the slice length.
+ //
+ final int sz = _stream.pos() - _writeSlice + 4;
+ _stream.rewriteInt(sz, _writeSlice - 4);
}
- void startSlice(String typeId, int compactId, boolean last)
+ void writePendingObjects()
{
- assert(_indirectionTable.isEmpty() && _indirectionMap.isEmpty());
- _sliceFlags = (byte)0;
- _sliceFlagsPos = _stream.pos();
+ while(_toBeMarshaledMap.size() > 0)
+ {
+ //
+ // Consider the to be marshalled objects as marshalled now,
+ // this is necessary to avoid adding again the "to be
+ // marshalled objects" into _toBeMarshaledMap while writing
+ // objects.
+ //
+ _marshaledMap.putAll(_toBeMarshaledMap);
+
+ java.util.IdentityHashMap<Ice.Object, Integer> savedMap = _toBeMarshaledMap;
+ _toBeMarshaledMap = new java.util.IdentityHashMap<Ice.Object, Integer>();
+ _stream.writeSize(savedMap.size());
+ for(java.util.Map.Entry<Ice.Object, Integer> p : savedMap.entrySet())
+ {
+ //
+ // Ask the instance to marshal itself. Any new class
+ // instances that are triggered by the classes marshaled
+ // are added to toBeMarshaledMap.
+ //
+ _stream.writeInt(p.getValue().intValue());
+
+ try
+ {
+ p.getKey().ice_preMarshal();
+ }
+ catch(java.lang.Exception ex)
+ {
+ String s = "exception raised by ice_preMarshal:\n" + Ex.toString(ex);
+ _stream.instance().initializationData().logger.warning(s);
+ }
+
+ p.getKey().__write(_stream);
+ }
+ }
+ _stream.writeSize(0); // Zero marker indicates end of sequence of sequences of instances.
+ }
+
+ private int registerObject(Ice.Object v)
+ {
+ assert(v != null);
+
+ //
+ // Look for this instance in the to-be-marshaled map.
+ //
+ Integer p = _toBeMarshaledMap.get(v);
+ if(p != null)
+ {
+ return p.intValue();
+ }
//
- // Encode the slice size for the old encoding and if using the
- // sliced format.
+ // Didn't find it, try the marshaled map next.
//
- if(_encaps.encoding_1_0 || _encaps.format == Ice.FormatType.SlicedFormat)
+ p = _marshaledMap.get(v);
+ if(p != null)
{
- _sliceFlags |= FLAG_HAS_SLICE_SIZE;
+ return p.intValue();
}
//
- // This is the last slice.
+ // We haven't seen this instance previously, create a new
+ // index, and insert it into the to-be-marshaled map.
//
+ _toBeMarshaledMap.put(v, ++_objectIdIndex);
+ return _objectIdIndex;
+ }
+
+ // Instance attributes
+ private SliceType _sliceType;
+ private boolean _firstSlice;
+
+ // Slice attributes
+ private int _writeSlice; // Position of the slice data members
+
+ // Encapsulation attributes for object marshalling.
+ private int _objectIdIndex;
+ private java.util.IdentityHashMap<Ice.Object, Integer> _toBeMarshaledMap;
+ };
+
+ private static final class EncapsEncoder11 extends EncapsEncoder
+ {
+ EncapsEncoder11(BasicStream stream, WriteEncaps encaps)
+ {
+ super(stream, encaps);
+ _current = null;
+ _objectIdIndex = 1;
+ }
+
+ void writeObject(Ice.Object v)
+ {
+ if(v == null)
+ {
+ _stream.writeSize(0);
+ }
+ else if(_current != null && _encaps.format == Ice.FormatType.SlicedFormat)
+ {
+ if(_current.indirectionTable == null) // Lazy initialization
+ {
+ _current.indirectionTable = new java.util.ArrayList<Ice.Object>();
+ _current.indirectionMap = new java.util.IdentityHashMap<Ice.Object, Integer>();
+ }
+
+ //
+ // If writting an object within a slice and using the sliced
+ // format, write an index from the object indirection
+ // table. The indirect object table is encoded at the end of
+ // each slice and is always read (even if the Slice is
+ // unknown).
+ //
+ Integer index = _current.indirectionMap.get(v);
+ if(index == null)
+ {
+ _current.indirectionTable.add(v);
+ final int idx = _current.indirectionTable.size(); // Position + 1 (0 is reserved for nil)
+ _current.indirectionMap.put(v, idx);
+ _stream.writeSize(idx);
+ }
+ else
+ {
+ _stream.writeSize(index.intValue());
+ }
+ }
+ else
+ {
+ writeInstance(v); // Write the instance or a reference if already marshaled.
+ }
+ }
+
+ void writeUserException(Ice.UserException v)
+ {
+ v.__write(_stream);
+ }
+
+ void startInstance(SliceType sliceType, Ice.SlicedData data)
+ {
+ if(_current == null)
+ {
+ _current = new InstanceData(null);
+ }
+ else
+ {
+ _current = _current.next == null ? new InstanceData(_current) : _current.next;
+ }
+ _current.sliceType = sliceType;
+ _current.firstSlice = true;
+
+ if(data != null)
+ {
+ writeSlicedData(data);
+ }
+ }
+
+ void endInstance()
+ {
+ _current = _current.previous;
+ }
+
+ void startSlice(String typeId, int compactId, boolean last)
+ {
+ assert((_current.indirectionTable == null || _current.indirectionTable.isEmpty()) &&
+ (_current.indirectionMap == null || _current.indirectionMap.isEmpty()));
+
+ _current.sliceFlagsPos = _stream.pos();
+
+ _current.sliceFlags = (byte)0;
+ if(_encaps.format == Ice.FormatType.SlicedFormat)
+ {
+ _current.sliceFlags |= FLAG_HAS_SLICE_SIZE; // Encode the slice size if using the sliced format.
+ }
if(last)
{
- _sliceFlags |= FLAG_IS_LAST_SLICE;
+ _current.sliceFlags |= FLAG_IS_LAST_SLICE; // This is the last slice.
}
+ _stream.writeByte((byte)0); // Placeholder for the slice flags
+
//
// For object slices, encode the flag and the type ID either as a
- // string or index. For exception slices, don't encode slice flags
- // for the old encoding and always encode the type ID a string.
+ // string or index. For exception slices, always encode the type
+ // ID a string.
//
- if(_sliceType == SliceType.ObjectSlice)
+ if(_current.sliceType == SliceType.ObjectSlice)
{
- _stream.writeByte((byte)0); // Placeholder for the slice flags
-
//
// Encode the type ID (only in the first slice for the compact
// encoding).
- //
- if(_encaps.format == Ice.FormatType.SlicedFormat || _encaps.encoding_1_0 || _firstSlice)
+ //
+ if(_encaps.format == Ice.FormatType.SlicedFormat || _current.firstSlice)
{
- if(!_encaps.encoding_1_0 && compactId >= 0)
+ if(compactId >= 0)
{
- _sliceFlags |= FLAG_HAS_TYPE_ID_COMPACT;
+ _current.sliceFlags |= FLAG_HAS_TYPE_ID_COMPACT;
_stream.writeSize(compactId);
}
else
{
- //
- // If the type ID has already been seen, write the index
- // of the type ID, otherwise allocate a new type ID and
- // write the string.
- //
- Integer p = _typeIdMap.get(typeId);
- if(p != null)
+ int index = registerTypeId(typeId);
+ if(index < 0)
{
- _sliceFlags |= FLAG_HAS_TYPE_ID_INDEX;
- _stream.writeSize(p.intValue());
+ _current.sliceFlags |= FLAG_HAS_TYPE_ID_STRING;
+ _stream.writeString(typeId);
}
else
{
- _sliceFlags |= FLAG_HAS_TYPE_ID_STRING;
- _typeIdMap.put(typeId, ++_typeIdIndex);
- _stream.writeString(typeId);
+ _current.sliceFlags |= FLAG_HAS_TYPE_ID_INDEX;
+ _stream.writeSize(index);
}
}
}
}
else
{
- if(!_encaps.encoding_1_0)
- {
- _stream.writeByte((byte)0); // Placeholder for the slice flags
- }
_stream.writeString(typeId);
}
- if((_sliceFlags & FLAG_HAS_SLICE_SIZE) != 0)
+ if((_current.sliceFlags & FLAG_HAS_SLICE_SIZE) != 0)
{
_stream.writeInt(0); // Placeholder for the slice length.
}
- _writeSlice = _stream.pos();
- _firstSlice = false;
+ _current.writeSlice = _stream.pos();
+ _current.firstSlice = false;
}
void endSlice()
@@ -3961,59 +4291,49 @@ public class BasicStream
// were encoded. Note that the optional members are encoded before
// the indirection table and are included in the slice size.
//
- if((_sliceFlags & FLAG_HAS_OPTIONAL_MEMBERS) != 0)
+ if((_current.sliceFlags & FLAG_HAS_OPTIONAL_MEMBERS) != 0)
{
- assert(!_encaps.encoding_1_0);
- _stream.writeByte((byte)Ice.OptionalFormat.EndMarker.value());
+ _stream.writeByte((byte)OPTIONAL_END_MARKER);
}
//
// Write the slice length if necessary.
//
- if((_sliceFlags & FLAG_HAS_SLICE_SIZE) != 0)
+ if((_current.sliceFlags & FLAG_HAS_SLICE_SIZE) != 0)
{
- final int sz = _stream.pos() - _writeSlice + 4;
- _stream.rewriteInt(sz, _writeSlice - 4);
+ final int sz = _stream.pos() - _current.writeSlice + 4;
+ _stream.rewriteInt(sz, _current.writeSlice - 4);
}
//
// Only write the indirection table if it contains entries.
//
- if(!_indirectionTable.isEmpty())
+ if(_current.indirectionTable != null && !_current.indirectionTable.isEmpty())
{
- assert(!_encaps.encoding_1_0);
assert(_encaps.format == Ice.FormatType.SlicedFormat);
- _sliceFlags |= FLAG_HAS_INDIRECTION_TABLE;
+ _current.sliceFlags |= FLAG_HAS_INDIRECTION_TABLE;
//
- // Write the indirection table as a sequence<size> to conserve space.
+ // Write the indirection object table.
//
- _stream.writeSizeSeq(_indirectionTable);
-
- _indirectionTable.clear();
- _indirectionMap.clear();
+ _stream.writeSize(_current.indirectionTable.size());
+ for(Ice.Object v : _current.indirectionTable)
+ {
+ writeInstance(v);
+ }
+ _current.indirectionTable.clear();
+ _current.indirectionMap.clear();
}
//
- // Finally, update the slice flags (or the object slice has index
- // type ID boolean for the 1.0 encoding)
+ // Finally, update the slice flags.
//
- if(_encaps.encoding_1_0)
- {
- if(_sliceType == SliceType.ObjectSlice) // No flags for 1.0 exception slices.
- {
- _stream.rewriteBool((_sliceFlags & FLAG_HAS_TYPE_ID_INDEX) != 0, _sliceFlagsPos);
- }
- }
- else
- {
- _stream.rewriteByte(_sliceFlags, _sliceFlagsPos);
- }
+ _stream.rewriteByte(_current.sliceFlags, _current.sliceFlagsPos);
}
-
+
boolean writeOpt(int tag, Ice.OptionalFormat format)
{
- if(_sliceType == SliceType.NoSlice)
+ if(_current == null)
{
return _stream.writeOptImpl(tag, format);
}
@@ -4021,7 +4341,7 @@ public class BasicStream
{
if(_stream.writeOptImpl(tag, format))
{
- _sliceFlags |= FLAG_HAS_OPTIONAL_MEMBERS;
+ _current.sliceFlags |= FLAG_HAS_OPTIONAL_MEMBERS;
return true;
}
else
@@ -4031,166 +4351,119 @@ public class BasicStream
}
}
- void writePendingObjects()
- {
- //
- // With the 1.0 encoding, write pending objects if the marshalled
- // data uses classes. Otherwise with encoding > 1.0, only write
- // pending objects if some non-nil references were written.
- //
- if(!_encaps.encoding_1_0)
- {
- if(_toBeMarshaledMap.isEmpty())
- {
- return;
- }
- else
- {
- //
- // Write end marker for encapsulation optionals before encoding
- // the pending objects.
- //
- _stream.writeByte((byte)Ice.OptionalFormat.EndMarker.value());
- }
- }
-
- while(_toBeMarshaledMap.size() > 0)
- {
- //
- // Consider the to be marshalled objects as marshalled now,
- // this is necessary to avoid adding again the "to be
- // marshalled objects" into _toBeMarshaledMap while writing
- // objects.
- //
- _marshaledMap.putAll(_toBeMarshaledMap);
-
- java.util.IdentityHashMap<Ice.Object, Integer> savedMap = _toBeMarshaledMap;
- _toBeMarshaledMap = new java.util.IdentityHashMap<Ice.Object, Integer>();
- _stream.writeSize(savedMap.size());
- for(java.util.Map.Entry<Ice.Object, Integer> p : savedMap.entrySet())
- {
- //
- // Ask the instance to marshal itself. Any new class
- // instances that are triggered by the classes marshaled
- // are added to toBeMarshaledMap.
- //
- if(_encaps.encoding_1_0)
- {
- _stream.writeInt(p.getValue().intValue());
- }
- else
- {
- _stream.writeSize(p.getValue().intValue());
- }
-
- try
- {
- p.getKey().ice_preMarshal();
- }
- catch(java.lang.Exception ex)
- {
- String s = "exception raised by ice_preUnmarshal:\n" + Ex.toString(ex);
- _stream.instance().initializationData().logger.warning(
- "exception raised by ice_preUnmarshal:\n");
- }
-
- p.getKey().__write(_stream);
- }
- }
- _stream.writeSize(0); // Zero marker indicates end of sequence of sequences of instances.
- }
-
private void writeSlicedData(Ice.SlicedData slicedData)
{
assert(slicedData != null);
-
+
//
- // We only remarshal preserved slices if the target encoding is > 1.0 and we are
- // using the sliced format. Otherwise, we ignore the preserved slices, which
- // essentially "slices" the object into the most-derived type known by the sender.
+ // We only remarshal preserved slices if we are using the sliced
+ // format. Otherwise, we ignore the preserved slices, which
+ // essentially "slices" the object into the most-derived type
+ // known by the sender.
//
- if(_encaps.encoding_1_0 || _encaps.format != Ice.FormatType.SlicedFormat)
+ if(_encaps.format != Ice.FormatType.SlicedFormat)
{
return;
}
- for(int n = 0; n < slicedData.slices.length; ++n)
+ for(Ice.SliceInfo info : slicedData.slices)
{
- Ice.SliceInfo info = slicedData.slices[n];
startSlice(info.typeId, info.compactId, info.isLastSlice);
-
+
//
// Write the bytes associated with this slice.
//
_stream.writeBlob(info.bytes);
-
+
if(info.hasOptionalMembers)
{
- _sliceFlags |= FLAG_HAS_OPTIONAL_MEMBERS;
+ _current.sliceFlags |= FLAG_HAS_OPTIONAL_MEMBERS;
}
//
- // Assemble and write the indirection table. The table must have the same order
- // as the list of objects.
+ // Make sure to also re-write the object indirection table.
//
- for(int j = 0; j < info.objects.length; ++j)
+ if(info.objects != null && info.objects.length > 0)
{
- _indirectionTable.add(registerObject(info.objects[j]));
+ if(_current.indirectionTable == null) // Lazy initialization
+ {
+ _current.indirectionTable = new java.util.ArrayList<Ice.Object>();
+ _current.indirectionMap = new java.util.IdentityHashMap<Ice.Object, Integer>();
+ }
+ for(Ice.Object o : info.objects)
+ {
+ _current.indirectionTable.add(o);
+ }
}
endSlice();
}
}
- private int registerObject(Ice.Object v)
+ private void writeInstance(Ice.Object v)
{
+ assert(v != null);
+
//
- // Look for this instance in the to-be-marshaled map.
+ // If the instance was already marshaled, just write it's ID.
//
- Integer p = _toBeMarshaledMap.get(v);
+ Integer p = _marshaledMap.get(v);
if(p != null)
{
- return p.intValue();
+ _stream.writeSize(p);
+ return;
}
//
- // Didn't find it, try the marshaled map next.
+ // We haven't seen this instance previously, create a new ID,
+ // insert it into the marshaled map, and write the instance.
//
- p = _marshaledMap.get(v);
- if(p != null)
+ _marshaledMap.put(v, ++_objectIdIndex);
+
+ try
{
- return p.intValue();
+ v.ice_preMarshal();
+ }
+ catch(java.lang.Exception ex)
+ {
+ String s = "exception raised by ice_preMarshal:\n" + Ex.toString(ex);
+ _stream.instance().initializationData().logger.warning(s);
}
- //
- // We haven't seen this instance previously, create a new
- // index, and insert it into the to-be-marshaled map.
- //
- _toBeMarshaledMap.put(v, ++_objectIdIndex);
- return _objectIdIndex;
- }
+ _stream.writeSize(1); // Object instance marker.
+ v.__write(_stream);
+ }
- private final BasicStream _stream;
- private final WriteEncaps _encaps;
+ private static final class InstanceData
+ {
+ InstanceData(InstanceData previous)
+ {
+ if(previous != null)
+ {
+ previous.next = this;
+ }
+ this.previous = previous;
+ this.next = null;
+ }
- // Object/exception attributes
- private SliceType _sliceType;
- private boolean _firstSlice;
+ // Instance attributes
+ SliceType sliceType;
+ boolean firstSlice;
- // Slice attributes
- private byte _sliceFlags;
- private int _writeSlice; // Position of the slice data members
- private int _sliceFlagsPos; // Position of the slice flags
- private java.util.ArrayList<Integer> _indirectionTable;
- private java.util.TreeMap<Integer, Integer> _indirectionMap;
+ // Slice attributes
+ byte sliceFlags;
+ int writeSlice; // Position of the slice data members
+ int sliceFlagsPos; // Position of the slice flags
+ java.util.List<Ice.Object> indirectionTable;
+ java.util.IdentityHashMap<Ice.Object, Integer> indirectionMap;
- // Encapsulation attributes for object marshalling.
- private int _objectIdIndex;
- private java.util.IdentityHashMap<Ice.Object, Integer> _toBeMarshaledMap;
- private java.util.IdentityHashMap<Ice.Object, Integer> _marshaledMap;
- private java.util.TreeMap<String, Integer> _typeIdMap;
- private int _typeIdIndex;
- }
+ final InstanceData previous;
+ InstanceData next;
+ };
+ private InstanceData _current;
+
+ private int _objectIdIndex; // The ID of the next object to marhsal
+ };
private static final class ReadEncaps
{
@@ -4280,7 +4553,15 @@ public class BasicStream
if(_readEncapsStack.decoder == null) // Lazy initialization.
{
- _readEncapsStack.decoder = new EncapsDecoder(this, _readEncapsStack, _sliceObjects);
+ ObjectFactoryManager factoryManager = _instance.servantFactoryManager();
+ if(_readEncapsStack.encoding_1_0)
+ {
+ _readEncapsStack.decoder = new EncapsDecoder10(this, _readEncapsStack, _sliceObjects, factoryManager);
+ }
+ else
+ {
+ _readEncapsStack.decoder = new EncapsDecoder11(this, _readEncapsStack, _sliceObjects, factoryManager);
+ };
}
}
@@ -4307,7 +4588,14 @@ public class BasicStream
if(_writeEncapsStack.encoder == null) // Lazy initialization.
{
- _writeEncapsStack.encoder = new EncapsEncoder(this, _writeEncapsStack);
+ if(_writeEncapsStack.encoding_1_0)
+ {
+ _writeEncapsStack.encoder = new EncapsEncoder10(this, _writeEncapsStack);
+ }
+ else
+ {
+ _writeEncapsStack.encoder = new EncapsEncoder11(this, _writeEncapsStack);
+ }
}
}
@@ -4321,6 +4609,8 @@ public class BasicStream
private int _sizePos;
+ private static final int OPTIONAL_END_MARKER = 0xFF;
+
private static final byte FLAG_HAS_TYPE_ID_STRING = (byte)(1<<0);
private static final byte FLAG_HAS_TYPE_ID_INDEX = (byte)(1<<1);
private static final byte FLAG_HAS_TYPE_ID_COMPACT = (byte)(1<<1 | 1<<0);