codesetconversion.java

来自「JAVA 所有包」· Java 代码 · 共 690 行 · 第 1/2 页

JAVA
690
字号
/* * @(#)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();                    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);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?