1 /* 2 * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.nio.cs; 27 28 import java.nio.charset.Charset; 29 import java.nio.charset.spi.CharsetProvider; 30 import java.util.Iterator; 31 import java.util.Map; 32 33 34 /** 35 * Abstract base class for fast charset providers. 36 * 37 * @author Mark Reinhold 38 */ 39 40 public class FastCharsetProvider 41 extends CharsetProvider 42 { 43 44 // Maps canonical names to class names 45 private Map<String,String> classMap; 46 47 // Maps alias names to canonical names 48 private Map<String,String> aliasMap; 49 50 // Maps canonical names to cached instances 51 private Map<String,Charset> cache; 52 53 private String packagePrefix; 54 55 protected FastCharsetProvider(String pp, 56 Map<String,String> am, 57 Map<String,String> cm, 58 Map<String,Charset> c) 59 { 60 packagePrefix = pp; 61 aliasMap = am; 62 classMap = cm; 63 cache = c; 64 } 65 66 private String canonicalize(String csn) { 67 String acn = aliasMap.get(csn); 68 return (acn != null) ? acn : csn; 69 } 70 71 // Private ASCII-only version, optimized for interpretation during startup 72 // 73 private static String toLower(String s) { 74 int n = s.length(); 75 boolean allLower = true; 76 for (int i = 0; i < n; i++) { 77 int c = s.charAt(i); 78 if (((c - 'A') | ('Z' - c)) >= 0) { 79 allLower = false; 80 break; 81 } 82 } 83 if (allLower) 84 return s; 85 char[] ca = new char[n]; 86 for (int i = 0; i < n; i++) { 87 int c = s.charAt(i); 88 if (((c - 'A') | ('Z' - c)) >= 0) 89 ca[i] = (char)(c + 0x20); 90 else 91 ca[i] = (char)c; 92 } 93 return new String(ca); 94 } 95 96 private Charset lookup(String charsetName) { 97 98 String csn = canonicalize(toLower(charsetName)); 99 100 // Check cache first 101 Charset cs = cache.get(csn); 102 if (cs != null) 103 return cs; 104 105 // Do we even support this charset? 106 String cln = classMap.get(csn); 107 if (cln == null) 108 return null; 109 110 if (cln.equals("US_ASCII")) { 111 cs = new US_ASCII(); 112 cache.put(csn, cs); 113 return cs; 114 } 115 116 // Instantiate the charset and cache it 117 try { 118 Class<?> c = Class.forName(packagePrefix + "." + cln, 119 true, 120 this.getClass().getClassLoader()); 121 cs = (Charset)c.newInstance(); 122 cache.put(csn, cs); 123 return cs; 124 } catch (ClassNotFoundException | 125 IllegalAccessException | 126 InstantiationException x) { 127 return null; 128 } 129 } 130 131 public final Charset charsetForName(String charsetName) { 132 synchronized (this) { 133 return lookup(canonicalize(charsetName)); 134 } 135 } 136 137 public final Iterator<Charset> charsets() { 138 139 return new Iterator<Charset>() { 140 141 Iterator<String> i = classMap.keySet().iterator(); 142 143 public boolean hasNext() { 144 return i.hasNext(); 145 } 146 147 public Charset next() { 148 String csn = i.next(); 149 return lookup(csn); 150 } 151 152 public void remove() { 153 throw new UnsupportedOperationException(); 154 } 155 156 }; 157 158 } 159 160 }