Merge "App onboarding fixes"
[portal.git] / ecomp-portal-widget-ms / widget-ms / src / main / java / org / onap / portalapp / widget / service / impl / StorageServiceImpl.java
1 package org.onap.portalapp.widget.service.impl;
2
3 import java.io.File;
4 import java.io.FileOutputStream;
5 import java.io.IOException;
6 import java.io.InputStream;
7 import java.io.UnsupportedEncodingException;
8 import java.nio.file.Files;
9 import java.nio.file.Paths;
10 import java.util.Arrays;
11 import java.util.List;
12 import java.util.Map;
13 import java.util.regex.Matcher;
14 import java.util.regex.Pattern;
15 import java.util.zip.ZipEntry;
16 import java.util.zip.ZipOutputStream;
17
18 import org.hibernate.Criteria;
19 import org.hibernate.Session;
20 import org.hibernate.SessionFactory;
21 import org.hibernate.Transaction;
22 import org.hibernate.criterion.Restrictions;
23 import org.onap.portalapp.widget.constant.WidgetConstant;
24 import org.onap.portalapp.widget.domain.ValidationRespond;
25 import org.onap.portalapp.widget.domain.WidgetCatalog;
26 import org.onap.portalapp.widget.domain.WidgetFile;
27 import org.onap.portalapp.widget.excetpion.StorageException;
28 import org.onap.portalapp.widget.service.StorageService;
29 import org.onap.portalapp.widget.service.WidgetCatalogService;
30 import org.onap.portalapp.widget.utils.UnzipUtil;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33 import org.springframework.beans.factory.annotation.Autowired;
34 import org.springframework.stereotype.Service;
35 import org.springframework.transaction.annotation.Transactional;
36 import org.springframework.web.multipart.MultipartFile;
37
38 @Service
39 public class StorageServiceImpl implements StorageService {
40
41         private static final Logger logger = LoggerFactory.getLogger(StorageServiceImpl.class);
42         private final String TMP_PATH = "/tmp/";
43
44         @Autowired
45         private SessionFactory sessionFactory;
46
47         @Autowired
48         WidgetCatalogService widgetCatalogService;
49
50         @Override
51         @Transactional
52         public void deleteWidgetFile(long widgetId) {
53                 WidgetFile widgetFile = getWidgetFile(widgetId);
54                 logger.debug("StorageServiceImpl.deleteWidgetFile: deleting widget file {}", widgetId);
55                 if (widgetFile == null) {
56                         logger.debug(
57                                         "StorageServiceImpl.deleteWidgetFile: No widget file found in database while performing StorageServiceImpl.deleteWidgetFile.");
58                         return;
59                 }
60                 Session session = sessionFactory.getCurrentSession();
61                 Transaction tx = session.beginTransaction();
62                 session.delete(widgetFile);
63                 tx.commit();
64         }
65
66         @Override
67         @SuppressWarnings("unchecked")
68         @Transactional
69         public WidgetFile getWidgetFile(long widgetId) {
70                 logger.debug("StorageServiceImpl.getWidgetFile: getting widget file {}", widgetId);
71                 WidgetFile widgetFile = null;
72                 Session session = sessionFactory.openSession();
73                 Criteria criteria = session.createCriteria(WidgetFile.class);
74                 criteria.add(Restrictions.eq("widgetId", widgetId));
75                 List<WidgetFile> widgetFiles = criteria.list();
76                 //session.flush();
77                 session.close();
78                 if (widgetFiles.size() > 0)
79                         widgetFile = widgetFiles.get(0);
80                 return widgetFile;
81         }
82
83         @Override
84         public ValidationRespond checkZipFile(MultipartFile file) {
85                 StringBuilder error_msg = new StringBuilder();
86                 UnzipUtil unzipper = new UnzipUtil();
87                 Map<String, byte[]> map;
88                 File convFile;
89                 boolean isValid = true;
90                 if (!file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf('.')).equals(".zip")) {
91                         isValid = false;
92                         error_msg.append(WidgetConstant.VALIDATION_MESSAGE_ZIP);
93                         logger.error("StorageServiceImpl.checkZipFile: invalid file format");
94                 }
95                 try {
96                         if (file.isEmpty()) {
97                                 logger.error(
98                                                 "StorageServiceImpl.checkZipFile: Failed to store empty file " + file.getOriginalFilename());
99                                 throw new StorageException(
100                                                 "StorageServiceImpl.checkZipFile: Failed to store empty file " + file.getOriginalFilename());
101                         }
102
103                         String fileLocation = TMP_PATH+file.getOriginalFilename();
104                         logger.debug("StorageServiceImpl.checkZipFile: store the widget to:" + fileLocation);
105                         convFile = new File(fileLocation);
106                         try(FileOutputStream fos = new FileOutputStream(convFile)){
107                                 fos.write(file.getBytes());
108                         }
109                         map = unzipper.unzip_db(fileLocation, TMP_PATH, "tempWidgets");
110                         convFile.delete();
111                 } catch (IOException e) {
112                         logger.error("StorageServiceImpl.checkZipFile: Failed to store file " + file.getOriginalFilename(), e);
113                         throw new StorageException(
114                                         "torageServiceImpl.checkZipFile: Failed to store file " + file.getOriginalFilename(), e);
115                 }
116
117                 for (byte[] b : map.values()) {
118                         if (isValid && b == null) {
119                                 isValid = false;
120                                 error_msg.append(WidgetConstant.VALIDATION_MESSAGE_FILES);
121                                 break;
122                         }
123                 }
124                 return new ValidationRespond(isValid, error_msg.toString());
125         }
126
127         @Override
128         @Transactional
129         public void save(MultipartFile file, WidgetCatalog newWidget, long widgetId) {
130
131                 UnzipUtil unzipper = new UnzipUtil();
132                 Map<String, byte[]> map;
133                 File convFile;
134                 try {
135                         if (file.isEmpty()) {
136                                 logger.error("Failed to store empty file " + file.getOriginalFilename());
137                                 throw new StorageException("Failed to store empty file " + file.getOriginalFilename());
138                         }
139                         String fileLocation = file.getOriginalFilename();
140                         logger.debug("StorageServiceImpl.save: store the widget to:" + fileLocation);
141                         convFile = new File(fileLocation);
142                         try(FileOutputStream fos = new FileOutputStream(convFile)){
143                                 fos.write(file.getBytes());
144                         }
145                         map = unzipper.unzip_db(fileLocation, ".", "tempWidgets");
146                         convFile.delete();
147                 } catch (IOException e) {
148                         logger.error("StorageServiceImpl.save: Failed to store file " + file.getOriginalFilename(), e);
149                         throw new StorageException("Failed to store file " + file.getOriginalFilename(), e);
150                 }
151                 saveJsHelper(newWidget, widgetId, map);
152         }
153
154         @Override
155         @Transactional
156         public void initSave(File file, WidgetCatalog newWidget, long widgetId) {
157
158                 UnzipUtil unzipper = new UnzipUtil();
159                 Map<String, byte[]> map;
160
161                 try {
162                         String fileLocation = file.getPath();
163                         logger.debug("StorageServiceImpl.save: store the widget to:" + fileLocation);
164                         map = unzipper.unzip_db(fileLocation, ".", "tempWidgets");
165                 } catch (IOException e) {
166                         logger.error("StorageServiceImpl.save: Failed to store file " + file.getName(), e);
167                         throw new StorageException("Failed to store file " + file.getName(), e);
168                 }
169                 
170                 saveJsHelper(newWidget, widgetId, map);
171         }
172
173         /**
174          * Helper method for saving widget files (controller.js, framework.js,
175          * markup.html and style.css) to ep_widget_catalog_files table in database
176          * 
177          * @param newWidget
178          * @param widgetId
179          * @param map
180          */
181         private void saveHelper(WidgetCatalog newWidget, long widgetId, Map<String, byte[]> map) {
182
183                 logger.debug("Going to save widget " + newWidget);
184                 WidgetFile widgetFile = new WidgetFile();
185                 widgetFile.setName(newWidget.getName());
186                 widgetFile.setWidgetId(widgetId);
187
188                 
189
190                 String sb = null;
191                 try(InputStream fileInputStream = this.getClass().getClassLoader().getResourceAsStream("framework-template.js")) {
192                         byte[] bytes = new byte[fileInputStream.available()];
193                         if(fileInputStream.read(bytes) > 0) {
194                                 sb = new String(bytes, "UTF-8");
195                         }
196                 } catch (IOException e) {
197                         logger.error("StorageServiceImpl.save: Failed to load framework-template.js file ", e);
198                 }
199
200                 String namespace = "Portal" + widgetId + "Widget";
201                 String controllerName = "Portal" + widgetId + "Ctrl";
202                 String cssName = "portal" + widgetId + "-css-ready";
203                 String colorArg1 = "color: #fff";
204                 String framework="";
205                 if(sb!=null) {
206                         framework = sb.replaceAll("ARGUMENT1", namespace).replaceAll("ARGUMENT2", controllerName)
207                                         .replaceAll("ARGUMENT3", cssName).replaceAll("CSS_ARG1", colorArg1)
208                                         .replaceAll("MICROSERVICE_ID", newWidget.getServiceId().toString())
209                                         .replaceAll("WIDGET_ID", Long.toString(widgetId));
210                 }
211                 widgetFile.setFramework(framework.getBytes());
212
213                 final byte[] controllerLoc = map.get(WidgetConstant.WIDGET_CONTROLLER_LOCATION);
214                 if (controllerLoc == null || controllerLoc.length == 0)
215                         throw new IllegalArgumentException(
216                                         "Map is missing required key " + WidgetConstant.WIDGET_CONTROLLER_LOCATION);
217                 String javascript = new String(controllerLoc);
218                 String functionHeader = javascript.substring(javascript.indexOf("function"), javascript.indexOf(")") + 1);
219                 String functionName = functionHeader.substring(functionHeader.indexOf(" "), functionHeader.indexOf("(")).trim();
220                 javascript = javascript.replaceFirst(functionName, controllerName);
221                 String functionParam = functionHeader.substring(functionHeader.indexOf("(") + 1, functionHeader.indexOf(")"));
222                 List<String> paramList = Arrays.asList(functionParam.split(","));
223
224                 int left_bracket_index = javascript.indexOf("{") + 1;
225                 String widgetData = namespace + "=" + namespace + "||{};" + "var res = " + namespace + ".widgetData;";
226                 javascript = javascript.substring(0, left_bracket_index) + widgetData
227                                 + javascript.substring(left_bracket_index);
228
229                 StringBuilder injectStr = new StringBuilder().append("[");
230                 for (int i = 0; i < paramList.size(); i++) {
231                         if (i == paramList.size() - 1)
232                                 injectStr.append("'" + paramList.get(i).trim() + "'];");
233                         else
234                                 injectStr.append("'" + paramList.get(i).trim() + "',");
235                 }
236                 javascript = namespace + ".controller = " + javascript + ";" + namespace + ".controller.$inject = "
237                                 + injectStr.toString();
238
239                 String html = new String(map.get(WidgetConstant.WIDGET_MARKUP_LOCATION)).replaceFirst(functionName,
240                                 controllerName);
241                 ;
242
243                 Pattern cssPattern = Pattern.compile("#.*-css-ready");
244                 Matcher cssMatcher = cssPattern.matcher(new String(map.get(WidgetConstant.WIDGET_STYLE_LOCATION)));
245                 if (cssMatcher.find()) {
246                         widgetFile.setCss(new String(map.get(WidgetConstant.WIDGET_STYLE_LOCATION))
247                                         .replace(cssMatcher.group(0), "#" + cssName).getBytes());
248                 }
249
250                 widgetFile.setMarkup(html.getBytes());
251                 widgetFile.setController(javascript.getBytes());
252                 Session session = sessionFactory.openSession();
253                 session.save(widgetFile);
254                 session.flush();
255                 session.close();
256                 // sessionFactory.getCurrentSession().save(widgetFile);
257                 logger.debug(
258                                 "StorageServiceImpl.save: saved fraemwork.js controller.js, markup.html and style.css files to the database for widget {}",
259                                 widgetId);
260
261         }
262         
263         /**
264          * Helper method to UnZip File
265          * 
266          * @param file
267          */
268         private Map<String, byte[]> unZipFile(MultipartFile file) {
269                 UnzipUtil unzipper = new UnzipUtil();
270                 Map<String, byte[]> map;
271                 File convFile;
272                 try {
273                         if (file.isEmpty()) {
274                                 logger.error("StorageServiceImpl.update: Failed to store empty file " + file.getOriginalFilename());
275                                 throw new StorageException("Failed to store empty file " + file.getOriginalFilename());
276                         }
277                         String fileLocation = file.getOriginalFilename();
278                         logger.debug("StorageServiceImpl.update: store the widget to:" + fileLocation);
279                         convFile = new File(fileLocation);
280                         try(FileOutputStream fos = new FileOutputStream(convFile)){
281                                 fos.write(file.getBytes());
282                         }
283                         map = unzipper.unzip_db(fileLocation, ".", "tempWidgets");
284                         convFile.delete();
285                         return map;
286                 } catch (IOException e) {
287                         logger.error("StorageServiceImpl.update: Failed to store file " + file.getOriginalFilename(), e);
288                         throw new StorageException("StorageServiceImpl.update: Failed to store file " + file.getOriginalFilename(),
289                                         e);
290                 }
291         }
292         
293         /**
294          * Helper method for saving widget file (controller.js) to ep_widget_catalog_files table in database
295          * 
296          * @param newWidget
297          * @param widgetId
298          * @param map
299          */
300         private void saveJsHelper(WidgetCatalog newWidget, long widgetId, Map<String, byte[]> map) {
301
302                 logger.debug("Going to save controller.js " + newWidget);
303                 WidgetFile widgetFile = new WidgetFile();
304                 widgetFile.setName(newWidget.getName());
305                 widgetFile.setWidgetId(widgetId);
306                 final byte[] controllerLoc = map.get(WidgetConstant.WIDGET_CONTROLLER_LOCATION);
307                 if (controllerLoc == null || controllerLoc.length == 0)
308                         throw new IllegalArgumentException(
309                                         "Map is missing required key " + WidgetConstant.WIDGET_CONTROLLER_LOCATION);
310                 String javascript = new String(controllerLoc);
311
312                 widgetFile.setController(javascript.getBytes());
313                 Session session = sessionFactory.openSession();
314                 session.save(widgetFile);
315                 session.flush();
316                 session.close();
317                 logger.debug(
318                                 "StorageServiceImpl.save: saved controller.js file to the database for widget {}",
319                                 widgetId);
320
321         }
322         
323         @Override
324         public void updateJsFile(MultipartFile file, WidgetCatalog newWidget, long widgetId) {
325                 Map<String, byte[]> map;
326                 map = unZipFile(file);
327                 //Get existing widget file from DB      
328                 WidgetFile widgetFile = getWidgetFile(widgetId);
329                 
330                 String javascript = new String(map.get(WidgetConstant.WIDGET_CONTROLLER_LOCATION));
331                 widgetFile.setController(javascript.getBytes());
332                 Session session = sessionFactory.openSession();
333                 Transaction tx = session.beginTransaction();
334                 session.update(widgetFile);
335                 tx.commit();
336                 session.flush();
337                 session.close();
338                 logger.debug(
339                                 "StorageServiceImpl.save: updated controller.js file to the database for widget {}",
340                                 widgetId);
341         }
342         
343         
344         
345         
346
347         @Override
348         public void update(MultipartFile file, WidgetCatalog newWidget, long widgetId) {
349                 UnzipUtil unzipper = new UnzipUtil();
350                 Map<String, byte[]> map;
351                 File convFile;
352                 try {
353                         if (file.isEmpty()) {
354                                 logger.error("StorageServiceImpl.update: Failed to store empty file " + file.getOriginalFilename());
355                                 throw new StorageException("Failed to store empty file " + file.getOriginalFilename());
356                         }
357                         String fileLocation = file.getOriginalFilename();
358                         logger.debug("StorageServiceImpl.update: store the widget to:" + fileLocation);
359                         convFile = new File(fileLocation);
360                         try(FileOutputStream fos = new FileOutputStream(convFile)){
361                                 fos.write(file.getBytes());
362                         }
363                         map = unzipper.unzip_db(fileLocation, ".", "tempWidgets");
364                         convFile.delete();
365                 } catch (IOException e) {
366                         logger.error("StorageServiceImpl.update: Failed to store file " + file.getOriginalFilename(), e);
367                         throw new StorageException("StorageServiceImpl.update: Failed to store file " + file.getOriginalFilename(),
368                                         e);
369                 }
370                 WidgetFile widgetFile = getWidgetFile(widgetId);
371
372                 String sb = null;
373                 try(InputStream fileInputStream = this.getClass().getClassLoader().getResourceAsStream("framework-template.js")){
374                         byte[] bytes = new byte[fileInputStream.available()];
375                         if(fileInputStream.read(bytes) > 0) {
376                                 sb = new String(bytes, "UTF-8");
377                         }
378                 } catch (IOException e) {
379                         logger.error("StorageServiceImpl.save: Failed to load framework-template.js file ", e);
380                 }
381
382                 String namespace = "Portal" + widgetId + "Widget";
383                 String controllerName = "Portal" + widgetId + "Ctrl";
384                 String cssName = "portal" + widgetId + "-css-ready";
385                 String colorArg1 = "color: #fff";
386                 String framework="";
387                 if(sb!=null) {
388                         framework = sb.replaceAll("ARGUMENT1", namespace).replaceAll("ARGUMENT2", controllerName)
389                                         .replaceAll("ARGUMENT3", cssName).replaceAll("CSS_ARG1", colorArg1)
390                                         .replaceAll("MICROSERVICE_ID", newWidget.getServiceId().toString())
391                                         .replaceAll("WIDGET_ID", Long.toString(widgetId));
392                 }
393                 widgetFile.setFramework(framework.getBytes());
394
395                 String javascript = new String(map.get(WidgetConstant.WIDGET_CONTROLLER_LOCATION));
396                 String functionHeader = javascript.substring(javascript.indexOf("function"), javascript.indexOf(")") + 1);
397                 String functionName = functionHeader.substring(functionHeader.indexOf(" "), functionHeader.indexOf("(")).trim();
398                 javascript = javascript.replaceFirst(functionName, controllerName);
399                 String functionParam = functionHeader.substring(functionHeader.indexOf("(") + 1, functionHeader.indexOf(")"));
400                 List<String> paramList = Arrays.asList(functionParam.split(","));
401
402                 int left_bracket_index = javascript.indexOf("{") + 1;
403                 String widgetData = namespace + "=" + namespace + "||{};" + "var res = " + namespace + ".widgetData;";
404                 javascript = javascript.substring(0, left_bracket_index) + widgetData
405                                 + javascript.substring(left_bracket_index);
406
407                 StringBuilder injectStr = new StringBuilder().append("[");
408                 for (int i = 0; i < paramList.size(); i++) {
409                         if (i == paramList.size() - 1)
410                                 injectStr.append("'" + paramList.get(i).trim() + "'];");
411                         else
412                                 injectStr.append("'" + paramList.get(i).trim() + "',");
413                 }
414                 javascript = namespace + ".controller = " + javascript + ";" + namespace + ".controller.$inject = "
415                                 + injectStr.toString();
416
417                 String html = new String(map.get(WidgetConstant.WIDGET_MARKUP_LOCATION)).replaceFirst(functionName,
418                                 controllerName);
419                 ;
420
421                 Pattern cssPattern = Pattern.compile("#.*-css-ready");
422                 Matcher cssMatcher = cssPattern.matcher(new String(map.get(WidgetConstant.WIDGET_STYLE_LOCATION)));
423                 if (cssMatcher.find()) {
424                         widgetFile.setCss(new String(map.get(WidgetConstant.WIDGET_STYLE_LOCATION))
425                                         .replace(cssMatcher.group(0), "#" + cssName).getBytes());
426                 }
427
428                 widgetFile.setMarkup(html.getBytes());
429                 widgetFile.setController(javascript.getBytes());
430                 // widgetFile.setCss(map.get(WidgetConstant.WIDGET_STYLE_LOCATION));
431                 Session session = sessionFactory.openSession();
432                 Transaction tx = session.beginTransaction();
433                 session.update(widgetFile);
434                 tx.commit();
435                 session.flush();
436                 session.close();
437                 logger.debug(
438                                 "StorageServiceImpl.save: updated fraemwork.js controller.js, markup.html and style.css files to the database for widget {}",
439                                 widgetId);
440         }
441
442         @Override
443         @SuppressWarnings("unchecked")
444         @Transactional
445         public String getWidgetMarkup(long widgetId) throws UnsupportedEncodingException {
446                 String markup = null;
447                 Session session = sessionFactory.getCurrentSession();
448                 Criteria criteria = session.createCriteria(WidgetFile.class);
449                 criteria.add(Restrictions.eq("widgetId", widgetId));
450                 List<WidgetFile> widgetFile = criteria.list();
451                 logger.debug("StorageServiceImpl.getWidgetMarkup: getting widget markup result={}", widgetFile);
452
453                 if (widgetFile.size() > 0)
454                         markup = new String(widgetFile.get(0).getMarkup(), "UTF-8");
455                 return markup;
456         }
457
458         @Override
459         @SuppressWarnings("unchecked")
460         @Transactional
461         public String getWidgetController(long widgetId) throws UnsupportedEncodingException {
462                 String controller = null;
463                 Session session = sessionFactory.getCurrentSession();
464                 Criteria criteria = session.createCriteria(WidgetFile.class);
465                 criteria.add(Restrictions.eq("widgetId", widgetId));
466                 List<WidgetFile> widgetFile = criteria.list();
467                 logger.debug("StorageServiceImpl.getWidgetController: getting widget controller result={}", widgetFile);
468
469                 if (widgetFile.size() > 0)
470                         controller = new String(widgetFile.get(0).getController(), "UTF-8");
471                 return controller;
472         }
473
474         @Override
475         @SuppressWarnings("unchecked")
476         @Transactional
477         public String getWidgetFramework(long widgetId) throws UnsupportedEncodingException {
478                 String framework = null;
479                 Session session = sessionFactory.getCurrentSession();
480                 Criteria criteria = session.createCriteria(WidgetFile.class);
481                 criteria.add(Restrictions.eq("widgetId", widgetId));
482                 List<WidgetFile> widgetFile = criteria.list();
483                 logger.debug("StorageServiceImpl.getWidgetFramework: getting widget framework result={}", widgetFile);
484
485                 if (widgetFile.size() > 0)
486                         framework = new String(widgetFile.get(0).getFramework(), "UTF-8");
487                 return framework;
488         }
489
490         @Override
491         @SuppressWarnings("unchecked")
492         @Transactional
493         public String getWidgetCSS(long widgetId) throws UnsupportedEncodingException {
494                 String css = null;
495                 Session session = sessionFactory.getCurrentSession();
496                 Criteria criteria = session.createCriteria(WidgetFile.class);
497                 criteria.add(Restrictions.eq("widgetId", widgetId));
498                 List<WidgetFile> widgetFile = criteria.list();
499                 logger.debug("StorageServiceImpl.getWidgetCSS: getting widget css result={}", widgetFile);
500
501                 if (widgetFile.size() > 0)
502                         css = new String(widgetFile.get(0).getCss(), "UTF-8");
503                 return css;
504         }
505
506         @Override
507         @Transactional
508         public byte[] getWidgetCatalogContent(long widgetId) throws Exception {
509
510                 WidgetCatalog widget = widgetCatalogService.getWidgetCatalog(widgetId);
511                 File f = File.createTempFile("temp", ".zip");
512                 try(ZipOutputStream out = new ZipOutputStream(new FileOutputStream(f))){
513                         String javascript = getWidgetController(widgetId);
514         
515                         ZipEntry e = new ZipEntry(widget.getName() + "/js/controller.js");
516                         out.putNextEntry(new ZipEntry(widget.getName() + "/js/"));
517                         out.putNextEntry(e);
518                         byte[] data = javascript.getBytes();
519                         out.write(data, 0, data.length);
520                         out.closeEntry();
521                         byte[] result = Files.readAllBytes(Paths.get(f.getPath()));
522                         f.delete();
523                         return result;
524                 }
525         }
526
527 }