summaryrefslogtreecommitdiffstats
path: root/nio_char/src
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
committerThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
commitfdb2704414a9ed92394ada0d1395e4db86889465 (patch)
tree9b591a4a50054274a197f02b3ccb51313681879f /nio_char/src
downloadlibcore-fdb2704414a9ed92394ada0d1395e4db86889465.zip
libcore-fdb2704414a9ed92394ada0d1395e4db86889465.tar.gz
libcore-fdb2704414a9ed92394ada0d1395e4db86889465.tar.bz2
Initial Contribution
Diffstat (limited to 'nio_char/src')
-rw-r--r--nio_char/src/main/java/java/nio/charset/CharacterCodingException.java41
-rw-r--r--nio_char/src/main/java/java/nio/charset/Charset.java873
-rw-r--r--nio_char/src/main/java/java/nio/charset/CharsetDecoder.java749
-rw-r--r--nio_char/src/main/java/java/nio/charset/CharsetEncoder.java811
-rw-r--r--nio_char/src/main/java/java/nio/charset/CoderMalfunctionError.java40
-rw-r--r--nio_char/src/main/java/java/nio/charset/CoderResult.java297
-rw-r--r--nio_char/src/main/java/java/nio/charset/CodingErrorAction.java64
-rw-r--r--nio_char/src/main/java/java/nio/charset/IllegalCharsetNameException.java56
-rw-r--r--nio_char/src/main/java/java/nio/charset/MalformedInputException.java65
-rw-r--r--nio_char/src/main/java/java/nio/charset/UnmappableCharacterException.java64
-rw-r--r--nio_char/src/main/java/java/nio/charset/UnsupportedCharsetException.java56
-rw-r--r--nio_char/src/main/java/java/nio/charset/package.html14
-rw-r--r--nio_char/src/main/java/java/nio/charset/spi/CharsetProvider.java61
-rw-r--r--nio_char/src/main/java/java/nio/charset/spi/package.html7
-rw-r--r--nio_char/src/main/java/org/apache/harmony/niochar/internal/nls/Messages.java125
-rw-r--r--nio_char/src/main/java/org/apache/harmony/niochar/internal/nls/messages.properties32
-rw-r--r--nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/ASCIICharsetEncoderTest.java451
-rw-r--r--nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/AllTests.java44
-rw-r--r--nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharacterCodingExceptionTest.java53
-rw-r--r--nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetDecoderTest.java231
-rw-r--r--nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetEncoderTest.java169
-rw-r--r--nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetTest.java292
-rw-r--r--nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CoderMalfunctionErrorTest.java62
-rw-r--r--nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/IllegalCharsetNameExceptionTest.java94
-rw-r--r--nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/MalformedInputExceptionTest.java85
-rw-r--r--nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/UnmappableCharacterExceptionTest.java86
-rw-r--r--nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/UnsupportedCharsetExceptionTest.java93
-rw-r--r--nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/spi/AllTests.java36
-rw-r--r--nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/spi/CharsetProviderTest.java94
-rw-r--r--nio_char/src/test/java/tests/api/java/nio/charset/ASCCharsetDecoderTest.java72
-rw-r--r--nio_char/src/test/java/tests/api/java/nio/charset/ASCCharsetTest.java59
-rw-r--r--nio_char/src/test/java/tests/api/java/nio/charset/AbstractCharsetTestCase.java158
-rw-r--r--nio_char/src/test/java/tests/api/java/nio/charset/AllTests.java62
-rw-r--r--nio_char/src/test/java/tests/api/java/nio/charset/CharsetDecoderTest.java784
-rw-r--r--nio_char/src/test/java/tests/api/java/nio/charset/CharsetEncoderTest.java1103
-rw-r--r--nio_char/src/test/java/tests/api/java/nio/charset/CharsetProviderTest.java438
-rw-r--r--nio_char/src/test/java/tests/api/java/nio/charset/CharsetTest.java869
-rw-r--r--nio_char/src/test/java/tests/api/java/nio/charset/CoderResultTest.java265
-rw-r--r--nio_char/src/test/java/tests/api/java/nio/charset/CodingErrorActionTest.java62
-rw-r--r--nio_char/src/test/java/tests/api/java/nio/charset/GBCharsetDecoderTest.java64
-rw-r--r--nio_char/src/test/java/tests/api/java/nio/charset/GBCharsetEncoderTest.java95
-rw-r--r--nio_char/src/test/java/tests/api/java/nio/charset/ISOCharsetDecoderTest.java61
-rw-r--r--nio_char/src/test/java/tests/api/java/nio/charset/ISOCharsetEncoderTest.java112
-rw-r--r--nio_char/src/test/java/tests/api/java/nio/charset/ISOCharsetTest.java58
-rw-r--r--nio_char/src/test/java/tests/api/java/nio/charset/UTF16BECharsetDecoderTest.java74
-rw-r--r--nio_char/src/test/java/tests/api/java/nio/charset/UTF16BECharsetEncoderTest.java121
-rw-r--r--nio_char/src/test/java/tests/api/java/nio/charset/UTF16BECharsetTest.java53
-rw-r--r--nio_char/src/test/java/tests/api/java/nio/charset/UTF16CharsetDecoderTest.java152
-rw-r--r--nio_char/src/test/java/tests/api/java/nio/charset/UTF16CharsetEncoderTest.java138
-rw-r--r--nio_char/src/test/java/tests/api/java/nio/charset/UTF16CharsetTest.java51
-rw-r--r--nio_char/src/test/java/tests/api/java/nio/charset/UTF16LECharsetDecoderTest.java74
-rw-r--r--nio_char/src/test/java/tests/api/java/nio/charset/UTF16LECharsetEncoderTest.java118
-rw-r--r--nio_char/src/test/java/tests/api/java/nio/charset/UTF16LECharsetTest.java54
-rw-r--r--nio_char/src/test/java/tests/api/java/nio/charset/UTF8CharsetTest.java53
-rw-r--r--nio_char/src/test/java/tests/api/java/nio/charset/UTFCharsetDecoderTest.java63
-rw-r--r--nio_char/src/test/java/tests/api/java/nio/charset/UTFCharsetEncoderTest.java102
-rw-r--r--nio_char/src/test/java/tests/nio_char/AllTests.java40
-rw-r--r--nio_char/src/test/resources/jars/charset_provider.jarbin0 -> 463 bytes
-rw-r--r--nio_char/src/test/resources/serialization/org/apache/harmony/nio_char/tests/java/nio/charset/CharacterCodingExceptionTest.golden.serbin0 -> 1822 bytes
-rw-r--r--nio_char/src/test/resources/serialization/org/apache/harmony/nio_char/tests/java/nio/charset/CoderMalfunctionErrorTest.golden.serbin0 -> 1771 bytes
-rw-r--r--nio_char/src/test/resources/serialization/org/apache/harmony/nio_char/tests/java/nio/charset/IllegalCharsetNameExceptionTest.golden.serbin0 -> 1924 bytes
-rw-r--r--nio_char/src/test/resources/serialization/org/apache/harmony/nio_char/tests/java/nio/charset/MalformedInputExceptionTest.golden.serbin0 -> 1893 bytes
-rw-r--r--nio_char/src/test/resources/serialization/org/apache/harmony/nio_char/tests/java/nio/charset/UnmappableCharacterExceptionTest.golden.serbin0 -> 1908 bytes
-rw-r--r--nio_char/src/test/resources/serialization/org/apache/harmony/nio_char/tests/java/nio/charset/UnsupportedCharsetExceptionTest.golden.serbin0 -> 1924 bytes
64 files changed, 10500 insertions, 0 deletions
diff --git a/nio_char/src/main/java/java/nio/charset/CharacterCodingException.java b/nio_char/src/main/java/java/nio/charset/CharacterCodingException.java
new file mode 100644
index 0000000..7a9773f
--- /dev/null
+++ b/nio_char/src/main/java/java/nio/charset/CharacterCodingException.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.charset;
+
+import java.io.IOException;
+
+/**
+ *
+ * Type of exception thrown when an encoding or decoding error occurs.
+ *
+ */
+public class CharacterCodingException extends IOException {
+
+ /*
+ * This constant is used during deserialization to check the J2SE version
+ * which created the serialized object.
+ */
+ private static final long serialVersionUID = 8421532232154627783L;
+
+ /**
+ * Default constructor.
+ */
+ public CharacterCodingException() {
+ super();
+ }
+}
diff --git a/nio_char/src/main/java/java/nio/charset/Charset.java b/nio_char/src/main/java/java/nio/charset/Charset.java
new file mode 100644
index 0000000..4274b26
--- /dev/null
+++ b/nio_char/src/main/java/java/nio/charset/Charset.java
@@ -0,0 +1,873 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.charset;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.spi.CharsetProvider;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+import com.ibm.icu4jni.charset.CharsetProviderICU;
+
+/**
+ * A charset defines a mapping between a Unicode character sequence and a byte
+ * sequence. It facilitate the encoding from a Unicode character sequence into a
+ * byte sequence, and the decoding from a byte sequence into a Unicode character
+ * sequence.
+ * <p>
+ * A charset has a canonical name, which are usually in uppercase. Typically it
+ * also has one or more aliases. The name string can only consist of the
+ * following characters: '0' - '9', 'A' - 'Z', 'a' - 'z', '.', ':'. '-' and '_'.
+ * The first character of the name must be a digit or a letter.
+ * </p>
+ * <p>
+ * The following charsets should be supported by any java platforms: US-ASCII,
+ * ISO-8859-1, UTF-8, UTF-16BE, UTF-16LE, UTF-16.
+ * </p>
+ * <p>
+ * Additional charsets can be made available by configuring one or more charset
+ * providers through provider configuration files. Such files are always named
+ * as "java.nio.charset.spi.CharsetProvider" and located in the
+ * "META-INF/services" sub folder of one or more classpaths. The files should be
+ * encoded in "UTF-8". Each line of their content specifies the class name of a
+ * charset provider which extends <code>java.nio.spi.CharsetProvider</code>.
+ * A line should ends with '\r', '\n' or '\r\n'. Leading and trailing
+ * whitespaces are trimmed. Blank lines, and lines (after trimmed) starting with
+ * "#" which are regarded as comments, are both ignored. Duplicates of already
+ * appeared names are also ignored. Both the configuration files and the
+ * provider classes will be loaded using the thread context class loader.
+ * </p>
+ * <p>
+ * This class is thread-safe.
+ * </p>
+ *
+ * @see java.nio.charset.spi.CharsetProvider
+ *
+ */
+public abstract class Charset implements Comparable<Charset> {
+
+ /*
+ * --------------------------------------------------------------------
+ * Constants
+ * --------------------------------------------------------------------
+ */
+
+ /*
+ * the name of configuration files where charset provider class names can be
+ * specified.
+ */
+ private static final String PROVIDER_CONFIGURATION_FILE_NAME = "META-INF/services/java.nio.charset.spi.CharsetProvider"; //$NON-NLS-1$
+
+ /*
+ * the encoding of configuration files
+ */
+ private static final String PROVIDER_CONFIGURATION_FILE_ENCODING = "UTF-8"; //$NON-NLS-1$
+
+ /*
+ * the comment string used in configuration files
+ */
+ private static final String PROVIDER_CONFIGURATION_FILE_COMMENT = "#"; //$NON-NLS-1$
+
+ private static ClassLoader systemClassLoader;
+
+ /*
+ * --------------------------------------------------------------------
+ * Class variables
+ * --------------------------------------------------------------------
+ */
+
+ // built in provider instance, assuming thread-safe
+ private static CharsetProviderICU _builtInProvider = null;
+
+ // cached built in charsets
+ private static TreeMap<String, Charset> _builtInCharsets = null;
+
+ /*
+ * --------------------------------------------------------------------
+ * Instance variables
+ * --------------------------------------------------------------------
+ */
+
+ private final String canonicalName;
+
+ // the aliases set
+ private final HashSet<String> aliasesSet;
+
+ // cached Charset table
+ private static HashMap<String, Charset> cachedCharsetTable = new HashMap<String, Charset>();
+
+ // cached CharsetDecoder table
+ private static HashMap<String, CharsetDecoder> cachedCharsetDecoderTable = new HashMap<String, CharsetDecoder>();
+
+ // cached CharsetEncoder table
+ private static HashMap<String, CharsetEncoder> cachedCharsetEncoderTable = new HashMap<String, CharsetEncoder>();
+
+ /*
+ * -------------------------------------------------------------------
+ * Global initialization
+ * -------------------------------------------------------------------
+ */
+ static {
+ /*
+ * create built-in charset provider even if no privilege to access
+ * charset provider.
+ */
+ _builtInProvider = AccessController
+ .doPrivileged(new PrivilegedAction<CharsetProviderICU>() {
+ public CharsetProviderICU run() {
+ return new CharsetProviderICU();
+ }
+ });
+ }
+
+ /*
+ * -------------------------------------------------------------------
+ * Constructors
+ * -------------------------------------------------------------------
+ */
+
+ /**
+ * Constructs a <code>Charset</code> object. Duplicated aliases are
+ * ignored.
+ *
+ * @param canonicalName
+ * the canonical name of the charset
+ * @param aliases
+ * an array containing all aliases of the charset
+ * @throws IllegalCharsetNameException
+ * on an illegal value being supplied for either
+ * <code>canonicalName</code> or for any element of
+ * <code>aliases</code>.
+ *
+ */
+ protected Charset(String canonicalName, String[] aliases)
+ throws IllegalCharsetNameException {
+ // throw IllegalArgumentException if name is null
+ if (null == canonicalName) {
+ throw new NullPointerException();
+ }
+ // check whether the given canonical name is legal
+ checkCharsetName(canonicalName);
+ this.canonicalName = canonicalName;
+ // check each alias and put into a set
+ this.aliasesSet = new HashSet<String>();
+ if (null != aliases) {
+ for (int i = 0; i < aliases.length; i++) {
+ checkCharsetName(aliases[i]);
+ this.aliasesSet.add(aliases[i]);
+ }
+ }
+ }
+
+ /*
+ * -------------------------------------------------------------------
+ * Methods
+ * -------------------------------------------------------------------
+ */
+
+ /*
+ * Checks whether a character is a special character that can be used in
+ * charset names, other than letters and digits.
+ */
+ private static boolean isSpecial(char c) {
+ return ('-' == c || '.' == c || ':' == c || '_' == c);
+ }
+
+ /*
+ * Checks whether a character is a letter (ascii) which are defined in Java
+ * Spec.
+ */
+ private static boolean isLetter(char c) {
+ return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z');
+ }
+
+ /*
+ * Checks whether a character is a digit (ascii) which are defined in Java
+ * Spec.
+ */
+ private static boolean isDigit(char c) {
+ return ('0' <= c && c <= '9');
+ }
+
+ /*
+ * Checks whether a given string is a legal charset name. The argument name
+ * should not be null.
+ */
+ private static void checkCharsetName(String name) {
+ // An empty string is illegal charset name
+ if (name.length() == 0) {
+ throw new IllegalCharsetNameException(name);
+ }
+ // The first character must be a letter or a digit
+ // This is related to HARMONY-68 (won't fix)
+ // char first = name.charAt(0);
+ // if (!isLetter(first) && !isDigit(first)) {
+ // throw new IllegalCharsetNameException(name);
+ // }
+ // Check the remaining characters
+ int length = name.length();
+ for (int i = 0; i < length; i++) {
+ char c = name.charAt(i);
+ if (!isLetter(c) && !isDigit(c) && !isSpecial(c)) {
+ throw new IllegalCharsetNameException(name);
+ }
+ }
+ }
+
+ /*
+ * Use privileged code to get the context class loader.
+ */
+ private static ClassLoader getContextClassLoader() {
+ final Thread t = Thread.currentThread();
+ return AccessController
+ .doPrivileged(new PrivilegedAction<ClassLoader>() {
+ public ClassLoader run() {
+ return t.getContextClassLoader();
+ }
+ });
+ }
+
+ /*
+ * Use privileged code to get the system class loader.
+ */
+ private static void getSystemClassLoader() {
+ if (null == systemClassLoader) {
+ systemClassLoader = AccessController
+ .doPrivileged(new PrivilegedAction<ClassLoader>() {
+ public ClassLoader run() {
+ return ClassLoader.getSystemClassLoader();
+ }
+ });
+ }
+ }
+
+ /*
+ * Add the charsets supported by the given provider to the map.
+ */
+ private static void addCharsets(CharsetProvider cp,
+ TreeMap<String, Charset> charsets) {
+ Iterator<Charset> it = cp.charsets();
+ while (it.hasNext()) {
+ Charset cs = it.next();
+ // Only new charsets will be added
+ if (!charsets.containsKey(cs.name())) {
+ charsets.put(cs.name(), cs);
+ }
+ }
+ }
+
+ /*
+ * Trim comment string, and then trim white spaces.
+ */
+ private static String trimClassName(String name) {
+ String trimedName = name;
+ int index = name.indexOf(PROVIDER_CONFIGURATION_FILE_COMMENT);
+ // Trim comments
+ if (index != -1) {
+ trimedName = name.substring(0, index);
+ }
+ return trimedName.trim();
+ }
+
+ /*
+ * Read a configuration file and add the charsets supported by the providers
+ * specified by this configuration file to the map.
+ */
+ private static void loadConfiguredCharsets(URL configFile,
+ ClassLoader contextClassLoader, TreeMap<String, Charset> charsets) {
+ BufferedReader reader = null;
+ try {
+ InputStream is = configFile.openStream();
+ // Read each line for charset provider class names
+ // BEGIN android-modified
+ reader = new BufferedReader(new InputStreamReader(is,
+ PROVIDER_CONFIGURATION_FILE_ENCODING), 8192);
+ // END android-modified
+ String providerClassName = reader.readLine();
+ while (null != providerClassName) {
+ providerClassName = trimClassName(providerClassName);
+ // Skip comments and blank lines
+ if (providerClassName.length() > 0) { // Non empty string
+ // Load the charset provider
+ Object cp = null;
+ try {
+ Class<?> c = Class.forName(providerClassName, true,
+ contextClassLoader);
+ cp = c.newInstance();
+ } catch (Exception ex) {
+ // try to use system classloader when context
+ // classloader failed to load config file.
+ try {
+ getSystemClassLoader();
+ Class<?> c = Class.forName(providerClassName, true,
+ systemClassLoader);
+ cp = c.newInstance();
+ } catch (Exception e) {
+ throw new Error(e.getMessage(), e);
+ }
+ }
+ // Put the charsets supported by this provider into the map
+ addCharsets((CharsetProvider) cp, charsets);
+ }
+ // Read the next line of the config file
+ providerClassName = reader.readLine();
+ }
+ } catch (IOException ex) {
+ // Can't read this configuration file, ignore
+ } finally {
+ try {
+ if (null != reader) {
+ reader.close();
+ }
+ } catch (IOException ex) {
+ // Ignore closing exception
+ }
+ }
+ }
+
+ /**
+ * Gets a map of all available charsets supported by the runtime.
+ * <p>
+ * The returned map contains mappings from canonical names to corresponding
+ * instances of <code>Charset</code>. The canonical names can be
+ * considered as case-insensitive.
+ * </p>
+ *
+ * @return an unmodifiable map of all available charsets supported by the
+ * runtime
+ */
+ @SuppressWarnings("unchecked")
+ public static SortedMap<String, Charset> availableCharsets() {
+ // Initialize the built-in charsets map cache if necessary
+ if (null == _builtInCharsets) {
+ synchronized (Charset.class) {
+ if (null == _builtInCharsets) {
+ _builtInCharsets = new TreeMap<String, Charset>(
+ IgnoreCaseComparator.getInstance());
+ _builtInProvider.putCharsets(_builtInCharsets);
+ }
+ }
+ }
+
+ // Add built-in charsets
+ TreeMap<String, Charset> charsets = (TreeMap<String, Charset>) _builtInCharsets
+ .clone();
+
+ // Collect all charsets provided by charset providers
+ ClassLoader contextClassLoader = getContextClassLoader();
+ Enumeration<URL> e = null;
+ try {
+ if (null != contextClassLoader) {
+ e = contextClassLoader
+ .getResources(PROVIDER_CONFIGURATION_FILE_NAME);
+ } else {
+ getSystemClassLoader();
+ e = systemClassLoader
+ .getResources(PROVIDER_CONFIGURATION_FILE_NAME);
+ }
+ // Examine each configuration file
+ while (e.hasMoreElements()) {
+ loadConfiguredCharsets(e.nextElement(), contextClassLoader,
+ charsets);
+ }
+ } catch (IOException ex) {
+ // Unexpected ClassLoader exception, ignore
+ }
+ return Collections.unmodifiableSortedMap(charsets);
+ }
+
+ /*
+ * Read a configuration file and try to find the desired charset among those
+ * which are supported by the providers specified in this configuration
+ * file.
+ */
+ private static Charset searchConfiguredCharsets(String charsetName,
+ ClassLoader contextClassLoader, URL configFile) {
+ BufferedReader reader = null;
+ try {
+ InputStream is = configFile.openStream();
+ // Read each line for charset provider class names
+ // BEGIN android-modified
+ reader = new BufferedReader(new InputStreamReader(is,
+ PROVIDER_CONFIGURATION_FILE_ENCODING), 8192);
+ // END android-modified
+ String providerClassName = reader.readLine();
+ while (null != providerClassName) {
+ providerClassName = trimClassName(providerClassName);
+ if (providerClassName.length() > 0) { // Non empty string
+ // Load the charset provider
+ Object cp = null;
+ try {
+ Class<?> c = Class.forName(providerClassName, true,
+ contextClassLoader);
+ cp = c.newInstance();
+ } catch (Exception ex) {
+ // try to use system classloader when context
+ // classloader failed to load config file.
+ try {
+ getSystemClassLoader();
+ Class<?> c = Class.forName(providerClassName, true,
+ systemClassLoader);
+ cp = c.newInstance();
+ } catch (SecurityException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new Error(e.getMessage(), e);
+ }
+ }
+ // Try to get the desired charset from this provider
+ Charset cs = ((CharsetProvider) cp)
+ .charsetForName(charsetName);
+ if (null != cs) {
+ return cs;
+ }
+ }
+ // Read the next line of the config file
+ providerClassName = reader.readLine();
+ }
+ return null;
+ } catch (IOException ex) {
+ // Can't read this configuration file
+ return null;
+ } finally {
+ try {
+ if (null != reader) {
+ reader.close();
+ }
+ } catch (IOException ex) {
+ // Ignore closing exception
+ }
+ }
+ }
+
+ /*
+ * Gets a <code> Charset </code> instance for the specified charset name. If
+ * the charset is not supported, returns null instead of throwing an
+ * exception.
+ */
+ private static Charset forNameInternal(String charsetName)
+ throws IllegalCharsetNameException {
+ if (null == charsetName) {
+ throw new IllegalArgumentException();
+ }
+ checkCharsetName(charsetName);
+ synchronized (Charset.class) {
+ // Try to get Charset from cachedCharsetTable
+ Charset cs = getCachedCharset(charsetName);
+ if (null != cs) {
+ return cs;
+ }
+ // Try built-in charsets
+ cs = _builtInProvider.charsetForName(charsetName);
+ if (null != cs) {
+ cacheCharset(cs);
+ return cs;
+ }
+
+ // Collect all charsets provided by charset providers
+ ClassLoader contextClassLoader = getContextClassLoader();
+ Enumeration<URL> e = null;
+ try {
+ if (null != contextClassLoader) {
+ e = contextClassLoader
+ .getResources(PROVIDER_CONFIGURATION_FILE_NAME);
+ } else {
+ getSystemClassLoader();
+ e = systemClassLoader
+ .getResources(PROVIDER_CONFIGURATION_FILE_NAME);
+ }
+ // Examine each configuration file
+ while (e.hasMoreElements()) {
+ cs = searchConfiguredCharsets(charsetName,
+ contextClassLoader, e.nextElement());
+ if (null != cs) {
+ cacheCharset(cs);
+ return cs;
+ }
+ }
+ } catch (IOException ex) {
+ // Unexpected ClassLoader exception, ignore
+ }
+ }
+ return null;
+ }
+
+ /*
+ * save charset into cachedCharsetTable
+ */
+ private static void cacheCharset(Charset cs) {
+ cachedCharsetTable.put(cs.name(), cs);
+ Set<String> aliasesSet = cs.aliases();
+ if (null != aliasesSet) {
+ Iterator<String> iter = aliasesSet.iterator();
+ while (iter.hasNext()) {
+ String alias = iter.next();
+ cachedCharsetTable.put(alias, cs);
+ }
+ }
+ }
+
+ /*
+ * get cached charset reference by name
+ */
+ private static Charset getCachedCharset(String name) {
+ return cachedCharsetTable.get(name);
+ }
+
+ /**
+ * Gets a <code>Charset</code> instance for the specified charset name.
+ *
+ * @param charsetName
+ * the name of the charset
+ * @return a <code>Charset</code> instance for the specified charset name
+ * @throws IllegalCharsetNameException
+ * If the specified charset name is illegal.
+ * @throws UnsupportedCharsetException
+ * If the desired charset is not supported by this runtime.
+ */
+ public static Charset forName(String charsetName)
+ throws IllegalCharsetNameException, UnsupportedCharsetException {
+ Charset c = forNameInternal(charsetName);
+ if (null == c) {
+ throw new UnsupportedCharsetException(charsetName);
+ }
+ return c;
+ }
+
+ /**
+ * Determines whether the specified charset is supported by this runtime.
+ *
+ * @param charsetName
+ * the name of the charset
+ * @return true if the specified charset is supported, otherwise false
+ * @throws IllegalCharsetNameException
+ * If the specified charset name is illegal.
+ */
+ public static boolean isSupported(String charsetName)
+ throws IllegalCharsetNameException {
+ Charset cs = forNameInternal(charsetName);
+ return (null != cs);
+ }
+
+ /**
+ * Determines whether this charset is a super set of the given charset.
+ *
+ * @param charset
+ * a given charset
+ * @return true if this charset is a super set of the given charset,
+ * otherwise false
+ */
+ public abstract boolean contains(Charset charset);
+
+ /**
+ * Gets a new instance of encoder for this charset.
+ *
+ * @return a new instance of encoder for this charset
+ */
+ public abstract CharsetEncoder newEncoder();
+
+ /**
+ * Gets a new instance of decoder for this charset.
+ *
+ * @return a new instance of decoder for this charset
+ */
+ public abstract CharsetDecoder newDecoder();
+
+ /**
+ * Gets the canonical name of this charset.
+ *
+ * @return this charset's name in canonical form.
+ */
+ public final String name() {
+ return this.canonicalName;
+ }
+
+ /**
+ * Gets the set of this charset's aliases.
+ *
+ * @return an unmodifiable set of this charset's aliases
+ */
+ public final Set<String> aliases() {
+ return Collections.unmodifiableSet(this.aliasesSet);
+ }
+
+ /**
+ * Gets the name of this charset for the default locale.
+ *
+ * @return the name of this charset for the default locale
+ */
+ public String displayName() {
+ return this.canonicalName;
+ }
+
+ /**
+ * Gets the name of this charset for the specified locale.
+ *
+ * @param l
+ * a certain locale
+ * @return the name of this charset for the specified locale
+ */
+ public String displayName(Locale l) {
+ return this.canonicalName;
+ }
+
+ /**
+ * Returns whether this charset is known to be registered in the IANA
+ * Charset Registry.
+ *
+ * @return true if the charset is known to be registered, otherwise returns
+ * false.
+ */
+ public final boolean isRegistered() {
+ return !canonicalName.startsWith("x-") //$NON-NLS-1$
+ && !canonicalName.startsWith("X-"); //$NON-NLS-1$
+ }
+
+ /**
+ * Returns true if this charset supports encoding, otherwise false.
+ *
+ * @return true
+ */
+ public boolean canEncode() {
+ return true;
+ }
+
+ /**
+ * Encodes the content of the give character buffer and outputs to a byte
+ * buffer that is to be returned.
+ * <p>
+ * The default action in case of encoding errors is
+ * <code>CodingErrorAction.REPLACE</code>.
+ * </p>
+ *
+ * @param buffer
+ * the character buffer containing the content to be encoded
+ * @return the result of the encoding
+ */
+ synchronized public final ByteBuffer encode(CharBuffer buffer) {
+ CharsetEncoder e = getCachedCharsetEncoder(canonicalName);
+ try {
+ synchronized (e) {
+ return e.encode(buffer);
+ }
+ } catch (CharacterCodingException ex) {
+ throw new Error(ex.getMessage(), ex);
+ }
+ }
+
+ /*
+ * get cached CharsetEncoder by canonical name
+ */
+ private CharsetEncoder getCachedCharsetEncoder(String name) {
+ synchronized (cachedCharsetEncoderTable) {
+ CharsetEncoder e = cachedCharsetEncoderTable
+ .get(name);
+ if (null == e) {
+ e = this.newEncoder();
+ e.onMalformedInput(CodingErrorAction.REPLACE);
+ e.onUnmappableCharacter(CodingErrorAction.REPLACE);
+ cachedCharsetEncoderTable.put(name, e);
+ }
+ return e;
+ }
+ }
+
+ /**
+ * Encodes a string and outputs to a byte buffer that is to be returned.
+ * <p>
+ * The default action in case of encoding errors is
+ * <code>CodingErrorAction.REPLACE</code>.
+ * </p>
+ *
+ * @param s
+ * the string to be encoded
+ * @return the result of the encoding
+ */
+ public final ByteBuffer encode(String s) {
+ return encode(CharBuffer.wrap(s));
+ }
+
+ /**
+ * Decodes the content of the give byte buffer and outputs to a character
+ * buffer that is to be returned.
+ * <p>
+ * The default action in case of decoding errors is
+ * <code>CodingErrorAction.REPLACE</code>.
+ * </p>
+ *
+ * @param buffer
+ * the byte buffer containing the content to be decoded
+ * @return a character buffer containing the output of the decoding
+ */
+ public final CharBuffer decode(ByteBuffer buffer) {
+ CharsetDecoder d = getCachedCharsetDecoder(canonicalName);
+ try {
+ synchronized (d) {
+ return d.decode(buffer);
+ }
+ } catch (CharacterCodingException ex) {
+ throw new Error(ex.getMessage(), ex);
+ }
+ }
+
+ /*
+ * get cached CharsetDecoder by canonical name
+ */
+ private CharsetDecoder getCachedCharsetDecoder(String name) {
+ synchronized (cachedCharsetDecoderTable) {
+ CharsetDecoder d = cachedCharsetDecoderTable
+ .get(name);
+ if (null == d) {
+ d = this.newDecoder();
+ d.onMalformedInput(CodingErrorAction.REPLACE);
+ d.onUnmappableCharacter(CodingErrorAction.REPLACE);
+ cachedCharsetDecoderTable.put(name, d);
+ }
+ return d;
+ }
+ }
+
+ /*
+ * -------------------------------------------------------------------
+ * Methods implementing parent interface Comparable
+ * -------------------------------------------------------------------
+ */
+
+ /**
+ * Compares this charset with the given charset.
+ *
+ * @param charset
+ * the given object to be compared with
+ * @return a negative integer if less than the given object, a positive
+ * integer if larger than it, or 0 if equal to it
+ */
+ public final int compareTo(Charset charset) {
+ return this.canonicalName.compareToIgnoreCase(charset.canonicalName);
+ }
+
+ /*
+ * -------------------------------------------------------------------
+ * Methods overriding parent class Object
+ * -------------------------------------------------------------------
+ */
+
+ /**
+ * Determines whether this charset equals to the given object. They are
+ * considered to be equal if they have the same canonical name.
+ *
+ * @param obj
+ * the given object to be compared with
+ * @return true if they have the same canonical name, otherwise false
+ */
+ @Override
+ public final boolean equals(Object obj) {
+ if (obj instanceof Charset) {
+ Charset that = (Charset) obj;
+ return this.canonicalName.equals(that.canonicalName);
+ }
+ return false;
+ }
+
+ /**
+ * Gets the hash code of this charset.
+ *
+ * @return the hash code of this charset
+ */
+ @Override
+ public final int hashCode() {
+ return this.canonicalName.hashCode();
+ }
+
+ /**
+ * Gets a string representation of this charset. Usually this contains the
+ * canonical name of the charset.
+ *
+ * @return a string representation of this charset
+ */
+ @Override
+ public final String toString() {
+ return "Charset[" + this.canonicalName + "]"; //$NON-NLS-1$//$NON-NLS-2$
+ }
+
+ /**
+ * Gets the system default charset from jvm.
+ *
+ * @return the default charset
+ */
+ public static Charset defaultCharset() {
+ Charset defaultCharset = null;
+ String encoding = AccessController
+ .doPrivileged(new PrivilegedAction<String>() {
+ public String run() {
+ return System.getProperty("file.encoding"); //$NON-NLS-1$
+ }
+ });
+ try {
+ defaultCharset = Charset.forName(encoding);
+ } catch (UnsupportedCharsetException e) {
+ defaultCharset = Charset.forName("UTF-8"); //$NON-NLS-1$
+ }
+ return defaultCharset;
+ }
+
+ /**
+ * A comparator that ignores case.
+ */
+ static class IgnoreCaseComparator implements Comparator<String> {
+
+ // the singleton
+ private static Comparator<String> c = new IgnoreCaseComparator();
+
+ /*
+ * Default constructor.
+ */
+ private IgnoreCaseComparator() {
+ // no action
+ }
+
+ /*
+ * Gets a single instance.
+ */
+ public static Comparator<String> getInstance() {
+ return c;
+ }
+
+ /*
+ * Compares two strings ignoring case.
+ */
+ public int compare(String s1, String s2) {
+ return s1.compareToIgnoreCase(s2);
+ }
+ }
+}
diff --git a/nio_char/src/main/java/java/nio/charset/CharsetDecoder.java b/nio_char/src/main/java/java/nio/charset/CharsetDecoder.java
new file mode 100644
index 0000000..5c1be6e
--- /dev/null
+++ b/nio_char/src/main/java/java/nio/charset/CharsetDecoder.java
@@ -0,0 +1,749 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.charset;
+
+import java.nio.BufferOverflowException;
+import java.nio.BufferUnderflowException;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+
+import org.apache.harmony.niochar.internal.nls.Messages;
+
+/**
+ * An converter that can convert bytes sequence in some charset to 16-bit
+ * Unicode character sequence.
+ * <p>
+ * The input byte sequence is wrapped by {@link java.nio.ByteBuffer ByteBuffer}
+ * and the output character sequence is {@link java.nio.CharBuffer CharBuffer}.
+ * A decoder instance should be used in following sequence, which is referred to
+ * as a decoding operation:
+ * <ol>
+ * <li>Invoking the {@link #reset() reset} method to reset the decoder if the
+ * decoder has been used;</li>
+ * <li>Invoking the {@link #decode(ByteBuffer, CharBuffer, boolean) decode}
+ * method until the additional input is not needed, the <code>endOfInput</code>
+ * parameter must be set to false, the input buffer must be filled and the
+ * output buffer must be flushed between invocations;</li>
+ * <li>Invoking the {@link #decode(ByteBuffer, CharBuffer, boolean) decode}
+ * method last time, and the the <code>endOfInput</code> parameter must be set
+ * to true</li>
+ * <li>Invoking the {@link #flush(CharBuffer) flush} method to flush the
+ * output.</li>
+ * </ol>
+ * </p>
+ * <p>
+ * The {@link #decode(ByteBuffer, CharBuffer, boolean) decode} method will
+ * convert as many bytes as possible, and the process won't stop except the
+ * input bytes has been run out of, the output buffer has been filled or some
+ * error has happened. A {@link CoderResult CoderResult} instance will be
+ * returned to indicate the stop reason, and the invoker can identify the result
+ * and choose further action, which can include filling the input buffer,
+ * flushing the output buffer, recovering from error and trying again.
+ * </p>
+ * <p>
+ * There are two common decoding errors. One is named as malformed and it is
+ * returned when the input byte sequence is illegal for current specific
+ * charset, the other is named as unmappable character and it is returned when a
+ * problem occurs mapping a legal input byte sequence to its Unicode character
+ * equivalent.
+ * </p>
+ * <p>
+ * The two errors can be handled in three ways, the default one is to report the
+ * error to the invoker by a {@link CoderResult CoderResult} instance, and the
+ * alternatives are to ignore it or to replace the erroneous input with the
+ * replacement string. The replacement string is "\uFFFD" by default and can be
+ * changed by invoking {@link #replaceWith(String) replaceWith} method. The
+ * invoker of this decoder can choose one way by specifying a
+ * {@link CodingErrorAction CodingErrorAction} instance for each error type via
+ * {@link #onMalformedInput(CodingErrorAction) onMalformedInput} method and
+ * {@link #onUnmappableCharacter(CodingErrorAction) onUnmappableCharacter}
+ * method.
+ * </p>
+ * <p>
+ * This class is abstract class and encapsulate many common operations of
+ * decoding process for all charsets. Decoder for specific charset should extend
+ * this class and need only implement
+ * {@link #decodeLoop(ByteBuffer, CharBuffer) decodeLoop} method for basic
+ * decoding loop. If a subclass maintains internal state, it should override the
+ * {@link #implFlush(CharBuffer) implFlush} method and
+ * {@link #implReset() implReset} method in addition.
+ * </p>
+ * <p>
+ * This class is not thread-safe.
+ * </p>
+ *
+ * @see java.nio.charset.Charset
+ * @see java.nio.charset.CharsetEncoder
+ */
+public abstract class CharsetDecoder {
+ /*
+ * --------------------------------------- Consts
+ * ---------------------------------------
+ */
+ /*
+ * internal status consts
+ */
+ private static final int INIT = 0;
+
+ private static final int ONGOING = 1;
+
+ private static final int END = 2;
+
+ private static final int FLUSH = 3;
+
+ /*
+ * --------------------------------------- Instance variables
+ * ---------------------------------------
+ */
+ // average number of chars for one byte
+ private float averChars;
+
+ // maximum number of chars for one byte
+ private float maxChars;
+
+ // charset for this decoder
+ private Charset cs;
+
+ // specify the action if malformed input error encountered
+ private CodingErrorAction malformAction;
+
+ // specify the action if unmappable character error encountered
+ private CodingErrorAction unmapAction;
+
+ // the replacement string
+ private String replace;
+
+ // the current status
+ private int status;
+
+ /*
+ * --------------------------------------- Constructor
+ * ---------------------------------------
+ */
+ /**
+ * Construct a new <code>CharsetDecoder</code> using given
+ * <code>Charset</code>, average number and maximum number of characters
+ * created by this decoder for one input byte, and the default replacement
+ * string "\uFFFD".
+ *
+ * @param charset
+ * this decoder's <code>Charset</code>, which create this
+ * decoder
+ * @param averageCharsPerByte
+ * average number of characters created by this decoder for one
+ * input byte, must be positive
+ * @param maxCharsPerByte
+ * maximum number of characters created by this decoder for one
+ * input byte, must be positive
+ * @throws IllegalArgumentException
+ * if <code>averageCharsPerByte</code> or
+ * <code>maxCharsPerByte</code> is negative
+ */
+ protected CharsetDecoder(Charset charset, float averageCharsPerByte,
+ float maxCharsPerByte) {
+ if (averageCharsPerByte <= 0 || maxCharsPerByte <= 0) {
+ // niochar.00=Characters number for one byte must be positive.
+ throw new IllegalArgumentException(Messages.getString("niochar.00")); //$NON-NLS-1$
+ }
+ if (averageCharsPerByte > maxCharsPerByte) {
+ // niochar.01=averageCharsPerByte is greater than maxCharsPerByte
+ throw new IllegalArgumentException(Messages.getString("niochar.01")); //$NON-NLS-1$
+ }
+ averChars = averageCharsPerByte;
+ maxChars = maxCharsPerByte;
+ cs = charset;
+ status = INIT;
+ malformAction = CodingErrorAction.REPORT;
+ unmapAction = CodingErrorAction.REPORT;
+ replace = "\ufffd"; //$NON-NLS-1$
+ }
+
+ /*
+ * --------------------------------------- Methods
+ * ---------------------------------------
+ */
+ /**
+ * get the average number of characters created by this decoder for single
+ * input byte
+ *
+ * @return the average number of characters created by this decoder for
+ * single input byte
+ */
+ public final float averageCharsPerByte() {
+ return averChars;
+ }
+
+ /**
+ * Get the <code>Charset</code> which creates this decoder.
+ *
+ * @return the <code>Charset</code> which creates this decoder
+ */
+ public final Charset charset() {
+ return cs;
+ }
+
+ /**
+ * This is a facade method for decoding operation.
+ * <p>
+ * This method decodes the remaining byte sequence of the given byte buffer
+ * into a new character buffer. This method performs a complete decoding
+ * operation, resets at first, then decodes, and flushes at last.
+ * </p>
+ * <p>
+ * This method should not be invoked if another decode operation is ongoing.
+ * </p>
+ *
+ * @param in
+ * the input buffer
+ * @return a new <code>CharBuffer</code> containing the the characters
+ * produced by this decoding operation. The buffer's limit will be
+ * the position of last character in buffer, and the position will
+ * be zero
+ * @throws IllegalStateException
+ * if another decoding operation is ongoing
+ * @throws MalformedInputException
+ * if illegal input byte sequence for this charset encountered,
+ * and the action for malformed error is
+ * {@link CodingErrorAction#REPORT CodingErrorAction.REPORT}
+ * @throws UnmappableCharacterException
+ * if legal but unmappable input byte sequence for this charset
+ * encountered, and the action for unmappable character error is
+ * {@link CodingErrorAction#REPORT CodingErrorAction.REPORT}.
+ * Unmappable means the byte sequence at the input buffer's
+ * current position cannot be mapped to a Unicode character
+ * sequence.
+ * @throws CharacterCodingException
+ * if other exception happened during the decode operation
+ */
+ public final CharBuffer decode(ByteBuffer in)
+ throws CharacterCodingException {
+ reset();
+ int length = (int) (in.remaining() * averChars);
+ CharBuffer output = CharBuffer.allocate(length);
+ CoderResult result = null;
+ while (true) {
+ result = decode(in, output, false);
+ checkCoderResult(result);
+ if (result.isUnderflow()) {
+ break;
+ } else if (result.isOverflow()) {
+ output = allocateMore(output);
+ }
+ }
+ result = decode(in, output, true);
+ checkCoderResult(result);
+
+ while (true) {
+ result = flush(output);
+ checkCoderResult(result);
+ if (result.isOverflow()) {
+ output = allocateMore(output);
+ } else {
+ break;
+ }
+ }
+
+ output.flip();
+ status = FLUSH;
+ return output;
+ }
+
+ /*
+ * checks the result whether it needs to throw CharacterCodingException.
+ */
+ private void checkCoderResult(CoderResult result)
+ throws CharacterCodingException {
+ if (result.isMalformed() && malformAction == CodingErrorAction.REPORT) {
+ throw new MalformedInputException(result.length());
+ } else if (result.isUnmappable()
+ && unmapAction == CodingErrorAction.REPORT) {
+ throw new UnmappableCharacterException(result.length());
+ }
+ }
+
+ /*
+ * original output is full and doesn't have remaining. allocate more space
+ * to new CharBuffer and return it, the contents in the given buffer will be
+ * copied into the new buffer.
+ */
+ private CharBuffer allocateMore(CharBuffer output) {
+ if (output.capacity() == 0) {
+ return CharBuffer.allocate(1);
+ }
+ CharBuffer result = CharBuffer.allocate(output.capacity() * 2);
+ output.flip();
+ result.put(output);
+ return result;
+ }
+
+ /**
+ * Decodes bytes starting at the current position of the given input buffer,
+ * and writes the equivalent character sequence into the given output buffer
+ * from its current position.
+ * <p>
+ * The buffers' position will be changed with the reading and writing
+ * operation, but their limits and marks will be kept intact.
+ * </p>
+ * <p>
+ * A <code>CoderResult</code> instance will be returned according to
+ * following rules:
+ * <ul>
+ * <li>{@link CoderResult#OVERFLOW CoderResult.OVERFLOW} indicates that
+ * even though not all of the input has been processed, the buffer the
+ * output is being written to has reached its capacity. In the event of this
+ * code being returned this method should be called once more with an
+ * <code>out</code> argument that has not already been filled.</li>
+ * <li>{@link CoderResult#UNDERFLOW CoderResult.UNDERFLOW} indicates that
+ * as many bytes as possible in the input buffer have been decoded. If there
+ * is no further input and no remaining bytes in the input buffer then this
+ * operation may be regarded as complete. Otherwise, this method should be
+ * called once more with additional input.</li>
+ * <li>A {@link CoderResult#malformedForLength(int) malformed input} result
+ * indicates that some malformed input error encountered, and the erroneous
+ * bytes start at the input buffer's position and their number can be got by
+ * result's {@link CoderResult#length() length}. This kind of result can be
+ * returned only if the malformed action is
+ * {@link CodingErrorAction#REPORT CodingErrorAction.REPORT}. </li>
+ * <li>A {@link CoderResult#unmappableForLength(int) unmappable character}
+ * result indicates that some unmappable character error encountered, and
+ * the erroneous bytes start at the input buffer's position and their number
+ * can be got by result's {@link CoderResult#length() length}. This kind of
+ * result can be returned only if the unmappable character action is
+ * {@link CodingErrorAction#REPORT CodingErrorAction.REPORT}. </li>
+ * </ul>
+ * </p>
+ * <p>
+ * The <code>endOfInput</code> parameter indicates that if the invoker can
+ * provider further input. This parameter is true if and only if the bytes
+ * in current input buffer are all inputs for this decoding operation. Note
+ * that it is common and won't cause error that the invoker sets false and
+ * then finds no more input available; while it may cause error that the
+ * invoker always sets true in several consecutive invocations so that any
+ * remaining input will be treated as malformed input.
+ * </p>
+ * <p>
+ * This method invokes
+ * {@link #decodeLoop(ByteBuffer, CharBuffer) decodeLoop} method to
+ * implement basic decode logic for specific charset.
+ * </p>
+ *
+ * @param in
+ * the input buffer
+ * @param out
+ * the output buffer
+ * @param endOfInput
+ * true if all the input characters have been provided
+ * @return a <code>CoderResult</code> instance which indicates the reason
+ * of termination
+ * @throws IllegalStateException
+ * if decoding has started or no more input is needed in this
+ * decoding progress.
+ * @throws CoderMalfunctionError
+ * if the {@link #decodeLoop(ByteBuffer, CharBuffer) decodeLoop}
+ * method threw an <code>BufferUnderflowException</code> or
+ * <code>BufferOverflowException</code>
+ */
+ public final CoderResult decode(ByteBuffer in, CharBuffer out,
+ boolean endOfInput) {
+ /*
+ * status check
+ */
+ if ((status == FLUSH) || (!endOfInput && status == END)) {
+ throw new IllegalStateException();
+ }
+
+ CoderResult result = null;
+
+ // begin to decode
+ while (true) {
+ CodingErrorAction action = null;
+ try {
+ result = decodeLoop(in, out);
+ } catch (BufferOverflowException ex) {
+ // unexpected exception
+ throw new CoderMalfunctionError(ex);
+ } catch (BufferUnderflowException ex) {
+ // unexpected exception
+ throw new CoderMalfunctionError(ex);
+ }
+
+ /*
+ * result handling
+ */
+ if (result.isUnderflow()) {
+ int remaining = in.remaining();
+ status = endOfInput ? END : ONGOING;
+ if (endOfInput && remaining > 0) {
+ result = CoderResult.malformedForLength(remaining);
+ in.position(in.position() + result.length());
+ } else {
+ return result;
+ }
+ }
+ if (result.isOverflow()) {
+ return result;
+ }
+ // set coding error handle action
+ action = malformAction;
+ if (result.isUnmappable()) {
+ action = unmapAction;
+ }
+ // If the action is IGNORE or REPLACE, we should continue decoding.
+ if (action == CodingErrorAction.REPLACE) {
+ if (out.remaining() < replace.length()) {
+ return CoderResult.OVERFLOW;
+ }
+ out.put(replace);
+ } else {
+ if (action != CodingErrorAction.IGNORE)
+ return result;
+ }
+ if (!result.isMalformed()) {
+ in.position(in.position() + result.length());
+ }
+ }
+ }
+
+ /**
+ * Decode bytes into characters. This method is called by
+ * {@link #decode(ByteBuffer, CharBuffer, boolean) decode} method.
+ *
+ * This method will implement the essential decoding operation, and it won't
+ * stop decoding until either all the input bytes are read, the output
+ * buffer is filled, or some exception encountered. And then it will return
+ * a <code>CoderResult</code> object indicating the result of current
+ * decoding operation. The rules to construct the <code>CoderResult</code>
+ * is same as the {@link #decode(ByteBuffer, CharBuffer, boolean) decode}.
+ * When exception encountered in the decoding operation, most implementation
+ * of this method will return a relevant result object to
+ * {@link #decode(ByteBuffer, CharBuffer, boolean) decode} method, and some
+ * performance optimized implementation may handle the exception and
+ * implement the error action itself.
+ *
+ * The buffers are scanned from their current positions, and their positions
+ * will be modified accordingly, while their marks and limits will be
+ * intact. At most {@link ByteBuffer#remaining() in.remaining()} characters
+ * will be read, and {@link CharBuffer#remaining() out.remaining()} bytes
+ * will be written.
+ *
+ * Note that some implementation may pre-scan the input buffer and return
+ * <code>CoderResult.UNDERFLOW</code> until it receives sufficient input.
+ *
+ * @param in
+ * the input buffer
+ * @param out
+ * the output buffer
+ * @return a <code>CoderResult</code> instance indicating the result
+ */
+ protected abstract CoderResult decodeLoop(ByteBuffer in, CharBuffer out);
+
+ /**
+ * Get the charset detected by this decoder, this method is optional.
+ * <p>
+ * If implementing an auto-detecting charset, then this decoder returns the
+ * detected charset from this method when it is available. The returned
+ * charset will be the same for the rest of the decode operation.
+ * </p>
+ * <p>
+ * If insufficient bytes have been read to determine the charset,
+ * <code>IllegalStateException</code> will be thrown.
+ * </p>
+ * <p>
+ * The default implementation always throws
+ * <code>UnsupportedOperationException</code>, so it should be overridden
+ * by subclass if needed.
+ * </p>
+ *
+ * @return the charset detected by this decoder, or null if it is not yet
+ * determined
+ * @throws UnsupportedOperationException
+ * if this decoder does not implement an auto-detecting charset
+ * @throws IllegalStateException
+ * if insufficient bytes have been read to determine the charset
+ */
+ public Charset detectedCharset() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Flush this decoder.
+ *
+ * This method will call {@link #implFlush(CharBuffer) implFlush}. Some
+ * decoders may need to write some characters to the output buffer when they
+ * have read all input bytes, subclasses can overridden
+ * {@link #implFlush(CharBuffer) implFlush} to perform writing action.
+ *
+ * The maximum number of written bytes won't larger than
+ * {@link CharBuffer#remaining() out.remaining()}. If some decoder want to
+ * write more bytes than output buffer's remaining spaces, then
+ * <code>CoderResult.OVERFLOW</code> will be returned, and this method
+ * must be called again with a character buffer that has more spaces.
+ * Otherwise this method will return <code>CoderResult.UNDERFLOW</code>,
+ * which means one decoding process has been completed successfully.
+ *
+ * During the flush, the output buffer's position will be changed
+ * accordingly, while its mark and limit will be intact.
+ *
+ * @param out
+ * the given output buffer
+ * @return <code>CoderResult.UNDERFLOW</code> or
+ * <code>CoderResult.OVERFLOW</code>
+ * @throws IllegalStateException
+ * if this decoder hasn't read all input bytes during one
+ * decoding process, which means neither after calling
+ * {@link #decode(ByteBuffer) decode(ByteBuffer)} nor after
+ * calling {@link #decode(ByteBuffer, CharBuffer, boolean)
+ * decode(ByteBuffer, CharBuffer, boolean)} with true value for
+ * the last boolean parameter
+ */
+ public final CoderResult flush(CharBuffer out) {
+ if (status != END && status != INIT) {
+ throw new IllegalStateException();
+ }
+ CoderResult result = implFlush(out);
+ if (result == CoderResult.UNDERFLOW) {
+ status = FLUSH;
+ }
+ return result;
+ }
+
+ /**
+ * Flush this decoder. Default implementation does nothing and always return
+ * <code>CoderResult.UNDERFLOW</code>, and this method can be overridden
+ * if needed.
+ *
+ * @param out
+ * the output buffer
+ * @return <code>CoderResult.UNDERFLOW</code> or
+ * <code>CoderResult.OVERFLOW</code>
+ */
+ protected CoderResult implFlush(CharBuffer out) {
+ return CoderResult.UNDERFLOW;
+ }
+
+ /**
+ * Notify that this decoder's <code>CodingErrorAction</code> specified for
+ * malformed input error has been changed. Default implementation does
+ * nothing, and this method can be overridden if needed.
+ *
+ * @param newAction
+ * The new action
+ */
+ protected void implOnMalformedInput(CodingErrorAction newAction) {
+ // default implementation is empty
+ }
+
+ /**
+ * Notify that this decoder's <code>CodingErrorAction</code> specified for
+ * unmappable character error has been changed. Default implementation does
+ * nothing, and this method can be overridden if needed.
+ *
+ * @param newAction
+ * The new action
+ */
+ protected void implOnUnmappableCharacter(CodingErrorAction newAction) {
+ // default implementation is empty
+ }
+
+ /**
+ * Notify that this decoder's replacement has been changed. Default
+ * implementation does nothing, and this method can be overridden if needed.
+ *
+ * @param newReplacement
+ * the new replacement string
+ */
+ protected void implReplaceWith(String newReplacement) {
+ // default implementation is empty
+ }
+
+ /**
+ * Reset this decoder's charset related state. Default implementation does
+ * nothing, and this method can be overridden if needed.
+ */
+ protected void implReset() {
+ // default implementation is empty
+ }
+
+ /**
+ * Get if this decoder implements an auto-detecting charset.
+ *
+ * @return <code>true</code> if this decoder implements an auto-detecting
+ * charset
+ */
+ public boolean isAutoDetecting() {
+ return false;
+ }
+
+ /**
+ * Get if this decoder has detected a charset, this method is optional.
+ * <p>
+ * If this decoder implements an auto-detecting charset, then this method
+ * may start to return true during decoding operation to indicate that a
+ * charset has been detected in the input bytes and that the charset can be
+ * retrieved by invoking {@link #detectedCharset() detectedCharset} method.
+ * </p>
+ * <p>
+ * Note that a decoder that implements an auto-detecting charset may still
+ * succeed in decoding a portion of the given input even when it is unable
+ * to detect the charset. For this reason users should be aware that a
+ * <code>false</code> return value does not indicate that no decoding took
+ * place.
+ * </p>
+ * <p>
+ * The default implementation always throws an
+ * <code>UnsupportedOperationException</code>; it should be overridden by
+ * subclass if needed.
+ * </p>
+ *
+ * @return <code>true</code> this decoder has detected a charset
+ * @throws UnsupportedOperationException
+ * if this decoder doesn't implement an auto-detecting charset
+ */
+ public boolean isCharsetDetected() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Gets this decoder's <code>CodingErrorAction</code> when malformed input
+ * occurred during decoding process.
+ *
+ * @return this decoder's <code>CodingErrorAction</code> when malformed
+ * input occurred during decoding process.
+ */
+ public CodingErrorAction malformedInputAction() {
+ return malformAction;
+ }
+
+ /**
+ * Get the maximum number of characters which can be created by this decoder
+ * for one input byte, must be positive
+ *
+ * @return the maximum number of characters which can be created by this
+ * decoder for one input byte, must be positive
+ */
+ public final float maxCharsPerByte() {
+ return maxChars;
+ }
+
+ /**
+ * Set this decoder's action on malformed input error.
+ *
+ * This method will call the
+ * {@link #implOnMalformedInput(CodingErrorAction) implOnMalformedInput}
+ * method with the given new action as argument.
+ *
+ * @param newAction
+ * the new action on malformed input error
+ * @return this decoder
+ * @throws IllegalArgumentException
+ * if the given newAction is null
+ */
+ public final CharsetDecoder onMalformedInput(CodingErrorAction newAction) {
+ if (null == newAction) {
+ throw new IllegalArgumentException();
+ }
+ malformAction = newAction;
+ implOnMalformedInput(newAction);
+ return this;
+ }
+
+ /**
+ * Set this decoder's action on unmappable character error.
+ *
+ * This method will call the
+ * {@link #implOnUnmappableCharacter(CodingErrorAction) implOnUnmappableCharacter}
+ * method with the given new action as argument.
+ *
+ * @param newAction
+ * the new action on unmappable character error
+ * @return this decoder
+ * @throws IllegalArgumentException
+ * if the given newAction is null
+ */
+ public final CharsetDecoder onUnmappableCharacter(
+ CodingErrorAction newAction) {
+ if (null == newAction) {
+ throw new IllegalArgumentException();
+ }
+ unmapAction = newAction;
+ implOnUnmappableCharacter(newAction);
+ return this;
+ }
+
+ /**
+ * Get the replacement string, which is never null or empty
+ *
+ * @return the replacement string, cannot be null or empty
+ */
+ public final String replacement() {
+ return replace;
+ }
+
+ /**
+ * Set new replacement value.
+ *
+ * This method first checks the given replacement's validity, then changes
+ * the replacement value, and at last calls
+ * {@link #implReplaceWith(String) implReplaceWith} method with the given
+ * new replacement as argument.
+ *
+ * @param newReplacement
+ * the replacement string, cannot be null or empty
+ * @return this decoder
+ * @throws IllegalArgumentException
+ * if the given replacement cannot satisfy the requirement
+ * mentioned above
+ */
+ public final CharsetDecoder replaceWith(String newReplacement) {
+ if (null == newReplacement || newReplacement.length() == 0) {
+ // niochar.06=Replacement string cannot be null or empty.
+ throw new IllegalArgumentException(Messages.getString("niochar.06")); //$NON-NLS-1$
+ }
+ if (newReplacement.length() > maxChars) {
+ // niochar.07=Replacement string's length cannot be larger than max
+ // characters per byte.
+ throw new IllegalArgumentException(Messages.getString("niochar.07")); //$NON-NLS-1$
+ }
+ replace = newReplacement;
+ implReplaceWith(newReplacement);
+ return this;
+ }
+
+ /**
+ * Reset this decoder. This method will reset internal status, and then call
+ * <code>implReset()</code> to reset any status related to specific
+ * charset.
+ *
+ * @return this decoder
+ */
+ public final CharsetDecoder reset() {
+ status = INIT;
+ implReset();
+ return this;
+ }
+
+ /**
+ * Gets this decoder's <code>CodingErrorAction</code> when unmappable
+ * character occurred during decoding process.
+ *
+ * @return this decoder's <code>CodingErrorAction</code> when unmappable
+ * character occurred during decoding process.
+ */
+ public CodingErrorAction unmappableCharacterAction() {
+ return unmapAction;
+ }
+}
diff --git a/nio_char/src/main/java/java/nio/charset/CharsetEncoder.java b/nio_char/src/main/java/java/nio/charset/CharsetEncoder.java
new file mode 100644
index 0000000..0cb3fdc
--- /dev/null
+++ b/nio_char/src/main/java/java/nio/charset/CharsetEncoder.java
@@ -0,0 +1,811 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.charset;
+
+import java.nio.BufferOverflowException;
+import java.nio.BufferUnderflowException;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+
+import org.apache.harmony.niochar.internal.nls.Messages;
+
+/**
+ * An converter that can convert 16-bit Unicode character sequence to byte
+ * sequence in some charset .
+ * <p>
+ * The input character sequence is wrapped by
+ * {@link java.nio.CharBuffer CharBuffer} and the output character sequence is
+ * {@link java.nio.ByteBuffer ByteBuffer}. A encoder instance should be used in
+ * following sequence, which is referred to as a encoding operation:
+ * <ol>
+ * <li>Invoking the {@link #reset() reset} method to reset the encoder if the
+ * encoder has been used;</li>
+ * <li>Invoking the {@link #encode(CharBuffer, ByteBuffer, boolean) encode}
+ * method until the additional input is not needed, the <code>endOfInput</code>
+ * parameter must be set to false, the input buffer must be filled and the
+ * output buffer must be flushed between invocations;</li>
+ * <li>Invoking the {@link #encode(CharBuffer, ByteBuffer, boolean) encode}
+ * method last time, and the the <code>endOfInput</code> parameter must be set
+ * to true</li>
+ * <li>Invoking the {@link #flush(ByteBuffer) flush} method to flush the
+ * output.</li>
+ * </ol>
+ * </p>
+ * <p>
+ * The {@link #encode(CharBuffer, ByteBuffer, boolean) encode} method will
+ * convert as many characters as possible, and the process won't stop except the
+ * input characters has been run out of, the output buffer has been filled or
+ * some error has happened. A {@link CoderResult CoderResult} instance will be
+ * returned to indicate the stop reason, and the invoker can identify the result
+ * and choose further action, which can include filling the input buffer,
+ * flushing the output buffer, recovering from error and trying again.
+ * </p>
+ * <p>
+ * There are two common encoding errors. One is named as malformed and it is
+ * returned when the input content is illegal 16-bit Unicode character sequence,
+ * the other is named as unmappable character and occurs when there is a problem
+ * mapping the input to a valid byte sequence in the specific charset.
+ * </p>
+ * <p>
+ * The two errors can be handled in three ways, the default one is to report the
+ * error to the invoker by a {@link CoderResult CoderResult} instance, and the
+ * alternatives are to ignore it or to replace the erroneous input with the
+ * replacement byte array. The replacement byte array is {(byte)'?'} by default
+ * and can be changed by invoking {@link #replaceWith(byte[]) replaceWith}
+ * method. The invoker of this encoder can choose one way by specifying a
+ * {@link CodingErrorAction CodingErrorAction} instance for each error type via
+ * {@link #onMalformedInput(CodingErrorAction) onMalformedInput} method and
+ * {@link #onUnmappableCharacter(CodingErrorAction) onUnmappableCharacter}
+ * method.
+ * </p>
+ * <p>
+ * This class is abstract class and encapsulate many common operations of
+ * encoding process for all charsets. encoder for specific charset should extend
+ * this class and need only implement
+ * {@link #encodeLoop(CharBuffer, ByteBuffer) encodeLoop} method for basic
+ * encoding loop. If a subclass maintains internal state, it should override the
+ * {@link #implFlush(ByteBuffer) implFlush} method and
+ * {@link #implReset() implReset} method in addition.
+ * </p>
+ * <p>
+ * This class is not thread-safe.
+ * </p>
+ *
+ * @see java.nio.charset.Charset
+ * @see java.nio.charset.CharsetDecoder
+ */
+public abstract class CharsetEncoder {
+ /*
+ * --------------------------------------- Consts
+ * ---------------------------------------
+ */
+ /*
+ * internal status consts
+ */
+ private static final int INIT = 0;
+
+ private static final int ONGOING = 1;
+
+ private static final int END = 2;
+
+ private static final int FLUSH = 3;
+
+ /*
+ * --------------------------------------- Instance variables
+ * ---------------------------------------
+ */
+ // the Charset which creates this encoder
+ private Charset cs;
+
+ // average bytes per character created by this encoder
+ private float averBytes;
+
+ // maximum bytes per character can be created by this encoder
+ private float maxBytes;
+
+ // replacement byte array
+ private byte[] replace;
+
+ // internal status
+ private int status;
+
+ // action for malformed input
+ private CodingErrorAction malformAction;
+
+ // action for unmapped char input
+ private CodingErrorAction unmapAction;
+
+ // decoder instance for this encoder's charset, used for replacement value
+ // checking
+ private CharsetDecoder decoder;
+
+ /*
+ * --------------------------------------- Constructors
+ * ---------------------------------------
+ */
+
+ /**
+ * Construct a new <code>CharsetEncoder</code> using given
+ * <code>Charset</code>, average number and maximum number of bytes
+ * created by this encoder for one input character.
+ *
+ * @param cs
+ * this encoder's <code>Charset</code>, which create this
+ * encoder
+ * @param averageBytesPerChar
+ * average number of bytes created by this encoder for one input
+ * character, must be positive
+ * @param maxBytesPerChar
+ * maximum number of bytes which can be created by this encoder
+ * for one input character, must be positive
+ * @throws IllegalArgumentException
+ * if <code>maxBytesPerChar</code> or
+ * <code>averageBytePerChar</code> is negative
+ */
+ protected CharsetEncoder(Charset cs, float averageBytesPerChar,
+ float maxBytesPerChar) {
+ this(cs, averageBytesPerChar, maxBytesPerChar,
+ new byte[] { (byte) '?' });
+ }
+
+ /**
+ * Construct a new <code>CharsetEncoder</code> using given
+ * <code>Charset</code>, replace byte array, average number and maximum
+ * number of bytes created by this encoder for one input character.
+ *
+ * @param cs
+ * the this encoder's <code>Charset</code>, which create this
+ * encoder
+ * @param averageBytesPerChar
+ * average number of bytes created by this encoder for single
+ * input character, must be positive
+ * @param maxBytesPerChar
+ * maximum number of bytes which can be created by this encoder
+ * for single input character, must be positive
+ * @param replacement
+ * the replacement byte array, cannot be null or empty, its
+ * length cannot larger than <code>maxBytesPerChar</code>, and
+ * must be legal replacement, which can be justified by
+ * {@link #isLegalReplacement(byte[]) isLegalReplacement}
+ * @throws IllegalArgumentException
+ * if any parameters are invalid
+ */
+ protected CharsetEncoder(Charset cs, float averageBytesPerChar,
+ float maxBytesPerChar, byte[] replacement) {
+ if (averageBytesPerChar <= 0 || maxBytesPerChar <= 0) {
+ // niochar.02=Bytes number for one character must be positive.
+ throw new IllegalArgumentException(Messages.getString("niochar.02")); //$NON-NLS-1$
+ }
+ if (averageBytesPerChar > maxBytesPerChar) {
+ // niochar.03=averageBytesPerChar is greater than maxBytesPerChar.
+ throw new IllegalArgumentException(Messages.getString("niochar.03")); //$NON-NLS-1$
+ }
+ this.cs = cs;
+ averBytes = averageBytesPerChar;
+ maxBytes = maxBytesPerChar;
+ status = INIT;
+ malformAction = CodingErrorAction.REPORT;
+ unmapAction = CodingErrorAction.REPORT;
+ replaceWith(replacement);
+ }
+
+ /*
+ * --------------------------------------- Methods
+ * ---------------------------------------
+ */
+ /**
+ * get the average number of bytes created by this encoder for single input
+ * character
+ *
+ * @return the average number of bytes created by this encoder for single
+ * input character
+ */
+ public final float averageBytesPerChar() {
+ return averBytes;
+ }
+
+ /**
+ * Check if given character can be encoded by this encoder.
+ *
+ * Note that this method can change the internal status of this encoder, so
+ * it should not be called when another encode process is ongoing, otherwise
+ * it will throw <code>IllegalStateException</code>.
+ *
+ * This method can be overridden for performance improvement.
+ *
+ * @param c
+ * the given encoder
+ * @return true if given character can be encoded by this encoder
+ * @throws IllegalStateException
+ * if another encode process is ongoing so that current internal
+ * status is neither RESET or FLUSH
+ */
+ public boolean canEncode(char c) {
+ return implCanEncode(CharBuffer.wrap(new char[] { c }));
+ }
+
+ // implementation of canEncode
+ private boolean implCanEncode(CharBuffer cb) {
+ if (status == FLUSH) {
+ status = INIT;
+ }
+ if (status != INIT) {
+ // niochar.0B=Another encoding process is ongoing\!
+ throw new IllegalStateException(Messages.getString("niochar.0B")); //$NON-NLS-1$
+ }
+ CodingErrorAction malformBak = malformAction;
+ CodingErrorAction unmapBak = unmapAction;
+ onMalformedInput(CodingErrorAction.REPORT);
+ onUnmappableCharacter(CodingErrorAction.REPORT);
+ boolean result = true;
+ try {
+ this.encode(cb);
+ } catch (CharacterCodingException e) {
+ result = false;
+ }
+ onMalformedInput(malformBak);
+ onUnmappableCharacter(unmapBak);
+ reset();
+ return result;
+ }
+
+ /**
+ * Check if given <code>CharSequence</code> can be encoded by this
+ * encoder.
+ *
+ * Note that this method can change the internal status of this encoder, so
+ * it should not be called when another encode process is ongoing, otherwise
+ * it will throw <code>IllegalStateException</code>.
+ *
+ * This method can be overridden for performance improvement.
+ *
+ * @param sequence
+ * the given <code>CharSequence</code>
+ * @return true if given <code>CharSequence</code> can be encoded by this
+ * encoder
+ * @throws IllegalStateException
+ * if current internal status is neither RESET or FLUSH
+ */
+ public boolean canEncode(CharSequence sequence) {
+ CharBuffer cb;
+ if (sequence instanceof CharBuffer) {
+ cb = ((CharBuffer) sequence).duplicate();
+ } else {
+ cb = CharBuffer.wrap(sequence);
+ }
+ return implCanEncode(cb);
+ }
+
+ /**
+ * Get the <code>Charset</code> which creates this encoder.
+ *
+ * @return the <code>Charset</code> which creates this encoder
+ */
+ public final Charset charset() {
+ return cs;
+ }
+
+ /**
+ * This is a facade method for encoding operation.
+ * <p>
+ * This method encodes the remaining character sequence of the given
+ * character buffer into a new byte buffer. This method performs a complete
+ * encoding operation, resets at first, then encodes, and flushes at last.
+ * </p>
+ * <p>
+ * This method should not be invoked if another encode operation is ongoing.
+ * </p>
+ *
+ * @param in
+ * the input buffer
+ * @return a new <code>ByteBuffer</code> containing the the bytes produced
+ * by this encoding operation. The buffer's limit will be the
+ * position of last byte in buffer, and the position will be zero
+ * @throws IllegalStateException
+ * if another encoding operation is ongoing
+ * @throws MalformedInputException
+ * if illegal input character sequence for this charset
+ * encountered, and the action for malformed error is
+ * {@link CodingErrorAction#REPORT CodingErrorAction.REPORT}
+ * @throws UnmappableCharacterException
+ * if legal but unmappable input character sequence for this
+ * charset encountered, and the action for unmappable character
+ * error is
+ * {@link CodingErrorAction#REPORT CodingErrorAction.REPORT}.
+ * Unmappable means the Unicode character sequence at the input
+ * buffer's current position cannot be mapped to a equivalent
+ * byte sequence.
+ * @throws CharacterCodingException
+ * if other exception happened during the encode operation
+ */
+ public final ByteBuffer encode(CharBuffer in)
+ throws CharacterCodingException {
+ if (in.remaining() == 0) {
+ return ByteBuffer.allocate(0);
+ }
+ reset();
+ int length = (int) (in.remaining() * averBytes);
+ ByteBuffer output = ByteBuffer.allocate(length);
+ CoderResult result = null;
+ while (true) {
+ result = encode(in, output, false);
+ checkCoderResult(result);
+ if (result.isUnderflow()) {
+ break;
+ } else if (result.isOverflow()) {
+ output = allocateMore(output);
+ }
+ }
+ result = encode(in, output, true);
+ checkCoderResult(result);
+
+ while (true) {
+ result = flush(output);
+ checkCoderResult(result);
+ if (result.isOverflow()) {
+ output = allocateMore(output);
+ } else {
+ break;
+ }
+ }
+
+ output.flip();
+ if (result.isMalformed()) {
+ throw new MalformedInputException(result.length());
+ } else if (result.isUnmappable()) {
+ throw new UnmappableCharacterException(result.length());
+ }
+ status = FLUSH;
+ return output;
+ }
+
+ /*
+ * checks the result whether it needs to throw CharacterCodingException.
+ */
+ private void checkCoderResult(CoderResult result)
+ throws CharacterCodingException {
+ if (result.isMalformed() && malformAction == CodingErrorAction.REPORT) {
+ throw new MalformedInputException(result.length());
+ } else if (result.isUnmappable()
+ && unmapAction == CodingErrorAction.REPORT) {
+ throw new UnmappableCharacterException(result.length());
+ }
+ }
+
+ // allocate more spaces to the given ByteBuffer
+ private ByteBuffer allocateMore(ByteBuffer output) {
+ if (output.capacity() == 0) {
+ return ByteBuffer.allocate(1);
+ }
+ ByteBuffer result = ByteBuffer.allocate(output.capacity() * 2);
+ output.flip();
+ result.put(output);
+ return result;
+ }
+
+ /**
+ * Encodes characters starting at the current position of the given input
+ * buffer, and writes the equivalent byte sequence into the given output
+ * buffer from its current position.
+ * <p>
+ * The buffers' position will be changed with the reading and writing
+ * operation, but their limits and marks will be kept intact.
+ * </p>
+ * <p>
+ * A <code>CoderResult</code> instance will be returned according to
+ * following rules:
+ * <ul>
+ * <li>A {@link CoderResult#malformedForLength(int) malformed input} result
+ * indicates that some malformed input error encountered, and the erroneous
+ * characters start at the input buffer's position and their number can be
+ * got by result's {@link CoderResult#length() length}. This kind of result
+ * can be returned only if the malformed action is
+ * {@link CodingErrorAction#REPORT CodingErrorAction.REPORT}. </li>
+ * <li>{@link CoderResult#UNDERFLOW CoderResult.UNDERFLOW} indicates that
+ * as many characters as possible in the input buffer has been encoded. If
+ * there is no further input and no characters left in the input buffer then
+ * this task is complete. If this is not the case then the client should
+ * call this method again supplying some more input characters.</li>
+ * <li>{@link CoderResult#OVERFLOW CoderResult.OVERFLOW} indicates that the
+ * output buffer has been filled, while there are still some characters
+ * remaining in the input buffer. This method should be invoked again with a
+ * non-full output buffer </li>
+ * <li>A {@link CoderResult#unmappableForLength(int) unmappable character}
+ * result indicates that some unmappable character error was encountered,
+ * and the erroneous characters start at the input buffer's position and
+ * their number can be got by result's {@link CoderResult#length() length}.
+ * This kind of result can be returned only on
+ * {@link CodingErrorAction#REPORT CodingErrorAction.REPORT}. </li>
+ * </ul>
+ * </p>
+ * <p>
+ * The <code>endOfInput</code> parameter indicates that if the invoker can
+ * provider further input. This parameter is true if and only if the
+ * characters in current input buffer are all inputs for this encoding
+ * operation. Note that it is common and won't cause error that the invoker
+ * sets false and then finds no more input available; while it may cause
+ * error that the invoker always sets true in several consecutive
+ * invocations so that any remaining input will be treated as malformed
+ * input.
+ * </p>
+ * <p>
+ * This method invokes
+ * {@link #encodeLoop(CharBuffer, ByteBuffer) encodeLoop} method to
+ * implement basic encode logic for specific charset.
+ * </p>
+ *
+ * @param in
+ * the input buffer
+ * @param out
+ * the output buffer
+ * @param endOfInput
+ * true if all the input characters have been provided
+ * @return a <code>CoderResult</code> instance indicating the result
+ * @throws IllegalStateException
+ * if the encoding operation has already started or no more
+ * input needed in this encoding progress.
+ * @throws CoderMalfunctionError
+ * If the {@link #encodeLoop(CharBuffer, ByteBuffer) encodeLoop}
+ * method threw an <code>BufferUnderflowException</code> or
+ * <code>BufferUnderflowException</code>
+ */
+ public final CoderResult encode(CharBuffer in, ByteBuffer out,
+ boolean endOfInput) {
+ if ((status == FLUSH) || (!endOfInput && status == END)) {
+ throw new IllegalStateException();
+ }
+
+ CoderResult result;
+ while (true) {
+ try {
+ result = encodeLoop(in, out);
+ } catch (BufferOverflowException e) {
+ throw new CoderMalfunctionError(e);
+ } catch (BufferUnderflowException e) {
+ throw new CoderMalfunctionError(e);
+ }
+ if (result.isUnderflow()) {
+ int remaining = in.remaining();
+ status = endOfInput ? END : ONGOING;
+ if (endOfInput && remaining > 0) {
+ result = CoderResult.malformedForLength(remaining);
+ } else {
+ return result;
+ }
+ }
+ if (result.isOverflow()) {
+ status = endOfInput ? END : ONGOING;
+ return result;
+ }
+ CodingErrorAction action = malformAction;
+ if (result.isUnmappable()) {
+ action = unmapAction;
+ }
+ // If the action is IGNORE or REPLACE, we should continue
+ // encoding.
+ if (action == CodingErrorAction.REPLACE) {
+ if (out.remaining() < replace.length) {
+ return CoderResult.OVERFLOW;
+ }
+ out.put(replace);
+ } else {
+ if (action != CodingErrorAction.IGNORE) {
+ return result;
+ }
+ }
+ in.position(in.position() + result.length());
+ }
+ }
+
+ /**
+ * Encode characters into bytes. This method is called by
+ * {@link #encode(CharBuffer, ByteBuffer, boolean) encode}.
+ *
+ * This method will implement the essential encoding operation, and it won't
+ * stop encoding until either all the input characters are read, the output
+ * buffer is filled, or some exception encountered. And then it will return
+ * a <code>CoderResult</code> object indicating the result of current
+ * encoding operation. The rules to construct the <code>CoderResult</code>
+ * is same as the {@link #encode(CharBuffer, ByteBuffer, boolean) encode}.
+ * When exception encountered in the encoding operation, most implementation
+ * of this method will return a relevant result object to
+ * {@link #encode(CharBuffer, ByteBuffer, boolean) encode} method, and some
+ * performance optimized implementation may handle the exception and
+ * implement the error action itself.
+ *
+ * The buffers are scanned from their current positions, and their positions
+ * will be modified accordingly, while their marks and limits will be
+ * intact. At most {@link CharBuffer#remaining() in.remaining()} characters
+ * will be read, and {@link ByteBuffer#remaining() out.remaining()} bytes
+ * will be written.
+ *
+ * Note that some implementation may pre-scan the input buffer and return
+ * <code>CoderResult.UNDERFLOW</code> until it receives sufficient input.
+ *
+ * @param in
+ * the input buffer
+ * @param out
+ * the output buffer
+ * @return a <code>CoderResult</code> instance indicating the result
+ */
+ protected abstract CoderResult encodeLoop(CharBuffer in, ByteBuffer out);
+
+ /**
+ * Flush this encoder.
+ *
+ * This method will call {@link #implFlush(ByteBuffer) implFlush}. Some
+ * encoders may need to write some bytes to the output buffer when they have
+ * read all input characters, subclasses can overridden
+ * {@link #implFlush(ByteBuffer) implFlush} to perform writing action.
+ *
+ * The maximum number of written bytes won't larger than
+ * {@link ByteBuffer#remaining() out.remaining()}. If some encoder want to
+ * write more bytes than output buffer's remaining spaces, then
+ * <code>CoderResult.OVERFLOW</code> will be returned, and this method
+ * must be called again with a byte buffer has more spaces. Otherwise this
+ * method will return <code>CoderResult.UNDERFLOW</code>, which means one
+ * encoding process has been completed successfully.
+ *
+ * During the flush, the output buffer's position will be changed
+ * accordingly, while its mark and limit will be intact.
+ *
+ * @param out
+ * the given output buffer
+ * @return <code>CoderResult.UNDERFLOW</code> or
+ * <code>CoderResult.OVERFLOW</code>
+ * @throws IllegalStateException
+ * if this encoder hasn't read all input characters during one
+ * encoding process, which means neither after calling
+ * {@link #encode(CharBuffer) encode(CharBuffer)} nor after
+ * calling {@link #encode(CharBuffer, ByteBuffer, boolean)
+ * encode(CharBuffer, ByteBuffer, boolean)} with true value for
+ * the last boolean parameter
+ */
+ public final CoderResult flush(ByteBuffer out) {
+ if (status != END && status != INIT) {
+ throw new IllegalStateException();
+ }
+ CoderResult result = implFlush(out);
+ if (result == CoderResult.UNDERFLOW) {
+ status = FLUSH;
+ }
+ return result;
+ }
+
+ /**
+ * Flush this encoder. Default implementation does nothing and always return
+ * <code>CoderResult.UNDERFLOW</code>, and this method can be overridden
+ * if needed.
+ *
+ * @param out
+ * the output buffer
+ * @return <code>CoderResult.UNDERFLOW</code> or
+ * <code>CoderResult.OVERFLOW</code>
+ */
+ protected CoderResult implFlush(ByteBuffer out) {
+ return CoderResult.UNDERFLOW;
+ }
+
+ /**
+ * Notify that this encoder's <code>CodingErrorAction</code> specified for
+ * malformed input error has been changed. Default implementation does
+ * nothing, and this method can be overridden if needed.
+ *
+ * @param newAction
+ * The new action
+ */
+ protected void implOnMalformedInput(CodingErrorAction newAction) {
+ // default implementation is empty
+ }
+
+ /**
+ * Notify that this encoder's <code>CodingErrorAction</code> specified for
+ * unmappable character error has been changed. Default implementation does
+ * nothing, and this method can be overridden if needed.
+ *
+ * @param newAction
+ * The new action
+ */
+ protected void implOnUnmappableCharacter(CodingErrorAction newAction) {
+ // default implementation is empty
+ }
+
+ /**
+ * Notify that this encoder's replacement has been changed. Default
+ * implementation does nothing, and this method can be overridden if needed.
+ *
+ * @param newReplacement
+ * the new replacement string
+ */
+ protected void implReplaceWith(byte[] newReplacement) {
+ // default implementation is empty
+ }
+
+ /**
+ * Reset this encoder's charset related state. Default implementation does
+ * nothing, and this method can be overridden if needed.
+ */
+ protected void implReset() {
+ // default implementation is empty
+ }
+
+ /**
+ * Check if the given argument is legal as this encoder's replacement byte
+ * array.
+ *
+ * The given byte array is legal if and only if it can be decode into
+ * sixteen bits Unicode characters.
+ *
+ * This method can be overridden for performance improvement.
+ *
+ * @param repl
+ * the given byte array to be checked
+ * @return true if the the given argument is legal as this encoder's
+ * replacement byte array.
+ */
+ public boolean isLegalReplacement(byte[] repl) {
+ if (decoder == null) {
+ decoder = cs.newDecoder();
+ }
+
+ CodingErrorAction malform = decoder.malformedInputAction();
+ CodingErrorAction unmap = decoder.unmappableCharacterAction();
+ decoder.onMalformedInput(CodingErrorAction.REPORT);
+ decoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+ ByteBuffer in = ByteBuffer.wrap(repl);
+ CharBuffer out = CharBuffer.allocate((int) (repl.length * decoder
+ .maxCharsPerByte()));
+ CoderResult result = decoder.decode(in, out, true);
+ decoder.onMalformedInput(malform);
+ decoder.onUnmappableCharacter(unmap);
+ return !result.isError();
+ }
+
+ /**
+ * Gets this encoder's <code>CodingErrorAction</code> when malformed input
+ * occurred during encoding process.
+ *
+ * @return this encoder's <code>CodingErrorAction</code> when malformed
+ * input occurred during encoding process.
+ */
+ public CodingErrorAction malformedInputAction() {
+ return malformAction;
+ }
+
+ /**
+ * Get the maximum number of bytes which can be created by this encoder for
+ * one input character, must be positive
+ *
+ * @return the maximum number of bytes which can be created by this encoder
+ * for one input character, must be positive
+ */
+ public final float maxBytesPerChar() {
+ return maxBytes;
+ }
+
+ /**
+ * Set this encoder's action on malformed input error.
+ *
+ * This method will call the
+ * {@link #implOnMalformedInput(CodingErrorAction) implOnMalformedInput}
+ * method with the given new action as argument.
+ *
+ * @param newAction
+ * the new action on malformed input error
+ * @return this encoder
+ * @throws IllegalArgumentException
+ * if the given newAction is null
+ */
+ public final CharsetEncoder onMalformedInput(CodingErrorAction newAction) {
+ if (null == newAction) {
+ // niochar.0C=Action on malformed input error cannot be null\!
+ throw new IllegalArgumentException(Messages.getString("niochar.0C")); //$NON-NLS-1$
+ }
+ malformAction = newAction;
+ implOnMalformedInput(newAction);
+ return this;
+ }
+
+ /**
+ * Set this encoder's action on unmappable character error.
+ *
+ * This method will call the
+ * {@link #implOnUnmappableCharacter(CodingErrorAction) implOnUnmappableCharacter}
+ * method with the given new action as argument.
+ *
+ * @param newAction
+ * the new action on unmappable character error
+ * @return this encoder
+ * @throws IllegalArgumentException
+ * if the given newAction is null
+ */
+ public final CharsetEncoder onUnmappableCharacter(
+ CodingErrorAction newAction) {
+ if (null == newAction) {
+ // niochar.0D=Action on unmappable character error cannot be null\!
+ throw new IllegalArgumentException(Messages.getString("niochar.0D")); //$NON-NLS-1$
+ }
+ unmapAction = newAction;
+ implOnUnmappableCharacter(newAction);
+ return this;
+ }
+
+ /**
+ * Get the replacement byte array, which is never null or empty, and it is
+ * legal
+ *
+ * @return the replacement byte array, cannot be null or empty, and it is
+ * legal
+ */
+ public final byte[] replacement() {
+ return replace;
+ }
+
+ /**
+ * Set new replacement value.
+ *
+ * This method first checks the given replacement's validity, then changes
+ * the replacement value, and at last calls
+ * {@link #implReplaceWith(byte[]) implReplaceWith} method with the given
+ * new replacement as argument.
+ *
+ * @param replacement
+ * the replacement byte array, cannot be null or empty, its
+ * length cannot larger than <code>maxBytesPerChar</code>, and
+ * must be legal replacement, which can be justified by
+ * <code>isLegalReplacement(byte[] repl)</code>
+ * @return this encoder
+ * @throws IllegalArgumentException
+ * if the given replacement cannot satisfy the requirement
+ * mentioned above
+ */
+ public final CharsetEncoder replaceWith(byte[] replacement) {
+ if (null == replacement || 0 == replacement.length
+ || maxBytes < replacement.length
+ || !isLegalReplacement(replacement)) {
+ // niochar.0E=Replacement is illegal
+ throw new IllegalArgumentException(Messages.getString("niochar.0E")); //$NON-NLS-1$
+ }
+ replace = replacement;
+ implReplaceWith(replacement);
+ return this;
+ }
+
+ /**
+ * Reset this encoder. This method will reset internal status, and then call
+ * <code>implReset()</code> to reset any status related to specific
+ * charset.
+ *
+ * @return this encoder
+ */
+ public final CharsetEncoder reset() {
+ status = INIT;
+ implReset();
+ return this;
+ }
+
+ /**
+ * Gets this encoder's <code>CodingErrorAction</code> when unmappable
+ * character occurred during encoding process.
+ *
+ * @return this encoder's <code>CodingErrorAction</code> when unmappable
+ * character occurred during encoding process.
+ */
+ public CodingErrorAction unmappableCharacterAction() {
+ return unmapAction;
+ }
+}
diff --git a/nio_char/src/main/java/java/nio/charset/CoderMalfunctionError.java b/nio_char/src/main/java/java/nio/charset/CoderMalfunctionError.java
new file mode 100644
index 0000000..c2400cb
--- /dev/null
+++ b/nio_char/src/main/java/java/nio/charset/CoderMalfunctionError.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.charset;
+
+/**
+ * Errors thrown when the encoder/decoder is malfunctioning.
+ */
+public class CoderMalfunctionError extends Error {
+
+ /*
+ * This constant is used during deserialization to check the J2SE version
+ * which created the serialized object.
+ */
+ private static final long serialVersionUID = -1151412348057794301L;
+
+ /**
+ * Constructs an instance of this error.
+ *
+ * @param ex
+ * the original exception thrown by the encoder/decoder
+ */
+ public CoderMalfunctionError(Exception ex) {
+ super(ex);
+ }
+}
diff --git a/nio_char/src/main/java/java/nio/charset/CoderResult.java b/nio_char/src/main/java/java/nio/charset/CoderResult.java
new file mode 100644
index 0000000..c222394
--- /dev/null
+++ b/nio_char/src/main/java/java/nio/charset/CoderResult.java
@@ -0,0 +1,297 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.charset;
+
+import java.nio.BufferOverflowException;
+import java.nio.BufferUnderflowException;
+import java.util.WeakHashMap;
+
+import org.apache.harmony.niochar.internal.nls.Messages;
+
+/**
+ * Used to indicate the result of encoding/decoding. There are four types of
+ * results:
+ * <ol>
+ * <li>UNDERFLOW indicates all input has been processed, or more input is
+ * required. It is represented by the unique object
+ * <code>CoderResult.UNDERFLOW</code>.
+ * <li>OVERFLOW indicates insufficient output buffer. It is represented by the
+ * unique object <code>CoderResult.OVERFLOW</code>.
+ * <li>A malformed-input error indicates an unrecognizable sequence of input
+ * units has been encountered. Get an instance of this type of result by calling
+ * <code>CoderResult.malformedForLength(int)</code> with the length of the
+ * malformed-input.
+ * <li>An unmappable-character error indicates a sequence of input units can
+ * not be mapped to the output charset. Get an instance of this type of result
+ * by calling <code>CoderResult.unmappableForLength(int)</code> with the input
+ * sequence size indicating the identity of the unmappable character.
+ * </ol>
+ *
+ */
+public class CoderResult {
+
+ // indicating underflow error type
+ private static final int TYPE_UNDERFLOW = 1;
+
+ // indicating overflow error type
+ private static final int TYPE_OVERFLOW = 2;
+
+ // indicating malformed-input error type
+ private static final int TYPE_MALFORMED_INPUT = 3;
+
+ // indicating unmappable character error type
+ private static final int TYPE_UNMAPPABLE_CHAR = 4;
+
+ /**
+ * Result object indicating that there is insufficient data in the
+ * encoding/decoding buffer or that additional data is required.
+ */
+ public static final CoderResult UNDERFLOW = new CoderResult(TYPE_UNDERFLOW,
+ 0);
+
+ /**
+ * Result object used to signify that the out buffer does not have enough
+ * space available in it to store the result of the encoding/decoding.
+ */
+ public static final CoderResult OVERFLOW = new CoderResult(TYPE_OVERFLOW, 0);
+
+ /*
+ * Stores unique result objects for each malformed-input error of a certain
+ * length
+ */
+ private static WeakHashMap<Integer, CoderResult> _malformedErrors = new WeakHashMap<Integer, CoderResult>();
+
+ /*
+ * Stores unique result objects for each unmappable-character error of a
+ * certain length
+ */
+ private static WeakHashMap<Integer, CoderResult> _unmappableErrors = new WeakHashMap<Integer, CoderResult>();
+
+ // the type this result
+ private final int type;
+
+ // the length of the erroneous input
+ private final int length;
+
+ /**
+ * Construct a <code>CoderResult</code> object with its text description.
+ *
+ * @param type
+ * the type of this result
+ * @param length
+ * the length of the erroneous input
+ */
+ private CoderResult(int type, int length) {
+ super();
+ this.type = type;
+ this.length = length;
+ }
+
+ /**
+ * Gets a <code>CoderResult</code> object indicating a malformed-input
+ * error.
+ *
+ * @param length
+ * the length of the malformed-input
+ * @return a <code>CoderResult</code> object indicating a malformed-input
+ * error
+ * @throws IllegalArgumentException
+ * If <code>length</code> is non-positive.
+ */
+ public static synchronized CoderResult malformedForLength(int length)
+ throws IllegalArgumentException {
+ if (length > 0) {
+ Integer key = Integer.valueOf(length);
+ synchronized (_malformedErrors) {
+ CoderResult r = _malformedErrors.get(key);
+ if (null == r) {
+ r = new CoderResult(TYPE_MALFORMED_INPUT, length);
+ _malformedErrors.put(key, r);
+ }
+ return r;
+ }
+ }
+ // niochar.08=The length must be positive: {0}.
+ throw new IllegalArgumentException(Messages.getString(
+ "niochar.08", length)); //$NON-NLS-1$
+ }
+
+ /**
+ * Gets a <code>CoderResult</code> object indicating an unmappable
+ * character error.
+ *
+ * @param length
+ * the length of the input unit sequence denoting the unmappable
+ * character
+ * @return a <code>CoderResult</code> object indicating an unmappable
+ * character error
+ * @throws IllegalArgumentException
+ * If <code>length</code> is non-positive.
+ */
+ public static synchronized CoderResult unmappableForLength(int length)
+ throws IllegalArgumentException {
+ if (length > 0) {
+ Integer key = Integer.valueOf(length);
+ synchronized (_unmappableErrors) {
+ CoderResult r = _unmappableErrors.get(key);
+ if (null == r) {
+ r = new CoderResult(TYPE_UNMAPPABLE_CHAR, length);
+ _unmappableErrors.put(key, r);
+ }
+ return r;
+ }
+ }
+ // niochar.08=The length must be positive: {0}.
+ throw new IllegalArgumentException(Messages.getString(
+ "niochar.08", length)); //$NON-NLS-1$
+ }
+
+ /**
+ * Returns true if this result is an underflow condition.
+ *
+ * @return true if an underflow, otherwise false
+ */
+ public boolean isUnderflow() {
+ return this.type == TYPE_UNDERFLOW;
+ }
+
+ /**
+ * Returns true if this result represents a malformed-input error or an
+ * unmappable-character error.
+ *
+ * @return true if a malformed-input error or an unmappable-character error,
+ * otherwise false
+ */
+ public boolean isError() {
+ return this.type == TYPE_MALFORMED_INPUT
+ || this.type == TYPE_UNMAPPABLE_CHAR;
+ }
+
+ /**
+ * Returns true if this result represents a malformed-input error.
+ *
+ * @return true if a malformed-input error, otherwise false
+ */
+ public boolean isMalformed() {
+ return this.type == TYPE_MALFORMED_INPUT;
+ }
+
+ /**
+ * Returns true if this result is an overflow condition.
+ *
+ * @return true if an overflow, otherwise false
+ */
+ public boolean isOverflow() {
+ return this.type == TYPE_OVERFLOW;
+ }
+
+ /**
+ * Returns true if this result represents an unmappable-character error.
+ *
+ * @return true if an unmappable-character error, otherwise false
+ */
+ public boolean isUnmappable() {
+ return this.type == TYPE_UNMAPPABLE_CHAR;
+ }
+
+ /**
+ * Gets the length of the erroneous input. The length is only meaningful to
+ * a malformed-input error or an unmappble character error.
+ *
+ * @return the length, as an integer, of this object's erroneous input
+ * @throws UnsupportedOperationException
+ * If this result is an overflow or underflow.
+ */
+ public int length() throws UnsupportedOperationException {
+ if (this.type == TYPE_MALFORMED_INPUT
+ || this.type == TYPE_UNMAPPABLE_CHAR) {
+ return this.length;
+ }
+ // niochar.09=The length of the erroneous input is only meaningful to
+ // a malformed-input error or an unmappble character error
+ throw new UnsupportedOperationException(Messages
+ .getString("niochar.09")); //$NON-NLS-1$
+ }
+
+ /**
+ * Throws an exception corresponding to this coder result.
+ *
+ * @throws BufferUnderflowException
+ * If an underflow.
+ * @throws BufferOverflowException
+ * If an overflow.
+ * @throws UnmappableCharacterException
+ * If an unmappable-character error.
+ * @throws MalformedInputException
+ * If a malformed-input error.
+ * @throws CharacterCodingException
+ * The default exception.
+ */
+ public void throwException() throws BufferUnderflowException,
+ BufferOverflowException, UnmappableCharacterException,
+ MalformedInputException, CharacterCodingException {
+ switch (this.type) {
+ case TYPE_UNDERFLOW:
+ throw new BufferUnderflowException();
+ case TYPE_OVERFLOW:
+ throw new BufferOverflowException();
+ case TYPE_UNMAPPABLE_CHAR:
+ throw new UnmappableCharacterException(this.length);
+ case TYPE_MALFORMED_INPUT:
+ throw new MalformedInputException(this.length);
+ default:
+ throw new CharacterCodingException();
+ }
+ }
+
+ /*
+ * -------------------------------------------------------------------
+ * Methods overriding parent class Object
+ * -------------------------------------------------------------------
+ */
+
+ /**
+ * Returns a text description of this result.
+ *
+ * @return a text description of this result
+ */
+ public String toString() {
+ String dsc = null;
+ switch (this.type) {
+ case TYPE_UNDERFLOW:
+ dsc = "UNDERFLOW error"; //$NON-NLS-1$
+ break;
+ case TYPE_OVERFLOW:
+ dsc = "OVERFLOW error"; //$NON-NLS-1$
+ break;
+ case TYPE_UNMAPPABLE_CHAR:
+ dsc = "Unmappable-character error with erroneous input length " //$NON-NLS-1$
+ + this.length;
+ break;
+ case TYPE_MALFORMED_INPUT:
+ dsc = "Malformed-input error with erroneous input length " //$NON-NLS-1$
+ + this.length;
+ break;
+ default:
+ dsc = ""; //$NON-NLS-1$
+ break;
+ }
+ return "CoderResult[" + dsc + "]"; //$NON-NLS-1$ //$NON-NLS-2$
+
+ }
+
+}
diff --git a/nio_char/src/main/java/java/nio/charset/CodingErrorAction.java b/nio_char/src/main/java/java/nio/charset/CodingErrorAction.java
new file mode 100644
index 0000000..e258c71
--- /dev/null
+++ b/nio_char/src/main/java/java/nio/charset/CodingErrorAction.java
@@ -0,0 +1,64 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.charset;
+
+/**
+ * Used to indicate what kind of actions to take in case of encoding/decoding
+ * errors. Currently three actions are defined, namely, IGNORE, REPLACE and
+ * REPORT.
+ */
+public class CodingErrorAction {
+
+ /**
+ * Indicating the action to ignore any errors.
+ */
+ public static final CodingErrorAction IGNORE = new CodingErrorAction(
+ "IGNORE"); //$NON-NLS-1$
+
+ /**
+ * Indicating the action to fill in the output with a replacement character
+ * when malformed input or an unmappable character is encountered.
+ */
+ public static final CodingErrorAction REPLACE = new CodingErrorAction(
+ "REPLACE"); //$NON-NLS-1$
+
+ /**
+ * Indicating the action to report the encountered error in an appropriate
+ * manner, for example, throw an exception or return an informative result.
+ */
+ public static final CodingErrorAction REPORT = new CodingErrorAction(
+ "REPORT"); //$NON-NLS-1$
+
+ // The name of this action
+ private String action;
+
+ /*
+ * Can't instantiate outside.
+ */
+ private CodingErrorAction(String action) {
+ this.action = action;
+ }
+
+ /**
+ * Returns a text description of this action indication..
+ *
+ * @return a text description of this action indication.
+ */
+ public String toString() {
+ return "Action: " + this.action; //$NON-NLS-1$
+ }
+}
diff --git a/nio_char/src/main/java/java/nio/charset/IllegalCharsetNameException.java b/nio_char/src/main/java/java/nio/charset/IllegalCharsetNameException.java
new file mode 100644
index 0000000..fae1269
--- /dev/null
+++ b/nio_char/src/main/java/java/nio/charset/IllegalCharsetNameException.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.charset;
+
+import org.apache.harmony.niochar.internal.nls.Messages;
+
+/**
+ * Thrown when an illegal charset name is encountered.
+ */
+public class IllegalCharsetNameException extends IllegalArgumentException {
+
+ /*
+ * This constant is used during deserialization to check the J2SE version
+ * which created the serialized object.
+ */
+ private static final long serialVersionUID = 1457525358470002989L;
+
+ // The illegal charset name
+ private String charsetName;
+
+ /**
+ * Constructs an instance of this exception with the supplied charset name.
+ *
+ * @param charset
+ * the encountered illegal charset name
+ */
+ public IllegalCharsetNameException(String charset) {
+ // niochar.0F=The illegal charset name is "{0}".
+ super(Messages.getString("niochar.0F", charset)); //$NON-NLS-1$
+ this.charsetName = charset;
+ }
+
+ /**
+ * Gets the encountered illegal charset name.
+ *
+ * @return the encountered illegal charset name
+ */
+ public String getCharsetName() {
+ return this.charsetName;
+ }
+}
diff --git a/nio_char/src/main/java/java/nio/charset/MalformedInputException.java b/nio_char/src/main/java/java/nio/charset/MalformedInputException.java
new file mode 100644
index 0000000..17b0005
--- /dev/null
+++ b/nio_char/src/main/java/java/nio/charset/MalformedInputException.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.charset;
+
+import org.apache.harmony.niochar.internal.nls.Messages;
+
+/**
+ * Thrown when a malformed input is encountered, for example, a byte sequence is
+ * illegal for the given charset.
+ */
+public class MalformedInputException extends CharacterCodingException {
+
+ /*
+ * This constant is used during deserialization to check the J2SE version
+ * which created the serialized object.
+ */
+ private static final long serialVersionUID = -3438823399834806194L;
+
+ // the length of the malformed input
+ private int inputLength;
+
+ /**
+ * Constructs an instance of this exception.
+ *
+ * @param length
+ * the length of the malformed input
+ */
+ public MalformedInputException(int length) {
+ this.inputLength = length;
+ }
+
+ /**
+ * Gets the length of the malformed input.
+ *
+ * @return the length of the malformed input
+ */
+ public int getInputLength() {
+ return this.inputLength;
+ }
+
+ /**
+ * Gets a message describing this exception.
+ *
+ * @return a message describing this exception
+ */
+ public String getMessage() {
+ // niochar.05=Malformed input length is {0}.
+ return Messages.getString("niochar.05", this.inputLength); //$NON-NLS-1$
+ }
+}
diff --git a/nio_char/src/main/java/java/nio/charset/UnmappableCharacterException.java b/nio_char/src/main/java/java/nio/charset/UnmappableCharacterException.java
new file mode 100644
index 0000000..1c66c52
--- /dev/null
+++ b/nio_char/src/main/java/java/nio/charset/UnmappableCharacterException.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.charset;
+
+import org.apache.harmony.niochar.internal.nls.Messages;
+
+/**
+ * Thrown when an unmappable character for the given charset is encountered.
+ */
+public class UnmappableCharacterException extends CharacterCodingException {
+
+ /*
+ * This constant is used during deserialization to check the J2SE version
+ * which created the serialized object.
+ */
+ private static final long serialVersionUID = -7026962371537706123L;
+
+ // The length of the unmappable character
+ private int inputLength;
+
+ /**
+ * Constructs an instance of this exception.
+ *
+ * @param length
+ * the length of the unmappable character
+ */
+ public UnmappableCharacterException(int length) {
+ this.inputLength = length;
+ }
+
+ /**
+ * Gets the length of the unmappable character.
+ *
+ * @return the length of the unmappable character
+ */
+ public int getInputLength() {
+ return this.inputLength;
+ }
+
+ /**
+ * Gets a message describing this exception.
+ *
+ * @return a message describing this exception
+ */
+ public String getMessage() {
+ // niochar.0A=The unmappable character length is {0}.
+ return Messages.getString("niochar.0A", this.inputLength); //$NON-NLS-1$
+ }
+}
diff --git a/nio_char/src/main/java/java/nio/charset/UnsupportedCharsetException.java b/nio_char/src/main/java/java/nio/charset/UnsupportedCharsetException.java
new file mode 100644
index 0000000..1b55397
--- /dev/null
+++ b/nio_char/src/main/java/java/nio/charset/UnsupportedCharsetException.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.charset;
+
+import org.apache.harmony.niochar.internal.nls.Messages;
+
+/**
+ * Thrown when an unsupported charset name is encountered.
+ */
+public class UnsupportedCharsetException extends IllegalArgumentException {
+
+ /*
+ * This constant is used during deserialization to check the J2SE version
+ * which created the serialized object.
+ */
+ private static final long serialVersionUID = 1490765524727386367L;
+
+ // the unsupported charset name
+ private String charsetName;
+
+ /**
+ * Constructs an instance of this exception with the supplied charset name.
+ *
+ * @param charset
+ * the encountered unsupported charset name
+ */
+ public UnsupportedCharsetException(String charset) {
+ // niochar.04=The unsupported charset name is "{0}".
+ super(Messages.getString("niochar.04", charset)); //$NON-NLS-1$
+ this.charsetName = charset;
+ }
+
+ /**
+ * Gets the encountered unsupported charset name.
+ *
+ * @return the encountered unsupported charset name
+ */
+ public String getCharsetName() {
+ return this.charsetName;
+ }
+}
diff --git a/nio_char/src/main/java/java/nio/charset/package.html b/nio_char/src/main/java/java/nio/charset/package.html
new file mode 100644
index 0000000..104fd50
--- /dev/null
+++ b/nio_char/src/main/java/java/nio/charset/package.html
@@ -0,0 +1,14 @@
+<html>
+ <body>
+ <p>
+ This package allows translating between bytes and different
+ character sets.
+ </p>
+ <p>
+ An encoder translates characters into bytes and a decoder can
+ translate a byte stream into characters. With a charset you can create a
+ de-/encoder pair that can be used to translate a byte stream. With the
+ service provider package it is possible to use your own charsets.
+ </p>
+ </body>
+</html>
diff --git a/nio_char/src/main/java/java/nio/charset/spi/CharsetProvider.java b/nio_char/src/main/java/java/nio/charset/spi/CharsetProvider.java
new file mode 100644
index 0000000..8a470d7
--- /dev/null
+++ b/nio_char/src/main/java/java/nio/charset/spi/CharsetProvider.java
@@ -0,0 +1,61 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.charset.spi;
+
+import java.nio.charset.Charset;
+import java.util.Iterator;
+
+/**
+ * The service provider class for character sets.
+ */
+public abstract class CharsetProvider {
+
+ // The permission required to construct a new provider.
+ private static final RuntimePermission CONSTRUCT_PERM = new RuntimePermission(
+ "charsetProvider"); //$NON-NLS-1$
+
+ /**
+ * Constructor for subclassing with concrete types.
+ *
+ * @throws SecurityException
+ * if there is a security manager installed that does not permit
+ * the runtime permission labeled "charsetProvider".
+ */
+ protected CharsetProvider() {
+ SecurityManager securityManager = System.getSecurityManager();
+ if (securityManager != null)
+ securityManager.checkPermission(CONSTRUCT_PERM);
+ }
+
+ /**
+ * Returns an iterator over all the available charsets.
+ *
+ * @return the iterator.
+ */
+ public abstract Iterator<Charset> charsets();
+
+ /**
+ * Returns the named charset.
+ * <p>
+ * If the charset is unavailable the method returns <code>null</code>.
+ *
+ * @param charsetName
+ * the canonical or alias name of a character set.
+ * @return the charset, or <code>null</code> if unavailable.
+ */
+ public abstract Charset charsetForName(String charsetName);
+}
diff --git a/nio_char/src/main/java/java/nio/charset/spi/package.html b/nio_char/src/main/java/java/nio/charset/spi/package.html
new file mode 100644
index 0000000..a68c6d3
--- /dev/null
+++ b/nio_char/src/main/java/java/nio/charset/spi/package.html
@@ -0,0 +1,7 @@
+<html>
+ <body>
+ <p>
+ Service-provider classe for nio charset.
+ </p>
+ </body>
+</html>
diff --git a/nio_char/src/main/java/org/apache/harmony/niochar/internal/nls/Messages.java b/nio_char/src/main/java/org/apache/harmony/niochar/internal/nls/Messages.java
new file mode 100644
index 0000000..3368864
--- /dev/null
+++ b/nio_char/src/main/java/org/apache/harmony/niochar/internal/nls/Messages.java
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * THE FILE HAS BEEN AUTOGENERATED BY MSGTOOL TOOL.
+ * All changes made to this file manually will be overwritten
+ * if this tool runs again. Better make changes in the template file.
+ */
+
+package org.apache.harmony.niochar.internal.nls;
+
+import org.apache.harmony.luni.util.MsgHelp;
+
+/**
+ * This class retrieves strings from a resource bundle and returns them,
+ * formatting them with MessageFormat when required.
+ * <p>
+ * It is used by the system classes to provide national language support, by
+ * looking up messages in the <code>
+ * org.apache.harmony.niochar.internal.nls.messages
+ * </code>
+ * resource bundle. Note that if this file is not available, or an invalid key
+ * is looked up, or resource bundle support is not available, the key itself
+ * will be returned as the associated message. This means that the <em>KEY</em>
+ * should a reasonable human-readable (english) string.
+ *
+ */
+public class Messages {
+
+ private static final String sResource =
+ "org.apache.harmony.niochar.internal.nls.messages"; //$NON-NLS-1$
+
+ /**
+ * Retrieves a message which has no arguments.
+ *
+ * @param msg
+ * String the key to look up.
+ * @return String the message for that key in the system message bundle.
+ */
+ static public String getString(String msg) {
+ return MsgHelp.getString(sResource, msg);
+ }
+
+ /**
+ * Retrieves a message which takes 1 argument.
+ *
+ * @param msg
+ * String the key to look up.
+ * @param arg
+ * Object the object to insert in the formatted output.
+ * @return String the message for that key in the system message bundle.
+ */
+ static public String getString(String msg, Object arg) {
+ return getString(msg, new Object[] { arg });
+ }
+
+ /**
+ * Retrieves a message which takes 1 integer argument.
+ *
+ * @param msg
+ * String the key to look up.
+ * @param arg
+ * int the integer to insert in the formatted output.
+ * @return String the message for that key in the system message bundle.
+ */
+ static public String getString(String msg, int arg) {
+ return getString(msg, new Object[] { Integer.toString(arg) });
+ }
+
+ /**
+ * Retrieves a message which takes 1 character argument.
+ *
+ * @param msg
+ * String the key to look up.
+ * @param arg
+ * char the character to insert in the formatted output.
+ * @return String the message for that key in the system message bundle.
+ */
+ static public String getString(String msg, char arg) {
+ return getString(msg, new Object[] { String.valueOf(arg) });
+ }
+
+ /**
+ * Retrieves a message which takes 2 arguments.
+ *
+ * @param msg
+ * String the key to look up.
+ * @param arg1
+ * Object an object to insert in the formatted output.
+ * @param arg2
+ * Object another object to insert in the formatted output.
+ * @return String the message for that key in the system message bundle.
+ */
+ static public String getString(String msg, Object arg1, Object arg2) {
+ return getString(msg, new Object[] { arg1, arg2 });
+ }
+
+ /**
+ * Retrieves a message which takes several arguments.
+ *
+ * @param msg
+ * String the key to look up.
+ * @param args
+ * Object[] the objects to insert in the formatted output.
+ * @return String the message for that key in the system message bundle.
+ */
+ static public String getString(String msg, Object[] args) {
+ return MsgHelp.getString(sResource, msg, args);
+ }
+}
+
diff --git a/nio_char/src/main/java/org/apache/harmony/niochar/internal/nls/messages.properties b/nio_char/src/main/java/org/apache/harmony/niochar/internal/nls/messages.properties
new file mode 100644
index 0000000..6737e2b
--- /dev/null
+++ b/nio_char/src/main/java/org/apache/harmony/niochar/internal/nls/messages.properties
@@ -0,0 +1,32 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# messages for EN locale
+niochar.00=Characters number for one byte must be positive.
+niochar.01=averageCharsPerByte is greater than maxCharsPerByte
+niochar.02=Bytes number for one character must be positive.
+niochar.03=averageBytesPerChar is greater than maxBytesPerChar.
+niochar.04=The unsupported charset name is "{0}".
+niochar.05=Malformed input length is {0}.
+niochar.06=Replacement string cannot be null or empty.
+niochar.07=Replacement string's length cannot be larger than max characters per byte.
+niochar.08=The length must be positive: {0}.
+niochar.09=The length of the erroneous input is only meaningful to a malformed-input error or an unmappble character error
+niochar.0A=The unmappable character length is {0}.
+niochar.0B=Another encoding process is ongoing\!
+niochar.0C=Action on malformed input error cannot be null\!
+niochar.0D=Action on unmappable character error cannot be null\!
+niochar.0E=Replacement is illegal
+niochar.0F=The illegal charset name is "{0}".
diff --git a/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/ASCIICharsetEncoderTest.java b/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/ASCIICharsetEncoderTest.java
new file mode 100644
index 0000000..01385f2
--- /dev/null
+++ b/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/ASCIICharsetEncoderTest.java
@@ -0,0 +1,451 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio_char.tests.java.nio.charset;
+
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.MalformedInputException;
+import java.nio.charset.UnmappableCharacterException;
+
+import junit.framework.TestCase;
+
+public class ASCIICharsetEncoderTest extends TestCase {
+
+ // charset for ascii
+ private static final Charset cs = Charset.forName("ascii");
+ private static final CharsetEncoder encoder = cs.newEncoder();
+ private static final int MAXCODEPOINT = 0x7F;
+ /*
+ * @see CharsetEncoderTest#setUp()
+ */
+ protected void setUp() throws Exception {
+ }
+
+ /*
+ * @see CharsetEncoderTest#tearDown()
+ */
+ protected void tearDown() throws Exception {
+ }
+
+ public void testCanEncodeCharSequence() {
+ // normal case for ascCS
+ assertTrue(encoder.canEncode("\u0077"));
+ assertFalse(encoder.canEncode("\uc2a3"));
+ assertFalse(encoder.canEncode("\ud800\udc00"));
+ try {
+ encoder.canEncode(null);
+ } catch (NullPointerException e) {
+ }
+ assertTrue(encoder.canEncode(""));
+ }
+
+ public void testCanEncodeSurrogate () {
+ assertFalse(encoder.canEncode('\ud800'));
+ assertFalse(encoder.canEncode("\udc00"));
+ }
+
+ public void testCanEncodechar() throws CharacterCodingException {
+ assertTrue(encoder.canEncode('\u0077'));
+ assertFalse(encoder.canEncode('\uc2a3'));
+ }
+
+ public void testSpecificDefaultValue() {
+ assertEquals(1.0, encoder.averageBytesPerChar(), 0.0);
+ assertEquals(1.0, encoder.maxBytesPerChar(), 0.0);
+ }
+
+ public void testMultiStepEncode() throws CharacterCodingException {
+ encoder.onMalformedInput(CodingErrorAction.REPORT);
+ encoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+ try {
+ encoder.encode(CharBuffer.wrap("\ud800\udc00"));
+ fail("should unmappable");
+ } catch (UnmappableCharacterException e) {
+ }
+ encoder.reset();
+ ByteBuffer out = ByteBuffer.allocate(10);
+ assertTrue(encoder.encode(CharBuffer.wrap("\ud800"), out, true)
+ .isMalformed());
+ encoder.flush(out);
+ encoder.reset();
+ out = ByteBuffer.allocate(10);
+ assertSame(CoderResult.UNDERFLOW, encoder.encode(CharBuffer
+ .wrap("\ud800"), out, false));
+ assertTrue(encoder.encode(CharBuffer.wrap("\udc00"), out, true)
+ .isMalformed());
+ }
+
+ public void testEncodeMapping() throws CharacterCodingException {
+ encoder.reset();
+
+ for (int i =0; i <= MAXCODEPOINT; i++) {
+ char[] chars = Character.toChars(i);
+ CharBuffer cb = CharBuffer.wrap(chars);
+ ByteBuffer bb = encoder.encode(cb);
+ assertEquals(i, bb.get(0));
+ }
+
+ CharBuffer cb = CharBuffer.wrap("\u0080");
+ try {
+ encoder.encode(cb);
+ } catch (UnmappableCharacterException e) {
+ //expected
+ }
+
+ cb = CharBuffer.wrap("\ud800");
+ try {
+ encoder.encode(cb);
+ } catch (MalformedInputException e) {
+ //expected
+ }
+
+ ByteBuffer bb = ByteBuffer.allocate(0x10);
+ cb = CharBuffer.wrap("A");
+ encoder.reset();
+ encoder.encode(cb, bb, false);
+ try {
+ encoder.encode(cb);
+ } catch (IllegalStateException e) {
+ //expected
+ }
+ }
+
+ public void testInternalState() {
+ CharBuffer in = CharBuffer.wrap("A");
+ ByteBuffer out = ByteBuffer.allocate(0x10);
+
+ //normal encoding process
+ encoder.reset();
+ encoder.encode(in, out, false);
+ in = CharBuffer.wrap("B");
+ encoder.encode(in, out, true);
+ encoder.flush(out);
+ }
+
+ //reset could be called at any time
+ public void testInternalState_Reset() {
+ CharsetEncoder newEncoder = cs.newEncoder();
+ //Init - > reset
+ newEncoder.reset();
+
+ //reset - > reset
+ newEncoder.reset();
+
+ //encoding - >reset
+ {
+ CharBuffer in = CharBuffer.wrap("A");
+ ByteBuffer out = ByteBuffer.allocate(0x10);
+ newEncoder.encode(in, out, false);
+ newEncoder.reset();
+ }
+
+ //encoding end -> reset
+ {
+ CharBuffer in = CharBuffer.wrap("A");
+ ByteBuffer out = ByteBuffer.allocate(0x10);
+ newEncoder.encode(in, out, true);
+ newEncoder.reset();
+ }
+ //flused -> reset
+ {
+ CharBuffer in = CharBuffer.wrap("A");
+ ByteBuffer out = ByteBuffer.allocate(0x10);
+ newEncoder.encode(in, out, true);
+ newEncoder.flush(out);
+ newEncoder.reset();
+ }
+ }
+
+ public void testInternalState_Encoding() {
+ CharsetEncoder newEncoder = cs.newEncoder();
+ //Init - > encoding
+ {
+ CharBuffer in = CharBuffer.wrap("A");
+ ByteBuffer out = ByteBuffer.allocate(0x10);
+ newEncoder.encode(in, out, false);
+ }
+
+ //reset - > encoding
+ {
+ CharBuffer in = CharBuffer.wrap("A");
+ ByteBuffer out = ByteBuffer.allocate(0x10);
+ newEncoder.reset();
+ newEncoder.encode(in, out, false);
+ }
+ //reset - > encoding - > encoding
+ {
+ newEncoder.reset();
+ CharBuffer in = CharBuffer.wrap("A");
+ ByteBuffer out = ByteBuffer.allocate(0x10);
+ newEncoder.encode(in, out, false);
+ in = CharBuffer.wrap("BC");
+ newEncoder.encode(in, out, false);
+ }
+
+ //encoding_end - > encoding
+ {
+ newEncoder.reset();
+ CharBuffer in = CharBuffer.wrap("A");
+ ByteBuffer out = ByteBuffer.allocate(0x10);
+ newEncoder.encode(in, out, true);
+ in = CharBuffer.wrap("BC");
+ try {
+ newEncoder.encode(in, out, false);
+ fail("Should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ //expected
+ }
+ }
+ //flushed - > encoding
+ {
+ newEncoder.reset();
+ CharBuffer in = CharBuffer.wrap("A");
+ ByteBuffer out = ByteBuffer.allocate(0x10);
+ newEncoder.encode(in, out, true);
+ newEncoder.flush(out);
+ in = CharBuffer.wrap("BC");
+ try {
+ newEncoder.encode(in, out, false);
+ fail("Should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ //expected
+ }
+ }
+ }
+
+ public void testInternalState_Encoding_END() {
+ CharsetEncoder newEncoder = cs.newEncoder();
+
+ //Init - >encoding_end
+ {
+ CharBuffer in = CharBuffer.wrap("A");
+ ByteBuffer out = ByteBuffer.allocate(0x10);
+ newEncoder.encode(in, out, true);
+ }
+
+ //Reset -> encoding_end
+ {
+ CharBuffer in = CharBuffer.wrap("A");
+ ByteBuffer out = ByteBuffer.allocate(0x10);
+ newEncoder.reset();
+ newEncoder.encode(in, out, true);
+ }
+
+ //encoding -> encoding_end
+ {
+ newEncoder.reset();
+ CharBuffer in = CharBuffer.wrap("A");
+ ByteBuffer out = ByteBuffer.allocate(0x10);
+ newEncoder.encode(in, out, false);
+ in = CharBuffer.wrap("BC");
+ newEncoder.encode(in, out, true);
+ }
+
+ //Reset -> encoding_end
+ {
+ newEncoder.reset();
+ CharBuffer in = CharBuffer.wrap("A");
+ ByteBuffer out = ByteBuffer.allocate(0x10);
+ newEncoder.encode(in, out, true);
+ in = CharBuffer.wrap("BC");
+ newEncoder.encode(in, out, true);
+ }
+
+ //Flushed -> encoding_end
+ {
+ newEncoder.reset();
+ CharBuffer in = CharBuffer.wrap("A");
+ ByteBuffer out = ByteBuffer.allocate(0x10);
+ newEncoder.encode(in, out, true);
+ newEncoder.flush(out);
+ in = CharBuffer.wrap("BC");
+ try {
+ newEncoder.encode(in, out, true);
+ fail("Should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ //expected
+ }
+ }
+ }
+
+ public void testInternalState_Flushed() {
+ CharsetEncoder newEncoder = cs.newEncoder();
+
+ //init -> flushed
+ {
+ ByteBuffer out = ByteBuffer.allocate(0x10);
+ newEncoder.flush(out);
+ }
+
+ //reset - > flushed
+ {
+ newEncoder.reset();
+ CharBuffer in = CharBuffer.wrap("A");
+ ByteBuffer out = ByteBuffer.allocate(0x10);
+ newEncoder.encode(in, out, true);
+ newEncoder.reset();
+ newEncoder.flush(out);
+ }
+
+ //encoding - > flushed
+ {
+ newEncoder.reset();
+ CharBuffer in = CharBuffer.wrap("A");
+ ByteBuffer out = ByteBuffer.allocate(0x10);
+ newEncoder.encode(in, out, false);
+ try {
+
+ newEncoder.flush(out);
+ fail("Should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ // expected
+ }
+ }
+
+ //encoding_end -> flushed
+ {
+ newEncoder.reset();
+ CharBuffer in = CharBuffer.wrap("A");
+ ByteBuffer out = ByteBuffer.allocate(0x10);
+ newEncoder.encode(in, out, true);
+ newEncoder.flush(out);
+ }
+
+ //flushd - > flushed
+ {
+ newEncoder.reset();
+ CharBuffer in = CharBuffer.wrap("A");
+ ByteBuffer out = ByteBuffer.allocate(0x10);
+ newEncoder.encode(in, out, true);
+ newEncoder.flush(out);
+ try {
+ newEncoder.flush(out);
+ fail("Should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ // expected
+ }
+ }
+ }
+
+ public void testInternalState_Encode() throws CharacterCodingException {
+ CharsetEncoder newEncoder = cs.newEncoder();
+ //Init - > encode
+ {
+ CharBuffer in = CharBuffer.wrap("A");
+ newEncoder.encode(in);
+ }
+
+ //Reset - > encode
+ {
+ newEncoder.reset();
+ CharBuffer in = CharBuffer.wrap("A");
+ newEncoder.encode(in);
+ }
+
+ //Encoding -> encode
+ {
+ newEncoder.reset();
+ CharBuffer in = CharBuffer.wrap("A");
+ ByteBuffer out = ByteBuffer.allocate(0x10);
+ newEncoder.encode(in, out, false);
+ in = CharBuffer.wrap("BC");
+ newEncoder.encode(in);
+ }
+
+ //Encoding_end -> encode
+ {
+ newEncoder.reset();
+ CharBuffer in = CharBuffer.wrap("A");
+ ByteBuffer out = ByteBuffer.allocate(0x10);
+ newEncoder.encode(in, out, true);
+ in = CharBuffer.wrap("BC");
+ newEncoder.encode(in);
+ }
+
+ //Flushed -> reset
+ {
+ newEncoder.reset();
+ CharBuffer in = CharBuffer.wrap("A");
+ ByteBuffer out = ByteBuffer.allocate(0x10);
+ newEncoder.encode(in, out, true);
+ in = CharBuffer.wrap("BC");
+ newEncoder.flush(out);
+ out = newEncoder.encode(in);
+ }
+ }
+
+ public void testInternalState_from_Encode() throws CharacterCodingException {
+ CharsetEncoder newEncoder = cs.newEncoder();
+
+ //Encode -> Reset
+ {
+ CharBuffer in = CharBuffer.wrap("A");
+ newEncoder.encode(in);
+ newEncoder.reset();
+ }
+
+ // Encode -> encoding
+ {
+ CharBuffer in = CharBuffer.wrap("A");
+ newEncoder.encode(in);
+ ByteBuffer out = ByteBuffer.allocate(0x10);
+ try {
+ newEncoder.encode(in, out, false);
+ fail("Should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ // expected
+ }
+ }
+
+ //Encode -> Encoding_end
+ {
+ CharBuffer in = CharBuffer.wrap("A");
+ newEncoder.encode(in);
+ ByteBuffer out = ByteBuffer.allocate(0x10);
+ try {
+ newEncoder.encode(in, out, true);
+ fail("Should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ // expected
+ }
+ }
+ //Encode -> Flushed
+ {
+ CharBuffer in = CharBuffer.wrap("A");
+ ByteBuffer out = newEncoder.encode(in);
+ try {
+ newEncoder.flush(out);
+ fail("Should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ // expected
+ }
+ }
+
+ //Encode - > encode
+ {
+ CharBuffer in = CharBuffer.wrap("A");
+ newEncoder.encode(in);
+ in = CharBuffer.wrap("BC");
+ newEncoder.encode(in);
+ }
+ }
+}
diff --git a/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/AllTests.java b/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/AllTests.java
new file mode 100644
index 0000000..8dd485c
--- /dev/null
+++ b/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/AllTests.java
@@ -0,0 +1,44 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio_char.tests.java.nio.charset;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AllTests {
+
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(AllTests.suite());
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(
+ "Test for org.apache.harmony.nio_char.tests.java.nio.charset");
+ //$JUnit-BEGIN$
+ suite.addTestSuite(CharacterCodingExceptionTest.class);
+ suite.addTestSuite(CharsetEncoderTest.class);
+ suite.addTestSuite(CharsetTest.class);
+ suite.addTestSuite(CharsetDecoderTest.class);
+ suite.addTestSuite(MalformedInputExceptionTest.class);
+ suite.addTestSuite(IllegalCharsetNameExceptionTest.class);
+ suite.addTestSuite(UnmappableCharacterExceptionTest.class);
+ suite.addTestSuite(UnsupportedCharsetExceptionTest.class);
+ suite.addTestSuite(CoderMalfunctionErrorTest.class);
+ //$JUnit-END$
+ return suite;
+ }
+}
diff --git a/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharacterCodingExceptionTest.java b/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharacterCodingExceptionTest.java
new file mode 100644
index 0000000..f1bab63
--- /dev/null
+++ b/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharacterCodingExceptionTest.java
@@ -0,0 +1,53 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio_char.tests.java.nio.charset;
+
+import java.io.IOException;
+import java.nio.charset.CharacterCodingException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Test CharacterCodingException
+ */
+public class CharacterCodingExceptionTest extends TestCase {
+
+ public void testConstructor() {
+ CharacterCodingException ex = new CharacterCodingException();
+ assertTrue(ex instanceof IOException);
+ assertNull(ex.getCause());
+ assertNull(ex.getMessage());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new CharacterCodingException());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+ SerializationTest.verifyGolden(this, new CharacterCodingException());
+
+ }
+}
diff --git a/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetDecoderTest.java b/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetDecoderTest.java
new file mode 100644
index 0000000..8617669
--- /dev/null
+++ b/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetDecoderTest.java
@@ -0,0 +1,231 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio_char.tests.java.nio.charset;
+
+import java.nio.BufferOverflowException;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CoderMalfunctionError;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.MalformedInputException;
+
+import junit.framework.TestCase;
+
+public class CharsetDecoderTest extends TestCase {
+
+ /**
+ * @tests java.nio.charset.CharsetDecoder.CharsetDecoder(Charset, float,
+ * float)
+ */
+ public void test_ConstructorLjava_nio_charset_CharsetFF() {
+ // Regression for HARMONY-142
+ try {
+ Charset cs = Charset.forName("UTF-8"); //$NON-NLS-1$
+ new MockCharsetDecoderForHarmony142(cs, 1.1f, 1);
+ fail("Assert 0: Should throw IllegalArgumentException."); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ /*
+ * MockCharsetDecoderForHarmony142: for constructor test
+ */
+ static class MockCharsetDecoderForHarmony142 extends CharsetDecoder {
+ protected MockCharsetDecoderForHarmony142(Charset cs,
+ float averageBytesPerChar, float maxBytesPerChar) {
+ super(cs, averageBytesPerChar, maxBytesPerChar);
+ }
+
+ protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) {
+ return null;
+ }
+ }
+
+ /**
+ * @tests java.nio.charset.CharsetDecoder#decode(java.nio.ByteBuffer)
+ */
+ public void test_decode() throws CharacterCodingException {
+ // Regression for HARMONY-33
+// ByteBuffer bb = ByteBuffer.allocate(1);
+// bb.put(0, (byte) 77);
+// CharsetDecoder decoder = Charset.forName("UTF-16").newDecoder();
+// decoder.onMalformedInput(CodingErrorAction.REPLACE);
+// decoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
+// decoder.decode(bb);
+
+ // Regression for HARMONY-67
+// byte[] b = new byte[] { (byte) 1 };
+// ByteBuffer buf = ByteBuffer.wrap(b);
+// CharBuffer charbuf = Charset.forName("UTF-16").decode(buf);
+// assertEquals("Assert 0: charset UTF-16", 1, charbuf.length());
+//
+// charbuf = Charset.forName("UTF-16BE").decode(buf);
+// assertEquals("Assert 1: charset UTF-16BE", 0, charbuf.length());
+//
+// charbuf = Charset.forName("UTF-16LE").decode(buf);
+// assertEquals("Assert 2: charset UTF16LE", 0, charbuf.length());
+
+ // Regression for HARMONY-99
+ CharsetDecoder decoder2 = Charset.forName("UTF-16").newDecoder();
+ decoder2.onMalformedInput(CodingErrorAction.REPORT);
+ decoder2.onUnmappableCharacter(CodingErrorAction.REPORT);
+ ByteBuffer in = ByteBuffer.wrap(new byte[] { 109, 97, 109 });
+ try {
+ decoder2.decode(in);
+ fail("Assert 3: MalformedInputException should have thrown");
+ } catch (MalformedInputException e) {
+ //expected
+ }
+ }
+
+ /*
+ * Test malfunction decode(ByteBuffer)
+ */
+ public void test_decodeLjava_nio_ByteBuffer() throws Exception {
+ MockMalfunctionCharset cs1 = new MockMalfunctionCharset(
+ "Harmony-124-1", null); //$NON-NLS-1$
+ try {
+ cs1.newDecoder().onMalformedInput(CodingErrorAction.REPLACE)
+ .onUnmappableCharacter(CodingErrorAction.REPLACE).decode(
+ ByteBuffer.wrap(new byte[] { 0x00, 0x11 }));
+ fail("Assert 0: should throw CoderMalfunctionError"); // NON-NLS-1$
+ } catch (CoderMalfunctionError e) {
+ // expected
+ }
+
+ MockMalfunctionCharset cs2 = new MockMalfunctionCharset(
+ "Harmony-124-2", null); //$NON-NLS-1$
+ try {
+ cs2.decode(ByteBuffer.wrap(new byte[] { 0x00, 0x11 }));
+ fail("Assert 1: Charset.decode should throw CoderMalfunctionError"); // NON-NLS-1
+ } catch (CoderMalfunctionError e) {
+ // expected
+ }
+ }
+
+ /*
+ * Mock charset class with malfunction decode & encode.
+ */
+ static final class MockMalfunctionCharset extends Charset {
+
+ public MockMalfunctionCharset(String canonicalName, String[] aliases) {
+ super(canonicalName, aliases);
+ }
+
+ public boolean contains(Charset cs) {
+ return false;
+ }
+
+ public CharsetDecoder newDecoder() {
+ return new MockMalfunctionDecoder(this);
+ }
+
+ public CharsetEncoder newEncoder() {
+ return new MockMalfunctionEncoder(this);
+ }
+ }
+
+ /*
+ * Mock decoder. decodeLoop always throws unexpected exception.
+ */
+ static class MockMalfunctionDecoder extends java.nio.charset.CharsetDecoder {
+
+ public MockMalfunctionDecoder(Charset cs) {
+ super(cs, 1, 10);
+ }
+
+ protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) {
+ throw new BufferOverflowException();
+ }
+ }
+
+ /*
+ * Mock encoder. encodeLoop always throws unexpected exception.
+ */
+ static class MockMalfunctionEncoder extends java.nio.charset.CharsetEncoder {
+
+ public MockMalfunctionEncoder(Charset cs) {
+ super(cs, 1, 3, new byte[] { (byte) '?' });
+ }
+
+ protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) {
+ throw new BufferOverflowException();
+ }
+ }
+
+ /*
+ * Test the method decode(ByteBuffer) .
+ */
+ public void testDecodeLjava_nio_ByteBuffer_ReplaceOverflow()
+ throws Exception {
+ String replaceString = "a";
+ Charset cs = Charset.forName("UTF-8");
+ MockMalformedDecoder decoder = new MockMalformedDecoder(cs);
+ decoder.onMalformedInput(CodingErrorAction.REPLACE);
+ decoder.replaceWith(replaceString);
+ CharBuffer out = CharBuffer.allocate(1);
+ // MockMalformedDecoder treats the second byte '0x38' as malformed,
+ // but "out" doesn't have enough space for replace string.
+ ByteBuffer in = ByteBuffer.wrap(new byte[] { 0x45, 0x38, 0x45, 0x45 });
+ CoderResult result = decoder.decode(in, out, false);
+ assertTrue(result.isOverflow());
+
+ // allocate enough space for "out"
+ out = CharBuffer.allocate(10);
+ // replace string should be put into "out" firstly,
+ // and then decode "in".
+ result = decoder.decode(in, out, true);
+ out.flip();
+ assertTrue(result.isUnderflow());
+ assertEquals("bb", out.toString());
+ }
+
+ /*
+ * Mock decoder. It treats byte whose value is less than "0x40" as
+ * malformed.
+ */
+ static class MockMalformedDecoder extends java.nio.charset.CharsetDecoder {
+
+ public MockMalformedDecoder(Charset cs) {
+ super(cs, 1, 10);
+ }
+
+ /*
+ * It treats byte whose value is less than "0x40" as malformed.
+ * Otherwise, it's decoded as 'b'.
+ */
+ protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) {
+ while (in.hasRemaining()) {
+ byte b = in.get();
+ if (b < 0x40) {
+ return CoderResult.malformedForLength(1);
+ }
+ if (!out.hasRemaining()) {
+ return CoderResult.OVERFLOW;
+ }
+ out.put((char) 'b');
+ }
+ return CoderResult.UNDERFLOW;
+ }
+ }
+}
diff --git a/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetEncoderTest.java b/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetEncoderTest.java
new file mode 100644
index 0000000..fce2a1a
--- /dev/null
+++ b/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetEncoderTest.java
@@ -0,0 +1,169 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio_char.tests.java.nio.charset;
+
+import java.nio.BufferOverflowException;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CoderMalfunctionError;
+import java.nio.charset.CoderResult;
+
+import junit.framework.TestCase;
+
+public class CharsetEncoderTest extends TestCase {
+
+ /**
+ * @tests java.nio.charset.CharsetEncoder.CharsetEncoder(
+ * java.nio.charset.Charset, float, float)
+ */
+ public void test_ConstructorLjava_nio_charset_CharsetFF() {
+ // Regression for HARMONY-141
+ try {
+ Charset cs = Charset.forName("UTF-8"); //$NON-NLS-1$
+ new MockCharsetEncoderForHarmony141(cs, 1.1f, 1);
+ fail("Assert 0: Should throw IllegalArgumentException."); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ Charset cs = Charset.forName("ISO8859-1"); //$NON-NLS-1$
+ new MockCharsetEncoderForHarmony141(cs, 1.1f, 1,
+ new byte[] { 0x1a });
+ fail("Assert 1: Should throw IllegalArgumentException."); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.charset.CharsetEncoder.CharsetEncoder(
+ * java.nio.charset.Charset, float, float)
+ */
+ public void test_ConstructorLjava_nio_charset_CharsetNull() {
+ // Regression for HARMONY-491
+ CharsetEncoder ech = new MockCharsetEncoderForHarmony491(null, 1, 1);
+ assertNull(ech.charset());
+ }
+
+ /**
+ * Helper for constructor tests
+ */
+
+ public static class MockCharsetEncoderForHarmony141 extends CharsetEncoder {
+
+ protected MockCharsetEncoderForHarmony141(Charset cs,
+ float averageBytesPerChar, float maxBytesPerChar) {
+ super(cs, averageBytesPerChar, maxBytesPerChar);
+ }
+
+ public MockCharsetEncoderForHarmony141(Charset cs,
+ float averageBytesPerChar, float maxBytesPerChar,
+ byte[] replacement) {
+ super(cs, averageBytesPerChar, maxBytesPerChar, replacement);
+ }
+
+ protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) {
+ return null;
+ }
+ }
+
+ public static class MockCharsetEncoderForHarmony491 extends CharsetEncoder {
+
+ public MockCharsetEncoderForHarmony491(Charset arg0, float arg1,
+ float arg2) {
+ super(arg0, arg1, arg2);
+ }
+
+ protected CoderResult encodeLoop(CharBuffer arg0, ByteBuffer arg1) {
+ return null;
+ }
+
+ public boolean isLegalReplacement(byte[] arg0) {
+ return true;
+ }
+ }
+
+ /*
+ * Test malfunction encode(CharBuffer)
+ */
+ public void test_EncodeLjava_nio_CharBuffer() throws Exception {
+ MockMalfunctionCharset cs = new MockMalfunctionCharset("mock", null);
+ try {
+ cs.encode(CharBuffer.wrap("AB"));
+ fail("should throw CoderMalfunctionError");// NON-NLS-1$
+ } catch (CoderMalfunctionError e) {
+ // expected
+ }
+ }
+
+ /*
+ * Mock charset class with malfunction decode & encode.
+ */
+ static final class MockMalfunctionCharset extends Charset {
+
+ public MockMalfunctionCharset(String canonicalName, String[] aliases) {
+ super(canonicalName, aliases);
+ }
+
+ public boolean contains(Charset cs) {
+ return false;
+ }
+
+ public CharsetDecoder newDecoder() {
+ return Charset.forName("UTF-8").newDecoder();
+ }
+
+ public CharsetEncoder newEncoder() {
+ return new MockMalfunctionEncoder(this);
+ }
+ }
+
+ /*
+ * Mock encoder. encodeLoop always throws unexpected exception.
+ */
+ static class MockMalfunctionEncoder extends java.nio.charset.CharsetEncoder {
+
+ public MockMalfunctionEncoder(Charset cs) {
+ super(cs, 1, 3, new byte[] { (byte) '?' });
+ }
+
+ protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) {
+ throw new BufferOverflowException();
+ }
+ }
+
+ /*
+ * Test reserve bytes encode(CharBuffer,ByteBuffer,boolean)
+ */
+ public void test_EncodeLjava_nio_CharBufferLjava_nio_ByteBufferB() {
+ CharsetEncoder encoder = Charset.forName("utf-8").newEncoder();
+ CharBuffer in1 = CharBuffer.wrap("\ud800");
+ CharBuffer in2 = CharBuffer.wrap("\udc00");
+ ByteBuffer out = ByteBuffer.allocate(4);
+ encoder.reset();
+ CoderResult result = encoder.encode(in1, out, false);
+ assertEquals(4, out.remaining());
+ assertTrue(result.isUnderflow());
+ result = encoder.encode(in2, out, true);
+ assertEquals(4, out.remaining());
+ assertTrue(result.isMalformed());
+ }
+}
diff --git a/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetTest.java b/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetTest.java
new file mode 100644
index 0000000..0c46cd9
--- /dev/null
+++ b/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetTest.java
@@ -0,0 +1,292 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio_char.tests.java.nio.charset;
+
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.IllegalCharsetNameException;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+public class CharsetTest extends TestCase {
+
+ // Will contain names of charsets registered with IANA
+ Set knownRegisteredCharsets = new HashSet();
+
+ // Will contain names of charsets not known to be registered with IANA
+ Set unknownRegisteredCharsets = new HashSet();
+
+ /**
+ * JUnit set-up method
+ */
+ public void setUp() {
+ // Populate the known charset vars
+ Set names = Charset.availableCharsets().keySet();
+ for (Iterator nameItr = names.iterator(); nameItr.hasNext();) {
+ String name = (String) nameItr.next();
+ if (name.toLowerCase().startsWith("x-"))
+ unknownRegisteredCharsets.add(name);
+ else
+ knownRegisteredCharsets.add(name);
+ }
+ }
+
+ /**
+ * @tests java.nio.charset.Charset#isRegistered()
+ */
+ public void test_isRegistered() {
+ // Regression for HARMONY-45
+ for (Iterator nameItr = knownRegisteredCharsets.iterator(); nameItr.hasNext();) {
+ String name = (String) nameItr.next();
+ assertTrue("Assert 0: isRegistered() failed for " + name,
+ Charset.forName(name).isRegistered());
+ }
+ for (Iterator nameItr = unknownRegisteredCharsets.iterator(); nameItr.hasNext();) {
+ String name = (String) nameItr.next();
+ assertFalse("Assert 0: isRegistered() failed for " + name,
+ Charset.forName(name).isRegistered());
+ }
+ }
+
+ /**
+ * @tests java.nio.charset.Charset#isSupported(String)
+ */
+ public void testIsSupported_EmptyString() {
+ // Regression for HARMONY-113
+ try {
+ Charset.isSupported("");
+ fail("Assert 0: Should throw IllegalCharsetNameException");
+ } catch (IllegalCharsetNameException e) {
+ // Expected
+ }
+ }
+
+ /**
+ * @tests java.nio.charset.Charset#defaultCharset()
+ */
+ public void test_defaultCharset() {
+ String charsetName = null;
+ String defaultCharsetName = null;
+ String oldDefaultEncoding = System.getProperty("file.encoding");
+ try {
+ // Normal behavior
+ charsetName = "UTF-8"; //$NON-NLS-1$
+ System.setProperty("file.encoding", charsetName);//$NON-NLS-1$
+ defaultCharsetName = Charset.defaultCharset().name();
+ assertEquals(charsetName, defaultCharsetName);
+
+ charsetName = "ISO-8859-1"; //$NON-NLS-1$
+ System.setProperty("file.encoding", charsetName);//$NON-NLS-1$
+ defaultCharsetName = Charset.defaultCharset().name();
+ assertEquals(charsetName, defaultCharsetName);
+
+ // Unsupported behavior
+ charsetName = "IMPOSSIBLE-8"; //$NON-NLS-1$
+ System.setProperty("file.encoding", charsetName);//$NON-NLS-1$
+ defaultCharsetName = Charset.defaultCharset().name();
+ assertEquals("UTF-8", defaultCharsetName);
+
+ // Null behavior
+ try {
+ Properties currentProps = System.getProperties();
+ currentProps.remove("file.encoding");//$NON-NLS-1$
+ Charset.defaultCharset().name();
+ fail("Should throw illegal IllegalArgumentException");//$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ // IllegalCharsetName behavior
+ try {
+ charsetName = "IMP~~OSSIBLE-8"; //$NON-NLS-1$
+ System.setProperty("file.encoding", charsetName);//$NON-NLS-1$
+ Charset.defaultCharset().name();
+ fail("Should throw IllegalCharsetNameException");//$NON-NLS-1$
+ } catch (IllegalCharsetNameException e) {
+ // expected
+ }
+ } finally {
+ System.setProperty("file.encoding", oldDefaultEncoding);//$NON-NLS-1$
+ }
+ }
+
+ /**
+ * @tests java.nio.charset.Charset#forName(java.lang.String)
+ */
+ public void test_forNameLjava_lang_String() {
+ /*
+ * invoke forName two times with the same canonical name, it
+ * should return the same reference.
+ */
+ Charset cs1 = Charset.forName("UTF-8");
+ Charset cs2 = Charset.forName("UTF-8");
+ assertSame(cs1, cs2);
+
+ /*
+ * test forName: invoke forName two times for the same Charset using
+ * canonical name and alias, it should return the same reference.
+ */
+ Charset cs3 = Charset.forName("ASCII");
+ Charset cs4 = Charset.forName("US-ASCII");
+ assertSame(cs3, cs4);
+ }
+
+ /*
+ * test cached decoder
+ */
+ public void test_DecodeLjava_nio_ByteBuffer() throws Exception{
+ MockCharsetForDecoder cs1 = new MockCharsetForDecoder("CachedCharset",null);
+ MockCharsetForDecoder cs2 = new MockCharsetForDecoder("CachedCharset",null);
+ ByteBuffer in = ByteBuffer.wrap(new byte[]{0x00});
+ cs1.decode(in);
+ in.flip();
+ cs2.decode(in);
+ in.flip();
+ }
+ /*
+ * Mock Charset for cached decoder test
+ */
+ static class MockCharsetForDecoder extends Charset{
+
+ public MockCharsetForDecoder(String canonicalName, String[] aliases){
+ super(canonicalName, aliases);
+ }
+
+ public boolean contains(Charset charset) {
+ return false;
+ }
+
+ public CharsetEncoder newEncoder() {
+ return null;
+ }
+
+ public CharsetDecoder newDecoder() {
+ return new MockCachedDecoder(this);
+ }
+
+
+ }
+ /*
+ * Mock decoder. Only one caller is permitted.
+ */
+ static class MockCachedDecoder extends CharsetDecoder {
+ static MockCachedDecoder caller = null;
+
+ public MockCachedDecoder(Charset cs) {
+ super(cs, 1, 10);
+ }
+
+ /*
+ * Only one caller is permitted.
+ * If there's another caller, throw RuntimeException.
+ */
+ protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) {
+ if(null == caller){
+ caller = this;
+ }else{
+ if(caller != this){
+ // Another instance
+ fail("should use the same instance");
+ }
+ }
+ return CoderResult.UNDERFLOW;
+ }
+ }
+
+ /*
+ * test cached encoder
+ */
+ public void test_EncodeLjava_nio_CharBuffer() throws Exception {
+ MockCharsetForEncoder cs1 = new MockCharsetForEncoder("CachedCharset", null);
+ MockCharsetForEncoder cs2 = new MockCharsetForEncoder("CachedCharset", null);
+ CharBuffer in = CharBuffer.wrap("A");
+ cs1.encode(in);
+ in.flip();
+ cs2.encode(in);
+ }
+
+ /*
+ * Mock Charset for cached encoder test
+ */
+ static class MockCharsetForEncoder extends Charset {
+
+ public MockCharsetForEncoder(String canonicalName, String[] aliases) {
+ super(canonicalName, aliases);
+ }
+
+ public boolean contains(Charset charset) {
+ return false;
+ }
+
+ public CharsetDecoder newDecoder() {
+ return new MockDecoderForEncoder(this);
+ }
+
+ public CharsetEncoder newEncoder() {
+ return new MockCachedEncoder(this);
+ }
+ }
+
+ /*
+ * Mock encoder. Only one caller is permitted.
+ */
+ static class MockCachedEncoder extends CharsetEncoder {
+ static MockCachedEncoder caller = null;
+
+ public MockCachedEncoder(Charset cs) {
+ super(cs, 1, 10);
+ }
+
+ /*
+ * Only one caller is permitted.
+ */
+ protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) {
+ if (null == caller) {
+ caller = this;
+ } else {
+ if (caller != this) {
+ // Another instance
+ fail("should use the same instance");
+ }
+ }
+ return CoderResult.UNDERFLOW;
+ }
+ }
+
+ /*
+ * Mock decoder for MockCachedEncoder.
+ */
+ static class MockDecoderForEncoder extends CharsetDecoder {
+ public MockDecoderForEncoder(Charset cs) {
+ super(cs, 1, 10);
+ }
+
+ protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) {
+ in.position(in.limit());
+ return CoderResult.UNDERFLOW;
+ }
+ }
+
+}
diff --git a/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CoderMalfunctionErrorTest.java b/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CoderMalfunctionErrorTest.java
new file mode 100644
index 0000000..dc9f269
--- /dev/null
+++ b/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CoderMalfunctionErrorTest.java
@@ -0,0 +1,62 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio_char.tests.java.nio.charset;
+
+import java.nio.charset.CoderMalfunctionError;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Test java.nio.CoderMalfunctionError.
+ */
+public class CoderMalfunctionErrorTest extends TestCase {
+
+ /*
+ * Test constructor with normal param.
+ */
+ public void testConstructor_Normal() {
+ Exception ex = new Exception();
+ CoderMalfunctionError e = new CoderMalfunctionError(ex);
+ assertSame(ex, e.getCause());
+ }
+
+ /*
+ * Test constructor with null param.
+ */
+ public void testConstructor_Null() {
+ CoderMalfunctionError e = new CoderMalfunctionError(null);
+ assertNull(e.getCause());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new CoderMalfunctionError(null));
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+ SerializationTest.verifyGolden(this, new CoderMalfunctionError(null));
+
+ }
+}
diff --git a/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/IllegalCharsetNameExceptionTest.java b/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/IllegalCharsetNameExceptionTest.java
new file mode 100644
index 0000000..914eea2
--- /dev/null
+++ b/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/IllegalCharsetNameExceptionTest.java
@@ -0,0 +1,94 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio_char.tests.java.nio.charset;
+
+import java.io.Serializable;
+import java.nio.charset.IllegalCharsetNameException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+import org.apache.harmony.testframework.serialization.SerializationTest.SerializableAssert;
+
+/**
+ * Test class IllegalCharsetNameException.
+ */
+public class IllegalCharsetNameExceptionTest extends TestCase {
+
+ public void testConstructor() {
+ IllegalCharsetNameException ex = new IllegalCharsetNameException(
+ "impossible");
+ assertTrue(ex instanceof IllegalArgumentException);
+ assertNull(ex.getCause());
+ assertEquals(ex.getCharsetName(), "impossible");
+ assertTrue(ex.getMessage().indexOf("impossible") != -1);
+
+ ex = new IllegalCharsetNameException("ascii");
+ assertNull(ex.getCause());
+ assertEquals(ex.getCharsetName(), "ascii");
+ assertTrue(ex.getMessage().indexOf("ascii") != -1);
+
+ ex = new IllegalCharsetNameException("");
+ assertNull(ex.getCause());
+ assertEquals(ex.getCharsetName(), "");
+ ex.getMessage();
+
+ ex = new IllegalCharsetNameException(null);
+ assertNull(ex.getCause());
+ assertNull(ex.getCharsetName());
+ assertTrue(ex.getMessage().indexOf("null") != -1);
+
+ }
+
+ // comparator for IllegalCharsetNameException objects
+ private static final SerializableAssert COMPARATOR = new SerializableAssert() {
+ public void assertDeserialized(Serializable initial,
+ Serializable deserialized) {
+
+ // FIXME?: getMessage() returns more helpful string but
+ // this leads to incompatible message in serial form
+ //
+ // do common checks for all throwable objects
+ // SerializationTest.THROWABLE_COMPARATOR.assertDeserialized(initial,
+ // deserialized);
+
+ IllegalCharsetNameException initEx = (IllegalCharsetNameException) initial;
+ IllegalCharsetNameException desrEx = (IllegalCharsetNameException) deserialized;
+
+ assertEquals("CharsetName", initEx.getCharsetName(), desrEx
+ .getCharsetName());
+ }
+ };
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new IllegalCharsetNameException(
+ "charsetName"), COMPARATOR);
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest.verifyGolden(this, new IllegalCharsetNameException(
+ "charsetName"), COMPARATOR);
+ }
+}
diff --git a/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/MalformedInputExceptionTest.java b/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/MalformedInputExceptionTest.java
new file mode 100644
index 0000000..40ab9c7
--- /dev/null
+++ b/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/MalformedInputExceptionTest.java
@@ -0,0 +1,85 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio_char.tests.java.nio.charset;
+
+import java.io.Serializable;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.MalformedInputException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+import org.apache.harmony.testframework.serialization.SerializationTest.SerializableAssert;
+
+/**
+ * Test class MalformedInputException.
+ */
+public class MalformedInputExceptionTest extends TestCase {
+
+ public void testConstructor() {
+ MalformedInputException ex = new MalformedInputException(3);
+ assertTrue(ex instanceof CharacterCodingException);
+ assertNull(ex.getCause());
+ assertEquals(ex.getInputLength(), 3);
+ assertTrue(ex.getMessage().indexOf("3") != -1);
+
+ ex = new MalformedInputException(-3);
+ assertNull(ex.getCause());
+ assertEquals(ex.getInputLength(), -3);
+ assertTrue(ex.getMessage().indexOf("-3") != -1);
+
+ ex = new MalformedInputException(0);
+ assertNull(ex.getCause());
+ assertEquals(ex.getInputLength(), 0);
+ assertTrue(ex.getMessage().indexOf("0") != -1);
+ }
+
+ // comparator for MalformedInputException objects
+ private static final SerializableAssert COMPARATOR = new SerializableAssert() {
+ public void assertDeserialized(Serializable initial,
+ Serializable deserialized) {
+
+ // do common checks for all throwable objects
+ SerializationTest.THROWABLE_COMPARATOR.assertDeserialized(initial,
+ deserialized);
+
+ MalformedInputException initEx = (MalformedInputException) initial;
+ MalformedInputException desrEx = (MalformedInputException) deserialized;
+
+ assertEquals("InputLength", initEx.getInputLength(), desrEx
+ .getInputLength());
+ }
+ };
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new MalformedInputException(11),
+ COMPARATOR);
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest.verifyGolden(this, new MalformedInputException(11),
+ COMPARATOR);
+ }
+}
diff --git a/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/UnmappableCharacterExceptionTest.java b/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/UnmappableCharacterExceptionTest.java
new file mode 100644
index 0000000..0abefbe
--- /dev/null
+++ b/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/UnmappableCharacterExceptionTest.java
@@ -0,0 +1,86 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio_char.tests.java.nio.charset;
+
+import java.io.Serializable;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.UnmappableCharacterException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+import org.apache.harmony.testframework.serialization.SerializationTest.SerializableAssert;
+
+/**
+ * Test class UnmappableCharacterException.
+ */
+public class UnmappableCharacterExceptionTest extends TestCase {
+
+ public void testConstructor() {
+ UnmappableCharacterException ex = new UnmappableCharacterException(3);
+ assertTrue(ex instanceof CharacterCodingException);
+ assertNull(ex.getCause());
+ assertEquals(ex.getInputLength(), 3);
+ assertTrue(ex.getMessage().indexOf("3") != -1);
+
+ ex = new UnmappableCharacterException(-3);
+ assertNull(ex.getCause());
+ assertEquals(ex.getInputLength(), -3);
+ assertTrue(ex.getMessage().indexOf("-3") != -1);
+
+ ex = new UnmappableCharacterException(0);
+ assertNull(ex.getCause());
+ assertEquals(ex.getInputLength(), 0);
+ assertTrue(ex.getMessage().indexOf("0") != -1);
+
+ }
+
+ // comparator for UnmappableCharacterException objects
+ private static final SerializableAssert COMPARATOR = new SerializableAssert() {
+ public void assertDeserialized(Serializable initial,
+ Serializable deserialized) {
+
+ // do common checks for all throwable objects
+ SerializationTest.THROWABLE_COMPARATOR.assertDeserialized(initial,
+ deserialized);
+
+ UnmappableCharacterException initEx = (UnmappableCharacterException) initial;
+ UnmappableCharacterException desrEx = (UnmappableCharacterException) deserialized;
+
+ assertEquals("InputLength", initEx.getInputLength(), desrEx
+ .getInputLength());
+ }
+ };
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new UnmappableCharacterException(11),
+ COMPARATOR);
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest.verifyGolden(this, new UnmappableCharacterException(
+ 11), COMPARATOR);
+ }
+}
diff --git a/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/UnsupportedCharsetExceptionTest.java b/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/UnsupportedCharsetExceptionTest.java
new file mode 100644
index 0000000..dd17848
--- /dev/null
+++ b/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/UnsupportedCharsetExceptionTest.java
@@ -0,0 +1,93 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio_char.tests.java.nio.charset;
+
+import java.io.Serializable;
+import java.nio.charset.UnsupportedCharsetException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+import org.apache.harmony.testframework.serialization.SerializationTest.SerializableAssert;
+
+/**
+ * Test class UnsupportedCharsetException.
+ */
+public class UnsupportedCharsetExceptionTest extends TestCase {
+
+ public void testConstructor() {
+ UnsupportedCharsetException ex = new UnsupportedCharsetException(
+ "impossible");
+ assertTrue(ex instanceof IllegalArgumentException);
+ assertNull(ex.getCause());
+ assertEquals(ex.getCharsetName(), "impossible");
+ assertTrue(ex.getMessage().indexOf("impossible") != -1);
+
+ ex = new UnsupportedCharsetException("ascii");
+ assertNull(ex.getCause());
+ assertEquals(ex.getCharsetName(), "ascii");
+ assertTrue(ex.getMessage().indexOf("ascii") != -1);
+
+ ex = new UnsupportedCharsetException("");
+ assertNull(ex.getCause());
+ assertEquals(ex.getCharsetName(), "");
+ ex.getMessage();
+
+ ex = new UnsupportedCharsetException(null);
+ assertNull(ex.getCause());
+ assertNull(ex.getCharsetName());
+ assertTrue(ex.getMessage().indexOf("null") != -1);
+ }
+
+ // comparator for UnsupportedCharsetException objects
+ private static final SerializableAssert COMPARATOR = new SerializableAssert() {
+ public void assertDeserialized(Serializable initial,
+ Serializable deserialized) {
+
+ // FIXME?: getMessage() returns more helpful string but
+ // this leads to incompatible message in serial form
+ //
+ // do common checks for all throwable objects
+ // SerializationTest.THROWABLE_COMPARATOR.assertDeserialized(initial,
+ // deserialized);
+
+ UnsupportedCharsetException initEx = (UnsupportedCharsetException) initial;
+ UnsupportedCharsetException desrEx = (UnsupportedCharsetException) deserialized;
+
+ assertEquals("CharsetName", initEx.getCharsetName(), desrEx
+ .getCharsetName());
+ }
+ };
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new UnsupportedCharsetException(
+ "charsetName"), COMPARATOR);
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest.verifyGolden(this, new UnsupportedCharsetException(
+ "charsetName"), COMPARATOR);
+ }
+}
diff --git a/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/spi/AllTests.java b/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/spi/AllTests.java
new file mode 100644
index 0000000..bf9546a
--- /dev/null
+++ b/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/spi/AllTests.java
@@ -0,0 +1,36 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio_char.tests.java.nio.charset.spi;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AllTests {
+
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(AllTests.suite());
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(
+ "Suite of tests for the java.nio.charset.spi package.");
+ // $JUnit-BEGIN$
+ suite.addTestSuite(CharsetProviderTest.class);
+ // $JUnit-END$
+ return suite;
+ }
+}
diff --git a/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/spi/CharsetProviderTest.java b/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/spi/CharsetProviderTest.java
new file mode 100644
index 0000000..7a90b56
--- /dev/null
+++ b/nio_char/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/spi/CharsetProviderTest.java
@@ -0,0 +1,94 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio_char.tests.java.nio.charset.spi;
+
+import java.nio.charset.Charset;
+import java.nio.charset.spi.CharsetProvider;
+import java.security.Permission;
+import java.util.Iterator;
+
+import junit.framework.TestCase;
+
+/**
+ * Test class java.nio.charset.spi.CharsetProvider.
+ */
+public class CharsetProviderTest extends TestCase {
+
+ /*
+ * Test the security check in the constructor.
+ */
+ public void testConstructor() {
+ // with sufficient privilege
+ new MockCharsetProvider();
+
+ SecurityManager oldMan = System.getSecurityManager();
+ System.setSecurityManager(new MockSecurityManager());
+ // set a normal value
+ try {
+ new MockCharsetProvider();
+ fail("Should throw SecurityException!");
+ } catch (SecurityException e) {
+ // expected
+ } finally {
+ System.setSecurityManager(oldMan);
+ }
+ }
+
+ /*
+ * Test the signature.
+ */
+ static class MockCharsetProvider extends CharsetProvider {
+
+ public Charset charsetForName(String charsetName) {
+ return null;
+ }
+
+ public Iterator charsets() {
+ return null;
+ }
+ }
+
+ /*
+ * Used to grant all permissions except charset provider access.
+ */
+ public static class MockSecurityManager extends SecurityManager {
+
+ public MockSecurityManager() {
+ }
+
+ public void checkPermission(Permission perm) {
+ // grant all permissions except logging control
+ if (perm instanceof RuntimePermission) {
+ RuntimePermission rp = (RuntimePermission) perm;
+ if (rp.getName().equals("charsetProvider")) {
+ throw new SecurityException();
+ }
+ }
+ }
+
+ public void checkPermission(Permission perm, Object context) {
+ // grant all permissions except logging control
+ if (perm instanceof RuntimePermission) {
+ RuntimePermission rp = (RuntimePermission) perm;
+ if (rp.getName().equals("charsetProvider")) {
+ throw new SecurityException();
+ }
+ }
+ }
+ }
+
+}
diff --git a/nio_char/src/test/java/tests/api/java/nio/charset/ASCCharsetDecoderTest.java b/nio_char/src/test/java/tests/api/java/nio/charset/ASCCharsetDecoderTest.java
new file mode 100644
index 0000000..5dcf956
--- /dev/null
+++ b/nio_char/src/test/java/tests/api/java/nio/charset/ASCCharsetDecoderTest.java
@@ -0,0 +1,72 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.api.java.nio.charset;
+
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+
+public class ASCCharsetDecoderTest extends CharsetDecoderTest {
+
+ protected void setUp() throws Exception {
+ cs = Charset.forName("ascii");
+ super.setUp();
+ }
+
+ /*
+ * @see CharsetDecoderTest#tearDown()
+ */
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ // FIXME: give up this tests
+ // public void testDefaultCharsPerByte(){
+ // // assertEquals(1, decoder.averageCharsPerByte());
+ // // assertEquals(1, decoder.maxCharsPerByte());
+ // assertEquals(decoder.averageCharsPerByte(), 1, 0.001);
+ // assertEquals(decoder.maxCharsPerByte(), 2, 0.001);
+ // }
+
+ ByteBuffer getUnmappedByteBuffer() throws UnsupportedEncodingException {
+ // FIXME: different here
+ return null;
+ // ByteBuffer buffer = ByteBuffer.allocate(8);
+ // buffer.put((byte)-1);
+ // buffer.put(unibytes);
+ // buffer.flip();
+ // return buffer;
+
+ }
+
+ ByteBuffer getMalformByteBuffer() throws UnsupportedEncodingException {
+ // FIXME: different here
+ ByteBuffer buffer = ByteBuffer.allocate(8);
+ buffer.put((byte) -1);
+ buffer.put(unibytes);
+ buffer.flip();
+ return buffer;
+
+ // TODO: how malform?
+ // return null;
+ }
+
+ ByteBuffer getExceptionByteArray() throws UnsupportedEncodingException {
+ return null;
+ }
+
+}
diff --git a/nio_char/src/test/java/tests/api/java/nio/charset/ASCCharsetTest.java b/nio_char/src/test/java/tests/api/java/nio/charset/ASCCharsetTest.java
new file mode 100644
index 0000000..d907e93
--- /dev/null
+++ b/nio_char/src/test/java/tests/api/java/nio/charset/ASCCharsetTest.java
@@ -0,0 +1,59 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.api.java.nio.charset;
+
+/**
+ * Test charset US-ASCII.
+ */
+public class ASCCharsetTest extends AbstractCharsetTestCase {
+
+ /**
+ * Constructor.
+ *
+ */
+ public ASCCharsetTest(String arg0) {
+ super(arg0, "US-ASCII", new String[] { "ISO646-US", "ASCII", "cp367",
+ "ascii7", "ANSI_X3.4-1986", "iso-ir-6", "us", "646",
+ "iso_646.irv:1983", "csASCII", "ANSI_X3.4-1968",
+ "ISO_646.irv:1991" }, true, true); // "ibm-367"
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see tests.api.java.nio.charset.ConcreteCharsetTest#testEncode_Normal()
+ */
+ public void testEncode_Normal() {
+ String input = "ab\u5D14\u654F";
+ byte[] output = new byte[] { 97, 98,
+ this.testingCharset.newEncoder().replacement()[0],
+ this.testingCharset.newEncoder().replacement()[0] };
+ internalTestEncode(input, output);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see tests.api.java.nio.charset.ConcreteCharsetTest#testDecode_Normal()
+ */
+ public void testDecode_Normal() {
+ byte[] input = new byte[] { 97, 98, 63, 63 };
+ char[] output = "ab??".toCharArray();
+ internalTestDecode(input, output);
+ }
+
+}
diff --git a/nio_char/src/test/java/tests/api/java/nio/charset/AbstractCharsetTestCase.java b/nio_char/src/test/java/tests/api/java/nio/charset/AbstractCharsetTestCase.java
new file mode 100644
index 0000000..9a9b45c
--- /dev/null
+++ b/nio_char/src/test/java/tests/api/java/nio/charset/AbstractCharsetTestCase.java
@@ -0,0 +1,158 @@
+package tests.api.java.nio.charset;
+
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+
+import junit.framework.TestCase;
+
+/**
+ * Super class for concrete charset test suites.
+ */
+public abstract class AbstractCharsetTestCase extends TestCase {
+
+ // the canonical name of this charset
+ protected final String canonicalName;
+
+ // the aliases set
+ protected final String[] aliases;
+
+ // canEncode
+ protected final boolean canEncode;
+
+ // isRegistered
+ protected final boolean isRegistered;
+
+ // charset instance
+ protected Charset testingCharset;
+
+ /*
+ * Initialize the field "testingCharset" here.
+ *
+ * @see TestCase#setUp()
+ */
+ protected void setUp() throws Exception {
+ super.setUp();
+ this.testingCharset = Charset.forName(this.canonicalName);
+ }
+
+ /*
+ * @see TestCase#tearDown()
+ */
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /**
+ * Constructor for ConcreteCharsetTest.
+ *
+ */
+ public AbstractCharsetTestCase(String arg0, String canonicalName,
+ String[] aliases, boolean canEncode, boolean isRegistered) {
+ super(arg0);
+ this.canonicalName = canonicalName;
+ this.canEncode = canEncode;
+ this.isRegistered = isRegistered;
+ this.aliases = aliases;
+ }
+
+ /*
+ * Test canEncode.
+ */
+ public void testCanEncode() {
+ assertEquals(this.canEncode, this.testingCharset.canEncode());
+ }
+
+ /*
+ * Test isRegistered.
+ */
+ public void testIsRegistered() {
+ assertEquals(this.isRegistered, this.testingCharset.isRegistered());
+ }
+
+ /*
+ * Test name.
+ */
+ public void testName() {
+ assertEquals(this.canonicalName, this.testingCharset.name());
+ // assertEquals(this.canonicalName, this.testingCharset.displayName());
+ // assertEquals(this.canonicalName,
+ // this.testingCharset.displayName(null));
+ }
+
+ /*
+ * Test aliases.
+ */
+ public void testAliases() {
+ for (int i = 0; i < this.aliases.length; i++) {
+ Charset c = Charset.forName(this.aliases[i]);
+ assertEquals(this.canonicalName, c.name());
+ // TODO
+ // assertTrue(this.testingCharset.aliases().contains(this.aliases[i]));
+ }
+ }
+
+ /*
+ * Test the method encode(String) with null.
+ */
+ public void testEncode_String_Null() {
+ try {
+ this.testingCharset.encode((String) null);
+ fail("Should throw NullPointerException!");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Test the method encode(CharBuffer) with null.
+ */
+ public void testEncode_CharBuffer_Null() {
+ try {
+ this.testingCharset.encode((CharBuffer) null);
+ fail("Should throw NullPointerException!");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Test encoding.
+ */
+ protected void internalTestEncode(String input, byte[] output) {
+ ByteBuffer bb = this.testingCharset.encode(input);
+ int i = 0;
+ bb.rewind();
+ while (bb.hasRemaining() && i < output.length) {
+ assertEquals(output[i], bb.get());
+ i++;
+ }
+ assertFalse(bb.hasRemaining());
+ assertEquals(output.length, i);
+ }
+
+ /*
+ * Test encoding.
+ */
+ public abstract void testEncode_Normal();
+
+ /*
+ * Test decoding.
+ */
+ protected void internalTestDecode(byte[] input, char[] output) {
+ CharBuffer chb = this.testingCharset.decode(ByteBuffer.wrap(input));
+ int i = 0;
+ chb.rewind();
+ while (chb.hasRemaining() && i < output.length) {
+ assertEquals(output[i], chb.get());
+ i++;
+ }
+ assertFalse(chb.hasRemaining());
+ assertEquals(output.length, i);
+ }
+
+ /*
+ * Test decoding.
+ */
+ public abstract void testDecode_Normal();
+}
diff --git a/nio_char/src/test/java/tests/api/java/nio/charset/AllTests.java b/nio_char/src/test/java/tests/api/java/nio/charset/AllTests.java
new file mode 100644
index 0000000..e718651
--- /dev/null
+++ b/nio_char/src/test/java/tests/api/java/nio/charset/AllTests.java
@@ -0,0 +1,62 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.api.java.nio.charset;
+
+import org.apache.harmony.nio_char.tests.java.nio.charset.ASCIICharsetEncoderTest;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Test suite for java.nio.charset package.
+ */
+public class AllTests {
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite("Test for tests.api.java.nio.charset");
+ // $JUnit-BEGIN$
+ suite.addTestSuite(CodingErrorActionTest.class);
+ suite.addTestSuite(CoderResultTest.class);
+ suite.addTestSuite(CharsetTest.class);
+ suite.addTestSuite(ASCCharsetTest.class);
+ suite.addTestSuite(ISOCharsetTest.class);
+ suite.addTestSuite(UTF8CharsetTest.class);
+ suite.addTestSuite(UTF16CharsetTest.class);
+ suite.addTestSuite(UTF16BECharsetTest.class);
+ suite.addTestSuite(UTF16LECharsetTest.class);
+ suite.addTestSuite(CharsetEncoderTest.class);
+ suite.addTestSuite(ISOCharsetEncoderTest.class);
+ suite.addTestSuite(UTFCharsetEncoderTest.class);
+ // GBCharset not supported
+ // suite.addTestSuite(GBCharsetEncoderTest.class);
+ suite.addTestSuite(ASCIICharsetEncoderTest.class);
+ suite.addTestSuite(UTF16CharsetEncoderTest.class);
+ suite.addTestSuite(UTF16LECharsetEncoderTest.class);
+ suite.addTestSuite(UTF16BECharsetEncoderTest.class);
+ suite.addTestSuite(CharsetDecoderTest.class);
+ suite.addTestSuite(ISOCharsetDecoderTest.class);
+ suite.addTestSuite(UTFCharsetDecoderTest.class);
+ // GBCharset not supported
+ // suite.addTestSuite(GBCharsetDecoderTest.class);
+ suite.addTestSuite(ASCCharsetDecoderTest.class);
+ suite.addTestSuite(UTF16CharsetDecoderTest.class);
+ suite.addTestSuite(UTF16LECharsetDecoderTest.class);
+ suite.addTestSuite(UTF16BECharsetDecoderTest.class);
+ // $JUnit-END$
+ return suite;
+ }
+}
diff --git a/nio_char/src/test/java/tests/api/java/nio/charset/CharsetDecoderTest.java b/nio_char/src/test/java/tests/api/java/nio/charset/CharsetDecoderTest.java
new file mode 100644
index 0000000..0d067b0
--- /dev/null
+++ b/nio_char/src/test/java/tests/api/java/nio/charset/CharsetDecoderTest.java
@@ -0,0 +1,784 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package tests.api.java.nio.charset;
+
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.MalformedInputException;
+import java.nio.charset.UnmappableCharacterException;
+
+import junit.framework.TestCase;
+
+/**
+ * API unit test for java.nio.CharsetDecoder
+ */
+public class CharsetDecoderTest extends TestCase {
+
+ static final String unistr = " buffer";// \u8000\u8001\u00a5\u3000\r\n";
+
+ byte[] unibytes = new byte[] { 32, 98, 117, 102, 102, 101, 114 };
+
+ protected static final int MAX_BYTES = 3;
+
+ protected static final double AVER_BYTES = 0.5;
+
+ // default charset
+ private static final Charset MOCKCS = new CharsetEncoderTest.MockCharset(
+ "mock", new String[0]);
+
+ Charset cs = MOCKCS;
+
+ // default decoder
+ protected static CharsetDecoder decoder;
+
+ String bom = "";
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ decoder = cs.newDecoder();
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ // FIXME: give up this tests
+ // /*
+ // * test default value
+ // */
+ // public void testDefaultCharsPerByte() {
+ // assertTrue(decoder.averageCharsPerByte() == AVER_BYTES);
+ // assertTrue(decoder.maxCharsPerByte() == MAX_BYTES);
+ // }
+
+ public void testDefaultValues() {
+ assertSame(cs, decoder.charset());
+ try {
+ decoder.detectedCharset();
+ fail("should unsupported");
+ } catch (UnsupportedOperationException e) {
+ }
+ try {
+ assertTrue(decoder.isCharsetDetected());
+ fail("should unsupported");
+ } catch (UnsupportedOperationException e) {
+ }
+ assertFalse(decoder.isAutoDetecting());
+ assertSame(CodingErrorAction.REPORT, decoder.malformedInputAction());
+ assertSame(CodingErrorAction.REPORT, decoder
+ .unmappableCharacterAction());
+ assertEquals(decoder.replacement(), "\ufffd");
+ }
+
+ /*
+ * test constructor
+ */
+ public void testCharsetDecoder() {
+ // default value
+ decoder = new MockCharsetDecoder(cs, (float) AVER_BYTES, MAX_BYTES);
+
+ // normal case
+ CharsetDecoder ec = new MockCharsetDecoder(cs, 1, MAX_BYTES);
+ assertSame(ec.charset(), cs);
+ assertEquals(1.0, ec.averageCharsPerByte(), 0.0);
+ assertTrue(ec.maxCharsPerByte() == MAX_BYTES);
+
+ /*
+ * ------------------------ Exceptional cases -------------------------
+ */
+ // Normal case: null charset
+ ec = new MockCharsetDecoder(null, 1, MAX_BYTES);
+ assertNull(ec.charset());
+ assertEquals(1.0, ec.averageCharsPerByte(), 0.0);
+ assertTrue(ec.maxCharsPerByte() == MAX_BYTES);
+
+ ec = new MockCharsetDecoder(new CharsetEncoderTest.MockCharset("mock",
+ new String[0]), 1, MAX_BYTES);
+
+ // Commented out since the comment is wrong since MAX_BYTES > 1
+ // // OK: average length less than max length
+ // ec = new MockCharsetDecoder(cs, MAX_BYTES, 1);
+ // assertTrue(ec.averageCharsPerByte() == MAX_BYTES);
+ // assertTrue(ec.maxCharsPerByte() == 1);
+
+ // Illegal Argument: zero length
+ try {
+ ec = new MockCharsetDecoder(cs, 0, MAX_BYTES);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ }
+ try {
+ ec = new MockCharsetDecoder(cs, 1, 0);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ }
+
+ // Illegal Argument: negative length
+ try {
+ ec = new MockCharsetDecoder(cs, -1, MAX_BYTES);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ }
+ try {
+ ec = new MockCharsetDecoder(cs, 1, -1);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ }
+ }
+
+ /*
+ * test onMalformedInput
+ */
+ public void testOnMalformedInput() {
+ assertSame(CodingErrorAction.REPORT, decoder.malformedInputAction());
+ try {
+ decoder.onMalformedInput(null);
+ fail("should throw null pointer exception");
+ } catch (IllegalArgumentException e) {
+ }
+ decoder.onMalformedInput(CodingErrorAction.IGNORE);
+ assertSame(CodingErrorAction.IGNORE, decoder.malformedInputAction());
+ }
+
+ /*
+ * test unmappableCharacter
+ */
+ public void testOnUnmappableCharacter() {
+ assertSame(CodingErrorAction.REPORT, decoder
+ .unmappableCharacterAction());
+ try {
+ decoder.onUnmappableCharacter(null);
+ fail("should throw null pointer exception");
+ } catch (IllegalArgumentException e) {
+ }
+ decoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
+ assertSame(CodingErrorAction.IGNORE, decoder
+ .unmappableCharacterAction());
+ }
+
+ /*
+ * test replaceWith
+ */
+ public void testReplaceWith() {
+ try {
+ decoder.replaceWith(null);
+ fail("should throw null pointer exception");
+ } catch (IllegalArgumentException e) {
+ }
+ try {
+ decoder.replaceWith("");
+ fail("should throw null pointer exception");
+ } catch (IllegalArgumentException e) {
+ }
+ try {
+ decoder.replaceWith("testReplaceWith");
+ fail("should throw illegal argument exception");
+ } catch (IllegalArgumentException e) {
+ }
+
+ decoder.replaceWith("a");
+ assertSame("a", decoder.replacement());
+ }
+
+ /*
+ * Class under test for CharBuffer decode(ByteBuffer)
+ */
+ public void testDecodeByteBuffer() throws CharacterCodingException {
+ implTestDecodeByteBuffer();
+ }
+
+ void implTestDecodeByteBuffer() throws CharacterCodingException {
+ // Null pointer
+ try {
+ decoder.decode(null);
+ fail("should throw null pointer exception");
+ } catch (NullPointerException e) {
+ }
+
+ // empty input buffer
+ CharBuffer out = decoder.decode(ByteBuffer.allocate(0));
+ assertCharBufferValue(out, "");
+
+ // normal case
+ ByteBuffer in = ByteBuffer.wrap(getUnibytes());
+ out = decoder.decode(in);
+ assertEquals(out.position(), 0);
+ assertEquals(out.limit(), unistr.length());
+ assertEquals(out.remaining(), unistr.length());
+ assertEquals(new String(out.array(), 0, out.limit()), unistr);
+ }
+
+ public void testDecodeByteBufferException()
+ throws CharacterCodingException, UnsupportedEncodingException {
+ CharBuffer out;
+ ByteBuffer in;
+ String replaceStr = decoder.replacement() + " buffer";
+
+ // MalformedException:
+ decoder.onMalformedInput(CodingErrorAction.REPORT);
+ decoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+ in = getMalformByteBuffer();
+ if (in != null) {
+ try {
+ CharBuffer buffer = decoder.decode(in);
+ assertTrue(buffer.remaining() > 0);
+ fail("should throw MalformedInputException");
+ } catch (MalformedInputException e) {
+ }
+
+ decoder.reset();
+ in.rewind();
+ decoder.onMalformedInput(CodingErrorAction.IGNORE);
+ out = decoder.decode(in);
+ assertCharBufferValue(out, " buffer");
+
+ decoder.reset();
+ in.rewind();
+ decoder.onMalformedInput(CodingErrorAction.REPLACE);
+ out = decoder.decode(in);
+ assertCharBufferValue(out, replaceStr);
+ }
+
+ // Unmapped Exception:
+ decoder.onMalformedInput(CodingErrorAction.REPORT);
+ decoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+ in = getUnmappedByteBuffer();
+ if (in != null) {
+ try {
+ decoder.decode(in);
+ fail("should throw UnmappableCharacterException");
+ } catch (UnmappableCharacterException e) {
+ }
+
+ decoder.reset();
+ in.rewind();
+ decoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
+ out = decoder.decode(in);
+ assertCharBufferValue(out, " buffer");
+
+ decoder.reset();
+ in.rewind();
+ decoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
+ out = decoder.decode(in);
+ assertCharBufferValue(out, replaceStr);
+ }
+
+ // RuntimeException
+ try {
+ decoder.decode(getExceptionByteArray());
+ fail("should throw runtime exception");
+ } catch (RuntimeException e) {
+ }
+ }
+
+ /*
+ * Class under test for CoderResult decode(ByteBuffer, CharBuffer, boolean)
+ */
+ public void testDecodeByteBufferCharBufferboolean() {
+ implTestDecodeByteBufferCharBufferboolean();
+ }
+
+ void implTestDecodeByteBufferCharBufferboolean() {
+ byte[] gb = getUnibytes();
+ ByteBuffer in = ByteBuffer.wrap(gb);
+ CharBuffer out = CharBuffer.allocate(100);
+
+ // Null pointer
+ try {
+ decoder.decode(null, out, true);
+ fail("should throw null pointer exception");
+ } catch (NullPointerException e) {
+ }
+ try {
+ decoder.decode(in, null, true);
+ fail("should throw null pointer exception");
+ } catch (NullPointerException e) {
+ }
+
+ // normal case, one complete operation
+ decoder.reset();
+ in.rewind();
+ out.rewind();
+ assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, true));
+ assertEquals(out.limit(), 100);
+ assertEquals(out.position(), unistr.length());
+ assertEquals(out.remaining(), 100 - unistr.length());
+ assertEquals(out.capacity(), 100);
+ assertCharBufferValue(out, unistr);
+ decoder.flush(out);
+
+ // normal case, one complete operation, but call twice, first time set
+ // endOfInput to false
+ decoder.reset();
+ in.rewind();
+ out.clear();
+ assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, false));
+ assertEquals(out.limit(), 100);
+ assertEquals(out.position(), unistr.length());
+ assertEquals(out.remaining(), 100 - unistr.length());
+ assertEquals(out.capacity(), 100);
+ assertCharBufferValue(out, unistr);
+
+ decoder.reset();
+ in.rewind();
+ out.clear();
+ assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, false));
+ in = ByteBuffer.wrap(unibytes);
+ assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, false));
+ in.rewind();
+ assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, true));
+ assertEquals(out.limit(), 100);
+ assertTrue(out.position() > 0);
+ assertEquals(out.remaining(), out.capacity() - out.position());
+ assertEquals(out.capacity(), 100);
+ assertCharBufferValue(out, unistr + unistr + unistr);
+
+ // overflow
+ out = CharBuffer.allocate(4);
+ decoder.reset();
+ in = ByteBuffer.wrap(getUnibytes());
+ out.rewind();
+ assertSame(CoderResult.OVERFLOW, decoder.decode(in, out, false));
+
+ assertEquals(new String(out.array()), unistr.substring(0, 4));
+ out = CharBuffer.allocate(100);
+ assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, false));
+ assertCharBufferValue(out, unistr.substring(4));
+ in.rewind();
+ out = CharBuffer.allocate(100);
+ assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, true));
+ assertCharBufferValue(out, bom + unistr);
+ }
+
+ public void testDecodeCharBufferByteBufferbooleanExceptionTrue()
+ throws CharacterCodingException, UnsupportedEncodingException {
+ implTestDecodeCharBufferByteBufferbooleanException(true);
+ }
+
+ public void testDecodeCharBufferByteBufferbooleanExceptionFalse()
+ throws CharacterCodingException, UnsupportedEncodingException {
+ implTestDecodeCharBufferByteBufferbooleanException(false);
+ }
+
+ void implTestDecodeCharBufferByteBufferbooleanException(boolean endOfInput)
+ throws CharacterCodingException, UnsupportedEncodingException {
+ CharBuffer out;
+ ByteBuffer in;
+
+ // Unmapped Exception:
+ in = getUnmappedByteBuffer();
+ out = CharBuffer.allocate(50);
+ decoder.onMalformedInput(CodingErrorAction.REPORT);
+ if (null != in) {
+ decoder.reset();
+ decoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+ CoderResult result = decoder.decode(in, out, endOfInput);
+ assertTrue(result.isUnmappable());
+
+ decoder.reset();
+ out.clear();
+ in.rewind();
+ decoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
+ assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out,
+ endOfInput));
+ assertCharBufferValue(out, " buffer");
+
+ decoder.reset();
+ out.clear();
+ in.rewind();
+ decoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
+ assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out,
+ endOfInput));
+ assertCharBufferValue(out, decoder.replacement() + " buffer");
+ } else if (endOfInput) {
+ // System.err.println("Cannot find unmappable byte array for "
+ // + cs.name());
+ }
+
+ // MalformedException:
+ in = getMalformByteBuffer();
+ out = CharBuffer.allocate(50);
+ decoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+ if (null != in) {
+ decoder.onMalformedInput(CodingErrorAction.REPORT);
+ CoderResult result = decoder.decode(in, out, endOfInput);
+ assertTrue(result.isMalformed());
+
+ decoder.reset();
+ out.clear();
+ in.rewind();
+ decoder.onMalformedInput(CodingErrorAction.IGNORE);
+ assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out,
+ endOfInput));
+ assertCharBufferValue(out, " buffer");
+
+ decoder.reset();
+ out.clear();
+ in.rewind();
+ decoder.onMalformedInput(CodingErrorAction.REPLACE);
+ assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out,
+ endOfInput));
+ assertCharBufferValue(out, decoder.replacement() + " buffer");
+ } else if (endOfInput) {
+ // System.err.println("Cannot find malform byte array for "
+ // + cs.name());
+ }
+
+ // RuntimeException
+ in = getExceptionByteArray();
+ try {
+ decoder.decode(in, out, endOfInput);
+ fail("should throw runtime exception");
+ } catch (RuntimeException e) {
+ }
+ }
+
+ ByteBuffer getExceptionByteArray() throws UnsupportedEncodingException {
+ // "runtime"
+ return ByteBuffer
+ .wrap(new byte[] { 114, 117, 110, 116, 105, 109, 101 });
+ }
+
+ ByteBuffer getUnmappedByteBuffer() throws UnsupportedEncodingException {
+ // "unmap buffer"
+ byte[] ba = new byte[] { 117, 110, 109, 97, 112, 32, 98, 117, 102, 102,
+ 101, 114 };
+ return ByteBuffer.wrap(ba);
+ }
+
+ ByteBuffer getMalformByteBuffer() throws UnsupportedEncodingException {
+ // "malform buffer"
+ byte[] ba = new byte[] { 109, 97, 108, 102, 111, 114, 109, 32, 98, 117,
+ 102, 102, 101, 114 };
+ return ByteBuffer.wrap(ba);
+ }
+
+ void assertCharBufferValue(CharBuffer out, String expected) {
+ if (out.position() != 0) {
+ out.flip();
+ }
+ assertEquals(new String(out.array(), 0, out.limit()), expected);
+ }
+
+ /*
+ * test flush
+ */
+ public void testFlush() throws CharacterCodingException {
+ CharBuffer out = CharBuffer.allocate(10);
+ ByteBuffer in = ByteBuffer.wrap(new byte[] { 12, 12 });
+ decoder.decode(in, out, true);
+ assertSame(CoderResult.UNDERFLOW, decoder.flush(out));
+
+ decoder.reset();
+ decoder.decode((ByteBuffer) in.rewind(), (CharBuffer) out.rewind(),
+ true);
+ assertSame(CoderResult.UNDERFLOW, decoder
+ .flush(CharBuffer.allocate(10)));
+ }
+
+ /*
+ * ---------------------------------- methods to test illegal state
+ * -----------------------------------
+ */
+ // Normal case: just after reset, and it also means reset can be done
+ // anywhere
+ public void testResetIllegalState() throws CharacterCodingException {
+ byte[] gb = getUnibytes();
+ decoder.reset();
+ decoder.decode(ByteBuffer.wrap(gb));
+ decoder.reset();
+ decoder.decode(ByteBuffer.wrap(gb), CharBuffer.allocate(3), false);
+ decoder.reset();
+ decoder.decode(ByteBuffer.wrap(gb), CharBuffer.allocate(3), true);
+ decoder.reset();
+ }
+
+ public void testFlushIllegalState() throws CharacterCodingException {
+ ByteBuffer in = ByteBuffer.wrap(new byte[] { 98, 98 });
+ CharBuffer out = CharBuffer.allocate(5);
+ // Normal case: after decode with endOfInput is true
+ decoder.reset();
+ decoder.decode(in, out, true);
+ out.rewind();
+ CoderResult result = decoder.flush(out);
+ assertSame(result, CoderResult.UNDERFLOW);
+
+ // Illegal state: flush twice
+ try {
+ decoder.flush(out);
+ fail("should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ }
+
+ // Illegal state: flush after decode with endOfInput is false
+ decoder.reset();
+ decoder.decode(in, out, false);
+ try {
+ decoder.flush(out);
+ fail("should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ }
+ }
+
+ byte[] getUnibytes() {
+ return unibytes;
+ }
+
+ // test illegal states for decode facade
+ public void testDecodeFacadeIllegalState() throws CharacterCodingException {
+ // decode facade can be execute in anywhere
+ byte[] gb = getUnibytes();
+ ByteBuffer in = ByteBuffer.wrap(gb);
+ // Normal case: just created
+ decoder.decode(in);
+ in.rewind();
+
+ // Normal case: just after decode facade
+ decoder.decode(in);
+ in.rewind();
+
+ // Normal case: just after decode with that endOfInput is true
+ decoder.reset();
+ decoder.decode(ByteBuffer.wrap(gb), CharBuffer.allocate(30), true);
+ decoder.decode(in);
+ in.rewind();
+
+ // Normal case:just after decode with that endOfInput is false
+ decoder.reset();
+ decoder.decode(ByteBuffer.wrap(gb), CharBuffer.allocate(30), false);
+ decoder.decode(in);
+ in.rewind();
+
+ // Normal case: just after flush
+ decoder.reset();
+ decoder.decode(ByteBuffer.wrap(gb), CharBuffer.allocate(30), true);
+ decoder.flush(CharBuffer.allocate(10));
+ decoder.decode(in);
+ in.rewind();
+ }
+
+ // test illegal states for two decode method with endOfInput is true
+ public void testDecodeTrueIllegalState() throws CharacterCodingException {
+ ByteBuffer in = ByteBuffer.wrap(new byte[] { 98, 98 });
+ CharBuffer out = CharBuffer.allocate(100);
+ // Normal case: just created
+ decoder.decode(in, out, true);
+ in.rewind();
+ out.rewind();
+
+ // Normal case: just after decode with that endOfInput is true
+ decoder.reset();
+ decoder.decode(in, CharBuffer.allocate(30), true);
+ in.rewind();
+ decoder.decode(in, out, true);
+ in.rewind();
+ out.rewind();
+
+ // Normal case:just after decode with that endOfInput is false
+ decoder.reset();
+ decoder.decode(in, CharBuffer.allocate(30), false);
+ in.rewind();
+ decoder.decode(in, out, true);
+ in.rewind();
+ out.rewind();
+
+ // Illegal state: just after flush
+ decoder.reset();
+ decoder.decode(in, CharBuffer.allocate(30), true);
+ decoder.flush(CharBuffer.allocate(10));
+ in.rewind();
+ try {
+ decoder.decode(in, out, true);
+ fail("should illegal state");
+ } catch (IllegalStateException e) {
+ }
+ in.rewind();
+ out.rewind();
+
+ }
+
+ // test illegal states for two decode method with endOfInput is false
+ public void testDecodeFalseIllegalState() throws CharacterCodingException {
+ ByteBuffer in = ByteBuffer.wrap(new byte[] { 98, 98 });
+ CharBuffer out = CharBuffer.allocate(5);
+ // Normal case: just created
+ decoder.decode(in, out, false);
+ in.rewind();
+ out.rewind();
+
+ // Illegal state: just after decode facade
+ decoder.reset();
+ decoder.decode(in);
+ in.rewind();
+ try {
+ decoder.decode(in, out, false);
+ fail("should illegal state");
+ } catch (IllegalStateException e) {
+ }
+ in.rewind();
+ out.rewind();
+
+ // Illegal state: just after decode with that endOfInput is true
+ decoder.reset();
+ decoder.decode(in, CharBuffer.allocate(30), true);
+ in.rewind();
+ try {
+ decoder.decode(in, out, false);
+ fail("should illegal state");
+ } catch (IllegalStateException e) {
+ }
+ in.rewind();
+ out.rewind();
+
+ // Normal case:just after decode with that endOfInput is false
+ decoder.reset();
+ decoder.decode(in, CharBuffer.allocate(30), false);
+ in.rewind();
+ decoder.decode(in, out, false);
+ in.rewind();
+ out.rewind();
+
+ // Illegal state: just after flush
+ decoder.reset();
+ decoder.decode(in, CharBuffer.allocate(30), true);
+ in.rewind();
+ decoder.flush(CharBuffer.allocate(10));
+ try {
+ decoder.decode(in, out, false);
+ fail("should illegal state");
+ } catch (IllegalStateException e) {
+ }
+ }
+
+ /*
+ * --------------------------------- illegal state test end
+ * ---------------------------------
+ */
+
+ public void testImplFlush() {
+ decoder = new MockCharsetDecoder(cs, 1, 3);
+ assertEquals(CoderResult.UNDERFLOW, ((MockCharsetDecoder) decoder)
+ .pubImplFlush(null));
+ }
+
+ public void testImplOnMalformedInput() {
+ decoder = new MockCharsetDecoder(cs, 1, 3);
+ assertEquals(CoderResult.UNDERFLOW, ((MockCharsetDecoder) decoder)
+ .pubImplFlush(null));
+
+ }
+
+ public void testImplOnUnmappableCharacter() {
+ decoder = new MockCharsetDecoder(cs, 1, 3);
+ ((MockCharsetDecoder) decoder).pubImplOnUnmappableCharacter(null);
+ }
+
+ public void testImplReplaceWith() {
+ decoder = new MockCharsetDecoder(cs, 1, 3);
+ ((MockCharsetDecoder) decoder).pubImplReplaceWith(null);
+ }
+
+ public void testImplReset() {
+ decoder = new MockCharsetDecoder(cs, 1, 3);
+ ((MockCharsetDecoder) decoder).pubImplReset();
+ }
+
+ /*
+ * mock decoder
+ */
+ public static class MockCharsetDecoder extends CharsetDecoder {
+ public MockCharsetDecoder(Charset cs, float ave, float max) {
+ super(cs, ave, max);
+ }
+
+ protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) {
+ int inPosition = in.position();
+ byte[] input = new byte[in.remaining()];
+ in.get(input);
+ String result = new String(input);
+ if (result.startsWith("malform")) {
+ // reset the cursor to the error position
+ in.position(inPosition + "malform".length());
+ // set the error length
+ return CoderResult.malformedForLength("malform".length());
+ } else if (result.startsWith("unmap")) {
+ // reset the cursor to the error position
+ in.position(inPosition);
+ // set the error length
+ return CoderResult.unmappableForLength("unmap".length());
+ } else if (result.startsWith("runtime")) {
+ // reset the cursor to the error position
+ in.position(0);
+ // set the error length
+ throw new RuntimeException("runtime");
+ }
+ int inLeft = input.length;
+ int outLeft = out.remaining();
+ CoderResult r = CoderResult.UNDERFLOW;
+ int length = inLeft;
+ if (outLeft < inLeft) {
+ r = CoderResult.OVERFLOW;
+ length = outLeft;
+ in.position(inPosition + outLeft);
+ }
+ for (int i = 0; i < length; i++) {
+ out.put((char) input[i]);
+ }
+ return r;
+ }
+
+ protected CoderResult implFlush(CharBuffer out) {
+ CoderResult result = super.implFlush(out);
+ if (out.remaining() >= 5) {
+ // TODO
+ // out.put("flush");
+ result = CoderResult.UNDERFLOW;
+ } else {
+ // out.put("flush", 0, out.remaining());
+ result = CoderResult.OVERFLOW;
+ }
+ return result;
+ }
+
+ public CoderResult pubImplFlush(CharBuffer out) {
+ return super.implFlush(out);
+ }
+
+ public void pubImplOnMalformedInput(CodingErrorAction newAction) {
+ super.implOnMalformedInput(newAction);
+ }
+
+ public void pubImplOnUnmappableCharacter(CodingErrorAction newAction) {
+ super.implOnUnmappableCharacter(newAction);
+ }
+
+ public void pubImplReplaceWith(String newReplacement) {
+ super.implReplaceWith(newReplacement);
+ }
+
+ public void pubImplReset() {
+ super.implReset();
+ }
+
+ }
+
+}
diff --git a/nio_char/src/test/java/tests/api/java/nio/charset/CharsetEncoderTest.java b/nio_char/src/test/java/tests/api/java/nio/charset/CharsetEncoderTest.java
new file mode 100644
index 0000000..3284a57
--- /dev/null
+++ b/nio_char/src/test/java/tests/api/java/nio/charset/CharsetEncoderTest.java
@@ -0,0 +1,1103 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package tests.api.java.nio.charset;
+
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.MalformedInputException;
+import java.nio.charset.UnmappableCharacterException;
+import java.nio.charset.UnsupportedCharsetException;
+import java.util.Arrays;
+
+import junit.framework.TestCase;
+
+/**
+ * API unit test for java.nio.charset.CharsetEncoder
+ */
+public class CharsetEncoderTest extends TestCase {
+
+ static final int MAX_BYTES = 3;
+
+ static final float AVER_BYTES = 0.5f;
+
+ // charset for mock class
+ private static final Charset MOCKCS = new MockCharset("CharsetEncoderTest_mock", new String[0]);
+
+ Charset cs = MOCKCS;
+
+ // default encoder
+ CharsetEncoder encoder;
+
+ // default for Charset abstract class
+ byte[] defaultReplacement = new byte[] { 63 };
+
+ // specific for Charset implementation subclass
+ byte[] specifiedReplacement = new byte[] { 26 };
+
+ static final String unistr = " buffer";// \u8000\u8001\u00a5\u3000\r\n";
+
+ byte[] unibytes = new byte[] { 32, 98, 117, 102, 102, 101, 114 };
+
+ byte[] unibytesWithRep = null;
+
+ byte[] surrogate = new byte[0];
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ encoder = cs.newEncoder();
+ if (null == unibytesWithRep) {
+ byte[] replacement = encoder.replacement();
+ unibytesWithRep = new byte[replacement.length + unibytes.length];
+ System.arraycopy(replacement, 0, unibytesWithRep, 0,
+ replacement.length);
+ System.arraycopy(unibytes, 0, unibytesWithRep, replacement.length,
+ unibytes.length);
+ }
+ }
+
+ /*
+ * @see TestCase#tearDown()
+ */
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testSpecificDefaultValue() {
+ assertTrue(encoder.averageBytesPerChar() == AVER_BYTES);
+ assertTrue(encoder.maxBytesPerChar() == MAX_BYTES);
+ }
+
+ public void testDefaultValue() {
+ assertEquals(CodingErrorAction.REPORT, encoder.malformedInputAction());
+ assertEquals(CodingErrorAction.REPORT, encoder
+ .unmappableCharacterAction());
+ assertSame(encoder, encoder.onMalformedInput(CodingErrorAction.IGNORE));
+ assertSame(encoder, encoder
+ .onUnmappableCharacter(CodingErrorAction.IGNORE));
+ if (encoder instanceof MockCharsetEncoder) {
+ assertTrue(Arrays.equals(encoder.replacement(), defaultReplacement));
+ } else {
+ assertTrue(Arrays.equals(encoder.replacement(),
+ specifiedReplacement));
+ }
+
+ }
+
+ /*
+ * Class under test for constructor CharsetEncoder(Charset, float, float)
+ */
+ public void testCharsetEncoderCharsetfloatfloat() {
+ // default value
+ encoder = new MockCharsetEncoder(cs, (float) AVER_BYTES, MAX_BYTES);
+ assertSame(encoder.charset(), cs);
+ assertTrue(encoder.averageBytesPerChar() == AVER_BYTES);
+ assertTrue(encoder.maxBytesPerChar() == MAX_BYTES);
+ assertEquals(CodingErrorAction.REPORT, encoder.malformedInputAction());
+ assertEquals(CodingErrorAction.REPORT, encoder
+ .unmappableCharacterAction());
+ assertEquals(new String(encoder.replacement()), new String(
+ defaultReplacement));
+ assertSame(encoder, encoder.onMalformedInput(CodingErrorAction.IGNORE));
+ assertSame(encoder, encoder
+ .onUnmappableCharacter(CodingErrorAction.IGNORE));
+
+ // normal case
+ CharsetEncoder ec = new MockCharsetEncoder(cs, 1, MAX_BYTES);
+ assertSame(ec.charset(), cs);
+ assertEquals(1.0, ec.averageBytesPerChar(), 0);
+ assertTrue(ec.maxBytesPerChar() == MAX_BYTES);
+
+ /*
+ * ------------------------ Exceptional cases -------------------------
+ */
+ // NullPointerException: null charset
+ try {
+ ec = new MockCharsetEncoder(null, 1, MAX_BYTES);
+ fail("should throw null pointer exception");
+ } catch (NullPointerException e) {
+ }
+
+ ec = new MockCharsetEncoder(new MockCharset("mock", new String[0]), 1,
+ MAX_BYTES);
+
+ // Commented out since the comment is wrong since MAX_BYTES > 1
+ // // OK: average length less than max length
+ // ec = new MockCharsetEncoder(cs, MAX_BYTES, 1);
+ // assertTrue(ec.averageBytesPerChar() == MAX_BYTES);
+ // assertTrue(ec.maxBytesPerChar() == 1);
+
+ // Illegal Argument: zero length
+ try {
+ ec = new MockCharsetEncoder(cs, 0, MAX_BYTES);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ }
+ try {
+ ec = new MockCharsetEncoder(cs, 1, 0);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ }
+
+ // Illegal Argument: negative length
+ try {
+ ec = new MockCharsetEncoder(cs, -1, MAX_BYTES);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ }
+ try {
+ ec = new MockCharsetEncoder(cs, 1, -1);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ }
+ }
+
+ /*
+ * Class under test for constructor CharsetEncoder(Charset, float, float,
+ * byte[])
+ */
+ public void testCharsetEncoderCharsetfloatfloatbyteArray() {
+ byte[] ba = getLegalByteArray();
+ // normal case
+ CharsetEncoder ec = new MockCharsetEncoder(cs, 1, MAX_BYTES, ba);
+ assertSame(ec.charset(), cs);
+ assertEquals(1.0, ec.averageBytesPerChar(), 0.0);
+ assertTrue(ec.maxBytesPerChar() == MAX_BYTES);
+ assertSame(ba, ec.replacement());
+
+ /*
+ * ------------------------ Exceptional cases -------------------------
+ */
+ // NullPointerException: null charset
+ try {
+ ec = new MockCharsetEncoder(null, 1, MAX_BYTES, ba);
+ fail("should throw null pointer exception");
+ } catch (NullPointerException e) {
+ }
+
+ // Illegal Argument: null byte array
+ try {
+ ec = new MockCharsetEncoder(cs, 1, MAX_BYTES, null);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ }
+ // Illegal Argument: empty byte array
+ try {
+ ec = new MockCharsetEncoder(cs, 1, MAX_BYTES, new byte[0]);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ }
+ // Illegal Argument: byte array is longer than max length
+ try {
+ ec = new MockCharsetEncoder(cs, 1, MAX_BYTES, new byte[] { 1, 2,
+ MAX_BYTES, 4 });
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ }
+
+ // Commented out since the comment is wrong since MAX_BYTES > 1
+ // This test throws IllegalArgumentException on Harmony and RI
+ // // OK: average length less than max length
+ // ec = new MockCharsetEncoder(cs, MAX_BYTES, ba.length, ba);
+ // assertTrue(ec.averageBytesPerChar() == MAX_BYTES);
+ // assertTrue(ec.maxBytesPerChar() == ba.length);
+
+ // Illegal Argument: zero length
+ try {
+ ec = new MockCharsetEncoder(cs, 0, MAX_BYTES, ba);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ }
+ try {
+ ec = new MockCharsetEncoder(cs, 1, 0, ba);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ }
+
+ // Illegal Argument: negative length
+ try {
+ ec = new MockCharsetEncoder(cs, -1, MAX_BYTES, ba);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ }
+ try {
+ ec = new MockCharsetEncoder(cs, 1, -1, ba);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ }
+ }
+
+ /*
+ * Class under test for boolean canEncode(char)
+ */
+ public void testCanEncodechar() throws CharacterCodingException {
+ // for non-mapped char
+ assertTrue(encoder.canEncode('\uc2c0'));
+ // surrogate char for unicode
+ // 1st byte: d800-dbff
+ // 2nd byte: dc00-dfff
+ assertTrue(encoder.canEncode('\ud800'));
+ // valid surrogate pair
+ assertTrue(encoder.canEncode('\udc00'));
+ }
+
+ /*-----------------------------------------
+ * Class under test for illegal state case
+ * methods which can change internal states are two encode, flush, two canEncode, reset
+ * -----------------------------------------
+ */
+
+ // Normal case: just after reset, and it also means reset can be done
+ // anywhere
+ public void testResetIllegalState() throws CharacterCodingException {
+ assertSame(encoder, encoder.reset());
+ encoder.canEncode('\ud901');
+ assertSame(encoder, encoder.reset());
+ encoder.canEncode("\ud901\udc00");
+ assertSame(encoder, encoder.reset());
+ encoder.encode(CharBuffer.wrap("aaa"));
+ assertSame(encoder, encoder.reset());
+ encoder.encode(CharBuffer.wrap("aaa"), ByteBuffer.allocate(3), false);
+ assertSame(encoder, encoder.reset());
+ encoder.encode(CharBuffer.wrap("aaa"), ByteBuffer.allocate(3), true);
+ assertSame(encoder, encoder.reset());
+ }
+
+ public void testFlushIllegalState() throws CharacterCodingException {
+ CharBuffer in = CharBuffer.wrap("aaa");
+ ByteBuffer out = ByteBuffer.allocate(5);
+
+ // Normal case: after encode with endOfInput is true
+ assertSame(encoder, encoder.reset());
+ encoder.encode(in, out, true);
+ out.rewind();
+ CoderResult result = encoder.flush(out);
+
+ // Illegal state: flush twice
+ try {
+ encoder.flush(out);
+ fail("should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ }
+
+ // Illegal state: flush after encode with endOfInput is false
+ assertSame(encoder, encoder.reset());
+ encoder.encode(in, out, false);
+ try {
+ encoder.flush(out);
+ fail("should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ }
+ }
+
+ // test illegal states for encode facade
+ public void testEncodeFacadeIllegalState() throws CharacterCodingException {
+ // encode facade can be execute in anywhere
+ CharBuffer in = CharBuffer.wrap("aaa");
+ // Normal case: just created
+ encoder.encode(in);
+ in.rewind();
+
+ // Normal case: just after encode facade
+ encoder.encode(in);
+ in.rewind();
+
+ // Normal case: just after canEncode
+ assertSame(encoder, encoder.reset());
+ encoder.canEncode("\ud902\udc00");
+ encoder.encode(in);
+ in.rewind();
+ assertSame(encoder, encoder.reset());
+ encoder.canEncode('\ud902');
+ encoder.encode(in);
+ in.rewind();
+
+ // Normal case: just after encode with that endOfInput is true
+ assertSame(encoder, encoder.reset());
+ encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState2"),
+ ByteBuffer.allocate(30), true);
+ encoder.encode(in);
+ in.rewind();
+
+ // Normal case:just after encode with that endOfInput is false
+ assertSame(encoder, encoder.reset());
+ encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState3"),
+ ByteBuffer.allocate(30), false);
+ encoder.encode(in);
+ in.rewind();
+
+ // Normal case: just after flush
+ assertSame(encoder, encoder.reset());
+ encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState4"),
+ ByteBuffer.allocate(30), true);
+ encoder.flush(ByteBuffer.allocate(10));
+ encoder.encode(in);
+ in.rewind();
+ }
+
+ // test illegal states for two encode method with endOfInput is true
+ public void testEncodeTrueIllegalState() throws CharacterCodingException {
+ CharBuffer in = CharBuffer.wrap("aaa");
+ ByteBuffer out = ByteBuffer.allocate(5);
+ // Normal case: just created
+ encoder.encode(in, out, true);
+ in.rewind();
+ out.rewind();
+
+ in.rewind();
+ out.rewind();
+
+ // Normal case: just after encode with that endOfInput is true
+ assertSame(encoder, encoder.reset());
+ encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState2"),
+ ByteBuffer.allocate(30), true);
+ encoder.encode(in, out, true);
+ in.rewind();
+ out.rewind();
+
+ // Normal case:just after encode with that endOfInput is false
+ assertSame(encoder, encoder.reset());
+ encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState3"),
+ ByteBuffer.allocate(30), false);
+ encoder.encode(in, out, true);
+ in.rewind();
+ out.rewind();
+
+ // Illegal state: just after flush
+ assertSame(encoder, encoder.reset());
+ encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState4"),
+ ByteBuffer.allocate(30), true);
+ encoder.flush(ByteBuffer.allocate(10));
+ try {
+ encoder.encode(in, out, true);
+ fail("should illegal state");
+ } catch (IllegalStateException e) {
+ }
+
+ // Normal case: after canEncode
+ assertSame(encoder, encoder.reset());
+ encoder.canEncode("\ud906\udc00");
+ encoder.encode(in, out, true);
+ in.rewind();
+ out.rewind();
+ assertSame(encoder, encoder.reset());
+ encoder.canEncode('\ud905');
+ encoder.encode(in, out, true);
+ }
+
+ // test illegal states for two encode method with endOfInput is false
+ public void testEncodeFalseIllegalState() throws CharacterCodingException {
+ CharBuffer in = CharBuffer.wrap("aaa");
+ ByteBuffer out = ByteBuffer.allocate(5);
+ // Normal case: just created
+ encoder.encode(in, out, false);
+ in.rewind();
+ out.rewind();
+
+ // Illegal state: just after encode facade
+ assertSame(encoder, encoder.reset());
+ encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState1"));
+ try {
+ encoder.encode(in, out, false);
+ fail("should illegal state");
+ } catch (IllegalStateException e) {
+ }
+
+ // Illegal state: just after encode with that endOfInput is true
+ assertSame(encoder, encoder.reset());
+ encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState2"),
+ ByteBuffer.allocate(30), true);
+ try {
+ encoder.encode(in, out, false);
+ fail("should illegal state");
+ } catch (IllegalStateException e) {
+ }
+
+ // Normal case:just after encode with that endOfInput is false
+ assertSame(encoder, encoder.reset());
+ encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState3"),
+ ByteBuffer.allocate(30), false);
+ encoder.encode(in, out, false);
+ in.rewind();
+ out.rewind();
+
+ // Illegal state: just after flush
+ assertSame(encoder, encoder.reset());
+ encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState4"),
+ ByteBuffer.allocate(30), true);
+ encoder.flush(ByteBuffer.allocate(10));
+ try {
+ encoder.encode(in, out, false);
+ fail("should illegal state");
+ } catch (IllegalStateException e) {
+ }
+
+ // Normal case: after canEncode
+ assertSame(encoder, encoder.reset());
+ encoder.canEncode("\ud906\udc00");
+ encoder.encode(in, out, false);
+ in.rewind();
+ out.rewind();
+ assertSame(encoder, encoder.reset());
+ encoder.canEncode('\ud905');
+ encoder.encode(in, out, false);
+ }
+
+ // test illegal states for two canEncode methods
+ public void testCanEncodeIllegalState() throws CharacterCodingException {
+ // Normal case: just created
+ encoder.canEncode("\ud900\udc00");
+ encoder.canEncode('\ud900');
+
+ // Illegal state: just after encode with that endOfInput is true
+ assertSame(encoder, encoder.reset());
+ encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState2"),
+ ByteBuffer.allocate(30), true);
+ try {
+ encoder.canEncode("\ud903\udc00");
+ fail("should throw illegal state exception");
+ } catch (IllegalStateException e) {
+ }
+
+ // Illegal state:just after encode with that endOfInput is false
+ assertSame(encoder, encoder.reset());
+ encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState3"),
+ ByteBuffer.allocate(30), false);
+ try {
+ encoder.canEncode("\ud904\udc00");
+ fail("should throw illegal state exception");
+ } catch (IllegalStateException e) {
+ }
+
+ // Normal case: just after flush
+ encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState4"),
+ ByteBuffer.allocate(30), true);
+ encoder.flush(ByteBuffer.allocate(10));
+ encoder.canEncode("\ud905\udc00");
+ encoder.canEncode('\ud906');
+
+ // Normal case: after reset again
+ assertSame(encoder, encoder.reset());
+ encoder.canEncode("\ud906\udc00");
+ encoder.canEncode('\ud905');
+ }
+
+ /*
+ * --------------------------------- illegal state test end
+ * ---------------------------------
+ */
+
+ /*
+ * Class under test for boolean canEncode(CharSequence)
+ */
+ public void testCanEncodeCharSequence() {
+ // for non-mapped char
+ assertTrue(encoder.canEncode("\uc2c0"));
+ // surrogate char for unicode
+ // 1st byte: d800-dbff
+ // 2nd byte: dc00-dfff
+ assertTrue(encoder.canEncode("\ud800"));
+ // valid surrogate pair
+ assertTrue(encoder.canEncode("\ud800\udc00"));
+ // invalid surrogate pair
+ assertTrue(encoder.canEncode("\ud800\udb00"));
+ }
+
+ /*
+ * Class under test for Charset charset()
+ */
+ public void testCharset() {
+ try {
+ encoder = new MockCharsetEncoder(Charset.forName("gbk"), 1,
+ MAX_BYTES);
+ // assertSame(encoder.charset(), Charset.forName("gbk"));
+ } catch (UnsupportedCharsetException e) {
+ // System.err
+ // .println("Don't support GBK encoding, ignore current test");
+ }
+ }
+
+ /*
+ * Class under test for ByteBuffer encode(CharBuffer)
+ */
+ public void testEncodeCharBuffer() throws CharacterCodingException {
+ // Null pointer
+ try {
+ encoder.encode(null);
+ fail("should throw null pointer exception");
+ } catch (NullPointerException e) {
+ }
+
+ // empty input buffer
+ ByteBuffer out = encoder.encode(CharBuffer.wrap(""));
+ assertEquals(out.position(), 0);
+ assertByteArray(out, new byte[0]);
+ // assertByteArray(out, surrogate);
+
+ // normal case
+ out = encoder.encode(CharBuffer.wrap(unistr));
+ assertEquals(out.position(), 0);
+ assertByteArray(out, addSurrogate(unibytes));
+
+ // Regression test for harmony-3378
+ Charset cs = Charset.forName("UTF-8");
+ CharsetEncoder encoder = cs.newEncoder();
+ encoder.onMalformedInput(CodingErrorAction.REPLACE);
+ encoder = encoder.replaceWith(new byte[] { (byte) 0xef, (byte) 0xbf,
+ (byte) 0xbd, });
+ CharBuffer in = CharBuffer.wrap("\ud800");
+ out = encoder.encode(in);
+ assertNotNull(out);
+ }
+
+ private byte[] addSurrogate(byte[] expected) {
+ if (surrogate.length > 0) {
+ byte[] temp = new byte[surrogate.length + expected.length];
+ System.arraycopy(surrogate, 0, temp, 0, surrogate.length);
+ System.arraycopy(expected, 0, temp, surrogate.length,
+ expected.length);
+ expected = temp;
+ }
+ return expected;
+ }
+
+ /**
+ * @return
+ */
+ protected byte[] getEmptyByteArray() {
+ return new byte[0];
+ }
+
+ CharBuffer getMalformedCharBuffer() {
+ return CharBuffer.wrap("malform buffer");
+ }
+
+ CharBuffer getUnmapCharBuffer() {
+ return CharBuffer.wrap("unmap buffer");
+ }
+
+ CharBuffer getExceptionCharBuffer() {
+ return CharBuffer.wrap("runtime buffer");
+ }
+
+ public void testEncodeCharBufferException() throws CharacterCodingException {
+ ByteBuffer out;
+ CharBuffer in;
+ // MalformedException:
+ in = getMalformedCharBuffer();
+ encoder.onMalformedInput(CodingErrorAction.REPORT);
+ encoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+ if (in != null) {
+ try {
+ // regression test for Harmony-1379
+ encoder.encode(in);
+ fail("should throw MalformedInputException");
+ } catch (MalformedInputException e) {
+ }
+
+ encoder.reset();
+ in.rewind();
+ encoder.onMalformedInput(CodingErrorAction.IGNORE);
+ out = encoder.encode(in);
+ assertByteArray(out, addSurrogate(unibytes));
+
+ encoder.reset();
+ in.rewind();
+ encoder.onMalformedInput(CodingErrorAction.REPLACE);
+ out = encoder.encode(in);
+ assertByteArray(out, addSurrogate(unibytesWithRep));
+ }
+
+ // Unmapped Exception:
+ in = getUnmapCharBuffer();
+ encoder.onMalformedInput(CodingErrorAction.REPORT);
+ encoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+ if (in != null) {
+ encoder.reset();
+ try {
+ encoder.encode(in);
+ fail("should throw UnmappableCharacterException");
+ } catch (UnmappableCharacterException e) {
+ }
+
+ encoder.reset();
+ in.rewind();
+ encoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
+ out = encoder.encode(in);
+ assertByteArray(out, unibytes);
+
+ encoder.reset();
+ in.rewind();
+ encoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
+ out = encoder.encode(in);
+ assertByteArray(out, unibytesWithRep);
+ }
+
+ // RuntimeException
+ try {
+ encoder.encode(getExceptionCharBuffer());
+ fail("should throw runtime exception");
+ } catch (RuntimeException e) {
+ }
+ }
+
+ /*
+ * utility method, extract given bytebuffer to a string and compare with
+ * give string
+ */
+ void assertByteArray(ByteBuffer out, byte[] expected) {
+ out = out.duplicate();
+ if (out.position() != 0) {
+ out.flip();
+ }
+ byte[] ba = new byte[out.limit() - out.position()];
+ out.get(ba);
+ // byte[] ba = out.array();
+ assertTrue(Arrays.equals(ba, expected));
+ }
+
+ /*
+ * Class under test for CoderResult encode(CharBuffer, ByteBuffer, boolean)
+ */
+ public void testEncodeCharBufferByteBufferboolean()
+ throws CharacterCodingException {
+ ByteBuffer out = ByteBuffer.allocate(200);
+ CharBuffer in = CharBuffer.wrap(unistr);
+ // Null pointer
+ try {
+ encoder.encode(null, out, true);
+ fail("should throw null pointer exception");
+ } catch (NullPointerException e) {
+ }
+ try {
+ encoder.encode(in, null, true);
+ fail("should throw null pointer exception");
+ } catch (NullPointerException e) {
+ }
+
+ // normal case, one complete operation
+ assertSame(encoder, encoder.reset());
+ in.rewind();
+ out.rewind();
+ assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out, true));
+ assertEquals(out.limit(), 200);
+ assertTrue(out.position() > 0);
+ assertTrue(out.remaining() > 0);
+ assertEquals(out.capacity(), 200);
+ assertByteArray(out, addSurrogate(unibytes));
+ in.rewind();
+
+ encoder.flush(out);
+
+ // normal case, one complete operation, but call twice, first time set
+ // endOfInput to false
+ assertSame(encoder, encoder.reset());
+ in.rewind();
+ out = ByteBuffer.allocate(200);
+ assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out, false));
+ assertEquals(out.limit(), 200);
+ assertTrue(out.position() > 0);
+ assertTrue(out.remaining() > 0);
+ assertEquals(out.capacity(), 200);
+ assertByteArray(out, addSurrogate(unibytes));
+
+ in.rewind();
+ assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out, false));
+ in.rewind();
+ assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out, true));
+ assertEquals(out.limit(), 200);
+ assertTrue(out.position() > 0);
+ assertTrue(out.remaining() > 0);
+ assertEquals(out.capacity(), 200);
+
+ assertByteArray(out, addSurrogate(duplicateByteArray(unibytes, 3)));
+
+ // overflow
+ out = ByteBuffer.allocate(4);
+ assertSame(encoder, encoder.reset());
+ in.rewind();
+ out.rewind();
+ assertSame(CoderResult.OVERFLOW, encoder.encode(in, out, true));
+ assertEquals(out.limit(), 4);
+ assertEquals(out.position(), 4);
+ assertEquals(out.remaining(), 0);
+ assertEquals(out.capacity(), 4);
+ ByteBuffer temp = ByteBuffer.allocate(200);
+ out.flip();
+ temp.put(out);
+ out = temp;
+ assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out, true));
+ assertEquals(out.limit(), 200);
+ assertTrue(out.position() > 0);
+ assertTrue(out.remaining() > 0);
+ assertEquals(out.capacity(), 200);
+ assertByteArray(out, addSurrogate(unibytes));
+
+ assertSame(encoder, encoder.reset());
+ in.rewind();
+ out = ByteBuffer.allocate(4);
+ assertSame(CoderResult.OVERFLOW, encoder.encode(in, out, false));
+ assertEquals(out.limit(), 4);
+ assertEquals(out.position(), 4);
+ assertEquals(out.remaining(), 0);
+ assertEquals(out.capacity(), 4);
+ temp = ByteBuffer.allocate(200);
+ out.flip();
+ temp.put(out);
+ out = temp;
+ assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out, false));
+ assertEquals(out.limit(), 200);
+ assertTrue(out.position() > 0);
+ assertTrue(out.remaining() > 0);
+ assertEquals(out.capacity(), 200);
+ assertByteArray(out, addSurrogate(unibytes));
+ }
+
+ void printByteBuffer(ByteBuffer buffer) {
+ System.out.println("print buffer");
+ if (buffer.position() != 0) {
+ buffer.flip();
+ }
+ byte[] ba = buffer.array();
+ for (int i = 0; i < ba.length; i++) {
+ System.out.println(Integer.toHexString(ba[i]));
+ }
+ }
+
+ public void testEncodeCharBufferByteBufferbooleanExceptionFalse()
+ throws CharacterCodingException {
+ implTestEncodeCharBufferByteBufferbooleanException(false);
+ }
+
+ public void testEncodeCharBufferByteBufferbooleanExceptionTrue()
+ throws CharacterCodingException {
+ implTestEncodeCharBufferByteBufferbooleanException(true);
+ }
+
+ private byte[] duplicateByteArray(byte[] ba, int times) {
+ byte[] result = new byte[ba.length * times];
+ for (int i = 0; i < times; i++) {
+ System.arraycopy(ba, 0, result, i * ba.length, ba.length);
+ }
+ return result;
+ }
+
+ protected void implTestEncodeCharBufferByteBufferbooleanException(
+ boolean endOfInput) throws CharacterCodingException {
+ ByteBuffer out = ByteBuffer.allocate(100);
+
+ // MalformedException:
+ CharBuffer in = getMalformedCharBuffer();
+ encoder.onMalformedInput(CodingErrorAction.REPORT);
+ encoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+ if (in != null) {
+ encoder.reset();
+ CoderResult r = encoder.encode(in, out, endOfInput);
+ assertTrue(r.isMalformed());
+
+ encoder.reset();
+ out.clear();
+ in.rewind();
+ encoder.onMalformedInput(CodingErrorAction.IGNORE);
+ assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out,
+ endOfInput));
+ assertCodingErrorAction(endOfInput, out, in, unibytes);
+
+ encoder.reset();
+ out.clear();
+ in.rewind();
+ encoder.onMalformedInput(CodingErrorAction.REPLACE);
+ assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out,
+ endOfInput));
+ assertCodingErrorAction(endOfInput, out, in, unibytesWithRep);
+ } else {
+ // System.out.println("Cannot find malformed char buffer for "
+ // + cs.name());
+ }
+
+ // Unmapped Exception:
+ in = getUnmapCharBuffer();
+ encoder.onMalformedInput(CodingErrorAction.REPORT);
+ encoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+ if (in != null) {
+ encoder.reset();
+ out.clear();
+ assertTrue(encoder.encode(in, out, endOfInput).isUnmappable());
+
+ encoder.reset();
+ out.clear();
+ in.rewind();
+ encoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
+ assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out,
+ endOfInput));
+ assertCodingErrorAction(endOfInput, out, in, unibytes);
+
+ encoder.reset();
+ out.clear();
+ in.rewind();
+ encoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
+ assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out,
+ endOfInput));
+ assertCodingErrorAction(endOfInput, out, in, unibytesWithRep);
+ } else {
+ // System.out.println("Cannot find unmapped char buffer for "
+ // + cs.name());
+ }
+
+ // RuntimeException
+ try {
+ encoder.encode(getExceptionCharBuffer());
+ fail("should throw runtime exception");
+ } catch (RuntimeException e) {
+ }
+ }
+
+ private void assertCodingErrorAction(boolean endOfInput, ByteBuffer out,
+ CharBuffer in, byte[] expect) {
+ if (endOfInput) {
+ assertByteArray(out, addSurrogate(expect));
+ } else {
+ in.rewind();
+ assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out,
+ endOfInput));
+ in.rewind();
+ assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out, true));
+ assertByteArray(out, addSurrogate(duplicateByteArray(expect, 3)));
+ }
+ }
+
+ /*
+ * Class under test for CoderResult flush(ByteBuffer)
+ */
+ public void testFlush() throws CharacterCodingException {
+ ByteBuffer out = ByteBuffer.allocate(6);
+ CharBuffer in = CharBuffer.wrap("aaa");
+ assertEquals(in.remaining(), 3);
+
+ // by encode facade, so that internal state will be wrong
+ encoder.encode(CharBuffer.wrap("testFlush"), ByteBuffer.allocate(20),
+ true);
+ assertSame(CoderResult.UNDERFLOW, encoder
+ .flush(ByteBuffer.allocate(50)));
+ }
+
+ /*
+ * test isLegalReplacement(byte[])
+ */
+ public void testIsLegalReplacement() {
+ try {
+ encoder.isLegalReplacement(null);
+ fail("should throw null pointer exception");
+ } catch (NullPointerException e) {
+ }
+ assertTrue(encoder.isLegalReplacement(specifiedReplacement));
+
+ assertTrue(encoder.isLegalReplacement(new byte[200]));
+ byte[] ba = getIllegalByteArray();
+ if (ba != null) {
+ assertFalse(encoder.isLegalReplacement(ba));
+ }
+ }
+
+ public void testIsLegalReplacementEmptyArray() {
+ // ISO, ASC, GB, UTF8 encoder will throw exception in RI
+ // others will pass
+ // try {
+ assertTrue(encoder.isLegalReplacement(new byte[0]));
+ // fail("should throw ArrayIndexOutOfBoundsException");
+ // } catch (ArrayIndexOutOfBoundsException e) {
+ // }
+ }
+
+ public void testOnMalformedInput() {
+ assertSame(CodingErrorAction.REPORT, encoder.malformedInputAction());
+ try {
+ encoder.onMalformedInput(null);
+ fail("should throw null pointer exception");
+ } catch (IllegalArgumentException e) {
+ }
+ encoder.onMalformedInput(CodingErrorAction.IGNORE);
+ assertSame(CodingErrorAction.IGNORE, encoder.malformedInputAction());
+ }
+
+ public void testOnUnmappableCharacter() {
+ assertSame(CodingErrorAction.REPORT, encoder
+ .unmappableCharacterAction());
+ try {
+ encoder.onUnmappableCharacter(null);
+ fail("should throw null pointer exception");
+ } catch (IllegalArgumentException e) {
+ }
+ encoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
+ assertSame(CodingErrorAction.IGNORE, encoder
+ .unmappableCharacterAction());
+ }
+
+ public void testReplacement() {
+ try {
+ encoder.replaceWith(null);
+ fail("should throw null pointer exception");
+ } catch (IllegalArgumentException e) {
+ }
+ try {
+ encoder.replaceWith(new byte[0]);
+ fail("should throw null pointer exception");
+ } catch (IllegalArgumentException e) {
+ }
+ try {
+ encoder.replaceWith(new byte[100]);
+ fail("should throw null pointer exception");
+ } catch (IllegalArgumentException e) {
+ }
+
+ byte[] nr = getLegalByteArray();
+ assertSame(encoder, encoder.replaceWith(nr));
+ assertSame(nr, encoder.replacement());
+
+ nr = getIllegalByteArray();
+ try {
+ encoder.replaceWith(new byte[100]);
+ fail("should throw null pointer exception");
+ } catch (IllegalArgumentException e) {
+ }
+ }
+
+ protected byte[] getLegalByteArray() {
+ return new byte[] { 'a' };
+ }
+
+ protected byte[] getIllegalByteArray() {
+ return new byte[155];
+ }
+
+ /*
+ * Mock subclass of CharsetEncoder For protected method test
+ */
+ public static class MockCharsetEncoder extends CharsetEncoder {
+
+ boolean flushed = false;
+
+ public boolean isFlushed() {
+ boolean result = flushed;
+ flushed = false;
+ return result;
+ }
+
+ public boolean isLegalReplacement(byte[] ba) {
+ if (ba.length == 155) {// specified magic number, return false
+ return false;
+ }
+ return super.isLegalReplacement(ba);
+ }
+
+ public MockCharsetEncoder(Charset cs, float aver, float max) {
+ super(cs, aver, max);
+ }
+
+ public MockCharsetEncoder(Charset cs, float aver, float max,
+ byte[] replacement) {
+ super(cs, aver, max, replacement);
+ }
+
+ protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) {
+ int inPosition = in.position();
+ char[] input = new char[in.remaining()];
+ in.get(input);
+ String result = new String(input);
+ if (result.startsWith("malform")) {
+ // reset the cursor to the error position
+ in.position(inPosition);
+ // in.position(0);
+ // set the error length
+ return CoderResult.malformedForLength("malform".length());
+ } else if (result.startsWith("unmap")) {
+ // reset the cursor to the error position
+ in.position(inPosition);
+ // in.position(0);
+ // set the error length
+ return CoderResult.unmappableForLength("unmap".length());
+ } else if (result.startsWith("runtime")) {
+ // reset the cursor to the error position
+ in.position(0);
+ // set the error length
+ throw new RuntimeException("runtime");
+ }
+ int inLeft = input.length;
+ int outLeft = out.remaining();
+ CoderResult r = CoderResult.UNDERFLOW;
+ int length = inLeft;
+ if (outLeft < inLeft) {
+ r = CoderResult.OVERFLOW;
+ length = outLeft;
+ in.position(inPosition + outLeft);
+ }
+ for (int i = 0; i < length; i++) {
+ out.put((byte) input[i]);
+ }
+ return r;
+ }
+
+ protected CoderResult implFlush(ByteBuffer out) {
+ CoderResult result = super.implFlush(out);
+ int length = 0;
+ if (out.remaining() >= 5) {
+ length = 5;
+ result = CoderResult.UNDERFLOW;
+ flushed = true;
+ // for (int i = 0; i < length; i++) {
+ // out.put((byte)'f');
+ // }
+ } else {
+ length = out.remaining();
+ result = CoderResult.OVERFLOW;
+ }
+ return result;
+ }
+
+ protected void implReplaceWith(byte[] ba) {
+ assertSame(ba, replacement());
+ }
+
+ }
+
+ /*
+ * mock charset for test encoder initialization
+ */
+ public static class MockCharset extends Charset {
+ protected MockCharset(String arg0, String[] arg1) {
+ super(arg0, arg1);
+ }
+
+ public boolean contains(Charset arg0) {
+ return false;
+ }
+
+ public CharsetDecoder newDecoder() {
+ return new CharsetDecoderTest.MockCharsetDecoder(this,
+ (float) AVER_BYTES, MAX_BYTES);
+ }
+
+ public CharsetEncoder newEncoder() {
+ return new MockCharsetEncoder(this, (float) AVER_BYTES, MAX_BYTES);
+ }
+ }
+
+}
diff --git a/nio_char/src/test/java/tests/api/java/nio/charset/CharsetProviderTest.java b/nio_char/src/test/java/tests/api/java/nio/charset/CharsetProviderTest.java
new file mode 100644
index 0000000..74b56a9
--- /dev/null
+++ b/nio_char/src/test/java/tests/api/java/nio/charset/CharsetProviderTest.java
@@ -0,0 +1,438 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package tests.api.java.nio.charset;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.OutputStreamWriter;
+import java.nio.charset.Charset;
+import java.nio.charset.UnsupportedCharsetException;
+import java.nio.charset.spi.CharsetProvider;
+import java.util.Iterator;
+import java.util.Vector;
+
+import junit.framework.TestCase;
+import tests.api.java.nio.charset.CharsetTest.MockCharset;
+import tests.api.java.nio.charset.CharsetTest.MockSecurityManager;
+
+/**
+ * Test charset providers managed by Charset.
+ */
+public class CharsetProviderTest extends TestCase {
+
+ // need to be modified, e.g., read from system property
+ static String PROP_CONFIG_FILE1 = "clear.tests.cp1";
+
+ static String CONFIG_FILE1 = null;
+
+
+ static MockCharset charset1 = new MockCharset("mockCharset00",
+ new String[] { "mockCharset01", "mockCharset02" });
+
+ static MockCharset charset2 = new MockCharset("mockCharset10",
+ new String[] { "mockCharset11", "mockCharset12" });
+
+ /**
+ * @param arg0
+ */
+ public CharsetProviderTest(String arg0) {
+ super(arg0);
+ CONFIG_FILE1 = System.getProperty("java.io.tmpdir")+"/bin/test";
+
+ String sep = System.getProperty("file.separator");
+
+ if (!CONFIG_FILE1.endsWith(sep)) {
+ CONFIG_FILE1 += sep;
+ }
+ CONFIG_FILE1 += "META-INF" + sep + "services" + sep
+ + "java.nio.charset.spi.CharsetProvider";
+ }
+
+ /*
+ * Write the string to the config file.
+ */
+ private void setupFile(String path, String content) throws Exception {
+ String sep = System.getProperty("file.separator");
+ int sepIndex = path.lastIndexOf(sep);
+ File f = new File(path.substring(0, sepIndex));
+ f.mkdirs();
+
+ FileOutputStream fos = new FileOutputStream(path);
+ OutputStreamWriter writer = new OutputStreamWriter(fos);// , "UTF-8");
+ try {
+ writer.write(content);
+ } finally {
+ writer.close();
+ }
+ }
+
+ /*
+ * Write the string to the config file.
+ */
+ private void cleanupFile(String path) throws Exception {
+ File f = new File(path);
+ f.delete();
+ }
+
+ /*
+ * Test the method isSupported(String) with charset supported by some
+ * providers (multiple).
+ */
+ public void testIsSupported_And_ForName_NormalProvider() throws Exception {
+ try {
+ assertFalse(Charset.isSupported("mockCharset10"));
+ assertFalse(Charset.isSupported("mockCharset11"));
+ assertFalse(Charset.isSupported("mockCharset12"));
+ try {
+ Charset.forName("mockCharset10");
+ fail("Should throw UnsupportedCharsetException!");
+ } catch (UnsupportedCharsetException e) {
+ // expected
+ }
+ try {
+ Charset.forName("mockCharset11");
+ fail("Should throw UnsupportedCharsetException!");
+ } catch (UnsupportedCharsetException e) {
+ // expected
+ }
+ try {
+ Charset.forName("mockCharset12");
+ fail("Should throw UnsupportedCharsetException!");
+ } catch (UnsupportedCharsetException e) {
+ // expected
+ }
+
+ StringBuffer sb = new StringBuffer();
+ sb.append("#comment\r");
+ sb.append("\n");
+ sb.append("\r\n");
+ sb
+ .append(" \ttests.api.java.nio.charset.CharsetTest$MockCharsetProvider \t\n\r");
+ sb
+ .append(" \ttests.api.java.nio.charset.CharsetTest$MockCharsetProvider \t");
+ setupFile(CONFIG_FILE1, sb.toString());
+
+ sb = new StringBuffer();
+ sb.append(" #comment\r");
+ sb.append("\n");
+ sb.append("\r\n");
+ sb
+ .append(" \ttests.api.java.nio.charset.CharsetProviderTest$MockCharsetProvider \t\n\r");
+ setupFile(CONFIG_FILE1, sb.toString());
+
+ assertTrue(Charset.isSupported("mockCharset10"));
+ // ignore case problem in mock, intended
+ assertTrue(Charset.isSupported("MockCharset11"));
+ assertTrue(Charset.isSupported("MockCharset12"));
+ assertTrue(Charset.isSupported("MOCKCharset10"));
+ // intended case problem in mock
+ assertTrue(Charset.isSupported("MOCKCharset11"));
+ assertTrue(Charset.isSupported("MOCKCharset12"));
+
+ assertTrue(Charset.forName("mockCharset10") instanceof MockCharset);
+ assertTrue(Charset.forName("mockCharset11") instanceof MockCharset);
+ assertTrue(Charset.forName("mockCharset12") instanceof MockCharset);
+
+ assertTrue(Charset.forName("mockCharset10") == charset2);
+ // intended case problem in mock
+ Charset.forName("mockCharset11");
+ assertTrue(Charset.forName("mockCharset12") == charset2);
+ } finally {
+ cleanupFile(CONFIG_FILE1);
+ }
+ }
+
+ /*
+ * Test the method isSupported(String) when the configuration file contains
+ * a non-existing class name.
+ */
+ public void testIsSupported_NonExistingClass() throws Exception {
+ try {
+ StringBuffer sb = new StringBuffer();
+ sb.append("impossible\r");
+ setupFile(CONFIG_FILE1, sb.toString());
+
+ Charset.isSupported("impossible");
+ fail("Should throw Error!");
+ } catch (Error e) {
+ // expected
+ } finally {
+ cleanupFile(CONFIG_FILE1);
+ }
+ }
+
+ /*
+ * Test the method isSupported(String) when the configuration file contains
+ * a non-CharsetProvider class name.
+ */
+ public void testIsSupported_NotCharsetProviderClass() throws Exception {
+ try {
+ StringBuffer sb = new StringBuffer();
+ sb.append("java.lang.String\r");
+ setupFile(CONFIG_FILE1, sb.toString());
+
+ Charset.isSupported("impossible");
+ fail("Should throw ClassCastException!");
+ } catch (ClassCastException e) {
+ // expected
+ } finally {
+ cleanupFile(CONFIG_FILE1);
+ }
+ }
+
+ /*
+ * Test the method isSupported(String) with insufficient privilege to use
+ * charset provider.
+ */
+ public void testIsSupported_InsufficientPrivilege() throws Exception {
+ SecurityManager oldMan = System.getSecurityManager();
+ System.setSecurityManager(new MockSecurityManager());
+ try {
+ Charset.isSupported("UTF-8");
+
+ try {
+ StringBuffer sb = new StringBuffer();
+ sb
+ .append("tests.api.java.nio.charset.CharsetProviderTest$MockCharsetProvider\r");
+ setupFile(CONFIG_FILE1, sb.toString());
+
+ Charset.isSupported("gb180300000");
+ fail("Should throw SecurityException!");
+ } catch (SecurityException e) {
+ // expected
+ } finally {
+ cleanupFile(CONFIG_FILE1);
+ }
+ } finally {
+ System.setSecurityManager(oldMan);
+ }
+ }
+
+ /*
+ * Test the method forName(String) when the charset provider supports a
+ * built-in charset.
+ */
+ public void testForName_DuplicateWithBuiltInCharset() throws Exception {
+ try {
+ StringBuffer sb = new StringBuffer();
+ sb
+ .append("tests.api.java.nio.charset.CharsetProviderTest$MockCharsetProviderACSII\r");
+ setupFile(CONFIG_FILE1, sb.toString());
+
+ assertFalse(Charset.forName("us-ascii") instanceof MockCharset);
+ assertFalse(Charset.availableCharsets().get("us-ascii") instanceof MockCharset);
+ } finally {
+ cleanupFile(CONFIG_FILE1);
+ }
+ }
+
+ /*
+ * Test the method forName(String) when the configuration file contains a
+ * non-existing class name.
+ */
+ public void testForName_NonExistingClass() throws Exception {
+ try {
+ StringBuffer sb = new StringBuffer();
+ sb.append("impossible\r");
+ setupFile(CONFIG_FILE1, sb.toString());
+
+ Charset.forName("impossible");
+ fail("Should throw Error!");
+ } catch (Error e) {
+ // expected
+ } finally {
+ cleanupFile(CONFIG_FILE1);
+ }
+ }
+
+ /*
+ * Test the method forName(String) when the configuration file contains a
+ * non-CharsetProvider class name.
+ */
+ public void testForName_NotCharsetProviderClass() throws Exception {
+ try {
+ StringBuffer sb = new StringBuffer();
+ sb.append("java.lang.String\r");
+ setupFile(CONFIG_FILE1, sb.toString());
+
+ Charset.forName("impossible");
+ fail("Should throw ClassCastException!");
+ } catch (ClassCastException e) {
+ // expected
+ } finally {
+ cleanupFile(CONFIG_FILE1);
+ }
+ }
+
+ /*
+ * Test the method availableCharsets() with charset supported by some
+ * providers (multiple).
+ */
+ public void testAvailableCharsets_NormalProvider() throws Exception {
+ try {
+ assertFalse(Charset.availableCharsets()
+ .containsKey("mockCharset10"));
+ assertFalse(Charset.availableCharsets()
+ .containsKey("mockCharset11"));
+ assertFalse(Charset.availableCharsets()
+ .containsKey("mockCharset12"));
+
+ StringBuffer sb = new StringBuffer();
+ sb.append("#comment\r");
+ sb.append("\n");
+ sb.append("\r\n");
+ sb
+ .append(" \ttests.api.java.nio.charset.CharsetTest$MockCharsetProvider \t\n\r");
+ sb
+ .append(" \ttests.api.java.nio.charset.CharsetTest$MockCharsetProvider \t");
+ setupFile(CONFIG_FILE1, sb.toString());
+
+ sb = new StringBuffer();
+ sb.append("#comment\r");
+ sb.append("\n");
+ sb.append("\r\n");
+ sb
+ .append(" \ttests.api.java.nio.charset.CharsetProviderTest$MockCharsetProvider \t\n\r");
+ setupFile(CONFIG_FILE1, sb.toString());
+
+ assertTrue(Charset.availableCharsets().containsKey("mockCharset00"));
+ assertTrue(Charset.availableCharsets().containsKey("MOCKCharset00"));
+ assertTrue(Charset.availableCharsets().get("mockCharset00") instanceof MockCharset);
+ assertTrue(Charset.availableCharsets().get("MOCKCharset00") instanceof MockCharset);
+ assertFalse(Charset.availableCharsets()
+ .containsKey("mockCharset01"));
+ assertFalse(Charset.availableCharsets()
+ .containsKey("mockCharset02"));
+
+ assertTrue(Charset.availableCharsets().get("mockCharset10") == charset2);
+ assertTrue(Charset.availableCharsets().get("MOCKCharset10") == charset2);
+ assertFalse(Charset.availableCharsets()
+ .containsKey("mockCharset11"));
+ assertFalse(Charset.availableCharsets()
+ .containsKey("mockCharset12"));
+
+ assertTrue(Charset.availableCharsets().containsKey("mockCharset10"));
+ assertTrue(Charset.availableCharsets().containsKey("MOCKCharset10"));
+ assertTrue(Charset.availableCharsets().get("mockCharset10") == charset2);
+ assertFalse(Charset.availableCharsets()
+ .containsKey("mockCharset11"));
+ assertFalse(Charset.availableCharsets()
+ .containsKey("mockCharset12"));
+ } finally {
+ cleanupFile(CONFIG_FILE1);
+ }
+ }
+
+ /*
+ * Test the method availableCharsets(String) when the configuration file
+ * contains a non-existing class name.
+ */
+ public void testAvailableCharsets_NonExistingClass() throws Exception {
+ try {
+ StringBuffer sb = new StringBuffer();
+ sb.append("impossible\r");
+ setupFile(CONFIG_FILE1, sb.toString());
+
+ Charset.availableCharsets();
+ fail("Should throw Error!");
+ } catch (Error e) {
+ // expected
+ } finally {
+ cleanupFile(CONFIG_FILE1);
+ }
+ }
+
+ /*
+ * Test the method availableCharsets(String) when the configuration file
+ * contains a non-CharsetProvider class name.
+ */
+ public void testAvailableCharsets_NotCharsetProviderClass()
+ throws Exception {
+ try {
+ StringBuffer sb = new StringBuffer();
+ sb.append("java.lang.String\r");
+ setupFile(CONFIG_FILE1, sb.toString());
+
+ Charset.availableCharsets();
+ fail("Should throw ClassCastException!");
+ } catch (ClassCastException e) {
+ // expected
+ } finally {
+ cleanupFile(CONFIG_FILE1);
+ }
+ }
+
+ /*
+ * Test the method availableCharsets(String) when the configuration file
+ * contains an illegal string.
+ */
+ public void testAvailableCharsets_IllegalString() throws Exception {
+ try {
+ StringBuffer sb = new StringBuffer();
+ sb.append("java String\r");
+ setupFile(CONFIG_FILE1, sb.toString());
+
+ Charset.availableCharsets();
+ fail("Should throw Error!");
+ } catch (Error e) {
+ // expected
+ } finally {
+ cleanupFile(CONFIG_FILE1);
+ }
+ }
+
+ /*
+ * Mock charset provider.
+ */
+ public static class MockCharsetProvider extends CharsetProvider {
+
+ public Charset charsetForName(String charsetName) {
+ if ("MockCharset10".equalsIgnoreCase(charsetName)
+ || "MockCharset11".equalsIgnoreCase(charsetName)
+ || "MockCharset12".equalsIgnoreCase(charsetName)) {
+ return charset2;
+ }
+ return null;
+ }
+
+ public Iterator charsets() {
+ Vector v = new Vector();
+ v.add(charset2);
+ return v.iterator();
+ }
+ }
+
+ /*
+ * Another mock charset provider providing build-in charset "ascii".
+ */
+ public static class MockCharsetProviderACSII extends CharsetProvider {
+
+ public Charset charsetForName(String charsetName) {
+ if ("US-ASCII".equalsIgnoreCase(charsetName)
+ || "ASCII".equalsIgnoreCase(charsetName)) {
+ return new MockCharset("US-ASCII", new String[] { "ASCII" });
+ }
+ return null;
+ }
+
+ public Iterator charsets() {
+ Vector v = new Vector();
+ v.add(new MockCharset("US-ASCII", new String[] { "ASCII" }));
+ return v.iterator();
+ }
+ }
+
+}
diff --git a/nio_char/src/test/java/tests/api/java/nio/charset/CharsetTest.java b/nio_char/src/test/java/tests/api/java/nio/charset/CharsetTest.java
new file mode 100644
index 0000000..daf24a5
--- /dev/null
+++ b/nio_char/src/test/java/tests/api/java/nio/charset/CharsetTest.java
@@ -0,0 +1,869 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.api.java.nio.charset;
+
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.IllegalCharsetNameException;
+import java.nio.charset.UnsupportedCharsetException;
+import java.nio.charset.spi.CharsetProvider;
+import java.security.Permission;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.SortedMap;
+import java.util.Vector;
+
+import junit.framework.TestCase;
+
+/**
+ * Test class java.nio.Charset.
+ */
+public class CharsetTest extends TestCase {
+
+ static MockCharset charset1 = new MockCharset("mockCharset00",
+ new String[] { "mockCharset01", "mockCharset02" });
+
+ static MockCharset charset2 = new MockCharset("mockCharset10",
+ new String[] { "mockCharset11", "mockCharset12" });
+
+ /*
+ * @see TestCase#setUp()
+ */
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ /*
+ * @see TestCase#tearDown()
+ */
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /*
+ * Test the required 6 charsets are supported.
+ */
+ public void testRequiredCharsetSupported() {
+ assertTrue(Charset.isSupported("US-ASCII"));
+ assertTrue(Charset.isSupported("ASCII"));
+ assertTrue(Charset.isSupported("ISO-8859-1"));
+ assertTrue(Charset.isSupported("ISO8859_1"));
+ assertTrue(Charset.isSupported("UTF-8"));
+ assertTrue(Charset.isSupported("UTF8"));
+ assertTrue(Charset.isSupported("UTF-16"));
+ assertTrue(Charset.isSupported("UTF-16BE"));
+ assertTrue(Charset.isSupported("UTF-16LE"));
+
+ Charset c1 = Charset.forName("US-ASCII");
+ assertEquals("US-ASCII", Charset.forName("US-ASCII").name());
+ assertEquals("US-ASCII", Charset.forName("ASCII").name());
+ assertEquals("ISO-8859-1", Charset.forName("ISO-8859-1").name());
+ assertEquals("ISO-8859-1", Charset.forName("ISO8859_1").name());
+ assertEquals("UTF-8", Charset.forName("UTF-8").name());
+ assertEquals("UTF-8", Charset.forName("UTF8").name());
+ assertEquals("UTF-16", Charset.forName("UTF-16").name());
+ assertEquals("UTF-16BE", Charset.forName("UTF-16BE").name());
+ assertEquals("UTF-16LE", Charset.forName("UTF-16LE").name());
+
+ assertNotSame(Charset.availableCharsets(), Charset.availableCharsets());
+ // assertSame(Charset.forName("US-ASCII"), Charset.availableCharsets()
+ // .get("US-ASCII"));
+ // assertSame(Charset.forName("US-ASCII"), c1);
+ assertTrue(Charset.availableCharsets().containsKey("US-ASCII"));
+ assertTrue(Charset.availableCharsets().containsKey("ISO-8859-1"));
+ assertTrue(Charset.availableCharsets().containsKey("UTF-8"));
+ assertTrue(Charset.availableCharsets().containsKey("UTF-16"));
+ assertTrue(Charset.availableCharsets().containsKey("UTF-16BE"));
+ assertTrue(Charset.availableCharsets().containsKey("UTF-16LE"));
+ }
+
+ /*
+ * Test the method isSupported(String) with null.
+ */
+ public void testIsSupported_Null() {
+ try {
+ Charset.isSupported(null);
+ fail("Should throw IllegalArgumentException!");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Test the method isSupported(String) with empty string.
+ *
+ */
+ public void testIsSupported_EmptyString() {
+ try {
+ Charset.isSupported("");
+ } catch (IllegalArgumentException e) {
+ // FIXME: Commented out since RI does throw IAE
+ // fail("Should not throw IllegalArgumentException!");
+ }
+ }
+
+ /*
+ * Test the method isSupported(String) with a string starting with ".".
+ *
+ */
+ public void testIsSupported_InvalidInitialCharacter() {
+ try {
+ Charset.isSupported(".char");
+ } catch (IllegalArgumentException e) {
+ fail("Should not throw IllegalArgumentException!");
+ }
+ }
+
+ /*
+ * Test the method isSupported(String) with illegal charset name.
+ */
+ public void testIsSupported_IllegalName() {
+ try {
+ Charset.isSupported(" ///#$$");
+ fail("Should throw IllegalCharsetNameException!");
+ } catch (IllegalCharsetNameException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Test the method isSupported(String) with not supported charset name.
+ */
+ public void testIsSupported_NotSupported() {
+ assertFalse(Charset.isSupported("impossible"));
+ }
+
+ /*
+ * Test the method forName(String) with null.
+ */
+ public void testForName_Null() {
+ try {
+ Charset.forName(null);
+ fail("Should throw IllegalArgumentException!");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Test the method forName(String) with empty string.
+ */
+ public void testForName_EmptyString() {
+ try {
+ Charset.forName("");
+ fail("Should throw IllegalArgumentException!");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Test the method forName(String) with a string starting with ".".
+ */
+ public void testForName_InvalidInitialCharacter() {
+ try {
+ Charset.forName(".char");
+ fail("Should throw IllegalArgumentException!");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Test the method forName(String) with illegal charset name.
+ */
+ public void testForName_IllegalName() {
+ try {
+ Charset.forName(" ///#$$");
+ fail("Should throw IllegalCharsetNameException!");
+ } catch (IllegalCharsetNameException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Test the method forName(String) with not supported charset name.
+ */
+ public void testForName_NotSupported() {
+ try {
+ Charset.forName("impossible");
+ fail("Should throw UnsupportedCharsetException!");
+ } catch (UnsupportedCharsetException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Test the constructor with normal parameter values.
+ */
+ public void testConstructor_Normal() {
+ final String mockName = "mockChar1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.:-_";
+ MockCharset c = new MockCharset(mockName, new String[] { "mock" });
+ assertEquals(mockName, c.name());
+ assertEquals(mockName, c.displayName());
+ assertEquals(mockName, c.displayName(Locale.getDefault()));
+ assertEquals("mock", c.aliases().toArray()[0]);
+ assertEquals(1, c.aliases().toArray().length);
+ }
+
+ /*
+ * Test the constructor with empty canonical name.
+ *
+ */
+ public void testConstructor_EmptyCanonicalName() {
+ try {
+ new MockCharset("", new String[0]);
+ } catch (IllegalCharsetNameException e) {
+ // FIXME: Commented out since RI does throw IAE
+ // fail("Should not throw IllegalArgumentException!");
+ }
+ }
+
+ /*
+ * Test the constructor with illegal canonical name: starting with neither a
+ * digit nor a letter.
+ *
+ */
+ public void testConstructor_IllegalCanonicalName_Initial() {
+ try {
+ new MockCharset("-123", new String[] { "mock" });
+ } catch (IllegalCharsetNameException e) {
+ fail("Should not throw IllegalArgumentException!");
+ }
+ }
+
+ /*
+ * Test the constructor with illegal canonical name, illegal character in
+ * the middle.
+ */
+ public void testConstructor_IllegalCanonicalName_Middle() {
+ try {
+ new MockCharset("1%%23", new String[] { "mock" });
+ fail("Should throw IllegalCharsetNameException!");
+ } catch (IllegalCharsetNameException e) {
+ // expected
+ }
+ try {
+ new MockCharset("1//23", new String[] { "mock" });
+ fail("Should throw IllegalCharsetNameException!");
+ } catch (IllegalCharsetNameException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Test the constructor with null canonical name.
+ */
+ public void testConstructor_NullCanonicalName() {
+ try {
+ MockCharset c = new MockCharset(null, new String[] { "mock" });
+ fail("Should throw NullPointerException!");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Test the constructor with null aliases.
+ */
+ public void testConstructor_NullAliases() {
+ MockCharset c = new MockCharset("mockChar", null);
+ assertEquals("mockChar", c.name());
+ assertEquals("mockChar", c.displayName());
+ assertEquals("mockChar", c.displayName(Locale.getDefault()));
+ assertEquals(0, c.aliases().toArray().length);
+ }
+
+ /*
+ * Test the constructor with a null aliases.
+ */
+ public void testConstructor_NullAliase() {
+ try {
+ new MockCharset("mockChar", new String[] { "mock", null });
+ fail("Should throw NullPointerException!");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Test the constructor with no aliases.
+ */
+ public void testConstructor_NoAliases() {
+ MockCharset c = new MockCharset("mockChar", new String[0]);
+ assertEquals("mockChar", c.name());
+ assertEquals("mockChar", c.displayName());
+ assertEquals("mockChar", c.displayName(Locale.getDefault()));
+ assertEquals(0, c.aliases().toArray().length);
+ }
+
+ /*
+ * Test the constructor with empty aliases.
+ *
+ */
+ public void testConstructor_EmptyAliases() {
+ try {
+ new MockCharset("mockChar", new String[] { "" });
+ } catch (IllegalCharsetNameException e) {
+ // FIXME: Commented out since RI does throw IAE
+ // fail("Should not throw IllegalArgumentException!");
+ }
+ }
+
+ /*
+ * Test the constructor with illegal aliases: starting with neither a digit
+ * nor a letter.
+ *
+ */
+ public void testConstructor_IllegalAliases_Initial() {
+ try {
+ new MockCharset("mockChar", new String[] { "mock", "-123" });
+ } catch (IllegalCharsetNameException e) {
+ fail("Should not throw IllegalArgumentException!");
+ }
+ }
+
+ /*
+ * Test the constructor with illegal aliase, illegal character in the
+ * middle.
+ */
+ public void testConstructor_IllegalAliases_Middle() {
+ try {
+ new MockCharset("mockChar", new String[] { "mock", "22##ab" });
+ fail("Should throw IllegalCharsetNameException!");
+ } catch (IllegalCharsetNameException e) {
+ // expected
+ }
+ try {
+ new MockCharset("mockChar", new String[] { "mock", "22%%ab" });
+ fail("Should throw IllegalCharsetNameException!");
+ } catch (IllegalCharsetNameException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Test the method aliases() with multiple aliases. Most conditions have
+ * been tested in the testcases for the constructors.
+ */
+ public void testAliases_Multiple() {
+ final String mockName = "mockChar1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.:-_";
+ MockCharset c = new MockCharset("mockChar", new String[] { "mock",
+ mockName, "mock2" });
+ assertEquals("mockChar", c.name());
+ assertEquals(3, c.aliases().size());
+ assertTrue(c.aliases().contains("mock"));
+ assertTrue(c.aliases().contains(mockName));
+ assertTrue(c.aliases().contains("mock2"));
+
+ try {
+ c.aliases().clear();
+ fail("Should throw UnsupportedOperationException!");
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Test the method aliases() with duplicate aliases, one same with its
+ * canonical name.
+ */
+ public void testAliases_Duplicate() {
+ final String mockName = "mockChar1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.:-_";
+ MockCharset c = new MockCharset("mockChar", new String[] { "mockChar",
+ "mock", mockName, "mock", "mockChar", "mock", "mock2" });
+ assertEquals("mockChar", c.name());
+ assertEquals(4, c.aliases().size());
+ assertTrue(c.aliases().contains("mockChar"));
+ assertTrue(c.aliases().contains("mock"));
+ assertTrue(c.aliases().contains(mockName));
+ assertTrue(c.aliases().contains("mock2"));
+ }
+
+ /*
+ * Test the method canEncode(). Test the default return value.
+ */
+ public void testCanEncode() {
+ MockCharset c = new MockCharset("mock", null);
+ assertTrue(c.canEncode());
+ }
+
+ /*
+ * Test the method isRegistered(). Test the default return value.
+ */
+ public void testIsRegistered() {
+ MockCharset c = new MockCharset("mock", null);
+ assertTrue(c.isRegistered());
+ }
+
+ /*
+ * The name() method has been tested by the testcases for the constructor.
+ */
+ public void testName() {
+ // already covered by testConstructor_XXX series
+ }
+
+ /*
+ * The displayName() method have been tested by the testcases for the
+ * constructor.
+ */
+ public void testDisplayName() {
+ // already covered by testConstructor_XXX series
+ }
+
+ /*
+ * Test displayName(Locale) with null.
+ */
+ public void testDisplayName_Locale_Null() {
+ MockCharset c = new MockCharset("mock", null);
+ assertEquals("mock", c.displayName(null));
+ }
+
+ /*
+ * Test the method compareTo(Object) with normal conditions.
+ */
+ public void testCompareTo_Normal() {
+ MockCharset c1 = new MockCharset("mock", null);
+ assertEquals(0, c1.compareTo(c1));
+
+ MockCharset c2 = new MockCharset("Mock", null);
+ assertEquals(0, c1.compareTo(c2));
+
+ c2 = new MockCharset("mock2", null);
+ assertTrue(c1.compareTo(c2) < 0);
+ assertTrue(c2.compareTo(c1) > 0);
+
+ c2 = new MockCharset("mack", null);
+ assertTrue(c1.compareTo(c2) > 0);
+ assertTrue(c2.compareTo(c1) < 0);
+
+ c2 = new MockCharset("m.", null);
+ assertTrue(c1.compareTo(c2) > 0);
+ assertTrue(c2.compareTo(c1) < 0);
+
+ c2 = new MockCharset("m:", null);
+ assertEquals("mock".compareToIgnoreCase("m:"), c1.compareTo(c2));
+ assertEquals("m:".compareToIgnoreCase("mock"), c2.compareTo(c1));
+
+ c2 = new MockCharset("m-", null);
+ assertTrue(c1.compareTo(c2) > 0);
+ assertTrue(c2.compareTo(c1) < 0);
+
+ c2 = new MockCharset("m_", null);
+ assertTrue(c1.compareTo(c2) > 0);
+ assertTrue(c2.compareTo(c1) < 0);
+ }
+
+ /*
+ * Test the method compareTo(Object) with null param.
+ */
+ public void testCompareTo_Null() {
+ MockCharset c1 = new MockCharset("mock", null);
+ try {
+ c1.compareTo(null);
+ fail("Should throw NullPointerException!");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Test the method compareTo(Object) with another kind of charset object.
+ */
+ public void testCompareTo_DiffCharsetClass() {
+ MockCharset c1 = new MockCharset("mock", null);
+ MockCharset2 c2 = new MockCharset2("Mock", new String[] { "myname" });
+ assertEquals(0, c1.compareTo(c2));
+ assertEquals(0, c2.compareTo(c1));
+ }
+
+ /*
+ * Test the method equals(Object) with null param.
+ */
+ public void testEquals_Normal() {
+ MockCharset c1 = new MockCharset("mock", null);
+ MockCharset2 c2 = new MockCharset2("mock", null);
+ assertTrue(c1.equals(c2));
+ assertTrue(c2.equals(c1));
+
+ c2 = new MockCharset2("Mock", null);
+ assertFalse(c1.equals(c2));
+ assertFalse(c2.equals(c1));
+ }
+
+ /*
+ * Test the method equals(Object) with normal conditions.
+ */
+ public void testEquals_Null() {
+ MockCharset c1 = new MockCharset("mock", null);
+ assertFalse(c1.equals(null));
+ }
+
+ /*
+ * Test the method equals(Object) with another kind of charset object.
+ */
+ public void testEquals_NonCharsetObject() {
+ MockCharset c1 = new MockCharset("mock", null);
+ assertFalse(c1.equals("test"));
+ }
+
+ /*
+ * Test the method equals(Object) with another kind of charset object.
+ */
+ public void testEquals_DiffCharsetClass() {
+ MockCharset c1 = new MockCharset("mock", null);
+ MockCharset2 c2 = new MockCharset2("mock", null);
+ assertTrue(c1.equals(c2));
+ assertTrue(c2.equals(c1));
+ }
+
+ /*
+ * Test the method hashCode().
+ */
+ public void testHashCode_DiffCharsetClass() {
+ MockCharset c1 = new MockCharset("mock", null);
+ assertEquals(c1.hashCode(), "mock".hashCode());
+
+ final String mockName = "mockChar1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.:-_";
+ c1 = new MockCharset(mockName, new String[] { "mockChar", "mock",
+ mockName, "mock", "mockChar", "mock", "mock2" });
+ assertEquals(mockName.hashCode(), c1.hashCode());
+ }
+
+ /*
+ * Test the method encode(CharBuffer) under normal condition.
+ */
+ public void testEncode_CharBuffer_Normal() throws Exception {
+ MockCharset c1 = new MockCharset("testEncode_CharBuffer_Normal_mock", null);
+ ByteBuffer bb = c1.encode(CharBuffer.wrap("abcdefg"));
+ assertEquals("abcdefg", new String(bb.array(), "iso8859-1"));
+ bb = c1.encode(CharBuffer.wrap(""));
+ assertEquals("", new String(bb.array(), "iso8859-1"));
+ }
+
+ /*
+ * Test the method encode(CharBuffer) with an unmappable char.
+ */
+ public void testEncode_CharBuffer_Unmappable() throws Exception {
+ Charset c1 = Charset.forName("iso8859-1");
+ ByteBuffer bb = c1.encode(CharBuffer.wrap("abcd\u5D14efg"));
+ assertEquals(new String(bb.array(), "iso8859-1"), "abcd"
+ + new String(c1.newEncoder().replacement(), "iso8859-1")
+ + "efg");
+ }
+
+ /*
+ * Test the method encode(CharBuffer) with null CharBuffer.
+ */
+ public void testEncode_CharBuffer_NullCharBuffer() {
+ MockCharset c = new MockCharset("mock", null);
+ try {
+ c.encode((CharBuffer) null);
+ fail("Should throw NullPointerException!");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Test the method encode(CharBuffer) with null encoder.
+ */
+ public void testEncode_CharBuffer_NullEncoder() {
+ MockCharset2 c = new MockCharset2("mock2", null);
+ try {
+ c.encode(CharBuffer.wrap("hehe"));
+ fail("Should throw NullPointerException!");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Test the method encode(String) under normal condition.
+ */
+ public void testEncode_String_Normal() throws Exception {
+ MockCharset c1 = new MockCharset("testEncode_String_Normal_mock", null);
+ ByteBuffer bb = c1.encode("abcdefg");
+ assertEquals("abcdefg", new String(bb.array(), "iso8859-1"));
+ bb = c1.encode("");
+ assertEquals("", new String(bb.array(), "iso8859-1"));
+ }
+
+ /*
+ * Test the method encode(String) with an unmappable char.
+ */
+ public void testEncode_String_Unmappable() throws Exception {
+ Charset c1 = Charset.forName("iso8859-1");
+ ByteBuffer bb = c1.encode("abcd\u5D14efg");
+ assertEquals(new String(bb.array(), "iso8859-1"), "abcd"
+ + new String(c1.newEncoder().replacement(), "iso8859-1")
+ + "efg");
+ }
+
+ /*
+ * Test the method encode(String) with null CharBuffer.
+ */
+ public void testEncode_String_NullString() {
+ MockCharset c = new MockCharset("mock", null);
+ try {
+ c.encode((String) null);
+ fail("Should throw NullPointerException!");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Test the method encode(String) with null encoder.
+ */
+ public void testEncode_String_NullEncoder() {
+
+ MockCharset2 c = new MockCharset2("mock2", null);
+ try {
+ c.encode("hehe");
+ fail("Should throw NullPointerException!");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Test the method decode(ByteBuffer) under normal condition.
+ */
+ public void testDecode_Normal() throws Exception {
+ MockCharset c1 = new MockCharset("mock", null);
+ CharBuffer cb = c1.decode(ByteBuffer.wrap("abcdefg"
+ .getBytes("iso8859-1")));
+ assertEquals("abcdefg", new String(cb.array()));
+ cb = c1.decode(ByteBuffer.wrap("".getBytes("iso8859-1")));
+ assertEquals("", new String(cb.array()));
+ }
+
+ /*
+ * Test the method decode(ByteBuffer) with a malformed input.
+ */
+ public void testDecode_Malformed() throws Exception {
+ Charset c1 = Charset.forName("iso8859-1");
+ CharBuffer cb = c1.decode(ByteBuffer.wrap("abcd\u5D14efg"
+ .getBytes("iso8859-1")));
+ byte[] replacement = c1.newEncoder().replacement();
+ assertEquals(new String(cb.array()), "abcd" + new String(replacement)
+ + "efg");
+ }
+
+ /*
+ * Test the method decode(ByteBuffer) with null CharBuffer.
+ */
+ public void testDecode_NullByteBuffer() {
+ MockCharset c = new MockCharset("mock", null);
+ try {
+ c.decode(null);
+ fail("Should throw NullPointerException!");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Test the method decode(ByteBuffer) with null encoder.
+ */
+ public void testDecode_NullDecoder() {
+ MockCharset2 c = new MockCharset2("mock2", null);
+ try {
+ c.decode(ByteBuffer.wrap("hehe".getBytes()));
+ fail("Should throw NullPointerException!");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Test the method toString().
+ */
+ public void testToString() {
+ MockCharset c1 = new MockCharset("mock", null);
+ assertTrue(-1 != c1.toString().indexOf("mock"));
+ }
+
+ /**
+ * @tests java.nio.charset.Charset#availableCharsets()
+ */
+ public void test_availableCharsets() throws Exception {
+ // regression test for Harmony-1051
+ ClassLoader originalClassLoader = Thread.currentThread()
+ .getContextClassLoader();
+ try {
+ Thread.currentThread().setContextClassLoader(null);
+ SortedMap<String, Charset> charsets = Charset.availableCharsets();
+ // make sure "mockCharset00" is loaded by MockCharsetProvider
+ assertTrue(charsets.containsKey("mockCharset00"));
+ } finally {
+ Thread.currentThread().setContextClassLoader(originalClassLoader);
+ }
+ }
+
+ /**
+ * @tests java.nio.charset.Charset#availableCharsets()
+ */
+ public void test_forNameLString() throws Exception {
+ // regression test for Harmony-1051
+ ClassLoader originalClassLoader = Thread.currentThread()
+ .getContextClassLoader();
+ try {
+ Thread.currentThread().setContextClassLoader(null);
+ // make sure "mockCharset00" is loaded by MockCharsetProvider
+ assertNotNull(Charset.forName("mockCharset00"));
+ } finally {
+ Thread.currentThread().setContextClassLoader(originalClassLoader);
+ }
+ }
+
+ /*
+ * Mock charset class.
+ */
+ static final class MockCharset extends Charset {
+
+ public MockCharset(String canonicalName, String[] aliases) {
+ super(canonicalName, aliases);
+ }
+
+ public boolean contains(Charset cs) {
+ return false;
+ }
+
+ public CharsetDecoder newDecoder() {
+ return new MockDecoder(this);
+ }
+
+ public CharsetEncoder newEncoder() {
+ return new MockEncoder(this);
+ }
+ }
+
+ /*
+ * Another mock charset class.
+ */
+ static class MockCharset2 extends Charset {
+
+ public MockCharset2(String canonicalName, String[] aliases) {
+ super(canonicalName, aliases);
+ }
+
+ public boolean contains(Charset cs) {
+ return false;
+ }
+
+ public CharsetDecoder newDecoder() {
+ return null;
+ }
+
+ public CharsetEncoder newEncoder() {
+ return null;
+ }
+ }
+
+ /*
+ * Mock encoder.
+ */
+ static class MockEncoder extends java.nio.charset.CharsetEncoder {
+
+ public MockEncoder(Charset cs) {
+ super(cs, 1, 3, new byte[] { (byte) '?' });
+ }
+
+ protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) {
+ while (in.remaining() > 0) {
+ out.put((byte) in.get());
+ // out.put((byte) '!');
+ }
+ return CoderResult.UNDERFLOW;
+ }
+ }
+
+ /*
+ * Mock decoder.
+ */
+ static class MockDecoder extends java.nio.charset.CharsetDecoder {
+
+ public MockDecoder(Charset cs) {
+ super(cs, 1, 10);
+ }
+
+ protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) {
+ while (in.remaining() > 0) {
+ out.put((char) in.get());
+ }
+ return CoderResult.UNDERFLOW;
+ }
+ }
+
+ /*
+ * Mock charset provider.
+ */
+ public static class MockCharsetProvider extends CharsetProvider {
+
+ public Charset charsetForName(String charsetName) {
+ if ("MockCharset00".equalsIgnoreCase(charsetName)
+ || "MockCharset01".equalsIgnoreCase(charsetName)
+ || "MockCharset02".equalsIgnoreCase(charsetName)) {
+ return new MockCharset("mockCharset00", new String[] {
+ "mockCharset01", "mockCharset02" });
+ }
+ return null;
+ }
+
+ public Iterator charsets() {
+ Vector v = new Vector();
+ v.add(new MockCharset("mockCharset00", new String[] {
+ "mockCharset01", "mockCharset02" }));
+ return v.iterator();
+ }
+ }
+
+ /*
+ * Used to grant all permissions except charset provider access.
+ */
+ public static class MockSecurityManager extends SecurityManager {
+
+ public MockSecurityManager() {
+ }
+
+ public void checkPermission(Permission perm) {
+ // grant all permissions except logging control
+ if (perm instanceof RuntimePermission) {
+ RuntimePermission rp = (RuntimePermission) perm;
+ if (rp.getName().equals("charsetProvider")) {
+ throw new SecurityException();
+ }
+ }
+ }
+
+ public void checkPermission(Permission perm, Object context) {
+ // grant all permissions except logging control
+ if (perm instanceof RuntimePermission) {
+ RuntimePermission rp = (RuntimePermission) perm;
+ if (rp.getName().equals("charsetProvider")) {
+ throw new SecurityException();
+ }
+ }
+ }
+ }
+}
diff --git a/nio_char/src/test/java/tests/api/java/nio/charset/CoderResultTest.java b/nio_char/src/test/java/tests/api/java/nio/charset/CoderResultTest.java
new file mode 100644
index 0000000..d362a57
--- /dev/null
+++ b/nio_char/src/test/java/tests/api/java/nio/charset/CoderResultTest.java
@@ -0,0 +1,265 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.api.java.nio.charset;
+
+import java.nio.BufferOverflowException;
+import java.nio.BufferUnderflowException;
+import java.nio.charset.CoderResult;
+import java.nio.charset.MalformedInputException;
+import java.nio.charset.UnmappableCharacterException;
+
+import junit.framework.TestCase;
+
+/**
+ * Test class java.nio.charset.CoderResult.
+ */
+public class CoderResultTest extends TestCase {
+
+ /*
+ * @see TestCase#setUp()
+ */
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ /*
+ * @see TestCase#tearDown()
+ */
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /*
+ * Test the constant OVERFLOW and UNDERFLOW.
+ */
+ public void testConstants() throws Exception {
+ assertNotSame(CoderResult.OVERFLOW, CoderResult.UNDERFLOW);
+
+ assertNotNull(CoderResult.OVERFLOW);
+ assertFalse(CoderResult.OVERFLOW.isError());
+ assertFalse(CoderResult.OVERFLOW.isMalformed());
+ assertFalse(CoderResult.OVERFLOW.isUnderflow());
+ assertFalse(CoderResult.OVERFLOW.isUnmappable());
+ assertTrue(CoderResult.OVERFLOW.isOverflow());
+ assertTrue(CoderResult.OVERFLOW.toString().indexOf("OVERFLOW") != -1);
+ try {
+ CoderResult.OVERFLOW.throwException();
+ fail("Should throw BufferOverflowException");
+ } catch (BufferOverflowException ex) {
+ // expected
+ }
+ try {
+ CoderResult.OVERFLOW.length();
+ fail("Should throw UnsupportedOperationException");
+ } catch (UnsupportedOperationException ex) {
+ // expected
+ }
+
+ assertNotNull(CoderResult.UNDERFLOW);
+ assertFalse(CoderResult.UNDERFLOW.isError());
+ assertFalse(CoderResult.UNDERFLOW.isMalformed());
+ assertTrue(CoderResult.UNDERFLOW.isUnderflow());
+ assertFalse(CoderResult.UNDERFLOW.isUnmappable());
+ assertFalse(CoderResult.UNDERFLOW.isOverflow());
+ assertTrue(CoderResult.UNDERFLOW.toString().indexOf("UNDERFLOW") != -1);
+ try {
+ CoderResult.UNDERFLOW.throwException();
+ fail("Should throw BufferOverflowException");
+ } catch (BufferUnderflowException ex) {
+ // expected
+ }
+ try {
+ CoderResult.UNDERFLOW.length();
+ fail("Should throw UnsupportedOperationException");
+ } catch (UnsupportedOperationException ex) {
+ // expected
+ }
+ }
+
+ /**
+ * Test method isError().
+ *
+ */
+ public void testIsError() {
+ assertFalse(CoderResult.UNDERFLOW.isError());
+ assertFalse(CoderResult.OVERFLOW.isError());
+ assertTrue(CoderResult.malformedForLength(1).isError());
+ assertTrue(CoderResult.unmappableForLength(1).isError());
+ }
+
+ /**
+ * Test method isMalformed().
+ *
+ */
+ public void testIsMalformed() {
+ assertFalse(CoderResult.UNDERFLOW.isMalformed());
+ assertFalse(CoderResult.OVERFLOW.isMalformed());
+ assertTrue(CoderResult.malformedForLength(1).isMalformed());
+ assertFalse(CoderResult.unmappableForLength(1).isMalformed());
+ }
+
+ /**
+ * Test method isMalformed().
+ *
+ */
+ public void testIsUnmappable() {
+ assertFalse(CoderResult.UNDERFLOW.isUnmappable());
+ assertFalse(CoderResult.OVERFLOW.isUnmappable());
+ assertFalse(CoderResult.malformedForLength(1).isUnmappable());
+ assertTrue(CoderResult.unmappableForLength(1).isUnmappable());
+ }
+
+ /**
+ * Test method isOverflow().
+ *
+ */
+ public void testIsOverflow() {
+ assertFalse(CoderResult.UNDERFLOW.isOverflow());
+ assertTrue(CoderResult.OVERFLOW.isOverflow());
+ assertFalse(CoderResult.malformedForLength(1).isOverflow());
+ assertFalse(CoderResult.unmappableForLength(1).isOverflow());
+ }
+
+ /**
+ * Test method isUnderflow().
+ *
+ */
+ public void testIsUnderflow() {
+ assertTrue(CoderResult.UNDERFLOW.isUnderflow());
+ assertFalse(CoderResult.OVERFLOW.isUnderflow());
+ assertFalse(CoderResult.malformedForLength(1).isUnderflow());
+ assertFalse(CoderResult.unmappableForLength(1).isUnderflow());
+ }
+
+ /**
+ * Test method length().
+ *
+ */
+ public void testLength() {
+ try {
+ CoderResult.UNDERFLOW.length();
+ fail("Should throw UnsupportedOperationException");
+ } catch (UnsupportedOperationException ex) {
+ // expected
+ }
+ try {
+ CoderResult.OVERFLOW.length();
+ fail("Should throw UnsupportedOperationException");
+ } catch (UnsupportedOperationException ex) {
+ // expected
+ }
+
+ assertEquals(CoderResult.malformedForLength(1).length(), 1);
+ assertEquals(CoderResult.unmappableForLength(1).length(), 1);
+ }
+
+ /**
+ * Test method malformedForLength(int).
+ *
+ */
+ public void testMalformedForLength() {
+ assertNotNull(CoderResult.malformedForLength(Integer.MAX_VALUE));
+ assertNotNull(CoderResult.malformedForLength(1));
+ assertSame(CoderResult.malformedForLength(1), CoderResult
+ .malformedForLength(1));
+ assertNotSame(CoderResult.malformedForLength(1), CoderResult
+ .unmappableForLength(1));
+ assertNotSame(CoderResult.malformedForLength(2), CoderResult
+ .malformedForLength(1));
+ try {
+ CoderResult.malformedForLength(-1);
+ fail("Should throw IllegalArgumentException");
+ } catch (IllegalArgumentException ex) {
+ // expected
+ }
+ try {
+ CoderResult.malformedForLength(0);
+ fail("Should throw IllegalArgumentException");
+ } catch (IllegalArgumentException ex) {
+ // expected
+ }
+ }
+
+ /**
+ * Test method unmappableForLength(int).
+ *
+ */
+ public void testUnmappableForLength() {
+ assertNotNull(CoderResult.unmappableForLength(Integer.MAX_VALUE));
+ assertNotNull(CoderResult.unmappableForLength(1));
+ assertSame(CoderResult.unmappableForLength(1), CoderResult
+ .unmappableForLength(1));
+ assertNotSame(CoderResult.unmappableForLength(2), CoderResult
+ .unmappableForLength(1));
+ try {
+ CoderResult.unmappableForLength(-1);
+ fail("Should throw IllegalArgumentException");
+ } catch (IllegalArgumentException ex) {
+ // expected
+ }
+ try {
+ CoderResult.unmappableForLength(0);
+ fail("Should throw IllegalArgumentException");
+ } catch (IllegalArgumentException ex) {
+ // expected
+ }
+ }
+
+ /**
+ * Test method throwException().
+ *
+ */
+ public void testThrowException() throws Exception {
+ try {
+ CoderResult.OVERFLOW.throwException();
+ fail("Should throw BufferOverflowException");
+ } catch (BufferOverflowException ex) {
+ // expected
+ }
+ try {
+ CoderResult.UNDERFLOW.throwException();
+ fail("Should throw BufferOverflowException");
+ } catch (BufferUnderflowException ex) {
+ // expected
+ }
+ try {
+ CoderResult.malformedForLength(1).throwException();
+ fail("Should throw MalformedInputException");
+ } catch (MalformedInputException ex) {
+ assertEquals(ex.getInputLength(), 1);
+ }
+ try {
+ CoderResult.unmappableForLength(1).throwException();
+ fail("Should throw UnmappableCharacterException");
+ } catch (UnmappableCharacterException ex) {
+ assertEquals(ex.getInputLength(), 1);
+ }
+ }
+
+ /**
+ * Test method toString().
+ *
+ */
+ public void testToString() throws Exception {
+ assertTrue(CoderResult.OVERFLOW.toString().indexOf("OVERFLOW") != -1);
+ assertTrue(CoderResult.UNDERFLOW.toString().indexOf("UNDERFLOW") != -1);
+ assertTrue(CoderResult.malformedForLength(666).toString()
+ .indexOf("666") != -1);
+ assertTrue(CoderResult.unmappableForLength(666).toString().indexOf(
+ "666") != -1);
+ }
+}
diff --git a/nio_char/src/test/java/tests/api/java/nio/charset/CodingErrorActionTest.java b/nio_char/src/test/java/tests/api/java/nio/charset/CodingErrorActionTest.java
new file mode 100644
index 0000000..1e23aef
--- /dev/null
+++ b/nio_char/src/test/java/tests/api/java/nio/charset/CodingErrorActionTest.java
@@ -0,0 +1,62 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.api.java.nio.charset;
+
+import java.nio.charset.CodingErrorAction;
+
+import junit.framework.TestCase;
+
+/**
+ * Test class java.nio.charset.CodingErrorAction
+ */
+public class CodingErrorActionTest extends TestCase {
+
+ /*
+ * @see TestCase#setUp()
+ */
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ /*
+ * @see TestCase#tearDown()
+ */
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /*
+ * Test the constants.
+ */
+ public void testIGNORE() {
+ assertNotNull(CodingErrorAction.IGNORE);
+ assertNotNull(CodingErrorAction.REPLACE);
+ assertNotNull(CodingErrorAction.REPORT);
+ assertNotSame(CodingErrorAction.IGNORE, CodingErrorAction.REPLACE);
+ assertNotSame(CodingErrorAction.IGNORE, CodingErrorAction.REPORT);
+ assertNotSame(CodingErrorAction.REPLACE, CodingErrorAction.REPORT);
+ }
+
+ /*
+ * Test the method toString().
+ */
+ public void testToString() {
+ assertTrue(CodingErrorAction.IGNORE.toString().indexOf("IGNORE") != -1);
+ assertTrue(CodingErrorAction.REPLACE.toString().indexOf("REPLACE") != -1);
+ assertTrue(CodingErrorAction.REPORT.toString().indexOf("REPORT") != -1);
+ }
+}
diff --git a/nio_char/src/test/java/tests/api/java/nio/charset/GBCharsetDecoderTest.java b/nio_char/src/test/java/tests/api/java/nio/charset/GBCharsetDecoderTest.java
new file mode 100644
index 0000000..855e85b
--- /dev/null
+++ b/nio_char/src/test/java/tests/api/java/nio/charset/GBCharsetDecoderTest.java
@@ -0,0 +1,64 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.api.java.nio.charset;
+
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+
+/**
+ * test gb18030 decoder
+ */
+public class GBCharsetDecoderTest extends CharsetDecoderTest {
+
+ protected void setUp() throws Exception {
+ cs = Charset.forName("gb18030");
+ super.setUp();
+ }
+
+ /*
+ * @see CharsetDecoderTest#tearDown()
+ */
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ // // FIXME: give up this tests
+ // public void testDefaultCharsPerByte(){
+ // //assertEquals(1, decoder.averageCharsPerByte());
+ // //assertEquals(1, decoder.maxCharsPerByte());
+ // assertEquals(decoder.averageCharsPerByte(), 0.25, 0.001);
+ // assertEquals(decoder.maxCharsPerByte(), 2, 0.001);
+ // }
+
+ ByteBuffer getUnmappedByteBuffer() throws UnsupportedEncodingException {
+ return null;
+ }
+
+ ByteBuffer getMalformByteBuffer() throws UnsupportedEncodingException {
+ ByteBuffer buffer = ByteBuffer.allocate(20);
+ buffer.put(new byte[] { (byte) 0xd8, 0 });
+ buffer.put(unibytes);
+ buffer.flip();
+ return buffer;
+ }
+
+ ByteBuffer getExceptionByteArray() throws UnsupportedEncodingException {
+ return null;
+ }
+
+}
diff --git a/nio_char/src/test/java/tests/api/java/nio/charset/GBCharsetEncoderTest.java b/nio_char/src/test/java/tests/api/java/nio/charset/GBCharsetEncoderTest.java
new file mode 100644
index 0000000..6890b0c
--- /dev/null
+++ b/nio_char/src/test/java/tests/api/java/nio/charset/GBCharsetEncoderTest.java
@@ -0,0 +1,95 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.api.java.nio.charset;
+
+import java.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+
+/**
+ * test case specific activity of gb18030 charset encoder
+ */
+public class GBCharsetEncoderTest extends CharsetEncoderTest {
+
+ // charset for gb180303
+ private static final Charset CS = Charset.forName("gb18030");
+
+ /*
+ * @see CharsetEncoderTest#setUp()
+ */
+ protected void setUp() throws Exception {
+ cs = CS;
+ super.setUp();
+ }
+
+ /*
+ * @see CharsetEncoderTest#tearDown()
+ */
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testCanEncodechar() throws CharacterCodingException {
+ // normal case for utfCS
+ assertTrue(encoder.canEncode('\u0077'));
+ assertTrue(encoder.canEncode('\uc2a3'));
+
+ // for non-mapped char
+ assertTrue(encoder.canEncode('\uc2c0'));
+ }
+
+ /*
+ * Class under test for boolean canEncode(CharSequence)
+ */
+ public void testCanEncodeCharSequence() {
+ assertTrue(encoder.canEncode(""));
+ // surrogate char
+
+ // valid surrogate pair
+ assertTrue(encoder.canEncode("\ud800\udc00"));
+ // invalid surrogate pair
+ assertFalse(encoder.canEncode("\ud800\udb00"));
+ assertFalse(encoder.canEncode("\ud800"));
+ }
+
+ public void testSpecificDefaultValue() {
+ // FIXME: different here!
+ assertEquals(4.0, encoder.maxBytesPerChar(), 0.0);
+ assertEquals(2.5, encoder.averageBytesPerChar(), 0.0);
+
+ // assertTrue(encoder.averageBytesPerChar() == 3);
+ // assertTrue(encoder.maxBytesPerChar() == 2);
+
+ }
+
+ CharBuffer getMalformedCharBuffer() {
+ return CharBuffer.wrap("\ud800 buffer");
+ }
+
+ CharBuffer getUnmapCharBuffer() {
+ return null;
+ }
+
+ CharBuffer getExceptionCharBuffer() {
+ return null;
+ }
+
+ protected byte[] getIllegalByteArray() {
+ return new byte[] { (byte) 0xd8, (byte) 0x00 };
+ }
+
+}
diff --git a/nio_char/src/test/java/tests/api/java/nio/charset/ISOCharsetDecoderTest.java b/nio_char/src/test/java/tests/api/java/nio/charset/ISOCharsetDecoderTest.java
new file mode 100644
index 0000000..f1104cd
--- /dev/null
+++ b/nio_char/src/test/java/tests/api/java/nio/charset/ISOCharsetDecoderTest.java
@@ -0,0 +1,61 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.api.java.nio.charset;
+
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+
+/**
+ * test ISO-8859-1 decoder
+ */
+public class ISOCharsetDecoderTest extends CharsetDecoderTest {
+
+ protected void setUp() throws Exception {
+ cs = Charset.forName("iso-8859-1");
+ super.setUp();
+ }
+
+ /*
+ * @see CharsetDecoderTest#tearDown()
+ */
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ // FIXME: give up this tests
+ // public void testDefaultCharsPerByte(){
+ // assertEquals(1, decoder.averageCharsPerByte());
+ // assertEquals(decoder.maxCharsPerByte(), 2, 0.001);
+ // }
+
+ ByteBuffer getUnmappedByteBuffer() throws UnsupportedEncodingException {
+ // TODO how on map?
+ return null;
+
+ }
+
+ ByteBuffer getMalformByteBuffer() throws UnsupportedEncodingException {
+ // TODO how malform
+ return null;
+ }
+
+ ByteBuffer getExceptionByteArray() throws UnsupportedEncodingException {
+ return null;
+ }
+
+}
diff --git a/nio_char/src/test/java/tests/api/java/nio/charset/ISOCharsetEncoderTest.java b/nio_char/src/test/java/tests/api/java/nio/charset/ISOCharsetEncoderTest.java
new file mode 100644
index 0000000..ea25929
--- /dev/null
+++ b/nio_char/src/test/java/tests/api/java/nio/charset/ISOCharsetEncoderTest.java
@@ -0,0 +1,112 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package tests.api.java.nio.charset;
+
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.UnmappableCharacterException;
+
+/**
+ * test case specific activity of iso-8859-1 charset encoder
+ */
+public class ISOCharsetEncoderTest extends CharsetEncoderTest {
+
+ // charset for iso-8859-1
+ private static final Charset CS = Charset.forName("iso-8859-1");
+
+ /*
+ * @see CharsetEncoderTest#setUp()
+ */
+ protected void setUp() throws Exception {
+ cs = CS;
+ super.setUp();
+ }
+
+ /*
+ * @see CharsetEncoderTest#tearDown()
+ */
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testCanEncodeCharSequence() {
+ // normal case for isoCS
+ assertTrue(encoder.canEncode("\u0077"));
+ assertFalse(encoder.canEncode("\uc2a3"));
+ assertFalse(encoder.canEncode("\ud800\udc00"));
+ try {
+ encoder.canEncode(null);
+ } catch (NullPointerException e) {
+ }
+ assertTrue(encoder.canEncode(""));
+ }
+
+ public void testCanEncodeICUBug() {
+ assertFalse(encoder.canEncode((char) '\ud800'));
+ assertFalse(encoder.canEncode((String) "\ud800"));
+ }
+
+ public void testCanEncodechar() throws CharacterCodingException {
+ assertTrue(encoder.canEncode('\u0077'));
+ assertFalse(encoder.canEncode('\uc2a3'));
+ }
+
+ public void testSpecificDefaultValue() {
+ assertEquals(1, encoder.averageBytesPerChar(), 0.001);
+ assertEquals(1, encoder.maxBytesPerChar(), 0.001);
+ }
+
+ CharBuffer getMalformedCharBuffer() {
+ return CharBuffer.wrap("\ud800 buffer");
+ }
+
+ CharBuffer getUnmapCharBuffer() {
+ return CharBuffer.wrap("\ud800\udc00 buffer");
+ }
+
+ CharBuffer getExceptionCharBuffer() {
+ return null;
+ }
+
+ protected byte[] getIllegalByteArray() {
+ return null;
+ }
+
+ public void testMultiStepEncode() throws CharacterCodingException {
+ encoder.onMalformedInput(CodingErrorAction.REPORT);
+ encoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+ try {
+ encoder.encode(CharBuffer.wrap("\ud800\udc00"));
+ fail("should unmappable");
+ } catch (UnmappableCharacterException e) {
+ }
+ encoder.reset();
+ ByteBuffer out = ByteBuffer.allocate(10);
+ assertTrue(encoder.encode(CharBuffer.wrap("\ud800"), out, true)
+ .isMalformed());
+ encoder.flush(out);
+ encoder.reset();
+ out = ByteBuffer.allocate(10);
+ assertSame(CoderResult.UNDERFLOW, encoder.encode(CharBuffer
+ .wrap("\ud800"), out, false));
+ assertTrue(encoder.encode(CharBuffer.wrap("\udc00"), out, true)
+ .isMalformed());
+ }
+}
diff --git a/nio_char/src/test/java/tests/api/java/nio/charset/ISOCharsetTest.java b/nio_char/src/test/java/tests/api/java/nio/charset/ISOCharsetTest.java
new file mode 100644
index 0000000..5c010b2
--- /dev/null
+++ b/nio_char/src/test/java/tests/api/java/nio/charset/ISOCharsetTest.java
@@ -0,0 +1,58 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.api.java.nio.charset;
+
+/**
+ * Test ISO-8859-1.
+ */
+public class ISOCharsetTest extends AbstractCharsetTestCase {
+
+ /**
+ * Constructor.
+ */
+ public ISOCharsetTest(String arg0) {
+ super(arg0, "ISO-8859-1", new String[] { "iso-ir-100", "8859_1",
+ "ISO_8859-1", "ISO8859_1", "819", "csISOLatin1", "IBM-819",
+ "ISO_8859-1:1987", "latin1", "cp819", "ISO8859-1", "IBM819",
+ "ISO_8859_1", "l1" }, true, true);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see tests.api.java.nio.charset.ConcreteCharsetTest#testEncode_Normal()
+ */
+ public void testEncode_Normal() {
+ String input = "ab\u5D14\u654F";
+ byte[] output = new byte[] { 97, 98,
+ this.testingCharset.newEncoder().replacement()[0],
+ this.testingCharset.newEncoder().replacement()[0] };
+ internalTestEncode(input, output);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see tests.api.java.nio.charset.ConcreteCharsetTest#testDecode_Normal()
+ */
+ public void testDecode_Normal() {
+ byte[] input = new byte[] { 97, 98, 63, 63 };
+ char[] output = "ab??".toCharArray();
+ internalTestDecode(input, output);
+ }
+
+}
diff --git a/nio_char/src/test/java/tests/api/java/nio/charset/UTF16BECharsetDecoderTest.java b/nio_char/src/test/java/tests/api/java/nio/charset/UTF16BECharsetDecoderTest.java
new file mode 100644
index 0000000..9e2b66d
--- /dev/null
+++ b/nio_char/src/test/java/tests/api/java/nio/charset/UTF16BECharsetDecoderTest.java
@@ -0,0 +1,74 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.api.java.nio.charset;
+
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+
+/**
+ *
+ */
+public class UTF16BECharsetDecoderTest extends CharsetDecoderTest {
+
+ protected void setUp() throws Exception {
+ cs = Charset.forName("utf-16be");
+ unibytes = new byte[] { 0, 32, 0, 98, 0, 117, 0, 102, 0, 102, 0, 101,
+ 0, 114 };
+ super.setUp();
+ }
+
+ /*
+ * @see CharsetDecoderTest#tearDown()
+ */
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ // FIXME: give up this tests
+ // public void testDefaultCharsPerByte() {
+ // // assertEquals(1, decoder.averageCharsPerByte());
+ // // assertEquals(1, decoder.maxCharsPerByte());
+ // assertEquals(decoder.averageCharsPerByte(), 0.5, 0.001);
+ // assertEquals(decoder.maxCharsPerByte(), 2, 0.001);
+ // }
+
+ ByteBuffer getUnmappedByteBuffer() throws UnsupportedEncodingException {
+ // no unmap byte buffer
+ return null;
+ }
+
+ ByteBuffer getMalformByteBuffer() throws UnsupportedEncodingException {
+ // FIXME: different here, RI can parse 0xd8d8
+ // ByteBuffer buffer = ByteBuffer.allocate(100);
+ // buffer.put((byte)0xd8);
+ // buffer.put((byte)0xd8);
+ // buffer.put(unibytes);
+ // buffer.flip();
+ // return buffer;
+ return null;
+ }
+
+ ByteBuffer getExceptionByteArray() throws UnsupportedEncodingException {
+ return null;
+ }
+
+ byte[] getUnibytes() {
+ return new byte[] { 0, 32, 0, 98, 0, 117, 0, 102, 0, 102, 0, 101, 0,
+ 114 };
+ }
+}
diff --git a/nio_char/src/test/java/tests/api/java/nio/charset/UTF16BECharsetEncoderTest.java b/nio_char/src/test/java/tests/api/java/nio/charset/UTF16BECharsetEncoderTest.java
new file mode 100644
index 0000000..194b3b3
--- /dev/null
+++ b/nio_char/src/test/java/tests/api/java/nio/charset/UTF16BECharsetEncoderTest.java
@@ -0,0 +1,121 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.api.java.nio.charset;
+
+import java.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+
+/**
+ * TODO type def
+ */
+public class UTF16BECharsetEncoderTest extends CharsetEncoderTest {
+
+ // charset for utf-16be
+ private static final Charset CS = Charset.forName("utf-16be");
+
+ /*
+ * @see CharsetEncoderTest#setUp()
+ */
+ protected void setUp() throws Exception {
+ cs = CS;
+ specifiedReplacement = new byte[] { -1, -3 };
+ unibytes = new byte[] { 0, 32, 0, 98, 0, 117, 0, 102, 0, 102, 0, 101,
+ 0, 114 };
+
+ // unibytesWithRep = new byte[] {(byte)0xff, (byte)0xfd,0, 32, 0, 98, 0,
+ // 117, 0, 102, 0, 102, 0, 101, 0, 114};
+
+ super.setUp();
+ }
+
+ /*
+ * @see CharsetEncoderTest#tearDown()
+ */
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testCharsetEncoderCharsetfloatfloat() {
+ // this constructor is invalid for UTF16LE CharsetEncoder
+ }
+
+ public void testCanEncodechar() throws CharacterCodingException {
+ // normal case for utfCS
+ assertTrue(encoder.canEncode('\u0077'));
+ assertTrue(encoder.canEncode('\uc2a3'));
+
+ // for non-mapped char
+ assertTrue(encoder.canEncode('\uc2c0'));
+
+ }
+
+ public void testCanEncodeCharSequence() {
+ // normal case for utfCS
+ assertTrue(encoder.canEncode("\u0077"));
+ assertTrue(encoder.canEncode("\uc2a3"));
+ assertTrue(encoder.canEncode(""));
+
+ // for non-mapped char
+ assertTrue(encoder.canEncode("\uc2c0"));
+
+ // surrogate char for unicode
+ // 1st byte: d800-dbff
+ // 2nd byte: dc00-dfff
+ // valid surrogate pair
+ assertTrue(encoder.canEncode("\ud800\udc00"));
+ // invalid surrogate pair
+ assertFalse(encoder.canEncode("\ud800\udb00"));
+ }
+
+ public void testCanEncodeICUBug() {
+ assertFalse(encoder.canEncode("\ud800"));
+ }
+
+ public void testSpecificDefaultValue() {
+ // ??? TODO NIO adapt to the actually used UTF16BE charset Encoder
+ // assertEquals(2, encoder.averageBytesPerChar(), 0.001);
+ assertEquals(2, encoder.maxBytesPerChar(), 0.001);
+ }
+
+ CharBuffer getMalformedCharBuffer() {
+ return CharBuffer.wrap("\ud800 buffer");
+ }
+
+ CharBuffer getUnmapCharBuffer() {
+ return null;
+ }
+
+ CharBuffer getExceptionCharBuffer() {
+ return null;
+ }
+
+ public void testIsLegalReplacementEmptyArray() {
+ assertTrue(encoder.isLegalReplacement(new byte[0]));
+ }
+
+ protected byte[] getIllegalByteArray() {
+ // FIXME: different here
+ // cannot replace by 0xd8d8, but RI can
+ // return new byte[]{(byte)0xd8, (byte)0xd8};
+ return new byte[] { 0 };
+ }
+
+ protected byte[] getLegalByteArray() {
+ return new byte[] { (byte) 0x00, (byte) 0xd8 };
+ }
+}
diff --git a/nio_char/src/test/java/tests/api/java/nio/charset/UTF16BECharsetTest.java b/nio_char/src/test/java/tests/api/java/nio/charset/UTF16BECharsetTest.java
new file mode 100644
index 0000000..754afa3
--- /dev/null
+++ b/nio_char/src/test/java/tests/api/java/nio/charset/UTF16BECharsetTest.java
@@ -0,0 +1,53 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.api.java.nio.charset;
+
+/**
+ * Test UTF-16BE.
+ */
+public class UTF16BECharsetTest extends AbstractCharsetTestCase {
+
+ /**
+ * Constructor.
+ */
+ public UTF16BECharsetTest(String arg0) {
+ super(arg0, "UTF-16BE", new String[] { "X-UTF-16BE", "UTF_16BE" },
+ true, true); // "ISO-10646-UCS-2"
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see tests.api.java.nio.charset.ConcreteCharsetTest#testEncode_Normal()
+ */
+ public void testEncode_Normal() {
+ String input = "ab\u5D14\u654F";
+ byte[] output = new byte[] { 0, 97, 0, 98, 93, 20, 101, 79 };
+ internalTestEncode(input, output);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see tests.api.java.nio.charset.ConcreteCharsetTest#testDecode_Normal()
+ */
+ public void testDecode_Normal() {
+ byte[] input = new byte[] { 0, 97, 0, 98, 93, 20, 101, 79 };
+ char[] output = "ab\u5D14\u654F".toCharArray();
+ internalTestDecode(input, output);
+ }
+}
diff --git a/nio_char/src/test/java/tests/api/java/nio/charset/UTF16CharsetDecoderTest.java b/nio_char/src/test/java/tests/api/java/nio/charset/UTF16CharsetDecoderTest.java
new file mode 100644
index 0000000..fa1d5ec
--- /dev/null
+++ b/nio_char/src/test/java/tests/api/java/nio/charset/UTF16CharsetDecoderTest.java
@@ -0,0 +1,152 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.api.java.nio.charset;
+
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+
+/**
+ *
+ */
+public class UTF16CharsetDecoderTest extends CharsetDecoderTest {
+
+ boolean bigEndian = true;
+
+ protected void setUp() throws Exception {
+ cs = Charset.forName("utf-16");
+ unibytes = new byte[] { 32, 0, 98, 0, 117, 0, 102, 0, 102, 0, 101, 0,
+ 114, 0 };
+ bom = "\ufeff";
+
+ // unibytes = new byte[] {-1, -2, 0, 32, 0, 98, 0, 117, 0, 102, 0, 102,
+ // 0, 101, 0, 114};
+ super.setUp();
+ }
+
+ /*
+ * @see CharsetDecoderTest#tearDown()
+ */
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ byte[] getUnibytes() {
+ // FIXME: different here
+ // if don't specified BOM
+ // ICU default is LE
+ // JDK default is BE
+
+ // maybe start with 0xFEFF, which means big endian
+ // 0xFFFE, which means little endian
+ if (bigEndian) {
+ return new byte[] { -1, -2, 32, 0, 98, 0, 117, 0, 102, 0, 102, 0,
+ 101, 0, 114, 0 };
+ } else {
+ unibytes = new byte[] { 0, 32, 0, 98, 0, 117, 0, 102, 0, 102, 0,
+ 101, 0, 114 };
+ return new byte[] { -2, -1, 0, 32, 0, 98, 0, 117, 0, 102, 0, 102,
+ 0, 101, 0, 114 };
+ }
+ }
+
+ public void testMultiStepDecode() throws CharacterCodingException {
+ if (!cs.name().equals("mock")) {
+ decoder.onMalformedInput(CodingErrorAction.REPORT);
+ decoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+ CharBuffer out = CharBuffer.allocate(10);
+ assertTrue(decoder.decode(
+ ByteBuffer.wrap(new byte[] { -1, -2, 32, 0, 98 }), out,
+ true).isMalformed());
+
+ decoder.flush(out);
+ decoder.reset();
+ out.clear();
+ assertSame(CoderResult.UNDERFLOW, decoder.decode(ByteBuffer
+ .wrap(new byte[] { -1, -2, 32, 0 }), out, false));
+ assertTrue(decoder.decode(ByteBuffer.wrap(new byte[] { 98 }), out,
+ true).isMalformed());
+
+ decoder.flush(out);
+ decoder.reset();
+ out.clear();
+ assertSame(CoderResult.UNDERFLOW, decoder.decode(ByteBuffer
+ .wrap(new byte[] { -1, -2, 32, 0, 98 }), out, false));
+ assertFalse(decoder
+ .decode(ByteBuffer.wrap(new byte[] {}), out, true)
+ .isMalformed());
+
+ decoder.flush(out);
+ decoder.reset();
+ out.clear();
+ assertFalse(decoder.decode(
+ ByteBuffer.wrap(new byte[] { -1, -2, 32, 0, 98, 0 }), out,
+ true).isError());
+
+ decoder.flush(out);
+ decoder.reset();
+ out.clear();
+ assertSame(CoderResult.UNDERFLOW, decoder.decode(ByteBuffer
+ .wrap(new byte[] { -1, -2, 32, 0, 98 }), out, false));
+ assertTrue(decoder.decode(ByteBuffer.wrap(new byte[] { 0 }), out,
+ true).isMalformed());
+
+ }
+ }
+
+ public void testLittleEndian() throws CharacterCodingException,
+ UnsupportedEncodingException {
+ bigEndian = false;
+ implTestDecodeByteBufferCharBufferboolean();
+ decoder.reset();
+ implTestDecodeByteBuffer();
+ bigEndian = true;
+ }
+
+ // FIXME: give up this tests
+ // public void testDefaultCharsPerByte() {
+ // // assertEquals(1, decoder.averageCharsPerByte());
+ // // assertEquals(1, decoder.maxCharsPerByte());
+ // assertEquals(decoder.averageCharsPerByte(), 0.5, 0.001);
+ // assertEquals(decoder.maxCharsPerByte(), 2, 0.001);
+ // }
+
+ ByteBuffer getUnmappedByteBuffer() throws UnsupportedEncodingException {
+ return null;
+ }
+
+ ByteBuffer getMalformByteBuffer() throws UnsupportedEncodingException {
+ return null;
+ // FIXME: different here, RI can parse 0xd8d8
+ // ByteBuffer buffer = ByteBuffer.allocate(100);
+ // buffer.put((byte) -1);
+ // buffer.put((byte) -2);
+ // buffer.put((byte) 0xdc);
+ // buffer.put((byte) 0xdc);
+ // buffer.put(unibytes);
+ // buffer.flip();
+ // return buffer;
+ }
+
+ ByteBuffer getExceptionByteArray() throws UnsupportedEncodingException {
+ return null;
+ }
+}
diff --git a/nio_char/src/test/java/tests/api/java/nio/charset/UTF16CharsetEncoderTest.java b/nio_char/src/test/java/tests/api/java/nio/charset/UTF16CharsetEncoderTest.java
new file mode 100644
index 0000000..bdc505d
--- /dev/null
+++ b/nio_char/src/test/java/tests/api/java/nio/charset/UTF16CharsetEncoderTest.java
@@ -0,0 +1,138 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.api.java.nio.charset;
+
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+
+/**
+ * TODO type def
+ */
+public class UTF16CharsetEncoderTest extends CharsetEncoderTest {
+
+ // charset for utf-16
+ // charset for utf-16be
+ private static final Charset CS = Charset.forName("utf-16");
+
+ private static final CharsetDecoder decoder = CS.newDecoder();
+
+ /*
+ * @see CharsetEncoderTest#setUp()
+ */
+ protected void setUp() throws Exception {
+ cs = CS;
+ specifiedReplacement = new byte[] { -3, -1 };
+ surrogate = new byte[] { -1, -2 };
+ unibytes = new byte[] { 32, 0, 98, 0, 117, 0, 102, 0, 102, 0, 101, 0,
+ 114, 0 };
+ unibytesWithRep = new byte[] { -3, -1, 32, 0, 98, 0, 117, 0, 102, 0,
+ 102, 0, 101, 0, 114, 0 };
+ super.setUp();
+ }
+
+ /*
+ * @see CharsetEncoderTest#tearDown()
+ */
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testCharsetEncoderCharsetfloatfloat() {
+ // this constructor is invalid for UTF16LE CharsetEncoder
+ }
+
+ public void testCanEncodechar() throws CharacterCodingException {
+ // normal case for utfCS
+ assertTrue(encoder.canEncode('\u0077'));
+ assertTrue(encoder.canEncode('\uc2a3'));
+
+ // for non-mapped char
+ assertTrue(encoder.canEncode('\uc2c0'));
+ }
+
+ public void testCanEncodeCharSequence() {
+ // normal case for utfCS
+ assertTrue(encoder.canEncode("\u0077"));
+ assertTrue(encoder.canEncode("\uc2a3"));
+ assertTrue(encoder.canEncode(""));
+
+ // for non-mapped char
+ assertTrue(encoder.canEncode("\uc2c0"));
+
+ // surrogate char for unicode
+ // 1st byte: d800-dbff
+ // 2nd byte: dc00-dfff
+ // valid surrogate pair
+ assertTrue(encoder.canEncode("\ud800\udc00"));
+ // invalid surrogate pair
+ assertFalse(encoder.canEncode("\ud800\udb00"));
+ }
+
+ public void testCanEncodeICUBug() {
+ assertFalse(encoder.canEncode('\ud800'));
+ assertFalse(encoder.canEncode("\ud800"));
+ }
+
+ public void testSpecificDefaultValue() {
+ assertEquals(encoder.averageBytesPerChar(), 2, 0.001);
+ // assertEquals(4, encoder.maxBytesPerChar());
+ // FIXME: different here!
+ assertEquals(encoder.maxBytesPerChar(), 2, 0.001);
+ }
+
+ CharBuffer getMalformedCharBuffer() {
+ return CharBuffer.wrap("\ud800 buffer");
+ }
+
+ CharBuffer getUnmapCharBuffer() {
+ return null;
+ }
+
+ CharBuffer getExceptionCharBuffer() {
+ return null;
+ }
+
+ public void testIsLegalReplacementEmptyArray() {
+ assertTrue(encoder.isLegalReplacement(new byte[0]));
+ }
+
+ protected byte[] getIllegalByteArray() {
+ return new byte[] { 0x00 };
+ }
+
+ protected byte[] getLegalByteArray() {
+ // FIXME: Different Here!
+ // return new byte[]{(byte)0xd8, 0x00};
+ return new byte[] { (byte) 0x00, (byte) 0xd8 };
+ }
+
+ void assertByteArray(ByteBuffer out, byte[] expected) {
+ out = out.duplicate();
+ if (out.position() > 0) {
+ out.flip();
+ }
+ try {
+ assertEquals(decoder.decode(out), decoder.decode(ByteBuffer
+ .wrap(expected)));
+ } catch (CharacterCodingException e) {
+ fail(e.toString());
+ }
+ }
+}
diff --git a/nio_char/src/test/java/tests/api/java/nio/charset/UTF16CharsetTest.java b/nio_char/src/test/java/tests/api/java/nio/charset/UTF16CharsetTest.java
new file mode 100644
index 0000000..e77be5e
--- /dev/null
+++ b/nio_char/src/test/java/tests/api/java/nio/charset/UTF16CharsetTest.java
@@ -0,0 +1,51 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.api.java.nio.charset;
+
+/**
+ * Test UTF-16.
+ */
+public class UTF16CharsetTest extends AbstractCharsetTestCase {
+
+ /**
+ * Constructor.
+ */
+ public UTF16CharsetTest(String arg0) {
+ super(arg0, "UTF-16", new String[] { "UTF_16" }, true, true);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see tests.api.java.nio.charset.ConcreteCharsetTest#testEncode_Normal()
+ */
+ public void testEncode_Normal() {
+ // TODO Auto-generated method stub
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see tests.api.java.nio.charset.ConcreteCharsetTest#testDecode_Normal()
+ */
+ public void testDecode_Normal() {
+ // TODO Auto-generated method stub
+
+ }
+
+}
diff --git a/nio_char/src/test/java/tests/api/java/nio/charset/UTF16LECharsetDecoderTest.java b/nio_char/src/test/java/tests/api/java/nio/charset/UTF16LECharsetDecoderTest.java
new file mode 100644
index 0000000..183fa47
--- /dev/null
+++ b/nio_char/src/test/java/tests/api/java/nio/charset/UTF16LECharsetDecoderTest.java
@@ -0,0 +1,74 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.api.java.nio.charset;
+
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+
+/**
+ * TODO typedef
+ */
+public class UTF16LECharsetDecoderTest extends CharsetDecoderTest {
+
+ protected void setUp() throws Exception {
+ cs = Charset.forName("utf-16le");
+ unibytes = new byte[] { 32, 0, 98, 0, 117, 0, 102, 0, 102, 0, 101, 0,
+ 114, 0 };
+ super.setUp();
+ }
+
+ /*
+ * @see CharsetDecoderTest#tearDown()
+ */
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ // // FIXME: give up this tests
+ // public void testDefaultCharsPerByte(){
+ // // assertEquals(1, decoder.averageCharsPerByte());
+ // // assertEquals(1, decoder.maxCharsPerByte());
+ // assertEquals(decoder.averageCharsPerByte(), 0.5, 0.001);
+ // assertEquals(decoder.maxCharsPerByte(), 2, 0.001);
+ // }
+
+ ByteBuffer getUnmappedByteBuffer() throws UnsupportedEncodingException {
+ // no unmap byte buffer
+ return null;
+ }
+
+ ByteBuffer getMalformByteBuffer() throws UnsupportedEncodingException {
+ // FIXME: different here, JDK can parse 0xd8d8
+ // ByteBuffer buffer = ByteBuffer.allocate(100);
+ // buffer.put((byte)0xd8);
+ // buffer.put((byte)0xd8);
+ // buffer.put(unibytes);
+ // buffer.flip();
+ // return buffer;
+ return null;
+ }
+
+ ByteBuffer getExceptionByteArray() throws UnsupportedEncodingException {
+ return null;
+ }
+
+ byte[] getUnibytes() {
+ return new byte[] { 32, 0, 98, 0, 117, 0, 102, 0, 102, 0, 101, 0, 114,
+ 0 };
+ }
+}
diff --git a/nio_char/src/test/java/tests/api/java/nio/charset/UTF16LECharsetEncoderTest.java b/nio_char/src/test/java/tests/api/java/nio/charset/UTF16LECharsetEncoderTest.java
new file mode 100644
index 0000000..e669e11
--- /dev/null
+++ b/nio_char/src/test/java/tests/api/java/nio/charset/UTF16LECharsetEncoderTest.java
@@ -0,0 +1,118 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.api.java.nio.charset;
+
+import java.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+
+/**
+ * TODO type def
+ */
+public class UTF16LECharsetEncoderTest extends CharsetEncoderTest {
+
+ // charset for utf-16le
+ private static final Charset CS = Charset.forName("utf-16le");
+
+ /*
+ * @see CharsetEncoderTest#setUp()
+ */
+ protected void setUp() throws Exception {
+ cs = CS;
+ specifiedReplacement = new byte[] { -3, -1 };
+
+ unibytes = new byte[] { 32, 0, 98, 0, 117, 0, 102, 0, 102, 0, 101, 0,
+ 114, 0 };
+
+ // unibytesWithRep = new byte[] {(byte)0xfd, (byte)0xff, 32, 0, 98, 0,
+ // 117, 0, 102, 0, 102, 0, 101, 0, 114 ,0};
+
+ super.setUp();
+ }
+
+ /*
+ * @see CharsetEncoderTest#tearDown()
+ */
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testCharsetEncoderCharsetfloatfloat() {
+ // this constructor is invalid for UTF16LE CharsetEncoder
+ }
+
+ public void testCanEncodechar() throws CharacterCodingException {
+ // normal case for utfCS
+ assertTrue(encoder.canEncode('\u0077'));
+ assertTrue(encoder.canEncode('\uc2a3'));
+
+ // for non-mapped char
+ assertTrue(encoder.canEncode('\uc2c0'));
+ }
+
+ public void testCanEncodeCharSequence() {
+ // normal case for utfCS
+ assertTrue(encoder.canEncode("\u0077"));
+ assertTrue(encoder.canEncode("\uc2a3"));
+ assertTrue(encoder.canEncode(""));
+
+ // for non-mapped char
+ assertTrue(encoder.canEncode("\uc2c0"));
+
+ // surrogate char for unicode
+ // 1st byte: d800-dbff
+ // 2nd byte: dc00-dfff
+ // valid surrogate pair
+ assertTrue(encoder.canEncode("\ud800\udc00"));
+ // invalid surrogate pair
+ assertFalse(encoder.canEncode("\ud800\udb00"));
+ }
+
+ public void testCanEncodeICUBug() {
+ assertFalse(encoder.canEncode("\ud800"));
+ }
+
+ public void testSpecificDefaultValue() {
+ assertEquals(2, encoder.averageBytesPerChar(), 0.001);
+ assertEquals(2, encoder.maxBytesPerChar(), 0.001);
+ }
+
+ public void testIsLegalReplacementEmptyArray() {
+ assertTrue(encoder.isLegalReplacement(new byte[0]));
+ }
+
+ CharBuffer getMalformedCharBuffer() {
+ return CharBuffer.wrap("\ud800 buffer");
+ }
+
+ CharBuffer getUnmapCharBuffer() {
+ return null;
+ }
+
+ CharBuffer getExceptionCharBuffer() {
+ return null;
+ }
+
+ protected byte[] getIllegalByteArray() {
+ return new byte[] { 0x00 };
+ }
+
+ protected byte[] getLegalByteArray() {
+ return new byte[] { (byte) 0xd8, 0x00 };
+ }
+
+}
diff --git a/nio_char/src/test/java/tests/api/java/nio/charset/UTF16LECharsetTest.java b/nio_char/src/test/java/tests/api/java/nio/charset/UTF16LECharsetTest.java
new file mode 100644
index 0000000..b32ab9b
--- /dev/null
+++ b/nio_char/src/test/java/tests/api/java/nio/charset/UTF16LECharsetTest.java
@@ -0,0 +1,54 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.api.java.nio.charset;
+
+/**
+ * Test UTF-16LE.
+ */
+public class UTF16LECharsetTest extends AbstractCharsetTestCase {
+
+ /**
+ * Constructor.
+ */
+ public UTF16LECharsetTest(String arg0) {
+ super(arg0, "UTF-16LE", new String[] { "UTF_16LE", "X-UTF-16LE" },
+ true, true);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see tests.api.java.nio.charset.ConcreteCharsetTest#testEncode_Normal()
+ */
+ public void testEncode_Normal() {
+ String input = "ab\u5D14\u654F";
+ byte[] output = new byte[] { 97, 0, 98, 0, 20, 93, 79, 101 };
+ internalTestEncode(input, output);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see tests.api.java.nio.charset.ConcreteCharsetTest#testDecode_Normal()
+ */
+ public void testDecode_Normal() {
+ byte[] input = new byte[] { 97, 0, 98, 0, 20, 93, 79, 101 };
+ char[] output = "ab\u5D14\u654F".toCharArray();
+ internalTestDecode(input, output);
+ }
+
+}
diff --git a/nio_char/src/test/java/tests/api/java/nio/charset/UTF8CharsetTest.java b/nio_char/src/test/java/tests/api/java/nio/charset/UTF8CharsetTest.java
new file mode 100644
index 0000000..8e0f57f
--- /dev/null
+++ b/nio_char/src/test/java/tests/api/java/nio/charset/UTF8CharsetTest.java
@@ -0,0 +1,53 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.api.java.nio.charset;
+
+/**
+ * Test UTF-8 charset.
+ */
+public class UTF8CharsetTest extends AbstractCharsetTestCase {
+
+ /**
+ * Constructor for UTF8CharsetTest.
+ *
+ */
+ public UTF8CharsetTest(String arg0) {
+ super(arg0, "UTF-8", new String[] { "UTF8" }, true, true);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see tests.api.java.nio.charset.ConcreteCharsetTest#testDecode_Normal()
+ */
+ public void testDecode_Normal() {
+ byte[] input = new byte[] { 97, 98, -27, -76, -108, -26, -107, -113 };
+ char[] output = "ab\u5D14\u654F".toCharArray();
+ internalTestDecode(input, output);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see tests.api.java.nio.charset.ConcreteCharsetTest#testEncode_Normal()
+ */
+ public void testEncode_Normal() {
+ String input = "ab\u5D14\u654F";
+ byte[] output = new byte[] { 97, 98, -27, -76, -108, -26, -107, -113 };
+ internalTestEncode(input, output);
+ }
+}
diff --git a/nio_char/src/test/java/tests/api/java/nio/charset/UTFCharsetDecoderTest.java b/nio_char/src/test/java/tests/api/java/nio/charset/UTFCharsetDecoderTest.java
new file mode 100644
index 0000000..288cd16
--- /dev/null
+++ b/nio_char/src/test/java/tests/api/java/nio/charset/UTFCharsetDecoderTest.java
@@ -0,0 +1,63 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.api.java.nio.charset;
+
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+
+/**
+ * test utf-8 decoder
+ */
+public class UTFCharsetDecoderTest extends CharsetDecoderTest {
+
+ protected void setUp() throws Exception {
+ cs = Charset.forName("utf-8");
+ super.setUp();
+ }
+
+ /*
+ * @see CharsetDecoderTest#tearDown()
+ */
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ // FIXME: give up this tests
+ // public void testDefaultCharsPerByte(){
+ // assertEquals(decoder.averageCharsPerByte(), 0.333, 0.001);
+ // assertEquals(decoder.maxCharsPerByte(), 2, 0.001);
+ // // assertEquals(1, decoder.averageCharsPerByte());
+ // // assertEquals(1, decoder.maxCharsPerByte());
+ // }
+
+ ByteBuffer getUnmappedByteBuffer() throws UnsupportedEncodingException {
+ return null;
+ }
+
+ ByteBuffer getMalformByteBuffer() throws UnsupportedEncodingException {
+ ByteBuffer buffer = ByteBuffer.allocate(20);
+ buffer.put((byte) 0xd8);
+ buffer.put(unibytes);
+ buffer.flip();
+ return buffer;
+ }
+
+ ByteBuffer getExceptionByteArray() throws UnsupportedEncodingException {
+ return null;
+ }
+}
diff --git a/nio_char/src/test/java/tests/api/java/nio/charset/UTFCharsetEncoderTest.java b/nio_char/src/test/java/tests/api/java/nio/charset/UTFCharsetEncoderTest.java
new file mode 100644
index 0000000..b4f1e7d
--- /dev/null
+++ b/nio_char/src/test/java/tests/api/java/nio/charset/UTFCharsetEncoderTest.java
@@ -0,0 +1,102 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.api.java.nio.charset;
+
+import java.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+
+/**
+ * test case specific activity of utf-8 charset encoder
+ */
+public class UTFCharsetEncoderTest extends CharsetEncoderTest {
+
+ // charset for UTF-8
+ private static final Charset CS = Charset.forName("utf-8");
+
+ /*
+ * @see CharsetEncoderTest#setUp()
+ */
+ protected void setUp() throws Exception {
+ cs = CS;
+ specifiedReplacement = new byte[] { -17, -65, -67 };
+ super.setUp();
+ }
+
+ /*
+ * @see CharsetEncoderTest#tearDown()
+ */
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testCanEncodechar() throws CharacterCodingException {
+ // normal case for utfCS
+ assertTrue(encoder.canEncode('\u0077'));
+ assertTrue(encoder.canEncode('\uc2a3'));
+
+ // for non-mapped char
+ assertTrue(encoder.canEncode('\uc2c0'));
+ }
+
+ public void testCanEncodeCharSequence() {
+ // normal case for utfCS
+ assertTrue(encoder.canEncode("\u0077"));
+ assertTrue(encoder.canEncode("\uc2a3"));
+ assertTrue(encoder.canEncode(""));
+
+ // for non-mapped char
+ assertTrue(encoder.canEncode("\uc2c0"));
+
+ // surrogate char for unicode
+ // 1st byte: d800-dbff
+ // 2nd byte: dc00-dfff
+ // valid surrogate pair
+ assertTrue(encoder.canEncode("\ud800\udc00"));
+ // invalid surrogate pair
+ assertFalse(encoder.canEncode("\ud800\udb00"));
+ }
+
+ public void testCanEncodeICUBug() {
+ assertFalse(encoder.canEncode("\ud800"));
+ }
+
+ public void testSpecificDefaultValue() {
+ // assertEquals(1.1, encoder.averageBytesPerChar(), 0.0001);
+ assertEquals(2, encoder.averageBytesPerChar(), 0.0001);
+ assertEquals(3, encoder.maxBytesPerChar(), 0);
+ }
+
+ CharBuffer getMalformedCharBuffer() {
+ return CharBuffer.wrap("\ud800 buffer");
+ }
+
+ CharBuffer getUnmapCharBuffer() {
+ return null;
+ }
+
+ CharBuffer getExceptionCharBuffer() {
+ return null;
+ }
+
+ protected byte[] getIllegalByteArray() {
+ return new byte[] { (byte) 0xd8, (byte) 0x00 };
+ }
+
+ protected void assertFlushed() {
+ }
+}
diff --git a/nio_char/src/test/java/tests/nio_char/AllTests.java b/nio_char/src/test/java/tests/nio_char/AllTests.java
new file mode 100644
index 0000000..f466b07
--- /dev/null
+++ b/nio_char/src/test/java/tests/nio_char/AllTests.java
@@ -0,0 +1,40 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.nio_char;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Test suite that includes all tests for the NIO_Char project.
+ */
+public class AllTests {
+
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(AllTests.suite());
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite("All NIO_Char test suites");
+ // $JUnit-BEGIN$
+ suite.addTest(org.apache.harmony.nio_char.tests.java.nio.charset.AllTests.suite());
+ suite.addTest(org.apache.harmony.nio_char.tests.java.nio.charset.spi.AllTests.suite());
+ suite.addTest(tests.api.java.nio.charset.AllTests.suite());
+ // $JUnit-END$
+ return suite;
+ }
+}
diff --git a/nio_char/src/test/resources/jars/charset_provider.jar b/nio_char/src/test/resources/jars/charset_provider.jar
new file mode 100644
index 0000000..f1230d9
--- /dev/null
+++ b/nio_char/src/test/resources/jars/charset_provider.jar
Binary files differ
diff --git a/nio_char/src/test/resources/serialization/org/apache/harmony/nio_char/tests/java/nio/charset/CharacterCodingExceptionTest.golden.ser b/nio_char/src/test/resources/serialization/org/apache/harmony/nio_char/tests/java/nio/charset/CharacterCodingExceptionTest.golden.ser
new file mode 100644
index 0000000..a95c4e4
--- /dev/null
+++ b/nio_char/src/test/resources/serialization/org/apache/harmony/nio_char/tests/java/nio/charset/CharacterCodingExceptionTest.golden.ser
Binary files differ
diff --git a/nio_char/src/test/resources/serialization/org/apache/harmony/nio_char/tests/java/nio/charset/CoderMalfunctionErrorTest.golden.ser b/nio_char/src/test/resources/serialization/org/apache/harmony/nio_char/tests/java/nio/charset/CoderMalfunctionErrorTest.golden.ser
new file mode 100644
index 0000000..6f4a4e3
--- /dev/null
+++ b/nio_char/src/test/resources/serialization/org/apache/harmony/nio_char/tests/java/nio/charset/CoderMalfunctionErrorTest.golden.ser
Binary files differ
diff --git a/nio_char/src/test/resources/serialization/org/apache/harmony/nio_char/tests/java/nio/charset/IllegalCharsetNameExceptionTest.golden.ser b/nio_char/src/test/resources/serialization/org/apache/harmony/nio_char/tests/java/nio/charset/IllegalCharsetNameExceptionTest.golden.ser
new file mode 100644
index 0000000..59e4d0b
--- /dev/null
+++ b/nio_char/src/test/resources/serialization/org/apache/harmony/nio_char/tests/java/nio/charset/IllegalCharsetNameExceptionTest.golden.ser
Binary files differ
diff --git a/nio_char/src/test/resources/serialization/org/apache/harmony/nio_char/tests/java/nio/charset/MalformedInputExceptionTest.golden.ser b/nio_char/src/test/resources/serialization/org/apache/harmony/nio_char/tests/java/nio/charset/MalformedInputExceptionTest.golden.ser
new file mode 100644
index 0000000..e2f0dec
--- /dev/null
+++ b/nio_char/src/test/resources/serialization/org/apache/harmony/nio_char/tests/java/nio/charset/MalformedInputExceptionTest.golden.ser
Binary files differ
diff --git a/nio_char/src/test/resources/serialization/org/apache/harmony/nio_char/tests/java/nio/charset/UnmappableCharacterExceptionTest.golden.ser b/nio_char/src/test/resources/serialization/org/apache/harmony/nio_char/tests/java/nio/charset/UnmappableCharacterExceptionTest.golden.ser
new file mode 100644
index 0000000..7933fb9
--- /dev/null
+++ b/nio_char/src/test/resources/serialization/org/apache/harmony/nio_char/tests/java/nio/charset/UnmappableCharacterExceptionTest.golden.ser
Binary files differ
diff --git a/nio_char/src/test/resources/serialization/org/apache/harmony/nio_char/tests/java/nio/charset/UnsupportedCharsetExceptionTest.golden.ser b/nio_char/src/test/resources/serialization/org/apache/harmony/nio_char/tests/java/nio/charset/UnsupportedCharsetExceptionTest.golden.ser
new file mode 100644
index 0000000..07c63bb
--- /dev/null
+++ b/nio_char/src/test/resources/serialization/org/apache/harmony/nio_char/tests/java/nio/charset/UnsupportedCharsetExceptionTest.golden.ser
Binary files differ