diff --git a/httpclient/src/main/java/org/apache/http/auth/util/ByteArrayBuilder.java b/httpclient/src/main/java/org/apache/http/auth/util/ByteArrayBuilder.java
new file mode 100644
index 000000000..ae446df7a
--- /dev/null
+++ b/httpclient/src/main/java/org/apache/http/auth/util/ByteArrayBuilder.java
@@ -0,0 +1,212 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ *
+ */
+package org.apache.http.auth.util;
+
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+
+import org.apache.http.Consts;
+import org.apache.http.annotation.Immutable;
+
+/**
+ * Builder class for sequences of bytes.
+ *
+ * @since 5.0
+ */
+@Immutable
+public class ByteArrayBuilder {
+
+ private CharsetEncoder charsetEncoder;
+ private ByteBuffer buffer;
+
+ public ByteArrayBuilder() {
+ }
+
+ public ByteArrayBuilder(final int initialCapacity) {
+ this.buffer = ByteBuffer.allocate(initialCapacity);
+ }
+
+ public int capacity() {
+ return this.buffer != null ? this.buffer.capacity() : 0;
+ }
+
+ static ByteBuffer ensureFreeCapacity(final ByteBuffer buffer, final int capacity) {
+ if (buffer == null) {
+ return ByteBuffer.allocate(capacity);
+ }
+ if (buffer.remaining() < capacity) {
+ final ByteBuffer newBuffer = ByteBuffer.allocate(buffer.position() + capacity);
+ buffer.flip();
+ newBuffer.put(buffer);
+ return newBuffer;
+ } else {
+ return buffer;
+ }
+ }
+
+ static ByteBuffer encode(
+ final ByteBuffer buffer, final CharBuffer in, final CharsetEncoder encoder) throws CharacterCodingException {
+
+ final int capacity = (int) (in.remaining() * encoder.averageBytesPerChar());
+ ByteBuffer out = ensureFreeCapacity(buffer, capacity);
+ for (;;) {
+ CoderResult result = in.hasRemaining() ? encoder.encode(in, out, true) : CoderResult.UNDERFLOW;
+ if (result.isError()) {
+ result.throwException();
+ }
+ if (result.isUnderflow()) {
+ result = encoder.flush(out);
+ }
+ if (result.isUnderflow()) {
+ break;
+ }
+ if (result.isOverflow()) {
+ out = ensureFreeCapacity(out, capacity);
+ }
+ }
+ return out;
+ }
+
+ public void ensureFreeCapacity(final int freeCapacity) {
+ this.buffer = ensureFreeCapacity(this.buffer, freeCapacity);
+ }
+
+ private void doAppend(final CharBuffer charBuffer) {
+ if (this.charsetEncoder == null) {
+ this.charsetEncoder = Consts.ASCII.newEncoder()
+ .onMalformedInput(CodingErrorAction.IGNORE)
+ .onUnmappableCharacter(CodingErrorAction.REPLACE);
+ }
+ this.charsetEncoder.reset();
+ try {
+ this.buffer = encode(this.buffer, charBuffer, this.charsetEncoder);
+ } catch (CharacterCodingException ex) {
+ // Should never happen
+ throw new IllegalStateException("Unexpected character coding error", ex);
+ }
+ }
+
+ public ByteArrayBuilder charset(final Charset charset) {
+ if (charset == null) {
+ this.charsetEncoder = null;
+ } else {
+ this.charsetEncoder = charset.newEncoder()
+ .onMalformedInput(CodingErrorAction.IGNORE)
+ .onUnmappableCharacter(CodingErrorAction.REPLACE);
+ }
+ return this;
+ }
+
+ public ByteArrayBuilder append(final byte[] b, final int off, final int len) {
+ if (b == null) {
+ return this;
+ }
+ if ((off < 0) || (off > b.length) || (len < 0) ||
+ ((off + len) < 0) || ((off + len) > b.length)) {
+ throw new IndexOutOfBoundsException("off: " + off + " len: " + len + " b.length: " + b.length);
+ }
+ ensureFreeCapacity(len);
+ this.buffer.put(b, off, len);
+ return this;
+ }
+
+ public ByteArrayBuilder append(final byte[] b) {
+ if (b == null) {
+ return this;
+ }
+ return append(b, 0, b.length);
+ }
+
+ public ByteArrayBuilder append(final CharBuffer charBuffer) {
+ if (charBuffer == null) {
+ return this;
+ }
+ doAppend(charBuffer);
+ return this;
+ }
+
+ public ByteArrayBuilder append(final char[] b, final int off, final int len) {
+ if (b == null) {
+ return this;
+ }
+ if ((off < 0) || (off > b.length) || (len < 0) ||
+ ((off + len) < 0) || ((off + len) > b.length)) {
+ throw new IndexOutOfBoundsException("off: " + off + " len: " + len + " b.length: " + b.length);
+ }
+ return append(CharBuffer.wrap(b, off, len));
+ }
+
+ public ByteArrayBuilder append(final char[] b) {
+ if (b == null) {
+ return this;
+ }
+ return append(b, 0, b.length);
+ }
+
+ public ByteArrayBuilder append(final String s) {
+ if (s == null) {
+ return this;
+ }
+ return append(CharBuffer.wrap(s));
+ }
+
+ public ByteBuffer toByteBuffer() {
+ return this.buffer != null ? this.buffer.duplicate() : ByteBuffer.allocate(0);
+ }
+
+ public byte[] toByteArray() {
+ if (this.buffer == null) {
+ return new byte[] {};
+ } else {
+ this.buffer.flip();
+ final byte[] b = new byte[this.buffer.remaining()];
+ this.buffer.get(b);
+ this.buffer.clear();
+ return b;
+ }
+ }
+
+ public void reset() {
+ if (this.charsetEncoder != null) {
+ this.charsetEncoder.reset();
+ }
+ if (this.buffer != null) {
+ this.buffer.clear();
+ }
+ }
+
+ @Override
+ public String toString() {
+ return this.buffer != null ? this.buffer.toString() : "null";
+ }
+
+}
diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/BasicScheme.java b/httpclient/src/main/java/org/apache/http/impl/auth/BasicScheme.java
index f75e0ac92..e5ee0ee33 100644
--- a/httpclient/src/main/java/org/apache/http/impl/auth/BasicScheme.java
+++ b/httpclient/src/main/java/org/apache/http/impl/auth/BasicScheme.java
@@ -51,10 +51,10 @@
import org.apache.http.auth.Credentials;
import org.apache.http.auth.CredentialsProvider;
import org.apache.http.auth.MalformedChallengeException;
+import org.apache.http.auth.util.ByteArrayBuilder;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.Args;
import org.apache.http.util.CharsetUtils;
-import org.apache.http.util.EncodingUtils;
/**
* Basic authentication scheme as defined in RFC 2617.
@@ -68,7 +68,10 @@ public class BasicScheme implements AuthScheme, Serializable {
private final Map paramMap;
private transient Charset charset;
+ private transient ByteArrayBuilder buffer;
+ private transient Base64 base64codec;
private boolean complete;
+
private String username;
private String password;
@@ -160,12 +163,17 @@ public String generateAuthResponse(
final HttpHost host,
final HttpRequest request,
final HttpContext context) throws AuthenticationException {
- final StringBuilder buffer = new StringBuilder();
- buffer.append(this.username);
- buffer.append(":");
- buffer.append(this.password);
- final Base64 base64codec = new Base64(0);
- final byte[] encodedCreds = base64codec.encode(EncodingUtils.getBytes(buffer.toString(), charset.name()));
+ if (this.buffer == null) {
+ this.buffer = new ByteArrayBuilder(64).charset(this.charset);
+ } else {
+ this.buffer.reset();
+ }
+ this.buffer.append(this.username).append(":").append(this.password);
+ if (this.base64codec == null) {
+ this.base64codec = new Base64(0);
+ }
+ final byte[] encodedCreds = this.base64codec.encode(this.buffer.toByteArray());
+ this.buffer.reset();
return "Basic " + new String(encodedCreds, 0, encodedCreds.length, Consts.ASCII);
}
diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/DigestScheme.java b/httpclient/src/main/java/org/apache/http/impl/auth/DigestScheme.java
index 441ae3873..ca4236eb1 100644
--- a/httpclient/src/main/java/org/apache/http/impl/auth/DigestScheme.java
+++ b/httpclient/src/main/java/org/apache/http/impl/auth/DigestScheme.java
@@ -28,6 +28,7 @@
import java.io.IOException;
import java.io.Serializable;
+import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.Principal;
import java.security.SecureRandom;
@@ -41,6 +42,7 @@
import java.util.Set;
import java.util.StringTokenizer;
+import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpHost;
@@ -54,12 +56,13 @@
import org.apache.http.auth.Credentials;
import org.apache.http.auth.CredentialsProvider;
import org.apache.http.auth.MalformedChallengeException;
+import org.apache.http.auth.util.ByteArrayBuilder;
import org.apache.http.message.BasicHeaderValueFormatter;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.Args;
import org.apache.http.util.CharArrayBuffer;
-import org.apache.http.util.EncodingUtils;
+import org.apache.http.util.CharsetUtils;
/**
* Digest authentication scheme as defined in RFC 2617.
@@ -84,7 +87,7 @@ public class DigestScheme implements AuthScheme, Serializable {
* Hexa values used when creating 32 character long digest in HTTP DigestScheme
* in case of authentication.
*
- * @see #encode(byte[])
+ * @see #formatHex(byte[])
*/
private static final char[] HEXADECIMAL = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',
@@ -98,11 +101,13 @@ public class DigestScheme implements AuthScheme, Serializable {
private final Map paramMap;
private boolean complete;
+ private transient ByteArrayBuilder buffer;
+
private String lastNonce;
private long nounceCount;
private String cnonce;
- private String a1;
- private String a2;
+ private byte[] a1;
+ private byte[] a2;
private String username;
private String password;
@@ -251,9 +256,10 @@ private String createDigestResponse(final HttpRequest request) throws Authentica
throw new AuthenticationException("None of the qop methods is supported: " + qoplist);
}
- String charset = this.paramMap.get("charset");
+ final String charsetName = this.paramMap.get("charset");
+ Charset charset = charsetName != null ? CharsetUtils.lookup(charsetName) : null;
if (charset == null) {
- charset = "ISO-8859-1";
+ charset = Consts.ISO_8859_1;
}
String digAlg = algorithm;
@@ -275,16 +281,24 @@ private String createDigestResponse(final HttpRequest request) throws Authentica
cnonce = null;
lastNonce = nonce;
}
- final StringBuilder sb = new StringBuilder(256);
+
+ final StringBuilder sb = new StringBuilder(8);
final Formatter formatter = new Formatter(sb, Locale.US);
- formatter.format("%08x", Long.valueOf(nounceCount));
+ formatter.format("%08x", nounceCount);
formatter.close();
final String nc = sb.toString();
if (cnonce == null) {
- cnonce = createCnonce();
+ cnonce = formatHex(createCnonce());
}
+ if (buffer == null) {
+ buffer = new ByteArrayBuilder();
+ } else {
+ buffer.reset();
+ }
+ buffer.charset(charset);
+
a1 = null;
a2 = null;
// 3.2.2.2: Calculating digest
@@ -294,24 +308,23 @@ private String createDigestResponse(final HttpRequest request) throws Authentica
// ":" unq(cnonce-value)
// calculated one per session
- sb.setLength(0);
- sb.append(username).append(':').append(realm).append(':').append(password);
- final String checksum = encode(digester.digest(EncodingUtils.getBytes(sb.toString(), charset)));
- sb.setLength(0);
- sb.append(checksum).append(':').append(nonce).append(':').append(cnonce);
- a1 = sb.toString();
+ buffer.append(username).append(":").append(realm).append(":").append(password);
+ final String checksum = formatHex(digester.digest(this.buffer.toByteArray()));
+ buffer.reset();
+ buffer.append(checksum).append(":").append(nonce).append(":").append(cnonce);
+ a1 = buffer.toByteArray();
} else {
// unq(username-value) ":" unq(realm-value) ":" passwd
- sb.setLength(0);
- sb.append(username).append(':').append(realm).append(':').append(password);
- a1 = sb.toString();
+ buffer.append(username).append(":").append(realm).append(":").append(password);
+ a1 = buffer.toByteArray();
}
- final String hasha1 = encode(digester.digest(EncodingUtils.getBytes(a1, charset)));
+ final String hasha1 = formatHex(digester.digest(a1));
+ buffer.reset();
if (qop == QOP_AUTH) {
// Method ":" digest-uri-value
- a2 = method + ':' + uri;
+ a2 = buffer.append(method).append(":").append(uri).toByteArray();
} else if (qop == QOP_AUTH_INT) {
// Method ":" digest-uri-value ":" H(entity-body)
HttpEntity entity = null;
@@ -322,7 +335,7 @@ private String createDigestResponse(final HttpRequest request) throws Authentica
// If the entity is not repeatable, try falling back onto QOP_AUTH
if (qopset.contains("auth")) {
qop = QOP_AUTH;
- a2 = method + ':' + uri;
+ a2 = buffer.append(method).append(":").append(uri).toByteArray();
} else {
throw new AuthenticationException("Qop auth-int cannot be used with " +
"a non-repeatable entity");
@@ -337,30 +350,31 @@ private String createDigestResponse(final HttpRequest request) throws Authentica
} catch (final IOException ex) {
throw new AuthenticationException("I/O error reading entity content", ex);
}
- a2 = method + ':' + uri + ':' + encode(entityDigester.getDigest());
+ a2 = buffer.append(method).append(":").append(uri)
+ .append(":").append(formatHex(entityDigester.getDigest())).toByteArray();
}
} else {
- a2 = method + ':' + uri;
+ a2 = buffer.append(method).append(":").append(uri).toByteArray();
}
- final String hasha2 = encode(digester.digest(EncodingUtils.getBytes(a2, charset)));
+ final String hasha2 = formatHex(digester.digest(a2));
+ buffer.reset();
// 3.2.2.1
- final String digestValue;
+ final byte[] digestInput;
if (qop == QOP_MISSING) {
- sb.setLength(0);
- sb.append(hasha1).append(':').append(nonce).append(':').append(hasha2);
- digestValue = sb.toString();
+ buffer.append(hasha1).append(":").append(nonce).append(":").append(hasha2);
+ digestInput = buffer.toByteArray();
} else {
- sb.setLength(0);
- sb.append(hasha1).append(':').append(nonce).append(':').append(nc).append(':')
- .append(cnonce).append(':').append(qop == QOP_AUTH_INT ? "auth-int" : "auth")
- .append(':').append(hasha2);
- digestValue = sb.toString();
+ buffer.append(hasha1).append(":").append(nonce).append(":").append(nc).append(":")
+ .append(cnonce).append(":").append(qop == QOP_AUTH_INT ? "auth-int" : "auth")
+ .append(":").append(hasha2);
+ digestInput = buffer.toByteArray();
}
+ buffer.reset();
- final String digest = encode(digester.digest(EncodingUtils.getAsciiBytes(digestValue)));
+ final String digest = formatHex(digester.digest(digestInput));
final CharArrayBuffer buffer = new CharArrayBuffer(128);
buffer.append("Digest ");
@@ -401,11 +415,11 @@ String getCnonce() {
}
String getA1() {
- return a1;
+ return a1 != null ? new String(a1, Consts.ASCII) : null;
}
String getA2() {
- return a2;
+ return a2 != null ? new String(a2, Consts.ASCII) : null;
}
/**
@@ -415,7 +429,7 @@ String getA2() {
* @param binaryData array containing the digest
* @return encoded MD5, or null
if encoding failed
*/
- static String encode(final byte[] binaryData) {
+ static String formatHex(final byte[] binaryData) {
final int n = binaryData.length;
final char[] buffer = new char[n * 2];
for (int i = 0; i < n; i++) {
@@ -433,11 +447,11 @@ static String encode(final byte[] binaryData) {
*
* @return The cnonce value as String.
*/
- public static String createCnonce() {
+ static byte[] createCnonce() {
final SecureRandom rnd = new SecureRandom();
final byte[] tmp = new byte[8];
rnd.nextBytes(tmp);
- return encode(tmp);
+ return tmp;
}
@Override
diff --git a/httpclient/src/test/java/org/apache/http/auth/util/TestByteArrayBuilder.java b/httpclient/src/test/java/org/apache/http/auth/util/TestByteArrayBuilder.java
new file mode 100644
index 000000000..3ab527ab6
--- /dev/null
+++ b/httpclient/src/test/java/org/apache/http/auth/util/TestByteArrayBuilder.java
@@ -0,0 +1,214 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ *
+ */
+package org.apache.http.auth.util;
+
+import java.nio.ByteBuffer;
+
+import org.apache.http.Consts;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * {@link ByteArrayBuilder} test cases.
+ */
+public class TestByteArrayBuilder {
+
+ @Test
+ public void testEmptyBuffer() throws Exception {
+ final ByteArrayBuilder buffer = new ByteArrayBuilder();
+ final ByteBuffer byteBuffer = buffer.toByteBuffer();
+ Assert.assertNotNull(byteBuffer);
+ Assert.assertEquals(0, byteBuffer.capacity());
+
+ final byte[] bytes = buffer.toByteArray();
+ Assert.assertNotNull(bytes);
+ Assert.assertEquals(0, bytes.length);
+ }
+
+ @Test
+ public void testAppendBytes() throws Exception {
+ final ByteArrayBuilder buffer = new ByteArrayBuilder();
+ buffer.append(new byte[]{1, 2, 3, 4, 5});
+ buffer.append(new byte[]{3, 4, 5, 6, 7, 8, 9, 10, 11}, 3, 5);
+ buffer.append((byte[]) null);
+
+ final byte[] bytes = buffer.toByteArray();
+ Assert.assertNotNull(bytes);
+ Assert.assertArrayEquals(new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, bytes);
+ }
+
+ @Test
+ public void testInvalidAppendBytes() throws Exception {
+ final ByteArrayBuilder buffer = new ByteArrayBuilder();
+ buffer.append((byte[])null, 0, 0);
+
+ final byte[] tmp = new byte[] { 1, 2, 3, 4};
+ try {
+ buffer.append(tmp, -1, 0);
+ Assert.fail("IndexOutOfBoundsException should have been thrown");
+ } catch (final IndexOutOfBoundsException ex) {
+ // expected
+ }
+ try {
+ buffer.append(tmp, 0, -1);
+ Assert.fail("IndexOutOfBoundsException should have been thrown");
+ } catch (final IndexOutOfBoundsException ex) {
+ // expected
+ }
+ try {
+ buffer.append(tmp, 0, 8);
+ Assert.fail("IndexOutOfBoundsException should have been thrown");
+ } catch (final IndexOutOfBoundsException ex) {
+ // expected
+ }
+ try {
+ buffer.append(tmp, 10, Integer.MAX_VALUE);
+ Assert.fail("IndexOutOfBoundsException should have been thrown");
+ } catch (final IndexOutOfBoundsException ex) {
+ // expected
+ }
+ try {
+ buffer.append(tmp, 2, 4);
+ Assert.fail("IndexOutOfBoundsException should have been thrown");
+ } catch (final IndexOutOfBoundsException ex) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testEnsureCapacity() throws Exception {
+ final ByteArrayBuilder buffer = new ByteArrayBuilder();
+ buffer.ensureFreeCapacity(10);
+ Assert.assertEquals(10, buffer.capacity());
+ buffer.ensureFreeCapacity(5);
+ Assert.assertEquals(10, buffer.capacity());
+ buffer.append(new byte[]{1, 2, 3, 4, 5, 6, 7, 8});
+ buffer.ensureFreeCapacity(5);
+ Assert.assertEquals(13, buffer.capacity());
+ buffer.ensureFreeCapacity(15);
+ Assert.assertEquals(23, buffer.capacity());
+ }
+
+ @Test
+ public void testAppendText() throws Exception {
+ final ByteArrayBuilder buffer = new ByteArrayBuilder();
+ buffer.append(new char[]{'1', '2', '3', '4', '5'});
+ buffer.append(new char[]{'3', '4', '5', '6', '7', '8', '9', 'a', 'b'}, 3, 5);
+ buffer.append("bcd");
+ buffer.append("e");
+ buffer.append("f");
+ buffer.append((String) null);
+ buffer.append((char[]) null);
+
+ final byte[] bytes = buffer.toByteArray();
+ Assert.assertNotNull(bytes);
+ Assert.assertEquals("123456789abcdef", new String(bytes, Consts.ASCII));
+ }
+
+ @Test
+ public void testInvalidAppendChars() throws Exception {
+ final ByteArrayBuilder buffer = new ByteArrayBuilder();
+ buffer.append((char[])null, 0, 0);
+
+ final char[] tmp = new char[] { 1, 2, 3, 4};
+ try {
+ buffer.append(tmp, -1, 0);
+ Assert.fail("IndexOutOfBoundsException should have been thrown");
+ } catch (final IndexOutOfBoundsException ex) {
+ // expected
+ }
+ try {
+ buffer.append(tmp, 0, -1);
+ Assert.fail("IndexOutOfBoundsException should have been thrown");
+ } catch (final IndexOutOfBoundsException ex) {
+ // expected
+ }
+ try {
+ buffer.append(tmp, 0, 8);
+ Assert.fail("IndexOutOfBoundsException should have been thrown");
+ } catch (final IndexOutOfBoundsException ex) {
+ // expected
+ }
+ try {
+ buffer.append(tmp, 10, Integer.MAX_VALUE);
+ Assert.fail("IndexOutOfBoundsException should have been thrown");
+ } catch (final IndexOutOfBoundsException ex) {
+ // expected
+ }
+ try {
+ buffer.append(tmp, 2, 4);
+ Assert.fail("IndexOutOfBoundsException should have been thrown");
+ } catch (final IndexOutOfBoundsException ex) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testReset() throws Exception {
+ final ByteArrayBuilder buffer = new ByteArrayBuilder();
+ buffer.append("abcd");
+ buffer.append("e");
+ buffer.append("f");
+
+ final byte[] bytes1 = buffer.toByteArray();
+ Assert.assertNotNull(bytes1);
+ Assert.assertEquals("abcdef", new String(bytes1, Consts.ASCII));
+
+ buffer.reset();
+
+ final byte[] bytes2 = buffer.toByteArray();
+ Assert.assertNotNull(bytes2);
+ Assert.assertEquals("", new String(bytes2, Consts.ASCII));
+ }
+
+ @Test
+ public void testNonAsciiCharset() throws Exception {
+ final int[] germanChars = { 0xE4, 0x2D, 0xF6, 0x2D, 0xFc };
+ final StringBuilder tmp = new StringBuilder();
+ for (final int germanChar : germanChars) {
+ tmp.append((char) germanChar);
+ }
+ final String umlauts = tmp.toString();
+
+
+ final ByteArrayBuilder buffer = new ByteArrayBuilder();
+ buffer.append(umlauts);
+
+ final byte[] bytes1 = buffer.toByteArray();
+ Assert.assertNotNull(bytes1);
+ Assert.assertEquals("?-?-?", new String(bytes1, Consts.ASCII));
+
+ buffer.reset();
+ buffer.charset(Consts.UTF_8);
+ buffer.append(umlauts);
+
+ final byte[] bytes2 = buffer.toByteArray();
+ Assert.assertNotNull(bytes2);
+ Assert.assertEquals(umlauts, new String(bytes2, Consts.UTF_8));
+ }
+
+}
diff --git a/httpclient/src/test/java/org/apache/http/impl/auth/TestDigestScheme.java b/httpclient/src/test/java/org/apache/http/impl/auth/TestDigestScheme.java
index 55b9bf184..3e26a7c98 100644
--- a/httpclient/src/test/java/org/apache/http/impl/auth/TestDigestScheme.java
+++ b/httpclient/src/test/java/org/apache/http/impl/auth/TestDigestScheme.java
@@ -567,7 +567,7 @@ public void testHttpEntityDigest() throws Exception {
digester.write(new byte[] { 'a', 'b', 'c'});
Assert.assertNull(digester.getDigest());
digester.close();
- Assert.assertEquals("acd2b59cd01c7737d8069015584c6cac", DigestScheme.encode(digester.getDigest()));
+ Assert.assertEquals("acd2b59cd01c7737d8069015584c6cac", DigestScheme.formatHex(digester.getDigest()));
try {
digester.write('a');
Assert.fail("IOException should have been thrown");