Merge changes from topics "VID-30", "VID-37"
[vid.git] / vid-app-common / src / main / java / org / onap / vid / mso / RestMsoImplementation.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * VID
4  * ================================================================================
5  * Copyright (C) 2017 - 2019 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.onap.vid.mso;
22
23 import static org.onap.vid.logging.Headers.INVOCATION_ID;
24 import static org.onap.vid.logging.Headers.PARTNER_NAME;
25 import static org.onap.vid.utils.Logging.ONAP_REQUEST_ID_HEADER_KEY;
26 import static org.onap.vid.utils.Logging.REQUEST_ID_HEADER_KEY;
27 import static org.onap.vid.utils.Logging.getMethodCallerName;
28 import static org.onap.vid.utils.Logging.getMethodName;
29
30 import com.att.eelf.configuration.EELFLogger;
31 import com.fasterxml.jackson.databind.ObjectMapper;
32 import java.util.Collections;
33 import java.util.Optional;
34 import javax.ws.rs.client.Client;
35 import javax.ws.rs.client.Entity;
36 import javax.ws.rs.client.Invocation;
37 import javax.ws.rs.core.MediaType;
38 import javax.ws.rs.core.MultivaluedHashMap;
39 import javax.ws.rs.core.Response;
40 import org.apache.commons.codec.binary.Base64;
41 import org.eclipse.jetty.util.security.Password;
42 import org.glassfish.jersey.client.ClientProperties;
43 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
44 import org.onap.vid.aai.util.HttpClientMode;
45 import org.onap.vid.aai.util.HttpsAuthClient;
46 import org.onap.vid.client.HttpBasicClient;
47 import org.onap.vid.utils.Logging;
48 import org.onap.vid.utils.SystemPropertiesWrapper;
49 import org.springframework.beans.factory.annotation.Autowired;
50 import org.springframework.http.HttpMethod;
51
52 /**
53  * Created by pickjonathan on 26/06/2017.
54  */
55 public class RestMsoImplementation {
56
57     
58     /**
59      * The logger.
60      */
61     protected EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(RestMsoImplementation.class);
62     private final EELFLogger outgoingRequestsLogger = Logging.getRequestsLogger("mso");
63
64     /** The client. */
65     private Client client = null;
66
67
68     protected HttpsAuthClient httpsAuthClient;
69     protected SystemPropertiesWrapper systemProperties;
70     protected final Logging loggingService;
71
72     private static final String START_LOG = " start";
73     private static final String APPLICATION_JSON = "application/json";
74     private static final String WITH_STATUS = " with status=";
75     private static final String URL_LOG = ", url=";
76     private static final String NO_RESPONSE_ENTITY_LOG = " No response entity, this is probably ok, e=";
77     private static final String WITH_URL_LOG = " with url=";
78     private static final String EXCEPTION_LOG = ", Exception: ";
79     private static final String REST_API_SUCCESSFULL_LOG = " REST api was successfull!";
80     private static final String REST_MSG_TEMPLATE = "start {}->{}({}, {}, {})";
81     /** The common headers. */
82     /**
83      * Instantiates a new mso rest interface.
84      */
85
86     @Autowired
87     public RestMsoImplementation(HttpsAuthClient httpsAuthClient, SystemPropertiesWrapper systemProperties, Logging loggingService){
88         this.httpsAuthClient=httpsAuthClient;
89         this.systemProperties = systemProperties;
90         this.loggingService = loggingService;
91     }
92
93     @SuppressWarnings("Duplicates")
94     protected MultivaluedHashMap<String, Object> initMsoClient()
95     {
96         final String methodname = "initRestClient()";
97
98         final String username = systemProperties.getProperty(MsoProperties.MSO_USER_NAME);
99         final String password = systemProperties.getProperty(MsoProperties.MSO_PASSWORD);
100         final String mso_url = systemProperties.getProperty(MsoProperties.MSO_SERVER_URL);
101         final String decrypted_password = Password.deobfuscate(password);
102
103         String authString = username + ":" + decrypted_password;
104
105         byte[] authEncBytes = Base64.encodeBase64(authString.getBytes());
106         String authStringEnc = new String(authEncBytes);
107
108         MultivaluedHashMap<String, Object> commonHeaders = new MultivaluedHashMap();
109         commonHeaders.put("Authorization",  Collections.singletonList(("Basic " + authStringEnc)));
110         commonHeaders.put(PARTNER_NAME.getHeaderName(), Collections.singletonList(PARTNER_NAME.getHeaderValue()));
111
112         String requestIdValue = Logging.extractOrGenerateRequestId();
113         commonHeaders.put(REQUEST_ID_HEADER_KEY, Collections.singletonList(requestIdValue));
114         commonHeaders.put(ONAP_REQUEST_ID_HEADER_KEY, Collections.singletonList(requestIdValue));
115         commonHeaders.put(INVOCATION_ID.getHeaderName(), Collections.singletonList(INVOCATION_ID.getHeaderValue()));
116
117         boolean useSsl = true;
118         if ( (mso_url != null) && ( !(mso_url.isEmpty()) ) ) {
119             useSsl = mso_url.startsWith("https");
120         }
121         if (client == null) {
122
123             try {
124                 if ( useSsl ) {
125                     client = httpsAuthClient.getClient(HttpClientMode.WITHOUT_KEYSTORE);
126                 }
127                 else {
128                     client = HttpBasicClient.getClient();
129                 }
130             } catch (Exception e) {
131                 logger.info(EELFLoggerDelegate.errorLogger,methodname + " Unable to get the SSL client");
132             }
133         }
134
135         return commonHeaders;
136     }
137
138     public <T> RestObject<T> GetForObject(String path, Class<T> clazz) {
139         final String methodName = getMethodName();
140         logger.debug(EELFLoggerDelegate.debugLogger, "start {}->{}({}, {})", getMethodCallerName(), methodName, path, clazz);
141
142         String url = systemProperties.getProperty(MsoProperties.MSO_SERVER_URL) + path;
143         logger.debug(EELFLoggerDelegate.debugLogger, "<== " +  methodName + " sending request to url= " + url);
144
145         MultivaluedHashMap<String, Object> commonHeaders = initMsoClient();
146         loggingService.logRequest(outgoingRequestsLogger, HttpMethod.GET, url);
147         final Response cres = client.target(url)
148                 .request()
149                 .accept(APPLICATION_JSON)
150                 .headers(commonHeaders)
151                 .get();
152         loggingService.logResponse(outgoingRequestsLogger, HttpMethod.GET, url, cres);
153         final RestObject<T> restObject = cresToRestObject(cres, clazz);
154         int status = cres.getStatus();
155
156         if (status == 200 || status == 202) {
157             logger.debug(EELFLoggerDelegate.debugLogger, methodName + REST_API_SUCCESSFULL_LOG);
158         } else {
159             logger.debug(EELFLoggerDelegate.debugLogger,"<== " + methodName + WITH_STATUS +status+ URL_LOG +url);
160         }
161
162         logger.debug(EELFLoggerDelegate.debugLogger,methodName + " received status=" + status );
163
164         return restObject;
165     }
166
167     public <T> RestObject<T> PostForObject(Object requestDetails, String path, Class<T> clazz) {
168         logger.debug(EELFLoggerDelegate.debugLogger, REST_MSG_TEMPLATE, getMethodCallerName(), getMethodName(), requestDetails, path, clazz);
169         return restCall(HttpMethod.POST, clazz, requestDetails, path);
170     }
171
172     public Invocation.Builder prepareClient(String path, String methodName) {
173         MultivaluedHashMap<String, Object> commonHeaders = initMsoClient();
174
175         String url = systemProperties.getProperty(MsoProperties.MSO_SERVER_URL) + path;
176         logger.debug(EELFLoggerDelegate.debugLogger,"<== " +  methodName + " sending request to url= " + url);
177         // Change the content length
178         return client.target(url)
179                 .request()
180                 .accept(APPLICATION_JSON)
181                 .headers(commonHeaders);
182     }
183
184     public <T> RestObject<T> restCall(HttpMethod httpMethod, Class<T> tClass, Object payload, String path) {
185         return restCall(httpMethod, tClass, payload, path, Optional.empty());
186     }
187
188
189     /*
190     user id is needed to be pass as X-RequestorID in new MSO flows like Delete instanceGroup
191      */
192     public <T> RestObject<T> restCall(HttpMethod httpMethod, Class<T> tClass, Object payload, String path, Optional<String> userId)  {
193         String methodName = httpMethod.name();
194         String url="";
195
196         try {
197
198             MultivaluedHashMap<String, Object> commonHeaders = initMsoClient();
199             userId.ifPresent(id->commonHeaders.put("X-RequestorID", Collections.singletonList(id)));
200
201             url = systemProperties.getProperty(MsoProperties.MSO_SERVER_URL) + path;
202             loggingService.logRequest(outgoingRequestsLogger, httpMethod, url, payload);
203             // Change the content length
204             final Invocation.Builder restBuilder = client.target(url)
205                     .request()
206                     .accept(APPLICATION_JSON)
207                     .headers(commonHeaders)
208                     .property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true)
209                 ;
210
211             Invocation restInvocation = payload==null ?
212                     restBuilder.build(httpMethod.name()) :
213                     restBuilder.build(httpMethod.name(), Entity.entity(payload, MediaType.APPLICATION_JSON));
214             final Response cres = restInvocation.invoke();
215
216             loggingService.logResponse(outgoingRequestsLogger, httpMethod, url, cres);
217             return cresToRestObject(cres, tClass);
218         }
219         catch (Exception e) {
220             logger.debug(EELFLoggerDelegate.debugLogger,"<== " + methodName + WITH_URL_LOG +url+ EXCEPTION_LOG + e.toString());
221             throw e;
222         }
223
224     }
225
226     private <T> RestObject<T> cresToRestObject(Response cres, Class<?> tClass) {
227         RestObject<T> restObject = new RestObject<>();
228
229         String rawEntity = null;
230         try {
231             cres.bufferEntity();
232             rawEntity = cres.readEntity(String.class);
233             restObject.setRaw(rawEntity);
234             T t = (T) new ObjectMapper().readValue(rawEntity, tClass);
235             restObject.set(t);
236         }
237         catch ( Exception e ) {
238             try {
239                 logger.debug(EELFLoggerDelegate.debugLogger, "<== " + getMethodCallerName() + " Error reading response entity as " + tClass + ": , e="
240                         + e.getMessage() + ", Entity=" + rawEntity);
241             } catch (Exception e2) {
242                 logger.debug(EELFLoggerDelegate.debugLogger, "<== " + getMethodCallerName() + NO_RESPONSE_ENTITY_LOG
243                         + e.getMessage());
244             }
245         }
246
247         int status = cres.getStatus();
248         restObject.setStatusCode (status);
249
250         return restObject;
251     }
252
253 }