src/share/classes/com/sun/corba/se/impl/encoding/CDRInputStream_1_0.java

Mon, 28 May 2018 10:29:43 +0800

author
aoqi
date
Mon, 28 May 2018 10:29:43 +0800
changeset 1655
bfd167e38830
parent 1618
4145ba26d9ff
parent 748
6845b95cba6b
permissions
-rw-r--r--

Merge

     1 /*
     2  * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    26 /*
    27  * Licensed Materials - Property of IBM
    28  * RMI-IIOP v1.0
    29  * Copyright IBM Corp. 1998 1999  All Rights Reserved
    30  *
    31  */
    33 package com.sun.corba.se.impl.encoding;
    35 import java.io.Serializable;
    36 import java.io.IOException;
    38 import java.net.MalformedURLException;
    40 import java.nio.ByteBuffer;
    42 import java.lang.reflect.InvocationTargetException;
    43 import java.lang.reflect.Method;
    45 import java.math.BigDecimal;
    47 import java.security.AccessController;
    48 import java.security.PrivilegedExceptionAction;
    49 import java.security.PrivilegedActionException;
    51 import org.omg.CORBA.SystemException;
    52 import org.omg.CORBA.portable.ValueBase;
    53 import org.omg.CORBA.portable.IndirectionException;
    54 import org.omg.CORBA.CompletionStatus;
    55 import org.omg.CORBA.TCKind;
    56 import org.omg.CORBA.TypeCodePackage.BadKind;
    57 import org.omg.CORBA.CustomMarshal;
    58 import org.omg.CORBA.TypeCode;
    59 import org.omg.CORBA.Principal;
    60 import org.omg.CORBA.Any;
    61 import org.omg.CORBA.portable.BoxedValueHelper;
    62 import org.omg.CORBA.portable.ValueFactory;
    63 import org.omg.CORBA.portable.CustomValue;
    64 import org.omg.CORBA.portable.StreamableValue;
    65 import org.omg.CORBA.MARSHAL;
    66 import org.omg.CORBA.portable.IDLEntity;
    68 import javax.rmi.CORBA.Tie;
    69 import javax.rmi.CORBA.ValueHandler;
    71 import com.sun.corba.se.pept.protocol.MessageMediator;
    72 import com.sun.corba.se.pept.transport.ByteBufferPool;
    74 import com.sun.corba.se.spi.protocol.CorbaClientDelegate;
    76 import com.sun.corba.se.spi.ior.IOR;
    77 import com.sun.corba.se.spi.ior.IORFactories;
    78 import com.sun.corba.se.spi.ior.iiop.GIOPVersion;
    80 import com.sun.corba.se.spi.orb.ORB;
    81 import com.sun.corba.se.spi.orb.ORBVersionFactory;
    83 import com.sun.corba.se.spi.logging.CORBALogDomains;
    84 import com.sun.corba.se.spi.presentation.rmi.PresentationManager;
    85 import com.sun.corba.se.spi.presentation.rmi.StubAdapter;
    86 import com.sun.corba.se.spi.presentation.rmi.PresentationDefaults;
    88 import com.sun.corba.se.impl.logging.ORBUtilSystemException;
    89 import com.sun.corba.se.impl.logging.OMGSystemException;
    91 import com.sun.corba.se.impl.corba.PrincipalImpl;
    92 import com.sun.corba.se.impl.corba.TypeCodeImpl;
    93 import com.sun.corba.se.impl.corba.CORBAObjectImpl;
    95 import com.sun.corba.se.impl.encoding.CDROutputObject;
    96 import com.sun.corba.se.impl.encoding.CodeSetConversion;
    98 import com.sun.corba.se.impl.util.Utility;
    99 import com.sun.corba.se.impl.util.RepositoryId;
   101 import com.sun.corba.se.impl.orbutil.RepositoryIdStrings;
   102 import com.sun.corba.se.impl.orbutil.RepositoryIdInterface;
   103 import com.sun.corba.se.impl.orbutil.RepositoryIdUtility;
   104 import com.sun.corba.se.impl.orbutil.RepositoryIdFactory;
   106 import com.sun.corba.se.impl.orbutil.ORBUtility;
   107 import com.sun.corba.se.impl.orbutil.CacheTable;
   110 import com.sun.org.omg.CORBA.portable.ValueHelper;
   112 import com.sun.org.omg.SendingContext.CodeBase;
   114 public class CDRInputStream_1_0 extends CDRInputStreamBase
   115     implements RestorableInputStream
   116 {
   117     private static final String kReadMethod = "read";
   118     private static final int maxBlockLength = 0x7fffff00;
   120     protected BufferManagerRead bufferManagerRead;
   121     protected ByteBufferWithInfo bbwi;
   123     // Set to the ORB's transportDebugFlag value.  This value is
   124     // used if the ORB is null.
   125     private boolean debug = false;
   127     protected boolean littleEndian;
   128     protected ORB orb;
   129     protected ORBUtilSystemException wrapper ;
   130     protected OMGSystemException omgWrapper ;
   131     protected ValueHandler valueHandler = null;
   133     // Value cache
   134     private CacheTable valueCache = null;
   136     // Repository ID cache
   137     private CacheTable repositoryIdCache = null;
   139     // codebase cache
   140     private CacheTable codebaseCache = null;
   142     // Current Class Stack (repository Ids of current class being read)
   143     // private Stack currentStack = null;
   145     // Length of current chunk, or a large positive number if not in a chunk
   146     protected int blockLength = maxBlockLength;
   148     // Read end flag (value nesting depth)
   149     protected int end_flag = 0;
   151     // Beginning with the resolution to interop issue 3526 (4328?),
   152     // only enclosing chunked valuetypes are taken into account
   153     // when computing the nesting level.  However, we still need
   154     // the old computation around for interoperability with our
   155     // older ORBs.
   156     private int chunkedValueNestingLevel = 0;
   158     // Flag used to determine whether blocksize was zero
   159     // private int checkForNullBlock = -1;
   161     // In block flag
   162     // private boolean inBlock = false;
   164     // Indicates whether we are inside a value
   165     // private boolean outerValueDone = true;
   167     // Int used by read_value(Serializable) that is set by this class
   168     // before calling ValueFactory.read_value
   169     protected int valueIndirection = 0;
   171     // Int set by readStringOrIndirection to communicate the actual
   172     // offset of the string length field back to the caller
   173     protected int stringIndirection = 0;
   175     // Flag indicating whether we are unmarshalling a chunked value
   176     protected boolean isChunked = false;
   178     // Repository ID handlers
   179     private RepositoryIdUtility repIdUtil;
   180     private RepositoryIdStrings repIdStrs;
   182     // Code set converters (created when first needed)
   183     private CodeSetConversion.BTCConverter charConverter;
   184     private CodeSetConversion.BTCConverter wcharConverter;
   186     // RMI-IIOP stream format version 2 case in which we know
   187     // that there is no more optional data available.  If the
   188     // Serializable's readObject method tries to read anything,
   189     // we must throw a MARSHAL with the special minor code
   190     // so that the ValueHandler can give the correct exception
   191     // to readObject.  The state is cleared when the ValueHandler
   192     // calls end_value after the readObject method exits.
   193     private boolean specialNoOptionalDataState = false;
   195     // Template method
   196     public CDRInputStreamBase dup()
   197     {
   198         CDRInputStreamBase result = null ;
   200         try {
   201             result = (CDRInputStreamBase)this.getClass().newInstance();
   202         } catch (Exception e) {
   203             throw wrapper.couldNotDuplicateCdrInputStream( e ) ;
   204         }
   205         result.init(this.orb,
   206                     this.bbwi.byteBuffer,
   207                     this.bbwi.buflen,
   208                     this.littleEndian,
   209                     this.bufferManagerRead);
   211         ((CDRInputStream_1_0)result).bbwi.position(this.bbwi.position());
   212         // To ensure we keep bbwi.byteBuffer.limit in sync with bbwi.buflen.
   213         ((CDRInputStream_1_0)result).bbwi.byteBuffer.limit(this.bbwi.buflen);
   215         return result;
   216     }
   218     /**
   219      * NOTE:  size passed to init means buffer size
   220      */
   221     public void init(org.omg.CORBA.ORB orb,
   222                      ByteBuffer byteBuffer,
   223                      int size,
   224                      boolean littleEndian,
   225                      BufferManagerRead bufferManager)
   226     {
   227         this.orb = (ORB)orb;
   228         this.wrapper = ORBUtilSystemException.get( (ORB)orb,
   229             CORBALogDomains.RPC_ENCODING ) ;
   230         this.omgWrapper = OMGSystemException.get( (ORB)orb,
   231             CORBALogDomains.RPC_ENCODING ) ;
   232         this.littleEndian = littleEndian;
   233         this.bufferManagerRead = bufferManager;
   234         this.bbwi = new ByteBufferWithInfo(orb,byteBuffer,0);
   235         this.bbwi.buflen = size;
   236         this.bbwi.byteBuffer.limit(bbwi.buflen);
   237         this.markAndResetHandler = bufferManagerRead.getMarkAndResetHandler();
   239         debug = ((ORB)orb).transportDebugFlag;
   240     }
   242     // See description in CDRInputStream
   243     void performORBVersionSpecificInit() {
   244         createRepositoryIdHandlers();
   245     }
   247     private final void createRepositoryIdHandlers()
   248     {
   249         repIdUtil = RepositoryIdFactory.getRepIdUtility();
   250         repIdStrs = RepositoryIdFactory.getRepIdStringsFactory();
   251     }
   253     public GIOPVersion getGIOPVersion() {
   254         return GIOPVersion.V1_0;
   255     }
   257     // Called by Request and Reply message. Valid for GIOP versions >= 1.2 only.
   258     // Illegal for GIOP versions < 1.2.
   259     void setHeaderPadding(boolean headerPadding) {
   260         throw wrapper.giopVersionError();
   261     }
   263     protected final int computeAlignment(int index, int align) {
   264         if (align > 1) {
   265             int incr = index & (align - 1);
   266             if (incr != 0)
   267                 return align - incr;
   268         }
   270         return 0;
   271     }
   273     public int getSize()
   274     {
   275         return bbwi.position();
   276     }
   278     protected void checkBlockLength(int align, int dataSize) {
   279         // Since chunks can end at arbitrary points (though not within
   280         // primitive CDR types, arrays of primitives, strings, wstrings,
   281         // or indirections),
   282         // we must check here for termination of the current chunk.
   283         if (!isChunked)
   284             return;
   286         // RMI-IIOP stream format version 2 case in which we know
   287         // that there is no more optional data available.  If the
   288         // Serializable's readObject method tries to read anything,
   289         // we must throw a MARSHAL exception with the special minor code
   290         // so that the ValueHandler can give the correct exception
   291         // to readObject.  The state is cleared when the ValueHandler
   292         // calls end_value after the readObject method exits.
   293         if (specialNoOptionalDataState) {
   294             throw omgWrapper.rmiiiopOptionalDataIncompatible1() ;
   295         }
   297         boolean checkForEndTag = false;
   299         // Are we at the end of the current chunk?  If so,
   300         // try to interpret the next long as a chunk length.
   301         // (It has to be either a chunk length, end tag,
   302         // or valuetag.)
   303         //
   304         // If it isn't a chunk length, blockLength will
   305         // remain set to maxBlockLength.
   306         if (blockLength == get_offset()) {
   308             blockLength = maxBlockLength;
   309             start_block();
   311             // What's next is either a valuetag or
   312             // an end tag.  If it's a valuetag, we're
   313             // probably being called as part of the process
   314             // to read the valuetag.  If it's an end tag,
   315             // then there isn't enough data left in
   316             // this valuetype to read!
   317             if (blockLength == maxBlockLength)
   318                 checkForEndTag = true;
   320         } else
   321         if (blockLength < get_offset()) {
   322             // Are we already past the end of the current chunk?
   323             // This is always an error.
   324             throw wrapper.chunkOverflow() ;
   325         }
   327         // If what's next on the wire isn't a chunk length or
   328         // what we want to read (which can't be split across chunks)
   329         // won't fit in the current chunk, throw this exception.
   330         // This probably means that we're in an RMI-IIOP
   331         // Serializable's readObject method or a custom marshaled
   332         // IDL type is reading too much/in an incorrect order
   333         int requiredNumBytes =
   334                             computeAlignment(bbwi.position(), align) + dataSize;
   336         if (blockLength != maxBlockLength &&
   337             blockLength < get_offset() + requiredNumBytes) {
   338             throw omgWrapper.rmiiiopOptionalDataIncompatible2() ;
   339         }
   341         // REVISIT - We should look at using the built in advancement
   342         //           of using ByteBuffer.get() rather than explicitly
   343         //           advancing the ByteBuffer's position.
   344         //           This is true for anywhere we are incrementing
   345         //           the ByteBuffer's position.
   346         if (checkForEndTag) {
   347             int nextLong = read_long();
   348             bbwi.position(bbwi.position() - 4);
   350             // It was an end tag, so there wasn't enough data
   351             // left in the valuetype's encoding on the wire
   352             // to read what we wanted
   353             if (nextLong < 0)
   354                 throw omgWrapper.rmiiiopOptionalDataIncompatible3() ;
   355         }
   356     }
   358     protected void alignAndCheck(int align, int n) {
   360         checkBlockLength(align, n);
   362         // WARNING: Must compute real alignment after calling
   363         // checkBlockLength since it may move the position
   364         int alignResult = computeAlignment(bbwi.position(), align);
   365         bbwi.position(bbwi.position() + alignResult);
   367         if (bbwi.position() + n > bbwi.buflen)
   368             grow(align, n);
   369     }
   371     //
   372     // This can be overridden....
   373     //
   374     protected void grow(int align, int n) {
   376         bbwi.needed = n;
   378         bbwi = bufferManagerRead.underflow(bbwi);
   380     }
   382     //
   383     // Marshal primitives.
   384     //
   386     public final void consumeEndian() {
   387         littleEndian = read_boolean();
   388     }
   390     // No such type in java
   391     public final double read_longdouble() {
   392         throw wrapper.longDoubleNotImplemented( CompletionStatus.COMPLETED_MAYBE);
   393     }
   395     public final boolean read_boolean() {
   396         return (read_octet() != 0);
   397     }
   399     public final char read_char() {
   400         alignAndCheck(1, 1);
   402         return getConvertedChars(1, getCharConverter())[0];
   403     }
   405     public char read_wchar() {
   407         // Don't allow transmission of wchar/wstring data with
   408         // foreign ORBs since it's against the spec.
   409         if (ORBUtility.isForeignORB((ORB)orb)) {
   410             throw wrapper.wcharDataInGiop10( CompletionStatus.COMPLETED_MAYBE);
   411         }
   413         // If we're talking to one of our legacy ORBs, do what
   414         // they did:
   415         int b1, b2;
   417         alignAndCheck(2, 2);
   419         if (littleEndian) {
   420             b2 = bbwi.byteBuffer.get(bbwi.position()) & 0x00FF;
   421             bbwi.position(bbwi.position() + 1);
   422             b1 = bbwi.byteBuffer.get(bbwi.position()) & 0x00FF;
   423             bbwi.position(bbwi.position() + 1);
   424         } else {
   425             b1 = bbwi.byteBuffer.get(bbwi.position()) & 0x00FF;
   426             bbwi.position(bbwi.position() + 1);
   427             b2 = bbwi.byteBuffer.get(bbwi.position()) & 0x00FF;
   428             bbwi.position(bbwi.position() + 1);
   429         }
   431         return (char)((b1 << 8) + (b2 << 0));
   432     }
   434     public final byte read_octet() {
   436         alignAndCheck(1, 1);
   438         byte b = bbwi.byteBuffer.get(bbwi.position());
   439         bbwi.position(bbwi.position() + 1);
   441         return b;
   442     }
   444     public final short read_short() {
   445         int b1, b2;
   447         alignAndCheck(2, 2);
   449         if (littleEndian) {
   450             b2 = (bbwi.byteBuffer.get(bbwi.position()) << 0) & 0x000000FF;
   451             bbwi.position(bbwi.position() + 1);
   452             b1 = (bbwi.byteBuffer.get(bbwi.position()) << 8) & 0x0000FF00;
   453             bbwi.position(bbwi.position() + 1);
   454         } else {
   455             b1 = (bbwi.byteBuffer.get(bbwi.position()) << 8) & 0x0000FF00;
   456             bbwi.position(bbwi.position() + 1);
   457             b2 = (bbwi.byteBuffer.get(bbwi.position()) << 0) & 0x000000FF;
   458             bbwi.position(bbwi.position() + 1);
   459         }
   461         return (short)(b1 | b2);
   462     }
   464     public final short read_ushort() {
   465         return read_short();
   466     }
   468     public final int read_long() {
   469         int b1, b2, b3, b4;
   471         alignAndCheck(4, 4);
   473         int bufPos = bbwi.position();
   474         if (littleEndian) {
   475             b4 = bbwi.byteBuffer.get(bufPos++) & 0xFF;
   476             b3 = bbwi.byteBuffer.get(bufPos++) & 0xFF;
   477             b2 = bbwi.byteBuffer.get(bufPos++) & 0xFF;
   478             b1 = bbwi.byteBuffer.get(bufPos++) & 0xFF;
   479         } else {
   480             b1 = bbwi.byteBuffer.get(bufPos++) & 0xFF;
   481             b2 = bbwi.byteBuffer.get(bufPos++) & 0xFF;
   482             b3 = bbwi.byteBuffer.get(bufPos++) & 0xFF;
   483             b4 = bbwi.byteBuffer.get(bufPos++) & 0xFF;
   484         }
   485         bbwi.position(bufPos);
   487         return (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
   488     }
   490     public final int read_ulong() {
   491         return read_long();
   492     }
   494     public final long read_longlong() {
   495         long i1, i2;
   497         alignAndCheck(8, 8);
   499         if (littleEndian) {
   500             i2 = read_long() & 0xFFFFFFFFL;
   501             i1 = (long)read_long() << 32;
   502         } else {
   503             i1 = (long)read_long() << 32;
   504             i2 = read_long() & 0xFFFFFFFFL;
   505         }
   507         return (i1 | i2);
   508     }
   510     public final long read_ulonglong() {
   511         return read_longlong();
   512     }
   514     public final float read_float() {
   515         return Float.intBitsToFloat(read_long());
   516     }
   518     public final double read_double() {
   519         return Double.longBitsToDouble(read_longlong());
   520     }
   522     protected final void checkForNegativeLength(int length) {
   523         if (length < 0)
   524             throw wrapper.negativeStringLength( CompletionStatus.COMPLETED_MAYBE,
   525                 new Integer(length) ) ;
   526     }
   528     protected final String readStringOrIndirection(boolean allowIndirection) {
   530         int len = read_long();
   532         //
   533         // Check for indirection
   534         //
   535         if (allowIndirection) {
   536             if (len == 0xffffffff)
   537                 return null;
   538             else
   539                 stringIndirection = get_offset() - 4;
   540         }
   542         checkForNegativeLength(len);
   544         return internalReadString(len);
   545     }
   547     private final String internalReadString(int len) {
   548         // Workaround for ORBs which send string lengths of
   549         // zero to mean empty string.
   550         //
   551         // IMPORTANT: Do not replace 'new String("")' with "", it may result
   552         // in a Serialization bug (See serialization.zerolengthstring) and
   553         // bug id: 4728756 for details
   554         if (len == 0)
   555             return new String("");
   557         char[] result = getConvertedChars(len - 1, getCharConverter());
   559         // Skip over the 1 byte null
   560         read_octet();
   562         return new String(result, 0, getCharConverter().getNumChars());
   563     }
   565     public final String read_string() {
   566         return readStringOrIndirection(false);
   567     }
   569     public String read_wstring() {
   570         // Don't allow transmission of wchar/wstring data with
   571         // foreign ORBs since it's against the spec.
   572         if (ORBUtility.isForeignORB((ORB)orb)) {
   573             throw wrapper.wcharDataInGiop10( CompletionStatus.COMPLETED_MAYBE);
   574         }
   576         int len = read_long();
   578         //
   579         // Workaround for ORBs which send string lengths of
   580         // zero to mean empty string.
   581         //
   582         //
   583         // IMPORTANT: Do not replace 'new String("")' with "", it may result
   584         // in a Serialization bug (See serialization.zerolengthstring) and
   585         // bug id: 4728756 for details
   586         if (len == 0)
   587             return new String("");
   589         checkForNegativeLength(len);
   591         len--;
   592         char[] c = new char[len];
   594         for (int i = 0; i < len; i++)
   595             c[i] = read_wchar();
   597         // skip the two null terminator bytes
   598         read_wchar();
   599         // bbwi.position(bbwi.position() + 2);
   601         return new String(c);
   602     }
   604     public final void read_octet_array(byte[] b, int offset, int length) {
   605         if ( b == null )
   606             throw wrapper.nullParam() ;
   608         // Must call alignAndCheck at least once to ensure
   609         // we aren't at the end of a chunk.  Of course, we
   610         // should only call it if we actually need to read
   611         // something, otherwise we might end up with an
   612         // exception at the end of the stream.
   613         if (length == 0)
   614             return;
   616         alignAndCheck(1, 1);
   618         int n = offset;
   619         while (n < length+offset) {
   620             int avail;
   621             int bytes;
   622             int wanted;
   624             avail = bbwi.buflen - bbwi.position();
   625             if (avail <= 0) {
   626                 grow(1, 1);
   627                 avail = bbwi.buflen - bbwi.position();
   628             }
   629             wanted = (length + offset) - n;
   630             bytes = (wanted < avail) ? wanted : avail;
   631             // Microbenchmarks are showing a loop of ByteBuffer.get(int) being
   632             // faster than ByteBuffer.get(byte[], int, int).
   633             for (int i = 0; i < bytes; i++) {
   634                 b[n+i] = bbwi.byteBuffer.get(bbwi.position() + i);
   635             }
   637             bbwi.position(bbwi.position() + bytes);
   639             n += bytes;
   640         }
   641     }
   643     public Principal read_Principal() {
   644         int len = read_long();
   645         byte[] pvalue = new byte[len];
   646         read_octet_array(pvalue,0,len);
   648         Principal p = new PrincipalImpl();
   649         p.name(pvalue);
   650         return p;
   651     }
   653     public TypeCode read_TypeCode() {
   654         TypeCodeImpl tc = new TypeCodeImpl(orb);
   655         tc.read_value(parent);
   656         return tc;
   657     }
   659     public Any read_any() {
   660         Any any = orb.create_any();
   661         TypeCodeImpl tc = new TypeCodeImpl(orb);
   663         // read off the typecode
   665         // REVISIT We could avoid this try-catch if we could peek the typecode
   666         // kind off this stream and see if it is a tk_value.  Looking at the
   667         // code we know that for tk_value the Any.read_value() below
   668         // ignores the tc argument anyway (except for the kind field).
   669         // But still we would need to make sure that the whole typecode,
   670         // including encapsulations, is read off.
   671         try {
   672             tc.read_value(parent);
   673         } catch (MARSHAL ex) {
   674             if (tc.kind().value() != TCKind._tk_value)
   675                 throw ex;
   676             // We can be sure that the whole typecode encapsulation has been
   677             // read off.
   678             dprintThrowable(ex);
   679         }
   680         // read off the value of the any
   681         any.read_value(parent, tc);
   683         return any;
   684     }
   686     public org.omg.CORBA.Object read_Object() {
   687         return read_Object(null);
   688     }
   690     // ------------ RMI related methods --------------------------
   692     // IDL to Java ptc-00-01-08 1.21.4.1
   693     //
   694     // The clz argument to read_Object can be either a stub
   695     // Class or the "Class object for the RMI/IDL interface type
   696     // that is statically expected."
   697     // This functions as follows:
   698     // 1. If clz==null, just use the repository ID from the stub
   699     // 2. If clz is a stub class, just use it as a static factory.
   700     //    clz is a stub class iff StubAdapter.isStubClass( clz ).
   701     //    In addition, clz is a IDL stub class iff
   702     //    IDLEntity.class.isAssignableFrom( clz ).
   703     // 3. If clz is an interface, use it to create the appropriate
   704     //    stub factory.
   706     public org.omg.CORBA.Object read_Object(Class clz)
   707     {
   708         // In any case, we must first read the IOR.
   709         IOR ior = IORFactories.makeIOR(parent) ;
   710         if (ior.isNil()) {
   711             return null ;
   712         }
   714         PresentationManager.StubFactoryFactory sff = ORB.getStubFactoryFactory() ;
   715         String codeBase = ior.getProfile().getCodebase() ;
   716         PresentationManager.StubFactory stubFactory = null ;
   718         if (clz == null) {
   719             RepositoryId rid = RepositoryId.cache.getId( ior.getTypeId() ) ;
   720             String className = rid.getClassName() ;
   721             orb.validateIORClass(className);
   722             boolean isIDLInterface = rid.isIDLType() ;
   724             if (className == null || className.equals( "" ))
   725                 stubFactory = null ;
   726             else
   727                 try {
   728                     stubFactory = sff.createStubFactory( className,
   729                         isIDLInterface, codeBase, (Class)null,
   730                         (ClassLoader)null );
   731                 } catch (Exception exc) {
   732                     // Could not create stubFactory, so use null.
   733                     // XXX stubFactory handling is still too complex:
   734                     // Can we resolve the stubFactory question once in
   735                     // a single place?
   736                     stubFactory = null ;
   737                 }
   738         } else if (StubAdapter.isStubClass( clz )) {
   739             stubFactory = PresentationDefaults.makeStaticStubFactory(
   740                 clz ) ;
   741         } else {
   742             // clz is an interface class
   743             boolean isIDL = IDLEntity.class.isAssignableFrom( clz ) ;
   744             stubFactory = sff.createStubFactory( clz.getName(),
   745                 isIDL, codeBase, clz, clz.getClassLoader() ) ;
   746         }
   747         return internalIORToObject( ior, stubFactory, orb ) ;
   748     }
   750     /*
   751      * This is used as a general utility (e.g., the PortableInterceptor
   752      * implementation uses it.   If stubFactory is null, the ior's
   753      * IIOPProfile must support getServant.
   754      */
   755     public static org.omg.CORBA.Object internalIORToObject(
   756         IOR ior, PresentationManager.StubFactory stubFactory, ORB orb)
   757     {
   758         ORBUtilSystemException wrapper = ORBUtilSystemException.get(
   759             (ORB)orb, CORBALogDomains.RPC_ENCODING ) ;
   761         java.lang.Object servant = ior.getProfile().getServant() ;
   762         if (servant != null ) {
   763             if (servant instanceof Tie) {
   764                 String codebase = ior.getProfile().getCodebase();
   765                 org.omg.CORBA.Object objref = (org.omg.CORBA.Object)
   766                     Utility.loadStub( (Tie)servant, stubFactory, codebase,
   767                         false);
   769                 // If we managed to load a stub, return it, otherwise we
   770                 // must fail...
   771                 if (objref != null) {
   772                     return objref;
   773                 } else {
   774                     throw wrapper.readObjectException() ;
   775                 }
   776             } else if (servant instanceof org.omg.CORBA.Object) {
   777                 if (!(servant instanceof
   778                         org.omg.CORBA.portable.InvokeHandler)) {
   779                     return (org.omg.CORBA.Object) servant;
   780                 }
   781             } else
   782                 throw wrapper.badServantReadObject() ;
   783         }
   785         CorbaClientDelegate del = ORBUtility.makeClientDelegate( ior ) ;
   786         org.omg.CORBA.Object objref = null ;
   787         try {
   788             objref = stubFactory.makeStub() ;
   789         } catch (Throwable e) {
   790             wrapper.stubCreateError( e ) ;
   792             if (e instanceof ThreadDeath) {
   793                 throw (ThreadDeath) e;
   794             }
   796             // Return the "default" stub...
   797             objref = new CORBAObjectImpl() ;
   798         }
   800         StubAdapter.setDelegate( objref, del ) ;
   801         return objref;
   802     }
   804     public java.lang.Object read_abstract_interface()
   805     {
   806         return read_abstract_interface(null);
   807     }
   809     public java.lang.Object read_abstract_interface(java.lang.Class clz)
   810     {
   811         boolean object = read_boolean();
   813         if (object) {
   814             return read_Object(clz);
   815         } else {
   816             return read_value();
   817         }
   818     }
   820     public Serializable read_value()
   821     {
   822         return read_value((Class)null);
   823     }
   825     private Serializable handleIndirection() {
   826         int indirection = read_long() + get_offset() - 4;
   827         if (valueCache != null && valueCache.containsVal(indirection)) {
   829             java.io.Serializable cachedValue
   830                 = (java.io.Serializable)valueCache.getKey(indirection);
   831             return cachedValue;
   832         } else {
   833             // In RMI-IIOP the ValueHandler will recognize this
   834             // exception and use the provided indirection value
   835             // to lookup a possible indirection to an object
   836             // currently on the deserialization stack.
   837             throw new IndirectionException(indirection);
   838         }
   839     }
   841     private String readRepositoryIds(int valueTag,
   842                                      Class expectedType,
   843                                      String expectedTypeRepId) {
   844         return readRepositoryIds(valueTag, expectedType,
   845                                  expectedTypeRepId, null);
   846     }
   848     /**
   849      * Examines the valuetag to see how many (if any) repository IDs
   850      * are present on the wire.  If no repository ID information
   851      * is on the wire but the expectedType or expectedTypeRepId
   852      * is known, it will return one of those (favoring the
   853      * expectedType's repId). Failing that, it uses the supplied
   854      * BoxedValueHelper to obtain the repository ID, as a last resort.
   855      */
   856     private String readRepositoryIds(int valueTag,
   857                                      Class expectedType,
   858                                      String expectedTypeRepId,
   859                                      BoxedValueHelper factory) {
   860         switch(repIdUtil.getTypeInfo(valueTag)) {
   861             case RepositoryIdUtility.NO_TYPE_INFO :
   862                 // Throw an exception if we have no repository ID info and
   863                 // no expectedType to work with.  Otherwise, how would we
   864                 // know what to unmarshal?
   865                 if (expectedType == null) {
   866                     if (expectedTypeRepId != null) {
   867                         return expectedTypeRepId;
   868                     } else if (factory != null) {
   869                         return factory.get_id();
   870                     } else {
   871                         throw wrapper.expectedTypeNullAndNoRepId(
   872                             CompletionStatus.COMPLETED_MAYBE);
   873                     }
   874                 }
   875                 return repIdStrs.createForAnyType(expectedType);
   876             case RepositoryIdUtility.SINGLE_REP_TYPE_INFO :
   877                 return read_repositoryId();
   878             case RepositoryIdUtility.PARTIAL_LIST_TYPE_INFO :
   879                 return read_repositoryIds();
   880             default:
   881                 throw wrapper.badValueTag( CompletionStatus.COMPLETED_MAYBE,
   882                     Integer.toHexString(valueTag) ) ;
   883         }
   884     }
   886     public Serializable read_value(Class expectedType) {
   888         // Read value tag
   889         int vType = readValueTag();
   891         // Is value null?
   892         if (vType == 0)
   893             return null;
   895         // Is this an indirection to a previously
   896         // read valuetype?
   897         if (vType == 0xffffffff)
   898             return handleIndirection();
   900         // Save where this valuetype started so we
   901         // can put it in the indirection valueCache
   902         // later
   903         int indirection = get_offset() - 4;
   905         // Need to save this special marker variable
   906         // to restore its value during recursion
   907         boolean saveIsChunked = isChunked;
   909         isChunked = repIdUtil.isChunkedEncoding(vType);
   911         java.lang.Object value = null;
   913         String codebase_URL = null;
   914         if (repIdUtil.isCodeBasePresent(vType)) {
   915             codebase_URL = read_codebase_URL();
   916         }
   918         // Read repository id(s)
   919         String repositoryIDString
   920             = readRepositoryIds(vType, expectedType, null);
   922         // If isChunked was determined to be true based
   923         // on the valuetag, this will read a chunk length
   924         start_block();
   926         // Remember that end_flag keeps track of all nested
   927         // valuetypes and is used for older ORBs
   928         end_flag--;
   929         if (isChunked)
   930             chunkedValueNestingLevel--;
   932         if (repositoryIDString.equals(repIdStrs.getWStringValueRepId())) {
   933             value = read_wstring();
   934         } else
   935         if (repositoryIDString.equals(repIdStrs.getClassDescValueRepId())) {
   936             // read in the class whether with the old ClassDesc or the
   937             // new one
   938             value = readClass();
   939         } else {
   941             Class valueClass = expectedType;
   943             // By this point, either the expectedType or repositoryIDString
   944             // is guaranteed to be non-null.
   945             if (expectedType == null ||
   946                 !repositoryIDString.equals(repIdStrs.createForAnyType(expectedType))) {
   948                 valueClass = getClassFromString(repositoryIDString,
   949                                                 codebase_URL,
   950                                                 expectedType);
   951             }
   953             if (valueClass == null) {
   954                 // No point attempting to use value handler below, since the
   955                 // class information is not available.
   956                 throw wrapper.couldNotFindClass(
   957                     CompletionStatus.COMPLETED_MAYBE,
   958                     new ClassNotFoundException());
   959             }
   961             if (valueClass != null &&
   962                 org.omg.CORBA.portable.IDLEntity.class.isAssignableFrom(valueClass)) {
   964                 value =  readIDLValue(indirection,
   965                                       repositoryIDString,
   966                                       valueClass,
   967                                       codebase_URL);
   969             } else {
   971                 // Must be some form of RMI-IIOP valuetype
   973                 try {
   974                     if (valueHandler == null)
   975                         valueHandler = ORBUtility.createValueHandler();
   977                     value = valueHandler.readValue(parent,
   978                                                    indirection,
   979                                                    valueClass,
   980                                                    repositoryIDString,
   981                                                    getCodeBase());
   983                 } catch(SystemException sysEx) {
   984                     // Just rethrow any CORBA system exceptions
   985                     // that come out of the ValueHandler
   986                     throw sysEx;
   987                 } catch(Exception ex) {
   988                     throw wrapper.valuehandlerReadException(
   989                         CompletionStatus.COMPLETED_MAYBE, ex ) ;
   990                 } catch(Error e) {
   991                     throw wrapper.valuehandlerReadError(
   992                         CompletionStatus.COMPLETED_MAYBE, e ) ;
   993                 }
   994             }
   995         }
   997         // Skip any remaining chunks until we get to
   998         // an end tag or a valuetag.  If we see a valuetag,
   999         // that means there was another valuetype in the sender's
  1000         // version of this class that we need to skip over.
  1001         handleEndOfValue();
  1003         // Read and process the end tag if we're chunking.
  1004         // Assumes that we're at the position of the end tag
  1005         // (handleEndOfValue should assure this)
  1006         readEndTag();
  1008         // Cache the valuetype that we read
  1009         if (valueCache == null)
  1010             valueCache = new CacheTable(orb,false);
  1011         valueCache.put(value, indirection);
  1013         // Allow for possible continuation chunk.
  1014         // If we're a nested valuetype inside of a chunked
  1015         // valuetype, and that enclosing valuetype has
  1016         // more data to write, it will need to have this
  1017         // new chunk begin after we wrote our end tag.
  1018         isChunked = saveIsChunked;
  1019         start_block();
  1021         return (java.io.Serializable)value;
  1024     public Serializable read_value(BoxedValueHelper factory) {
  1026         // Read value tag
  1027         int vType = readValueTag();
  1029         if (vType == 0)
  1030             return null; // value is null
  1031         else if (vType == 0xffffffff) { // Indirection tag
  1032             int indirection = read_long() + get_offset() - 4;
  1033             if (valueCache != null && valueCache.containsVal(indirection))
  1035                     java.io.Serializable cachedValue =
  1036                            (java.io.Serializable)valueCache.getKey(indirection);
  1037                     return cachedValue;
  1039             else {
  1040                 throw new IndirectionException(indirection);
  1043         else {
  1044             int indirection = get_offset() - 4;
  1046             // end_block();
  1048             boolean saveIsChunked = isChunked;
  1049             isChunked = repIdUtil.isChunkedEncoding(vType);
  1051             java.lang.Object value = null;
  1053             String codebase_URL = null;
  1054             if (repIdUtil.isCodeBasePresent(vType)){
  1055                 codebase_URL = read_codebase_URL();
  1058             // Read repository id
  1059             String repositoryIDString
  1060                 = readRepositoryIds(vType, null, null, factory);
  1062             // Compare rep. ids to see if we should use passed helper
  1063             if (!repositoryIDString.equals(factory.get_id()))
  1064                 factory = Utility.getHelper(null, codebase_URL, repositoryIDString);
  1066             start_block();
  1067             end_flag--;
  1068             if (isChunked)
  1069                 chunkedValueNestingLevel--;
  1071             if (factory instanceof ValueHelper) {
  1072                 value = readIDLValueWithHelper((ValueHelper)factory, indirection);
  1073             } else {
  1074                 valueIndirection = indirection;  // for callback
  1075                 value = factory.read_value(parent);
  1078             handleEndOfValue();
  1079             readEndTag();
  1081             // Put into valueCache
  1082             if (valueCache == null)
  1083                 valueCache = new CacheTable(orb,false);
  1084             valueCache.put(value, indirection);
  1086             // allow for possible continuation chunk
  1087             isChunked = saveIsChunked;
  1088             start_block();
  1090             return (java.io.Serializable)value;
  1094     private boolean isCustomType(ValueHelper helper) {
  1095         try{
  1096             TypeCode tc = helper.get_type();
  1097             int kind = tc.kind().value();
  1098             if (kind == TCKind._tk_value) {
  1099                 return (tc.type_modifier() == org.omg.CORBA.VM_CUSTOM.value);
  1101         } catch(BadKind ex) {
  1102             throw wrapper.badKind(ex) ;
  1105         return false;
  1108     // This method is actually called indirectly by
  1109     // read_value(String repositoryId).
  1110     // Therefore, it is not a truly independent read call that handles
  1111     // header information itself.
  1112     public java.io.Serializable read_value(java.io.Serializable value) {
  1114         // Put into valueCache using valueIndirection
  1115         if (valueCache == null)
  1116             valueCache = new CacheTable(orb,false);
  1117         valueCache.put(value, valueIndirection);
  1119         if (value instanceof StreamableValue)
  1120             ((StreamableValue)value)._read(parent);
  1121         else if (value instanceof CustomValue)
  1122             ((CustomValue)value).unmarshal(parent);
  1124         return value;
  1127     public java.io.Serializable read_value(java.lang.String repositoryId) {
  1129         // if (inBlock)
  1130         //    end_block();
  1132         // Read value tag
  1133         int vType = readValueTag();
  1135         if (vType == 0)
  1136             return null; // value is null
  1137         else if (vType == 0xffffffff) { // Indirection tag
  1138             int indirection = read_long() + get_offset() - 4;
  1139             if (valueCache != null && valueCache.containsVal(indirection))
  1141                     java.io.Serializable cachedValue =
  1142                           (java.io.Serializable)valueCache.getKey(indirection);
  1143                     return cachedValue;
  1145             else {
  1146                 throw new IndirectionException(indirection);
  1149         else {
  1150             int indirection = get_offset() - 4;
  1152             // end_block();
  1154             boolean saveIsChunked = isChunked;
  1155             isChunked = repIdUtil.isChunkedEncoding(vType);
  1157             java.lang.Object value = null;
  1159             String codebase_URL = null;
  1160             if (repIdUtil.isCodeBasePresent(vType)){
  1161                 codebase_URL = read_codebase_URL();
  1164             // Read repository id
  1165             String repositoryIDString
  1166                 = readRepositoryIds(vType, null, repositoryId);
  1168             ValueFactory factory =
  1169                Utility.getFactory(null, codebase_URL, orb, repositoryIDString);
  1171             start_block();
  1172             end_flag--;
  1173             if (isChunked)
  1174                 chunkedValueNestingLevel--;
  1176             valueIndirection = indirection;  // for callback
  1177             value = factory.read_value(parent);
  1179             handleEndOfValue();
  1180             readEndTag();
  1182             // Put into valueCache
  1183             if (valueCache == null)
  1184                 valueCache = new CacheTable(orb,false);
  1185             valueCache.put(value, indirection);
  1187             // allow for possible continuation chunk
  1188             isChunked = saveIsChunked;
  1189             start_block();
  1191             return (java.io.Serializable)value;
  1195     private Class readClass() {
  1197         String codebases = null, classRepId = null;
  1199         if (orb == null ||
  1200             ORBVersionFactory.getFOREIGN().equals(orb.getORBVersion()) ||
  1201             ORBVersionFactory.getNEWER().compareTo(orb.getORBVersion()) <= 0) {
  1203             codebases = (String)read_value(java.lang.String.class);
  1204             classRepId = (String)read_value(java.lang.String.class);
  1205         } else {
  1206             // Pre-Merlin/J2EE 1.3 ORBs wrote the repository ID
  1207             // and codebase strings in the wrong order.
  1208             classRepId = (String)read_value(java.lang.String.class);
  1209             codebases = (String)read_value(java.lang.String.class);
  1212         if (debug) {
  1213             dprint("readClass codebases: "
  1214                    + codebases
  1215                    + " rep Id: "
  1216                    + classRepId);
  1219         Class cl = null;
  1221         RepositoryIdInterface repositoryID
  1222             = repIdStrs.getFromString(classRepId);
  1224         try {
  1225             cl = repositoryID.getClassFromType(codebases);
  1226         } catch(ClassNotFoundException cnfe) {
  1227             throw wrapper.cnfeReadClass( CompletionStatus.COMPLETED_MAYBE,
  1228                 cnfe, repositoryID.getClassName() ) ;
  1229         } catch(MalformedURLException me) {
  1230             throw wrapper.malformedUrl( CompletionStatus.COMPLETED_MAYBE,
  1231                 me, repositoryID.getClassName(), codebases ) ;
  1234         return cl;
  1237     private java.lang.Object readIDLValueWithHelper(ValueHelper helper, int indirection)
  1239         // look for two-argument static read method
  1240         Method readMethod;
  1241         try {
  1242             Class argTypes[] = {org.omg.CORBA.portable.InputStream.class, helper.get_class()};
  1243             readMethod = helper.getClass().getDeclaredMethod(kReadMethod, argTypes);
  1245         catch(NoSuchMethodException nsme) { // must be boxed value helper
  1246             java.lang.Object result = helper.read_value(parent);
  1247             return result;
  1250         // found two-argument read method, so must be non-boxed value...
  1251         // ...create a blank instance
  1252         java.lang.Object val = null;
  1253         try {
  1254             val = helper.get_class().newInstance();
  1255         } catch(java.lang.InstantiationException ie) {
  1256             throw wrapper.couldNotInstantiateHelper( ie,
  1257                 helper.get_class() ) ;
  1258         } catch(IllegalAccessException iae){
  1259             // Value's constructor is protected or private
  1260             //
  1261             // So, use the helper to read the value.
  1262             //
  1263             // NOTE : This means that in this particular case a recursive ref.
  1264             // would fail.
  1265             return helper.read_value(parent);
  1268         // add blank instance to cache table
  1269         if (valueCache == null)
  1270             valueCache = new CacheTable(orb,false);
  1271         valueCache.put(val, indirection);
  1273         // if custom type, call unmarshal method
  1274         if (val instanceof CustomMarshal && isCustomType(helper)) {
  1275             ((CustomMarshal)val).unmarshal(parent);
  1276             return val;
  1279         // call two-argument read method using reflection
  1280         try {
  1281             java.lang.Object args[] = {parent, val};
  1282             readMethod.invoke(helper, args);
  1283             return val;
  1284         } catch(IllegalAccessException iae2) {
  1285             throw wrapper.couldNotInvokeHelperReadMethod( iae2, helper.get_class() ) ;
  1286         } catch(InvocationTargetException ite){
  1287             throw wrapper.couldNotInvokeHelperReadMethod( ite, helper.get_class() ) ;
  1291     private java.lang.Object readBoxedIDLEntity(Class clazz, String codebase)
  1293         Class cls = null ;
  1295         try {
  1296             ClassLoader clazzLoader = (clazz == null ? null : clazz.getClassLoader());
  1298             cls = Utility.loadClassForClass(clazz.getName()+"Helper", codebase,
  1299                                                    clazzLoader, clazz, clazzLoader);
  1300             final Class helperClass = cls ;
  1302             final Class argTypes[] = {org.omg.CORBA.portable.InputStream.class};
  1304             // getDeclaredMethod requires RuntimePermission accessDeclaredMembers
  1305             // if a different class loader is used (even though the javadoc says otherwise)
  1306             Method readMethod = null;
  1307             try {
  1308                 readMethod = (Method)AccessController.doPrivileged(
  1309                     new PrivilegedExceptionAction() {
  1310                         public java.lang.Object run() throws NoSuchMethodException {
  1311                             return helperClass.getDeclaredMethod(kReadMethod, argTypes);
  1314                 );
  1315             } catch (PrivilegedActionException pae) {
  1316                 // this gets caught below
  1317                 throw (NoSuchMethodException)pae.getException();
  1320             java.lang.Object args[] = {parent};
  1321             return readMethod.invoke(null, args);
  1323         } catch (ClassNotFoundException cnfe) {
  1324             throw wrapper.couldNotInvokeHelperReadMethod( cnfe, cls ) ;
  1325         } catch(NoSuchMethodException nsme) {
  1326             throw wrapper.couldNotInvokeHelperReadMethod( nsme, cls ) ;
  1327         } catch(IllegalAccessException iae) {
  1328             throw wrapper.couldNotInvokeHelperReadMethod( iae, cls ) ;
  1329         } catch(InvocationTargetException ite) {
  1330             throw wrapper.couldNotInvokeHelperReadMethod( ite, cls ) ;
  1334     private java.lang.Object readIDLValue(int indirection, String repId,
  1335                                           Class clazz, String codebase)
  1337         ValueFactory factory ;
  1339         // Always try to find a ValueFactory first, as required by the spec.
  1340         // There are some complications here in the IDL 3.0 mapping (see 1.13.8),
  1341         // but basically we must always be able to override the DefaultFactory
  1342         // or Helper mappings that are also used.  This appears to be the case
  1343         // even in the boxed value cases.  The original code only did the lookup
  1344         // in the case of class implementing either StreamableValue or CustomValue,
  1345         // but abstract valuetypes only implement ValueBase, and really require
  1346         // the use of the repId to find a factory (including the DefaultFactory).
  1347         try {
  1348             // use new-style OBV support (factory object)
  1349             factory = Utility.getFactory(clazz, codebase, orb, repId);
  1350         } catch (MARSHAL marshal) {
  1351             // XXX log marshal at one of the INFO levels
  1353             // Could not get a factory, so try alternatives
  1354             if (!StreamableValue.class.isAssignableFrom(clazz) &&
  1355                 !CustomValue.class.isAssignableFrom(clazz) &&
  1356                 ValueBase.class.isAssignableFrom(clazz)) {
  1357                 // use old-style OBV support (helper object)
  1358                 BoxedValueHelper helper = Utility.getHelper(clazz, codebase, repId);
  1359                 if (helper instanceof ValueHelper)
  1360                     return readIDLValueWithHelper((ValueHelper)helper, indirection);
  1361                 else
  1362                     return helper.read_value(parent);
  1363             } else {
  1364                 // must be a boxed IDLEntity, so make a reflective call to the
  1365                 // helper's static read method...
  1366                 return readBoxedIDLEntity(clazz, codebase);
  1370         // If there was no error in getting the factory, use it.
  1371         valueIndirection = indirection;  // for callback
  1372         return factory.read_value(parent);
  1375     /**
  1376      * End tags are only written for chunked valuetypes.
  1378      * Before Merlin, our ORBs wrote end tags which took into account
  1379      * all enclosing valuetypes.  This was changed by an interop resolution
  1380      * (see details around chunkedValueNestingLevel) to only include
  1381      * enclosing chunked types.
  1383      * ORB versioning and end tag compaction are handled here.
  1384      */
  1385     private void readEndTag() {
  1386         if (isChunked) {
  1388             // Read the end tag
  1389             int anEndTag = read_long();
  1391             // End tags should always be negative, and the outermost
  1392             // enclosing chunked valuetype should have a -1 end tag.
  1393             //
  1394             // handleEndOfValue should have assured that we were
  1395             // at the end tag position!
  1396             if (anEndTag >= 0) {
  1397                 throw wrapper.positiveEndTag( CompletionStatus.COMPLETED_MAYBE,
  1398                     new Integer(anEndTag), new Integer( get_offset() - 4 ) ) ;
  1401             // If the ORB is null, or if we're sure we're talking to
  1402             // a foreign ORB, Merlin, or something more recent, we
  1403             // use the updated end tag computation, and are more strenuous
  1404             // about the values.
  1405             if (orb == null ||
  1406                 ORBVersionFactory.getFOREIGN().equals(orb.getORBVersion()) ||
  1407                 ORBVersionFactory.getNEWER().compareTo(orb.getORBVersion()) <= 0) {
  1409                 // If the end tag we read was less than what we were expecting,
  1410                 // then the sender must think it's sent more enclosing
  1411                 // chunked valuetypes than we have.  Throw an exception.
  1412                 if (anEndTag < chunkedValueNestingLevel)
  1413                     throw wrapper.unexpectedEnclosingValuetype(
  1414                         CompletionStatus.COMPLETED_MAYBE, new Integer( anEndTag ),
  1415                         new Integer( chunkedValueNestingLevel ) ) ;
  1417                 // If the end tag is bigger than what we expected, but
  1418                 // still negative, then the sender has done some end tag
  1419                 // compaction.  We back up the stream 4 bytes so that the
  1420                 // next time readEndTag is called, it will get down here
  1421                 // again.  Even with fragmentation, we'll always be able
  1422                 // to do this.
  1423                 if (anEndTag != chunkedValueNestingLevel) {
  1424                     bbwi.position(bbwi.position() - 4);
  1427             } else {
  1429                 // When talking to Kestrel or Ladybird, we use our old
  1430                 // end tag rules and are less strict.  If the end tag
  1431                 // isn't what we expected, we back up, assuming
  1432                 // compaction.
  1433                 if (anEndTag != end_flag) {
  1434                     bbwi.position(bbwi.position() - 4);
  1438             // This only keeps track of the enclosing chunked
  1439             // valuetypes
  1440             chunkedValueNestingLevel++;
  1443         // This keeps track of all enclosing valuetypes
  1444         end_flag++;
  1447     protected int get_offset() {
  1448         return bbwi.position();
  1451     private void start_block() {
  1453         // if (outerValueDone)
  1454         if (!isChunked)
  1455             return;
  1457         // if called from alignAndCheck, need to reset blockLength
  1458         // to avoid an infinite recursion loop on read_long() call
  1459         blockLength = maxBlockLength;
  1461         blockLength = read_long();
  1463         // Must remember where we began the chunk to calculate how far
  1464         // along we are.  See notes above about chunkBeginPos.
  1466         if (blockLength > 0 && blockLength < maxBlockLength) {
  1467             blockLength += get_offset();  // _REVISIT_ unsafe, should use a Java long
  1469             // inBlock = true;
  1470         } else {
  1472             // System.out.println("start_block snooped a " + Integer.toHexString(blockLength));
  1474             // not a chunk length field
  1475             blockLength = maxBlockLength;
  1477             bbwi.position(bbwi.position() - 4);
  1481     // Makes sure that if we were reading a chunked value, we end up
  1482     // at the right place in the stream, no matter how little the
  1483     // unmarshalling code read.
  1484     //
  1485     // After calling this method, if we are chunking, we should be
  1486     // in position to read the end tag.
  1487     private void handleEndOfValue() {
  1489         // If we're not chunking, we don't have to worry about
  1490         // skipping remaining chunks or finding end tags
  1491         if (!isChunked)
  1492             return;
  1494         // Skip any remaining chunks
  1495         while (blockLength != maxBlockLength) {
  1496             end_block();
  1497             start_block();
  1500         // Now look for the end tag
  1502         // This is a little wasteful since we're reading
  1503         // this long up to 3 times in the worst cases (once
  1504         // in start_block, once here, and once in readEndTag
  1505         //
  1506         // Peek next long
  1507         int nextLong = read_long();
  1508         bbwi.position(bbwi.position() - 4);
  1510         // We did find an end tag, so we're done.  readEndTag
  1511         // should take care of making sure it's the correct
  1512         // end tag, etc.  Remember that since end tags,
  1513         // chunk lengths, and valuetags have non overlapping
  1514         // ranges, we can tell by the value what the longs are.
  1515         if (nextLong < 0)
  1516             return;
  1518         if (nextLong == 0 || nextLong >= maxBlockLength) {
  1520             // A custom marshaled valuetype left extra data
  1521             // on the wire, and that data had another
  1522             // nested value inside of it.  We've just
  1523             // read the value tag or null of that nested value.
  1524             //
  1525             // In an attempt to get by it, we'll try to call
  1526             // read_value() to get the nested value off of
  1527             // the wire.  Afterwards, we must call handleEndOfValue
  1528             // recursively to read any further chunks that the containing
  1529             // valuetype might still have after the nested
  1530             // value.
  1531             read_value();
  1532             handleEndOfValue();
  1533         } else {
  1534             // This probably means that the code to skip chunks has
  1535             // an error, and ended up setting blockLength to something
  1536             // other than maxBlockLength even though we weren't
  1537             // starting a new chunk.
  1538             throw wrapper.couldNotSkipBytes( CompletionStatus.COMPLETED_MAYBE,
  1539                 new Integer( nextLong ), new Integer( get_offset() ) ) ;
  1543     private void end_block() {
  1545         // if in a chunk, check for underflow or overflow
  1546         if (blockLength != maxBlockLength) {
  1547             if (blockLength == get_offset()) {
  1548                 // Chunk ended correctly
  1549                 blockLength = maxBlockLength;
  1550             } else {
  1551                 // Skip over anything left by bad unmarshaling code (ex:
  1552                 // a buggy custom unmarshaler).  See handleEndOfValue.
  1553                 if (blockLength > get_offset()) {
  1554                     skipToOffset(blockLength);
  1555                 } else {
  1556                     throw wrapper.badChunkLength( new Integer( blockLength ),
  1557                         new Integer( get_offset() ) ) ;
  1563     private int readValueTag(){
  1564         // outerValueDone = false;
  1565         return read_long();
  1568     public org.omg.CORBA.ORB orb() {
  1569         return orb;
  1572     // ------------ End RMI related methods --------------------------
  1574     public final void read_boolean_array(boolean[] value, int offset, int length) {
  1575         for(int i=0; i < length; i++) {
  1576             value[i+offset] = read_boolean();
  1580     public final void read_char_array(char[] value, int offset, int length) {
  1581         for(int i=0; i < length; i++) {
  1582             value[i+offset] = read_char();
  1586     public final void read_wchar_array(char[] value, int offset, int length) {
  1587         for(int i=0; i < length; i++) {
  1588             value[i+offset] = read_wchar();
  1592     public final void read_short_array(short[] value, int offset, int length) {
  1593         for(int i=0; i < length; i++) {
  1594             value[i+offset] = read_short();
  1598     public final void read_ushort_array(short[] value, int offset, int length) {
  1599         read_short_array(value, offset, length);
  1602     public final void read_long_array(int[] value, int offset, int length) {
  1603         for(int i=0; i < length; i++) {
  1604             value[i+offset] = read_long();
  1608     public final void read_ulong_array(int[] value, int offset, int length) {
  1609         read_long_array(value, offset, length);
  1612     public final void read_longlong_array(long[] value, int offset, int length) {
  1613         for(int i=0; i < length; i++) {
  1614             value[i+offset] = read_longlong();
  1618     public final void read_ulonglong_array(long[] value, int offset, int length) {
  1619         read_longlong_array(value, offset, length);
  1622     public final void read_float_array(float[] value, int offset, int length) {
  1623         for(int i=0; i < length; i++) {
  1624             value[i+offset] = read_float();
  1628     public final void read_double_array(double[] value, int offset, int length) {
  1629         for(int i=0; i < length; i++) {
  1630             value[i+offset] = read_double();
  1634     public final void read_any_array(org.omg.CORBA.Any[] value, int offset, int length) {
  1635         for(int i=0; i < length; i++) {
  1636             value[i+offset] = read_any();
  1640     //--------------------------------------------------------------------//
  1641     // CDRInputStream state management.
  1642     //
  1644     /**
  1645      * Are we at the end of the input stream?
  1646      */
  1647 //     public final boolean isAtEnd() {
  1648 //      return bbwi.position() == bbwi.buflen;
  1649 //     }
  1651 //     public int available() throws IOException {
  1652 //         return bbwi.buflen - bbwi.position();
  1653 //     }
  1655     private String read_repositoryIds() {
  1657         // Read # of repository ids
  1658         int numRepIds = read_long();
  1659         if (numRepIds == 0xffffffff) {
  1660             int indirection = read_long() + get_offset() - 4;
  1661             if (repositoryIdCache != null && repositoryIdCache.containsOrderedVal(indirection))
  1662                 return (String)repositoryIdCache.getKey(indirection);
  1663             else
  1664                 throw wrapper.unableToLocateRepIdArray( new Integer( indirection ) ) ;
  1665         } else {
  1667             // read first array element and store it as an indirection to the whole array
  1668             int indirection = get_offset();
  1669             String repID = read_repositoryId();
  1670             if (repositoryIdCache == null)
  1671                 repositoryIdCache = new CacheTable(orb,false);
  1672             repositoryIdCache.put(repID, indirection);
  1674             // read and ignore the subsequent array elements, but put them in the
  1675             // indirection table in case there are later indirections back to them
  1676             for (int i = 1; i < numRepIds; i++) {
  1677                 read_repositoryId();
  1680             return repID;
  1684     private final String read_repositoryId()
  1686         String result = readStringOrIndirection(true);
  1688         if (result == null) { // Indirection
  1689             int indirection = read_long() + get_offset() - 4;
  1691             if (repositoryIdCache != null && repositoryIdCache.containsOrderedVal(indirection))
  1692                 return (String)repositoryIdCache.getKey(indirection);
  1693             else
  1694                 throw wrapper.badRepIdIndirection( CompletionStatus.COMPLETED_MAYBE,
  1695                     new Integer(bbwi.position()) ) ;
  1696         } else {
  1697             if (repositoryIdCache == null)
  1698                 repositoryIdCache = new CacheTable(orb,false);
  1699             repositoryIdCache.put(result, stringIndirection);
  1702         return result ;
  1705     private final String read_codebase_URL()
  1707         String result = readStringOrIndirection(true);
  1709         if (result == null) { // Indirection
  1710             int indirection = read_long() + get_offset() - 4;
  1712             if (codebaseCache != null && codebaseCache.containsVal(indirection))
  1713                 return (String)codebaseCache.getKey(indirection);
  1714             else
  1715                 throw wrapper.badCodebaseIndirection(
  1716                     CompletionStatus.COMPLETED_MAYBE,
  1717                     new Integer(bbwi.position()) ) ;
  1718         } else {
  1719             if (codebaseCache == null)
  1720                 codebaseCache = new CacheTable(orb,false);
  1721             codebaseCache.put(result, stringIndirection);
  1724         return result;
  1727     /* DataInputStream methods */
  1729     public java.lang.Object read_Abstract () {
  1730         return read_abstract_interface();
  1733     public java.io.Serializable read_Value () {
  1734         return read_value();
  1737     public void read_any_array (org.omg.CORBA.AnySeqHolder seq, int offset, int length) {
  1738         read_any_array(seq.value, offset, length);
  1741     public void read_boolean_array (org.omg.CORBA.BooleanSeqHolder seq, int offset, int length) {
  1742         read_boolean_array(seq.value, offset, length);
  1745     public void read_char_array (org.omg.CORBA.CharSeqHolder seq, int offset, int length) {
  1746         read_char_array(seq.value, offset, length);
  1749     public void read_wchar_array (org.omg.CORBA.WCharSeqHolder seq, int offset, int length) {
  1750         read_wchar_array(seq.value, offset, length);
  1753     public void read_octet_array (org.omg.CORBA.OctetSeqHolder seq, int offset, int length) {
  1754         read_octet_array(seq.value, offset, length);
  1757     public void read_short_array (org.omg.CORBA.ShortSeqHolder seq, int offset, int length) {
  1758         read_short_array(seq.value, offset, length);
  1761     public void read_ushort_array (org.omg.CORBA.UShortSeqHolder seq, int offset, int length) {
  1762         read_ushort_array(seq.value, offset, length);
  1765     public void read_long_array (org.omg.CORBA.LongSeqHolder seq, int offset, int length) {
  1766         read_long_array(seq.value, offset, length);
  1769     public void read_ulong_array (org.omg.CORBA.ULongSeqHolder seq, int offset, int length) {
  1770         read_ulong_array(seq.value, offset, length);
  1773     public void read_ulonglong_array (org.omg.CORBA.ULongLongSeqHolder seq, int offset, int length) {
  1774         read_ulonglong_array(seq.value, offset, length);
  1777     public void read_longlong_array (org.omg.CORBA.LongLongSeqHolder seq, int offset, int length) {
  1778         read_longlong_array(seq.value, offset, length);
  1781     public void read_float_array (org.omg.CORBA.FloatSeqHolder seq, int offset, int length) {
  1782         read_float_array(seq.value, offset, length);
  1785     public void read_double_array (org.omg.CORBA.DoubleSeqHolder seq, int offset, int length) {
  1786         read_double_array(seq.value, offset, length);
  1789     public java.math.BigDecimal read_fixed(short digits, short scale) {
  1790         // digits isn't really needed here
  1791         StringBuffer buffer = read_fixed_buffer();
  1792         if (digits != buffer.length())
  1793             throw wrapper.badFixed( new Integer(digits),
  1794                 new Integer(buffer.length()) ) ;
  1795         buffer.insert(digits - scale, '.');
  1796         return new BigDecimal(buffer.toString());
  1799     // This method is unable to yield the correct scale.
  1800     public java.math.BigDecimal read_fixed() {
  1801         return new BigDecimal(read_fixed_buffer().toString());
  1804     // Each octet contains (up to) two decimal digits.
  1805     // If the fixed type has an odd number of decimal digits, then the representation
  1806     // begins with the first (most significant) digit.
  1807     // Otherwise, this first half-octet is all zero, and the first digit
  1808     // is in the second half-octet.
  1809     // The sign configuration, in the last half-octet of the representation,
  1810     // is 0xD for negative numbers and 0xC for positive and zero values.
  1811     private StringBuffer read_fixed_buffer() {
  1812         StringBuffer buffer = new StringBuffer(64);
  1813         byte doubleDigit;
  1814         int firstDigit;
  1815         int secondDigit;
  1816         boolean wroteFirstDigit = false;
  1817         boolean more = true;
  1818         while (more) {
  1819             doubleDigit = this.read_octet();
  1820             firstDigit = (int)((doubleDigit & 0xf0) >> 4);
  1821             secondDigit = (int)(doubleDigit & 0x0f);
  1822             if (wroteFirstDigit || firstDigit != 0) {
  1823                 buffer.append(Character.forDigit(firstDigit, 10));
  1824                 wroteFirstDigit = true;
  1826             if (secondDigit == 12) {
  1827                 // positive number or zero
  1828                 if ( ! wroteFirstDigit) {
  1829                     // zero
  1830                     return new StringBuffer("0.0");
  1831                 } else {
  1832                     // positive number
  1833                     // done
  1835                 more = false;
  1836             } else if (secondDigit == 13) {
  1837                 // negative number
  1838                 buffer.insert(0, '-');
  1839                 more = false;
  1840             } else {
  1841                 buffer.append(Character.forDigit(secondDigit, 10));
  1842                 wroteFirstDigit = true;
  1845         return buffer;
  1848     private final static String _id = "IDL:omg.org/CORBA/DataInputStream:1.0";
  1849     private final static String[] _ids = { _id };
  1851     public String[] _truncatable_ids() {
  1852         if (_ids == null)
  1853             return null;
  1855         return (String[])_ids.clone();
  1858     /* for debugging */
  1860     public void printBuffer() {
  1861         CDRInputStream_1_0.printBuffer(this.bbwi);
  1864     public static void printBuffer(ByteBufferWithInfo bbwi) {
  1866         System.out.println("----- Input Buffer -----");
  1867         System.out.println();
  1868         System.out.println("Current position: " + bbwi.position());
  1869         System.out.println("Total length : " + bbwi.buflen);
  1870         System.out.println();
  1872         try {
  1874             char[] charBuf = new char[16];
  1876             for (int i = 0; i < bbwi.buflen; i += 16) {
  1878                 int j = 0;
  1880                 // For every 16 bytes, there is one line
  1881                 // of output.  First, the hex output of
  1882                 // the 16 bytes with each byte separated
  1883                 // by a space.
  1884                 while (j < 16 && j + i < bbwi.buflen) {
  1885                     int k = bbwi.byteBuffer.get(i + j);
  1886                     if (k < 0)
  1887                         k = 256 + k;
  1888                     String hex = Integer.toHexString(k);
  1889                     if (hex.length() == 1)
  1890                         hex = "0" + hex;
  1891                     System.out.print(hex + " ");
  1892                     j++;
  1895                 // Add any extra spaces to align the
  1896                 // text column in case we didn't end
  1897                 // at 16
  1898                 while (j < 16) {
  1899                     System.out.print("   ");
  1900                     j++;
  1903                 // Now output the ASCII equivalents.  Non-ASCII
  1904                 // characters are shown as periods.
  1905                 int x = 0;
  1906                 while (x < 16 && x + i < bbwi.buflen) {
  1907                     if (ORBUtility.isPrintable((char)bbwi.byteBuffer.get(i + x)))
  1908                         charBuf[x] = (char)bbwi.byteBuffer.get(i + x);
  1909                     else
  1910                         charBuf[x] = '.';
  1911                     x++;
  1913                 System.out.println(new String(charBuf, 0, x));
  1916         } catch (Throwable t) {
  1917             t.printStackTrace();
  1920         System.out.println("------------------------");
  1923     public ByteBuffer getByteBuffer() {
  1924         ByteBuffer result = null;
  1925         if (bbwi != null) {
  1926             result = bbwi.byteBuffer;
  1928         return result;
  1931     public int getBufferLength() {
  1932         return bbwi.buflen;
  1935     public void setBufferLength(int value) {
  1936         bbwi.buflen = value;
  1937         bbwi.byteBuffer.limit(bbwi.buflen);
  1940     public void setByteBufferWithInfo(ByteBufferWithInfo bbwi) {
  1941         this.bbwi = bbwi;
  1944     public void setByteBuffer(ByteBuffer byteBuffer) {
  1945         bbwi.byteBuffer = byteBuffer;
  1948     public int getIndex() {
  1949         return bbwi.position();
  1952     public void setIndex(int value) {
  1953         bbwi.position(value);
  1956     public boolean isLittleEndian() {
  1957         return littleEndian;
  1960     public void orb(org.omg.CORBA.ORB orb) {
  1961         this.orb = (ORB)orb;
  1964     public BufferManagerRead getBufferManager() {
  1965         return bufferManagerRead;
  1968     private void skipToOffset(int offset) {
  1970         // Number of bytes to skip
  1971         int len = offset - get_offset();
  1973         int n = 0;
  1975         while (n < len) {
  1976             int avail;
  1977             int bytes;
  1978             int wanted;
  1980             avail = bbwi.buflen - bbwi.position();
  1981             if (avail <= 0) {
  1982                 grow(1, 1);
  1983                 avail = bbwi.buflen - bbwi.position();
  1986             wanted = len - n;
  1987             bytes = (wanted < avail) ? wanted : avail;
  1988             bbwi.position(bbwi.position() + bytes);
  1989             n += bytes;
  1994     // Mark and reset -------------------------------------------------
  1996     protected MarkAndResetHandler markAndResetHandler = null;
  1998     protected class StreamMemento
  2000         // These are the fields that may change after marking
  2001         // the stream position, so we need to save them.
  2002         private int blockLength_;
  2003         private int end_flag_;
  2004         private int chunkedValueNestingLevel_;
  2005         private int valueIndirection_;
  2006         private int stringIndirection_;
  2007         private boolean isChunked_;
  2008         private javax.rmi.CORBA.ValueHandler valueHandler_;
  2009         private ByteBufferWithInfo bbwi_;
  2010         private boolean specialNoOptionalDataState_;
  2012         public StreamMemento()
  2014             blockLength_ = blockLength;
  2015             end_flag_ = end_flag;
  2016             chunkedValueNestingLevel_ = chunkedValueNestingLevel;
  2017             valueIndirection_ = valueIndirection;
  2018             stringIndirection_ = stringIndirection;
  2019             isChunked_ = isChunked;
  2020             valueHandler_ = valueHandler;
  2021             specialNoOptionalDataState_ = specialNoOptionalDataState;
  2022             bbwi_ = new ByteBufferWithInfo(bbwi);
  2026     public java.lang.Object createStreamMemento() {
  2027         return new StreamMemento();
  2030     public void restoreInternalState(java.lang.Object streamMemento) {
  2032         StreamMemento mem = (StreamMemento)streamMemento;
  2034         blockLength = mem.blockLength_;
  2035         end_flag = mem.end_flag_;
  2036         chunkedValueNestingLevel = mem.chunkedValueNestingLevel_;
  2037         valueIndirection = mem.valueIndirection_;
  2038         stringIndirection = mem.stringIndirection_;
  2039         isChunked = mem.isChunked_;
  2040         valueHandler = mem.valueHandler_;
  2041         specialNoOptionalDataState = mem.specialNoOptionalDataState_;
  2042         bbwi = mem.bbwi_;
  2045     public int getPosition() {
  2046         return get_offset();
  2049     public void mark(int readlimit) {
  2050         markAndResetHandler.mark(this);
  2053     public void reset() {
  2054         markAndResetHandler.reset();
  2057     // ---------------------------------- end Mark and Reset
  2059     // Provides a hook so subclasses of CDRInputStream can provide
  2060     // a CodeBase.  This ultimately allows us to grab a Connection
  2061     // instance in IIOPInputStream, the only subclass where this
  2062     // is actually used.
  2063     CodeBase getCodeBase() {
  2064         return parent.getCodeBase();
  2067     /**
  2068      * Attempts to find the class described by the given
  2069      * repository ID string and expected type.  The first
  2070      * attempt is to find the class locally, falling back
  2071      * on the URL that came with the value.  The second
  2072      * attempt is to use a URL from the remote CodeBase.
  2073      */
  2074     private Class getClassFromString(String repositoryIDString,
  2075                                      String codebaseURL,
  2076                                      Class expectedType)
  2078         RepositoryIdInterface repositoryID
  2079             = repIdStrs.getFromString(repositoryIDString);
  2081         try {
  2082             try {
  2083                 // First try to load the class locally, then use
  2084                 // the provided URL (if it isn't null)
  2085                 return repositoryID.getClassFromType(expectedType,
  2086                                                      codebaseURL);
  2087             } catch (ClassNotFoundException cnfeOuter) {
  2089                 try {
  2091                     if (getCodeBase() == null) {
  2092                         return null; // class cannot be loaded remotely.
  2095                     // Get a URL from the remote CodeBase and retry
  2096                     codebaseURL = getCodeBase().implementation(repositoryIDString);
  2098                     // Don't bother trying to find it locally again if
  2099                     // we got a null URL
  2100                     if (codebaseURL == null)
  2101                         return null;
  2103                     return repositoryID.getClassFromType(expectedType,
  2104                                                          codebaseURL);
  2105                 } catch (ClassNotFoundException cnfeInner) {
  2106                     dprintThrowable(cnfeInner);
  2107                     // Failed to load the class
  2108                     return null;
  2111         } catch (MalformedURLException mue) {
  2112             // Always report a bad URL
  2113             throw wrapper.malformedUrl( CompletionStatus.COMPLETED_MAYBE,
  2114                 mue, repositoryIDString, codebaseURL ) ;
  2118     /**
  2119      * Attempts to find the class described by the given
  2120      * repository ID string.  At most, three attempts are made:
  2121      * Try to find it locally, through the provided URL, and
  2122      * finally, via a URL from the remote CodeBase.
  2123      */
  2124     private Class getClassFromString(String repositoryIDString,
  2125                                      String codebaseURL)
  2127         RepositoryIdInterface repositoryID
  2128             = repIdStrs.getFromString(repositoryIDString);
  2130         for (int i = 0; i < 3; i++) {
  2132             try {
  2134                 switch (i)
  2136                     case 0:
  2137                         // First try to load the class locally
  2138                         return repositoryID.getClassFromType();
  2139                     case 1:
  2140                         // Try to load the class using the provided
  2141                         // codebase URL (falls out below)
  2142                         break;
  2143                     case 2:
  2144                         // Try to load the class using a URL from the
  2145                         // remote CodeBase
  2146                         codebaseURL = getCodeBase().implementation(repositoryIDString);
  2147                         break;
  2150                 // Don't bother if the codebaseURL is null
  2151                 if (codebaseURL == null)
  2152                     continue;
  2154                 return repositoryID.getClassFromType(codebaseURL);
  2156             } catch(ClassNotFoundException cnfe) {
  2157                 // Will ultimately return null if all three
  2158                 // attempts fail, but don't do anything here.
  2159             } catch (MalformedURLException mue) {
  2160                 throw wrapper.malformedUrl( CompletionStatus.COMPLETED_MAYBE,
  2161                     mue, repositoryIDString, codebaseURL ) ;
  2165         // If we get here, we have failed to load the class
  2166         dprint("getClassFromString failed with rep id "
  2167                + repositoryIDString
  2168                + " and codebase "
  2169                + codebaseURL);
  2171         return null;
  2174     // Utility method used to get chars from bytes
  2175     char[] getConvertedChars(int numBytes,
  2176                              CodeSetConversion.BTCConverter converter) {
  2178         // REVISIT - Look at CodeSetConversion.BTCConverter to see
  2179         //           if it can work with an NIO ByteBuffer. We should
  2180         //           avoid getting the bytes into an array if possible.
  2182         // To be honest, I doubt this saves much real time
  2183         if (bbwi.buflen - bbwi.position() >= numBytes) {
  2184             // If the entire string is in this buffer,
  2185             // just convert directly from the bbwi rather than
  2186             // allocating and copying.
  2187             byte[] tmpBuf;
  2188             if (bbwi.byteBuffer.hasArray())
  2190                 tmpBuf = bbwi.byteBuffer.array();
  2192             else
  2194                  tmpBuf = new byte[bbwi.buflen];
  2195                  // Microbenchmarks are showing a loop of ByteBuffer.get(int)
  2196                  // being faster than ByteBuffer.get(byte[], int, int).
  2197                  for (int i = 0; i < bbwi.buflen; i++)
  2198                      tmpBuf[i] = bbwi.byteBuffer.get(i);
  2200             char[] result = converter.getChars(tmpBuf,bbwi.position(),numBytes);
  2202             bbwi.position(bbwi.position() + numBytes);
  2203             return result;
  2204         } else {
  2205             // Stretches across buffers.  Unless we provide an
  2206             // incremental conversion interface, allocate and
  2207             // copy the bytes.
  2208             byte[] bytes = new byte[numBytes];
  2209             read_octet_array(bytes, 0, bytes.length);
  2211             return converter.getChars(bytes, 0, numBytes);
  2215     protected CodeSetConversion.BTCConverter getCharConverter() {
  2216         if (charConverter == null)
  2217             charConverter = parent.createCharBTCConverter();
  2219         return charConverter;
  2222     protected CodeSetConversion.BTCConverter getWCharConverter() {
  2223         if (wcharConverter == null)
  2224             wcharConverter = parent.createWCharBTCConverter();
  2226         return wcharConverter;
  2229     protected void dprintThrowable(Throwable t) {
  2230         if (debug && t != null)
  2231             t.printStackTrace();
  2234     protected void dprint(String msg) {
  2235         if (debug) {
  2236             ORBUtility.dprint(this, msg);
  2240     /**
  2241      * Aligns the current position on the given octet boundary
  2242      * if there are enough bytes available to do so.  Otherwise,
  2243      * it just returns.  This is used for some (but not all)
  2244      * GIOP 1.2 message headers.
  2245      */
  2247     void alignOnBoundary(int octetBoundary) {
  2248         int needed = computeAlignment(bbwi.position(), octetBoundary);
  2250         if (bbwi.position() + needed <= bbwi.buflen)
  2252             bbwi.position(bbwi.position() + needed);
  2256     public void resetCodeSetConverters() {
  2257         charConverter = null;
  2258         wcharConverter = null;
  2261     public void start_value() {
  2262         // Read value tag
  2263         int vType = readValueTag();
  2265         if (vType == 0) {
  2266             // Stream needs to go into a state where it
  2267             // throws standard exception until end_value
  2268             // is called.  This means the sender didn't
  2269             // send any custom data.  If the reader here
  2270             // tries to read more, we need to throw an
  2271             // exception before reading beyond where
  2272             // we're supposed to
  2273             specialNoOptionalDataState = true;
  2275             return;
  2278         if (vType == 0xffffffff) {
  2279             // One should never indirect to a custom wrapper
  2280             throw wrapper.customWrapperIndirection(
  2281                 CompletionStatus.COMPLETED_MAYBE);
  2284         if (repIdUtil.isCodeBasePresent(vType)) {
  2285             throw wrapper.customWrapperWithCodebase(
  2286                 CompletionStatus.COMPLETED_MAYBE);
  2289         if (repIdUtil.getTypeInfo(vType)
  2290             != RepositoryIdUtility.SINGLE_REP_TYPE_INFO) {
  2291             throw wrapper.customWrapperNotSingleRepid(
  2292                 CompletionStatus.COMPLETED_MAYBE);
  2296         // REVISIT - Could verify repository ID even though
  2297         // it isn't used elsewhere
  2298         read_repositoryId();
  2300         // Note: isChunked should be true here.  Should have
  2301         // been set to true in the containing value's read_value
  2302         // method.
  2304         start_block();
  2305         end_flag--;
  2306         chunkedValueNestingLevel--;
  2309     public void end_value() {
  2311         if (specialNoOptionalDataState) {
  2312             specialNoOptionalDataState = false;
  2313             return;
  2316         handleEndOfValue();
  2317         readEndTag();
  2319         // Note that isChunked should still be true here.
  2320         // If the containing valuetype is the highest
  2321         // chunked value, it will get set to false
  2322         // at the end of read_value.
  2324         // allow for possible continuation chunk
  2325         start_block();
  2328     public void close() throws IOException
  2331         // tell BufferManagerRead to release any ByteBuffers
  2332         getBufferManager().close(bbwi);
  2334         // It's possible bbwi.byteBuffer is shared between
  2335         // this InputStream and an OutputStream. Thus, we check
  2336         // if the Input/Output streams are using the same ByteBuffer.
  2337         // If they sharing the same ByteBuffer we need to ensure only
  2338         // one of those ByteBuffers are released to the ByteBufferPool.
  2340         if (bbwi != null && getByteBuffer() != null)
  2342             MessageMediator messageMediator = parent.getMessageMediator();
  2343             if (messageMediator != null)
  2345                 CDROutputObject outputObj =
  2346                              (CDROutputObject)messageMediator.getOutputObject();
  2347                 if (outputObj != null)
  2349                     if (outputObj.isSharing(getByteBuffer()))
  2351                         // Set OutputStream's ByteBuffer and bbwi to null
  2352                         // so its ByteBuffer cannot be released to the pool
  2353                         outputObj.setByteBuffer(null);
  2354                         outputObj.setByteBufferWithInfo(null);
  2359             // release this stream's ByteBuffer to the pool
  2360             ByteBufferPool byteBufferPool = orb.getByteBufferPool();
  2361             if (debug)
  2363                 // print address of ByteBuffer being released
  2364                 int bbAddress = System.identityHashCode(bbwi.byteBuffer);
  2365                 StringBuffer sb = new StringBuffer(80);
  2366                 sb.append(".close - releasing ByteBuffer id (");
  2367                 sb.append(bbAddress).append(") to ByteBufferPool.");
  2368                 String msg = sb.toString();
  2369                 dprint(msg);
  2371             byteBufferPool.releaseByteBuffer(bbwi.byteBuffer);
  2372             bbwi.byteBuffer = null;
  2373             bbwi = null;

mercurial