Merge "Reorder modifiers"
[so.git] / common / src / main / java / org / openecomp / mso / client / policy / RestClient.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP - SO
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
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
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=========================================================
19  */
20
21 package org.openecomp.mso.client.policy;
22
23 import java.net.MalformedURLException;
24 import java.net.URI;
25 import java.net.URL;
26 import java.security.GeneralSecurityException;
27 import java.util.HashMap;
28 import java.util.Map;
29 import java.util.Map.Entry;
30 import java.util.Optional;
31 import java.util.UUID;
32
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;
44
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;
51
52 import com.fasterxml.jackson.databind.ObjectMapper;
53
54 @Service
55 public abstract class RestClient {
56         protected static final String ECOMP_COMPONENT_NAME = "MSO";
57         
58         private static final int MAX_PAYLOAD_SIZE = 1024 * 1024;
59         private WebTarget webTarget;
60
61         protected final Map<String, String> headerMap;
62         protected final MsoLogger msoLogger;
63         protected URL host;
64         protected Optional<URI> path;
65         protected Logger logger;
66         protected String accept;
67         protected String contentType;
68         protected UUID requestId;
69
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<>();
75                 try {
76                         host = props.getEndpoint();
77                 } catch (MalformedURLException e) {
78                         logger.error("url not valid", e);
79                         throw new RuntimeException(e);
80                 }
81                 
82                 this.path = path;
83                 initializeClient(getClient());
84         }
85
86         protected RestClient(RestProperties props, UUID requestId, Optional<URI> path, String accept, String contentType) {
87                 this(props, requestId, path);
88                 this.accept = accept;
89                 this.contentType = contentType;
90         }
91
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();
97                 this.host = host;
98                 this.contentType = contentType;
99                 this.requestId = requestId;
100                 initializeClient(getClient());
101         }
102
103         /**
104          * Override method to return false to disable logging.
105          * 
106          * @return true - to enable logging, false otherwise
107          */
108         protected boolean enableLogging() {
109                 return true;
110         }
111         
112         /**
113          * Override method to return custom value for max payload size.
114          * 
115          * @return Default value for MAX_PAYLOAD_SIZE = 1024 * 1024
116          */
117         protected int getMaxPayloadSize()
118         {
119                 return MAX_PAYLOAD_SIZE;
120         }
121
122         protected Builder getBuilder() {
123
124                 Builder builder = webTarget.request();
125                 initializeHeaderMap(headerMap);
126
127                 for (Entry<String, String> entry : headerMap.entrySet()) {
128                         builder.header(entry.getKey(), entry.getValue());
129                 }
130                 return builder;
131         }
132
133         protected abstract void initializeHeaderMap(Map<String, String> headerMap);
134
135         protected abstract Optional<ClientResponseFilter> addResponseFilter();
136
137         public abstract RestClient addRequestId(UUID requestId);
138         
139         /**
140          * Adds a basic authentication header to the request.
141          * @param auth the encrypted credentials
142          * @param key the key for decrypting the credentials
143          */
144         protected void addBasicAuthHeader(String auth, String key) {
145                 try {
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);
151                 }
152         }
153
154         protected ContextResolver<ObjectMapper> getMapper() {
155                 return new CommonObjectMapperProvider();
156         }
157
158         protected String getAccept() {
159                 return accept;
160         }
161
162         protected String getContentType() {
163                 return contentType;
164         }
165
166         protected String getMergeContentType() {
167                 return "application/merge-patch+json";
168         }
169
170         protected Client getClient() {
171                 return ClientBuilder.newBuilder().build();
172         }
173
174         protected UUID getRequestId() {
175                 return this.requestId;
176         }
177         protected void initializeClient(Client client) {
178                 if (this.enableLogging()) {
179                         client.register(logger).register(new LoggingFilter(this.getMaxPayloadSize()));
180                 }
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;
188         }
189
190         public Response get() {
191                 return this.getBuilder().accept(this.getAccept()).get();
192         }
193
194         public Response post(Object obj) {
195                 return this.getBuilder().accept(this.getAccept()).post(Entity.entity(obj, this.getContentType()));
196         }
197
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()));
201         }
202
203         public Response put(Object obj) {
204                 return this.getBuilder().accept(this.getAccept()).put(Entity.entity(obj, this.getContentType()));
205         }
206
207         public Response delete() {
208                 return this.getBuilder().accept(this.getAccept()).delete();
209         }
210
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()));
214         }
215
216         public <T> T get(Class<T> resultClass) {
217                 return this.get().readEntity(resultClass);
218         }
219
220         public <T> T get(GenericType<T> resultClass) {
221                 return this.get().readEntity(resultClass);
222         }
223
224         public <T> T post(Object obj, Class<T> resultClass) {
225                 return this.post(obj).readEntity(resultClass);
226         }
227
228         public <T> T patch(Object obj, Class<T> resultClass) {
229                 return this.patch(obj).readEntity(resultClass);
230         }
231
232         public <T> T put(Object obj, Class<T> resultClass) {
233                 return this.put(obj).readEntity(resultClass);
234         }
235
236         public <T> T delete(Class<T> resultClass) {
237                 return this.delete().readEntity(resultClass);
238         }
239         
240         public <T> T delete(Object obj, Class<T> resultClass) {
241                 return this.delete(obj).readEntity(resultClass);
242         }
243 }