Change content download rest template config.
[federation.git] / gateway / src / main / java / org / acumos / federation / gateway / common / FederationClient.java
1 /*-
2  * ===============LICENSE_START=======================================================
3  * Acumos
4  * ===================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
6  * ===================================================================================
7  * This Acumos software file is distributed by AT&T and Tech Mahindra
8  * 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  * This file 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.acumos.federation.gateway.common;
22
23 import java.lang.invoke.MethodHandles;
24 import java.net.URI;
25 import java.util.Collections;
26 import java.util.List;
27 import java.util.Map;
28
29 import org.acumos.cds.domain.MLPArtifact;
30 import org.acumos.cds.domain.MLPDocument;
31 import org.acumos.cds.domain.MLPPeer;
32 import org.acumos.cds.domain.MLPSolution;
33 import org.acumos.cds.domain.MLPSolutionRevision;
34 import org.acumos.federation.gateway.config.EELFLoggerDelegate;
35 import org.acumos.federation.gateway.util.Utils;
36 import org.apache.http.client.HttpClient;
37 import org.springframework.core.ParameterizedTypeReference;
38 import org.springframework.core.io.Resource;
39 import org.springframework.http.HttpMethod;
40 import org.springframework.http.HttpStatus;
41 import org.springframework.http.RequestEntity;
42 import org.springframework.http.ResponseEntity;
43 import org.springframework.http.MediaType;
44 import org.springframework.util.Base64Utils;
45 import org.springframework.web.client.HttpStatusCodeException;
46 import org.springframework.web.client.HttpClientErrorException;
47
48 import com.fasterxml.jackson.databind.ObjectMapper;
49
50 /**
51  */
52 public class FederationClient extends AbstractClient {
53
54         private static final EELFLoggerDelegate log = EELFLoggerDelegate.getLogger(MethodHandles.lookup().lookupClass());
55
56         /**
57          * @param theTarget
58          *            Target
59          * @param theClient
60          *            HttpClient
61          */
62         public FederationClient(String theTarget, HttpClient theClient) {
63                 super(theTarget, theClient);
64         }
65
66         public FederationClient(String theTarget, HttpClient theClient, ObjectMapper theMapper) {
67                 super(theTarget, theClient, theMapper);
68         }
69
70         /**
71          * @return Ping information from/for Remote Acumos
72          * @throws HttpStatusCodeException
73          *             Throws HttpStatusCodeException if remote acumos interaction has failed.
74          */
75         public JsonResponse<MLPPeer> ping()
76                         throws HttpStatusCodeException {
77                 URI uri = API.PING.buildUri(this.baseUrl);
78                 log.info(EELFLoggerDelegate.debugLogger, "Query for " + uri);
79                 ResponseEntity<JsonResponse<MLPPeer>> response = null;
80                 try {
81                         response = restTemplate.exchange(uri, HttpMethod.GET, null,
82                                         new ParameterizedTypeReference<JsonResponse<MLPPeer>>() {
83                                         });
84                 }
85                 catch (HttpStatusCodeException x) {
86                         log.error(EELFLoggerDelegate.errorLogger, uri + " failed", x);
87                         throw x;
88                 }
89                 catch (Throwable t) {
90                         log.error(EELFLoggerDelegate.errorLogger, uri + " unexpected failure.", t);
91                 }
92                 finally {
93                         log.info(EELFLoggerDelegate.debugLogger, uri + " response " + response);
94                 }
95                 return response == null ? null : response.getBody();
96         }
97
98         /**
99          */
100         public JsonResponse<List<MLPPeer>> getPeers()
101                         throws HttpStatusCodeException {
102                 URI uri = API.PEERS.buildUri(this.baseUrl);
103                 log.info(EELFLoggerDelegate.debugLogger, "Query for " + uri);
104                 ResponseEntity<JsonResponse<List<MLPPeer>>> response = null;
105                 try {
106                         response = restTemplate.exchange(uri, HttpMethod.GET, null,
107                                         new ParameterizedTypeReference<JsonResponse<List<MLPPeer>>>() {
108                                         });
109                 }
110                 catch (HttpStatusCodeException x) {
111                         log.error(EELFLoggerDelegate.errorLogger, uri + " failed", x);
112                         throw x;
113                 }
114                 catch (Throwable t) {
115                         log.error(EELFLoggerDelegate.errorLogger, uri + " unexpected failure.", t);
116                 }
117                 finally {
118                         log.info(EELFLoggerDelegate.debugLogger, uri + " response " + response);
119                 }
120                 return response == null ? null : response.getBody();
121         }       
122
123
124         /**
125          * 
126          * @param theSelection
127          *            key-value pairs; ignored if null or empty. Gives special treatment
128          *            to Date-type values.
129          * @return List of MLPSolutions from Remote Acumos
130          * @throws HttpStatusCodeException
131          *             Throws HttpStatusCodeException is remote acumos is not available
132          */
133         public JsonResponse<List<MLPSolution>> getSolutions(Map<String, Object> theSelection)
134                         throws HttpStatusCodeException {
135
136                 String selectorParam = null;
137                 try {
138                         selectorParam = theSelection == null ? null
139                                         // : UriUtils.encodeQueryParam(Utils.mapToJsonString(theSelection),"UTF-8");
140                                         : Base64Utils.encodeToString(Utils.mapToJsonString(theSelection).getBytes("UTF-8"));
141                 }
142                 catch (Exception x) {
143                         throw new IllegalArgumentException("Cannot process the selection argument", x);
144                 }
145
146                 URI uri = API.SOLUTIONS.buildUri(this.baseUrl, selectorParam == null ? Collections.EMPTY_MAP
147                                 : Collections.singletonMap(API.QueryParameters.SOLUTIONS_SELECTOR, selectorParam));
148                 log.info(EELFLoggerDelegate.debugLogger, "Query for " + uri);
149                 ResponseEntity<JsonResponse<List<MLPSolution>>> response = null;
150                 try {
151                         response = restTemplate.exchange(uri, HttpMethod.GET, null,
152                                         new ParameterizedTypeReference<JsonResponse<List<MLPSolution>>>() {
153                                         });
154                 }
155                 catch (HttpStatusCodeException x) {
156                         log.error(EELFLoggerDelegate.errorLogger, uri + " failed", x);
157                         throw x;
158                 }
159                 catch (Throwable t) {
160                         log.error(EELFLoggerDelegate.errorLogger, uri + " unexpected failure.", t);
161                 }
162                 finally {
163                         log.info(EELFLoggerDelegate.debugLogger, uri + " response " + response);
164                 }
165                 return response == null ? null : response.getBody();
166         }
167
168         /**
169          * @param theSolutionId the solution id
170          * @return Peer information from Remote Acumos
171          * @throws HttpStatusCodeException
172          *             Throws HttpStatusCodeException if remote acumos interaction has failed.
173          */
174         public JsonResponse<MLPSolution> getSolution(String theSolutionId)
175                         throws HttpStatusCodeException {
176
177                 URI uri = API.SOLUTION_DETAIL.buildUri(this.baseUrl, theSolutionId);
178                 log.info(EELFLoggerDelegate.debugLogger, "Query for " + uri);
179                 ResponseEntity<JsonResponse<MLPSolution>> response = null;
180                 try {
181                         response = restTemplate.exchange(uri, HttpMethod.GET, null,
182                                         new ParameterizedTypeReference<JsonResponse<MLPSolution>>() {
183                                         });
184                 }
185                 catch (HttpStatusCodeException x) {
186                         log.error(EELFLoggerDelegate.errorLogger, uri + " failed", x);
187                         throw x;
188                 }
189                 catch (Throwable t) {
190                         log.error(EELFLoggerDelegate.errorLogger, uri + " unexpected failure.", t);
191                 }
192                 finally {
193                         log.info(EELFLoggerDelegate.debugLogger, uri + " response " + response);
194                 }
195                 return response == null ? null : response.getBody();
196         }
197
198         /**
199          * 
200          * @param theSolutionId the solution id
201          * @return List of MLPSolution Revisions from Remote Acumos
202          * @throws HttpStatusCodeException
203          *             Throws HttpStatusCodeException is remote acumos is not available
204          */
205         public JsonResponse<List<MLPSolutionRevision>> getSolutionRevisions(String theSolutionId)
206                         throws HttpStatusCodeException {
207
208                 URI uri = API.SOLUTION_REVISIONS.buildUri(this.baseUrl, theSolutionId);
209                 log.info(EELFLoggerDelegate.debugLogger, "Query for " + uri);
210                 ResponseEntity<JsonResponse<List<MLPSolutionRevision>>> response = null;
211                 try {
212                         response = restTemplate.exchange(uri, HttpMethod.GET, null,
213                                         new ParameterizedTypeReference<JsonResponse<List<MLPSolutionRevision>>>() {
214                                         });
215                 }
216                 catch (HttpStatusCodeException x) {
217                         log.error(EELFLoggerDelegate.errorLogger, uri + " failed", x);
218                         throw x;
219                 }
220                 catch (Throwable t) {
221                         log.info(EELFLoggerDelegate.errorLogger, uri + " unexpected failure.", t);
222                 }
223                 finally {
224                         log.info(EELFLoggerDelegate.debugLogger, uri + " response " + response);
225                 }
226                 return response == null ? null : response.getBody();
227         }
228
229         /**
230          * @param theSolutionId
231          *            Solution ID
232          * @param theRevisionId
233          *            Revision ID
234          * @return Detailed artifact information from Remote Acumos. The returned value can be safely cast to ..gateway.cds.SolutionRevision.
235          * @throws HttpStatusCodeException
236          *             Throws HttpStatusCodeException is remote acumos is not available
237          */
238         public JsonResponse<MLPSolutionRevision> getSolutionRevision(String theSolutionId, String theRevisionId)
239                         throws HttpStatusCodeException {
240
241                 URI uri = API.SOLUTION_REVISION_DETAILS.buildUri(this.baseUrl, theSolutionId, theRevisionId);
242                 log.info(EELFLoggerDelegate.debugLogger, "Query for " + uri);
243                 ResponseEntity<JsonResponse<MLPSolutionRevision>> response = null;
244                 try {
245                         response = restTemplate.exchange(uri, HttpMethod.GET, null,
246                                         new ParameterizedTypeReference<JsonResponse<MLPSolutionRevision>>() {
247                                         });
248                 }
249                 catch (HttpStatusCodeException x) {
250                         log.error(EELFLoggerDelegate.errorLogger, uri + " failed", x);
251                         throw x;
252                 }
253                 catch (Throwable t) {
254                         log.info(EELFLoggerDelegate.errorLogger, uri + " unexpected failure.", t);
255                 }
256                 finally {
257                         log.info(EELFLoggerDelegate.debugLogger, uri + " response " + response);
258                 }
259                 return response == null ? null : response.getBody();
260         }
261
262         /**
263          * 
264          * @param theSolutionId
265          *            Solution ID
266          * @param theRevisionId
267          *            Revision ID
268          * @return List of MLPArtifacts from Remote Acumos
269          * @throws HttpStatusCodeException
270          *             Throws HttpStatusCodeException is remote acumos is not available
271          */
272         public JsonResponse<List<MLPArtifact>> getArtifacts(String theSolutionId, String theRevisionId)
273                         throws HttpStatusCodeException {
274                 URI uri = API.SOLUTION_REVISION_ARTIFACTS.buildUri(this.baseUrl, theSolutionId, theRevisionId);
275                 log.info(EELFLoggerDelegate.debugLogger, "Query for " + uri);
276                 ResponseEntity<JsonResponse<List<MLPArtifact>>> response = null;
277                 try {
278                         response = restTemplate.exchange(uri, HttpMethod.GET, null,
279                                         new ParameterizedTypeReference<JsonResponse<List<MLPArtifact>>>() {
280                                         });
281                 }
282                 catch (HttpStatusCodeException x) {
283                         log.error(EELFLoggerDelegate.errorLogger, uri + " failed", x);
284                         throw x;
285                 }
286                 catch (Throwable t) {
287                         log.error(EELFLoggerDelegate.errorLogger, uri + " unexpected failure.", t);
288                 }
289                 finally {
290                         log.info(EELFLoggerDelegate.debugLogger, uri + " response " + response);
291                 }
292                 return response == null ? null : response.getBody();
293         }
294
295         /**
296          * @param theSolutionId
297          *            Solution ID
298          * @param theRevisionId
299          *            Revision ID
300          * @param theArtifactId
301          *            Artifact ID
302          * @return Resource
303          * @throws HttpStatusCodeException
304          *             On failure
305          */
306         public Resource getArtifactContent(String theSolutionId, String theRevisionId, String theArtifactId)
307                                                                                                                                                                                                                                                                                                                                                         throws HttpStatusCodeException {
308                 return download(API.ARTIFACT_CONTENT.buildUri(this.baseUrl, theSolutionId, theRevisionId, theArtifactId));
309         }
310
311         /**
312          * 
313          * @param theSolutionId
314          *            Solution ID
315          * @param theRevisionId
316          *            Revision ID
317          * @return List of MLPDocuments from Remote Acumos
318          * @throws HttpStatusCodeException
319          *             Throws HttpStatusCodeException is remote acumos is not available
320          */
321         public JsonResponse<List<MLPDocument>> getDocuments(String theSolutionId, String theRevisionId)
322                         throws HttpStatusCodeException {
323                 URI uri = API.SOLUTION_REVISION_DOCUMENTS.buildUri(this.baseUrl, theSolutionId, theRevisionId);
324                 log.info(EELFLoggerDelegate.debugLogger, "Query for " + uri);
325                 ResponseEntity<JsonResponse<List<MLPDocument>>> response = null;
326                 try {
327                         response = restTemplate.exchange(uri, HttpMethod.GET, null,
328                                         new ParameterizedTypeReference<JsonResponse<List<MLPDocument>>>() {
329                                         });
330                 }
331                 catch (HttpStatusCodeException x) {
332                         log.error(EELFLoggerDelegate.errorLogger, uri + " failed", x);
333                         throw x;
334                 }
335                 catch (Throwable t) {
336                         log.error(EELFLoggerDelegate.errorLogger, uri + " unexpected failure.", t);
337                 }
338                 finally {
339                         log.info(EELFLoggerDelegate.debugLogger, uri + " response " + response);
340                 }
341                 return response == null ? null : response.getBody();
342         }
343
344         /**
345          * @param theSolutionId
346          *            Solution ID
347          * @param theRevisionId
348          *            Revision ID
349          * @param theDocumentId
350          *            Document ID
351          * @return Resource
352          * @throws HttpStatusCodeException
353          *             On failure
354          */
355         public Resource getDocumentContent(String theSolutionId, String theRevisionId, String theDocumentId)
356                                                                                                                                                                                                                                                                                                                                                 throws HttpStatusCodeException {
357                 return download(API.DOCUMENT_CONTENT.buildUri(this.baseUrl, theSolutionId, theRevisionId, theDocumentId));
358         }
359
360         protected Resource download(URI theUri) throws HttpStatusCodeException {
361                 log.info(EELFLoggerDelegate.debugLogger, "Query for {}", theUri);
362                 ResponseEntity<Resource> response = null;
363                 RequestEntity<Void> request = RequestEntity
364                                                                                                                                         .get(theUri)
365                                                                                                                                         .accept(MediaType.ALL)
366                                                                                                                                         .build();
367                 try {
368                         response = restTemplate.exchange(request, Resource.class);
369                 }
370                 catch (HttpStatusCodeException x) {
371                         log.error(EELFLoggerDelegate.errorLogger, theUri + " failed", x);
372                         throw x;
373                 }
374                 catch (Throwable t) {
375                         log.error(EELFLoggerDelegate.errorLogger, theUri + " unexpected failure.", t);
376                         //not very clean
377                         throw new HttpClientErrorException(HttpStatus.BAD_REQUEST, theUri + " unexpected failure: " + t);
378                 }
379                 finally {
380                         log.info(EELFLoggerDelegate.debugLogger, theUri + " response " + response);
381                 }
382
383                 if (response == null) {
384                         //should never get here         
385                         return null;
386                 }
387                 else {
388                         return response.getBody();
389                 }
390         }
391
392         /**
393          * @return Register self with the peer this client points to.
394          * @throws HttpStatusCodeException
395          *             Throws HttpStatusCodeException if remote acumos interaction has failed.
396          */
397         public JsonResponse<MLPPeer> register(MLPPeer theSelf)
398                         throws HttpStatusCodeException {
399                 URI uri = API.PEER_REGISTER.buildUri(this.baseUrl);
400                 log.info(EELFLoggerDelegate.debugLogger, "Query for " + uri);
401                 ResponseEntity<JsonResponse<MLPPeer>> response = null;
402                 try {
403                         response = restTemplate.exchange(uri, HttpMethod.GET, null,
404                                         new ParameterizedTypeReference<JsonResponse<MLPPeer>>() {
405                                         });
406                 }
407                 catch (HttpStatusCodeException x) {
408                         log.error(EELFLoggerDelegate.errorLogger, uri + " failed", x);
409                         throw x;
410                 }
411                 catch (Throwable t) {
412                         log.error(EELFLoggerDelegate.errorLogger, uri + " unexpected failure.", t);
413                 }
414                 finally {
415                         log.info(EELFLoggerDelegate.debugLogger, uri + " response " + response);
416                 }
417                 return response == null ? null : response.getBody();
418         }       
419 }