summaryrefslogtreecommitdiff
path: root/java/src
diff options
context:
space:
mode:
authorMark Spruiell <mes@zeroc.com>2012-06-13 16:19:58 -0700
committerMark Spruiell <mes@zeroc.com>2012-06-13 16:19:58 -0700
commitf1f199b777e32d0ff2a566af6eaa363d391aa18e (patch)
tree4cf8e91f33967c24f2369319585057df222503f7 /java/src
parentFixed support unknown types in unknown optionals (diff)
downloadice-f1f199b777e32d0ff2a566af6eaa363d391aa18e.tar.bz2
ice-f1f199b777e32d0ff2a566af6eaa363d391aa18e.tar.xz
ice-f1f199b777e32d0ff2a566af6eaa363d391aa18e.zip
* Minor C++ fixes
* Adding UnknownSlicedObject in Java
Diffstat (limited to 'java/src')
-rw-r--r--java/src/Ice/InputStream.java40
-rw-r--r--java/src/Ice/InputStreamI.java30
-rw-r--r--java/src/Ice/OptionalType.java70
-rw-r--r--java/src/Ice/OutputStream.java30
-rw-r--r--java/src/Ice/OutputStreamI.java24
-rw-r--r--java/src/Ice/SliceInfo.java5
-rw-r--r--java/src/Ice/UnknownSlicedObject.java55
-rw-r--r--java/src/IceInternal/BasicStream.java549
-rw-r--r--java/src/IceInternal/Ex.java19
9 files changed, 625 insertions, 197 deletions
diff --git a/java/src/Ice/InputStream.java b/java/src/Ice/InputStream.java
index d7194e757f1..140551f042d 100644
--- a/java/src/Ice/InputStream.java
+++ b/java/src/Ice/InputStream.java
@@ -189,6 +189,14 @@ public interface InputStream
void readObject(ReadObjectCallback cb);
/**
+ * Read an enumerated value.
+ *
+ * @param limit The number of enumerators in the definition.
+ * @return The enumerator.
+ **/
+ int readEnum(int limit);
+
+ /**
* Extracts a user exception from the stream and throws it.
**/
void throwException() throws UserException;
@@ -247,7 +255,7 @@ public interface InputStream
*
* @return The encapsulation encoding version.
**/
- Ice.EncodingVersion startEncapsulation();
+ EncodingVersion startEncapsulation();
/**
* Indicates that the end of an encapsulation has been reached.
@@ -259,7 +267,14 @@ public interface InputStream
*
* @return The encapsulation encoding version.
**/
- Ice.EncodingVersion skipEncapsulation();
+ EncodingVersion skipEncapsulation();
+
+ /**
+ * Determines the current encoding version.
+ *
+ * @return The encoding version.
+ **/
+ EncodingVersion getEncoding();
/**
* Indicates that unmarshaling is complete, except for any Slice objects. The application must call this method
@@ -275,6 +290,27 @@ public interface InputStream
void rewind();
/**
+ * Skips ahead in the stream.
+ *
+ * @param sz The number of bytes to skip.
+ **/
+ void skip(int sz);
+
+ /**
+ * Skips over a size value.
+ **/
+ void skipSize();
+
+ /**
+ * Determine if an optional value is available for reading.
+ *
+ * @param tag The tag associated with the value.
+ * @param type The optional type for the value.
+ * @return True if the value is present, false otherwise.
+ **/
+ boolean readOptional(int tag, OptionalType type);
+
+ /**
* Destroys the stream and its associated resources. The application must call <code>destroy</code> prior
* to releasing the last reference to a stream; failure to do so may result in resource leaks.
**/
diff --git a/java/src/Ice/InputStreamI.java b/java/src/Ice/InputStreamI.java
index 06d1d216a31..c68d5ba4042 100644
--- a/java/src/Ice/InputStreamI.java
+++ b/java/src/Ice/InputStreamI.java
@@ -186,6 +186,12 @@ public class InputStreamI implements InputStream
_is.readObject(new Patcher(cb));
}
+ public int
+ readEnum(int limit)
+ {
+ return _is.readEnum(limit);
+ }
+
public void
throwException()
throws UserException
@@ -282,6 +288,12 @@ public class InputStreamI implements InputStream
return _is.skipEncaps();
}
+ public EncodingVersion
+ getEncoding()
+ {
+ return _is.getReadEncoding();
+ }
+
public void
readPendingObjects()
{
@@ -296,6 +308,24 @@ public class InputStreamI implements InputStream
}
public void
+ skip(int sz)
+ {
+ _is.skip(sz);
+ }
+
+ public void
+ skipSize()
+ {
+ _is.skipSize();
+ }
+
+ public boolean
+ readOptional(int tag, OptionalType type)
+ {
+ return _is.readOpt(tag, type);
+ }
+
+ public void
destroy()
{
if(_is != null)
diff --git a/java/src/Ice/OptionalType.java b/java/src/Ice/OptionalType.java
new file mode 100644
index 00000000000..0d0141814c0
--- /dev/null
+++ b/java/src/Ice/OptionalType.java
@@ -0,0 +1,70 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2012 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * The optional type.
+ *
+ * An optional value is encoded with a specific optional type. This optional
+ * type describes how the data is encoded and how it can be skipped by the
+ * unmarshaling code if the optional is not known to the receiver.
+ *
+ **/
+public enum OptionalType
+{
+ F1(0),
+ F2(1),
+ F4(2),
+ F8(3),
+ Size(4),
+ VSize(5),
+ FSize(6),
+ EndMarker(7);
+
+ private
+ OptionalType(int value)
+ {
+ _value = value;
+ }
+
+ public int
+ value()
+ {
+ return _value;
+ }
+
+ public static OptionalType
+ valueOf(int v)
+ {
+ switch(v)
+ {
+ case 0:
+ return F1;
+ case 1:
+ return F2;
+ case 2:
+ return F4;
+ case 3:
+ return F8;
+ case 4:
+ return Size;
+ case 5:
+ return VSize;
+ case 6:
+ return FSize;
+ case 7:
+ return EndMarker;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ private int _value;
+}
diff --git a/java/src/Ice/OutputStream.java b/java/src/Ice/OutputStream.java
index e86c20983a7..7d7df18b576 100644
--- a/java/src/Ice/OutputStream.java
+++ b/java/src/Ice/OutputStream.java
@@ -175,6 +175,14 @@ public interface OutputStream
void writeObject(Ice.Object v);
/**
+ * Write an enumerated value.
+ *
+ * @param v The enumerator.
+ * @param limit The number of enumerators in the definition.
+ **/
+ void writeEnum(int v, int limit);
+
+ /**
* Writes a user exception to the stream.
*
* @param id The user exception to write.
@@ -243,6 +251,13 @@ public interface OutputStream
void endEncapsulation();
/**
+ * Determines the current encoding version.
+ *
+ * @return The encoding version.
+ **/
+ EncodingVersion getEncoding();
+
+ /**
* Writes the state of Slice classes whose index was previously
* written with {@link #writeObject} to the stream.
**/
@@ -256,6 +271,21 @@ public interface OutputStream
byte[] finished();
/**
+ * Determines the current position in the stream.
+ *
+ * @return The current position.
+ **/
+ int pos();
+
+ /**
+ * Inserts a fixed 32-bit size value into the stream at the given position.
+ *
+ * @param pos The position at which to write the value.
+ * @param sz The size value.
+ **/
+ void rewrite(int pos, int sz);
+
+ /**
* Resets this output stream. This method allows the stream to be reused, to avoid creating
* unnecessary garbage.
*
diff --git a/java/src/Ice/OutputStreamI.java b/java/src/Ice/OutputStreamI.java
index 21a1d177c84..d7b4ffd23d5 100644
--- a/java/src/Ice/OutputStreamI.java
+++ b/java/src/Ice/OutputStreamI.java
@@ -160,6 +160,12 @@ public class OutputStreamI implements OutputStream
}
public void
+ writeEnum(int v, int limit)
+ {
+ _os.writeEnum(v, limit);
+ }
+
+ public void
writeException(UserException v)
{
_os.writeUserException(v);
@@ -225,6 +231,12 @@ public class OutputStreamI implements OutputStream
_os.endWriteEncapsChecked();
}
+ public EncodingVersion
+ getEncoding()
+ {
+ return _os.getWriteEncoding();
+ }
+
public void
writePendingObjects()
{
@@ -241,6 +253,18 @@ public class OutputStreamI implements OutputStream
return result;
}
+ public int
+ pos()
+ {
+ return _os.pos();
+ }
+
+ public void
+ rewrite(int pos, int sz)
+ {
+ _os.writeInt(sz, pos);
+ }
+
public void
reset(boolean clearBuffer)
{
diff --git a/java/src/Ice/SliceInfo.java b/java/src/Ice/SliceInfo.java
index 3f3494aa920..9e65cfa2429 100644
--- a/java/src/Ice/SliceInfo.java
+++ b/java/src/Ice/SliceInfo.java
@@ -28,4 +28,9 @@ public class SliceInfo
* The Ice objects referenced by this slice.
**/
public Ice.Object[] objects;
+
+ /**
+ * Whether or not the slice contains optional members.
+ **/
+ public boolean hasOptionalMembers;
}
diff --git a/java/src/Ice/UnknownSlicedObject.java b/java/src/Ice/UnknownSlicedObject.java
new file mode 100644
index 00000000000..af6b66a81d3
--- /dev/null
+++ b/java/src/Ice/UnknownSlicedObject.java
@@ -0,0 +1,55 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2012 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package Ice;
+
+/**
+ * Unknown sliced object holds an instance of unknown type.
+ **/
+public final class UnknownSlicedObject extends ObjectImpl
+{
+ /**
+ * Instantiates the class for an Ice object having the given Slice type.
+ *
+ * @param unknownTypeId The Slice type ID of the unknown object.
+ **/
+ public
+ UnknownSlicedObject(String unknownTypeId)
+ {
+ _unknownTypeId = unknownTypeId;
+ }
+
+ /**
+ * Determine the Slice type ID associated with this object.
+ *
+ * @return The type ID.
+ **/
+ public String
+ getUnknownTypeId()
+ {
+ return _unknownTypeId;
+ }
+
+ public void
+ __write(IceInternal.BasicStream __os)
+ {
+ __os.startWriteObject(_slicedData);
+ __os.endWriteObject();
+ }
+
+ public void
+ __read(IceInternal.BasicStream __is)
+ {
+ __is.startReadObject();
+ _slicedData = __is.endReadObject(true);
+ }
+
+ private final String _unknownTypeId;
+ private SlicedData _slicedData;
+}
diff --git a/java/src/IceInternal/BasicStream.java b/java/src/IceInternal/BasicStream.java
index 3e881b87919..7a93f5db4f2 100644
--- a/java/src/IceInternal/BasicStream.java
+++ b/java/src/IceInternal/BasicStream.java
@@ -36,7 +36,6 @@ public class BasicStream
_buf = new Buffer(_instance.messageSizeMax(), direct);
_closure = null;
_encoding = encoding;
- _unlimited = unlimited;
_readEncapsStack = null;
_writeEncapsStack = null;
@@ -46,6 +45,7 @@ public class BasicStream
_sliceObjects = true;
_messageSizeMax = _instance.messageSizeMax(); // Cached for efficiency.
+ _unlimited = unlimited;
_startSeq = -1;
_format = _instance.defaultsAndOverrides().defaultFormat;
@@ -122,12 +122,12 @@ public class BasicStream
_closure = tmpClosure;
//
- // Swap is never called for BasicStreams that have encapsulations being read/write.
+ // Swap is never called for BasicStreams that have encapsulations being read/write. However,
+ // encapsulations might still be set in case marshalling or un-marshalling failed. We just
+ // reset the encapsulations if there are still some set.
//
- assert(_readEncapsStack == null);
- assert(_writeEncapsStack == null);
- assert(other._readEncapsStack == null);
- assert(other._writeEncapsStack == null);
+ resetEncaps();
+ other.resetEncaps();
boolean tmpUnlimited = other._unlimited;
other._unlimited = _unlimited;
@@ -147,6 +147,13 @@ public class BasicStream
}
public void
+ resetEncaps()
+ {
+ _readEncapsStack = null;
+ _writeEncapsStack = null;
+ }
+
+ public void
resize(int sz, boolean reading)
{
//
@@ -294,8 +301,9 @@ public class BasicStream
_writeEncapsStack.encoder.writePendingObjects();
}
+ // Size includes size and version.
int start = _writeEncapsStack.start;
- int sz = _buf.size() - start; // Size includes size and version.
+ int sz = _buf.size() - start;
_buf.b.putInt(start, sz);
WriteEncaps curr = _writeEncapsStack;
@@ -392,6 +400,22 @@ public class BasicStream
{
_readEncapsStack.decoder.readPendingObjects();
}
+ else if(_buf.b.position() < _readEncapsStack.start + _readEncapsStack.sz &&
+ !_readEncapsStack.encoding.equals(Ice.Util.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())
+ {
+ _buf.b.position(_readEncapsStack.start + _readEncapsStack.sz);
+ }
+ }
if(_buf.b.position() != _readEncapsStack.start + _readEncapsStack.sz)
{
@@ -657,7 +681,7 @@ public class BasicStream
if(sz == 0)
{
- return 0;
+ return sz;
}
//
@@ -741,18 +765,33 @@ public class BasicStream
}
}
+ // Read/write type and tag for optionals
public void
- writeOpt(int tag, int type)
+ writeOpt(int tag, Ice.OptionalType type)
{
- assert(_writeEncapsStack != null && _writeEncapsStack.encoder != null);
- _writeEncapsStack.encoder.writeOpt(tag, type);
+ assert(_writeEncapsStack != null);
+ if(_writeEncapsStack.encoder != null)
+ {
+ _writeEncapsStack.encoder.writeOpt(tag, type);
+ }
+ else
+ {
+ writeOptImpl(tag, type);
+ }
}
public boolean
- readOpt(int tag, int expectedType)
+ readOpt(int tag, Ice.OptionalType expectedType)
{
- assert(_readEncapsStack != null && _readEncapsStack.decoder != null);
- return _readEncapsStack.decoder.readOpt(tag, expectedType);
+ assert(_readEncapsStack != null);
+ if(_readEncapsStack.decoder != null)
+ {
+ return _readEncapsStack.decoder.readOpt(tag, expectedType);
+ }
+ else
+ {
+ return readOptImpl(tag, expectedType);
+ }
}
public void
@@ -763,17 +802,7 @@ public class BasicStream
}
public void
- writeByte(byte v, int end)
- {
- if(v < 0 || v >= end)
- {
- throw new Ice.MarshalException("enumerator out of range");
- }
- writeByte(v);
- }
-
- public void
- writeByteAt(byte v, int dest)
+ writeByte(byte v, int dest)
{
_buf.b.put(dest, v);
}
@@ -828,17 +857,6 @@ public class BasicStream
}
}
- public byte
- readByte(int end)
- {
- byte v = readByte();
- if(v < 0 || v >= end)
- {
- throw new Ice.MarshalException("enumerator out of range");
- }
- return v;
- }
-
public byte[]
readByteSeq()
{
@@ -946,16 +964,6 @@ public class BasicStream
}
public void
- writeShort(short v, int end)
- {
- if(v < 0 || v >= end)
- {
- throw new Ice.MarshalException("enumerator out of range");
- }
- writeShort(v);
- }
-
- public void
writeShortSeq(short[] v)
{
if(v == null)
@@ -985,17 +993,6 @@ public class BasicStream
}
}
- public short
- readShort(int end)
- {
- short v = readShort();
- if(v < 0 || v >= end)
- {
- throw new Ice.MarshalException("enumerator out of range");
- }
- return v;
- }
-
public short[]
readShortSeq()
{
@@ -1022,17 +1019,7 @@ public class BasicStream
}
public void
- writeInt(int v, int end)
- {
- if(v < 0 || v >= end)
- {
- throw new Ice.MarshalException("enumerator out of range");
- }
- writeInt(v);
- }
-
- public void
- writeIntAt(int v, int dest)
+ writeInt(int v, int dest)
{
_buf.b.putInt(dest, v);
}
@@ -1067,17 +1054,6 @@ public class BasicStream
}
}
- public int
- readInt(int end)
- {
- int v = readInt();
- if(v < 0 || v >= end)
- {
- throw new Ice.MarshalException("enumerator out of range");
- }
- return v;
- }
-
public int[]
readIntSeq()
{
@@ -1447,6 +1423,54 @@ public class BasicStream
}
public void
+ writeEnum(int v, int limit)
+ {
+ if(getWriteEncoding().equals(Ice.Util.Encoding_1_0))
+ {
+ if(limit <= 127)
+ {
+ writeByte((byte)v);
+ }
+ else if(limit <= 32767)
+ {
+ writeShort((short)v);
+ }
+ else
+ {
+ writeInt(v);
+ }
+ }
+ else
+ {
+ writeSize(v);
+ }
+ }
+
+ public int
+ readEnum(int limit)
+ {
+ if(getReadEncoding().equals(Ice.Util.Encoding_1_0))
+ {
+ if(limit <= 127)
+ {
+ return readByte();
+ }
+ else if(limit <= 32767)
+ {
+ return readShort();
+ }
+ else
+ {
+ return readInt();
+ }
+ }
+ else
+ {
+ return readSize();
+ }
+ }
+
+ public void
writeObject(Ice.Object v)
{
initWriteEncaps();
@@ -1482,6 +1506,166 @@ public class BasicStream
_sliceObjects = b;
}
+ public boolean
+ readOptImpl(int readTag, Ice.OptionalType expectedType)
+ {
+ int tag = 0;
+ Ice.OptionalType type;
+ do
+ {
+ if(_buf.b.position() >= _readEncapsStack.start + _readEncapsStack.sz)
+ {
+ return false; // End of encapsulation also indicates end of optionals.
+ }
+
+ int v = readByte();
+ type = Ice.OptionalType.valueOf(v & 0x07); // First 3 bits.
+ tag = v >> 3;
+ if(tag == 31)
+ {
+ tag = readSize();
+ }
+ }
+ while(type != Ice.OptionalType.EndMarker && tag < readTag && skipOpt(type)); // Skip optional data members
+
+ if(type == Ice.OptionalType.EndMarker || tag > readTag)
+ {
+ //
+ // Rewind the stream to correctly read the next optional data
+ // member tag & type 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.
+ }
+
+ assert(readTag == tag);
+ if(type != expectedType)
+ {
+ String msg = "invalid optional data member `" + tag + "': unexpected type";
+ throw new Ice.MarshalException(msg);
+ }
+
+ //
+ // We have an optional data member with the requested tag and
+ // type.
+ //
+ return true;
+ }
+
+ public void
+ writeOptImpl(int tag, Ice.OptionalType type)
+ {
+ int v = type.value();
+ if(tag < 31)
+ {
+ v |= tag << 3;
+ writeByte((byte)v);
+ }
+ else
+ {
+ v |= 0x0F8; // tag = 31
+ writeByte((byte)v);
+ writeSize(tag);
+ }
+ }
+
+ public boolean
+ skipOpt(Ice.OptionalType type)
+ {
+ int sz;
+ switch(type)
+ {
+ case F1:
+ {
+ sz = 1;
+ break;
+ }
+ case F2:
+ {
+ sz = 2;
+ break;
+ }
+ case F4:
+ {
+ sz = 4;
+ break;
+ }
+ case F8:
+ {
+ sz = 8;
+ break;
+ }
+ case Size:
+ {
+ skipSize();
+ return true;
+ }
+ case VSize:
+ {
+ sz = readSize();
+ break;
+ }
+ case FSize:
+ {
+ sz = readInt();
+ break;
+ }
+ default:
+ {
+ return false;
+ }
+ }
+ skip(sz);
+ return true;
+ }
+
+ public boolean
+ skipOpts()
+ {
+ //
+ // Skip remaining un-read optional members.
+ //
+ Ice.OptionalType type;
+ do
+ {
+ if(_buf.b.position() >= _readEncapsStack.start + _readEncapsStack.sz)
+ {
+ return false; // End of encapsulation also indicates end of optionals.
+ }
+
+ int v = readByte();
+ type = Ice.OptionalType.valueOf(v & 0x07); // Read first 3 bits.
+ if((v >> 3) == 31)
+ {
+ skipSize();
+ }
+ }
+ while(skipOpt(type));
+ assert(type == Ice.OptionalType.EndMarker);
+ return true;
+ }
+
+ public void
+ skip(int size)
+ {
+ if(size > _buf.b.remaining())
+ {
+ throw new Ice.UnmarshalOutOfBoundsException();
+ }
+ _buf.b.position(_buf.b.position() + size);
+ }
+
+ public void
+ skipSize()
+ {
+ byte b = readByte();
+ if(b == -1)
+ {
+ skip(4);
+ }
+ }
+
public int
pos()
{
@@ -2169,8 +2353,8 @@ public class BasicStream
}
//
- // Performance sensitive, so we use lazy initialization
- // for tracing.
+ // Performance sensitive, so we use lazy initialization for
+ // tracing.
//
if(_traceSlicing == -1)
{
@@ -2183,13 +2367,17 @@ public class BasicStream
_stream.instance().initializationData().logger);
}
+ //
+ // Slice off what we don't understand.
+ //
+ skipSlice();
+
if((_sliceFlags & FLAG_IS_LAST_SLICE) != 0)
{
- // TODO: Consider adding a new exception, such as NoExceptionFactory?
- throw new Ice.UnmarshalOutOfBoundsException("unknown exception type `" + mostDerivedId + "'");
+ throw new Ice.NoExceptionFactoryException("unknown exception type `" + mostDerivedId + "'",
+ mostDerivedId);
}
- skipSlice(); // Slice off what we don't understand.
try
{
startSlice();
@@ -2360,15 +2548,7 @@ public class BasicStream
{
if((_sliceFlags & FLAG_HAS_OPTIONAL_MEMBERS) != 0)
{
- //
- // Read remaining un-read optional members.
- //
- byte v;
- do
- {
- v = _stream.readByte();
- }
- while(skipOpt(v & 0x07));
+ _stream.skipOpts();
}
//
@@ -2383,13 +2563,16 @@ public class BasicStream
int[] indirectionTable = _stream.readSizeSeq();
//
- // Sanity checks.
+ // 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())
{
throw new Ice.MarshalException("empty indirection table");
}
- else if(indirectionTable.length > 0 && _indirectPatchList.isEmpty())
+ else if(indirectionTable.length > 0 && _indirectPatchList.isEmpty() &&
+ (_sliceFlags & FLAG_HAS_OPTIONAL_MEMBERS) == 0)
{
throw new Ice.MarshalException("no references to indirection table");
}
@@ -2424,15 +2607,12 @@ public class BasicStream
if((_sliceFlags & FLAG_HAS_SLICE_SIZE) != 0)
{
assert(_sliceSize >= 4);
- _stream.pos(start + _sliceSize - 4);
- if((start + _sliceSize - 4) > _stream.size())
- {
- throw new Ice.UnmarshalOutOfBoundsException();
- }
+ _stream.skip(_sliceSize - 4);
}
else
{
- throw new Ice.MarshalException("compact format prevents slicing");
+ throw new Ice.MarshalException(
+ "compact format prevents slicing (the sender should use the sliced format instead)");
}
if(!_encaps.encoding.equals(Ice.Util.Encoding_1_0))
@@ -2442,8 +2622,17 @@ public class BasicStream
//
Ice.SliceInfo info = new Ice.SliceInfo();
info.typeId = _typeId;
+ info.hasOptionalMembers = (_sliceFlags & FLAG_HAS_OPTIONAL_MEMBERS) != 0;
java.nio.ByteBuffer b = _stream.getBuffer().b;
- final int end = b.position();
+ int end = b.position();
+ 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.
+ //
+ --end;
+ }
info.bytes = new byte[end - start];
b.position(start);
b.get(info.bytes);
@@ -2463,71 +2652,25 @@ public class BasicStream
}
}
- boolean readOpt(int readTag, int expectedType)
+ boolean readOpt(int readTag, Ice.OptionalType expectedType)
{
- assert(_sliceType != SliceType.NoSlice);
- if((_sliceFlags & FLAG_HAS_OPTIONAL_MEMBERS) == 0)
- {
- return false; // No optional data members
- }
-
- int tag;
- int type;
- do
- {
- byte v = _stream.readByte();
-
- type = v & 0x07; // Read first 3 bits.
- tag = (int)(v >> 3);
- if(tag == 31)
- {
- tag = _stream.readSize();
- }
- }
- while(tag < readTag && skipOpt(type)); // Skip optional data members with lower tag values.
-
- if(type == MemberTypeEndMarker)
- {
- //
- // Clear the optional members flag since we've reach the end. We clear
- // the flag to prevent endSlice to skip un-read optional members and
- // to prevent other optional members from being read.
- //
- _sliceFlags &= ~FLAG_HAS_OPTIONAL_MEMBERS;
- return false;
- }
- else if(tag > readTag)
+ if(_sliceType == SliceType.NoSlice)
{
- //
- // Rewind the stream so that we correctly read the next
- // optional data member tag & type.
- //
- int pos = _stream.pos();
- pos -= tag < 31 ? 1 : (tag < 255 ? 2 : 6);
- _stream.pos(pos);
- return false; // No optional data members with the requested tag.
+ return _stream.readOptImpl(readTag, expectedType);
}
-
- assert(readTag == tag);
- if(type != expectedType)
+ else if((_sliceFlags & FLAG_HAS_OPTIONAL_MEMBERS) != 0)
{
- throw new Ice.MarshalException("invalid optional data member `" + tag + "' in `" + _typeId +
- "': unexpected type");
+ return _stream.readOptImpl(readTag, expectedType);
}
-
- //
- // We have an optional data member with the requested tag and
- // type.
- //
- return true;
+ return false;
}
void readPendingObjects()
{
//
- // With the 1.0 encoding, only read pending objects if nil or
- // non-nil references were read (_usesClasses == true). Otherwise,
- // read pending objects only if some non-nil references were read.
+ // With the 1.0 encoding, read pending objects if nil or non-nil
+ // references were read (_usesClasses == true). Otherwise, read
+ // pending objects only if some non-nil references were read.
//
if(_encaps.encoding.equals(Ice.Util.Encoding_1_0))
{
@@ -2541,6 +2684,14 @@ public class BasicStream
{
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>();
@@ -2613,12 +2764,10 @@ public class BasicStream
while(true)
{
//
- // For the 1.0 encoding, the type ID for the base Object class marks
- // the last slice. For later encodings, an empty type ID means the
- // class was marshaled in the compact format and therefore cannot be
- // sliced.
+ // For the 1.0 encoding, the type ID for the base Object class
+ // marks the last slice.
//
- if(_typeId.length() == 0 || _typeId.equals(Ice.ObjectImpl.ice_staticId()))
+ if(_typeId.equals(Ice.ObjectImpl.ice_staticId()))
{
throw new Ice.NoObjectFactoryException("", mostDerivedId);
}
@@ -2668,19 +2817,6 @@ public class BasicStream
}
//
- // If object slicing is disabled, or if the flags indicate that this is the
- // last slice (for encodings >= 1.1), we raise NoObjectFactoryException.
- //
- if(!_sliceObjects)
- {
- throw new Ice.NoObjectFactoryException("object slicing is disabled", _typeId);
- }
- else if((_sliceFlags & FLAG_IS_LAST_SLICE) != 0)
- {
- throw new Ice.NoObjectFactoryException("", _typeId);
- }
-
- //
// Performance sensitive, so we use lazy initialization for tracing.
//
if(_traceSlicing == -1)
@@ -2694,7 +2830,29 @@ public class BasicStream
_stream.instance().initializationData().logger);
}
- skipSlice(); // Slice off what we don't understand.
+ //
+ // 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();
+
+ //
+ // If this is the last slice, keep the object as an opaque
+ // UnknownSlicedData object.
+ //
+ if((_sliceFlags & FLAG_IS_LAST_SLICE) != 0)
+ {
+ v = new Ice.UnknownSlicedObject(mostDerivedId);
+ break;
+ }
+
startSlice(); // Read next Slice header for next iteration.
}
@@ -3123,7 +3281,7 @@ public class BasicStream
//
if((_sliceFlags & FLAG_HAS_OPTIONAL_MEMBERS) != 0)
{
- _stream.writeByte((byte)MemberTypeEndMarker);
+ _stream.writeByte((byte)Ice.OptionalType.EndMarker.value());
}
//
@@ -3132,7 +3290,7 @@ public class BasicStream
if((_sliceFlags & FLAG_HAS_SLICE_SIZE) != 0)
{
final int sz = _stream.pos() - _writeSlice + 4;
- _stream.writeIntAt(sz, _writeSlice - 4);
+ _stream.writeInt(sz, _writeSlice - 4);
}
//
@@ -3164,33 +3322,29 @@ public class BasicStream
}
else
{
- _stream.writeByteAt(_sliceFlags, _sliceFlagsPos);
+ _stream.writeByte(_sliceFlags, _sliceFlagsPos);
}
}
- void writeOpt(int tag, int type)
+ void writeOpt(int tag, Ice.OptionalType type)
{
- assert(_sliceType != SliceType.NoSlice);
- _sliceFlags |= FLAG_HAS_OPTIONAL_MEMBERS;
- byte v = (byte)type;
- if(tag < 31)
+ if(_sliceType == SliceType.NoSlice)
{
- v |= (byte)(tag << 3);
+ _stream.writeOptImpl(tag, type);
}
else
{
- v |= (byte)0x0F8; // tag = 31
- _stream.writeSize(tag);
+ _sliceFlags |= FLAG_HAS_OPTIONAL_MEMBERS;
+ _stream.writeOptImpl(tag, type);
}
}
void writePendingObjects()
{
//
- // With the 1.0 encoding, only write pending objects if nil or
- // non-nil references were written (_usesClasses =
- // true). Otherwise, write pending objects only if some non-nil
- // references were written.
+ // With the 1.0 encoding, write pending objects if nil or non-nil
+ // references were written (_usesClasses = true). Otherwise, write
+ // pending objects only if some non-nil references were written.
//
if(_encaps.encoding.equals(Ice.Util.Encoding_1_0))
{
@@ -3204,6 +3358,14 @@ public class BasicStream
{
return;
}
+ else
+ {
+ //
+ // Write end marker for encapsulation optionals before encoding
+ // the pending objects.
+ //
+ _stream.writeByte((byte)Ice.OptionalType.EndMarker.value());
+ }
while(_toBeMarshaledMap.size() > 0)
{
@@ -3275,6 +3437,11 @@ public class BasicStream
//
_stream.writeBlob(info.bytes);
+ if(info.hasOptionalMembers)
+ {
+ _sliceFlags |= FLAG_HAS_OPTIONAL_MEMBERS;
+ }
+
//
// Assemble and write the indirection table. The table must have the same order
// as the list of objects.
diff --git a/java/src/IceInternal/Ex.java b/java/src/IceInternal/Ex.java
index dc22ab17893..91b1a981fec 100644
--- a/java/src/IceInternal/Ex.java
+++ b/java/src/IceInternal/Ex.java
@@ -11,11 +11,22 @@ package IceInternal;
public class Ex
{
- public static void throwUOE(String expectedType, String actualType)
+ public static void throwUOE(String expectedType, Ice.Object v)
{
- throw new Ice.UnexpectedObjectException(
- "expected element of type `" + expectedType + "' but received '" + actualType,
- actualType, expectedType);
+ //
+ // If the object is an unknown sliced object, we didn't find an
+ // object factory, in this case raise a NoObjectFactoryException
+ // instead.
+ //
+ if(v instanceof Ice.UnknownSlicedObject)
+ {
+ Ice.UnknownSlicedObject uso = (Ice.UnknownSlicedObject)v;
+ throw new Ice.NoObjectFactoryException("", uso.getUnknownTypeId());
+ }
+
+ String type = v.ice_id();
+ throw new Ice.UnexpectedObjectException("expected element of type `" + expectedType + "' but received '" +
+ type, type, expectedType);
}
public static void throwMemoryLimitException(int requested, int maximum)