f19de3d04a310b8ac263a2dba2dbee80ed20fbd0
[sdc.git] /
1 /*
2  * Copyright © 2018 European Support Limited
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package org.openecomp.sdcrests.item.rest.services;
18
19 import java.io.FileInputStream;
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.io.UnsupportedEncodingException;
23 import java.util.Collection;
24 import java.util.LinkedHashMap;
25 import java.util.Map;
26 import java.util.concurrent.Callable;
27 import java.util.concurrent.Executors;
28 import java.util.concurrent.ScheduledExecutorService;
29 import java.util.concurrent.TimeUnit;
30 import java.util.function.Function;
31 import javax.ws.rs.core.HttpHeaders;
32 import javax.ws.rs.core.MediaType;
33 import org.apache.http.HttpEntity;
34 import org.apache.http.HttpResponse;
35 import org.apache.http.client.methods.HttpPost;
36 import org.apache.http.entity.StringEntity;
37 import org.apache.http.impl.client.CloseableHttpClient;
38 import org.apache.http.impl.client.HttpClients;
39 import org.onap.sdc.tosca.services.YamlUtil;
40 import org.openecomp.core.utilities.json.JsonUtil;
41 import org.openecomp.sdc.common.session.SessionContextProviderFactory;
42 import org.openecomp.sdc.logging.api.Logger;
43 import org.openecomp.sdc.logging.api.LoggerFactory;
44 import org.openecomp.sdc.logging.api.LoggingContext;
45 import org.openecomp.sdcrests.item.types.ItemAction;
46
47 public class CatalogNotifier {
48
49     private static final Logger LOGGER = LoggerFactory.getLogger(CatalogNotifier.class);
50
51     private static final String USER_ID_HEADER_PARAM = "USER_ID";
52     private static final String CONFIG_FILE = "configuration.yaml";
53     private static final String PROTOCOL_KEY = "beProtocol";
54     private static final String HOST_KEY = "beFqdn";
55     private static final String PORT_KEY = "beHttpPort";
56     private static final String URL_KEY = "onboardCatalogNotificationUrl";
57     private static final String URL_DEFAULT_FORMAT = "%s://%s:%s/sdc2/rest/v1/catalog/notif/vsp/";
58
59     private static String configurationYamlFile = System.getProperty(CONFIG_FILE);
60     private static String notifyCatalogUrl;
61
62     private static ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
63     private static boolean executeNotificationFlag = true;
64
65
66     static {
67         Function<InputStream, Map<String, LinkedHashMap<String, Object>>> reader = is -> {
68             YamlUtil yamlUtil = new YamlUtil();
69             return yamlUtil.yamlToMap(is);
70         };
71
72         Map<String, LinkedHashMap<String, Object>> configurationMap;
73
74         try {
75             configurationMap = readFromFile(configurationYamlFile, reader);
76             Object protocol = configurationMap.get(PROTOCOL_KEY);
77             Object host = configurationMap.get(HOST_KEY);
78             Object port = configurationMap.get(PORT_KEY);
79
80             if (protocol == null || host == null || port == null) {
81                 LOGGER.error("Could not read configuration file configuration.yaml");
82                 executeNotificationFlag = false;
83             }
84
85             if (configurationMap.get(URL_KEY) != null) {
86                 String urlFormat = String.valueOf(configurationMap.get(URL_KEY));
87                 notifyCatalogUrl =
88                         String.format(urlFormat, String.valueOf(protocol), String.valueOf(host), String.valueOf(port));
89
90             } else {
91                 notifyCatalogUrl = String.format(URL_DEFAULT_FORMAT, String.valueOf(protocol), String.valueOf(host),
92                         String.valueOf(port));
93             }
94
95         } catch (Exception e) {
96            LOGGER.error("Could not read configuration file configuration.yaml");
97            executeNotificationFlag = false;
98         }
99     }
100
101
102     public void execute(Collection<String> itemIds, ItemAction action, int numOfRetries) {
103
104         if (executeNotificationFlag) {
105
106             String userId = SessionContextProviderFactory.getInstance().createInterface().get().getUser().getUserId();
107
108             Callable callable = createCallable(JsonUtil.object2Json(itemIds), action, numOfRetries, userId);
109
110             executor.submit(callable);
111         }
112
113     }
114
115     private Callable createCallable(String itemIds, ItemAction action, int numOfRetries, String userId) {
116         Callable callable = () -> handleHttpRequest(getUrl(action), itemIds, action, userId, numOfRetries);
117         LoggingContext.copyToCallable(callable);
118         return callable;
119     }
120
121     private Void handleHttpRequest(String url, String itemIds, ItemAction action, String userId,
122             int numOfRetries) {
123
124         try (CloseableHttpClient httpclient =  HttpClients.createDefault()) {
125             HttpPost request = createPostRequest(url, itemIds, userId);
126             HttpResponse response = httpclient.execute(request);
127             LOGGER.error(
128                     String.format("Catalog notification on vspId - %s action  - %s. Response: %s", itemIds,
129                             action.name(), response.getStatusLine()));
130
131             if (numOfRetries > 1 && response.getStatusLine().getStatusCode() == 500) {
132                 Callable callable =
133                         createCallable(getFailedIds(itemIds, response.getEntity()), action, --numOfRetries, userId);
134                 executor.schedule(callable, 5 , TimeUnit.SECONDS);
135             }
136
137         } catch (Exception e) {
138             LOGGER.error(String.format("Catalog notification on vspId - %s action  - %s FAILED. Error: %S",
139                     itemIds.toString(), action.name(), e.getMessage()));
140         }
141         return null;
142     }
143
144     private String getFailedIds(String itemIds, HttpEntity responseBody) {
145         try {
146             Map jsonBody = JsonUtil.json2Object(responseBody.getContent(), Map.class);
147             return jsonBody.get("failedIds").toString();
148         } catch (Exception e) {
149             LOGGER.error("Catalog Notification RETRY - no failed IDs in response");
150         }
151         return JsonUtil.object2Json(itemIds);
152     }
153
154     private HttpPost createPostRequest(String postUrl, String itemIds, String userId)
155             throws UnsupportedEncodingException {
156
157         HttpPost request = new HttpPost(postUrl);
158
159         request.addHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON);
160         request.addHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON);
161         request.addHeader(USER_ID_HEADER_PARAM, userId);
162
163         HttpEntity entity = new StringEntity(itemIds);
164         request.setEntity(entity);
165
166         return request;
167     }
168
169     private String getUrl(ItemAction action) {
170         String actionStr = "";
171         if (action == ItemAction.ARCHIVE) {
172             actionStr = "archived";
173         } else if (action == ItemAction.RESTORE) {
174             actionStr = "restored";
175         }
176         LOGGER.error("Catalog notification on URL - " + notifyCatalogUrl + actionStr);
177         return notifyCatalogUrl + actionStr;
178     }
179
180     private static <T> T readFromFile(String file, Function<InputStream, T> reader) throws IOException {
181         try (InputStream is = new FileInputStream(file)) {
182             return reader.apply(is);
183         }
184     }
185 }