catalog-be servlets refactoring
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / distribution / servlet / DistributionCatalogServlet.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2017 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.openecomp.sdc.be.distribution.servlet;
22
23 import com.jcabi.aspects.Loggable;
24 import fj.data.Either;
25 import io.swagger.annotations.*;
26 import org.openecomp.sdc.be.components.impl.ArtifactsBusinessLogic;
27 import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;
28 import org.openecomp.sdc.be.components.impl.GroupBusinessLogic;
29 import org.openecomp.sdc.be.config.BeEcompErrorManager;
30 import org.openecomp.sdc.be.dao.api.ActionStatus;
31 import org.openecomp.sdc.be.impl.ComponentsUtils;
32 import org.openecomp.sdc.be.resources.data.auditing.model.DistributionData;
33 import org.openecomp.sdc.be.servlets.BeGenericServlet;
34 import org.openecomp.sdc.be.user.UserBusinessLogic;
35 import org.openecomp.sdc.common.api.Constants;
36 import org.openecomp.sdc.common.log.wrappers.Logger;
37 import org.openecomp.sdc.exception.ResponseFormat;
38
39 import javax.inject.Singleton;
40 import javax.servlet.ServletContext;
41 import javax.servlet.http.HttpServletRequest;
42 import javax.ws.rs.*;
43 import javax.ws.rs.core.Context;
44 import javax.ws.rs.core.MediaType;
45 import javax.ws.rs.core.Response;
46 import java.io.ByteArrayInputStream;
47 import java.io.InputStream;
48 import java.util.HashMap;
49 import java.util.Map;
50 import org.springframework.beans.factory.annotation.Autowired;
51
52 /**
53  * This Servlet serves external users to download artifacts.
54  * 
55  * @author tgitelman
56  *
57  */
58
59 @Loggable(prepend = true, value = Loggable.DEBUG, trim = false)
60 @Path("/v1/catalog")
61 @Api(value = "Distribution Catalog Servlet", description = "This Servlet serves external users to download artifacts.")
62 @Singleton
63 public class DistributionCatalogServlet extends BeGenericServlet {
64
65     private static final String DOWNLOAD_ARTIFACT_FAILED_WITH_EXCEPTION = "download artifact failed with exception";
66         private static final String MISSING_X_ECOMP_INSTANCE_ID_HEADER = "Missing X-ECOMP-InstanceID header";
67         private static final Logger log = Logger.getLogger(DistributionCatalogServlet.class);
68         private final ArtifactsBusinessLogic artifactsBusinessLogic;
69
70           @Autowired
71     public DistributionCatalogServlet(UserBusinessLogic userBusinessLogic,
72         ComponentsUtils componentsUtils,
73         ArtifactsBusinessLogic artifactsBusinessLogic) {
74         super(userBusinessLogic, componentsUtils);
75         this.artifactsBusinessLogic = artifactsBusinessLogic;
76     }
77
78     @Context
79     private HttpServletRequest request;
80
81     // *******************************************************
82     // Download (GET) artifacts
83     // **********************************************************/
84     /**
85      *
86      * @param requestId
87      * @param instanceIdHeader
88      * @param accept
89      * @param authorization
90      * @param serviceName
91      * @param serviceVersion
92      * @param artifactName
93      * @return
94      */
95     @GET
96     @Path("/services/{serviceName}/{serviceVersion}/artifacts/{artifactName}")
97     @Consumes(MediaType.APPLICATION_JSON)
98     @Produces(MediaType.APPLICATION_OCTET_STREAM)
99     @ApiOperation(value = "Download service artifact", httpMethod = "GET", notes = "Returns downloaded artifact", response = String.class)
100     @ApiResponses(value = {
101             @ApiResponse(code = 200, message = "The artifact is found and streamed.", response = String.class),
102             @ApiResponse(code = 400, message = "Missing  'X-ECOMP-InstanceID'  HTTP header - POL5001"),
103             @ApiResponse(code = 401, message = "ECOMP component  should authenticate itself  and  to  re-send  again  HTTP  request  with its Basic  Authentication credentials - POL5002"),
104             @ApiResponse(code = 403, message = "ECOMP component is not authorized - POL5003"),
105             @ApiResponse(code = 404, message = "Specified Service is not found - SVC4503"),
106             @ApiResponse(code = 404, message = "Specified Service Version is  not  found - SVC4504"),
107             @ApiResponse(code = 404, message = "Specified artifact is  not found - SVC4505"),
108             @ApiResponse(code = 405, message = "Method  Not Allowed: Invalid HTTP method type used (PUT,DELETE,POST will be rejected) - POL4050"),
109             @ApiResponse(code = 500, message = "The GET request failed either due to internal SDC problem or Cambria Service failure. ECOMP Component should continue the attempts to get the needed information - POL5000")})
110     public Response downloadServiceArtifact(
111             @ApiParam(value = "X-ECOMP-RequestID header", required = false)@HeaderParam(value = Constants.X_ECOMP_REQUEST_ID_HEADER) String requestId,
112             @ApiParam(value = "X-ECOMP-InstanceID header", required = true)@HeaderParam(value = Constants.X_ECOMP_INSTANCE_ID_HEADER) final String instanceIdHeader,
113             @ApiParam(value = "Determines the format of the body of the response", required = false)@HeaderParam(value = Constants.ACCEPT_HEADER) String accept,
114             @ApiParam(value = "The username and password", required = true)@HeaderParam(value = Constants.AUTHORIZATION_HEADER) String authorization,
115             @PathParam("serviceName") final String serviceName,
116             @PathParam("serviceVersion") final String serviceVersion,
117             @PathParam("artifactName") final String artifactName) {
118
119         Response response = null;
120         String requestURI = request.getRequestURI();
121         if (instanceIdHeader == null || instanceIdHeader.isEmpty()) {
122             log.debug(MISSING_X_ECOMP_INSTANCE_ID_HEADER);
123             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.MISSING_X_ECOMP_INSTANCE_ID);
124             getComponentsUtils().auditDistributionDownload(responseFormat, new DistributionData(instanceIdHeader, requestURI));
125             return buildErrorResponse(responseFormat);
126         }
127
128         try {
129             Either<byte[], ResponseFormat> downloadRsrcArtifactEither = artifactsBusinessLogic
130                 .downloadServiceArtifactByNames(serviceName, serviceVersion, artifactName);
131             if (downloadRsrcArtifactEither.isRight()) {
132                 ResponseFormat responseFormat = downloadRsrcArtifactEither.right().value();
133                 getComponentsUtils().auditDistributionDownload(responseFormat, new DistributionData(instanceIdHeader, requestURI));
134                 response = buildErrorResponse(responseFormat);
135             } else {
136                 byte[] value = downloadRsrcArtifactEither.left().value();
137                 InputStream is = new ByteArrayInputStream(value);
138
139                 Map<String, String> headers = new HashMap<>();
140                 headers.put(Constants.CONTENT_DISPOSITION_HEADER, getContentDispositionValue(artifactName));
141                 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.OK);
142                 getComponentsUtils().auditDistributionDownload(responseFormat, new DistributionData(instanceIdHeader, requestURI));
143                 response = buildOkResponse(responseFormat, is, headers);
144             }
145             return response;
146
147         } catch (Exception e) {
148             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("download Murano package artifact for service - external API");
149             log.debug(DOWNLOAD_ARTIFACT_FAILED_WITH_EXCEPTION, e);
150             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
151         }
152     }
153
154     /**
155      *
156      * @param requestId
157      * @param instanceIdHeader
158      * @param accept
159      * @param authorization
160      * @param serviceName
161      * @param serviceVersion
162      * @param resourceName
163      * @param resourceVersion
164      * @param artifactName
165      * @return
166      */
167     @GET
168     @Path("/services/{serviceName}/{serviceVersion}/resources/{resourceName}/{resourceVersion}/artifacts/{artifactName}")
169     @Consumes(MediaType.APPLICATION_JSON)
170     @Produces(MediaType.APPLICATION_OCTET_STREAM)
171     @ApiOperation(value = "Download resource artifact", httpMethod = "GET", notes = "Returns downloaded artifact", response = String.class)
172     @ApiResponses(value = {
173             @ApiResponse(code = 200, message = "The artifact is found and streamed.", response = String.class),
174             @ApiResponse(code = 400, message = "Missing  'X-ECOMP-InstanceID'  HTTP header - POL5001"),
175             @ApiResponse(code = 401, message = "ECOMP component  should authenticate itself  and  to  re-send  again  HTTP  request  with its Basic  Authentication credentials - POL5002"),
176             @ApiResponse(code = 403, message = "ECOMP component is not authorized - POL5003"),
177             @ApiResponse(code = 404, message = "Specified Service is not found - SVC4503"),
178             @ApiResponse(code = 404, message = "Specified Resource Instance  is not found - SVC4526"),
179             @ApiResponse(code = 404, message = "Specified Service Version is  not  found - SVC4504"),
180             @ApiResponse(code = 404, message = "Specified artifact is  not found - SVC4505"),
181             @ApiResponse(code = 405, message = "Method  Not Allowed: Invalid HTTP method type used (PUT,DELETE,POST will be rejected) - POL4050"),
182             @ApiResponse(code = 500, message = "The GET request failed either due to internal SDC problem or Cambria Service failure. ECOMP Component should continue the attempts to get the needed information - POL5000")})
183     public Response downloadResourceArtifact(
184             @ApiParam(value = "X-ECOMP-RequestID header", required = false)@HeaderParam(value = Constants.X_ECOMP_REQUEST_ID_HEADER) String requestId,
185             @ApiParam(value = "X-ECOMP-InstanceID header", required = true)@HeaderParam(value = Constants.X_ECOMP_INSTANCE_ID_HEADER) final String instanceIdHeader,
186             @ApiParam(value = "Determines the format of the body of the response", required = false)@HeaderParam(value = Constants.ACCEPT_HEADER) String accept,
187             @ApiParam(value = "The username and password", required = true)@HeaderParam(value = Constants.AUTHORIZATION_HEADER) String authorization,
188             @PathParam("serviceName") final String serviceName,
189             @PathParam("serviceVersion") final String serviceVersion,
190             @PathParam("resourceName") final String resourceName,
191             @PathParam("resourceVersion") final String resourceVersion,
192             @PathParam("artifactName") final String artifactName) {
193
194         Response response = null;
195         String requestURI = request.getRequestURI();
196
197         if (instanceIdHeader == null || instanceIdHeader.isEmpty()) {
198             log.debug(MISSING_X_ECOMP_INSTANCE_ID_HEADER);
199             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.MISSING_X_ECOMP_INSTANCE_ID);
200             getComponentsUtils().auditDistributionDownload(responseFormat, new DistributionData(instanceIdHeader, requestURI));
201             return buildErrorResponse(responseFormat);
202         }
203
204         try {
205             Either<byte[], ResponseFormat> downloadRsrcArtifactEither = artifactsBusinessLogic
206                 .downloadRsrcArtifactByNames(serviceName, serviceVersion, resourceName, resourceVersion, artifactName);
207             if (downloadRsrcArtifactEither.isRight()) {
208                 ResponseFormat responseFormat = downloadRsrcArtifactEither.right().value();
209                 getComponentsUtils().auditDistributionDownload(responseFormat, new DistributionData(instanceIdHeader, requestURI));
210                 response = buildErrorResponse(responseFormat);
211             } else {
212                 byte[] value = downloadRsrcArtifactEither.left().value();
213                 // Returning 64-encoded as it was received during upload
214                 InputStream is = new ByteArrayInputStream(value);
215                 Map<String, String> headers = new HashMap<>();
216                 headers.put(Constants.CONTENT_DISPOSITION_HEADER, getContentDispositionValue(artifactName));
217                 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.OK);
218                 getComponentsUtils().auditDistributionDownload(responseFormat, new DistributionData(instanceIdHeader, requestURI));
219                 response = buildOkResponse(responseFormat, is, headers);
220             }
221             return response;
222
223         } catch (Exception e) {
224             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("download interface artifact for resource - external API");
225             log.debug(DOWNLOAD_ARTIFACT_FAILED_WITH_EXCEPTION, e);
226             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
227         }
228     }
229
230     /**
231      *
232      * @param requestId
233      * @param instanceIdHeader
234      * @param accept
235      * @param authorization
236      * @param serviceName
237      * @param serviceVersion
238      * @param resourceInstanceName
239      * @param artifactName
240      * @return
241      */
242     @GET
243     @Path("/services/{serviceName}/{serviceVersion}/resourceInstances/{resourceInstanceName}/artifacts/{artifactName}")
244     @Consumes(MediaType.APPLICATION_JSON)
245     @Produces(MediaType.APPLICATION_OCTET_STREAM)
246     @ApiOperation(value = "Download resource instance artifact", httpMethod = "GET", notes = "Returns downloaded artifact", response = String.class)
247     @ApiResponses(value = {
248             @ApiResponse(code = 200, message = "The artifact is found and streamed.", response = String.class),
249             @ApiResponse(code = 400, message = "Missing  'X-ECOMP-InstanceID'  HTTP header - POL5001"),
250             @ApiResponse(code = 401, message = "ECOMP component  should authenticate itself  and  to  re-send  again  HTTP  request  with its Basic  Authentication credentials - POL5002"),
251             @ApiResponse(code = 403, message = "ECOMP component is not authorized - POL5003"),
252             @ApiResponse(code = 404, message = "Specified Service is not found - SVC4503"),
253             @ApiResponse(code = 404, message = "Specified Resource Instance  is not found - SVC4526"),
254             @ApiResponse(code = 404, message = "Specified Service Version is  not  found - SVC4504"),
255             @ApiResponse(code = 404, message = "Specified artifact is  not found - SVC4505"),
256             @ApiResponse(code = 405, message = "Method  Not Allowed: Invalid HTTP method type used (PUT,DELETE,POST will be rejected) - POL4050"),
257             @ApiResponse(code = 500, message = "The GET request failed either due to internal SDC problem or Cambria Service failure. ECOMP Component should continue the attempts to get the needed information - POL5000")})
258     public Response downloadResourceInstanceArtifactByName(
259             @ApiParam(value = "X-ECOMP-RequestID header", required = false)@HeaderParam(value = Constants.X_ECOMP_REQUEST_ID_HEADER) String requestId,
260             @ApiParam(value = "X-ECOMP-InstanceID header", required = true)@HeaderParam(value = Constants.X_ECOMP_INSTANCE_ID_HEADER) final String instanceIdHeader,
261             @ApiParam(value = "Determines the format of the body of the response", required = false)@HeaderParam(value = Constants.ACCEPT_HEADER) String accept,
262             @ApiParam(value = "The username and password", required = true)@HeaderParam(value = Constants.AUTHORIZATION_HEADER) String authorization,
263             @PathParam("serviceName") final String serviceName,
264             @PathParam("serviceVersion") final String serviceVersion,
265             @PathParam("resourceInstanceName") final String resourceInstanceName,
266             @PathParam("artifactName") final String artifactName) {
267
268         Response response = null;
269         String requestURI = request.getRequestURI();
270
271         if (instanceIdHeader == null || instanceIdHeader.isEmpty()) {
272             log.debug(MISSING_X_ECOMP_INSTANCE_ID_HEADER);
273             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.MISSING_X_ECOMP_INSTANCE_ID);
274             getComponentsUtils().auditDistributionDownload(responseFormat, new DistributionData(instanceIdHeader, requestURI));
275             return buildErrorResponse(responseFormat);
276         }
277
278         try {
279             Either<byte[], ResponseFormat> downloadRsrcArtifactEither = artifactsBusinessLogic
280                 .downloadRsrcInstArtifactByNames(serviceName, serviceVersion, resourceInstanceName, artifactName);
281             if (downloadRsrcArtifactEither.isRight()) {
282                 ResponseFormat responseFormat = downloadRsrcArtifactEither.right().value();
283                 getComponentsUtils().auditDistributionDownload(responseFormat, new DistributionData(instanceIdHeader, requestURI));
284                 response = buildErrorResponse(responseFormat);
285             } else {
286                 byte[] value = downloadRsrcArtifactEither.left().value();
287                 // Returning 64-encoded as it was received during upload
288                 InputStream is = new ByteArrayInputStream(value);
289                 Map<String, String> headers = new HashMap<>();
290                 headers.put(Constants.CONTENT_DISPOSITION_HEADER, getContentDispositionValue(artifactName));
291                 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.OK);
292                 getComponentsUtils().auditDistributionDownload(responseFormat, new DistributionData(instanceIdHeader, requestURI));
293                 response = buildOkResponse(responseFormat, is, headers);
294             }
295             return response;
296
297         } catch (Exception e) {
298             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("download interface artifact for resource - external API");
299             log.debug(DOWNLOAD_ARTIFACT_FAILED_WITH_EXCEPTION, e);
300             return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
301         }
302     }
303 }