Skip to content

Commit 554a577

Browse files
author
Stephane Landelle
committed
Pool StringBuilders, close AsyncHttpClient#777
1 parent 0f514b1 commit 554a577

File tree

9 files changed

+73
-56
lines changed

9 files changed

+73
-56
lines changed

api/src/main/java/org/asynchttpclient/Realm.java

Lines changed: 39 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,17 @@
1616
*/
1717
package org.asynchttpclient;
1818

19-
import static java.nio.charset.StandardCharsets.*;
19+
import static java.nio.charset.StandardCharsets.ISO_8859_1;
20+
import static java.nio.charset.StandardCharsets.UTF_8;
2021
import static org.asynchttpclient.util.MiscUtils.isNonEmpty;
2122

22-
import org.asynchttpclient.uri.Uri;
23-
2423
import java.nio.charset.Charset;
2524
import java.security.MessageDigest;
2625
import java.security.NoSuchAlgorithmException;
2726

27+
import org.asynchttpclient.uri.Uri;
28+
import org.asynchttpclient.util.StringUtils;
29+
2830
/**
2931
* This class is required when authentication is needed. The class support DIGEST and BASIC.
3032
*/
@@ -534,54 +536,62 @@ private void newResponse() {
534536
} catch (NoSuchAlgorithmException e) {
535537
throw new SecurityException(e);
536538
}
537-
md.update(new StringBuilder(principal).append(":")//
538-
.append(realmName).append(":")//
539-
.append(password).toString()//
540-
.getBytes(ISO_8859_1));
539+
540+
StringBuilder sb = StringUtils.stringBuilder();
541+
md.update(sb.append(principal)
542+
.append(":")
543+
.append(realmName)
544+
.append(":")
545+
.append(password)
546+
.toString().getBytes(ISO_8859_1));
541547
byte[] ha1 = md.digest();
542548

543549
md.reset();
544550

545-
// HA2 if qop is auth-int is methodName:url:md5(entityBody)
546-
md.update(new StringBuilder(methodName).append(':')//
547-
.append(uri).toString()//
548-
.getBytes(ISO_8859_1));
551+
//HA2 if qop is auth-int is methodName:url:md5(entityBody)
552+
553+
// BEWARE: compute first as it used the cached StringBuilder
554+
String url = uri.toUrl();
555+
556+
sb.setLength(0);
557+
md.update(sb.append(methodName)
558+
.append(':')
559+
.append(url).toString().getBytes(ISO_8859_1));
549560
byte[] ha2 = md.digest();
550561

551-
if (qop == null || qop.length() == 0) {
552-
md.update(new StringBuilder(toBase16(ha1)).append(':')//
553-
.append(nonce).append(':')//
554-
.append(toBase16(ha2)).toString()//
555-
.getBytes(ISO_8859_1));
556-
557-
} else {
558-
// qop ="auth" or "auth-int"
559-
md.update(new StringBuilder(toBase16(ha1)).append(':')//
560-
.append(nonce).append(':')//
561-
.append(NC).append(':')//
562-
.append(cnonce).append(':')//
563-
.append(qop).append(':')//
564-
.append(toBase16(ha2)).toString()//
565-
.getBytes(ISO_8859_1));
562+
sb.setLength(0);
563+
appendBase16(sb, ha1);
564+
sb.append(':').append(nonce).append(':');
565+
566+
if (isNonEmpty(qop)) {
567+
//qop ="auth" or "auth-int"
568+
sb.append(NC)//
569+
.append(':')//
570+
.append(cnonce)//
571+
.append(':')//
572+
.append(qop)//
573+
.append(':');
566574
}
567575

576+
appendBase16(sb, ha2);
577+
md.update(sb.toString().getBytes(ISO_8859_1));
578+
568579
byte[] digest = md.digest();
569580

570581
response = toHexString(digest);
571582
}
572583

573584
private static String toHexString(byte[] data) {
574-
StringBuilder buffer = new StringBuilder();
585+
StringBuilder buffer = StringUtils.stringBuilder();
575586
for (int i = 0; i < data.length; i++) {
576587
buffer.append(Integer.toHexString((data[i] & 0xf0) >>> 4));
577588
buffer.append(Integer.toHexString(data[i] & 0x0f));
578589
}
579590
return buffer.toString();
580591
}
581592

582-
private static String toBase16(byte[] bytes) {
593+
private static void appendBase16(StringBuilder buf, byte[] bytes) {
583594
int base = 16;
584-
StringBuilder buf = new StringBuilder();
585595
for (byte b : bytes) {
586596
int bi = 0xff & b;
587597
int c = '0' + (bi / base) % base;
@@ -593,7 +603,6 @@ private static String toBase16(byte[] bytes) {
593603
c = 'a' + (c - '0' - 10);
594604
buf.append((char) c);
595605
}
596-
return buf.toString();
597606
}
598607

599608
/**

api/src/main/java/org/asynchttpclient/cookie/CookieDecoder.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
import org.asynchttpclient.date.CalendarTimeConverter;
1616
import org.asynchttpclient.date.TimeConverter;
17+
import org.asynchttpclient.util.StringUtils;
1718

1819
public class CookieDecoder {
1920

@@ -92,7 +93,7 @@ public static Cookie decode(String header, TimeConverter timeConverter) {
9293
char c = header.charAt(i);
9394
if (c == '"' || c == '\'') {
9495
// NAME="VALUE" or NAME='VALUE'
95-
StringBuilder newValueBuf = new StringBuilder(header.length() - i);
96+
StringBuilder newValueBuf = StringUtils.stringBuilder();
9697

9798
int rawValueStart = i;
9899
int rawValueEnd = i;

api/src/main/java/org/asynchttpclient/cookie/CookieEncoder.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@
1414

1515
import java.util.Collection;
1616

17+
import org.asynchttpclient.util.StringUtils;
18+
1719
public final class CookieEncoder {
1820

1921
private CookieEncoder() {
2022
}
2123

2224
public static String encode(Collection<Cookie> cookies) {
23-
StringBuilder sb = new StringBuilder();
25+
StringBuilder sb = StringUtils.stringBuilder();
2426

2527
for (Cookie cookie : cookies) {
2628
add(sb, cookie.getName(), cookie.getRawValue());

api/src/main/java/org/asynchttpclient/multipart/MultipartUtils.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,11 @@
1515
*/
1616
package org.asynchttpclient.multipart;
1717

18-
import static java.nio.charset.StandardCharsets.*;
18+
import static java.nio.charset.StandardCharsets.US_ASCII;
1919
import static org.asynchttpclient.multipart.Part.CRLF_BYTES;
2020
import static org.asynchttpclient.multipart.Part.EXTRA_BYTES;
2121
import static org.asynchttpclient.util.MiscUtils.isNonEmpty;
2222

23-
import org.asynchttpclient.FluentCaseInsensitiveStringsMap;
24-
import org.slf4j.Logger;
25-
import org.slf4j.LoggerFactory;
26-
2723
import java.io.ByteArrayOutputStream;
2824
import java.io.IOException;
2925
import java.nio.ByteBuffer;
@@ -35,6 +31,11 @@
3531
import java.util.Random;
3632
import java.util.Set;
3733

34+
import org.asynchttpclient.FluentCaseInsensitiveStringsMap;
35+
import org.asynchttpclient.util.StringUtils;
36+
import org.slf4j.Logger;
37+
import org.slf4j.LoggerFactory;
38+
3839
public class MultipartUtils {
3940

4041
private static final Logger LOGGER = LoggerFactory.getLogger(MultipartUtils.class);
@@ -100,9 +101,9 @@ private static byte[] generateMultipartBoundary() {
100101
}
101102

102103
private static String computeContentType(String base, byte[] multipartBoundary) {
103-
StringBuilder buffer = new StringBuilder(base);
104+
StringBuilder buffer = StringUtils.stringBuilder().append(base);
104105
if (!base.endsWith(";"))
105-
buffer.append(";");
106+
buffer.append(';');
106107
return buffer.append(" boundary=").append(new String(multipartBoundary, US_ASCII)).toString();
107108
}
108109

api/src/main/java/org/asynchttpclient/oauth/OAuthSignatureCalculator.java

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,22 +16,23 @@
1616
*/
1717
package org.asynchttpclient.oauth;
1818

19-
import static java.nio.charset.StandardCharsets.*;
19+
import static java.nio.charset.StandardCharsets.UTF_8;
2020
import static org.asynchttpclient.util.MiscUtils.isNonEmpty;
2121

22+
import java.util.ArrayList;
23+
import java.util.Arrays;
24+
import java.util.List;
25+
import java.util.Random;
26+
2227
import org.asynchttpclient.Param;
2328
import org.asynchttpclient.Request;
2429
import org.asynchttpclient.RequestBuilderBase;
2530
import org.asynchttpclient.SignatureCalculator;
2631
import org.asynchttpclient.uri.Uri;
2732
import org.asynchttpclient.util.Base64;
33+
import org.asynchttpclient.util.StringUtils;
2834
import org.asynchttpclient.util.UTF8UrlEncoder;
2935

30-
import java.util.ArrayList;
31-
import java.util.Arrays;
32-
import java.util.List;
33-
import java.util.Random;
34-
3536
/**
3637
* Simple OAuth signature calculator that can used for constructing client signatures
3738
* for accessing services that use OAuth for authorization.
@@ -96,7 +97,7 @@ public void calculateAndAddSignature(Request request, RequestBuilderBase<?> requ
9697
*/
9798
public String calculateSignature(String method, Uri uri, long oauthTimestamp, String nonce,
9899
List<Param> formParams, List<Param> queryParams) {
99-
StringBuilder signedText = new StringBuilder(100);
100+
StringBuilder signedText = StringUtils.stringBuilder();
100101
signedText.append(method); // POST / GET etc (nothing to URL encode)
101102
signedText.append('&');
102103

@@ -163,7 +164,7 @@ else if (scheme.equals("https"))
163164
* Method used for constructing
164165
*/
165166
public String constructAuthHeader(String signature, String nonce, long oauthTimestamp) {
166-
StringBuilder sb = new StringBuilder(200);
167+
StringBuilder sb = StringUtils.stringBuilder();
167168
sb.append("OAuth ");
168169
sb.append(KEY_OAUTH_CONSUMER_KEY).append("=\"").append(consumerAuth.getKey()).append("\", ");
169170
if (userAuth.getKey() != null) {

api/src/main/java/org/asynchttpclient/uri/Uri.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import java.net.URISyntaxException;
1717

1818
import org.asynchttpclient.util.MiscUtils;
19+
import org.asynchttpclient.util.StringUtils;
1920

2021
public class Uri {
2122

@@ -93,7 +94,7 @@ public URI toJavaNetURI() throws URISyntaxException {
9394

9495
public String toUrl() {
9596
if (url == null) {
96-
StringBuilder sb = new StringBuilder();
97+
StringBuilder sb = StringUtils.stringBuilder();
9798
sb.append(scheme).append("://");
9899
if (userInfo != null)
99100
sb.append(userInfo).append('@');
@@ -111,7 +112,7 @@ public String toUrl() {
111112
}
112113

113114
public String toRelativeUrl() {
114-
StringBuilder sb = new StringBuilder();
115+
StringBuilder sb = StringUtils.stringBuilder();
115116
if (MiscUtils.isNonEmpty(path))
116117
sb.append(path);
117118
else

api/src/main/java/org/asynchttpclient/util/QueryComputer.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ private final void encodeAndAppendQuery(final StringBuilder sb, final String que
5555

5656
protected final String withQueryWithParams(final String query, final List<Param> queryParams) {
5757
// concatenate encoded query + encoded query params
58-
StringBuilder sb = new StringBuilder(query.length() + queryParams.size() * 16);
58+
StringBuilder sb = StringUtils.stringBuilder();
5959
encodeAndAppendQuery(sb, query);
6060
encodeAndAppendQueryParams(sb, queryParams);
6161
sb.setLength(sb.length() - 1);
@@ -64,15 +64,15 @@ protected final String withQueryWithParams(final String query, final List<Param>
6464

6565
protected final String withQueryWithoutParams(final String query) {
6666
// encode query
67-
StringBuilder sb = new StringBuilder(query.length() + 6);
67+
StringBuilder sb = StringUtils.stringBuilder();
6868
encodeAndAppendQuery(sb, query);
6969
sb.setLength(sb.length() - 1);
7070
return sb.toString();
7171
}
7272

7373
protected final String withoutQueryWithParams(final List<Param> queryParams) {
7474
// concatenate encoded query params
75-
StringBuilder sb = new StringBuilder(queryParams.size() * 16);
75+
StringBuilder sb = StringUtils.stringBuilder();
7676
encodeAndAppendQueryParams(sb, queryParams);
7777
sb.setLength(sb.length() - 1);
7878
return sb.toString();
@@ -95,7 +95,7 @@ private final void appendRawQueryParams(final StringBuilder sb, final List<Param
9595

9696
protected final String withQueryWithParams(final String query, final List<Param> queryParams) {
9797
// concatenate raw query + raw query params
98-
StringBuilder sb = new StringBuilder(query.length() + queryParams.size() * 16);
98+
StringBuilder sb = StringUtils.stringBuilder();
9999
sb.append(query);
100100
appendRawQueryParams(sb, queryParams);
101101
sb.setLength(sb.length() - 1);
@@ -109,7 +109,7 @@ protected final String withQueryWithoutParams(final String query) {
109109

110110
protected final String withoutQueryWithParams(final List<Param> queryParams) {
111111
// concatenate raw queryParams
112-
StringBuilder sb = new StringBuilder(queryParams.size() * 16);
112+
StringBuilder sb = StringUtils.stringBuilder();
113113
appendRawQueryParams(sb, queryParams);
114114
sb.setLength(sb.length() - 1);
115115
return sb.toString();

providers/netty3/src/main/java/org/asynchttpclient/providers/netty3/request/NettyRequestFactory.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
import org.asynchttpclient.providers.netty3.request.body.NettyMultipartBody;
5252
import org.asynchttpclient.spnego.SpnegoEngine;
5353
import org.asynchttpclient.uri.Uri;
54+
import org.asynchttpclient.util.StringUtils;
5455
import org.asynchttpclient.util.UTF8UrlEncoder;
5556
import org.jboss.netty.buffer.ChannelBuffer;
5657
import org.jboss.netty.handler.codec.http.DefaultHttpRequest;
@@ -187,7 +188,7 @@ private String systematicProxyAuthorizationHeader(Request request, ProxyServer p
187188

188189
private byte[] computeBodyFromParams(List<Param> params, Charset bodyCharset) {
189190

190-
StringBuilder sb = new StringBuilder();
191+
StringBuilder sb = StringUtils.stringBuilder();
191192
for (Param param : params) {
192193
UTF8UrlEncoder.appendEncoded(sb, param.getName());
193194
sb.append('=');

providers/netty4/src/main/java/org/asynchttpclient/providers/netty4/request/NettyRequestFactory.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
import org.asynchttpclient.providers.netty4.request.body.NettyMultipartBody;
5959
import org.asynchttpclient.spnego.SpnegoEngine;
6060
import org.asynchttpclient.uri.Uri;
61+
import org.asynchttpclient.util.StringUtils;
6162
import org.asynchttpclient.util.UTF8UrlEncoder;
6263

6364
public final class NettyRequestFactory {
@@ -188,7 +189,7 @@ private String systematicProxyAuthorizationHeader(Request request, ProxyServer p
188189

189190
private byte[] computeBodyFromParams(List<Param> params, Charset bodyCharset) {
190191

191-
StringBuilder sb = new StringBuilder();
192+
StringBuilder sb = StringUtils.stringBuilder();
192193
for (Param param : params) {
193194
UTF8UrlEncoder.appendEncoded(sb, param.getName());
194195
sb.append('=');

0 commit comments

Comments
 (0)