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             @SuppressWarnings("deprecation")
 119             Object o= Class.forName(packagePrefix + "." + cln,
 120                                     true,
 121                                     this.getClass().getClassLoader()).newInstance();
 122             cs = (Charset)o;
 123             cache.put(csn, cs);
 124             return cs;
 125         } catch (ClassNotFoundException |
 126                  IllegalAccessException |
 127                  InstantiationException x) {
 128             return null;
 129         }
 130     }
 131 
 132     public final Charset charsetForName(String charsetName) {
 133         synchronized (this) {
 134             return lookup(canonicalize(charsetName));
 135         }
 136     }
 137 
 138     public final Iterator<Charset> charsets() {
 139 
 140         return new Iterator<Charset>() {
 141 
 142                 Iterator<String> i = classMap.keySet().iterator();
 143 
 144                 public boolean hasNext() {
 145                     return i.hasNext();
 146                 }
 147 
 148                 public Charset next() {
 149                     String csn = i.next();
 150                     return lookup(csn);
 151                 }
 152 
 153                 public void remove() {
 154                     throw new UnsupportedOperationException();
 155                 }
 156 
 157             };
 158 
 159     }
 160 
 161 }