summaryrefslogtreecommitdiffstats
path: root/openstack-client-connectors
diff options
context:
space:
mode:
Diffstat (limited to 'openstack-client-connectors')
-rw-r--r--openstack-client-connectors/http-connector/pom.xml31
-rw-r--r--openstack-client-connectors/http-connector/src/main/java/com/woorea/openstack/connector/HttpClientConnector.java227
-rw-r--r--openstack-client-connectors/http-connector/src/main/java/com/woorea/openstack/connector/HttpClientException.java45
-rw-r--r--openstack-client-connectors/http-connector/src/main/java/com/woorea/openstack/connector/HttpClientRedirectStrategy.java109
-rw-r--r--openstack-client-connectors/http-connector/src/main/java/com/woorea/openstack/connector/HttpClientResponse.java110
-rw-r--r--openstack-client-connectors/http-connector/src/main/resources/META-INF/services/com.woorea.openstack.base.client.OpenStackClientConnector1
-rw-r--r--openstack-client-connectors/jersey-connector/pom.xml25
-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
-rw-r--r--openstack-client-connectors/jersey2-connector/pom.xml35
-rw-r--r--openstack-client-connectors/jersey2-connector/src/main/java/com/woorea/openstack/connector/JaxRs20Connector.java65
-rw-r--r--openstack-client-connectors/jersey2-connector/src/main/java/com/woorea/openstack/connector/JaxRs20Response.java61
-rw-r--r--openstack-client-connectors/jersey2-connector/src/main/java/com/woorea/openstack/connector/OpenStack.java110
-rw-r--r--openstack-client-connectors/jersey2-connector/src/main/resources/META-INF/services/com.woorea.openstack.base.client.OpenStackClientConnector1
-rw-r--r--openstack-client-connectors/pom.xml60
-rw-r--r--openstack-client-connectors/resteasy-connector/pom.xml30
-rw-r--r--openstack-client-connectors/resteasy-connector/src/main/java/com/woorea/openstack/connector/RESTEasyConnector.java125
-rw-r--r--openstack-client-connectors/resteasy-connector/src/main/java/com/woorea/openstack/connector/RESTEasyInputStream.java37
-rw-r--r--openstack-client-connectors/resteasy-connector/src/main/java/com/woorea/openstack/connector/RESTEasyResponse.java59
-rw-r--r--openstack-client-connectors/resteasy-connector/src/main/resources/META-INF/services/com.woorea.openstack.base.client.OpenStackClientConnector1
22 files changed, 1582 insertions, 0 deletions
diff --git a/openstack-client-connectors/http-connector/pom.xml b/openstack-client-connectors/http-connector/pom.xml
new file mode 100644
index 0000000..375f579
--- /dev/null
+++ b/openstack-client-connectors/http-connector/pom.xml
@@ -0,0 +1,31 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.openecomp.mso.libs.openstack-java-sdk</groupId>
+ <artifactId>client-connectors</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+ </parent>
+
+ <groupId>org.openecomp.mso.libs.openstack-java-sdk.client-connectors</groupId>
+ <artifactId>http-connector</artifactId>
+ <name>OpenStack HTTP-Client Connector</name>
+ <description>OpenStack HTTP-Client Connector</description>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ <version>4.3.5</version>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.jackson</groupId>
+ <artifactId>jackson-mapper-asl</artifactId>
+ <version>1.9.13</version>
+ </dependency>
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ <version>1.2.17</version>
+ </dependency>
+ </dependencies>
+
+</project> \ No newline at end of file
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
new file mode 100644
index 0000000..d748a79
--- /dev/null
+++ b/openstack-client-connectors/http-connector/src/main/java/com/woorea/openstack/connector/HttpClientConnector.java
@@ -0,0 +1,227 @@
+/*
+ * ============LICENSE_START==========================================
+ * ===================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ *
+ * ECOMP and OpenECOMP are trademarks
+ * and service marks of AT&T Intellectual Property.
+ *
+ */
+
+package com.woorea.openstack.connector;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.UnknownHostException;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpStatus;
+import org.apache.http.client.HttpResponseException;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpDelete;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.methods.HttpPut;
+import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.client.utils.URIBuilder;
+import org.apache.http.entity.ContentType;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.log4j.Logger;
+import org.codehaus.jackson.JsonProcessingException;
+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.woorea.openstack.base.client.OpenStackClientConnector;
+import com.woorea.openstack.base.client.OpenStackConnectException;
+import com.woorea.openstack.base.client.OpenStackRequest;
+import com.woorea.openstack.base.client.OpenStackResponse;
+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 <T> ObjectMapper getObjectMapper (Class<T> type) {
+ return type.getAnnotation(JsonRootName.class) == null ? DEFAULT_MAPPER : WRAPPED_MAPPER;
+ }
+
+ public <T> OpenStackResponse request(OpenStackRequest<T> 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<String, List<Object> > 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()));
+
+ System.out.println("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<String, List<Object>> 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
+ e.printStackTrace();
+ 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
new file mode 100644
index 0000000..9f93455
--- /dev/null
+++ b/openstack-client-connectors/http-connector/src/main/java/com/woorea/openstack/connector/HttpClientException.java
@@ -0,0 +1,45 @@
+/*
+ * ============LICENSE_START==========================================
+ * ===================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ *
+ * ECOMP and OpenECOMP are trademarks
+ * and service marks of AT&T Intellectual Property.
+ *
+ */
+
+package com.woorea.openstack.connector;
+
+/*
+ * Declare a RuntimeException since the Interface does not declare any
+ * throwables. Any caught exception will be wrapped in HttpClientException
+ */
+public class HttpClientException extends RuntimeException {
+
+ 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);
+ }
+}
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
new file mode 100644
index 0000000..88f20bb
--- /dev/null
+++ b/openstack-client-connectors/http-connector/src/main/java/com/woorea/openstack/connector/HttpClientRedirectStrategy.java
@@ -0,0 +1,109 @@
+/*
+ * ============LICENSE_START==========================================
+ * ===================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ *
+ * ECOMP and OpenECOMP are trademarks
+ * and service marks of AT&T Intellectual Property.
+ *
+ */
+
+package com.woorea.openstack.connector;
+
+import java.net.URI;
+
+import org.apache.http.HttpRequest;
+import org.apache.http.HttpResponse;
+import org.apache.http.HttpStatus;
+import org.apache.http.ProtocolException;
+import org.apache.http.annotation.Immutable;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpHead;
+import org.apache.http.client.methods.HttpDelete;
+import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.client.methods.RequestBuilder;
+import org.apache.http.impl.client.DefaultRedirectStrategy;
+import org.apache.http.protocol.HttpContext;
+
+/**
+ * Custom {@link org.apache.http.client.RedirectStrategy} implementation
+ * that automatically redirects all HEAD, GET and DELETE requests.
+ * The {@link org.apache.http.client.DefaultRedirectStrategy} only
+ * redirects GET and HEAD automatically, per the HTTP specification
+ * (POST and PUT typically have bodies and thus cannot be redirected).
+ *
+ * A custom strategy is needed for the Openstack API, which can also send
+ * 302 on a DELETE (by name) request, expecting the client to follow the
+ * redirect to perform the actual deletion.
+ */
+@Immutable
+public class HttpClientRedirectStrategy extends DefaultRedirectStrategy {
+
+ /**
+ * Redirectable methods.
+ */
+ private static final String[] REDIRECT_METHODS = new String[] {
+ HttpGet.METHOD_NAME,
+ HttpDelete.METHOD_NAME,
+ HttpHead.METHOD_NAME
+ };
+
+ /**
+ * Determine if the request should be redirected.
+ * This may not actually be needed, since the REDIRECT_METHODS
+ * array has been updated with the DELETE.
+ */
+ @Override
+ protected boolean isRedirectable(final String method) {
+ for (final String m: REDIRECT_METHODS) {
+ if (m.equalsIgnoreCase(method)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Override the default redirect handling method. As implemented
+ * in HttpClient, it does not preserve the method on 301 or 302
+ * responses, always redirecting to a GET.
+ */
+ @Override
+ public HttpUriRequest getRedirect(
+ 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)) {
+ return new HttpHead(uri);
+ } else if (method.equalsIgnoreCase(HttpGet.METHOD_NAME)) {
+ return new HttpGet(uri);
+ } else {
+
+ final int status = response.getStatusLine().getStatusCode();
+
+ HttpUriRequest newRequest = null;
+ 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;
+ }
+ }
+}
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
new file mode 100644
index 0000000..e1850a2
--- /dev/null
+++ b/openstack-client-connectors/http-connector/src/main/java/com/woorea/openstack/connector/HttpClientResponse.java
@@ -0,0 +1,110 @@
+/*
+ * ============LICENSE_START==========================================
+ * ===================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ *
+ * ECOMP and OpenECOMP are trademarks
+ * and service marks of AT&T Intellectual Property.
+ *
+ */
+
+package com.woorea.openstack.connector;
+
+import org.apache.http.Header;
+import org.apache.http.HttpResponse;
+import org.apache.log4j.Logger;
+import org.codehaus.jackson.map.ObjectMapper;
+
+import com.woorea.openstack.base.client.OpenStackResponse;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+public class HttpClientResponse implements OpenStackResponse {
+
+ private static Logger LOGGER = Logger.getLogger(HttpClientConnector.class);
+
+ private HttpResponse response = null;
+ private String entityBody = null;
+
+ public HttpClientResponse(HttpResponse response)
+ {
+ this.response = response;
+
+ // Read the body so InputStream can be closed
+ if (response.getEntity() == null) {
+ // 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);
+ }
+
+
+ @Override
+ public <T> T getEntity (Class<T> 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
+ public <T> T getErrorEntity(Class<T> returnType) {
+ return getEntity(returnType);
+ }
+
+ @Override
+ public InputStream getInputStream() {
+ return new ByteArrayInputStream (entityBody.getBytes());
+ }
+
+ @Override
+ public String header(String name) {
+ return response.getFirstHeader(name).getValue();
+ }
+
+ @Override
+ public Map<String, String> headers() {
+ Map<String, String> headers = new HashMap<String, String>();
+
+ Header responseHeaders[] = response.getAllHeaders();
+ for (Header h : responseHeaders) {
+ headers.put(h.getName(), h.getValue());
+ }
+
+ return headers;
+ }
+
+}
diff --git a/openstack-client-connectors/http-connector/src/main/resources/META-INF/services/com.woorea.openstack.base.client.OpenStackClientConnector b/openstack-client-connectors/http-connector/src/main/resources/META-INF/services/com.woorea.openstack.base.client.OpenStackClientConnector
new file mode 100644
index 0000000..1281d32
--- /dev/null
+++ b/openstack-client-connectors/http-connector/src/main/resources/META-INF/services/com.woorea.openstack.base.client.OpenStackClientConnector
@@ -0,0 +1 @@
+com.woorea.openstack.connector.HttpClientConnector \ No newline at end of file
diff --git a/openstack-client-connectors/jersey-connector/pom.xml b/openstack-client-connectors/jersey-connector/pom.xml
new file mode 100644
index 0000000..24489d9
--- /dev/null
+++ b/openstack-client-connectors/jersey-connector/pom.xml
@@ -0,0 +1,25 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.openecomp.mso.libs.openstack-java-sdk</groupId>
+ <artifactId>client-connectors</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+ </parent>
+ <groupId>org.openecomp.mso.libs.openstack-java-sdk.client-connectors</groupId>
+ <artifactId>jersey-connector</artifactId>
+ <name>OpenStack Jersey Connector</name>
+ <description>OpenStack Jersey Connector</description>
+ <dependencies>
+ <dependency>
+ <groupId>com.sun.jersey</groupId>
+ <artifactId>jersey-client</artifactId>
+ <version>1.17.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.jackson</groupId>
+ <artifactId>jackson-jaxrs</artifactId>
+ <version>1.9.12</version>
+ </dependency>
+ </dependencies>
+
+</project>
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
diff --git a/openstack-client-connectors/jersey2-connector/pom.xml b/openstack-client-connectors/jersey2-connector/pom.xml
new file mode 100644
index 0000000..4cf7e83
--- /dev/null
+++ b/openstack-client-connectors/jersey2-connector/pom.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.openecomp.mso.libs.openstack-java-sdk</groupId>
+ <artifactId>client-connectors</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+ </parent>
+ <groupId>org.openecomp.mso.libs.openstack-java-sdk.client-connectors</groupId>
+ <artifactId>jersey2-connector</artifactId>
+ <name>OpenStack Jersey2 Connector</name>
+ <description>OpenStack Jersey2 Connector</description>
+ <url>http://maven.apache.org</url>
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.core</groupId>
+ <artifactId>jersey-client</artifactId>
+ <version>2.6</version>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-json-jackson</artifactId>
+ <version>2.6</version>
+ </dependency>
+ <dependency>
+ <groupId>org.openecomp.mso.libs.openstack-java-sdk</groupId>
+ <artifactId>openstack-client</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+ </dependency>
+ </dependencies>
+
+</project>
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
new file mode 100644
index 0000000..2171bea
--- /dev/null
+++ b/openstack-client-connectors/jersey2-connector/src/main/java/com/woorea/openstack/connector/JaxRs20Connector.java
@@ -0,0 +1,65 @@
+package com.woorea.openstack.connector;
+
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Logger;
+
+import javax.ws.rs.ClientErrorException;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.Invocation;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.MediaType;
+
+import org.glassfish.jersey.filter.LoggingFilter;
+
+import com.woorea.openstack.base.client.HttpMethod;
+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 JaxRs20Connector implements OpenStackClientConnector {
+
+ protected Client client = OpenStack.CLIENT;
+ private LoggingFilter logger = new LoggingFilter(Logger.getLogger("os"), 10000);
+
+ @Override
+ public <T> OpenStackResponse request(OpenStackRequest<T> request) {
+ WebTarget target = client.target(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(), o);
+ }
+ }
+ target.register(logger);
+ Invocation.Builder invocation = target.request();
+
+ for(Map.Entry<String, List<Object>> 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());
+
+ 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
new file mode 100644
index 0000000..f27f337
--- /dev/null
+++ b/openstack-client-connectors/jersey2-connector/src/main/java/com/woorea/openstack/connector/JaxRs20Response.java
@@ -0,0 +1,61 @@
+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 javax.ws.rs.core.Response;
+
+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;
+ }
+
+ @Override
+ public <T> T getEntity(Class<T> returnType) {
+ if(response.getStatus() >= 400) {
+ throw new OpenStackResponseException(response.getStatusInfo().getReasonPhrase(),
+ response.getStatusInfo().getStatusCode(), this);
+ }
+ return response.readEntity(returnType);
+ }
+
+ @Override
+ public <T> T getErrorEntity(Class<T> returnType) {
+ if(response.getStatus() >= 400 && response.hasEntity()) {
+ return response.readEntity(returnType);
+ }
+ return null;
+ }
+
+
+ @Override
+ public InputStream getInputStream() {
+ return (InputStream) response.getEntity();
+ }
+
+ @Override
+ public String header(String name) {
+ return response.getHeaderString(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.getHeaderString(k));
+ }
+ return headers;
+ }
+
+}
diff --git a/openstack-client-connectors/jersey2-connector/src/main/java/com/woorea/openstack/connector/OpenStack.java b/openstack-client-connectors/jersey2-connector/src/main/java/com/woorea/openstack/connector/OpenStack.java
new file mode 100644
index 0000000..f514cc8
--- /dev/null
+++ b/openstack-client-connectors/jersey2-connector/src/main/java/com/woorea/openstack/connector/OpenStack.java
@@ -0,0 +1,110 @@
+package com.woorea.openstack.connector;
+
+import java.io.IOException;
+
+import javax.net.ssl.SSLContext;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.ClientRequestContext;
+import javax.ws.rs.client.ClientRequestFilter;
+import javax.ws.rs.ext.ContextResolver;
+
+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 org.glassfish.jersey.SslConfigurator;
+import org.glassfish.jersey.jackson.JacksonFeature;
+
+public class OpenStack {
+
+ public static Client CLIENT;
+
+ public static ObjectMapper DEFAULT_MAPPER;
+
+ public static ObjectMapper WRAPPED_MAPPER;
+
+ static {
+ initialize();
+ }
+
+ private static void initialize() {
+
+ /*
+ //class MyX509TrustManager implements X509TrustManager
+ TrustManager mytm[] = null;
+ KeyManager mykm[] = null;
+
+ try {
+ mytm = new TrustManager[]{new MyX509TrustManager("./truststore_client", "asdfgh".toCharArray())};
+ mykm = new KeyManager[]{new MyX509KeyManager("./keystore_client", "asdfgh".toCharArray())};
+ } catch (Exception ex) {
+
+ }
+
+ SSLContext context = null;
+ context = SSLContext.getInstance("SSL");
+ context.init(mykm, mytm, null);
+
+ */
+
+ try {
+
+ SSLContext context = null;
+ context = SSLContext.getInstance("SSL");
+ context.init(null, null, null);
+
+ SslConfigurator sslConfig = SslConfigurator.newInstance();
+ /*
+ .trustStoreFile("./truststore_client")
+ .trustStorePassword("asdfgh")
+
+ .keyStoreFile("./keystore_client")
+ .keyPassword("asdfgh");
+ */
+ //old: CLIENT.property(ClientProperties.SSL_CONFIG, new SslConfig(context));
+
+ CLIENT = ClientBuilder.newBuilder().sslContext(sslConfig.createSSLContext()).build();
+
+ 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);
+
+ CLIENT.register(new JacksonFeature()).register(new ContextResolver<ObjectMapper>() {
+
+ public ObjectMapper getContext(Class<?> type) {
+ return type.getAnnotation(JsonRootName.class) == null ? DEFAULT_MAPPER : WRAPPED_MAPPER;
+ }
+
+ });
+
+ CLIENT.register(new ClientRequestFilter() {
+
+ public void filter(ClientRequestContext requestContext) throws IOException {
+ requestContext.getHeaders().remove("Content-Language");
+ requestContext.getHeaders().remove("Content-Encoding");
+ }
+ });
+
+ } catch(Exception e) {
+ throw new RuntimeException(e.getMessage(), e);
+ }
+
+ }
+
+}
diff --git a/openstack-client-connectors/jersey2-connector/src/main/resources/META-INF/services/com.woorea.openstack.base.client.OpenStackClientConnector b/openstack-client-connectors/jersey2-connector/src/main/resources/META-INF/services/com.woorea.openstack.base.client.OpenStackClientConnector
new file mode 100644
index 0000000..fc24457
--- /dev/null
+++ b/openstack-client-connectors/jersey2-connector/src/main/resources/META-INF/services/com.woorea.openstack.base.client.OpenStackClientConnector
@@ -0,0 +1 @@
+com.woorea.openstack.connector.JaxRs20Connector \ No newline at end of file
diff --git a/openstack-client-connectors/pom.xml b/openstack-client-connectors/pom.xml
new file mode 100644
index 0000000..6db50a8
--- /dev/null
+++ b/openstack-client-connectors/pom.xml
@@ -0,0 +1,60 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.openecomp.mso.libs</groupId>
+ <artifactId>openstack-java-sdk</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+ </parent>
+ <groupId>org.openecomp.mso.libs.openstack-java-sdk</groupId>
+ <artifactId>client-connectors</artifactId>
+ <name>OpenStack Client Connectors</name>
+ <description>OpenStack Client Connectors</description>
+ <packaging>pom</packaging>
+ <profiles>
+ <profile>
+ <id>jersey</id>
+ <activation>
+ <activeByDefault>true</activeByDefault>
+ </activation>
+ <modules>
+ <module>jersey-connector</module>
+ </modules>
+ </profile>
+ <profile>
+ <id>jersey2</id>
+ <activation>
+ <activeByDefault>true</activeByDefault>
+ </activation>
+ <modules>
+ <module>jersey2-connector</module>
+ </modules>
+ </profile>
+ <profile>
+ <id>resteasy</id>
+ <activation>
+ <activeByDefault>true</activeByDefault>
+ </activation>
+ <modules>
+ <module>resteasy-connector</module>
+ </modules>
+ </profile>
+ <profile>
+ <id>http</id>
+ <activation>
+ <activeByDefault>true</activeByDefault>
+ </activation>
+ <modules>
+ <module>http-connector</module>
+ </modules>
+ </profile>
+
+ </profiles>
+ <dependencies>
+ <dependency>
+ <groupId>org.openecomp.mso.libs.openstack-java-sdk</groupId>
+ <artifactId>openstack-client</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+ </dependency>
+ </dependencies>
+
+</project> \ No newline at end of file
diff --git a/openstack-client-connectors/resteasy-connector/pom.xml b/openstack-client-connectors/resteasy-connector/pom.xml
new file mode 100644
index 0000000..6cbdd3a
--- /dev/null
+++ b/openstack-client-connectors/resteasy-connector/pom.xml
@@ -0,0 +1,30 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.openecomp.mso.libs.openstack-java-sdk</groupId>
+ <artifactId>client-connectors</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+ </parent>
+ <groupId>org.openecomp.mso.libs.openstack-java-sdk.client-connectors</groupId>
+ <artifactId>resteasy-connector</artifactId>
+ <name>OpenStack RESTEasy Connector</name>
+ <description>OpenStack RESTEasy Connector</description>
+ <dependencies>
+ <dependency>
+ <groupId>org.jboss.resteasy</groupId>
+ <artifactId>resteasy-jaxrs</artifactId>
+ <version>2.3.2.Final</version>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.jackson</groupId>
+ <artifactId>jackson-jaxrs</artifactId>
+ <version>1.9.4</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-httpclient</groupId>
+ <artifactId>commons-httpclient</artifactId>
+ <version>3.1</version>
+ </dependency>
+ </dependencies>
+
+</project> \ No newline at end of file
diff --git a/openstack-client-connectors/resteasy-connector/src/main/java/com/woorea/openstack/connector/RESTEasyConnector.java b/openstack-client-connectors/resteasy-connector/src/main/java/com/woorea/openstack/connector/RESTEasyConnector.java
new file mode 100644
index 0000000..b2ec415
--- /dev/null
+++ b/openstack-client-connectors/resteasy-connector/src/main/java/com/woorea/openstack/connector/RESTEasyConnector.java
@@ -0,0 +1,125 @@
+package com.woorea.openstack.connector;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.ext.ContextResolver;
+
+import org.apache.commons.httpclient.HttpStatus;
+import org.codehaus.jackson.jaxrs.JacksonJsonProvider;
+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 org.jboss.resteasy.client.ClientRequest;
+import org.jboss.resteasy.client.ClientResponse;
+import org.jboss.resteasy.plugins.providers.InputStreamProvider;
+import org.jboss.resteasy.spi.ResteasyProviderFactory;
+
+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 RESTEasyConnector implements OpenStackClientConnector {
+
+ public static ObjectMapper DEFAULT_MAPPER;
+
+ public static ObjectMapper WRAPPED_MAPPER;
+
+ static class OpenStackProviderFactory extends ResteasyProviderFactory {
+
+ private JacksonJsonProvider jsonProvider;
+ private InputStreamProvider streamProvider;
+
+ public OpenStackProviderFactory() {
+ super();
+
+ addContextResolver(new ContextResolver<ObjectMapper>() {
+ public ObjectMapper getContext(Class<?> type) {
+ return type.getAnnotation(JsonRootName.class) == null ? DEFAULT_MAPPER : WRAPPED_MAPPER;
+ }
+ });
+
+ jsonProvider = new JacksonJsonProvider();
+ addMessageBodyReader(jsonProvider);
+ addMessageBodyWriter(jsonProvider);
+
+ streamProvider = new InputStreamProvider();
+ addMessageBodyReader(streamProvider);
+ addMessageBodyWriter(streamProvider);
+ }
+
+ }
+
+ private static OpenStackProviderFactory providerFactory;
+
+ 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);
+
+ providerFactory = new OpenStackProviderFactory();
+ }
+
+ public <T> OpenStackResponse request(OpenStackRequest<T> request) {
+ ClientRequest client = new ClientRequest(UriBuilder.fromUri(request.endpoint() + "/" + request.path()),
+ ClientRequest.getDefaultExecutor(), providerFactory);
+
+ for(Map.Entry<String, List<Object> > entry : request.queryParams().entrySet()) {
+ for (Object o : entry.getValue()) {
+ client = client.queryParameter(entry.getKey(), String.valueOf(o));
+ }
+ }
+
+ for (Entry<String, List<Object>> h : request.headers().entrySet()) {
+ StringBuilder sb = new StringBuilder();
+ for (Object v : h.getValue()) {
+ sb.append(String.valueOf(v));
+ }
+ client.header(h.getKey(), sb);
+ }
+
+ if (request.entity() != null) {
+ client.body(request.entity().getContentType(), request.entity().getEntity());
+ }
+
+ ClientResponse<T> response;
+
+ try {
+ response = client.httpMethod(request.method().name(), request.returnType());
+ } catch (Exception e) {
+ throw new RuntimeException("Unexpected client exception", e);
+ }
+
+ if (response.getStatus() == HttpStatus.SC_OK
+ || response.getStatus() == HttpStatus.SC_CREATED
+ || response.getStatus() == HttpStatus.SC_NO_CONTENT
+ || response.getStatus() == HttpStatus.SC_ACCEPTED) {
+ return new RESTEasyResponse(client, response);
+ }
+
+ response.releaseConnection();
+
+ throw new OpenStackResponseException(response.getResponseStatus()
+ .getReasonPhrase(), response.getStatus());
+ }
+
+}
diff --git a/openstack-client-connectors/resteasy-connector/src/main/java/com/woorea/openstack/connector/RESTEasyInputStream.java b/openstack-client-connectors/resteasy-connector/src/main/java/com/woorea/openstack/connector/RESTEasyInputStream.java
new file mode 100644
index 0000000..913a500
--- /dev/null
+++ b/openstack-client-connectors/resteasy-connector/src/main/java/com/woorea/openstack/connector/RESTEasyInputStream.java
@@ -0,0 +1,37 @@
+package com.woorea.openstack.connector;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.SocketException;
+
+import org.jboss.resteasy.client.ClientExecutor;
+
+
+public class RESTEasyInputStream extends FilterInputStream {
+
+ protected ClientExecutor clientExecutor;
+
+ public RESTEasyInputStream(InputStream inputStream, ClientExecutor clientExecutor) {
+ super(inputStream);
+ this.clientExecutor = clientExecutor;
+ }
+
+ @Override
+ public void close() throws IOException {
+ try {
+ clientExecutor.close();
+ } catch (Exception e) {
+ // Silently skip errors in the socket close errors
+ }
+
+ try {
+ super.close();
+ } catch (SocketException e) {
+ // We expect this exception because the socket is closed
+ } catch (IllegalStateException e) {
+ // We expect this exception because the socket is closed (httpclient 4.2)
+ }
+ }
+
+}
diff --git a/openstack-client-connectors/resteasy-connector/src/main/java/com/woorea/openstack/connector/RESTEasyResponse.java b/openstack-client-connectors/resteasy-connector/src/main/java/com/woorea/openstack/connector/RESTEasyResponse.java
new file mode 100644
index 0000000..82e3187
--- /dev/null
+++ b/openstack-client-connectors/resteasy-connector/src/main/java/com/woorea/openstack/connector/RESTEasyResponse.java
@@ -0,0 +1,59 @@
+package com.woorea.openstack.connector;
+
+/*
+ * Modifications copyright (c) 2017 AT&T Intellectual Property
+ */
+
+import org.jboss.resteasy.client.ClientRequest;
+import org.jboss.resteasy.client.ClientResponse;
+import com.woorea.openstack.base.client.OpenStackResponse;
+
+import javax.ws.rs.core.MultivaluedMap;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+public class RESTEasyResponse implements OpenStackResponse {
+
+ private ClientRequest client;
+
+ private ClientResponse response;
+
+ public RESTEasyResponse(ClientRequest client, ClientResponse response) {
+ this.client = client;
+ this.response = response;
+ }
+
+ @Override
+ public <T> T getEntity(Class<T> returnType) {
+ return (T) response.getEntity(returnType);
+ }
+
+ @Override
+ public <T> T getErrorEntity(Class<T> returnType) {
+ return (T) response.getEntity(returnType);
+ }
+
+ @Override
+ public InputStream getInputStream() {
+ return new RESTEasyInputStream((InputStream) response.getEntity(InputStream.class), client.getExecutor());
+ }
+
+ @Override
+ public String header(String name) {
+ return response.getHeaders().getFirst(name).toString();
+ }
+
+ @Override
+ public Map<String, String> headers() {
+ Map<String, String> headers = new HashMap<String, String>();
+ MultivaluedMap<String, Object> responseHeaders = response.getHeaders();
+
+ for (String key : responseHeaders.keySet()) {
+ headers.put(key, responseHeaders.getFirst(key).toString());
+ }
+
+ return headers;
+ }
+
+}
diff --git a/openstack-client-connectors/resteasy-connector/src/main/resources/META-INF/services/com.woorea.openstack.base.client.OpenStackClientConnector b/openstack-client-connectors/resteasy-connector/src/main/resources/META-INF/services/com.woorea.openstack.base.client.OpenStackClientConnector
new file mode 100644
index 0000000..dbb991d
--- /dev/null
+++ b/openstack-client-connectors/resteasy-connector/src/main/resources/META-INF/services/com.woorea.openstack.base.client.OpenStackClientConnector
@@ -0,0 +1 @@
+com.woorea.openstack.connector.RESTEasyConnector \ No newline at end of file