You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by te...@apache.org on 2006/03/29 14:28:40 UTC

svn commit: r389782 - in /incubator/harmony/enhanced/classlib/trunk/modules/nio_char/src: main/java/java/nio/charset/Charset.java test/java/org/apache/harmony/tests/java/nio/charset/CharsetTest.java

Author: tellison
Date: Wed Mar 29 04:28:36 2006
New Revision: 389782

URL: http://svn.apache.org/viewcvs?rev=389782&view=rev
Log:
Apply patch HARMONY-150 (java.nio.charset.Charset.decode(in) doesn't use the same cached decoder)

Modified:
    incubator/harmony/enhanced/classlib/trunk/modules/nio_char/src/main/java/java/nio/charset/Charset.java
    incubator/harmony/enhanced/classlib/trunk/modules/nio_char/src/test/java/org/apache/harmony/tests/java/nio/charset/CharsetTest.java

Modified: incubator/harmony/enhanced/classlib/trunk/modules/nio_char/src/main/java/java/nio/charset/Charset.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/nio_char/src/main/java/java/nio/charset/Charset.java?rev=389782&r1=389781&r2=389782&view=diff
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/nio_char/src/main/java/java/nio/charset/Charset.java (original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/nio_char/src/main/java/java/nio/charset/Charset.java Wed Mar 29 04:28:36 2006
@@ -115,26 +115,6 @@
 	 * --------------------------------------------------------------------
 	 */
 
-	// 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
@@ -142,6 +122,13 @@
 
 	// cached Charset table
 	private static HashMap cachedCharsetTable = new HashMap();
+	
+	// cached CharsetDecoder table
+	private static HashMap cachedCharsetDecoderTable = new HashMap();
+	
+	// cached CharsetEncoder table
+	private static HashMap cachedCharsetEncoderTable = new HashMap();
+	
 	/*
 	 * -------------------------------------------------------------------
 	 * Global initialization
@@ -637,14 +624,33 @@
 	 *            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();
+	synchronized public final ByteBuffer encode(CharBuffer buffer) {
+		CharsetEncoder e = getCachedCharsetEncoder(canonicalName);
+		if(null == e){
+			e = this.newEncoder();
+			e.onMalformedInput(CodingErrorAction.REPLACE);
+			e.onUnmappableCharacter(CodingErrorAction.REPLACE);
+			cacheCharsetEncoder(this.canonicalName,e);
+		}
 		try {
 			return e.encode(buffer);
 		} catch (CharacterCodingException ex) {
 			throw new Error(ex.getMessage(), ex);
 		}
 	}
+	
+	/*
+	 * get cached CharsetEncoder by canonical name
+	 */
+	private CharsetEncoder getCachedCharsetEncoder(String name){
+		return (CharsetEncoder) cachedCharsetEncoderTable.get(name);
+	}
+	/*
+	 * save CharsetEncoder into cachedCharsetEncoderTable
+	 */
+	private void cacheCharsetEncoder(String name, CharsetEncoder encoder){
+		cachedCharsetEncoderTable.put(name,encoder);
+	}
 
 	/**
 	 * Encodes a string and outputs to a byte buffer that is to be retured.
@@ -673,13 +679,32 @@
 	 *            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();
+	synchronized public final CharBuffer decode(ByteBuffer buffer) {
+		CharsetDecoder d = getCachedCharsetDecoder(canonicalName);
+		if(null == d){
+			d = this.newDecoder();
+			d.onMalformedInput(CodingErrorAction.REPLACE);
+			d.onUnmappableCharacter(CodingErrorAction.REPLACE);
+			cacheCharsetDecoder(canonicalName,d);
+		}
 		try {
 			return d.decode(buffer);
 		} catch (CharacterCodingException ex) {
 			throw new Error(ex.getMessage(), ex);
 		}
+	}
+	
+	/*
+	 * get cached CharsetDecoder by canonical name
+	 */
+	private CharsetDecoder getCachedCharsetDecoder(String name){
+		return (CharsetDecoder) cachedCharsetDecoderTable.get(name);
+	}
+	/*
+	 * save CharsetDecoder into cachedCharsetDecoderTable
+	 */
+	private void cacheCharsetDecoder(String name, CharsetDecoder decoder){
+		cachedCharsetDecoderTable.put(name,decoder);
 	}
 
 	/*

Modified: incubator/harmony/enhanced/classlib/trunk/modules/nio_char/src/test/java/org/apache/harmony/tests/java/nio/charset/CharsetTest.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/nio_char/src/test/java/org/apache/harmony/tests/java/nio/charset/CharsetTest.java?rev=389782&r1=389781&r2=389782&view=diff
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/nio_char/src/test/java/org/apache/harmony/tests/java/nio/charset/CharsetTest.java (original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/nio_char/src/test/java/org/apache/harmony/tests/java/nio/charset/CharsetTest.java Wed Mar 29 04:28:36 2006
@@ -15,7 +15,12 @@
 
 package org.apache.harmony.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;
@@ -150,5 +155,142 @@
 		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;
+            }
+    }
+
 }