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/05/10 14:40:58 UTC
svn commit: r1101437 -
/httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/impl/io/AbstractSessionOutputBuffer.java
Author: olegk
Date: Tue May 10 12:40:58 2011
New Revision: 1101437
URL: http://svn.apache.org/viewvc?rev=1101437&view=rev
Log:
More efficient handling of non-ascii coded lines by input/output session buffers due to utilization of Java 1.5 charset decoder / encoder API
Modified:
httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/impl/io/AbstractSessionOutputBuffer.java
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=1101437&r1=1101436&r2=1101437&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 Tue May 10 12:40:58 2011
@@ -29,6 +29,11 @@ package org.apache.http.impl.io;
import java.io.IOException;
import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CoderResult;
import org.apache.http.io.BufferInfo;
import org.apache.http.io.SessionOutputBuffer;
@@ -60,12 +65,15 @@ import org.apache.http.util.CharArrayBuf
*/
public abstract class AbstractSessionOutputBuffer implements SessionOutputBuffer, BufferInfo {
+ private static final Charset ASCII = Charset.forName("US-ASCII");
private static final byte[] CRLF = new byte[] {HTTP.CR, HTTP.LF};
private OutputStream outstream;
private ByteArrayBuffer buffer;
- private String charset = HTTP.US_ASCII;
+ private Charset charset;
+ private CharsetEncoder encoder;
+ private ByteBuffer bbuf;
private boolean ascii = true;
private int minChunkLimit = 512;
@@ -90,9 +98,9 @@ public abstract class AbstractSessionOut
}
this.outstream = outstream;
this.buffer = new ByteArrayBuffer(buffersize);
- this.charset = HttpProtocolParams.getHttpElementCharset(params);
- this.ascii = this.charset.equalsIgnoreCase(HTTP.US_ASCII)
- || this.charset.equalsIgnoreCase(HTTP.ASCII);
+ this.charset = Charset.forName(HttpProtocolParams.getHttpElementCharset(params));
+ this.ascii = this.charset.equals(ASCII);
+ this.encoder = null;
this.minChunkLimit = params.getIntParameter(CoreConnectionPNames.MIN_CHUNK_LIMIT, 512);
this.metrics = createTransportMetrics();
}
@@ -105,7 +113,7 @@ public abstract class AbstractSessionOut
}
/**
- * @since 4.`1
+ * @since 4.1
*/
public int capacity() {
return this.buffer.capacity();
@@ -192,7 +200,14 @@ public abstract class AbstractSessionOut
return;
}
if (s.length() > 0) {
- write(s.getBytes(this.charset));
+ if (this.ascii) {
+ for (int i = 0; i < s.length(); i++) {
+ write(s.charAt(i));
+ }
+ } else {
+ CharBuffer cbuf = CharBuffer.wrap(s);
+ writeEncoded(cbuf);
+ }
}
write(CRLF);
}
@@ -203,21 +218,21 @@ public abstract class AbstractSessionOut
* <p>
* This method uses CR-LF as a line delimiter.
*
- * @param s the buffer containing chars of the line.
+ * @param charbuffer the buffer containing chars of the line.
* @exception IOException if an I/O error occurs.
*/
- public void writeLine(final CharArrayBuffer s) throws IOException {
- if (s == null) {
+ public void writeLine(final CharArrayBuffer charbuffer) throws IOException {
+ if (charbuffer == null) {
return;
}
if (this.ascii) {
int off = 0;
- int remaining = s.length();
+ int remaining = charbuffer.length();
while (remaining > 0) {
int chunk = this.buffer.capacity() - this.buffer.length();
chunk = Math.min(chunk, remaining);
if (chunk > 0) {
- this.buffer.append(s, off, chunk);
+ this.buffer.append(charbuffer, off, chunk);
}
if (this.buffer.isFull()) {
flushBuffer();
@@ -226,14 +241,40 @@ public abstract class AbstractSessionOut
remaining -= chunk;
}
} else {
- // This is VERY memory inefficient, BUT since non-ASCII charsets are
- // NOT meant to be used anyway, there's no point optimizing it
- byte[] tmp = s.toString().getBytes(this.charset);
- write(tmp);
+ CharBuffer cbuf = CharBuffer.wrap(charbuffer.buffer(), 0, charbuffer.length());
+ writeEncoded(cbuf);
}
write(CRLF);
}
+ private void writeEncoded(final CharBuffer cbuf) throws IOException {
+ if (this.encoder == null) {
+ this.encoder = this.charset.newEncoder();
+ }
+ if (this.bbuf == null) {
+ this.bbuf = ByteBuffer.allocate(1024);
+ }
+ this.encoder.reset();
+ while (cbuf.hasRemaining()) {
+ CoderResult result = this.encoder.encode(cbuf, this.bbuf, true);
+ handleEncodingResult(result);
+ }
+ CoderResult result = this.encoder.flush(this.bbuf);
+ handleEncodingResult(result);
+ this.bbuf.clear();
+ }
+
+ private void handleEncodingResult(final CoderResult result) throws IOException {
+ if (result.isError()) {
+ result.throwException();
+ }
+ this.bbuf.flip();
+ while (this.bbuf.hasRemaining()) {
+ write(this.bbuf.get());
+ }
+ this.bbuf.compact();
+ }
+
public HttpTransportMetrics getMetrics() {
return this.metrics;
}