summaryrefslogtreecommitdiffstats
path: root/openstack-client-connectors/jersey-connector/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'openstack-client-connectors/jersey-connector/src/main')
-rw-r--r--openstack-client-connectors/jersey-connector/src/main/java/com/woorea/openstack/connector/JerseyConnector.java104
-rw-r--r--openstack-client-connectors/jersey-connector/src/main/java/com/woorea/openstack/connector/JerseyLoggingFilter.java279
-rw-r--r--openstack-client-connectors/jersey-connector/src/main/java/com/woorea/openstack/connector/JerseyResponse.java66
-rw-r--r--openstack-client-connectors/jersey-connector/src/main/resources/META-INF/services/com.woorea.openstack.base.client.OpenStackClientConnector1
4 files changed, 450 insertions, 0 deletions
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
new file mode 100644
index 0000000..afd7a2b
--- /dev/null
+++ b/openstack-client-connectors/jersey-connector/src/main/java/com/woorea/openstack/connector/JerseyConnector.java
@@ -0,0 +1,104 @@
+package com.woorea.openstack.connector;
+
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Logger;
+
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.ContextResolver;
+import javax.ws.rs.ext.Provider;
+
+import org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider;
+import org.codehaus.jackson.map.DeserializationConfig;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.map.SerializationConfig;
+import org.codehaus.jackson.map.annotate.JsonRootName;
+import org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion;
+
+import com.sun.jersey.api.client.Client;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.UniformInterfaceException;
+import com.sun.jersey.api.client.WebResource;
+import com.sun.jersey.api.client.config.ClientConfig;
+import com.sun.jersey.api.client.config.DefaultClientConfig;
+import com.sun.jersey.client.impl.ClientRequestImpl;
+import com.sun.jersey.core.header.OutBoundHeaders;
+import com.woorea.openstack.base.client.OpenStackClientConnector;
+import com.woorea.openstack.base.client.OpenStackRequest;
+import com.woorea.openstack.base.client.OpenStackResponse;
+import com.woorea.openstack.base.client.OpenStackResponseException;
+
+public class JerseyConnector implements OpenStackClientConnector {
+
+ 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);
+ }
+
+ @Override
+ public <T> OpenStackResponse request(OpenStackRequest<T> request) {
+ WebResource target = client.resource(request.endpoint()).path(request.path());
+ for(Map.Entry<String, List<Object> > entry : request.queryParams().entrySet()) {
+ for (Object o : entry.getValue()) {
+ target = target.queryParam(entry.getKey(), String.valueOf(o));
+ }
+ }
+ target.addFilter(logger);
+ MultivaluedMap<String, Object> headers = new OutBoundHeaders();
+ for(Map.Entry<String, List<Object>> 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 = null;
+ 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<ObjectMapper> {
+ 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;
+ }
+ }
+}
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
new file mode 100644
index 0000000..c1877c3
--- /dev/null
+++ b/openstack-client-connectors/jersey-connector/src/main/java/com/woorea/openstack/connector/JerseyLoggingFilter.java
@@ -0,0 +1,279 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright (c) 2010-2011 Oracle and/or its affiliates. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common Development
+ * and Distribution License("CDDL") (collectively, the "License"). You
+ * may not use this file except in compliance with the License. You can
+ * obtain a copy of the License at
+ * http://glassfish.java.net/public/CDDL+GPL_1_1.html
+ * or packager/legal/LICENSE.txt. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ * When distributing the software, include this License Header Notice in each
+ * file and include the License file at packager/legal/LICENSE.txt.
+ *
+ * GPL Classpath Exception:
+ * Oracle designates this particular file as subject to the "Classpath"
+ * exception as provided by Oracle in the GPL Version 2 section of the License
+ * file that accompanied this code.
+ *
+ * Modifications:
+ * If applicable, add the following below the License Header, with the fields
+ * enclosed by brackets [] replaced by your own identifying information:
+ * "Portions Copyright [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ * If you wish your version of this file to be governed by only the CDDL or
+ * only the GPL Version 2, indicate your decision by adding "[Contributor]
+ * elects to include this software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice of license, a
+ * recipient has the option to distribute your version of this file under
+ * either the CDDL, the GPL Version 2 or to extend the choice of license to
+ * its licensees as provided above. However, if you add GPL Version 2 code
+ * and therefore, elected the GPL Version 2 license, then the option applies
+ * only if the new code is made subject to such option by the copyright
+ * holder.
+ */
+package com.woorea.openstack.connector;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Logger;
+
+import javax.ws.rs.core.MultivaluedMap;
+
+import com.sun.jersey.api.client.AbstractClientRequestAdapter;
+import com.sun.jersey.api.client.ClientHandlerException;
+import com.sun.jersey.api.client.ClientRequest;
+import com.sun.jersey.api.client.ClientRequestAdapter;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.filter.ClientFilter;
+import com.sun.jersey.api.client.filter.LoggingFilter;
+import com.sun.jersey.core.util.ReaderWriter;
+
+/**
+ * A logging filter.
+ *
+ */
+public class JerseyLoggingFilter extends ClientFilter {
+
+ private static final Logger LOGGER = Logger.getLogger(LoggingFilter.class.getName());
+
+ private static final String NOTIFICATION_PREFIX = "* ";
+
+ private static final String REQUEST_PREFIX = "> ";
+
+ private static final String RESPONSE_PREFIX = "< ";
+
+ private static final String PASSWORD_PATTERN = "\"password\".*:.*\"(.*)\"";
+
+ private final class Adapter extends AbstractClientRequestAdapter {
+ private final StringBuilder b;
+
+ Adapter(ClientRequestAdapter cra, StringBuilder b) {
+ super(cra);
+ this.b = b;
+ }
+
+ public OutputStream adapt(ClientRequest request, OutputStream out) throws IOException {
+ return new LoggingOutputStream(getAdapter().adapt(request, out), b);
+ }
+
+ }
+
+ private final class LoggingOutputStream extends OutputStream {
+ private final OutputStream out;
+
+ private final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ private final StringBuilder b;
+
+ LoggingOutputStream(OutputStream out, StringBuilder b) {
+ this.out = out;
+ this.b = b;
+ }
+
+ @Override
+ public void write(byte[] b) throws IOException {
+ baos.write(b);
+ out.write(b);
+ }
+
+ @Override
+ public void write(byte[] b, int off, int len) throws IOException {
+ baos.write(b, off, len);
+ out.write(b, off, len);
+ }
+
+ @Override
+ public void write(int b) throws IOException {
+ baos.write(b);
+ out.write(b);
+ }
+
+ @Override
+ public void close() throws IOException {
+ printEntity(b, baos.toByteArray());
+ log(b);
+ out.close();
+ }
+ }
+
+ private final PrintStream loggingStream;
+
+ private final Logger logger;
+
+ private long _id = 0;
+
+ /**
+ * Create a logging filter logging the request and response to
+ * a default JDK logger, named as the fully qualified class name of this
+ * class.
+ */
+ public JerseyLoggingFilter() {
+ this(LOGGER);
+ }
+
+ /**
+ * Create a logging filter logging the request and response to
+ * a JDK logger.
+ *
+ * @param logger the logger to log requests and responses.
+ */
+ public JerseyLoggingFilter(Logger logger) {
+ this.loggingStream = null;
+ this.logger = logger;
+ }
+
+ /**
+ * Create a logging filter logging the request and response to
+ * print stream.
+ *
+ * @param loggingStream the print stream to log requests and responses.
+ */
+ public JerseyLoggingFilter(PrintStream loggingStream) {
+ this.loggingStream = loggingStream;
+ this.logger = null;
+ }
+
+ private void log(StringBuilder b) {
+ if (logger != null) {
+ logger.info(b.toString());
+ } else {
+ loggingStream.print(b);
+ }
+ }
+
+ private StringBuilder prefixId(StringBuilder b, long id) {
+ b.append(Long.toString(id)).append(" ");
+ return b;
+ }
+
+ @Override
+ public ClientResponse handle(ClientRequest request) throws ClientHandlerException {
+ long id = ++this._id;
+
+ logRequest(id, request);
+
+ ClientResponse response = getNext().handle(request);
+
+ logResponse(id, response);
+
+ return response;
+ }
+
+ private void logRequest(long id, ClientRequest request) {
+ StringBuilder b = new StringBuilder();
+
+ printRequestLine(b, id, request);
+ printRequestHeaders(b, id, request.getHeaders());
+
+ if (request.getEntity() != null) {
+ request.setAdapter(new Adapter(request.getAdapter(), b));
+ } else {
+ log(b);
+ }
+ }
+
+ private void printRequestLine(StringBuilder b, long id, ClientRequest request) {
+ prefixId(b, id).append(NOTIFICATION_PREFIX).append("Client out-bound request").append("\n");
+ prefixId(b, id).append(REQUEST_PREFIX).append(request.getMethod()).append(" ").
+ append(request.getURI().toASCIIString()).append("\n");
+ }
+
+ private void printRequestHeaders(StringBuilder b, long id, MultivaluedMap<String, Object> headers) {
+ for (Map.Entry<String, List<Object>> e : headers.entrySet()) {
+ List<Object> val = e.getValue();
+ String header = e.getKey();
+
+ if(val.size() == 1) {
+ prefixId(b, id).append(REQUEST_PREFIX).append(header).append(": ").append(ClientRequest.getHeaderValue(val.get(0))).append("\n");
+ } else {
+ StringBuilder sb = new StringBuilder();
+ boolean add = false;
+ for(Object o : val) {
+ if(add) sb.append(',');
+ add = true;
+ sb.append(ClientRequest.getHeaderValue(o));
+ }
+ prefixId(b, id).append(REQUEST_PREFIX).append(header).append(": ").append(sb.toString()).append("\n");
+ }
+ }
+ }
+
+ private void logResponse(long id, ClientResponse response) {
+ StringBuilder b = new StringBuilder();
+
+ printResponseLine(b, id, response);
+ printResponseHeaders(b, id, response.getHeaders());
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ InputStream in = response.getEntityInputStream();
+ try {
+ ReaderWriter.writeTo(in, out);
+
+ byte[] requestEntity = out.toByteArray();
+ printEntity(b, requestEntity);
+ response.setEntityInputStream(new ByteArrayInputStream(requestEntity));
+ } catch (IOException ex) {
+ throw new ClientHandlerException(ex);
+ }
+ log(b);
+ }
+
+ private void printResponseLine(StringBuilder b, long id, ClientResponse response) {
+ prefixId(b, id).append(NOTIFICATION_PREFIX).
+ append("Client in-bound response").append("\n");
+ prefixId(b, id).append(RESPONSE_PREFIX).
+ append(Integer.toString(response.getStatus())).
+ append("\n");
+ }
+
+ private void printResponseHeaders(StringBuilder b, long id, MultivaluedMap<String, String> headers) {
+ for (Map.Entry<String, List<String>> e : headers.entrySet()) {
+ String header = e.getKey();
+ for (String value : e.getValue()) {
+ prefixId(b, id).append(RESPONSE_PREFIX).append(header).append(": ").
+ append(value).append("\n");
+ }
+ }
+ prefixId(b, id).append(RESPONSE_PREFIX).append("\n");
+ }
+
+ private void printEntity(StringBuilder b, byte[] entity) throws IOException {
+ if (entity.length == 0)
+ return;
+ String entityString = new String(entity);
+ entityString = entityString.replaceAll(PASSWORD_PATTERN, "\"password\" : \"******\"");
+ b.append(entityString).append("\n");
+ }
+} \ 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
new file mode 100644
index 0000000..5e8dc8c
--- /dev/null
+++ b/openstack-client-connectors/jersey-connector/src/main/java/com/woorea/openstack/connector/JerseyResponse.java
@@ -0,0 +1,66 @@
+package com.woorea.openstack.connector;
+
+/*
+ * Modifications copyright (c) 2017 AT&T Intellectual Property
+ */
+
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.sun.jersey.api.client.ClientResponse;
+import com.woorea.openstack.base.client.OpenStackResponse;
+import com.woorea.openstack.base.client.OpenStackResponseException;
+
+public class JerseyResponse implements OpenStackResponse {
+
+ private ClientResponse response;
+
+ public JerseyResponse(ClientResponse response) {
+ this.response = response;
+ }
+
+ @Override
+ public <T> T getEntity(Class<T> 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> T getErrorEntity(Class<T> 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 String header(String name) {
+ return response.getHeaders().getFirst(name);
+ }
+
+ @Override
+ public Map<String, String> headers() {
+ Map<String, String> headers = new HashMap<String, String>();
+ for(String k : response.getHeaders().keySet()) {
+ headers.put(k, response.getHeaders().getFirst(k));
+ }
+ return headers;
+ }
+}
diff --git a/openstack-client-connectors/jersey-connector/src/main/resources/META-INF/services/com.woorea.openstack.base.client.OpenStackClientConnector b/openstack-client-connectors/jersey-connector/src/main/resources/META-INF/services/com.woorea.openstack.base.client.OpenStackClientConnector
new file mode 100644
index 0000000..5b9a158
--- /dev/null
+++ b/openstack-client-connectors/jersey-connector/src/main/resources/META-INF/services/com.woorea.openstack.base.client.OpenStackClientConnector
@@ -0,0 +1 @@
+com.woorea.openstack.connector.JerseyConnector \ No newline at end of file