Merge "Resolved the Sonar issues"
[policy/engine.git] / POLICY-SDK-APP / src / main / java / org / onap / policy / controller / ExportAndImportDecisionBlackListEntries.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP Policy Engine
4  * ================================================================================
5  * Copyright (C) 2018 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.controller;
22
23 import com.google.gson.Gson;
24
25 import java.io.File;
26 import java.io.FileOutputStream;
27 import java.io.IOException;
28 import java.io.InputStream;
29 import java.io.OutputStream;
30 import java.io.PrintWriter;
31 import java.nio.file.Files;
32 import java.text.SimpleDateFormat;
33 import java.util.ArrayList;
34 import java.util.Date;
35 import java.util.HashMap;
36 import java.util.HashSet;
37 import java.util.Iterator;
38 import java.util.List;
39 import java.util.Map;
40 import java.util.Set;
41 import java.util.stream.Collectors;
42 import javax.servlet.http.HttpServletRequest;
43 import javax.servlet.http.HttpServletResponse;
44 import org.apache.commons.compress.utils.IOUtils;
45 import org.apache.commons.fileupload.FileItem;
46 import org.apache.commons.fileupload.FileUploadException;
47 import org.apache.commons.fileupload.disk.DiskFileItemFactory;
48 import org.apache.commons.fileupload.servlet.ServletFileUpload;
49 import org.apache.poi.hssf.usermodel.HSSFRow;
50 import org.apache.poi.hssf.usermodel.HSSFSheet;
51 import org.apache.poi.hssf.usermodel.HSSFWorkbook;
52 import org.apache.poi.ss.usermodel.Cell;
53 import org.apache.poi.ss.usermodel.Row;
54 import org.apache.poi.ss.usermodel.Sheet;
55 import org.apache.poi.ss.usermodel.Workbook;
56 import org.apache.poi.ss.usermodel.WorkbookFactory;
57 import org.json.JSONObject;
58 import org.onap.policy.common.logging.flexlogger.FlexLogger;
59 import org.onap.policy.common.logging.flexlogger.Logger;
60 import org.onap.policy.rest.adapter.PolicyRestAdapter;
61 import org.onap.policy.rest.adapter.ReturnBlackList;
62 import org.onap.policy.xacml.api.XACMLErrorConstants;
63 import org.onap.portalsdk.core.controller.RestrictedBaseController;
64 import org.onap.portalsdk.core.web.support.JsonMessage;
65 import org.springframework.stereotype.Controller;
66 import org.springframework.web.bind.annotation.RequestMapping;
67 import org.springframework.web.bind.annotation.RequestMethod;
68
69
70 /**
71  * This class is used to import and export the black list entries which were used in the Decision Blacklist Guard YAML
72  * Policy.
73  *
74  */
75 @Controller
76 @RequestMapping("/")
77 public class ExportAndImportDecisionBlackListEntries extends RestrictedBaseController {
78
79     private static final Logger policyLogger = FlexLogger.getLogger(ExportAndImportDecisionBlackListEntries.class);
80     private static final String BLACKLISTENTRIESDATA = "blackListEntries";
81     private static final String ACTION = "Action";
82     private static final String BLACKLISTENTRY = "BlackListEntry";
83
84     /**
85      * This method is used to Export the Black List entries data from Decision BlackList Guard YAML Policy. So, user can
86      * update the file on adding or removing the entries, for updating the policies or using in other Environments.
87      * 
88      * @param request the request contains the policy data. So, based on that we can populate and read and write the
89      *        entries.
90      * @param response after reading and writing the blacklist list entries to file, the file is copied to tmp directory
91      *        and making available to user to download from GUI.
92      * @throws IOException exception throws if anything goes wrong in the process.
93      */
94     @RequestMapping(value = {"/policycreation/exportDecisionBlackListEntries"}, method = {RequestMethod.POST})
95     public void exportBlackList(HttpServletRequest request, HttpServletResponse response) throws IOException {
96         try (HSSFWorkbook workBook = new HSSFWorkbook()) {
97             String requestData = request.getReader().lines().collect(Collectors.joining());
98             JSONObject root = new JSONObject(requestData);
99             PolicyRestAdapter adapter = new Gson().fromJson(root.get("policyData").toString(), PolicyRestAdapter.class);
100             DecisionPolicyController controller = new DecisionPolicyController();
101             controller.prePopulateDecisionPolicyData(adapter, null);
102             List<String> blackLists = adapter.getYamlparams().getBlackList();
103             HSSFSheet sheet = workBook.createSheet("BlackList");
104             HSSFRow headingRow = sheet.createRow(0);
105             headingRow.createCell(0).setCellValue(ACTION);
106             headingRow.createCell(1).setCellValue(BLACKLISTENTRY);
107
108             short rowNo = 1;
109             for (Object object : blackLists) {
110                 HSSFRow row = sheet.createRow(rowNo);
111                 row.createCell(0).setCellValue(1);
112                 row.createCell(1).setCellValue(object.toString());
113                 rowNo++;
114             }
115
116             String tmpFile = System.getProperty("catalina.base") + File.separator + "webapps" + File.separator + "temp";
117
118             /*
119              * Export FileName is the combination of BlacList+Scope+PolicyName+Version+PolicyCreatedDate.
120              * 
121              */
122
123             SimpleDateFormat parseFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
124             Date date = parseFormat.parse(root.get("date").toString().replaceAll("\"", ""));
125             SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss");
126             String formatedDate = dateFormat.format(date);
127
128             String fileName = "BlackList_Scope_" + adapter.getDomainDir() + "_Name_" + adapter.getPolicyName()
129             + "_Version_" + root.get("version").toString() + "_Date_" + formatedDate + ".xls";
130
131             String deleteCheckPath = tmpFile + File.separator + fileName;
132             File deleteCheck = new File(deleteCheckPath);
133             if (deleteCheck.exists() && deleteCheck.delete()) {
134                 policyLogger.info("Deleted the file from system before exporting a new file.");
135             }
136
137             File temPath = new File(tmpFile);
138             if (!temPath.exists()) {
139                 temPath.mkdir();
140             }
141
142             String file = temPath + File.separator + fileName;
143             File filepath = new File(file);
144             FileOutputStream fos = new FileOutputStream(filepath);
145             workBook.write(fos);
146             fos.flush();
147
148             response.setCharacterEncoding("UTF-8");
149             response.setContentType("application / json");
150             request.setCharacterEncoding("UTF-8");
151
152             PrintWriter out = response.getWriter();
153             String successMap = file.substring(file.lastIndexOf("webapps") + 8);
154             String responseString = new Gson().toJson(successMap);
155             JSONObject jsonResposne = new JSONObject("{data: " + responseString + "}");
156             out.write(jsonResposne.toString());
157         } catch (Exception e) {
158             policyLogger.error(
159                     XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Exception Occured while Exporting BlackList Entries", e);
160         }
161     }
162
163     /**
164      * This method is used to import the BlackList excel file into the system. Which is used to create Decision
165      * Blacklist Guard YAML Policy.
166      * 
167      * @param request the HTTP request contains file upload stream form GUI.
168      * @param response the response is send to the GUI after reading the file input stream.
169      */
170     @RequestMapping(value = {"/policycreation/importBlackListForDecisionPolicy"}, method = {RequestMethod.POST})
171     public void importBlackListFile(HttpServletRequest request, HttpServletResponse response) {
172         try {
173             List<FileItem> items = new ServletFileUpload(new DiskFileItemFactory()).parseRequest(request);
174             List<String> errorLogs = new ArrayList<>();
175             Gson mapper = new Gson();
176             errorLogs.add("error");
177             Map<String, Object> model = new HashMap<>();
178             if (items.isEmpty()) {
179                 errorLogs.add("The File doesn't have any content and it is invalid.");
180                 model.put(BLACKLISTENTRIESDATA, errorLogs);
181             } else {
182                 readItems(items, errorLogs, model);
183             }
184             JsonMessage msg = new JsonMessage(mapper.toJson(model));
185             JSONObject jsonResposne = new JSONObject(msg);
186             response.getWriter().write(jsonResposne.toString());
187         } catch (FileUploadException | IOException e) {
188             policyLogger.error("Exception Occured while importing the BlackListEntry", e);
189         }
190     }
191
192     /**
193      * This method is used to read the first item, as we expect only one entry in the file upload.
194      * 
195      * @param items The file entries which were uploaded from GUI.
196      * @param errorLogs on adding all incorrect entries, we can let user know what need to fixed.
197      * @param model Map which stores key value (blacklist and append list data)
198      * @throws Exception throws exception if it is not .xls format
199      */
200     private void readItems(List<FileItem> items, List<String> errorLogs, Map<String, Object> model) throws IOException {
201         Map<String, InputStream> files = new HashMap<>();
202
203         FileItem item = items.get(0);
204         files.put(item.getName(), item.getInputStream());
205         File file = new File(item.getName());
206         String fileName = file.getName();
207         try (OutputStream outputStream = new FileOutputStream(file);) {
208             IOUtils.copy(item.getInputStream(), outputStream);
209             if (fileName.startsWith("BlackList") && fileName.endsWith(".xls")) {
210                 readWorkBook(fileName, errorLogs, model);
211             } else {
212                 errorLogs.add("The File Name should start with BlackList and must be .xls format.");
213                 model.put(BLACKLISTENTRIESDATA, errorLogs);
214             }
215         }
216         Files.delete(file.toPath());
217     }
218
219     /**
220      * This method is used to read the workbook in xls file item.
221      * 
222      * @param fileName fileName as input parameter
223      * @param errorLogs on adding all incorrect entries, we can let user know what need to fixed.
224      * @param model Map which stores key value (blacklist and append list data)
225      */
226     private void readWorkBook(String fileName, List<String> errorLogs, Map<String, Object> model) {
227         Set<String> blackListEntries = new HashSet<>();
228         Set<String> appendBlackListEntries = new HashSet<>();
229         try (Workbook workbook = WorkbookFactory.create(new File(fileName))) {
230             Sheet datatypeSheet = workbook.getSheetAt(0);
231             Iterator<Row> rowIterator = datatypeSheet.iterator();
232             readExcelRows(rowIterator, blackListEntries, appendBlackListEntries, errorLogs);
233             if (errorLogs.size() == 1) {
234                 model.put(BLACKLISTENTRIESDATA, blackListEntries);
235                 model.put("appendBlackListEntries", appendBlackListEntries);
236             } else {
237                 model.put(BLACKLISTENTRIESDATA, errorLogs);
238             }
239         } catch (Exception e) {
240             String error = "Error Occured While Reading File. Please check the format of the file.";
241             errorLogs.add(error);
242             model.put(BLACKLISTENTRIESDATA, errorLogs);
243             policyLogger.error(error, e);
244         }
245     }
246
247     /**
248      * This method is used to read all the rows from imported Excel sheet and set to respective objects.
249      * 
250      * @param rowIterator Excel Sheet rows are passed as input parameters.
251      * @param blackListEntries the data is set to this object, which is going to be added.
252      * @param appendBlackListEntries the data is set to this object which is going to be removed.
253      * @param errorLogs on adding all incorrect entries, we can let user know what need to fixed.
254      */
255     private void readExcelRows(Iterator<Row> rowIterator, Set<String> blackListEntries,
256             Set<String> appendBlackListEntries, List<String> errorLogs) {
257         while (rowIterator.hasNext()) {
258             Row currentRow = rowIterator.next();
259             if (currentRow.getRowNum() == 0) {
260                 continue;
261             }
262             Iterator<Cell> cellIterator = currentRow.cellIterator();
263             readExcelCells(cellIterator, blackListEntries, appendBlackListEntries, errorLogs);
264         }
265     }
266
267     /**
268      * This method is used to read all the cells in the row.
269      * 
270      * @param cellIterator iterating the cells and will parse based on the cell type.
271      * @param blackListEntries the data is set to this object, which is going to be added.
272      * @param appendBlackListEntries the data is set to this object which is going to be removed.
273      * @param errorLogs on adding all incorrect entries, we can let user know what need to fixed.
274      */
275     private void readExcelCells(Iterator<Cell> cellIterator, Set<String> blackListEntries,
276             Set<String> appendBlackListEntries, List<String> errorLogs) {
277         boolean actionCheck = false;
278         boolean blackListCheck = false;
279         String blEntry = "";
280         int actionEntry = 0;
281         int lineNo = 1;
282         while (cellIterator.hasNext()) {
283             Cell cell = cellIterator.next();
284             if (ACTION.equalsIgnoreCase(getCellHeaderName(cell))) {
285                 ReturnBlackList returnList = readActionCell(cell, lineNo, errorLogs);
286                 actionEntry = returnList.getActionValue();
287                 actionCheck = returnList.isEntryCheck();
288             }
289             if (BLACKLISTENTRY.equalsIgnoreCase(getCellHeaderName(cell))) {
290                 ReturnBlackList returnList = readBlackListCell(cell, lineNo, errorLogs);
291                 blEntry = returnList.getEntryValue();
292                 blackListCheck = returnList.isEntryCheck();
293             }
294             lineNo++;
295         }
296         if (actionCheck && blackListCheck) {
297             addBlackListEntries(actionEntry, blackListEntries, appendBlackListEntries, blEntry);
298         }
299     }
300
301     /**
302      * This method is used to read the Action cell entry.
303      * 
304      * @param cell reading the action entry cell.
305      * @param lineNo counts the number of the cell.
306      * @param errorLogs on adding all incorrect entries, we can let user know what need to fixed.
307      * @return returns the response on setting to ReturnBlackList class.
308      */
309     private ReturnBlackList readActionCell(Cell cell, int lineNo, List<String> errorLogs) {
310         ReturnBlackList returnValues = new ReturnBlackList();
311         String error = "Entry at row " + lineNo + " not added, the value in the " + ACTION
312                 + "column is neither \"0\" nor \"1\"";
313         int actionEntry = 0;
314         try {
315             actionEntry = (int) cell.getNumericCellValue();
316             returnValues.setEntryCheck(true);
317             if (actionEntry != 1 && actionEntry != 0) {
318                 errorLogs.add(error);
319             }
320         } catch (Exception e) {
321             errorLogs.add(error);
322             policyLogger.error(error, e);
323             actionEntry = 0;
324         }
325         returnValues.setActionValue(actionEntry);
326         return returnValues;
327     }
328
329     /**
330      * This method is used to read the BlackList cell entry.
331      * 
332      * @param cell reading the blacklist entry cell.
333      * @param lineNo counts the number of the cell.
334      * @param errorLogs on adding all incorrect entries, we can let user know what need to fixed.
335      * @return returns the response on setting to ReturnBlackList class.
336      */
337     private ReturnBlackList readBlackListCell(Cell cell, int lineNo, List<String> errorLogs) {
338         ReturnBlackList returnValues = new ReturnBlackList();
339         String blEntry = "";
340         try {
341             blEntry = cell.getStringCellValue();
342             returnValues.setEntryCheck(true);
343         } catch (Exception e) {
344             String error = "Entry at row " + lineNo + " not added, the value in the " + BLACKLISTENTRY
345                     + " column is not a valid string";
346             errorLogs.add(error);
347             policyLogger.error(error, e);
348             returnValues.setActionValue(0);
349         }
350         returnValues.setEntryValue(blEntry);
351         return returnValues;
352     }
353
354     /**
355      * This method is used to add the data to blacklist and append list after parsing each and every row.
356      * 
357      * @param actionEntry it has the input to add or not and holds either 0 or 1.
358      * @param blackListEntries list to add blacklist entries based on action entry = 1.
359      * @param appendBlackListEntries list to add append list entries based on action entry = 0.
360      * @param blEntry the value added to both entries based on action entry.
361      */
362     private void addBlackListEntries(int actionEntry, Set<String> blackListEntries, Set<String> appendBlackListEntries,
363             String blEntry) {
364         if (actionEntry == 1) {
365             blackListEntries.add(blEntry);
366         } else {
367             appendBlackListEntries.add(blEntry);
368         }
369     }
370
371     /**
372      * This method is used to identify the header of the cell.
373      * 
374      * @param cell Excel sheet cell is passed as input parameter.
375      * @return the column header name value
376      */
377     private String getCellHeaderName(Cell cell) {
378         return cell.getSheet().getRow(0).getCell(cell.getColumnIndex()).getRichStringCellValue().toString();
379     }
380 }