diff options
author | Mark Spruiell <mes@zeroc.com> | 2012-06-13 16:19:58 -0700 |
---|---|---|
committer | Mark Spruiell <mes@zeroc.com> | 2012-06-13 16:19:58 -0700 |
commit | f1f199b777e32d0ff2a566af6eaa363d391aa18e (patch) | |
tree | 4cf8e91f33967c24f2369319585057df222503f7 /java/src | |
parent | Fixed support unknown types in unknown optionals (diff) | |
download | ice-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.java | 40 | ||||
-rw-r--r-- | java/src/Ice/InputStreamI.java | 30 | ||||
-rw-r--r-- | java/src/Ice/OptionalType.java | 70 | ||||
-rw-r--r-- | java/src/Ice/OutputStream.java | 30 | ||||
-rw-r--r-- | java/src/Ice/OutputStreamI.java | 24 | ||||
-rw-r--r-- | java/src/Ice/SliceInfo.java | 5 | ||||
-rw-r--r-- | java/src/Ice/UnknownSlicedObject.java | 55 | ||||
-rw-r--r-- | java/src/IceInternal/BasicStream.java | 549 | ||||
-rw-r--r-- | java/src/IceInternal/Ex.java | 19 |
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) |