/* * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package java.awt.datatransfer; import java.awt.Toolkit; import java.lang.ref.SoftReference; import java.io.BufferedReader;import java.io.File;import java.io.InputStreamReader;import java.io.IOException; import java.net.URL;import java.net.MalformedURLException; import java.util.ArrayList;import java.util.HashMap;import java.util.HashSet;import java.util.Iterator;import java.util.LinkedList;import java.util.List;import java.util.Map;import java.util.Set;import java.util.WeakHashMap; import sun.awt.datatransfer.DataTransferer; /** * The SystemFlavorMap is a configurable map between "natives" (Strings), which * correspond to platform-specific data formats, and "flavors" (DataFlavors), * which correspond to platform-independent MIME types. This mapping is used * by the data transfer subsystem to transfer data between Java and native * applications, and between Java applications in separate VMs. * <p> * In the Sun reference implementation, the default SystemFlavorMap is * initialized by the file <code>jre/lib/flavormap.properties</code> and the * contents of the URL referenced by the AWT property * <code>AWT.DnD.flavorMapFileURL</code>. See <code>flavormap.properties</code> * for details. * * @since 1.2 */public final class SystemFlavorMap implements FlavorMap, FlavorTable { /** * Constant prefix used to tag Java types converted to native platform * type. */ private static String JavaMIME = "JAVA_DATAFLAVOR:"; /** * System singleton which maps a thread's ClassLoader to a SystemFlavorMap. */ private static final WeakHashMap flavorMaps = new WeakHashMap(); /** * Copied from java.util.Properties. */ private static final String keyValueSeparators = "=: \t\r\n\f"; private static final String strictKeyValueSeparators = "=:"; private static final String whiteSpaceChars = " \t\r\n\f"; /** * The list of valid, decoded text flavor representation classes, in order * from best to worst. */ private static final String[] UNICODE_TEXT_CLASSES = { "java.io.Reader", "java.lang.String", "java.nio.CharBuffer", "\"[C\"" }; /** * The list of valid, encoded text flavor representation classes, in order * from best to worst. */ private static final String[] ENCODED_TEXT_CLASSES = { "java.io.InputStream", "java.nio.ByteBuffer", "\"[B\"" }; /** * A String representing text/plain MIME type. */ private static final String TEXT_PLAIN_BASE_TYPE = "text/plain"; /** * This constant is passed to flavorToNativeLookup() to indicate that a * a native should be synthesized, stored, and returned by encoding the * DataFlavor's MIME type in case if the DataFlavor is not found in * 'flavorToNative' map. */ private static final boolean SYNTHESIZE_IF_NOT_FOUND = true; /** * Maps native Strings to Lists of DataFlavors (or base type Strings for * text DataFlavors). * Do not use the field directly, use getNativeToFlavor() instead. */ private Map nativeToFlavor = new HashMap(); /** * Accessor to nativeToFlavor map. Since we use lazy initialization we must * use this accessor instead of direct access to the field which may not be * initialized yet. This method will initialize the field if needed. * * @return nativeToFlavor */ private Map getNativeToFlavor() { if (!isMapInitialized) { initSystemFlavorMap(); } return nativeToFlavor; } /** * Maps DataFlavors (or base type Strings for text DataFlavors) to Lists of * native Strings. * Do not use the field directly, use getFlavorToNative() instead. */ private Map flavorToNative = new HashMap(); /** * Accessor to flavorToNative map. Since we use lazy initialization we must * use this accessor instead of direct access to the field which may not be * initialized yet. This method will initialize the field if needed. * * @return flavorToNative */ private synchronized Map getFlavorToNative() { if (!isMapInitialized) { initSystemFlavorMap(); } return flavorToNative; } /** * Shows if the object has been initialized. */ private boolean isMapInitialized = false; /** * Caches the result of getNativesForFlavor(). Maps DataFlavors to * SoftReferences which reference Lists of String natives. */ private Map getNativesForFlavorCache = new HashMap(); /** * Caches the result getFlavorsForNative(). Maps String natives to * SoftReferences which reference Lists of DataFlavors. */ private Map getFlavorsForNativeCache = new HashMap(); /** * Dynamic mapping generation used for text mappings should not be applied * to the DataFlavors and String natives for which the mappings have been * explicitly specified with setFlavorsForNative() or * setNativesForFlavor(). This keeps all such keys. */ private Set disabledMappingGenerationKeys = new HashSet(); /** * Returns the default FlavorMap for this thread's ClassLoader. */ public static FlavorMap getDefaultFlavorMap() { ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); if (contextClassLoader == null) { contextClassLoader = ClassLoader.getSystemClassLoader(); } FlavorMap fm; synchronized(flavorMaps) { fm = (FlavorMap)flavorMaps.get(contextClassLoader); if (fm == null) { fm = new SystemFlavorMap(); flavorMaps.put(contextClassLoader, fm); } } return fm; } private SystemFlavorMap() { } /** * Initializes a SystemFlavorMap by reading flavormap.properties and * AWT.DnD.flavorMapFileURL. * For thread-safety must be called under lock on this. */ private void initSystemFlavorMap() { if (isMapInitialized) { return; } isMapInitialized = true; BufferedReader flavormapDotProperties = java.security.AccessController.doPrivileged( new java.security.PrivilegedAction<BufferedReader>() { public BufferedReader run() { String fileName = System.getProperty("java.home") + File.separator + "lib" + File.separator + "flavormap.properties"; try { return new BufferedReader (new InputStreamReader (new File(fileName).toURI().toURL().openStream(), "ISO-8859-1")); } catch (MalformedURLException e) { System.err.println("MalformedURLException:" + e + " while loading default flavormap.properties file:" + fileName); } catch (IOException e) { System.err.println("IOException:" + e + " while loading default flavormap.properties file:" + fileName); } return null; } }); BufferedReader flavormapURL = java.security.AccessController.doPrivileged( new java.security.PrivilegedAction<BufferedReader>() { public BufferedReader run() { String url = Toolkit.getProperty("AWT.DnD.flavorMapFileURL", null); if (url == null) { return null; } try { return new BufferedReader (new InputStreamReader (new URL(url).openStream(), "ISO-8859-1")); } catch (MalformedURLException e) { System.err.println("MalformedURLException:" + e + " while reading AWT.DnD.flavorMapFileURL:" + url); } catch (IOException e) { System.err.println("IOException:" + e + " while reading AWT.DnD.flavorMapFileURL:" + url); } return null; } }); if (flavormapDotProperties != null) { try { parseAndStoreReader(flavormapDotProperties); } catch (IOException e) { System.err.println("IOException:" + e + " while parsing default flavormap.properties file"); } } if (flavormapURL != null) { try { parseAndStoreReader(flavormapURL); } catch (IOException e) { System.err.println("IOException:" + e + " while parsing AWT.DnD.flavorMapFileURL"); } } } /** * Copied code from java.util.Properties. Parsing the data ourselves is the * only way to handle duplicate keys and values. */ private void parseAndStoreReader(BufferedReader in) throws IOException { while (true) { // Get next line String line = in.readLine(); if (line == null) { return; } if (line.length() > 0) { // Continue lines that end in slashes if they are not comments char firstChar = line.charAt(0); if (firstChar != '#' && firstChar != '!') { while (continueLine(line)) { String nextLine = in.readLine(); if (nextLine == null) { nextLine = ""; } String loppedLine = line.substring(0, line.length() - 1); // Advance beyond whitespace on new line int startIndex = 0; for(; startIndex < nextLine.length(); startIndex++) { if (whiteSpaceChars. indexOf(nextLine.charAt(startIndex)) == -1) { break; } } nextLine = nextLine.substring(startIndex, nextLine.length()); line = loppedLine+nextLine; } // Find start of key int len = line.length(); int keyStart = 0; for(; keyStart < len; keyStart++) { if(whiteSpaceChars. indexOf(line.charAt(keyStart)) == -1) { break; } } // Blank lines are ignored if (keyStart == len) { continue; } // Find separation between key and value int separatorIndex = keyStart; for(; separatorIndex < len; separatorIndex++) { char currentChar = line.charAt(separatorIndex); if (currentChar == '\\') { separatorIndex++; } else if (keyValueSeparators. indexOf(currentChar) != -1) { break; } } // Skip over whitespace after key if any int valueIndex = separatorIndex; for (; valueIndex < len; valueIndex++) { if (whiteSpaceChars. indexOf(line.charAt(valueIndex)) == -1) { break; } } // Skip over one non whitespace key value separators if any if (valueIndex < len) { if (strictKeyValueSeparators. indexOf(line.charAt(valueIndex)) != -1) { valueIndex++; } } // Skip over white space after other separators if any while (valueIndex < len) { if (whiteSpaceChars. indexOf(line.charAt(valueIndex)) == -1) { break; } valueIndex++; } String key = line.substring(keyStart, separatorIndex); String value = (separatorIndex < len) ? line.substring(valueIndex, len) : ""; // Convert then store key and value key = loadConvert(key); value = loadConvert(value); try { MimeType mime = new MimeType(value); if ("text".equals(mime.getPrimaryType())) { String charset = mime.getParameter("charset"); if (DataTransferer.doesSubtypeSupportCharset (mime.getSubType(), charset)) { // We need to store the charset and eoln // parameters, if any, so that the // DataTransferer will have this information // for conversion into the native format. DataTransferer transferer = DataTransferer.getInstance(); if (transferer != null) { transferer.registerTextFlavorProperties (key, charset, mime.getParameter("eoln"), mime.getParameter("terminators")); } } // But don't store any of these parameters in the // DataFlavor itself for any text natives (even // non-charset ones). The SystemFlavorMap will // synthesize the appropriate mappings later. mime.removeParameter("charset"); mime.removeParameter("class"); mime.removeParameter("eoln"); mime.removeParameter("terminators"); value = mime.toString(); } } catch (MimeTypeParseException e) { e.printStackTrace(); continue; } DataFlavor flavor; try { flavor = new DataFlavor(value); } catch (Exception e) { try { flavor = new DataFlavor(value, (String)null); } catch (Exception ee) { ee.printStackTrace(); continue; } } // For text/* flavors, store mappings in separate maps to // enable dynamic mapping generation at a run-time. if ("text".equals(flavor.getPrimaryType())) { store(value, key, getFlavorToNative()); store(key, value, getNativeToFlavor()); } else { store(flavor, key, getFlavorToNative()); store(key, flavor, getNativeToFlavor()); } } } } } /** * Copied from java.util.Properties. */ private boolean continueLine (String line) { int slashCount = 0; int index = line.length() - 1; while((index >= 0) && (line.charAt(index--) == '\\')) { slashCount++; } return (slashCount % 2 == 1); } /** * Copied from java.util.Properties. */ private String loadConvert(String theString) { char aChar; int len = theString.length(); StringBuilder outBuffer = new StringBuilder(len); for (int x = 0; x < len; ) { aChar = theString.charAt(x++); if (aChar == '\\') { aChar = theString.charAt(x++); if (aChar == 'u') { // Read the xxxx int value = 0; for (int i = 0; i < 4; i++) { aChar = theString.charAt(x++); switch (aChar) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { value = (value << 4) + aChar - '0'; break; } case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': { value = (value << 4) + 10 + aChar - 'a'; break; } case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': { value = (value << 4) + 10 + aChar - 'A'; break; } default: { throw new IllegalArgumentException( "Malformed \\uxxxx encoding."); } } } outBuffer.append((char)value); } else { if (aChar == 't') { aChar = '\t'; } else if (aChar == 'r') { aChar = '\r'; } else if (aChar == 'n') {Lines 1–500 of 1299. Load more
/* * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package java.awt.datatransfer; import java.awt.Toolkit; import java.lang.ref.SoftReference; import java.io.BufferedReader; import java.io.File; import java.io.InputStreamReader; import java.io.IOException; import java.net.URL; import java.net.MalformedURLException; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.WeakHashMap; import sun.awt.datatransfer.DataTransferer; /** * The SystemFlavorMap is a configurable map between "natives" (Strings), which * correspond to platform-specific data formats, and "flavors" (DataFlavors), * which correspond to platform-independent MIME types. This mapping is used * by the data transfer subsystem to transfer data between Java and native * applications, and between Java applications in separate VMs. * <p> * In the Sun reference implementation, the default SystemFlavorMap is * initialized by the file <code>jre/lib/flavormap.properties</code> and the * contents of the URL referenced by the AWT property * <code>AWT.DnD.flavorMapFileURL</code>. See <code>flavormap.properties</code> * for details. * * @since 1.2 */ public final class SystemFlavorMap implements FlavorMap, FlavorTable { /** * Constant prefix used to tag Java types converted to native platform * type. */ private static String JavaMIME = "JAVA_DATAFLAVOR:"; /** * System singleton which maps a thread's ClassLoader to a SystemFlavorMap. */ private static final WeakHashMap flavorMaps = new WeakHashMap(); /** * Copied from java.util.Properties. */ private static final String keyValueSeparators = "=: \t\r\n\f"; private static final String strictKeyValueSeparators = "=:"; private static final String whiteSpaceChars = " \t\r\n\f"; /** * The list of valid, decoded text flavor representation classes, in order * from best to worst. */ private static final String[] UNICODE_TEXT_CLASSES = { "java.io.Reader", "java.lang.String", "java.nio.CharBuffer", "\"[C\"" }; /** * The list of valid, encoded text flavor representation classes, in order * from best to worst. */ private static final String[] ENCODED_TEXT_CLASSES = { "java.io.InputStream", "java.nio.ByteBuffer", "\"[B\"" }; /** * A String representing text/plain MIME type. */ private static final String TEXT_PLAIN_BASE_TYPE = "text/plain"; /** * This constant is passed to flavorToNativeLookup() to indicate that a * a native should be synthesized, stored, and returned by encoding the * DataFlavor's MIME type in case if the DataFlavor is not found in * 'flavorToNative' map. */ private static final boolean SYNTHESIZE_IF_NOT_FOUND = true; /** * Maps native Strings to Lists of DataFlavors (or base type Strings for * text DataFlavors). * Do not use the field directly, use getNativeToFlavor() instead. */ private Map nativeToFlavor = new HashMap(); /** * Accessor to nativeToFlavor map. Since we use lazy initialization we must * use this accessor instead of direct access to the field which may not be * initialized yet. This method will initialize the field if needed. * * @return nativeToFlavor */ private Map getNativeToFlavor() { if (!isMapInitialized) { initSystemFlavorMap(); } return nativeToFlavor; } /** * Maps DataFlavors (or base type Strings for text DataFlavors) to Lists of * native Strings. * Do not use the field directly, use getFlavorToNative() instead. */ private Map flavorToNative = new HashMap(); /** * Accessor to flavorToNative map. Since we use lazy initialization we must * use this accessor instead of direct access to the field which may not be * initialized yet. This method will initialize the field if needed. * * @return flavorToNative */ private synchronized Map getFlavorToNative() { if (!isMapInitialized) { initSystemFlavorMap(); } return flavorToNative; } /** * Shows if the object has been initialized. */ private boolean isMapInitialized = false; /** * Caches the result of getNativesForFlavor(). Maps DataFlavors to * SoftReferences which reference Lists of String natives. */ private Map getNativesForFlavorCache = new HashMap(); /** * Caches the result getFlavorsForNative(). Maps String natives to * SoftReferences which reference Lists of DataFlavors. */ private Map getFlavorsForNativeCache = new HashMap(); /** * Dynamic mapping generation used for text mappings should not be applied * to the DataFlavors and String natives for which the mappings have been * explicitly specified with setFlavorsForNative() or * setNativesForFlavor(). This keeps all such keys. */ private Set disabledMappingGenerationKeys = new HashSet(); /** * Returns the default FlavorMap for this thread's ClassLoader. */ public static FlavorMap getDefaultFlavorMap() { ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); if (contextClassLoader == null) { contextClassLoader = ClassLoader.getSystemClassLoader(); } FlavorMap fm; synchronized(flavorMaps) { fm = (FlavorMap)flavorMaps.get(contextClassLoader); if (fm == null) { fm = new SystemFlavorMap(); flavorMaps.put(contextClassLoader, fm); } } return fm; } private SystemFlavorMap() { } /** * Initializes a SystemFlavorMap by reading flavormap.properties and * AWT.DnD.flavorMapFileURL. * For thread-safety must be called under lock on this. */ private void initSystemFlavorMap() { if (isMapInitialized) { return; } isMapInitialized = true; BufferedReader flavormapDotProperties = java.security.AccessController.doPrivileged( new java.security.PrivilegedAction<BufferedReader>() { public BufferedReader run() { String fileName = System.getProperty("java.home") + File.separator + "lib" + File.separator + "flavormap.properties"; try { return new BufferedReader (new InputStreamReader (new File(fileName).toURI().toURL().openStream(), "ISO-8859-1")); } catch (MalformedURLException e) { System.err.println("MalformedURLException:" + e + " while loading default flavormap.properties file:" + fileName); } catch (IOException e) { System.err.println("IOException:" + e + " while loading default flavormap.properties file:" + fileName); } return null; } }); BufferedReader flavormapURL = java.security.AccessController.doPrivileged( new java.security.PrivilegedAction<BufferedReader>() { public BufferedReader run() { String url = Toolkit.getProperty("AWT.DnD.flavorMapFileURL", null); if (url == null) { return null; } try { return new BufferedReader (new InputStreamReader (new URL(url).openStream(), "ISO-8859-1")); } catch (MalformedURLException e) { System.err.println("MalformedURLException:" + e + " while reading AWT.DnD.flavorMapFileURL:" + url); } catch (IOException e) { System.err.println("IOException:" + e + " while reading AWT.DnD.flavorMapFileURL:" + url); } return null; } }); if (flavormapDotProperties != null) { try { parseAndStoreReader(flavormapDotProperties); } catch (IOException e) { System.err.println("IOException:" + e + " while parsing default flavormap.properties file"); } } if (flavormapURL != null) { try { parseAndStoreReader(flavormapURL); } catch (IOException e) { System.err.println("IOException:" + e + " while parsing AWT.DnD.flavorMapFileURL"); } } } /** * Copied code from java.util.Properties. Parsing the data ourselves is the * only way to handle duplicate keys and values. */ private void parseAndStoreReader(BufferedReader in) throws IOException { while (true) { // Get next line String line = in.readLine(); if (line == null) { return; } if (line.length() > 0) { // Continue lines that end in slashes if they are not comments char firstChar = line.charAt(0); if (firstChar != '#' && firstChar != '!') { while (continueLine(line)) { String nextLine = in.readLine(); if (nextLine == null) { nextLine = ""; } String loppedLine = line.substring(0, line.length() - 1); // Advance beyond whitespace on new line int startIndex = 0; for(; startIndex < nextLine.length(); startIndex++) { if (whiteSpaceChars. indexOf(nextLine.charAt(startIndex)) == -1) { break; } } nextLine = nextLine.substring(startIndex, nextLine.length()); line = loppedLine+nextLine; } // Find start of key int len = line.length(); int keyStart = 0; for(; keyStart < len; keyStart++) { if(whiteSpaceChars. indexOf(line.charAt(keyStart)) == -1) { break; } } // Blank lines are ignored if (keyStart == len) { continue; } // Find separation between key and value int separatorIndex = keyStart; for(; separatorIndex < len; separatorIndex++) { char currentChar = line.charAt(separatorIndex); if (currentChar == '\\') { separatorIndex++; } else if (keyValueSeparators. indexOf(currentChar) != -1) { break; } } // Skip over whitespace after key if any int valueIndex = separatorIndex; for (; valueIndex < len; valueIndex++) { if (whiteSpaceChars. indexOf(line.charAt(valueIndex)) == -1) { break; } } // Skip over one non whitespace key value separators if any if (valueIndex < len) { if (strictKeyValueSeparators. indexOf(line.charAt(valueIndex)) != -1) { valueIndex++; } } // Skip over white space after other separators if any while (valueIndex < len) { if (whiteSpaceChars. indexOf(line.charAt(valueIndex)) == -1) { break; } valueIndex++; } String key = line.substring(keyStart, separatorIndex); String value = (separatorIndex < len) ? line.substring(valueIndex, len) : ""; // Convert then store key and value key = loadConvert(key); value = loadConvert(value); try { MimeType mime = new MimeType(value); if ("text".equals(mime.getPrimaryType())) { String charset = mime.getParameter("charset"); if (DataTransferer.doesSubtypeSupportCharset (mime.getSubType(), charset)) { // We need to store the charset and eoln // parameters, if any, so that the // DataTransferer will have this information // for conversion into the native format. DataTransferer transferer = DataTransferer.getInstance(); if (transferer != null) { transferer.registerTextFlavorProperties (key, charset, mime.getParameter("eoln"), mime.getParameter("terminators")); } } // But don't store any of these parameters in the // DataFlavor itself for any text natives (even // non-charset ones). The SystemFlavorMap will // synthesize the appropriate mappings later. mime.removeParameter("charset"); mime.removeParameter("class"); mime.removeParameter("eoln"); mime.removeParameter("terminators"); value = mime.toString(); } } catch (MimeTypeParseException e) { e.printStackTrace(); continue; } DataFlavor flavor; try { flavor = new DataFlavor(value); } catch (Exception e) { try { flavor = new DataFlavor(value, (String)null); } catch (Exception ee) { ee.printStackTrace(); continue; } } // For text/* flavors, store mappings in separate maps to // enable dynamic mapping generation at a run-time. if ("text".equals(flavor.getPrimaryType())) { store(value, key, getFlavorToNative()); store(key, value, getNativeToFlavor()); } else { store(flavor, key, getFlavorToNative()); store(key, flavor, getNativeToFlavor()); } } } } } /** * Copied from java.util.Properties. */ private boolean continueLine (String line) { int slashCount = 0; int index = line.length() - 1; while((index >= 0) && (line.charAt(index--) == '\\')) { slashCount++; } return (slashCount % 2 == 1); } /** * Copied from java.util.Properties. */ private String loadConvert(String theString) { char aChar; int len = theString.length(); StringBuilder outBuffer = new StringBuilder(len); for (int x = 0; x < len; ) { aChar = theString.charAt(x++); if (aChar == '\\') { aChar = theString.charAt(x++); if (aChar == 'u') { // Read the xxxx int value = 0; for (int i = 0; i < 4; i++) { aChar = theString.charAt(x++); switch (aChar) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { value = (value << 4) + aChar - '0'; break; } case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': { value = (value << 4) + 10 + aChar - 'a'; break; } case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': { value = (value << 4) + 10 + aChar - 'A'; break; } default: { throw new IllegalArgumentException( "Malformed \\uxxxx encoding."); } } } outBuffer.append((char)value); } else { if (aChar == 't') { aChar = '\t'; } else if (aChar == 'r') { aChar = '\r'; } else if (aChar == 'n') {