re base code
[sdc.git] / openecomp-be / api / openecomp-sdc-rest-webapp / item-rest / item-rest-services / src / main / java / org / openecomp / sdcrests / item / rest / services / CatalogNotifier.java
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 org.apache.http.HttpEntity;
20 import org.apache.http.HttpResponse;
21 import org.apache.http.client.methods.HttpPost;
22 import org.apache.http.entity.StringEntity;
23 import org.apache.http.impl.client.CloseableHttpClient;
24 import org.apache.http.impl.client.HttpClients;
25 import org.onap.sdc.tosca.services.YamlUtil;
26 import org.openecomp.core.utilities.json.JsonUtil;
27 import org.openecomp.sdc.common.session.SessionContextProviderFactory;
28 import org.openecomp.sdc.logging.api.Logger;
29 import org.openecomp.sdc.logging.api.LoggerFactory;
30 import org.openecomp.sdc.logging.api.LoggingContext;
31 import org.openecomp.sdcrests.item.types.ItemAction;
32
33 import javax.ws.rs.core.HttpHeaders;
34 import javax.ws.rs.core.MediaType;
35 import javax.ws.rs.core.Response;
36 import java.io.FileInputStream;
37 import java.io.IOException;
38 import java.io.InputStream;
39 import java.io.UnsupportedEncodingException;
40 import java.util.Collection;
41 import java.util.LinkedHashMap;
42 import java.util.Map;
43 import java.util.concurrent.Callable;
44 import java.util.concurrent.Executors;
45 import java.util.concurrent.ScheduledExecutorService;
46 import java.util.concurrent.TimeUnit;
47 import java.util.function.Function;
48
49  class CatalogNotifier {
50
51     private static final Logger LOGGER = LoggerFactory.getLogger(CatalogNotifier.class);
52
53     private static final String USER_ID_HEADER_PARAM = "USER_ID";
54     private static final String CONFIG_FILE = "configuration.yaml";
55     private static final String PROTOCOL_KEY = "beProtocol";
56     private static final String HTTP_PROTOCOL = "http|HTTP";
57     private static final String HTTPS_PROTOCOL = "https|HTTPS";
58     private static final String HOST_KEY = "beFqdn";
59     private static final String HTTP_PORT_KEY = "beHttpPort";
60     private static final String HTTPS_PORT_KEY = "beSslPort";
61     private static final String URL_KEY = "onboardCatalogNotificationUrl";
62     private static final String URL_DEFAULT_FORMAT = "%s://%s:%s/sdc2/rest/v1/catalog/notif/vsp/";
63
64     private static String configurationYamlFile = System.getProperty(CONFIG_FILE);
65     private static String notifyCatalogUrl;
66
67     private static ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
68
69
70     static {
71         Function<InputStream, Map<String, LinkedHashMap<String, Object>>> reader = is -> {
72             YamlUtil yamlUtil = new YamlUtil();
73             return yamlUtil.yamlToMap(is);
74         };
75
76         Map<String, LinkedHashMap<String, Object>> configurationMap;
77
78         try {
79             configurationMap = readFromFile(configurationYamlFile, reader);
80             Object protocol = configurationMap.get(PROTOCOL_KEY);
81             Object host = configurationMap.get(HOST_KEY);
82
83             if (protocol == null || host == null) {
84                 throw new ExceptionInInitializerError("Could not read configuration file configuration.yaml.");
85             }
86
87             Object port = null;
88             if (String.valueOf(protocol).matches(HTTP_PROTOCOL)) {
89                 port = configurationMap.get(HTTP_PORT_KEY);
90             }
91             if (String.valueOf(protocol).matches(HTTPS_PROTOCOL)) {
92                 port = configurationMap.get(HTTPS_PORT_KEY);
93             }
94
95             if (configurationMap.get(URL_KEY) != null) {
96                 String urlFormat = String.valueOf(configurationMap.get(URL_KEY));
97                 notifyCatalogUrl =
98                         String.format(urlFormat, String.valueOf(protocol), String.valueOf(host), String.valueOf(port));
99
100             } else {
101                 notifyCatalogUrl = String.format(URL_DEFAULT_FORMAT, String.valueOf(protocol), String.valueOf(host),
102                         String.valueOf(port));
103             }
104
105         } catch (Exception e) {
106             throw new ExceptionInInitializerError(
107                     "Could not read configuration file configuration.yaml. Error: " + e.getMessage());
108
109         }
110     }
111
112
113     public void execute(Collection<String> itemIds, ItemAction action, int numOfRetries) {
114
115         String userId = SessionContextProviderFactory.getInstance().createInterface().get().getUser().getUserId();
116
117         Callable callable = createCallable(JsonUtil.object2Json(itemIds), action, numOfRetries, userId);
118
119         executor.submit(callable);
120
121     }
122
123     private Callable createCallable(String itemIds, ItemAction action, int numOfRetries, String userId) {
124         Callable callable = () -> handleHttpRequest(getUrl(action), itemIds, action, userId, numOfRetries);
125         LoggingContext.copyToCallable(callable);
126         return callable;
127     }
128
129     private Void handleHttpRequest(String url, String itemIds, ItemAction action, String userId,
130             int numOfRetries) {
131
132         try (CloseableHttpClient httpclient = HttpClients.createDefault()) {
133             HttpPost request = createPostRequest(url, itemIds, userId);
134             HttpResponse response = httpclient.execute(request);
135             LOGGER.debug(String.format("Catalog notification on vspId - %s action  - %s. Response: %s", itemIds,
136                     action.name(), response.getStatusLine()));
137
138             if (numOfRetries > 1 && response.getStatusLine().getStatusCode() == Response.Status.INTERNAL_SERVER_ERROR
139                                                                                         .getStatusCode()) {
140                 Callable callable =
141                         createCallable(getFailedIds(itemIds, response.getEntity()), action, --numOfRetries, userId);
142                 executor.schedule(callable, 5, TimeUnit.SECONDS);
143             }
144
145         } catch (Exception e) {
146             LOGGER.error(String.format("Catalog notification on vspId - %s action  - %s FAILED. Error: %S", itemIds,
147                     action.name(), e.getMessage()));
148         }
149         return null;
150     }
151
152     private String getFailedIds(String itemIds, HttpEntity responseBody) {
153         try {
154             Map jsonBody = JsonUtil.json2Object(responseBody.getContent(), Map.class);
155             return jsonBody.get("failedIds").toString();
156         } catch (Exception e) {
157             LOGGER.error("Catalog Notification RETRY - no failed IDs in response");
158         }
159         return JsonUtil.object2Json(itemIds);
160     }
161
162     private HttpPost createPostRequest(String postUrl, String itemIds, String userId)
163             throws UnsupportedEncodingException {
164
165         HttpPost request = new HttpPost(postUrl);
166
167         request.addHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON);
168         request.addHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON);
169         request.addHeader(USER_ID_HEADER_PARAM, userId);
170
171         HttpEntity entity = new StringEntity(itemIds);
172         request.setEntity(entity);
173
174         return request;
175     }
176
177     private String getUrl(ItemAction action) {
178         String actionStr = "";
179         if (action == ItemAction.ARCHIVE) {
180             actionStr = "archived";
181         } else if (action == ItemAction.RESTORE) {
182             actionStr = "restored";
183         }
184         LOGGER.debug("Catalog notification URL - " + notifyCatalogUrl + actionStr);
185         return notifyCatalogUrl + actionStr;
186     }
187
188     private static <T> T readFromFile(String file, Function<InputStream, T> reader) throws IOException {
189         try (InputStream is = new FileInputStream(file)) {
190             return reader.apply(is);
191         }
192     }
193 }