harmony-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ge...@apache.org
Subject svn commit: r350181 [130/198] - in /incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core: ./ depends/ depends/files/ depends/jars/ depends/libs/ depends/libs/linux.IA32/ depends/libs/win.IA32/ depends/oss/ depends/oss/linux.IA32/ depends/oss/win....
Date Thu, 01 Dec 2005 06:04:00 GMT
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio/src/java/nio/channels/Selector.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio/src/java/nio/channels/Selector.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio/src/java/nio/channels/Selector.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio/src/java/nio/channels/Selector.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,54 @@
+/* Copyright 2005 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed 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.channels;
+
+
+import java.io.IOException;
+import java.nio.channels.spi.SelectorProvider;
+import java.util.Set;
+
+/**
+ * TODO Type description
+ * 
+ */
+public abstract class Selector {
+
+	public static Selector open() throws IOException {
+		return SelectorProvider.provider().openSelector();
+	}
+
+	protected Selector() {
+		super();
+	}
+
+	public abstract void close() throws IOException;
+
+	public abstract boolean isOpen();
+
+	public abstract Set keys();
+
+	public abstract SelectorProvider provider();
+
+	public abstract int select() throws IOException;
+
+	public abstract int select(long timeout) throws IOException;
+
+	public abstract Set selectedKeys();
+
+	public abstract int selectNow() throws IOException;
+
+	public abstract Selector wakeup();
+}

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio/src/java/nio/channels/UnresolvedAddressException.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio/src/java/nio/channels/UnresolvedAddressException.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio/src/java/nio/channels/UnresolvedAddressException.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio/src/java/nio/channels/UnresolvedAddressException.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,35 @@
+/* Copyright 2005 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed 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.channels;
+
+
+/**
+ * Thrown when trying to use an unresolved network address in a network
+ * operation.
+ * 
+ */
+public class UnresolvedAddressException extends IllegalArgumentException {
+
+	static final long serialVersionUID = 6136959093620794148L;
+
+	/**
+	 * Default constructor.
+	 * 
+	 */
+	public UnresolvedAddressException() {
+		super();
+	}
+}

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio/src/java/nio/channels/UnsupportedAddressTypeException.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio/src/java/nio/channels/UnsupportedAddressTypeException.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio/src/java/nio/channels/UnsupportedAddressTypeException.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio/src/java/nio/channels/UnsupportedAddressTypeException.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,34 @@
+/* Copyright 2005 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed 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.channels;
+
+
+/**
+ * Thrown when connecting or binding to an unsupported address type.
+ * 
+ */
+public class UnsupportedAddressTypeException extends IllegalArgumentException {
+
+	static final long serialVersionUID = -2964323842829700493L;
+
+	/**
+	 * Default constructor.
+	 * 
+	 */
+	public UnsupportedAddressTypeException() {
+		super();
+	}
+}

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio/src/java/nio/channels/WritableByteChannel.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio/src/java/nio/channels/WritableByteChannel.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio/src/java/nio/channels/WritableByteChannel.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio/src/java/nio/channels/WritableByteChannel.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,67 @@
+/* Copyright 2004 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed 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.channels;
+
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+/**
+ * A WriteableByteChannel is a type of Channel that can write bytes.
+ * <p>
+ * Writes are synchronous on a WriteableByteChannel, that is, if a write is
+ * already in progress on the channel then subsequent writes will block until
+ * the first write completes. It is undefined whether non-write operations will
+ * block.
+ * 
+ */
+public interface WritableByteChannel extends Channel {
+
+	/**
+	 * Writes bytes from the given buffer to the channel.
+	 * <p>
+	 * The maximum number of bytes that will be written is the
+	 * <code>remaining()</code> number of bytes in the buffer when the method
+	 * invoked. The bytes will be written from the buffer starting at the
+	 * buffer's <code>position</code>.
+	 * </p>
+	 * <p>
+	 * The call may block if other threads are also attempting to write on the
+	 * same channel.
+	 * </p>
+	 * <p>
+	 * Upon completion, the buffer's <code>position()</code> is updated to the
+	 * end of the bytes that were written. The buffer's <code>limit()</code>
+	 * is unmodified.
+	 * </p>
+	 * 
+	 * @param buffer
+	 *            the byte buffer containing the bytes to be written.
+	 * @return the number of bytes actually written.
+	 * @throws NonWritableChannelException
+	 *             if the channel was not opened for writing.
+	 * @throws ClosedChannelException
+	 *             if the channel was already closed.
+	 * @throws AsynchronousCloseException
+	 *             if another thread closes the channel during the write.
+	 * @throws ClosedByInterruptException
+	 *             if another thread interrupt the calling thread during the
+	 *             write.
+	 * @throws IOException
+	 *             another IO exception occurs, details are in the message.
+	 */
+	public int write(ByteBuffer buffer) throws IOException;
+}

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio/src/java/nio/channels/spi/AbstractInterruptibleChannel.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio/src/java/nio/channels/spi/AbstractInterruptibleChannel.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio/src/java/nio/channels/spi/AbstractInterruptibleChannel.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio/src/java/nio/channels/spi/AbstractInterruptibleChannel.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,114 @@
+/* Copyright 2004 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed 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.channels.spi;
+
+
+import java.io.IOException;
+import java.nio.channels.AsynchronousCloseException;
+import java.nio.channels.Channel;
+import java.nio.channels.InterruptibleChannel;
+
+/**
+ * This class roots the implementation of interruptable channels.
+ * <p>
+ * The basic usage pattern for an interruptible channel is to invoke
+ * <code>begin()</code> before any IO operations, then
+ * <code>end(boolean)</code> after completing the operation. The argument to
+ * the end method shows whether there has been any change to the java
+ * environment that is visible to the API user.
+ * </p>
+ * 
+ */
+public abstract class AbstractInterruptibleChannel implements Channel,
+		InterruptibleChannel {
+
+	private boolean isClosed = false;
+
+	/**
+	 * Default constructor.
+	 */
+	public AbstractInterruptibleChannel() {
+		super();
+	}
+
+	/**
+	 * Answers whether the channel is open.
+	 * 
+	 * @return true if the channel is open, and false if it is closed.
+	 * @see java.nio.channels.Channel#isOpen()
+	 */
+	public boolean isOpen() {
+		return !isClosed;
+	}
+
+	/**
+	 * Closes the channel.
+	 * <p>
+	 * If the channel is already closed then this method has no effect,
+	 * otherwise it closes the receiver via the implCloseChannel method.
+	 * </p>
+	 * 
+	 * @see java.nio.channels.Channel#close()
+	 */
+	public synchronized final void close() throws IOException {
+		if (!isClosed) {
+			closeChannel();
+			isClosed = true;
+		}
+	}
+
+	/**
+	 * Start an IO operation that is potentially blocking.
+	 * <p>
+	 * Once the operation is completed the applicaion should invoke a
+	 * corresponding <code>end(boolean)</code>.
+	 */
+	protected synchronized final void begin() {
+		// TODO
+	}
+
+	/**
+	 * End an IO operation that was previously started with <code>begin()</code>.
+	 * 
+	 * @param success
+	 *            pass true if the operation succeeded and had a side effcet on
+	 *            the Java system, or false if not.
+	 * @throws AsynchronousCloseException
+	 *             the channel was closed while the IO operation was in
+	 *             progress.
+	 * @throws java.nio.channels.ClosedByInterruptException
+	 *             the thread conducting the IO operation was interrupted.
+	 */
+	protected final void end(boolean success) throws AsynchronousCloseException {
+		// TODO
+	}
+
+	/**
+	 * Implements the close channel behavior.
+	 * <p>
+	 * Closes the channel with a guarantee that the channel is not currently
+	 * closed via <code>close()</code> and that the method is thread-safe.
+	 * </p>
+	 * <p>
+	 * any outstanding threads blocked on IO operations on this channel must be
+	 * released with either a normal return code, or an
+	 * <code>AsynchronousCloseException</code>.
+	 * 
+	 * @throws IOException
+	 *             if a problem occurs closig the channel.
+	 */
+	protected abstract void closeChannel() throws IOException;
+}

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio/src/java/nio/channels/spi/AbstractSelectableChannel.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio/src/java/nio/channels/spi/AbstractSelectableChannel.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio/src/java/nio/channels/spi/AbstractSelectableChannel.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio/src/java/nio/channels/spi/AbstractSelectableChannel.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,38 @@
+/* Copyright 2005 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed 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.channels.spi;
+
+
+import java.nio.channels.Channel;
+import java.nio.channels.InterruptibleChannel;
+import java.nio.channels.SelectableChannel;
+
+/**
+ * TODO Type description
+ * 
+ */
+public abstract class AbstractSelectableChannel extends SelectableChannel
+		implements Channel, InterruptibleChannel {
+
+	/**
+	 * @param provider
+	 */
+	public AbstractSelectableChannel(SelectorProvider provider) {
+
+		// TODO Auto-generated constructor stub
+	}
+
+}

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio/src/java/nio/channels/spi/AbstractSelector.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio/src/java/nio/channels/spi/AbstractSelector.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio/src/java/nio/channels/spi/AbstractSelector.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio/src/java/nio/channels/spi/AbstractSelector.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,27 @@
+/* Copyright 2005 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed 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.channels.spi;
+
+
+import java.nio.channels.Selector;
+
+/**
+ * TODO Type description
+ * 
+ */
+public abstract class AbstractSelector extends Selector {
+
+}

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio/src/java/nio/channels/spi/SelectorProvider.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio/src/java/nio/channels/spi/SelectorProvider.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio/src/java/nio/channels/spi/SelectorProvider.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio/src/java/nio/channels/spi/SelectorProvider.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,39 @@
+/* Copyright 2005 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed 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.channels.spi;
+
+
+import java.io.IOException;
+import java.nio.channels.Pipe;
+
+/**
+ * TODO Type description
+ * 
+ */
+public abstract class SelectorProvider {
+
+	/**
+	 * @return TODO
+	 */
+	public static SelectorProvider provider() {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public abstract Pipe openPipe() throws IOException;
+
+	public abstract AbstractSelector openSelector() throws IOException;
+}

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio_char/META-INF/MANIFEST.MF
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio_char/META-INF/MANIFEST.MF?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio_char/META-INF/MANIFEST.MF (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio_char/META-INF/MANIFEST.MF Wed Nov 30 21:29:27 2005
@@ -0,0 +1,19 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Harmony NIO_Charset
+Bundle-SymbolicName: org.apache.harmony.nio_char
+Bundle-Version: 1.0.0
+Bundle-ClassPath: .
+Eclipse-JREBundle: true
+Export-Package: java.nio.charset,
+ java.nio.charset.spi
+Import-Package: java.lang,
+ java.util, 
+ java.net, 
+ java.io,  
+ java.lang.ref, 
+ java.security, 
+ java.nio
+Require-Bundle: org.apache.harmony.luni,
+ org.apache.harmony.nio,
+ org.apache.harmony.security

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio_char/src/java/nio/charset/CharacterCodingException.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio_char/src/java/nio/charset/CharacterCodingException.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio_char/src/java/nio/charset/CharacterCodingException.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio_char/src/java/nio/charset/CharacterCodingException.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,46 @@
+/* Copyright 2004, 2005 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed 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 {
+
+	/*
+	 * -------------------------------------------------------------------
+	 * Constants
+	 * -------------------------------------------------------------------
+	 */
+
+	/*
+	 * This constant is used during deserialization to check the J2SE version
+	 * which created the serialized object.
+	 */
+	static final long serialVersionUID = 8421532232154627783L; // J2SE 1.4.2
+
+	/**
+	 * Default constructor.
+	 */
+	public CharacterCodingException() {
+		super();
+	}
+}

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio_char/src/java/nio/charset/Charset.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio_char/src/java/nio/charset/Charset.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio_char/src/java/nio/charset/Charset.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio_char/src/java/nio/charset/Charset.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,728 @@
+/* Copyright 2004 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed 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.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 trimed. Blank lines, and lines (after trimed) 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 {
+
+	/*
+	 * --------------------------------------------------------------------
+	 * 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$
+
+	/*
+	 * --------------------------------------------------------------------
+	 * Class variables
+	 * --------------------------------------------------------------------
+	 */
+
+	// the shared pattern used to check charset names
+	// private static Pattern _charsetNamePattern = Pattern
+	// .compile("[0-9A-Za-z][0-9A-Za-z\\x2e\\x3a\\x2d\\x5f]*"); //$NON-NLS-1$
+	// built in provider instance, assuming thread-safe
+	private static CharsetProviderICU _builtInProvider = null;
+
+	// cached built in charsets
+	private static TreeMap _builtInCharsets = null;
+
+	/*
+	 * --------------------------------------------------------------------
+	 * Instance variables
+	 * --------------------------------------------------------------------
+	 */
+
+	// a cached instance of encoder for each thread
+	ThreadLocal cachedEncoder = new ThreadLocal() {
+		protected synchronized Object initialValue() {
+			CharsetEncoder e = newEncoder();
+			e.onMalformedInput(CodingErrorAction.REPLACE);
+			e.onUnmappableCharacter(CodingErrorAction.REPLACE);
+			return e;
+		}
+	};
+
+	// a cached instance of decoder for each thread
+	ThreadLocal cachedDecoder = new ThreadLocal() {
+		protected synchronized Object initialValue() {
+			CharsetDecoder d = newDecoder();
+			d.onMalformedInput(CodingErrorAction.REPLACE);
+			d.onUnmappableCharacter(CodingErrorAction.REPLACE);
+			return d;
+		}
+	};
+
+	private final String canonicalName;
+
+	// the aliases set
+	private final HashSet aliasesSet;
+
+	/*
+	 * -------------------------------------------------------------------
+	 * Global initialization
+	 * -------------------------------------------------------------------
+	 */
+	static {
+		/*
+		 * create built-in charset provider even if no privilege to access
+		 * charset provider.
+		 */
+		_builtInProvider = (CharsetProviderICU) AccessController
+				.doPrivileged(new PrivilegedAction() {
+					public Object 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 {
+		// check whether the given canonical name is legal
+		checkCharsetName(canonicalName);
+		this.canonicalName = canonicalName;
+		// check each aliase and put into a set
+		this.aliasesSet = new HashSet();
+		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 given string is a legal charset name. To be compatible
+	 * with JDK's behavior, allow empty strings and strings not starting with a
+	 * letter or digit. These are not allowed according to the 1.4.2 javadoc.
+	 */
+	private static void checkCharsetName(String name) {
+		boolean isDigit;
+		boolean isLetter;
+		int length = name.length();
+		for (int i = 0; i < length; i++) {
+			char c = name.charAt(i);
+			isLetter = ('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z');
+			isDigit = ('0' <= c && c <= '9');
+			if (isDigit || isLetter || isSpecial(c)) {
+				continue;
+			}
+			throw new IllegalCharsetNameException(name);
+		}
+	}
+
+	/*
+	 * Use privileged code to get the context class loader.
+	 */
+	private static ClassLoader getContextClassLoader() {
+		final Thread t = Thread.currentThread();
+		return (ClassLoader) AccessController
+				.doPrivileged(new PrivilegedAction() {
+					public Object run() {
+						return t.getContextClassLoader();
+					}
+				});
+	}
+
+	/*
+	 * Add the charsets supported by the given provider to the map.
+	 */
+	private static void addCharsets(CharsetProvider cp, TreeMap charsets) {
+		Iterator it = cp.charsets();
+		while (it.hasNext()) {
+			Charset cs = (Charset) it.next();
+			// Only new charsets will be added
+			if (!charsets.containsKey(cs.name())) {
+				charsets.put(cs.name(), cs);
+			}
+		}
+	}
+
+	/*
+	 * 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 cl,
+			TreeMap charsets) {
+		BufferedReader reader = null;
+		try {
+			InputStream is = configFile.openStream();
+			// Read each line for charset provider class names
+			reader = new BufferedReader(new InputStreamReader(is,
+					PROVIDER_CONFIGURATION_FILE_ENCODING));
+			String providerClassName = reader.readLine();
+			while (null != providerClassName) {
+				// Trim leading and trailing whitespaces
+				providerClassName = providerClassName.trim();
+				// Skip comments and blank lines
+				if (!providerClassName
+						.startsWith(PROVIDER_CONFIGURATION_FILE_COMMENT)
+						&& !"".equals(providerClassName)) { //$NON-NLS-1$
+					// Load the charset provider
+					Object cp = null;
+					try {
+						Class c = Class.forName(providerClassName, true, cl);
+						cp = c.newInstance();
+					} catch (SecurityException ex) {
+						// assume no permission to use charset provider
+						throw ex;
+					} catch (Exception ex) {
+						throw new Error(ex.getMessage(), ex);
+					}
+					// 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
+	 */
+	public static SortedMap availableCharsets() {
+		// Initialize the built-in charsets map cache if necessary
+		if (null == _builtInCharsets) {
+			synchronized (Charset.class) {
+				if (null == _builtInCharsets) {
+					_builtInCharsets = new TreeMap(IgnoreCaseComparator
+							.getInstance());
+					_builtInProvider.putCharsets(_builtInCharsets);
+				}
+			}
+		}
+
+		// Add built-in charsets
+		TreeMap charsets = (TreeMap) _builtInCharsets.clone();
+
+		// Collect all charsets provided by charset providers
+		final ClassLoader cl = getContextClassLoader();
+		if (null != cl) {
+			try {
+				// Load all configuration files
+				Enumeration e = cl
+						.getResources(PROVIDER_CONFIGURATION_FILE_NAME);
+				// Examine each configuration file
+				while (e.hasMoreElements()) {
+					loadConfiguredCharsets((URL) e.nextElement(), cl, 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,
+			URL configFile, ClassLoader cl) {
+		BufferedReader reader = null;
+		try {
+			InputStream is = configFile.openStream();
+			// Read each line for charset provider class names
+			reader = new BufferedReader(new InputStreamReader(is,
+					PROVIDER_CONFIGURATION_FILE_ENCODING));
+			String providerClassName = reader.readLine();
+			while (null != providerClassName) {
+				// Trim leading and trailing whitespaces
+				providerClassName = providerClassName.trim();
+				// Skip comments and blank lines
+				if (!providerClassName
+						.startsWith(PROVIDER_CONFIGURATION_FILE_COMMENT)
+						&& !"".equals(providerClassName)) { //$NON-NLS-1$
+					// Load the charset provider
+					Object cp = null;
+					try {
+						Class c = Class.forName(providerClassName, true, cl);
+						cp = c.newInstance();
+					} catch (SecurityException ex) {
+						// assume no permission to use charset provider
+						throw ex;
+					} catch (Exception ex) {
+						throw new Error(ex.getMessage(), ex);
+					}
+					// 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 {
+		checkCharsetName(charsetName);
+		// Try built-in charsets
+		Charset cs = _builtInProvider.charsetForName(charsetName);
+		if (null != cs) {
+			return cs;
+		}
+
+		// Collect all charsets provided by charset providers
+		final ClassLoader cl = getContextClassLoader();
+		if (null != cl) {
+			try {
+				// Load all configuration files
+				Enumeration e = cl
+						.getResources(PROVIDER_CONFIGURATION_FILE_NAME);
+				// Examine each configuration file
+				while (e.hasMoreElements()) {
+					cs = searchConfiguredCharsets(charsetName, (URL) e
+							.nextElement(), cl);
+					if (null != cs) {
+						return cs;
+					}
+				}
+			} catch (IOException ex) {
+				// Unexpected ClassLoader exception, ignore
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * 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 {
+		/*
+		 * The following ugly checks try to keep compatibility with JDK. It
+		 * rejects empty names and names starting with a non-letter&digit
+		 * character.
+		 */
+		if (null == charsetName || "".equals(charsetName)) { //$NON-NLS-1$
+			throw new IllegalArgumentException();
+		}
+		char initial = charsetName.charAt(0);
+		if (isSpecial(initial)) {
+			throw new IllegalArgumentException();
+		}
+
+		Charset c = forNameInternal(charsetName);
+		if (null != c) {
+			return c;
+		}
+		throw new UnsupportedCharsetException(charsetName);
+	}
+
+	/**
+	 * 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 {
+		if (null == charsetName) {
+			throw new IllegalCharsetNameException(charsetName);
+		}
+		return null != forNameInternal(charsetName);
+	}
+
+	/**
+	 * 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 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;
+	}
+
+	/**
+	 * Answers whether this charset is registered in the IANA Charset Registry.
+	 * 
+	 * @return true
+	 */
+	public final boolean isRegistered() {
+		return true;
+	}
+
+	/**
+	 * Answers 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
+	 */
+	public final ByteBuffer encode(CharBuffer buffer) {
+		CharsetEncoder e = (CharsetEncoder) this.cachedEncoder.get();
+		try {
+			return e.encode(buffer);
+		} catch (CharacterCodingException ex) {
+			throw new Error(ex.getMessage(), ex);
+		}
+	}
+
+	/**
+	 * Encodes a string and outputs to a byte buffer that is to be retured.
+	 * <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 retured.
+	 * <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 dencoding
+	 */
+	public final CharBuffer decode(ByteBuffer buffer) {
+		CharsetDecoder d = (CharsetDecoder) this.cachedDecoder.get();
+		try {
+			return d.decode(buffer);
+		} catch (CharacterCodingException ex) {
+			throw new Error(ex.getMessage(), ex);
+		}
+	}
+
+	/*
+	 * -------------------------------------------------------------------
+	 * Methods implementing parent interface Comparable
+	 * -------------------------------------------------------------------
+	 */
+
+	/**
+	 * Compares this charset with the given charset.
+	 * 
+	 * @param obj
+	 *            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(Object obj) {
+		Charset that = (Charset) obj;
+		return this.canonicalName.compareToIgnoreCase(that.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
+	 */
+	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
+	 */
+	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
+	 */
+	public final String toString() {
+		return "Charset[" + this.canonicalName + "]"; //$NON-NLS-1$//$NON-NLS-2$
+	}
+
+	/**
+	 * A comparator that ignores case.
+	 */
+	static class IgnoreCaseComparator implements Comparator {
+
+		// the singleton
+		private static Comparator c = new IgnoreCaseComparator();
+
+		/*
+		 * Default constructor.
+		 */
+		private IgnoreCaseComparator() {
+			// no action
+		}
+
+		/*
+		 * Gets a single instance.
+		 */
+		public static Comparator getInstance() {
+			return c;
+		}
+
+		/*
+		 * Compares two strings ignoring case.
+		 */
+		public int compare(Object obj1, Object obj2) {
+			String s1 = (String) obj1;
+			String s2 = (String) obj2;
+
+			return s1.compareToIgnoreCase(s2);
+		}
+	}
+}

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio_char/src/java/nio/charset/CharsetDecoder.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio_char/src/java/nio/charset/CharsetDecoder.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio_char/src/java/nio/charset/CharsetDecoder.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/nio_char/src/java/nio/charset/CharsetDecoder.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,743 @@
+/* Copyright 2004 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed 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.ByteBuffer;
+import java.nio.CharBuffer;
+
+/**
+ * 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 addtional 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 specifing 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 mantains internl 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;
+
+	private byte[] remains = null;
+
+	/*
+	 * --------------------------------------- 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) {
+			throw new IllegalArgumentException(
+					"Characters number for one byte must be positive."); //$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 remaning 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 postion 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);
+		while (true) {
+			CoderResult result = decode(in, output, false);
+			if (result.isUnderflow()) {
+				break;
+			} else if (result.isMalformed()
+					&& malformAction == CodingErrorAction.REPORT) {
+				throw new MalformedInputException(result.length());
+			} else if (result.isUnmappable()
+					&& unmapAction == CodingErrorAction.REPORT) {
+				throw new UnmappableCharacterException(result.length());
+			}
+			output = allocateMore(output);
+		}
+		decode(in, output, true);
+		while (flush(output) != CoderResult.UNDERFLOW) {
+			output = allocateMore(output);
+		}
+		output.flip();
+		status = FLUSH;
+		return output;
+	}
+
+	/*
+	 * 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 postion.
+	 * <p>
+	 * The buffers' position will be changed with the reading and writing
+	 * operation, but their limis 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 ben 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 postion 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 postion 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 = CoderResult.UNDERFLOW;
+		while (true) {
+			CodingErrorAction action = null;
+			result = CoderResult.UNDERFLOW;
+			/*
+			 * handle the remained bytes if there are some(bug#545)
+			 */
+			if (remains != null) {
+				int remainLength = remains.length;
+				ByteBuffer remainBuffer = ByteBuffer.wrap(remains);
+				while(remainBuffer.hasRemaining() && in.hasRemaining() && result.isUnderflow()){
+					//get one more byte from input ByteBuffer
+					//merge it with remained bytes
+					//and try to decode them to one char
+					byte b = in.get();
+					ByteBuffer temp = ByteBuffer.allocate(++remainLength);
+					temp.put(remainBuffer);
+					temp.put(b);
+					remainBuffer = temp;
+					remainBuffer.flip();
+					result = decodeLoop(remainBuffer, out);
+				}
+				remains = remainBuffer.hasRemaining()?remainBuffer.array():null;
+			}
+			
+			/*
+			 * decode input bytes
+			 */
+			//if no remained bytes left and no any error happened
+			//go on to decode other input bytes
+			//else, go to result handling part
+			result = result.isUnderflow() && (null == remains) ? decodeLoop(in,
+					out) : result;
+			
+			/*
+			 * result handling
+			 */
+			//handle the underflow result, if endOfInput and some input bytes remained
+			//which mean the malform error happened
+			if (result.isUnderflow()) {
+				if (endOfInput) {
+					if (in.hasRemaining()) {
+						result = CoderResult.malformedForLength(in.remaining());
+						in.position(in.position() + result.length());
+					} else if (null != remains) {
+						result = CoderResult.malformedForLength(remains.length);
+					}
+				} else if (in.hasRemaining()) {
+					remains = new byte[in.remaining()];
+					in.get(remains);
+				}
+			}			
+			if (result.isMalformed()) {
+				action = malformAction;
+			} else if (result.isUnmappable()) {
+				action = unmapAction;
+			}
+
+			//respond to the CodingErrorAction
+			//if the action is REPORT, break and return
+			//else, skip the error bytes and go on to decode 
+			if (action == CodingErrorAction.IGNORE) {
+				continue;
+			} else if (action == CodingErrorAction.REPLACE) {
+				out.put(replace);
+				continue;
+			}
+			break;
+		}
+		status = endOfInput ? END : ONGOING;
+		return result;
+	}
+
+	/**
+	 * 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 mehtod 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 postions
+	 * 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 insuffient bytes have been read to determine the charset,
+	 * <code>IllegalStateException</code> will be throwed.
+	 * </p>
+	 * <p>
+	 * The default implementation alwyas 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 implmenet an auto-detecting charset
+	 * @throws IllegalStateException
+	 *             if insuffient 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 charaters 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 sucessfully.
+	 * 
+	 * 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 implementaion 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 implementaion 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 implementaion 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
+	 * implementaion 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 implementaion 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
+	 * occured during decoding process.
+	 * 
+	 * @return this decoder's <code>CodingErrorAction</code> when malformed
+	 *         input occured 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
+	 *             metioned above
+	 */
+	public final CharsetDecoder replaceWith(String newReplacement) {
+		if (null == newReplacement || newReplacement.length() == 0) {
+			throw new IllegalArgumentException(
+					"Replacement string cannot be null or empty."); //$NON-NLS-1$
+		}
+		if (newReplacement.length() > maxChars) {
+			throw new IllegalArgumentException(
+					"Replacement string's length cannot be larger than max characters per byte."); //$NON-NLS-1$
+		}
+		replace = newReplacement;
+		implReplaceWith(newReplacement);
+		return this;
+	}
+
+	/**
+	 * Reset this decoder. This method will reset internla status, and then call
+	 * <code>implReset()</code> to reset any status related to specific
+	 * charset.
+	 * 
+	 * @return this decoder
+	 */
+	public final CharsetDecoder reset() {
+		status = INIT;
+		remains = null;
+		implReset();
+		return this;
+	}
+
+	/**
+	 * Gets this decoder's <code>CodingErrorAction</code> when unmappable
+	 * character occured during decoding process.
+	 * 
+	 * @return this decoder's <code>CodingErrorAction</code> when unmappable
+	 *         character occured during decoding process.
+	 */
+	public CodingErrorAction unmappableCharacterAction() {
+		return unmapAction;
+	}
+}



Mime
View raw message