Initial add of APPC client libraries

Issue-ID: APPC-180
Change-Id: Ie0be2b518b90bb7f9996e9260c43fef75d1a5821
Signed-off-by: Skip Wonnell <kw5258@att.com>
diff --git a/appc-client/client-simulator/src/main/java/org/openecomp/appc/simulator/client/RequestHandler.java b/appc-client/client-simulator/src/main/java/org/openecomp/appc/simulator/client/RequestHandler.java
new file mode 100644
index 0000000..225f6bb
--- /dev/null
+++ b/appc-client/client-simulator/src/main/java/org/openecomp/appc/simulator/client/RequestHandler.java
@@ -0,0 +1,33 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * 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.
+ * 
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.appc.simulator.client;
+
+import java.io.File;
+import java.io.IOException;
+
+public interface RequestHandler {
+    void proceedFile(File source, File log) throws IOException, ClassNotFoundException, NoSuchMethodException;
+    void shutdown(boolean isForceShutdown);
+}
diff --git a/appc-client/client-simulator/src/main/java/org/openecomp/appc/simulator/client/ResponseHandler.java b/appc-client/client-simulator/src/main/java/org/openecomp/appc/simulator/client/ResponseHandler.java
new file mode 100644
index 0000000..459804a
--- /dev/null
+++ b/appc-client/client-simulator/src/main/java/org/openecomp/appc/simulator/client/ResponseHandler.java
@@ -0,0 +1,31 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * 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.
+ * 
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.appc.simulator.client;
+
+import java.io.File;
+
+public interface ResponseHandler {
+    void validateResponse(File output);
+}
diff --git a/appc-client/client-simulator/src/main/java/org/openecomp/appc/simulator/client/impl/JsonRequestHandler.java b/appc-client/client-simulator/src/main/java/org/openecomp/appc/simulator/client/impl/JsonRequestHandler.java
new file mode 100644
index 0000000..de1a205
--- /dev/null
+++ b/appc-client/client-simulator/src/main/java/org/openecomp/appc/simulator/client/impl/JsonRequestHandler.java
@@ -0,0 +1,272 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * 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.
+ * 
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.appc.simulator.client.impl;
+
+import org.openecomp.appc.client.lcm.api.*;
+import org.openecomp.appc.client.lcm.exceptions.*;
+import org.openecomp.appc.simulator.client.RequestHandler;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+import java.io.*;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Properties;
+
+public class JsonRequestHandler implements RequestHandler {
+
+    private enum modeT {
+        SYNCH,
+        ASYNCH
+    }
+
+    public static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
+    private String rpcName = null;
+    private String inputClassName = null;
+    private String actionName = null;
+    private String methodName = null;
+    String packageName = null;
+    private LifeCycleManagerStateful service = null;
+    private Properties properties;
+    HashMap<String, String> exceptRpcMap = null;
+    private final EELFLogger LOG = EELFManager.getInstance().getLogger(JsonRequestHandler.class);
+    private AppcLifeCycleManagerServiceFactory appcLifeCycleManagerServiceFactory = null;
+
+
+    public JsonRequestHandler(Properties prop) throws AppcClientException {
+        properties = prop;
+        packageName = properties.getProperty("ctx.model.package") + ".";
+        try {
+            service = createService();
+        } catch (AppcClientException e) {
+            e.printStackTrace();
+        }
+        exceptRpcMap = prepareExceptionsMap();
+    }
+
+    private HashMap<String,String> prepareExceptionsMap() {
+        exceptRpcMap = new HashMap<String, String>();
+
+        String line;
+        BufferedReader reader = null;
+        try {
+            reader = new BufferedReader(new FileReader(properties.getProperty("client.rpc.exceptions.map.file")));
+        } catch (FileNotFoundException e) {
+            return exceptRpcMap;
+        }
+
+        try {
+            while ((line = reader.readLine()) != null)
+            {
+                String[] parts = line.split(":", 2);
+                if (parts.length >= 2)
+                {
+                    String key = parts[0];
+                    String value = parts[1];
+                    exceptRpcMap.put(key, value);
+                } else {
+                    System.out.println("ignoring line: " + line);
+                }
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        try {
+            reader.close();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return exceptRpcMap;
+    }
+
+    @Override
+    public void proceedFile(File source, File log) throws IOException {
+        final JsonNode inputNode = OBJECT_MAPPER.readTree(source);
+
+        try {
+            // proceed with inputNode and get some xxxInput object, depends on action
+            prepareNames(inputNode);
+
+            Object input = prepareObject(inputNode);
+
+            JsonResponseHandler response = new JsonResponseHandler();
+            response.setFile(source.getPath().toString());
+            switch (isSyncMode(inputNode)) {
+                case SYNCH: {
+                    LOG.debug("Received input request will be processed in synchronously mode");
+                    Method rpc = LifeCycleManagerStateful.class.getDeclaredMethod(methodName, input.getClass());
+                    response.onResponse(rpc.invoke(service, input));
+                    break;
+                }
+                case ASYNCH: {
+                    LOG.debug("Received input request will be processed in asynchronously mode");
+                    Method rpc = LifeCycleManagerStateful.class.getDeclaredMethod(methodName, input.getClass(), ResponseHandler.class);
+                    rpc.invoke(service, input, response);
+                    break;
+                }
+                default: {
+                    throw new RuntimeException("Unrecognized request mode");
+                }
+            }
+        }
+        catch(Exception ex){
+            //ex.printStackTrace();
+        }
+
+        LOG.debug("Action <" + actionName + "> from input file <" + source.getPath().toString() + "> processed");
+    }
+
+    private modeT isSyncMode(JsonNode inputNode) {
+        // The following solution is for testing purposes only
+        // the sync/async decision logic may change upon request
+        try {
+            int mode = Integer.parseInt(inputNode.findValue("input").findValue("common-header").findValue("sub-request-id").asText());
+            if ((mode % 2) == 0) {
+                return modeT.SYNCH;
+            }
+        }catch (Throwable ex) {
+            //use ASYNC as default, if value is not integer.
+        }
+        return modeT.ASYNCH;
+    }
+
+    private LifeCycleManagerStateful createService() throws AppcClientException {
+        appcLifeCycleManagerServiceFactory = AppcClientServiceFactoryProvider.getFactory(AppcLifeCycleManagerServiceFactory.class);
+        return appcLifeCycleManagerServiceFactory.createLifeCycleManagerStateful(new ApplicationContext(), properties);
+    }
+
+    public void shutdown(boolean isForceShutdown){
+        appcLifeCycleManagerServiceFactory.shutdownLifeCycleManager(isForceShutdown);
+    }
+
+    public Object prepareObject(JsonNode input) {
+        try {
+            Class cls = Class.forName(inputClassName);
+            try {
+                // since payload is not mandatory field and not all actions contains payload
+                // so we have to check that during input parsing
+                alignPayload(input);
+            } catch (NoSuchFieldException e) {
+                LOG.debug("In " + actionName + " no payload defined");
+            }
+
+            return OBJECT_MAPPER.treeToValue(input.get("input"), cls);
+        }
+        catch(Exception ex){
+            //ex.printStackTrace();
+        }
+        return null;
+    }
+
+    private void prepareNames(JsonNode input) throws NoSuchFieldException {
+        JsonNode inputNode = input.findValue("input");
+        actionName = inputNode.findValue("action").asText();
+        if (actionName.isEmpty()) {
+            throw new NoSuchFieldException("Input doesn't contains field <action>");
+        }
+
+        rpcName = prepareRpcFromAction(actionName);
+        inputClassName = packageName + actionName + "Input";
+        methodName = prepareMethodName(rpcName);
+    }
+
+    private void alignPayload(JsonNode input) throws NoSuchFieldException {
+        JsonNode inputNode = input.findValue("input");
+        JsonNode payload = inputNode.findValue("payload");
+        if (payload == null || payload.asText().isEmpty() || payload.toString().isEmpty())
+            throw new NoSuchFieldException("Input doesn't contains field <payload>");
+
+        String payloadData = payload.asText();
+        if (payloadData.isEmpty())
+            payloadData = payload.toString();
+        ((ObjectNode)inputNode).put("payload", payloadData);
+    }
+
+    private String prepareRpcFromAction(String action) {
+        String rpc = checkExceptionalRpcList(action);
+        if (rpc!= null && !rpc.isEmpty()) {
+            return rpc; // we found exceptional rpc, so no need to format it
+        }
+
+        rpc = "";
+        boolean makeItLowerCase = true;
+        for(int i = 0; i < action.length(); i++)
+        {
+            if(makeItLowerCase) // first character will make lower case
+            {
+                rpc+=Character.toLowerCase(action.charAt(i));
+                makeItLowerCase = false;
+            }
+            else  if((i+1 < action.length()) && Character.isUpperCase(action.charAt(i+1)))
+            {
+                rpc+=action.charAt(i) + "-";
+                makeItLowerCase = true;
+            }
+            else
+            {
+                rpc+=action.charAt(i);
+                makeItLowerCase = false;
+            }
+        }
+        return rpc;
+    }
+
+    private String checkExceptionalRpcList(String action) {
+        if (exceptRpcMap.isEmpty()) {
+            return null;
+        }
+        return exceptRpcMap.get(action);
+    }
+
+    private String prepareMethodName(String inputRpcName) {
+        boolean makeItUpperCase = false;
+        String method = "";
+
+        for(int i = 0; i < inputRpcName.length(); i++)  //to check the characters of string..
+        {
+            if(Character.isLowerCase(inputRpcName.charAt(i)) && makeItUpperCase) // skip first character if it lower case
+            {
+                method+=Character.toUpperCase(inputRpcName.charAt(i));
+                makeItUpperCase = false;
+            }
+            else  if(inputRpcName.charAt(i) == '-')
+            {
+                makeItUpperCase = true;
+            }
+            else
+            {
+                method+=inputRpcName.charAt(i);
+                makeItUpperCase = false;
+            }
+        }
+        return method;
+    }
+
+}
diff --git a/appc-client/client-simulator/src/main/java/org/openecomp/appc/simulator/client/impl/JsonResponseHandler.java b/appc-client/client-simulator/src/main/java/org/openecomp/appc/simulator/client/impl/JsonResponseHandler.java
new file mode 100644
index 0000000..aef034f
--- /dev/null
+++ b/appc-client/client-simulator/src/main/java/org/openecomp/appc/simulator/client/impl/JsonResponseHandler.java
@@ -0,0 +1,147 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * 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.
+ * 
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.appc.simulator.client.impl;
+
+import org.openecomp.appc.client.lcm.api.ResponseHandler;
+import org.openecomp.appc.client.lcm.exceptions.AppcClientException;
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import java.io.FileWriter;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class JsonResponseHandler implements ResponseHandler<Object> {
+
+    public static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
+    private final EELFLogger LOG = EELFManager.getInstance().getLogger(JsonResponseHandler.class);
+
+    private String fileName = "default";
+    private static final int ACCEPT_FAMILY = 1;
+    private static final int SUCCESS_FAMILY = 4;
+    private static final int INTERMEDIATE_MESSAGES =5;
+
+    private AtomicInteger messageCount =new AtomicInteger(1);
+
+    public void setFile(String name) {
+        fileName = name;
+    }
+
+    @Override
+    public void onResponse(Object response) {
+
+        String output = null;
+        try {
+            output = OBJECT_MAPPER.writeValueAsString(response);
+        } catch (JsonProcessingException e) {
+            e.printStackTrace();
+        }
+        LOG.debug("Received response : " + output);
+
+        int errorCode = 0;
+        boolean isFinal = true;
+        try {
+            JsonNode code = OBJECT_MAPPER.readTree(output).findValue("status").findValue("code");
+            if (code == null)
+            {
+                LOG.error("Status code doesn't exist. Malformed response : " + output);
+                flushToErrorFile(output, isFinal);
+                return;
+            }
+            errorCode = code.asInt();
+            errorCode = errorCode / 100;
+            switch (errorCode) {
+                case ACCEPT_FAMILY:
+                    isFinal = false; // for ACCEPT that it is not a final response
+                    break;
+                case INTERMEDIATE_MESSAGES:
+                    isFinal = false; // for 5xx series messages are not a final response
+                    break;
+                default:
+                    break;
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RuntimeException(e);
+        }
+
+        switch (errorCode) {
+            case ACCEPT_FAMILY: {
+                try {
+                    System.out.println("== THR#" + Thread.currentThread().getId() + " Got ACCEPT on ReqID <" +
+                            OBJECT_MAPPER.readTree(output).findValue("common-header").findValue("request-id").asText() + ">");
+                } catch (Exception e) {
+                    e.printStackTrace();
+                    throw new RuntimeException(e);
+                }
+                // no need to report ACCEPT into output file
+                break;
+            }
+            case SUCCESS_FAMILY:
+                flushToOutputFile(output, isFinal);
+                break;
+            case INTERMEDIATE_MESSAGES:
+                flushToMessageFile(output, isFinal);
+                break;
+            default:
+                flushToErrorFile(output, isFinal);
+        }
+    }
+
+    @Override
+    public void onException(AppcClientException exception) {
+        flushToErrorFile("exception: " + exception, true);
+    }
+
+    private void flushToOutputFile(String output, boolean isFinal) {
+        this.flushToFile(output, ".output", isFinal);
+    }
+    private void flushToMessageFile(String output, boolean isFinal) {
+        this.flushToFile(output, ".message" + messageCount.getAndIncrement(), isFinal);
+
+    }
+
+    private void flushToErrorFile(String output, boolean isFinal) {
+        this.flushToFile(output, ".error", isFinal);
+    }
+
+    private void flushToFile(String output, String suffix, boolean isFinal) {
+        try (FileWriter fileWriter = new FileWriter(fileName + suffix);){
+            LOG.info("Output file : " + fileName + suffix);
+
+            fileWriter.write(output);
+            fileWriter.flush();
+            if (isFinal){
+                fileWriter.close();
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        System.out.println("== THR#" +Thread.currentThread().getId()+ " Output file : " + fileName + suffix);
+    }
+}
diff --git a/appc-client/client-simulator/src/main/java/org/openecomp/appc/simulator/client/main/ClientRunner.java b/appc-client/client-simulator/src/main/java/org/openecomp/appc/simulator/client/main/ClientRunner.java
new file mode 100644
index 0000000..d289273
--- /dev/null
+++ b/appc-client/client-simulator/src/main/java/org/openecomp/appc/simulator/client/main/ClientRunner.java
@@ -0,0 +1,99 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * 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.
+ * 
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.appc.simulator.client.main;
+
+import org.apache.commons.io.filefilter.WildcardFileFilter;
+import org.openecomp.appc.simulator.client.RequestHandler;
+import org.openecomp.appc.simulator.client.impl.JsonRequestHandler;
+
+import java.io.*;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Properties;
+
+public class ClientRunner {
+    public static void main(String ... args) throws Exception {
+        String folder = args[0];
+        if (folder == null) {
+            folder = System.getProperty("user.dir");
+        }
+        System.out.println("== THR#" +Thread.currentThread().getId()+ " Reading files under the folder : " + folder);
+
+        String inputType = args[1];
+        if (inputType != null && !inputType.matches("JSON")) {
+            throw new RuntimeException("### ERROR ### - Unsupported file type <" + inputType + "> was provided");
+        }
+
+        Properties properties = getProperties(folder);
+        RequestHandler reqHandler = new JsonRequestHandler(properties);
+        List<File> sources = getJsonFiles(folder);
+        File log = new File(folder + "/output.txt");
+        int filesNum = 0;
+        for (File source: sources) {
+            reqHandler.proceedFile(source, log);
+            System.out.println("== THR#" +Thread.currentThread().getId()+ " File <" + source.getName() + "> processed.");
+            ++filesNum;
+        }
+        System.out.println("DONE with " + filesNum + " files under the folder : " + folder);
+        Thread.sleep(30);
+        System.out.println("Shutdown ...");
+        reqHandler.shutdown(Boolean.parseBoolean(properties.getProperty("client.force.shutdown")));
+//        System.exit(0);
+    }
+
+    private static Properties getProperties(String folder) {
+        Properties prop = new Properties();
+
+        InputStream conf = null;
+        try {
+            conf = new FileInputStream(folder + "client-simulator.properties");
+        } catch (FileNotFoundException e) {
+
+        }
+        if (conf != null) {
+            try {
+                prop.load(conf);
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        } else {
+            try {
+                prop.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("client-simulator.properties"));
+            } catch (Exception e) {
+                throw new RuntimeException("### ERROR ### - Could not load properties to test");
+            }
+        }
+        return prop;
+    }
+
+    private static List<File> getJsonFiles(String folder) throws FileNotFoundException {
+        Path dir = Paths.get(folder);
+        FileFilter fileFilter = new WildcardFileFilter("*.json");
+        return new ArrayList<File>(Arrays.asList(dir.toFile().listFiles(fileFilter)));
+    }
+}
diff --git a/appc-client/client-simulator/src/main/resources/assembly.xml b/appc-client/client-simulator/src/main/resources/assembly.xml
new file mode 100644
index 0000000..69e500f
--- /dev/null
+++ b/appc-client/client-simulator/src/main/resources/assembly.xml
@@ -0,0 +1,51 @@
+<!--
+  ============LICENSE_START=======================================================
+  ONAP : APPC
+  ================================================================================
+  Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+  ================================================================================
+  Copyright (C) 2017 Amdocs
+  =============================================================================
+  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.
+  
+  ECOMP is a trademark and service mark of AT&T Intellectual Property.
+  ============LICENSE_END=========================================================
+  -->
+
+<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.0.0"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.0.0 http://maven.apache.org/xsd/assembly-2.0.0.xsd">
+    <!-- TODO: a jarjar format would be better -->
+    <id>jar-with-dependencies</id>
+    <formats>
+        <format>jar</format>
+    </formats>
+    <includeBaseDirectory>false</includeBaseDirectory>
+    <dependencySets>
+        <dependencySet>
+            <!--<outputDirectory>/</outputDirectory>-->
+            <useProjectArtifact>true</useProjectArtifact>
+            <unpack>true</unpack>
+            <scope>runtime</scope>
+        </dependencySet>
+    </dependencySets>
+    <fileSets>
+        <fileSet>
+            <directory>${basedir}/resources</directory>
+            <includes>
+                <include>*.properties</include>
+            </includes>
+            <outputDirectory>resources</outputDirectory>
+        </fileSet>
+    </fileSets>
+</assembly>
diff --git a/appc-client/client-simulator/src/main/resources/assembly_zip.xml b/appc-client/client-simulator/src/main/resources/assembly_zip.xml
new file mode 100644
index 0000000..2a5202f
--- /dev/null
+++ b/appc-client/client-simulator/src/main/resources/assembly_zip.xml
@@ -0,0 +1,54 @@
+<!--
+  ============LICENSE_START=======================================================
+  ONAP : APPC
+  ================================================================================
+  Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+  ================================================================================
+  Copyright (C) 2017 Amdocs
+  =============================================================================
+  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.
+  
+  ECOMP is a trademark and service mark of AT&T Intellectual Property.
+  ============LICENSE_END=========================================================
+  -->
+
+<assembly
+    xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+    <id>client</id>
+    <formats>
+        <format>tar.gz</format>
+    </formats>
+
+    <includeBaseDirectory>false</includeBaseDirectory>
+
+    <fileSets>
+        <fileSet>
+            <directory>${project.basedir}/src/main/resources</directory>
+            <outputDirectory>.</outputDirectory>
+            <excludes>
+                <exclude>**/*.xml</exclude>
+            </excludes>
+            <lineEnding>unix</lineEnding>
+        </fileSet>
+        <fileSet>
+            <directory>${project.build.directory}</directory>
+            <outputDirectory>.</outputDirectory>
+            <includes>
+                <include>*-jar-with-dependencies.jar</include>
+            </includes>
+        </fileSet>
+    </fileSets>
+</assembly>
+
diff --git a/appc-client/client-simulator/src/main/resources/client-simulator.properties b/appc-client/client-simulator/src/main/resources/client-simulator.properties
new file mode 100644
index 0000000..242b34f
--- /dev/null
+++ b/appc-client/client-simulator/src/main/resources/client-simulator.properties
@@ -0,0 +1,58 @@
+###
+# ============LICENSE_START=======================================================
+# ONAP : APPC
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# Copyright (C) 2017 Amdocs
+# =============================================================================
+# 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.
+# 
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+# ============LICENSE_END=========================================================
+###
+
+#
+# Default Properties - Configured for client simulator
+#
+#--------------------------------------------------------------------------------------------
+ctx.model.package=org.openecomp.appc.client.lcm.model
+
+client.pool.size=10
+client.rpc.exceptions.map.file=C:\\test\\test1\\exceptions.txt
+
+#------------------
+# UEB configuration
+#------------------
+#topic.read=client.test.2
+#topic.read.timeout=10
+#topic.write=client.test.1
+#poolMembers=uebsb91sfdc.it.att.com:3904
+#client.key=1
+#client.secret=1
+#client.name=ClientTest1
+client.name.id=0
+client.response.timeout=60000
+#true - force shutdown
+client.force.shutdown=false
+client.graceful.shutdown.timeout=60000
+
+#topic.read=Topic102-Write
+#topic.read.timeout=60000
+#topic.write=Topic102-Read
+#poolMembers=10.147.100.36:3904
+
+topic.read=Topic106-Write
+topic.read.timeout=20000
+topic.write=Topic106-Read
+poolMembers=10.147.29.67:3904
diff --git a/appc-client/client-simulator/src/main/resources/exceptions.txt b/appc-client/client-simulator/src/main/resources/exceptions.txt
new file mode 100644
index 0000000..54d4330
--- /dev/null
+++ b/appc-client/client-simulator/src/main/resources/exceptions.txt
@@ -0,0 +1 @@
+ConfigScaleOut:config-scaleout
diff --git a/appc-client/client-simulator/src/main/resources/logback.xml b/appc-client/client-simulator/src/main/resources/logback.xml
new file mode 100644
index 0000000..934c2bc
--- /dev/null
+++ b/appc-client/client-simulator/src/main/resources/logback.xml
@@ -0,0 +1,81 @@
+<!--
+  ============LICENSE_START=======================================================
+  ONAP : APPC
+  ================================================================================
+  Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+  ================================================================================
+  Copyright (C) 2017 Amdocs
+  =============================================================================
+  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.
+  
+  ECOMP is a trademark and service mark of AT&T Intellectual Property.
+  ============LICENSE_END=========================================================
+  -->
+
+ <configuration scan="true">
+
+  <property name="componentName" value="APPC-Client"/>
+  <property name="debugDir" value="logs" />
+
+  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+    <filter class="ch.qos.logback.classic.filter.LevelFilter">
+        <level>ERROR</level>
+        <onMatch>ACCEPT</onMatch>
+        <onMismatch>DENY</onMismatch>
+    </filter>
+    <encoder>
+      <pattern>%date{"yyyy-MM-dd HH:mm:ss.SSS z"} [%thread] %-5level %logger{36} %X{akkaSource} - %msg%n</pattern>
+    </encoder>
+  </appender>
+
+  <appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+     <file>logs/client-debug.log</file>
+
+     <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+         <fileNamePattern>logs/client-debug.%d.log.zip</fileNamePattern>
+         <maxHistory>1</maxHistory>
+     </rollingPolicy>
+
+     <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
+         <maxFileSize>10MB</maxFileSize>
+     </triggeringPolicy>
+
+     <encoder>
+         <pattern>%date{"yyyy-MM-dd HH:mm:ss.SSS z"} [%thread] %-5level %logger{35} - %msg%n</pattern>
+     </encoder>
+ </appender>
+
+  <appender name="asyncEELF" class="ch.qos.logback.classic.AsyncAppender">
+     <queueSize>256</queueSize>
+     <appender-ref ref="ERROR_FILE" />
+  </appender>
+
+
+   <root level="debug">
+     <appender-ref ref="DEBUG_FILE" />
+   </root>
+
+     <!--<logger name="ch.qos.logback" level="error" additivity="false">-->
+         <!--<appender-ref ref="asyncEELFServer" />-->
+     <!--</logger>-->
+
+     <!--<logger name="ch.qos.logback" level="error" additivity="false">-->
+         <!--<appender-ref ref="asyncEELFPerformance" />-->
+     <!--</logger>-->
+
+     <!--<logger name="ch.qos.logback" level="error" additivity="false">-->
+         <!--<appender-ref ref="asyncEELFPolicy" />-->
+     <!--</logger>-->
+
+</configuration>
+
diff --git a/appc-client/client-simulator/src/main/resources/run.bat b/appc-client/client-simulator/src/main/resources/run.bat
new file mode 100644
index 0000000..0fb66f4
--- /dev/null
+++ b/appc-client/client-simulator/src/main/resources/run.bat
@@ -0,0 +1,2 @@
+java -jar client-simulator-1.4.07-SNAPSHOT-jar-with-dependencies.jar C:\test\1\ JSON
+pause