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 org.apache.http.HttpStatus;
27 import org.json.JSONException;
28 import org.json.JSONObject;
29 import org.openecomp.sdc.be.components.impl.CsarValidationUtils;
30 import org.openecomp.sdc.be.components.impl.ImportUtils;
31 import org.openecomp.sdc.be.components.impl.ResourceBusinessLogic;
32 import org.openecomp.sdc.be.config.BeEcompErrorManager;
33 import org.openecomp.sdc.be.dao.api.ActionStatus;
34 import org.openecomp.sdc.be.datamodel.api.HighestFilterEnum;
35 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
36 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
37 import org.openecomp.sdc.be.model.Resource;
38 import org.openecomp.sdc.be.model.UploadResourceInfo;
39 import org.openecomp.sdc.be.model.User;
40 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
41 import org.openecomp.sdc.be.servlets.ResourceUploadServlet.ResourceAuthorityTypeEnum;
42 import org.openecomp.sdc.common.api.Constants;
43 import org.openecomp.sdc.common.datastructure.Wrapper;
44 import org.openecomp.sdc.common.log.wrappers.Logger;
45 import org.openecomp.sdc.exception.ResponseFormat;
47 import javax.inject.Singleton;
48 import javax.servlet.ServletContext;
49 import javax.servlet.http.HttpServletRequest;
51 import javax.ws.rs.core.Context;
52 import javax.ws.rs.core.MediaType;
53 import javax.ws.rs.core.Response;
54 import java.io.FileNotFoundException;
55 import java.io.IOException;
56 import java.util.List;
59 @Loggable(prepend = true, value = Loggable.DEBUG, trim = false)
61 @Api(value = "Resources Catalog", description = "Resources Servlet")
63 public class ResourcesServlet extends AbstractValidationsServlet {
65 private static final Logger log = Logger.getLogger(ResourcesServlet.class);
69 @Consumes(MediaType.APPLICATION_JSON)
70 @Produces(MediaType.APPLICATION_JSON)
71 @ApiOperation(value = "Create Resource", httpMethod = "POST", notes = "Returns created resource", response = Resource.class)
72 @ApiResponses(value = { @ApiResponse(code = 201, message = "Resource created"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content"),
73 @ApiResponse(code = 409, message = "Resource already exist") })
74 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) {
76 userId = (userId != null) ? userId : request.getHeader(Constants.USER_ID_HEADER);
79 ServletContext context = request.getSession().getServletContext();
81 String url = request.getMethod() + " " + request.getRequestURI();
82 log.debug("Start handle request of {}" , url);
85 User modifier = new User();
86 modifier.setUserId(userId);
87 log.debug("modifier id is {}", userId);
92 Wrapper<Response> responseWrapper = new Wrapper<>();
94 if (isUIImport(data)) {
95 performUIImport(responseWrapper, data, request, userId, null);
100 ResourceBusinessLogic businessLogic = getResourceBL(context);
102 Either<Resource, ResponseFormat> convertResponse = parseToResource(data, modifier);
103 if (convertResponse.isRight()) {
104 log.debug("failed to parse resource");
105 response = buildErrorResponse(convertResponse.right().value());
109 Resource resource = convertResponse.left().value();
110 Resource createdResource = businessLogic.createResource(resource, AuditingActionEnum.CREATE_RESOURCE, modifier, null, null);
111 Object representation = RepresentationUtils.toRepresentation(createdResource);
112 response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.CREATED), representation);
113 responseWrapper.setInnerElement(response);
115 return responseWrapper.getInnerElement();
116 } catch (IOException e) {
117 BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Create Resource");
118 log.debug("create resource failed with exception", e);
119 response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
124 private boolean isUIImport(String data) {
127 JSONObject json = new JSONObject(data);
128 String payloadName = json.getString(ImportUtils.Constants.UI_JSON_PAYLOAD_NAME);
129 isUIImport = payloadName != null && !payloadName.isEmpty();
130 } catch (JSONException e) {
131 log.debug("failed to parse json sent from client, json:{}", data, e);
137 private void performUIImport(Wrapper<Response> responseWrapper, String data, final HttpServletRequest request, String userId, String resourceUniqueId) throws FileNotFoundException {
139 Wrapper<User> userWrapper = new Wrapper<>();
140 Wrapper<UploadResourceInfo> uploadResourceInfoWrapper = new Wrapper<>();
141 Wrapper<String> yamlStringWrapper = new Wrapper<>();
143 ResourceAuthorityTypeEnum resourceAuthorityEnum = ResourceAuthorityTypeEnum.USER_TYPE_UI;
145 commonGeneralValidations(responseWrapper, userWrapper, uploadResourceInfoWrapper, resourceAuthorityEnum, userId, data);
147 if (!CsarValidationUtils.isCsarPayloadName(uploadResourceInfoWrapper.getInnerElement().getPayloadName())) {
148 fillPayload(responseWrapper, uploadResourceInfoWrapper, yamlStringWrapper, userWrapper.getInnerElement(), data, resourceAuthorityEnum, null);
150 // PayLoad Validations
151 commonPayloadValidations(responseWrapper, yamlStringWrapper, userWrapper.getInnerElement(), uploadResourceInfoWrapper.getInnerElement());
153 specificResourceAuthorityValidations(responseWrapper, uploadResourceInfoWrapper, yamlStringWrapper, userWrapper.getInnerElement(), request, data, resourceAuthorityEnum);
155 if (responseWrapper.isEmpty()) {
156 handleImport(responseWrapper, userWrapper.getInnerElement(), uploadResourceInfoWrapper.getInnerElement(), yamlStringWrapper.getInnerElement(), resourceAuthorityEnum, true, resourceUniqueId);
160 private Either<Resource, ResponseFormat> parseToResource(String resourceJson, User user) {
161 return getComponentsUtils().convertJsonToObjectUsingObjectMapper(resourceJson, user, Resource.class, AuditingActionEnum.CREATE_RESOURCE, ComponentTypeEnum.RESOURCE);
164 private Either<Resource, ResponseFormat> parseToLightResource(String resourceJson, User user) {
165 Either<Resource, ResponseFormat> ret = getComponentsUtils().convertJsonToObjectUsingObjectMapper(resourceJson, user, Resource.class, AuditingActionEnum.UPDATE_RESOURCE_METADATA, ComponentTypeEnum.RESOURCE);
166 if (ret.isLeft()) {// drop unwanted data (sent from UI in update flow)
167 ret.left().value().setRequirements(null);
168 ret.left().value().setCapabilities(null);
174 @Path("/resources/{resourceId}")
175 public Response deleteResource(@PathParam("resourceId") final String resourceId, @Context final HttpServletRequest request) {
177 ServletContext context = request.getSession().getServletContext();
179 String url = request.getMethod() + " " + request.getRequestURI();
180 log.debug("Start handle request of {}" , url);
183 String userId = request.getHeader(Constants.USER_ID_HEADER);
184 User modifier = new User();
185 modifier.setUserId(userId);
186 log.debug("modifier id is {}" , userId);
191 String resourceIdLower = resourceId.toLowerCase();
192 ResourceBusinessLogic businessLogic = getResourceBL(context);
193 ResponseFormat actionResponse = businessLogic.deleteResource(resourceIdLower, modifier);
195 if (actionResponse.getStatus() != HttpStatus.SC_NO_CONTENT) {
196 log.debug("failed to delete resource");
197 response = buildErrorResponse(actionResponse);
200 response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.NO_CONTENT), null);
203 } catch (JSONException e) {
204 BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Delete Resource");
205 log.debug("delete resource failed with exception", e);
206 response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
213 @Path("/resources/{resourceName}/{version}")
214 public Response deleteResourceByNameAndVersion(@PathParam("resourceName") final String resourceName, @PathParam("version") final String version, @Context final HttpServletRequest request) {
216 ServletContext context = request.getSession().getServletContext();
218 String url = request.getMethod() + " " + request.getRequestURI();
219 log.debug("Start handle request of {}" , url);
222 String userId = request.getHeader(Constants.USER_ID_HEADER);
223 User modifier = new User();
224 modifier.setUserId(userId);
225 log.debug("modifier id is {}" , userId);
228 ResourceBusinessLogic businessLogic = getResourceBL(context);
229 ResponseFormat actionResponse = businessLogic.deleteResourceByNameAndVersion(resourceName, version, modifier);
231 if (actionResponse.getStatus() != HttpStatus.SC_NO_CONTENT) {
232 log.debug("failed to delete resource");
233 response = buildErrorResponse(actionResponse);
236 response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.NO_CONTENT), null);
241 @Path("/resources/{resourceId}")
242 @Consumes(MediaType.APPLICATION_JSON)
243 @Produces(MediaType.APPLICATION_JSON)
244 @ApiOperation(value = "Retrieve Resource", httpMethod = "GET", notes = "Returns resource according to resourceId", response = Resource.class)
245 @ApiResponses(value = { @ApiResponse(code = 200, message = "Resource found"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 404, message = "Resource not found") })
246 public Response getResourceById(@PathParam("resourceId") final String resourceId, @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
248 ServletContext context = request.getSession().getServletContext();
250 String url = request.getMethod() + " " + request.getRequestURI();
251 log.debug("Start handle request of {}" , url);
254 User modifier = new User();
255 modifier.setUserId(userId);
256 log.debug("modifier id is {}" , userId);
261 String resourceIdLower = resourceId.toLowerCase();
262 ResourceBusinessLogic businessLogic = getResourceBL(context);
263 log.trace("get resource with id {}", resourceId);
264 Either<Resource, ResponseFormat> actionResponse = businessLogic.getResource(resourceIdLower, modifier);
266 if (actionResponse.isRight()) {
267 log.debug("failed to get resource");
268 response = buildErrorResponse(actionResponse.right().value());
271 Object resource = RepresentationUtils.toRepresentation(actionResponse.left().value());
272 return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), resource);
274 } catch (IOException e) {
275 BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get Resource");
276 log.debug("get resource failed with exception", e);
277 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
283 @Path("/resources/resourceName/{resourceName}/resourceVersion/{resourceVersion}")
284 @Consumes(MediaType.APPLICATION_JSON)
285 @Produces(MediaType.APPLICATION_JSON)
286 @ApiOperation(value = "Retrieve Resource by name and version", httpMethod = "GET", notes = "Returns resource according to resourceId", response = Resource.class)
287 @ApiResponses(value = { @ApiResponse(code = 200, message = "Resource found"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 404, message = "Resource not found") })
288 public Response getResourceByNameAndVersion(@PathParam("resourceName") final String resourceName, @PathParam("resourceVersion") final String resourceVersion, @Context final HttpServletRequest request,
289 @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
291 ServletContext context = request.getSession().getServletContext();
293 User modifier = new User();
294 modifier.setUserId(userId);
295 log.debug("modifier id is {}" , userId);
298 ResourceBusinessLogic businessLogic = getResourceBL(context);
299 Either<Resource, ResponseFormat> actionResponse = businessLogic.getResourceByNameAndVersion(resourceName, resourceVersion, userId);
300 if (actionResponse.isRight()) {
301 response = buildErrorResponse(actionResponse.right().value());
304 Object resource = RepresentationUtils.toRepresentation(actionResponse.left().value());
305 return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), resource);
307 } catch (IOException e) {
308 BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get Resource by name and version");
309 log.debug("get resource failed with exception", e);
310 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
316 @Path("/resources/validate-name/{resourceName}")
317 @Consumes(MediaType.APPLICATION_JSON)
318 @Produces(MediaType.APPLICATION_JSON)
319 @ApiOperation(value = "validate resource name", httpMethod = "GET", notes = "checks if the chosen resource name is available ", response = Response.class)
320 @ApiResponses(value = { @ApiResponse(code = 200, message = "Resource found"), @ApiResponse(code = 403, message = "Restricted operation") })
321 public Response validateResourceName(@PathParam("resourceName") final String resourceName, @QueryParam("subtype") String resourceType, @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
322 ServletContext context = request.getSession().getServletContext();
323 String url = request.getMethod() + " " + request.getRequestURI();
324 log.debug("Start handle request of {}" , url);
327 User modifier = new User();
328 modifier.setUserId(userId);
329 log.debug("modifier id is {}" , userId);
331 ResourceBusinessLogic businessLogic = getResourceBL(context);
333 if (resourceType != null && !ResourceTypeEnum.containsName(resourceType)) {
334 log.debug("invalid resource type received");
335 response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
339 ResourceTypeEnum typeEnum = null;
340 if (resourceType != null) {
341 typeEnum = ResourceTypeEnum.valueOf(resourceType);
343 Either<Map<String, Boolean>, ResponseFormat> actionResponse = businessLogic.validateResourceNameExists(resourceName, typeEnum, userId);
345 if (actionResponse.isRight()) {
346 log.debug("failed to validate resource name");
347 response = buildErrorResponse(actionResponse.right().value());
350 return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), actionResponse.left().value());
354 @Path("/resources/certified/abstract")
355 @Consumes(MediaType.APPLICATION_JSON)
356 @Produces(MediaType.APPLICATION_JSON)
357 public Response getCertifiedAbstractResources(@Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
359 ServletContext context = request.getSession().getServletContext();
361 String url = request.getMethod() + " " + request.getRequestURI();
362 log.debug("(get) Start handle request of {}" , url);
364 List<Resource> resources = getResourceBL(context)
365 .getAllCertifiedResources(true, HighestFilterEnum.HIGHEST_ONLY, userId);
366 return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), RepresentationUtils.toRepresentation(resources));
368 } catch (IOException e) {
369 BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get Certified Abstract Resources");
370 log.debug("getCertifiedAbstractResources failed with exception", e);
371 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
376 @Path("/resources/certified/notabstract")
377 @Consumes(MediaType.APPLICATION_JSON)
378 @Produces(MediaType.APPLICATION_JSON)
379 public Response getCertifiedNotAbstractResources(@Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
380 ServletContext context = request.getSession().getServletContext();
381 String url = request.getMethod() + " " + request.getRequestURI();
382 log.debug("(get) Start handle request of {}" , url);
384 ResourceBusinessLogic businessLogic = getResourceBL(context);
385 List<Resource> resouces = businessLogic.getAllCertifiedResources(false, HighestFilterEnum.ALL, userId);
386 return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), RepresentationUtils.toRepresentation(resouces));
388 } catch (IOException e) {
389 BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get Certified Non Abstract Resources");
390 log.debug("getCertifiedNotAbstractResources failed with exception", e);
391 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
397 @Path("/resources/{resourceId}/metadata")
398 @Consumes(MediaType.APPLICATION_JSON)
399 @Produces(MediaType.APPLICATION_JSON)
400 @ApiOperation(value = "Update Resource Metadata", httpMethod = "PUT", notes = "Returns updated resource metadata", response = Resource.class)
401 @ApiResponses(value = { @ApiResponse(code = 200, message = "Resource metadata updated"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content") })
402 public Response updateResourceMetadata(@PathParam("resourceId") final String resourceId, @ApiParam(value = "Resource metadata to be updated", required = true) String data, @Context final HttpServletRequest request,
403 @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
405 ServletContext context = request.getSession().getServletContext();
407 String url = request.getMethod() + " " + request.getRequestURI();
408 log.debug("Start handle request of {}" , url);
411 User modifier = new User();
412 modifier.setUserId(userId);
413 log.debug("modifier id is {}", userId);
416 ResourceBusinessLogic businessLogic = getResourceBL(context);
417 String resourceIdLower = resourceId.toLowerCase();
418 Either<Resource, ResponseFormat> updateInfoResource = getComponentsUtils().convertJsonToObjectUsingObjectMapper(data, modifier, Resource.class, AuditingActionEnum.UPDATE_RESOURCE_METADATA, ComponentTypeEnum.RESOURCE);
419 if (updateInfoResource.isRight()) {
420 log.debug("failed to parse resource metadata");
421 response = buildErrorResponse(updateInfoResource.right().value());
424 Resource updatedResource = businessLogic.updateResourceMetadata(resourceIdLower, updateInfoResource.left().value(), null, modifier, false);
425 Object resource = RepresentationUtils.toRepresentation(updatedResource);
426 return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), resource);
427 } catch (IOException e) {
428 BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Update Resource Metadata");
429 log.debug("Update Resource Metadata failed with exception", e);
430 response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
437 @Path("/resources/{resourceId}")
438 @Consumes(MediaType.APPLICATION_JSON)
439 @Produces(MediaType.APPLICATION_JSON)
440 @ApiOperation(value = "Update Resource", httpMethod = "PUT", notes = "Returns updated resource", response = Resource.class)
441 @ApiResponses(value = { @ApiResponse(code = 200, message = "Resource updated"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content"),
442 @ApiResponse(code = 409, message = "Resource already exist") })
443 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,
444 @PathParam(value = "resourceId") String resourceId) {
446 userId = (userId != null) ? userId : request.getHeader(Constants.USER_ID_HEADER);
448 ServletContext context = request.getSession().getServletContext();
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 ResourceBusinessLogic businessLogic = getResourceBL(context);
463 Either<Resource, ResponseFormat> convertResponse = parseToLightResource(data, modifier);
464 if (convertResponse.isRight()) {
465 log.debug("failed to parse resource");
466 response = buildErrorResponse(convertResponse.right().value());
469 Resource updatedResource = businessLogic.validateAndUpdateResourceFromCsar(convertResponse.left().value(), modifier, null, null, resourceId);
470 Object representation = RepresentationUtils.toRepresentation(updatedResource);
471 response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), representation);
472 responseWrapper.setInnerElement(response);
474 return responseWrapper.getInnerElement();
475 } catch (IOException e) {
476 BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Update Resource");
477 log.debug("update resource failed with exception", e);
478 response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
485 @Path("/resources/csar/{csaruuid}")
486 @Consumes(MediaType.APPLICATION_JSON)
487 @Produces(MediaType.APPLICATION_JSON)
488 @ApiOperation(value = "Create Resource", httpMethod = "POST", notes = "Returns resource created from csar uuid", response = Resource.class)
489 @ApiResponses(value = { @ApiResponse(code = 201, message = "Resource retrieced"), @ApiResponse(code = 403, message = "Restricted operation"), @ApiResponse(code = 400, message = "Invalid content / Missing content") })
490 public Response getResourceFromCsar(@Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId, @PathParam(value = "csaruuid") String csarUUID) {
494 ServletContext context = request.getSession().getServletContext();
496 String url = request.getMethod() + " " + request.getRequestURI();
497 log.debug("Start handle request of {}" , url);
499 // retrieve user details
500 userId = (userId != null) ? userId : request.getHeader(Constants.USER_ID_HEADER);
501 User user = new User();
502 user.setUserId(userId);
504 log.debug("user id is {}", userId);
510 ResourceBusinessLogic businessLogic = getResourceBL(context);
512 Either<Resource, ResponseFormat> eitherResource = businessLogic.getLatestResourceFromCsarUuid(csarUUID, user);
515 if (eitherResource.isRight()) {
516 log.debug("failed to get resource from csarUuid : {}", csarUUID);
517 response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), eitherResource.right().value());
519 Object representation = RepresentationUtils.toRepresentation(eitherResource.left().value());
520 response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), representation);
525 } catch (IOException e) {
526 log.debug("get resource by csar failed with exception", e);
527 response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));