Fix Sonar Blocker for resource leak
[appc.git] / appc-client / client-simulator / src / main / java / org / openecomp / appc / simulator / client / impl / JsonRequestHandler.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP : APPC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Copyright (C) 2017 Amdocs
8  * =============================================================================
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  * 
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  * 
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  * 
21  * ECOMP is a trademark and service mark of AT&T Intellectual Property.
22  * ============LICENSE_END=========================================================
23  */
24
25 package org.openecomp.appc.simulator.client.impl;
26
27 import org.openecomp.appc.client.lcm.api.AppcClientServiceFactoryProvider;
28 import org.openecomp.appc.client.lcm.api.AppcLifeCycleManagerServiceFactory;
29 import org.openecomp.appc.client.lcm.api.ApplicationContext;
30 import org.openecomp.appc.client.lcm.api.LifeCycleManagerStateful;
31 import org.openecomp.appc.client.lcm.api.ResponseHandler;
32
33 import org.openecomp.appc.client.lcm.exceptions.AppcClientException;
34 import org.openecomp.appc.simulator.client.RequestHandler;
35
36 import com.att.eelf.configuration.EELFLogger;
37 import com.att.eelf.configuration.EELFManager;
38 import com.fasterxml.jackson.databind.JsonNode;
39 import com.fasterxml.jackson.databind.ObjectMapper;
40 import com.fasterxml.jackson.databind.node.ObjectNode;
41
42 import java.io.BufferedReader;
43 import java.io.File;
44 import java.io.FileNotFoundException;
45 import java.io.FileReader;
46 import java.io.IOException;
47 import java.lang.reflect.Method;
48 import java.util.HashMap;
49 import java.util.Properties;
50
51 public class JsonRequestHandler implements RequestHandler {
52
53     private enum modeT {
54         SYNCH,
55         ASYNCH
56     }
57
58     public static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
59     private String rpcName = null;
60     private String inputClassName = null;
61     private String actionName = null;
62     private String methodName = null;
63     String packageName = null;
64     private LifeCycleManagerStateful service = null;
65     private Properties properties;
66     HashMap<String, String> exceptRpcMap = null;
67     private final EELFLogger LOG = EELFManager.getInstance().getLogger(JsonRequestHandler.class);
68     private AppcLifeCycleManagerServiceFactory appcLifeCycleManagerServiceFactory = null;
69
70
71     public JsonRequestHandler(Properties prop) throws AppcClientException {
72         properties = prop;
73         packageName = properties.getProperty("ctx.model.package") + ".";
74         try {
75             service = createService();
76         } catch (AppcClientException e) {
77             e.printStackTrace();
78         }
79         exceptRpcMap = prepareExceptionsMap();
80     }
81
82     private HashMap<String,String> prepareExceptionsMap() {
83         exceptRpcMap = new HashMap<>();
84
85         try (BufferedReader reader = new BufferedReader(
86                  new FileReader(properties.getProperty(
87                       "client.rpc.exceptions.map.file")))) {
88             String line;
89             while ((line = reader.readLine()) != null) {
90                 String[] parts = line.split(":", 2);
91                 if (parts.length >= 2) {
92                     String key = parts[0];
93                     String value = parts[1];
94                     exceptRpcMap.put(key, value);
95                 } else {
96                     System.out.println("ignoring line: " + line);
97                 }
98             }
99         } catch (FileNotFoundException e) {
100             return exceptRpcMap;
101         } catch (IOException e) {
102             e.printStackTrace();
103         }
104
105         return exceptRpcMap;
106     }
107
108     @Override
109     public void proceedFile(File source, File log) throws IOException {
110         final JsonNode inputNode = OBJECT_MAPPER.readTree(source);
111
112         try {
113             // proceed with inputNode and get some xxxInput object, depends on action
114             prepareNames(inputNode);
115
116             Object input = prepareObject(inputNode);
117
118             JsonResponseHandler response = new JsonResponseHandler();
119             response.setFile(source.getPath().toString());
120             switch (isSyncMode(inputNode)) {
121                 case SYNCH: {
122                     LOG.debug("Received input request will be processed in synchronously mode");
123                     Method rpc = LifeCycleManagerStateful.class.getDeclaredMethod(methodName, input.getClass());
124                     response.onResponse(rpc.invoke(service, input));
125                     break;
126                 }
127                 case ASYNCH: {
128                     LOG.debug("Received input request will be processed in asynchronously mode");
129                     Method rpc = LifeCycleManagerStateful.class.getDeclaredMethod(methodName, input.getClass(), ResponseHandler.class);
130                     rpc.invoke(service, input, response);
131                     break;
132                 }
133                 default: {
134                     throw new RuntimeException("Unrecognized request mode");
135                 }
136             }
137         }
138         catch(Exception ex){
139             //ex.printStackTrace();
140         }
141
142         LOG.debug("Action <" + actionName + "> from input file <" + source.getPath().toString() + "> processed");
143     }
144
145     private modeT isSyncMode(JsonNode inputNode) {
146         // The following solution is for testing purposes only
147         // the sync/async decision logic may change upon request
148         try {
149             int mode = Integer.parseInt(inputNode.findValue("input").findValue("common-header").findValue("sub-request-id").asText());
150             if ((mode % 2) == 0) {
151                 return modeT.SYNCH;
152             }
153         }catch (Exception ex) {
154             //use ASYNC as default, if value is not integer.
155         }
156         return modeT.ASYNCH;
157     }
158
159     private LifeCycleManagerStateful createService() throws AppcClientException {
160         appcLifeCycleManagerServiceFactory = AppcClientServiceFactoryProvider.getFactory(AppcLifeCycleManagerServiceFactory.class);
161         return appcLifeCycleManagerServiceFactory.createLifeCycleManagerStateful(new ApplicationContext(), properties);
162     }
163
164     public void shutdown(boolean isForceShutdown){
165         appcLifeCycleManagerServiceFactory.shutdownLifeCycleManager(isForceShutdown);
166     }
167
168     public Object prepareObject(JsonNode input) {
169         try {
170             Class cls = Class.forName(inputClassName);
171             try {
172                 // since payload is not mandatory field and not all actions contains payload
173                 // so we have to check that during input parsing
174                 alignPayload(input);
175             } catch (NoSuchFieldException e) {
176                 LOG.debug("In " + actionName + " no payload defined");
177             }
178
179             return OBJECT_MAPPER.treeToValue(input.get("input"), cls);
180         }
181         catch(Exception ex){
182             //ex.printStackTrace();
183         }
184         return null;
185     }
186
187     private void prepareNames(JsonNode input) throws NoSuchFieldException {
188         JsonNode inputNode = input.findValue("input");
189         actionName = inputNode.findValue("action").asText();
190         if (actionName.isEmpty()) {
191             throw new NoSuchFieldException("Input doesn't contains field <action>");
192         }
193
194         rpcName = prepareRpcFromAction(actionName);
195         inputClassName = packageName + actionName + "Input";
196         methodName = prepareMethodName(rpcName);
197     }
198
199     private void alignPayload(JsonNode input) throws NoSuchFieldException {
200         JsonNode inputNode = input.findValue("input");
201         JsonNode payload = inputNode.findValue("payload");
202         if (payload == null || payload.asText().isEmpty() || payload.toString().isEmpty())
203             throw new NoSuchFieldException("Input doesn't contains field <payload>");
204
205         String payloadData = payload.asText();
206         if (payloadData.isEmpty())
207             payloadData = payload.toString();
208         ((ObjectNode)inputNode).put("payload", payloadData);
209     }
210
211     private String prepareRpcFromAction(String action) {
212         String rpc = checkExceptionalRpcList(action);
213         if (rpc!= null && !rpc.isEmpty()) {
214             return rpc; // we found exceptional rpc, so no need to format it
215         }
216
217         rpc = "";
218         boolean makeItLowerCase = true;
219         for(int i = 0; i < action.length(); i++)
220         {
221             if(makeItLowerCase) // first character will make lower case
222             {
223                 rpc+=Character.toLowerCase(action.charAt(i));
224                 makeItLowerCase = false;
225             }
226             else  if((i+1 < action.length()) && Character.isUpperCase(action.charAt(i+1)))
227             {
228                 rpc+=action.charAt(i) + "-";
229                 makeItLowerCase = true;
230             }
231             else
232             {
233                 rpc+=action.charAt(i);
234                 makeItLowerCase = false;
235             }
236         }
237         return rpc;
238     }
239
240     private String checkExceptionalRpcList(String action) {
241         if (exceptRpcMap.isEmpty()) {
242             return null;
243         }
244         return exceptRpcMap.get(action);
245     }
246
247     private String prepareMethodName(String inputRpcName) {
248         boolean makeItUpperCase = false;
249         String method = "";
250
251         for(int i = 0; i < inputRpcName.length(); i++)  //to check the characters of string..
252         {
253             if(Character.isLowerCase(inputRpcName.charAt(i)) && makeItUpperCase) // skip first character if it lower case
254             {
255                 method+=Character.toUpperCase(inputRpcName.charAt(i));
256                 makeItUpperCase = false;
257             }
258             else  if(inputRpcName.charAt(i) == '-')
259             {
260                 makeItUpperCase = true;
261             }
262             else
263             {
264                 method+=inputRpcName.charAt(i);
265                 makeItUpperCase = false;
266             }
267         }
268         return method;
269     }
270
271 }