2 * Copyright 2017 Huawei Technologies Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package org.onap.cli.fw.http.utils;
19 import java.util.ArrayList;
20 import java.util.HashMap;
21 import java.util.Iterator;
22 import java.util.List;
24 import java.util.Map.Entry;
26 import org.onap.cli.fw.error.OnapCommandException;
27 import org.onap.cli.fw.error.OnapCommandInvalidParameterValue;
28 import org.onap.cli.fw.error.OnapCommandParameterNotFound;
29 import org.onap.cli.fw.error.OnapCommandResultEmpty;
30 import org.onap.cli.fw.error.OnapCommandResultMapProcessingFailed;
31 import org.onap.cli.fw.http.conf.OnapCommandHttpConstants;
32 import org.onap.cli.fw.http.connect.HttpInput;
33 import org.onap.cli.fw.http.connect.HttpResult;
34 import org.onap.cli.fw.http.error.OnapCommandHttpHeaderNotFound;
35 import org.onap.cli.fw.http.error.OnapCommandHttpInvalidRequestBody;
36 import org.onap.cli.fw.http.error.OnapCommandHttpInvalidResponseBody;
37 import org.onap.cli.fw.input.OnapCommandParameter;
38 import org.onap.cli.fw.input.OnapCommandParameterType;
39 import org.onap.cli.fw.utils.OnapCommandUtils;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
43 import com.google.gson.Gson;
44 import com.google.gson.GsonBuilder;
45 import com.google.gson.JsonElement;
46 import com.google.gson.JsonParser;
48 import com.jayway.jsonpath.JsonPath;
49 import com.jayway.jsonpath.PathNotFoundException;
51 import net.minidev.json.JSONArray;
53 public class OnapCommandHttpUtils {
55 static Logger log = LoggerFactory.getLogger(OnapCommandHttpUtils.class);
56 private static Gson gson = new GsonBuilder().serializeNulls().create();
57 private OnapCommandHttpUtils() {
58 throw new IllegalStateException("Utility class");
61 * Set argument to param value.
68 * @throws OnapCommandParameterNotFound
70 * @throws OnapCommandInvalidParameterValue
73 public static HttpInput populateParameters(Map<String, OnapCommandParameter> params, HttpInput input)
74 throws OnapCommandException {
76 HttpInput inp = new HttpInput();
78 for (OnapCommandParameter param : params.values()) {
79 if (OnapCommandParameterType.BINARY.equals(param.getParameterType())) {
80 inp.setBinaryData(true);
85 inp.setUri(OnapCommandUtils.replaceLineForSpecialValues(input.getUri()));
86 inp.setUri(OnapCommandUtils.replaceLineFromInputParameters(input.getUri(), params));
88 inp.setMethod(input.getMethod().toLowerCase());
90 boolean isRemoveEmptyNodes = Boolean.parseBoolean(input.getContext().getOrDefault(OnapCommandHttpConstants.CONTEXT_REMOVE_EMPTY_JSON_NODES, "false"));
93 Map <String, String> values = new HashMap<>();
94 for (Map.Entry<String, OnapCommandParameter> param: params.entrySet()) {
95 values.put(param.getKey(), param.getValue().getValue().toString());
98 if (!input.getMultiparts().isEmpty()) {
99 for (HttpInput.Part part: input.getMultiparts()) {
100 part.setContent(OnapCommandUtils.replaceLineForSpecialValues(part.getContent(), values));
101 part.setContent(OnapCommandUtils.replaceLineFromInputParameters(part.getContent(), params));
102 if (isRemoveEmptyNodes) {
103 part.setContent(OnapCommandHttpUtils.normalizeJson(part.getContent()));
107 inp.setMultiparts(input.getMultiparts());
109 inp.setMultipartEntityName(input.getMultipartEntityName());
110 inp.setBody(OnapCommandUtils.replaceLineForSpecialValues(input.getBody(), values));
111 inp.setBody(OnapCommandUtils.replaceLineFromInputParameters(inp.getBody(), params));
112 if (isRemoveEmptyNodes) {
113 inp.setBody(OnapCommandHttpUtils.normalizeJson(inp.getBody()));
117 //consider __body__ spl entry
118 values.put(OnapCommandHttpConstants.__BODY__, inp.getBody());
120 for (String h : input.getReqHeaders().keySet()) {
121 String value = input.getReqHeaders().get(h);
122 value = OnapCommandUtils.replaceLineForSpecialValues(value, values);
123 inp.getReqHeaders().put(h, OnapCommandUtils.replaceLineFromInputParameters(value, params));
126 for (String h : input.getReqQueries().keySet()) {
127 String value = input.getReqQueries().get(h);
128 value = OnapCommandUtils.replaceLineForSpecialValues(value, values);
129 inp.getReqQueries().put(h, OnapCommandUtils.replaceLineFromInputParameters(value, params));
143 * @throws OnapCommandHttpHeaderNotFound
144 * header not found exception
145 * @throws OnapCommandHttpInvalidResponseBody
146 * invalid response body exception
147 * @throws OnapCommandResultMapProcessingFailed
148 * map processing failed exception
150 public static Map<String, List<String>> populateOutputs(Map<String, String> resultMap, HttpResult resultHttp)
151 throws OnapCommandException {
152 Map<String, List<String>> resultsProcessed = new HashMap<>();
154 for (Entry<String, String> entry : resultMap.entrySet()) {
155 String key = entry.getKey();
157 resultsProcessed.put(key, OnapCommandHttpUtils.replaceLineFromOutputResults(resultMap.get(key), resultHttp));
158 } catch(OnapCommandResultEmpty e) { // NOSONAR
163 return resultsProcessed;
166 public static List<String> replaceLineFromOutputResults(String line, HttpResult resultHttp)
167 throws OnapCommandHttpHeaderNotFound, OnapCommandHttpInvalidResponseBody,
168 OnapCommandResultMapProcessingFailed, OnapCommandResultEmpty {
169 StringBuilder headerProcessedLine = new StringBuilder();
171 ArrayList<String> result = new ArrayList<>();
172 if (!line.contains("$b{") && !line.contains("$h{")) {
178 * In case of empty response body [] or {}
180 if (resultHttp.getBody() != null && resultHttp.getBody().length() <= 2) {
185 * Process headers macros : line: $h{abc}-$b{$.[*].xyz} , After processing line will be [abc's
186 * value]-$b{$.[*].xyz}
189 while (currentIdx < line.length()) {
190 int idxS = line.indexOf("$h{", currentIdx);
192 headerProcessedLine.append(line.substring(currentIdx));
195 int idxE = line.indexOf('}', idxS);
196 String headerName = line.substring(idxS + 3, idxE);
197 headerName = headerName.trim();
198 if (!resultHttp.getRespHeaders().containsKey(headerName)) {
199 throw new OnapCommandHttpHeaderNotFound(headerName);
201 String value = resultHttp.getRespHeaders().get(headerName);
203 headerProcessedLine.append(line.substring(currentIdx, idxS) + value);
204 currentIdx = idxE + 1;
207 // Process body jsonpath macros
208 List<Object> values = new ArrayList<>();
209 StringBuilder bodyProcessedPattern = new StringBuilder();
211 int maxRows = 1; // in normal case, only one row will be there
212 while (currentIdx < headerProcessedLine.length()) {
213 int idxS = headerProcessedLine.indexOf("$b{", currentIdx);
215 bodyProcessedPattern.append(headerProcessedLine.substring(currentIdx));
218 int idxE = headerProcessedLine.indexOf("}", idxS);
219 String jsonPath = headerProcessedLine.substring(idxS + 3, idxE);
220 jsonPath = jsonPath.trim();
221 Object value = new Object();
223 // JSONArray or String
224 value = JsonPath.read(resultHttp.getBody(), jsonPath);
225 } catch (PathNotFoundException e1) { // NOSONAR
226 //set to blank for those entries which are missing from the output json
228 } catch (Exception e) {
229 throw new OnapCommandHttpInvalidResponseBody(jsonPath, e);
232 if (value instanceof JSONArray) {
233 JSONArray arr = (JSONArray) value;
234 if (arr.size() > maxRows) {
235 maxRows = arr.size();
238 bodyProcessedPattern.append(headerProcessedLine.substring(currentIdx, idxS) + "%s");
240 currentIdx = idxE + 1;
243 if (bodyProcessedPattern.toString().isEmpty()) {
244 result.add(headerProcessedLine.toString());
247 for (int i = 0; i < maxRows; i++) {
249 StringBuilder bodyProcessedLine = new StringBuilder();
250 int positionalIdx = 0; // %s positional idx
251 while (currentIdx < bodyProcessedPattern.length()) {
252 int idxS = bodyProcessedPattern.indexOf("%s", currentIdx);
254 bodyProcessedLine.append(bodyProcessedPattern.substring(currentIdx));
257 int idxE = idxS + 2; // %s
259 Object value = values.get(positionalIdx);
260 String valueS = String.valueOf(value);
261 if (value instanceof JSONArray) {
262 JSONArray arr = (JSONArray) value;
263 if (!arr.isEmpty()) {
264 valueS = arr.get(i).toString();
266 throw new OnapCommandResultEmpty();
270 bodyProcessedLine.append(bodyProcessedPattern.substring(currentIdx, idxS) + valueS);
273 } catch (OnapCommandResultEmpty e) {
275 } catch (Exception e) {
276 throw new OnapCommandResultMapProcessingFailed(line, e);
279 result.add(bodyProcessedLine.toString());
286 public static void normalizeJson(JsonElement node) {
287 Iterator<Entry<String, JsonElement>> it = node.getAsJsonObject().entrySet().iterator();
289 while (it.hasNext()) {
290 JsonElement child = it.next().getValue();
291 if (child.isJsonPrimitive() && child.getAsJsonPrimitive().isString() && child.getAsJsonPrimitive().getAsString().equals(""))
293 else if (child.isJsonNull())
295 else if (child.isJsonObject())
296 normalizeJson(child);
297 else if (child.isJsonArray()) {
298 for (JsonElement ele:child.getAsJsonArray()) {
299 if (ele.isJsonObject())
306 public static String normalizeJson(String json) throws OnapCommandHttpInvalidRequestBody {
309 node = JsonParser.parseString(json);
311 return gson.toJson(node);
312 } catch (Exception e) { //NOSONAR
313 throw new OnapCommandHttpInvalidRequestBody(e);