0001: package org.jacorb.orb;
0002:
0003: /*
0004: * JacORB - a free Java ORB
0005: *
0006: * Copyright (C) 1997-2004 Gerald Brose.
0007: *
0008: * This library is free software; you can redistribute it and/or
0009: * modify it under the terms of the GNU Library General Public
0010: * License as published by the Free Software Foundation; either
0011: * version 2 of the License, or (at your option) any later version.
0012: *
0013: * This library is distributed in the hope that it will be useful,
0014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0016: * Library General Public License for more details.
0017: *
0018: * You should have received a copy of the GNU Library General Public
0019: * License along with this library; if not, write to the Free
0020: * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
0021: */
0022:
0023: import java.io.IOException;
0024: import java.io.Serializable;
0025: import java.math.BigDecimal;
0026: import java.util.*;
0027:
0028: import org.apache.avalon.framework.configuration.*;
0029: import org.apache.avalon.framework.logger.*;
0030:
0031: import org.jacorb.orb.giop.CodeSet;
0032: import org.jacorb.orb.giop.GIOPConnection;
0033: import org.jacorb.util.ObjectUtil;
0034: import org.jacorb.util.Stack;
0035: import org.jacorb.util.ValueHandler;
0036:
0037: import org.omg.CORBA.BAD_PARAM;
0038: import org.omg.CORBA.INTERNAL;
0039: import org.omg.CORBA.MARSHAL;
0040: import org.omg.CORBA.NO_IMPLEMENT;
0041: import org.omg.CORBA.StructMember;
0042: import org.omg.CORBA.TCKind;
0043: import org.omg.CORBA.UnionMember;
0044: import org.omg.CORBA.ValueMember;
0045: import org.omg.CORBA.portable.IDLEntity;
0046: import org.omg.CORBA.TypeCodePackage.BadKind;
0047: import org.omg.CORBA.TypeCodePackage.Bounds;
0048:
0049: /**
0050: * Read CDR encoded data
0051: *
0052: * @author Gerald Brose, FU Berlin
0053: * $Id: CDRInputStream.java,v 1.114 2007/01/08 12:18:45 alphonse.bendt Exp $
0054: */
0055:
0056: public class CDRInputStream extends
0057: org.omg.CORBA_2_3.portable.InputStream {
0058: /**
0059: * <code>encaps_stack</code> is used to saving/restoring
0060: * encapsulation information.
0061: */
0062: private Stack encaps_stack;
0063:
0064: /**
0065: * This Map is basically a one-entry map pool to be used in
0066: * read_TypeCode() as the repeatedTCMap.
0067: */
0068: private Map repeatedTCMap;
0069:
0070: /**
0071: * <code>cachedTypecodes</code> stores a mapping of ID/Typecode to
0072: * speed reading from the stream. Do NOT access this variable directly. It
0073: * is initialized on demand. Use the methods
0074: * {@link #getCachedTypecode(Object id)} and
0075: * {@link #putCachedTypecode(Object id, Pair result)}
0076: * Skip amount is
0077: * skip (size - ((pos - start_pos) - 4 - 4));
0078: * EncapsulationSize -
0079: * ( PositionAfterReadingId - start_pos
0080: * - 4 [Size] - 4 [KindSize] ) = RemainingSizeToSkip
0081: */
0082: private Map cachedTypecodes;
0083:
0084: /** indexes to support mark/reset */
0085: private int marked_pos;
0086: private int marked_index;
0087:
0088: private boolean closed;
0089:
0090: /** configurable properties */
0091: private Logger logger;
0092: private boolean cometInteropFix;
0093: private boolean laxBooleanEncoding;
0094: private boolean cacheTypecodes;
0095:
0096: /* character encoding code sets for char and wchar, default ISO8859_1 */
0097: private int codeSet = CodeSet.getTCSDefault();
0098: private int codeSetW = CodeSet.getTCSWDefault();
0099: protected int giop_minor = 2; // needed to determine size in chars
0100:
0101: /**
0102: * <code>valueMap</code> maps indices within the buffer
0103: * (java.lang.Integer) to the values that appear at these indices. Do
0104: * NOT access this variable directly. It is initialized on demand.
0105: * Use the method {@link #getValueMap()}
0106: */
0107: private Map valueMap;
0108:
0109: /**
0110: * Index of the current IDL value that is being unmarshalled.
0111: * This is kept here so that when the value object has been
0112: * created, the value factory can immediately store it into this
0113: * stream's valueMap by calling `register_value()'.
0114: */
0115: private int currentValueIndex;
0116:
0117: /**
0118: * <code>repIdMap</code> maps indices within the buffer
0119: * (java.lang.Integer) to repository ids that appear at these indices.
0120: * Do NOT access this variable directly. It is initialized on demand.
0121: * Use the method {@link #getRepIdMap()}
0122: */
0123: private Map repIdMap;
0124:
0125: /**
0126: * <code>codebaseMap</code> maps indices within the buffer
0127: * (java.lang.Integer) to codebase strings that appear at these indices.
0128: * Do NOT access this variable directly. It is initialized on demand.
0129: * Use the method {@link #getCodebaseMap()}
0130: */
0131: private Map codebaseMap;
0132:
0133: public boolean littleEndian = false;
0134:
0135: /** indices into the actual buffer */
0136: protected byte[] buffer = null;
0137: protected int pos = 0;
0138: protected int index = 0;
0139:
0140: /** Last value tag read had the chunking bit on */
0141: private boolean chunkedValue = false;
0142:
0143: /** Nesting level of chunked valuetypes */
0144: private int valueNestingLevel = 0;
0145:
0146: /** Ending position of the current chunk */
0147: private int chunk_end_pos = -1; // -1 means we're not within a chunk
0148:
0149: /**
0150: * <code>mutator</code> is a pluggable IOR mutator.
0151: */
0152: private IORMutator mutator;
0153:
0154: private boolean isMutatorEnabled;
0155:
0156: /**
0157: * <code>codesetEnabled</code> denotes whether codeset marshalling is enabled.
0158: */
0159: private boolean codesetEnabled;
0160:
0161: /**
0162: * for this stream to be able to return a live object reference, a
0163: * full ORB (not the Singleton!) must be known. If this stream is
0164: * used only to demarshal base type data, the Singleton is enough
0165: */
0166: private final org.omg.CORBA.ORB orb;
0167:
0168: /**
0169: * this is the lowest possible value_tag indicating the
0170: * begin of a valuetype (15.3.4)
0171: */
0172: private static final int MAX_BLOCK_SIZE = 0x7fffff00;
0173:
0174: /**
0175: * fixes RMI/IIOP related interoperability issues with the
0176: * sun the orb that occured
0177: * while receiving serialized collections.
0178: * see mailing list for details:
0179: * {@link http://lists.spline.inf.fu-berlin.de/mailman/htdig/jacorb-developer/2006-May/008251.html}
0180: */
0181: private boolean sunInteropFix;
0182:
0183: private Map tcMap;
0184:
0185: public CDRInputStream(final org.omg.CORBA.ORB orb, final byte[] buf) {
0186: super ();
0187:
0188: buffer = buf;
0189: // orb may be null!
0190: if (orb != null) {
0191: this .orb = orb;
0192: // orb may be the singleton!
0193: if (orb instanceof org.jacorb.orb.ORB) {
0194: try {
0195:
0196: configure(((org.jacorb.orb.ORB) orb)
0197: .getConfiguration());
0198: } catch (ConfigurationException ce) {
0199: throw new INTERNAL("ConfigurationException: " + ce);
0200: }
0201: }
0202: } else {
0203: this .orb = org.omg.CORBA.ORB.init();
0204: }
0205: }
0206:
0207: public CDRInputStream(final org.omg.CORBA.ORB orb,
0208: final byte[] buf, final boolean littleEndian) {
0209: this (orb, buf);
0210: this .littleEndian = littleEndian;
0211: }
0212:
0213: public CDRInputStream(byte[] buffer, boolean littleEndian) {
0214: this (null, buffer, littleEndian);
0215: }
0216:
0217: /**
0218: * This stream is self-configuring, i.e. configure() is private
0219: * and only called from the constructors.
0220: */
0221:
0222: private void configure(Configuration configuration)
0223: throws ConfigurationException {
0224: final org.jacorb.config.Configuration jacorbConfig = (org.jacorb.config.Configuration) configuration;
0225: logger = jacorbConfig.getNamedLogger("jacorb.orb.cdr");
0226:
0227: codesetEnabled = configuration.getAttribute("jacorb.codeset",
0228: "on").equals("on");
0229: cometInteropFix = configuration.getAttribute(
0230: "jacorb.interop.comet", "off").equals("on");
0231: laxBooleanEncoding = configuration.getAttribute(
0232: "jacorb.interop.lax_boolean_encoding", "off").equals(
0233: "on");
0234: cacheTypecodes = configuration.getAttribute(
0235: "jacorb.cacheTypecodes", "off").equals("on");
0236: sunInteropFix = configuration.getAttribute(
0237: "jacorb.interop.sun", "off").equalsIgnoreCase("on");
0238: isMutatorEnabled = configuration.getAttribute(
0239: "jacorb.iormutator", "").length() > 0;
0240:
0241: if (isMutatorEnabled) {
0242: mutator = (IORMutator) jacorbConfig
0243: .getAttributeAsObject("jacorb.iormutator");
0244: }
0245: }
0246:
0247: /**
0248: * Gets the Map that is used to demarshal shared valuetype instances.
0249: *
0250: * @return a <code>Map</code> value
0251: */
0252: private Map getValueMap() {
0253: if (valueMap == null) {
0254: // Unlike the valueMap in CDROutputStream, this one
0255: // does need to be an equality-based HashMap.
0256: valueMap = new HashMap();
0257: }
0258: return valueMap;
0259: }
0260:
0261: /**
0262: * Gets the Map that is used to implement indirections for RepositoryIDs.
0263: *
0264: * @return a <code>Map</code> value
0265: */
0266: private Map getRepIdMap() {
0267: if (repIdMap == null) {
0268: repIdMap = new HashMap();
0269: }
0270: return repIdMap;
0271: }
0272:
0273: /**
0274: * Gets the Map that is used to implement sharing for codebase
0275: * specifications.
0276: *
0277: * @return a <code>Map</code> value
0278: */
0279: private Map getCodebaseMap() {
0280: if (codebaseMap == null) {
0281: codebaseMap = new HashMap();
0282: }
0283: return codebaseMap;
0284: }
0285:
0286: /**
0287: * <code>getCachedTypecode</code> to retrieve a value from cachedTypecodes.
0288: * It may initialize the value on demand.
0289: *
0290: * @param id a <code>Object</code> value, can be String (id) or actual TypeCode
0291: * for sequence/array tcs
0292: * @return a <code>org.omg.CORBA.TypeCode</code> value, possibly null.
0293: */
0294: private Pair getCachedTypecode(Object id) {
0295: final Pair result;
0296:
0297: if (cacheTypecodes) {
0298: if (cachedTypecodes == null) {
0299: cachedTypecodes = new HashMap();
0300: result = null;
0301: } else {
0302: result = (Pair) cachedTypecodes.get(id);
0303: }
0304: } else {
0305: result = null;
0306: }
0307: return result;
0308: }
0309:
0310: /**
0311: * <code>putCachedTypecode</code> is used to store typecodes within the
0312: * cachedTypecodes. It will only do it cacheTypecodes is on.
0313: *
0314: * @param id a <code>String</code> or <code>TypeCode</code> value
0315: * @param result an Pair value
0316: */
0317: private void putCachedTypecode(Object id, Pair result) {
0318: if (cacheTypecodes) {
0319: // By definition get/put should be paired so cachedTypecodes should
0320: // never be null here.
0321: cachedTypecodes.put(id, result);
0322: }
0323: }
0324:
0325: public void setGIOPMinor(final int giop_minor) {
0326: this .giop_minor = giop_minor;
0327: }
0328:
0329: public int getGIOPMinor() {
0330: return giop_minor;
0331: }
0332:
0333: public void close() {
0334: // Don't need to call super.close as super is noop.
0335:
0336: if (closed) {
0337: return;
0338: }
0339:
0340: // commented out as this caused test failures.
0341: // as the buffer has been passed into this CDRInputStream
0342: // we cannot assume ownership of the buffer here (alphonse).
0343: // BufferManager.getInstance().returnBuffer(buffer);
0344:
0345: buffer = null;
0346: encaps_stack = null;
0347: closed = true;
0348:
0349: if (tcMap != null) {
0350: tcMap.clear();
0351: }
0352: }
0353:
0354: public org.omg.CORBA.ORB orb() {
0355: return orb;
0356: }
0357:
0358: public void setCodeSet(final int codeSet, final int codeSetWide) {
0359: this .codeSet = codeSet;
0360: this .codeSetW = codeSetWide;
0361: }
0362:
0363: private static final int _read4int(final boolean _littleEndian,
0364: final byte[] _buffer, final int _pos) {
0365: if (_littleEndian) {
0366: return (((_buffer[_pos + 3] & 0xff) << 24)
0367: + ((_buffer[_pos + 2] & 0xff) << 16)
0368: + ((_buffer[_pos + 1] & 0xff) << 8) + ((_buffer[_pos] & 0xff) << 0));
0369: }
0370: return (((_buffer[_pos] & 0xff) << 24)
0371: + ((_buffer[_pos + 1] & 0xff) << 16)
0372: + ((_buffer[_pos + 2] & 0xff) << 8) + ((_buffer[_pos + 3] & 0xff) << 0));
0373: }
0374:
0375: private static final short _read2int(final boolean _littleEndian,
0376: final byte[] _buffer, final int _pos) {
0377: if (_littleEndian) {
0378: return (short) (((_buffer[_pos + 1] & 0xff) << 8) + ((_buffer[_pos] & 0xff) << 0));
0379: }
0380: return (short) (((_buffer[_pos] & 0xff) << 8) + ((_buffer[_pos + 1] & 0xff) << 0));
0381: }
0382:
0383: private final int _read_long() {
0384: int result;
0385:
0386: result = _read4int(littleEndian, buffer, pos);
0387:
0388: index += 4;
0389: pos += 4;
0390: return result;
0391: }
0392:
0393: private final long _read_longlong() {
0394: if (littleEndian) {
0395: return (_read_long() & 0xFFFFFFFFL)
0396: + ((long) _read_long() << 32);
0397: }
0398:
0399: return ((long) _read_long() << 32)
0400: + (_read_long() & 0xFFFFFFFFL);
0401: }
0402:
0403: private final void handle_chunking() {
0404: int remainder = 4 - (index % 4);
0405: int aligned_pos = (remainder != 4) ? pos + remainder : pos;
0406:
0407: if (chunk_end_pos >= pos && chunk_end_pos <= aligned_pos) {
0408: chunk_end_pos = -1;
0409: int saved_pos = pos;
0410: int saved_index = index;
0411: int tag = read_long();
0412:
0413: if (tag < 0) {
0414:
0415: // tag is an end tag
0416:
0417: if (!(-tag <= valueNestingLevel)) {
0418: throw new INTERNAL("received end tag " + tag
0419: + " with value nesting level "
0420: + valueNestingLevel);
0421: }
0422: valueNestingLevel = -tag;
0423: valueNestingLevel--;
0424:
0425: if (valueNestingLevel > 0) {
0426: chunk_end_pos = pos;
0427: handle_chunking();
0428: }
0429: } else if (tag < 0x7fffff00) {
0430: // tag is the chunk size tag of another chunk
0431:
0432: chunk_end_pos = pos + tag;
0433: } else // (tag >= 0x7fffff00)
0434: {
0435: // tag is the value tag of a nested value
0436:
0437: pos = saved_pos; // "unread" the value tag
0438: index = saved_index;
0439: }
0440: }
0441: }
0442:
0443: protected final void skip(final int distance) {
0444: pos += distance;
0445: index += distance;
0446: }
0447:
0448: /**
0449: * close a CDR encapsulation and
0450: * restore index and byte order information
0451: */
0452:
0453: public final void closeEncapsulation() {
0454: if (encaps_stack == null) {
0455: throw new MARSHAL(
0456: "Internal Error - closeEncapsulation failed");
0457: }
0458:
0459: EncapsInfo ei = (EncapsInfo) encaps_stack.pop();
0460: littleEndian = ei.littleEndian;
0461: int size = ei.size;
0462: int start = ei.start;
0463:
0464: if (pos < start + size) {
0465: pos = start + size;
0466: }
0467:
0468: index = ei.index + size;
0469: }
0470:
0471: /**
0472: * open a CDR encapsulation and
0473: * restore index and byte order information
0474: */
0475:
0476: public final int openEncapsulation() {
0477: boolean old_endian = littleEndian;
0478: int size = read_long();
0479:
0480: // Check if size looks sane. If not try changing byte order.
0481: // This is a specific fix for interoperability with the Iona
0482: // Comet COM/CORBA bridge that has problems with size marshalling.
0483:
0484: if (cometInteropFix && ((size < 0) || (size > buffer.length))) {
0485: int temp = (((size >> 24) & 0x000000FF)
0486: + ((size >> 8) & 0x0000FF00)
0487: + ((size << 8) & 0x00FF0000) + ((size << 24) & 0xFF000000));
0488:
0489: if (logger.isDebugEnabled()) {
0490: logger
0491: .debug("Size of CDR encapsulation larger than buffer, swapping byte order\n"
0492: + "Size of CDR encapsulation was "
0493: + size + ", is now " + temp);
0494: }
0495:
0496: size = temp;
0497: }
0498: /* save current index plus size of the encapsulation on the stack.
0499: When the encapsulation is closed, this value will be restored as
0500: index */
0501:
0502: if (encaps_stack == null) {
0503: encaps_stack = new Stack();
0504: }
0505: encaps_stack.push(new EncapsInfo(old_endian, index, pos, size));
0506:
0507: openEncapsulatedArray();
0508:
0509: return size;
0510: }
0511:
0512: public final void openEncapsulatedArray() {
0513: /* reset index to zero, i.e. align relative to the beginning
0514: of the encaps. */
0515: resetIndex();
0516: littleEndian = read_boolean();
0517: }
0518:
0519: /*
0520: * Return a copy of the current buffer.
0521: *
0522: * @return a <code>byte[]</code> value.
0523: */
0524: public byte[] getBufferCopy() {
0525: byte[] result = new byte[buffer.length];
0526: System.arraycopy(buffer, 0, result, 0, buffer.length);
0527: return result;
0528: }
0529:
0530: /**
0531: * Reads the next byte of data from the input stream. The value byte is
0532: * returned as an <code>int</code> in the range <code>0</code> to
0533: * <code>255</code>. If no byte is available because the end of the stream
0534: * has been reached, the value <code>-1</code> is returned.
0535: * @return the next byte of data, or <code>-1</code> if the end of the
0536: * stream is reached.
0537: * @throws java.io.IOException if stream is closed.
0538: */
0539: public int read() throws java.io.IOException {
0540: if (closed) {
0541: throw new java.io.IOException("Stream already closed!");
0542: }
0543:
0544: if (available() < 1) {
0545: return -1;
0546: }
0547:
0548: ++index;
0549: return buffer[pos++]; // read_index++];
0550: }
0551:
0552: /**
0553: * @return the number of bytes that can be read (or skipped over) from this
0554: * input stream. This is not necessarily the number of 'valid' bytes.
0555: */
0556: public int available() {
0557: return buffer.length - index;
0558: }
0559:
0560: /**
0561: * Has the effect of read(b, 0, b.length);
0562: * @see #read(byte[], int, int)
0563: */
0564: public int read(final byte[] b) throws java.io.IOException {
0565: return read(b, 0, b.length);
0566: }
0567:
0568: /**
0569: * Performs as described by <code>java.io.InputStream.read(byte[], int, int)</code>,
0570: * but never blocks.
0571: */
0572: public int read(final byte[] b, final int off, final int len)
0573: throws java.io.IOException {
0574: if (b == null) {
0575: throw new java.io.IOException("buffer may not be null");
0576: }
0577:
0578: if (off < 0 || len < 0 || off + len > b.length) {
0579: throw new java.io.IOException("buffer index out of bounds");
0580: }
0581:
0582: if (len == 0) {
0583: return 0;
0584: }
0585:
0586: if (available() < 1) {
0587: return -1;
0588: }
0589:
0590: if (closed) {
0591: throw new java.io.IOException("Stream already closed!");
0592: }
0593:
0594: int min = Math.min(len, available());
0595: System.arraycopy(buffer, index, b, off, min);
0596: pos += min;
0597: index += min;
0598: return min;
0599: }
0600:
0601: public final org.omg.CORBA.Any read_any() {
0602: org.omg.CORBA.TypeCode _tc = read_TypeCode();
0603: org.omg.CORBA.Any any = orb.create_any();
0604: any.read_value(this , _tc);
0605: return any;
0606: }
0607:
0608: public final boolean read_boolean() {
0609: handle_chunking();
0610: index++;
0611: byte value = buffer[pos++];
0612:
0613: if (value == 0) {
0614: return false;
0615: }
0616:
0617: if (value == 1) {
0618: return true;
0619: }
0620:
0621: if (laxBooleanEncoding) {
0622: // Technically only valid values are 0 (false) and 1 (true)
0623: // however some ORBs send values other than 1 for true.
0624: return true;
0625: }
0626:
0627: throw new MARSHAL("Unexpected boolean value: " + value
0628: + " pos: " + pos + " index: " + index);
0629: }
0630:
0631: /** arrays */
0632:
0633: public final void read_boolean_array(final boolean[] value,
0634: final int offset, final int length) {
0635: handle_chunking();
0636: byte bb;
0637: for (int j = offset; j < offset + length; j++) {
0638: index++;
0639: bb = buffer[pos++];
0640: if (bb == 1) {
0641: value[j] = true;
0642: } else if (bb == 0) {
0643: value[j] = false;
0644: } else {
0645: throw new MARSHAL("Unexpected boolean value: " + bb
0646: + " pos: " + pos + " index: " + index);
0647: }
0648: }
0649: }
0650:
0651: /**
0652: * <code>read_char</code> reads a character from the stream.
0653: *
0654: * @return a <code>char</code> value
0655: */
0656: public final char read_char() {
0657: handle_chunking();
0658:
0659: index++;
0660: return (char) (buffer[pos++] & 0xFF);
0661: }
0662:
0663: /**
0664: * <code>read_char_array</code> reads an character array from the stream.
0665: *
0666: * @param value a <code>char[]</code>, the result array.
0667: * @param offset an <code>int</code>, an offset into <code>value</code>
0668: * @param length an <code>int</code>, the length of the array to read
0669: */
0670: public final void read_char_array(final char[] value,
0671: final int offset, final int length) {
0672: if (value == null) {
0673: throw new MARSHAL("Cannot marshall result into null array.");
0674: } else if (offset + length > value.length || length < 0
0675: || offset < 0) {
0676: throw new MARSHAL(
0677: "Cannot marshall as indices for array are out bounds.");
0678: }
0679:
0680: handle_chunking();
0681:
0682: for (int j = offset; j < offset + length; j++) {
0683: index++;
0684: value[j] = (char) (0xff & buffer[pos++]);
0685: }
0686: }
0687:
0688: public final double read_double() {
0689: return Double.longBitsToDouble(read_longlong());
0690: }
0691:
0692: public final void read_double_array(final double[] value,
0693: final int offset, final int length) {
0694: if (length == 0) {
0695: return;
0696: }
0697:
0698: handle_chunking();
0699:
0700: int remainder = 8 - (index % 8);
0701: if (remainder != 8) {
0702: index += remainder;
0703: pos += remainder;
0704: }
0705:
0706: for (int j = offset; j < offset + length; j++) {
0707: value[j] = Double.longBitsToDouble(_read_longlong());
0708: }
0709: }
0710:
0711: public final BigDecimal read_fixed() {
0712: handle_chunking();
0713:
0714: final StringBuffer sb = new StringBuffer();
0715:
0716: final int c = read_fixed_internal(sb);
0717:
0718: final java.math.BigDecimal result = new java.math.BigDecimal(
0719: new java.math.BigInteger(sb.toString()));
0720:
0721: return read_fixed_negate(c, result);
0722: }
0723:
0724: private BigDecimal read_fixed_negate(final int c,
0725: final java.math.BigDecimal result) {
0726: if (c == 0xD) {
0727: return result.negate();
0728: }
0729:
0730: return result;
0731: }
0732:
0733: private int read_fixed_internal(StringBuffer sb) {
0734: int b = buffer[pos++];
0735: int c = b & 0x0F; // second half byte
0736: index++;
0737:
0738: while (true) {
0739: c = (b & 0xF0) >>> 4;
0740: sb.append(c);
0741:
0742: c = b & 0x0F;
0743: if (c == 0xC || c == 0xD) {
0744: break;
0745: }
0746: sb.append(c);
0747:
0748: b = buffer[pos++];
0749: index++;
0750: }
0751: return c;
0752: }
0753:
0754: public final java.math.BigDecimal read_fixed(short digits,
0755: short scale) {
0756: handle_chunking();
0757:
0758: final StringBuffer sb = new StringBuffer();
0759:
0760: final int c = read_fixed_internal(sb);
0761:
0762: final java.math.BigDecimal result = new java.math.BigDecimal(
0763: new java.math.BigInteger(sb.toString()), scale);
0764:
0765: return read_fixed_negate(c, result);
0766: }
0767:
0768: public final float read_float() {
0769: return Float.intBitsToFloat(read_long());
0770: }
0771:
0772: public final void read_float_array(final float[] value,
0773: final int offset, final int length) {
0774: if (length == 0) {
0775: return;
0776: }
0777:
0778: handle_chunking();
0779:
0780: int remainder = 4 - (index % 4);
0781: if (remainder != 4) {
0782: index += remainder;
0783: pos += remainder;
0784: }
0785:
0786: for (int j = offset; j < offset + length; j++) {
0787: value[j] = Float.intBitsToFloat(_read_long());
0788: }
0789: }
0790:
0791: public final int read_long() {
0792: handle_chunking();
0793:
0794: int result;
0795:
0796: int remainder = 4 - (index % 4);
0797: if (remainder != 4) {
0798: index += remainder;
0799: pos += remainder;
0800: }
0801:
0802: result = _read4int(littleEndian, buffer, pos);
0803:
0804: index += 4;
0805: pos += 4;
0806: return result;
0807: }
0808:
0809: public final void read_long_array(final int[] value,
0810: final int offset, final int length) {
0811: if (length == 0) {
0812: return;
0813: }
0814:
0815: handle_chunking();
0816:
0817: int remainder = 4 - (index % 4);
0818: if (remainder != 4) {
0819: index += remainder;
0820: pos += remainder;
0821: }
0822:
0823: for (int j = offset; j < offset + length; j++) {
0824: value[j] = _read4int(littleEndian, buffer, pos);
0825: pos += 4;
0826: }
0827:
0828: index += 4 * length;
0829: }
0830:
0831: public final long read_longlong() {
0832: handle_chunking();
0833:
0834: int remainder = 8 - (index % 8);
0835: if (remainder != 8) {
0836: index += remainder;
0837: pos += remainder;
0838: }
0839:
0840: if (littleEndian) {
0841: return (_read_long() & 0xFFFFFFFFL)
0842: + ((long) _read_long() << 32);
0843: }
0844:
0845: return ((long) _read_long() << 32)
0846: + (_read_long() & 0xFFFFFFFFL);
0847: }
0848:
0849: public final void read_longlong_array(final long[] value,
0850: final int offset, final int length) {
0851: if (length == 0) {
0852: return;
0853: }
0854:
0855: handle_chunking();
0856:
0857: int remainder = 8 - (index % 8);
0858: if (remainder != 8) {
0859: index += remainder;
0860: pos += remainder;
0861: }
0862:
0863: if (littleEndian) {
0864: for (int j = offset; j < offset + length; j++) {
0865: value[j] = (_read_long() & 0xFFFFFFFFL)
0866: + ((long) _read_long() << 32);
0867: }
0868: } else {
0869: for (int j = offset; j < offset + length; j++) {
0870: value[j] = ((long) _read_long() << 32)
0871: + (_read_long() & 0xFFFFFFFFL);
0872: }
0873: }
0874:
0875: // Do not need to modify pos and index as use read_long above
0876: }
0877:
0878: public final org.omg.CORBA.Object read_Object() {
0879: if (!(orb instanceof org.jacorb.orb.ORB)) {
0880: throw new MARSHAL(
0881: "Cannot use the singleton ORB to receive object references, "
0882: + "please initialize a full ORB instead.");
0883: }
0884:
0885: handle_chunking();
0886:
0887: org.omg.IOP.IOR ior = org.omg.IOP.IORHelper.read(this );
0888:
0889: if (isMutatorEnabled) {
0890: ior = mutator.mutateIncoming(ior);
0891: }
0892:
0893: ParsedIOR pior = new ParsedIOR((org.jacorb.orb.ORB) orb, ior);
0894:
0895: if (pior.isNull()) {
0896: return null;
0897: }
0898:
0899: return ((org.jacorb.orb.ORB) orb)._getObject(pior);
0900: }
0901:
0902: public org.omg.CORBA.Object read_Object(final java.lang.Class clazz) {
0903: if (org.omg.CORBA.portable.ObjectImpl.class
0904: .isAssignableFrom(clazz)) {
0905: org.omg.CORBA.Object obj = read_Object();
0906: if (obj instanceof org.omg.CORBA.portable.ObjectImpl) {
0907: org.omg.CORBA.portable.ObjectImpl stub = null;
0908: try {
0909: stub = (org.omg.CORBA.portable.ObjectImpl) clazz
0910: .newInstance();
0911: } catch (InstantiationException e) {
0912: throw new MARSHAL(
0913: "Exception in stub instantiation: " + e);
0914: } catch (IllegalAccessException e) {
0915: throw new MARSHAL(
0916: "Exception in stub instantiation: " + e);
0917: }
0918: stub
0919: ._set_delegate(((org.omg.CORBA.portable.ObjectImpl) obj)
0920: ._get_delegate());
0921: return stub;
0922: }
0923: return obj;
0924: } else if (clazz.isInterface()
0925: && java.rmi.Remote.class.isAssignableFrom(clazz)) {
0926: return (org.omg.CORBA.Object) org.jacorb.util.ValueHandler
0927: .portableRemoteObject_narrow(read_Object(), clazz);
0928: } else {
0929: return read_Object();
0930: }
0931: }
0932:
0933: public final byte read_octet() {
0934: handle_chunking();
0935: index++;
0936: return buffer[pos++];
0937: }
0938:
0939: public final void read_octet_array(final byte[] value,
0940: final int offset, final int length) {
0941: handle_chunking();
0942: System.arraycopy(buffer, pos, value, offset, length);
0943: index += length;
0944: pos += length;
0945: }
0946:
0947: /*
0948: * @deprecated
0949: * @see org.omg.CORBA.portable.InputStream#read_Principal()
0950: */
0951: public final org.omg.CORBA.Principal read_Principal() {
0952: throw new NO_IMPLEMENT("Principal deprecated");
0953: }
0954:
0955: /**
0956: * Read methods for big-endian as well as little endian data input
0957: * contributed by Mark Allerton <MAllerton@img.seagatesoftware.com>
0958: */
0959:
0960: public final short read_short() {
0961: handle_chunking();
0962:
0963: int remainder = 2 - (index % 2);
0964: if (remainder != 2) {
0965: index += remainder;
0966: pos += remainder;
0967: }
0968:
0969: short result = _read2int(littleEndian, buffer, pos);
0970: pos += 2;
0971: index += 2;
0972: return result;
0973: }
0974:
0975: public final void read_short_array(final short[] value,
0976: final int offset, final int length) {
0977: if (length == 0) {
0978: return;
0979: }
0980:
0981: handle_chunking();
0982:
0983: int remainder = 2 - (index % 2);
0984:
0985: if (remainder != 2) {
0986: index += remainder;
0987: pos += remainder;
0988: }
0989:
0990: for (int j = offset; j < offset + length; j++) {
0991: value[j] = _read2int(littleEndian, buffer, pos);
0992: pos += 2;
0993: }
0994:
0995: index += length * 2;
0996: }
0997:
0998: /**
0999: * <code>read_string</code> reads a string from the buffer. It is optimized
1000: * for whether it is reading a blank string, and whether codeset translation
1001: * is active.
1002: *
1003: * @return a <code>String</code> value, possibly blank, never null.
1004: */
1005: public final String read_string() {
1006: String result = null;
1007:
1008: handle_chunking();
1009:
1010: int remainder = 4 - (index % 4);
1011: if (remainder != 4) {
1012: index += remainder;
1013: pos += remainder;
1014: }
1015:
1016: // read size (#bytes)
1017: int size = _read4int(littleEndian, buffer, pos);
1018: int start = pos + 4;
1019:
1020: index += (size + 4);
1021: pos += (size + 4);
1022:
1023: if ((size > 0) && (buffer[start + size - 1] == 0)) {
1024: size--;
1025: }
1026: // Optimize for empty strings.
1027: if (size == 0) {
1028: return "";
1029: }
1030:
1031: if (start + size > buffer.length) {
1032: if (logger.isDebugEnabled()) {
1033: logger
1034: .debug("Size ("
1035: + size
1036: + ") invalid for string extraction from buffer length of "
1037: + buffer.length + " from position "
1038: + start);
1039: }
1040: throw new MARSHAL("Invalid size for string extraction");
1041: }
1042:
1043: if (codesetEnabled) {
1044: String csname = CodeSet.csName(codeSet);
1045:
1046: try {
1047: result = new String(buffer, start, size, csname);
1048: } catch (java.io.UnsupportedEncodingException ex) {
1049: if (logger != null && logger.isErrorEnabled()) {
1050: logger.error("Charset " + csname
1051: + " is unsupported");
1052: result = "";
1053: }
1054: }
1055: } else {
1056: char[] buf = new char[size];
1057:
1058: for (int i = 0; i < size; i++) {
1059: buf[i] = (char) (0xff & buffer[start + i]);
1060: }
1061: result = new String(buf);
1062: }
1063:
1064: return result;
1065: }
1066:
1067: public final org.omg.CORBA.TypeCode read_TypeCode() {
1068: if (tcMap == null) {
1069: // Initialise tcMap. We keep it for the lifetime of this
1070: // stream so it is possible to examine any found recursive
1071: // typecodes.
1072: tcMap = new TreeMap();
1073: }
1074:
1075: if (repeatedTCMap == null) {
1076: repeatedTCMap = new HashMap();
1077: }
1078:
1079: try {
1080: return read_TypeCode(tcMap, repeatedTCMap);
1081: } finally {
1082: repeatedTCMap.clear();
1083: }
1084: }
1085:
1086: private final org.omg.CORBA.TypeCode read_TypeCode(
1087: final Map recursiveTCMap, final Map repeatedTCMap) {
1088: final String id;
1089: final String name;
1090: final Pair cachedObject;
1091: final int member_count;
1092: final int length;
1093: final int size;
1094: final org.omg.CORBA.TypeCode result;
1095: final org.omg.CORBA.TypeCode content_type;
1096: final String[] member_names;
1097:
1098: final int kind = read_long();
1099: final int start_pos = pos - 4;
1100: final Integer startPosition = ObjectUtil.newInteger(start_pos);
1101:
1102: if (logger != null && logger.isDebugEnabled()) {
1103: logger.debug("Read Type code of kind " + kind + " at pos: "
1104: + start_pos);
1105: }
1106:
1107: switch (kind) {
1108: case -1: //0xffffffff:
1109: {
1110: // recursive or repeated TC
1111: int negative_offset = read_long();
1112:
1113: final Integer origTCStartPos = ObjectUtil.newInteger(pos
1114: - 4 + negative_offset);
1115:
1116: // need to check for repeated typecode first since a recursive
1117: // typecode may also be repeated (i.e. both maps have an entry
1118: // for the given origTCStartPos), but if we find an entry in
1119: // the repeatedTCMap, we know the typecode must have
1120: // completely been read already, so the marker can't indicate
1121: // a recursive typecode
1122: final org.omg.CORBA.TypeCode repeatedTC = (org.omg.CORBA.TypeCode) repeatedTCMap
1123: .get(origTCStartPos);
1124:
1125: if (repeatedTC != null) {
1126: result = repeatedTC;
1127: break;
1128: }
1129:
1130: final String recursiveId = (String) recursiveTCMap
1131: .get(origTCStartPos);
1132: if (recursiveId != null) {
1133: try {
1134: result = orb.create_recursive_tc(recursiveId);
1135: break;
1136: } catch (org.omg.CORBA.SystemException e) {
1137: throw new MARSHAL(
1138: "Failed to create recursive typecode: " + e);
1139: }
1140: }
1141:
1142: //if we end up here, we didn't find an entry in either
1143: //repeatedTCMap and recursiveTCMap
1144: throw new MARSHAL(
1145: "Found indirection marker, but no corresponding "
1146: + "original typecode (pos: "
1147: + origTCStartPos + ")");
1148: }
1149: case TCKind._tk_null: // 0
1150: case TCKind._tk_void: // 1
1151: case TCKind._tk_short: // 2
1152: case TCKind._tk_long: // 3
1153: case TCKind._tk_ushort: // 4
1154: case TCKind._tk_ulong: // 5
1155: case TCKind._tk_float: // 6
1156: case TCKind._tk_double: // 7
1157: case TCKind._tk_boolean: // 8
1158: case TCKind._tk_char: // 9
1159: case TCKind._tk_octet: // 10
1160: case TCKind._tk_any: // 11
1161: case TCKind._tk_TypeCode: // 12
1162: case TCKind._tk_Principal: // 13
1163: {
1164: result = orb.get_primitive_tc(org.omg.CORBA.TCKind
1165: .from_int(kind));
1166: break;
1167: }
1168: case TCKind._tk_objref: // 14
1169: {
1170: size = openEncapsulation();
1171: id = validateID(read_string());
1172: cachedObject = getCachedTypecode(id);
1173:
1174: if (cachedObject == null) {
1175: name = validateName(read_string());
1176: result = orb.create_interface_tc(id, name);
1177: putCachedTypecode(id, new Pair(result, startPosition));
1178: } else {
1179: final int skipAmount = calcSkipAmount(size, start_pos);
1180: skip(skipAmount);
1181: result = cachedObject.typeCode;
1182: }
1183:
1184: closeEncapsulation();
1185: break;
1186: }
1187: case TCKind._tk_struct: // 15
1188: {
1189: size = openEncapsulation();
1190: id = validateID(read_string());
1191: cachedObject = getCachedTypecode(id);
1192:
1193: if (cachedObject == null) {
1194: name = validateName(read_string());
1195: member_count = read_long();
1196: recursiveTCMap.put(startPosition, id);
1197: StructMember[] struct_members = new StructMember[member_count];
1198:
1199: for (int i = 0; i < member_count; i++) {
1200: struct_members[i] = new StructMember(
1201: read_string(),
1202: read_TypeCode(recursiveTCMap, repeatedTCMap),
1203: null);
1204: }
1205:
1206: result = ((ORBSingleton) orb).create_struct_tc(id,
1207: name, struct_members, false);
1208: putCachedTypecode(id, new Pair(result, startPosition));
1209: } else {
1210: final int skipAmount = calcSkipAmount(size, start_pos);
1211: updateTcMap(recursiveTCMap, start_pos, skipAmount,
1212: cachedObject.position);
1213: skip(skipAmount);
1214: recursiveTCMap.put(startPosition, id);
1215: result = cachedObject.typeCode;
1216: }
1217:
1218: closeEncapsulation();
1219: break;
1220: }
1221: case TCKind._tk_union: // 16
1222: {
1223: size = openEncapsulation();
1224: id = validateID(read_string());
1225: cachedObject = getCachedTypecode(id);
1226:
1227: if (cachedObject == null) {
1228: name = validateName(read_string());
1229:
1230: recursiveTCMap.put(startPosition, id);
1231:
1232: org.omg.CORBA.TypeCode discriminator_type = read_TypeCode(
1233: recursiveTCMap, repeatedTCMap);
1234: // Use the dealiased discriminator type for the label types.
1235: // This works because the JacORB IDL compiler ignores any aliasing
1236: // of label types and only the discriminator type is passed on the
1237: // wire.
1238: org.omg.CORBA.TypeCode orig_disc_type = TypeCode
1239: .originalType(discriminator_type);
1240:
1241: int default_index = read_long();
1242: member_count = read_long();
1243:
1244: UnionMember[] union_members = new UnionMember[member_count];
1245: for (int i = 0; i < member_count; i++) {
1246: org.omg.CORBA.Any label = orb.create_any();
1247:
1248: if (i == default_index) {
1249: // Default discriminator
1250: label.insert_octet(read_octet());
1251: } else {
1252: // use the dealiased discriminator type to construct labels
1253: label.read_value(this , orig_disc_type);
1254: }
1255:
1256: union_members[i] = new UnionMember(read_string(),
1257: label, read_TypeCode(recursiveTCMap,
1258: repeatedTCMap), null);
1259: }
1260:
1261: result = ((ORBSingleton) orb).create_union_tc(id, name,
1262: discriminator_type, union_members, false);
1263: putCachedTypecode(id, new Pair(result, startPosition));
1264: } else {
1265: final int skipAmount = calcSkipAmount(size, start_pos);
1266: updateTcMap(recursiveTCMap, start_pos, skipAmount,
1267: cachedObject.position);
1268: skip(skipAmount);
1269: recursiveTCMap.put(startPosition, id);
1270: result = cachedObject.typeCode;
1271: }
1272:
1273: closeEncapsulation();
1274: break;
1275: }
1276: case TCKind._tk_enum: // 17
1277: {
1278: size = openEncapsulation();
1279: id = validateID(read_string());
1280: cachedObject = getCachedTypecode(id);
1281:
1282: if (cachedObject == null) {
1283: name = validateName(read_string());
1284: member_count = read_long();
1285: member_names = new String[member_count];
1286:
1287: for (int i = 0; i < member_count; i++) {
1288: member_names[i] = read_string();
1289: }
1290:
1291: result = ((ORBSingleton) orb).create_enum_tc(id, name,
1292: member_names, false);
1293: putCachedTypecode(id, new Pair(result, startPosition));
1294: } else {
1295: final int skipAmount = calcSkipAmount(size, start_pos);
1296: skip(skipAmount);
1297: result = cachedObject.typeCode;
1298: }
1299: closeEncapsulation();
1300: break;
1301: }
1302: case TCKind._tk_string: // 18
1303: {
1304: result = orb.create_string_tc(read_long());
1305: break;
1306: }
1307: case TCKind._tk_sequence: // 19
1308: {
1309: size = openEncapsulation();
1310: content_type = read_TypeCode(recursiveTCMap, repeatedTCMap);
1311: cachedObject = getCachedTypecode(content_type);
1312:
1313: if (cachedObject == null) {
1314: length = read_long();
1315: result = orb.create_sequence_tc(length, content_type);
1316: putCachedTypecode(result, new Pair(result,
1317: startPosition));
1318: } else {
1319: final int skipAmount = calcSkipAmount(size, start_pos);
1320: skip(skipAmount);
1321: result = cachedObject.typeCode;
1322: }
1323:
1324: closeEncapsulation();
1325:
1326: break;
1327: }
1328: case TCKind._tk_array: // 20
1329: {
1330: size = openEncapsulation();
1331: content_type = read_TypeCode(recursiveTCMap, repeatedTCMap);
1332: cachedObject = getCachedTypecode(content_type);
1333:
1334: if (cachedObject == null) {
1335: result = orb.create_array_tc(read_long(), content_type);
1336:
1337: // Store in cache
1338: putCachedTypecode(result, new Pair(result,
1339: startPosition));
1340: } else {
1341: int skipAmount = calcSkipAmount(size, start_pos);
1342:
1343: skip(skipAmount);
1344: result = cachedObject.typeCode;
1345: }
1346:
1347: closeEncapsulation();
1348:
1349: break;
1350: }
1351: case TCKind._tk_alias: // 21
1352: {
1353: size = openEncapsulation();
1354: id = validateID(read_string());
1355: cachedObject = getCachedTypecode(id);
1356:
1357: if (cachedObject == null) {
1358: name = validateName(read_string());
1359:
1360: recursiveTCMap.put(startPosition, id);
1361:
1362: content_type = read_TypeCode(recursiveTCMap,
1363: repeatedTCMap);
1364: result = orb.create_alias_tc(id, name, content_type);
1365: putCachedTypecode(id, new Pair(result, startPosition));
1366: } else {
1367: final int skipAmount = calcSkipAmount(size, start_pos);
1368: updateTcMap(recursiveTCMap, start_pos, skipAmount,
1369: cachedObject.position);
1370: skip(skipAmount);
1371: recursiveTCMap.put(startPosition, id);
1372: result = cachedObject.typeCode;
1373: }
1374: closeEncapsulation();
1375: break;
1376: }
1377: case TCKind._tk_except: // 22
1378: {
1379: size = openEncapsulation();
1380: id = validateID(read_string());
1381: cachedObject = getCachedTypecode(id);
1382:
1383: if (cachedObject == null) {
1384: name = validateName(read_string());
1385: member_count = read_long();
1386:
1387: recursiveTCMap.put(startPosition, id);
1388:
1389: StructMember[] members = new StructMember[member_count];
1390: for (int i = 0; i < member_count; i++) {
1391: members[i] = new StructMember(
1392: read_string(),
1393: read_TypeCode(recursiveTCMap, repeatedTCMap),
1394: null);
1395: }
1396: result = ((ORBSingleton) orb).create_exception_tc(id,
1397: name, members, false);
1398:
1399: // Store in cache
1400: putCachedTypecode(id, new Pair(result, startPosition));
1401: } else {
1402: final int skipAmount = calcSkipAmount(size, start_pos);
1403: updateTcMap(recursiveTCMap, start_pos, skipAmount,
1404: cachedObject.position);
1405: skip(skipAmount);
1406: recursiveTCMap.put(startPosition, id);
1407: result = cachedObject.typeCode;
1408: }
1409:
1410: closeEncapsulation();
1411: break;
1412: }
1413: case TCKind._tk_longlong: // 23
1414: case TCKind._tk_ulonglong: // 24
1415: {
1416: result = orb.get_primitive_tc(org.omg.CORBA.TCKind
1417: .from_int(kind));
1418: break;
1419: }
1420: case TCKind._tk_longdouble: //25
1421: {
1422: throw new MARSHAL("Cannot handle TypeCode with kind "
1423: + kind);
1424: }
1425: case TCKind._tk_wchar: // 26
1426: {
1427: result = orb.get_primitive_tc(org.omg.CORBA.TCKind
1428: .from_int(kind));
1429: break;
1430: }
1431: case TCKind._tk_wstring: // 27
1432: {
1433: result = orb.create_wstring_tc(read_long());
1434: break;
1435: }
1436: case TCKind._tk_fixed: // 28
1437: {
1438: result = orb.create_fixed_tc(read_ushort(), read_short());
1439: break;
1440: }
1441: case TCKind._tk_value: // 29
1442: {
1443: size = openEncapsulation();
1444: id = validateID(read_string());
1445: cachedObject = getCachedTypecode(id);
1446:
1447: if (cachedObject == null) {
1448: name = validateName(read_string());
1449:
1450: recursiveTCMap.put(startPosition, id);
1451:
1452: short type_modifier = read_short();
1453: org.omg.CORBA.TypeCode concrete_base_type = read_TypeCode(
1454: recursiveTCMap, repeatedTCMap);
1455: member_count = read_long();
1456: ValueMember[] vMembers = new ValueMember[member_count];
1457:
1458: for (int i = 0; i < member_count; i++) {
1459: vMembers[i] = new ValueMember(
1460: read_string(),
1461: null, // id
1462: null, // defined_in
1463: null, // version
1464: read_TypeCode(recursiveTCMap, repeatedTCMap),
1465: null, // type_def
1466: read_short());
1467: }
1468: result = orb.create_value_tc(id, name, type_modifier,
1469: concrete_base_type, vMembers);
1470: putCachedTypecode(id, new Pair(result, startPosition));
1471: } else {
1472: final int skipAmount = calcSkipAmount(size, start_pos);
1473: updateTcMap(recursiveTCMap, start_pos, skipAmount,
1474: cachedObject.position);
1475: skip(skipAmount);
1476: recursiveTCMap.put(startPosition, id);
1477: result = cachedObject.typeCode;
1478: }
1479: closeEncapsulation();
1480: break;
1481: }
1482: case TCKind._tk_value_box: // 30
1483: {
1484: size = openEncapsulation();
1485: id = validateID(read_string());
1486: cachedObject = getCachedTypecode(id);
1487:
1488: if (cachedObject == null) {
1489: name = validateName(read_string());
1490:
1491: recursiveTCMap.put(startPosition, id);
1492:
1493: content_type = read_TypeCode(recursiveTCMap,
1494: repeatedTCMap);
1495: result = orb
1496: .create_value_box_tc(id, name, content_type);
1497: putCachedTypecode(id, new Pair(result, startPosition));
1498: } else {
1499: final int skipAmount = calcSkipAmount(size, start_pos);
1500: updateTcMap(recursiveTCMap, start_pos, skipAmount,
1501: cachedObject.position);
1502: skip(skipAmount);
1503: recursiveTCMap.put(startPosition, id);
1504: result = cachedObject.typeCode;
1505: }
1506: closeEncapsulation();
1507: break;
1508: }
1509: case TCKind._tk_native: //31
1510: {
1511: throw new MARSHAL("Cannot handle TypeCode with kind "
1512: + kind);
1513: }
1514: case TCKind._tk_abstract_interface: // 32
1515: {
1516: size = openEncapsulation();
1517: id = validateID(read_string());
1518: cachedObject = getCachedTypecode(id);
1519:
1520: if (cachedObject == null) {
1521: name = validateName(read_string());
1522: recursiveTCMap.put(startPosition, id);
1523: result = orb.create_abstract_interface_tc(id, name);
1524: putCachedTypecode(id, new Pair(result, startPosition));
1525: } else {
1526: final int skipAmount = calcSkipAmount(size, start_pos);
1527: updateTcMap(recursiveTCMap, start_pos, skipAmount,
1528: cachedObject.position);
1529: skip(skipAmount);
1530: recursiveTCMap.put(startPosition, id);
1531: result = cachedObject.typeCode;
1532: }
1533: closeEncapsulation();
1534: break;
1535: }
1536: default: {
1537: // error, dump buffer contents for diagnosis
1538: throw new MARSHAL("Cannot handle TypeCode with kind "
1539: + kind);
1540: }
1541: }
1542:
1543: repeatedTCMap.put(startPosition, result);
1544: return result;
1545: }
1546:
1547: /**
1548: * see cachedTypecodes for calculation.
1549: * @param size
1550: * @param start_pos
1551: */
1552: private int calcSkipAmount(final int size, final int start_pos) {
1553: return (size - ((pos - start_pos) - 4 - 4));
1554: }
1555:
1556: /**
1557: * <code>updateTcMap</code> is used during cached typecodes. As a cached
1558: * typecode is being used we may miss placing markers for the recursive
1559: * tcMap. Therefore, by recording the original typecodes start, and as we
1560: * know the length it is possible find and calculate and extra positions
1561: * that should be added.
1562: *
1563: * @param tcMap a <code>Map</code> value which may be updated.
1564: * @param new_start an <code>int</code> value
1565: * @param size an <code>int</code> value
1566: * @param old_start an <code>Integer</code> value
1567: */
1568: private void updateTcMap(final Map tcMap, final int new_start,
1569: final int size, final Integer old_start) {
1570: final SortedMap sortedMap = ((TreeMap) tcMap).subMap(old_start,
1571: ObjectUtil.newInteger(size + old_start.intValue()));
1572:
1573: // If we have found anything between the original start position and the size.
1574: if (sortedMap.size() > 0) {
1575: final TreeMap toMerge = new TreeMap();
1576: final Iterator iterator = sortedMap.entrySet().iterator();
1577:
1578: while (iterator.hasNext()) {
1579: final Map.Entry entry = (Map.Entry) iterator.next();
1580:
1581: int value = ((Integer) entry.getKey()).intValue();
1582: // This calculation is the offset; the distance between the missing
1583: // tc and the original start added onto the new start.
1584: toMerge.put(ObjectUtil.newInteger(new_start
1585: + (value - old_start.intValue())), entry
1586: .getValue());
1587: }
1588: tcMap.putAll(toMerge);
1589: }
1590: }
1591:
1592: public final int read_ulong() {
1593: handle_chunking();
1594:
1595: int result;
1596:
1597: int remainder = 4 - (index % 4);
1598: if (remainder != 4) {
1599: index += remainder;
1600: pos += remainder;
1601: }
1602:
1603: result = _read4int(littleEndian, buffer, pos);
1604:
1605: index += 4;
1606: pos += 4;
1607: return result;
1608: }
1609:
1610: public final void read_ulong_array(final int[] value,
1611: final int offset, final int length) {
1612: if (length == 0) {
1613: return;
1614: }
1615:
1616: handle_chunking();
1617:
1618: int remainder = 4 - (index % 4);
1619: if (remainder != 4) {
1620: index += remainder;
1621: pos += remainder;
1622: }
1623:
1624: for (int j = offset; j < offset + length; j++) {
1625: value[j] = _read4int(littleEndian, buffer, pos);
1626: pos += 4;
1627: }
1628:
1629: index += 4 * length;
1630: }
1631:
1632: public final long read_ulonglong() {
1633: handle_chunking();
1634:
1635: int remainder = 8 - (index % 8);
1636: if (remainder != 8) {
1637: index += remainder;
1638: pos += remainder;
1639: }
1640:
1641: if (littleEndian) {
1642: return (_read_long() & 0xFFFFFFFFL)
1643: + ((long) _read_long() << 32);
1644: }
1645:
1646: return ((long) _read_long() << 32)
1647: + (_read_long() & 0xFFFFFFFFL);
1648: }
1649:
1650: public final void read_ulonglong_array(final long[] value,
1651: final int offset, final int length) {
1652: if (length == 0) {
1653: return;
1654: }
1655:
1656: handle_chunking();
1657:
1658: int remainder = 8 - (index % 8);
1659: if (remainder != 8) {
1660: index += remainder;
1661: pos += remainder;
1662: }
1663:
1664: if (littleEndian) {
1665: for (int j = offset; j < offset + length; j++) {
1666: value[j] = (_read_long() & 0xFFFFFFFFL)
1667: + ((long) _read_long() << 32);
1668: }
1669: } else {
1670: for (int j = offset; j < offset + length; j++) {
1671: value[j] = ((long) _read_long() << 32)
1672: + (_read_long() & 0xFFFFFFFFL);
1673: }
1674: }
1675:
1676: // Do not need to modify pos and index as use read_long above
1677: }
1678:
1679: public final short read_ushort() {
1680: handle_chunking();
1681:
1682: int remainder = 2 - (index % 2);
1683: if (remainder != 2) {
1684: index += remainder;
1685: pos += remainder;
1686: }
1687:
1688: short result = _read2int(littleEndian, buffer, pos);
1689: pos += 2;
1690: index += 2;
1691: return result;
1692: }
1693:
1694: public final void read_ushort_array(final short[] value,
1695: final int offset, final int length) {
1696: if (length == 0) {
1697: return;
1698: }
1699:
1700: handle_chunking();
1701:
1702: int remainder = 2 - (index % 2);
1703:
1704: if (remainder != 2) {
1705: index += remainder;
1706: pos += remainder;
1707: }
1708:
1709: for (int j = offset; j < offset + length; j++) {
1710: value[j] = _read2int(littleEndian, buffer, pos);
1711: pos += 2;
1712: }
1713:
1714: index += length * 2;
1715: }
1716:
1717: public final char read_wchar() {
1718: handle_chunking();
1719:
1720: if (giop_minor == 2) {
1721: //ignore size indicator
1722: read_wchar_size();
1723:
1724: boolean wchar_little_endian = readBOM();
1725:
1726: return read_wchar(wchar_little_endian);
1727: }
1728:
1729: return read_wchar(littleEndian);
1730: }
1731:
1732: /**
1733: * The number of bytes this char takes. This is actually not
1734: * necessary since the encodings used are either fixed-length
1735: * (UTF-16) or have their length encoded internally (UTF-8).
1736: */
1737: private final int read_wchar_size() {
1738: index++;
1739:
1740: return buffer[pos++];
1741: }
1742:
1743: private final char read_wchar(final boolean wchar_little_endian) {
1744: switch (codeSetW) {
1745: case CodeSet.UTF8: {
1746: if (giop_minor < 2) {
1747: throw new MARSHAL(
1748: "GIOP 1."
1749: + giop_minor
1750: + " only allows 2 Byte encodings for wchar, but the selected TCSW is UTF-8");
1751: }
1752:
1753: short value = (short) (0xff & buffer[pos++]);
1754: index++;
1755:
1756: if ((value & 0x80) == 0) {
1757: return (char) value;
1758: } else if ((value & 0xe0) == 0xc0) {
1759: index++;
1760: return (char) (((value & 0x1F) << 6) | (buffer[pos++] & 0x3F));
1761: } else {
1762: index += 2;
1763: short b2 = (short) (0xff & buffer[pos++]);
1764: return (char) (((value & 0x0F) << 12)
1765: | ((b2 & 0x3F) << 6) | (buffer[pos++] & 0x3F));
1766: }
1767: }
1768: case CodeSet.UTF16: {
1769: char value;
1770:
1771: if (wchar_little_endian) {
1772: value = (char) ((buffer[pos++] & 0xFF) | (buffer[pos++] << 8));
1773: } else {
1774: value = (char) ((buffer[pos++] << 8) | (buffer[pos++] & 0xFF));
1775: }
1776:
1777: index += 2;
1778: return value;
1779: }
1780: default: {
1781: throw new MARSHAL("Bad CodeSet: " + codeSetW);
1782: }
1783: }
1784: }
1785:
1786: /**
1787: * Read the byte order marker indicating the endianess.
1788: *
1789: * @return true for little endianess, false otherwise (including
1790: * no BOM present. In this case, big endianess is assumed per
1791: * spec).
1792: */
1793: private final boolean readBOM() {
1794: if ((buffer[pos] == (byte) 0xFE)
1795: && (buffer[pos + 1] == (byte) 0xFF)) {
1796: //encountering a byte order marker indicating big
1797: //endianess
1798:
1799: pos += 2;
1800: index += 2;
1801:
1802: return false;
1803: } else if ((buffer[pos] == (byte) 0xFF)
1804: && (buffer[pos + 1] == (byte) 0xFE)) {
1805: //encountering a byte order marker indicating
1806: //little endianess
1807:
1808: pos += 2;
1809: index += 2;
1810:
1811: return true;
1812: } else {
1813: //no BOM so big endian per spec.
1814: return false;
1815: }
1816: }
1817:
1818: public final void read_wchar_array(final char[] value,
1819: final int offset, final int length) {
1820: handle_chunking();
1821: for (int j = offset; j < offset + length; j++) {
1822: value[j] = read_wchar(); // inlining later...
1823: }
1824: }
1825:
1826: public final String read_wstring() {
1827: String result = null;
1828: char buf[] = null;
1829:
1830: handle_chunking();
1831:
1832: int remainder = 4 - (index % 4);
1833: if (remainder != 4) {
1834: index += remainder;
1835: pos += remainder;
1836: }
1837: if (giop_minor == 2) {
1838: // read size in bytes
1839: int size = _read4int(littleEndian, buffer, pos);
1840: index += 4;
1841: pos += 4;
1842:
1843: if (size == 0) {
1844: return "";
1845: }
1846:
1847: buf = new char[size];
1848:
1849: int i = 0;
1850: int endPos = pos + size;
1851:
1852: boolean wchar_litte_endian = readBOM();
1853:
1854: while (pos < endPos) {
1855: //ignore size
1856: //read_wchar_size();
1857:
1858: buf[i++] = read_wchar(wchar_litte_endian);
1859: }
1860:
1861: result = new String(buf, 0, i);
1862: } else //GIOP 1.1 / 1.0
1863: {
1864: // read size
1865: int size = _read4int(littleEndian, buffer, pos);
1866: index += 4;
1867: pos += 4;
1868: buf = new char[size];
1869:
1870: int endPos = pos + size;
1871:
1872: if (codeSetW == CodeSet.UTF16) {
1873: //size is in chars, but char has 2 bytes
1874: endPos += size;
1875: }
1876:
1877: int i = 0;
1878:
1879: while (pos < endPos) {
1880: //use the stream-wide endianess
1881: buf[i++] = read_wchar(littleEndian);
1882: }
1883:
1884: if ((i != 0) && (buf[i - 1] == 0)) {
1885: //don't return terminating NUL
1886: result = new String(buf, 0, i - 1);
1887: } else {
1888: //doesn't have a terminating NUL. This is actually not
1889: //allowed.
1890: result = new String(buf, 0, i);
1891: }
1892: }
1893: buf = null;
1894: return result;
1895: }
1896:
1897: public boolean markSupported() {
1898: return true;
1899: }
1900:
1901: public void mark(final int readLimit) {
1902: marked_pos = pos;
1903: marked_index = index;
1904: }
1905:
1906: public void reset() throws IOException {
1907: if (pos < 0) {
1908: throw new MARSHAL("Mark has not been set!");
1909: }
1910: pos = marked_pos;
1911: index = marked_index;
1912: }
1913:
1914: // JacORB-specific
1915:
1916: private final void resetIndex() {
1917: index = 0;
1918: }
1919:
1920: public final void setLittleEndian(final boolean b) {
1921: littleEndian = b;
1922: }
1923:
1924: /**
1925: * Reads an instance of the type described by type code <code>tc</code>
1926: * from this CDRInputStream, and remarshals it to the given OutputStream,
1927: * <code>out</code>. Called from Any.
1928: */
1929: final void read_value(final org.omg.CORBA.TypeCode typeCode,
1930: final org.omg.CORBA.portable.OutputStream out) {
1931: if (typeCode == null) {
1932: throw new BAD_PARAM("TypeCode is null");
1933: }
1934:
1935: int kind = typeCode.kind().value();
1936:
1937: try {
1938: switch (kind) {
1939: case TCKind._tk_null: // 0
1940: // fallthrough
1941: case TCKind._tk_void: // 1
1942: {
1943: break;
1944: }
1945: case TCKind._tk_short: // 2
1946: {
1947: out.write_short(read_short());
1948: break;
1949: }
1950: case TCKind._tk_long: // 3
1951: {
1952: out.write_long(read_long());
1953: break;
1954: }
1955: case TCKind._tk_ushort: // 4
1956: {
1957: out.write_ushort(read_ushort());
1958: break;
1959: }
1960: case TCKind._tk_ulong: // 5
1961: {
1962: out.write_ulong(read_ulong());
1963: break;
1964: }
1965: case TCKind._tk_float: // 6
1966: {
1967: out.write_float(read_float());
1968: break;
1969: }
1970: case TCKind._tk_double: // 7
1971: {
1972: out.write_double(read_double());
1973: break;
1974: }
1975: case TCKind._tk_boolean: // 8
1976: {
1977: out.write_boolean(read_boolean());
1978: break;
1979: }
1980: case TCKind._tk_char: // 9
1981: {
1982: out.write_char(read_char());
1983: break;
1984: }
1985: case TCKind._tk_octet: // 10
1986: {
1987: out.write_octet(read_octet());
1988: break;
1989: }
1990: case TCKind._tk_any: // 11
1991: {
1992: out.write_any(read_any());
1993: break;
1994: }
1995: case TCKind._tk_TypeCode: // 12
1996: {
1997: out.write_TypeCode(read_TypeCode());
1998: break;
1999: }
2000: case TCKind._tk_Principal: // 13
2001: {
2002: throw new NO_IMPLEMENT("Principal deprecated");
2003: }
2004: case TCKind._tk_objref: // 14
2005: {
2006: out.write_Object(read_Object());
2007: break;
2008: }
2009: case TCKind._tk_struct: // 15
2010: {
2011: for (int i = 0; i < typeCode.member_count(); i++) {
2012: read_value(typeCode.member_type(i), out);
2013: }
2014: break;
2015: }
2016: case TCKind._tk_union: // 16
2017: {
2018: org.omg.CORBA.TypeCode disc = typeCode
2019: .discriminator_type();
2020: disc = TypeCode.originalType(disc);
2021: int def_idx = typeCode.default_index();
2022: int member_idx = -1;
2023: switch (disc.kind().value()) {
2024: case TCKind._tk_short: // 2
2025: {
2026: short s = read_short();
2027: out.write_short(s);
2028: for (int i = 0; i < typeCode.member_count(); i++) {
2029: if (i != def_idx) {
2030: if (s == typeCode.member_label(i)
2031: .extract_short()) {
2032: member_idx = i;
2033: break;
2034: }
2035: }
2036: }
2037: break;
2038: }
2039:
2040: case TCKind._tk_long: // 3
2041: {
2042: int s = read_long();
2043: out.write_long(s);
2044: for (int i = 0; i < typeCode.member_count(); i++) {
2045: if (i != def_idx) {
2046: if (s == typeCode.member_label(i)
2047: .extract_long()) {
2048: member_idx = i;
2049: break;
2050: }
2051: }
2052: }
2053: break;
2054: }
2055: case TCKind._tk_ushort: // 4
2056: {
2057: short s = read_ushort();
2058: out.write_ushort(s);
2059: for (int i = 0; i < typeCode.member_count(); i++) {
2060: if (i != def_idx) {
2061: if (s == typeCode.member_label(i)
2062: .extract_ushort()) {
2063: member_idx = i;
2064: break;
2065: }
2066: }
2067: }
2068: break;
2069: }
2070:
2071: case TCKind._tk_ulong: // 5
2072: {
2073: int s = read_ulong();
2074: out.write_ulong(s);
2075: for (int i = 0; i < typeCode.member_count(); i++) {
2076: if (i != def_idx) {
2077: if (s == typeCode.member_label(i)
2078: .extract_ulong()) {
2079: member_idx = i;
2080: break;
2081: }
2082: }
2083: }
2084: break;
2085: }
2086: case TCKind._tk_float: // 6
2087: // fallthrough
2088: case TCKind._tk_double: // 7
2089: {
2090: throw new MARSHAL(
2091: "Invalid union discriminator type: " + disc);
2092: }
2093: case TCKind._tk_boolean: // 8
2094: {
2095: boolean b = read_boolean();
2096: out.write_boolean(b);
2097: for (int i = 0; i < typeCode.member_count(); i++) {
2098: if (i != def_idx) {
2099: if (b == typeCode.member_label(i)
2100: .extract_boolean()) {
2101: member_idx = i;
2102: break;
2103: }
2104: }
2105: }
2106: break;
2107: }
2108: case TCKind._tk_char: // 9
2109: {
2110: char s = read_char();
2111: out.write_char(s);
2112: for (int i = 0; i < typeCode.member_count(); i++) {
2113: if (i != def_idx) {
2114: if (s == typeCode.member_label(i)
2115: .extract_char()) {
2116: member_idx = i;
2117: break;
2118: }
2119: }
2120: }
2121: break;
2122: }
2123: case TCKind._tk_octet: // 10
2124: // fallthrough
2125: case TCKind._tk_any: // 11
2126: // fallthrough
2127: case TCKind._tk_TypeCode: // 12
2128: // fallthrough
2129: case TCKind._tk_Principal: // 13
2130: // fallthrough
2131: case TCKind._tk_objref: // 14
2132: // fallthrough
2133: case TCKind._tk_struct: // 15
2134: // fallthrough
2135: case TCKind._tk_union: // 16
2136: {
2137: throw new MARSHAL(
2138: "Invalid union discriminator type: " + disc);
2139: }
2140: case TCKind._tk_enum: // 17
2141: {
2142: int s = read_long();
2143: out.write_long(s);
2144: for (int i = 0; i < typeCode.member_count(); i++) {
2145: if (i != def_idx) {
2146: int label = typeCode.member_label(i)
2147: .create_input_stream().read_long();
2148: if (s == label) {
2149: member_idx = i;
2150: break;
2151: }
2152: }
2153: }
2154: break;
2155: }
2156: case TCKind._tk_string: // 18
2157: // fallthrough
2158: case TCKind._tk_sequence: // 19
2159: // fallthrough
2160: case TCKind._tk_array: // 20
2161: // fallthrough
2162: case TCKind._tk_alias: // 21
2163: // fallthrough
2164: case TCKind._tk_except: // 22
2165: {
2166: throw new MARSHAL(
2167: "Invalid union discriminator type: " + disc);
2168: }
2169: case TCKind._tk_longlong: // 23
2170: {
2171: long s = read_longlong();
2172: out.write_longlong(s);
2173: for (int i = 0; i < typeCode.member_count(); i++) {
2174: if (i != def_idx) {
2175: if (s == typeCode.member_label(i)
2176: .extract_longlong()) {
2177: member_idx = i;
2178: break;
2179: }
2180: }
2181: }
2182: break;
2183: }
2184: case TCKind._tk_ulonglong: // 24
2185: {
2186: long s = read_ulonglong();
2187: out.write_ulonglong(s);
2188: for (int i = 0; i < typeCode.member_count(); i++) {
2189: if (i != def_idx) {
2190: if (s == typeCode.member_label(i)
2191: .extract_ulonglong()) {
2192: member_idx = i;
2193: break;
2194: }
2195: }
2196: }
2197: break;
2198: }
2199: default: {
2200: throw new MARSHAL(
2201: "Invalid union discriminator type: " + disc);
2202: }
2203: } // switch
2204:
2205: if (member_idx != -1) {
2206: read_value(typeCode.member_type(member_idx), out);
2207: } else if (def_idx != -1) {
2208: read_value(typeCode.member_type(def_idx), out);
2209: }
2210: break;
2211: }
2212: case TCKind._tk_enum: // 17
2213: {
2214: out.write_long(read_long());
2215: break;
2216: }
2217: case TCKind._tk_string: // 18
2218: {
2219: out.write_string(read_string());
2220: break;
2221: }
2222: case TCKind._tk_sequence: // 19
2223: {
2224: int len = read_long();
2225: out.write_long(len);
2226: for (int i = 0; i < len; i++) {
2227: read_value(typeCode.content_type(), out);
2228: }
2229: break;
2230: }
2231: case TCKind._tk_array: // 20
2232: {
2233: int length = typeCode.length();
2234: for (int i = 0; i < length; i++) {
2235: read_value(typeCode.content_type(), out);
2236: }
2237: break;
2238: }
2239: case TCKind._tk_alias: // 21
2240: {
2241: read_value(typeCode.content_type(), out);
2242: break;
2243: }
2244: case TCKind._tk_except: // 22
2245: {
2246: out.write_string(read_string());
2247:
2248: for (int i = 0; i < typeCode.member_count(); i++) {
2249: read_value(typeCode.member_type(i), out);
2250: }
2251:
2252: break;
2253: }
2254: case TCKind._tk_longlong: // 23
2255: {
2256: out.write_longlong(read_longlong());
2257: break;
2258: }
2259: case TCKind._tk_ulonglong: // 24
2260: {
2261: out.write_ulonglong(read_ulonglong());
2262: break;
2263: }
2264: case TCKind._tk_longdouble: // 25
2265: {
2266: throw new org.omg.CORBA.BAD_TYPECODE(
2267: "type longdouble not supported in java");
2268: }
2269: case TCKind._tk_wchar: // 26
2270: {
2271: out.write_wchar(read_wchar());
2272: break;
2273: }
2274: case TCKind._tk_wstring: // 27
2275: {
2276: out.write_wstring(read_wstring());
2277: break;
2278: }
2279: case TCKind._tk_fixed: // 28
2280: {
2281: out.write_fixed(read_fixed());
2282: break;
2283: }
2284: case TCKind._tk_value: // 29
2285: {
2286: Serializable val = read_value();
2287: ((org.omg.CORBA_2_3.portable.OutputStream) out)
2288: .write_value(val, typeCode.id());
2289: break;
2290: }
2291: case TCKind._tk_value_box: // 30
2292: {
2293: String id = typeCode.id();
2294: org.omg.CORBA.portable.BoxedValueHelper helper = ((org.jacorb.orb.ORB) orb)
2295: .getBoxedValueHelper(id);
2296: if (helper == null) {
2297: throw new MARSHAL("No BoxedValueHelper for id "
2298: + id);
2299: }
2300: java.io.Serializable value = read_value(helper);
2301: ((org.omg.CORBA_2_3.portable.OutputStream) out)
2302: .write_value(value, helper);
2303: break;
2304: }
2305: default: {
2306: throw new MARSHAL("Cannot handle TypeCode with kind "
2307: + kind);
2308: }
2309: }
2310: } catch (BadKind ex) {
2311: throw new MARSHAL("When processing TypeCode with kind: "
2312: + kind + " caught " + ex);
2313: } catch (Bounds ex) {
2314: throw new MARSHAL("When processing TypeCode with kind: "
2315: + kind + " caught " + ex);
2316: }
2317: }
2318:
2319: public java.io.Serializable read_value() {
2320: int tag = read_long();
2321: int start_offset = pos - 4;
2322:
2323: if (tag == 0xffffffff) {
2324: // indirection
2325: return read_indirect_value();
2326: } else if (tag == 0x00000000) {
2327: // null tag
2328: return null;
2329: }
2330:
2331: String codebase = ((tag & 1) != 0) ? read_codebase() : null;
2332: chunkedValue = ((tag & 8) != 0);
2333:
2334: int theTag = tag;
2335: tag = tag & 0xfffffff6;
2336:
2337: if (tag == 0x7fffff00) {
2338: throw new MARSHAL("missing value type information");
2339: } else if (tag == 0x7fffff02) {
2340: return read_typed_value(start_offset, codebase);
2341: } else if (tag == 0x7fffff06) {
2342: return read_multi_typed_value(start_offset, codebase);
2343: } else {
2344: throw new MARSHAL("unknown value tag: 0x"
2345: + Integer.toHexString(theTag) + " (offset=0x"
2346: + Integer.toHexString(start_offset) + ")");
2347: }
2348: }
2349:
2350: /**
2351: * Overrides read_value(java.io.Serializable value) in
2352: * org.omg.CORBA_2_3.portable.InputStream
2353: */
2354: public java.io.Serializable read_value(final String rep_id) {
2355: int tag = read_long();
2356: final int start_offset = pos - 4;
2357:
2358: if (tag == 0xffffffff) {
2359: // indirection
2360: return read_indirect_value();
2361: } else if (tag == 0x00000000) {
2362: // null tag
2363: return null;
2364: }
2365:
2366: final String codebase = ((tag & 1) != 0) ? read_codebase()
2367: : null;
2368: chunkedValue = ((tag & 8) != 0);
2369:
2370: int theTag = tag;
2371: tag = tag & 0xfffffff6;
2372:
2373: if (tag == 0x7fffff00) {
2374: return read_untyped_value(new String[] { rep_id },
2375: start_offset, codebase);
2376: } else if (tag == 0x7fffff02) {
2377: return read_typed_value(start_offset, codebase);
2378: } else if (tag == 0x7fffff06) {
2379: return read_multi_typed_value(start_offset, codebase);
2380: } else {
2381: throw new MARSHAL("unknown value tag: 0x"
2382: + Integer.toHexString(theTag) + " (offset=0x"
2383: + Integer.toHexString(start_offset) + ")");
2384: }
2385: }
2386:
2387: /**
2388: * Unmarshals a valuetype instance from this stream. The value returned
2389: * is the same value passed in, with all the data unmarshaled
2390: * (IDL-to-Java Mapping 1.2, August 2002, 1.13.1, p. 1-39). The specified
2391: * value is an uninitialized value that is added to the ORB's indirection
2392: * table before unmarshaling (1.21.4.1, p. 1-117).
2393: *
2394: * This method is intended to be called from custom valuetype factories.
2395: * Unlike the other read_value() methods in this class, this method does
2396: * not expect a GIOP value tag nor a repository id in the stream.
2397: *
2398: * Overrides read_value(value) in
2399: * org.omg.CORBA_2_3.portable.InputStream
2400: */
2401: public java.io.Serializable read_value(java.io.Serializable value) {
2402: if (value instanceof org.omg.CORBA.portable.Streamable) {
2403: register_value(value);
2404: ((org.omg.CORBA.portable.Streamable) value)._read(this );
2405: } else if (value instanceof org.omg.CORBA.portable.CustomValue) {
2406: register_value(value);
2407: ((org.omg.CORBA.portable.CustomValue) value)
2408: .unmarshal(new DataInputStream(this ));
2409: } else {
2410: throw new BAD_PARAM(
2411: "read_value is only implemented for Streamables");
2412: }
2413: return value;
2414: }
2415:
2416: /**
2417: * Overrides read_value(clz) in
2418: * org.omg.CORBA_2_3.portable.InputStream
2419: */
2420:
2421: public java.io.Serializable read_value(final java.lang.Class clz) {
2422: int tag = read_long();
2423: int start_offset = pos - 4;
2424:
2425: if (tag == 0xffffffff) {
2426: // indirection
2427: return read_indirect_value();
2428: } else if (tag == 0x00000000) {
2429: // null tag
2430: return null;
2431: }
2432:
2433: String codebase = ((tag & 1) != 0) ? read_codebase() : null;
2434: chunkedValue = ((tag & 8) != 0);
2435:
2436: int theTag = tag;
2437: tag = tag & 0xfffffff6;
2438:
2439: if (tag == 0x7fffff00) {
2440: return read_untyped_value(new String[] { ValueHandler
2441: .getRMIRepositoryID(clz) }, start_offset, codebase);
2442: } else if (tag == 0x7fffff02) {
2443: return read_typed_value(start_offset, codebase);
2444: } else if (tag == 0x7fffff06) {
2445: return read_multi_typed_value(start_offset, codebase);
2446: } else {
2447: throw new MARSHAL("unknown value tag: 0x"
2448: + Integer.toHexString(theTag) + " (offset=0x"
2449: + Integer.toHexString(start_offset) + ")");
2450: }
2451: }
2452:
2453: /**
2454: * Overrides read_value(factory) in
2455: * org.omg.CORBA_2_3.portable.InputStream
2456: */
2457: public java.io.Serializable read_value(
2458: final org.omg.CORBA.portable.BoxedValueHelper factory) {
2459: int tag = read_long();
2460: int start_offset = pos - 4;
2461:
2462: if (tag == 0xffffffff) {
2463: // indirection
2464: return read_indirect_value();
2465: } else if (tag == 0x00000000) {
2466: // null tag, explicit representation of null value
2467: return null;
2468: }
2469:
2470: String codebase = ((tag & 1) != 0) ? read_codebase() : null;
2471: chunkedValue = ((tag & 8) != 0);
2472:
2473: int theTag = tag;
2474: tag = tag & 0xfffffff6;
2475:
2476: if (tag == 0x7fffff00) {
2477: java.io.Serializable result = factory.read_value(this );
2478:
2479: if (result != null) {
2480: getValueMap().put(ObjectUtil.newInteger(start_offset),
2481: result);
2482: }
2483:
2484: return result;
2485: } else if (tag == 0x7fffff02) {
2486: // Read value according to type information.
2487: // Possible optimization: ignore type info and use factory for
2488: // reading the value anyway, since the type information is
2489: // most likely redundant.
2490: return read_typed_value(start_offset, codebase);
2491: } else {
2492: throw new MARSHAL("unknown value tag: 0x"
2493: + Integer.toHexString(theTag) + " (offset=0x"
2494: + Integer.toHexString(start_offset) + ")");
2495: }
2496: }
2497:
2498: /**
2499: * Immediately reads a value from this stream; i.e. without any
2500: * repository id preceding it. The expected type of the value is given
2501: * by `repository_id', and the index at which the value started is
2502: * `index'.
2503: */
2504: private java.io.Serializable read_untyped_value(
2505: final String[] repository_ids, final int index,
2506: final String codebase) {
2507: java.io.Serializable result = null;
2508:
2509: if (chunkedValue || valueNestingLevel > 0) {
2510: valueNestingLevel++;
2511: int chunk_size_tag = readChunkSizeTag();
2512: chunk_end_pos = pos + chunk_size_tag;
2513: }
2514:
2515: for (int i = 0; i < repository_ids.length; i++) {
2516: if (repository_ids[i]
2517: .equals("IDL:omg.org/CORBA/WStringValue:1.0")) {
2518: // special handling of strings, according to spec
2519: result = read_wstring();
2520: break;
2521: } else if (repository_ids[i]
2522: .startsWith("RMI:javax.rmi.CORBA.ClassDesc:")) {
2523: // special handling of java.lang.Class instances
2524: final String classCodebase = (String) read_value(String.class);
2525: final String reposId = (String) read_value(String.class);
2526: final String className = org.jacorb.ir.RepositoryID
2527: .className(reposId, null);
2528:
2529: try {
2530: result = loadClass(className, classCodebase);
2531: } catch (ClassNotFoundException e) {
2532: if (i < repository_ids.length - 1) {
2533: continue;
2534: }
2535:
2536: throw new MARSHAL("class not found: " + className);
2537: }
2538: break;
2539: } else if (repository_ids[i].startsWith("IDL:")) {
2540: org.omg.CORBA.portable.ValueFactory factory = ((org.omg.CORBA_2_3.ORB) orb())
2541: .lookup_value_factory(repository_ids[i]);
2542:
2543: if (factory != null) {
2544: currentValueIndex = index;
2545: result = factory.read_value(this );
2546: break;
2547: }
2548:
2549: if (i < repository_ids.length - 1) {
2550: continue;
2551: }
2552:
2553: throw new MARSHAL("No factory found for: "
2554: + repository_ids[0]);
2555: } else // RMI
2556: {
2557: final String className = org.jacorb.ir.RepositoryID
2558: .className(repository_ids[i], null);
2559:
2560: try {
2561: final Class clazz = loadClass(className, codebase);
2562:
2563: if (IDLEntity.class.isAssignableFrom(clazz)) {
2564: java.lang.reflect.Method readMethod = null;
2565: if (clazz != org.omg.CORBA.Any.class) {
2566: String helperClassName = clazz.getName()
2567: + "Helper";
2568:
2569: try {
2570: final ClassLoader classLoader = clazz
2571: .getClassLoader();
2572: final Class helperClass;
2573: if (classLoader == null) {
2574: helperClass = ObjectUtil
2575: .classForName(helperClassName);
2576: } else {
2577: helperClass = classLoader
2578: .loadClass(helperClassName);
2579: }
2580:
2581: Class[] paramTypes = { org.omg.CORBA.portable.InputStream.class };
2582: readMethod = helperClass.getMethod(
2583: "read", paramTypes);
2584: } catch (ClassNotFoundException e) {
2585: throw new MARSHAL(
2586: "Error loading class "
2587: + helperClassName
2588: + ": " + e);
2589: } catch (NoSuchMethodException e) {
2590: throw new MARSHAL(
2591: "No read method in helper class "
2592: + helperClassName
2593: + ": " + e);
2594: }
2595: }
2596:
2597: if (readMethod == null) {
2598: result = read_any();
2599: } else {
2600: try {
2601: result = (java.io.Serializable) readMethod
2602: .invoke(
2603: null,
2604: new java.lang.Object[] { this });
2605: } catch (IllegalAccessException e) {
2606: throw new MARSHAL("Internal error: "
2607: + e);
2608: } catch (java.lang.reflect.InvocationTargetException e) {
2609: throw new MARSHAL(
2610: "Exception unmarshaling IDLEntity: "
2611: + e
2612: .getTargetException());
2613: }
2614: }
2615: } else {
2616: result = ValueHandler.readValue(this , index,
2617: clazz, repository_ids[i], null);
2618: }
2619: } catch (ClassNotFoundException e) {
2620: if (i < repository_ids.length - 1) {
2621: continue;
2622: }
2623:
2624: throw new MARSHAL("class not found: " + className);
2625: }
2626: }
2627: }
2628:
2629: // value type instances may be null...
2630: if (result != null) {
2631: getValueMap().put(ObjectUtil.newInteger(index), result);
2632: }
2633:
2634: return result;
2635: }
2636:
2637: /** Load the value's class, using the context class loader
2638: * of the current thread if possible. Here's Francisco
2639: * Reverbel's <reverbel@ime.usp.br> explanation of why
2640: * this is needed in JBoss:
2641: *
2642: * "It seems that ValueHandler.loadClass() uses the thread
2643: * context classloader only after it looks for other
2644: * classloaders in the call stack (weird). In some
2645: * situations (when EJBs are undeployed and then
2646: * redeployed) it finds in the call stack a classloader
2647: * used for an undeployed EJB. A value of class Foo is
2648: * then unmarshalled with type
2649: * classloaderOfEJB1:Foo, when the expected type is
2650: * classloaderOfEJB2:Foo. I am getting ClassCastExceptions is this
2651: * situation.
2652: * Explicitly using the thread context class loader in the
2653: * first place solves the problem."
2654: */
2655: private Class loadClass(String className, final String codebase)
2656: throws ClassNotFoundException {
2657: Class clazz;
2658: //#ifjdk 1.2
2659: ClassLoader clazzLoader = Thread.currentThread()
2660: .getContextClassLoader();
2661: //#else
2662: //# ClassLoader ctxcl = null;
2663: //#endif
2664:
2665: if (clazzLoader == null) {
2666: clazz = ValueHandler.loadClass(className, codebase, null);
2667: } else {
2668: try {
2669: clazz = clazzLoader.loadClass(className);
2670: } catch (ClassNotFoundException e) {
2671: clazz = ValueHandler.loadClass(className, codebase,
2672: null);
2673: }
2674: }
2675: return clazz;
2676: }
2677:
2678: /**
2679: * try to read in the chunk size.
2680: * special handling if there's no chunk size
2681: * in the stream.
2682: */
2683: private int readChunkSizeTag() {
2684: int savedPos = pos;
2685: int savedIndex = index;
2686: int chunk_size_tag = read_long();
2687:
2688: if (!sunInteropFix || chunk_size_tag > 0
2689: && chunk_size_tag < MAX_BLOCK_SIZE) {
2690: // looks like the correct chunk size
2691: return chunk_size_tag;
2692: }
2693:
2694: // reset buffer
2695: pos = savedPos;
2696: index = savedIndex;
2697: return MAX_BLOCK_SIZE;
2698: }
2699:
2700: /**
2701: * Reads a value with type information, i.e. one that is preceded
2702: * by a single RepositoryID. It is assumed that the tag and the codebase
2703: * of the value have already been read.
2704: */
2705: private java.io.Serializable read_typed_value(final int index,
2706: final String codebase) {
2707: return read_untyped_value(
2708: new String[] { read_repository_id() }, index, codebase);
2709: }
2710:
2711: /**
2712: * Reads a value with type information, i.e. one that is preceded
2713: * by an array of RepositoryIDs. It is assumed that the tag and the codebase
2714: * of the value have already been read.
2715: */
2716: private java.io.Serializable read_multi_typed_value(
2717: final int index, final String codebase) {
2718: int id_count = read_long();
2719: String[] ids = new String[id_count];
2720:
2721: for (int i = 0; i < id_count; i++) {
2722: ids[i] = read_repository_id();
2723: }
2724:
2725: return read_untyped_value(ids, index, codebase);
2726: }
2727:
2728: /**
2729: * Reads a RepositoryID from the buffer, either directly or via
2730: * indirection.
2731: */
2732: private String read_repository_id() {
2733: int tag = read_long();
2734: if (tag == 0xffffffff) {
2735: // indirection
2736: int index = read_long();
2737: index = index + pos - 4;
2738:
2739: String repId = (String) getRepIdMap().get(
2740: ObjectUtil.newInteger(index));
2741: if (repId == null) {
2742: throw new MARSHAL("stale RepositoryID indirection");
2743: }
2744: return repId;
2745: }
2746:
2747: // a new id
2748: pos -= 4;
2749: index -= 4;
2750: int start_offset = pos;
2751: String repId = read_string();
2752:
2753: getRepIdMap().put(ObjectUtil.newInteger(start_offset), repId);
2754: return repId;
2755: }
2756:
2757: /**
2758: * Reads a codebase from the buffer, either directly or via
2759: * indirection.
2760: */
2761: private String read_codebase() {
2762: int tag = read_long();
2763:
2764: if (tag == 0xffffffff) {
2765: // indirection
2766: int index = read_long();
2767: index = index + pos - 4;
2768: String codebase = (String) getCodebaseMap().get(
2769: ObjectUtil.newInteger(index));
2770: if (codebase == null) {
2771: throw new MARSHAL("stale codebase indirection");
2772: }
2773:
2774: return codebase;
2775: }
2776: // a new codebase string
2777: pos -= 4;
2778: index -= 4;
2779: int start_offset = pos;
2780: String codebase = read_string();
2781: getCodebaseMap().put(ObjectUtil.newInteger(start_offset),
2782: codebase);
2783: return codebase;
2784: }
2785:
2786: /**
2787: * Reads an indirect value from this stream. It is assumed that the
2788: * value tag (0xffffffff) has already been read.
2789: */
2790: private java.io.Serializable read_indirect_value() {
2791: // indirection
2792: int index = read_long();
2793: index = index + pos - 4;
2794: java.lang.Object value = getValueMap().get(
2795: ObjectUtil.newInteger(index));
2796:
2797: if (value == null) {
2798: // Java to IDL Language Mapping, v1.1, page 1-44:
2799: //
2800: // "The ValueHandler object may receive an IndirectionException
2801: // from the ORB stream. The ORB input stream throws this exception
2802: // when it is called to unmarshal a value encoded as an indirection
2803: // that is in the process of being unmarshaled. This can occur when
2804: // the ORB stream calls the ValueHandler object to unmarshal an RMI
2805: // value whose state contains a recursive reference to itself.
2806: // Because the top-level ValueHandler.readValue call has not yet
2807: // returned a value, the ORB stream's indirection table contains no
2808: // entry for an object with the stream offset specified by the
2809: // indirection tag. This stream offset is returned in the
2810: // exception's offset field."
2811:
2812: throw new org.omg.CORBA.portable.IndirectionException(index);
2813: }
2814:
2815: return (java.io.Serializable) value;
2816: }
2817:
2818: private String validateName(String name) {
2819: if (name != null && name.length() == 0) {
2820: return null;
2821: }
2822: return name;
2823: }
2824:
2825: private String validateID(String id) {
2826: if (id == null || id.length() == 0) {
2827: return "IDL:";
2828: }
2829: return id;
2830: }
2831:
2832: /**
2833: * Reads an abstract interface from this stream. The abstract interface
2834: * Reads an abstract interface from this stream. The abstract interface
2835: * appears as a union with a boolean discriminator, which is true if the
2836: * union contains a CORBA object reference, or false if the union contains
2837: * a value.
2838: */
2839: public java.lang.Object read_abstract_interface() {
2840: return read_boolean() ? (java.lang.Object) read_Object()
2841: : (java.lang.Object) read_value();
2842: }
2843:
2844: /**
2845: * Reads an abstract interface from this stream. The abstract interface
2846: * appears as a union with a boolean discriminator, which is true if the
2847: * union contains a CORBA object reference, or false if the union contains
2848: * a value.
2849: */
2850: public java.lang.Object read_abstract_interface(
2851: final java.lang.Class clazz) {
2852: return read_boolean() ? (java.lang.Object) read_Object(clazz)
2853: : (java.lang.Object) read_value(clazz);
2854: }
2855:
2856: public int get_pos() {
2857: return pos;
2858: }
2859:
2860: /**
2861: * Stores `value' into this stream's valueMap. This is provided
2862: * as a callback for value factories, so that a value factory can
2863: * store an object into the map before actually reading its state.
2864: * This is essential for unmarshalling recursive values.
2865: */
2866: public void register_value(final java.io.Serializable value) {
2867: getValueMap().put(ObjectUtil.newInteger(currentValueIndex),
2868: value);
2869: }
2870:
2871: /**
2872: * <code>updateMutatorConnection</code> is an accessor that updates the
2873: * ior mutator.
2874: *
2875: * By making callers pass in a GIOPConnection not a transport this allows
2876: * callers to not have to call getTransport which would require a synchronized
2877: * lock. Therefore if the mutator has not been enabled this is effectively a
2878: * NOP.
2879: *
2880: * @param connection an <code>org.omg.ETF.Connection</code> value
2881: */
2882: public void updateMutatorConnection(GIOPConnection connection) {
2883: if (isMutatorEnabled) {
2884: mutator.updateConnection(connection.getTransport());
2885: }
2886: }
2887:
2888: /**
2889: * <code>Pair</code> is merely a private storage class used by
2890: * {@link #cachedTypecodes}.
2891: */
2892: private static final class Pair {
2893: /**
2894: * <code>first</code> is the typecode we are caching.
2895: */
2896: public final org.omg.CORBA.TypeCode typeCode;
2897: /**
2898: * <code>second</code> is the location the original typecode was found.
2899: */
2900: public final Integer position;
2901:
2902: /**
2903: * Create a new <code>Pair</code>.
2904: *
2905: * @param typeCode an <code>org.omg.CORBA.TypeCode</code> value
2906: * @param position an <code>Integer</code> value
2907: */
2908: public Pair(org.omg.CORBA.TypeCode typeCode, Integer position) {
2909: this .typeCode = typeCode;
2910: this .position = position;
2911: }
2912:
2913: /**
2914: * <code>toString</code> used for debugging ONLY.
2915: *
2916: * @return a <code>String</code> value
2917: */
2918: public String toString() {
2919: return (typeCode + " and " + position);
2920: }
2921: }
2922: }
|