From 9d07a8f00e984dd8d90356201e333cf3c808c7a3 Mon Sep 17 00:00:00 2001 From: seshukm Date: Wed, 25 Jul 2018 19:32:59 +0800 Subject: basic code refactoring client connector Issue-ID: SO-729 Change-Id: If7331155e44582fcfeb1f7473ee42b1d8d55238a Signed-off-by: seshukm --- .../openstack/connector/HttpClientConnector.java | 326 ++++++++-------- .../openstack/connector/HttpClientException.java | 24 +- .../connector/HttpClientRedirectStrategy.java | 8 +- .../openstack/connector/HttpClientResponse.java | 50 +-- .../openstack/connector/JerseyConnector.java | 132 +++---- .../openstack/connector/JerseyLoggingFilter.java | 362 +++++++++--------- .../woorea/openstack/connector/JerseyResponse.java | 86 ++--- .../connector/JerseyLoggingFilterTest.java | 416 ++++++++++----------- .../openstack/connector/JaxRs20Connector.java | 68 ++-- .../openstack/connector/JaxRs20Response.java | 76 ++-- 10 files changed, 774 insertions(+), 774 deletions(-) diff --git a/openstack-client-connectors/http-connector/src/main/java/com/woorea/openstack/connector/HttpClientConnector.java b/openstack-client-connectors/http-connector/src/main/java/com/woorea/openstack/connector/HttpClientConnector.java index 050a4d9..02d851e 100644 --- a/openstack-client-connectors/http-connector/src/main/java/com/woorea/openstack/connector/HttpClientConnector.java +++ b/openstack-client-connectors/http-connector/src/main/java/com/woorea/openstack/connector/HttpClientConnector.java @@ -62,168 +62,168 @@ import com.woorea.openstack.base.client.OpenStackResponseException; public class HttpClientConnector implements OpenStackClientConnector { - public static ObjectMapper DEFAULT_MAPPER; - public static ObjectMapper WRAPPED_MAPPER; - - private static Logger LOGGER = Logger.getLogger(HttpClientConnector.class); - - static { - DEFAULT_MAPPER = new ObjectMapper(); - - DEFAULT_MAPPER.setSerializationInclusion(Inclusion.NON_NULL); - DEFAULT_MAPPER.disable(SerializationConfig.Feature.INDENT_OUTPUT); - DEFAULT_MAPPER.enable(DeserializationConfig.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY); - DEFAULT_MAPPER.disable(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES); - - WRAPPED_MAPPER = new ObjectMapper(); - - WRAPPED_MAPPER.setSerializationInclusion(Inclusion.NON_NULL); - WRAPPED_MAPPER.disable(SerializationConfig.Feature.INDENT_OUTPUT); - WRAPPED_MAPPER.enable(SerializationConfig.Feature.WRAP_ROOT_VALUE); - WRAPPED_MAPPER.enable(DeserializationConfig.Feature.UNWRAP_ROOT_VALUE); - WRAPPED_MAPPER.enable(DeserializationConfig.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY); - WRAPPED_MAPPER.disable(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES); - } - - protected static ObjectMapper getObjectMapper (Class type) { - return type.getAnnotation(JsonRootName.class) == null ? DEFAULT_MAPPER : WRAPPED_MAPPER; - } - - @Override - public OpenStackResponse request(OpenStackRequest request) { - - CloseableHttpClient httpClient = null; //HttpClients.createDefault(); - httpClient = HttpClients.custom().setRedirectStrategy(new HttpClientRedirectStrategy()).build(); - - URI uri = null; - - // Build the URI with query params - try { - URIBuilder uriBuilder = new URIBuilder(request.endpoint() + request.path()); - - for(Map.Entry > entry : request.queryParams().entrySet()) { - for (Object o : entry.getValue()) { - uriBuilder.setParameter(entry.getKey(), String.valueOf(o)); - } - } - - uri = uriBuilder.build(); - } catch (URISyntaxException e) { - throw new HttpClientException (e); - } - - HttpEntity entity = null; - if (request.entity() != null) { - // Flatten the entity to a Json string - - try { - // Get appropriate mapper, based on existence of a root element in Entity class - ObjectMapper mapper = getObjectMapper (request.entity().getEntity().getClass()); - - String entityJson = mapper.writeValueAsString (request.entity().getEntity()); - entity = new StringEntity(entityJson, ContentType.create(request.entity().getContentType())); - - LOGGER.debug("Openstack query JSON:"+entityJson); - LOGGER.debug ("Request JSON Body: " + entityJson.replaceAll("\"password\":\"[^\"]*\"", "\"password\":\"***\"")); - - } catch (JsonProcessingException e) { - throw new HttpClientException ("Json processing error on request entity", e); - } catch (IOException e) { - throw new HttpClientException ("Json IO error on request entity", e); - } - } - - // Determine the HttpRequest class based on the method - HttpUriRequest httpRequest; - - switch (request.method()) { - case POST: - HttpPost post = new HttpPost(uri); - post.setEntity (entity); - httpRequest = post; - break; - - case GET: - httpRequest = new HttpGet(uri); - break; - - case PUT: - HttpPut put = new HttpPut(uri); - put.setEntity (entity); - httpRequest = put; - break; - - case DELETE: - httpRequest = new HttpDelete(uri); - break; - - default: - throw new HttpClientException ("Unrecognized HTTP Method: " + request.method()); - } - - for (Entry> h : request.headers().entrySet()) { - StringBuilder sb = new StringBuilder(); - for (Object v : h.getValue()) { - sb.append(String.valueOf(v)); - } - httpRequest.addHeader(h.getKey(), sb.toString()); - } - - LOGGER.debug ("Sending HTTP request: " + httpRequest.toString()); - - // Get the Response. But don't get the body entity yet, as this response - // will be wrapped in an HttpClientResponse. The HttpClientResponse - // buffers the body in constructor, so can close the response here. - HttpClientResponse httpClientResponse = null; - CloseableHttpResponse httpResponse = null; - - // Catch known HttpClient exceptions, and wrap them in OpenStack Client Exceptions - // so calling functions can distinguish. Only RuntimeExceptions are allowed. - try { - httpResponse = httpClient.execute(httpRequest); - - LOGGER.debug ("Response status: " + httpResponse.getStatusLine().getStatusCode()); - - httpClientResponse = new HttpClientResponse (httpResponse); - - int status = httpResponse.getStatusLine().getStatusCode(); - if (status == HttpStatus.SC_OK || status == HttpStatus.SC_CREATED || - status == HttpStatus.SC_NO_CONTENT || status == HttpStatus.SC_ACCEPTED) - { - return httpClientResponse; - } - } - catch (HttpResponseException e) { - // What exactly does this mean? It does not appear to get thrown for - // non-2XX responses as documented. - throw new OpenStackResponseException(e.getMessage(), e.getStatusCode()); - } - catch (UnknownHostException e) { - throw new OpenStackConnectException("Unknown Host: " + e.getMessage()); - } - catch (IOException e) { - // Catch all other IOExceptions and throw as OpenStackConnectException - throw new OpenStackConnectException(e.getMessage()); - } - catch (Exception e) { - // Catchall for anything else, must throw as a RuntimeException - LOGGER.error ("Unexpected client exception: " +e.getMessage()); - throw new RuntimeException("Unexpected client exception", e); - } - finally { - // Have the body. Close the stream - if (httpResponse != null) - try { - httpResponse.close(); - } catch (IOException e) { - LOGGER.warn("Unable to close HTTP Response: " + e); - } - } - - // Get here on an error response (4XX-5XX) - throw new OpenStackResponseException(httpResponse.getStatusLine().getReasonPhrase(), - httpResponse.getStatusLine().getStatusCode(), - httpClientResponse); - } + public static ObjectMapper DEFAULT_MAPPER; + public static ObjectMapper WRAPPED_MAPPER; + + private static Logger LOGGER = Logger.getLogger(HttpClientConnector.class); + + static { + DEFAULT_MAPPER = new ObjectMapper(); + + DEFAULT_MAPPER.setSerializationInclusion(Inclusion.NON_NULL); + DEFAULT_MAPPER.disable(SerializationConfig.Feature.INDENT_OUTPUT); + DEFAULT_MAPPER.enable(DeserializationConfig.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY); + DEFAULT_MAPPER.disable(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES); + + WRAPPED_MAPPER = new ObjectMapper(); + + WRAPPED_MAPPER.setSerializationInclusion(Inclusion.NON_NULL); + WRAPPED_MAPPER.disable(SerializationConfig.Feature.INDENT_OUTPUT); + WRAPPED_MAPPER.enable(SerializationConfig.Feature.WRAP_ROOT_VALUE); + WRAPPED_MAPPER.enable(DeserializationConfig.Feature.UNWRAP_ROOT_VALUE); + WRAPPED_MAPPER.enable(DeserializationConfig.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY); + WRAPPED_MAPPER.disable(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES); + } + + protected static ObjectMapper getObjectMapper (Class type) { + return type.getAnnotation(JsonRootName.class) == null ? DEFAULT_MAPPER : WRAPPED_MAPPER; + } + + @Override + public OpenStackResponse request(OpenStackRequest request) { + + CloseableHttpClient httpClient = null; //HttpClients.createDefault(); + httpClient = HttpClients.custom().setRedirectStrategy(new HttpClientRedirectStrategy()).build(); + + URI uri = null; + + // Build the URI with query params + try { + URIBuilder uriBuilder = new URIBuilder(request.endpoint() + request.path()); + + for(Map.Entry > entry : request.queryParams().entrySet()) { + for (Object o : entry.getValue()) { + uriBuilder.setParameter(entry.getKey(), String.valueOf(o)); + } + } + + uri = uriBuilder.build(); + } catch (URISyntaxException e) { + throw new HttpClientException (e); + } + + HttpEntity entity = null; + if (request.entity() != null) { + // Flatten the entity to a Json string + + try { + // Get appropriate mapper, based on existence of a root element in Entity class + ObjectMapper mapper = getObjectMapper (request.entity().getEntity().getClass()); + + String entityJson = mapper.writeValueAsString (request.entity().getEntity()); + entity = new StringEntity(entityJson, ContentType.create(request.entity().getContentType())); + + LOGGER.debug("Openstack query JSON:"+entityJson); + LOGGER.debug ("Request JSON Body: " + entityJson.replaceAll("\"password\":\"[^\"]*\"", "\"password\":\"***\"")); + + } catch (JsonProcessingException e) { + throw new HttpClientException ("Json processing error on request entity", e); + } catch (IOException e) { + throw new HttpClientException ("Json IO error on request entity", e); + } + } + + // Determine the HttpRequest class based on the method + HttpUriRequest httpRequest; + + switch (request.method()) { + case POST: + HttpPost post = new HttpPost(uri); + post.setEntity (entity); + httpRequest = post; + break; + + case GET: + httpRequest = new HttpGet(uri); + break; + + case PUT: + HttpPut put = new HttpPut(uri); + put.setEntity (entity); + httpRequest = put; + break; + + case DELETE: + httpRequest = new HttpDelete(uri); + break; + + default: + throw new HttpClientException ("Unrecognized HTTP Method: " + request.method()); + } + + for (Entry> h : request.headers().entrySet()) { + StringBuilder sb = new StringBuilder(); + for (Object v : h.getValue()) { + sb.append(String.valueOf(v)); + } + httpRequest.addHeader(h.getKey(), sb.toString()); + } + + LOGGER.debug ("Sending HTTP request: " + httpRequest.toString()); + + // Get the Response. But don't get the body entity yet, as this response + // will be wrapped in an HttpClientResponse. The HttpClientResponse + // buffers the body in constructor, so can close the response here. + HttpClientResponse httpClientResponse = null; + CloseableHttpResponse httpResponse = null; + + // Catch known HttpClient exceptions, and wrap them in OpenStack Client Exceptions + // so calling functions can distinguish. Only RuntimeExceptions are allowed. + try { + httpResponse = httpClient.execute(httpRequest); + + LOGGER.debug ("Response status: " + httpResponse.getStatusLine().getStatusCode()); + + httpClientResponse = new HttpClientResponse (httpResponse); + + int status = httpResponse.getStatusLine().getStatusCode(); + if (status == HttpStatus.SC_OK || status == HttpStatus.SC_CREATED || + status == HttpStatus.SC_NO_CONTENT || status == HttpStatus.SC_ACCEPTED) + { + return httpClientResponse; + } + } + catch (HttpResponseException e) { + // What exactly does this mean? It does not appear to get thrown for + // non-2XX responses as documented. + throw new OpenStackResponseException(e.getMessage(), e.getStatusCode()); + } + catch (UnknownHostException e) { + throw new OpenStackConnectException("Unknown Host: " + e.getMessage()); + } + catch (IOException e) { + // Catch all other IOExceptions and throw as OpenStackConnectException + throw new OpenStackConnectException(e.getMessage()); + } + catch (Exception e) { + // Catchall for anything else, must throw as a RuntimeException + LOGGER.error ("Unexpected client exception: " +e.getMessage()); + throw new RuntimeException("Unexpected client exception", e); + } + finally { + // Have the body. Close the stream + if (httpResponse != null) + try { + httpResponse.close(); + } catch (IOException e) { + LOGGER.warn("Unable to close HTTP Response: " + e); + } + } + + // Get here on an error response (4XX-5XX) + throw new OpenStackResponseException(httpResponse.getStatusLine().getReasonPhrase(), + httpResponse.getStatusLine().getStatusCode(), + httpClientResponse); + } } diff --git a/openstack-client-connectors/http-connector/src/main/java/com/woorea/openstack/connector/HttpClientException.java b/openstack-client-connectors/http-connector/src/main/java/com/woorea/openstack/connector/HttpClientException.java index 4c51574..ffb7379 100644 --- a/openstack-client-connectors/http-connector/src/main/java/com/woorea/openstack/connector/HttpClientException.java +++ b/openstack-client-connectors/http-connector/src/main/java/com/woorea/openstack/connector/HttpClientException.java @@ -45,17 +45,17 @@ package com.woorea.openstack.connector; */ public class HttpClientException extends RuntimeException { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - public HttpClientException (String s) { - super (s); - } - - public HttpClientException (Exception e) { - super ("Caught nested exception in HttpClient", e); - } - - public HttpClientException (String s, Exception e) { - super (s, e); - } + public HttpClientException (String s) { + super (s); + } + + public HttpClientException (Exception e) { + super ("Caught nested exception in HttpClient", e); + } + + public HttpClientException (String s, Exception e) { + super (s, e); + } } diff --git a/openstack-client-connectors/http-connector/src/main/java/com/woorea/openstack/connector/HttpClientRedirectStrategy.java b/openstack-client-connectors/http-connector/src/main/java/com/woorea/openstack/connector/HttpClientRedirectStrategy.java index 2ba17fb..f9aedf5 100644 --- a/openstack-client-connectors/http-connector/src/main/java/com/woorea/openstack/connector/HttpClientRedirectStrategy.java +++ b/openstack-client-connectors/http-connector/src/main/java/com/woorea/openstack/connector/HttpClientRedirectStrategy.java @@ -102,7 +102,7 @@ public class HttpClientRedirectStrategy extends DefaultRedirectStrategy { final HttpRequest request, final HttpResponse response, final HttpContext context) throws ProtocolException { - + final URI uri = getLocationURI(request, response, context); final String method = request.getRequestLine().getMethod(); if (method.equalsIgnoreCase(HttpHead.METHOD_NAME)) { @@ -113,13 +113,13 @@ public class HttpClientRedirectStrategy extends DefaultRedirectStrategy { final int status = response.getStatusLine().getStatusCode(); - HttpUriRequest newRequest; - if (status == HttpStatus.SC_TEMPORARY_REDIRECT || status == HttpStatus.SC_MOVED_TEMPORARILY) { + HttpUriRequest newRequest; + if (status == HttpStatus.SC_TEMPORARY_REDIRECT || status == HttpStatus.SC_MOVED_TEMPORARILY) { newRequest = RequestBuilder.copy(request).setUri(uri).build(); } else { newRequest = new HttpGet(uri); } - return newRequest; + return newRequest; } } } diff --git a/openstack-client-connectors/http-connector/src/main/java/com/woorea/openstack/connector/HttpClientResponse.java b/openstack-client-connectors/http-connector/src/main/java/com/woorea/openstack/connector/HttpClientResponse.java index 74df0e6..108861a 100644 --- a/openstack-client-connectors/http-connector/src/main/java/com/woorea/openstack/connector/HttpClientResponse.java +++ b/openstack-client-connectors/http-connector/src/main/java/com/woorea/openstack/connector/HttpClientResponse.java @@ -55,8 +55,8 @@ import java.util.Map; public class HttpClientResponse implements OpenStackResponse { - private static Logger LOGGER = Logger.getLogger(HttpClientConnector.class); - + private static Logger LOGGER = Logger.getLogger(HttpClientConnector.class); + private HttpResponse response = null; private String entityBody = null; @@ -66,34 +66,34 @@ public class HttpClientResponse implements OpenStackResponse { // Read the body so InputStream can be closed if (response.getEntity() == null) { - // No body - LOGGER.debug ("No Response Body"); - return; + // No body + LOGGER.debug ("No Response Body"); + return; } - ByteArrayOutputStream responseBody = new ByteArrayOutputStream(); - try { - response.getEntity().writeTo(responseBody); - } catch (IOException e) { - throw new HttpClientException ("Error Reading Response Body", e); - } - entityBody = responseBody.toString(); - LOGGER.debug (entityBody); + ByteArrayOutputStream responseBody = new ByteArrayOutputStream(); + try { + response.getEntity().writeTo(responseBody); + } catch (IOException e) { + throw new HttpClientException ("Error Reading Response Body", e); + } + entityBody = responseBody.toString(); + LOGGER.debug (entityBody); } @Override - public T getEntity (Class returnType) { - // Get appropriate mapper, based on existence of a root element - ObjectMapper mapper = HttpClientConnector.getObjectMapper (returnType); - - T resp = null; - try { - resp = mapper.readValue(entityBody, returnType); - } catch (Exception e) { - throw new HttpClientException ("Caught exception in getEntity", e); - } - return resp; + public T getEntity (Class returnType) { + // Get appropriate mapper, based on existence of a root element + ObjectMapper mapper = HttpClientConnector.getObjectMapper (returnType); + + T resp = null; + try { + resp = mapper.readValue(entityBody, returnType); + } catch (Exception e) { + throw new HttpClientException ("Caught exception in getEntity", e); + } + return resp; } @Override @@ -103,7 +103,7 @@ public class HttpClientResponse implements OpenStackResponse { @Override public InputStream getInputStream() { - return new ByteArrayInputStream (entityBody.getBytes()); + return new ByteArrayInputStream (entityBody.getBytes()); } @Override diff --git a/openstack-client-connectors/jersey-connector/src/main/java/com/woorea/openstack/connector/JerseyConnector.java b/openstack-client-connectors/jersey-connector/src/main/java/com/woorea/openstack/connector/JerseyConnector.java index eb1b3d5..ea22970 100644 --- a/openstack-client-connectors/jersey-connector/src/main/java/com/woorea/openstack/connector/JerseyConnector.java +++ b/openstack-client-connectors/jersey-connector/src/main/java/com/woorea/openstack/connector/JerseyConnector.java @@ -45,76 +45,76 @@ import com.woorea.openstack.base.client.OpenStackResponse; import com.woorea.openstack.base.client.OpenStackResponseException; public class JerseyConnector implements OpenStackClientConnector { - - protected Client client = null; + + protected Client client = null; protected boolean logPassword; private JerseyLoggingFilter logger = new JerseyLoggingFilter(Logger.getLogger("os")); - public JerseyConnector() { - ClientConfig clientConfig = new DefaultClientConfig(); - clientConfig.getClasses().add(JacksonJaxbJsonProvider.class); - clientConfig.getClasses().add(OpenStackObjectMapper.class); - client = Client.create(clientConfig); - } + public JerseyConnector() { + ClientConfig clientConfig = new DefaultClientConfig(); + clientConfig.getClasses().add(JacksonJaxbJsonProvider.class); + clientConfig.getClasses().add(OpenStackObjectMapper.class); + client = Client.create(clientConfig); + } - @Override - public OpenStackResponse request(OpenStackRequest request) { - WebResource target = client.resource(request.endpoint()).path(request.path()); - for(Map.Entry > entry : request.queryParams().entrySet()) { - for (Object o : entry.getValue()) { - target = target.queryParam(entry.getKey(), String.valueOf(o)); - } - } - target.addFilter(logger); - MultivaluedMap headers = new OutBoundHeaders(); - for(Map.Entry> h : request.headers().entrySet()) { - for(Object v : h.getValue()) { - headers.add(h.getKey(), v); - } - } - if(request.entity() != null && request.entity().getContentType() != null) { - headers.add("Content-Type", request.entity().getContentType()); - } else { - headers.add("Content-Type", "application/json"); - } - try { - ClientResponse response; - if (request.entity() != null && request.entity().getEntity() != null) { - response = target.getHeadHandler().handle(new ClientRequestImpl(target.getURI(), request.method().name(), request.entity().getEntity(), headers)); - } else { - response = target.getHeadHandler().handle(new ClientRequestImpl(target.getURI(), request.method().name(), null, headers)); - } - return new JerseyResponse(response); - } catch (UniformInterfaceException e) { - throw new OpenStackResponseException(e.getResponse().getClientResponseStatus().getReasonPhrase(), e.getResponse().getStatus()); - } - } + @Override + public OpenStackResponse request(OpenStackRequest request) { + WebResource target = client.resource(request.endpoint()).path(request.path()); + for(Map.Entry > entry : request.queryParams().entrySet()) { + for (Object o : entry.getValue()) { + target = target.queryParam(entry.getKey(), String.valueOf(o)); + } + } + target.addFilter(logger); + MultivaluedMap headers = new OutBoundHeaders(); + for(Map.Entry> h : request.headers().entrySet()) { + for(Object v : h.getValue()) { + headers.add(h.getKey(), v); + } + } + if(request.entity() != null && request.entity().getContentType() != null) { + headers.add("Content-Type", request.entity().getContentType()); + } else { + headers.add("Content-Type", "application/json"); + } + try { + ClientResponse response; + if (request.entity() != null && request.entity().getEntity() != null) { + response = target.getHeadHandler().handle(new ClientRequestImpl(target.getURI(), request.method().name(), request.entity().getEntity(), headers)); + } else { + response = target.getHeadHandler().handle(new ClientRequestImpl(target.getURI(), request.method().name(), null, headers)); + } + return new JerseyResponse(response); + } catch (UniformInterfaceException e) { + throw new OpenStackResponseException(e.getResponse().getClientResponseStatus().getReasonPhrase(), e.getResponse().getStatus()); + } + } - @Provider - public static class OpenStackObjectMapper implements ContextResolver { - static ObjectMapper DEFAULT_MAPPER; - static ObjectMapper WRAPPED_MAPPER; - static { - DEFAULT_MAPPER = new ObjectMapper(); - DEFAULT_MAPPER.setSerializationInclusion(Inclusion.NON_NULL); - DEFAULT_MAPPER.enable(SerializationConfig.Feature.INDENT_OUTPUT); - DEFAULT_MAPPER.enable(DeserializationConfig.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY); - DEFAULT_MAPPER.disable(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES); - DEFAULT_MAPPER.enable(DeserializationConfig.Feature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT); + @Provider + public static class OpenStackObjectMapper implements ContextResolver { + static ObjectMapper DEFAULT_MAPPER; + static ObjectMapper WRAPPED_MAPPER; + static { + DEFAULT_MAPPER = new ObjectMapper(); + DEFAULT_MAPPER.setSerializationInclusion(Inclusion.NON_NULL); + DEFAULT_MAPPER.enable(SerializationConfig.Feature.INDENT_OUTPUT); + DEFAULT_MAPPER.enable(DeserializationConfig.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY); + DEFAULT_MAPPER.disable(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES); + DEFAULT_MAPPER.enable(DeserializationConfig.Feature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT); - WRAPPED_MAPPER = new ObjectMapper(); - WRAPPED_MAPPER.setSerializationInclusion(Inclusion.NON_NULL); - WRAPPED_MAPPER.enable(SerializationConfig.Feature.INDENT_OUTPUT); - WRAPPED_MAPPER.enable(SerializationConfig.Feature.WRAP_ROOT_VALUE); - WRAPPED_MAPPER.enable(DeserializationConfig.Feature.UNWRAP_ROOT_VALUE); - WRAPPED_MAPPER.enable(DeserializationConfig.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY); - WRAPPED_MAPPER.disable(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES); - WRAPPED_MAPPER.enable(DeserializationConfig.Feature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT); - } - - @Override - public ObjectMapper getContext(Class type) { - return type.getAnnotation(JsonRootName.class) == null ? DEFAULT_MAPPER : WRAPPED_MAPPER; - } - } + WRAPPED_MAPPER = new ObjectMapper(); + WRAPPED_MAPPER.setSerializationInclusion(Inclusion.NON_NULL); + WRAPPED_MAPPER.enable(SerializationConfig.Feature.INDENT_OUTPUT); + WRAPPED_MAPPER.enable(SerializationConfig.Feature.WRAP_ROOT_VALUE); + WRAPPED_MAPPER.enable(DeserializationConfig.Feature.UNWRAP_ROOT_VALUE); + WRAPPED_MAPPER.enable(DeserializationConfig.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY); + WRAPPED_MAPPER.disable(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES); + WRAPPED_MAPPER.enable(DeserializationConfig.Feature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT); + } + + @Override + public ObjectMapper getContext(Class type) { + return type.getAnnotation(JsonRootName.class) == null ? DEFAULT_MAPPER : WRAPPED_MAPPER; + } + } } diff --git a/openstack-client-connectors/jersey-connector/src/main/java/com/woorea/openstack/connector/JerseyLoggingFilter.java b/openstack-client-connectors/jersey-connector/src/main/java/com/woorea/openstack/connector/JerseyLoggingFilter.java index 6d98005..ffdeb83 100644 --- a/openstack-client-connectors/jersey-connector/src/main/java/com/woorea/openstack/connector/JerseyLoggingFilter.java +++ b/openstack-client-connectors/jersey-connector/src/main/java/com/woorea/openstack/connector/JerseyLoggingFilter.java @@ -8,7 +8,7 @@ * 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 + * 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, @@ -42,184 +42,184 @@ import com.sun.jersey.core.util.ReaderWriter; */ public class JerseyLoggingFilter extends ClientFilter { - private final AtomicLong counter = new AtomicLong(0); - private final Logger logger; - - /** - * Constructor - * @param logger the logger to which the request and response are written. - */ - public JerseyLoggingFilter(Logger logger) { - this.logger = logger; - } - - @Override - public ClientResponse handle(ClientRequest request) throws ClientHandlerException { - long id = counter.incrementAndGet(); - logRequest(id, request); - ClientResponse response = getNext().handle(request); - logResponse(id, response); - return response; - } - - /** - * Logs a request. - * @param id the request id (counter) - * @param request the request - */ - private void logRequest(long id, ClientRequest request) { - StringBuilder builder = new StringBuilder(); - - builder.append(String.valueOf(id)); - builder.append(" * Client out-bound request\n"); - - builder.append(String.valueOf(id)); - builder.append(" > "); - builder.append(request.getMethod()); - builder.append(" "); - builder.append(request.getURI().toASCIIString()); - builder.append("\n"); - - // Request headers - - for (Map.Entry> entry : request.getHeaders().entrySet()) { - String header = entry.getKey(); - List values = entry.getValue(); - - if (values.size() == 1) { - builder.append(String.valueOf(id)); - builder.append(" > "); - builder.append(header); - builder.append(": "); - builder.append(ClientRequest.getHeaderValue(values.get(0))); - builder.append("\n"); - } else { - StringBuilder buf = new StringBuilder(); - boolean first = true; - - for(Object value : values) { - if (first) { - first = false; - } else { - buf.append(","); - } - - buf.append(ClientRequest.getHeaderValue(value)); - } - - builder.append(String.valueOf(id)); - builder.append(" > "); - builder.append(header); - builder.append(": "); - builder.append(buf.toString()); - builder.append("\n"); - } - } - - // Request body - - if (request.getEntity() != null) { - request.setAdapter(new JerseyLoggingAdapter(request.getAdapter(), builder)); - } else { - logger.info(builder.toString()); - } - } - - /** - * Logs a response. - * @param id the request id (counter) - * @param response the response - */ - private void logResponse(long id, ClientResponse response) { - StringBuilder builder = new StringBuilder(); - - builder.append(String.valueOf(id)); - builder.append(" * Client in-bound response\n"); - - builder.append(String.valueOf(id)); - builder.append(" < "); - builder.append(String.valueOf(response.getStatus())); - builder.append("\n"); - - // Response headers - - for (Map.Entry> entry : response.getHeaders().entrySet()) { - String header = entry.getKey(); - for (String value : entry.getValue()) { - builder.append(String.valueOf(id)); - builder.append(" < "); - builder.append(header); - builder.append(": "); - builder.append(value).append("\n"); - } - } - - // Response body - - ByteArrayOutputStream out = new ByteArrayOutputStream(); - InputStream in = response.getEntityInputStream(); - try { - ReaderWriter.writeTo(in, out); - - byte[] requestEntity = out.toByteArray(); - appendToBuffer(builder, requestEntity); - response.setEntityInputStream(new ByteArrayInputStream(requestEntity)); - } catch (IOException ex) { - throw new ClientHandlerException(ex); - } - - logger.info(builder.toString()); - } - - /** - * Appends bytes to the builder. If the bytes contain the password pattern, - * the password is obliterated. - * @param builder the builder - * @param bytes the bytes to append - */ - private void appendToBuffer(StringBuilder builder, byte[] bytes) { - if (bytes.length != 0) { - String s = new String(bytes); - builder.append(s.replaceAll("\"password\".*:.*\"(.*)\"", "\"password\" : \"******\"")); - builder.append("\n"); - } - } - - private class JerseyLoggingAdapter extends AbstractClientRequestAdapter { - private final StringBuilder builder; - - JerseyLoggingAdapter(ClientRequestAdapter adapter, StringBuilder builder) { - super(adapter); - this.builder = builder; - } - - @Override - public OutputStream adapt(ClientRequest request, OutputStream out) throws IOException { - return new JerseyLoggingOutputStream(getAdapter().adapt(request, out), builder); - } - } - - private class JerseyLoggingOutputStream extends OutputStream { - private final OutputStream stream; - private final StringBuilder builder; - private final ByteArrayOutputStream logStream = new ByteArrayOutputStream(); - - JerseyLoggingOutputStream(OutputStream stream, StringBuilder builder) { - this.stream = stream; - this.builder = builder; - } - - @Override - public void write(int value) throws IOException { - logStream.write(value); - stream.write(value); - } - - @Override - public void close() throws IOException { - appendToBuffer(builder, logStream.toByteArray()); - logger.info(builder.toString()); - stream.close(); - } - } + private final AtomicLong counter = new AtomicLong(0); + private final Logger logger; + + /** + * Constructor + * @param logger the logger to which the request and response are written. + */ + public JerseyLoggingFilter(Logger logger) { + this.logger = logger; + } + + @Override + public ClientResponse handle(ClientRequest request) throws ClientHandlerException { + long id = counter.incrementAndGet(); + logRequest(id, request); + ClientResponse response = getNext().handle(request); + logResponse(id, response); + return response; + } + + /** + * Logs a request. + * @param id the request id (counter) + * @param request the request + */ + private void logRequest(long id, ClientRequest request) { + StringBuilder builder = new StringBuilder(); + + builder.append(String.valueOf(id)); + builder.append(" * Client out-bound request\n"); + + builder.append(String.valueOf(id)); + builder.append(" > "); + builder.append(request.getMethod()); + builder.append(" "); + builder.append(request.getURI().toASCIIString()); + builder.append("\n"); + + // Request headers + + for (Map.Entry> entry : request.getHeaders().entrySet()) { + String header = entry.getKey(); + List values = entry.getValue(); + + if (values.size() == 1) { + builder.append(String.valueOf(id)); + builder.append(" > "); + builder.append(header); + builder.append(": "); + builder.append(ClientRequest.getHeaderValue(values.get(0))); + builder.append("\n"); + } else { + StringBuilder buf = new StringBuilder(); + boolean first = true; + + for(Object value : values) { + if (first) { + first = false; + } else { + buf.append(","); + } + + buf.append(ClientRequest.getHeaderValue(value)); + } + + builder.append(String.valueOf(id)); + builder.append(" > "); + builder.append(header); + builder.append(": "); + builder.append(buf.toString()); + builder.append("\n"); + } + } + + // Request body + + if (request.getEntity() != null) { + request.setAdapter(new JerseyLoggingAdapter(request.getAdapter(), builder)); + } else { + logger.info(builder.toString()); + } + } + + /** + * Logs a response. + * @param id the request id (counter) + * @param response the response + */ + private void logResponse(long id, ClientResponse response) { + StringBuilder builder = new StringBuilder(); + + builder.append(String.valueOf(id)); + builder.append(" * Client in-bound response\n"); + + builder.append(String.valueOf(id)); + builder.append(" < "); + builder.append(String.valueOf(response.getStatus())); + builder.append("\n"); + + // Response headers + + for (Map.Entry> entry : response.getHeaders().entrySet()) { + String header = entry.getKey(); + for (String value : entry.getValue()) { + builder.append(String.valueOf(id)); + builder.append(" < "); + builder.append(header); + builder.append(": "); + builder.append(value).append("\n"); + } + } + + // Response body + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + InputStream in = response.getEntityInputStream(); + try { + ReaderWriter.writeTo(in, out); + + byte[] requestEntity = out.toByteArray(); + appendToBuffer(builder, requestEntity); + response.setEntityInputStream(new ByteArrayInputStream(requestEntity)); + } catch (IOException ex) { + throw new ClientHandlerException(ex); + } + + logger.info(builder.toString()); + } + + /** + * Appends bytes to the builder. If the bytes contain the password pattern, + * the password is obliterated. + * @param builder the builder + * @param bytes the bytes to append + */ + private void appendToBuffer(StringBuilder builder, byte[] bytes) { + if (bytes.length != 0) { + String s = new String(bytes); + builder.append(s.replaceAll("\"password\".*:.*\"(.*)\"", "\"password\" : \"******\"")); + builder.append("\n"); + } + } + + private class JerseyLoggingAdapter extends AbstractClientRequestAdapter { + private final StringBuilder builder; + + JerseyLoggingAdapter(ClientRequestAdapter adapter, StringBuilder builder) { + super(adapter); + this.builder = builder; + } + + @Override + public OutputStream adapt(ClientRequest request, OutputStream out) throws IOException { + return new JerseyLoggingOutputStream(getAdapter().adapt(request, out), builder); + } + } + + private class JerseyLoggingOutputStream extends OutputStream { + private final OutputStream stream; + private final StringBuilder builder; + private final ByteArrayOutputStream logStream = new ByteArrayOutputStream(); + + JerseyLoggingOutputStream(OutputStream stream, StringBuilder builder) { + this.stream = stream; + this.builder = builder; + } + + @Override + public void write(int value) throws IOException { + logStream.write(value); + stream.write(value); + } + + @Override + public void close() throws IOException { + appendToBuffer(builder, logStream.toByteArray()); + logger.info(builder.toString()); + stream.close(); + } + } } \ No newline at end of file diff --git a/openstack-client-connectors/jersey-connector/src/main/java/com/woorea/openstack/connector/JerseyResponse.java b/openstack-client-connectors/jersey-connector/src/main/java/com/woorea/openstack/connector/JerseyResponse.java index b6ccd04..5b01660 100644 --- a/openstack-client-connectors/jersey-connector/src/main/java/com/woorea/openstack/connector/JerseyResponse.java +++ b/openstack-client-connectors/jersey-connector/src/main/java/com/woorea/openstack/connector/JerseyResponse.java @@ -30,53 +30,53 @@ import com.woorea.openstack.base.client.OpenStackResponseException; public class JerseyResponse implements OpenStackResponse { - private ClientResponse response; + private ClientResponse response; - public JerseyResponse(ClientResponse response) { - this.response = response; - } + public JerseyResponse(ClientResponse response) { + this.response = response; + } - @Override - public T getEntity(Class returnType) { - if(response.getStatus() >= 400) { - throw new OpenStackResponseException(response.getClientResponseStatus().getReasonPhrase(), - response.getStatus(), this); - } - if(response.hasEntity() && returnType != null && Void.class != returnType) { - return response.getEntity(returnType); - } else { - return null; - } - } + @Override + public T getEntity(Class returnType) { + if(response.getStatus() >= 400) { + throw new OpenStackResponseException(response.getClientResponseStatus().getReasonPhrase(), + response.getStatus(), this); + } + if(response.hasEntity() && returnType != null && Void.class != returnType) { + return response.getEntity(returnType); + } else { + return null; + } + } - @Override - public T getErrorEntity(Class returnType) { - if(response.getStatus() >= 400 && response.hasEntity()) { - return response.getEntity(returnType); - } - return null; - } + @Override + public T getErrorEntity(Class returnType) { + if(response.getStatus() >= 400 && response.hasEntity()) { + return response.getEntity(returnType); + } + return null; + } - @Override - public InputStream getInputStream() { - if(response.hasEntity()) { - return response.getEntityInputStream(); - } else { - return null; - } - } + @Override + public InputStream getInputStream() { + if(response.hasEntity()) { + return response.getEntityInputStream(); + } else { + return null; + } + } - @Override - public String header(String name) { - return response.getHeaders().getFirst(name); - } + @Override + public String header(String name) { + return response.getHeaders().getFirst(name); + } - @Override - public Map headers() { - Map headers = new HashMap<>(); - for(String k : response.getHeaders().keySet()) { - headers.put(k, response.getHeaders().getFirst(k)); - } - return headers; - } + @Override + public Map headers() { + Map headers = new HashMap<>(); + for(String k : response.getHeaders().keySet()) { + headers.put(k, response.getHeaders().getFirst(k)); + } + return headers; + } } diff --git a/openstack-client-connectors/jersey-connector/src/test/java/com/woorea/openstack/connector/JerseyLoggingFilterTest.java b/openstack-client-connectors/jersey-connector/src/test/java/com/woorea/openstack/connector/JerseyLoggingFilterTest.java index 3bd0717..3ebad7c 100644 --- a/openstack-client-connectors/jersey-connector/src/test/java/com/woorea/openstack/connector/JerseyLoggingFilterTest.java +++ b/openstack-client-connectors/jersey-connector/src/test/java/com/woorea/openstack/connector/JerseyLoggingFilterTest.java @@ -56,212 +56,212 @@ import com.sun.jersey.api.client.filter.ClientFilter; public class JerseyLoggingFilterTest { - private static Logger logger; - private static LogFormatter logFormatter; - - @BeforeClass - public static void setUpClass() throws Exception { - logger = Logger.getLogger(JerseyLoggingFilterTest.class.getSimpleName()); - logger.setLevel(Level.ALL); - logger.setUseParentHandlers(false); - - ConsoleHandler handler = new ConsoleHandler(); - logFormatter = new LogFormatter(); - handler.setFormatter(logFormatter); - handler.setLevel(Level.ALL); - logger.addHandler(handler); - } - - @Before - public void setUpTest() { - logFormatter.clearLog(); - } - - /** - * Tests a scenario with no request content (GET). - * @throws Exception for unexpected errors - */ - @Test - public void testGET() throws Exception { - String responseContent = "Hello, I am Eliza."; - execute("GET", "http://www.onap.org/eliza", null, responseContent); - } - - /** - * Tests a scenario with request content (POST). - * @throws Exception for unexpected errors - */ - @Test - public void testPOST() throws Exception { - String requestContent = "I feel sad."; - String responseContent = "Do you often feel sad?"; - execute("POST", "http://www.onap.org/eliza", requestContent, responseContent); - } - - /** - * Runs a single test. - * @param httpMethod any HTTP method (POST, GET, ...) - * @param url any URL - * @param requestContent mock request content, possibly null - * @param responseContent mock response content, never null - * @throws Exception for unexpected errors - */ - private void execute(String httpMethod, String url, String requestContent, String responseContent) - throws Exception { - JerseyLoggingFilter loggingFilter = new JerseyLoggingFilter(logger); - - // Mock multi-valued and single valued request headers - - HashMap> requestHeaderMap = new HashMap<>(); - requestHeaderMap.put("Accept", Arrays.asList(new Object[]{"application/xml","application/json"})); - - if (requestContent != null) { - requestHeaderMap.put("Content-Type", Arrays.asList(new Object[]{"application/xml"})); - requestHeaderMap.put("Content-Length", Arrays.asList(new Object[]{String.valueOf(requestContent.length())})); - } - - @SuppressWarnings("unchecked") - MultivaluedMap requestHeaders = mock(MultivaluedMap.class); - when(requestHeaders.entrySet()).thenReturn(requestHeaderMap.entrySet()); - - // Mock the request object - - ClientRequest request = mock(TestClientRequest.class); - when(request.getURI()).thenReturn(new URI(url)); - when(request.getMethod()).thenReturn(httpMethod); - when(request.getHeaders()).thenReturn(requestHeaders); - - if (requestContent != null) { - when(request.getEntity()).thenReturn(requestContent.getBytes("UTF-8")); - } - - doCallRealMethod().when(request).setAdapter(any(ClientRequestAdapter.class)); - when(request.getAdapter()).thenCallRealMethod(); - request.setAdapter(new DefaultClientRequestAdapter()); - - // Mock multi-valued and single valued response headers - - HashMap> responseHeaderMap = new HashMap<>(); - responseHeaderMap.put("Cache-Control", Arrays.asList(new String[]{"no-cache","no-store"})); - responseHeaderMap.put("Content-Type", Arrays.asList(new String[]{"application/xml"})); - responseHeaderMap.put("Content-Length", Arrays.asList(new String[]{String.valueOf(responseContent.length())})); - @SuppressWarnings("unchecked") - MultivaluedMap responseHeaders = mock(MultivaluedMap.class); - when(responseHeaders.entrySet()).thenReturn(responseHeaderMap.entrySet()); - - // Mock the response object - - ClientResponse response = mock(ClientResponse.class); - when(response.getStatus()).thenReturn(200); - when(response.getHeaders()).thenReturn(responseHeaders); - when(response.getEntityInputStream()).thenReturn( - new ByteArrayInputStream(responseContent.getBytes("UTF-8"))); - - // Mock a handler that returns the response object and set - // it to be the next filter after the logging filter. - - ClientFilter handler = mock(ClientFilter.class); - when(handler.handle(request)).then(produceResponse(response)); - Method setNext = ClientFilter.class.getDeclaredMethod("setNext", new Class[]{ClientHandler.class}); - setNext.setAccessible(true); - setNext.invoke(loggingFilter, new Object[]{handler}); - - // Run the request into the logging filter - - loggingFilter.handle(request); - - // Validate resulting the log content - - String log = logFormatter.getLog(); - - assertContains(log, "* Client out-bound request"); - assertContains(log, "> " + httpMethod + " " + url); - - for (String header : requestHeaderMap.keySet()) { - assertContains(log, "> " + header + ": "); - } - - if (requestContent != null) { - assertContains(log, requestContent); - } - - assertContains(log, "* Client in-bound response"); - assertContains(log, "< 200"); - - for (String header : responseHeaderMap.keySet()) { - assertContains(log, "< " + header + ": "); - } - - assertContains(log, responseContent); - } - - private void assertContains(String log, String expect) { - assertTrue("Log does not contain '" + expect + "'", log.contains(expect)); - } - - private class DefaultClientRequestAdapter implements ClientRequestAdapter { - @Override - public OutputStream adapt(ClientRequest request, OutputStream out) throws IOException { - return out; - } - } - - private abstract class TestClientRequest extends ClientRequest { - private ClientRequestAdapter adapter; - - @Override - public ClientRequestAdapter getAdapter() { - return adapter; - } - - @Override - public void setAdapter(ClientRequestAdapter adapter) { - this.adapter = adapter; - } - } - - private Answer produceResponse(final ClientResponse response) { - return new Answer() { - public ClientResponse answer(InvocationOnMock invocation) throws IOException { - ClientRequest request = (ClientRequest) invocation.getArguments()[0]; - byte[] entity = (byte[]) request.getEntity(); - - if (entity != null) { - ClientRequestAdapter adapter = request.getAdapter(); - - OutputStream nullOutputStream = new OutputStream() { - @Override - public void write(int b) { - // Discard - } - }; - - OutputStream outputStream = adapter.adapt(request, nullOutputStream); - outputStream.write(entity); - outputStream.close(); - } - - return response; - } - }; - } - - private static class LogFormatter extends SimpleFormatter { - StringBuilder buffer = new StringBuilder(); - - public synchronized String getLog() { - return buffer.toString(); - } - - public synchronized void clearLog() { - buffer.setLength(0); - } - - @Override - public synchronized String format(LogRecord record) { - String logData = super.format(record); - buffer.append(logData); - return logData; - } - } + private static Logger logger; + private static LogFormatter logFormatter; + + @BeforeClass + public static void setUpClass() throws Exception { + logger = Logger.getLogger(JerseyLoggingFilterTest.class.getSimpleName()); + logger.setLevel(Level.ALL); + logger.setUseParentHandlers(false); + + ConsoleHandler handler = new ConsoleHandler(); + logFormatter = new LogFormatter(); + handler.setFormatter(logFormatter); + handler.setLevel(Level.ALL); + logger.addHandler(handler); + } + + @Before + public void setUpTest() { + logFormatter.clearLog(); + } + + /** + * Tests a scenario with no request content (GET). + * @throws Exception for unexpected errors + */ + @Test + public void testGET() throws Exception { + String responseContent = "Hello, I am Eliza."; + execute("GET", "http://www.onap.org/eliza", null, responseContent); + } + + /** + * Tests a scenario with request content (POST). + * @throws Exception for unexpected errors + */ + @Test + public void testPOST() throws Exception { + String requestContent = "I feel sad."; + String responseContent = "Do you often feel sad?"; + execute("POST", "http://www.onap.org/eliza", requestContent, responseContent); + } + + /** + * Runs a single test. + * @param httpMethod any HTTP method (POST, GET, ...) + * @param url any URL + * @param requestContent mock request content, possibly null + * @param responseContent mock response content, never null + * @throws Exception for unexpected errors + */ + private void execute(String httpMethod, String url, String requestContent, String responseContent) + throws Exception { + JerseyLoggingFilter loggingFilter = new JerseyLoggingFilter(logger); + + // Mock multi-valued and single valued request headers + + HashMap> requestHeaderMap = new HashMap<>(); + requestHeaderMap.put("Accept", Arrays.asList(new Object[]{"application/xml","application/json"})); + + if (requestContent != null) { + requestHeaderMap.put("Content-Type", Arrays.asList(new Object[]{"application/xml"})); + requestHeaderMap.put("Content-Length", Arrays.asList(new Object[]{String.valueOf(requestContent.length())})); + } + + @SuppressWarnings("unchecked") + MultivaluedMap requestHeaders = mock(MultivaluedMap.class); + when(requestHeaders.entrySet()).thenReturn(requestHeaderMap.entrySet()); + + // Mock the request object + + ClientRequest request = mock(TestClientRequest.class); + when(request.getURI()).thenReturn(new URI(url)); + when(request.getMethod()).thenReturn(httpMethod); + when(request.getHeaders()).thenReturn(requestHeaders); + + if (requestContent != null) { + when(request.getEntity()).thenReturn(requestContent.getBytes("UTF-8")); + } + + doCallRealMethod().when(request).setAdapter(any(ClientRequestAdapter.class)); + when(request.getAdapter()).thenCallRealMethod(); + request.setAdapter(new DefaultClientRequestAdapter()); + + // Mock multi-valued and single valued response headers + + HashMap> responseHeaderMap = new HashMap<>(); + responseHeaderMap.put("Cache-Control", Arrays.asList(new String[]{"no-cache","no-store"})); + responseHeaderMap.put("Content-Type", Arrays.asList(new String[]{"application/xml"})); + responseHeaderMap.put("Content-Length", Arrays.asList(new String[]{String.valueOf(responseContent.length())})); + @SuppressWarnings("unchecked") + MultivaluedMap responseHeaders = mock(MultivaluedMap.class); + when(responseHeaders.entrySet()).thenReturn(responseHeaderMap.entrySet()); + + // Mock the response object + + ClientResponse response = mock(ClientResponse.class); + when(response.getStatus()).thenReturn(200); + when(response.getHeaders()).thenReturn(responseHeaders); + when(response.getEntityInputStream()).thenReturn( + new ByteArrayInputStream(responseContent.getBytes("UTF-8"))); + + // Mock a handler that returns the response object and set + // it to be the next filter after the logging filter. + + ClientFilter handler = mock(ClientFilter.class); + when(handler.handle(request)).then(produceResponse(response)); + Method setNext = ClientFilter.class.getDeclaredMethod("setNext", new Class[]{ClientHandler.class}); + setNext.setAccessible(true); + setNext.invoke(loggingFilter, new Object[]{handler}); + + // Run the request into the logging filter + + loggingFilter.handle(request); + + // Validate resulting the log content + + String log = logFormatter.getLog(); + + assertContains(log, "* Client out-bound request"); + assertContains(log, "> " + httpMethod + " " + url); + + for (String header : requestHeaderMap.keySet()) { + assertContains(log, "> " + header + ": "); + } + + if (requestContent != null) { + assertContains(log, requestContent); + } + + assertContains(log, "* Client in-bound response"); + assertContains(log, "< 200"); + + for (String header : responseHeaderMap.keySet()) { + assertContains(log, "< " + header + ": "); + } + + assertContains(log, responseContent); + } + + private void assertContains(String log, String expect) { + assertTrue("Log does not contain '" + expect + "'", log.contains(expect)); + } + + private class DefaultClientRequestAdapter implements ClientRequestAdapter { + @Override + public OutputStream adapt(ClientRequest request, OutputStream out) throws IOException { + return out; + } + } + + private abstract class TestClientRequest extends ClientRequest { + private ClientRequestAdapter adapter; + + @Override + public ClientRequestAdapter getAdapter() { + return adapter; + } + + @Override + public void setAdapter(ClientRequestAdapter adapter) { + this.adapter = adapter; + } + } + + private Answer produceResponse(final ClientResponse response) { + return new Answer() { + public ClientResponse answer(InvocationOnMock invocation) throws IOException { + ClientRequest request = (ClientRequest) invocation.getArguments()[0]; + byte[] entity = (byte[]) request.getEntity(); + + if (entity != null) { + ClientRequestAdapter adapter = request.getAdapter(); + + OutputStream nullOutputStream = new OutputStream() { + @Override + public void write(int b) { + // Discard + } + }; + + OutputStream outputStream = adapter.adapt(request, nullOutputStream); + outputStream.write(entity); + outputStream.close(); + } + + return response; + } + }; + } + + private static class LogFormatter extends SimpleFormatter { + StringBuilder buffer = new StringBuilder(); + + public synchronized String getLog() { + return buffer.toString(); + } + + public synchronized void clearLog() { + buffer.setLength(0); + } + + @Override + public synchronized String format(LogRecord record) { + String logData = super.format(record); + buffer.append(logData); + return logData; + } + } } \ No newline at end of file diff --git a/openstack-client-connectors/jersey2-connector/src/main/java/com/woorea/openstack/connector/JaxRs20Connector.java b/openstack-client-connectors/jersey2-connector/src/main/java/com/woorea/openstack/connector/JaxRs20Connector.java index d18a64f..b1b528f 100644 --- a/openstack-client-connectors/jersey2-connector/src/main/java/com/woorea/openstack/connector/JaxRs20Connector.java +++ b/openstack-client-connectors/jersey2-connector/src/main/java/com/woorea/openstack/connector/JaxRs20Connector.java @@ -37,45 +37,45 @@ import com.woorea.openstack.base.client.OpenStackResponseException; public class JaxRs20Connector implements OpenStackClientConnector { - protected Client client = OpenStack.CLIENT; + protected Client client = OpenStack.CLIENT; private LoggingFilter logger = new LoggingFilter(Logger.getLogger("os"), 10000); - @Override - public OpenStackResponse request(OpenStackRequest request) { - WebTarget target = client.target(request.endpoint()).path(request.path()); + @Override + public OpenStackResponse request(OpenStackRequest request) { + WebTarget target = client.target(request.endpoint()).path(request.path()); - for(Map.Entry > entry : request.queryParams().entrySet()) { - for (Object o : entry.getValue()) { - target = target.queryParam(entry.getKey(), o); - } - } + for(Map.Entry > entry : request.queryParams().entrySet()) { + for (Object o : entry.getValue()) { + target = target.queryParam(entry.getKey(), o); + } + } target.register(logger); - Invocation.Builder invocation = target.request(); + Invocation.Builder invocation = target.request(); - for(Map.Entry> h : request.headers().entrySet()) { - StringBuilder sb = new StringBuilder(); - for(Object v : h.getValue()) { - sb.append(String.valueOf(v)); - } - invocation.header(h.getKey(), sb); - } + for(Map.Entry> h : request.headers().entrySet()) { + StringBuilder sb = new StringBuilder(); + for(Object v : h.getValue()) { + sb.append(String.valueOf(v)); + } + invocation.header(h.getKey(), sb); + } - Entity entity = (request.entity() == null) ? null : - Entity.entity(request.entity().getEntity(), request.entity().getContentType()); + Entity entity = (request.entity() == null) ? null : + Entity.entity(request.entity().getEntity(), request.entity().getContentType()); - try { - if (entity != null) { - return new JaxRs20Response(invocation.method(request.method().name(), entity)); - } else { - if(HttpMethod.PUT == request.method()) { - return new JaxRs20Response(invocation.method(request.method().name(), Entity.entity("", MediaType.APPLICATION_JSON))); - } else { - return new JaxRs20Response(invocation.method(request.method().name())); - } - } - } catch (ClientErrorException e) { - throw new OpenStackResponseException(e.getResponse() - .getStatusInfo().toString(), e.getResponse().getStatus()); - } - } + try { + if (entity != null) { + return new JaxRs20Response(invocation.method(request.method().name(), entity)); + } else { + if(HttpMethod.PUT == request.method()) { + return new JaxRs20Response(invocation.method(request.method().name(), Entity.entity("", MediaType.APPLICATION_JSON))); + } else { + return new JaxRs20Response(invocation.method(request.method().name())); + } + } + } catch (ClientErrorException e) { + throw new OpenStackResponseException(e.getResponse() + .getStatusInfo().toString(), e.getResponse().getStatus()); + } + } } diff --git a/openstack-client-connectors/jersey2-connector/src/main/java/com/woorea/openstack/connector/JaxRs20Response.java b/openstack-client-connectors/jersey2-connector/src/main/java/com/woorea/openstack/connector/JaxRs20Response.java index b51c833..2b1820e 100644 --- a/openstack-client-connectors/jersey2-connector/src/main/java/com/woorea/openstack/connector/JaxRs20Response.java +++ b/openstack-client-connectors/jersey2-connector/src/main/java/com/woorea/openstack/connector/JaxRs20Response.java @@ -30,48 +30,48 @@ import com.woorea.openstack.base.client.OpenStackResponse; import com.woorea.openstack.base.client.OpenStackResponseException; public class JaxRs20Response implements OpenStackResponse { - - private Response response; - - public JaxRs20Response(Response response) { - this.response = response; - } + + private Response response; + + public JaxRs20Response(Response response) { + this.response = response; + } - @Override - public T getEntity(Class returnType) { - if(response.getStatus() >= 400) { - throw new OpenStackResponseException(response.getStatusInfo().getReasonPhrase(), - response.getStatusInfo().getStatusCode(), this); - } - return response.readEntity(returnType); - } + @Override + public T getEntity(Class returnType) { + if(response.getStatus() >= 400) { + throw new OpenStackResponseException(response.getStatusInfo().getReasonPhrase(), + response.getStatusInfo().getStatusCode(), this); + } + return response.readEntity(returnType); + } - @Override - public T getErrorEntity(Class returnType) { - if(response.getStatus() >= 400 && response.hasEntity()) { - return response.readEntity(returnType); - } - return null; - } - + @Override + public T getErrorEntity(Class returnType) { + if(response.getStatus() >= 400 && response.hasEntity()) { + return response.readEntity(returnType); + } + return null; + } + - @Override - public InputStream getInputStream() { - return (InputStream) response.getEntity(); - } + @Override + public InputStream getInputStream() { + return (InputStream) response.getEntity(); + } - @Override - public String header(String name) { - return response.getHeaderString(name); - } + @Override + public String header(String name) { + return response.getHeaderString(name); + } - @Override - public Map headers() { - Map headers = new HashMap<>(); - for(String k : response.getHeaders().keySet()) { - headers.put(k, response.getHeaderString(k)); - } - return headers; - } + @Override + public Map headers() { + Map headers = new HashMap<>(); + for(String k : response.getHeaders().keySet()) { + headers.put(k, response.getHeaderString(k)); + } + return headers; + } } -- cgit 1.2.3-korg