3b867537d9a8de1f9f91b7faa30126bdb52a39b5
[federation.git] / gateway / src / main / java / org / acumos / federation / gateway / controller / CatalogController.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.controller;
22
23 import java.net.URI;
24 import java.util.List;
25 import java.util.Map;
26
27 import javax.servlet.http.HttpServletRequest;
28 import javax.servlet.http.HttpServletResponse;
29
30 import org.acumos.cds.domain.MLPArtifact;
31 import org.acumos.cds.domain.MLPSolution;
32 import org.acumos.cds.domain.MLPSolutionRevision;
33 import org.acumos.federation.gateway.common.API;
34 import org.acumos.federation.gateway.common.JSONTags;
35 import org.acumos.federation.gateway.common.JsonResponse;
36 import org.acumos.federation.gateway.config.EELFLoggerDelegate;
37 import org.acumos.federation.gateway.security.Peer;
38 import org.acumos.federation.gateway.service.CatalogService;
39 import org.acumos.federation.gateway.service.ServiceContext;
40 import org.acumos.federation.gateway.util.Utils;
41 import org.springframework.beans.factory.annotation.Autowired;
42 import org.springframework.core.io.InputStreamResource;
43 import org.springframework.http.MediaType;
44 import org.springframework.security.access.prepost.PreAuthorize;
45 import org.springframework.security.core.context.SecurityContextHolder;
46 import org.springframework.stereotype.Controller;
47 import org.springframework.util.Base64Utils;
48 import org.springframework.web.bind.annotation.CrossOrigin;
49 import org.springframework.web.bind.annotation.PathVariable;
50 import org.springframework.web.bind.annotation.RequestMapping;
51 import org.springframework.web.bind.annotation.RequestMethod;
52 import org.springframework.web.bind.annotation.RequestParam;
53 import org.springframework.web.bind.annotation.ResponseBody;
54
55 import io.swagger.annotations.ApiOperation;
56
57 /**
58  * 
59  *
60  */
61 @Controller
62 @RequestMapping("/")
63 public class CatalogController extends AbstractController {
64
65         @Autowired
66         CatalogService catalogService;
67
68         // /**
69         // * @param request
70         // * HttpServletRequest
71         // * @param response
72         // * HttpServletResponse
73         // * @return List of Published ML Solutions in JSON format.
74         // */
75         // @CrossOrigin
76         // @ApiOperation(value = "Invoked by Peer Acumos to get a Paginated list of
77         // Published Solutions from the Catalog of the local Acumos Instance .",
78         // response = MLPSolution.class, responseContainer = "Page")
79         // @RequestMapping(value = {API.Paths.SOLUTIONS}, method = RequestMethod.GET,
80         // produces = APPLICATION_JSON)
81         // @ResponseBody
82         // public JsonResponse<RestPageResponse<MLPSolution>>
83         // getSolutionsListFromPeer(HttpServletRequest request, HttpServletResponse
84         // response,
85         // @RequestParam("pageNumber") Integer pageNumber, @RequestParam("maxSize")
86         // Integer maxSize,
87         // @RequestParam(required = false) String sortingOrder, @RequestParam(required =
88         // false) String mlpModelTypes) {
89         // JsonResponse<RestPageResponse<MLPSolution>> data = null;
90         // RestPageResponse<MLPSolution> peerCatalogSolutions = null;
91         // try {
92         // data = new JsonResponse<RestPageResponse<MLPSolution>>();
93         // peerCatalogSolutions =
94         // federationGatewayService.getPeerCatalogSolutions(pageNumber, maxSize,
95         // sortingOrder, null);
96         // if(peerCatalogSolutions != null) {
97         // data.setResponseBody(peerCatalogSolutions);
98         // logger.debug(EELFLoggerDelegate.debugLogger, "getSolutionsListFromPeer: size
99         // is {} ");
100         // }
101         // } catch (Exception e) {
102         // logger.error(EELFLoggerDelegate.errorLogger, "Exception Occurred Fetching
103         // Solutions for Market Place Catalog", e);
104         // }
105         // return data;
106         // }
107
108         /**
109          * @param theHttpResponse
110          *            HttpServletResponse
111          * @param theSelector
112          * @return List of Published ML Solutions in JSON format.
113          */
114         @CrossOrigin
115         // @PreAuthorize("hasAuthority('PEER')"
116         @PreAuthorize("hasAuthority(T(org.acumos.federation.gateway.security.Priviledge).CATALOG_ACCESS)")
117         @ApiOperation(value = "Invoked by Peer Acumos to get a list of Published Solutions from the Catalog of the local Acumos Instance .", response = MLPSolution.class, responseContainer = "List")
118         @RequestMapping(value = { API.Paths.SOLUTIONS }, method = RequestMethod.GET, produces = APPLICATION_JSON)
119         @ResponseBody
120         public JsonResponse<List<MLPSolution>> getSolutions(
121                         /* HttpServletRequest theHttpRequest, */
122                         HttpServletResponse theHttpResponse,
123                         @RequestParam(value = API.QueryParameters.SOLUTIONS_SELECTOR, required = false) String theSelector) {
124                 JsonResponse<List<MLPSolution>> response = null;
125                 List<MLPSolution> peerCatalogSolutions = null;
126                 log.debug(EELFLoggerDelegate.debugLogger, API.Paths.SOLUTIONS);
127                 try {
128                         response = new JsonResponse<List<MLPSolution>>();
129                         log.debug(EELFLoggerDelegate.debugLogger, "getSolutionsListFromPeer: selector " + theSelector);
130                         Map<String, ?> selector = null;
131                         if (theSelector != null)
132                                 selector = Utils.jsonStringToMap(new String(Base64Utils.decodeFromString(theSelector), "UTF-8"));
133
134                         peerCatalogSolutions = catalogService.getSolutions(selector, new ControllerContext());
135                         if (peerCatalogSolutions != null) {
136                                 response.setResponseBody(peerCatalogSolutions);
137                                 response.setResponseCode(String.valueOf(HttpServletResponse.SC_OK));
138                                 response.setResponseDetail(JSONTags.TAG_STATUS_SUCCESS);
139                                 response.setStatus(true);
140                                 theHttpResponse.setStatus(HttpServletResponse.SC_OK);
141                                 log.debug(EELFLoggerDelegate.debugLogger, "getSolutions: size is " + peerCatalogSolutions.size());
142                         }
143                 } catch (Exception e) {
144                         response.setResponseCode(String.valueOf(HttpServletResponse.SC_BAD_REQUEST));
145                         response.setResponseDetail(JSONTags.TAG_STATUS_FAILURE);
146                         response.setStatus(false);
147                         theHttpResponse.setStatus(HttpServletResponse.SC_BAD_REQUEST);
148                         log.error(EELFLoggerDelegate.errorLogger, "Exception occurred fetching Solutions for Market Place Catalog",
149                                         e);
150                 }
151                 return response;
152         }
153
154         @CrossOrigin
155         @PreAuthorize("hasAuthority('CATALOG_ACCESS')")
156         @ApiOperation(value = "Invoked by Peer Acumos to get a list detailed solution information from the Catalog of the local Acumos Instance .", response = MLPSolution.class)
157         @RequestMapping(value = { API.Paths.SOLUTION_DETAILS }, method = RequestMethod.GET, produces = APPLICATION_JSON)
158         @ResponseBody
159         public JsonResponse<MLPSolution> getSolutionDetails(HttpServletResponse theHttpResponse,
160                         @PathVariable(value = "solutionId") String theSolutionId) {
161                 JsonResponse<MLPSolution> response = null;
162                 MLPSolution solution = null;
163                 log.debug(EELFLoggerDelegate.debugLogger, API.Paths.SOLUTION_DETAILS + ": " + theSolutionId);
164                 try {
165                         response = new JsonResponse<MLPSolution>();
166                         solution = catalogService.getSolution(theSolutionId, new ControllerContext());
167                         if (solution != null) {
168                                 response.setResponseBody(solution);
169                                 response.setResponseCode(String.valueOf(HttpServletResponse.SC_OK));
170                                 response.setResponseDetail(JSONTags.TAG_STATUS_SUCCESS);
171                                 response.setStatus(true);
172                                 theHttpResponse.setStatus(HttpServletResponse.SC_OK);
173                         }
174                 } catch (Exception e) {
175                         response.setResponseCode(String.valueOf(HttpServletResponse.SC_BAD_REQUEST));
176                         response.setResponseDetail(JSONTags.TAG_STATUS_FAILURE);
177                         response.setStatus(false);
178                         theHttpResponse.setStatus(HttpServletResponse.SC_BAD_REQUEST);
179                         log.error(EELFLoggerDelegate.errorLogger, "An error occurred fetching solution " + theSolutionId, e);
180                 }
181                 return response;
182         }
183
184         /**
185          * @param theSolutionId
186          * @param theHttpResponse
187          *            HttpServletResponse
188          * @return List of Published ML Solutions in JSON format.
189          */
190         @CrossOrigin
191         @PreAuthorize("hasAuthority('CATALOG_ACCESS')")
192         @ApiOperation(value = "Invoked by Peer Acumos to get a list of Solution Revision from the Catalog of the local Acumos Instance .", response = MLPSolutionRevision.class, responseContainer = "List")
193         @RequestMapping(value = { API.Paths.SOLUTION_REVISIONS }, method = RequestMethod.GET, produces = APPLICATION_JSON)
194         @ResponseBody
195         public JsonResponse<List<MLPSolutionRevision>> getSolutionRevisions(HttpServletResponse theHttpResponse,
196                         @PathVariable("solutionId") String theSolutionId) {
197                 JsonResponse<List<MLPSolutionRevision>> response = null;
198                 List<MLPSolutionRevision> solutionRevisions = null;
199                 log.debug(EELFLoggerDelegate.debugLogger, API.Paths.SOLUTION_REVISIONS);
200                 try {
201                         response = new JsonResponse<List<MLPSolutionRevision>>();
202                         solutionRevisions = catalogService.getSolutionRevisions(theSolutionId, new ControllerContext());
203                         if (solutionRevisions != null) {
204                                 response.setResponseBody(solutionRevisions);
205                                 response.setResponseCode(String.valueOf(HttpServletResponse.SC_OK));
206                                 response.setResponseDetail(JSONTags.TAG_STATUS_SUCCESS);
207                                 response.setStatus(true);
208                                 theHttpResponse.setStatus(HttpServletResponse.SC_OK);
209                                 log.debug(EELFLoggerDelegate.debugLogger, "getSolutionsRevisions: size is {} ",
210                                                 solutionRevisions.size());
211                         }
212                 } catch (Exception e) {
213                         response.setResponseCode(String.valueOf(HttpServletResponse.SC_BAD_REQUEST));
214                         response.setResponseDetail(JSONTags.TAG_STATUS_FAILURE);
215                         response.setStatus(false);
216                         theHttpResponse.setStatus(HttpServletResponse.SC_BAD_REQUEST);
217                         log.error(EELFLoggerDelegate.errorLogger, "Exception Occurred Fetching Solution Revisions", e);
218                 }
219                 return response;
220         }
221
222         /**
223          * 
224          * @param theSolutionId
225          * @param theRevisionId
226          * @param theHttpResponse
227          *            HttpServletResponse
228          * @return List of Published ML Solutions in JSON format.
229          */
230         @CrossOrigin
231         @PreAuthorize("hasAuthority('CATALOG_ACCESS')")
232         @ApiOperation(value = "Invoked by Peer Acumos to get Solution Revision details from the Catalog of the local Acumos Instance .", response = MLPSolutionRevision.class)
233         @RequestMapping(value = {
234                         API.Paths.SOLUTION_REVISION_DETAILS }, method = RequestMethod.GET, produces = APPLICATION_JSON)
235         @ResponseBody
236         public JsonResponse<MLPSolutionRevision> getSolutionRevisionDetails(HttpServletResponse theHttpResponse,
237                         @PathVariable("solutionId") String theSolutionId, @PathVariable("revisionId") String theRevisionId) {
238                 JsonResponse<MLPSolutionRevision> response = null;
239                 MLPSolutionRevision solutionRevision = null;
240                 log.debug(EELFLoggerDelegate.debugLogger,
241                                 API.Paths.SOLUTION_REVISION_DETAILS + "(" + theSolutionId + "," + theRevisionId + ")");
242                 try {
243                         response = new JsonResponse<MLPSolutionRevision>();
244                         solutionRevision = catalogService.getSolutionRevision(theSolutionId, theRevisionId,
245                                         new ControllerContext());
246                         if (solutionRevision != null) {
247                                 response.setResponseBody(solutionRevision);
248                                 response.setResponseCode(String.valueOf(HttpServletResponse.SC_OK));
249                                 response.setResponseDetail(JSONTags.TAG_STATUS_SUCCESS);
250                                 response.setStatus(true);
251                                 theHttpResponse.setStatus(HttpServletResponse.SC_OK);
252                         }
253                 } catch (Exception e) {
254                         response.setResponseCode(String.valueOf(HttpServletResponse.SC_BAD_REQUEST));
255                         response.setResponseDetail(JSONTags.TAG_STATUS_FAILURE);
256                         response.setStatus(false);
257                         theHttpResponse.setStatus(HttpServletResponse.SC_BAD_REQUEST);
258                         log.error(EELFLoggerDelegate.errorLogger, "Exception Occurred Fetching Solution Revision", e);
259                 }
260                 return response;
261         }
262
263         /**
264          * @param theHttpRequest
265          *            HttpServletRequest
266          * @param theHttpResponse
267          *            HttpServletResponse
268          * @param theSolutionId
269          * @param theRevisionId
270          * @return List of Published ML Solutions in JSON format.
271          */
272         @CrossOrigin
273         @PreAuthorize("hasAuthority('CATALOG_ACCESS')")
274         @ApiOperation(value = "Invoked by Peer Acumos to get a list of Solution Revision Artifacts from the Catalog of the local Acumos Instance .", response = MLPArtifact.class, responseContainer = "List")
275         @RequestMapping(value = {
276                         API.Paths.SOLUTION_REVISION_ARTIFACTS }, method = RequestMethod.GET, produces = APPLICATION_JSON)
277         @ResponseBody
278         public JsonResponse<List<MLPArtifact>> getSolutionRevisionArtifacts(HttpServletRequest theHttpRequest,
279                         HttpServletResponse theHttpResponse, @PathVariable("solutionId") String theSolutionId,
280                         @PathVariable("revisionId") String theRevisionId) {
281                 JsonResponse<List<MLPArtifact>> response = null;
282                 List<MLPArtifact> solutionRevisionArtifacts = null;
283                 log.debug(EELFLoggerDelegate.debugLogger,
284                                 API.Paths.SOLUTION_REVISION_ARTIFACTS + "(" + theSolutionId + "," + theRevisionId + ")");
285                 try {
286                         response = new JsonResponse<List<MLPArtifact>>();
287                         solutionRevisionArtifacts = catalogService.getSolutionRevisionArtifacts(theSolutionId, theRevisionId,
288                                         new ControllerContext());
289                         if (solutionRevisionArtifacts != null) {
290                                 // re-encode the artifact uri
291                                 {
292                                         for (MLPArtifact artifact : solutionRevisionArtifacts) {
293                                                 // sooo cumbersome
294                                                 URI requestUri = new URI(theHttpRequest.getRequestURL().toString());
295                                                 URI artifactUri = API.ARTIFACT_DOWNLOAD
296                                                                 .buildUri(
297                                                                                 new URI(requestUri.getScheme(), null, requestUri.getHost(),
298                                                                                                 requestUri.getPort(), null, null, null).toString(),
299                                                                                 artifact.getArtifactId());
300                                                 log.debug(EELFLoggerDelegate.debugLogger,
301                                                                 "getSolutionRevisionArtifacts: content uri " + artifactUri);
302                                                 artifact.setUri(artifactUri.toString());
303                                         }
304                                 }
305                                 response.setResponseBody(solutionRevisionArtifacts);
306                                 response.setResponseCode(String.valueOf(HttpServletResponse.SC_OK));
307                                 response.setResponseDetail(JSONTags.TAG_STATUS_SUCCESS);
308                                 response.setStatus(true);
309                                 theHttpResponse.setStatus(HttpServletResponse.SC_OK);
310                                 log.debug(EELFLoggerDelegate.debugLogger, "getSolutionRevisionArtifacts: size is {} ",
311                                                 solutionRevisionArtifacts.size());
312                         }
313                 } catch (Exception e) {
314                         response.setResponseCode(String.valueOf(HttpServletResponse.SC_BAD_REQUEST));
315                         response.setResponseDetail(JSONTags.TAG_STATUS_FAILURE);
316                         response.setStatus(false);
317                         theHttpResponse.setStatus(HttpServletResponse.SC_BAD_REQUEST);
318                         log.error(EELFLoggerDelegate.errorLogger, "Failed to fetch solution revision artifacts", e);
319                 }
320                 return response;
321         }
322
323         /**
324          * @param theHttpRequest
325          *            HttpServletRequest
326          * @param theHttpResponse
327          *            HttpServletResponse
328          * @param theArtifactId
329          * @return Archive file of the Artifact for the Solution.
330          */
331         @CrossOrigin
332         @PreAuthorize("hasAuthority('CATALOG_ACCESS')")
333         @ApiOperation(value = "API to download the Machine Learning Artifact of the Machine Learning Solution", response = InputStreamResource.class, code = 200)
334         @RequestMapping(value = {
335                         API.Paths.ARTIFACT_DOWNLOAD }, method = RequestMethod.GET, produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
336         @ResponseBody
337         public InputStreamResource downloadSolutionArtifact(HttpServletRequest theHttpRequest,
338                         HttpServletResponse theHttpResponse, @PathVariable("artifactId") String theArtifactId) {
339                 InputStreamResource inputStreamResource = null;
340                 try {
341                         inputStreamResource = catalogService.getSolutionRevisionArtifactContent(theArtifactId,
342                                         new ControllerContext());
343                         theHttpResponse.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
344                         theHttpResponse.setHeader("Pragma", "no-cache");
345                         theHttpResponse.setHeader("Expires", "0");
346                         theHttpResponse.setStatus(HttpServletResponse.SC_OK);
347                 } catch (Exception e) {
348                         theHttpResponse.setStatus(HttpServletResponse.SC_BAD_REQUEST);
349                         log.error(EELFLoggerDelegate.errorLogger,
350                                         "Exception Occurred downloading a artifact for a Solution in Market Place Catalog", e);
351                 }
352                 return inputStreamResource;
353         }
354
355         protected class ControllerContext implements ServiceContext {
356
357                 public Peer getPeer() {
358                         return (Peer) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
359                 }
360         }
361 }