[sword-svn] r299 - in trunk/src: . com com/sun com/sun/corba com/sun/corba/se com/sun/corba/se/impl com/sun/corba/se/impl/encoding
scribe at www.crosswire.org
scribe at www.crosswire.org
Wed Sep 24 18:36:34 MST 2008
Author: scribe
Date: 2008-09-24 18:36:34 -0700 (Wed, 24 Sep 2008)
New Revision: 299
Added:
trunk/src/com/
trunk/src/com/sun/
trunk/src/com/sun/corba/
trunk/src/com/sun/corba/se/
trunk/src/com/sun/corba/se/impl/
trunk/src/com/sun/corba/se/impl/encoding/
trunk/src/com/sun/corba/se/impl/encoding/CDRInputStream.java
trunk/src/com/sun/corba/se/impl/encoding/CDROutputStream.java
trunk/src/com/sun/corba/se/impl/encoding/CodeSetConversion.java
Log:
Added CORBA mods to default to lenient UTF-8 codesets
Added: trunk/src/com/sun/corba/se/impl/encoding/CDRInputStream.java
===================================================================
--- trunk/src/com/sun/corba/se/impl/encoding/CDRInputStream.java (rev 0)
+++ trunk/src/com/sun/corba/se/impl/encoding/CDRInputStream.java 2008-09-25 01:36:34 UTC (rev 299)
@@ -0,0 +1,521 @@
+/*
+ * @(#)CDRInputStream.java 1.35 05/11/17
+ *
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ */
+package com.sun.corba.se.impl.encoding;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.nio.ByteBuffer;
+
+import org.omg.CORBA.TypeCode;
+import org.omg.CORBA.Principal;
+import org.omg.CORBA.Any;
+
+import com.sun.org.omg.SendingContext.CodeBase;
+
+import com.sun.corba.se.pept.protocol.MessageMediator;
+
+import com.sun.corba.se.spi.logging.CORBALogDomains;
+import com.sun.corba.se.spi.orb.ORB;
+import com.sun.corba.se.spi.ior.iiop.GIOPVersion;
+import com.sun.corba.se.spi.protocol.CorbaMessageMediator;
+
+import com.sun.corba.se.impl.logging.ORBUtilSystemException;
+import com.sun.corba.se.impl.encoding.CodeSetConversion;
+import com.sun.corba.se.impl.encoding.OSFCodeSetRegistry;
+import com.sun.corba.se.impl.orbutil.ORBUtility;
+import com.sun.corba.se.impl.protocol.giopmsgheaders.Message;
+
+/**
+ * This is delegates to the real implementation.
+ *
+ * NOTE:
+ *
+ * Before using the stream for valuetype unmarshaling, one must call
+ * performORBVersionSpecificInit().
+ */
+public abstract class CDRInputStream
+ extends org.omg.CORBA_2_3.portable.InputStream
+ implements com.sun.corba.se.impl.encoding.MarshalInputStream,
+ org.omg.CORBA.DataInputStream, org.omg.CORBA.portable.ValueInputStream
+{
+ protected CorbaMessageMediator messageMediator;
+ private CDRInputStreamBase impl;
+
+ // We can move this out somewhere later. For now, it serves its purpose
+ // to create a concrete CDR delegate based on the GIOP version.
+ private static class InputStreamFactory {
+
+ public static CDRInputStreamBase newInputStream(
+ ORB orb, GIOPVersion version, byte encodingVersion) {
+ switch(version.intValue()) {
+ case GIOPVersion.VERSION_1_0:
+ return new CDRInputStream_1_0();
+ case GIOPVersion.VERSION_1_1:
+ return new CDRInputStream_1_1();
+ case GIOPVersion.VERSION_1_2:
+ if (encodingVersion != Message.CDR_ENC_VERSION) {
+ return
+ new IDLJavaSerializationInputStream(encodingVersion);
+ }
+ return new CDRInputStream_1_2();
+ // else fall through and report exception.
+ default:
+ ORBUtilSystemException wrapper = ORBUtilSystemException.get( orb,
+ CORBALogDomains.RPC_ENCODING ) ;
+ throw wrapper.unsupportedGiopVersion( version ) ;
+ }
+ }
+ }
+
+ // Required for the case when a ClientResponseImpl is
+ // created with a SystemException due to a dead server/closed
+ // connection with no warning. Note that the stream will
+ // not be initialized in this case.
+ //
+ // Probably also required by ServerRequestImpl.
+ //
+ // REVISIT.
+ public CDRInputStream() {
+ }
+
+ public CDRInputStream(CDRInputStream is) {
+ impl = is.impl.dup();
+ impl.setParent(this);
+ }
+
+ public CDRInputStream(org.omg.CORBA.ORB orb,
+ ByteBuffer byteBuffer,
+ int size,
+ boolean littleEndian,
+ GIOPVersion version,
+ byte encodingVersion,
+ BufferManagerRead bufMgr)
+ {
+ impl = InputStreamFactory.newInputStream((ORB)orb, version,
+ encodingVersion);
+
+ impl.init(orb, byteBuffer, size, littleEndian, bufMgr);
+
+ impl.setParent(this);
+ }
+
+ // org.omg.CORBA.portable.InputStream
+ public final boolean read_boolean() {
+ return impl.read_boolean();
+ }
+
+ public final char read_char() {
+ return impl.read_char();
+ }
+
+ public final char read_wchar() {
+ return impl.read_wchar();
+ }
+
+ public final byte read_octet() {
+ return impl.read_octet();
+ }
+
+ public final short read_short() {
+ return impl.read_short();
+ }
+
+ public final short read_ushort() {
+ return impl.read_ushort();
+ }
+
+ public final int read_long() {
+ return impl.read_long();
+ }
+
+ public final int read_ulong() {
+ return impl.read_ulong();
+ }
+
+ public final long read_longlong() {
+ return impl.read_longlong();
+ }
+
+ public final long read_ulonglong() {
+ return impl.read_ulonglong();
+ }
+
+ public final float read_float() {
+ return impl.read_float();
+ }
+
+ public final double read_double() {
+ return impl.read_double();
+ }
+
+ public final String read_string() {
+ return impl.read_string();
+ }
+
+ public final String read_wstring() {
+ return impl.read_wstring();
+ }
+
+ public final void read_boolean_array(boolean[] value, int offset, int length) {
+ impl.read_boolean_array(value, offset, length);
+ }
+
+ public final void read_char_array(char[] value, int offset, int length) {
+ impl.read_char_array(value, offset, length);
+ }
+
+ public final void read_wchar_array(char[] value, int offset, int length) {
+ impl.read_wchar_array(value, offset, length);
+ }
+
+ public final void read_octet_array(byte[] value, int offset, int length) {
+ impl.read_octet_array(value, offset, length);
+ }
+
+ public final void read_short_array(short[] value, int offset, int length) {
+ impl.read_short_array(value, offset, length);
+ }
+
+ public final void read_ushort_array(short[] value, int offset, int length) {
+ impl.read_ushort_array(value, offset, length);
+ }
+
+ public final void read_long_array(int[] value, int offset, int length) {
+ impl.read_long_array(value, offset, length);
+ }
+
+ public final void read_ulong_array(int[] value, int offset, int length) {
+ impl.read_ulong_array(value, offset, length);
+ }
+
+ public final void read_longlong_array(long[] value, int offset, int length) {
+ impl.read_longlong_array(value, offset, length);
+ }
+
+ public final void read_ulonglong_array(long[] value, int offset, int length) {
+ impl.read_ulonglong_array(value, offset, length);
+ }
+
+ public final void read_float_array(float[] value, int offset, int length) {
+ impl.read_float_array(value, offset, length);
+ }
+
+ public final void read_double_array(double[] value, int offset, int length) {
+ impl.read_double_array(value, offset, length);
+ }
+
+ public final org.omg.CORBA.Object read_Object() {
+ return impl.read_Object();
+ }
+
+ public final TypeCode read_TypeCode() {
+ return impl.read_TypeCode();
+ }
+ public final Any read_any() {
+ return impl.read_any();
+ }
+
+ public final Principal read_Principal() {
+ return impl.read_Principal();
+ }
+
+ public final int read() throws java.io.IOException {
+ return impl.read();
+ }
+
+ public final java.math.BigDecimal read_fixed() {
+ return impl.read_fixed();
+ }
+
+ public final org.omg.CORBA.Context read_Context() {
+ return impl.read_Context();
+ }
+
+ public final org.omg.CORBA.Object read_Object(java.lang.Class clz) {
+ return impl.read_Object(clz);
+ }
+
+ public final org.omg.CORBA.ORB orb() {
+ return impl.orb();
+ }
+
+ // org.omg.CORBA_2_3.portable.InputStream
+ public final java.io.Serializable read_value() {
+ return impl.read_value();
+ }
+
+ public final java.io.Serializable read_value(java.lang.Class clz) {
+ return impl.read_value(clz);
+ }
+
+ public final java.io.Serializable read_value(org.omg.CORBA.portable.BoxedValueHelper factory) {
+ return impl.read_value(factory);
+ }
+
+ public final java.io.Serializable read_value(java.lang.String rep_id) {
+ return impl.read_value(rep_id);
+ }
+
+ public final java.io.Serializable read_value(java.io.Serializable value) {
+ return impl.read_value(value);
+ }
+
+ public final java.lang.Object read_abstract_interface() {
+ return impl.read_abstract_interface();
+ }
+
+ public final java.lang.Object read_abstract_interface(java.lang.Class clz) {
+ return impl.read_abstract_interface(clz);
+ }
+ // com.sun.corba.se.impl.encoding.MarshalInputStream
+
+ public final void consumeEndian() {
+ impl.consumeEndian();
+ }
+
+ public final int getPosition() {
+ return impl.getPosition();
+ }
+
+ // org.omg.CORBA.DataInputStream
+
+ public final java.lang.Object read_Abstract () {
+ return impl.read_Abstract();
+ }
+
+ public final java.io.Serializable read_Value () {
+ return impl.read_Value();
+ }
+
+ public final void read_any_array (org.omg.CORBA.AnySeqHolder seq, int offset, int length) {
+ impl.read_any_array(seq, offset, length);
+ }
+
+ public final void read_boolean_array (org.omg.CORBA.BooleanSeqHolder seq, int offset, int length) {
+ impl.read_boolean_array(seq, offset, length);
+ }
+
+ public final void read_char_array (org.omg.CORBA.CharSeqHolder seq, int offset, int length) {
+ impl.read_char_array(seq, offset, length);
+ }
+
+ public final void read_wchar_array (org.omg.CORBA.WCharSeqHolder seq, int offset, int length) {
+ impl.read_wchar_array(seq, offset, length);
+ }
+
+ public final void read_octet_array (org.omg.CORBA.OctetSeqHolder seq, int offset, int length) {
+ impl.read_octet_array(seq, offset, length);
+ }
+
+ public final void read_short_array (org.omg.CORBA.ShortSeqHolder seq, int offset, int length) {
+ impl.read_short_array(seq, offset, length);
+ }
+
+ public final void read_ushort_array (org.omg.CORBA.UShortSeqHolder seq, int offset, int length) {
+ impl.read_ushort_array(seq, offset, length);
+ }
+
+ public final void read_long_array (org.omg.CORBA.LongSeqHolder seq, int offset, int length) {
+ impl.read_long_array(seq, offset, length);
+ }
+
+ public final void read_ulong_array (org.omg.CORBA.ULongSeqHolder seq, int offset, int length) {
+ impl.read_ulong_array(seq, offset, length);
+ }
+
+ public final void read_ulonglong_array (org.omg.CORBA.ULongLongSeqHolder seq, int offset, int length) {
+ impl.read_ulonglong_array(seq, offset, length);
+ }
+
+ public final void read_longlong_array (org.omg.CORBA.LongLongSeqHolder seq, int offset, int length) {
+ impl.read_longlong_array(seq, offset, length);
+ }
+
+ public final void read_float_array (org.omg.CORBA.FloatSeqHolder seq, int offset, int length) {
+ impl.read_float_array(seq, offset, length);
+ }
+
+ public final void read_double_array (org.omg.CORBA.DoubleSeqHolder seq, int offset, int length) {
+ impl.read_double_array(seq, offset, length);
+ }
+
+ // org.omg.CORBA.portable.ValueBase
+ public final String[] _truncatable_ids() {
+ return impl._truncatable_ids();
+ }
+
+ // java.io.InputStream
+ public final int read(byte b[]) throws IOException {
+ return impl.read(b);
+ }
+
+ public final int read(byte b[], int off, int len) throws IOException {
+ return impl.read(b, off, len);
+ }
+
+ public final long skip(long n) throws IOException {
+ return impl.skip(n);
+ }
+
+ public final int available() throws IOException {
+ return impl.available();
+ }
+
+ public final void close() throws IOException {
+ impl.close();
+ }
+
+ public final void mark(int readlimit) {
+ impl.mark(readlimit);
+ }
+
+ public final void reset() {
+ impl.reset();
+ }
+
+ public final boolean markSupported() {
+ return impl.markSupported();
+ }
+
+ public abstract CDRInputStream dup();
+
+ // Needed by TCUtility
+ public final java.math.BigDecimal read_fixed(short digits, short scale) {
+ return impl.read_fixed(digits, scale);
+ }
+
+ public final boolean isLittleEndian() {
+ return impl.isLittleEndian();
+ }
+
+ protected final ByteBuffer getByteBuffer() {
+ return impl.getByteBuffer();
+ }
+
+ protected final void setByteBuffer(ByteBuffer byteBuffer) {
+ impl.setByteBuffer(byteBuffer);
+ }
+
+ protected final void setByteBufferWithInfo(ByteBufferWithInfo bbwi) {
+ impl.setByteBufferWithInfo(bbwi);
+ }
+
+ public final int getBufferLength() {
+ return impl.getBufferLength();
+ }
+
+ protected final void setBufferLength(int value) {
+ impl.setBufferLength(value);
+ }
+
+ protected final int getIndex() {
+ return impl.getIndex();
+ }
+
+ protected final void setIndex(int value) {
+ impl.setIndex(value);
+ }
+
+ public final void orb(org.omg.CORBA.ORB orb) {
+ impl.orb(orb);
+ }
+
+ public final GIOPVersion getGIOPVersion() {
+ return impl.getGIOPVersion();
+ }
+
+ public final BufferManagerRead getBufferManager() {
+ return impl.getBufferManager();
+ }
+
+ // This should be overridden by any stream (ex: IIOPInputStream)
+ // which wants to read values. Thus, TypeCodeInputStream doesn't
+ // have to do this.
+ public CodeBase getCodeBase() {
+ return null;
+ }
+
+ // Use Latin-1 for GIOP 1.0 or when code set negotiation was not
+ // performed.
+ protected CodeSetConversion.BTCConverter createCharBTCConverter() {
+ CodeSetConversion.BTCConverter btc =
+ CodeSetConversion.impl().getBTCConverter(OSFCodeSetRegistry.UTF_8,
+ impl.isLittleEndian());
+ return btc;
+ }
+
+ // Subclasses must decide what to do here. It's inconvenient to
+ // make the class and this method abstract because of dup().
+ protected abstract CodeSetConversion.BTCConverter createWCharBTCConverter();
+
+ // Prints the current buffer in a human readable form
+ void printBuffer() {
+ impl.printBuffer();
+ }
+
+ /**
+ * Aligns the current position on the given octet boundary
+ * if there are enough bytes available to do so. Otherwise,
+ * it just returns. This is used for some (but not all)
+ * GIOP 1.2 message headers.
+ */
+ public void alignOnBoundary(int octetBoundary) {
+ impl.alignOnBoundary(octetBoundary);
+ }
+
+ // Needed by request and reply messages for GIOP versions >= 1.2 only.
+ public void setHeaderPadding(boolean headerPadding) {
+ impl.setHeaderPadding(headerPadding);
+ }
+
+ /**
+ * This must be called after determining the proper ORB version,
+ * and setting it on the stream's ORB instance. It can be called
+ * after reading the service contexts, since that is the only place
+ * we can get the ORB version info.
+ *
+ * Trying to unmarshal things requiring repository IDs before calling
+ * this will result in NullPtrExceptions.
+ */
+ public void performORBVersionSpecificInit() {
+ // In the case of SystemExceptions, a stream is created
+ // with its default constructor (and thus no impl is set).
+ if (impl != null)
+ impl.performORBVersionSpecificInit();
+ }
+
+ /**
+ * Resets any internal references to code set converters.
+ * This is useful for forcing the CDR stream to reacquire
+ * converters (probably from its subclasses) when state
+ * has changed.
+ */
+ public void resetCodeSetConverters() {
+ impl.resetCodeSetConverters();
+ }
+
+ public void setMessageMediator(MessageMediator messageMediator)
+ {
+ this.messageMediator = (CorbaMessageMediator) messageMediator;
+ }
+
+ public MessageMediator getMessageMediator()
+ {
+ return messageMediator;
+ }
+
+ // ValueInputStream -----------------------------
+
+ public void start_value() {
+ impl.start_value();
+ }
+
+ public void end_value() {
+ impl.end_value();
+ }
+}
Added: trunk/src/com/sun/corba/se/impl/encoding/CDROutputStream.java
===================================================================
--- trunk/src/com/sun/corba/se/impl/encoding/CDROutputStream.java (rev 0)
+++ trunk/src/com/sun/corba/se/impl/encoding/CDROutputStream.java 2008-09-25 01:36:34 UTC (rev 299)
@@ -0,0 +1,413 @@
+/*
+ * @(#)CDROutputStream.java 1.29 05/11/17
+ *
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ */
+package com.sun.corba.se.impl.encoding;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.nio.ByteBuffer;
+
+import org.omg.CORBA.TypeCode;
+import org.omg.CORBA.Principal;
+import org.omg.CORBA.Any;
+
+import com.sun.corba.se.pept.protocol.MessageMediator;
+
+import com.sun.corba.se.spi.orb.ORB;
+import com.sun.corba.se.spi.logging.CORBALogDomains;
+import com.sun.corba.se.spi.ior.iiop.GIOPVersion;
+import com.sun.corba.se.spi.protocol.CorbaMessageMediator;
+
+import com.sun.corba.se.impl.encoding.CodeSetConversion;
+import com.sun.corba.se.impl.encoding.OSFCodeSetRegistry;
+import com.sun.corba.se.impl.orbutil.ORBConstants;
+import com.sun.corba.se.impl.logging.ORBUtilSystemException;
+import com.sun.corba.se.impl.protocol.giopmsgheaders.Message;
+
+/**
+ * This is delegates to the real implementation.
+ */
+public abstract class CDROutputStream
+ extends org.omg.CORBA_2_3.portable.OutputStream
+ implements com.sun.corba.se.impl.encoding.MarshalOutputStream,
+ org.omg.CORBA.DataOutputStream, org.omg.CORBA.portable.ValueOutputStream
+{
+ private CDROutputStreamBase impl;
+ protected ORB orb ;
+ protected ORBUtilSystemException wrapper ;
+ protected CorbaMessageMediator corbaMessageMediator;
+
+
+ // We can move this out somewhere later. For now, it serves its purpose
+ // to create a concrete CDR delegate based on the GIOP version.
+ private static class OutputStreamFactory {
+
+ public static CDROutputStreamBase newOutputStream(
+ ORB orb, GIOPVersion version, byte encodingVersion) {
+ switch(version.intValue()) {
+ case GIOPVersion.VERSION_1_0:
+ return new CDROutputStream_1_0();
+ case GIOPVersion.VERSION_1_1:
+ return new CDROutputStream_1_1();
+ case GIOPVersion.VERSION_1_2:
+ if (encodingVersion != Message.CDR_ENC_VERSION) {
+ return
+ new IDLJavaSerializationOutputStream(encodingVersion);
+ }
+ return new CDROutputStream_1_2();
+ default:
+ ORBUtilSystemException wrapper = ORBUtilSystemException.get( orb,
+ CORBALogDomains.RPC_ENCODING ) ;
+ // REVISIT - what is appropriate? INTERNAL exceptions
+ // are really hard to track later.
+ throw wrapper.unsupportedGiopVersion( version ) ;
+ }
+ }
+ }
+
+ // REVISIT - These two constructors should be re-factored to better hide
+ // the fact that someone extending this class 'can' construct a CDROutputStream
+ // that does not use pooled ByteBuffers. Right now, only EncapsOutputStream
+ // does _not_ use pooled ByteBuffers, see EncapsOutputStream.
+
+ // NOTE: When a stream is constructed for non-channel-backed sockets
+ // it notifies the constructor not to use pooled (i.e, direct)
+ // ByteBuffers.
+
+ public CDROutputStream(ORB orb,
+ GIOPVersion version,
+ byte encodingVersion,
+ boolean littleEndian,
+ BufferManagerWrite bufferManager,
+ byte streamFormatVersion,
+ boolean usePooledByteBuffers)
+ {
+ impl = OutputStreamFactory.newOutputStream(orb, version,
+ encodingVersion);
+ impl.init(orb, littleEndian, bufferManager,
+ streamFormatVersion, usePooledByteBuffers);
+
+ impl.setParent(this);
+ this.orb = orb ;
+ this.wrapper = ORBUtilSystemException.get( orb,
+ CORBALogDomains.RPC_ENCODING ) ;
+ }
+
+ public CDROutputStream(ORB orb,
+ GIOPVersion version,
+ byte encodingVersion,
+ boolean littleEndian,
+ BufferManagerWrite bufferManager,
+ byte streamFormatVersion)
+ {
+ this(orb, version, encodingVersion, littleEndian,
+ bufferManager, streamFormatVersion, true);
+ }
+
+ // org.omg.CORBA.portable.OutputStream
+
+ // Provided by IIOPOutputStream and EncapsOutputStream
+ public abstract org.omg.CORBA.portable.InputStream create_input_stream();
+
+ public final void write_boolean(boolean value) {
+ impl.write_boolean(value);
+ }
+ public final void write_char(char value) {
+ impl.write_char(value);
+ }
+ public final void write_wchar(char value) {
+ impl.write_wchar(value);
+ }
+ public final void write_octet(byte value) {
+ impl.write_octet(value);
+ }
+ public final void write_short(short value) {
+ impl.write_short(value);
+ }
+ public final void write_ushort(short value) {
+ impl.write_ushort(value);
+ }
+ public final void write_long(int value) {
+ impl.write_long(value);
+ }
+ public final void write_ulong(int value) {
+ impl.write_ulong(value);
+ }
+ public final void write_longlong(long value) {
+ impl.write_longlong(value);
+ }
+ public final void write_ulonglong(long value) {
+ impl.write_ulonglong(value);
+ }
+ public final void write_float(float value) {
+ impl.write_float(value);
+ }
+ public final void write_double(double value) {
+ impl.write_double(value);
+ }
+ public final void write_string(String value) {
+ impl.write_string(value);
+ }
+ public final void write_wstring(String value) {
+ impl.write_wstring(value);
+ }
+
+ public final void write_boolean_array(boolean[] value, int offset, int length) {
+ impl.write_boolean_array(value, offset, length);
+ }
+ public final void write_char_array(char[] value, int offset, int length) {
+ impl.write_char_array(value, offset, length);
+ }
+ public final void write_wchar_array(char[] value, int offset, int length) {
+ impl.write_wchar_array(value, offset, length);
+ }
+ public final void write_octet_array(byte[] value, int offset, int length) {
+ impl.write_octet_array(value, offset, length);
+ }
+ public final void write_short_array(short[] value, int offset, int length) {
+ impl.write_short_array(value, offset, length);
+ }
+ public final void write_ushort_array(short[] value, int offset, int length){
+ impl.write_ushort_array(value, offset, length);
+ }
+ public final void write_long_array(int[] value, int offset, int length) {
+ impl.write_long_array(value, offset, length);
+ }
+ public final void write_ulong_array(int[] value, int offset, int length) {
+ impl.write_ulong_array(value, offset, length);
+ }
+ public final void write_longlong_array(long[] value, int offset, int length) {
+ impl.write_longlong_array(value, offset, length);
+ }
+ public final void write_ulonglong_array(long[] value, int offset,int length) {
+ impl.write_ulonglong_array(value, offset, length);
+ }
+ public final void write_float_array(float[] value, int offset, int length) {
+ impl.write_float_array(value, offset, length);
+ }
+ public final void write_double_array(double[] value, int offset, int length) {
+ impl.write_double_array(value, offset, length);
+ }
+ public final void write_Object(org.omg.CORBA.Object value) {
+ impl.write_Object(value);
+ }
+ public final void write_TypeCode(TypeCode value) {
+ impl.write_TypeCode(value);
+ }
+ public final void write_any(Any value) {
+ impl.write_any(value);
+ }
+
+ public final void write_Principal(Principal value) {
+ impl.write_Principal(value);
+ }
+
+ public final void write(int b) throws java.io.IOException {
+ impl.write(b);
+ }
+
+ public final void write_fixed(java.math.BigDecimal value) {
+ impl.write_fixed(value);
+ }
+
+ public final void write_Context(org.omg.CORBA.Context ctx,
+ org.omg.CORBA.ContextList contexts) {
+ impl.write_Context(ctx, contexts);
+ }
+
+ public final org.omg.CORBA.ORB orb() {
+ return impl.orb();
+ }
+
+ // org.omg.CORBA_2_3.portable.OutputStream
+ public final void write_value(java.io.Serializable value) {
+ impl.write_value(value);
+ }
+
+ public final void write_value(java.io.Serializable value, java.lang.Class clz) {
+ impl.write_value(value, clz);
+ }
+
+ public final void write_value(java.io.Serializable value, String repository_id) {
+ impl.write_value(value, repository_id);
+ }
+
+ public final void write_value(java.io.Serializable value,
+ org.omg.CORBA.portable.BoxedValueHelper factory) {
+ impl.write_value(value, factory);
+ }
+
+ public final void write_abstract_interface(java.lang.Object obj) {
+ impl.write_abstract_interface(obj);
+ }
+
+ // java.io.OutputStream
+ public final void write(byte b[]) throws IOException {
+ impl.write(b);
+ }
+
+ public final void write(byte b[], int off, int len) throws IOException {
+ impl.write(b, off, len);
+ }
+
+ public final void flush() throws IOException {
+ impl.flush();
+ }
+
+ public final void close() throws IOException {
+ impl.close();
+ }
+
+ // com.sun.corba.se.impl.encoding.MarshalOutputStream
+ public final void start_block() {
+ impl.start_block();
+ }
+
+ public final void end_block() {
+ impl.end_block();
+ }
+
+ public final void putEndian() {
+ impl.putEndian();
+ }
+
+ public void writeTo(java.io.OutputStream s)
+ throws IOException
+ {
+ impl.writeTo(s);
+ }
+
+ public final byte[] toByteArray() {
+ return impl.toByteArray();
+ }
+
+ // org.omg.CORBA.DataOutputStream
+ public final void write_Abstract (java.lang.Object value) {
+ impl.write_Abstract(value);
+ }
+
+ public final void write_Value (java.io.Serializable value) {
+ impl.write_Value(value);
+ }
+
+ public final void write_any_array(org.omg.CORBA.Any[] seq, int offset, int length) {
+ impl.write_any_array(seq, offset, length);
+ }
+
+ public void setMessageMediator(MessageMediator messageMediator)
+ {
+ this.corbaMessageMediator = (CorbaMessageMediator) messageMediator;
+ }
+
+ public MessageMediator getMessageMediator()
+ {
+ return corbaMessageMediator;
+ }
+
+ // org.omg.CORBA.portable.ValueBase
+ public final String[] _truncatable_ids() {
+ return impl._truncatable_ids();
+ }
+
+ // Other
+ protected final int getSize() {
+ return impl.getSize();
+ }
+
+ protected final int getIndex() {
+ return impl.getIndex();
+ }
+
+ protected int getRealIndex(int index) {
+ // Used in indirections. Overridden by TypeCodeOutputStream.
+ return index;
+ }
+
+ protected final void setIndex(int value) {
+ impl.setIndex(value);
+ }
+
+ protected final ByteBuffer getByteBuffer() {
+ return impl.getByteBuffer();
+ }
+
+ protected final void setByteBuffer(ByteBuffer byteBuffer) {
+ impl.setByteBuffer(byteBuffer);
+ }
+
+ public final boolean isLittleEndian() {
+ return impl.isLittleEndian();
+ }
+
+ // XREVISIT - return to final if possible
+ // REVISIT - was protected - need access from msgtypes test.
+ public ByteBufferWithInfo getByteBufferWithInfo() {
+ return impl.getByteBufferWithInfo();
+ }
+
+ protected void setByteBufferWithInfo(ByteBufferWithInfo bbwi) {
+ impl.setByteBufferWithInfo(bbwi);
+ }
+
+ // REVISIT: was protected - but need to access from xgiop.
+ public final BufferManagerWrite getBufferManager() {
+ return impl.getBufferManager();
+ }
+
+ public final void write_fixed(java.math.BigDecimal bigDecimal, short digits, short scale) {
+ impl.write_fixed(bigDecimal, digits, scale);
+ }
+
+ public final void writeOctetSequenceTo(org.omg.CORBA.portable.OutputStream s) {
+ impl.writeOctetSequenceTo(s);
+ }
+
+ public final GIOPVersion getGIOPVersion() {
+ return impl.getGIOPVersion();
+ }
+
+ public final void writeIndirection(int tag, int posIndirectedTo) {
+ impl.writeIndirection(tag, posIndirectedTo);
+ }
+
+ // Use Latin-1 for GIOP 1.0 or when code set negotiation was not
+ // performed.
+ protected CodeSetConversion.CTBConverter createCharCTBConverter() {
+ return CodeSetConversion.impl().getCTBConverter(OSFCodeSetRegistry.UTF_8);
+ }
+
+ // Subclasses must decide what to do here. It's inconvenient to
+ // make the class and this method abstract because of dup().
+ protected abstract CodeSetConversion.CTBConverter createWCharCTBConverter();
+
+ protected final void freeInternalCaches() {
+ impl.freeInternalCaches();
+ }
+
+ void printBuffer() {
+ impl.printBuffer();
+ }
+
+ public void alignOnBoundary(int octetBoundary) {
+ impl.alignOnBoundary(octetBoundary);
+ }
+
+ // Needed by request and reply messages for GIOP versions >= 1.2 only.
+ public void setHeaderPadding(boolean headerPadding) {
+ impl.setHeaderPadding(headerPadding);
+ }
+
+ // ValueOutputStream -----------------------------
+
+ public void start_value(String rep_id) {
+ impl.start_value(rep_id);
+ }
+
+ public void end_value() {
+ impl.end_value();
+ }
+}
Added: trunk/src/com/sun/corba/se/impl/encoding/CodeSetConversion.java
===================================================================
--- trunk/src/com/sun/corba/se/impl/encoding/CodeSetConversion.java (rev 0)
+++ trunk/src/com/sun/corba/se/impl/encoding/CodeSetConversion.java 2008-09-25 01:36:34 UTC (rev 299)
@@ -0,0 +1,693 @@
+/*
+ * @(#)CodeSetConversion.java 1.20 05/11/17
+ *
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ */
+package com.sun.corba.se.impl.encoding;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.IllegalCharsetNameException;
+import java.nio.charset.MalformedInputException;
+import java.nio.charset.UnsupportedCharsetException;
+import java.nio.charset.UnmappableCharacterException;
+import com.sun.corba.se.impl.logging.ORBUtilSystemException;
+import com.sun.corba.se.impl.logging.OMGSystemException;
+import com.sun.corba.se.spi.logging.CORBALogDomains;
+
+/**
+ * Collection of classes, interfaces, and factory methods for
+ * CORBA code set conversion.
+ *
+ * This is mainly used to shield other code from the sun.io
+ * converters which might change, as well as provide some basic
+ * translation from conversion to CORBA error exceptions. Some
+ * extra work is required here to facilitate the way CORBA
+ * says it uses UTF-16 as of the 00-11-03 spec.
+ *
+ * REVISIT - Since the nio.Charset and nio.Charset.Encoder/Decoder
+ * use NIO ByteBuffer and NIO CharBuffer, the interaction
+ * and interface between this class and the CDR streams
+ * should be looked at more closely for optimizations to
+ * avoid unnecessary copying of data between char[] &
+ * CharBuffer and byte[] & ByteBuffer, especially
+ * DirectByteBuffers.
+ *
+ */
+public class CodeSetConversion
+{
+ /**
+ * Abstraction for char to byte conversion.
+ *
+ * Must be used in the proper sequence:
+ *
+ * 1) convert
+ * 2) Optional getNumBytes and/or getAlignment (if necessary)
+ * 3) getBytes (see warning)
+ */
+ public abstract static class CTBConverter
+ {
+ // Perform the conversion of the provided char or String,
+ // allowing the caller to query for more information
+ // before writing.
+ public abstract void convert(char chToConvert);
+ public abstract void convert(String strToConvert);
+
+ // How many bytes resulted from the conversion?
+ public abstract int getNumBytes();
+
+ // What's the maximum number of bytes per character?
+ public abstract float getMaxBytesPerChar();
+
+ public abstract boolean isFixedWidthEncoding();
+
+ // What byte boundary should the stream align to before
+ // calling writeBytes? For instance, a fixed width
+ // encoding with 2 bytes per char in a stream which
+ // doesn't encapsulate the char's bytes should align
+ // on a 2 byte boundary. (Ex: UTF16 in GIOP1.1)
+ //
+ // Note: This has no effect on the converted bytes. It
+ // is just information available to the caller.
+ public abstract int getAlignment();
+
+ // Get the resulting bytes. Warning: You must use getNumBytes()
+ // to determine the end of the data in the byte array instead
+ // of array.length! The array may be used internally, so don't
+ // save references.
+ public abstract byte[] getBytes();
+ }
+
+ /**
+ * Abstraction for byte to char conversion.
+ */
+ public abstract static class BTCConverter
+ {
+ // In GIOP 1.1, interoperability can only be achieved with
+ // fixed width encodings like UTF-16. This is because wstrings
+ // specified how many code points follow rather than specifying
+ // the length in octets.
+ public abstract boolean isFixedWidthEncoding();
+ public abstract int getFixedCharWidth();
+
+ // Called after getChars to determine the true size of the
+ // converted array.
+ public abstract int getNumChars();
+
+ // Perform the conversion using length bytes from the given
+ // input stream. Warning: You must use getNumChars() to
+ // determine the correct length of the resulting array.
+ // The same array may be used internally over multiple
+ // calls.
+ public abstract char[] getChars(byte[] bytes, int offset, int length);
+ }
+
+ /**
+ * Implementation of CTBConverter which uses a nio.Charset.CharsetEncoder
+ * to do the real work. Handles translation of exceptions to the
+ * appropriate CORBA versions.
+ */
+ private class JavaCTBConverter extends CTBConverter
+ {
+ private ORBUtilSystemException wrapper = ORBUtilSystemException.get(
+ CORBALogDomains.RPC_ENCODING ) ;
+
+ private OMGSystemException omgWrapper = OMGSystemException.get(
+ CORBALogDomains.RPC_ENCODING ) ;
+
+ // nio.Charset.CharsetEncoder actually does the work here
+ // have to use it directly rather than through String's interface
+ // because we want to know when errors occur during the conversion.
+ private CharsetEncoder ctb;
+
+ // Proper alignment for this type of converter. For instance,
+ // ASCII has alignment of 1 (1 byte per char) but UTF16 has
+ // alignment of 2 (2 bytes per char)
+ private int alignment;
+
+ // Char buffer to hold the input.
+ private char[] chars = null;
+
+ // How many bytes are generated from the conversion?
+ private int numBytes = 0;
+
+ // How many characters were converted (temporary variable
+ // for cross method communication)
+ private int numChars = 0;
+
+ // ByteBuffer holding the converted input. This is necessary
+ // since we have to do calculations that require the conversion
+ // before writing the array to the stream.
+ private ByteBuffer buffer;
+
+ // What code set are we using?
+ private OSFCodeSetRegistry.Entry codeset;
+
+ public JavaCTBConverter(OSFCodeSetRegistry.Entry codeset,
+ int alignmentForEncoding) {
+
+ try {
+ ctb = cache.getCharToByteConverter(codeset.getName());
+ if (ctb == null) {
+ Charset tmpCharset = Charset.forName(codeset.getName());
+ ctb = tmpCharset.newEncoder();
+ ctb.onMalformedInput(java.nio.charset.CodingErrorAction.REPLACE);
+ ctb.onUnmappableCharacter(java.nio.charset.CodingErrorAction.REPLACE);
+ cache.setConverter(codeset.getName(), ctb);
+ }
+ } catch(IllegalCharsetNameException icne) {
+
+ // This can only happen if one of our Entries has
+ // an invalid name.
+ throw wrapper.invalidCtbConverterName(icne,codeset.getName());
+ } catch(UnsupportedCharsetException ucne) {
+
+ // This can only happen if one of our Entries has
+ // an unsupported name.
+ throw wrapper.invalidCtbConverterName(ucne,codeset.getName());
+ }
+
+ this.codeset = codeset;
+ alignment = alignmentForEncoding;
+ }
+
+ public final float getMaxBytesPerChar() {
+ return ctb.maxBytesPerChar();
+ }
+
+ public void convert(char chToConvert) {
+ if (chars == null)
+ chars = new char[1];
+
+ // The CharToByteConverter only takes a char[]
+ chars[0] = chToConvert;
+ numChars = 1;
+
+ convertCharArray();
+ }
+
+ public void convert(String strToConvert) {
+ // Try to save a memory allocation if possible. Usual
+ // space/time trade off. If we could get the char[] out of
+ // the String without copying, that would be great, but
+ // it's forbidden since String is immutable.
+ if (chars == null || chars.length < strToConvert.length())
+ chars = new char[strToConvert.length()];
+
+ numChars = strToConvert.length();
+
+ strToConvert.getChars(0, numChars, chars, 0);
+
+ convertCharArray();
+ }
+
+ public final int getNumBytes() {
+ return numBytes;
+ }
+
+ public final int getAlignment() {
+ return alignment;
+ }
+
+ public final boolean isFixedWidthEncoding() {
+ return codeset.isFixedWidth();
+ }
+
+ public byte[] getBytes() {
+ // Note that you can't use buffer.length since the buffer might
+ // be larger than the actual number of converted bytes depending
+ // on the encoding.
+ return buffer.array();
+ }
+
+ private void convertCharArray() {
+ try {
+
+ // Possible optimization of directly converting into the CDR buffer.
+ // However, that means the CDR code would have to reserve
+ // a 4 byte string length ahead of time, and we'd need a
+ // confusing partial conversion scheme for when we couldn't
+ // fit everything in the buffer but needed to know the
+ // converted length before proceeding due to fragmentation.
+ // Then there's the issue of the chunking code.
+ //
+ // For right now, this is less messy and basic tests don't
+ // show more than a 1 ms penalty worst case. Less than a
+ // factor of 2 increase.
+
+ // Convert the characters
+ buffer = ctb.encode(CharBuffer.wrap(chars,0,numChars));
+
+ // ByteBuffer returned by the encoder will set its limit
+ // to byte immediately after the last written byte.
+ numBytes = buffer.limit();
+
+ } catch (IllegalStateException ise) {
+ // an encoding operation is already in progress
+ throw wrapper.ctbConverterFailure( ise ) ;
+ } catch (MalformedInputException mie) {
+ // There were illegal Unicode char pairs
+ throw wrapper.badUnicodePair( mie ) ;
+ } catch (UnmappableCharacterException uce) {
+ // A character doesn't map to the desired code set
+ // CORBA formal 00-11-03.
+ throw omgWrapper.charNotInCodeset( uce ) ;
+ } catch (CharacterCodingException cce) {
+ // If this happens, then some other encoding error occured
+ throw wrapper.ctbConverterFailure( cce ) ;
+ }
+ }
+ }
+
+ /**
+ * Special UTF16 converter which can either always write a BOM
+ * or use a specified byte order without one.
+ */
+ private class UTF16CTBConverter extends JavaCTBConverter
+ {
+ // Using this constructor, we will always write a BOM
+ public UTF16CTBConverter() {
+ super(OSFCodeSetRegistry.UTF_16, 2);
+ }
+
+ // Using this constructor, we don't use a BOM and use the
+ // byte order specified
+ public UTF16CTBConverter(boolean littleEndian) {
+ super(littleEndian ?
+ OSFCodeSetRegistry.UTF_16LE :
+ OSFCodeSetRegistry.UTF_16BE,
+ 2);
+ }
+ }
+
+ /**
+ * Implementation of BTCConverter which uses a sun.io.ByteToCharConverter
+ * for the real work. Handles translation of exceptions to the
+ * appropriate CORBA versions.
+ */
+ private class JavaBTCConverter extends BTCConverter
+ {
+ private ORBUtilSystemException wrapper = ORBUtilSystemException.get(
+ CORBALogDomains.RPC_ENCODING ) ;
+
+ private OMGSystemException omgWrapper = OMGSystemException.get(
+ CORBALogDomains.RPC_ENCODING ) ;
+
+ protected CharsetDecoder btc;
+ private char[] buffer;
+ private int resultingNumChars;
+ private OSFCodeSetRegistry.Entry codeset;
+
+ public JavaBTCConverter(OSFCodeSetRegistry.Entry codeset) {
+
+ // Obtain a Decoder
+ btc = this.getConverter(codeset.getName());
+
+ this.codeset = codeset;
+ }
+
+ public final boolean isFixedWidthEncoding() {
+ return codeset.isFixedWidth();
+ }
+
+ // Should only be called if isFixedWidthEncoding is true
+ // IMPORTANT: This calls OSFCodeSetRegistry.Entry, not
+ // CharsetDecoder.maxCharsPerByte().
+ public final int getFixedCharWidth() {
+ return codeset.getMaxBytesPerChar();
+ }
+
+ public final int getNumChars() {
+ return resultingNumChars;
+ }
+
+ public char[] getChars(byte[] bytes, int offset, int numBytes) {
+
+ // Possible optimization of reading directly from the CDR
+ // byte buffer. The sun.io converter supposedly can handle
+ // incremental conversions in which a char is broken across
+ // two convert calls.
+ //
+ // Basic tests didn't show more than a 1 ms increase
+ // worst case. It's less than a factor of 2 increase.
+ // Also makes the interface more difficult.
+
+
+ try {
+
+ ByteBuffer byteBuf = ByteBuffer.wrap(bytes, offset, numBytes);
+ CharBuffer charBuf = btc.decode(byteBuf);
+
+ // CharBuffer returned by the decoder will set its limit
+ // to byte immediately after the last written byte.
+ resultingNumChars = charBuf.limit();
+
+ // IMPORTANT - It's possible the underlying char[] in the
+ // CharBuffer returned by btc.decode(byteBuf)
+ // is longer in length than the number of characters
+ // decoded. Hence, the check below to ensure the
+ // char[] returned contains all the chars that have
+ // been decoded and no more.
+ if (charBuf.limit() == charBuf.capacity()) {
+ buffer = charBuf.array();
+ } else {
+ buffer = new char[charBuf.limit()];
+ charBuf.get(buffer, 0, charBuf.limit()).position(0);
+ }
+
+ return buffer;
+
+ } catch (IllegalStateException ile) {
+ // There were a decoding operation already in progress
+ throw wrapper.btcConverterFailure( ile ) ;
+ } catch (MalformedInputException mie) {
+ // There were illegal Unicode char pairs
+ throw wrapper.badUnicodePair( mie ) ;
+ } catch (UnmappableCharacterException uce) {
+ // A character doesn't map to the desired code set.
+ // CORBA formal 00-11-03.
+ throw omgWrapper.charNotInCodeset( uce ) ;
+ } catch (CharacterCodingException cce) {
+ // If this happens, then a character decoding error occured.
+ throw wrapper.btcConverterFailure( cce ) ;
+ }
+ }
+
+ /**
+ * Utility method to find a CharsetDecoder in the
+ * cache or create a new one if necessary. Throws an
+ * INTERNAL if the code set is unknown.
+ */
+ protected CharsetDecoder getConverter(String javaCodeSetName) {
+
+ CharsetDecoder result = null;
+ try {
+ result = cache.getByteToCharConverter(javaCodeSetName);
+
+ if (result == null) {
+ Charset tmpCharset = Charset.forName(javaCodeSetName);
+ result = tmpCharset.newDecoder();
+ result.onMalformedInput(java.nio.charset.CodingErrorAction.REPLACE);
+ result.onUnmappableCharacter(java.nio.charset.CodingErrorAction.REPLACE);
+ cache.setConverter(javaCodeSetName, result);
+ }
+
+ } catch(IllegalCharsetNameException icne) {
+ // This can only happen if one of our charset entries has
+ // an illegal name.
+ throw wrapper.invalidBtcConverterName( icne, javaCodeSetName ) ;
+ }
+
+ return result;
+ }
+ }
+
+ /**
+ * Special converter for UTF16 since it's required to optionally
+ * support a byte order marker while the internal Java converters
+ * either require it or require that it isn't there.
+ *
+ * The solution is to check for the byte order marker, and if we
+ * need to do something differently, switch internal converters.
+ */
+ private class UTF16BTCConverter extends JavaBTCConverter
+ {
+ private boolean defaultToLittleEndian;
+ private boolean converterUsesBOM = true;
+
+ private static final char UTF16_BE_MARKER = (char) 0xfeff;
+ private static final char UTF16_LE_MARKER = (char) 0xfffe;
+
+ // When there isn't a byte order marker, used the byte
+ // order specified.
+ public UTF16BTCConverter(boolean defaultToLittleEndian) {
+ super(OSFCodeSetRegistry.UTF_16);
+
+ this.defaultToLittleEndian = defaultToLittleEndian;
+ }
+
+ public char[] getChars(byte[] bytes, int offset, int numBytes) {
+
+ if (hasUTF16ByteOrderMarker(bytes, offset, numBytes)) {
+ if (!converterUsesBOM)
+ switchToConverter(OSFCodeSetRegistry.UTF_16);
+
+ converterUsesBOM = true;
+
+ return super.getChars(bytes, offset, numBytes);
+ } else {
+ if (converterUsesBOM) {
+ if (defaultToLittleEndian)
+ switchToConverter(OSFCodeSetRegistry.UTF_16LE);
+ else
+ switchToConverter(OSFCodeSetRegistry.UTF_16BE);
+
+ converterUsesBOM = false;
+ }
+
+ return super.getChars(bytes, offset, numBytes);
+ }
+ }
+
+ /**
+ * Utility method for determining if a UTF-16 byte order marker is present.
+ */
+ private boolean hasUTF16ByteOrderMarker(byte[] array, int offset, int length) {
+ // If there aren't enough bytes to represent the marker and data,
+ // return false.
+ if (length >= 4) {
+
+ int b1 = array[offset] & 0x00FF;
+ int b2 = array[offset + 1] & 0x00FF;
+
+ char marker = (char)((b1 << 8) | (b2 << 0));
+
+ return (marker == UTF16_BE_MARKER || marker == UTF16_LE_MARKER);
+ } else
+ return false;
+ }
+
+ /**
+ * The current solution for dealing with UTF-16 in CORBA
+ * is that if our sun.io converter requires byte order markers,
+ * and then we see a CORBA wstring/wchar without them, we
+ * switch to the sun.io converter that doesn't require them.
+ */
+ private void switchToConverter(OSFCodeSetRegistry.Entry newCodeSet) {
+
+ // Use the getConverter method from our superclass.
+ btc = super.getConverter(newCodeSet.getName());
+ }
+ }
+
+ /**
+ * CTB converter factory for single byte or variable length encodings.
+ */
+ public CTBConverter getCTBConverter(OSFCodeSetRegistry.Entry codeset) {
+ int alignment = (!codeset.isFixedWidth() ?
+ 1 :
+ codeset.getMaxBytesPerChar());
+
+ return new JavaCTBConverter(codeset, alignment);
+ }
+
+ /**
+ * CTB converter factory for multibyte (mainly fixed) encodings.
+ *
+ * Because of the awkwardness with byte order markers and the possibility of
+ * using UCS-2, you must specify both the endianness of the stream as well as
+ * whether or not to use byte order markers if applicable. UCS-2 has no byte
+ * order markers. UTF-16 has optional markers.
+ *
+ * If you select useByteOrderMarkers, there is no guarantee that the encoding
+ * will use the endianness specified.
+ *
+ */
+ public CTBConverter getCTBConverter(OSFCodeSetRegistry.Entry codeset,
+ boolean littleEndian,
+ boolean useByteOrderMarkers) {
+
+ // UCS2 doesn't have byte order markers, and we're encoding it
+ // as UTF-16 since UCS2 isn't available in all Java platforms.
+ // They should be identical with only minor differences in
+ // negative cases.
+ if (codeset == OSFCodeSetRegistry.UCS_2)
+ return new UTF16CTBConverter(littleEndian);
+
+ // We can write UTF-16 with or without a byte order marker.
+ if (codeset == OSFCodeSetRegistry.UTF_16) {
+ if (useByteOrderMarkers)
+ return new UTF16CTBConverter();
+ else
+ return new UTF16CTBConverter(littleEndian);
+ }
+
+ // Everything else uses the generic JavaCTBConverter.
+ //
+ // Variable width encodings are aligned on 1 byte boundaries.
+ // A fixed width encoding with a max. of 4 bytes/char should
+ // align on a 4 byte boundary. Note that UTF-16 is a special
+ // case because of the optional byte order marker, so it's
+ // handled above.
+ //
+ // This doesn't matter for GIOP 1.2 wchars and wstrings
+ // since the encoded bytes are treated as an encapsulation.
+ int alignment = (!codeset.isFixedWidth() ?
+ 1 :
+ codeset.getMaxBytesPerChar());
+
+ return new JavaCTBConverter(codeset, alignment);
+ }
+
+ /**
+ * BTCConverter factory for single byte or variable width encodings.
+ */
+ public BTCConverter getBTCConverter(OSFCodeSetRegistry.Entry codeset) {
+ return new JavaBTCConverter(codeset);
+ }
+
+ /**
+ * BTCConverter factory for fixed width multibyte encodings.
+ */
+ public BTCConverter getBTCConverter(OSFCodeSetRegistry.Entry codeset,
+ boolean defaultToLittleEndian) {
+
+ if (codeset == OSFCodeSetRegistry.UTF_16 ||
+ codeset == OSFCodeSetRegistry.UCS_2) {
+
+ return new UTF16BTCConverter(defaultToLittleEndian);
+ } else {
+ return new JavaBTCConverter(codeset);
+ }
+ }
+
+ /**
+ * Follows the code set negotiation algorithm in CORBA formal 99-10-07 13.7.2.
+ *
+ * Returns the proper negotiated OSF character encoding number or
+ * CodeSetConversion.FALLBACK_CODESET.
+ */
+ private int selectEncoding(CodeSetComponentInfo.CodeSetComponent client,
+ CodeSetComponentInfo.CodeSetComponent server) {
+
+ // A "null" value for the server's nativeCodeSet means that
+ // the server desired not to indicate one. We'll take that
+ // to mean that it wants the first thing in its conversion list.
+ // If it's conversion list is empty, too, then use the fallback
+ // codeset.
+ int serverNative = server.nativeCodeSet;
+
+ if (serverNative == 0) {
+ if (server.conversionCodeSets.length > 0)
+ serverNative = server.conversionCodeSets[0];
+ else
+ return CodeSetConversion.FALLBACK_CODESET;
+ }
+
+ if (client.nativeCodeSet == serverNative) {
+ // Best case -- client and server don't have to convert
+ return serverNative;
+ }
+
+ // Is this client capable of converting to the server's
+ // native code set?
+ for (int i = 0; i < client.conversionCodeSets.length; i++) {
+ if (serverNative == client.conversionCodeSets[i]) {
+ // The client will convert to the server's
+ // native code set.
+ return serverNative;
+ }
+ }
+
+ // Is the server capable of converting to the client's
+ // native code set?
+ for (int i = 0; i < server.conversionCodeSets.length; i++) {
+ if (client.nativeCodeSet == server.conversionCodeSets[i]) {
+ // The server will convert to the client's
+ // native code set.
+ return client.nativeCodeSet;
+ }
+ }
+
+ // See if there are any code sets that both the server and client
+ // support (giving preference to the server). The order
+ // of conversion sets is from most to least desired.
+ for (int i = 0; i < server.conversionCodeSets.length; i++) {
+ for (int y = 0; y < client.conversionCodeSets.length; y++) {
+ if (server.conversionCodeSets[i] == client.conversionCodeSets[y]) {
+ return server.conversionCodeSets[i];
+ }
+ }
+ }
+
+ // Before using the fallback codesets, the spec calls for a
+ // compatibility check on the native code sets. It doesn't make
+ // sense because loss free communication is always possible with
+ // UTF8 and UTF16, the fall back code sets. It's also a lot
+ // of work to implement. In the case of incompatibility, the
+ // spec says to throw a CODESET_INCOMPATIBLE exception.
+
+ // Use the fallback
+ return CodeSetConversion.FALLBACK_CODESET;
+ }
+
+ /**
+ * Perform the code set negotiation algorithm and come up with
+ * the two encodings to use.
+ */
+ public CodeSetComponentInfo.CodeSetContext negotiate(CodeSetComponentInfo client,
+ CodeSetComponentInfo server) {
+ int charData
+ = selectEncoding(client.getCharComponent(),
+ server.getCharComponent());
+
+ if (charData == CodeSetConversion.FALLBACK_CODESET) {
+ charData = OSFCodeSetRegistry.UTF_8.getNumber();
+ }
+
+ int wcharData
+ = selectEncoding(client.getWCharComponent(),
+ server.getWCharComponent());
+
+ if (wcharData == CodeSetConversion.FALLBACK_CODESET) {
+ wcharData = OSFCodeSetRegistry.UTF_16.getNumber();
+ }
+
+ return new CodeSetComponentInfo.CodeSetContext(charData,
+ wcharData);
+ }
+
+ // No one should instantiate a CodeSetConversion but the singleton
+ // instance method
+ private CodeSetConversion() {}
+
+ // initialize-on-demand holder
+ private static class CodeSetConversionHolder {
+ static final CodeSetConversion csc = new CodeSetConversion() ;
+ }
+
+ /**
+ * CodeSetConversion is a singleton, and this is the access point.
+ */
+ public final static CodeSetConversion impl() {
+ return CodeSetConversionHolder.csc ;
+ }
+
+ // Singleton instance
+ private static CodeSetConversion implementation;
+
+ // Number used internally to indicate the fallback code
+ // set.
+ private static final int FALLBACK_CODESET = 0;
+
+ // Provides a thread local cache for the sun.io
+ // converters.
+ private CodeSetCache cache = new CodeSetCache();
+}
More information about the sword-cvs
mailing list