configurable param resolution
[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  * Modifications Copyright © 2018 IBM.
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  * ============LICENSE_END=========================================================
21  */
22
23 package org.onap.ccsdk.sli.plugins.restapicall;
24
25 import static java.lang.Boolean.valueOf;
26 import static javax.ws.rs.client.Entity.entity;
27 import static org.onap.ccsdk.sli.plugins.restapicall.AuthType.fromString;
28 import java.io.File;
29 import java.io.FileInputStream;
30 import java.io.IOException;
31 import java.net.SocketException;
32 import java.net.URI;
33 import java.nio.file.Files;
34 import java.nio.file.Paths;
35 import java.security.KeyStore;
36 import java.util.ArrayList;
37 import java.util.Collections;
38 import java.util.HashMap;
39 import java.util.HashSet;
40 import java.util.Iterator;
41 import java.util.List;
42 import java.util.Map;
43 import java.util.Map.Entry;
44 import java.util.Properties;
45 import java.util.Set;
46 import javax.net.ssl.HttpsURLConnection;
47 import javax.net.ssl.KeyManagerFactory;
48 import javax.net.ssl.SSLContext;
49 import javax.ws.rs.ProcessingException;
50 import javax.ws.rs.client.Client;
51 import javax.ws.rs.client.ClientBuilder;
52 import javax.ws.rs.client.Entity;
53 import javax.ws.rs.client.Invocation;
54 import javax.ws.rs.client.WebTarget;
55 import javax.ws.rs.core.EntityTag;
56 import javax.ws.rs.core.Feature;
57 import javax.ws.rs.core.MediaType;
58 import javax.ws.rs.core.MultivaluedMap;
59 import javax.ws.rs.core.Response;
60 import org.apache.commons.lang3.StringUtils;
61 import org.codehaus.jettison.json.JSONException;
62 import org.codehaus.jettison.json.JSONObject;
63 import org.glassfish.jersey.client.ClientProperties;
64 import org.glassfish.jersey.client.HttpUrlConnectorProvider;
65 import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
66 import org.glassfish.jersey.client.oauth1.ConsumerCredentials;
67 import org.glassfish.jersey.client.oauth1.OAuth1ClientSupport;
68 import org.glassfish.jersey.media.multipart.MultiPart;
69 import org.glassfish.jersey.media.multipart.MultiPartFeature;
70 import org.glassfish.jersey.media.multipart.file.FileDataBodyPart;
71 import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
72 import org.onap.ccsdk.sli.core.sli.SvcLogicException;
73 import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin;
74 import org.slf4j.Logger;
75 import org.slf4j.LoggerFactory;
76
77 public class RestapiCallNode implements SvcLogicJavaPlugin {
78
79     protected static final String PARTNERS_FILE_NAME = "partners.json";
80     protected static final String UEB_PROPERTIES_FILE_NAME = "ueb.properties";
81     protected static final String DEFAULT_PROPERTIES_DIR = "/opt/onap/ccsdk/data/properties";
82     protected static final String PROPERTIES_DIR_KEY = "SDNC_CONFIG_DIR";
83     protected static final int DEFAULT_HTTP_CONNECT_TIMEOUT_MS = 30000; // 30 seconds
84     protected static final int DEFAULT_HTTP_READ_TIMEOUT_MS = 600000; // 10 minutes
85
86     private static final Logger log = LoggerFactory.getLogger(RestapiCallNode.class);
87     private String uebServers;
88     private String defaultUebTemplateFileName = "/opt/bvc/restapi/templates/default-ueb-message.json";
89
90     private String responseReceivedMessage = "Response received. Time: {}";
91     private String responseHttpCodeMessage = "HTTP response code: {}";
92     private String requestPostingException = "Exception while posting http request to client ";
93     protected static final String skipSendingMessage = "skipSending";
94     protected static final String responsePrefix = "responsePrefix";
95     protected static final String restapiUrlString = "restapiUrl";
96     protected static final String restapiUserKey = "restapiUser";
97     protected static final String restapiPasswordKey = "restapiPassword";
98     protected Integer httpConnectTimeout;
99     protected Integer httpReadTimeout;
100     
101     protected HashMap<String, PartnerDetails> partnerStore;
102
103     public RestapiCallNode() {
104         String configDir = System.getProperty(PROPERTIES_DIR_KEY, DEFAULT_PROPERTIES_DIR);
105         try {
106             String jsonString = readFile(configDir + "/" + PARTNERS_FILE_NAME);
107             JSONObject partners = new JSONObject(jsonString);
108             partnerStore = new HashMap<>();
109             loadPartners(partners);
110             log.info("Partners support enabled");
111         } catch (Exception e) {
112             log.warn("Partners file could not be read, Partner support will not be enabled.", e);
113         }
114
115         try (FileInputStream in = new FileInputStream(configDir + "/" + UEB_PROPERTIES_FILE_NAME)) {
116             Properties props = new Properties();
117             props.load(in);
118             uebServers = props.getProperty("servers");
119             log.info("UEB support enabled");
120         } catch (Exception e) {
121             log.warn("UEB properties could not be read, UEB support will not be enabled.", e);
122         }
123         httpConnectTimeout = readOptionalInteger("HTTP_CONNECT_TIMEOUT_MS",DEFAULT_HTTP_CONNECT_TIMEOUT_MS);
124         httpReadTimeout = readOptionalInteger("HTTP_READ_TIMEOUT_MS",DEFAULT_HTTP_READ_TIMEOUT_MS);       
125     }
126
127     protected void loadPartners(JSONObject partners) {
128         Iterator<String> keys = partners.keys();
129         String partnerUserKey = "user";
130         String partnerPasswordKey = "password";
131         String partnerUrlKey = "url";
132
133         while (keys.hasNext()) {
134             String partnerKey = keys.next();
135             try {
136                 JSONObject partnerObject = (JSONObject) partners.get(partnerKey);
137                 if (partnerObject.has(partnerUserKey) && partnerObject.has(partnerPasswordKey)) {
138                     String url = null;
139                     if (partnerObject.has(partnerUrlKey)) {
140                         url = partnerObject.getString(partnerUrlKey);
141                     }
142                     String userName = partnerObject.getString(partnerUserKey);
143                     String password = partnerObject.getString(partnerPasswordKey);
144                     PartnerDetails details = new PartnerDetails(userName, getObfuscatedVal(password), url);
145                     partnerStore.put(partnerKey, details);
146                     log.info("mapped partner using partner key " + partnerKey);
147                 } else {
148                     log.info("Partner " + partnerKey + " is missing required keys, it won't be mapped");
149                 }
150             } catch (JSONException e) {
151                 log.info("Couldn't map the partner using partner key " + partnerKey, e);
152             }
153         }
154     }
155
156     /* Unobfuscate param value */ 
157     private static String getObfuscatedVal(String paramValue) {
158         String resValue = paramValue;
159         if (paramValue != null && paramValue.startsWith("${") && paramValue.endsWith("}"))
160         {
161                 String paramStr = paramValue.substring(2, paramValue.length()-1);
162                 if (paramStr  != null && paramStr.length() > 0)
163                 {
164                         String val = System.getenv(paramStr);
165                         if (val != null && val.length() > 0)
166                         {
167                              resValue=val;
168                              log.info("Obfuscated value RESET for param value:" + paramValue);
169                         }
170                  }
171         }
172         return resValue;
173     }
174
175     /**
176      * Returns parameters from the parameter map.
177      *
178      * @param paramMap parameter map
179      * @param p parameters instance
180      * @return parameters filed instance
181      * @throws SvcLogicException when svc logic exception occurs
182      */
183     public static Parameters getParameters(Map<String, String> paramMap, Parameters p) throws SvcLogicException {
184
185         p.templateFileName = parseParam(paramMap, "templateFileName", false, null);
186         p.requestBody = parseParam(paramMap, "requestBody", false, null);
187         p.restapiUrl = parseParam(paramMap, restapiUrlString, true, null);
188         validateUrl(p.restapiUrl);
189         p.restapiUrlSuffix = parseParam(paramMap, "restapiUrlSuffix", false, null);
190         p.restapiUser = parseParam(paramMap, restapiUserKey, false, null);
191         p.restapiPassword = parseParam(paramMap, restapiPasswordKey, false, null);
192         if (p.restapiUrlSuffix != null) {
193             p.restapiUrl = p.restapiUrl + p.restapiUrlSuffix;
194             validateUrl(p.restapiUrl);
195         }
196         p.oAuthConsumerKey = parseParam(paramMap, "oAuthConsumerKey", false, null);
197         p.oAuthConsumerSecret = parseParam(paramMap, "oAuthConsumerSecret", false, null);
198         p.oAuthSignatureMethod = parseParam(paramMap, "oAuthSignatureMethod", false, null);
199         p.oAuthVersion = parseParam(paramMap, "oAuthVersion", false, null);
200         p.contentType = parseParam(paramMap, "contentType", false, null);
201         p.format = Format.fromString(parseParam(paramMap, "format", false, "json"));
202         p.authtype = fromString(parseParam(paramMap, "authType", false, "unspecified"));
203         p.httpMethod = HttpMethod.fromString(parseParam(paramMap, "httpMethod", false, "post"));
204         p.responsePrefix = parseParam(paramMap, responsePrefix, false, null);
205         p.listNameList = getListNameList(paramMap);
206         String skipSendingStr = paramMap.get(skipSendingMessage);
207         p.skipSending = "true".equalsIgnoreCase(skipSendingStr);
208         p.convertResponse = valueOf(parseParam(paramMap, "convertResponse", false, "true"));
209         p.trustStoreFileName = parseParam(paramMap, "trustStoreFileName", false, null);
210         p.trustStorePassword = parseParam(paramMap, "trustStorePassword", false, null);
211         p.keyStoreFileName = parseParam(paramMap, "keyStoreFileName", false, null);
212         p.keyStorePassword = parseParam(paramMap, "keyStorePassword", false, null);
213         p.ssl = p.trustStoreFileName != null && p.trustStorePassword != null && p.keyStoreFileName != null
214                 && p.keyStorePassword != null;
215         p.customHttpHeaders = parseParam(paramMap, "customHttpHeaders", false, null);
216         p.partner = parseParam(paramMap, "partner", false, null);
217         p.dumpHeaders = valueOf(parseParam(paramMap, "dumpHeaders", false, null));
218         p.returnRequestPayload = valueOf(parseParam(paramMap, "returnRequestPayload", false, null));
219         p.accept = parseParam(paramMap, "accept", false, null);
220         p.multipartFormData = valueOf(parseParam(paramMap, "multipartFormData", false, "false"));
221         p.multipartFile = parseParam(paramMap, "multipartFile", false, null);
222         return p;
223     }
224
225     /**
226      * Validates the given URL in the parameters.
227      *
228      * @param restapiUrl rest api URL
229      * @throws SvcLogicException when URL validation fails
230      */
231     private static void validateUrl(String restapiUrl) throws SvcLogicException {
232         if (restapiUrl.contains(",")) {
233             String[] urls = restapiUrl.split(",");
234             for (String url : urls) {
235                 validateUrl(url);
236             }
237         } else {
238             try {
239                 URI.create(restapiUrl);
240             } catch (IllegalArgumentException e) {
241                 throw new SvcLogicException("Invalid input of url " + e.getLocalizedMessage(), e);
242             }
243         }
244     }
245
246     /**
247      * Returns the list of list name.
248      *
249      * @param paramMap parameters map
250      * @return list of list name
251      */
252     private static Set<String> getListNameList(Map<String, String> paramMap) {
253         Set<String> ll = new HashSet<>();
254         for (Map.Entry<String, String> entry : paramMap.entrySet()) {
255             if (entry.getKey().startsWith("listName")) {
256                 ll.add(entry.getValue());
257             }
258         }
259         return ll;
260     }
261
262     /**
263      * Parses the parameter string map of property, validates if required, assigns default value if
264      * present and returns the value.
265      *
266      * @param paramMap string param map
267      * @param name name of the property
268      * @param required if value required
269      * @param def default value
270      * @return value of the property
271      * @throws SvcLogicException if required parameter value is empty
272      */
273     public static String parseParam(Map<String, String> paramMap, String name, boolean required, String def)
274             throws SvcLogicException {
275         String s = paramMap.get(name);
276
277         if (s == null || s.trim().length() == 0) {
278             if (!required) {
279                 return def;
280             }
281             throw new SvcLogicException("Parameter " + name + " is required in RestapiCallNode");
282         }
283
284         s = s.trim();
285         StringBuilder value = new StringBuilder();
286         int i = 0;
287         int i1 = s.indexOf('%');
288         while (i1 >= 0) {
289             int i2 = s.indexOf('%', i1 + 1);
290             if (i2 < 0) {
291                 break;
292             }
293
294             String varName = s.substring(i1 + 1, i2);
295             String varValue = System.getenv(varName);
296             if (varValue == null) {
297                 varValue = "%" + varName + "%";
298             }
299
300             value.append(s.substring(i, i1));
301             value.append(varValue);
302
303             i = i2 + 1;
304             i1 = s.indexOf('%', i);
305         }
306         value.append(s.substring(i));
307
308         log.info("Parameter {}: [{}]", name, maskPassword(name, value));
309
310         return value.toString();
311     }
312
313     private static Object maskPassword(String name, Object value) {
314         String[] pwdNames = {"pwd", "passwd", "password", "Pwd", "Passwd", "Password"};
315         for (String pwdName : pwdNames) {
316             if (name.contains(pwdName)) {
317                 return "**********";
318             }
319         }
320         return value;
321     }
322
323     /**
324      * Allows Directed Graphs the ability to interact with REST APIs.
325      *
326      * @param paramMap HashMap<String,String> of parameters passed by the DG to this function
327      *        <table border="1">
328      *        <thead>
329      *        <th>parameter</th>
330      *        <th>Mandatory/Optional</th>
331      *        <th>description</th>
332      *        <th>example values</th></thead> <tbody>
333      *        <tr>
334      *        <td>templateFileName</td>
335      *        <td>Optional</td>
336      *        <td>full path to template file that can be used to build a request</td>
337      *        <td>/sdncopt/bvc/restapi/templates/vnf_service-configuration-operation_minimal.json</td>
338      *        </tr>
339      *        <tr>
340      *        <td>restapiUrl</td>
341      *        <td>Mandatory</td>
342      *        <td>url to send the request to</td>
343      *        <td>https://sdncodl:8543/restconf/operations/L3VNF-API:create-update-vnf-request</td>
344      *        </tr>
345      *        <tr>
346      *        <td>restapiUser</td>
347      *        <td>Optional</td>
348      *        <td>user name to use for http basic authentication</td>
349      *        <td>sdnc_ws</td>
350      *        </tr>
351      *        <tr>
352      *        <td>restapiPassword</td>
353      *        <td>Optional</td>
354      *        <td>unencrypted password to use for http basic authentication</td>
355      *        <td>plain_password</td>
356      *        </tr>
357      *        <tr>
358      *        <td>oAuthConsumerKey</td>
359      *        <td>Optional</td>
360      *        <td>Consumer key to use for http oAuth authentication</td>
361      *        <td>plain_key</td>
362      *        </tr>
363      *        <tr>
364      *        <td>oAuthConsumerSecret</td>
365      *        <td>Optional</td>
366      *        <td>Consumer secret to use for http oAuth authentication</td>
367      *        <td>plain_secret</td>
368      *        </tr>
369      *        <tr>
370      *        <td>oAuthSignatureMethod</td>
371      *        <td>Optional</td>
372      *        <td>Consumer method to use for http oAuth authentication</td>
373      *        <td>method</td>
374      *        </tr>
375      *        <tr>
376      *        <td>oAuthVersion</td>
377      *        <td>Optional</td>
378      *        <td>Version http oAuth authentication</td>
379      *        <td>version</td>
380      *        </tr>
381      *        <tr>
382      *        <td>contentType</td>
383      *        <td>Optional</td>
384      *        <td>http content type to set in the http header</td>
385      *        <td>usually application/json or application/xml</td>
386      *        </tr>
387      *        <tr>
388      *        <td>format</td>
389      *        <td>Optional</td>
390      *        <td>should match request body format</td>
391      *        <td>json or xml</td>
392      *        </tr>
393      *        <tr>
394      *        <td>httpMethod</td>
395      *        <td>Optional</td>
396      *        <td>http method to use when sending the request</td>
397      *        <td>get post put delete patch</td>
398      *        </tr>
399      *        <tr>
400      *        <td>responsePrefix</td>
401      *        <td>Optional</td>
402      *        <td>location the response will be written to in context memory</td>
403      *        <td>tmp.restapi.result</td>
404      *        </tr>
405      *        <tr>
406      *        <td>listName[i]</td>
407      *        <td>Optional</td>
408      *        <td>Used for processing XML responses with repeating
409      *        elements.</td>vpn-information.vrf-details
410      *        <td></td>
411      *        </tr>
412      *        <tr>
413      *        <td>skipSending</td>
414      *        <td>Optional</td>
415      *        <td></td>
416      *        <td>true or false</td>
417      *        </tr>
418      *        <tr>
419      *        <td>convertResponse</td>
420      *        <td>Optional</td>
421      *        <td>whether the response should be converted</td>
422      *        <td>true or false</td>
423      *        </tr>
424      *        <tr>
425      *        <td>customHttpHeaders</td>
426      *        <td>Optional</td>
427      *        <td>a list additional http headers to be passed in, follow the format in the example</td>
428      *        <td>X-CSI-MessageId=messageId,headerFieldName=headerFieldValue</td>
429      *        </tr>
430      *        <tr>
431      *        <td>dumpHeaders</td>
432      *        <td>Optional</td>
433      *        <td>when true writes http header content to context memory</td>
434      *        <td>true or false</td>
435      *        </tr>
436      *        <tr>
437      *        <td>partner</td>
438      *        <td>Optional</td>
439      *        <td>used to retrieve username, password and url if partner store exists</td>
440      *        <td>aaf</td>
441      *        </tr>
442      *        <tr>
443      *        <td>returnRequestPayload</td>
444      *        <td>Optional</td>
445      *        <td>used to return payload built in the request</td>
446      *        <td>true or false</td>
447      *        </tr>
448      *        </tbody>
449      *        </table>
450      * @param ctx Reference to context memory
451      * @throws SvcLogicException
452      * @since 11.0.2
453      * @see String#split(String, int)
454      */
455     public void sendRequest(Map<String, String> paramMap, SvcLogicContext ctx) throws SvcLogicException {
456         sendRequest(paramMap, ctx, null);
457     }
458
459     protected void sendRequest(Map<String, String> paramMap, SvcLogicContext ctx, RetryPolicy retryPolicy)
460             throws SvcLogicException {
461
462         HttpResponse r = new HttpResponse();
463         try {
464             handlePartner(paramMap);
465             Parameters p = getParameters(paramMap, new Parameters());
466             if (p.restapiUrl.contains(",") && retryPolicy == null) {
467                 String[] urls = p.restapiUrl.split(",");
468                 retryPolicy = new RetryPolicy(urls, urls.length * 2);
469                 p.restapiUrl = urls[0];
470             }
471             String pp = p.responsePrefix != null ? p.responsePrefix + '.' : "";
472
473             String req = null;
474             if (p.templateFileName != null) {
475                 String reqTemplate = readFile(p.templateFileName);
476                 req = buildXmlJsonRequest(ctx, reqTemplate, p.format);
477             } else if (p.requestBody != null) {
478                 req = p.requestBody;
479             }
480             r = sendHttpRequest(req, p);
481             setResponseStatus(ctx, p.responsePrefix, r);
482
483             if (p.dumpHeaders && r.headers != null) {
484                 for (Entry<String, List<String>> a : r.headers.entrySet()) {
485                     ctx.setAttribute(pp + "header." + a.getKey(), StringUtils.join(a.getValue(), ","));
486                 }
487             }
488
489             if (p.returnRequestPayload && req != null) {
490                 ctx.setAttribute(pp + "httpRequest", req);
491             }
492
493             if (r.body != null && r.body.trim().length() > 0) {
494                 ctx.setAttribute(pp + "httpResponse", r.body);
495
496                 if (p.convertResponse) {
497                     Map<String, String> mm = null;
498                     if (p.format == Format.XML) {
499                         mm = XmlParser.convertToProperties(r.body, p.listNameList);
500                     } else if (p.format == Format.JSON) {
501                         mm = JsonParser.convertToProperties(r.body);
502                     }
503
504                     if (mm != null) {
505                         for (Map.Entry<String, String> entry : mm.entrySet()) {
506                             ctx.setAttribute(pp + entry.getKey(), entry.getValue());
507                         }
508                     }
509                 }
510             }
511         } catch (SvcLogicException e) {
512             boolean shouldRetry = false;
513             if (e.getCause().getCause() instanceof SocketException) {
514                 shouldRetry = true;
515             }
516
517             log.error("Error sending the request: " + e.getMessage(), e);
518             String prefix = parseParam(paramMap, responsePrefix, false, null);
519             if (retryPolicy == null || !shouldRetry) {
520                 setFailureResponseStatus(ctx, prefix, e.getMessage(), r);
521             } else {
522                 log.debug(retryPolicy.getRetryMessage());
523                 try {
524                     // calling getNextHostName increments the retry count so it should be called before shouldRetry
525                     String retryString = retryPolicy.getNextHostName();
526                     if (retryPolicy.shouldRetry()) {
527                         paramMap.put(restapiUrlString, retryString);
528                         log.debug("retry attempt {} will use the retry url {}", retryPolicy.getRetryCount(),
529                                 retryString);
530                         sendRequest(paramMap, ctx, retryPolicy);
531                     } else {
532                         log.debug("Maximum retries reached, won't attempt to retry. Calling setFailureResponseStatus.");
533                         setFailureResponseStatus(ctx, prefix, e.getMessage(), r);
534                     }
535                 } catch (Exception ex) {
536                     String retryErrorMessage = "Retry attempt " + retryPolicy.getRetryCount()
537                             + "has failed with error message " + ex.getMessage();
538                     setFailureResponseStatus(ctx, prefix, retryErrorMessage, r);
539                 }
540             }
541         }
542
543         if (r != null && r.code >= 300) {
544             throw new SvcLogicException(String.valueOf(r.code) + ": " + r.message);
545         }
546     }
547
548     protected void handlePartner(Map<String, String> paramMap) {
549         String partner = paramMap.get("partner");
550         if (partner != null && partner.length() > 0) {
551             PartnerDetails details = partnerStore.get(partner);
552             paramMap.put(restapiUserKey, details.username);
553             paramMap.put(restapiPasswordKey, details.password);
554             if (paramMap.get(restapiUrlString) == null) {
555                 paramMap.put(restapiUrlString, details.url);
556             }
557         }
558     }
559
560     protected String buildXmlJsonRequest(SvcLogicContext ctx, String template, Format format) throws SvcLogicException {
561         log.info("Building {} started", format);
562         long t1 = System.currentTimeMillis();
563         String originalTemplate = template;
564
565         template = expandRepeats(ctx, template, 1);
566
567         Map<String, String> mm = new HashMap<>();
568         for (String s : ctx.getAttributeKeySet()) {
569             mm.put(s, ctx.getAttribute(s));
570         }
571
572         StringBuilder ss = new StringBuilder();
573         int i = 0;
574         while (i < template.length()) {
575             int i1 = template.indexOf("${", i);
576             if (i1 < 0) {
577                 ss.append(template.substring(i));
578                 break;
579             }
580
581             int i2 = template.indexOf('}', i1 + 2);
582             if (i2 < 0) {
583                 throw new SvcLogicException("Template error: Matching } not found");
584             }
585
586             String var1 = template.substring(i1 + 2, i2);
587             String value1 = format == Format.XML ? XmlJsonUtil.getXml(mm, var1) : XmlJsonUtil.getJson(mm, var1);
588             if (value1 == null || value1.trim().length() == 0) {
589                 // delete the whole element (line)
590                 int i3 = template.lastIndexOf('\n', i1);
591                 if (i3 < 0) {
592                     i3 = 0;
593                 }
594                 int i4 = template.indexOf('\n', i1);
595                 if (i4 < 0) {
596                     i4 = template.length();
597                 }
598
599                 if (i < i3) {
600                     ss.append(template.substring(i, i3));
601                 }
602                 i = i4;
603             } else {
604                 ss.append(template.substring(i, i1)).append(value1);
605                 i = i2 + 1;
606             }
607         }
608
609         String req = format == Format.XML ? XmlJsonUtil.removeEmptyStructXml(ss.toString())
610                 : XmlJsonUtil.removeEmptyStructJson(originalTemplate, ss.toString());
611
612         if (format == Format.JSON) {
613             req = XmlJsonUtil.removeLastCommaJson(req);
614         }
615
616         long t2 = System.currentTimeMillis();
617         log.info("Building {} completed. Time: {}", format, t2 - t1);
618
619         return req;
620     }
621
622     protected String expandRepeats(SvcLogicContext ctx, String template, int level) throws SvcLogicException {
623         StringBuilder newTemplate = new StringBuilder();
624         int k = 0;
625         while (k < template.length()) {
626             int i1 = template.indexOf("${repeat:", k);
627             if (i1 < 0) {
628                 newTemplate.append(template.substring(k));
629                 break;
630             }
631
632             int i2 = template.indexOf(':', i1 + 9);
633             if (i2 < 0) {
634                 throw new SvcLogicException(
635                         "Template error: Context variable name followed by : is required after repeat");
636             }
637
638             // Find the closing }, store in i3
639             int nn = 1;
640             int i3 = -1;
641             int i = i2;
642             while (nn > 0 && i < template.length()) {
643                 i3 = template.indexOf('}', i);
644                 if (i3 < 0) {
645                     throw new SvcLogicException("Template error: Matching } not found");
646                 }
647                 int i32 = template.indexOf('{', i);
648                 if (i32 >= 0 && i32 < i3) {
649                     nn++;
650                     i = i32 + 1;
651                 } else {
652                     nn--;
653                     i = i3 + 1;
654                 }
655             }
656
657             String var1 = template.substring(i1 + 9, i2);
658             String value1 = ctx.getAttribute(var1);
659             log.info("     {}:{}", var1, value1);
660             int n = 0;
661             try {
662                 n = Integer.parseInt(value1);
663             } catch (NumberFormatException e) {
664                 log.info("value1 not set or not a number, n will remain set at zero");
665             }
666
667             newTemplate.append(template.substring(k, i1));
668
669             String rpt = template.substring(i2 + 1, i3);
670
671             for (int ii = 0; ii < n; ii++) {
672                 String ss = rpt.replaceAll("\\[\\$\\{" + level + "\\}\\]", "[" + ii + "]");
673                 if (ii == n - 1 && ss.trim().endsWith(",")) {
674                     int i4 = ss.lastIndexOf(',');
675                     if (i4 > 0) {
676                         ss = ss.substring(0, i4) + ss.substring(i4 + 1);
677                     }
678                 }
679                 newTemplate.append(ss);
680             }
681
682             k = i3 + 1;
683         }
684
685         if (k == 0) {
686             return newTemplate.toString();
687         }
688
689         return expandRepeats(ctx, newTemplate.toString(), level + 1);
690     }
691
692     protected String readFile(String fileName) throws SvcLogicException {
693         try {
694             byte[] encoded = Files.readAllBytes(Paths.get(fileName));
695             return new String(encoded, "UTF-8");
696         } catch (IOException | SecurityException e) {
697             throw new SvcLogicException("Unable to read file " + fileName + e.getLocalizedMessage(), e);
698         }
699     }
700
701     protected Client addAuthType(Client c, FileParam fp) throws SvcLogicException {
702         Parameters p = new Parameters();
703         p.restapiUser = fp.user;
704         p.restapiPassword = fp.password;
705         p.oAuthConsumerKey = fp.oAuthConsumerKey;
706         p.oAuthVersion = fp.oAuthVersion;
707         p.oAuthConsumerSecret = fp.oAuthConsumerSecret;
708         p.oAuthSignatureMethod = fp.oAuthSignatureMethod;
709         p.authtype = fp.authtype;
710         return addAuthType(c, p);
711     }
712
713     public Client addAuthType(Client client, Parameters p) throws SvcLogicException {
714         if (p.authtype == AuthType.Unspecified) {
715             if (p.restapiUser != null && p.restapiPassword != null) {
716                 client.register(HttpAuthenticationFeature.basic(p.restapiUser, p.restapiPassword));
717             } else if (p.oAuthConsumerKey != null && p.oAuthConsumerSecret != null && p.oAuthSignatureMethod != null) {
718                 Feature oAuth1Feature =
719                         OAuth1ClientSupport.builder(new ConsumerCredentials(p.oAuthConsumerKey, p.oAuthConsumerSecret))
720                                 .version(p.oAuthVersion).signatureMethod(p.oAuthSignatureMethod).feature().build();
721                 client.register(oAuth1Feature);
722
723             }
724         } else {
725             if (p.authtype == AuthType.DIGEST) {
726                 if (p.restapiUser != null && p.restapiPassword != null) {
727                     client.register(HttpAuthenticationFeature.digest(p.restapiUser, p.restapiPassword));
728                 } else {
729                     throw new SvcLogicException(
730                             "oAUTH authentication type selected but all restapiUser and restapiPassword "
731                                     + "parameters doesn't exist",
732                             new Throwable());
733                 }
734             } else if (p.authtype == AuthType.BASIC) {
735                 if (p.restapiUser != null && p.restapiPassword != null) {
736                     client.register(HttpAuthenticationFeature.basic(p.restapiUser, p.restapiPassword));
737                 } else {
738                     throw new SvcLogicException(
739                             "oAUTH authentication type selected but all restapiUser and restapiPassword "
740                                     + "parameters doesn't exist",
741                             new Throwable());
742                 }
743             } else if (p.authtype == AuthType.OAUTH) {
744                 if (p.oAuthConsumerKey != null && p.oAuthConsumerSecret != null && p.oAuthSignatureMethod != null) {
745                     Feature oAuth1Feature = OAuth1ClientSupport
746                             .builder(new ConsumerCredentials(p.oAuthConsumerKey, p.oAuthConsumerSecret))
747                             .version(p.oAuthVersion).signatureMethod(p.oAuthSignatureMethod).feature().build();
748                     client.register(oAuth1Feature);
749                 } else {
750                     throw new SvcLogicException(
751                             "oAUTH authentication type selected but all oAuthConsumerKey, oAuthConsumerSecret "
752                                     + "and oAuthSignatureMethod parameters doesn't exist",
753                             new Throwable());
754                 }
755             }
756         }
757         return client;
758     }
759
760     /**
761      * Receives the http response for the http request sent.
762      *
763      * @param request request msg
764      * @param p parameters
765      * @return HTTP response
766      * @throws SvcLogicException when sending http request fails
767      */
768     public HttpResponse sendHttpRequest(String request, Parameters p) throws SvcLogicException {
769
770         SSLContext ssl = null;
771         if (p.ssl && p.restapiUrl.startsWith("https")) {
772             ssl = createSSLContext(p);
773         }
774         Client client;
775
776         if (ssl != null) {
777             HttpsURLConnection.setDefaultSSLSocketFactory(ssl.getSocketFactory());
778             client = ClientBuilder.newBuilder().sslContext(ssl).hostnameVerifier((s, sslSession) -> true).build();
779         } else {
780             client = ClientBuilder.newBuilder().hostnameVerifier((s, sslSession) -> true).build();
781         }
782         setClientTimeouts(client);
783         // Needed to support additional HTTP methods such as PATCH
784         client.property(HttpUrlConnectorProvider.SET_METHOD_WORKAROUND, true);
785
786         WebTarget webTarget = addAuthType(client, p).target(p.restapiUrl);
787
788         log.info("Sending request below to url " + p.restapiUrl);
789         log.info(request);
790         long t1 = System.currentTimeMillis();
791
792         HttpResponse r = new HttpResponse();
793         r.code = 200;
794         String accept = p.accept;
795         if (accept == null) {
796             accept = p.format == Format.XML ? "application/xml" : "application/json";
797         }
798
799         String contentType = p.contentType;
800         if (contentType == null) {
801             contentType = accept + ";charset=UTF-8";
802         }
803
804         if (!p.skipSending && !p.multipartFormData) {
805
806             Invocation.Builder invocationBuilder = webTarget.request(contentType).accept(accept);
807
808             if (p.format == Format.NONE) {
809                 invocationBuilder.header("", "");
810             }
811
812             if (p.customHttpHeaders != null && p.customHttpHeaders.length() > 0) {
813                 String[] keyValuePairs = p.customHttpHeaders.split(",");
814                 for (String singlePair : keyValuePairs) {
815                     int equalPosition = singlePair.indexOf('=');
816                     invocationBuilder.header(singlePair.substring(0, equalPosition),
817                             singlePair.substring(equalPosition + 1, singlePair.length()));
818                 }
819             }
820
821             invocationBuilder.header("X-ECOMP-RequestID", org.slf4j.MDC.get("X-ECOMP-RequestID"));
822
823             invocationBuilder.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
824
825             Response response;
826
827             try {
828                 response = invocationBuilder.method(p.httpMethod.toString(), entity(request, contentType));
829             } catch (ProcessingException | IllegalStateException e) {
830                 throw new SvcLogicException(requestPostingException + e.getLocalizedMessage(), e);
831             }
832
833             r.code = response.getStatus();
834             r.headers = response.getStringHeaders();
835             EntityTag etag = response.getEntityTag();
836             if (etag != null) {
837                 r.message = etag.getValue();
838             }
839             if (response.hasEntity() && r.code != 204) {
840                 r.body = response.readEntity(String.class);
841             }
842         } else if (!p.skipSending && p.multipartFormData) {
843
844             WebTarget wt = client.register(MultiPartFeature.class).target(p.restapiUrl);
845
846             MultiPart multiPart = new MultiPart();
847             multiPart.setMediaType(MediaType.MULTIPART_FORM_DATA_TYPE);
848
849             FileDataBodyPart fileDataBodyPart =
850                     new FileDataBodyPart("file", new File(p.multipartFile), MediaType.APPLICATION_OCTET_STREAM_TYPE);
851             multiPart.bodyPart(fileDataBodyPart);
852
853
854             Invocation.Builder invocationBuilder = wt.request(contentType).accept(accept);
855
856             if (p.format == Format.NONE) {
857                 invocationBuilder.header("", "");
858             }
859
860             if (p.customHttpHeaders != null && p.customHttpHeaders.length() > 0) {
861                 String[] keyValuePairs = p.customHttpHeaders.split(",");
862                 for (String singlePair : keyValuePairs) {
863                     int equalPosition = singlePair.indexOf('=');
864                     invocationBuilder.header(singlePair.substring(0, equalPosition),
865                             singlePair.substring(equalPosition + 1, singlePair.length()));
866                 }
867             }
868
869             invocationBuilder.header("X-ECOMP-RequestID", org.slf4j.MDC.get("X-ECOMP-RequestID"));
870
871             Response response;
872
873             try {
874                 response =
875                         invocationBuilder.method(p.httpMethod.toString(), entity(multiPart, multiPart.getMediaType()));
876             } catch (ProcessingException | IllegalStateException e) {
877                 throw new SvcLogicException(requestPostingException + e.getLocalizedMessage(), e);
878             }
879
880             r.code = response.getStatus();
881             r.headers = response.getStringHeaders();
882             EntityTag etag = response.getEntityTag();
883             if (etag != null) {
884                 r.message = etag.getValue();
885             }
886             if (response.hasEntity() && r.code != 204) {
887                 r.body = response.readEntity(String.class);
888             }
889
890         }
891
892         long t2 = System.currentTimeMillis();
893         log.info(responseReceivedMessage, t2 - t1);
894         log.info(responseHttpCodeMessage, r.code);
895         log.info("HTTP response message: {}", r.message);
896         logHeaders(r.headers);
897         log.info("HTTP response: {}", r.body);
898
899         return r;
900     }
901
902     protected SSLContext createSSLContext(Parameters p) {
903         try (FileInputStream in = new FileInputStream(p.keyStoreFileName)) {
904             System.setProperty("jsse.enableSNIExtension", "false");
905             System.setProperty("javax.net.ssl.trustStore", p.trustStoreFileName);
906             System.setProperty("javax.net.ssl.trustStorePassword", p.trustStorePassword);
907
908             HttpsURLConnection.setDefaultHostnameVerifier((string, ssls) -> true);
909
910             KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
911             KeyStore ks = KeyStore.getInstance("PKCS12");
912             char[] pwd = p.keyStorePassword.toCharArray();
913             ks.load(in, pwd);
914             kmf.init(ks, pwd);
915
916             SSLContext ctx = SSLContext.getInstance("TLS");
917             ctx.init(kmf.getKeyManagers(), null, null);
918             return ctx;
919         } catch (Exception e) {
920             log.error("Error creating SSLContext: {}", e.getMessage(), e);
921         }
922         return null;
923     }
924
925     protected void setFailureResponseStatus(SvcLogicContext ctx, String prefix, String errorMessage,
926             HttpResponse resp) {
927         resp.code = 500;
928         resp.message = errorMessage;
929         String pp = prefix != null ? prefix + '.' : "";
930         ctx.setAttribute(pp + "response-code", String.valueOf(resp.code));
931         ctx.setAttribute(pp + "response-message", resp.message);
932     }
933
934     protected void setResponseStatus(SvcLogicContext ctx, String prefix, HttpResponse r) {
935         String pp = prefix != null ? prefix + '.' : "";
936         ctx.setAttribute(pp + "response-code", String.valueOf(r.code));
937         ctx.setAttribute(pp + "response-message", r.message);
938     }
939
940     public void sendFile(Map<String, String> paramMap, SvcLogicContext ctx) throws SvcLogicException {
941         HttpResponse r = null;
942         try {
943             FileParam p = getFileParameters(paramMap);
944             byte[] data = Files.readAllBytes(Paths.get(p.fileName));
945
946             r = sendHttpData(data, p);
947             setResponseStatus(ctx, p.responsePrefix, r);
948
949         } catch (SvcLogicException | IOException e) {
950             log.error("Error sending the request: {}", e.getMessage(), e);
951
952             r = new HttpResponse();
953             r.code = 500;
954             r.message = e.getMessage();
955             String prefix = parseParam(paramMap, responsePrefix, false, null);
956             setResponseStatus(ctx, prefix, r);
957         }
958
959         if (r != null && r.code >= 300) {
960             throw new SvcLogicException(String.valueOf(r.code) + ": " + r.message);
961         }
962     }
963
964     private FileParam getFileParameters(Map<String, String> paramMap) throws SvcLogicException {
965         FileParam p = new FileParam();
966         p.fileName = parseParam(paramMap, "fileName", true, null);
967         p.url = parseParam(paramMap, "url", true, null);
968         p.user = parseParam(paramMap, "user", false, null);
969         p.password = parseParam(paramMap, "password", false, null);
970         p.httpMethod = HttpMethod.fromString(parseParam(paramMap, "httpMethod", false, "post"));
971         p.responsePrefix = parseParam(paramMap, responsePrefix, false, null);
972         String skipSendingStr = paramMap.get(skipSendingMessage);
973         p.skipSending = "true".equalsIgnoreCase(skipSendingStr);
974         p.oAuthConsumerKey = parseParam(paramMap, "oAuthConsumerKey", false, null);
975         p.oAuthVersion = parseParam(paramMap, "oAuthVersion", false, null);
976         p.oAuthConsumerSecret = parseParam(paramMap, "oAuthConsumerSecret", false, null);
977         p.oAuthSignatureMethod = parseParam(paramMap, "oAuthSignatureMethod", false, null);
978         p.authtype = fromString(parseParam(paramMap, "authType", false, "unspecified"));
979         return p;
980     }
981
982     public void postMessageOnUeb(Map<String, String> paramMap, SvcLogicContext ctx) throws SvcLogicException {
983         HttpResponse r;
984         try {
985             UebParam p = getUebParameters(paramMap);
986
987             String pp = p.responsePrefix != null ? p.responsePrefix + '.' : "";
988
989             String req;
990
991             if (p.templateFileName == null) {
992                 log.info("No template file name specified. Using default UEB template: {}", defaultUebTemplateFileName);
993                 p.templateFileName = defaultUebTemplateFileName;
994             }
995
996             String reqTemplate = readFile(p.templateFileName);
997             reqTemplate = reqTemplate.replaceAll("rootVarName", p.rootVarName);
998             req = buildXmlJsonRequest(ctx, reqTemplate, Format.JSON);
999
1000             r = postOnUeb(req, p);
1001             setResponseStatus(ctx, p.responsePrefix, r);
1002             if (r.body != null) {
1003                 ctx.setAttribute(pp + "httpResponse", r.body);
1004             }
1005
1006         } catch (SvcLogicException e) {
1007             log.error("Error sending the request: {}", e.getMessage(), e);
1008
1009             r = new HttpResponse();
1010             r.code = 500;
1011             r.message = e.getMessage();
1012             String prefix = parseParam(paramMap, responsePrefix, false, null);
1013             setResponseStatus(ctx, prefix, r);
1014         }
1015
1016         if (r.code >= 300) {
1017             throw new SvcLogicException(String.valueOf(r.code) + ": " + r.message);
1018         }
1019     }
1020
1021     protected HttpResponse sendHttpData(byte[] data, FileParam p) throws SvcLogicException {
1022
1023         Client client = ClientBuilder.newBuilder().build();
1024         setClientTimeouts(client);
1025         client.property(ClientProperties.FOLLOW_REDIRECTS, true);
1026         WebTarget webTarget = addAuthType(client, p).target(p.url);
1027
1028         log.info("Sending file");
1029         long t1 = System.currentTimeMillis();
1030
1031         HttpResponse r = new HttpResponse();
1032         r.code = 200;
1033
1034         if (!p.skipSending) {
1035             String tt = "application/octet-stream";
1036             Invocation.Builder invocationBuilder = webTarget.request(tt).accept(tt);
1037
1038             Response response;
1039
1040             try {
1041                 if (p.httpMethod == HttpMethod.POST) {
1042                     response = invocationBuilder.post(Entity.entity(data, tt));
1043                 } else if (p.httpMethod == HttpMethod.PUT) {
1044                     response = invocationBuilder.put(Entity.entity(data, tt));
1045                 } else {
1046                     throw new SvcLogicException("Http operation" + p.httpMethod + "not supported");
1047                 }
1048             } catch (ProcessingException e) {
1049                 throw new SvcLogicException(requestPostingException + e.getLocalizedMessage(), e);
1050             }
1051
1052             r.code = response.getStatus();
1053             r.headers = response.getStringHeaders();
1054             EntityTag etag = response.getEntityTag();
1055             if (etag != null) {
1056                 r.message = etag.getValue();
1057             }
1058             if (response.hasEntity() && r.code != 204) {
1059                 r.body = response.readEntity(String.class);
1060             }
1061
1062             if (r.code == 301) {
1063                 String newUrl = response.getStringHeaders().getFirst("Location");
1064
1065                 log.info("Got response code 301. Sending same request to URL: {}", newUrl);
1066
1067                 webTarget = client.target(newUrl);
1068                 invocationBuilder = webTarget.request(tt).accept(tt);
1069
1070                 try {
1071                     if (p.httpMethod == HttpMethod.POST) {
1072                         response = invocationBuilder.post(Entity.entity(data, tt));
1073                     } else if (p.httpMethod == HttpMethod.PUT) {
1074                         response = invocationBuilder.put(Entity.entity(data, tt));
1075                     } else {
1076                         throw new SvcLogicException("Http operation" + p.httpMethod + "not supported");
1077                     }
1078                 } catch (ProcessingException e) {
1079                     throw new SvcLogicException(requestPostingException + e.getLocalizedMessage(), e);
1080                 }
1081
1082                 r.code = response.getStatus();
1083                 etag = response.getEntityTag();
1084                 if (etag != null) {
1085                     r.message = etag.getValue();
1086                 }
1087                 if (response.hasEntity() && r.code != 204) {
1088                     r.body = response.readEntity(String.class);
1089                 }
1090             }
1091         }
1092
1093         long t2 = System.currentTimeMillis();
1094         log.info(responseReceivedMessage, t2 - t1);
1095         log.info(responseHttpCodeMessage, r.code);
1096         log.info("HTTP response message: {}", r.message);
1097         logHeaders(r.headers);
1098         log.info("HTTP response: {}", r.body);
1099
1100         return r;
1101     }
1102
1103     private UebParam getUebParameters(Map<String, String> paramMap) throws SvcLogicException {
1104         UebParam p = new UebParam();
1105         p.topic = parseParam(paramMap, "topic", true, null);
1106         p.templateFileName = parseParam(paramMap, "templateFileName", false, null);
1107         p.rootVarName = parseParam(paramMap, "rootVarName", false, null);
1108         p.responsePrefix = parseParam(paramMap, responsePrefix, false, null);
1109         String skipSendingStr = paramMap.get(skipSendingMessage);
1110         p.skipSending = "true".equalsIgnoreCase(skipSendingStr);
1111         return p;
1112     }
1113
1114     protected void logProperties(Map<String, Object> mm) {
1115         List<String> ll = new ArrayList<>();
1116         for (Object o : mm.keySet()) {
1117             ll.add((String) o);
1118         }
1119         Collections.sort(ll);
1120
1121         log.info("Properties:");
1122         for (String name : ll) {
1123             log.info("--- {}:{}", name, String.valueOf(mm.get(name)));
1124         }
1125     }
1126
1127     protected void logHeaders(MultivaluedMap<String, String> mm) {
1128         log.info("HTTP response headers:");
1129
1130         if (mm == null) {
1131             return;
1132         }
1133
1134         List<String> ll = new ArrayList<>();
1135         for (Object o : mm.keySet()) {
1136             ll.add((String) o);
1137         }
1138         Collections.sort(ll);
1139
1140         for (String name : ll) {
1141             log.info("--- {}:{}", name, String.valueOf(mm.get(name)));
1142         }
1143     }
1144
1145     protected HttpResponse postOnUeb(String request, UebParam p) throws SvcLogicException {
1146         String[] urls = uebServers.split(" ");
1147         for (int i = 0; i < urls.length; i++) {
1148             if (!urls[i].endsWith("/")) {
1149                 urls[i] += "/";
1150             }
1151             urls[i] += "events/" + p.topic;
1152         }
1153
1154         Client client = ClientBuilder.newBuilder().build();
1155         setClientTimeouts(client);
1156         WebTarget webTarget = client.target(urls[0]);
1157
1158         log.info("UEB URL: {}", urls[0]);
1159         log.info("Sending request:");
1160         log.info(request);
1161         long t1 = System.currentTimeMillis();
1162
1163         HttpResponse r = new HttpResponse();
1164         r.code = 200;
1165
1166         if (!p.skipSending) {
1167             String tt = "application/json";
1168             String tt1 = tt + ";charset=UTF-8";
1169
1170             Response response;
1171             Invocation.Builder invocationBuilder = webTarget.request(tt1).accept(tt);
1172
1173             try {
1174                 response = invocationBuilder.post(Entity.entity(request, tt1));
1175             } catch (ProcessingException e) {
1176                 throw new SvcLogicException(requestPostingException + e.getLocalizedMessage(), e);
1177             }
1178             r.code = response.getStatus();
1179             r.headers = response.getStringHeaders();
1180             if (response.hasEntity()) {
1181                 r.body = response.readEntity(String.class);
1182             }
1183         }
1184
1185         long t2 = System.currentTimeMillis();
1186         log.info(responseReceivedMessage, t2 - t1);
1187         log.info(responseHttpCodeMessage, r.code);
1188         logHeaders(r.headers);
1189         log.info("HTTP response:\n {}", r.body);
1190
1191         return r;
1192     }
1193
1194     public void setUebServers(String uebServers) {
1195         this.uebServers = uebServers;
1196     }
1197
1198     public void setDefaultUebTemplateFileName(String defaultUebTemplateFileName) {
1199         this.defaultUebTemplateFileName = defaultUebTemplateFileName;
1200     }
1201     
1202     protected void setClientTimeouts(Client client) {
1203         client.property(ClientProperties.CONNECT_TIMEOUT, httpConnectTimeout);
1204         client.property(ClientProperties.READ_TIMEOUT, httpReadTimeout);
1205     }
1206
1207     protected Integer readOptionalInteger(String propertyName, Integer defaultValue) {
1208         String stringValue = System.getProperty(propertyName);
1209         if (stringValue != null && stringValue.length() > 0) {
1210             try {
1211                 return Integer.valueOf(stringValue);
1212             } catch (NumberFormatException e) {
1213                 log.warn("property " + propertyName + " had the value " + stringValue + " that could not be converted to an Integer, default " + defaultValue + " will be used instead", e);
1214             }
1215         }
1216         return defaultValue;
1217     }
1218
1219     
1220     private static class FileParam {
1221
1222         public String fileName;
1223         public String url;
1224         public String user;
1225         public String password;
1226         public HttpMethod httpMethod;
1227         public String responsePrefix;
1228         public boolean skipSending;
1229         public String oAuthConsumerKey;
1230         public String oAuthConsumerSecret;
1231         public String oAuthSignatureMethod;
1232         public String oAuthVersion;
1233         public AuthType authtype;
1234     }
1235
1236     private static class UebParam {
1237
1238         public String topic;
1239         public String templateFileName;
1240         public String rootVarName;
1241         public String responsePrefix;
1242         public boolean skipSending;
1243     }
1244 }