CCSDK plugin has authType param for DG to sel type
[ccsdk/sli/plugins.git] / restapi-call-node / provider / src / main / java / org / onap / ccsdk / sli / plugins / restapicall / RestapiCallNode.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * openECOMP : SDN-C
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights
6  *                      reserved.
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.onap.ccsdk.sli.plugins.restapicall;
23
24 import com.sun.jersey.api.client.ClientHandlerException;
25 import com.sun.jersey.api.client.UniformInterfaceException;
26 import java.io.FileInputStream;
27 import java.io.IOException;
28 import java.net.SocketException;
29 import java.net.URI;
30 import java.nio.file.Files;
31 import java.nio.file.Paths;
32 import java.security.KeyStore;
33 import java.util.ArrayList;
34 import java.util.Collections;
35 import java.util.HashMap;
36 import java.util.HashSet;
37 import java.util.List;
38 import java.util.Map;
39 import java.util.Map.Entry;
40 import java.util.Set;
41
42 import javax.net.ssl.HostnameVerifier;
43 import javax.net.ssl.HttpsURLConnection;
44 import javax.net.ssl.KeyManagerFactory;
45 import javax.net.ssl.SSLContext;
46 import javax.net.ssl.SSLSession;
47 import javax.ws.rs.core.EntityTag;
48 import javax.ws.rs.core.MultivaluedMap;
49 import javax.ws.rs.core.UriBuilder;
50
51 import org.apache.commons.lang3.StringUtils;
52 import org.codehaus.jettison.json.JSONException;
53 import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
54 import org.onap.ccsdk.sli.core.sli.SvcLogicException;
55 import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin;
56 import org.slf4j.Logger;
57 import org.slf4j.LoggerFactory;
58
59 import com.sun.jersey.api.client.Client;
60 import com.sun.jersey.api.client.ClientResponse;
61 import com.sun.jersey.api.client.WebResource;
62 import com.sun.jersey.api.client.config.ClientConfig;
63 import com.sun.jersey.api.client.config.DefaultClientConfig;
64 import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter;
65 import com.sun.jersey.api.client.filter.HTTPDigestAuthFilter;
66 import com.sun.jersey.oauth.client.OAuthClientFilter;
67 import com.sun.jersey.oauth.signature.OAuthParameters;
68 import com.sun.jersey.oauth.signature.OAuthSecrets;
69 import com.sun.jersey.client.urlconnection.HTTPSProperties;
70
71 public class RestapiCallNode implements SvcLogicJavaPlugin {
72
73     private static final Logger log = LoggerFactory.getLogger(RestapiCallNode.class);
74
75     private String uebServers;
76     private String defaultUebTemplateFileName = "/opt/bvc/restapi/templates/default-ueb-message.json";
77     protected RetryPolicyStore retryPolicyStore;
78
79     protected RetryPolicyStore getRetryPolicyStore() {
80         return retryPolicyStore;
81     }
82
83     public void setRetryPolicyStore(RetryPolicyStore retryPolicyStore) {
84         this.retryPolicyStore = retryPolicyStore;
85     }
86
87     public RestapiCallNode() {
88
89     }
90
91      /**
92      * Allows Directed Graphs  the ability to interact with REST APIs.
93      * @param parameters HashMap<String,String> of parameters passed by the DG to this function
94      * <table border="1">
95      *  <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th><th>example values</th></thead>
96      *  <tbody>
97      *      <tr><td>templateFileName</td><td>Optional</td><td>full path to template file that can be used to build a request</td><td>/sdncopt/bvc/restapi/templates/vnf_service-configuration-operation_minimal.json</td></tr>
98      *      <tr><td>restapiUrl</td><td>Mandatory</td><td>url to send the request to</td><td>https://sdncodl:8543/restconf/operations/L3VNF-API:create-update-vnf-request</td></tr>
99      *      <tr><td>restapiUser</td><td>Optional</td><td>user name to use for http basic authentication</td><td>sdnc_ws</td></tr>
100      *      <tr><td>restapiPassword</td><td>Optional</td><td>unencrypted password to use for http basic authentication</td><td>plain_password</td></tr>
101      *      <tr><td>oAuthConsumerKey</td><td>Optional</td><td>Consumer key to use for http oAuth authentication</td><td>plain_key</td></tr>
102      *      <tr><td>oAuthConsumerSecret</td><td>Optional</td><td>Consumer secret to use for http oAuth authentication</td><td>plain_secret</td></tr>
103      *      <tr><td>oAuthSignatureMethod</td><td>Optional</td><td>Consumer method to use for http oAuth authentication</td><td>method</td></tr>
104      *      <tr><td>oAuthVersion</td><td>Optional</td><td>Version http oAuth authentication</td><td>version</td></tr>
105      *      <tr><td>contentType</td><td>Optional</td><td>http content type to set in the http header</td><td>usually application/json or application/xml</td></tr>
106      *      <tr><td>format</td><td>Optional</td><td>should match request body format</td><td>json or xml</td></tr>
107      *      <tr><td>httpMethod</td><td>Optional</td><td>http method to use when sending the request</td><td>get post put delete patch</td></tr>
108      *      <tr><td>responsePrefix</td><td>Optional</td><td>location the response will be written to in context memory</td><td>tmp.restapi.result</td></tr>
109      *      <tr><td>listName[i]</td><td>Optional</td><td>Used for processing XML responses with repeating elements.</td>vpn-information.vrf-details<td></td></tr>
110      *      <tr><td>skipSending</td><td>Optional</td><td></td><td>true or false</td></tr>
111      *      <tr><td>convertResponse </td><td>Optional</td><td>whether the response should be converted</td><td>true or false</td></tr>
112      *      <tr><td>customHttpHeaders</td><td>Optional</td><td>a list additional http headers to be passed in, follow the format in the example</td><td>X-CSI-MessageId=messageId,headerFieldName=headerFieldValue</td></tr>
113      *      <tr><td>dumpHeaders</td><td>Optional</td><td>when true writes http header content to context memory</td><td>true or false</td></tr>
114      *      <tr><td>partner</td><td>Optional</td><td>needed for DME2 calls</td><td>dme2proxy</td></tr>
115      *  </tbody>
116      * </table>
117      * @param ctx Reference to context memory
118      * @throws SvcLogicException
119      * @since 11.0.2
120      * @see String#split(String, int)
121      */
122     public void sendRequest(Map<String, String> paramMap, SvcLogicContext ctx) throws SvcLogicException {
123         sendRequest(paramMap, ctx, null);
124     }
125
126     public void sendRequest(Map<String, String> paramMap, SvcLogicContext ctx, Integer retryCount)
127             throws SvcLogicException {
128
129         RetryPolicy retryPolicy = null;
130         HttpResponse r = new HttpResponse();
131         try {
132             Parameters p = getParameters(paramMap);
133             if (p.partner != null) {
134                 retryPolicy = retryPolicyStore.getRetryPolicy(p.partner);
135             }
136             String pp = p.responsePrefix != null ? p.responsePrefix + '.' : "";
137
138             String req = null;
139             if (p.templateFileName != null) {
140                 String reqTemplate = readFile(p.templateFileName);
141                 req = buildXmlJsonRequest(ctx, reqTemplate, p.format);
142             } else if (p.requestBody != null) {
143                 req = p.requestBody;
144             }
145             r = sendHttpRequest(req, p);
146             setResponseStatus(ctx, p.responsePrefix, r);
147
148             if (p.dumpHeaders && r.headers != null) {
149                 for (Entry<String, List<String>> a : r.headers.entrySet()) {
150                     ctx.setAttribute(pp + "header." + a.getKey(), StringUtils.join(a.getValue(), ","));
151                 }
152             }
153
154             if (r.body != null && r.body.trim().length() > 0) {
155                 ctx.setAttribute(pp + "httpResponse", r.body);
156
157                 if (p.convertResponse) {
158                     Map<String, String> mm = null;
159                     if (p.format == Format.XML)
160                         mm = XmlParser.convertToProperties(r.body, p.listNameList);
161                     else if (p.format == Format.JSON)
162                         mm = JsonParser.convertToProperties(r.body);
163
164                     if (mm != null)
165                         for (Map.Entry<String,String> entry : mm.entrySet())
166                             ctx.setAttribute(pp + entry.getKey(), entry.getValue());
167                 }
168             }
169         } catch (SvcLogicException e) {
170             boolean shouldRetry = false;
171             if (e.getCause().getCause() instanceof SocketException) {
172                 shouldRetry = true;
173             }
174
175             log.error("Error sending the request: " + e.getMessage(), e);
176             String prefix = parseParam(paramMap, "responsePrefix", false, null);
177             if (retryPolicy == null || shouldRetry == false) {
178                 setFailureResponseStatus(ctx, prefix, e.getMessage(), r);
179             } else {
180                 if (retryCount == null) {
181                     retryCount = 0;
182                 }
183                 String retryMessage = retryCount + " attempts were made out of " + retryPolicy.getMaximumRetries() +
184                         " maximum retries.";
185                 log.debug(retryMessage);
186                 try {
187                     retryCount = retryCount + 1;
188                     if (retryCount < retryPolicy.getMaximumRetries() + 1) {
189                         URI uri = new URI(paramMap.get("restapiUrl"));
190                         String hostname = uri.getHost();
191                         String retryString = retryPolicy.getNextHostName(uri.toString());
192                         URI uriTwo = new URI(retryString);
193                         URI retryUri = UriBuilder.fromUri(uri).host(uriTwo.getHost()).port(uriTwo.getPort()).scheme(
194                                 uriTwo.getScheme()).build();
195                         paramMap.put("restapiUrl", retryUri.toString());
196                         log.debug("URL was set to {}", retryUri.toString());
197                         log.debug("Failed to communicate with host {}. Request will be re-attempted using the host {}.",
198                             hostname, retryString);
199                         log.debug("This is retry attempt {} out of {}", retryCount, retryPolicy.getMaximumRetries());
200                         sendRequest(paramMap, ctx, retryCount);
201                     } else {
202                         log.debug("Maximum retries reached, calling setFailureResponseStatus.");
203                         setFailureResponseStatus(ctx, prefix, e.getMessage(), r);
204                     }
205                 } catch (Exception ex) {
206                     log.error("Could not attempt retry.", ex);
207                     String retryErrorMessage =
208                             "Retry attempt has failed. No further retry shall be attempted, calling " +
209                                 "setFailureResponseStatus.";
210                     setFailureResponseStatus(ctx, prefix, retryErrorMessage, r);
211                 }
212             }
213         }
214
215         if (r != null && r.code >= 300)
216             throw new SvcLogicException(String.valueOf(r.code) + ": " + r.message);
217     }
218
219     protected Parameters getParameters(Map<String, String> paramMap) throws SvcLogicException {
220         Parameters p = new Parameters();
221         p.templateFileName = parseParam(paramMap, "templateFileName", false, null);
222         p.requestBody = parseParam(paramMap, "requestBody", false, null);
223         p.restapiUrl = parseParam(paramMap, "restapiUrl", true, null);
224         validateUrl(p.restapiUrl);
225         p.restapiUser = parseParam(paramMap, "restapiUser", false, null);
226         p.restapiPassword = parseParam(paramMap, "restapiPassword", false, null);
227         p.oAuthConsumerKey = parseParam(paramMap, "oAuthConsumerKey", false, null);
228         p.oAuthConsumerSecret = parseParam(paramMap, "oAuthConsumerSecret", false, null);
229         p.oAuthSignatureMethod = parseParam(paramMap, "oAuthSignatureMethod", false, null);
230         p.oAuthVersion = parseParam(paramMap, "oAuthVersion", false, null);
231         p.contentType = parseParam(paramMap, "contentType", false, null);
232         p.format = Format.fromString(parseParam(paramMap, "format", false, "json"));
233         p.authtype = AuthType.fromString(parseParam(paramMap, "authType", false, "unspecified"));
234         p.httpMethod = HttpMethod.fromString(parseParam(paramMap, "httpMethod", false, "post"));
235         p.responsePrefix = parseParam(paramMap, "responsePrefix", false, null);
236         p.listNameList = getListNameList(paramMap);
237         String skipSendingStr = paramMap.get("skipSending");
238         p.skipSending = "true".equalsIgnoreCase(skipSendingStr);
239         p.convertResponse = Boolean.valueOf(parseParam(paramMap, "convertResponse", false, "true"));
240         p.trustStoreFileName = parseParam(paramMap, "trustStoreFileName", false, null);
241         p.trustStorePassword = parseParam(paramMap, "trustStorePassword", false, null);
242         p.keyStoreFileName = parseParam(paramMap, "keyStoreFileName", false, null);
243         p.keyStorePassword = parseParam(paramMap, "keyStorePassword", false, null);
244         p.ssl = p.trustStoreFileName != null && p.trustStorePassword != null && p.keyStoreFileName != null &&
245                 p.keyStorePassword != null;
246         p.customHttpHeaders = parseParam(paramMap, "customHttpHeaders", false, null);
247         p.partner = parseParam(paramMap, "partner", false, null);
248         p.dumpHeaders = Boolean.valueOf(parseParam(paramMap, "dumpHeaders", false, null));
249         return p;
250     }
251
252     private void validateUrl(String restapiUrl) throws SvcLogicException {
253         try {
254             URI.create(restapiUrl);
255         } catch (IllegalArgumentException e) {
256             throw new SvcLogicException("Invalid input of url " + e.getLocalizedMessage(), e);
257         }
258     }
259
260     protected Set<String> getListNameList(Map<String, String> paramMap) {
261         Set<String> ll = new HashSet<>();
262         for (Map.Entry<String,String> entry : paramMap.entrySet())
263             if (entry.getKey().startsWith("listName"))
264                 ll.add(entry.getValue());
265         return ll;
266     }
267
268     protected String parseParam(Map<String, String> paramMap, String name, boolean required, String def)
269             throws SvcLogicException {
270         String s = paramMap.get(name);
271
272         if (s == null || s.trim().length() == 0) {
273             if (!required)
274                 return def;
275             throw new SvcLogicException("Parameter " + name + " is required in RestapiCallNode");
276         }
277
278         s = s.trim();
279         StringBuilder value = new StringBuilder();
280         int i = 0;
281         int i1 = s.indexOf('%');
282         while (i1 >= 0) {
283             int i2 = s.indexOf('%', i1 + 1);
284             if (i2 < 0)
285                 break;
286
287             String varName = s.substring(i1 + 1, i2);
288             String varValue = System.getenv(varName);
289             if (varValue == null)
290                 varValue = "%" + varName + "%";
291
292             value.append(s.substring(i, i1));
293             value.append(varValue);
294
295             i = i2 + 1;
296             i1 = s.indexOf('%', i);
297         }
298         value.append(s.substring(i));
299
300         log.info("Parameter {}: [{}]", name, value);
301         return value.toString();
302     }
303
304     protected String buildXmlJsonRequest(SvcLogicContext ctx, String template, Format format)
305         throws SvcLogicException {
306         log.info("Building {} started", format);
307         long t1 = System.currentTimeMillis();
308
309         template = expandRepeats(ctx, template, 1);
310
311         Map<String, String> mm = new HashMap<>();
312         for (String s : ctx.getAttributeKeySet())
313             mm.put(s, ctx.getAttribute(s));
314
315         StringBuilder ss = new StringBuilder();
316         int i = 0;
317         while (i < template.length()) {
318             int i1 = template.indexOf("${", i);
319             if (i1 < 0) {
320                 ss.append(template.substring(i));
321                 break;
322             }
323
324             int i2 = template.indexOf('}', i1 + 2);
325             if (i2 < 0)
326                 throw new SvcLogicException("Template error: Matching } not found");
327
328             String var1 = template.substring(i1 + 2, i2);
329             String value1 = format == Format.XML ? XmlJsonUtil.getXml(mm, var1) : XmlJsonUtil.getJson(mm, var1);
330             // log.info(" " + var1 + ": " + value1);
331             if (value1 == null || value1.trim().length() == 0) {
332                 // delete the whole element (line)
333                 int i3 = template.lastIndexOf('\n', i1);
334                 if (i3 < 0)
335                     i3 = 0;
336                 int i4 = template.indexOf('\n', i1);
337                 if (i4 < 0)
338                     i4 = template.length();
339
340                 if (i < i3)
341                     ss.append(template.substring(i, i3));
342                 i = i4;
343             } else {
344                 ss.append(template.substring(i, i1)).append(value1);
345                 i = i2 + 1;
346             }
347         }
348
349         String req = format == Format.XML
350                 ? XmlJsonUtil.removeEmptyStructXml(ss.toString()) : XmlJsonUtil.removeEmptyStructJson(ss.toString());
351
352         if (format == Format.JSON)
353             req = XmlJsonUtil.removeLastCommaJson(req);
354
355         long t2 = System.currentTimeMillis();
356         log.info("Building {} completed. Time: {}", format, (t2 - t1));
357
358         return req;
359     }
360
361     protected String expandRepeats(SvcLogicContext ctx, String template, int level) throws SvcLogicException {
362         StringBuilder newTemplate = new StringBuilder();
363         int k = 0;
364         while (k < template.length()) {
365             int i1 = template.indexOf("${repeat:", k);
366             if (i1 < 0) {
367                 newTemplate.append(template.substring(k));
368                 break;
369             }
370
371             int i2 = template.indexOf(':', i1 + 9);
372             if (i2 < 0)
373                 throw new SvcLogicException(
374                         "Template error: Context variable name followed by : is required after repeat");
375
376             // Find the closing }, store in i3
377             int nn = 1;
378             int i3 = -1;
379             int i = i2;
380             while (nn > 0 && i < template.length()) {
381                 i3 = template.indexOf('}', i);
382                 if (i3 < 0)
383                     throw new SvcLogicException("Template error: Matching } not found");
384                 int i32 = template.indexOf('{', i);
385                 if (i32 >= 0 && i32 < i3) {
386                     nn++;
387                     i = i32 + 1;
388                 } else {
389                     nn--;
390                     i = i3 + 1;
391                 }
392             }
393
394             String var1 = template.substring(i1 + 9, i2);
395             String value1 = ctx.getAttribute(var1);
396             log.info("     {}:{}", var1, value1);
397             int n = 0;
398             try {
399                 n = Integer.parseInt(value1);
400             } catch (NumberFormatException e) {
401                 log.info("value1 not set or not a number, n will remain set at zero");
402             }
403
404             newTemplate.append(template.substring(k, i1));
405
406             String rpt = template.substring(i2 + 1, i3);
407
408             for (int ii = 0; ii < n; ii++) {
409                 String ss = rpt.replaceAll("\\[\\$\\{" + level + "\\}\\]", "[" + ii + "]");
410                 if (ii == n - 1 && ss.trim().endsWith(",")) {
411                     int i4 = ss.lastIndexOf(',');
412                     if (i4 > 0)
413                         ss = ss.substring(0, i4) + ss.substring(i4 + 1);
414                 }
415                 newTemplate.append(ss);
416             }
417
418             k = i3 + 1;
419         }
420
421         if (k == 0)
422             return newTemplate.toString();
423
424         return expandRepeats(ctx, newTemplate.toString(), level + 1);
425     }
426
427     protected String readFile(String fileName) throws SvcLogicException {
428         try {
429             byte[] encoded = Files.readAllBytes(Paths.get(fileName));
430             return new String(encoded, "UTF-8");
431         } catch (IOException | SecurityException e) {
432             throw new SvcLogicException("Unable to read file " + fileName + e.getLocalizedMessage(), e);
433         }
434     }
435
436     protected Client addAuthType(Client c, FileParam fp) throws SvcLogicException {
437         Parameters p = new Parameters();
438         p.restapiUser = fp.user;
439         p.restapiPassword = fp.password;
440         p.oAuthConsumerKey = fp.oAuthConsumerKey;
441         p.oAuthVersion = fp.oAuthVersion;
442         p.oAuthConsumerSecret = fp.oAuthConsumerSecret;
443         p.oAuthSignatureMethod = fp.oAuthSignatureMethod;
444         p.authtype = fp.authtype;
445         return addAuthType(c,p);
446     }
447
448     protected Client addAuthType(Client client, Parameters p) throws SvcLogicException {
449         if (p.authtype == AuthType.Unspecified){
450             if (p.restapiUser != null && p.restapiPassword != null)
451                 client.addFilter(new HTTPBasicAuthFilter(p.restapiUser, p.restapiPassword));
452             else if(p.oAuthConsumerKey != null && p.oAuthConsumerSecret != null
453                     && p.oAuthSignatureMethod != null) {
454                 OAuthParameters params = new OAuthParameters()
455                         .signatureMethod(p.oAuthSignatureMethod)
456                         .consumerKey(p.oAuthConsumerKey)
457                         .version(p.oAuthVersion);
458
459                 OAuthSecrets secrets = new OAuthSecrets()
460                         .consumerSecret(p.oAuthConsumerSecret);
461                 client.addFilter(new OAuthClientFilter(client.getProviders(), params, secrets));
462             }
463         } else {
464             if (p.authtype == AuthType.DIGEST) {
465                 if (p.restapiUser != null && p.restapiPassword != null) {
466                     client.addFilter(new HTTPDigestAuthFilter(p.restapiUser, p.restapiPassword));
467                 } else {
468                     throw new SvcLogicException("oAUTH authentication type selected but all restapiUser and restapiPassword " +
469                                                         "parameters doesn't exist", new Throwable());
470                 }
471             } else if (p.authtype == AuthType.BASIC){
472                 if (p.restapiUser != null && p.restapiPassword != null) {
473                     client.addFilter(new HTTPBasicAuthFilter(p.restapiUser, p.restapiPassword));
474                 } else {
475                     throw new SvcLogicException("oAUTH authentication type selected but all restapiUser and restapiPassword " +
476                                                         "parameters doesn't exist", new Throwable());
477                 }
478             } else if(p.authtype == AuthType.OAUTH ) {
479                 if(p.oAuthConsumerKey != null && p.oAuthConsumerSecret != null && p.oAuthSignatureMethod != null) {
480                     OAuthParameters params = new OAuthParameters()
481                             .signatureMethod(p.oAuthSignatureMethod)
482                             .consumerKey(p.oAuthConsumerKey)
483                             .version(p.oAuthVersion);
484
485                     OAuthSecrets secrets = new OAuthSecrets()
486                             .consumerSecret(p.oAuthConsumerSecret);
487                     client.addFilter(new OAuthClientFilter(client.getProviders(), params, secrets));
488                 } else {
489                     throw new SvcLogicException("oAUTH authentication type selected but all oAuthConsumerKey, oAuthConsumerSecret " +
490                                                         "and oAuthSignatureMethod parameters doesn't exist", new Throwable());
491                 }
492             }
493         }
494         return client;
495     }
496
497     protected HttpResponse sendHttpRequest(String request, Parameters p) throws SvcLogicException {
498
499         ClientConfig config = new DefaultClientConfig();
500         SSLContext ssl = null;
501         if (p.ssl && p.restapiUrl.startsWith("https"))
502             ssl = createSSLContext(p);
503         if (ssl != null) {
504             HostnameVerifier hostnameVerifier = (hostname, session) -> true;
505
506             config.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES,
507                     new HTTPSProperties(hostnameVerifier, ssl));
508         }
509
510         logProperties(config.getProperties());
511
512         Client client = Client.create(config);
513         client.setConnectTimeout(5000);
514         WebResource webResource = addAuthType(client,p).resource(p.restapiUrl);
515
516         log.info("Sending request:");
517         log.info(request);
518         long t1 = System.currentTimeMillis();
519
520         HttpResponse r = new HttpResponse();
521         r.code = 200;
522
523         if (!p.skipSending) {
524             String tt = p.format == Format.XML ? "application/xml" : "application/json";
525             String tt1 = tt + ";charset=UTF-8";
526             if (p.contentType != null) {
527                 tt = p.contentType;
528                 tt1 = p.contentType;
529             }
530
531             WebResource.Builder webResourceBuilder = webResource.accept(tt).type(tt1);
532             if(p.format == Format.NONE){
533                 webResourceBuilder = webResource.header("","");
534             }
535
536             if (p.customHttpHeaders != null && p.customHttpHeaders.length() > 0) {
537                 String[] keyValuePairs = p.customHttpHeaders.split(",");
538                 for (String singlePair : keyValuePairs) {
539                     int equalPosition = singlePair.indexOf('=');
540                     webResourceBuilder.header(singlePair.substring(0, equalPosition),
541                             singlePair.substring(equalPosition + 1, singlePair.length()));
542                 }
543             }
544
545             webResourceBuilder.header("X-ECOMP-RequestID",org.slf4j.MDC.get("X-ECOMP-RequestID"));
546
547             ClientResponse response;
548
549             try {
550                 response = webResourceBuilder.method(p.httpMethod.toString(), ClientResponse.class, request);
551             } catch (UniformInterfaceException | ClientHandlerException e) {
552                 throw new SvcLogicException("Exception while sending http request to client "
553                     + e.getLocalizedMessage(), e);
554             }
555
556             r.code = response.getStatus();
557             r.headers = response.getHeaders();
558             EntityTag etag = response.getEntityTag();
559             if (etag != null)
560                 r.message = etag.getValue();
561             if (response.hasEntity() && r.code != 204)
562                 r.body = response.getEntity(String.class);
563         }
564
565         long t2 = System.currentTimeMillis();
566         log.info("Response received. Time: {}", (t2 - t1));
567         log.info("HTTP response code: {}", r.code);
568         log.info("HTTP response message: {}", r.message);
569         logHeaders(r.headers);
570         log.info("HTTP response: {}", r.body);
571
572         return r;
573     }
574
575     protected SSLContext createSSLContext(Parameters p) {
576         try (FileInputStream in = new FileInputStream(p.keyStoreFileName)) {
577             System.setProperty("jsse.enableSNIExtension", "false");
578             System.setProperty("javax.net.ssl.trustStore", p.trustStoreFileName);
579             System.setProperty("javax.net.ssl.trustStorePassword", p.trustStorePassword);
580
581             HttpsURLConnection.setDefaultHostnameVerifier((string, ssls) -> true);
582
583             KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
584             KeyStore ks = KeyStore.getInstance("PKCS12");
585             char[] pwd = p.keyStorePassword.toCharArray();
586             ks.load(in, pwd);
587             kmf.init(ks, pwd);
588
589             SSLContext ctx = SSLContext.getInstance("TLS");
590             ctx.init(kmf.getKeyManagers(), null, null);
591             return ctx;
592         } catch (Exception e) {
593             log.error("Error creating SSLContext: {}", e.getMessage(), e);
594         }
595         return null;
596     }
597
598     protected void setFailureResponseStatus(SvcLogicContext ctx, String prefix, String errorMessage,
599         HttpResponse resp) {
600         resp.code = 500;
601         resp.message = errorMessage;
602         String pp = prefix != null ? prefix + '.' : "";
603         ctx.setAttribute(pp + "response-code", String.valueOf(resp.code));
604         ctx.setAttribute(pp + "response-message", resp.message);
605     }
606
607     protected void setResponseStatus(SvcLogicContext ctx, String prefix, HttpResponse r) {
608         String pp = prefix != null ? prefix + '.' : "";
609         ctx.setAttribute(pp + "response-code", String.valueOf(r.code));
610         ctx.setAttribute(pp + "response-message", r.message);
611     }
612
613     public void sendFile(Map<String, String> paramMap, SvcLogicContext ctx) throws SvcLogicException {
614         HttpResponse r = null;
615         try {
616             FileParam p = getFileParameters(paramMap);
617             byte[] data = Files.readAllBytes(Paths.get(p.fileName));
618
619             r = sendHttpData(data, p);
620             setResponseStatus(ctx, p.responsePrefix, r);
621
622         } catch (SvcLogicException | IOException e) {
623             log.error("Error sending the request: {}", e.getMessage(), e);
624
625             r = new HttpResponse();
626             r.code = 500;
627             r.message = e.getMessage();
628             String prefix = parseParam(paramMap, "responsePrefix", false, null);
629             setResponseStatus(ctx, prefix, r);
630         }
631
632         if (r != null && r.code >= 300)
633             throw new SvcLogicException(String.valueOf(r.code) + ": " + r.message);
634     }
635
636     private static class FileParam {
637
638         public String fileName;
639         public String url;
640         public String user;
641         public String password;
642         public HttpMethod httpMethod;
643         public String responsePrefix;
644         public boolean skipSending;
645         public String oAuthConsumerKey;
646         public String oAuthConsumerSecret;
647         public String oAuthSignatureMethod;
648         public String oAuthVersion;
649         public AuthType authtype;
650     }
651
652     private FileParam getFileParameters(Map<String, String> paramMap) throws SvcLogicException {
653         FileParam p = new FileParam();
654         p.fileName = parseParam(paramMap, "fileName", true, null);
655         p.url = parseParam(paramMap, "url", true, null);
656         p.user = parseParam(paramMap, "user", false, null);
657         p.password = parseParam(paramMap, "password", false, null);
658         p.httpMethod = HttpMethod.fromString(parseParam(paramMap, "httpMethod", false, "post"));
659         p.responsePrefix = parseParam(paramMap, "responsePrefix", false, null);
660         String skipSendingStr = paramMap.get("skipSending");
661         p.skipSending = "true".equalsIgnoreCase(skipSendingStr);
662         p.oAuthConsumerKey = parseParam(paramMap, "oAuthConsumerKey", false, null);
663         p.oAuthVersion = parseParam(paramMap, "oAuthVersion", false, null);
664         p.oAuthConsumerSecret = parseParam(paramMap, "oAuthConsumerSecret", false, null);
665         p.oAuthSignatureMethod = parseParam(paramMap, "oAuthSignatureMethod", false, null);
666         p.authtype = AuthType.fromString(parseParam(paramMap, "authType", false, "unspecified"));
667         return p;
668     }
669
670     protected HttpResponse sendHttpData(byte[] data, FileParam p) throws SvcLogicException {
671         Client client = Client.create();
672         client.setConnectTimeout(5000);
673         client.setFollowRedirects(true);
674         WebResource webResource = addAuthType(client,p).resource(p.url);
675
676         log.info("Sending file");
677         long t1 = System.currentTimeMillis();
678
679         HttpResponse r = new HttpResponse();
680         r.code = 200;
681
682         if (!p.skipSending) {
683             String tt = "application/octet-stream";
684
685             ClientResponse response;
686             try {
687                 if (p.httpMethod == HttpMethod.POST)
688                     response = webResource.accept(tt).type(tt).post(ClientResponse.class, data);
689                 else if (p.httpMethod == HttpMethod.PUT)
690                     response = webResource.accept(tt).type(tt).put(ClientResponse.class, data);
691                 else
692                     throw new SvcLogicException("Http operation" + p.httpMethod + "not supported");
693             } catch (UniformInterfaceException | ClientHandlerException e) {
694                 throw new SvcLogicException("Exception while sending http request to client " +
695                     e.getLocalizedMessage(), e);
696             }
697
698             r.code = response.getStatus();
699             r.headers = response.getHeaders();
700             EntityTag etag = response.getEntityTag();
701             if (etag != null)
702                 r.message = etag.getValue();
703             if (response.hasEntity() && r.code != 204)
704                 r.body = response.getEntity(String.class);
705
706             if (r.code == 301) {
707                 String newUrl = response.getHeaders().getFirst("Location");
708
709                 log.info("Got response code 301. Sending same request to URL: {}", newUrl);
710
711                 webResource = client.resource(newUrl);
712
713                 try {
714                     if (p.httpMethod == HttpMethod.POST)
715                         response = webResource.accept(tt).type(tt).post(ClientResponse.class, data);
716                     else if (p.httpMethod == HttpMethod.PUT)
717                         response = webResource.accept(tt).type(tt).put(ClientResponse.class, data);
718                     else
719                         throw new SvcLogicException("Http operation" + p.httpMethod + "not supported");
720                 } catch (UniformInterfaceException | ClientHandlerException e) {
721                     throw new SvcLogicException("Exception while sending http request to client " +
722                         e.getLocalizedMessage(), e);
723                 }
724
725                 r.code = response.getStatus();
726                 etag = response.getEntityTag();
727                 if (etag != null)
728                     r.message = etag.getValue();
729                 if (response.hasEntity() && r.code != 204)
730                     r.body = response.getEntity(String.class);
731             }
732         }
733
734         long t2 = System.currentTimeMillis();
735         log.info("Response received. Time: {}", (t2 - t1));
736         log.info("HTTP response code: {}", r.code);
737         log.info("HTTP response message: {}", r.message);
738         logHeaders(r.headers);
739         log.info("HTTP response: {}", r.body);
740
741         return r;
742     }
743
744     public void postMessageOnUeb(Map<String, String> paramMap, SvcLogicContext ctx) throws SvcLogicException {
745         HttpResponse r;
746         try {
747             UebParam p = getUebParameters(paramMap);
748
749             String pp = p.responsePrefix != null ? p.responsePrefix + '.' : "";
750
751             String req;
752
753             if (p.templateFileName == null) {
754                 log.info("No template file name specified. Using default UEB template: {}", defaultUebTemplateFileName);
755                 p.templateFileName = defaultUebTemplateFileName;
756             }
757
758             String reqTemplate = readFile(p.templateFileName);
759             reqTemplate = reqTemplate.replaceAll("rootVarName", p.rootVarName);
760             req = buildXmlJsonRequest(ctx, reqTemplate, Format.JSON);
761
762             r = postOnUeb(req, p);
763             setResponseStatus(ctx, p.responsePrefix, r);
764             if (r.body != null)
765                 ctx.setAttribute(pp + "httpResponse", r.body);
766
767         } catch (SvcLogicException e) {
768             log.error("Error sending the request: {}", e.getMessage(), e);
769
770             r = new HttpResponse();
771             r.code = 500;
772             r.message = e.getMessage();
773             String prefix = parseParam(paramMap, "responsePrefix", false, null);
774             setResponseStatus(ctx, prefix, r);
775         }
776
777         if (r.code >= 300)
778             throw new SvcLogicException(String.valueOf(r.code) + ": " + r.message);
779     }
780
781     private static class UebParam {
782
783         public String topic;
784         public String templateFileName;
785         public String rootVarName;
786         public String responsePrefix;
787         public boolean skipSending;
788     }
789
790     private UebParam getUebParameters(Map<String, String> paramMap) throws SvcLogicException {
791         UebParam p = new UebParam();
792         p.topic = parseParam(paramMap, "topic", true, null);
793         p.templateFileName = parseParam(paramMap, "templateFileName", false, null);
794         p.rootVarName = parseParam(paramMap, "rootVarName", false, null);
795         p.responsePrefix = parseParam(paramMap, "responsePrefix", false, null);
796         String skipSendingStr = paramMap.get("skipSending");
797         p.skipSending = "true".equalsIgnoreCase(skipSendingStr);
798         return p;
799     }
800
801     protected HttpResponse postOnUeb(String request, UebParam p) throws SvcLogicException {
802         String[] urls = uebServers.split(" ");
803         for (int i = 0; i < urls.length; i++) {
804             if (!urls[i].endsWith("/"))
805                 urls[i] += "/";
806             urls[i] += "events/" + p.topic;
807         }
808
809         Client client = Client.create();
810         client.setConnectTimeout(5000);
811         WebResource webResource = client.resource(urls[0]);
812
813         log.info("UEB URL: {}", urls[0]);
814         log.info("Sending request:");
815         log.info(request);
816         long t1 = System.currentTimeMillis();
817
818         HttpResponse r = new HttpResponse();
819         r.code = 200;
820
821         if (!p.skipSending) {
822             String tt = "application/json";
823             String tt1 = tt + ";charset=UTF-8";
824
825             ClientResponse response;
826
827             try {
828                 response = webResource.accept(tt).type(tt1).post(ClientResponse.class, request);
829             } catch (UniformInterfaceException | ClientHandlerException e) {
830                 throw new SvcLogicException("Exception while posting http request to client " +
831                     e.getLocalizedMessage(), e);
832             }
833
834             r.code = response.getStatus();
835             r.headers = response.getHeaders();
836             if (response.hasEntity())
837                 r.body = response.getEntity(String.class);
838         }
839
840         long t2 = System.currentTimeMillis();
841         log.info("Response received. Time: {}", (t2 - t1));
842         log.info("HTTP response code: {}", r.code);
843         logHeaders(r.headers);
844         log.info("HTTP response:\n {}", r.body);
845
846         return r;
847     }
848
849     protected void logProperties(Map<String, Object> mm) {
850         List<String> ll = new ArrayList<>();
851         for (Object o : mm.keySet())
852             ll.add((String) o);
853         Collections.sort(ll);
854
855         log.info("Properties:");
856         for (String name : ll)
857             log.info("--- {}:{}", name, String.valueOf(mm.get(name)));
858     }
859
860     protected void logHeaders(MultivaluedMap<String, String> mm) {
861         log.info("HTTP response headers:");
862
863         if (mm == null)
864             return;
865
866         List<String> ll = new ArrayList<>();
867         for (Object o : mm.keySet())
868             ll.add((String) o);
869         Collections.sort(ll);
870
871         for (String name : ll)
872             log.info("--- {}:{}", name, String.valueOf(mm.get(name)));
873     }
874
875     public void setUebServers(String uebServers) {
876         this.uebServers = uebServers;
877     }
878
879     public void setDefaultUebTemplateFileName(String defaultUebTemplateFileName) {
880         this.defaultUebTemplateFileName = defaultUebTemplateFileName;
881     }
882 }