// ********************************************************************** // // Copyright (c) 2003 // ZeroC, Inc. // Billerica, MA, USA // // All Rights Reserved. // // Ice is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License version 2 as published by // the Free Software Foundation. // // ********************************************************************** package IceInternal; public class BasicStream { public BasicStream(IceInternal.Instance instance) { _instance = instance; _bufferManager = instance.bufferManager(); _buf = _bufferManager.allocate(1500); assert(_buf != null); _capacity = _buf.capacity(); _limit = 0; assert(_buf.limit() == _capacity); _readEncapsStack = null; _writeEncapsStack = null; _readEncapsCache = null; _writeEncapsCache = null; _traceSlicing = -1; _marshalFacets = true; _messageSizeMax = _instance.messageSizeMax(); // Cached for efficiency. } /* * Do NOT use a finalizer for BasicStream - this causes a * severe performance penalty! * protected void finalize() throws Throwable { if(_buf != null) { _bufferManager.reclaim(_buf); } super.finalize(); } */ public void reset() { _limit = 0; _buf.limit(_capacity); _buf.position(0); if(_readEncapsStack != null) { assert(_readEncapsStack.next == null); _readEncapsStack.next = _readEncapsCache; _readEncapsCache = _readEncapsStack; _readEncapsStack = null; } } // // Must be called in order to reclaim the buffer // public void destroy() { _bufferManager.reclaim(_buf); _buf = null; } public IceInternal.Instance instance() { return _instance; } public void swap(BasicStream other) { assert(_instance == other._instance); java.nio.ByteBuffer tmpBuf = other._buf; other._buf = _buf; _buf = tmpBuf; int tmpCapacity = other._capacity; other._capacity = _capacity; _capacity = tmpCapacity; int tmpLimit = other._limit; other._limit = _limit; _limit = tmpLimit; ReadEncaps tmpRead = other._readEncapsStack; other._readEncapsStack = _readEncapsStack; _readEncapsStack = tmpRead; tmpRead = other._readEncapsCache; other._readEncapsCache = _readEncapsCache; _readEncapsCache = tmpRead; WriteEncaps tmpWrite = other._writeEncapsStack; other._writeEncapsStack = _writeEncapsStack; _writeEncapsStack = tmpWrite; tmpWrite = other._writeEncapsCache; other._writeEncapsCache = _writeEncapsCache; _writeEncapsCache = tmpWrite; int tmpReadSlice = other._readSlice; other._readSlice = _readSlice; _readSlice = tmpReadSlice; int tmpWriteSlice = other._writeSlice; other._writeSlice = _writeSlice; _writeSlice = tmpWriteSlice; } public void resize(int total, boolean reading) { if(total > _messageSizeMax) { throw new Ice.MemoryLimitException(); } if(total > _capacity) { final int cap2 = _capacity << 1; int newCapacity = cap2 > total ? cap2 : total; _buf.limit(_limit); _buf.position(0); _buf = _bufferManager.reallocate(_buf, newCapacity); assert(_buf != null); _capacity = _buf.capacity(); } // // If this stream is used for reading, then we want to set // the buffer's limit to the new total size. If this buffer // is used for writing, then we must set the buffer's limit // to the buffer's capacity. // if(reading) { _buf.limit(total); } else { _buf.limit(_capacity); } _buf.position(total); _limit = total; } public java.nio.ByteBuffer prepareRead() { return _buf; } public java.nio.ByteBuffer prepareWrite() { _buf.limit(_limit); _buf.position(0); return _buf; } public void startWriteEncaps() { { WriteEncaps curr = _writeEncapsCache; if(curr != null) { if(curr.toBeMarshaledMap != null) { curr.writeIndex = 0; curr.toBeMarshaledMap.clear(); curr.marshaledMap.clear(); curr.typeIdIndex = 0; curr.typeIdMap.clear(); } _writeEncapsCache = _writeEncapsCache.next; } else { curr = new WriteEncaps(); } curr.next = _writeEncapsStack; _writeEncapsStack = curr; } _writeEncapsStack.start = _buf.position(); writeInt(0); // Placeholder for the encapsulation length. writeByte(Protocol.encodingMajor); writeByte(Protocol.encodingMinor); } public void endWriteEncaps() { assert(_writeEncapsStack != null); int start = _writeEncapsStack.start; int sz = _buf.position() - start; // Size includes size and version. _buf.putInt(start, sz); { WriteEncaps curr = _writeEncapsStack; _writeEncapsStack = curr.next; curr.next = _writeEncapsCache; _writeEncapsCache = curr; } } public void startReadEncaps() { { ReadEncaps curr = _readEncapsCache; if(curr != null) { if(curr.patchMap != null) { curr.patchMap.clear(); curr.unmarshaledMap.clear(); curr.typeIdIndex = 0; curr.typeIdMap.clear(); } _readEncapsCache = _readEncapsCache.next; } else { curr = new ReadEncaps(); } curr.next = _readEncapsStack; _readEncapsStack = curr; } _readEncapsStack.start = _buf.position(); // // I don't use readSize() and writeSize() for encapsulations, // because when creating an encapsulation, I must know in // advance how many bytes the size information will require in // the data stream. If I use an Int, it is always 4 bytes. For // readSize()/writeSize(), it could be 1 or 5 bytes. // int sz = readInt(); if(sz < 0) { throw new Ice.NegativeSizeException(); } // TODO: How to implement this check in Java? /* if(sz - 4 > _buf.length()) { throw UnmarshalOutOfBoundsException(__FILE__, __LINE__); } */ _readEncapsStack.sz = sz; byte eMajor = readByte(); byte eMinor = readByte(); if(eMajor != Protocol.encodingMajor || eMinor > Protocol.encodingMinor) { Ice.UnsupportedEncodingException e = new Ice.UnsupportedEncodingException(); e.badMajor = eMajor < 0 ? eMajor + 256 : eMajor; e.badMinor = eMinor < 0 ? eMinor + 256 : eMinor; e.major = Protocol.encodingMajor; e.minor = Protocol.encodingMinor; throw e; } _readEncapsStack.encodingMajor = eMajor; _readEncapsStack.encodingMinor = eMinor; } public void endReadEncaps() { assert(_readEncapsStack != null); int start = _readEncapsStack.start; int sz = _readEncapsStack.sz; try { _buf.position(start + sz); } catch(IllegalArgumentException ex) { throw new Ice.UnmarshalOutOfBoundsException(); } { ReadEncaps curr = _readEncapsStack; _readEncapsStack = curr.next; curr.next = _readEncapsCache; _readEncapsCache = curr; } } public void checkReadEncaps() { assert(_readEncapsStack != null); int start = _readEncapsStack.start; int sz = _readEncapsStack.sz; if(_buf.position() != start + sz) { throw new Ice.EncapsulationException(); } } public int getReadEncapsSize() { assert(_readEncapsStack != null); return _readEncapsStack.sz - 6; } public void skipEncaps() { int sz = readInt(); if(sz < 0) { throw new Ice.NegativeSizeException(); } try { _buf.position(_buf.position() + sz - 4); } catch(IllegalArgumentException ex) { throw new Ice.UnmarshalOutOfBoundsException(); } } public void startWriteSlice() { writeInt(0); // Placeholder for the slice length. _writeSlice = _buf.position(); } public void endWriteSlice() { final int sz = _buf.position() - _writeSlice + 4; _buf.putInt(_writeSlice - 4, sz); } public void startReadSlice() { int sz = readInt(); if(sz < 0) { throw new Ice.NegativeSizeException(); } _readSlice = _buf.position(); } public void endReadSlice() { } public void skipSlice() { int sz = readInt(); if(sz < 0) { throw new Ice.NegativeSizeException(); } try { _buf.position(_buf.position() + sz - 4); } catch(IllegalArgumentException ex) { throw new Ice.UnmarshalOutOfBoundsException(); } } public void writeSize(int v) { if(v > 254) { expand(5); _buf.put((byte)-1); _buf.putInt(v); } else { expand(1); _buf.put((byte)v); } } public int readSize() { try { byte b = _buf.get(); if(b == -1) { int v = _buf.getInt(); if(v < 0) { throw new Ice.NegativeSizeException(); } return v; } else { return (int)(b < 0 ? b + 256 : b); } } catch(java.nio.BufferUnderflowException ex) { throw new Ice.UnmarshalOutOfBoundsException(); } } public void writeTypeId(String id) { Integer index = (Integer)_writeEncapsStack.typeIdMap.get(id); if(index != null) { writeBool(true); writeSize(index.intValue()); } else { index = new Integer(++_writeEncapsStack.typeIdIndex); _writeEncapsStack.typeIdMap.put(id, index); writeBool(false); writeString(id); } } public String readTypeId() { String id; Integer index; final boolean isIndex = readBool(); if(isIndex) { index = new Integer(readSize()); id = (String)_readEncapsStack.typeIdMap.get(index); if(id == null) { throw new Ice.UnmarshalOutOfBoundsException(); } } else { id = readString(); index = new Integer(++_readEncapsStack.typeIdIndex); _readEncapsStack.typeIdMap.put(index, id); } return id; } public void writeBlob(byte[] v) { expand(v.length); _buf.put(v); } public byte[] readBlob(int sz) { byte[] v = new byte[sz]; try { _buf.get(v); return v; } catch(java.nio.BufferUnderflowException ex) { throw new Ice.UnmarshalOutOfBoundsException(); } } public void writeByte(byte v) { expand(1); _buf.put(v); } public void writeByteSeq(byte[] v) { if(v == null) { writeSize(0); } else { writeSize(v.length); expand(v.length); _buf.put(v); } } public byte readByte() { try { return _buf.get(); } catch(java.nio.BufferUnderflowException ex) { throw new Ice.UnmarshalOutOfBoundsException(); } } public byte[] readByteSeq() { try { final int sz = readSize(); byte[] v = new byte[sz]; _buf.get(v); return v; } catch(java.nio.BufferUnderflowException ex) { throw new Ice.UnmarshalOutOfBoundsException(); } } public void writeBool(boolean v) { expand(1); _buf.put(v ? (byte)1 : (byte)0); } public void writeBoolSeq(boolean[] v) { if(v == null) { writeSize(0); } else { writeSize(v.length); expand(v.length); for(int i = 0; i < v.length; i++) { _buf.put(v[i] ? (byte)1 : (byte)0); } } } public boolean readBool() { try { return _buf.get() == 1; } catch(java.nio.BufferUnderflowException ex) { throw new Ice.UnmarshalOutOfBoundsException(); } } public boolean[] readBoolSeq() { try { final int sz = readSize(); boolean[] v = new boolean[sz]; for(int i = 0; i < sz; i++) { v[i] = _buf.get() == 1; } return v; } catch(java.nio.BufferUnderflowException ex) { throw new Ice.UnmarshalOutOfBoundsException(); } } public void writeShort(short v) { expand(2); _buf.putShort(v); } public void writeShortSeq(short[] v) { if(v == null) { writeSize(0); } else { writeSize(v.length); expand(v.length * 2); java.nio.ShortBuffer shortBuf = _buf.asShortBuffer(); shortBuf.put(v); _buf.position(_buf.position() + v.length * 2); } } public short readShort() { try { return _buf.getShort(); } catch(java.nio.BufferUnderflowException ex) { throw new Ice.UnmarshalOutOfBoundsException(); } } public short[] readShortSeq() { try { final int sz = readSize(); short[] v = new short[sz]; java.nio.ShortBuffer shortBuf = _buf.asShortBuffer(); shortBuf.get(v); _buf.position(_buf.position() + sz * 2); return v; } catch(java.nio.BufferUnderflowException ex) { throw new Ice.UnmarshalOutOfBoundsException(); } } public void writeInt(int v) { expand(4); _buf.putInt(v); } public void writeIntSeq(int[] v) { if(v == null) { writeSize(0); } else { writeSize(v.length); expand(v.length * 4); java.nio.IntBuffer intBuf = _buf.asIntBuffer(); intBuf.put(v); _buf.position(_buf.position() + v.length * 4); } } public int readInt() { try { return _buf.getInt(); } catch(java.nio.BufferUnderflowException ex) { throw new Ice.UnmarshalOutOfBoundsException(); } } public int[] readIntSeq() { try { final int sz = readSize(); int[] v = new int[sz]; java.nio.IntBuffer intBuf = _buf.asIntBuffer(); intBuf.get(v); _buf.position(_buf.position() + sz * 4); return v; } catch(java.nio.BufferUnderflowException ex) { throw new Ice.UnmarshalOutOfBoundsException(); } } public void writeLong(long v) { expand(8); _buf.putLong(v); } public void writeLongSeq(long[] v) { if(v == null) { writeSize(0); } else { writeSize(v.length); expand(v.length * 8); java.nio.LongBuffer longBuf = _buf.asLongBuffer(); longBuf.put(v); _buf.position(_buf.position() + v.length * 8); } } public long readLong() { try { return _buf.getLong(); } catch(java.nio.BufferUnderflowException ex) { throw new Ice.UnmarshalOutOfBoundsException(); } } public long[] readLongSeq() { try { final int sz = readSize(); long[] v = new long[sz]; java.nio.LongBuffer longBuf = _buf.asLongBuffer(); longBuf.get(v); _buf.position(_buf.position() + sz * 8); return v; } catch(java.nio.BufferUnderflowException ex) { throw new Ice.UnmarshalOutOfBoundsException(); } } public void writeFloat(float v) { expand(4); _buf.putFloat(v); } public void writeFloatSeq(float[] v) { if(v == null) { writeSize(0); } else { writeSize(v.length); expand(v.length * 4); java.nio.FloatBuffer floatBuf = _buf.asFloatBuffer(); floatBuf.put(v); _buf.position(_buf.position() + v.length * 4); } } public float readFloat() { try { return _buf.getFloat(); } catch(java.nio.BufferUnderflowException ex) { throw new Ice.UnmarshalOutOfBoundsException(); } } public float[] readFloatSeq() { try { final int sz = readSize(); float[] v = new float[sz]; java.nio.FloatBuffer floatBuf = _buf.asFloatBuffer(); floatBuf.get(v); _buf.position(_buf.position() + sz * 4); return v; } catch(java.nio.BufferUnderflowException ex) { throw new Ice.UnmarshalOutOfBoundsException(); } } public void writeDouble(double v) { expand(8); _buf.putDouble(v); } public void writeDoubleSeq(double[] v) { if(v == null) { writeSize(0); } else { writeSize(v.length); expand(v.length * 8); java.nio.DoubleBuffer doubleBuf = _buf.asDoubleBuffer(); doubleBuf.put(v); _buf.position(_buf.position() + v.length * 8); } } public double readDouble() { try { return _buf.getDouble(); } catch(java.nio.BufferUnderflowException ex) { throw new Ice.UnmarshalOutOfBoundsException(); } } public double[] readDoubleSeq() { try { final int sz = readSize(); double[] v = new double[sz]; java.nio.DoubleBuffer doubleBuf = _buf.asDoubleBuffer(); doubleBuf.get(v); _buf.position(_buf.position() + sz * 8); return v; } catch(java.nio.BufferUnderflowException ex) { throw new Ice.UnmarshalOutOfBoundsException(); } } public void writeString(String v) { if(v == null) { writeSize(0); } else { final int len = v.length(); if(len > 0) { try { byte[] arr = v.getBytes("UTF8"); writeSize(arr.length); expand(arr.length); _buf.put(arr); } catch(java.io.UnsupportedEncodingException ex) { assert(false); } } else { writeSize(0); } } } public void writeStringSeq(String[] v) { if(v == null) { writeSize(0); } else { writeSize(v.length); for(int i = 0; i < v.length; i++) { writeString(v[i]); } } } public String readString() { final int len = readSize(); if(len == 0) { return ""; } else { try { // // We reuse the _stringBytes array to avoid creating // excessive garbage // if(_stringBytes == null || len > _stringBytes.length) { _stringBytes = new byte[len]; _stringChars = new char[len]; } _buf.get(_stringBytes, 0, len); // // It's more efficient to construct a string using a // character array instead of a byte array, because // byte arrays require conversion. // for(int i = 0; i < len; i++) { if(_stringBytes[i] < 0) { // // Multi-byte character found - we must // use conversion // return new String(_stringBytes, 0, len, "UTF8"); } else { _stringChars[i] = (char)_stringBytes[i]; } } return new String(_stringChars, 0, len); } catch(java.io.UnsupportedEncodingException ex) { assert(false); return ""; } catch(java.nio.BufferUnderflowException ex) { throw new Ice.UnmarshalOutOfBoundsException(); } } } public String[] readStringSeq() { final int sz = readSize(); String[] v = new String[sz]; for(int i = 0; i < sz; i++) { v[i] = readString(); } return v; } public void writeProxy(Ice.ObjectPrx v) { _instance.proxyFactory().proxyToStream(v, this); } public Ice.ObjectPrx readProxy() { return _instance.proxyFactory().streamToProxy(this); } public void writeObject(Ice.Object v) { if(_writeEncapsStack == null) // Lazy initialization { _writeEncapsStack = _writeEncapsCache; if(_writeEncapsStack != null) { _writeEncapsCache = _writeEncapsCache.next; } else { _writeEncapsStack = new WriteEncaps(); } } if(_writeEncapsStack.toBeMarshaledMap == null) // Lazy initialization { _writeEncapsStack.toBeMarshaledMap = new java.util.IdentityHashMap(); _writeEncapsStack.marshaledMap = new java.util.IdentityHashMap(); _writeEncapsStack.typeIdMap = new java.util.TreeMap(); } if(v != null) { // // Look for this instance in the to-be-marshaled map. // Integer p = (Integer)_writeEncapsStack.toBeMarshaledMap.get(v); if(p == null) { // // Didn't find it, try the marshaled map next. // Integer q = (Integer)_writeEncapsStack.marshaledMap.get(v); if(q == null) { // // We haven't seen this instance previously, create a new index, and // insert it into the to-be-marshaled map. // q = new Integer(++_writeEncapsStack.writeIndex); _writeEncapsStack.toBeMarshaledMap.put(v, q); } p = q; } writeInt(-p.intValue()); } else { writeInt(0); // Write null reference } } public void readObject(IceInternal.Patcher patcher) { Ice.Object v = null; if(_readEncapsStack == null) // Lazy initialization { _readEncapsStack = _readEncapsCache; if(_readEncapsStack != null) { _readEncapsCache = _readEncapsCache.next; } else { _readEncapsStack = new ReadEncaps(); } } if(_readEncapsStack.patchMap == null) // Lazy initialization { _readEncapsStack.patchMap = new java.util.TreeMap(); _readEncapsStack.unmarshaledMap = new java.util.TreeMap(); _readEncapsStack.typeIdMap = new java.util.TreeMap(); } int index = readInt(); if(index == 0) { patcher.patch(null); return; } if(index < 0 && patcher != null) { Integer i = new Integer(-index); java.util.LinkedList patchlist = (java.util.LinkedList)_readEncapsStack.patchMap.get(i); if(patchlist == null) { // // We have no outstanding instances to be patched for this index, so make a new entry // in the patch map. // patchlist = new java.util.LinkedList(); _readEncapsStack.patchMap.put(i, patchlist); } // // Append a patcher for this instance and see if we can patch the instance. (The instance // may have been unmarshaled previously.) // patchlist.add(patcher); patchReferences(null, i); return; } while(true) { String id = readTypeId(); // // Try to find a factory registered for the specific type. // Ice.ObjectFactory userFactory = _instance.servantFactoryManager().find(id); if(userFactory != null) { v = userFactory.create(id); } // // If that fails, invoke the default factory if one has been registered. // if(v == null) { userFactory = _instance.servantFactoryManager().find(""); if(userFactory != null) { v = userFactory.create(id); } } // // There isn't a static factory for Ice::Object, so check for that case now. // We do this *after* the factory inquiries above so that a factory could be // registered for "::Ice::Object". // if(v == null && id.equals(Ice.ObjectImpl.ice_staticId())) { v = new Ice.ObjectImpl(); } // // Last chance: check the table of static factories (i.e., automatically generated // factories for concrete classes). // if(v == null) { userFactory = loadObjectFactory(id); if(userFactory != null) { v = userFactory.create(id); } } if(v == null) { // // Performance sensitive, so we use lazy initialization for tracing. // if(_traceSlicing == -1) { _traceSlicing = _instance.traceLevels().slicing; _slicingCat = _instance.traceLevels().slicingCat; } if(_traceSlicing > 0) { TraceUtil.traceSlicing("class", id, _slicingCat, _instance.logger()); } skipSlice(); // Slice off this derived part -- we don't understand it. continue; } Integer i = new Integer(index); _readEncapsStack.unmarshaledMap.put(i, v); v.__read(this, false); patchReferences(i, null); return; } } public void writeUserException(Ice.UserException v) { writeBool(v.__usesClasses()); v.__write(this); if(v.__usesClasses()) { writePendingObjects(); } } public void throwException() throws Ice.UserException { boolean usesClasses = readBool(); String id = readString(); while(!id.equals("")) { // // Look for a factory for this ID. // UserExceptionFactory factory = _instance.userExceptionFactoryManager().find(id); if(factory == null) { factory = loadUserExceptionFactory(id); } if(factory != null) { // // Got factory -- get the factory to instantiate the exception, initialize the // exception members, and throw the exception. // try { factory.createAndThrow(); } catch(Ice.UserException ex) { ex.__read(this, false); if(usesClasses) { readPendingObjects(); } throw ex; } } else { // // Performance sensitive, so we use lazy initialization for tracing. // if(_traceSlicing == -1) { _traceSlicing = _instance.traceLevels().slicing; _slicingCat = _instance.traceLevels().slicingCat; } if(_traceSlicing > 0) { TraceUtil.traceSlicing("exception", id, _slicingCat, _instance.logger()); } skipSlice(); // Slice off what we don't understand id = readString(); // Read type id for next slice } } // // Getting here should be impossible: we can get here only if the sender has marshaled a sequence // of type IDs, none of which we have factory for. This means that sender and receiver disagree // about the Slice definitions they use. // throw new Ice.UnknownUserException(); } public void writePendingObjects() { if(_writeEncapsStack != null && _writeEncapsStack.toBeMarshaledMap != null) { while(_writeEncapsStack.toBeMarshaledMap.size() > 0) { java.util.IdentityHashMap savedMap = new java.util.IdentityHashMap(_writeEncapsStack.toBeMarshaledMap); writeSize(savedMap.size()); for(java.util.Iterator p = savedMap.entrySet().iterator(); p.hasNext(); ) { // // Add an instance from the old to-be-marshaled map to the marshaled map and then // ask the instance to marshal itself. Any new class instances that are triggered // by the classes marshaled are added to toBeMarshaledMap. // java.util.Map.Entry e = (java.util.Map.Entry)p.next(); _writeEncapsStack.marshaledMap.put(e.getKey(), e.getValue()); writeInstance((Ice.Object)e.getKey(), (Integer)e.getValue()); } // // We have marshaled all the instances for this pass, substract what we have // marshaled from the toBeMarshaledMap. // for(java.util.Iterator p = savedMap.keySet().iterator(); p.hasNext(); ) { _writeEncapsStack.toBeMarshaledMap.remove(p.next()); } } } writeSize(0); // Zero marker indicates end of sequence of sequences of instances. } public void readPendingObjects() { int num; do { num = readSize(); for(int k = num; k > 0; --k) { readObject(null); } } while(num > 0); } public void marshalFacets(boolean b) { _marshalFacets = b; } void writeInstance(Ice.Object v, Integer index) { writeInt(index.intValue()); v.__write(this, _marshalFacets); } void patchReferences(Integer instanceIndex, Integer patchIndex) { // // Called whenever we have unmarshaled a new instance or an index. // The instanceIndex is the index of the instance just unmarshaled and patchIndex is the index // just unmarshaled. (Exactly one of the two parameters must be null.) // Patch any pointers in the patch map with the new address. // assert((instanceIndex != null && patchIndex == null) || (instanceIndex == null && patchIndex != null)); java.util.LinkedList patchlist; Ice.Object v; if(instanceIndex != null) { // // We have just unmarshaled an instance -- check if something needs patching for that instance. // patchlist = (java.util.LinkedList)_readEncapsStack.patchMap.get(instanceIndex); if(patchlist == null) { return; // We don't have anything to patch for the instance just unmarshaled } v = (Ice.Object)_readEncapsStack.unmarshaledMap.get(instanceIndex); patchIndex = instanceIndex; } else { // // We have just unmarshaled an index -- check if we have unmarshaled the instance for that index yet. // v = (Ice.Object)_readEncapsStack.unmarshaledMap.get(patchIndex); if(v == null) { return; // We haven't unmarshaled the instance for this index yet } patchlist = (java.util.LinkedList)_readEncapsStack.patchMap.get(patchIndex); } assert(patchlist != null && patchlist.size() > 0); assert(v != null); // // Patch all references that refer to the instance. // for(java.util.Iterator i = patchlist.iterator(); i.hasNext(); ) { IceInternal.Patcher p = (IceInternal.Patcher)i.next(); try { p.patch(v); } catch(ClassCastException ex) { Ice.NoObjectFactoryException nof = new Ice.NoObjectFactoryException(); nof.type = p.type(); nof.initCause(ex); throw nof; } } // // Clear out the patch map for that index -- there is nothing left to patch for that // index for the time being. // _readEncapsStack.patchMap.remove(patchIndex); } int pos() { return _buf.position(); } void pos(int n) { _buf.position(n); } int size() { return _limit; } boolean isEmpty() { return _limit == 0; } private void expand(int size) { if(_buf.position() == _limit) { int oldLimit = _limit; _limit += size; if(_limit > _messageSizeMax) { throw new Ice.MemoryLimitException(); } if(_limit > _capacity) { final int cap2 = _capacity << 1; int newCapacity = cap2 > _limit ? cap2 : _limit; _buf.limit(oldLimit); int pos = _buf.position(); _buf.position(0); _buf = _bufferManager.reallocate(_buf, newCapacity); assert(_buf != null); _capacity = _buf.capacity(); _buf.limit(_capacity); _buf.position(pos); } } } private static final class DynamicObjectFactory extends Ice.LocalObjectImpl implements Ice.ObjectFactory { DynamicObjectFactory(Class c) { _class = c; } public Ice.Object create(String type) { try { return (Ice.Object)_class.newInstance(); } catch(Exception ex) { Ice.SyscallException e = new Ice.SyscallException(); e.initCause(ex); throw e; } } public void destroy() { } private Class _class; } private Ice.ObjectFactory loadObjectFactory(String id) { Ice.ObjectFactory factory = null; try { Class c = Class.forName(typeToClass(id)); // // Ensure the class is instantiable. The constants are // defined in the JVM specification (0x200 = interface, // 0x400 = abstract). // int modifiers = c.getModifiers(); if((modifiers & 0x200) == 0 && (modifiers & 0x400) == 0) { Ice.ObjectFactory dynamicFactory = new DynamicObjectFactory(c); // // We will try to install the dynamic factory, but another thread // may install a factory first. // while(factory == null) { try { _instance.servantFactoryManager().add(dynamicFactory, id); factory = dynamicFactory; } catch(Ice.AlreadyRegisteredException ex) { // // Another thread already installed the factory, so try // to obtain it. It's possible (but unlikely) that the factory // will have already been removed, in which case the return // value will be null and the while loop will attempt to // install the dynamic factory again. // factory = _instance.servantFactoryManager().find(id); } } } } catch(ClassNotFoundException ex) { // Ignore } catch(Exception ex) { Ice.NoObjectFactoryException e = new Ice.NoObjectFactoryException(); e.type = id; e.initCause(ex); throw e; } return factory; } private static final class DynamicUserExceptionFactory extends Ice.LocalObjectImpl implements UserExceptionFactory { DynamicUserExceptionFactory(Class c) { _class = c; } public void createAndThrow() throws Ice.UserException { try { throw (Ice.UserException)_class.newInstance(); } catch(Ice.UserException ex) { throw ex; } catch(Exception ex) { Ice.SyscallException e = new Ice.SyscallException(); e.initCause(ex); throw e; } } public void destroy() { } private Class _class; } private UserExceptionFactory loadUserExceptionFactory(String id) { UserExceptionFactory factory = null; try { Class c = Class.forName(typeToClass(id)); // // Ensure the class is instantiable. The constants are // defined in the JVM specification (0x200 = interface, // 0x400 = abstract). // int modifiers = c.getModifiers(); assert((modifiers & 0x200) == 0 && (modifiers & 0x400) == 0); factory = new DynamicUserExceptionFactory(c); _instance.userExceptionFactoryManager().add(factory, id); } catch(ClassNotFoundException ex) { // Ignore } catch(Exception ex) { throw new Ice.UnknownUserException(); } return factory; } private String typeToClass(String id) { assert(id.startsWith("::")); return id.substring(2).replaceAll("::", "."); } private IceInternal.Instance _instance; private BufferManager _bufferManager; private java.nio.ByteBuffer _buf; private int _capacity; // Cache capacity to avoid excessive method calls private int _limit; // Cache limit to avoid excessive method calls private byte[] _stringBytes; // Reusable array for reading strings private char[] _stringChars; // Reusable array for reading strings private static final class ReadEncaps { int start; int sz; byte encodingMajor; byte encodingMinor; java.util.TreeMap patchMap; java.util.TreeMap unmarshaledMap; int typeIdIndex; java.util.TreeMap typeIdMap; ReadEncaps next; } private static final class WriteEncaps { int start; int writeIndex; java.util.IdentityHashMap toBeMarshaledMap; java.util.IdentityHashMap marshaledMap; int typeIdIndex; java.util.TreeMap typeIdMap; WriteEncaps next; } private ReadEncaps _readEncapsStack; private WriteEncaps _writeEncapsStack; private ReadEncaps _readEncapsCache; private WriteEncaps _writeEncapsCache; private int _readSlice; private int _writeSlice; private int _traceSlicing; private String _slicingCat; private boolean _marshalFacets; private int _messageSizeMax; }