Merge "Add swagger generation for jaxrs api"
diff --git a/INFO.yaml b/INFO.yaml
new file mode 100644
index 0000000..345217e
--- /dev/null
+++ b/INFO.yaml
@@ -0,0 +1,51 @@
+---
+project: 'clamp'
+project_creation_date: '2017-06-15'
+lifecycle_state: 'Incubation'
+project_lead: &onap_releng_ptl
+    name: 'Gervais-Martial Ngueko'
+    email: 'gn422w@intl.att.com'
+    id: 'osgn422w'
+    company: 'ATT'
+    timezone: 'Belgium/Namur'
+primary_contact: *onap_releng_ptl
+issue_tracking:
+    type: 'jira'
+    url: 'https://jira.onap.org/projects/CLAMP'
+    key: 'CLAMP'
+meetings:
+    - type: 'zoom'
+        agenda: 'https://wiki.onap.org/pages/viewpage.action?pageId=6593117'
+        url: 'https://wiki.onap.org/pages/viewpage.action?pageId=6593117'
+        server: 'n/a'
+        channel: 'n/a'
+        repeats: 'weekly'
+        time: '13:00 UTC'
+committers:
+    - name: 'Christophe Closset'
+        email: 'cc697w@intl.att.com'
+        company: 'ATT'
+        id: 'ChrisC'
+        timezone: 'Belgium/Namur'
+    - name: 'Eddy Hautot'
+        email: 'eh552t@intl.att.com'
+        company: 'ATT'
+        id: 'ehautot'
+        timezone: 'Belgium/Namur'
+    - name: 'Pierre Close'
+        email: 'pc457b@intl.att.com'
+        company: 'ATT'
+        id: 'piclose'
+        timezone: 'Belgium/Namur'
+    - name: 'Sébastien Determe'
+        email: 'sd378r@intl.att.com'
+        company: 'ATT'
+        id: 'sebdet'
+        timezone: 'Belgium/Namur'
+    - name: 'Xinyuan Wang'
+        email: 'wang.xinyuan1@zte.com.cn'
+        company: 'ZTE'
+        id: 'Xinyuan'
+        timezone: 'Belgium/Namur'
+tsc:
+    approval: 'https://lists.onap.org/pipermail/onap-tsc'
diff --git a/pom.xml b/pom.xml
index 9591e7f..0d97cf6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -502,8 +502,15 @@
 				<dependency>
 						<groupId>org.openecomp.sdc.sdc-distribution-client</groupId>
 						<artifactId>sdc-distribution-client</artifactId>
-						<version>1.2.3</version>
+						<version>1.2.2</version>
 				</dependency>
+				<dependency>
+					<groupId>org.openecomp.sdc.sdc-tosca</groupId>
+					<artifactId>sdc-tosca</artifactId>
+					<version>1.2.2</version>
+				</dependency>
+				
+				
 		</dependencies>
 
 		<build>
@@ -514,6 +521,7 @@
 								<directory>src/test/resources</directory>
 								<excludes>
 										<exclude>**/*.jks</exclude>
+										<exclude>**/*.csar</exclude>
 								</excludes>
 								<filtering>true</filtering>
 						</testResource>
@@ -525,6 +533,14 @@
 								<filtering>false</filtering>
 								<targetPath>https</targetPath>
 						</testResource>
+					  <testResource>
+								<directory>src/test/resources/example/sdc</directory>
+								<includes>
+										<include>**.csar</include>
+								</includes>
+								<filtering>false</filtering>
+								<targetPath>example/sdc</targetPath>
+						</testResource>
 				</testResources>
 				<resources>
 						<resource>
diff --git a/src/main/java/org/onap/clamp/clds/client/req/policy/PolicyClient.java b/src/main/java/org/onap/clamp/clds/client/req/policy/PolicyClient.java
index 144a48c..8caac0c 100644
--- a/src/main/java/org/onap/clamp/clds/client/req/policy/PolicyClient.java
+++ b/src/main/java/org/onap/clamp/clds/client/req/policy/PolicyClient.java
@@ -125,7 +125,7 @@
         PolicyParameters policyParameters = new PolicyParameters();
         // Set Policy Type
         policyParameters.setPolicyConfigType(PolicyConfigType.MicroService);
-        policyParameters.setEcompName(refProp.getStringValue(POLICY_ONAPNAME_PROPERTY_NAME));
+        policyParameters.setOnapName(refProp.getStringValue(POLICY_ONAPNAME_PROPERTY_NAME));
         policyParameters.setPolicyName(prop.getCurrentPolicyScopeAndPolicyName());
         policyParameters.setConfigBody(policyJson);
         policyParameters.setConfigBodyType(PolicyType.JSON);
@@ -159,7 +159,7 @@
         PolicyParameters policyParameters = new PolicyParameters();
         // Set Policy Type
         policyParameters.setPolicyConfigType(PolicyConfigType.Base);
-        policyParameters.setEcompName(refProp.getStringValue(POLICY_ONAPNAME_PROPERTY_NAME));
+        policyParameters.setOnapName(refProp.getStringValue(POLICY_ONAPNAME_PROPERTY_NAME));
         policyParameters.setPolicyName(prop.getCurrentPolicyScopeAndPolicyName());
         policyParameters.setConfigBody(configBody);
         policyParameters.setConfigBodyType(PolicyType.OTHER);
@@ -187,7 +187,7 @@
         PolicyParameters policyParameters = new PolicyParameters();
         // Set Policy Type
         policyParameters.setPolicyConfigType(PolicyConfigType.MicroService);
-        policyParameters.setEcompName(refProp.getStringValue(POLICY_ONAPNAME_PROPERTY_NAME));
+        policyParameters.setOnapName(refProp.getStringValue(POLICY_ONAPNAME_PROPERTY_NAME));
         policyParameters.setPolicyName(prop.getCurrentPolicyScopeAndPolicyName());
         policyParameters.setConfigBody(configBody);
         String policyNamePrefix = refProp.getStringValue("policy.ms.policyNamePrefix");
diff --git a/src/main/java/org/onap/clamp/clds/config/sdc/SdcControllersConfiguration.java b/src/main/java/org/onap/clamp/clds/config/sdc/SdcControllersConfiguration.java
index 5b54904..f1a9618 100644
--- a/src/main/java/org/onap/clamp/clds/config/sdc/SdcControllersConfiguration.java
+++ b/src/main/java/org/onap/clamp/clds/config/sdc/SdcControllersConfiguration.java
@@ -71,8 +71,7 @@
     }
 
     public SdcSingleControllerConfiguration getSdcSingleControllerConfiguration(String controllerName) {
-        Map<String, SdcSingleControllerConfiguration> controllerMap = getAllDefinedControllers();
-        return controllerMap.get(controllerName);
+        return getAllDefinedControllers().get(controllerName);
     }
 
     /**
diff --git a/src/main/java/org/onap/clamp/clds/config/sdc/SdcSingleControllerConfiguration.java b/src/main/java/org/onap/clamp/clds/config/sdc/SdcSingleControllerConfiguration.java
index c97beb0..d8bd992 100644
--- a/src/main/java/org/onap/clamp/clds/config/sdc/SdcSingleControllerConfiguration.java
+++ b/src/main/java/org/onap/clamp/clds/config/sdc/SdcSingleControllerConfiguration.java
@@ -56,14 +56,14 @@
     public static final String CONSUMER_GROUP_ATTRIBUTE_NAME = "consumerGroup";
     public static final String CONSUMER_ID_ATTRIBUTE_NAME = "consumerId";
     public static final String ENVIRONMENT_NAME_ATTRIBUTE_NAME = "environmentName";
-    public static final String PASSWORD_ATTRIBUTE_NAME = "password";
+    public static final String SDC_KEY_ATTRIBUTE_NAME = "password";
     public static final String POLLING_INTERVAL_ATTRIBUTE_NAME = "pollingInterval";
     public static final String RELEVANT_ARTIFACT_TYPES_ATTRIBUTE_NAME = "relevantArtifactTypes";
     public static final String USER_ATTRIBUTE_NAME = "user";
     public static final String SDC_ADDRESS_ATTRIBUTE_NAME = "sdcAddress";
     public static final String POLLING_TIMEOUT_ATTRIBUTE_NAME = "pollingTimeout";
     public static final String ACTIVATE_SERVER_TLS_AUTH = "activateServerTLSAuth";
-    public static final String KEY_STORE_PASSWORD = "keyStorePassword";
+    public static final String KEY_STORE_KEY = "keyStorePassword";
     public static final String KEY_STORE_PATH = "keyStorePath";
     private String errorMessageKeyNotFound;
     /**
@@ -109,6 +109,30 @@
         testAllRequiredParameters();
     }
 
+    private String getStringConfig(String key) {
+        if (jsonRootNode != null && jsonRootNode.get(key) != null) {
+            String config = jsonRootNode.get(key).asText();
+            return config.isEmpty() ? null : config;
+        }
+        return null;
+    }
+
+    private Integer getIntConfig(String key) {
+        if (jsonRootNode != null && jsonRootNode.get(key) != null) {
+            return jsonRootNode.get(key).asInt();
+        } else {
+            return 0;
+        }
+    }
+
+    private String getEncryptedStringConfig(String key) throws GeneralSecurityException, DecoderException {
+        if (jsonRootNode != null && jsonRootNode.get(key) != null) {
+            String config = CryptoUtils.decrypt(jsonRootNode.get(key).asText());
+            return config.isEmpty() ? null : config;
+        }
+        return null;
+    }
+
     @Override
     public java.lang.Boolean isUseHttpsWithDmaap() {
         return false;
@@ -125,42 +149,27 @@
 
     @Override
     public String getConsumerID() {
-        if (jsonRootNode != null && jsonRootNode.get(CONSUMER_ID_ATTRIBUTE_NAME) != null) {
-            String config = jsonRootNode.get(CONSUMER_ID_ATTRIBUTE_NAME).asText();
-            return config.isEmpty() ? null : config;
-        }
-        return null;
+        return getStringConfig(CONSUMER_ID_ATTRIBUTE_NAME);
     }
 
     @Override
     public String getEnvironmentName() {
-        if (jsonRootNode != null && jsonRootNode.get(ENVIRONMENT_NAME_ATTRIBUTE_NAME) != null) {
-            String config = jsonRootNode.get(ENVIRONMENT_NAME_ATTRIBUTE_NAME).asText();
-            return config.isEmpty() ? null : config;
-        }
-        return null;
+        return getStringConfig(ENVIRONMENT_NAME_ATTRIBUTE_NAME);
     }
 
     @Override
     public String getPassword() {
         try {
-            if (jsonRootNode != null && jsonRootNode.get(PASSWORD_ATTRIBUTE_NAME) != null) {
-                String config = CryptoUtils.decrypt(jsonRootNode.get(PASSWORD_ATTRIBUTE_NAME).asText());
-                return config.isEmpty() ? null : config;
-            }
+            return getEncryptedStringConfig(SDC_KEY_ATTRIBUTE_NAME);
         } catch (GeneralSecurityException | DecoderException e) {
             logger.error("Unable to decrypt the SDC password", e);
+            return null;
         }
-        return null;
     }
 
     @Override
     public int getPollingInterval() {
-        if (jsonRootNode != null && jsonRootNode.get(POLLING_INTERVAL_ATTRIBUTE_NAME) != null) {
-            return jsonRootNode.get(POLLING_INTERVAL_ATTRIBUTE_NAME).asInt();
-        } else {
-            return 0;
-        }
+        return getIntConfig(POLLING_INTERVAL_ATTRIBUTE_NAME);
     }
 
     @Override
@@ -172,29 +181,17 @@
 
     @Override
     public String getUser() {
-        if (jsonRootNode != null && jsonRootNode.get(USER_ATTRIBUTE_NAME) != null) {
-            String config = jsonRootNode.get(USER_ATTRIBUTE_NAME).asText();
-            return config.isEmpty() ? null : config;
-        }
-        return null;
+        return getStringConfig(USER_ATTRIBUTE_NAME);
     }
 
     @Override
     public String getAsdcAddress() {
-        if (jsonRootNode != null && jsonRootNode.get(SDC_ADDRESS_ATTRIBUTE_NAME) != null) {
-            String config = jsonRootNode.get(SDC_ADDRESS_ATTRIBUTE_NAME).asText();
-            return config.isEmpty() ? null : config;
-        }
-        return null;
+        return getStringConfig(SDC_ADDRESS_ATTRIBUTE_NAME);
     }
 
     @Override
     public int getPollingTimeout() {
-        if (jsonRootNode != null && jsonRootNode.get(POLLING_TIMEOUT_ATTRIBUTE_NAME) != null) {
-            return jsonRootNode.get(POLLING_TIMEOUT_ATTRIBUTE_NAME).asInt();
-        } else {
-            return 0;
-        }
+        return getIntConfig(POLLING_TIMEOUT_ATTRIBUTE_NAME);
     }
 
     @Override
@@ -209,23 +206,16 @@
     @Override
     public String getKeyStorePassword() {
         try {
-            if (jsonRootNode != null && jsonRootNode.get(KEY_STORE_PASSWORD) != null) {
-                String config = CryptoUtils.decrypt(jsonRootNode.get(KEY_STORE_PASSWORD).asText());
-                return config.isEmpty() ? null : config;
-            }
+            return getEncryptedStringConfig(KEY_STORE_KEY);
         } catch (GeneralSecurityException | DecoderException e) {
             logger.error("Unable to decrypt the SDC password", e);
+            return null;
         }
-        return null;
     }
 
     @Override
     public String getKeyStorePath() {
-        if (jsonRootNode != null && jsonRootNode.get(KEY_STORE_PATH) != null) {
-            String config = jsonRootNode.get(KEY_STORE_PATH).asText();
-            return config.isEmpty() ? null : config;
-        }
-        return null;
+        return getStringConfig(KEY_STORE_PATH);
     }
 
     /**
@@ -252,7 +242,7 @@
             throw new SdcParametersException(SDC_ADDRESS_ATTRIBUTE_NAME + errorMessageKeyNotFound);
         }
         if (this.getPassword() == null || this.getPassword().isEmpty()) {
-            throw new SdcParametersException(PASSWORD_ATTRIBUTE_NAME + errorMessageKeyNotFound);
+            throw new SdcParametersException(SDC_KEY_ATTRIBUTE_NAME + errorMessageKeyNotFound);
         }
         if (this.getPollingInterval() == 0) {
             throw new SdcParametersException(POLLING_INTERVAL_ATTRIBUTE_NAME + errorMessageKeyNotFound);
diff --git a/src/main/java/org/onap/clamp/clds/exception/sdc/controller/CsarHandlerException.java b/src/main/java/org/onap/clamp/clds/exception/sdc/controller/CsarHandlerException.java
new file mode 100644
index 0000000..16fd779
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/exception/sdc/controller/CsarHandlerException.java
@@ -0,0 +1,55 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2018 AT&T Intellectual Property. All rights
+ *                             reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+
+package org.onap.clamp.clds.exception.sdc.controller;
+
+/**
+ * Exception during Csar operations.
+ */
+public class CsarHandlerException extends Exception {
+
+    /**
+     * 
+     */
+    private static final long serialVersionUID = -7628640776124409155L;
+
+    /**
+     * @param message
+     *            The message to dump
+     * @param cause
+     *            The Throwable cause object
+     */
+    public CsarHandlerException(final String message) {
+        super(message);
+    }
+
+    /**
+     * @param message
+     *            The message to dump
+     * @param cause
+     *            The Throwable cause object
+     */
+    public CsarHandlerException(final String message, final Throwable cause) {
+        super(message, cause);
+    }
+}
diff --git a/src/main/java/org/onap/clamp/clds/sdc/controller/installer/CsarHandler.java b/src/main/java/org/onap/clamp/clds/sdc/controller/installer/CsarHandler.java
new file mode 100644
index 0000000..270286b
--- /dev/null
+++ b/src/main/java/org/onap/clamp/clds/sdc/controller/installer/CsarHandler.java
@@ -0,0 +1,109 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2018 AT&T Intellectual Property. All rights
+ *                             reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+
+package org.onap.clamp.clds.sdc.controller.installer;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+
+import org.onap.clamp.clds.exception.sdc.controller.CsarHandlerException;
+import org.onap.clamp.clds.exception.sdc.controller.SdcArtifactInstallerException;
+import org.openecomp.sdc.api.notification.IArtifactInfo;
+import org.openecomp.sdc.api.notification.INotificationData;
+import org.openecomp.sdc.api.results.IDistributionClientDownloadResult;
+import org.openecomp.sdc.tosca.parser.api.ISdcCsarHelper;
+import org.openecomp.sdc.tosca.parser.exceptions.SdcToscaParserException;
+import org.openecomp.sdc.tosca.parser.impl.SdcToscaParserFactory;
+
+/**
+ * CsarDescriptor that will be used to deploy in CLAMP.
+ */
+public class CsarHandler {
+
+    private static final EELFLogger logger = EELFManager.getInstance().getLogger(CsarHandler.class);
+    private IArtifactInfo artifactElement;
+    private String filePath;
+    private String controllerName;
+    private SdcToscaParserFactory factory = SdcToscaParserFactory.getInstance();
+    private ISdcCsarHelper sdcCsarHelper;
+    public static final String CSAR_TYPE = "TOSCA_CSAR";
+    private String csarPath;
+
+    public CsarHandler(INotificationData iNotif, String controller, String sdcCsarPath) throws CsarHandlerException {
+        this.csarPath = sdcCsarPath;
+        this.controllerName = controller;
+        this.artifactElement = searchForUniqueCsar(iNotif);
+        this.filePath = buildFilePathForCsar(artifactElement);
+    }
+
+    private String buildFilePathForCsar(IArtifactInfo artifactElement) {
+        return csarPath + "/" + controllerName + "/" + artifactElement.getArtifactName();
+    }
+
+    private IArtifactInfo searchForUniqueCsar(INotificationData iNotif) throws CsarHandlerException {
+        List<IArtifactInfo> serviceArtifacts = iNotif.getServiceArtifacts();
+        for (IArtifactInfo artifact : serviceArtifacts) {
+            if (artifact.getArtifactType().equals(CSAR_TYPE)) {
+                return artifact;
+            }
+        }
+        throw new CsarHandlerException("Unable to find a CSAR in the Sdc Notification");
+    }
+
+    public void save(IDistributionClientDownloadResult resultArtifact)
+            throws SdcArtifactInstallerException, SdcToscaParserException {
+        try {
+            logger.info("Writing CSAR file : " + artifactElement.getArtifactURL() + " UUID "
+                    + artifactElement.getArtifactUUID() + ")");
+            Path path = Paths.get(filePath);
+            Files.createDirectories(path.getParent());
+            Files.createFile(path);
+            try (FileOutputStream outFile = new FileOutputStream(filePath)) {
+                outFile.write(resultArtifact.getArtifactPayload(), 0, resultArtifact.getArtifactPayload().length);
+            }
+            sdcCsarHelper = factory.getSdcCsarHelper(filePath);
+        } catch (IOException e) {
+            throw new SdcArtifactInstallerException(
+                    "Exception caught when trying to write the CSAR on the file system to " + filePath, e);
+        }
+    }
+
+    public IArtifactInfo getArtifactElement() {
+        return artifactElement;
+    }
+
+    public String getFilePath() {
+        return filePath;
+    }
+
+    public ISdcCsarHelper getSdcCsarHelper() {
+        return sdcCsarHelper;
+    }
+}
diff --git a/src/main/java/org/onap/clamp/clds/service/CldsService.java b/src/main/java/org/onap/clamp/clds/service/CldsService.java
index 9bd9c41..d22a518 100644
--- a/src/main/java/org/onap/clamp/clds/service/CldsService.java
+++ b/src/main/java/org/onap/clamp/clds/service/CldsService.java
@@ -52,6 +52,7 @@
 import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
 import javax.xml.transform.TransformerException;
 
 import org.apache.camel.Produce;
@@ -207,7 +208,7 @@
 
     /**
      * REST service that retrieves clds healthcheck information.
-     * 
+     *
      * @return CldsHealthCheck class containing healthcheck info
      */
     @GET
@@ -396,95 +397,106 @@
     @Path("/action/{action}/{modelName}")
     @Consumes(MediaType.APPLICATION_JSON)
     @Produces(MediaType.APPLICATION_JSON)
-    public CldsModel putModelAndProcessAction(@PathParam("action") String action,
+    public Response putModelAndProcessAction(@PathParam("action") String action,
             @PathParam("modelName") String modelName, @QueryParam("test") String test, CldsModel model)
             throws TransformerException, ParseException, GeneralSecurityException, DecoderException {
         Date startTime = new Date();
-        LoggingUtils.setRequestContext("CldsService: Process model action", getPrincipalName());
-        String actionCd = action.toUpperCase();
-        SecureServicePermission permisionManage = SecureServicePermission.create(cldsPermissionTypeClManage,
-                cldsPermissionInstance, actionCd);
-        isAuthorized(permisionManage);
-        isAuthorizedForVf(model);
-        String userId = getUserId();
-        String actionStateCd = CldsEvent.ACTION_STATE_INITIATED;
-        String processDefinitionKey = "clds-process-action-wf";
-        logger.info("PUT actionCd={}", actionCd);
-        logger.info("PUT actionStateCd={}", actionStateCd);
-        logger.info("PUT processDefinitionKey={}", processDefinitionKey);
-        logger.info("PUT modelName={}", modelName);
-        logger.info("PUT test={}", test);
-        logger.info("PUT bpmnText={}", model.getBpmnText());
-        logger.info("PUT propText={}", model.getPropText());
-        logger.info("PUT userId={}", userId);
-        logger.info("PUT getTypeId={}", model.getTypeId());
-        logger.info("PUT deploymentId={}", model.getDeploymentId());
-        if (model.getTemplateName() != null) {
-            CldsTemplate template = cldsDao.getTemplate(model.getTemplateName());
-            if (template != null) {
-                model.setTemplateId(template.getId());
-                model.setDocText(template.getPropText());
-                // This is to provide the Bpmn XML when Template part in UI is
-                // disabled
-                model.setBpmnText(template.getBpmnText());
-            }
-        }
-        // save model to db
-        model.setName(modelName);
-        model.save(cldsDao, getUserId());
-        // get vars and format if necessary
-        String prop = model.getPropText();
-        String bpmn = model.getBpmnText();
-        String docText = model.getDocText();
-        String controlName = model.getControlName();
-        String bpmnJson = cldsBpmnTransformer.doXslTransformToString(bpmn);
-        logger.info("PUT bpmnJson={}", bpmnJson);
-        // Flag indicates whether it is triggered by Validation Test button from
-        // UI
-        boolean isTest = false;
-        if (test != null && test.equalsIgnoreCase("true")) {
-            isTest = true;
-        } else {
-            String actionTestOverride = refProp.getStringValue("action.test.override");
-            if (actionTestOverride != null && actionTestOverride.equalsIgnoreCase("true")) {
-                logger.info("PUT actionTestOverride={}", actionTestOverride);
-                logger.info("PUT override test indicator and setting it to true");
-                isTest = true;
-            }
-        }
-        logger.info("PUT isTest={}", isTest);
-        boolean isInsertTestEvent = false;
-        String insertTestEvent = refProp.getStringValue("action.insert.test.event");
-        if (insertTestEvent != null && insertTestEvent.equalsIgnoreCase("true")) {
-            isInsertTestEvent = true;
-        }
-        logger.info("PUT isInsertTestEvent={}", isInsertTestEvent);
-        // determine if requested action is permitted
-        model.validateAction(actionCd);
-        logger.info("modelProp - " + prop);
-        logger.info("docText - " + docText);
+        CldsModel retrievedModel = null;
+        Boolean errorCase = false;
         try {
-            String result = camelProxy.submit(actionCd, prop, bpmnJson, modelName, controlName, docText, isTest, userId,
-                    isInsertTestEvent);
-            logger.info("Starting Camel flow on request, result is: ", result);
-        } catch (SdcCommunicationException | PolicyClientException | BadRequestException e) {
-            logger.error("Exception occured during invoking Camel process", e);
-            throw new CldsConfigException(e.getMessage(), e);
+            LoggingUtils.setRequestContext("CldsService: Process model action", getPrincipalName());
+            String actionCd = action.toUpperCase();
+            SecureServicePermission permisionManage = SecureServicePermission.create(cldsPermissionTypeClManage,
+                    cldsPermissionInstance, actionCd);
+            isAuthorized(permisionManage);
+            isAuthorizedForVf(model);
+            String userId = getUserId();
+            String actionStateCd = CldsEvent.ACTION_STATE_INITIATED;
+            String processDefinitionKey = "clds-process-action-wf";
+            logger.info("PUT actionCd={}", actionCd);
+            logger.info("PUT actionStateCd={}", actionStateCd);
+            logger.info("PUT processDefinitionKey={}", processDefinitionKey);
+            logger.info("PUT modelName={}", modelName);
+            logger.info("PUT test={}", test);
+            logger.info("PUT bpmnText={}", model.getBpmnText());
+            logger.info("PUT propText={}", model.getPropText());
+            logger.info("PUT userId={}", userId);
+            logger.info("PUT getTypeId={}", model.getTypeId());
+            logger.info("PUT deploymentId={}", model.getDeploymentId());
+            if (model.getTemplateName() != null) {
+                CldsTemplate template = cldsDao.getTemplate(model.getTemplateName());
+                if (template != null) {
+                    model.setTemplateId(template.getId());
+                    model.setDocText(template.getPropText());
+                    // This is to provide the Bpmn XML when Template part in UI is
+                    // disabled
+                    model.setBpmnText(template.getBpmnText());
+                }
+            }
+            // save model to db
+            model.setName(modelName);
+            model.save(cldsDao, getUserId());
+            // get vars and format if necessary
+            String prop = model.getPropText();
+            String bpmn = model.getBpmnText();
+            String docText = model.getDocText();
+            String controlName = model.getControlName();
+            String bpmnJson = cldsBpmnTransformer.doXslTransformToString(bpmn);
+            logger.info("PUT bpmnJson={}", bpmnJson);
+            // Flag indicates whether it is triggered by Validation Test button from
+            // UI
+            boolean isTest = false;
+            if (test != null && test.equalsIgnoreCase("true")) {
+                isTest = true;
+            } else {
+                String actionTestOverride = refProp.getStringValue("action.test.override");
+                if (actionTestOverride != null && actionTestOverride.equalsIgnoreCase("true")) {
+                    logger.info("PUT actionTestOverride={}", actionTestOverride);
+                    logger.info("PUT override test indicator and setting it to true");
+                    isTest = true;
+                }
+            }
+            logger.info("PUT isTest={}", isTest);
+            boolean isInsertTestEvent = false;
+            String insertTestEvent = refProp.getStringValue("action.insert.test.event");
+            if (insertTestEvent != null && insertTestEvent.equalsIgnoreCase("true")) {
+                isInsertTestEvent = true;
+            }
+            logger.info("PUT isInsertTestEvent={}", isInsertTestEvent);
+            // determine if requested action is permitted
+            model.validateAction(actionCd);
+            logger.info("modelProp - " + prop);
+            logger.info("docText - " + docText);
+            try {
+                String result = camelProxy.submit(actionCd, prop, bpmnJson, modelName, controlName, docText, isTest, userId,
+                        isInsertTestEvent);
+                logger.info("Starting Camel flow on request, result is: ", result);
+            } catch (SdcCommunicationException | PolicyClientException | BadRequestException e) {
+                errorCase = true;
+                logger.error("Exception occured during invoking Camel process", e);
+            }
+            // refresh model info from db (get fresh event info)
+            retrievedModel = CldsModel.retrieve(cldsDao, modelName, false);
+            if (!isTest && (actionCd.equalsIgnoreCase(CldsEvent.ACTION_SUBMIT)
+                    || actionCd.equalsIgnoreCase(CldsEvent.ACTION_RESUBMIT)
+                    || actionCd.equalsIgnoreCase(CldsEvent.ACTION_SUBMITDCAE))) {
+                // To verify inventory status and modify model status to distribute
+                dcaeInventoryServices.setEventInventory(retrievedModel, getUserId());
+                retrievedModel.save(cldsDao, getUserId());
+            }
+            // audit log
+            LoggingUtils.setTimeContext(startTime, new Date());
+            LoggingUtils.setResponseContext("0", "Process model action success", this.getClass().getName());
+            auditLogger.info("Process model action completed");
+        } catch (Exception e) {
+            errorCase = true;
+            logger.error("Exception occured during putModelAndProcessAction", e);
         }
-        // refresh model info from db (get fresh event info)
-        CldsModel retrievedModel = CldsModel.retrieve(cldsDao, modelName, false);
-        if (!isTest && (actionCd.equalsIgnoreCase(CldsEvent.ACTION_SUBMIT)
-                || actionCd.equalsIgnoreCase(CldsEvent.ACTION_RESUBMIT)
-                || actionCd.equalsIgnoreCase(CldsEvent.ACTION_SUBMITDCAE))) {
-            // To verify inventory status and modify model status to distribute
-            dcaeInventoryServices.setEventInventory(retrievedModel, getUserId());
-            retrievedModel.save(cldsDao, getUserId());
+
+        if (errorCase) {
+            return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(retrievedModel).build();
         }
-        // audit log
-        LoggingUtils.setTimeContext(startTime, new Date());
-        LoggingUtils.setResponseContext("0", "Process model action success", this.getClass().getName());
-        auditLogger.info("Process model action completed");
-        return retrievedModel;
+        return Response.status(Response.Status.OK).entity(retrievedModel).build();
     }
 
     /**
@@ -542,7 +554,7 @@
 
     /**
      * REST service that retrieves sdc services
-     * 
+     *
      * @throws GeneralSecurityException
      *             In case of issue when decryting the SDC password
      * @throws DecoderException
@@ -572,7 +584,7 @@
 
     /**
      * REST service that retrieves total properties required by UI
-     * 
+     *
      * @throws IOException
      *             In case of issues
      */
@@ -586,7 +598,7 @@
     /**
      * REST service that retrieves total properties by using invariantUUID based
      * on refresh and non refresh
-     * 
+     *
      * @throws GeneralSecurityException
      *             In case of issues with the decryting the encrypted password
      * @throws DecoderException
@@ -794,102 +806,123 @@
     @Path("/deploy/{modelName}")
     @Consumes(MediaType.APPLICATION_JSON)
     @Produces(MediaType.APPLICATION_JSON)
-    public CldsModel deployModel(@PathParam("action") String action, @PathParam("modelName") String modelName,
+    public Response deployModel(@PathParam("action") String action, @PathParam("modelName") String modelName,
             @QueryParam("test") String test, CldsModel model) {
         Date startTime = new Date();
         LoggingUtils.setRequestContext("CldsService: Deploy model", getPrincipalName());
+        Boolean errorCase = false;
         try {
-            checkForDuplicateServiceVf(modelName, model.getPropText());
-        } catch (IOException | BadRequestException e) {
-            logger.error("Exception occured during duplicate check for service and VF", e);
-            throw new CldsConfigException(e.getMessage(), e);
-        }
-        String deploymentId = "";
-        // If model is already deployed then pass same deployment id
-        if (model.getDeploymentId() != null && !model.getDeploymentId().isEmpty()) {
-            deploymentId = model.getDeploymentId();
-        } else {
-            deploymentId = "closedLoop_" + UUID.randomUUID() + "_deploymentId";
-        }
-        String createNewDeploymentStatusUrl = dcaeDispatcherServices.createNewDeployment(deploymentId,
-                model.getTypeId());
-        String operationStatus = "processing";
-        long waitingTime = System.nanoTime() + TimeUnit.MINUTES.toNanos(10);
-        while ("processing".equalsIgnoreCase(operationStatus)) {
-            // Break the loop if waiting for more than 10 mins
-            if (waitingTime < System.nanoTime()) {
-                break;
+            try {
+                checkForDuplicateServiceVf(modelName, model.getPropText());
+            } catch (IOException | BadRequestException e) {
+                errorCase = true;
+                logger.error("Exception occured during duplicate check for service and VF", e);
             }
-            operationStatus = dcaeDispatcherServices.getOperationStatus(createNewDeploymentStatusUrl);
-        }
-        if ("succeeded".equalsIgnoreCase(operationStatus)) {
-            String artifactName = model.getControlName();
-            if (artifactName != null) {
-                artifactName = artifactName + ".yml";
+            String deploymentId = "";
+            // If model is already deployed then pass same deployment id
+            if (model.getDeploymentId() != null && !model.getDeploymentId().isEmpty()) {
+                deploymentId = model.getDeploymentId();
+            } else {
+                deploymentId = "closedLoop_" + UUID.randomUUID() + "_deploymentId";
             }
-            DcaeEvent dcaeEvent = new DcaeEvent();
-            /* set dcae events */
-            dcaeEvent.setArtifactName(artifactName);
-            dcaeEvent.setEvent(DcaeEvent.EVENT_DEPLOYMENT);
-            CldsEvent.insEvent(cldsDao, dcaeEvent.getControlName(), getUserId(), dcaeEvent.getCldsActionCd(),
-                    CldsEvent.ACTION_STATE_RECEIVED, null);
-            model.setDeploymentId(deploymentId);
-            model.save(cldsDao, getUserId());
-        } else {
-            logger.info("Deploy model (" + modelName + ") failed...Operation Status is - " + operationStatus);
-            throw new HttpClientErrorException(HttpStatus.INTERNAL_SERVER_ERROR,
-                    "Deploy model (" + modelName + ") failed...Operation Status is - " + operationStatus);
+            String createNewDeploymentStatusUrl = dcaeDispatcherServices.createNewDeployment(deploymentId,
+                    model.getTypeId());
+            String operationStatus = "processing";
+            long waitingTime = System.nanoTime() + TimeUnit.MINUTES.toNanos(10);
+            while ("processing".equalsIgnoreCase(operationStatus)) {
+                // Break the loop if waiting for more than 10 mins
+                if (waitingTime < System.nanoTime()) {
+                    break;
+                }
+                operationStatus = dcaeDispatcherServices.getOperationStatus(createNewDeploymentStatusUrl);
+            }
+            if ("succeeded".equalsIgnoreCase(operationStatus)) {
+                String artifactName = model.getControlName();
+                if (artifactName != null) {
+                    artifactName = artifactName + ".yml";
+                }
+                DcaeEvent dcaeEvent = new DcaeEvent();
+                /* set dcae events */
+                dcaeEvent.setArtifactName(artifactName);
+                dcaeEvent.setEvent(DcaeEvent.EVENT_DEPLOYMENT);
+                CldsEvent.insEvent(cldsDao, dcaeEvent.getControlName(), getUserId(), dcaeEvent.getCldsActionCd(),
+                        CldsEvent.ACTION_STATE_RECEIVED, null);
+                model.setDeploymentId(deploymentId);
+                model.save(cldsDao, getUserId());
+            } else {
+                logger.info("Deploy model (" + modelName + ") failed...Operation Status is - " + operationStatus);
+                throw new HttpClientErrorException(HttpStatus.INTERNAL_SERVER_ERROR,
+                        "Deploy model (" + modelName + ") failed...Operation Status is - " + operationStatus);
+            }
+            logger.info("Deploy model (" + modelName + ") succeeded...Deployment Id is - " + deploymentId);
+            // audit log
+            LoggingUtils.setTimeContext(startTime, new Date());
+            LoggingUtils.setResponseContext("0", "Deploy model success", this.getClass().getName());
+            auditLogger.info("Deploy model completed");
+        } catch (Exception e) {
+            errorCase = true;
+            logger.error("Exception occured during deployModel", e);
         }
-        logger.info("Deploy model (" + modelName + ") succeeded...Deployment Id is - " + deploymentId);
-        // audit log
-        LoggingUtils.setTimeContext(startTime, new Date());
-        LoggingUtils.setResponseContext("0", "Deploy model success", this.getClass().getName());
-        auditLogger.info("Deploy model completed");
-        return model;
+
+        if (errorCase) {
+            return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(model).build();
+        }
+        return Response.status(Response.Status.OK).entity(model).build();
     }
 
     @PUT
     @Path("/undeploy/{modelName}")
     @Consumes(MediaType.APPLICATION_JSON)
     @Produces(MediaType.APPLICATION_JSON)
-    public CldsModel unDeployModel(@PathParam("action") String action, @PathParam("modelName") String modelName,
+    public Response unDeployModel(@PathParam("action") String action, @PathParam("modelName") String modelName,
             @QueryParam("test") String test, CldsModel model) {
         Date startTime = new Date();
         LoggingUtils.setRequestContext("CldsService: Undeploy model", getPrincipalName());
-        String operationStatusUndeployUrl = dcaeDispatcherServices.deleteExistingDeployment(model.getDeploymentId(),
-                model.getTypeId());
-        String operationStatus = "processing";
-        long waitingTime = System.nanoTime() + TimeUnit.MINUTES.toNanos(10);
-        while ("processing".equalsIgnoreCase(operationStatus)) {
-            if (waitingTime < System.nanoTime()) {
-                break;
+
+        Boolean errorCase = false;
+        try {
+            String operationStatusUndeployUrl = dcaeDispatcherServices.deleteExistingDeployment(model.getDeploymentId(),
+                    model.getTypeId());
+            String operationStatus = "processing";
+            long waitingTime = System.nanoTime() + TimeUnit.MINUTES.toNanos(10);
+            while ("processing".equalsIgnoreCase(operationStatus)) {
+                if (waitingTime < System.nanoTime()) {
+                    break;
+                }
+                operationStatus = dcaeDispatcherServices.getOperationStatus(operationStatusUndeployUrl);
             }
-            operationStatus = dcaeDispatcherServices.getOperationStatus(operationStatusUndeployUrl);
-        }
-        if ("succeeded".equalsIgnoreCase(operationStatus)) {
-            String artifactName = model.getControlName();
-            if (artifactName != null) {
-                artifactName = artifactName + ".yml";
+            if ("succeeded".equalsIgnoreCase(operationStatus)) {
+                String artifactName = model.getControlName();
+                if (artifactName != null) {
+                    artifactName = artifactName + ".yml";
+                }
+                DcaeEvent dcaeEvent = new DcaeEvent();
+                // set dcae events
+                dcaeEvent.setArtifactName(artifactName);
+                dcaeEvent.setEvent(DcaeEvent.EVENT_UNDEPLOYMENT);
+                CldsEvent.insEvent(cldsDao, model.getControlName(), getUserId(), dcaeEvent.getCldsActionCd(),
+                        CldsEvent.ACTION_STATE_RECEIVED, null);
+                model.setDeploymentId(null);
+                model.save(cldsDao, getUserId());
+            } else {
+                logger.info("Undeploy model (" + modelName + ") failed...Operation Status is - " + operationStatus);
+                throw new HttpClientErrorException(HttpStatus.INTERNAL_SERVER_ERROR,
+                        "Undeploy model (" + modelName + ") failed...Operation Status is - " + operationStatus);
             }
-            DcaeEvent dcaeEvent = new DcaeEvent();
-            // set dcae events
-            dcaeEvent.setArtifactName(artifactName);
-            dcaeEvent.setEvent(DcaeEvent.EVENT_UNDEPLOYMENT);
-            CldsEvent.insEvent(cldsDao, model.getControlName(), getUserId(), dcaeEvent.getCldsActionCd(),
-                    CldsEvent.ACTION_STATE_RECEIVED, null);
-            model.setDeploymentId(null);
-            model.save(cldsDao, getUserId());
-        } else {
-            logger.info("Undeploy model (" + modelName + ") failed...Operation Status is - " + operationStatus);
-            throw new HttpClientErrorException(HttpStatus.INTERNAL_SERVER_ERROR,
-                    "Undeploy model (" + modelName + ") failed...Operation Status is - " + operationStatus);
+            logger.info("Undeploy model (" + modelName + ") succeeded.");
+            // audit log
+            LoggingUtils.setTimeContext(startTime, new Date());
+            LoggingUtils.setResponseContext("0", "Undeploy model success", this.getClass().getName());
+            auditLogger.info("Undeploy model completed");
+        } catch (Exception e) {
+            errorCase = true;
+            logger.error("Exception occured during unDeployModel", e);
         }
-        logger.info("Undeploy model (" + modelName + ") succeeded.");
-        // audit log
-        LoggingUtils.setTimeContext(startTime, new Date());
-        LoggingUtils.setResponseContext("0", "Undeploy model success", this.getClass().getName());
-        auditLogger.info("Undeploy model completed");
-        return model;
+
+        if (errorCase) {
+            return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(model).build();
+        }
+        return Response.status(Response.Status.OK).entity(model).build();
     }
 
     private void checkForDuplicateServiceVf(String modelName, String modelPropText) throws IOException {
diff --git a/src/main/java/org/onap/clamp/clds/util/ResourceFileUtil.java b/src/main/java/org/onap/clamp/clds/util/ResourceFileUtil.java
index 720576c..0402754 100644
--- a/src/main/java/org/onap/clamp/clds/util/ResourceFileUtil.java
+++ b/src/main/java/org/onap/clamp/clds/util/ResourceFileUtil.java
@@ -52,7 +52,7 @@
     }
 
     /**
-     * Return resource as a Stream.
+     * Return resource as a String.
      */
     public static String getResourceAsString(String name) throws IOException {
         InputStream is = getResourceAsStream(name);
diff --git a/src/main/resources/META-INF/resources/designer/scripts/CldsModelService.js b/src/main/resources/META-INF/resources/designer/scripts/CldsModelService.js
index f6092b8..0887550 100644
--- a/src/main/resources/META-INF/resources/designer/scripts/CldsModelService.js
+++ b/src/main/resources/META-INF/resources/designer/scripts/CldsModelService.js
@@ -214,6 +214,7 @@
 
       })
       .error(function(data) {
+        def.resolve(data);
         alertService.alertMessage("Action Failure:" + uiAction, 2);
         //def         alertService.alertMessage("Action Successful:"+uiAction,1);
         def.reject(svcAction + " not successful");
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index 3d56725..f626e1a 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -177,6 +177,7 @@
 clamp.config.sdc.InstanceID=X-ECOMP-InstanceID

 clamp.config.sdc.header.requestId = X-ECOMP-RequestID

 #

+clamp.config.sdc.csarFolder = /tmp/sdc-controllers

 #

 clamp.config.ui.location.default=classpath:/clds/templates/ui-location-default.json

 clamp.config.ui.alarm.default=classpath:/clds/templates/ui-alarm-default.json

diff --git a/src/test/java/org/onap/clamp/clds/sdc/controller/installer/CsarHandlerTest.java b/src/test/java/org/onap/clamp/clds/sdc/controller/installer/CsarHandlerTest.java
new file mode 100644
index 0000000..4c3ab86
--- /dev/null
+++ b/src/test/java/org/onap/clamp/clds/sdc/controller/installer/CsarHandlerTest.java
@@ -0,0 +1,104 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2018 AT&T Intellectual Property. All rights
+ *                             reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ */
+
+package org.onap.clamp.clds.sdc.controller.installer;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import com.att.aft.dme2.internal.apache.commons.io.IOUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.AfterClass;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.onap.clamp.clds.exception.sdc.controller.CsarHandlerException;
+import org.onap.clamp.clds.exception.sdc.controller.SdcArtifactInstallerException;
+import org.onap.clamp.clds.util.ResourceFileUtil;
+import org.openecomp.sdc.api.notification.IArtifactInfo;
+import org.openecomp.sdc.api.notification.INotificationData;
+import org.openecomp.sdc.api.results.IDistributionClientDownloadResult;
+import org.openecomp.sdc.tosca.parser.exceptions.SdcToscaParserException;
+
+public class CsarHandlerTest {
+
+    private static final String sdcFolder = "/tmp/csar-handler-tests";
+    private static final String csarArtifactName = "testArtifact.csar";
+
+    @AfterClass
+    public static void removeAllFiles() throws IOException {
+        // Do some cleanup
+        Path path = Paths.get(sdcFolder + "/test-controller/" + csarArtifactName);
+        Files.deleteIfExists(path);
+    }
+
+    @Test
+    public void testConstructor() throws CsarHandlerException {
+        IArtifactInfo serviceArtifact = Mockito.mock(IArtifactInfo.class);
+        Mockito.when(serviceArtifact.getArtifactType()).thenReturn(CsarHandler.CSAR_TYPE);
+        Mockito.when(serviceArtifact.getArtifactName()).thenReturn(csarArtifactName);
+        List<IArtifactInfo> servicesList = new ArrayList<>();
+        servicesList.add(serviceArtifact);
+        INotificationData iNotifData = Mockito.mock(INotificationData.class);
+        Mockito.when(iNotifData.getServiceArtifacts()).thenReturn(servicesList);
+        CsarHandler csar = new CsarHandler(iNotifData, "test-controller", sdcFolder);
+        assertEquals(sdcFolder + "/test-controller" + "/" + csarArtifactName, csar.getFilePath());
+    }
+
+    @Test(expected = CsarHandlerException.class)
+    public void testFailingConstructor() throws CsarHandlerException {
+        INotificationData iNotifData = Mockito.mock(INotificationData.class);
+        Mockito.when(iNotifData.getServiceArtifacts()).thenReturn(new ArrayList<>());
+        new CsarHandler(iNotifData, "test-controller", "/tmp/csar-handler-tests");
+        fail("Exception should have been raised");
+    }
+
+    @Test
+    public void testSave()
+            throws SdcArtifactInstallerException, SdcToscaParserException, CsarHandlerException, IOException {
+        IArtifactInfo serviceArtifact = Mockito.mock(IArtifactInfo.class);
+        Mockito.when(serviceArtifact.getArtifactType()).thenReturn(CsarHandler.CSAR_TYPE);
+        Mockito.when(serviceArtifact.getArtifactName()).thenReturn(csarArtifactName);
+        List<IArtifactInfo> servicesList = new ArrayList<>();
+        servicesList.add(serviceArtifact);
+        INotificationData iNotifData = Mockito.mock(INotificationData.class);
+        Mockito.when(iNotifData.getServiceArtifacts()).thenReturn(servicesList);
+        CsarHandler csar = new CsarHandler(iNotifData, "test-controller", "/tmp/csar-handler-tests");
+        IDistributionClientDownloadResult resultArtifact = Mockito.mock(IDistributionClientDownloadResult.class);
+        Mockito.when(resultArtifact.getArtifactPayload()).thenReturn(
+                IOUtils.toByteArray(ResourceFileUtil.getResourceAsStream("example/sdc/service-Simsfoimap0112.csar")));
+        csar.save(resultArtifact);
+        assertTrue((new File(sdcFolder + "/test-controller/" + csarArtifactName)).exists());
+        assertEquals(csarArtifactName, csar.getArtifactElement().getArtifactName());
+        assertNotNull(csar.getSdcCsarHelper());
+    }
+}
diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties
index adcd4d9..413cfe7 100644
--- a/src/test/resources/application.properties
+++ b/src/test/resources/application.properties
@@ -177,6 +177,7 @@
 clamp.config.sdc.InstanceID=X-ECOMP-InstanceID

 clamp.config.sdc.header.requestId = X-ECOMP-RequestID

 #

+clamp.config.sdc.csarFolder = /tmp/sdc-tests

 #

 clamp.config.ui.location.default=classpath:/clds/templates/ui-location-default.json

 clamp.config.ui.alarm.default=classpath:/clds/templates/ui-alarm-default.json

diff --git a/src/test/resources/example/sdc/service-Simsfoimap0112.csar b/src/test/resources/example/sdc/service-Simsfoimap0112.csar
new file mode 100644
index 0000000..160c8f2
--- /dev/null
+++ b/src/test/resources/example/sdc/service-Simsfoimap0112.csar
Binary files differ