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 {