001: /*
002: * Copyright 2000-2004 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.nio.cs;
027:
028: import java.lang.ref.SoftReference;
029: import java.nio.charset.Charset;
030: import java.nio.charset.spi.CharsetProvider;
031: import java.util.ArrayList;
032: import java.util.TreeMap;
033: import java.util.Iterator;
034: import java.util.Locale;
035: import java.util.Map;
036: import sun.misc.ASCIICaseInsensitiveComparator;
037:
038: /**
039: * Abstract base class for charset providers.
040: *
041: * @author Mark Reinhold
042: * @version 1.21, 07/05/05
043: */
044:
045: public class AbstractCharsetProvider extends CharsetProvider {
046:
047: /* Maps canonical names to class names
048: */
049: private Map classMap = new TreeMap(
050: ASCIICaseInsensitiveComparator.CASE_INSENSITIVE_ORDER);
051:
052: /* Maps alias names to canonical names
053: */
054: private Map aliasMap = new TreeMap(
055: ASCIICaseInsensitiveComparator.CASE_INSENSITIVE_ORDER);
056:
057: /* Maps canonical names to alias-name arrays
058: */
059: private Map aliasNameMap = new TreeMap(
060: ASCIICaseInsensitiveComparator.CASE_INSENSITIVE_ORDER);
061:
062: /* Maps canonical names to soft references that hold cached instances
063: */
064: private Map cache = new TreeMap(
065: ASCIICaseInsensitiveComparator.CASE_INSENSITIVE_ORDER);
066:
067: private String packagePrefix;
068:
069: protected AbstractCharsetProvider() {
070: packagePrefix = "sun.nio.cs";
071: }
072:
073: protected AbstractCharsetProvider(String pkgPrefixName) {
074: packagePrefix = pkgPrefixName;
075: }
076:
077: /* Add an entry to the given map, but only if no mapping yet exists
078: * for the given name.
079: */
080: private static void put(Map m, String name, Object value) {
081: if (!m.containsKey(name))
082: m.put(name, value);
083: }
084:
085: private static void remove(Map m, String name) {
086: Object x = m.remove(name);
087: assert (x != null);
088: }
089:
090: /* Declare support for the given charset
091: */
092: protected void charset(String name, String className,
093: String[] aliases) {
094: synchronized (this ) {
095: put(classMap, name, className);
096: for (int i = 0; i < aliases.length; i++)
097: put(aliasMap, aliases[i], name);
098: put(aliasNameMap, name, aliases);
099: cache.clear();
100: }
101: }
102:
103: protected void deleteCharset(String name, String[] aliases) {
104: synchronized (this ) {
105: remove(classMap, name);
106: for (int i = 0; i < aliases.length; i++)
107: remove(aliasMap, aliases[i]);
108: remove(aliasNameMap, name);
109: cache.clear();
110: }
111: }
112:
113: /* Late initialization hook, needed by some providers
114: */
115: protected void init() {
116: }
117:
118: private String canonicalize(String charsetName) {
119: String acn = (String) aliasMap.get(charsetName);
120: return (acn != null) ? acn : charsetName;
121: }
122:
123: private Charset lookup(String csn) {
124:
125: // Check cache first
126: SoftReference sr = (SoftReference) cache.get(csn);
127: if (sr != null) {
128: Charset cs = (Charset) sr.get();
129: if (cs != null)
130: return cs;
131: }
132:
133: // Do we even support this charset?
134: String cln = (String) classMap.get(csn);
135:
136: if (cln == null)
137: return null;
138:
139: // Instantiate the charset and cache it
140: try {
141:
142: Class c = Class.forName(packagePrefix + "." + cln, true,
143: this .getClass().getClassLoader());
144:
145: Charset cs = (Charset) c.newInstance();
146: cache.put(csn, new SoftReference(cs));
147: return cs;
148: } catch (ClassNotFoundException x) {
149: return null;
150: } catch (IllegalAccessException x) {
151: return null;
152: } catch (InstantiationException x) {
153: return null;
154: }
155: }
156:
157: public final Charset charsetForName(String charsetName) {
158: synchronized (this ) {
159: init();
160: return lookup(canonicalize(charsetName));
161: }
162: }
163:
164: public final Iterator<Charset> charsets() {
165:
166: final ArrayList ks;
167: synchronized (this ) {
168: init();
169: ks = new ArrayList(classMap.keySet());
170: }
171:
172: return new Iterator<Charset>() {
173: Iterator i = ks.iterator();
174:
175: public boolean hasNext() {
176: return i.hasNext();
177: }
178:
179: public Charset next() {
180: String csn = (String) i.next();
181: return lookup(csn);
182: }
183:
184: public void remove() {
185: throw new UnsupportedOperationException();
186: }
187: };
188: }
189:
190: public final String[] aliases(String charsetName) {
191: synchronized (this ) {
192: init();
193: return (String[]) aliasNameMap.get(charsetName);
194: }
195: }
196:
197: }
|