Merge from ECOMP's repository
[vid.git] / vid-app-common / src / main / java / org / onap / vid / aai / util / AAIRestInterface.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * VID
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * Modifications Copyright (C) 2018 Nokia. All rights reserved.
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  */
21 package org.onap.vid.aai.util;
22
23
24 import com.att.eelf.configuration.EELFLogger;
25 import org.apache.commons.lang3.StringUtils;
26 import org.apache.commons.lang3.exception.ExceptionUtils;
27 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
28 import org.onap.vid.aai.ExceptionWithRequestInfo;
29 import org.onap.vid.aai.ResponseWithRequestInfo;
30 import org.onap.vid.aai.exceptions.InvalidPropertyException;
31 import org.onap.vid.utils.Logging;
32 import org.onap.vid.utils.Unchecked;
33 import org.springframework.beans.factory.annotation.Autowired;
34 import org.springframework.http.HttpMethod;
35
36 import javax.ws.rs.client.Client;
37 import javax.ws.rs.client.Entity;
38 import javax.ws.rs.client.Invocation;
39 import javax.ws.rs.core.MediaType;
40 import javax.ws.rs.core.Response;
41 import java.io.UnsupportedEncodingException;
42 import java.net.URI;
43 import java.net.URLEncoder;
44 import java.util.Optional;
45 import java.util.UUID;
46
47 import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
48 import static org.onap.vid.utils.Logging.REQUEST_ID_HEADER_KEY;
49
50
51 /**
52  * The Class AAIRestInterface.
53  */
54 public class AAIRestInterface {
55
56         /** The logger. */
57         protected EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(AAIRestInterface.class);
58
59         protected final EELFLogger outgoingRequestsLogger = Logging.getRequestsLogger("aai");
60
61         /** The client. */
62         private Client client = null;
63
64         /** The rest srvr base URL. */
65         private String restSrvrBaseURL;
66
67         @Autowired
68         protected HttpsAuthClient httpsAuthClientFactory;
69         private final ServletRequestHelper servletRequestHelper;
70         private final SystemPropertyHelper systemPropertyHelper;
71
72         protected static final String START_STRING = " start";
73         protected static final String TRANSACTION_ID_HEADER = "X-TransactionId";
74         protected static final String FROM_APP_ID_HEADER = "X-FromAppId";
75         protected static final String SUCCESSFUL_API_MESSAGE = " REST api call was successful!";
76         protected static final String URL_DECLARATION = ", url=";
77
78         public AAIRestInterface(HttpsAuthClient httpsAuthClientFactory, ServletRequestHelper servletRequestHelper, SystemPropertyHelper systemPropertyHelper) {
79                 this.httpsAuthClientFactory = httpsAuthClientFactory;
80                 this.servletRequestHelper = servletRequestHelper;
81                 this.systemPropertyHelper = systemPropertyHelper;
82                 initRestClient();
83         }
84
85         /**
86          * For testing purpose
87          */
88         AAIRestInterface(Optional<Client> client,
89                                          HttpsAuthClient httpsAuthClientFactory, ServletRequestHelper servletRequestHelper, SystemPropertyHelper systemPropertyHelper){
90                 this.httpsAuthClientFactory = httpsAuthClientFactory;
91                 this.servletRequestHelper = servletRequestHelper;
92                 this.systemPropertyHelper = systemPropertyHelper;
93                 if (client != null && client.isPresent()){
94                         this.client = client.get();
95                 }
96
97         }
98
99         /**
100          * Encode URL.
101          *
102          * @param nodeKey the node key
103          * @return the string
104          * @throws UnsupportedEncodingException the unsupported encoding exception
105          */
106         public String encodeURL (String nodeKey) throws UnsupportedEncodingException {
107                 return URLEncoder.encode(nodeKey, "UTF-8").replaceAll("\\+", "%20");
108         }
109
110         protected void initRestClient() {
111                 initRestClient(false);
112         }
113
114
115         private void initRestClient(boolean propagateExceptions) {
116                 if (client == null) {
117                         try {
118                                 client = httpsAuthClientFactory.getClient(HttpClientMode.WITH_KEYSTORE);
119                         } catch (Exception e) {
120                                 logger.info(EELFLoggerDelegate.errorLogger, "Exception in REST call to DB in initRestClient" + e.toString());
121                                 logger.debug(EELFLoggerDelegate.debugLogger, "Exception in REST call to DB : " + e.toString());
122                                 if (propagateExceptions) {
123                                         ExceptionUtils.rethrow(e);
124                                 }
125                         }
126                 }
127         }
128
129
130
131         /**
132          * Sets the rest srvr base URL.
133          *
134          * @param baseURL the base URL
135          */
136         public void SetRestSrvrBaseURL(String baseURL)
137         {
138                 if (baseURL == null) {
139                         logger.info(EELFLoggerDelegate.errorLogger, "REST Server base URL cannot be null.");
140                         logger.debug(EELFLoggerDelegate.debugLogger, "REST Server base URL cannot be null.");
141                 }
142
143                 restSrvrBaseURL = baseURL;
144         }
145
146         /**
147          * Gets the rest srvr base URL.
148          *
149          * @return the rest srvr base URL
150          */
151         public String getRestSrvrBaseURL() {
152                 return restSrvrBaseURL;
153         }
154
155
156         /**
157          * Rest get.
158          *
159          * @param fromAppId the from app id
160          * @param transId the trans id
161          * @param requestUri the request uri
162          * @param xml the xml
163          * @return the string
164          */
165         public ResponseWithRequestInfo RestGet(String fromAppId, String transId, URI requestUri, boolean xml) {
166                 return RestGet(fromAppId, transId, requestUri, xml, false);
167         }
168
169         public ResponseWithRequestInfo RestGet(String fromAppId, String transId, URI requestUri, boolean xml, boolean propagateExceptions) {
170                 return doRest(fromAppId, transId, requestUri, null, HttpMethod.GET, xml, propagateExceptions);
171         }
172
173         public ResponseWithRequestInfo doRest(String fromAppId, String transId, URI requestUri, String payload, HttpMethod method, boolean xml, boolean propagateExceptions) {
174                 String url = null;
175                 String methodName = "Rest"+method.name();
176                 try {
177
178                         url = systemPropertyHelper.getFullServicePath(requestUri);
179
180                         initRestClient(propagateExceptions);
181
182                         logger.debug(EELFLoggerDelegate.debugLogger, methodName + START_STRING);
183                         logger.debug(EELFLoggerDelegate.debugLogger, url + " for the get REST API");
184
185                         Logging.logRequest(outgoingRequestsLogger, method, url, payload);
186
187                         final Response response;
188                         Invocation.Builder requestBuilder = client.target(url)
189                                         .request()
190                                         .accept(xml ? MediaType.APPLICATION_XML : MediaType.APPLICATION_JSON)
191                                         .header(TRANSACTION_ID_HEADER, transId)
192                                         .header(FROM_APP_ID_HEADER, fromAppId)
193                                         .header("Content-Type", MediaType.APPLICATION_JSON)
194                                         .header(REQUEST_ID_HEADER_KEY, extractOrGenerateRequestId());
195
196                         requestBuilder = systemPropertyHelper.isClientCertEnabled() ?
197                                         requestBuilder : authenticateRequest(requestBuilder);
198
199                         Invocation restInvocation = StringUtils.isEmpty(payload) ?
200                                         requestBuilder.build(method.name()) :
201                                         requestBuilder.build(method.name(), Entity.entity(payload, MediaType.APPLICATION_JSON));
202
203                         response = restInvocation.invoke();
204                         Logging.logResponse(outgoingRequestsLogger, method, url, response);
205
206                         if (response.getStatusInfo().getFamily() == Response.Status.Family.SUCCESSFUL) {
207                                 logger.debug(EELFLoggerDelegate.debugLogger, methodName + SUCCESSFUL_API_MESSAGE);
208                                 logger.info(EELFLoggerDelegate.errorLogger, methodName + SUCCESSFUL_API_MESSAGE);
209                         } else {
210                                 logger.debug(EELFLoggerDelegate.debugLogger, getInvalidResponseLogMessage(url, methodName, response));
211                         }
212                         return new ResponseWithRequestInfo(response, url, method);
213                 } catch (Exception e) {
214                         logger.debug(EELFLoggerDelegate.debugLogger, getFailedResponseLogMessage(url, methodName, e));
215                         if (propagateExceptions) {
216                                 throw new ExceptionWithRequestInfo(method, defaultIfNull(url, requestUri.toASCIIString()), e);
217                         } else {
218                                 return new ResponseWithRequestInfo(null, url, method);
219                         }
220                 }
221         }
222
223         protected String extractOrGenerateRequestId() {
224                 return servletRequestHelper.extractOrGenerateRequestId();
225         }
226
227
228         /**
229          * Delete.
230          *
231          * @param sourceID the source ID
232          * @param transId the trans id
233          * @param path the path
234          * @return true, if successful
235          */
236         public boolean Delete(String sourceID, String transId, String path) {
237                 String methodName = "Delete";
238                 transId += ":" + UUID.randomUUID().toString();
239                 logger.debug(methodName + START_STRING);
240                 Boolean response = false;
241                 String url = systemPropertyHelper.getFullServicePath(path);
242                 try {
243
244                         initRestClient();
245                         Logging.logRequest(outgoingRequestsLogger, HttpMethod.DELETE, url);
246                         final Response cres = client.target(url)
247                                         .request()
248                                         .accept(MediaType.APPLICATION_JSON)
249                                         .header(TRANSACTION_ID_HEADER, transId)
250                                         .header(FROM_APP_ID_HEADER, sourceID)
251                                         .header(REQUEST_ID_HEADER_KEY, extractOrGenerateRequestId())
252                                         .delete();
253                         Logging.logResponse(outgoingRequestsLogger, HttpMethod.DELETE, url, cres);
254                         if (cres.getStatusInfo().equals(Response.Status.NOT_FOUND)) {
255                                 logger.debug(EELFLoggerDelegate.debugLogger, "Resource does not exist...: " + cres.getStatus()
256                                                 + ":" + cres.readEntity(String.class));
257                                 response = false;
258                         } else if (cres.getStatusInfo().equals(Response.Status.OK) || cres.getStatusInfo().equals(Response.Status.NO_CONTENT)) {
259                                 logger.debug(EELFLoggerDelegate.debugLogger, "Resource " + url + " deleted");
260                                 logger.info(EELFLoggerDelegate.errorLogger, "Resource " + url + " deleted");
261                                 response = true;
262                         } else {
263                                 logger.debug(EELFLoggerDelegate.debugLogger, "Deleting Resource failed: " + cres.getStatus()
264                                                 + ":" + cres.readEntity(String.class));
265                                 response = false;
266                         }
267
268                 } catch (Exception e) {
269                         logger.debug(EELFLoggerDelegate.debugLogger, getFailedResponseLogMessage(url, methodName, e));
270                 }
271                 return response;
272         }
273
274
275         /**
276          * Rest put.
277          *
278          * @param fromAppId the from app id
279          * @param path the path
280          * @param payload the payload
281          * @param xml the xml
282          * @param propagateExceptions
283          * @return the string
284          */
285         public ResponseWithRequestInfo RestPut(String fromAppId, String path, String payload, boolean xml, boolean propagateExceptions) {
286                 return doRest(fromAppId, UUID.randomUUID().toString(), Unchecked.toURI(path), payload, HttpMethod.PUT, xml, propagateExceptions);
287         }
288
289
290
291         /**
292          * Rest post.
293          *
294          * @param fromAppId the from app id
295          * @param path the path
296          * @param payload the payload
297          * @param xml the xml
298          * @return the string
299          */
300         public Response RestPost(String fromAppId, String path, String payload, boolean xml) {
301                 String methodName = "RestPost";
302                 String url=systemPropertyHelper.getServiceBasePath(path);
303                 String transId = UUID.randomUUID().toString();
304                 logger.debug(EELFLoggerDelegate.debugLogger, methodName + START_STRING);
305
306                 Response response = null;
307                 try {
308                         initRestClient();
309                         Logging.logRequest(outgoingRequestsLogger, HttpMethod.POST, url, payload);
310                         response = authenticateRequest(client.target(url)
311                                         .request()
312                                         .accept(xml ? MediaType.APPLICATION_XML : MediaType.APPLICATION_JSON)
313                                         .header(TRANSACTION_ID_HEADER, transId)
314                                         .header(FROM_APP_ID_HEADER,  fromAppId))
315                                         .header(REQUEST_ID_HEADER_KEY, extractOrGenerateRequestId())
316                                         .post(Entity.entity(payload, MediaType.APPLICATION_JSON));
317                         Logging.logResponse(outgoingRequestsLogger, HttpMethod.POST, url, response);
318
319                         if (response.getStatusInfo().getFamily().equals(Response.Status.Family.SUCCESSFUL)) {
320                                 logger.info(EELFLoggerDelegate.errorLogger, getValidResponseLogMessage(methodName));
321                                 logger.debug(EELFLoggerDelegate.debugLogger, getValidResponseLogMessage(methodName));
322                         } else {
323                                 logger.debug(EELFLoggerDelegate.debugLogger, getInvalidResponseLogMessage(url, methodName, response));
324                         }
325                 } catch (Exception e) {
326                         logger.debug(EELFLoggerDelegate.debugLogger, getFailedResponseLogMessage(url, methodName, e));
327                 }
328                 return response;
329         }
330
331         protected String getFailedResponseLogMessage(String path, String methodName, Exception e) {
332                 return methodName + URL_DECLARATION + path + ", Exception: " + e.toString();
333         }
334
335         protected String getValidResponseLogMessage(String methodName) {
336                 return methodName + URL_DECLARATION;
337         }
338
339         protected String getInvalidResponseLogMessage(String path, String methodName, Response cres) {
340                 return methodName + " with status=" + cres.getStatus() + URL_DECLARATION + path;
341         }
342
343         private Invocation.Builder authenticateRequest(Invocation.Builder requestBuilder) throws InvalidPropertyException, UnsupportedEncodingException {
344                 return requestBuilder
345                                 .header("Authorization", "Basic " + systemPropertyHelper.getEncodedCredentials());
346         }
347
348 }