stratosphere-ssp plugin: Fix HttpClient4 connection leak

Replaced HttpClient#execute(HttpUriRequest) with
HttpClient#execute(HttpUriRequest,ResponseHandler<T>).
The former requires extra EntityUtils#consume(HttpEntity).
This commit is contained in:
Hiroaki KAWAI 2014-02-05 16:20:10 +09:00
parent 54f32a8e46
commit 0d222b14a1
2 changed files with 36 additions and 94 deletions

View File

@ -17,15 +17,15 @@
package org.apache.cloudstack.network.element; package org.apache.cloudstack.network.element;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.util.Arrays; import java.util.Arrays;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus; import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient; import org.apache.http.client.HttpClient;
import org.apache.http.client.HttpResponseException;
import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpDelete; import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPost;
@ -35,6 +35,7 @@ import org.apache.http.client.params.ClientPNames;
import org.apache.http.client.params.CookiePolicy; import org.apache.http.client.params.CookiePolicy;
import org.apache.http.entity.ContentType; import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity; import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.PoolingClientConnectionManager; import org.apache.http.impl.conn.PoolingClientConnectionManager;
import org.apache.http.message.BasicNameValuePair; import org.apache.http.message.BasicNameValuePair;
@ -42,8 +43,6 @@ import org.apache.http.params.CoreConnectionPNames;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.JsonIOException;
import com.google.gson.JsonSyntaxException;
import com.google.gson.annotations.SerializedName; import com.google.gson.annotations.SerializedName;
/** /**
@ -74,7 +73,7 @@ public class SspClient {
return s_client; return s_client;
} }
private HttpResponse innerExecuteMethod(HttpRequestBase req, String path) { private String executeMethod(HttpRequestBase req, String path) {
try { try {
URI base = new URI(apiUrl); URI base = new URI(apiUrl);
req.setURI(new URI(base.getScheme(), base.getUserInfo(), base.getHost(), req.setURI(new URI(base.getScheme(), base.getUserInfo(), base.getHost(),
@ -83,23 +82,26 @@ public class SspClient {
s_logger.error("invalid API URL " + apiUrl + " path " + path, e); s_logger.error("invalid API URL " + apiUrl + " path " + path, e);
return null; return null;
} }
HttpResponse res = null;
try { try {
res = getHttpClient().execute(req); String content = null;
s_logger.info("ssp api call:" + req + " status=" + res.getStatusLine()); try {
content = getHttpClient().execute(req, new BasicResponseHandler());
s_logger.info("ssp api call: " + req);
} catch (HttpResponseException e) {
s_logger.info("ssp api call failed: " + req, e);
if (e.getStatusCode() == HttpStatus.SC_UNAUTHORIZED && login()) {
req.reset();
content = getHttpClient().execute(req, new BasicResponseHandler());
s_logger.info("ssp api retry call: " + req);
}
}
return content;
} catch (ClientProtocolException e) { // includes HttpResponseException
s_logger.error("ssp api call failed: " + req, e);
} catch (IOException e) { } catch (IOException e) {
s_logger.error("ssp api call failed: " + req, e); s_logger.error("ssp api call failed: " + req, e);
} }
return res; return null;
}
private HttpResponse executeMethod(HttpRequestBase req, String path) {
HttpResponse res = innerExecuteMethod(req, path);
if (res.getStatusLine().getStatusCode() == HttpStatus.SC_UNAUTHORIZED && login()) {
req.reset();
res = innerExecuteMethod(req, path);
}
return res;
} }
public boolean login() { public boolean login() {
@ -112,9 +114,7 @@ public class SspClient {
s_logger.error("invalid username or password", e); s_logger.error("invalid username or password", e);
return false; return false;
} }
if (executeMethod(method, "/ws.v1/login") != null) {
HttpResponse res = this.innerExecuteMethod(method, "/ws.v1/login");
if (res != null && res.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
return true; return true;
} }
return false; return false;
@ -134,29 +134,14 @@ public class SspClient {
HttpPost method = new HttpPost(); HttpPost method = new HttpPost();
method.setEntity(new StringEntity(new Gson().toJson(req), ContentType.APPLICATION_JSON)); method.setEntity(new StringEntity(new Gson().toJson(req), ContentType.APPLICATION_JSON));
HttpResponse res = executeMethod(method, "/ssp.v1/tenant-networks"); return new Gson().fromJson(
if (res == null || res.getStatusLine().getStatusCode() != HttpStatus.SC_CREATED) { executeMethod(method, "/ssp.v1/tenant-networks"),
return null; TenantNetwork.class);
}
try {
return new Gson().fromJson(new InputStreamReader(res.getEntity().getContent(), "UTF-8"),
TenantNetwork.class);
} catch (JsonSyntaxException e) {
s_logger.error("reading response body failed", e);
} catch (JsonIOException e) {
s_logger.error("reading response body failed", e);
} catch (IllegalStateException e) {
s_logger.error("reading response body failed", e);
} catch (IOException e) {
s_logger.error("reading response body failed", e);
}
return null;
} }
public boolean deleteTenantNetwork(String tenantNetworkUuid) { public boolean deleteTenantNetwork(String tenantNetworkUuid) {
HttpDelete method = new HttpDelete(); HttpDelete method = new HttpDelete();
HttpResponse res = executeMethod(method, "/ssp.v1/tenant-networks/" + tenantNetworkUuid); if (executeMethod(method, "/ssp.v1/tenant-networks/" + tenantNetworkUuid) != null) {
if (res != null && res.getStatusLine().getStatusCode() == HttpStatus.SC_NO_CONTENT) {
return true; return true;
} }
return false; return false;
@ -182,31 +167,14 @@ public class SspClient {
HttpPost method = new HttpPost(); HttpPost method = new HttpPost();
method.setEntity(new StringEntity(new Gson().toJson(req), ContentType.APPLICATION_JSON)); method.setEntity(new StringEntity(new Gson().toJson(req), ContentType.APPLICATION_JSON));
HttpResponse res = executeMethod(method, "/ssp.v1/tenant-ports"); return new Gson().fromJson(
executeMethod(method, "/ssp.v1/tenant-ports"),
if (res == null || res.getStatusLine().getStatusCode() != HttpStatus.SC_CREATED) { TenantPort.class);
return null;
}
try {
return new Gson().fromJson(new InputStreamReader(res.getEntity().getContent(), "UTF-8"),
TenantPort.class);
} catch (JsonSyntaxException e) {
s_logger.error("reading response body failed", e);
} catch (JsonIOException e) {
s_logger.error("reading response body failed", e);
} catch (IllegalStateException e) {
s_logger.error("reading response body failed", e);
} catch (IOException e) {
s_logger.error("reading response body failed", e);
}
return null;
} }
public boolean deleteTenantPort(String tenantPortUuid) { public boolean deleteTenantPort(String tenantPortUuid) {
HttpDelete method = new HttpDelete(); HttpDelete method = new HttpDelete();
HttpResponse res = executeMethod(method, "/ssp.v1/tenant-ports/" + tenantPortUuid); if (executeMethod(method, "/ssp.v1/tenant-ports/" + tenantPortUuid) != null) {
if (res != null && res.getStatusLine().getStatusCode() == HttpStatus.SC_NO_CONTENT) {
return true; return true;
} }
return false; return false;
@ -223,22 +191,8 @@ public class SspClient {
HttpPut method = new HttpPut(); HttpPut method = new HttpPut();
method.setEntity(new StringEntity(new Gson().toJson(req), ContentType.APPLICATION_JSON)); method.setEntity(new StringEntity(new Gson().toJson(req), ContentType.APPLICATION_JSON));
HttpResponse res = executeMethod(method, "/ssp.v1/tenant-ports/" + portUuid); return new Gson().fromJson(
if (res == null || res.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { executeMethod(method, "/ssp.v1/tenant-ports/" + portUuid),
return null; TenantPort.class);
}
try {
return new Gson().fromJson(new InputStreamReader(res.getEntity().getContent(), "UTF-8"),
TenantPort.class);
} catch (JsonSyntaxException e) {
s_logger.error("reading response body failed", e);
} catch (JsonIOException e) {
s_logger.error("reading response body failed", e);
} catch (IllegalStateException e) {
s_logger.error("reading response body failed", e);
} catch (IOException e) {
s_logger.error("reading response body failed", e);
}
return null;
} }
} }

View File

@ -23,15 +23,11 @@ import static org.mockito.Mockito.when;
import static org.mockito.Mockito.any; import static org.mockito.Mockito.any;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
import java.io.ByteArrayInputStream;
import java.util.UUID; import java.util.UUID;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient; import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.impl.client.BasicResponseHandler;
import org.junit.Test; import org.junit.Test;
public class SspClientTest { public class SspClientTest {
@ -46,10 +42,8 @@ public class SspClientTest {
SspClient sspClient = spy(new SspClient(apiUrl, username, password)); SspClient sspClient = spy(new SspClient(apiUrl, username, password));
HttpClient client = mock(HttpClient.class); HttpClient client = mock(HttpClient.class);
HttpResponse res = mock(HttpResponse.class, RETURNS_DEEP_STUBS);
doReturn(client).when(sspClient).getHttpClient(); doReturn(client).when(sspClient).getHttpClient();
when(client.execute(any(HttpUriRequest.class))).thenReturn(res); when(client.execute(any(HttpUriRequest.class), any(BasicResponseHandler.class))).thenReturn("");
when(res.getStatusLine().getStatusCode()).thenReturn(HttpStatus.SC_OK);
assertTrue(sspClient.login()); assertTrue(sspClient.login());
assertTrue(sspClient.login()); assertTrue(sspClient.login());
@ -63,14 +57,10 @@ public class SspClientTest {
SspClient sspClient = spy(new SspClient(apiUrl, username, password)); SspClient sspClient = spy(new SspClient(apiUrl, username, password));
HttpClient client = mock(HttpClient.class); HttpClient client = mock(HttpClient.class);
HttpResponse res = mock(HttpResponse.class, RETURNS_DEEP_STUBS);
doReturn(client).when(sspClient).getHttpClient(); doReturn(client).when(sspClient).getHttpClient();
when(client.execute(any(HttpUriRequest.class))).thenReturn(res);
when(res.getStatusLine().getStatusCode()).thenReturn(HttpStatus.SC_CREATED);
String body = "{\"uuid\":\"" + tenant_net_uuid + "\",\"name\":\"" + networkName String body = "{\"uuid\":\"" + tenant_net_uuid + "\",\"name\":\"" + networkName
+ "\",\"tenant_uuid\":\"" + uuid + "\"}"; + "\",\"tenant_uuid\":\"" + uuid + "\"}";
when(res.getEntity().getContent()).thenReturn( when(client.execute(any(HttpUriRequest.class), any(BasicResponseHandler.class))).thenReturn(body);
new ByteArrayInputStream(body.getBytes("UTF-8")));
SspClient.TenantNetwork tnet = sspClient.createTenantNetwork(uuid, networkName); SspClient.TenantNetwork tnet = sspClient.createTenantNetwork(uuid, networkName);
assertEquals(tnet.name, networkName); assertEquals(tnet.name, networkName);
@ -84,10 +74,8 @@ public class SspClientTest {
SspClient sspClient = spy(new SspClient(apiUrl, username, password)); SspClient sspClient = spy(new SspClient(apiUrl, username, password));
HttpClient client = mock(HttpClient.class); HttpClient client = mock(HttpClient.class);
HttpResponse res = mock(HttpResponse.class, RETURNS_DEEP_STUBS);
doReturn(client).when(sspClient).getHttpClient(); doReturn(client).when(sspClient).getHttpClient();
when(client.execute(any(HttpUriRequest.class))).thenReturn(res); when(client.execute(any(HttpUriRequest.class), any(BasicResponseHandler.class))).thenReturn("");
when(res.getStatusLine().getStatusCode()).thenReturn(HttpStatus.SC_NO_CONTENT);
sspClient.deleteTenantNetwork(tenant_net_uuid); sspClient.deleteTenantNetwork(tenant_net_uuid);
} }