1 7 8 package java.nio.charset; 9 10 import java.nio.ByteBuffer ; 11 import java.nio.CharBuffer ; 12 import java.nio.charset.spi.CharsetProvider ; 13 import java.security.AccessController ; 14 import java.security.AccessControlException ; 15 import java.security.PrivilegedAction ; 16 import java.util.Collections ; 17 import java.util.HashSet ; 18 import java.util.Iterator ; 19 import java.util.Locale ; 20 import java.util.Map ; 21 import java.util.NoSuchElementException ; 22 import java.util.Set ; 23 import java.util.SortedMap ; 24 import java.util.TreeMap ; 25 import sun.misc.ASCIICaseInsensitiveComparator; 26 import sun.misc.Service; 27 import sun.misc.ServiceConfigurationError; 28 import sun.nio.cs.StandardCharsets; 29 import sun.nio.cs.ThreadLocalCoders; 30 import sun.security.action.GetPropertyAction; 31 32 33 239 240 public abstract class Charset 241 implements Comparable <Charset > 242 { 243 244 245 246 private static String bugLevel = null; 247 248 static boolean atBugLevel(String bl) { if (bugLevel == null) { 250 if (!sun.misc.VM.isBooted()) 251 return false; 252 java.security.PrivilegedAction pa = 253 new GetPropertyAction("sun.nio.cs.bugLevel"); 254 bugLevel = (String )AccessController.doPrivileged(pa); 255 if (bugLevel == null) 256 bugLevel = ""; 257 } 258 return (bugLevel != null) && bugLevel.equals(bl); 259 } 260 261 270 private static void checkName(String s) { 271 int n = s.length(); 272 if (!atBugLevel("1.4")) { 273 if (n == 0) 274 throw new IllegalCharsetNameException (s); 275 } 276 for (int i = 0; i < n; i++) { 277 char c = s.charAt(i); 278 if (c >= 'A' && c <= 'Z') continue; 279 if (c >= 'a' && c <= 'z') continue; 280 if (c >= '0' && c <= '9') continue; 281 if (c == '-') continue; 282 if (c == ':') continue; 283 if (c == '_') continue; 284 if (c == '.') continue; 285 throw new IllegalCharsetNameException (s); 286 } 287 } 288 289 290 private static CharsetProvider standardProvider = new StandardCharsets(); 291 292 private static volatile Object [] cache1 = null; private static volatile Object [] cache2 = null; 298 private static void cache(String charsetName, Charset cs) { 299 cache2 = cache1; 300 cache1 = new Object [] { charsetName, cs }; 301 } 302 303 private static Iterator providers() { 308 return new Iterator () { 309 310 Class c = java.nio.charset.spi.CharsetProvider .class; 311 ClassLoader cl = ClassLoader.getSystemClassLoader(); 312 Iterator i = Service.providers(c, cl); 313 Object next = null; 314 315 private boolean getNext() { 316 while (next == null) { 317 try { 318 if (!i.hasNext()) 319 return false; 320 next = i.next(); 321 } catch (ServiceConfigurationError sce) { 322 if (sce.getCause() instanceof SecurityException ) { 323 continue; 325 } 326 throw sce; 327 } 328 } 329 return true; 330 } 331 332 public boolean hasNext() { 333 return getNext(); 334 } 335 336 public Object next() { 337 if (!getNext()) 338 throw new NoSuchElementException (); 339 Object n = next; 340 next = null; 341 return n; 342 } 343 344 public void remove() { 345 throw new UnsupportedOperationException (); 346 } 347 348 }; 349 } 350 351 private static ThreadLocal gate = new ThreadLocal (); 353 354 private static Charset lookupViaProviders(final String charsetName) { 355 356 if (!sun.misc.VM.isBooted()) 365 return null; 366 367 if (gate.get() != null) 368 return null; 370 try { 371 gate.set(gate); 372 373 return (Charset )AccessController 374 .doPrivileged(new PrivilegedAction () { 375 public Object run() { 376 for (Iterator i = providers(); i.hasNext();) { 377 CharsetProvider cp = (CharsetProvider )i.next(); 378 Charset cs = cp.charsetForName(charsetName); 379 if (cs != null) 380 return cs; 381 } 382 return null; 383 } 384 }); 385 386 } finally { 387 gate.set(null); 388 } 389 } 390 391 392 private static Object extendedProviderLock = new Object (); 393 private static boolean extendedProviderProbed = false; 394 private static CharsetProvider extendedProvider = null; 395 396 private static void probeExtendedProvider() { 397 AccessController.doPrivileged(new PrivilegedAction () { 398 public Object run() { 399 try { 400 Class epc 401 = Class.forName("sun.nio.cs.ext.ExtendedCharsets"); 402 extendedProvider = (CharsetProvider )epc.newInstance(); 403 } catch (ClassNotFoundException x) { 404 } catch (InstantiationException x) { 407 throw new Error (x); 408 } catch (IllegalAccessException x) { 409 throw new Error (x); 410 } 411 return null; 412 } 413 }); 414 } 415 416 private static Charset lookupExtendedCharset(String charsetName) { 417 CharsetProvider ecp = null; 418 synchronized (extendedProviderLock) { 419 if (!extendedProviderProbed) { 420 probeExtendedProvider(); 421 extendedProviderProbed = true; 422 } 423 ecp = extendedProvider; 424 } 425 return (ecp != null) ? ecp.charsetForName(charsetName) : null; 426 } 427 428 private static Charset lookup(String charsetName) { 429 if (charsetName == null) 430 throw new IllegalArgumentException ("Null charset name"); 431 432 Object [] a; 433 if ((a = cache1) != null && charsetName.equals(a[0])) 434 return (Charset )a[1]; 435 return lookup2(charsetName); 439 } 440 441 private static Charset lookup2(String charsetName) { 442 Object [] a; 443 if ((a = cache2) != null && charsetName.equals(a[0])) { 444 cache2 = cache1; 445 cache1 = a; 446 return (Charset )a[1]; 447 } 448 449 Charset cs; 450 if ((cs = standardProvider.charsetForName(charsetName)) != null || 451 (cs = lookupExtendedCharset(charsetName)) != null || 452 (cs = lookupViaProviders(charsetName)) != null) 453 { 454 cache(charsetName, cs); 455 return cs; 456 } 457 458 459 checkName(charsetName); 460 return null; 461 } 462 463 476 public static boolean isSupported(String charsetName) { 477 return (lookup(charsetName) != null); 478 } 479 480 496 public static Charset forName(String charsetName) { 497 Charset cs = lookup(charsetName); 498 if (cs != null) 499 return cs; 500 throw new UnsupportedCharsetException (charsetName); 501 } 502 503 private static void put(Iterator i, Map m) { 507 while (i.hasNext()) { 508 Charset cs = (Charset )i.next(); 509 if (!m.containsKey(cs.name())) 510 m.put(cs.name(), cs); 511 } 512 } 513 514 540 public static SortedMap <String ,Charset > availableCharsets() { 541 return (SortedMap )AccessController 542 .doPrivileged(new PrivilegedAction () { 543 public Object run() { 544 TreeMap m = new TreeMap (ASCIICaseInsensitiveComparator.CASE_INSENSITIVE_ORDER); 545 put(standardProvider.charsets(), m); 546 for (Iterator i = providers(); i.hasNext();) { 547 CharsetProvider cp = (CharsetProvider )i.next(); 548 put(cp.charsets(), m); 549 } 550 return Collections.unmodifiableSortedMap(m); 551 } 552 }); 553 } 554 555 private static Charset defaultCharset; 556 557 568 public static Charset defaultCharset() { 569 synchronized (Charset .class) { 570 if (defaultCharset == null) { 571 java.security.PrivilegedAction pa = 572 new GetPropertyAction("file.encoding"); 573 String csn = (String )AccessController.doPrivileged(pa); 574 Charset cs = lookup(csn); 575 if (cs != null) 576 return cs; 577 return forName("UTF-8"); 578 } 579 return defaultCharset; 580 } 581 } 582 583 584 585 586 private final String name; private final String [] aliases; private Set aliasSet = null; 589 590 603 protected Charset(String canonicalName, String [] aliases) { 604 checkName(canonicalName); 605 String [] as = (aliases == null) ? new String [0] : aliases; 606 for (int i = 0; i < as.length; i++) 607 checkName(as[i]); 608 this.name = canonicalName; 609 this.aliases = as; 610 } 611 612 617 public final String name() { 618 return name; 619 } 620 621 626 public final Set <String > aliases() { 627 if (aliasSet != null) 628 return aliasSet; 629 int n = aliases.length; 630 HashSet hs = new HashSet (n); 631 for (int i = 0; i < n; i++) 632 hs.add(aliases[i]); 633 aliasSet = Collections.unmodifiableSet(hs); 634 return aliasSet; 635 } 636 637 646 public String displayName() { 647 return name; 648 } 649 650 658 public final boolean isRegistered() { 659 return !name.startsWith("X-") && !name.startsWith("x-"); 660 } 661 662 674 public String displayName(Locale locale) { 675 return name; 676 } 677 678 703 public abstract boolean contains(Charset cs); 704 705 710 public abstract CharsetDecoder newDecoder(); 711 712 720 public abstract CharsetEncoder newEncoder(); 721 722 735 public boolean canEncode() { 736 return true; 737 } 738 739 764 public final CharBuffer decode(ByteBuffer bb) { 765 try { 766 return ThreadLocalCoders.decoderFor(this) 767 .onMalformedInput(CodingErrorAction.REPLACE) 768 .onUnmappableCharacter(CodingErrorAction.REPLACE) 769 .decode(bb); 770 } catch (CharacterCodingException x) { 771 throw new Error (x); } 773 } 774 775 800 public final ByteBuffer encode(CharBuffer cb) { 801 try { 802 return ThreadLocalCoders.encoderFor(this) 803 .onMalformedInput(CodingErrorAction.REPLACE) 804 .onUnmappableCharacter(CodingErrorAction.REPLACE) 805 .encode(cb); 806 } catch (CharacterCodingException x) { 807 throw new Error (x); } 809 } 810 811 824 public final ByteBuffer encode(String str) { 825 return encode(CharBuffer.wrap(str)); 826 } 827 828 840 public final int compareTo(Charset that) { 841 return (name().compareToIgnoreCase(that.name())); 842 } 843 844 849 public final int hashCode() { 850 return name().hashCode(); 851 } 852 853 862 public final boolean equals(Object ob) { 863 if (!(ob instanceof Charset )) 864 return false; 865 if (this == ob) 866 return true; 867 return name.equals(((Charset )ob).name()); 868 } 869 870 875 public final String toString() { 876 return name(); 877 } 878 879 } 880 | Popular Tags |