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