Only formatting changes for checkstyle fixes
[policy/engine.git] / ONAP-PAP-REST / src / main / java / org / onap / policy / pap / xacml / rest / elk / client / ElkConnectorImpl.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP-PAP-REST
4  * ================================================================================
5  * Copyright (C) 2017-2019 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
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
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=========================================================
19  */
20
21 package org.onap.policy.pap.xacml.rest.elk.client;
22
23 import io.searchbox.action.Action;
24 import io.searchbox.client.JestClient;
25 import io.searchbox.client.JestClientFactory;
26 import io.searchbox.client.JestResult;
27 import io.searchbox.client.config.HttpClientConfig;
28 import io.searchbox.core.Delete;
29 import io.searchbox.core.Index;
30 import io.searchbox.core.Search;
31 import io.searchbox.core.Search.Builder;
32 import io.searchbox.indices.IndicesExists;
33 import io.searchbox.indices.type.TypeExist;
34 import io.searchbox.params.Parameters;
35 import java.io.IOException;
36 import java.util.Map;
37 import java.util.Map.Entry;
38 import org.elasticsearch.index.query.QueryBuilders;
39 import org.elasticsearch.index.query.QueryStringQueryBuilder;
40 import org.elasticsearch.search.builder.SearchSourceBuilder;
41 import org.json.JSONObject;
42 import org.onap.policy.common.logging.flexlogger.FlexLogger;
43 import org.onap.policy.common.logging.flexlogger.Logger;
44 import org.onap.policy.rest.adapter.PolicyRestAdapter;
45 import org.onap.policy.xacml.api.XACMLErrorConstants;
46
47 public class ElkConnectorImpl implements ElkConnector {
48
49     private static final Logger LOGGER = FlexLogger.getLogger(ElkConnector.class);
50
51     protected final JestClientFactory jestFactory = new JestClientFactory();
52     protected final JestClient jestClient;
53     protected static int QUERY_MAXRECORDS = 1000;
54
55     public ElkConnectorImpl() {
56         if (LOGGER.isDebugEnabled()) {
57             LOGGER.debug("ENTER: -");
58         }
59         HttpClientConfig jestClientConfig =
60                 new HttpClientConfig.Builder(ELK_URL).multiThreaded(true).build();
61         jestFactory.setHttpClientConfig(jestClientConfig);
62         jestClient = jestFactory.getObject();
63     }
64
65     protected boolean isType(PolicyIndexType type) throws IOException {
66         if (LOGGER.isDebugEnabled()) {
67             LOGGER.debug("ENTER: -");
68         }
69
70         try {
71             Action<JestResult> typeQuery =
72                     new TypeExist.Builder(ELK_INDEX_POLICY).addType(type.toString()).build();
73             JestResult result = jestClient.execute(typeQuery);
74
75             if (LOGGER.isInfoEnabled()) {
76                 LOGGER.info("JSON:" + result.getJsonString());
77                 LOGGER.info("ERROR:" + result.getErrorMessage());
78                 LOGGER.info("PATH:" + result.getPathToResult());
79                 LOGGER.info(result.getJsonObject());
80             }
81             return result.isSucceeded();
82         } catch (IOException e) {
83             LOGGER.warn(
84                     "Error checking type existance of " + type.toString() + ": " + e.getMessage(),
85                     e);
86             throw e;
87         }
88     }
89
90     protected boolean isIndex() throws IOException {
91         try {
92             Action<JestResult> indexQuery = new IndicesExists.Builder(ELK_INDEX_POLICY).build();
93
94             JestResult result = jestClient.execute(indexQuery);
95             if (LOGGER.isInfoEnabled()) {
96                 LOGGER.info("JSON:" + result.getJsonString());
97                 LOGGER.info("ERROR:" + result.getErrorMessage());
98                 LOGGER.info("PATH:" + result.getPathToResult());
99                 LOGGER.info(result.getJsonObject());
100             }
101             return result.isSucceeded();
102         } catch (IOException e) {
103             LOGGER.warn(
104                     "Error checking index existance of " + ELK_INDEX_POLICY + ": " + e.getMessage(),
105                     e);
106             throw e;
107         }
108     }
109
110     private boolean isAlphaNumeric(String query) {
111         return query.matches("[a-zA-Z_0-9]+");
112     }
113
114     @Override
115     public JestResult search(PolicyIndexType type, String text)
116             throws IllegalStateException, IllegalArgumentException {
117         if (LOGGER.isTraceEnabled()) {
118             LOGGER.trace("ENTER: " + text);
119         }
120
121         if (text == null || text.isEmpty()) {
122             throw new IllegalArgumentException("No search string provided");
123         }
124
125         if (!isAlphaNumeric(text)) {
126             throw new IllegalArgumentException("Search must be alpha numeric");
127         }
128
129         QueryStringQueryBuilder mQ = QueryBuilders.queryStringQuery("*" + text + "*");
130         SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().query(mQ);
131
132         Builder searchBuilder =
133                 new Search.Builder(searchSourceBuilder.toString()).addIndex(ELK_INDEX_POLICY)
134                         .setParameter(Parameters.SIZE, ElkConnectorImpl.QUERY_MAXRECORDS);
135
136         if (type == null || type == PolicyIndexType.all) {
137             for (PolicyIndexType pT : PolicyIndexType.values()) {
138                 if (pT != PolicyIndexType.all) {
139                     searchBuilder.addType(pT.toString());
140                 }
141             }
142         } else {
143             searchBuilder.addType(type.toString());
144         }
145
146         Search search = searchBuilder.build();
147         JestResult result;
148         try {
149             result = jestClient.execute(search);
150         } catch (IOException ioe) {
151             LOGGER.warn(
152                     XACMLErrorConstants.ERROR_SYSTEM_ERROR + ":" + search + ": " + ioe.getMessage(),
153                     ioe);
154             throw new IllegalStateException(ioe);
155         }
156
157         if (result.isSucceeded()) {
158             if (LOGGER.isInfoEnabled()) {
159                 LOGGER.info("OK:" + result.getResponseCode() + ":" + search + ": "
160                         + result.getPathToResult() + ":" + System.lineSeparator()
161                         + result.getJsonString());
162             }
163         } else {
164             /* Unsuccessful search */
165             if (LOGGER.isWarnEnabled()) {
166                 LOGGER.warn(XACMLErrorConstants.ERROR_PROCESS_FLOW + ":" + result.getResponseCode()
167                         + ": " + search.getURI() + ":" + result.getPathToResult() + ":"
168                         + result.getJsonString() + ":" + result.getErrorMessage());
169             }
170
171             String errorMessage = result.getErrorMessage();
172             if (errorMessage != null && !errorMessage.isEmpty()) {
173                 String xMessage;
174                 if (errorMessage.contains("TokenMgrError")) {
175                     int indexError = errorMessage.lastIndexOf("TokenMgrError");
176                     xMessage = "Invalid Search Expression.  Details: "
177                             + errorMessage.substring(indexError);
178                 } else if (errorMessage.contains("QueryParsingException")) {
179                     int indexError = errorMessage.lastIndexOf("QueryParsingException");
180                     xMessage = "Invalid Search Expression.  Details: "
181                             + errorMessage.substring(indexError);
182                 } else if (errorMessage.contains("JsonParseException")) {
183                     int indexError = errorMessage.lastIndexOf("JsonParseException");
184                     xMessage = "Invalid Search Expression.  Details: "
185                             + errorMessage.substring(indexError);
186                 } else if (errorMessage.contains("Parse Failure")) {
187                     int indexError = errorMessage.lastIndexOf("Parse Failure");
188                     xMessage = "Invalid Search Expression.  Details: "
189                             + errorMessage.substring(indexError);
190                 } else if (errorMessage.contains("SearchParseException")) {
191                     int indexError = errorMessage.lastIndexOf("SearchParseException");
192                     xMessage = "Invalid Search Expression.  Details: "
193                             + errorMessage.substring(indexError);
194                 } else {
195                     xMessage = result.getErrorMessage();
196                 }
197                 throw new IllegalStateException(xMessage);
198             }
199         }
200
201         return result;
202     }
203
204
205     @Override
206     public JestResult search(PolicyIndexType type, String text, Map<String, String> filter_s)
207             throws IllegalStateException, IllegalArgumentException {
208         if (LOGGER.isTraceEnabled()) {
209             LOGGER.trace("ENTER: " + text);
210         }
211
212         if (filter_s == null || filter_s.size() == 0) {
213             return search(type, text);
214         }
215
216         if (!isAlphaNumeric(text)) {
217             throw new IllegalArgumentException("Search must be alpha numeric");
218         }
219
220         String matches_s = "";
221         matches_s = "{\n" + "    \"size\" : " + ElkConnectorImpl.QUERY_MAXRECORDS + ",\n"
222                 + "    \"query\": {\n" + "        \"bool\" : {\n" + "            \"must\" : [";
223
224         String match_params = "";
225         boolean first = true;
226         for (Entry<String, String> entry : filter_s.entrySet()) {
227             String key = entry.getKey();
228             String value = entry.getValue();
229             if (first) {
230                 match_params = "\"match\" : {\"" + key + "\" : \"" + value + "\" }},";
231                 first = false;
232             } else {
233                 match_params =
234                         match_params + "{\"match\" : { \"" + key + "\" : \"" + value + "\" } },";
235             }
236         }
237         if (match_params.endsWith(",")) {
238             match_params = match_params.substring(0, match_params.length() - 2);
239         }
240
241         matches_s = matches_s + "{\n" + match_params + "\n}";
242
243         boolean query = false;
244         String query_String = "";
245         if (text != null) {
246             query = true;
247             query_String = "{\n \"query_string\" : {\n \"query\" : \"*" + text + "*\"\n} \n}";
248         }
249
250         if (query) {
251             matches_s = matches_s + "," + query_String + "]\n}\n}\n}";
252         } else {
253             matches_s = matches_s + "]\n}\n}\n}";
254         }
255
256         Builder searchBuilder = new Search.Builder(matches_s).addIndex(ELK_INDEX_POLICY);
257
258         if (type == null || type == PolicyIndexType.all) {
259             for (PolicyIndexType pT : PolicyIndexType.values()) {
260                 if (pT != PolicyIndexType.all) {
261                     searchBuilder.addType(pT.toString());
262                 }
263             }
264         } else {
265             searchBuilder.addType(type.toString());
266         }
267
268         Search search = searchBuilder.build();
269
270         JestResult result;
271         try {
272             result = jestClient.execute(search);
273         } catch (IOException ioe) {
274             LOGGER.warn(
275                     XACMLErrorConstants.ERROR_SYSTEM_ERROR + ":" + search + ": " + ioe.getMessage(),
276                     ioe);
277             throw new IllegalStateException(ioe);
278         }
279
280         if (result.isSucceeded()) {
281             if (LOGGER.isInfoEnabled()) {
282                 LOGGER.info("OK:" + result.getResponseCode() + ":" + search + ": "
283                         + result.getPathToResult() + ":" + System.lineSeparator()
284                         + result.getJsonString());
285             }
286         } else {
287             /* Unsuccessful search */
288             if (LOGGER.isWarnEnabled()) {
289                 LOGGER.warn(XACMLErrorConstants.ERROR_PROCESS_FLOW + ":" + result.getResponseCode()
290                         + ": " + search.getURI() + ":" + result.getPathToResult() + ":"
291                         + result.getJsonString() + ":" + result.getErrorMessage());
292             }
293
294             String errorMessage = result.getErrorMessage();
295             if (errorMessage != null && !errorMessage.isEmpty()) {
296                 String xMessage = errorMessage;
297                 if (errorMessage.contains("TokenMgrError")) {
298                     int indexError = errorMessage.lastIndexOf("TokenMgrError");
299                     xMessage = "Invalid Search Expression.  Details: "
300                             + errorMessage.substring(indexError);
301                 } else if (errorMessage.contains("QueryParsingException")) {
302                     int indexError = errorMessage.lastIndexOf("QueryParsingException");
303                     xMessage = "Invalid Search Expression.  Details: "
304                             + errorMessage.substring(indexError);
305                 } else if (errorMessage.contains("JsonParseException")) {
306                     int indexError = errorMessage.lastIndexOf("JsonParseException");
307                     xMessage = "Invalid Search Expression.  Details: "
308                             + errorMessage.substring(indexError);
309                 } else if (errorMessage.contains("Parse Failure")) {
310                     int indexError = errorMessage.lastIndexOf("Parse Failure");
311                     xMessage = "Invalid Search Expression.  Details: "
312                             + errorMessage.substring(indexError);
313                 } else if (errorMessage.contains("SearchParseException")) {
314                     int indexError = errorMessage.lastIndexOf("SearchParseException");
315                     xMessage = "Invalid Search Expression.  Details: "
316                             + errorMessage.substring(indexError);
317                 } else {
318                     xMessage = result.getErrorMessage();
319                 }
320                 throw new IllegalStateException(xMessage);
321             }
322         }
323
324         return result;
325     }
326
327     public boolean put(PolicyRestAdapter policyData) throws IOException, IllegalStateException {
328         if (LOGGER.isTraceEnabled())
329             LOGGER.trace("ENTER");
330
331         PolicyIndexType indexType;
332         try {
333             String policyName = policyData.getNewFileName();
334             if (policyName.contains("Config_")) {
335                 policyName = policyName.replace(".Config_", ":Config_");
336             } else if (policyName.contains("Action_")) {
337                 policyName = policyName.replace(".Action_", ":Action_");
338             } else if (policyName.contains("Decision_")) {
339                 policyName = policyName.replace(".Decision_", ":Decision_");
340             }
341
342             String[] splitPolicyName = policyName.split(":");
343             indexType = ElkConnector.toPolicyIndexType(splitPolicyName[1]);
344         } catch (IllegalArgumentException e) {
345             LOGGER.error(e);
346             throw new IllegalStateException("ELK: Index: " + ELK_INDEX_POLICY + e.getMessage());
347         }
348         PolicyElasticData elasticData = new PolicyElasticData(policyData);
349         JSONObject jsonObj = new JSONObject(elasticData);
350         Index elkPut = new Index.Builder(jsonObj.toString()).index(ELK_INDEX_POLICY)
351                 .type(indexType.name()).id(elasticData.getPolicyName()).refresh(true).build();
352
353         JestResult result = jestClient.execute(elkPut);
354
355         if (result.isSucceeded()) {
356             if (LOGGER.isInfoEnabled())
357                 LOGGER.info("ElkConnector: OK: PUT operation of " + "->" + ": " + "success="
358                         + result.isSucceeded() + "[" + result.getResponseCode() + ":"
359                         + result.getPathToResult() + "]" + System.lineSeparator()
360                         + result.getJsonString());
361         } else {
362             if (LOGGER.isWarnEnabled())
363                 LOGGER.warn("ElkConnector: FAILURE: PUT operation of " + "->" + ": " + "success="
364                         + result.isSucceeded() + "[" + result.getResponseCode() + ":"
365                         + result.getPathToResult() + "]" + System.lineSeparator()
366                         + result.getJsonString());
367
368         }
369
370         return result.isSucceeded();
371     }
372
373     @Override
374     public boolean delete(PolicyRestAdapter policyData) throws IllegalStateException {
375         PolicyIndexType indexType = null;
376         JestResult result;
377         try {
378             String policyName = policyData.getNewFileName();
379             if (policyName.contains("Config_")) {
380                 policyName = policyName.replace(".Config_", ":Config_");
381             } else if (policyName.contains("Action_")) {
382                 policyName = policyName.replace(".Action_", ":Action_");
383             } else if (policyName.contains("Decision_")) {
384                 policyName = policyName.replace(".Decision_", ":Decision_");
385             }
386
387             String[] splitPolicyName = policyName.split(":");
388             indexType = ElkConnector.toPolicyIndexType(splitPolicyName[1]);
389             if (!isType(indexType)) {
390                 throw new IllegalStateException("ELK: Index: " + ELK_INDEX_POLICY + " Type: "
391                         + indexType + " is not configured");
392             }
393             PolicyElasticData elasticData = new PolicyElasticData(policyData);
394             Delete deleteRequest = new Delete.Builder(elasticData.getPolicyName())
395                     .index(ELK_INDEX_POLICY).type(indexType.name()).build();
396             result = jestClient.execute(deleteRequest);
397         } catch (IllegalArgumentException | IOException e) {
398             LOGGER.warn(XACMLErrorConstants.ERROR_SYSTEM_ERROR + ": delete:" + indexType + ": null"
399                     + ":" + policyData.getNewFileName() + ": " + e.getMessage(), e);
400             throw new IllegalStateException(e);
401         }
402
403         if (result.isSucceeded()) {
404             if (LOGGER.isInfoEnabled())
405                 LOGGER.info("OK: DELETE operation of " + indexType + ":"
406                         + policyData.getNewFileName() + ": " + "success=" + result.isSucceeded()
407                         + "[" + result.getResponseCode() + ":" + result.getPathToResult() + "]"
408                         + System.lineSeparator() + result.getJsonString());
409         } else {
410             if (LOGGER.isWarnEnabled())
411                 LOGGER.warn("FAILURE: DELETE operation of " + indexType + ":"
412                         + policyData.getNewFileName() + ": " + "success=" + result.isSucceeded()
413                         + "[" + result.getResponseCode() + ":" + result.getPathToResult() + "]"
414                         + System.lineSeparator() + result.getJsonString());
415         }
416
417         return result.isSucceeded();
418     }
419
420     @Override
421     public boolean update(PolicyRestAdapter policyData) throws IllegalStateException {
422         if (LOGGER.isDebugEnabled()) {
423             LOGGER.debug("ENTER");
424         }
425         try {
426             boolean success = put(policyData);
427             return success;
428         } catch (Exception e) {
429             LOGGER.warn(XACMLErrorConstants.ERROR_UNKNOWN + ":" + "cannot test and update", e);
430             throw new IllegalStateException(e);
431         }
432     }
433 }