2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.openecomp.mso.adapters.vnf;
24 import java.io.IOException;
26 import java.util.TreeSet;
28 import javax.xml.bind.DatatypeConverter;
30 import org.apache.http.HttpEntity;
31 import org.apache.http.client.config.RequestConfig;
32 import org.apache.http.client.methods.CloseableHttpResponse;
33 import org.apache.http.client.methods.HttpPost;
34 import org.apache.http.entity.ContentType;
35 import org.apache.http.entity.StringEntity;
36 import org.apache.http.impl.client.CloseableHttpClient;
37 import org.apache.http.impl.client.HttpClients;
38 import org.apache.http.util.EntityUtils;
40 import org.openecomp.mso.logger.MessageEnum;
41 import org.openecomp.mso.logger.MsoLogger;
42 import org.openecomp.mso.properties.MsoJavaProperties;
43 import org.openecomp.mso.properties.MsoPropertiesException;
44 import org.openecomp.mso.properties.MsoPropertiesFactory;
47 * This is the class that is used to POST replies from the MSO adapters to the BPEL engine.
48 * It can be configured via property file, or modified using the member methods.
49 * The properties to use are:
50 * org.openecomp.mso.adapters.vnf.bpelauth encrypted authorization string to send to BEPL engine
51 * org.openecomp.mso.adapters.vnf.sockettimeout socket timeout value
52 * org.openecomp.mso.adapters.vnf.connecttimeout connect timeout value
53 * org.openecomp.mso.adapters.vnf.retrycount number of times to retry failed connections
54 * org.openecomp.mso.adapters.vnf.retryinterval interval (in seconds) between retries
55 * org.openecomp.mso.adapters.vnf.retrylist list of response codes that will trigger a retry (the special code
56 * 900 means "connection was not established")
58 public class BpelRestClient {
59 public static final String MSO_PROP_VNF_ADAPTER = "MSO_PROP_VNF_ADAPTER";
60 private static final String PROPERTY_DOMAIN = "org.openecomp.mso.adapters.vnf";
61 private static final String BPEL_AUTH_PROPERTY = PROPERTY_DOMAIN+".bpelauth";
62 private static final String SOCKET_TIMEOUT_PROPERTY = PROPERTY_DOMAIN+".sockettimeout";
63 private static final String CONN_TIMEOUT_PROPERTY = PROPERTY_DOMAIN+".connecttimeout";
64 private static final String RETRY_COUNT_PROPERTY = PROPERTY_DOMAIN+".retrycount";
65 private static final String RETRY_INTERVAL_PROPERTY = PROPERTY_DOMAIN+".retryinterval";
66 private static final String RETRY_LIST_PROPERTY = PROPERTY_DOMAIN+".retrylist";
67 private static final String ENCRYPTION_KEY = "aa3871669d893c7fb8abbcda31b88b4f";
68 private static final MsoLogger LOGGER = MsoLogger.getMsoLogger (MsoLogger.Catalog.RA);
70 /** Default socket timeout (in seconds) */
71 public static final int DEFAULT_SOCKET_TIMEOUT = 5;
72 /** Default connect timeout (in seconds) */
73 public static final int DEFAULT_CONNECT_TIMEOUT = 5;
74 /** By default, retry up to five times */
75 public static final int DEFAULT_RETRY_COUNT = 5;
76 /** Default interval to wait between retries (in seconds), negative means use backoff algorithm */
77 public static final int DEFAULT_RETRY_INTERVAL = -15;
78 /** Default list of response codes to trigger a retry */
79 public static final String DEFAULT_RETRY_LIST = "408,429,500,502,503,504,900"; // 900 is "connection failed"
80 /** Default credentials */
81 public static final String DEFAULT_CREDENTIALS = "";
83 // Properties of the BPEL client -- all are configurable
84 private int socketTimeout;
85 private int connectTimeout;
86 private int retryCount;
87 private int retryInterval;
88 private Set<Integer> retryList;
89 private String credentials;
91 // last response from BPEL engine
92 private int lastResponseCode;
93 private String lastResponse;
96 * Create a client to send results to the BPEL engine, using configuration from the
97 * MSO_PROP_VNF_ADAPTER properties.
99 public BpelRestClient() {
100 socketTimeout = DEFAULT_SOCKET_TIMEOUT;
101 connectTimeout = DEFAULT_CONNECT_TIMEOUT;
102 retryCount = DEFAULT_RETRY_COUNT;
103 retryInterval = DEFAULT_RETRY_INTERVAL;
104 setRetryList(DEFAULT_RETRY_LIST);
105 credentials = DEFAULT_CREDENTIALS;
106 lastResponseCode = 0;
110 MsoPropertiesFactory msoPropertiesFactory = new MsoPropertiesFactory();
111 MsoJavaProperties jp = msoPropertiesFactory.getMsoJavaProperties (MSO_PROP_VNF_ADAPTER);
112 socketTimeout = jp.getIntProperty(SOCKET_TIMEOUT_PROPERTY, DEFAULT_SOCKET_TIMEOUT);
113 connectTimeout = jp.getIntProperty(CONN_TIMEOUT_PROPERTY, DEFAULT_CONNECT_TIMEOUT);
114 retryCount = jp.getIntProperty(RETRY_COUNT_PROPERTY, DEFAULT_RETRY_COUNT);
115 retryInterval = jp.getIntProperty(RETRY_INTERVAL_PROPERTY, DEFAULT_RETRY_INTERVAL);
116 setRetryList(jp.getProperty(RETRY_LIST_PROPERTY, DEFAULT_RETRY_LIST));
117 credentials = jp.getEncryptedProperty(BPEL_AUTH_PROPERTY, DEFAULT_CREDENTIALS, ENCRYPTION_KEY);
118 } catch (MsoPropertiesException e) {
119 String error = "Unable to get properties:" + MSO_PROP_VNF_ADAPTER;
120 LOGGER.error (MessageEnum.RA_CONFIG_EXC, error, "Camunda", "", MsoLogger.ErrorCode.AvailabilityError, "MsoPropertiesException - Unable to get properties", e);
124 public int getSocketTimeout() {
125 return socketTimeout;
128 public void setSocketTimeout(int socketTimeout) {
129 this.socketTimeout = socketTimeout;
132 public int getConnectTimeout() {
133 return connectTimeout;
136 public void setConnectTimeout(int connectTimeout) {
137 this.connectTimeout = connectTimeout;
140 public int getRetryCount() {
144 public void setRetryCount(int retryCount) {
145 int newRetryCount = retryCount;
146 if (newRetryCount < 0)
147 newRetryCount = DEFAULT_RETRY_COUNT;
148 this.retryCount = newRetryCount;
151 public int getRetryInterval() {
152 return retryInterval;
155 public void setRetryInterval(int retryInterval) {
156 this.retryInterval = retryInterval;
159 public String getCredentials() {
163 public void setCredentials(String credentials) {
164 this.credentials = credentials;
167 public String getRetryList() {
168 if (retryList.isEmpty())
170 String t = retryList.toString();
171 return t.substring(1, t.length()-1);
174 public void setRetryList(String retryList) {
175 Set<Integer> s = new TreeSet<>();
176 for (String t : retryList.split("[, ]")) {
178 s.add(Integer.parseInt(t));
179 } catch (NumberFormatException x) {
186 public int getLastResponseCode() {
187 return lastResponseCode;
190 public String getLastResponse() {
195 * Post a response to the URL of the BPEL engine. As long as the response code is one of those in
196 * the retryList, the post will be retried up to "retrycount" times with an interval (in seconds)
197 * of "retryInterval". If retryInterval is negative, then each successive retry interval will be
198 * double the previous one.
199 * @param toBpelStr the content (XML or JSON) to post
200 * @param bpelUrl the URL to post to
201 * @param isxml true if the content is XML, otherwise assumed to be JSON
202 * @return true if the post succeeded, false if all retries failed
204 public boolean bpelPost(final String toBpelStr, final String bpelUrl, final boolean isxml) {
205 debug("Sending response to BPEL: " + toBpelStr);
206 int totalretries = 0;
207 int retryint = retryInterval;
209 sendOne(toBpelStr, bpelUrl, isxml);
210 // Note: really should handle response code 415 by switching between content types if needed
211 if (!retryList.contains(lastResponseCode)) {
212 debug("Got response code: " + lastResponseCode + ": returning.");
215 if (totalretries >= retryCount) {
216 debug("Retried " + totalretries + " times, giving up.");
217 LOGGER.error(MessageEnum.RA_SEND_VNF_NOTIF_ERR, "Could not deliver response to BPEL after "+totalretries+" tries: "+toBpelStr, "Camunda", "", MsoLogger.ErrorCode.BusinessProcesssError, "Could not deliver response to BPEL");
221 int sleepinterval = retryint;
223 // if retry interval is negative double the retry on each pass
224 sleepinterval = -retryint;
227 debug("Sleeping for " + sleepinterval + " seconds.");
229 Thread.sleep(sleepinterval * 1000L);
230 } catch (InterruptedException e) {
235 private void debug(String m) {
238 private void sendOne(final String toBpelStr, final String bpelUrl, final boolean isxml) {
239 LOGGER.debug("Sending to BPEL server: "+bpelUrl);
240 LOGGER.debug("Content is: "+toBpelStr);
243 HttpPost post = new HttpPost(bpelUrl);
244 if (credentials != null && !credentials.isEmpty())
245 post.addHeader("Authorization", "Basic " + DatatypeConverter.printBase64Binary(credentials.getBytes()));
248 ContentType ctype = isxml ? ContentType.APPLICATION_XML : ContentType.APPLICATION_JSON;
249 post.setEntity(new StringEntity(toBpelStr, ctype));
252 RequestConfig requestConfig = RequestConfig
254 .setSocketTimeout(socketTimeout * 1000)
255 .setConnectTimeout(connectTimeout * 1000)
257 post.setConfig(requestConfig);
260 //Execute & GetResponse
261 try(CloseableHttpClient client = HttpClients.createDefault()) {
262 CloseableHttpResponse response = client.execute(post);
263 if (response != null) {
264 lastResponseCode = response.getStatusLine().getStatusCode();
265 HttpEntity entity = response.getEntity();
266 lastResponse = (entity != null) ? EntityUtils.toString(entity) : "";
268 lastResponseCode = 900;
271 } catch (Exception e) {
272 String error = "Error sending Bpel notification:" + toBpelStr;
273 LOGGER.error (MessageEnum.RA_SEND_VNF_NOTIF_ERR, error, "Camunda", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - Error sending Bpel notification", e);
274 lastResponseCode = 900;
277 LOGGER.debug("Response code from BPEL server: "+lastResponseCode);
278 LOGGER.debug("Response body is: "+lastResponse);