2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.openecomp.mso.client.policy;
23 import java.net.MalformedURLException;
26 import java.security.GeneralSecurityException;
27 import java.util.HashMap;
29 import java.util.Map.Entry;
30 import java.util.Optional;
31 import java.util.UUID;
33 import javax.ws.rs.client.Client;
34 import javax.ws.rs.client.ClientBuilder;
35 import javax.ws.rs.client.ClientResponseFilter;
36 import javax.ws.rs.client.Entity;
37 import javax.ws.rs.client.Invocation.Builder;
38 import javax.ws.rs.client.WebTarget;
39 import javax.ws.rs.core.GenericType;
40 import javax.ws.rs.core.MediaType;
41 import javax.ws.rs.core.Response;
42 import javax.ws.rs.core.UriBuilder;
43 import javax.ws.rs.ext.ContextResolver;
45 import org.apache.commons.codec.binary.Base64;
46 import org.apache.log4j.Logger;
47 import org.openecomp.mso.client.RestProperties;
48 import org.openecomp.mso.logger.MsoLogger;
49 import org.openecomp.mso.utils.CryptoUtils;
50 import org.springframework.stereotype.Service;
52 import com.fasterxml.jackson.databind.ObjectMapper;
55 public abstract class RestClient {
56 protected static final String ECOMP_COMPONENT_NAME = "MSO";
58 private static final int MAX_PAYLOAD_SIZE = 1024 * 1024;
59 private WebTarget webTarget;
61 protected final Map<String, String> headerMap;
62 protected final MsoLogger msoLogger;
64 protected Optional<URI> path;
65 protected Logger logger;
66 protected String accept;
67 protected String contentType;
68 protected UUID requestId;
70 protected RestClient(RestProperties props, UUID requestId, Optional<URI> path) {
71 logger = Logger.getLogger(getClass().getName());
72 msoLogger = MsoLogger.getMsoLogger(MsoLogger.Catalog.GENERAL);
73 this.requestId = requestId;
74 headerMap = new HashMap<>();
76 host = props.getEndpoint();
77 } catch (MalformedURLException e) {
78 logger.error("url not valid", e);
79 throw new RuntimeException(e);
83 initializeClient(getClient());
86 protected RestClient(RestProperties props, UUID requestId, Optional<URI> path, String accept, String contentType) {
87 this(props, requestId, path);
89 this.contentType = contentType;
92 protected RestClient(URL host, UUID requestId, String contentType) {
93 headerMap = new HashMap<>();
94 logger = Logger.getLogger(getClass().getName());
95 msoLogger = MsoLogger.getMsoLogger(MsoLogger.Catalog.GENERAL);
96 this.path = Optional.empty();
98 this.contentType = contentType;
99 this.requestId = requestId;
100 initializeClient(getClient());
104 * Override method to return false to disable logging.
106 * @return true - to enable logging, false otherwise
108 protected boolean enableLogging() {
113 * Override method to return custom value for max payload size.
115 * @return Default value for MAX_PAYLOAD_SIZE = 1024 * 1024
117 protected int getMaxPayloadSize()
119 return MAX_PAYLOAD_SIZE;
122 protected Builder getBuilder() {
124 Builder builder = webTarget.request();
125 initializeHeaderMap(headerMap);
127 for (Entry<String, String> entry : headerMap.entrySet()) {
128 builder.header(entry.getKey(), entry.getValue());
133 protected abstract void initializeHeaderMap(Map<String, String> headerMap);
135 protected abstract Optional<ClientResponseFilter> addResponseFilter();
137 public abstract RestClient addRequestId(UUID requestId);
140 * Adds a basic authentication header to the request.
141 * @param auth the encrypted credentials
142 * @param key the key for decrypting the credentials
144 protected void addBasicAuthHeader(String auth, String key) {
146 byte[] decryptedAuth = CryptoUtils.decrypt(auth, key).getBytes();
147 String authHeaderValue = "Basic " + new String(Base64.encodeBase64(decryptedAuth));
148 headerMap.put("Authorization", authHeaderValue);
149 } catch (GeneralSecurityException e) {
150 logger.warn(e.getMessage(), e);
154 protected ContextResolver<ObjectMapper> getMapper() {
155 return new CommonObjectMapperProvider();
158 protected String getAccept() {
162 protected String getContentType() {
166 protected String getMergeContentType() {
167 return "application/merge-patch+json";
170 protected Client getClient() {
171 return ClientBuilder.newBuilder().build();
174 protected UUID getRequestId() {
175 return this.requestId;
177 protected void initializeClient(Client client) {
178 if (this.enableLogging()) {
179 client.register(logger).register(new LoggingFilter(this.getMaxPayloadSize()));
181 client.register(this.getMapper());
182 Optional<ClientResponseFilter> responseFilter = this.addResponseFilter();
183 responseFilter.ifPresent(clientResponseFilter -> client.register(clientResponseFilter));
184 webTarget = path.<WebTarget>map(uri -> client.target(UriBuilder.fromUri(host + uri.toString())))
185 .orElseGet(() -> client.target(host.toString()));
186 this.accept = MediaType.APPLICATION_JSON;
187 this.contentType = MediaType.APPLICATION_JSON;
190 public Response get() {
191 return this.getBuilder().accept(this.getAccept()).get();
194 public Response post(Object obj) {
195 return this.getBuilder().accept(this.getAccept()).post(Entity.entity(obj, this.getContentType()));
198 public Response patch(Object obj) {
199 return this.getBuilder().header("X-HTTP-Method-Override", "PATCH").accept(this.getAccept())
200 .post(Entity.entity(obj, this.getMergeContentType()));
203 public Response put(Object obj) {
204 return this.getBuilder().accept(this.getAccept()).put(Entity.entity(obj, this.getContentType()));
207 public Response delete() {
208 return this.getBuilder().accept(this.getAccept()).delete();
211 public Response delete(Object obj) {
212 return this.getBuilder().header("X-HTTP-Method-Override", "DELETE").accept(this.getAccept())
213 .put(Entity.entity(obj, this.getContentType()));
216 public <T> T get(Class<T> resultClass) {
217 return this.get().readEntity(resultClass);
220 public <T> T get(GenericType<T> resultClass) {
221 return this.get().readEntity(resultClass);
224 public <T> T post(Object obj, Class<T> resultClass) {
225 return this.post(obj).readEntity(resultClass);
228 public <T> T patch(Object obj, Class<T> resultClass) {
229 return this.patch(obj).readEntity(resultClass);
232 public <T> T put(Object obj, Class<T> resultClass) {
233 return this.put(obj).readEntity(resultClass);
236 public <T> T delete(Class<T> resultClass) {
237 return this.delete().readEntity(resultClass);
240 public <T> T delete(Object obj, Class<T> resultClass) {
241 return this.delete(obj).readEntity(resultClass);