[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