You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2011/10/02 22:13:46 UTC

svn commit: r1178247 - in /httpcomponents/httpcore/trunk: httpcore-nio/src/main/java/org/apache/http/impl/nio/reactor/ httpcore-nio/src/test/java/org/apache/http/impl/nio/reactor/ httpcore/src/main/java/org/apache/http/impl/io/ httpcore/src/main/java/o...

Author: olegk
Date: Sun Oct  2 20:13:46 2011
New Revision: 1178247

URL: http://svn.apache.org/viewvc?rev=1178247&view=rev
Log:
HTTPCORE-278: Making CharsetEncoder/CharsetDecoder CodingErrorAction to be configurable
Contributed by Rajika Kumarasiri <rajika at wso2.com>

Modified:
    httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/impl/nio/reactor/SessionInputBufferImpl.java
    httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/impl/nio/reactor/SessionOutputBufferImpl.java
    httpcomponents/httpcore/trunk/httpcore-nio/src/test/java/org/apache/http/impl/nio/reactor/TestSessionInOutBuffers.java
    httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/impl/io/AbstractSessionInputBuffer.java
    httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/impl/io/AbstractSessionOutputBuffer.java
    httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/params/CoreProtocolPNames.java
    httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/params/HttpProtocolParams.java
    httpcomponents/httpcore/trunk/httpcore/src/test/java/org/apache/http/impl/io/TestSessionBuffers.java

Modified: httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/impl/nio/reactor/SessionInputBufferImpl.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/impl/nio/reactor/SessionInputBufferImpl.java?rev=1178247&r1=1178246&r2=1178247&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/impl/nio/reactor/SessionInputBufferImpl.java (original)
+++ httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/impl/nio/reactor/SessionInputBufferImpl.java Sun Oct  2 20:13:46 2011
@@ -32,10 +32,7 @@ import java.nio.ByteBuffer;
 import java.nio.CharBuffer;
 import java.nio.channels.ReadableByteChannel;
 import java.nio.channels.WritableByteChannel;
-import java.nio.charset.CharacterCodingException;
-import java.nio.charset.Charset;
-import java.nio.charset.CharsetDecoder;
-import java.nio.charset.CoderResult;
+import java.nio.charset.*;
 
 import org.apache.http.annotation.NotThreadSafe;
 import org.apache.http.nio.reactor.SessionInputBuffer;
@@ -75,6 +72,8 @@ public class SessionInputBufferImpl exte
         this.charbuffer = CharBuffer.allocate(linebuffersize);
         this.charset = Charset.forName(HttpProtocolParams.getHttpElementCharset(params));
         this.chardecoder = this.charset.newDecoder();
+        this.chardecoder.onMalformedInput(HttpProtocolParams.getMalformedInputAction(params));
+        this.chardecoder.onUnmappableCharacter(HttpProtocolParams.getUnmappableInputAction(params));
     }
 
     public SessionInputBufferImpl(

Modified: httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/impl/nio/reactor/SessionOutputBufferImpl.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/impl/nio/reactor/SessionOutputBufferImpl.java?rev=1178247&r1=1178246&r2=1178247&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/impl/nio/reactor/SessionOutputBufferImpl.java (original)
+++ httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/impl/nio/reactor/SessionOutputBufferImpl.java Sun Oct  2 20:13:46 2011
@@ -77,6 +77,8 @@ public class SessionOutputBufferImpl ext
         this.charbuffer = CharBuffer.allocate(linebuffersize);
         this.charset = Charset.forName(HttpProtocolParams.getHttpElementCharset(params));
         this.charencoder = this.charset.newEncoder();
+        this.charencoder.onMalformedInput(HttpProtocolParams.getMalformedInputAction(params));
+        this.charencoder.onUnmappableCharacter(HttpProtocolParams.getUnmappableInputAction(params));
     }
 
     public SessionOutputBufferImpl(

Modified: httpcomponents/httpcore/trunk/httpcore-nio/src/test/java/org/apache/http/impl/nio/reactor/TestSessionInOutBuffers.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore-nio/src/test/java/org/apache/http/impl/nio/reactor/TestSessionInOutBuffers.java?rev=1178247&r1=1178246&r2=1178247&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore-nio/src/test/java/org/apache/http/impl/nio/reactor/TestSessionInOutBuffers.java (original)
+++ httpcomponents/httpcore/trunk/httpcore-nio/src/test/java/org/apache/http/impl/nio/reactor/TestSessionInOutBuffers.java Sun Oct  2 20:13:46 2011
@@ -35,6 +35,7 @@ import java.nio.channels.Channels;
 import java.nio.channels.ReadableByteChannel;
 import java.nio.channels.WritableByteChannel;
 import java.nio.charset.CharacterCodingException;
+import java.nio.charset.CodingErrorAction;
 
 import org.apache.http.nio.reactor.SessionInputBuffer;
 import org.apache.http.nio.reactor.SessionOutputBuffer;
@@ -478,4 +479,79 @@ public class TestSessionInOutBuffers {
         outbuf.writeLine(s1);
     }
 
+    @Test
+    public void testMalformedInputAction() throws Exception {
+        HttpParams params = new BasicHttpParams();
+        String s1 = constructString(SWISS_GERMAN_HELLO);
+
+        byte[] tmp = s1.getBytes("ISO-8859-1");
+        ReadableByteChannel channel = newChannel(tmp);
+        SessionInputBuffer inbuf = new SessionInputBufferImpl(16, 16, params);
+        while (inbuf.fill(channel) > 0) {
+        }
+
+        // Action with report
+        HttpProtocolParams.setMalformedInputAction(params, CodingErrorAction.REPORT);
+        try {
+            String s = inbuf.readLine(true);
+            Assert.fail("Expected CharacterCodingException, got '" + s + "'");
+        } catch (CharacterCodingException expected) {
+        }
+
+        // Action with ignore
+        HttpProtocolParams.setMalformedInputAction(params, CodingErrorAction.IGNORE);
+        inbuf = new SessionInputBufferImpl(16, 16, params);
+        String s2 = null;
+        try {
+            s2 = inbuf.readLine(true);
+        } catch (CharacterCodingException e) {
+            Assert.fail("Unexpected CharacterCodingException " +
+                    (s2 == null ? "" : ", got '" + s2 + "'"));
+        }
+
+        // Action with replace
+        HttpProtocolParams.setMalformedInputAction(params, CodingErrorAction.REPLACE);
+        inbuf = new SessionInputBufferImpl(16, 16, params);
+        String s3 = null;
+        try {
+            s3 = inbuf.readLine(true);
+        } catch (CharacterCodingException e) {
+            Assert.fail("Unexpected CharacterCodingException " +
+                    (s3 == null ? "" : ", got '" + s3 + "'"));
+        }
+    }
+
+    @Test
+    public void testUnmappableInputAction() throws Exception {
+        HttpParams params = new BasicHttpParams();
+        String s1 = constructString(SWISS_GERMAN_HELLO);
+
+        // Action with report
+        HttpProtocolParams.setUnmappableInputAction(params, CodingErrorAction.REPORT);
+        SessionOutputBuffer outbuf = new SessionOutputBufferImpl(1024, 16, params);
+        try {
+            outbuf.writeLine(s1);
+            Assert.fail("Expected CharacterCodingException");
+        } catch (CharacterCodingException expected) {
+        }
+
+        // Action with ignore
+        HttpProtocolParams.setUnmappableInputAction(params, CodingErrorAction.IGNORE);
+        outbuf = new SessionOutputBufferImpl(1024, 16, params);
+        try {
+            outbuf.writeLine(s1);
+        } catch (CharacterCodingException e) {
+            Assert.fail("Unexpected CharacterCodingException");
+        }
+
+        // Action with replace
+        HttpProtocolParams.setUnmappableInputAction(params, CodingErrorAction.REPLACE);
+        outbuf = new SessionOutputBufferImpl(1024, 16, params);
+        try {
+            outbuf.writeLine(s1);
+        } catch (CharacterCodingException e) {
+            Assert.fail("Unexpected CharacterCodingException");
+        }
+    }
+
 }

Modified: httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/impl/io/AbstractSessionInputBuffer.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/impl/io/AbstractSessionInputBuffer.java?rev=1178247&r1=1178246&r2=1178247&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/impl/io/AbstractSessionInputBuffer.java (original)
+++ httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/impl/io/AbstractSessionInputBuffer.java Sun Oct  2 20:13:46 2011
@@ -34,6 +34,7 @@ import java.nio.CharBuffer;
 import java.nio.charset.Charset;
 import java.nio.charset.CharsetDecoder;
 import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
 
 import org.apache.http.annotation.NotThreadSafe;
 import org.apache.http.io.BufferInfo;
@@ -86,6 +87,9 @@ public abstract class AbstractSessionInp
 
     private HttpTransportMetricsImpl metrics;
 
+    private CodingErrorAction onMalformedInputAction;
+    private CodingErrorAction onUnMappableInputAction;
+
     /**
      * Initializes this session input buffer.
      *
@@ -114,6 +118,8 @@ public abstract class AbstractSessionInp
         this.maxLineLen = params.getIntParameter(CoreConnectionPNames.MAX_LINE_LENGTH, -1);
         this.minChunkLimit = params.getIntParameter(CoreConnectionPNames.MIN_CHUNK_LIMIT, 512);
         this.metrics = createTransportMetrics();
+        this.onMalformedInputAction = HttpProtocolParams.getMalformedInputAction(params);
+        this.onUnMappableInputAction = HttpProtocolParams.getUnmappableInputAction(params);
     }
 
     /**
@@ -352,6 +358,8 @@ public abstract class AbstractSessionInp
         }
         if (this.decoder == null) {
             this.decoder = this.charset.newDecoder();
+            this.decoder.onMalformedInput(onMalformedInputAction);
+            this.decoder.onUnmappableCharacter(onUnMappableInputAction);
         }
         if (this.cbuf == null) {
             this.cbuf = CharBuffer.allocate(1024);

Modified: httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/impl/io/AbstractSessionOutputBuffer.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/impl/io/AbstractSessionOutputBuffer.java?rev=1178247&r1=1178246&r2=1178247&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/impl/io/AbstractSessionOutputBuffer.java (original)
+++ httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/impl/io/AbstractSessionOutputBuffer.java Sun Oct  2 20:13:46 2011
@@ -34,6 +34,7 @@ import java.nio.CharBuffer;
 import java.nio.charset.Charset;
 import java.nio.charset.CharsetEncoder;
 import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
 
 import org.apache.http.annotation.NotThreadSafe;
 import org.apache.http.io.BufferInfo;
@@ -81,6 +82,9 @@ public abstract class AbstractSessionOut
 
     private HttpTransportMetricsImpl metrics;
 
+    private CodingErrorAction onMalformedInputAction;
+    private CodingErrorAction onUnMappableInputAction;
+
     /**
      * Initializes this session output buffer.
      *
@@ -105,6 +109,8 @@ public abstract class AbstractSessionOut
         this.encoder = null;
         this.minChunkLimit = params.getIntParameter(CoreConnectionPNames.MIN_CHUNK_LIMIT, 512);
         this.metrics = createTransportMetrics();
+        this.onMalformedInputAction = HttpProtocolParams.getMalformedInputAction(params);
+        this.onUnMappableInputAction = HttpProtocolParams.getUnmappableInputAction(params);
     }
 
     /**
@@ -255,6 +261,8 @@ public abstract class AbstractSessionOut
         }
         if (this.encoder == null) {
             this.encoder = this.charset.newEncoder();
+            this.encoder.onMalformedInput(onMalformedInputAction);
+            this.encoder.onUnmappableCharacter(onUnMappableInputAction);
         }
         if (this.bbuf == null) {
             this.bbuf = ByteBuffer.allocate(1024);

Modified: httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/params/CoreProtocolPNames.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/params/CoreProtocolPNames.java?rev=1178247&r1=1178246&r2=1178247&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/params/CoreProtocolPNames.java (original)
+++ httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/params/CoreProtocolPNames.java Sun Oct  2 20:13:46 2011
@@ -122,4 +122,29 @@ public interface CoreProtocolPNames {
      */
     public static final String WAIT_FOR_CONTINUE = "http.protocol.wait-for-continue";
 
+    /**
+     * <p>
+     * Defines the action to perform upon receiving a malformed input. If the input byte sequence
+     * is not legal for this charset then the input is said to be malformed
+     * </p>
+     *
+     * This parameter expects a value of type {@link java.nio.charset.CodingErrorAction}
+     *
+     * @since 4.2
+     */
+    public static final String HTTP_MALFORMED_INPUT_ACTION = "http.malformed.input.action";
+
+    /**
+     * <p>
+     * Defines the action to perform upon receiving an unmappable input. If the input byte sequence
+     * is legal but cannot be mapped to a valid Unicode character then the input is said to be
+     * unmappable
+     * </p>
+     *
+     * This parameter expects a value of type {@link java.nio.charset.CodingErrorAction}
+     *
+     * @since 4.2
+     */
+    public static final String HTTP_UNMAPPABLE_INPUT_ACTION = "http.unmappable.input.action";
+
 }

Modified: httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/params/HttpProtocolParams.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/params/HttpProtocolParams.java?rev=1178247&r1=1178246&r2=1178247&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/params/HttpProtocolParams.java (original)
+++ httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/params/HttpProtocolParams.java Sun Oct  2 20:13:46 2011
@@ -31,6 +31,8 @@ import org.apache.http.HttpVersion;
 import org.apache.http.ProtocolVersion;
 import org.apache.http.protocol.HTTP;
 
+import java.nio.charset.CodingErrorAction;
+
 /**
  * Utility class for accessing protocol parameters in {@link HttpParams}.
  *
@@ -195,4 +197,69 @@ public final class HttpProtocolParams im
         params.setBooleanParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE, b);
     }
 
+    /**
+     * Obtains value of the {@link CoreProtocolPNames#HTTP_MALFORMED_INPUT_ACTION} parameter.
+     * @param params HTTP parameters.
+     * @return Action to perform upon receiving a malformed input
+     *
+     * @since 4.2
+     */
+    public static CodingErrorAction getMalformedInputAction(final HttpParams params) {
+        if (params == null) {
+            throw new IllegalArgumentException("HTTP parameters may not be null");
+        }
+        Object param = params.getParameter(CoreProtocolPNames.HTTP_MALFORMED_INPUT_ACTION);
+        if (param == null) {
+            // the default CodingErrorAction
+            return CodingErrorAction.REPORT;
+        }
+        return (CodingErrorAction) param;
+    }
+
+    /**
+     * Sets value of the {@link CoreProtocolPNames#HTTP_MALFORMED_INPUT_ACTION} parameter.
+     * @param params HTTP parameters
+     * @param action action to perform on malformed inputs
+     *
+     * @since 4.2
+     */
+    public static void setMalformedInputAction(final HttpParams params, CodingErrorAction action) {
+        if (params == null) {
+            throw new IllegalArgumentException("HTTP parameters may not be null");
+        }
+        params.setParameter(CoreProtocolPNames.HTTP_MALFORMED_INPUT_ACTION, action);
+    }
+
+    /**
+     * Obtains the value of the  {@link CoreProtocolPNames#HTTP_UNMAPPABLE_INPUT_ACTION} parameter.
+     * @param params HTTP parameters
+     * @return Action to perform upon receiving a unmapped input
+     *
+     * @since 4.2
+     */
+    public static CodingErrorAction getUnmappableInputAction(final HttpParams params) {
+        if (params == null) {
+            throw new IllegalArgumentException("HTTP parameters may not be null");
+        }
+        Object param = params.getParameter(CoreProtocolPNames.HTTP_UNMAPPABLE_INPUT_ACTION);
+        if (param == null) {
+            // the default CodingErrorAction
+            return CodingErrorAction.REPORT;
+        }
+        return (CodingErrorAction) param;
+    }
+
+    /**
+     * Sets the value of the {@link CoreProtocolPNames#HTTP_UNMAPPABLE_INPUT_ACTION} parameter.
+     * @param params HTTP parameters
+     * @param action action to perform on un mappable inputs
+     *
+     * @since 4.2
+     */
+    public static void setUnmappableInputAction(final HttpParams params, CodingErrorAction action) {
+        if (params == null) {
+            throw new IllegalArgumentException("HTTP parameters may no be null");
+        }
+        params.setParameter(CoreProtocolPNames.HTTP_UNMAPPABLE_INPUT_ACTION, action);
+    }
 }

Modified: httpcomponents/httpcore/trunk/httpcore/src/test/java/org/apache/http/impl/io/TestSessionBuffers.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore/src/test/java/org/apache/http/impl/io/TestSessionBuffers.java?rev=1178247&r1=1178246&r2=1178247&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore/src/test/java/org/apache/http/impl/io/TestSessionBuffers.java (original)
+++ httpcomponents/httpcore/trunk/httpcore/src/test/java/org/apache/http/impl/io/TestSessionBuffers.java Sun Oct  2 20:13:46 2011
@@ -31,6 +31,8 @@ import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.CodingErrorAction;
 
 import org.apache.http.impl.SessionInputBufferMock;
 import org.apache.http.impl.SessionOutputBufferMock;
@@ -534,6 +536,76 @@ public class TestSessionBuffers {
     }
 
     @Test
+    public void testUnmappableInputAction() throws Exception {
+        BasicHttpParams params = new BasicHttpParams();
+        String s = "In valid ISO-8859-1 character string because  of Ŵ and ŵ";
+        HttpProtocolParams.setHttpElementCharset(params, HTTP.ISO_8859_1);
+
+        // Action with report
+        HttpProtocolParams.setUnmappableInputAction(params, CodingErrorAction.REPORT);
+        SessionOutputBufferMock outbuf = new SessionOutputBufferMock(params);
+        try {
+            outbuf.writeLine(s);
+            Assert.fail("Expected CharacterCodingException");
+        } catch (CharacterCodingException expected) {
+        }
+
+        // Action with ignore
+        HttpProtocolParams.setUnmappableInputAction(params, CodingErrorAction.IGNORE);
+        outbuf = new SessionOutputBufferMock(params);
+        try {
+            outbuf.writeLine(s);
+        } catch (CharacterCodingException e) {
+            Assert.fail("Unexpected CharacterCodingException");
+        }
+
+        // Action with replace
+        HttpProtocolParams.setUnmappableInputAction(params, CodingErrorAction.REPLACE);
+        outbuf = new SessionOutputBufferMock(params);
+        try {
+            outbuf.writeLine(s);
+        } catch (IOException e) {
+            Assert.fail("Unexpected CharacterCodingException");
+        }
+    }
+
+    @Test
+    public void testMalformedInputAction() throws Exception {
+        byte[] tmp = constructString(SWISS_GERMAN_HELLO).getBytes("UTF-16");
+        CharArrayBuffer buf = new CharArrayBuffer(1);
+
+        BasicHttpParams params = new BasicHttpParams();
+        HttpProtocolParams.setHttpElementCharset(params, "UTF-8");
+
+        // Action with report
+        HttpProtocolParams.setMalformedInputAction(params, CodingErrorAction.REPORT);
+        SessionInputBufferMock inbuffer = new SessionInputBufferMock(tmp, params);
+        try {
+            inbuffer.readLine(buf);
+            Assert.fail("Expected CharacterCodingException");
+        } catch (CharacterCodingException e) {
+        }
+
+        // Action with replace
+        HttpProtocolParams.setMalformedInputAction(params, CodingErrorAction.REPLACE);
+        inbuffer = new SessionInputBufferMock(tmp, params);
+        try {
+            inbuffer.readLine(buf);
+        } catch (CharacterCodingException e) {
+            Assert.fail("Unexpected CharacterCodingException");
+        }
+
+        // Action with ignore
+        HttpProtocolParams.setMalformedInputAction(params, CodingErrorAction.IGNORE);
+        inbuffer = new SessionInputBufferMock(tmp, params);
+        try {
+            inbuffer.readLine();
+        } catch (IOException e) {
+            Assert.fail("Unexpected CharacterCodingException");
+        }
+    }
+
+    @Test
     public void testInvalidCharArrayBuffer() throws Exception {
         SessionInputBufferMock inbuffer = new SessionInputBufferMock(new byte[] {});
         try {