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.fasterxml.jackson.databind.DeserializationFeature;
24 import com.fasterxml.jackson.databind.ObjectMapper;
25 import com.fasterxml.jackson.databind.module.SimpleModule;
26 import com.google.gson.Gson;
27 import com.google.gson.GsonBuilder;
28 import com.google.gson.reflect.TypeToken;
29 import fj.data.Either;
30 import java.lang.reflect.Type;
31 import java.util.HashMap;
32 import java.util.Iterator;
33 import java.util.List;
35 import java.util.Map.Entry;
36 import java.util.Objects;
38 import java.util.function.Supplier;
39 import javax.servlet.ServletContext;
40 import javax.servlet.http.HttpServletRequest;
41 import javax.ws.rs.core.Context;
42 import javax.ws.rs.core.Response;
43 import javax.ws.rs.core.Response.ResponseBuilder;
44 import org.json.simple.JSONArray;
45 import org.json.simple.JSONObject;
46 import org.json.simple.parser.JSONParser;
47 import org.json.simple.parser.ParseException;
48 import org.openecomp.sdc.be.components.impl.ArtifactsBusinessLogic;
49 import org.openecomp.sdc.be.components.impl.BaseBusinessLogic;
50 import org.openecomp.sdc.be.components.impl.CapabilitiesBusinessLogic;
51 import org.openecomp.sdc.be.components.impl.ComponentBusinessLogic;
52 import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;
53 import org.openecomp.sdc.be.components.impl.ElementBusinessLogic;
54 import org.openecomp.sdc.be.components.impl.GenericArtifactBrowserBusinessLogic;
55 import org.openecomp.sdc.be.components.impl.GroupBusinessLogic;
56 import org.openecomp.sdc.be.components.impl.InputsBusinessLogic;
57 import org.openecomp.sdc.be.components.impl.InterfaceOperationBusinessLogic;
58 import org.openecomp.sdc.be.components.impl.MonitoringBusinessLogic;
59 import org.openecomp.sdc.be.components.impl.PolicyBusinessLogic;
60 import org.openecomp.sdc.be.components.impl.ProductBusinessLogic;
61 import org.openecomp.sdc.be.components.impl.PropertyBusinessLogic;
62 import org.openecomp.sdc.be.components.impl.RelationshipTypeBusinessLogic;
63 import org.openecomp.sdc.be.components.impl.RequirementBusinessLogic;
64 import org.openecomp.sdc.be.components.impl.ResourceBusinessLogic;
65 import org.openecomp.sdc.be.components.impl.ServiceBusinessLogic;
66 import org.openecomp.sdc.be.components.lifecycle.LifecycleBusinessLogic;
67 import org.openecomp.sdc.be.components.scheduledtasks.ComponentsCleanBusinessLogic;
68 import org.openecomp.sdc.be.components.upgrade.UpgradeBusinessLogic;
69 import org.openecomp.sdc.be.config.BeEcompErrorManager;
70 import org.openecomp.sdc.be.dao.api.ActionStatus;
71 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
72 import org.openecomp.sdc.be.datatypes.enums.DeclarationTypeEnum;
73 import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition;
74 import org.openecomp.sdc.be.ecomp.converters.AssetMetadataConverter;
75 import org.openecomp.sdc.be.impl.ComponentsUtils;
76 import org.openecomp.sdc.be.impl.WebAppContextWrapper;
77 import org.openecomp.sdc.be.model.ComponentInstInputsMap;
78 import org.openecomp.sdc.be.model.PropertyConstraint;
79 import org.openecomp.sdc.be.model.PropertyDefinition;
80 import org.openecomp.sdc.be.model.User;
81 import org.openecomp.sdc.be.model.operations.impl.PropertyOperation;
82 import org.openecomp.sdc.be.model.operations.impl.PropertyOperation.PropertyConstraintJacksonDeserializer;
83 import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
84 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
85 import org.openecomp.sdc.be.user.UserBusinessLogic;
86 import org.openecomp.sdc.common.api.Constants;
87 import org.openecomp.sdc.common.datastructure.Wrapper;
88 import org.openecomp.sdc.common.log.wrappers.Logger;
89 import org.openecomp.sdc.common.servlets.BasicServlet;
90 import org.openecomp.sdc.exception.ResponseFormat;
91 import org.springframework.web.context.WebApplicationContext;
93 public class BeGenericServlet extends BasicServlet {
96 protected HttpServletRequest servletRequest;
98 private static final Logger log = Logger.getLogger(BeGenericServlet.class);
100 private static final String PROPERTY_NAME_REGEX = "[\\w,\\d,_]+";
102 /******************** New error response mechanism
103 * @param requestErrorWrapper **************/
105 protected Response buildErrorResponse(ResponseFormat requestErrorWrapper) {
106 return Response.status(requestErrorWrapper.getStatus()).entity(gson.toJson(requestErrorWrapper.getRequestError())).build();
109 protected Response buildGeneralErrorResponse() {
110 return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
113 protected Response buildOkResponse(Object entity) {
114 return buildOkResponseStatic(entity);
117 private static Response buildOkResponseStatic(Object entity) {
118 return Response.status(Response.Status.OK)
123 protected Response buildOkResponse(ResponseFormat errorResponseWrapper, Object entity) {
124 return buildOkResponse(errorResponseWrapper, entity, null);
127 protected Response buildOkResponse(ResponseFormat errorResponseWrapper, Object entity, Map<String, String> additionalHeaders) {
128 int status = errorResponseWrapper.getStatus();
129 ResponseBuilder responseBuilder = Response.status(status);
130 if (entity != null) {
131 if (log.isTraceEnabled())
132 log.trace("returned entity is {}", entity.toString());
133 responseBuilder = responseBuilder.entity(entity);
135 if (additionalHeaders != null) {
136 for (Entry<String, String> additionalHeader : additionalHeaders.entrySet()) {
137 String headerName = additionalHeader.getKey();
138 String headerValue = additionalHeader.getValue();
139 if (log.isTraceEnabled())
140 log.trace("Adding header {} with value {} to the response", headerName, headerValue);
141 responseBuilder.header(headerName, headerValue);
144 return responseBuilder.build();
147 /*******************************************************************************************************/
148 protected Either<User, ResponseFormat> getUser(final HttpServletRequest request, String userId) {
149 Either<User, ActionStatus> eitherCreator = getUserAdminManager(request.getSession().getServletContext()).getUser(userId, false);
150 if (eitherCreator.isRight()) {
151 log.info("createResource method - user is not listed. userId= {}", userId);
152 ResponseFormat errorResponse = getComponentsUtils().getResponseFormat(ActionStatus.MISSING_INFORMATION);
153 User user = new User("", "", userId, "", null, null);
155 getComponentsUtils().auditResource(errorResponse, user, "", AuditingActionEnum.CHECKOUT_RESOURCE);
156 return Either.right(errorResponse);
158 return Either.left(eitherCreator.left().value());
162 UserBusinessLogic getUserAdminManager(ServletContext context) {
163 return getClassFromWebAppContext(context, () -> UserBusinessLogic.class);
166 protected GenericArtifactBrowserBusinessLogic getGenericArtifactBrowserBL(ServletContext context) {
167 return getClassFromWebAppContext(context, () -> GenericArtifactBrowserBusinessLogic.class);
170 protected ResourceBusinessLogic getResourceBL(ServletContext context) {
171 return getClassFromWebAppContext(context, () -> ResourceBusinessLogic.class);
174 protected InterfaceOperationBusinessLogic getInterfaceOperationBL(ServletContext context) {
175 return getClassFromWebAppContext(context, () -> InterfaceOperationBusinessLogic.class);
178 protected CapabilitiesBusinessLogic getCapabilitiesBL(ServletContext context) {
179 return getClassFromWebAppContext(context, () -> CapabilitiesBusinessLogic.class);
182 protected RelationshipTypeBusinessLogic getRelationshipTypeBL(ServletContext context) {
183 return getClassFromWebAppContext(context, () -> RelationshipTypeBusinessLogic.class);
185 protected RequirementBusinessLogic getRequirementBL(ServletContext context) {
186 return getClassFromWebAppContext(context, () -> RequirementBusinessLogic.class);
188 ComponentsCleanBusinessLogic getComponentCleanerBL(ServletContext context) {
189 return getClassFromWebAppContext(context, () -> ComponentsCleanBusinessLogic.class);
192 protected ServiceBusinessLogic getServiceBL(ServletContext context) {
193 return getClassFromWebAppContext(context, () -> ServiceBusinessLogic.class);
196 ProductBusinessLogic getProductBL(ServletContext context) {
197 return getClassFromWebAppContext(context, () -> ProductBusinessLogic.class);
200 protected ArtifactsBusinessLogic getArtifactBL(ServletContext context) {
201 return getClassFromWebAppContext(context, () -> ArtifactsBusinessLogic.class);
203 protected UpgradeBusinessLogic getUpgradeBL(ServletContext context) {
204 return getClassFromWebAppContext(context, () -> UpgradeBusinessLogic.class);
207 protected ElementBusinessLogic getElementBL(ServletContext context) {
208 return getClassFromWebAppContext(context, () -> ElementBusinessLogic.class);
211 MonitoringBusinessLogic getMonitoringBL(ServletContext context) {
212 return getClassFromWebAppContext(context, () -> MonitoringBusinessLogic.class);
215 protected AssetMetadataConverter getAssetUtils(ServletContext context) {
216 return getClassFromWebAppContext(context, () -> AssetMetadataConverter.class);
219 protected LifecycleBusinessLogic getLifecycleBL(ServletContext context) {
220 return getClassFromWebAppContext(context, () -> LifecycleBusinessLogic.class);
223 <T> T getClassFromWebAppContext(ServletContext context, Supplier<Class<T>> businessLogicClassGen) {
224 WebAppContextWrapper webApplicationContextWrapper = (WebAppContextWrapper) context.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR);
225 WebApplicationContext webApplicationContext = webApplicationContextWrapper.getWebAppContext(context);
226 return webApplicationContext.getBean(businessLogicClassGen.get());
229 GroupBusinessLogic getGroupBL(ServletContext context) {
231 WebAppContextWrapper webApplicationContextWrapper = (WebAppContextWrapper) context.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR);
232 WebApplicationContext webApplicationContext = webApplicationContextWrapper.getWebAppContext(context);
233 return webApplicationContext.getBean(GroupBusinessLogic.class);
236 protected ComponentInstanceBusinessLogic getComponentInstanceBL(ServletContext context) {
237 WebAppContextWrapper webApplicationContextWrapper = (WebAppContextWrapper) context.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR);
238 WebApplicationContext webApplicationContext = webApplicationContextWrapper.getWebAppContext(context);
239 return webApplicationContext.getBean(ComponentInstanceBusinessLogic.class);
242 protected ComponentsUtils getComponentsUtils() {
243 ServletContext context = this.servletRequest.getSession().getServletContext();
245 WebAppContextWrapper webApplicationContextWrapper = (WebAppContextWrapper) context.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR);
246 WebApplicationContext webApplicationContext = webApplicationContextWrapper.getWebAppContext(context);
247 return webApplicationContext.getBean(ComponentsUtils.class);
251 * Used to support Unit Test.<br>
252 * Header Params are not supported in Unit Tests
256 String initHeaderParam(String headerValue, HttpServletRequest request, String headerName) {
258 if (headerValue != null) {
259 retValue = headerValue;
261 retValue = request.getHeader(headerName);
266 protected String getContentDispositionValue(String artifactFileName) {
267 return new StringBuilder().append("attachment; filename=\"").append(artifactFileName).append("\"").toString();
272 protected ComponentBusinessLogic getComponentBL(ComponentTypeEnum componentTypeEnum, ServletContext context) {
273 ComponentBusinessLogic businessLogic;
274 switch (componentTypeEnum) {
276 businessLogic = getResourceBL(context);
279 businessLogic = getServiceBL(context);
282 businessLogic = getProductBL(context);
284 case RESOURCE_INSTANCE:
285 businessLogic = getResourceBL(context);
288 BeEcompErrorManager.getInstance().logBeSystemError("getComponentBL");
289 throw new IllegalArgumentException("Illegal component type:" + componentTypeEnum.getValue());
291 return businessLogic;
294 <T> void convertJsonToObjectOfClass(String json, Wrapper<T> policyWrapper, Class<T> clazz, Wrapper<Response> errorWrapper) {
296 ObjectMapper mapper = new ObjectMapper()
297 .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
298 .configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
300 log.trace("Starting to convert json to object. Json=\n{}", json);
302 SimpleModule module = new SimpleModule("customDeserializationModule");
303 module.addDeserializer(PropertyConstraint.class, new PropertyConstraintJacksonDeserializer());
304 mapper.registerModule(module);
306 object = mapper.readValue(json, clazz);
307 if (object != null) {
308 policyWrapper.setInnerElement(object);
310 BeEcompErrorManager.getInstance().logBeInvalidJsonInput("convertJsonToObject");
311 log.debug("The object of class {} is null after converting from json. ", clazz);
312 errorWrapper.setInnerElement(buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT)));
314 } catch (Exception e) {
315 BeEcompErrorManager.getInstance().logBeInvalidJsonInput("convertJsonToObject");
316 log.debug("The exception {} occured upon json to object convertation. Json=\n{}", e, json);
317 errorWrapper.setInnerElement(buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT)));
321 protected Either<Map<String, PropertyDefinition>, ActionStatus> getPropertyModel(String componentId, String data) {
322 JSONParser parser = new JSONParser();
325 Map<String, PropertyDefinition> properties = new HashMap<>();
326 root = (JSONObject) parser.parse(data);
328 Set entrySet = root.entrySet();
329 Iterator iterator = entrySet.iterator();
330 while (iterator.hasNext()) {
331 Entry next = (Entry) iterator.next();
332 String propertyName = (String) next.getKey();
334 if(!isPropertyNameValid(propertyName)) {
335 return Either.right(ActionStatus.INVALID_PROPERTY_NAME);
338 JSONObject value = (JSONObject) next.getValue();
339 Either<PropertyDefinition, ActionStatus> propertyDefinitionEither =
340 getPropertyDefinitionFromJson(componentId, propertyName, value);
342 if(propertyDefinitionEither.isRight()) {
343 return Either.right(propertyDefinitionEither.right().value());
346 properties.put(propertyName, propertyDefinitionEither.left().value());
349 return Either.left(properties);
350 } catch (ParseException e) {
351 log.info("Property conetnt is invalid - {}", data);
352 return Either.right(ActionStatus.INVALID_CONTENT);
356 protected boolean isPropertyNameValid(String propertyName) {
357 return Objects.nonNull(propertyName)
358 && propertyName.matches(PROPERTY_NAME_REGEX);
362 private Either<PropertyDefinition, ActionStatus> getPropertyDefinitionFromJson(String componentId, String propertyName, JSONObject value) {
363 String jsonString = value.toJSONString();
364 Either<PropertyDefinition, ActionStatus> convertJsonToObject = convertJsonToObject(jsonString, PropertyDefinition.class);
365 if (convertJsonToObject.isRight()) {
366 return Either.right(convertJsonToObject.right().value());
368 PropertyDefinition propertyDefinition = convertJsonToObject.left().value();
369 String uniqueId = UniqueIdBuilder.buildPropertyUniqueId(componentId, propertyName);
370 propertyDefinition.setUniqueId(uniqueId);
372 return Either.left(propertyDefinition);
375 protected Either<Map<String, PropertyDefinition>, ActionStatus> getPropertiesListForUpdate(String data) {
377 Map<String, PropertyDefinition> properties = new HashMap<>();
378 JSONParser parser = new JSONParser();
382 jsonArray = (JSONArray) parser.parse(data);
383 for (Object jsonElement : jsonArray) {
384 String propertyAsString = jsonElement.toString();
385 Either<PropertyDefinition, ActionStatus> convertJsonToObject = convertJsonToObject(propertyAsString, PropertyDefinition.class);
387 if (convertJsonToObject.isRight()) {
388 return Either.right(convertJsonToObject.right().value());
391 PropertyDefinition propertyDefinition = convertJsonToObject.left().value();
392 properties.put(propertyDefinition.getName(), propertyDefinition);
395 return Either.left(properties);
396 } catch (Exception e) {
397 log.info("Property content is invalid - {}", data);
398 return Either.right(ActionStatus.INVALID_CONTENT);
404 protected String propertyToJson(Map.Entry<String, PropertyDefinition> property) {
405 JSONObject root = new JSONObject();
406 String propertyName = property.getKey();
407 PropertyDefinition propertyDefinition = property.getValue();
408 JSONObject propertyDefinitionO = getPropertyDefinitionJSONObject(propertyDefinition);
409 root.put(propertyName, propertyDefinitionO);
410 propertyDefinition.getType();
411 return root.toString();
414 private JSONObject getPropertyDefinitionJSONObject(PropertyDefinition propertyDefinition) {
416 Either<String, ActionStatus> either = convertObjectToJson(propertyDefinition);
417 if (either.isRight()) {
418 return new JSONObject();
420 String value = either.left().value();
422 JSONObject root = (JSONObject) new JSONParser().parse(value);
424 } catch (ParseException e) {
425 log.info("failed to convert input to json");
426 log.error("failed to convert to json", e);
427 return new JSONObject();
432 protected <T> Either<T, ActionStatus> convertJsonToObject(String data, Class<T> clazz) {
434 Type constraintType = new TypeToken<PropertyConstraint>() {
437 gson = new GsonBuilder().registerTypeAdapter(constraintType, new PropertyOperation.PropertyConstraintDeserialiser()).create();
439 log.trace("convert json to object. json=\n {}", data);
440 t = gson.fromJson(data, clazz);
442 log.info("object is null after converting from json");
443 return Either.right(ActionStatus.INVALID_CONTENT);
445 } catch (Exception e) {
447 log.info("failed to convert from json");
448 log.error("failed to convert from json", e);
449 return Either.right(ActionStatus.INVALID_CONTENT);
451 return Either.left(t);
454 private Either<String, ActionStatus> convertObjectToJson(PropertyDefinition propertyDefinition) {
455 Type constraintType = new TypeToken<PropertyConstraint>() {
457 Gson gson = new GsonBuilder().registerTypeAdapter(constraintType, new PropertyOperation.PropertyConstraintSerialiser()).create();
459 log.trace("convert object to json. propertyDefinition= {}", propertyDefinition);
460 String json = gson.toJson(propertyDefinition);
462 log.info("object is null after converting to json");
463 return Either.right(ActionStatus.INVALID_CONTENT);
465 return Either.left(json);
466 } catch (Exception e) {
468 log.info("failed to convert to json");
469 log.debug("failed to convert fto json", e);
470 return Either.right(ActionStatus.INVALID_CONTENT);
475 protected PropertyBusinessLogic getPropertyBL(ServletContext context) {
476 WebAppContextWrapper webApplicationContextWrapper = (WebAppContextWrapper) context.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR);
477 WebApplicationContext webApplicationContext = webApplicationContextWrapper.getWebAppContext(context);
478 PropertyBusinessLogic propertytBl = webApplicationContext.getBean(PropertyBusinessLogic.class);
482 protected InputsBusinessLogic getInputBL(ServletContext context) {
483 WebAppContextWrapper webApplicationContextWrapper = (WebAppContextWrapper) context.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR);
484 WebApplicationContext webApplicationContext = webApplicationContextWrapper.getWebAppContext(context);
485 return webApplicationContext.getBean(InputsBusinessLogic.class);
488 protected PolicyBusinessLogic getPolicyBL(ServletContext context) {
489 WebAppContextWrapper webApplicationContextWrapper = (WebAppContextWrapper) context.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR);
490 WebApplicationContext webApplicationContext = webApplicationContextWrapper.getWebAppContext(context);
491 return webApplicationContext.getBean(PolicyBusinessLogic.class);
494 protected Either<ComponentInstInputsMap, ResponseFormat> parseToComponentInstanceMap(String componentJson, User user, ComponentTypeEnum componentType) {
495 return getComponentsUtils().convertJsonToObjectUsingObjectMapper(componentJson, user, ComponentInstInputsMap.class, AuditingActionEnum.CREATE_RESOURCE, componentType);
498 protected Response declareProperties(String userId, String componentId, String componentType,
499 String componentInstInputsMapObj, DeclarationTypeEnum typeEnum, HttpServletRequest request) {
500 ServletContext context = request.getSession().getServletContext();
501 String url = request.getMethod() + " " + request.getRequestURI();
502 log.debug("(get) Start handle request of {}", url);
503 Response response = null;
506 BaseBusinessLogic businessLogic = getBlForPropertyDeclaration(typeEnum, context);
509 User modifier = new User();
510 modifier.setUserId(userId);
511 log.debug("modifier id is {}", userId);
512 ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(componentType);
513 Either<ComponentInstInputsMap, ResponseFormat> componentInstInputsMapRes = parseToComponentInstanceMap(componentInstInputsMapObj, modifier, componentTypeEnum);
514 if (componentInstInputsMapRes.isRight()) {
515 log.debug("failed to parse componentInstInputsMap");
516 response = buildErrorResponse(componentInstInputsMapRes.right().value());
520 Either<List<ToscaDataDefinition>, ResponseFormat> propertiesAfterDeclaration = businessLogic
521 .declareProperties(userId, componentId,
523 componentInstInputsMapRes.left().value());
524 if (propertiesAfterDeclaration.isRight()) {
525 log.debug("failed to create inputs for service: {}", componentId);
526 return buildErrorResponse(propertiesAfterDeclaration.right().value());
528 Object properties = RepresentationUtils.toRepresentation(propertiesAfterDeclaration.left().value());
529 return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), properties);
531 } catch (Exception e) {
532 BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Create inputs for service with id: " + componentId);
533 log.debug("Properties declaration failed with exception", e);
534 response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
539 public BaseBusinessLogic getBlForPropertyDeclaration(DeclarationTypeEnum typeEnum,
540 ServletContext context) {
541 if(typeEnum.equals(DeclarationTypeEnum.POLICY)) {
542 return getPolicyBL(context);
545 return getInputBL(context);