Merge "Code refactoring"
[clamp.git] / src / main / java / org / onap / clamp / clds / service / CldsService.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP CLAMP
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights
6  *                             reserved.
7  * ================================================================================
8  * Licensed 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  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END============================================
20  * ===================================================================
21  * ECOMP is a trademark and service mark of AT&T Intellectual Property.
22  */
23
24 package org.onap.clamp.clds.service;
25
26 import com.att.ajsc.common.AjscService;
27 import com.att.eelf.configuration.EELFLogger;
28 import com.att.eelf.configuration.EELFManager;
29 import com.fasterxml.jackson.databind.JsonNode;
30 import com.fasterxml.jackson.databind.ObjectMapper;
31 import com.fasterxml.jackson.databind.node.ObjectNode;
32
33 import java.io.IOException;
34 import java.io.InputStream;
35 import java.security.GeneralSecurityException;
36 import java.util.Date;
37 import java.util.HashMap;
38 import java.util.List;
39 import java.util.Map;
40 import java.util.Properties;
41 import java.util.UUID;
42 import java.util.concurrent.TimeUnit;
43
44 import javax.annotation.PostConstruct;
45 import javax.ws.rs.BadRequestException;
46 import javax.ws.rs.Consumes;
47 import javax.ws.rs.DefaultValue;
48 import javax.ws.rs.GET;
49 import javax.ws.rs.NotAuthorizedException;
50 import javax.ws.rs.POST;
51 import javax.ws.rs.PUT;
52 import javax.ws.rs.Path;
53 import javax.ws.rs.PathParam;
54 import javax.ws.rs.Produces;
55 import javax.ws.rs.QueryParam;
56 import javax.ws.rs.core.MediaType;
57 import javax.xml.transform.TransformerException;
58
59 import org.apache.commons.codec.DecoderException;
60 import org.apache.commons.lang3.StringUtils;
61 import org.camunda.bpm.engine.RuntimeService;
62 import org.camunda.bpm.engine.runtime.ProcessInstance;
63 import org.json.simple.parser.ParseException;
64 import org.onap.clamp.clds.client.DcaeDispatcherServices;
65 import org.onap.clamp.clds.client.DcaeInventoryServices;
66 import org.onap.clamp.clds.client.req.sdc.SdcCatalogServices;
67 import org.onap.clamp.clds.dao.CldsDao;
68 import org.onap.clamp.clds.exception.CldsConfigException;
69 import org.onap.clamp.clds.exception.SdcCommunicationException;
70 import org.onap.clamp.clds.exception.policy.PolicyClientException;
71 import org.onap.clamp.clds.model.CldsDBServiceCache;
72 import org.onap.clamp.clds.model.CldsEvent;
73 import org.onap.clamp.clds.model.CldsHealthCheck;
74 import org.onap.clamp.clds.model.CldsInfo;
75 import org.onap.clamp.clds.model.CldsModel;
76 import org.onap.clamp.clds.model.CldsModelProp;
77 import org.onap.clamp.clds.model.CldsSdcResource;
78 import org.onap.clamp.clds.model.CldsSdcServiceDetail;
79 import org.onap.clamp.clds.model.CldsSdcServiceInfo;
80 import org.onap.clamp.clds.model.CldsServiceData;
81 import org.onap.clamp.clds.model.CldsTemplate;
82 import org.onap.clamp.clds.model.DcaeEvent;
83 import org.onap.clamp.clds.model.ValueItem;
84 import org.onap.clamp.clds.model.prop.AbstractModelElement;
85 import org.onap.clamp.clds.model.prop.ModelProperties;
86 import org.onap.clamp.clds.model.refprop.RefProp;
87 import org.onap.clamp.clds.transform.XslTransformer;
88 import org.onap.clamp.clds.util.LoggingUtils;
89 import org.springframework.beans.factory.annotation.Autowired;
90 import org.springframework.beans.factory.annotation.Value;
91 import org.springframework.context.ApplicationContext;
92 import org.springframework.http.HttpStatus;
93 import org.springframework.web.client.HttpClientErrorException;
94
95 import io.swagger.annotations.Api;
96 import io.swagger.annotations.ApiOperation;
97
98 /**
99  * Service to save and retrieve the CLDS model attributes.
100  */
101 @AjscService
102 @Api(value = "/clds")
103 @Path("/clds")
104 public class CldsService extends SecureServiceBase {
105     protected static final EELFLogger securityLogger = EELFManager.getInstance().getSecurityLogger();
106     @Autowired
107     private ApplicationContext        appContext;
108     private static final String       RESOURCE_NAME  = "clds-version.properties";
109     @Value("${CLDS_PERMISSION_TYPE_CL:permission-type-cl}")
110     private String                    cldsPersmissionTypeCl;
111     @Value("${CLDS_PERMISSION_TYPE_CL_MANAGE:permission-type-cl-manage}")
112     private String                    cldsPermissionTypeClManage;
113     @Value("${CLDS_PERMISSION_TYPE_CL_EVENT:permission-type-cl-event}")
114     private String                    cldsPermissionTypeClEvent;
115     @Value("${CLDS_PERMISSION_TYPE_FILTER_VF:permission-type-filter-vf}")
116     private String                    cldsPermissionTypeFilterVf;
117     @Value("${CLDS_PERMISSION_TYPE_TEMPLATE:permission-type-template}")
118     private String                    cldsPermissionTypeTemplate;
119     @Value("${CLDS_PERMISSION_INSTANCE:dev}")
120     private String                    cldsPermissionInstance;
121     private SecureServicePermission   permissionReadCl;
122     private SecureServicePermission   permissionUpdateCl;
123     private SecureServicePermission   permissionReadTemplate;
124     private SecureServicePermission   permissionUpdateTemplate;
125
126     @PostConstruct
127     private final void afterConstruction() {
128         permissionReadCl = SecureServicePermission.create(cldsPersmissionTypeCl, cldsPermissionInstance, "read");
129         permissionUpdateCl = SecureServicePermission.create(cldsPersmissionTypeCl, cldsPermissionInstance, "update");
130         permissionReadTemplate = SecureServicePermission.create(cldsPermissionTypeTemplate, cldsPermissionInstance,
131                 "read");
132         permissionUpdateTemplate = SecureServicePermission.create(cldsPermissionTypeTemplate, cldsPermissionInstance,
133                 "update");
134     }
135
136     @Value("${org.onap.clamp.config.files.globalClds:'classpath:/clds/globalClds.properties'}")
137     private String                 globalClds;
138     private Properties             globalCldsProperties;
139     @Autowired
140     private CldsDao                cldsDao;
141     @Autowired
142     private RuntimeService         runtimeService;
143     @Autowired
144     private XslTransformer         cldsBpmnTransformer;
145     @Autowired
146     private RefProp                refProp;
147     @Autowired
148     private SdcCatalogServices     sdcCatalogServices;
149     @Autowired
150     private DcaeDispatcherServices dcaeDispatcherServices;
151     @Autowired
152     private DcaeInventoryServices  dcaeInventoryServices;
153
154     /*
155      *
156      * CLDS IFO service will return 3 things 1. User Name 2. CLDS code version
157      * that is currently installed from pom.xml file 3. User permissions
158      *
159      */
160     @GET
161     @Path("/cldsInfo")
162     @Produces(MediaType.APPLICATION_JSON)
163     public CldsInfo getCldsInfo() {
164         CldsInfo cldsInfo = new CldsInfo();
165         Date startTime = new Date();
166         LoggingUtils.setRequestContext("CldsService: GET cldsInfo", getPrincipalName());
167         LoggingUtils.setTimeContext(startTime, new Date());
168         // Get the user info
169         cldsInfo.setUserName(getUserName());
170         // Get CLDS application version
171         String cldsVersion = "";
172         Properties props = new Properties();
173         ClassLoader loader = Thread.currentThread().getContextClassLoader();
174         try (InputStream resourceStream = loader.getResourceAsStream(RESOURCE_NAME)) {
175             props.load(resourceStream);
176             cldsVersion = props.getProperty("clds.version");
177         } catch (Exception ex) {
178             logger.error("Exception caught during the clds.version reading", ex);
179         }
180         cldsInfo.setCldsVersion(cldsVersion);
181         // Get the user list of permissions
182         cldsInfo.setPermissionReadCl(isAuthorizedNoException(permissionReadCl));
183         cldsInfo.setPermissionUpdateCl(isAuthorizedNoException(permissionUpdateCl));
184         cldsInfo.setPermissionReadTemplate(isAuthorizedNoException(permissionReadTemplate));
185         cldsInfo.setPermissionUpdateTemplate(isAuthorizedNoException(permissionUpdateTemplate));
186         // audit log
187         LoggingUtils.setTimeContext(startTime, new Date());
188         LoggingUtils.setResponseContext("0", "Get cldsInfo success", this.getClass().getName());
189         securityLogger.info("GET cldsInfo completed");
190         return cldsInfo;
191     }
192
193     /**
194      * REST service that retrieves clds healthcheck information.
195      * 
196      * @return CldsHealthCheck class containing healthcheck info
197      */
198     @GET
199     @Path("/healthcheck")
200     @Produces(MediaType.APPLICATION_JSON)
201     public CldsHealthCheck gethealthcheck() {
202         CldsHealthCheck cldsHealthCheck = new CldsHealthCheck();
203         Date startTime = new Date();
204         LoggingUtils.setRequestContext("CldsService: GET healthcheck", getPrincipalName());
205         LoggingUtils.setTimeContext(startTime, new Date());
206         try {
207             cldsDao.doHealthCheck();
208             cldsHealthCheck.setHealthCheckComponent("CLDS-APP");
209             cldsHealthCheck.setHealthCheckStatus("UP");
210             cldsHealthCheck.setDescription("OK");
211         } catch (Exception e) {
212             logger.error("CLAMP application DB Error", e);
213             cldsHealthCheck.setHealthCheckComponent("CLDS-APP");
214             cldsHealthCheck.setHealthCheckStatus("DOWN");
215             cldsHealthCheck.setDescription("NOT-OK");
216         }
217         // audit log
218         LoggingUtils.setTimeContext(startTime, new Date());
219         LoggingUtils.setResponseContext("0", "Get healthcheck success", this.getClass().getName());
220         securityLogger.info("GET healthcheck completed");
221         return cldsHealthCheck;
222     }
223
224     /**
225      * REST service that retrieves BPMN for a CLDS model name from the database.
226      * This is subset of the json getModel. This is only expected to be used for
227      * testing purposes, not by the UI.
228      *
229      * @param modelName
230      * @return bpmn xml text - content of bpmn given name
231      */
232     @ApiOperation(value = "Retrieves BPMN for a CLDS model name from the database", notes = "This is only expected to be used for testing purposes, not by the UI", response = String.class)
233     @GET
234     @Path("/model/bpmn/{modelName}")
235     @Produces(MediaType.TEXT_XML)
236     public String getBpmnXml(@PathParam("modelName") String modelName) {
237         Date startTime = new Date();
238         LoggingUtils.setRequestContext("CldsService: GET model bpmn", getPrincipalName());
239         isAuthorized(permissionReadCl);
240         logger.info("GET bpmnText for modelName={}", modelName);
241         CldsModel model = CldsModel.retrieve(cldsDao, modelName, false);
242         // audit log
243         LoggingUtils.setTimeContext(startTime, new Date());
244         LoggingUtils.setResponseContext("0", "Get model bpmn success", this.getClass().getName());
245         auditLogger.info("GET model bpmn completed");
246         return model.getBpmnText();
247     }
248
249     /**
250      * REST service that retrieves image for a CLDS model name from the
251      * database. This is subset of the json getModel. This is only expected to
252      * be used for testing purposes, not by the UI.
253      *
254      * @param modelName
255      * @return image xml text - content of image given name
256      */
257     @ApiOperation(value = "Retrieves image for a CLDS model name from the database", notes = "This is only expected to be used for testing purposes, not by the UI", response = String.class)
258     @GET
259     @Path("/model/image/{modelName}")
260     @Produces(MediaType.TEXT_XML)
261     public String getImageXml(@PathParam("modelName") String modelName) {
262         Date startTime = new Date();
263         LoggingUtils.setRequestContext("CldsService: GET model image", getPrincipalName());
264         isAuthorized(permissionReadCl);
265         logger.info("GET imageText for modelName={}", modelName);
266         CldsModel model = CldsModel.retrieve(cldsDao, modelName, false);
267         // audit log
268         LoggingUtils.setTimeContext(startTime, new Date());
269         LoggingUtils.setResponseContext("0", "Get model image success", this.getClass().getName());
270         auditLogger.info("GET model image completed");
271         return model.getImageText();
272     }
273
274     /**
275      * REST service that retrieves a CLDS model by name from the database.
276      *
277      * @param modelName
278      * @return clds model - clds model for the given model name
279      */
280     @ApiOperation(value = "Retrieves a CLDS model by name from the database", notes = "", response = String.class)
281     @GET
282     @Path("/model/{modelName}")
283     @Produces(MediaType.APPLICATION_JSON)
284     public CldsModel getModel(@PathParam("modelName") String modelName) {
285         Date startTime = new Date();
286         LoggingUtils.setRequestContext("CldsService: GET model", getPrincipalName());
287         isAuthorized(permissionReadCl);
288         logger.debug("GET model for  modelName={}", modelName);
289         CldsModel cldsModel = CldsModel.retrieve(cldsDao, modelName, false);
290         isAuthorizedForVf(cldsModel);
291         /**
292          * Checking condition whether our CLDS model can call INventory Method
293          */
294         if (cldsModel.canInventoryCall()) {
295             try {
296                 /*
297                  * Below is the method to for inventory call and DB insert for
298                  * event methods
299                  */
300                 dcaeInventoryServices.setEventInventory(cldsModel, getUserId());
301             } catch (Exception e) {
302                 LoggingUtils.setErrorContext("900", "Set event inventory error");
303                 logger.error("getModel set event Inventory error:" + e);
304             }
305         }
306         // audit log
307         LoggingUtils.setTimeContext(startTime, new Date());
308         LoggingUtils.setResponseContext("0", "Get model success", this.getClass().getName());
309         auditLogger.info("GET model completed");
310         return cldsModel;
311     }
312
313     /**
314      * REST service that saves a CLDS model by name in the database.
315      *
316      * @param modelName
317      */
318     @ApiOperation(value = "Saves a CLDS model by name in the database", notes = "", response = String.class)
319     @PUT
320     @Path("/model/{modelName}")
321     @Consumes(MediaType.APPLICATION_JSON)
322     @Produces(MediaType.APPLICATION_JSON)
323     public CldsModel putModel(@PathParam("modelName") String modelName, CldsModel cldsModel) {
324         Date startTime = new Date();
325         LoggingUtils.setRequestContext("CldsService: PUT model", getPrincipalName());
326         isAuthorized(permissionUpdateCl);
327         isAuthorizedForVf(cldsModel);
328         logger.info("PUT model for  modelName={}", modelName);
329         logger.info("PUT bpmnText={}", cldsModel.getBpmnText());
330         logger.info("PUT propText={}", cldsModel.getPropText());
331         logger.info("PUT imageText={}", cldsModel.getImageText());
332         cldsModel.setName(modelName);
333         if (cldsModel.getTemplateName() != null) {
334             CldsTemplate template = cldsDao.getTemplate(cldsModel.getTemplateName());
335             if (template != null) {
336                 cldsModel.setTemplateId(template.getId());
337                 cldsModel.setDocText(template.getPropText());
338             }
339         }
340         cldsModel.save(cldsDao, getUserId());
341         // audit log
342         LoggingUtils.setTimeContext(startTime, new Date());
343         LoggingUtils.setResponseContext("0", "Put model success", this.getClass().getName());
344         auditLogger.info("PUT model completed");
345         return cldsModel;
346     }
347
348     /**
349      * REST service that retrieves a list of CLDS model names.
350      *
351      * @return model names in JSON
352      */
353     @ApiOperation(value = "Retrieves a list of CLDS model names", notes = "", response = String.class)
354     @GET
355     @Path("/model-names")
356     @Produces(MediaType.APPLICATION_JSON)
357     public List<ValueItem> getModelNames() {
358         Date startTime = new Date();
359         LoggingUtils.setRequestContext("CldsService: GET model names", getPrincipalName());
360         isAuthorized(permissionReadCl);
361         logger.info("GET list of model names");
362         List<ValueItem> names = cldsDao.getBpmnNames();
363         // audit log
364         LoggingUtils.setTimeContext(startTime, new Date());
365         LoggingUtils.setResponseContext("0", "Get model names success", this.getClass().getName());
366         auditLogger.info("GET model names completed");
367         return names;
368     }
369
370     /**
371      * REST service that saves and processes an action for a CLDS model by name.
372      *
373      * @param action
374      * @param modelName
375      * @param test
376      * @param model
377      * @return
378      * @throws TransformerException
379      *             In case of issues when doing the XSLT of the BPMN flow
380      * @throws ParseException
381      *             In case of issues when parsing the JSON
382      * @throws GeneralSecurityException
383      *             In case of issues when decrypting the password
384      * @throws DecoderException
385      *             In case of issues with the Hex String decoding
386      */
387     @ApiOperation(value = "Saves and processes an action for a CLDS model by name", notes = "", response = String.class)
388     @PUT
389     @Path("/action/{action}/{modelName}")
390     @Consumes(MediaType.APPLICATION_JSON)
391     @Produces(MediaType.APPLICATION_JSON)
392     public CldsModel putModelAndProcessAction(@PathParam("action") String action,
393             @PathParam("modelName") String modelName, @QueryParam("test") String test, CldsModel model)
394             throws TransformerException, ParseException, GeneralSecurityException, DecoderException {
395         Date startTime = new Date();
396         LoggingUtils.setRequestContext("CldsService: Process model action", getPrincipalName());
397         String actionCd = action.toUpperCase();
398         SecureServicePermission permisionManage = SecureServicePermission.create(cldsPermissionTypeClManage,
399                 cldsPermissionInstance, actionCd);
400         isAuthorized(permisionManage);
401         isAuthorizedForVf(model);
402         String userid = getUserId();
403         String actionStateCd = CldsEvent.ACTION_STATE_INITIATED;
404         String processDefinitionKey = "clds-process-action-wf";
405         logger.info("PUT actionCd={}", actionCd);
406         logger.info("PUT actionStateCd={}", actionStateCd);
407         logger.info("PUT processDefinitionKey={}", processDefinitionKey);
408         logger.info("PUT modelName={}", modelName);
409         logger.info("PUT test={}", test);
410         logger.info("PUT bpmnText={}", model.getBpmnText());
411         logger.info("PUT propText={}", model.getPropText());
412         logger.info("PUT userid={}", userid);
413         logger.info("PUT getTypeId={}", model.getTypeId());
414         logger.info("PUT deploymentId={}", model.getDeploymentId());
415         if (model.getTemplateName() != null) {
416             CldsTemplate template = cldsDao.getTemplate(model.getTemplateName());
417             if (template != null) {
418                 model.setTemplateId(template.getId());
419                 model.setDocText(template.getPropText());
420             }
421         }
422         // save model to db
423         model.setName(modelName);
424         model.save(cldsDao, getUserId());
425         // get vars and format if necessary
426         String prop = model.getPropText();
427         String bpmn = model.getBpmnText();
428         String docText = model.getDocText();
429         String controlName = model.getControlName();
430         String bpmnJson = cldsBpmnTransformer.doXslTransformToString(bpmn);
431         logger.info("PUT bpmnJson={}", bpmnJson);
432         // Flag indicates whether it is triggered by Validation Test button from
433         // UI
434         boolean isTest = false;
435         if (test != null && test.equalsIgnoreCase("true")) {
436             isTest = true;
437         } else {
438             String actionTestOverride = refProp.getStringValue("action.test.override");
439             if (actionTestOverride != null && actionTestOverride.equalsIgnoreCase("true")) {
440                 logger.info("PUT actionTestOverride={}", actionTestOverride);
441                 logger.info("PUT override test indicator and setting it to true");
442                 isTest = true;
443             }
444         }
445         logger.info("PUT isTest={}", isTest);
446         boolean isInsertTestEvent = false;
447         String insertTestEvent = refProp.getStringValue("action.insert.test.event");
448         if (insertTestEvent != null && insertTestEvent.equalsIgnoreCase("true")) {
449             isInsertTestEvent = true;
450         }
451         logger.info("PUT isInsertTestEvent={}", isInsertTestEvent);
452         // determine if requested action is permitted
453         model.validateAction(actionCd);
454         // input variables to camunda process
455         Map<String, Object> variables = new HashMap<>();
456         variables.put("actionCd", actionCd);
457         variables.put("modelProp", prop.getBytes());
458         variables.put("modelBpmnProp", bpmnJson);
459         variables.put("modelName", modelName);
460         variables.put("controlName", controlName);
461         variables.put("docText", docText.getBytes());
462         variables.put("isTest", isTest);
463         variables.put("userid", userid);
464         variables.put("isInsertTestEvent", isInsertTestEvent);
465         logger.info("modelProp - " + prop);
466         logger.info("docText - " + docText);
467         try {
468             // start camunda process
469             ProcessInstance pi = runtimeService.startProcessInstanceByKey(processDefinitionKey, variables);
470             // log process info
471             logger.info("Started processDefinitionId={}, processInstanceId={}", pi.getProcessDefinitionId(),
472                     pi.getProcessInstanceId());
473         } catch (SdcCommunicationException | PolicyClientException | BadRequestException e) {
474             logger.error("Exception occured during invoking bpmn process", e);
475             throw new CldsConfigException(e.getMessage(), e);
476         }
477         // refresh model info from db (get fresh event info)
478         CldsModel retreivedModel = CldsModel.retrieve(cldsDao, modelName, false);
479         if (actionCd.equalsIgnoreCase(CldsEvent.ACTION_SUBMIT)
480                 || actionCd.equalsIgnoreCase(CldsEvent.ACTION_RESUBMIT)) {
481             // To verify inventory status and modify model status to distribute
482             dcaeInventoryServices.setEventInventory(retreivedModel, getUserId());
483             retreivedModel.save(cldsDao, getUserId());
484         }
485         // audit log
486         LoggingUtils.setTimeContext(startTime, new Date());
487         LoggingUtils.setResponseContext("0", "Process model action success", this.getClass().getName());
488         auditLogger.info("Process model action completed");
489         return retreivedModel;
490     }
491
492     /**
493      * REST service that accepts events for a model.
494      *
495      * @param test
496      * @param dcaeEvent
497      */
498     @ApiOperation(value = "Accepts events for a model", notes = "", response = String.class)
499     @POST
500     @Path("/dcae/event")
501     @Consumes(MediaType.APPLICATION_JSON)
502     @Produces(MediaType.APPLICATION_JSON)
503     public String postDcaeEvent(@QueryParam("test") String test, DcaeEvent dcaeEvent) {
504         Date startTime = new Date();
505         LoggingUtils.setRequestContext("CldsService: Post dcae event", getPrincipalName());
506         String userid = null;
507         // TODO: allow auth checking to be turned off by removing the permission
508         // type property
509         if (cldsPermissionTypeClEvent != null && cldsPermissionTypeClEvent.length() > 0) {
510             SecureServicePermission permissionEvent = SecureServicePermission.create(cldsPermissionTypeClEvent,
511                     cldsPermissionInstance, dcaeEvent.getEvent());
512             isAuthorized(permissionEvent);
513             userid = getUserId();
514         }
515         // Flag indicates whether it is triggered by Validation Test button from
516         // UI
517         boolean isTest = false;
518         if (test != null && test.equalsIgnoreCase("true")) {
519             isTest = true;
520         }
521         int instanceCount = 0;
522         if (dcaeEvent.getInstances() != null) {
523             instanceCount = dcaeEvent.getInstances().size();
524         }
525         String msgInfo = "event=" + dcaeEvent.getEvent() + " serviceUUID=" + dcaeEvent.getServiceUUID()
526                 + " resourceUUID=" + dcaeEvent.getResourceUUID() + " artifactName=" + dcaeEvent.getArtifactName()
527                 + " instance count=" + instanceCount + " isTest=" + isTest;
528         logger.info("POST dcae event {}", msgInfo);
529         if (isTest) {
530             logger.warn("Ignorning test event from DCAE");
531         } else {
532             if (DcaeEvent.EVENT_DEPLOYMENT.equalsIgnoreCase(dcaeEvent.getEvent())) {
533                 CldsModel.insertModelInstance(cldsDao, dcaeEvent, userid);
534             } else {
535                 CldsEvent.insEvent(cldsDao, dcaeEvent.getControlName(), userid, dcaeEvent.getCldsActionCd(),
536                         CldsEvent.ACTION_STATE_RECEIVED, null);
537             }
538         }
539         // audit log
540         LoggingUtils.setTimeContext(startTime, new Date());
541         LoggingUtils.setResponseContext("0", "Post dcae event success", this.getClass().getName());
542         auditLogger.info("Post dcae event completed");
543         return msgInfo;
544     }
545
546     /**
547      * REST service that retrieves sdc services
548      * 
549      * @throws GeneralSecurityException
550      *             In case of issue when decryting the SDC password
551      * @throws DecoderException
552      *             In case of issues with the decoding of the Hex String
553      *
554      */
555     @ApiOperation(value = "Retrieves sdc services", notes = "", response = String.class)
556     @GET
557     @Path("/sdc/services")
558     @Produces(MediaType.APPLICATION_JSON)
559     public String getSdcServices() throws GeneralSecurityException, DecoderException {
560         Date startTime = new Date();
561         LoggingUtils.setRequestContext("CldsService: GET sdc services", getPrincipalName());
562         String retStr;
563         String responseStr = sdcCatalogServices.getSdcServicesInformation(null);
564         try {
565             retStr = createUiServiceFormatJson(responseStr);
566         } catch (IOException e) {
567             logger.error("IOException during SDC communication", e);
568             throw new SdcCommunicationException("IOException during SDC communication", e);
569         }
570         logger.info("value of sdcServices : {}", retStr);
571         // audit log
572         LoggingUtils.setTimeContext(startTime, new Date());
573         LoggingUtils.setResponseContext("0", "Get sdc services success", this.getClass().getName());
574         auditLogger.info("GET sdc services completed");
575         return retStr;
576     }
577
578     /**
579      * REST service that retrieves total properties required by UI
580      * 
581      * @throws IOException
582      *             In case of issues
583      *
584      */
585     @ApiOperation(value = "Retrieves total properties required by UI", notes = "", response = String.class)
586     @GET
587     @Path("/properties")
588     @Produces(MediaType.APPLICATION_JSON)
589     public String getSdcProperties() throws IOException {
590         return createPropertiesObjectByUUID(getGlobalCldsString(), "{}");
591     }
592
593     /**
594      * REST service that retrieves total properties by using invariantUUID based
595      * on refresh and non refresh
596      * 
597      * @throws GeneralSecurityException
598      *             In case of issues with the decryting the encrypted password
599      * @throws DecoderException
600      *             In case of issues with the decoding of the Hex String
601      * 
602      */
603     @ApiOperation(value = "Retrieves total properties by using invariantUUID based on refresh and non refresh", notes = "", response = String.class)
604     @GET
605     @Path("/properties/{serviceInvariantUUID}")
606     @Produces(MediaType.APPLICATION_JSON)
607     public String getSdcPropertiesByServiceUUIDForRefresh(
608             @PathParam("serviceInvariantUUID") String serviceInvariantUUID,
609             @DefaultValue("false") @QueryParam("refresh") String refresh)
610             throws GeneralSecurityException, DecoderException {
611         Date startTime = new Date();
612         LoggingUtils.setRequestContext("CldsService: GET sdc properties by uuid", getPrincipalName());
613         CldsServiceData cldsServiceData = new CldsServiceData();
614         cldsServiceData.setServiceInvariantUUID(serviceInvariantUUID);
615         boolean isCldsSdcDataExpired = true;
616         // To getcldsService information from database cache using invariantUUID
617         // only when refresh = false
618         if (refresh != null && refresh.equalsIgnoreCase("false")) {
619             cldsServiceData = cldsServiceData.getCldsServiceCache(cldsDao, serviceInvariantUUID);
620             // If cldsService is available in database Cache , verify is data
621             // expired or not
622             if (cldsServiceData != null) {
623                 isCldsSdcDataExpired = sdcCatalogServices.isCldsSdcCacheDataExpired(cldsServiceData);
624             }
625         }
626         // If user Requested for refresh or database cache expired , get all
627         // data from sdc api.
628         if ((refresh != null && refresh.equalsIgnoreCase("true")) || isCldsSdcDataExpired) {
629             cldsServiceData = sdcCatalogServices.getCldsServiceDataWithAlarmConditions(serviceInvariantUUID);
630             CldsDBServiceCache cldsDBServiceCache = sdcCatalogServices
631                     .getCldsDbServiceCacheUsingCldsServiceData(cldsServiceData);
632             if (cldsDBServiceCache != null && cldsDBServiceCache.getInvariantId() != null
633                     && cldsDBServiceCache.getServiceId() != null) {
634                 cldsServiceData.setCldsServiceCache(cldsDao, cldsDBServiceCache);
635             }
636         }
637         // filter out VFs the user is not authorized for
638         cldsServiceData.filterVfs(this);
639         // format retrieved data into properties json
640         String sdcProperties = sdcCatalogServices.createPropertiesObjectByUUID(getGlobalCldsString(), cldsServiceData);
641         // audit log
642         LoggingUtils.setTimeContext(startTime, new Date());
643         LoggingUtils.setResponseContext("0", "Get sdc properties by uuid success", this.getClass().getName());
644         auditLogger.info("GET sdc properties by uuid completed");
645         return sdcProperties;
646     }
647
648     /**
649      * Determine if the user is authorized for a particular VF by its invariant
650      * UUID.
651      *
652      * @param vfInvariantUuid
653      * @throws NotAuthorizedException
654      * @return
655      */
656     public boolean isAuthorizedForVf(String vfInvariantUuid) {
657         if (cldsPermissionTypeFilterVf != null && !cldsPermissionTypeFilterVf.isEmpty()) {
658             SecureServicePermission permission = SecureServicePermission.create(cldsPermissionTypeFilterVf,
659                     cldsPermissionInstance, vfInvariantUuid);
660             return isAuthorized(permission);
661         } else {
662             // if CLDS_PERMISSION_TYPE_FILTER_VF property is not provided, then
663             // VF filtering is turned off
664             logger.warn("VF filtering turned off");
665             return true;
666         }
667     }
668
669     /**
670      * Determine if the user is authorized for a particular VF by its invariant
671      * UUID. If not authorized, then NotAuthorizedException is thrown.
672      *
673      * @param model
674      * @return
675      */
676     private boolean isAuthorizedForVf(CldsModel model) {
677         String vf = ModelProperties.getVf(model);
678         if (vf == null || vf.length() == 0) {
679             logger.info("VF not found in model");
680             return true;
681         } else {
682             return isAuthorizedForVf(vf);
683         }
684     }
685
686     private String createUiServiceFormatJson(String responseStr) throws IOException {
687         if (StringUtils.isBlank(responseStr)) {
688             return "";
689         }
690         ObjectMapper objectMapper = new ObjectMapper();
691         List<CldsSdcServiceInfo> rawList = objectMapper.readValue(responseStr,
692                 objectMapper.getTypeFactory().constructCollectionType(List.class, CldsSdcServiceInfo.class));
693         ObjectNode invariantIdServiceNode = objectMapper.createObjectNode();
694         ObjectNode serviceNode = objectMapper.createObjectNode();
695         logger.info("value of cldsserviceiNfolist: {}", rawList);
696         if (rawList != null && !rawList.isEmpty()) {
697             List<CldsSdcServiceInfo> cldsSdcServiceInfoList = sdcCatalogServices.removeDuplicateServices(rawList);
698             for (CldsSdcServiceInfo currCldsSdcServiceInfo : cldsSdcServiceInfoList) {
699                 if (currCldsSdcServiceInfo != null) {
700                     invariantIdServiceNode.put(currCldsSdcServiceInfo.getInvariantUUID(),
701                             currCldsSdcServiceInfo.getName());
702                 }
703             }
704             serviceNode.putPOJO("service", invariantIdServiceNode);
705         }
706         return serviceNode.toString();
707     }
708
709     private String createPropertiesObjectByUUID(String globalProps, String cldsResponseStr) throws IOException {
710         ObjectMapper mapper = new ObjectMapper();
711         CldsSdcServiceDetail cldsSdcServiceDetail = mapper.readValue(cldsResponseStr, CldsSdcServiceDetail.class);
712         ObjectNode globalPropsJson = null;
713         if (cldsSdcServiceDetail != null && cldsSdcServiceDetail.getUuid() != null) {
714             /**
715              * to create json with vf, alarm and locations
716              */
717             ObjectNode serviceObjectNode = createEmptyVfAlarmObject(mapper);
718             ObjectNode vfObjectNode = mapper.createObjectNode();
719             /**
720              * to create json with vf and vfresourceId
721              */
722             createVfObjectNode(vfObjectNode, mapper, cldsSdcServiceDetail.getResources());
723             serviceObjectNode.putPOJO(cldsSdcServiceDetail.getInvariantUUID(), vfObjectNode);
724             ObjectNode byServiceBasicObjetNode = mapper.createObjectNode();
725             byServiceBasicObjetNode.putPOJO("byService", serviceObjectNode);
726             /**
727              * to create json with VFC Node
728              */
729             ObjectNode emptyvfcobjectNode = createByVFCObjectNode(mapper, cldsSdcServiceDetail.getResources());
730             byServiceBasicObjetNode.putPOJO("byVf", emptyvfcobjectNode);
731             globalPropsJson = (ObjectNode) mapper.readValue(globalProps, JsonNode.class);
732             globalPropsJson.putPOJO("shared", byServiceBasicObjetNode);
733             logger.info("valuie of objNode: {}", globalPropsJson);
734         } else {
735             /**
736              * to create json with total properties when no serviceUUID passed
737              */
738             globalPropsJson = (ObjectNode) mapper.readValue(globalProps, JsonNode.class);
739         }
740         return globalPropsJson.toString();
741     }
742
743     private ObjectNode createEmptyVfAlarmObject(ObjectMapper mapper) {
744         ObjectNode emptyObjectNode = mapper.createObjectNode();
745         emptyObjectNode.put("", "");
746         ObjectNode vfObjectNode = mapper.createObjectNode();
747         vfObjectNode.putPOJO("vf", emptyObjectNode);
748         vfObjectNode.putPOJO("location", emptyObjectNode);
749         vfObjectNode.putPOJO("alarmCondition", emptyObjectNode);
750         ObjectNode emptyServiceObjectNode = mapper.createObjectNode();
751         emptyServiceObjectNode.putPOJO("", vfObjectNode);
752         return emptyServiceObjectNode;
753     }
754
755     private void createVfObjectNode(ObjectNode vfObjectNode2, ObjectMapper mapper,
756             List<CldsSdcResource> rawCldsSdcResourceList) {
757         ObjectNode vfNode = mapper.createObjectNode();
758         vfNode.put("", "");
759         // To remove repeated resource instance name from
760         // resourceInstanceList
761         List<CldsSdcResource> cldsSdcResourceList = sdcCatalogServices
762                 .removeDuplicateSdcResourceInstances(rawCldsSdcResourceList);
763         /**
764          * Creating vf resource node using cldsSdcResource Object
765          */
766         if (cldsSdcResourceList != null && !cldsSdcResourceList.isEmpty()) {
767             for (CldsSdcResource cldsSdcResource : cldsSdcResourceList) {
768                 if (cldsSdcResource != null && "VF".equalsIgnoreCase(cldsSdcResource.getResoucreType())) {
769                     vfNode.put(cldsSdcResource.getResourceUUID(), cldsSdcResource.getResourceName());
770                 }
771             }
772         }
773         vfObjectNode2.putPOJO("vf", vfNode);
774         /**
775          * creating location json object using properties file value
776          */
777         ObjectNode locationJsonNode;
778         try {
779             locationJsonNode = (ObjectNode) mapper.readValue(refProp.getStringValue("ui.location.default"),
780                     JsonNode.class);
781         } catch (IOException e) {
782             logger.error("Unable to load ui.location.default JSON in clds-references.properties properly", e);
783             throw new CldsConfigException(
784                     "Unable to load ui.location.default JSON in clds-references.properties properly", e);
785         }
786         vfObjectNode2.putPOJO("location", locationJsonNode);
787         /**
788          * creating alarm json object using properties file value
789          */
790         String alarmStringValue = refProp.getStringValue("ui.alarm.default");
791         logger.info("value of alarm: {}", alarmStringValue);
792         ObjectNode alarmStringJsonNode;
793         try {
794             alarmStringJsonNode = (ObjectNode) mapper.readValue(alarmStringValue, JsonNode.class);
795         } catch (IOException e) {
796             logger.error("Unable to ui.alarm.default JSON in clds-references.properties properly", e);
797             throw new CldsConfigException("Unable to load ui.alarm.default JSON in clds-references.properties properly",
798                     e);
799         }
800         vfObjectNode2.putPOJO("alarmCondition", alarmStringJsonNode);
801     }
802
803     private ObjectNode createByVFCObjectNode(ObjectMapper mapper, List<CldsSdcResource> cldsSdcResourceList) {
804         ObjectNode emptyObjectNode = mapper.createObjectNode();
805         ObjectNode emptyvfcobjectNode = mapper.createObjectNode();
806         ObjectNode vfCObjectNode = mapper.createObjectNode();
807         vfCObjectNode.putPOJO("vfC", emptyObjectNode);
808         ObjectNode subVfCObjectNode = mapper.createObjectNode();
809         subVfCObjectNode.putPOJO("vfc", emptyObjectNode);
810         if (cldsSdcResourceList != null && !cldsSdcResourceList.isEmpty()) {
811             for (CldsSdcResource cldsSdcResource : cldsSdcResourceList) {
812                 if (cldsSdcResource != null && "VF".equalsIgnoreCase(cldsSdcResource.getResoucreType())) {
813                     vfCObjectNode.putPOJO(cldsSdcResource.getResourceUUID(), subVfCObjectNode);
814                 }
815             }
816         }
817         emptyvfcobjectNode.putPOJO("", vfCObjectNode);
818         return emptyvfcobjectNode;
819     }
820
821     @PUT
822     @Path("/deploy/{modelName}")
823     @Consumes(MediaType.APPLICATION_JSON)
824     @Produces(MediaType.APPLICATION_JSON)
825     public CldsModel deployModel(@PathParam("action") String action, @PathParam("modelName") String modelName,
826             @QueryParam("test") String test, CldsModel model) {
827         Date startTime = new Date();
828         LoggingUtils.setRequestContext("CldsService: Deploy model", getPrincipalName());
829         try {
830             checkForDuplicateServiceVf(modelName, model.getPropText());
831         } catch (IOException | BadRequestException e) {
832             logger.error("Exception occured during duplicate check for service and VF", e);
833             throw new CldsConfigException(e.getMessage(), e);
834         }
835         String deploymentId = "";
836         // If model is already deployed then pass same deployment id
837         if (model.getDeploymentId() != null && !model.getDeploymentId().isEmpty()) {
838             deploymentId = model.getDeploymentId();
839         } else {
840             deploymentId = "closedLoop_" + UUID.randomUUID() + "_deploymentId";
841         }
842         String createNewDeploymentStatusUrl = dcaeDispatcherServices.createNewDeployment(deploymentId,
843                 model.getTypeId());
844         String operationStatus = "processing";
845         long waitingTime = System.nanoTime() + TimeUnit.MINUTES.toNanos(10);
846         while ("processing".equalsIgnoreCase(operationStatus)) {
847             // Break the loop if waiting for more than 10 mins
848             if (waitingTime < System.nanoTime()) {
849                 break;
850             }
851             operationStatus = dcaeDispatcherServices.getOperationStatus(createNewDeploymentStatusUrl);
852         }
853         if ("succeeded".equalsIgnoreCase(operationStatus)) {
854             String artifactName = model.getControlName();
855             if (artifactName != null) {
856                 artifactName = artifactName + ".yml";
857             }
858             DcaeEvent dcaeEvent = new DcaeEvent();
859             /* set dcae events */
860             dcaeEvent.setArtifactName(artifactName);
861             dcaeEvent.setEvent(DcaeEvent.EVENT_DEPLOYMENT);
862             CldsEvent.insEvent(cldsDao, dcaeEvent.getControlName(), getUserId(), dcaeEvent.getCldsActionCd(),
863                     CldsEvent.ACTION_STATE_RECEIVED, null);
864             model.setDeploymentId(deploymentId);
865             model.save(cldsDao, getUserId());
866         } else {
867             logger.info("Deploy model (" + modelName + ") failed...Operation Status is - " + operationStatus);
868             throw new HttpClientErrorException(HttpStatus.INTERNAL_SERVER_ERROR,
869                     "Deploy model (" + modelName + ") failed...Operation Status is - " + operationStatus);
870         }
871         logger.info("Deploy model (" + modelName + ") succeeded...Deployment Id is - " + deploymentId);
872         // audit log
873         LoggingUtils.setTimeContext(startTime, new Date());
874         LoggingUtils.setResponseContext("0", "Deploy model success", this.getClass().getName());
875         auditLogger.info("Deploy model completed");
876         return model;
877     }
878
879     @PUT
880     @Path("/undeploy/{modelName}")
881     @Consumes(MediaType.APPLICATION_JSON)
882     @Produces(MediaType.APPLICATION_JSON)
883     public CldsModel unDeployModel(@PathParam("action") String action, @PathParam("modelName") String modelName,
884             @QueryParam("test") String test, CldsModel model) throws IOException {
885         Date startTime = new Date();
886         LoggingUtils.setRequestContext("CldsService: Undeploy model", getPrincipalName());
887         String operationStatusUndeployUrl = dcaeDispatcherServices.deleteExistingDeployment(model.getDeploymentId(),
888                 model.getTypeId());
889         String operationStatus = "processing";
890         long waitingTime = System.nanoTime() + TimeUnit.MINUTES.toNanos(10);
891         while ("processing".equalsIgnoreCase(operationStatus)) {
892             if (waitingTime < System.nanoTime()) {
893                 break;
894             }
895             operationStatus = dcaeDispatcherServices.getOperationStatus(operationStatusUndeployUrl);
896         }
897         if ("succeeded".equalsIgnoreCase(operationStatus)) {
898             String artifactName = model.getControlName();
899             if (artifactName != null) {
900                 artifactName = artifactName + ".yml";
901             }
902             DcaeEvent dcaeEvent = new DcaeEvent();
903             // set dcae events
904             dcaeEvent.setArtifactName(artifactName);
905             dcaeEvent.setEvent(DcaeEvent.EVENT_UNDEPLOYMENT);
906             CldsEvent.insEvent(cldsDao, model.getControlName(), getUserId(), dcaeEvent.getCldsActionCd(),
907                     CldsEvent.ACTION_STATE_RECEIVED, null);
908             model.setDeploymentId(null);
909             model.save(cldsDao, getUserId());
910         } else {
911             logger.info("Undeploy model (" + modelName + ") failed...Operation Status is - " + operationStatus);
912             throw new HttpClientErrorException(HttpStatus.INTERNAL_SERVER_ERROR,
913                     "Undeploy model (" + modelName + ") failed...Operation Status is - " + operationStatus);
914         }
915         logger.info("Undeploy model (" + modelName + ") succeeded.");
916         // audit log
917         LoggingUtils.setTimeContext(startTime, new Date());
918         LoggingUtils.setResponseContext("0", "Undeploy model success", this.getClass().getName());
919         auditLogger.info("Undeploy model completed");
920         return model;
921     }
922
923     private String getGlobalCldsString() {
924         try {
925             if (null == globalCldsProperties) {
926                 globalCldsProperties = new Properties();
927                 globalCldsProperties.load(appContext.getResource(globalClds).getInputStream());
928             }
929             return (String) globalCldsProperties.get("globalCldsProps");
930         } catch (IOException e) {
931             logger.error("Unable to load the globalClds due to an exception", e);
932             throw new CldsConfigException("Unable to load the globalClds due to an exception", e);
933         }
934     }
935
936     private void checkForDuplicateServiceVf(String modelName, String modelPropText) throws IOException {
937         JsonNode modelJson = new ObjectMapper().readTree(modelPropText);
938         JsonNode globalNode = modelJson.get("global");
939         String service = AbstractModelElement.getValueByName(globalNode, "service");
940         List<String> resourceVf = AbstractModelElement.getValuesByName(globalNode, "vf");
941         if (service != null && resourceVf != null && !resourceVf.isEmpty()) {
942             List<CldsModelProp> cldsModelPropList = cldsDao.getDeployedModelProperties();
943             for (CldsModelProp cldsModelProp : cldsModelPropList) {
944                 JsonNode currentJson = new ObjectMapper().readTree(cldsModelProp.getPropText());
945                 JsonNode currentNode = currentJson.get("global");
946                 String currentService = AbstractModelElement.getValueByName(currentNode, "service");
947                 List<String> currentVf = AbstractModelElement.getValuesByName(currentNode, "vf");
948                 if (currentVf != null && !currentVf.isEmpty()) {
949                     if (!modelName.equalsIgnoreCase(cldsModelProp.getName()) && service.equalsIgnoreCase(currentService)
950                             && resourceVf.get(0).equalsIgnoreCase(currentVf.get(0))) {
951                         throw new BadRequestException("Same Service/VF already exists in " + cldsModelProp.getName()
952                                 + " model, please select different Service/VF.");
953
954                     }
955                 }
956             }
957         }
958     }
959 }