1 7 package com.sun.corba.se.impl.encoding; 8 9 import java.util.Map ; 10 import java.util.HashMap ; 11 import java.nio.ByteBuffer ; 12 import java.nio.CharBuffer ; 13 import java.nio.charset.Charset ; 14 import java.nio.charset.CharsetEncoder ; 15 import java.nio.charset.CharsetDecoder ; 16 import java.nio.charset.CharacterCodingException ; 17 import java.nio.charset.IllegalCharsetNameException ; 18 import java.nio.charset.MalformedInputException ; 19 import java.nio.charset.UnsupportedCharsetException ; 20 import java.nio.charset.UnmappableCharacterException ; 21 import com.sun.corba.se.impl.logging.ORBUtilSystemException; 22 import com.sun.corba.se.impl.logging.OMGSystemException; 23 import com.sun.corba.se.spi.logging.CORBALogDomains; 24 25 44 public class CodeSetConversion 45 { 46 55 public abstract static class CTBConverter 56 { 57 public abstract void convert(char chToConvert); 61 public abstract void convert(String strToConvert); 62 63 public abstract int getNumBytes(); 65 66 public abstract float getMaxBytesPerChar(); 68 69 public abstract boolean isFixedWidthEncoding(); 70 71 public abstract int getAlignment(); 80 81 public abstract byte[] getBytes(); 86 } 87 88 91 public abstract static class BTCConverter 92 { 93 public abstract boolean isFixedWidthEncoding(); 98 public abstract int getFixedCharWidth(); 99 100 public abstract int getNumChars(); 103 104 public abstract char[] getChars(byte[] bytes, int offset, int length); 110 } 111 112 117 private class JavaCTBConverter extends CTBConverter 118 { 119 private ORBUtilSystemException wrapper = ORBUtilSystemException.get( 120 CORBALogDomains.RPC_ENCODING ) ; 121 122 private OMGSystemException omgWrapper = OMGSystemException.get( 123 CORBALogDomains.RPC_ENCODING ) ; 124 125 private CharsetEncoder ctb; 129 130 private int alignment; 134 135 private char[] chars = null; 137 138 private int numBytes = 0; 140 141 private int numChars = 0; 144 145 private ByteBuffer buffer; 149 150 private OSFCodeSetRegistry.Entry codeset; 152 153 public JavaCTBConverter(OSFCodeSetRegistry.Entry codeset, 154 int alignmentForEncoding) { 155 156 try { 157 ctb = cache.getCharToByteConverter(codeset.getName()); 158 if (ctb == null) { 159 Charset tmpCharset = Charset.forName(codeset.getName()); 160 ctb = tmpCharset.newEncoder(); 161 cache.setConverter(codeset.getName(), ctb); 162 } 163 } catch(IllegalCharsetNameException icne) { 164 165 throw wrapper.invalidCtbConverterName(icne,codeset.getName()); 168 } catch(UnsupportedCharsetException ucne) { 169 170 throw wrapper.invalidCtbConverterName(ucne,codeset.getName()); 173 } 174 175 this.codeset = codeset; 176 alignment = alignmentForEncoding; 177 } 178 179 public final float getMaxBytesPerChar() { 180 return ctb.maxBytesPerChar(); 181 } 182 183 public void convert(char chToConvert) { 184 if (chars == null) 185 chars = new char[1]; 186 187 chars[0] = chToConvert; 189 numChars = 1; 190 191 convertCharArray(); 192 } 193 194 public void convert(String strToConvert) { 195 if (chars == null || chars.length < strToConvert.length()) 200 chars = new char[strToConvert.length()]; 201 202 numChars = strToConvert.length(); 203 204 strToConvert.getChars(0, numChars, chars, 0); 205 206 convertCharArray(); 207 } 208 209 public final int getNumBytes() { 210 return numBytes; 211 } 212 213 public final int getAlignment() { 214 return alignment; 215 } 216 217 public final boolean isFixedWidthEncoding() { 218 return codeset.isFixedWidth(); 219 } 220 221 public byte[] getBytes() { 222 return buffer.array(); 226 } 227 228 private void convertCharArray() { 229 try { 230 231 243 buffer = ctb.encode(CharBuffer.wrap(chars,0,numChars)); 245 246 numBytes = buffer.limit(); 249 250 } catch (IllegalStateException ise) { 251 throw wrapper.ctbConverterFailure( ise ) ; 253 } catch (MalformedInputException mie) { 254 throw wrapper.badUnicodePair( mie ) ; 256 } catch (UnmappableCharacterException uce) { 257 throw omgWrapper.charNotInCodeset( uce ) ; 260 } catch (CharacterCodingException cce) { 261 throw wrapper.ctbConverterFailure( cce ) ; 263 } 264 } 265 } 266 267 271 private class UTF16CTBConverter extends JavaCTBConverter 272 { 273 public UTF16CTBConverter() { 275 super(OSFCodeSetRegistry.UTF_16, 2); 276 } 277 278 public UTF16CTBConverter(boolean littleEndian) { 281 super(littleEndian ? 282 OSFCodeSetRegistry.UTF_16LE : 283 OSFCodeSetRegistry.UTF_16BE, 284 2); 285 } 286 } 287 288 293 private class JavaBTCConverter extends BTCConverter 294 { 295 private ORBUtilSystemException wrapper = ORBUtilSystemException.get( 296 CORBALogDomains.RPC_ENCODING ) ; 297 298 private OMGSystemException omgWrapper = OMGSystemException.get( 299 CORBALogDomains.RPC_ENCODING ) ; 300 301 protected CharsetDecoder btc; 302 private char[] buffer; 303 private int resultingNumChars; 304 private OSFCodeSetRegistry.Entry codeset; 305 306 public JavaBTCConverter(OSFCodeSetRegistry.Entry codeset) { 307 308 btc = this.getConverter(codeset.getName()); 310 311 this.codeset = codeset; 312 } 313 314 public final boolean isFixedWidthEncoding() { 315 return codeset.isFixedWidth(); 316 } 317 318 public final int getFixedCharWidth() { 322 return codeset.getMaxBytesPerChar(); 323 } 324 325 public final int getNumChars() { 326 return resultingNumChars; 327 } 328 329 public char[] getChars(byte[] bytes, int offset, int numBytes) { 330 331 340 341 try { 342 343 ByteBuffer byteBuf = ByteBuffer.wrap(bytes, offset, numBytes); 344 CharBuffer charBuf = btc.decode(byteBuf); 345 346 resultingNumChars = charBuf.limit(); 349 350 if (charBuf.limit() == charBuf.capacity()) { 357 buffer = charBuf.array(); 358 } else { 359 buffer = new char[charBuf.limit()]; 360 charBuf.get(buffer, 0, charBuf.limit()).position(0); 361 } 362 363 return buffer; 364 365 } catch (IllegalStateException ile) { 366 throw wrapper.btcConverterFailure( ile ) ; 368 } catch (MalformedInputException mie) { 369 throw wrapper.badUnicodePair( mie ) ; 371 } catch (UnmappableCharacterException uce) { 372 throw omgWrapper.charNotInCodeset( uce ) ; 375 } catch (CharacterCodingException cce) { 376 throw wrapper.btcConverterFailure( cce ) ; 378 } 379 } 380 381 386 protected CharsetDecoder getConverter(String javaCodeSetName) { 387 388 CharsetDecoder result = null; 389 try { 390 result = cache.getByteToCharConverter(javaCodeSetName); 391 392 if (result == null) { 393 Charset tmpCharset = Charset.forName(javaCodeSetName); 394 result = tmpCharset.newDecoder(); 395 cache.setConverter(javaCodeSetName, result); 396 } 397 398 } catch(IllegalCharsetNameException icne) { 399 throw wrapper.invalidBtcConverterName( icne, javaCodeSetName ) ; 402 } 403 404 return result; 405 } 406 } 407 408 416 private class UTF16BTCConverter extends JavaBTCConverter 417 { 418 private boolean defaultToLittleEndian; 419 private boolean converterUsesBOM = true; 420 421 private static final char UTF16_BE_MARKER = (char) 0xfeff; 422 private static final char UTF16_LE_MARKER = (char) 0xfffe; 423 424 public UTF16BTCConverter(boolean defaultToLittleEndian) { 427 super(OSFCodeSetRegistry.UTF_16); 428 429 this.defaultToLittleEndian = defaultToLittleEndian; 430 } 431 432 public char[] getChars(byte[] bytes, int offset, int numBytes) { 433 434 if (hasUTF16ByteOrderMarker(bytes, offset, numBytes)) { 435 if (!converterUsesBOM) 436 switchToConverter(OSFCodeSetRegistry.UTF_16); 437 438 converterUsesBOM = true; 439 440 return super.getChars(bytes, offset, numBytes); 441 } else { 442 if (converterUsesBOM) { 443 if (defaultToLittleEndian) 444 switchToConverter(OSFCodeSetRegistry.UTF_16LE); 445 else 446 switchToConverter(OSFCodeSetRegistry.UTF_16BE); 447 448 converterUsesBOM = false; 449 } 450 451 return super.getChars(bytes, offset, numBytes); 452 } 453 } 454 455 458 private boolean hasUTF16ByteOrderMarker(byte[] array, int offset, int length) { 459 if (length >= 4) { 462 463 int b1 = array[offset] & 0x00FF; 464 int b2 = array[offset + 1] & 0x00FF; 465 466 char marker = (char)((b1 << 8) | (b2 << 0)); 467 468 return (marker == UTF16_BE_MARKER || marker == UTF16_LE_MARKER); 469 } else 470 return false; 471 } 472 473 479 private void switchToConverter(OSFCodeSetRegistry.Entry newCodeSet) { 480 481 btc = super.getConverter(newCodeSet.getName()); 483 } 484 } 485 486 489 public CTBConverter getCTBConverter(OSFCodeSetRegistry.Entry codeset) { 490 int alignment = (!codeset.isFixedWidth() ? 491 1 : 492 codeset.getMaxBytesPerChar()); 493 494 return new JavaCTBConverter(codeset, alignment); 495 } 496 497 509 public CTBConverter getCTBConverter(OSFCodeSetRegistry.Entry codeset, 510 boolean littleEndian, 511 boolean useByteOrderMarkers) { 512 513 if (codeset == OSFCodeSetRegistry.UCS_2) 518 return new UTF16CTBConverter(littleEndian); 519 520 if (codeset == OSFCodeSetRegistry.UTF_16) { 522 if (useByteOrderMarkers) 523 return new UTF16CTBConverter(); 524 else 525 return new UTF16CTBConverter(littleEndian); 526 } 527 528 int alignment = (!codeset.isFixedWidth() ? 539 1 : 540 codeset.getMaxBytesPerChar()); 541 542 return new JavaCTBConverter(codeset, alignment); 543 } 544 545 548 public BTCConverter getBTCConverter(OSFCodeSetRegistry.Entry codeset) { 549 return new JavaBTCConverter(codeset); 550 } 551 552 555 public BTCConverter getBTCConverter(OSFCodeSetRegistry.Entry codeset, 556 boolean defaultToLittleEndian) { 557 558 if (codeset == OSFCodeSetRegistry.UTF_16 || 559 codeset == OSFCodeSetRegistry.UCS_2) { 560 561 return new UTF16BTCConverter(defaultToLittleEndian); 562 } else { 563 return new JavaBTCConverter(codeset); 564 } 565 } 566 567 573 private int selectEncoding(CodeSetComponentInfo.CodeSetComponent client, 574 CodeSetComponentInfo.CodeSetComponent server) { 575 576 int serverNative = server.nativeCodeSet; 582 583 if (serverNative == 0) { 584 if (server.conversionCodeSets.length > 0) 585 serverNative = server.conversionCodeSets[0]; 586 else 587 return CodeSetConversion.FALLBACK_CODESET; 588 } 589 590 if (client.nativeCodeSet == serverNative) { 591 return serverNative; 593 } 594 595 for (int i = 0; i < client.conversionCodeSets.length; i++) { 598 if (serverNative == client.conversionCodeSets[i]) { 599 return serverNative; 602 } 603 } 604 605 for (int i = 0; i < server.conversionCodeSets.length; i++) { 608 if (client.nativeCodeSet == server.conversionCodeSets[i]) { 609 return client.nativeCodeSet; 612 } 613 } 614 615 for (int i = 0; i < server.conversionCodeSets.length; i++) { 619 for (int y = 0; y < client.conversionCodeSets.length; y++) { 620 if (server.conversionCodeSets[i] == client.conversionCodeSets[y]) { 621 return server.conversionCodeSets[i]; 622 } 623 } 624 } 625 626 633 return CodeSetConversion.FALLBACK_CODESET; 635 } 636 637 641 public CodeSetComponentInfo.CodeSetContext negotiate(CodeSetComponentInfo client, 642 CodeSetComponentInfo server) { 643 int charData 644 = selectEncoding(client.getCharComponent(), 645 server.getCharComponent()); 646 647 if (charData == CodeSetConversion.FALLBACK_CODESET) { 648 charData = OSFCodeSetRegistry.UTF_8.getNumber(); 649 } 650 651 int wcharData 652 = selectEncoding(client.getWCharComponent(), 653 server.getWCharComponent()); 654 655 if (wcharData == CodeSetConversion.FALLBACK_CODESET) { 656 wcharData = OSFCodeSetRegistry.UTF_16.getNumber(); 657 } 658 659 return new CodeSetComponentInfo.CodeSetContext(charData, 660 wcharData); 661 } 662 663 private CodeSetConversion() {} 666 667 private static class CodeSetConversionHolder { 669 static final CodeSetConversion csc = new CodeSetConversion() ; 670 } 671 672 675 public final static CodeSetConversion impl() { 676 return CodeSetConversionHolder.csc ; 677 } 678 679 private static CodeSetConversion implementation; 681 682 private static final int FALLBACK_CODESET = 0; 685 686 private CodeSetCache cache = new CodeSetCache(); 689 } 690 | Popular Tags |