diff options
author | Skip Wonnell <kw5258@att.com> | 2017-08-29 22:39:17 -0500 |
---|---|---|
committer | Marcus Williams <marcus.williams@intel.com> | 2017-08-30 15:36:41 +0000 |
commit | abe9420ac5220879d4790f9020c583cb037dd577 (patch) | |
tree | 178e8b7b0cdaa6317064add7e5e29299459188c5 /appc-client/client-simulator/src/main/java | |
parent | 8c9631e438b9491424df0f43d43445f098436834 (diff) |
Initial add of APPC client libraries
Issue-ID: APPC-180
Change-Id: Ie0be2b518b90bb7f9996e9260c43fef75d1a5821
Signed-off-by: Skip Wonnell <kw5258@att.com>
Diffstat (limited to 'appc-client/client-simulator/src/main/java')
5 files changed, 582 insertions, 0 deletions
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 000000000..225f6bba9 --- /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 000000000..459804aaa --- /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 000000000..de1a2055b --- /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 000000000..aef034f53 --- /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 000000000..d28927302 --- /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))); + } +} |