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.*;
0024: import java.math.BigDecimal;
0025: import java.util.*;
0026:
0027: import org.apache.avalon.framework.configuration.*;
0028:
0029: import org.jacorb.ir.RepositoryID;
0030: import org.jacorb.orb.giop.CodeSet;
0031: import org.jacorb.orb.giop.GIOPConnection;
0032: import org.jacorb.util.ValueHandler;
0033: import org.jacorb.util.ObjectUtil;
0034:
0035: import org.omg.CORBA.BAD_PARAM;
0036: import org.omg.CORBA.CODESET_INCOMPATIBLE;
0037: import org.omg.CORBA.DATA_CONVERSION;
0038: import org.omg.CORBA.INTERNAL;
0039: import org.omg.CORBA.MARSHAL;
0040: import org.omg.CORBA.NO_IMPLEMENT;
0041: import org.omg.CORBA.TCKind;
0042: import org.omg.CORBA.TypeCodePackage.BadKind;
0043: import org.omg.CORBA.TypeCodePackage.Bounds;
0044: import org.omg.IOP.IOR;
0045: import org.omg.IOP.IORHelper;
0046: import org.omg.IOP.TaggedProfile;
0047:
0048: /**
0049: * @author Gerald Brose, 1999
0050: * @version $Id: CDROutputStream.java,v 1.122 2006/11/30 13:11:07 alphonse.bendt Exp $
0051: *
0052: * A stream for CDR marshalling.
0053: *
0054: */
0055:
0056: public class CDROutputStream extends
0057: org.omg.CORBA_2_3.portable.OutputStream {
0058: private final static IOR null_ior = new IOR("",
0059: new TaggedProfile[0]);
0060:
0061: /** needed for alignment purposes */
0062: private int index;
0063:
0064: /** the current write position in the buffer */
0065: private int pos;
0066:
0067: /** the number of bytes that will only make up the final buffer
0068: size, but that have not yet been written */
0069: private int deferred_writes;
0070:
0071: private BufferManager bufMgr;
0072: protected byte[] buffer;
0073:
0074: private boolean closed;
0075:
0076: /* character encoding code sets for char and wchar, default ISO8859_1 */
0077: private int codeSet = CodeSet.getTCSDefault();
0078: private int codeSetW = CodeSet.getTCSWDefault();
0079:
0080: private int encaps_start = -1;
0081:
0082: /**
0083: * <code>encaps_stack</code> is used to store encapsulations. Do NOT
0084: * access this variable directly. It is initialized on demand. Use the
0085: * method {@link #getEncapsStack() getEncapsStack()}
0086: */
0087: private Stack encaps_stack;
0088:
0089: /**
0090: * <code>valueMap</code> is used to maps all value objects that have
0091: * already been written to this stream to their position within the
0092: * buffer. The position is stored as a java.lang.Integer. Do NOT access
0093: * this variable directly. It is initialised on demand. Use the method
0094: * {@link #getValueMap() getValueMap()}
0095: */
0096: private Map valueMap;
0097:
0098: /**
0099: * <code>repIdMap</code> is used to map all repository ids that have already
0100: * been written to this stream to their position within the buffer. The
0101: * position is stored as a java.lang.Integer. Do NOT access this variable
0102: * directly. It is initialised on demand. Use the method
0103: * {@link #getRepIdMap() getRepIdMap()}
0104: */
0105: private Map repIdMap;
0106:
0107: /**
0108: * <code>codebaseMap</code> is used to maps all codebase strings that have
0109: * already been written to this stream to their position within the buffer.
0110: * The position is stored as a java.lang.Integer. Do NOT access this variable
0111: * directly. It is initialised on demand. Use the method
0112: * {@link #getCodebaseMap() getCodebaseMap()}
0113: */
0114: private Map codebaseMap;
0115:
0116: /**
0117: * <code>cachedTypecodes</code> is used to cache compacted typecodes when
0118: * writing to the stream. This variable is initialised on demand.
0119: */
0120: private Map cachedTypecodes;
0121:
0122: /**
0123: * This Map is basically a one-entry map pool to be used in
0124: * write_TypeCode() as the repeatedTCMap.
0125: */
0126: private Map repeatedTCMap;
0127:
0128: /**
0129: * This Map is basically a one-entry map pool to be used in
0130: * write_TypeCode() as the recursiveTCMap.
0131: */
0132: private Map recursiveTCMap;
0133:
0134: /** Remembers the starting position of the current chunk. */
0135: private int chunk_size_tag_pos = -1; // -1 means we're not within a chunk
0136: private int chunk_size_tag_index;
0137: private int chunk_octets_pos;
0138:
0139: /** Nesting level of chunked valuetypes */
0140: private int valueNestingLevel = 0;
0141:
0142: /** Nesting level of calls write_value_internal */
0143: private int writeValueNestingLevel = 0;
0144:
0145: /** True if write_value_internal called writeReplace */
0146: private boolean writeReplaceCalled = false;
0147:
0148: private final List deferredArrayQueue = new ArrayList();
0149:
0150: private org.omg.CORBA.ORB orb = null;
0151:
0152: protected int giop_minor = 2;
0153:
0154: /** The chunking flag is either 0 (no chunking) or 0x00000008 (chunking),
0155: to be bitwise or'ed into value tags. */
0156: private int chunkingFlag = 0;
0157:
0158: /**
0159: * <code>mutator</code> is a pluggable IOR mutator.
0160: */
0161: private IORMutator mutator;
0162:
0163: private boolean isMutatorEnabled;
0164:
0165: /**
0166: * <code>codesetEnabled</code> denotes whether codeset marshalling is enabled.
0167: */
0168: private boolean codesetEnabled;
0169:
0170: /** configurable properties */
0171: private boolean useBOM = false;
0172: private boolean chunkCustomRmiValuetypes = false;
0173: private int compactTypeCodes = 0;
0174: private boolean useIndirection = true;
0175:
0176: /**
0177: * This stream is self-configuring, i.e. configure() is private
0178: * and only called from the constructor
0179: *
0180: * TODO this led to situations were streams weren't configured properly
0181: * (see callers of configure) so i changed the method to be public.
0182: * should be fixed. alphonse 11.05.2006
0183: */
0184:
0185: public void configure(Configuration configuration) {
0186: codesetEnabled = configuration.getAttribute("jacorb.codeset",
0187: "on").equals("on");
0188:
0189: useBOM = configuration.getAttribute("jacorb.use_bom", "off")
0190: .equals("on");
0191:
0192: chunkCustomRmiValuetypes = configuration.getAttribute(
0193: "jacorb.interop.chunk_custom_rmi_valuetypes", "off")
0194: .equals("on");
0195: compactTypeCodes = configuration.getAttributeAsInteger(
0196: "jacorb.compactTypecodes", 0);
0197:
0198: useIndirection = !(configuration.getAttribute(
0199: "jacorb.interop.indirection_encoding_disable", "off")
0200: .equals("on"));
0201:
0202: isMutatorEnabled = configuration.getAttribute(
0203: "jacorb.iormutator", "").length() > 0;
0204:
0205: if (isMutatorEnabled) {
0206: try {
0207: mutator = (IORMutator) ((org.jacorb.config.Configuration) configuration)
0208: .getAttributeAsObject("jacorb.iormutator");
0209: } catch (ConfigurationException e) {
0210: throw new RuntimeException();
0211: }
0212: }
0213:
0214: }
0215:
0216: private static class DeferredWriteFrame {
0217: public int write_pos = 0;
0218: public int start = 0;
0219: public int length = 0;
0220: public byte[] buf = null;
0221:
0222: public DeferredWriteFrame(int write_pos, int start, int length,
0223: byte[] buf) {
0224: super ();
0225:
0226: this .write_pos = write_pos;
0227: this .start = start;
0228: this .length = length;
0229: this .buf = buf;
0230: }
0231: }
0232:
0233: /**
0234: * OutputStreams created using the empty constructor are used for
0235: * in memory marshaling, but do not use the ORB's output buffer
0236: * manager. A stream created with this c'tor is not explicitly
0237: * configured, i.e. it will use default configuration only
0238: */
0239:
0240: public CDROutputStream() {
0241: super ();
0242: bufMgr = BufferManager.getInstance(); // the BufferManager will be configured by now!
0243: buffer = bufMgr.getPreferredMemoryBuffer();
0244: }
0245:
0246: /**
0247: * OutputStreams created using this constructor
0248: * are used also for in memory marshaling, but do use the
0249: * ORB's output buffer manager
0250: */
0251: public CDROutputStream(final org.omg.CORBA.ORB orb) {
0252: this ();
0253: if (orb != null) {
0254: this .orb = orb;
0255: configure(((org.jacorb.orb.ORB) orb).getConfiguration());
0256: }
0257: }
0258:
0259: /**
0260: * Class constructor setting the buffer size for the message and
0261: * the character encoding sets. A stream created with this c'tor
0262: * is not explicitly configured, i.e. it will use default
0263: * configuration only!
0264: */
0265:
0266: public CDROutputStream(final byte[] buf) {
0267: super ();
0268:
0269: bufMgr = BufferManager.getInstance();
0270: buffer = buf;
0271: }
0272:
0273: public org.omg.CORBA.ORB orb() {
0274: if (orb == null) {
0275: orb = org.omg.CORBA.ORB.init((String[]) null, null);
0276: }
0277: return orb;
0278: }
0279:
0280: /**
0281: * <code>getEncapsStack</code> is used to initialize encaps_stack
0282: * on demand.
0283: *
0284: * @return a <code>Stack</code> value
0285: */
0286: private Stack getEncapsStack() {
0287: if (encaps_stack == null) {
0288: encaps_stack = new Stack();
0289: }
0290: return encaps_stack;
0291: }
0292:
0293: /**
0294: * Gets the Map that is used to detect reference sharing when
0295: * marshaling valuetype instances.
0296: *
0297: * @return a <code>Map</code> value
0298: */
0299: private Map getValueMap() {
0300: if (valueMap == null) {
0301: valueMap = new IdentityHashMap();
0302: }
0303: return valueMap;
0304: }
0305:
0306: /**
0307: * Gets the Map that is used to implement indirections for RepositoryIDs.
0308: *
0309: * @return a <code>Map</code> value
0310: */
0311: private Map getRepIdMap() {
0312: if (repIdMap == null) {
0313: repIdMap = new HashMap();
0314: }
0315: return repIdMap;
0316: }
0317:
0318: /**
0319: * Gets the Map that is used to implement indirections for Codebase
0320: * specifications.
0321: *
0322: * @return a <code>Map</code> value
0323: */
0324: private Map getCodebaseMap() {
0325: if (codebaseMap == null) {
0326: codebaseMap = new HashMap();
0327: }
0328: return codebaseMap;
0329: }
0330:
0331: /**
0332: * write the contents of this CDR stream to the output stream,
0333: * includes all deferred writes (e.g., for byte arrays)...
0334: * called by, e.g. GIOPConnection to write directly to the
0335: * wire.
0336: */
0337:
0338: public void write(OutputStream out, int start, int length)
0339: throws IOException {
0340: int write_idx = start;
0341: int read_idx = start;
0342:
0343: // needed to calculate the actual read position in the
0344: // current buffer,
0345: int skip_count = 0;
0346:
0347: int list_idx = 0;
0348:
0349: DeferredWriteFrame next_frame = null;
0350:
0351: if (deferredArrayQueue.size() > 0) {
0352: // find the first frame that falls within the current window,
0353: // i.e. that need s to be written
0354: next_frame = (DeferredWriteFrame) deferredArrayQueue
0355: .get(list_idx++);
0356:
0357: // skip all frames beginning before the current start pos, but
0358: // record their length
0359: while (next_frame.write_pos < start
0360: && list_idx < deferredArrayQueue.size()) {
0361: skip_count += next_frame.length;
0362: next_frame = (DeferredWriteFrame) deferredArrayQueue
0363: .get(list_idx++);
0364: }
0365:
0366: // skip
0367: if (next_frame.write_pos < start
0368: && list_idx >= deferredArrayQueue.size()) {
0369: skip_count += next_frame.length;
0370: next_frame = null;
0371: }
0372: }
0373:
0374: while (write_idx < start + length) {
0375: if (next_frame != null && write_idx == next_frame.write_pos) {
0376: if (!(next_frame.length <= start + length - write_idx)) {
0377: throw new MARSHAL("Deferred array does not fit");
0378: }
0379:
0380: // write a frame, i.e. a byte array
0381: out.write(next_frame.buf, next_frame.start,
0382: next_frame.length);
0383:
0384: // advance
0385: write_idx += next_frame.length;
0386:
0387: // clear the fram variable...
0388: next_frame = null;
0389:
0390: // and look up the next frame
0391: if (list_idx < deferredArrayQueue.size()) {
0392: next_frame = (DeferredWriteFrame) deferredArrayQueue
0393: .get(list_idx++);
0394: if (next_frame.write_pos > start + length) {
0395: // unset, frame is beyond our current reach
0396: next_frame = null;
0397: }
0398: }
0399: }
0400:
0401: if (write_idx < start + length) {
0402: // write data that was previously marshaled
0403:
0404: int write_now = Math.min(start + length,
0405: (next_frame != null ? next_frame.write_pos
0406: : start + length));
0407:
0408: write_now -= write_idx; // calculate length
0409:
0410: //
0411: out.write(buffer, read_idx - skip_count, write_now);
0412:
0413: // advance
0414: read_idx += write_now;
0415: write_idx += write_now;
0416: }
0417: }
0418: }
0419:
0420: public void setCodeSet(final int codeSet, final int codeSetWide) {
0421: this .codeSet = codeSet;
0422: this .codeSetW = codeSetWide;
0423: }
0424:
0425: public void setGIOPMinor(final int giop_minor) {
0426: this .giop_minor = giop_minor;
0427: }
0428:
0429: public int getGIOPMinor() {
0430: return giop_minor;
0431: }
0432:
0433: public void close() {
0434: // Don't need to call super.close as super is noop.
0435: if (closed) {
0436: return;
0437: }
0438:
0439: bufMgr.returnBuffer(buffer, true);
0440:
0441: buffer = null;
0442: closed = true;
0443: deferredArrayQueue.clear();
0444: deferred_writes = 0;
0445: }
0446:
0447: /**
0448: * This version of check does both array length checking and
0449: * data type alignment. It is a convenience method.
0450: */
0451: private final void check(final int i, final int align) {
0452: int remainder = align - (index % align);
0453:
0454: check(i + remainder);
0455:
0456: if (remainder != align) {
0457: // Clear padding. Allowing for possible buffer end.
0458: int topad = Math.min(buffer.length - pos, 8);
0459: int j = 0;
0460: switch (topad) {
0461: case 8:
0462: buffer[pos + j++] = (byte) 0;
0463: case 7:
0464: buffer[pos + j++] = (byte) 0;
0465: case 6:
0466: buffer[pos + j++] = (byte) 0;
0467: case 5:
0468: buffer[pos + j++] = (byte) 0;
0469: case 4:
0470: buffer[pos + j++] = (byte) 0;
0471: case 3:
0472: buffer[pos + j++] = (byte) 0;
0473: case 2:
0474: buffer[pos + j++] = (byte) 0;
0475: case 1:
0476: buffer[pos + j++] = (byte) 0;
0477: }
0478:
0479: index += remainder;
0480: pos += remainder;
0481: }
0482: }
0483:
0484: /**
0485: * check whether the current buffer is big enough to receive
0486: * i more bytes. If it isn't, get a bigger buffer.
0487: */
0488:
0489: private final void check(final int i) {
0490: if (buffer == null || (pos + i + 2) > buffer.length) {
0491: final byte[] new_buf = bufMgr.getBuffer(pos + i + 2, true);
0492:
0493: if (buffer != null) {
0494: System.arraycopy(buffer, 0, new_buf, 0, pos);
0495: }
0496: // Change buffer size so return the old one.
0497: bufMgr.returnBuffer(buffer, true);
0498:
0499: buffer = new_buf;
0500: }
0501: }
0502:
0503: private final static void _write4int(final byte[] buf,
0504: final int _pos, final int value) {
0505: buf[_pos] = (byte) ((value >> 24) & 0xFF);
0506: buf[_pos + 1] = (byte) ((value >> 16) & 0xFF);
0507: buf[_pos + 2] = (byte) ((value >> 8) & 0xFF);
0508: buf[_pos + 3] = (byte) (value & 0xFF);
0509: }
0510:
0511: /**
0512: * Start a CDR encapsulation. All subsequent writes
0513: * will place data in the encapsulation until
0514: * endEncapsulation is called. This will write
0515: * the size of the encapsulation.
0516: */
0517:
0518: public final void beginEncapsulation() {
0519: // align to the next four byte boundary
0520: // as a preparation for writing the size
0521: // integer (which we don't know before the
0522: // encapsulation is closed)
0523:
0524: check(8, 4);
0525:
0526: // leave 4 bytes for the encaps. size that
0527: // is to be written later
0528:
0529: pos += 4;
0530: index += 4;
0531:
0532: /* Because encapsulations can be nested, we need to
0533: remember the beginnning of the enclosing
0534: encapsulation (or -1 if we are in the outermost encapsulation)
0535: Also, remember the current index and the indirection maps because
0536: we need to restore these when closing the encapsulation */
0537:
0538: getEncapsStack().push(
0539: new EncapsInfo(index, encaps_start, getValueMap(),
0540: getRepIdMap(), getCodebaseMap()));
0541:
0542: // set up new indirection maps for this encapsulation
0543:
0544: valueMap = new IdentityHashMap();
0545: repIdMap = new HashMap();
0546: codebaseMap = new HashMap();
0547:
0548: // the start of this encapsulation
0549:
0550: encaps_start = pos;
0551: beginEncapsulatedArray();
0552: }
0553:
0554: /**
0555: * Can be used locally for data type conversions
0556: * without preceeding call to beginEncapsulation, i.e.
0557: * without a leading long that indicates the size.
0558: */
0559:
0560: public final void beginEncapsulatedArray() {
0561: /* set the index for alignment to 0, i.e. align relative to the
0562: beginning of the encapsulation */
0563: resetIndex();
0564:
0565: // byte_order flag set to FALSE
0566:
0567: buffer[pos++] = 0;
0568: index++;
0569: }
0570:
0571: /**
0572: * Terminate the encapsulation by writing its length
0573: * to its beginning.
0574: */
0575:
0576: public final void endEncapsulation() {
0577: if (encaps_start == -1) {
0578: throw new MARSHAL("Too many end-of-encapsulations");
0579: }
0580:
0581: if (encaps_stack == null) {
0582: throw new MARSHAL(
0583: "Internal Error - closeEncapsulation failed");
0584: }
0585:
0586: // determine the size of this encapsulation
0587:
0588: int encaps_size = pos - encaps_start;
0589:
0590: // insert the size integer into the appropriate place
0591:
0592: buffer[encaps_start - 4] = (byte) ((encaps_size >>> 24) & 0xFF);
0593: buffer[encaps_start - 3] = (byte) ((encaps_size >>> 16) & 0xFF);
0594: buffer[encaps_start - 2] = (byte) ((encaps_size >>> 8) & 0xFF);
0595: buffer[encaps_start - 1] = (byte) (encaps_size & 0xFF);
0596:
0597: /* restore index and encaps_start information and indirection maps */
0598:
0599: EncapsInfo ei = (EncapsInfo) getEncapsStack().pop();
0600: encaps_start = ei.start;
0601: index = ei.index + encaps_size;
0602: valueMap = ei.valueMap;
0603: repIdMap = ei.repIdMap;
0604: codebaseMap = ei.codebaseMap;
0605: }
0606:
0607: public byte[] getBufferCopy() {
0608: final ByteArrayOutputStream bos = new ByteArrayOutputStream(
0609: size());
0610:
0611: try {
0612: write(bos, 0, size());
0613: } catch (IOException e) {
0614: throw new INTERNAL("should not happen: " + e.toString());
0615: }
0616:
0617: return bos.toByteArray();
0618: }
0619:
0620: private void resetIndex() {
0621: index = 0;
0622: }
0623:
0624: public int size() {
0625: return pos + deferred_writes;
0626: }
0627:
0628: public void reset() {
0629: deferredArrayQueue.clear();
0630: pos = 0;
0631: deferred_writes = 0;
0632: index = 0;
0633: }
0634:
0635: protected void finalize() throws Throwable {
0636: try {
0637: bufMgr.returnBuffer(buffer, true);
0638: } finally {
0639: super .finalize();
0640: }
0641: }
0642:
0643: public final void skip(final int step) {
0644: pos += step;
0645: index += step;
0646: }
0647:
0648: public final void reduceSize(final int amount) {
0649: pos -= amount;
0650: }
0651:
0652: /**
0653: * Add <tt>amount</tt> empty space
0654: */
0655:
0656: public final void increaseSize(final int amount) {
0657: check(amount);
0658:
0659: pos += amount;
0660: }
0661:
0662: public void setBuffer(final byte[] b) {
0663: bufMgr.returnBuffer(buffer, true);
0664:
0665: buffer = b;
0666:
0667: reset();
0668: }
0669:
0670: // For appligator
0671:
0672: public void setBufferWithoutReset(byte[] b, int size) {
0673: close();
0674: buffer = b;
0675: pos = size;
0676: }
0677:
0678: /**************************************************
0679: * The following operations are from OutputStream *
0680: **************************************************/
0681:
0682: public org.omg.CORBA.portable.InputStream create_input_stream() {
0683: if (deferred_writes > 0) {
0684: ByteArrayOutputStream baos = new ByteArrayOutputStream(
0685: index + 1);
0686: try {
0687: write(baos, 0, index);
0688: } catch (IOException e) {
0689: throw new MARSHAL(e.toString());
0690: }
0691: return new CDRInputStream(orb(), baos.toByteArray());
0692: }
0693:
0694: byte[] result = new byte[index + 1];
0695: System.arraycopy(buffer, 0, result, 0, result.length);
0696: return new CDRInputStream(orb, result);
0697: }
0698:
0699: public final void write_any(final org.omg.CORBA.Any value) {
0700: write_TypeCode(value.type());
0701: value.write_value(this );
0702: }
0703:
0704: public final void write_boolean(final boolean value) {
0705: check(1);
0706:
0707: if (value) {
0708: buffer[pos++] = 1;
0709: } else {
0710: buffer[pos++] = 0;
0711: }
0712: index++;
0713: }
0714:
0715: public final void write_boolean_array(final boolean[] value,
0716: final int offset, final int length) {
0717: if (value != null) {
0718: //no alignment necessary
0719: check(length);
0720:
0721: for (int i = offset; i < offset + length; i++) {
0722: if (value[i]) {
0723: buffer[pos++] = 1;
0724: } else {
0725: buffer[pos++] = 0;
0726: }
0727: }
0728: index += length;
0729: }
0730: }
0731:
0732: /**
0733: * <code>write_char</code> writes a character to the output stream. If
0734: * codeset translation is active then it will use String and an encoding to
0735: * get the bytes. It can then do a test for whether to throw DATA_CONVERSION.
0736: *
0737: * @param c a <code>char</code> value
0738: */
0739: public final void write_char(final char c) {
0740: // According to 15.3.1.6 of CORBA 3.0 'a single instance of the char type
0741: // may only hold one octet of any multi-byte character encoding.'
0742: // Therefore we ensure that we are in the single byte range i.e.
0743: // less than 0xFF or \377.
0744: if (c > '\377') {
0745: throw new DATA_CONVERSION("Char " + c + " out of range");
0746: }
0747:
0748: check(1);
0749: buffer[pos++] = (byte) c;
0750: index++;
0751: }
0752:
0753: public final void write_char_array(final char[] value,
0754: final int offset, final int length) {
0755: if (value == null) {
0756: throw new MARSHAL("Cannot marshall null array.");
0757: } else if (offset + length > value.length || length < 0
0758: || offset < 0) {
0759: throw new MARSHAL(
0760: "Cannot marshall as indices for array are out bounds.");
0761: }
0762:
0763: check(length);
0764:
0765: for (int i = offset; i < length + offset; i++) {
0766: if (value[i] > '\377') {
0767: throw new DATA_CONVERSION("Char " + value[i]
0768: + " out of range");
0769: }
0770: buffer[pos++] = (byte) value[i];
0771: }
0772: index += length;
0773: }
0774:
0775: /**
0776: * <code>write_string</code> writes a string to the output stream. It is
0777: * optimised for whether it is writing a blank string or for whether codeset
0778: * translation is active.
0779: *
0780: * @param s a <code>String</code> value
0781: */
0782: public final void write_string(final String s) {
0783: // size leaves room for ulong, plus the string itself (one or more
0784: // bytes per char in the string, depending on the codeset), plus the
0785: // terminating NUL char
0786: int size;
0787: // sizePosition is the position in the buffer for the size to be
0788: // written.
0789: int sizePosition;
0790:
0791: if (s == null) {
0792: throw new MARSHAL("Cannot marshall null string.");
0793: }
0794:
0795: if (codesetEnabled) {
0796: // in the worst case (UTF-8) a string char might take up to 3 bytes
0797: size = 4 + 3 * s.length() + 1;
0798: } else {
0799: // just one byte per string char
0800: size = 4 + s.length() + 1;
0801: }
0802: check(size, 4);
0803: sizePosition = pos;
0804:
0805: pos += 4;
0806: index += 4;
0807:
0808: for (int i = 0; i < s.length(); i++) {
0809: if (codesetEnabled) {
0810: write_char_i(s.charAt(i), false, false, codeSet);
0811: } else {
0812: buffer[pos++] = (byte) s.charAt(i);
0813: index++;
0814: }
0815: }
0816:
0817: buffer[pos++] = (byte) 0; //terminating NUL char
0818: index++;
0819:
0820: // Now write the size back in.
0821: size = pos - (sizePosition + 4); // compute translated size
0822:
0823: _write4int(buffer, sizePosition, size);
0824: }
0825:
0826: public final void write_wchar(final char c) {
0827: check(3);
0828: write_char_i(c, useBOM, true, codeSetW);//with length indicator
0829: }
0830:
0831: // Used by both write_wchar/wstring and write_string
0832: private final void write_char_i(final char c,
0833: final boolean write_bom,
0834: final boolean write_length_indicator, final int cs) {
0835: // alignment/check must happen prior to calling.
0836: switch (cs) {
0837: case CodeSet.ISO8859_1: {
0838: buffer[pos++] = (byte) c;
0839: index++;
0840: break;
0841: }
0842: case CodeSet.UTF8: {
0843: if (c <= 0x007F) {
0844: if (giop_minor == 2 && write_length_indicator) {
0845: //the chars length in bytes
0846: buffer[pos++] = (byte) 1;
0847: index++;
0848: }
0849:
0850: buffer[pos++] = (byte) c;
0851: index++;
0852: } else if (c > 0x07FF) {
0853: if (giop_minor == 2 && write_length_indicator) {
0854: //the chars length in bytes
0855: buffer[pos++] = (byte) 3;
0856: index++;
0857: }
0858:
0859: buffer[pos++] = (byte) (0xE0 | ((c >> 12) & 0x0F));
0860: buffer[pos++] = (byte) (0x80 | ((c >> 6) & 0x3F));
0861: buffer[pos++] = (byte) (0x80 | ((c >> 0) & 0x3F));
0862:
0863: index += 3;
0864: } else {
0865: if (giop_minor == 2 && write_length_indicator) {
0866: //the chars length in bytes
0867: buffer[pos++] = (byte) 2;
0868: index++;
0869: }
0870:
0871: buffer[pos++] = (byte) (0xC0 | ((c >> 6) & 0x1F));
0872: buffer[pos++] = (byte) (0x80 | ((c >> 0) & 0x3F));
0873:
0874: index += 2;
0875: }
0876: break;
0877: }
0878: case CodeSet.UTF16: {
0879: if (giop_minor == 2) {
0880: if (write_length_indicator) {
0881: //the chars length in bytes
0882: buffer[pos++] = (byte) 2;
0883: index++;
0884: }
0885:
0886: if (write_bom) {
0887: //big endian encoding
0888: buffer[pos++] = (byte) 0xFE;
0889: buffer[pos++] = (byte) 0xFF;
0890:
0891: index += 2;
0892: }
0893:
0894: //write unaligned
0895: buffer[pos++] = (byte) ((c >> 8) & 0xFF);
0896: buffer[pos++] = (byte) (c & 0xFF);
0897: index += 2;
0898: } else {
0899: //UTF-16 char is treated as an ushort (write aligned)
0900: write_short((short) c);
0901: }
0902:
0903: break;
0904: }
0905: default: {
0906: throw new CODESET_INCOMPATIBLE("Bad codeset: " + codeSet);
0907: }
0908: }
0909: }
0910:
0911: public final void write_wchar_array(final char[] value,
0912: final int offset, final int length) {
0913: if (value == null) {
0914: throw new MARSHAL("Null References");
0915: }
0916:
0917: check(length * 3);
0918:
0919: for (int i = offset; i < offset + length; i++) {
0920: write_wchar(value[i]);
0921: }
0922: }
0923:
0924: public final void write_wstring(final String s) {
0925: if (s == null) {
0926: throw new MARSHAL("Null References");
0927: }
0928:
0929: //size ulong + no of bytes per char (max 3 if UTF-8) +
0930: //terminating NUL
0931: check(4 + s.length() * 3 + 3, 4);
0932:
0933: int startPos = pos; // store position for length indicator
0934: pos += 4;
0935: index += 4; // reserve for length indicator
0936:
0937: //the byte order marker
0938: if (giop_minor == 2 && useBOM && s.length() > 0) {
0939: //big endian encoding
0940: buffer[pos++] = (byte) 0xFE;
0941: buffer[pos++] = (byte) 0xFF;
0942:
0943: index += 2;
0944: }
0945:
0946: // write characters in current wide encoding, add null terminator
0947: for (int i = 0; i < s.length(); i++) {
0948: write_char_i(s.charAt(i), false, false, codeSetW); //no BOM
0949: }
0950:
0951: if (giop_minor < 2) {
0952: //terminating NUL char
0953: write_char_i((char) 0, false, false, codeSetW); //no BOM
0954: }
0955:
0956: int str_size = 0;
0957: if (giop_minor == 2) {
0958: //size in bytes (without the size ulong)
0959: str_size = pos - startPos - 4;
0960: } else {
0961: if (codeSetW == CodeSet.UTF8) {
0962: //size in bytes (without the size ulong)
0963: str_size = pos - startPos - 4;
0964: } else if (codeSetW == CodeSet.UTF16) {
0965: //size in chars (+ NUL char)
0966: str_size = s.length() + 1;
0967: }
0968: }
0969:
0970: // write length indicator
0971: _write4int(buffer, startPos, str_size);
0972: }
0973:
0974: public final void write_double(final double value) {
0975: write_longlong(Double.doubleToLongBits(value));
0976: }
0977:
0978: public final void write_double_array(final double[] value,
0979: final int offset, final int length) {
0980: //if nothing has to be written, return, and especially DON'T
0981: //ALIGN
0982: if (length == 0) {
0983: return;
0984: }
0985:
0986: /* align to 8 byte boundary */
0987:
0988: check(7 + length * 8, 8);
0989:
0990: if (value != null) {
0991: for (int i = offset; i < offset + length; i++) {
0992: long d = Double.doubleToLongBits(value[i]);
0993: buffer[pos] = (byte) ((d >>> 56) & 0xFF);
0994: buffer[pos + 1] = (byte) ((d >>> 48) & 0xFF);
0995: buffer[pos + 2] = (byte) ((d >>> 40) & 0xFF);
0996: buffer[pos + 3] = (byte) ((d >>> 32) & 0xFF);
0997: buffer[pos + 4] = (byte) ((d >>> 24) & 0xFF);
0998: buffer[pos + 5] = (byte) ((d >>> 16) & 0xFF);
0999: buffer[pos + 6] = (byte) ((d >>> 8) & 0xFF);
1000: buffer[pos + 7] = (byte) (d & 0xFF);
1001: pos += 8;
1002: }
1003: index += 8 * length;
1004: }
1005: }
1006:
1007: public final void write_fixed(BigDecimal value, short digits,
1008: short scale) {
1009: write_fixed(value);
1010: }
1011:
1012: public final void write_fixed(final java.math.BigDecimal value) {
1013: String v = value.unscaledValue().toString();
1014: byte[] representation;
1015: int b, c;
1016:
1017: // Strip off any leading '-' from value to encode
1018:
1019: if (v.startsWith("-")) {
1020: v = v.substring(1);
1021: }
1022:
1023: if ((v.length() % 2) == 0) {
1024: representation = new byte[v.length() / 2 + 1];
1025: representation[0] = 0x00;
1026:
1027: for (int i = 0; i < v.length(); i++) {
1028: c = Character.digit(v.charAt(i), 10);
1029: b = representation[(1 + i) / 2] << 4;
1030: b |= c;
1031: representation[(1 + i) / 2] = (byte) b;
1032: }
1033: } else {
1034: representation = new byte[(v.length() + 1) / 2];
1035: for (int i = 0; i < v.length(); i++) {
1036: c = Character.digit(v.charAt(i), 10);
1037: b = representation[i / 2] << 4;
1038: b |= c;
1039: representation[i / 2] = (byte) b;
1040: }
1041: }
1042: b = representation[representation.length - 1] << 4;
1043:
1044: representation[representation.length - 1] = (byte) ((value
1045: .signum() < 0) ? (b | 0xD) : (b | 0xC));
1046:
1047: check(representation.length);
1048: System.arraycopy(representation, 0, buffer, pos,
1049: representation.length);
1050: index += representation.length;
1051: pos += representation.length;
1052: }
1053:
1054: public final void write_float(final float value) {
1055: write_long(Float.floatToIntBits(value));
1056: }
1057:
1058: public final void write_float_array(final float[] value,
1059: final int offset, final int length) {
1060: //if nothing has to be written, return, and especially DON'T
1061: //ALIGN
1062: if (length == 0) {
1063: return;
1064: }
1065:
1066: /* align to 4 byte boundary */
1067:
1068: check(3 + length * 4, 4);
1069:
1070: if (value != null) {
1071: for (int i = offset; i < offset + length; i++) {
1072: _write4int(buffer, pos, Float.floatToIntBits(value[i]));
1073: pos += 4;
1074: }
1075: index += 4 * length;
1076: }
1077: }
1078:
1079: public final void write_long(final int value) {
1080: check(7, 4);
1081:
1082: _write4int(buffer, pos, value);
1083:
1084: pos += 4;
1085: index += 4;
1086: }
1087:
1088: public final void write_long_array(final int[] value,
1089: final int offset, final int length) {
1090: //if nothing has to be written, return, and especially DON'T
1091: //ALIGN
1092: if (length == 0) {
1093: return;
1094: }
1095:
1096: /* align to 4 byte boundary */
1097:
1098: check(3 + length * 4, 4);
1099:
1100: int remainder = 4 - (index % 4);
1101: if (remainder != 4) {
1102: index += remainder;
1103: pos += remainder;
1104: }
1105:
1106: if (value != null) {
1107: for (int i = offset; i < offset + length; i++) {
1108: _write4int(buffer, pos, value[i]);
1109: pos += 4;
1110: }
1111: index += 4 * length;
1112: }
1113: }
1114:
1115: public final void write_longlong(final long value) {
1116: check(15, 8);
1117:
1118: buffer[pos] = (byte) ((value >>> 56) & 0xFF);
1119: buffer[pos + 1] = (byte) ((value >>> 48) & 0xFF);
1120: buffer[pos + 2] = (byte) ((value >>> 40) & 0xFF);
1121: buffer[pos + 3] = (byte) ((value >>> 32) & 0xFF);
1122: buffer[pos + 4] = (byte) ((value >>> 24) & 0xFF);
1123: buffer[pos + 5] = (byte) ((value >>> 16) & 0xFF);
1124: buffer[pos + 6] = (byte) ((value >>> 8) & 0xFF);
1125: buffer[pos + 7] = (byte) (value & 0xFF);
1126:
1127: index += 8;
1128: pos += 8;
1129: }
1130:
1131: public final void write_longlong_array(final long[] value,
1132: final int offset, final int length) {
1133: //if nothing has to be written, return, and especially DON'T
1134: //ALIGN
1135: if (length == 0) {
1136: return;
1137: }
1138:
1139: check(7 + length * 8, 8);
1140:
1141: if (value != null) {
1142: for (int i = offset; i < offset + length; i++) {
1143: buffer[pos] = (byte) ((value[i] >>> 56) & 0xFF);
1144: buffer[pos + 1] = (byte) ((value[i] >>> 48) & 0xFF);
1145: buffer[pos + 2] = (byte) ((value[i] >>> 40) & 0xFF);
1146: buffer[pos + 3] = (byte) ((value[i] >>> 32) & 0xFF);
1147: buffer[pos + 4] = (byte) ((value[i] >>> 24) & 0xFF);
1148: buffer[pos + 5] = (byte) ((value[i] >>> 16) & 0xFF);
1149: buffer[pos + 6] = (byte) ((value[i] >>> 8) & 0xFF);
1150: buffer[pos + 7] = (byte) (value[i] & 0xFF);
1151: pos += 8;
1152: }
1153: index += 8 * length;
1154: }
1155: }
1156:
1157: public void write_Object(final org.omg.CORBA.Object value) {
1158: if (value == null) {
1159: IORHelper.write(this , null_ior);
1160: } else {
1161: if (value instanceof org.omg.CORBA.LocalObject) {
1162: throw new MARSHAL(
1163: "Attempt to serialize a locality-constrained object.");
1164: }
1165: org.omg.CORBA.portable.ObjectImpl obj = (org.omg.CORBA.portable.ObjectImpl) value;
1166:
1167: IOR intermediary = ((Delegate) obj._get_delegate())
1168: .getIOR();
1169:
1170: if (isMutatorEnabled) {
1171: intermediary = mutator.mutateOutgoing(intermediary);
1172: }
1173:
1174: IORHelper.write(this , intermediary);
1175: }
1176: }
1177:
1178: ////////////////////////////////////////////// NEW!
1179: public void write_IOR(final IOR ior) {
1180: if (ior == null) {
1181: IORHelper.write(this , null_ior);
1182: } else {
1183: IORHelper.write(this , ior);
1184: }
1185: }
1186:
1187: ////////////////////////////////////////////// NEW!
1188:
1189: public final void write_octet(final byte value) {
1190: check(1);
1191: index++;
1192: buffer[pos++] = value;
1193: }
1194:
1195: public final void write_octet_array(final byte[] value,
1196: final int offset, final int length) {
1197: if (value != null) {
1198: if (length > 4000) {
1199: deferredArrayQueue.add(new DeferredWriteFrame(index,
1200: offset, length, value));
1201: index += length;
1202: deferred_writes += length;
1203: } else {
1204: check(length);
1205: System.arraycopy(value, offset, buffer, pos, length);
1206: index += length;
1207: pos += length;
1208: }
1209: }
1210: }
1211:
1212: public final void write_Principal(
1213: final org.omg.CORBA.Principal value) {
1214: throw new NO_IMPLEMENT("Principal deprecated");
1215: }
1216:
1217: public final void write_short(final short value) {
1218: check(3, 2);
1219:
1220: buffer[pos] = (byte) ((value >> 8) & 0xFF);
1221: buffer[pos + 1] = (byte) (value & 0xFF);
1222: index += 2;
1223: pos += 2;
1224: }
1225:
1226: public final void write_short_array(final short[] value,
1227: final int offset, final int length) {
1228: //if nothing has to be written, return, and especially DON'T
1229: //ALIGN
1230: if (length == 0) {
1231: return;
1232: }
1233:
1234: /* align to 2-byte boundary */
1235:
1236: check(2 * length + 3);
1237:
1238: int remainder = 2 - (index % 2);
1239: if (remainder != 2) {
1240: index += remainder;
1241: pos += remainder;
1242: }
1243:
1244: if (value != null) {
1245: for (int i = offset; i < offset + length; i++) {
1246: buffer[pos] = (byte) ((value[i] >>> 8) & 0xFF);
1247: buffer[pos + 1] = (byte) (value[i] & 0xFF);
1248: pos += 2;
1249: }
1250: index += 2 * length;
1251: }
1252: }
1253:
1254: public final void write_TypeCode(org.omg.CORBA.TypeCode typeCode) {
1255: if (compactTypeCodes > 0) {
1256: final String id;
1257: try {
1258: switch (typeCode.kind().value()) {
1259: case TCKind._tk_objref: //14
1260: case TCKind._tk_struct: //15
1261: case TCKind._tk_union: //16
1262: case TCKind._tk_enum: //17
1263: {
1264: id = typeCode.id();
1265: break;
1266: }
1267: case TCKind._tk_string: //18
1268: case TCKind._tk_sequence: //19
1269: case TCKind._tk_array: //20
1270: {
1271: id = null;
1272: break; //dummy cases for optimized switch
1273: }
1274: case TCKind._tk_alias: //21
1275: case TCKind._tk_except: //22
1276: {
1277: id = typeCode.id();
1278: break;
1279: }
1280: case TCKind._tk_longlong: // 23
1281: case TCKind._tk_ulonglong: // 24
1282: case TCKind._tk_longdouble:// 25
1283: case TCKind._tk_wchar: // 26
1284: case TCKind._tk_wstring: // 27
1285: case TCKind._tk_fixed: // 28
1286: {
1287: id = null;
1288: break; //dummy cases for optimized switch
1289: }
1290: case TCKind._tk_value: // 29
1291: case TCKind._tk_value_box: // 30
1292: {
1293: id = typeCode.id();
1294: break;
1295: }
1296: case TCKind._tk_native: // 31
1297: {
1298: id = null;
1299: break; //dummy cases for optimized switch
1300: }
1301: case TCKind._tk_abstract_interface: //32
1302: case TCKind._tk_local_interface: //33
1303: {
1304: id = typeCode.id();
1305: break;
1306: }
1307: default: {
1308: id = null;
1309: break; //TC has no id
1310: }
1311: }
1312: } catch (org.omg.CORBA.TypeCodePackage.BadKind e) {
1313: throw new INTERNAL("should never happen");
1314: }
1315:
1316: if (id != null) {
1317: final org.omg.CORBA.TypeCode cached;
1318:
1319: if (cachedTypecodes == null) {
1320: cachedTypecodes = new HashMap();
1321: cached = null;
1322: } else {
1323: // We may previously have already compacted and cached this
1324: // typecode.
1325: cached = (org.omg.CORBA.TypeCode) cachedTypecodes
1326: .get(id);
1327: }
1328:
1329: // If we don't have a cached value get the compact form and
1330: // cache it.
1331: if (cached == null) {
1332: typeCode = typeCode.get_compact_typecode();
1333: cachedTypecodes.put(id, typeCode);
1334: } else {
1335: typeCode = cached;
1336: }
1337: }
1338: }
1339:
1340: if (repeatedTCMap == null) {
1341: repeatedTCMap = new HashMap();
1342: }
1343:
1344: if (recursiveTCMap == null) {
1345: recursiveTCMap = new HashMap();
1346: }
1347:
1348: try {
1349: write_TypeCode(typeCode, recursiveTCMap, repeatedTCMap);
1350: } finally {
1351: repeatedTCMap.clear();
1352: recursiveTCMap.clear();
1353: }
1354: }
1355:
1356: private final void writeIndirectionMarker(final Object key,
1357: final Map indirectionTCMap) {
1358: write_long(-1); // recursion marker
1359: int negative_offset = ((Integer) indirectionTCMap.get(key))
1360: .intValue()
1361: - pos - 4;
1362:
1363: write_long(negative_offset);
1364: }
1365:
1366: private final void writeIndirectionMarker(
1367: final org.omg.CORBA.TypeCode value,
1368: final Map recursiveTCMap, boolean typeCodeKey)
1369: throws BadKind {
1370: final java.lang.Object key;
1371:
1372: /* Sequence and array tcs will be stored under the actual TypeCode as they
1373: * do not have IDs.
1374: */
1375: if (typeCodeKey) {
1376: key = value;
1377: } else {
1378: key = value.id();
1379: }
1380:
1381: write_long(-1); // recursion marker
1382: int negative_offset = ((Integer) recursiveTCMap.get(key))
1383: .intValue()
1384: - pos - 4;
1385:
1386: write_long(negative_offset);
1387: }
1388:
1389: private final void write_TypeCode(
1390: final org.omg.CORBA.TypeCode typeCode,
1391: final Map recursiveTCMap, final Map repeatedTCMap) {
1392: if (typeCode == null) {
1393: throw new BAD_PARAM("TypeCode is null");
1394: }
1395:
1396: int _kind = -1;
1397: final int _memberCount;
1398:
1399: try {
1400: if (TypeCode.isRecursive(typeCode)
1401: && recursiveTCMap.containsKey(typeCode.id())) {
1402: writeIndirectionMarker(typeCode.id(), recursiveTCMap);
1403: } else {
1404: _kind = typeCode.kind().value();
1405: // regular TypeCodes
1406: switch (_kind) {
1407: case 0: //_tk_null
1408: case 1: //_tk_void
1409: case 2: //_tk_short
1410: case 3: //_tk_long
1411: case 4: //_tk_ushort
1412: case 5: //_tk_ulong
1413: case 6: //_tk_float
1414: case 7: //_tk_double
1415: case 8: //_tk_boolean
1416: case 9: //_tk_char
1417: case 10: //_tk_octet
1418: case 11: //_tk_any
1419: case 12: //_tk_TypeCode
1420: case 13: //_tk_Principal
1421: {
1422: write_long(_kind);
1423: break;
1424: }
1425: case TCKind._tk_objref: // 14
1426: {
1427: if (useIndirection
1428: && repeatedTCMap.containsKey(typeCode)) {
1429: writeIndirectionMarker(typeCode, repeatedTCMap);
1430: } else {
1431: write_long(_kind);
1432:
1433: // remember tc start pos before we start writing it
1434: // out
1435: Integer tcStartPos = ObjectUtil.newInteger(pos);
1436: recursiveTCMap.put(typeCode.id(), tcStartPos);
1437:
1438: beginEncapsulation();
1439: write_string(typeCode.id());
1440: write_string(typeCode.name());
1441: endEncapsulation();
1442:
1443: //add typecode to cache not until here to account for
1444: //recursive TCs
1445: repeatedTCMap.put(typeCode, tcStartPos);
1446: }
1447: break;
1448: }
1449: case TCKind._tk_struct: // 15
1450: {
1451: if (useIndirection
1452: && repeatedTCMap.containsKey(typeCode)) {
1453: writeIndirectionMarker(typeCode, repeatedTCMap);
1454: } else {
1455: write_long(_kind);
1456:
1457: final Integer tcStartPos = ObjectUtil
1458: .newInteger(pos);
1459: recursiveTCMap.put(typeCode.id(), tcStartPos);
1460:
1461: beginEncapsulation();
1462: write_string(typeCode.id());
1463: write_string(typeCode.name());
1464: _memberCount = typeCode.member_count();
1465: write_long(_memberCount);
1466: for (int i = 0; i < _memberCount; i++) {
1467: write_string(typeCode.member_name(i));
1468: write_TypeCode(typeCode.member_type(i),
1469: recursiveTCMap, repeatedTCMap);
1470: }
1471: endEncapsulation();
1472:
1473: // add typecode to cache not until here to account for
1474: // recursive TCs
1475: repeatedTCMap.put(typeCode, tcStartPos);
1476: }
1477: break;
1478: }
1479: case TCKind._tk_union: // 16
1480: {
1481: if (useIndirection
1482: && repeatedTCMap.containsKey(typeCode)) {
1483: writeIndirectionMarker(typeCode, repeatedTCMap);
1484: } else {
1485: write_long(_kind);
1486: // remember tc start pos before we start writing it
1487: // out
1488: final Integer tcStartPos = ObjectUtil
1489: .newInteger(pos);
1490: recursiveTCMap.put(typeCode.id(), tcStartPos);
1491:
1492: beginEncapsulation();
1493: write_string(typeCode.id());
1494: write_string(typeCode.name());
1495:
1496: write_TypeCode(typeCode.discriminator_type(),
1497: recursiveTCMap, repeatedTCMap);
1498: write_long(typeCode.default_index());
1499: _memberCount = typeCode.member_count();
1500: write_long(_memberCount);
1501: for (int i = 0; i < _memberCount; i++) {
1502: if (i == typeCode.default_index()) {
1503: write_octet((byte) 0);
1504: } else {
1505: typeCode.member_label(i).write_value(
1506: this );
1507: }
1508: write_string(typeCode.member_name(i));
1509: write_TypeCode(typeCode.member_type(i),
1510: recursiveTCMap, repeatedTCMap);
1511: }
1512: endEncapsulation();
1513:
1514: // add typecode to cache not until here to account
1515: // for recursive TCs
1516: repeatedTCMap.put(typeCode, tcStartPos);
1517: }
1518: break;
1519: }
1520: case TCKind._tk_enum: // 17
1521: {
1522: if (useIndirection
1523: && repeatedTCMap.containsKey(typeCode)) {
1524: writeIndirectionMarker(typeCode, repeatedTCMap);
1525: } else {
1526: write_long(_kind);
1527:
1528: final Integer tcStartPos = ObjectUtil
1529: .newInteger(pos);
1530: recursiveTCMap.put(typeCode.id(), tcStartPos);
1531:
1532: beginEncapsulation();
1533: write_string(typeCode.id());
1534: write_string(typeCode.name());
1535: _memberCount = typeCode.member_count();
1536: write_long(_memberCount);
1537: for (int i = 0; i < _memberCount; i++) {
1538: write_string(typeCode.member_name(i));
1539: }
1540: endEncapsulation();
1541:
1542: repeatedTCMap.put(typeCode, tcStartPos);
1543: }
1544: break;
1545: }
1546: case TCKind._tk_string: // 18
1547: {
1548: write_long(_kind);
1549: write_long(typeCode.length());
1550: break;
1551: }
1552: case TCKind._tk_sequence: // 19
1553: // fallthrough
1554: case TCKind._tk_array: // 20
1555: {
1556: // Sequence and array TypeCodes don't have an id
1557: // so we need to store using the actual TypeCode
1558: if (useIndirection
1559: && repeatedTCMap.containsKey(typeCode)) {
1560: writeIndirectionMarker(typeCode, repeatedTCMap,
1561: true);
1562: } else {
1563: write_long(_kind);
1564:
1565: // remember tc start pos before we start writing it
1566: // out
1567: Integer tcStartPos = ObjectUtil.newInteger(pos);
1568: recursiveTCMap.put(typeCode, tcStartPos);
1569:
1570: beginEncapsulation();
1571: write_TypeCode(typeCode.content_type(),
1572: recursiveTCMap, repeatedTCMap);
1573: write_long(typeCode.length());
1574: endEncapsulation();
1575:
1576: //add typecode to cache not until here to account
1577: //for recursive TCs
1578: repeatedTCMap.put(typeCode, tcStartPos);
1579: }
1580: break;
1581: }
1582: case TCKind._tk_alias: // 21
1583: {
1584: if (useIndirection
1585: && repeatedTCMap.containsKey(typeCode)) {
1586: writeIndirectionMarker(typeCode, repeatedTCMap);
1587: } else {
1588: write_long(_kind);
1589:
1590: // remember tc start pos before we start writing it
1591: // out
1592: Integer tcStartPos = ObjectUtil.newInteger(pos);
1593: recursiveTCMap.put(typeCode, tcStartPos);
1594:
1595: beginEncapsulation();
1596: write_string(typeCode.id());
1597: write_string(typeCode.name());
1598: write_TypeCode(typeCode.content_type(),
1599: recursiveTCMap, repeatedTCMap);
1600: endEncapsulation();
1601:
1602: //add typecode to cache not until here to account
1603: //for recursive TCs
1604: repeatedTCMap.put(typeCode, tcStartPos);
1605: }
1606: break;
1607: }
1608: case TCKind._tk_except: // 22
1609: {
1610: if (useIndirection
1611: && repeatedTCMap.containsKey(typeCode)) {
1612: writeIndirectionMarker(typeCode, repeatedTCMap);
1613: } else {
1614: write_long(_kind);
1615:
1616: // remember tc start pos before we start writing it
1617: // out
1618: Integer tcStartPos = ObjectUtil.newInteger(pos);
1619: recursiveTCMap.put(typeCode, tcStartPos);
1620:
1621: beginEncapsulation();
1622: write_string(typeCode.id());
1623: write_string(typeCode.name());
1624: _memberCount = typeCode.member_count();
1625: write_long(_memberCount);
1626: for (int i = 0; i < _memberCount; i++) {
1627: write_string(typeCode.member_name(i));
1628: write_TypeCode(typeCode.member_type(i),
1629: recursiveTCMap, repeatedTCMap);
1630: }
1631: endEncapsulation();
1632:
1633: //add typecode to cache not until here to account
1634: //for recursive TCs
1635: repeatedTCMap.put(typeCode, tcStartPos);
1636: }
1637: break;
1638: }
1639: case TCKind._tk_longlong: // 23
1640: // fallthrough
1641: case TCKind._tk_ulonglong: // 24
1642: {
1643: write_long(_kind);
1644: break;
1645: }
1646: case TCKind._tk_longdouble: // 25
1647: {
1648: throw new MARSHAL(
1649: "Cannot handle TypeCode with kind: "
1650: + _kind);
1651: }
1652: case TCKind._tk_wchar: // 26
1653: {
1654: write_long(_kind);
1655: break;
1656: }
1657: case TCKind._tk_wstring: // 27
1658: {
1659: write_long(_kind);
1660: write_long(typeCode.length());
1661: break;
1662: }
1663: case TCKind._tk_fixed: //28
1664: {
1665: write_long(_kind);
1666: write_ushort(typeCode.fixed_digits());
1667: write_short(typeCode.fixed_scale());
1668: break;
1669: }
1670: case TCKind._tk_value: // 29
1671: {
1672: if (useIndirection
1673: && repeatedTCMap.containsKey(typeCode)) {
1674: writeIndirectionMarker(typeCode, repeatedTCMap);
1675: } else {
1676: write_long(_kind);
1677:
1678: final Integer tcStartPos = ObjectUtil
1679: .newInteger(pos);
1680: recursiveTCMap.put(typeCode.id(), tcStartPos);
1681:
1682: beginEncapsulation();
1683: write_string(typeCode.id());
1684: write_string(typeCode.name());
1685: write_short(typeCode.type_modifier());
1686: final org.omg.CORBA.TypeCode baseType = typeCode
1687: .concrete_base_type();
1688: if (baseType == null) {
1689: write_long(TCKind._tk_null);
1690: } else {
1691: write_TypeCode(baseType, recursiveTCMap,
1692: repeatedTCMap);
1693: }
1694: _memberCount = typeCode.member_count();
1695: write_long(_memberCount);
1696: for (int i = 0; i < _memberCount; i++) {
1697: write_string(typeCode.member_name(i));
1698: write_TypeCode(typeCode.member_type(i),
1699: recursiveTCMap, repeatedTCMap);
1700: write_short(typeCode.member_visibility(i));
1701: }
1702: endEncapsulation();
1703:
1704: // add typecode to cache not until here to account
1705: // for recursive TCs
1706: repeatedTCMap.put(typeCode, tcStartPos);
1707: }
1708: break;
1709: }
1710: case TCKind._tk_value_box: // 30
1711: {
1712: if (useIndirection
1713: && repeatedTCMap.containsKey(typeCode)) {
1714: writeIndirectionMarker(typeCode, repeatedTCMap);
1715: } else {
1716: write_long(_kind);
1717: final Integer tcStartPos = ObjectUtil
1718: .newInteger(pos);
1719: recursiveTCMap.put(typeCode.id(), tcStartPos);
1720:
1721: beginEncapsulation();
1722: write_string(typeCode.id());
1723: write_string(typeCode.name());
1724: write_TypeCode(typeCode.content_type(),
1725: recursiveTCMap, repeatedTCMap);
1726: endEncapsulation();
1727:
1728: // add typecode to cache not until here to account
1729: // for recursive TCs
1730: repeatedTCMap.put(typeCode, tcStartPos);
1731: }
1732: break;
1733: }
1734: case TCKind._tk_native: {
1735: throw new MARSHAL(
1736: "Cannot handle TypeCode with kind: "
1737: + _kind);
1738: }
1739: case TCKind._tk_abstract_interface: {
1740: if (useIndirection
1741: && repeatedTCMap.containsKey(typeCode)) {
1742: writeIndirectionMarker(typeCode, repeatedTCMap);
1743: } else {
1744: write_long(_kind);
1745: final Integer tcStartPos = ObjectUtil
1746: .newInteger(pos);
1747: recursiveTCMap.put(typeCode.id(), tcStartPos);
1748:
1749: beginEncapsulation();
1750: write_string(typeCode.id());
1751: write_string(typeCode.name());
1752: endEncapsulation();
1753:
1754: // add typecode to cache not until here to account
1755: // for recursive TCs
1756: repeatedTCMap.put(typeCode, tcStartPos);
1757: }
1758: break;
1759: }
1760: default: {
1761: throw new MARSHAL(
1762: "Cannot handle TypeCode with kind: "
1763: + _kind);
1764: }
1765: }
1766: }
1767: } catch (BadKind ex) {
1768: throw new MARSHAL("When processing TypeCode with kind: "
1769: + _kind + " caught " + ex);
1770: } catch (Bounds ex) {
1771: throw new MARSHAL("When processing TypeCode with kind: "
1772: + _kind + " caught " + ex);
1773: }
1774: }
1775:
1776: public final void write_ulong(final int value) {
1777: write_long(value);
1778: }
1779:
1780: public final void write_ulong_array(final int[] value,
1781: final int offset, final int length) {
1782: write_long_array(value, offset, length);
1783: }
1784:
1785: public final void write_ulonglong(final long value) {
1786: write_longlong(value);
1787: }
1788:
1789: public final void write_ulonglong_array(final long[] value,
1790: final int offset, final int length) {
1791: write_longlong_array(value, offset, length);
1792: }
1793:
1794: public final void write_ushort(final short value) {
1795: write_short(value);
1796: }
1797:
1798: public final void write_ushort_array(final short[] value,
1799: final int offset, final int length) {
1800: write_short_array(value, offset, length);
1801: }
1802:
1803: /**
1804: * Reads a value of the type indicated by <code>tc</code> from the
1805: * InputStream <code>in</code> and remarshals it to this CDROutputStream.
1806: * Called from Any.
1807: */
1808: public final void write_value(
1809: final org.omg.CORBA.TypeCode typeCode,
1810: final org.omg.CORBA.portable.InputStream input) {
1811: if (typeCode == null) {
1812: throw new BAD_PARAM("TypeCode is null");
1813: }
1814:
1815: int kind = typeCode.kind().value();
1816:
1817: try {
1818: switch (kind) {
1819: case TCKind._tk_null: // 0
1820: // fallthrough
1821: case TCKind._tk_void: // 1
1822: {
1823: break;
1824: }
1825: case TCKind._tk_short: // 2
1826: {
1827: write_short(input.read_short());
1828: break;
1829: }
1830: case TCKind._tk_long: // 3
1831: {
1832: write_long(input.read_long());
1833: break;
1834: }
1835: case TCKind._tk_ushort: // 4
1836: {
1837: write_ushort(input.read_ushort());
1838: break;
1839: }
1840: case TCKind._tk_ulong: // 5
1841: {
1842: write_ulong(input.read_ulong());
1843: break;
1844: }
1845: case TCKind._tk_float: // 6
1846: {
1847: write_float(input.read_float());
1848: break;
1849: }
1850: case TCKind._tk_double: // 7
1851: {
1852: write_double(input.read_double());
1853: break;
1854: }
1855: case TCKind._tk_boolean: // 8
1856: {
1857: write_boolean(input.read_boolean());
1858: break;
1859: }
1860: case TCKind._tk_char: // 9
1861: {
1862: write_char(input.read_char());
1863: break;
1864: }
1865: case TCKind._tk_octet: // 10
1866: {
1867: write_octet(input.read_octet());
1868: break;
1869: }
1870: case TCKind._tk_any: // 11
1871: {
1872: write_any(input.read_any());
1873: break;
1874: }
1875: case TCKind._tk_TypeCode: // 12
1876: {
1877: write_TypeCode(input.read_TypeCode());
1878: break;
1879: }
1880: case TCKind._tk_Principal: // 13
1881: {
1882: throw new NO_IMPLEMENT("Principal deprecated");
1883: }
1884: case TCKind._tk_objref: // 14
1885: {
1886: write_Object(input.read_Object());
1887: break;
1888: }
1889: case TCKind._tk_struct: // 15
1890: {
1891: for (int i = 0; i < typeCode.member_count(); i++) {
1892: write_value(typeCode.member_type(i), input);
1893: }
1894: break;
1895: }
1896: case TCKind._tk_union: // 16
1897: {
1898: org.omg.CORBA.TypeCode disc = typeCode
1899: .discriminator_type();
1900: disc = TypeCode.originalType(disc);
1901: int def_idx = typeCode.default_index();
1902: int member_idx = -1;
1903:
1904: switch (disc.kind().value()) {
1905: case TCKind._tk_short: // 2
1906: {
1907: short s = input.read_short();
1908: write_short(s);
1909: for (int i = 0; i < typeCode.member_count(); i++) {
1910: if (i != def_idx) {
1911: if (s == typeCode.member_label(i)
1912: .extract_short()) {
1913: member_idx = i;
1914: break;
1915: }
1916: }
1917: }
1918: break;
1919: }
1920: case TCKind._tk_long: // 3
1921: {
1922: int s = input.read_long();
1923: write_long(s);
1924: for (int i = 0; i < typeCode.member_count(); i++) {
1925: if (i != def_idx) {
1926: if (s == typeCode.member_label(i)
1927: .extract_long()) {
1928: member_idx = i;
1929: break;
1930: }
1931: }
1932: }
1933: break;
1934: }
1935: case TCKind._tk_ushort: // 4
1936: {
1937: short s = input.read_ushort();
1938: write_ushort(s);
1939: for (int i = 0; i < typeCode.member_count(); i++) {
1940: if (i != def_idx) {
1941: if (s == typeCode.member_label(i)
1942: .extract_ushort()) {
1943: member_idx = i;
1944: break;
1945: }
1946: }
1947: }
1948: break;
1949: }
1950: case TCKind._tk_ulong: // 5
1951: {
1952: int s = input.read_ulong();
1953: write_ulong(s);
1954: for (int i = 0; i < typeCode.member_count(); i++) {
1955: if (i != def_idx) {
1956: if (s == typeCode.member_label(i)
1957: .extract_ulong()) {
1958: member_idx = i;
1959: break;
1960: }
1961: }
1962: }
1963: break;
1964: }
1965: case TCKind._tk_float: // 6
1966: // fallthrough
1967: case TCKind._tk_double: // 7
1968: {
1969: throw new MARSHAL(
1970: "Invalid union discriminator type: " + disc);
1971: }
1972: case TCKind._tk_boolean: // 8
1973: {
1974: boolean s = input.read_boolean();
1975: write_boolean(s);
1976: for (int i = 0; i < typeCode.member_count(); i++) {
1977: if (i != def_idx) {
1978: if (s == typeCode.member_label(i)
1979: .extract_boolean()) {
1980: member_idx = i;
1981: break;
1982: }
1983: }
1984: }
1985: break;
1986: }
1987: case TCKind._tk_char: // 9
1988: {
1989: char s = input.read_char();
1990: write_char(s);
1991: for (int i = 0; i < typeCode.member_count(); i++) {
1992: if (i != def_idx) {
1993: if (s == typeCode.member_label(i)
1994: .extract_char()) {
1995: member_idx = i;
1996: break;
1997: }
1998: }
1999: }
2000: break;
2001: }
2002: case TCKind._tk_octet: // 10
2003: case TCKind._tk_any: // 11
2004: case TCKind._tk_TypeCode: // 12
2005: case TCKind._tk_Principal: // 13
2006: case TCKind._tk_objref: // 14
2007: case TCKind._tk_struct: // 15
2008: case TCKind._tk_union: // 16
2009: {
2010: throw new MARSHAL(
2011: "Invalid union discriminator type: " + disc);
2012: }
2013: case TCKind._tk_enum: // 17
2014: {
2015: int s = input.read_long();
2016: write_long(s);
2017: for (int i = 0; i < typeCode.member_count(); i++) {
2018: if (i != def_idx) {
2019: int label = typeCode.member_label(i)
2020: .create_input_stream().read_long();
2021: /* we have to use the any's input
2022: stream because enums are not
2023: inserted as longs */
2024:
2025: if (s == label) {
2026: member_idx = i;
2027: break;
2028: }
2029: }
2030: }
2031: break;
2032: }
2033: case TCKind._tk_string: // 18
2034: case TCKind._tk_sequence: // 19
2035: case TCKind._tk_array: // 20
2036: case TCKind._tk_alias: // 21
2037: case TCKind._tk_except: // 22
2038: {
2039: throw new MARSHAL(
2040: "Invalid union discriminator type: " + disc);
2041: }
2042: case TCKind._tk_longlong: // 23
2043: {
2044: long s = input.read_longlong();
2045: write_longlong(s);
2046: for (int i = 0; i < typeCode.member_count(); i++) {
2047: if (i != def_idx) {
2048: if (s == typeCode.member_label(i)
2049: .extract_longlong()) {
2050: member_idx = i;
2051: break;
2052: }
2053: }
2054: }
2055: break;
2056: }
2057: case TCKind._tk_ulonglong: // 24
2058: {
2059: long s = input.read_ulonglong();
2060: write_ulonglong(s);
2061: for (int i = 0; i < typeCode.member_count(); i++) {
2062: if (i != def_idx) {
2063: if (s == typeCode.member_label(i)
2064: .extract_ulonglong()) {
2065: member_idx = i;
2066: break;
2067: }
2068: }
2069: }
2070: break;
2071: }
2072: default: {
2073: throw new MARSHAL(
2074: "Invalid union discriminator type: " + disc);
2075: }
2076: }
2077:
2078: // write the member or default value, if any
2079: // (if the union has no explicit default but the
2080: // the case labels do not cover the range of
2081: // possible discriminator values, there may be
2082: // several "implicit defaults" without associated
2083: // union values.
2084:
2085: if (member_idx != -1) {
2086: write_value(typeCode.member_type(member_idx), input);
2087: } else if (def_idx != -1) {
2088: write_value(typeCode.member_type(def_idx), input);
2089: }
2090: break;
2091: }
2092: case TCKind._tk_enum: // 17
2093: {
2094: write_long(input.read_long());
2095: break;
2096: }
2097: case TCKind._tk_string: // 18
2098: {
2099: write_string(input.read_string());
2100: break;
2101: }
2102: case TCKind._tk_sequence: // 19
2103: {
2104: int len = input.read_long();
2105: write_long(len);
2106:
2107: org.omg.CORBA.TypeCode content_tc = typeCode
2108: .content_type();
2109: for (int i = 0; i < len; i++) {
2110: write_value(content_tc, input);
2111: }
2112:
2113: break;
2114: }
2115: case TCKind._tk_array: // 20
2116: {
2117: int length = typeCode.length();
2118: if (typeCode.content_type().kind().value() == TCKind._tk_octet) {
2119: check(length);
2120: input.read_octet_array(buffer, pos, length);
2121: index += length;
2122: pos += length;
2123: } else {
2124: for (int i = 0; i < length; i++) {
2125: write_value(typeCode.content_type(), input);
2126: }
2127: }
2128: break;
2129: }
2130: case TCKind._tk_alias: // 21
2131: {
2132: write_value(typeCode.content_type(), input);
2133: break;
2134: }
2135: case TCKind._tk_except: // 22
2136: {
2137: write_string(input.read_string());
2138: for (int i = 0; i < typeCode.member_count(); i++) {
2139: write_value(typeCode.member_type(i), input);
2140: }
2141: break;
2142: }
2143: case TCKind._tk_longlong: // 23
2144: {
2145: write_longlong(input.read_longlong());
2146: break;
2147: }
2148: case TCKind._tk_ulonglong: // 24
2149: {
2150: write_ulonglong(input.read_ulonglong());
2151: break;
2152: }
2153: case TCKind._tk_longdouble: // 25
2154: {
2155: throw new org.omg.CORBA.BAD_TYPECODE(
2156: "type longdouble not supported in java");
2157: }
2158: case TCKind._tk_wchar: // 26
2159: {
2160: write_wchar(input.read_wchar());
2161: break;
2162: }
2163: case TCKind._tk_wstring: // 27
2164: {
2165: write_wstring(input.read_wstring());
2166: break;
2167: }
2168: case TCKind._tk_fixed: // 28
2169: {
2170: write_fixed(input.read_fixed());
2171: break;
2172: }
2173: case TCKind._tk_value: // 29
2174: {
2175: final Serializable val = ((org.omg.CORBA_2_3.portable.InputStream) input)
2176: .read_value();
2177: write_value(val, typeCode.id());
2178: break;
2179: }
2180: case TCKind._tk_value_box: {
2181: String id = typeCode.id();
2182: org.omg.CORBA.portable.BoxedValueHelper helper = ((org.jacorb.orb.ORB) orb())
2183: .getBoxedValueHelper(id);
2184: if (helper == null) {
2185: throw new MARSHAL("No BoxedValueHelper for id "
2186: + id);
2187: }
2188: java.io.Serializable value = ((org.omg.CORBA_2_3.portable.InputStream) input)
2189: .read_value(helper);
2190: write_value(value, helper);
2191: break;
2192: }
2193: default: {
2194: throw new MARSHAL("Cannot handle TypeCode with kind "
2195: + kind);
2196: }
2197: }
2198: } catch (BadKind ex) {
2199: throw new MARSHAL("When processing TypeCode with kind: "
2200: + kind + " caught " + ex);
2201: } catch (Bounds ex) {
2202: throw new MARSHAL("When processing TypeCode with kind: "
2203: + kind + " caught " + ex);
2204: }
2205: }
2206:
2207: /**
2208: * Writes the serialized state of `value' to this stream.
2209: */
2210:
2211: public void write_value(final java.io.Serializable value) {
2212: if (!write_special_value(value)) {
2213: write_value_internal(value, ValueHandler
2214: .getRMIRepositoryID(value.getClass()));
2215: }
2216: }
2217:
2218: public void write_value(final java.io.Serializable value,
2219: final org.omg.CORBA.portable.BoxedValueHelper factory) {
2220: if (!write_special_value(value)) {
2221: check(7, 4);
2222: getValueMap().put(value, ObjectUtil.newInteger(pos));
2223: write_previous_chunk_size();
2224: if ((value instanceof org.omg.CORBA.portable.IDLEntity)
2225: || (value instanceof java.lang.String)) {
2226: write_long(0x7fffff00 | chunkingFlag);
2227: } else {
2228: // repository id is required for RMI: types
2229: write_long(0x7fffff02 | chunkingFlag);
2230: write_repository_id(RepositoryID
2231: .repId(value.getClass()));
2232: }
2233: start_chunk();
2234: factory.write_value(this , value);
2235: end_chunk();
2236: }
2237: }
2238:
2239: public void write_value(final java.io.Serializable value,
2240: final java.lang.Class clazz) {
2241: if (!write_special_value(value)) {
2242: final Class _clazz = value.getClass();
2243: final String repId = ValueHandler
2244: .getRMIRepositoryID(_clazz);
2245: if (_clazz == clazz && !repId.startsWith("RMI:")) {
2246: // the repository id is required for "RMI:" valuetypes
2247: write_value_internal(value, null);
2248: } else if (clazz.isInstance(value)) {
2249: write_value_internal(value, repId);
2250: } else {
2251: throw new BAD_PARAM();
2252: }
2253: }
2254: }
2255:
2256: public void write_value(final java.io.Serializable value,
2257: final String repository_id) {
2258: if (!write_special_value(value)) {
2259: write_value_internal(value, repository_id);
2260: }
2261: }
2262:
2263: /**
2264: * If `value' is null, or has already been written to this stream,
2265: * then this method writes that information to the stream and returns
2266: * true, otherwise does nothing and returns false.
2267: */
2268: private boolean write_special_value(final java.io.Serializable value) {
2269: if (value == null) {
2270: // null tag
2271: write_long(0x00000000);
2272: return true;
2273: }
2274:
2275: Integer index = (Integer) getValueMap().get(value);
2276: if (index != null) {
2277: // value has already been written -- make an indirection
2278: write_long(0xffffffff);
2279: write_long(index.intValue() - size());
2280: return true;
2281: }
2282: return false;
2283: }
2284:
2285: /**
2286: * Writes `repository_id' to this stream, perhaps via indirection.
2287: */
2288: private void write_repository_id(final String repository_id) {
2289: Integer _index = (Integer) getRepIdMap().get(repository_id);
2290: if (_index == null) {
2291: // a new repository id -- write it
2292:
2293: // first make sure the pos we're about to remember is
2294: // a correctly aligned one, i.e., the actual writing position
2295: int remainder = 4 - (index % 4);
2296: if (remainder != 4) {
2297: index += remainder;
2298: pos += remainder;
2299: }
2300:
2301: getRepIdMap()
2302: .put(repository_id, ObjectUtil.newInteger(pos));
2303: write_string(repository_id);
2304: } else {
2305: // a previously written repository id -- make an indirection
2306: write_long(0xffffffff);
2307: write_long(_index.intValue() - size());
2308: }
2309: }
2310:
2311: /**
2312: * Writes `codebase' to this stream, perhaps via indirection.
2313: */
2314: private void write_codebase(final String codebase) {
2315: Integer _index = null;
2316: if (codebaseMap == null) {
2317: codebaseMap = new HashMap();
2318: } else {
2319: _index = (Integer) getCodebaseMap().get(codebase);
2320: }
2321: if (_index == null) {
2322: // a new codebase -- write it#
2323:
2324: // first make sure the pos we're about to remember is
2325: // a correctly aligned one
2326: int remainder = 4 - (index % 4);
2327: if (remainder != 4) {
2328: index += remainder;
2329: pos += remainder;
2330: }
2331:
2332: getCodebaseMap().put(codebase, ObjectUtil.newInteger(pos));
2333: write_string(codebase);
2334: } else {
2335: // a previously written codebase -- make an indirection
2336: write_long(0xffffffff);
2337: write_long(_index.intValue() - size());
2338: }
2339: }
2340:
2341: /**
2342: * Writes to this stream a value header with the specified `repository_id'
2343: * and no codebase string.
2344: */
2345: private void write_value_header(final String[] repository_ids) {
2346: write_previous_chunk_size();
2347: if (repository_ids != null) {
2348: if (repository_ids.length > 1) {
2349: // truncatable value type, must use chunking!
2350:
2351: chunkingFlag = 0x00000008;
2352: write_long(0x7fffff06 | chunkingFlag);
2353: write_long(repository_ids.length);
2354: for (int i = 0; i < repository_ids.length; i++) {
2355: write_repository_id(repository_ids[i]);
2356: }
2357: } else {
2358: write_long(0x7fffff02 | chunkingFlag);
2359: write_repository_id(repository_ids[0]);
2360: }
2361: } else {
2362: write_long(0x7fffff00 | chunkingFlag);
2363: }
2364: }
2365:
2366: /**
2367: * Writes to this stream a value header with the specified `repository_id'.
2368: * and `codebase' string.
2369: */
2370: private void write_value_header(final String[] repository_ids,
2371: final String codebase) {
2372: if (codebase != null) {
2373: write_previous_chunk_size();
2374: if (repository_ids != null) {
2375: if (repository_ids.length > 1) {
2376: // truncatable value type, must use chunking!
2377:
2378: chunkingFlag = 0x00000008;
2379: write_long(0x7fffff07 | chunkingFlag);
2380: write_codebase(codebase);
2381: write_long(repository_ids.length);
2382:
2383: for (int i = 0; i < repository_ids.length; i++) {
2384: write_repository_id(repository_ids[i]);
2385: }
2386: } else {
2387: write_long(0x7fffff03 | chunkingFlag);
2388: write_codebase(codebase);
2389: write_repository_id(repository_ids[0]);
2390: }
2391: } else {
2392: write_long(0x7fffff01 | chunkingFlag);
2393: write_codebase(codebase);
2394: }
2395: } else {
2396: write_value_header(repository_ids);
2397: }
2398: }
2399:
2400: /**
2401: * This method does the actual work of writing `value' to this
2402: * stream. If `repository_id' is non-null, then it is used as
2403: * the type information for `value' (possibly via indirection).
2404: * If `repository_id' is null, `value' is written without
2405: * type information.
2406: * Note: This method does not check for the special cases covered
2407: * by write_special_value().
2408: */
2409: private void write_value_internal(final java.io.Serializable value,
2410: final String repository_id) {
2411: check(7, 4);
2412: getValueMap().put(value, ObjectUtil.newInteger(pos));
2413:
2414: if (value.getClass() == String.class) {
2415: // special handling for strings required according to spec
2416: String[] repository_ids = (repository_id == null) ? null
2417: : new String[] { repository_id };
2418: write_value_header(repository_ids);
2419: start_chunk();
2420: write_wstring((String) value);
2421: end_chunk();
2422: } else if (value.getClass() == Class.class) {
2423: String[] repository_ids = new String[] { ValueHandler
2424: .getRMIRepositoryID(javax.rmi.CORBA.ClassDesc.class) };
2425: write_value_header(repository_ids);
2426: start_chunk();
2427: write_value(ValueHandler.getCodebase((Class) value));
2428: write_value(ValueHandler.getRMIRepositoryID((Class) value));
2429: end_chunk();
2430: } else if (value instanceof org.omg.CORBA.portable.StreamableValue) {
2431: org.omg.CORBA.portable.StreamableValue streamable = (org.omg.CORBA.portable.StreamableValue) value;
2432:
2433: write_value_header(streamable._truncatable_ids());
2434: start_chunk();
2435: ((org.omg.CORBA.portable.StreamableValue) value)
2436: ._write(this );
2437: end_chunk();
2438: } else if (value instanceof org.omg.CORBA.portable.CustomValue) {
2439: org.omg.CORBA.DataOutputStream outputStream = new DataOutputStream(
2440: this );
2441:
2442: write_value_header(((org.omg.CORBA.portable.CustomValue) value)
2443: ._truncatable_ids());
2444: ((org.omg.CORBA.portable.CustomValue) value)
2445: .marshal(outputStream);
2446: } else {
2447: String[] repository_ids = (repository_id == null) ? null
2448: : new String[] { repository_id };
2449: Class clazz = value.getClass();
2450: String codebase = ValueHandler.getCodebase(clazz);
2451: if (value instanceof org.omg.CORBA.portable.IDLEntity) {
2452: java.lang.reflect.Method writeMethod = null;
2453: if (clazz != org.omg.CORBA.Any.class) {
2454: String helperClassName = clazz.getName() + "Helper";
2455:
2456: try {
2457: Class helperClass = (clazz.getClassLoader() != null) ? clazz
2458: .getClassLoader().loadClass(
2459: helperClassName)
2460: : ObjectUtil
2461: .classForName(helperClassName);
2462:
2463: Class[] paramTypes = {
2464: org.omg.CORBA.portable.OutputStream.class,
2465: clazz };
2466: writeMethod = helperClass.getMethod("write",
2467: paramTypes);
2468: } catch (ClassNotFoundException e) {
2469: throw new MARSHAL("Error loading class "
2470: + helperClassName + ": " + e);
2471: } catch (NoSuchMethodException e) {
2472: throw new MARSHAL(
2473: "No write method in helper class "
2474: + helperClassName + ": " + e);
2475: }
2476: }
2477: write_value_header(repository_ids, codebase);
2478: start_chunk();
2479: if (writeMethod == null) {
2480: write_any((org.omg.CORBA.Any) value);
2481: } else {
2482: try {
2483: writeMethod.invoke(null, new Object[] { this ,
2484: value });
2485: } catch (IllegalAccessException e) {
2486: throw new MARSHAL("Internal error: " + e);
2487: } catch (java.lang.reflect.InvocationTargetException e) {
2488: throw new MARSHAL(
2489: "Exception marshaling IDLEntity: "
2490: + e.getTargetException());
2491: }
2492: }
2493: end_chunk();
2494:
2495: } else {
2496: try {
2497: writeValueNestingLevel++;
2498: if (chunkCustomRmiValuetypes
2499: && ValueHandler.isCustomMarshaled(clazz)) {
2500: chunkingFlag = 0x00000008;
2501: }
2502:
2503: Serializable newValue = value;
2504: if (!writeReplaceCalled) {
2505: // writeReplace must be called only once for this value
2506: newValue = ValueHandler.writeReplace(value);
2507: writeReplaceCalled = true; // won't call it again
2508: }
2509:
2510: if (newValue != value) {
2511: // recompute codebase and/or repositoryID as might have changed
2512: String new_rep_id = ValueHandler
2513: .getRMIRepositoryID(newValue.getClass());
2514: repository_ids = (new_rep_id == null) ? null
2515: : new String[] { new_rep_id };
2516: clazz = newValue.getClass();
2517: codebase = ValueHandler.getCodebase(clazz);
2518: }
2519:
2520: write_value_header(repository_ids, codebase);
2521: start_chunk();
2522:
2523: if (newValue != value) {
2524: // look at the new value
2525: Integer index = (Integer) getValueMap().get(
2526: newValue);
2527: if (index != null) {
2528: // previously marshaled value -- make an indirection
2529: write_long(0xffffffff);
2530: write_long(index.intValue() - size());
2531: } else if (newValue instanceof org.omg.CORBA.Object) {
2532: write_Object((org.omg.CORBA.Object) newValue);
2533: } else {
2534: ValueHandler.writeValue(this , newValue);
2535: }
2536: } else {
2537: // Skip writeReplace call
2538: // (writeReplace was already called for this value)
2539: ValueHandler.writeValue(this , value);
2540: }
2541: end_chunk();
2542: } finally {
2543: if (--writeValueNestingLevel == 0) {
2544: writeReplaceCalled = false;
2545: }
2546: }
2547: }
2548: }
2549: }
2550:
2551: /**
2552: * start a new chunk, end any previously started chunk (no nesting!)
2553: */
2554:
2555: private void start_chunk() {
2556: if (chunkingFlag > 0) {
2557: write_previous_chunk_size();
2558: valueNestingLevel++;
2559: skip_chunk_size_tag();
2560: }
2561: }
2562:
2563: private void end_chunk() {
2564: if (chunkingFlag > 0) {
2565: write_previous_chunk_size();
2566: write_long(-valueNestingLevel);
2567: if (--valueNestingLevel == 0) {
2568: // ending chunk for outermost value
2569: chunkingFlag = 0;
2570: } else {
2571: // start continuation chunk for outer value
2572: skip_chunk_size_tag();
2573: }
2574: }
2575: }
2576:
2577: /**
2578: * writes the chunk size to the header of the previous chunk
2579: */
2580: private void write_previous_chunk_size() {
2581: if (chunk_size_tag_pos != -1) {
2582: if (pos == chunk_octets_pos) {
2583: // empty chunk: erase chunk size tag
2584: pos = chunk_size_tag_pos; // the tag will be overwritten
2585: index = chunk_size_tag_index; // by subsequent data
2586: } else {
2587: // go to the beginning of the chunk and write the size tag
2588: rewrite_long(chunk_size_tag_pos, chunk_size_tag_index,
2589: pos - chunk_octets_pos);
2590: }
2591: chunk_size_tag_pos = -1; // no chunk is currently open
2592: }
2593: }
2594:
2595: private void skip_chunk_size_tag() {
2596: // remember where we are right now,
2597: chunk_size_tag_pos = pos;
2598: chunk_size_tag_index = index;
2599:
2600: // insert four bytes here as a place-holder
2601: write_long(0); // need to go back later and write the actual size
2602:
2603: // remember starting position of chunk data
2604: chunk_octets_pos = pos;
2605: }
2606:
2607: /**
2608: * Writes a CORBA long value to (write_pos, write_index) without clearing
2609: * the buffer padding. In the case of a non-sequential write, clearing
2610: * buffer positions after the data just written is likely to erase data
2611: * previously written.
2612: */
2613: private final void rewrite_long(int write_pos, int write_index,
2614: final int value) {
2615: final int align = 4;
2616: int remainder = align - (write_index % align);
2617: if (remainder != align) {
2618: write_index += remainder;
2619: write_pos += remainder;
2620: }
2621: _write4int(buffer, write_pos, value);
2622: }
2623:
2624: /**
2625: * Writes an abstract interface to this stream. The abstract interface is
2626: * written as a union with a boolean discriminator, which is true if the
2627: * union contains a CORBA object reference, or false if the union contains
2628: * a value.
2629: */
2630: public void write_abstract_interface(final java.lang.Object object) {
2631: if (object instanceof org.omg.CORBA.Object) {
2632: write_boolean(true);
2633: write_Object((org.omg.CORBA.Object) object);
2634: } else {
2635: write_boolean(false);
2636: write_value((java.io.Serializable) object);
2637: }
2638: }
2639:
2640: /**
2641: * <code>updateMutatorConnection</code> is an accessor that updates the
2642: * ior mutator.
2643: *
2644: * By making callers pass in a GIOPConnection not a transport this allows
2645: * callers to not have to call getTransport which would require a synchronized
2646: * lock. Therefore if the mutator has not been enabled this is effectively a
2647: * NOP.
2648: *
2649: * @param connection an <code>org.omg.ETF.Connection</code> value
2650: */
2651: public void updateMutatorConnection(GIOPConnection connection) {
2652: if (isMutatorEnabled) {
2653: mutator.updateConnection(connection.getTransport());
2654: }
2655: }
2656: }
|