2 * ============LICENSE_START=======================================================
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
21 package org.openecomp.sdc.be.servlets;
23 import com.jcabi.aspects.Loggable;
24 import fj.data.Either;
25 import io.swagger.annotations.*;
26 import javax.inject.Inject;
27 import org.apache.http.HttpStatus;
28 import org.json.JSONException;
29 import org.json.JSONObject;
30 import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;
31 import org.openecomp.sdc.be.components.impl.CsarValidationUtils;
32 import org.openecomp.sdc.be.components.impl.GroupBusinessLogic;
33 import org.openecomp.sdc.be.components.impl.ImportUtils;
34 import org.openecomp.sdc.be.components.impl.ResourceBusinessLogic;
35 import org.openecomp.sdc.be.components.impl.ResourceImportManager;
36 import org.openecomp.sdc.be.config.BeEcompErrorManager;
37 import org.openecomp.sdc.be.dao.api.ActionStatus;
38 import org.openecomp.sdc.be.datamodel.api.HighestFilterEnum;
39 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
40 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
41 import org.openecomp.sdc.be.impl.ComponentsUtils;
42 import org.openecomp.sdc.be.impl.ServletUtils;
43 import org.openecomp.sdc.be.model.Resource;
44 import org.openecomp.sdc.be.model.UploadResourceInfo;
45 import org.openecomp.sdc.be.model.User;
46 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
47 import org.openecomp.sdc.be.servlets.ResourceUploadServlet.ResourceAuthorityTypeEnum;
48 import org.openecomp.sdc.be.user.UserBusinessLogic;
49 import org.openecomp.sdc.common.api.Constants;
50 import org.openecomp.sdc.common.datastructure.Wrapper;
51 import org.openecomp.sdc.common.log.wrappers.Logger;
52 import org.openecomp.sdc.exception.ResponseFormat;
54 import javax.inject.Singleton;
55 import javax.servlet.ServletContext;
56 import javax.servlet.http.HttpServletRequest;
58 import javax.ws.rs.core.Context;
59 import javax.ws.rs.core.MediaType;
60 import javax.ws.rs.core.Response;
61 import java.io.FileNotFoundException;
62 import java.io.IOException;
63 import java.util.List;
66 @Loggable(prepend = true, value = Loggable.DEBUG, trim = false)
68 @Api(value = "Resources Catalog", description = "Resources Servlet")
70 public class ResourcesServlet extends AbstractValidationsServlet {
72 private static final Logger log = Logger.getLogger(ResourcesServlet.class);
73 private final ResourceBusinessLogic resourceBusinessLogic;
76 public ResourcesServlet(UserBusinessLogic userBusinessLogic,
77 ComponentInstanceBusinessLogic componentInstanceBL,
78 ResourceBusinessLogic resourceBusinessLogic,
79 ComponentsUtils componentsUtils, ServletUtils servletUtils,
80 ResourceImportManager resourceImportManager) {
81 super(userBusinessLogic, componentInstanceBL, componentsUtils, servletUtils, resourceImportManager);
82 this.resourceBusinessLogic = resourceBusinessLogic;
87 @Consumes(MediaType.APPLICATION_JSON)
88 @Produces(MediaType.APPLICATION_JSON)
89 @ApiOperation(value = "Create Resource", httpMethod = "POST", notes = "Returns created resource", response = Resource.class)
90 @ApiResponses(value = { @ApiResponse(code = 201, message = "Resource created"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content"),
91 @ApiResponse(code = 409, message = "Resource already exist") })
92 public Response createResource(@ApiParam(value = "Resource object to be created", required = true) String data, @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
94 userId = (userId != null) ? userId : request.getHeader(Constants.USER_ID_HEADER);
97 String url = request.getMethod() + " " + request.getRequestURI();
98 log.debug("Start handle request of {}" , url);
101 User modifier = new User();
102 modifier.setUserId(userId);
103 log.debug("modifier id is {}", userId);
108 Wrapper<Response> responseWrapper = new Wrapper<>();
110 if (isUIImport(data)) {
111 performUIImport(responseWrapper, data, request, userId, null);
116 Either<Resource, ResponseFormat> convertResponse = parseToResource(data, modifier);
117 if (convertResponse.isRight()) {
118 log.debug("failed to parse resource");
119 response = buildErrorResponse(convertResponse.right().value());
123 Resource resource = convertResponse.left().value();
124 Resource createdResource = resourceBusinessLogic.createResource(resource, AuditingActionEnum.CREATE_RESOURCE, modifier, null, null);
125 Object representation = RepresentationUtils.toRepresentation(createdResource);
126 response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.CREATED), representation);
127 responseWrapper.setInnerElement(response);
129 return responseWrapper.getInnerElement();
130 } catch (IOException e) {
131 BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Create Resource");
132 log.debug("create resource failed with exception", e);
133 response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
138 private boolean isUIImport(String data) {
141 JSONObject json = new JSONObject(data);
142 String payloadName = json.getString(ImportUtils.Constants.UI_JSON_PAYLOAD_NAME);
143 isUIImport = payloadName != null && !payloadName.isEmpty();
144 } catch (JSONException e) {
145 log.debug("failed to parse json sent from client, json:{}", data, e);
151 private void performUIImport(Wrapper<Response> responseWrapper, String data, final HttpServletRequest request, String userId, String resourceUniqueId) throws FileNotFoundException {
153 Wrapper<User> userWrapper = new Wrapper<>();
154 Wrapper<UploadResourceInfo> uploadResourceInfoWrapper = new Wrapper<>();
155 Wrapper<String> yamlStringWrapper = new Wrapper<>();
157 ResourceAuthorityTypeEnum resourceAuthorityEnum = ResourceAuthorityTypeEnum.USER_TYPE_UI;
159 commonGeneralValidations(responseWrapper, userWrapper, uploadResourceInfoWrapper, resourceAuthorityEnum, userId, data);
161 if (!CsarValidationUtils.isCsarPayloadName(uploadResourceInfoWrapper.getInnerElement().getPayloadName())) {
162 fillPayload(responseWrapper, uploadResourceInfoWrapper, yamlStringWrapper, userWrapper.getInnerElement(), data, resourceAuthorityEnum, null);
164 // PayLoad Validations
165 commonPayloadValidations(responseWrapper, yamlStringWrapper, userWrapper.getInnerElement(), uploadResourceInfoWrapper.getInnerElement());
167 specificResourceAuthorityValidations(responseWrapper, uploadResourceInfoWrapper, yamlStringWrapper, userWrapper.getInnerElement(), request, data, resourceAuthorityEnum);
169 if (responseWrapper.isEmpty()) {
170 handleImport(responseWrapper, userWrapper.getInnerElement(), uploadResourceInfoWrapper.getInnerElement(), yamlStringWrapper.getInnerElement(), resourceAuthorityEnum, true, resourceUniqueId);
174 private Either<Resource, ResponseFormat> parseToResource(String resourceJson, User user) {
175 return getComponentsUtils().convertJsonToObjectUsingObjectMapper(resourceJson, user, Resource.class, AuditingActionEnum.CREATE_RESOURCE, ComponentTypeEnum.RESOURCE);
178 private Either<Resource, ResponseFormat> parseToLightResource(String resourceJson, User user) {
179 Either<Resource, ResponseFormat> ret = getComponentsUtils().convertJsonToObjectUsingObjectMapper(resourceJson, user, Resource.class, AuditingActionEnum.UPDATE_RESOURCE_METADATA, ComponentTypeEnum.RESOURCE);
180 if (ret.isLeft()) {// drop unwanted data (sent from UI in update flow)
181 ret.left().value().setRequirements(null);
182 ret.left().value().setCapabilities(null);
188 @Path("/resources/{resourceId}")
189 public Response deleteResource(@PathParam("resourceId") final String resourceId, @Context final HttpServletRequest request) {
191 ServletContext context = request.getSession().getServletContext();
193 String url = request.getMethod() + " " + request.getRequestURI();
194 log.debug("Start handle request of {}" , url);
197 String userId = request.getHeader(Constants.USER_ID_HEADER);
198 User modifier = new User();
199 modifier.setUserId(userId);
200 log.debug("modifier id is {}" , userId);
205 String resourceIdLower = resourceId.toLowerCase();
206 ResponseFormat actionResponse = resourceBusinessLogic.deleteResource(resourceIdLower, modifier);
208 if (actionResponse.getStatus() != HttpStatus.SC_NO_CONTENT) {
209 log.debug("failed to delete resource");
210 response = buildErrorResponse(actionResponse);
213 response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.NO_CONTENT), null);
216 } catch (JSONException e) {
217 BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Delete Resource");
218 log.debug("delete resource failed with exception", e);
219 response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
226 @Path("/resources/{resourceName}/{version}")
227 public Response deleteResourceByNameAndVersion(@PathParam("resourceName") final String resourceName, @PathParam("version") final String version, @Context final HttpServletRequest request) {
229 ServletContext context = request.getSession().getServletContext();
231 String url = request.getMethod() + " " + request.getRequestURI();
232 log.debug("Start handle request of {}" , url);
235 String userId = request.getHeader(Constants.USER_ID_HEADER);
236 User modifier = new User();
237 modifier.setUserId(userId);
238 log.debug("modifier id is {}" , userId);
241 ResponseFormat actionResponse = resourceBusinessLogic.deleteResourceByNameAndVersion(resourceName, version, modifier);
243 if (actionResponse.getStatus() != HttpStatus.SC_NO_CONTENT) {
244 log.debug("failed to delete resource");
245 response = buildErrorResponse(actionResponse);
248 response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.NO_CONTENT), null);
253 @Path("/resources/{resourceId}")
254 @Consumes(MediaType.APPLICATION_JSON)
255 @Produces(MediaType.APPLICATION_JSON)
256 @ApiOperation(value = "Retrieve Resource", httpMethod = "GET", notes = "Returns resource according to resourceId", response = Resource.class)
257 @ApiResponses(value = { @ApiResponse(code = 200, message = "Resource found"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 404, message = "Resource not found") })
258 public Response getResourceById(@PathParam("resourceId") final String resourceId, @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
260 ServletContext context = request.getSession().getServletContext();
262 String url = request.getMethod() + " " + request.getRequestURI();
263 log.debug("Start handle request of {}" , url);
266 User modifier = new User();
267 modifier.setUserId(userId);
268 log.debug("modifier id is {}" , userId);
273 String resourceIdLower = resourceId.toLowerCase();
274 log.trace("get resource with id {}", resourceId);
275 Either<Resource, ResponseFormat> actionResponse = resourceBusinessLogic.getResource(resourceIdLower, modifier);
277 if (actionResponse.isRight()) {
278 log.debug("failed to get resource");
279 response = buildErrorResponse(actionResponse.right().value());
282 Object resource = RepresentationUtils.toRepresentation(actionResponse.left().value());
283 return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), resource);
285 } catch (IOException e) {
286 BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get Resource");
287 log.debug("get resource failed with exception", e);
288 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
294 @Path("/resources/resourceName/{resourceName}/resourceVersion/{resourceVersion}")
295 @Consumes(MediaType.APPLICATION_JSON)
296 @Produces(MediaType.APPLICATION_JSON)
297 @ApiOperation(value = "Retrieve Resource by name and version", httpMethod = "GET", notes = "Returns resource according to resourceId", response = Resource.class)
298 @ApiResponses(value = { @ApiResponse(code = 200, message = "Resource found"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 404, message = "Resource not found") })
299 public Response getResourceByNameAndVersion(@PathParam("resourceName") final String resourceName, @PathParam("resourceVersion") final String resourceVersion, @Context final HttpServletRequest request,
300 @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
302 ServletContext context = request.getSession().getServletContext();
304 User modifier = new User();
305 modifier.setUserId(userId);
306 log.debug("modifier id is {}" , userId);
309 Either<Resource, ResponseFormat> actionResponse = resourceBusinessLogic.getResourceByNameAndVersion(resourceName, resourceVersion, userId);
310 if (actionResponse.isRight()) {
311 response = buildErrorResponse(actionResponse.right().value());
314 Object resource = RepresentationUtils.toRepresentation(actionResponse.left().value());
315 return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), resource);
317 } catch (IOException e) {
318 BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get Resource by name and version");
319 log.debug("get resource failed with exception", e);
320 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
326 @Path("/resources/validate-name/{resourceName}")
327 @Consumes(MediaType.APPLICATION_JSON)
328 @Produces(MediaType.APPLICATION_JSON)
329 @ApiOperation(value = "validate resource name", httpMethod = "GET", notes = "checks if the chosen resource name is available ", response = Response.class)
330 @ApiResponses(value = { @ApiResponse(code = 200, message = "Resource found"), @ApiResponse(code = 403, message = "Restricted operation") })
331 public Response validateResourceName(@PathParam("resourceName") final String resourceName, @QueryParam("subtype") String resourceType, @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
332 ServletContext context = request.getSession().getServletContext();
333 String url = request.getMethod() + " " + request.getRequestURI();
334 log.debug("Start handle request of {}" , url);
337 User modifier = new User();
338 modifier.setUserId(userId);
339 log.debug("modifier id is {}" , userId);
342 if (resourceType != null && !ResourceTypeEnum.containsName(resourceType)) {
343 log.debug("invalid resource type received");
344 response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
348 ResourceTypeEnum typeEnum = null;
349 if (resourceType != null) {
350 typeEnum = ResourceTypeEnum.valueOf(resourceType);
352 Either<Map<String, Boolean>, ResponseFormat> actionResponse = resourceBusinessLogic.validateResourceNameExists(resourceName, typeEnum, userId);
354 if (actionResponse.isRight()) {
355 log.debug("failed to validate resource name");
356 response = buildErrorResponse(actionResponse.right().value());
359 return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), actionResponse.left().value());
363 @Path("/resources/certified/abstract")
364 @Consumes(MediaType.APPLICATION_JSON)
365 @Produces(MediaType.APPLICATION_JSON)
366 public Response getCertifiedAbstractResources(@Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
367 String url = request.getMethod() + " " + request.getRequestURI();
368 log.debug("(get) Start handle request of {}" , url);
370 List<Resource> resources = resourceBusinessLogic
371 .getAllCertifiedResources(true, HighestFilterEnum.HIGHEST_ONLY, userId);
372 return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), RepresentationUtils.toRepresentation(resources));
374 } catch (IOException e) {
375 BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get Certified Abstract Resources");
376 log.debug("getCertifiedAbstractResources failed with exception", e);
377 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
382 @Path("/resources/certified/notabstract")
383 @Consumes(MediaType.APPLICATION_JSON)
384 @Produces(MediaType.APPLICATION_JSON)
385 public Response getCertifiedNotAbstractResources(@Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
386 String url = request.getMethod() + " " + request.getRequestURI();
387 log.debug("(get) Start handle request of {}" , url);
389 List<Resource> resouces = resourceBusinessLogic.getAllCertifiedResources(false, HighestFilterEnum.ALL, userId);
390 return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), RepresentationUtils.toRepresentation(resouces));
392 } catch (IOException e) {
393 BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get Certified Non Abstract Resources");
394 log.debug("getCertifiedNotAbstractResources failed with exception", e);
395 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
401 @Path("/resources/{resourceId}/metadata")
402 @Consumes(MediaType.APPLICATION_JSON)
403 @Produces(MediaType.APPLICATION_JSON)
404 @ApiOperation(value = "Update Resource Metadata", httpMethod = "PUT", notes = "Returns updated resource metadata", response = Resource.class)
405 @ApiResponses(value = { @ApiResponse(code = 200, message = "Resource metadata updated"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content") })
406 public Response updateResourceMetadata(@PathParam("resourceId") final String resourceId, @ApiParam(value = "Resource metadata to be updated", required = true) String data, @Context final HttpServletRequest request,
407 @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
409 String url = request.getMethod() + " " + request.getRequestURI();
410 log.debug("Start handle request of {}" , url);
413 User modifier = new User();
414 modifier.setUserId(userId);
415 log.debug("modifier id is {}", userId);
418 String resourceIdLower = resourceId.toLowerCase();
419 Either<Resource, ResponseFormat> updateInfoResource = getComponentsUtils().convertJsonToObjectUsingObjectMapper(data, modifier, Resource.class, AuditingActionEnum.UPDATE_RESOURCE_METADATA, ComponentTypeEnum.RESOURCE);
420 if (updateInfoResource.isRight()) {
421 log.debug("failed to parse resource metadata");
422 response = buildErrorResponse(updateInfoResource.right().value());
425 Resource updatedResource = resourceBusinessLogic.updateResourceMetadata(resourceIdLower, updateInfoResource.left().value(), null, modifier, false);
426 Object resource = RepresentationUtils.toRepresentation(updatedResource);
427 return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), resource);
428 } catch (IOException e) {
429 BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Update Resource Metadata");
430 log.debug("Update Resource Metadata failed with exception", e);
431 response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
438 @Path("/resources/{resourceId}")
439 @Consumes(MediaType.APPLICATION_JSON)
440 @Produces(MediaType.APPLICATION_JSON)
441 @ApiOperation(value = "Update Resource", httpMethod = "PUT", notes = "Returns updated resource", response = Resource.class)
442 @ApiResponses(value = { @ApiResponse(code = 200, message = "Resource updated"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content"),
443 @ApiResponse(code = 409, message = "Resource already exist") })
444 public Response updateResource(@ApiParam(value = "Resource object to be updated", required = true) String data, @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId,
445 @PathParam(value = "resourceId") String resourceId) {
447 userId = (userId != null) ? userId : request.getHeader(Constants.USER_ID_HEADER);
449 String url = request.getMethod() + " " + request.getRequestURI();
450 log.debug("Start handle request of {}" , url);
452 User modifier = new User();
453 modifier.setUserId(userId);
454 log.debug("modifier id is {}", userId);
457 Wrapper<Response> responseWrapper = new Wrapper<>();
459 if (isUIImport(data)) {
460 performUIImport(responseWrapper, data, request, userId, resourceId);
462 Either<Resource, ResponseFormat> convertResponse = parseToLightResource(data, modifier);
463 if (convertResponse.isRight()) {
464 log.debug("failed to parse resource");
465 response = buildErrorResponse(convertResponse.right().value());
468 Resource updatedResource = resourceBusinessLogic.validateAndUpdateResourceFromCsar(convertResponse.left().value(), modifier, null, null, resourceId);
469 Object representation = RepresentationUtils.toRepresentation(updatedResource);
470 response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), representation);
471 responseWrapper.setInnerElement(response);
473 return responseWrapper.getInnerElement();
474 } catch (IOException e) {
475 BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Update Resource");
476 log.debug("update resource failed with exception", e);
477 response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
484 @Path("/resources/csar/{csaruuid}")
485 @Consumes(MediaType.APPLICATION_JSON)
486 @Produces(MediaType.APPLICATION_JSON)
487 @ApiOperation(value = "Create Resource", httpMethod = "POST", notes = "Returns resource created from csar uuid", response = Resource.class)
488 @ApiResponses(value = { @ApiResponse(code = 201, message = "Resource retrieced"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content") })
489 public Response getResourceFromCsar(@Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId, @PathParam(value = "csaruuid") String csarUUID) {
493 String url = request.getMethod() + " " + request.getRequestURI();
494 log.debug("Start handle request of {}" , url);
496 // retrieve user details
497 userId = (userId != null) ? userId : request.getHeader(Constants.USER_ID_HEADER);
498 User user = new User();
499 user.setUserId(userId);
501 log.debug("user id is {}", userId);
507 Either<Resource, ResponseFormat> eitherResource = resourceBusinessLogic.getLatestResourceFromCsarUuid(csarUUID, user);
510 if (eitherResource.isRight()) {
511 log.debug("failed to get resource from csarUuid : {}", csarUUID);
512 response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), eitherResource.right().value());
514 Object representation = RepresentationUtils.toRepresentation(eitherResource.left().value());
515 response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), representation);
520 } catch (IOException e) {
521 log.debug("get resource by csar failed with exception", e);
522 response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));