X-Git-Url: https://gerrit.onap.org/r/gitweb?a=blobdiff_plain;f=restapi-call-node%2Fprovider%2Fsrc%2Fmain%2Fjava%2Forg%2Fonap%2Fccsdk%2Fsli%2Fplugins%2Frestapicall%2FRestapiCallNode.java;h=9b50eaa4499b9682c6f29fc323eb493a1733155c;hb=a8287a9b4c1b679e04307669fffee6eb1d5f4ab5;hp=e5c1859686a3fc6a41b5dcd3817d381237fe0762;hpb=c6029168cd1b95ef2c4a2b554fd0f3b61df185da;p=ccsdk%2Fsli%2Fplugins.git diff --git a/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/RestapiCallNode.java b/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/RestapiCallNode.java index e5c18596..9b50eaa4 100644 --- a/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/RestapiCallNode.java +++ b/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/RestapiCallNode.java @@ -4,6 +4,7 @@ * ================================================================================ * Copyright (C) 2017 AT&T Intellectual Property. All rights * reserved. + * Modifications Copyright © 2018 IBM. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,8 +22,10 @@ package org.onap.ccsdk.sli.plugins.restapicall; -import com.sun.jersey.api.client.ClientHandlerException; -import com.sun.jersey.api.client.UniformInterfaceException; +import static java.lang.Boolean.valueOf; +import static javax.ws.rs.client.Entity.entity; +import static org.onap.ccsdk.sli.plugins.restapicall.AuthType.fromString; +import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.net.SocketException; @@ -37,56 +40,239 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Properties; import java.util.Set; - -import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLSession; +import javax.ws.rs.ProcessingException; +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.client.Entity; +import javax.ws.rs.client.Invocation; +import javax.ws.rs.client.WebTarget; import javax.ws.rs.core.EntityTag; +import javax.ws.rs.core.Feature; +import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response; import javax.ws.rs.core.UriBuilder; - import org.apache.commons.lang3.StringUtils; -import org.codehaus.jettison.json.JSONException; +import org.glassfish.jersey.client.ClientProperties; +import org.glassfish.jersey.client.HttpUrlConnectorProvider; +import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature; +import org.glassfish.jersey.client.oauth1.ConsumerCredentials; +import org.glassfish.jersey.client.oauth1.OAuth1ClientSupport; +import org.glassfish.jersey.media.multipart.MultiPart; +import org.glassfish.jersey.media.multipart.MultiPartFeature; +import org.glassfish.jersey.media.multipart.file.FileDataBodyPart; import org.onap.ccsdk.sli.core.sli.SvcLogicContext; import org.onap.ccsdk.sli.core.sli.SvcLogicException; import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.sun.jersey.api.client.Client; -import com.sun.jersey.api.client.ClientResponse; -import com.sun.jersey.api.client.WebResource; -import com.sun.jersey.api.client.config.ClientConfig; -import com.sun.jersey.api.client.config.DefaultClientConfig; -import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter; -import com.sun.jersey.client.urlconnection.HTTPSProperties; - public class RestapiCallNode implements SvcLogicJavaPlugin { - private static final Logger log = LoggerFactory.getLogger(RestapiCallNode.class); + protected static final String DME2_PROPERTIES_FILE_NAME = "dme2.properties"; + protected static final String UEB_PROPERTIES_FILE_NAME = "ueb.properties"; + protected static final String DEFAULT_PROPERTIES_DIR = "/opt/onap/ccsdk/data/properties"; + protected static final String PROPERTIES_DIR_KEY = "SDNC_CONFIG_DIR"; + private static final Logger log = LoggerFactory.getLogger(RestapiCallNode.class); + protected RetryPolicyStore retryPolicyStore; private String uebServers; private String defaultUebTemplateFileName = "/opt/bvc/restapi/templates/default-ueb-message.json"; - protected RetryPolicyStore retryPolicyStore; - protected RetryPolicyStore getRetryPolicyStore() { - return retryPolicyStore; + private String responseReceivedMessage = "Response received. Time: {}"; + private String responseHttpCodeMessage = "HTTP response code: {}"; + private String requestPostingException = "Exception while posting http request to client "; + private static String skipSendingMessage = "skipSending"; + private static String responsePrefix = "responsePrefix"; + private static String restapiUrlString = "restapiUrl"; + + public RestapiCallNode() { + String configDir = System.getProperty(PROPERTIES_DIR_KEY, DEFAULT_PROPERTIES_DIR); + + try (FileInputStream in = new FileInputStream(configDir + "/" + DME2_PROPERTIES_FILE_NAME)) { + Properties props = new Properties(); + props.load(in); + retryPolicyStore = new RetryPolicyStore(); + retryPolicyStore.setProxyServers(props.getProperty("proxyUrl")); + log.info("DME2 support enabled"); + } catch (Exception e) { + log.warn("DME2 properties could not be read, DME2 support will not be enabled.", e); + } + + try (FileInputStream in = new FileInputStream(configDir + "/" + UEB_PROPERTIES_FILE_NAME)) { + Properties props = new Properties(); + props.load(in); + uebServers = props.getProperty("servers"); + log.info("UEB support enabled"); + } catch (Exception e) { + log.warn("UEB properties could not be read, UEB support will not be enabled.", e); + } } - public void setRetryPolicyStore(RetryPolicyStore retryPolicyStore) { - this.retryPolicyStore = retryPolicyStore; + /** + * Returns parameters from the parameter map. + * + * @param paramMap parameter map + * @param p parameters instance + * @return parameters filed instance + * @throws SvcLogicException when svc logic exception occurs + */ + public static Parameters getParameters(Map paramMap, + Parameters p) + throws SvcLogicException { + p.templateFileName = parseParam(paramMap, "templateFileName", + false, null); + p.requestBody = parseParam(paramMap, "requestBody", false, null); + p.restapiUrl = parseParam(paramMap, restapiUrlString, true, null); + validateUrl(p.restapiUrl); + p.restapiUser = parseParam(paramMap, "restapiUser", false, null); + p.restapiPassword = parseParam(paramMap, "restapiPassword", false, + null); + p.oAuthConsumerKey = parseParam(paramMap, "oAuthConsumerKey", + false, null); + p.oAuthConsumerSecret = parseParam(paramMap, "oAuthConsumerSecret", + false, null); + p.oAuthSignatureMethod = parseParam(paramMap, "oAuthSignatureMethod", + false, null); + p.oAuthVersion = parseParam(paramMap, "oAuthVersion", false, null); + p.contentType = parseParam(paramMap, "contentType", false, null); + p.format = Format.fromString(parseParam(paramMap, "format", false, + "json")); + p.authtype = fromString(parseParam(paramMap, "authType", false, + "unspecified")); + p.httpMethod = HttpMethod.fromString(parseParam(paramMap, "httpMethod", + false, "post")); + p.responsePrefix = parseParam(paramMap, responsePrefix, false, null); + p.listNameList = getListNameList(paramMap); + String skipSendingStr = paramMap.get(skipSendingMessage); + p.skipSending = "true".equalsIgnoreCase(skipSendingStr); + p.convertResponse = valueOf(parseParam(paramMap, "convertResponse", + false, "true")); + p.trustStoreFileName = parseParam(paramMap, "trustStoreFileName", + false, null); + p.trustStorePassword = parseParam(paramMap, "trustStorePassword", + false, null); + p.keyStoreFileName = parseParam(paramMap, "keyStoreFileName", + false, null); + p.keyStorePassword = parseParam(paramMap, "keyStorePassword", + false, null); + p.ssl = p.trustStoreFileName != null && p.trustStorePassword != null + && p.keyStoreFileName != null && p.keyStorePassword != null; + p.customHttpHeaders = parseParam(paramMap, "customHttpHeaders", + false, null); + p.partner = parseParam(paramMap, "partner", false, null); + p.dumpHeaders = valueOf(parseParam(paramMap, "dumpHeaders", + false, null)); + p.returnRequestPayload = valueOf(parseParam( + paramMap, "returnRequestPayload", false, null)); + p.accept = parseParam(paramMap, "accept", + false, null); + p.multipartFormData = valueOf(parseParam(paramMap, "multipartFormData", + false, "false")); + p.multipartFile = parseParam(paramMap, "multipartFile", + false, null); + return p; } - public RestapiCallNode() { + /** + * Validates the given URL in the parameters. + * + * @param restapiUrl rest api URL + * @throws SvcLogicException when URL validation fails + */ + private static void validateUrl(String restapiUrl) + throws SvcLogicException { + try { + URI.create(restapiUrl); + } catch (IllegalArgumentException e) { + throw new SvcLogicException("Invalid input of url " + + e.getLocalizedMessage(), e); + } + } + /** + * Returns the list of list name. + * + * @param paramMap parameters map + * @return list of list name + */ + private static Set getListNameList(Map paramMap) { + Set ll = new HashSet<>(); + for (Map.Entry entry : paramMap.entrySet()) { + if (entry.getKey().startsWith("listName")) { + ll.add(entry.getValue()); + } + } + return ll; } - /** + /** + * Parses the parameter string map of property, validates if required, + * assigns default value if present and returns the value. + * + * @param paramMap string param map + * @param name name of the property + * @param required if value required + * @param def default value + * @return value of the property + * @throws SvcLogicException if required parameter value is empty + */ + public static String parseParam(Map paramMap, String name, + boolean required, String def) + throws SvcLogicException { + String s = paramMap.get(name); + + if (s == null || s.trim().length() == 0) { + if (!required) { + return def; + } + throw new SvcLogicException("Parameter " + name + " is required in RestapiCallNode"); + } + + s = s.trim(); + StringBuilder value = new StringBuilder(); + int i = 0; + int i1 = s.indexOf('%'); + while (i1 >= 0) { + int i2 = s.indexOf('%', i1 + 1); + if (i2 < 0) { + break; + } + + String varName = s.substring(i1 + 1, i2); + String varValue = System.getenv(varName); + if (varValue == null) { + varValue = "%" + varName + "%"; + } + + value.append(s.substring(i, i1)); + value.append(varValue); + + i = i2 + 1; + i1 = s.indexOf('%', i); + } + value.append(s.substring(i)); + + log.info("Parameter {}: [{}]", name, value); + return value.toString(); + } + + public RetryPolicyStore getRetryPolicyStore() { + return retryPolicyStore; + } + + public void setRetryPolicyStore(RetryPolicyStore retryPolicyStore) { + this.retryPolicyStore = retryPolicyStore; + } + + /** * Allows Directed Graphs the ability to interact with REST APIs. - * @param parameters HashMap of parameters passed by the DG to this function + * @param paramMap HashMap of parameters passed by the DG to this function * * * @@ -94,6 +280,10 @@ public class RestapiCallNode implements SvcLogicJavaPlugin { * * * + * + * + * + * * * * @@ -104,6 +294,7 @@ public class RestapiCallNode implements SvcLogicJavaPlugin { * * * + * * *
parameterMandatory/Optionaldescriptionexample values
restapiUrlMandatoryurl to send the request tohttps://sdncodl:8543/restconf/operations/L3VNF-API:create-update-vnf-request
restapiUserOptionaluser name to use for http basic authenticationsdnc_ws
restapiPasswordOptionalunencrypted password to use for http basic authenticationplain_password
oAuthConsumerKeyOptionalConsumer key to use for http oAuth authenticationplain_key
oAuthConsumerSecretOptionalConsumer secret to use for http oAuth authenticationplain_secret
oAuthSignatureMethodOptionalConsumer method to use for http oAuth authenticationmethod
oAuthVersionOptionalVersion http oAuth authenticationversion
contentTypeOptionalhttp content type to set in the http headerusually application/json or application/xml
formatOptionalshould match request body formatjson or xml
httpMethodOptionalhttp method to use when sending the requestget post put delete patch
customHttpHeadersOptionala list additional http headers to be passed in, follow the format in the exampleX-CSI-MessageId=messageId,headerFieldName=headerFieldValue
dumpHeadersOptionalwhen true writes http header content to context memorytrue or false
partnerOptionalneeded for DME2 callsdme2proxy
returnRequestPayloadOptionalused to return payload built in the requesttrue or false
* @param ctx Reference to context memory @@ -116,12 +307,12 @@ public class RestapiCallNode implements SvcLogicJavaPlugin { } public void sendRequest(Map paramMap, SvcLogicContext ctx, Integer retryCount) - throws SvcLogicException { + throws SvcLogicException { RetryPolicy retryPolicy = null; HttpResponse r = new HttpResponse(); try { - Parameters p = getParameters(paramMap); + Parameters p = getParameters(paramMap, new Parameters()); if (p.partner != null) { retryPolicy = retryPolicyStore.getRetryPolicy(p.partner); } @@ -143,19 +334,26 @@ public class RestapiCallNode implements SvcLogicJavaPlugin { } } + if (p.returnRequestPayload && req != null) { + ctx.setAttribute(pp + "httpRequest", req); + } + if (r.body != null && r.body.trim().length() > 0) { ctx.setAttribute(pp + "httpResponse", r.body); if (p.convertResponse) { Map mm = null; - if (p.format == Format.XML) + if (p.format == Format.XML) { mm = XmlParser.convertToProperties(r.body, p.listNameList); - else if (p.format == Format.JSON) + } else if (p.format == Format.JSON) { mm = JsonParser.convertToProperties(r.body); + } - if (mm != null) - for (Map.Entry entry : mm.entrySet()) + if (mm != null) { + for (Map.Entry entry : mm.entrySet()) { ctx.setAttribute(pp + entry.getKey(), entry.getValue()); + } + } } } } catch (SvcLogicException e) { @@ -165,26 +363,26 @@ public class RestapiCallNode implements SvcLogicJavaPlugin { } log.error("Error sending the request: " + e.getMessage(), e); - String prefix = parseParam(paramMap, "responsePrefix", false, null); - if (retryPolicy == null || shouldRetry == false) { + String prefix = parseParam(paramMap, responsePrefix, false, null); + if (retryPolicy == null || !shouldRetry) { setFailureResponseStatus(ctx, prefix, e.getMessage(), r); } else { if (retryCount == null) { retryCount = 0; } String retryMessage = retryCount + " attempts were made out of " + retryPolicy.getMaximumRetries() + - " maximum retries."; + " maximum retries."; log.debug(retryMessage); try { retryCount = retryCount + 1; if (retryCount < retryPolicy.getMaximumRetries() + 1) { - URI uri = new URI(paramMap.get("restapiUrl")); + URI uri = new URI(paramMap.get(restapiUrlString)); String hostname = uri.getHost(); String retryString = retryPolicy.getNextHostName(uri.toString()); URI uriTwo = new URI(retryString); URI retryUri = UriBuilder.fromUri(uri).host(uriTwo.getHost()).port(uriTwo.getPort()).scheme( - uriTwo.getScheme()).build(); - paramMap.put("restapiUrl", retryUri.toString()); + uriTwo.getScheme()).build(); + paramMap.put(restapiUrlString, retryUri.toString()); log.debug("URL was set to {}", retryUri.toString()); log.debug("Failed to communicate with host {}. Request will be re-attempted using the host {}.", hostname, retryString); @@ -197,107 +395,30 @@ public class RestapiCallNode implements SvcLogicJavaPlugin { } catch (Exception ex) { log.error("Could not attempt retry.", ex); String retryErrorMessage = - "Retry attempt has failed. No further retry shall be attempted, calling " + - "setFailureResponseStatus."; + "Retry attempt has failed. No further retry shall be attempted, calling " + + "setFailureResponseStatus."; setFailureResponseStatus(ctx, prefix, retryErrorMessage, r); } } } - if (r != null && r.code >= 300) + if (r != null && r.code >= 300) { throw new SvcLogicException(String.valueOf(r.code) + ": " + r.message); - } - - protected Parameters getParameters(Map paramMap) throws SvcLogicException { - Parameters p = new Parameters(); - p.templateFileName = parseParam(paramMap, "templateFileName", false, null); - p.requestBody = parseParam(paramMap, "requestBody", false, null); - p.restapiUrl = parseParam(paramMap, "restapiUrl", true, null); - validateUrl(p.restapiUrl); - p.restapiUser = parseParam(paramMap, "restapiUser", false, null); - p.restapiPassword = parseParam(paramMap, "restapiPassword", false, null); - p.contentType = parseParam(paramMap, "contentType", false, null); - p.format = Format.fromString(parseParam(paramMap, "format", false, "json")); - p.httpMethod = HttpMethod.fromString(parseParam(paramMap, "httpMethod", false, "post")); - p.responsePrefix = parseParam(paramMap, "responsePrefix", false, null); - p.listNameList = getListNameList(paramMap); - String skipSendingStr = paramMap.get("skipSending"); - p.skipSending = "true".equalsIgnoreCase(skipSendingStr); - p.convertResponse = Boolean.valueOf(parseParam(paramMap, "convertResponse", false, "true")); - p.trustStoreFileName = parseParam(paramMap, "trustStoreFileName", false, null); - p.trustStorePassword = parseParam(paramMap, "trustStorePassword", false, null); - p.keyStoreFileName = parseParam(paramMap, "keyStoreFileName", false, null); - p.keyStorePassword = parseParam(paramMap, "keyStorePassword", false, null); - p.ssl = p.trustStoreFileName != null && p.trustStorePassword != null && p.keyStoreFileName != null && - p.keyStorePassword != null; - p.customHttpHeaders = parseParam(paramMap, "customHttpHeaders", false, null); - p.partner = parseParam(paramMap, "partner", false, null); - p.dumpHeaders = Boolean.valueOf(parseParam(paramMap, "dumpHeaders", false, null)); - return p; - } - - private void validateUrl(String restapiUrl) throws SvcLogicException { - try { - URI.create(restapiUrl); - } catch (IllegalArgumentException e) { - throw new SvcLogicException("Invalid input of url " + e.getLocalizedMessage(), e); - } - } - - protected Set getListNameList(Map paramMap) { - Set ll = new HashSet<>(); - for (Map.Entry entry : paramMap.entrySet()) - if (entry.getKey().startsWith("listName")) - ll.add(entry.getValue()); - return ll; - } - - protected String parseParam(Map paramMap, String name, boolean required, String def) - throws SvcLogicException { - String s = paramMap.get(name); - - if (s == null || s.trim().length() == 0) { - if (!required) - return def; - throw new SvcLogicException("Parameter " + name + " is required in RestapiCallNode"); - } - - s = s.trim(); - StringBuilder value = new StringBuilder(); - int i = 0; - int i1 = s.indexOf('%'); - while (i1 >= 0) { - int i2 = s.indexOf('%', i1 + 1); - if (i2 < 0) - break; - - String varName = s.substring(i1 + 1, i2); - String varValue = System.getenv(varName); - if (varValue == null) - varValue = "%" + varName + "%"; - - value.append(s.substring(i, i1)); - value.append(varValue); - - i = i2 + 1; - i1 = s.indexOf('%', i); } - value.append(s.substring(i)); - - log.info("Parameter {}: [{}]", name, value); - return value.toString(); } protected String buildXmlJsonRequest(SvcLogicContext ctx, String template, Format format) throws SvcLogicException { log.info("Building {} started", format); long t1 = System.currentTimeMillis(); + String originalTemplate = template; template = expandRepeats(ctx, template, 1); Map mm = new HashMap<>(); - for (String s : ctx.getAttributeKeySet()) + for (String s : ctx.getAttributeKeySet()) { mm.put(s, ctx.getAttribute(s)); + } StringBuilder ss = new StringBuilder(); int i = 0; @@ -309,23 +430,26 @@ public class RestapiCallNode implements SvcLogicJavaPlugin { } int i2 = template.indexOf('}', i1 + 2); - if (i2 < 0) + if (i2 < 0) { throw new SvcLogicException("Template error: Matching } not found"); + } String var1 = template.substring(i1 + 2, i2); String value1 = format == Format.XML ? XmlJsonUtil.getXml(mm, var1) : XmlJsonUtil.getJson(mm, var1); - // log.info(" " + var1 + ": " + value1); if (value1 == null || value1.trim().length() == 0) { // delete the whole element (line) int i3 = template.lastIndexOf('\n', i1); - if (i3 < 0) + if (i3 < 0) { i3 = 0; + } int i4 = template.indexOf('\n', i1); - if (i4 < 0) + if (i4 < 0) { i4 = template.length(); + } - if (i < i3) + if (i < i3) { ss.append(template.substring(i, i3)); + } i = i4; } else { ss.append(template.substring(i, i1)).append(value1); @@ -334,13 +458,14 @@ public class RestapiCallNode implements SvcLogicJavaPlugin { } String req = format == Format.XML - ? XmlJsonUtil.removeEmptyStructXml(ss.toString()) : XmlJsonUtil.removeEmptyStructJson(ss.toString()); + ? XmlJsonUtil.removeEmptyStructXml(ss.toString()) : XmlJsonUtil.removeEmptyStructJson(originalTemplate, ss.toString()); - if (format == Format.JSON) + if (format == Format.JSON) { req = XmlJsonUtil.removeLastCommaJson(req); + } long t2 = System.currentTimeMillis(); - log.info("Building {} completed. Time: {}", format, (t2 - t1)); + log.info("Building {} completed. Time: {}", format, t2 - t1); return req; } @@ -356,9 +481,10 @@ public class RestapiCallNode implements SvcLogicJavaPlugin { } int i2 = template.indexOf(':', i1 + 9); - if (i2 < 0) + if (i2 < 0) { throw new SvcLogicException( - "Template error: Context variable name followed by : is required after repeat"); + "Template error: Context variable name followed by : is required after repeat"); + } // Find the closing }, store in i3 int nn = 1; @@ -366,8 +492,9 @@ public class RestapiCallNode implements SvcLogicJavaPlugin { int i = i2; while (nn > 0 && i < template.length()) { i3 = template.indexOf('}', i); - if (i3 < 0) + if (i3 < 0) { throw new SvcLogicException("Template error: Matching } not found"); + } int i32 = template.indexOf('{', i); if (i32 >= 0 && i32 < i3) { nn++; @@ -396,8 +523,9 @@ public class RestapiCallNode implements SvcLogicJavaPlugin { String ss = rpt.replaceAll("\\[\\$\\{" + level + "\\}\\]", "[" + ii + "]"); if (ii == n - 1 && ss.trim().endsWith(",")) { int i4 = ss.lastIndexOf(','); - if (i4 > 0) + if (i4 > 0) { ss = ss.substring(0, i4) + ss.substring(i4 + 1); + } } newTemplate.append(ss); } @@ -405,8 +533,9 @@ public class RestapiCallNode implements SvcLogicJavaPlugin { k = i3 + 1; } - if (k == 0) + if (k == 0) { return newTemplate.toString(); + } return expandRepeats(ctx, newTemplate.toString(), level + 1); } @@ -420,26 +549,92 @@ public class RestapiCallNode implements SvcLogicJavaPlugin { } } - protected HttpResponse sendHttpRequest(String request, Parameters p) throws SvcLogicException { + protected Client addAuthType(Client c, FileParam fp) throws SvcLogicException { + Parameters p = new Parameters(); + p.restapiUser = fp.user; + p.restapiPassword = fp.password; + p.oAuthConsumerKey = fp.oAuthConsumerKey; + p.oAuthVersion = fp.oAuthVersion; + p.oAuthConsumerSecret = fp.oAuthConsumerSecret; + p.oAuthSignatureMethod = fp.oAuthSignatureMethod; + p.authtype = fp.authtype; + return addAuthType(c, p); + } + + public Client addAuthType(Client client, Parameters p) throws SvcLogicException { + if (p.authtype == AuthType.Unspecified) { + if (p.restapiUser != null && p.restapiPassword != null) { + client.register(HttpAuthenticationFeature.basic(p.restapiUser, p.restapiPassword)); + } else if (p.oAuthConsumerKey != null && p.oAuthConsumerSecret != null + && p.oAuthSignatureMethod != null) { + Feature oAuth1Feature = OAuth1ClientSupport + .builder(new ConsumerCredentials(p.oAuthConsumerKey, p.oAuthConsumerSecret)) + .version(p.oAuthVersion).signatureMethod(p.oAuthSignatureMethod).feature().build(); + client.register(oAuth1Feature); + } + } else { + if (p.authtype == AuthType.DIGEST) { + if (p.restapiUser != null && p.restapiPassword != null) { + client.register(HttpAuthenticationFeature.digest(p.restapiUser, p.restapiPassword)); + } else { + throw new SvcLogicException( + "oAUTH authentication type selected but all restapiUser and restapiPassword " + + "parameters doesn't exist", new Throwable()); + } + } else if (p.authtype == AuthType.BASIC) { + if (p.restapiUser != null && p.restapiPassword != null) { + client.register(HttpAuthenticationFeature.basic(p.restapiUser, p.restapiPassword)); + } else { + throw new SvcLogicException( + "oAUTH authentication type selected but all restapiUser and restapiPassword " + + "parameters doesn't exist", new Throwable()); + } + } else if (p.authtype == AuthType.OAUTH) { + if (p.oAuthConsumerKey != null && p.oAuthConsumerSecret != null && p.oAuthSignatureMethod != null) { + Feature oAuth1Feature = OAuth1ClientSupport + .builder(new ConsumerCredentials(p.oAuthConsumerKey, p.oAuthConsumerSecret)) + .version(p.oAuthVersion).signatureMethod(p.oAuthSignatureMethod).feature().build(); + client.register(oAuth1Feature); + } else { + throw new SvcLogicException( + "oAUTH authentication type selected but all oAuthConsumerKey, oAuthConsumerSecret " + + "and oAuthSignatureMethod parameters doesn't exist", new Throwable()); + } + } + } + return client; + } + + /** + * Receives the http response for the http request sent. + * + * @param request request msg + * @param p parameters + * @return HTTP response + * @throws SvcLogicException when sending http request fails + */ + public HttpResponse sendHttpRequest(String request, Parameters p) + throws SvcLogicException { - ClientConfig config = new DefaultClientConfig(); SSLContext ssl = null; - if (p.ssl && p.restapiUrl.startsWith("https")) + if (p.ssl && p.restapiUrl.startsWith("https")) { ssl = createSSLContext(p); - if (ssl != null) { - HostnameVerifier hostnameVerifier = (hostname, session) -> true; - - config.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES, - new HTTPSProperties(hostnameVerifier, ssl)); } + Client client; - logProperties(config.getProperties()); + if (ssl != null) { + HttpsURLConnection.setDefaultSSLSocketFactory(ssl.getSocketFactory()); + client = ClientBuilder.newBuilder().sslContext(ssl).hostnameVerifier((s, sslSession) -> true) + .build(); + } else { + client = ClientBuilder.newBuilder().hostnameVerifier((s, sslSession) -> true) + .build(); + } + client.property(ClientProperties.CONNECT_TIMEOUT, 5000); + // Needed to support additional HTTP methods such as PATCH + client.property(HttpUrlConnectorProvider.SET_METHOD_WORKAROUND, true); - Client client = Client.create(config); - client.setConnectTimeout(5000); - if (p.restapiUser != null) - client.addFilter(new HTTPBasicAuthFilter(p.restapiUser, p.restapiPassword)); - WebResource webResource = client.resource(p.restapiUrl); + WebTarget webTarget = addAuthType(client, p).target(p.restapiUrl); log.info("Sending request:"); log.info(request); @@ -448,48 +643,109 @@ public class RestapiCallNode implements SvcLogicJavaPlugin { HttpResponse r = new HttpResponse(); r.code = 200; - if (!p.skipSending) { - String tt = p.format == Format.XML ? "application/xml" : "application/json"; - String tt1 = tt + ";charset=UTF-8"; - if (p.contentType != null) { - tt = p.contentType; - tt1 = p.contentType; + String accept = p.accept; + if(accept == null) { + accept = p.format == Format.XML ? "application/xml" : "application/json"; + } + + String contentType = p.contentType; + if(contentType == null) { + contentType = accept + ";charset=UTF-8"; + } + + if (!p.skipSending && !p.multipartFormData) { + + Invocation.Builder invocationBuilder = webTarget.request(contentType).accept(accept); + + if (p.format == Format.NONE) { + invocationBuilder.header("", ""); + } + + if (p.customHttpHeaders != null && p.customHttpHeaders.length() > 0) { + String[] keyValuePairs = p.customHttpHeaders.split(","); + for (String singlePair : keyValuePairs) { + int equalPosition = singlePair.indexOf('='); + invocationBuilder.header(singlePair.substring(0, equalPosition), + singlePair.substring(equalPosition + 1, singlePair.length())); + } + } + + invocationBuilder.header("X-ECOMP-RequestID", org.slf4j.MDC.get("X-ECOMP-RequestID")); + + invocationBuilder.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true); + + Response response; + + try { + response = invocationBuilder.method(p.httpMethod.toString(), entity(request, contentType)); + } catch (ProcessingException | IllegalStateException e) { + throw new SvcLogicException(requestPostingException + + e.getLocalizedMessage(), e); + } + + r.code = response.getStatus(); + r.headers = response.getStringHeaders(); + EntityTag etag = response.getEntityTag(); + if (etag != null) { + r.message = etag.getValue(); + } + if (response.hasEntity() && r.code != 204) { + r.body = response.readEntity(String.class); } + } else if (!p.skipSending && p.multipartFormData) { + + WebTarget wt = client.register(MultiPartFeature.class).target(p.restapiUrl); - WebResource.Builder webResourceBuilder = webResource.accept(tt).type(tt1); + MultiPart multiPart = new MultiPart(); + multiPart.setMediaType(MediaType.MULTIPART_FORM_DATA_TYPE); + + FileDataBodyPart fileDataBodyPart = new FileDataBodyPart("file", + new File(p.multipartFile), + MediaType.APPLICATION_OCTET_STREAM_TYPE); + multiPart.bodyPart(fileDataBodyPart); + + + Invocation.Builder invocationBuilder = wt.request(contentType).accept(accept); + + if (p.format == Format.NONE) { + invocationBuilder.header("", ""); + } if (p.customHttpHeaders != null && p.customHttpHeaders.length() > 0) { String[] keyValuePairs = p.customHttpHeaders.split(","); for (String singlePair : keyValuePairs) { int equalPosition = singlePair.indexOf('='); - webResourceBuilder.header(singlePair.substring(0, equalPosition), + invocationBuilder.header(singlePair.substring(0, equalPosition), singlePair.substring(equalPosition + 1, singlePair.length())); } } - webResourceBuilder.header("X-ECOMP-RequestID",org.slf4j.MDC.get("X-ECOMP-RequestID")); + invocationBuilder.header("X-ECOMP-RequestID", org.slf4j.MDC.get("X-ECOMP-RequestID")); - ClientResponse response; + Response response; try { - response = webResourceBuilder.method(p.httpMethod.toString(), ClientResponse.class, request); - } catch (UniformInterfaceException | ClientHandlerException e) { - throw new SvcLogicException("Exception while sending http request to client " - + e.getLocalizedMessage(), e); + response = invocationBuilder.method(p.httpMethod.toString(), entity(multiPart, multiPart.getMediaType())); + } catch (ProcessingException | IllegalStateException e) { + throw new SvcLogicException(requestPostingException + + e.getLocalizedMessage(), e); } r.code = response.getStatus(); - r.headers = response.getHeaders(); + r.headers = response.getStringHeaders(); EntityTag etag = response.getEntityTag(); - if (etag != null) + if (etag != null) { r.message = etag.getValue(); - if (response.hasEntity() && r.code != 204) - r.body = response.getEntity(String.class); + } + if (response.hasEntity() && r.code != 204) { + r.body = response.readEntity(String.class); + } + } long t2 = System.currentTimeMillis(); - log.info("Response received. Time: {}", (t2 - t1)); - log.info("HTTP response code: {}", r.code); + log.info(responseReceivedMessage, t2 - t1); + log.info(responseHttpCodeMessage, r.code); log.info("HTTP response message: {}", r.message); logHeaders(r.headers); log.info("HTTP response: {}", r.body); @@ -550,23 +806,13 @@ public class RestapiCallNode implements SvcLogicJavaPlugin { r = new HttpResponse(); r.code = 500; r.message = e.getMessage(); - String prefix = parseParam(paramMap, "responsePrefix", false, null); + String prefix = parseParam(paramMap, responsePrefix, false, null); setResponseStatus(ctx, prefix, r); } - if (r != null && r.code >= 300) + if (r != null && r.code >= 300) { throw new SvcLogicException(String.valueOf(r.code) + ": " + r.message); - } - - private static class FileParam { - - public String fileName; - public String url; - public String user; - public String password; - public HttpMethod httpMethod; - public String responsePrefix; - public boolean skipSending; + } } private FileParam getFileParameters(Map paramMap) throws SvcLogicException { @@ -576,19 +822,62 @@ public class RestapiCallNode implements SvcLogicJavaPlugin { p.user = parseParam(paramMap, "user", false, null); p.password = parseParam(paramMap, "password", false, null); p.httpMethod = HttpMethod.fromString(parseParam(paramMap, "httpMethod", false, "post")); - p.responsePrefix = parseParam(paramMap, "responsePrefix", false, null); - String skipSendingStr = paramMap.get("skipSending"); + p.responsePrefix = parseParam(paramMap, responsePrefix, false, null); + String skipSendingStr = paramMap.get(skipSendingMessage); p.skipSending = "true".equalsIgnoreCase(skipSendingStr); + p.oAuthConsumerKey = parseParam(paramMap, "oAuthConsumerKey", false, null); + p.oAuthVersion = parseParam(paramMap, "oAuthVersion", false, null); + p.oAuthConsumerSecret = parseParam(paramMap, "oAuthConsumerSecret", false, null); + p.oAuthSignatureMethod = parseParam(paramMap, "oAuthSignatureMethod", false, null); + p.authtype = fromString(parseParam(paramMap, "authType", false, "unspecified")); return p; } + public void postMessageOnUeb(Map paramMap, SvcLogicContext ctx) throws SvcLogicException { + HttpResponse r; + try { + UebParam p = getUebParameters(paramMap); + + String pp = p.responsePrefix != null ? p.responsePrefix + '.' : ""; + + String req; + + if (p.templateFileName == null) { + log.info("No template file name specified. Using default UEB template: {}", defaultUebTemplateFileName); + p.templateFileName = defaultUebTemplateFileName; + } + + String reqTemplate = readFile(p.templateFileName); + reqTemplate = reqTemplate.replaceAll("rootVarName", p.rootVarName); + req = buildXmlJsonRequest(ctx, reqTemplate, Format.JSON); + + r = postOnUeb(req, p); + setResponseStatus(ctx, p.responsePrefix, r); + if (r.body != null) { + ctx.setAttribute(pp + "httpResponse", r.body); + } + + } catch (SvcLogicException e) { + log.error("Error sending the request: {}", e.getMessage(), e); + + r = new HttpResponse(); + r.code = 500; + r.message = e.getMessage(); + String prefix = parseParam(paramMap, responsePrefix, false, null); + setResponseStatus(ctx, prefix, r); + } + + if (r.code >= 300) { + throw new SvcLogicException(String.valueOf(r.code) + ": " + r.message); + } + } + protected HttpResponse sendHttpData(byte[] data, FileParam p) throws SvcLogicException { - Client client = Client.create(); - client.setConnectTimeout(5000); - client.setFollowRedirects(true); - if (p.user != null) - client.addFilter(new HTTPBasicAuthFilter(p.user, p.password)); - WebResource webResource = client.resource(p.url); + + Client client = ClientBuilder.newBuilder().build(); + client.property(ClientProperties.CONNECT_TIMEOUT, 5000); + client.property(ClientProperties.FOLLOW_REDIRECTS, true); + WebTarget webTarget = addAuthType(client, p).target(p.url); log.info("Sending file"); long t1 = System.currentTimeMillis(); @@ -598,59 +887,68 @@ public class RestapiCallNode implements SvcLogicJavaPlugin { if (!p.skipSending) { String tt = "application/octet-stream"; + Invocation.Builder invocationBuilder = webTarget.request(tt).accept(tt); + + Response response; - ClientResponse response; try { - if (p.httpMethod == HttpMethod.POST) - response = webResource.accept(tt).type(tt).post(ClientResponse.class, data); - else if (p.httpMethod == HttpMethod.PUT) - response = webResource.accept(tt).type(tt).put(ClientResponse.class, data); - else + if (p.httpMethod == HttpMethod.POST) { + response = invocationBuilder.post(Entity.entity(data, tt)); + } else if (p.httpMethod == HttpMethod.PUT) { + response = invocationBuilder.put(Entity.entity(data, tt)); + } else { throw new SvcLogicException("Http operation" + p.httpMethod + "not supported"); - } catch (UniformInterfaceException | ClientHandlerException e) { - throw new SvcLogicException("Exception while sending http request to client " + + } + } catch (ProcessingException e) { + throw new SvcLogicException(requestPostingException + e.getLocalizedMessage(), e); } r.code = response.getStatus(); - r.headers = response.getHeaders(); + r.headers = response.getStringHeaders(); EntityTag etag = response.getEntityTag(); - if (etag != null) + if (etag != null) { r.message = etag.getValue(); - if (response.hasEntity() && r.code != 204) - r.body = response.getEntity(String.class); + } + if (response.hasEntity() && r.code != 204) { + r.body = response.readEntity(String.class); + } if (r.code == 301) { - String newUrl = response.getHeaders().getFirst("Location"); + String newUrl = response.getStringHeaders().getFirst("Location"); log.info("Got response code 301. Sending same request to URL: {}", newUrl); - webResource = client.resource(newUrl); + webTarget = client.target(newUrl); + invocationBuilder = webTarget.request(tt).accept(tt); try { - if (p.httpMethod == HttpMethod.POST) - response = webResource.accept(tt).type(tt).post(ClientResponse.class, data); - else if (p.httpMethod == HttpMethod.PUT) - response = webResource.accept(tt).type(tt).put(ClientResponse.class, data); - else + if (p.httpMethod == HttpMethod.POST) { + response = invocationBuilder.post(Entity.entity(data, tt)); + } else if (p.httpMethod == HttpMethod.PUT) { + response = invocationBuilder.put(Entity.entity(data, tt)); + } else { throw new SvcLogicException("Http operation" + p.httpMethod + "not supported"); - } catch (UniformInterfaceException | ClientHandlerException e) { - throw new SvcLogicException("Exception while sending http request to client " + + } + } catch (ProcessingException e) { + throw new SvcLogicException(requestPostingException + e.getLocalizedMessage(), e); } r.code = response.getStatus(); etag = response.getEntityTag(); - if (etag != null) + if (etag != null) { r.message = etag.getValue(); - if (response.hasEntity() && r.code != 204) - r.body = response.getEntity(String.class); + } + if (response.hasEntity() && r.code != 204) { + r.body = response.readEntity(String.class); + } } } long t2 = System.currentTimeMillis(); - log.info("Response received. Time: {}", (t2 - t1)); - log.info("HTTP response code: {}", r.code); + log.info(responseReceivedMessage, t2 - t1); + log.info(responseHttpCodeMessage, r.code); log.info("HTTP response message: {}", r.message); logHeaders(r.headers); log.info("HTTP response: {}", r.body); @@ -658,74 +956,60 @@ public class RestapiCallNode implements SvcLogicJavaPlugin { return r; } - public void postMessageOnUeb(Map paramMap, SvcLogicContext ctx) throws SvcLogicException { - HttpResponse r; - try { - UebParam p = getUebParameters(paramMap); - - String pp = p.responsePrefix != null ? p.responsePrefix + '.' : ""; - - String req; - - if (p.templateFileName == null) { - log.info("No template file name specified. Using default UEB template: {}", defaultUebTemplateFileName); - p.templateFileName = defaultUebTemplateFileName; - } - - String reqTemplate = readFile(p.templateFileName); - reqTemplate = reqTemplate.replaceAll("rootVarName", p.rootVarName); - req = buildXmlJsonRequest(ctx, reqTemplate, Format.JSON); - - r = postOnUeb(req, p); - setResponseStatus(ctx, p.responsePrefix, r); - if (r.body != null) - ctx.setAttribute(pp + "httpResponse", r.body); - - } catch (SvcLogicException e) { - log.error("Error sending the request: {}", e.getMessage(), e); - - r = new HttpResponse(); - r.code = 500; - r.message = e.getMessage(); - String prefix = parseParam(paramMap, "responsePrefix", false, null); - setResponseStatus(ctx, prefix, r); - } - - if (r.code >= 300) - throw new SvcLogicException(String.valueOf(r.code) + ": " + r.message); - } - - private static class UebParam { - - public String topic; - public String templateFileName; - public String rootVarName; - public String responsePrefix; - public boolean skipSending; - } - private UebParam getUebParameters(Map paramMap) throws SvcLogicException { UebParam p = new UebParam(); p.topic = parseParam(paramMap, "topic", true, null); p.templateFileName = parseParam(paramMap, "templateFileName", false, null); p.rootVarName = parseParam(paramMap, "rootVarName", false, null); - p.responsePrefix = parseParam(paramMap, "responsePrefix", false, null); - String skipSendingStr = paramMap.get("skipSending"); + p.responsePrefix = parseParam(paramMap, responsePrefix, false, null); + String skipSendingStr = paramMap.get(skipSendingMessage); p.skipSending = "true".equalsIgnoreCase(skipSendingStr); return p; } + protected void logProperties(Map mm) { + List ll = new ArrayList<>(); + for (Object o : mm.keySet()) { + ll.add((String) o); + } + Collections.sort(ll); + + log.info("Properties:"); + for (String name : ll) { + log.info("--- {}:{}", name, String.valueOf(mm.get(name))); + } + } + + protected void logHeaders(MultivaluedMap mm) { + log.info("HTTP response headers:"); + + if (mm == null) { + return; + } + + List ll = new ArrayList<>(); + for (Object o : mm.keySet()) { + ll.add((String) o); + } + Collections.sort(ll); + + for (String name : ll) { + log.info("--- {}:{}", name, String.valueOf(mm.get(name))); + } + } + protected HttpResponse postOnUeb(String request, UebParam p) throws SvcLogicException { String[] urls = uebServers.split(" "); for (int i = 0; i < urls.length; i++) { - if (!urls[i].endsWith("/")) + if (!urls[i].endsWith("/")) { urls[i] += "/"; + } urls[i] += "events/" + p.topic; } - Client client = Client.create(); - client.setConnectTimeout(5000); - WebResource webResource = client.resource(urls[0]); + Client client = ClientBuilder.newBuilder().build(); + client.property(ClientProperties.CONNECT_TIMEOUT, 5000); + WebTarget webTarget = client.target(urls[0]); log.info("UEB URL: {}", urls[0]); log.info("Sending request:"); @@ -739,61 +1023,61 @@ public class RestapiCallNode implements SvcLogicJavaPlugin { String tt = "application/json"; String tt1 = tt + ";charset=UTF-8"; - ClientResponse response; + Response response; + Invocation.Builder invocationBuilder = webTarget.request(tt1).accept(tt); try { - response = webResource.accept(tt).type(tt1).post(ClientResponse.class, request); - } catch (UniformInterfaceException | ClientHandlerException e) { - throw new SvcLogicException("Exception while posting http request to client " + + response = invocationBuilder.post(Entity.entity(request, tt1)); + } catch (ProcessingException e) { + throw new SvcLogicException(requestPostingException + e.getLocalizedMessage(), e); } - r.code = response.getStatus(); - r.headers = response.getHeaders(); - if (response.hasEntity()) - r.body = response.getEntity(String.class); + r.headers = response.getStringHeaders(); + if (response.hasEntity()) { + r.body = response.readEntity(String.class); + } } long t2 = System.currentTimeMillis(); - log.info("Response received. Time: {}", (t2 - t1)); - log.info("HTTP response code: {}", r.code); + log.info(responseReceivedMessage, t2 - t1); + log.info(responseHttpCodeMessage, r.code); logHeaders(r.headers); log.info("HTTP response:\n {}", r.body); return r; } - protected void logProperties(Map mm) { - List ll = new ArrayList<>(); - for (Object o : mm.keySet()) - ll.add((String) o); - Collections.sort(ll); - - log.info("Properties:"); - for (String name : ll) - log.info("--- {}:{}", name, String.valueOf(mm.get(name))); + public void setUebServers(String uebServers) { + this.uebServers = uebServers; } - protected void logHeaders(MultivaluedMap mm) { - log.info("HTTP response headers:"); - - if (mm == null) - return; + public void setDefaultUebTemplateFileName(String defaultUebTemplateFileName) { + this.defaultUebTemplateFileName = defaultUebTemplateFileName; + } - List ll = new ArrayList<>(); - for (Object o : mm.keySet()) - ll.add((String) o); - Collections.sort(ll); + private static class FileParam { - for (String name : ll) - log.info("--- {}:{}", name, String.valueOf(mm.get(name))); + public String fileName; + public String url; + public String user; + public String password; + public HttpMethod httpMethod; + public String responsePrefix; + public boolean skipSending; + public String oAuthConsumerKey; + public String oAuthConsumerSecret; + public String oAuthSignatureMethod; + public String oAuthVersion; + public AuthType authtype; } - public void setUebServers(String uebServers) { - this.uebServers = uebServers; - } + private static class UebParam { - public void setDefaultUebTemplateFileName(String defaultUebTemplateFileName) { - this.defaultUebTemplateFileName = defaultUebTemplateFileName; + public String topic; + public String templateFileName; + public String rootVarName; + public String responsePrefix; + public boolean skipSending; } }