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 + -
显示快捷键?