001// Generated by delombok at Thu May 02 07:34:48 CEST 2019 002package com.credibledoc.substitution.doc.module.substitution.file; 003 004import com.credibledoc.combiner.application.Application; 005import com.credibledoc.combiner.application.ApplicationService; 006import com.credibledoc.combiner.file.FileService; 007import com.credibledoc.combiner.node.applicationlog.ApplicationLog; 008import com.credibledoc.combiner.node.file.NodeFileService; 009import com.credibledoc.substitution.core.exception.SubstitutionRuntimeException; 010import com.google.common.base.Preconditions; 011import org.apache.commons.compress.archivers.ArchiveInputStream; 012import org.apache.commons.compress.archivers.ArchiveStreamFactory; 013import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; 014import org.apache.commons.compress.utils.IOUtils; 015import org.slf4j.Logger; 016import org.slf4j.LoggerFactory; 017import org.springframework.stereotype.Service; 018import javax.inject.Inject; 019import java.io.File; 020import java.io.FileInputStream; 021import java.io.FileOutputStream; 022import java.io.InputStream; 023import java.util.*; 024import java.util.Map.Entry; 025 026@Service 027public class FileUtilService { 028 private static final Logger logger = LoggerFactory.getLogger(FileUtilService.class); 029 private static final char DOT = '.'; 030 private static final String REPORT_FOLDER_EXTENSION = ".report"; 031 032 /** 033 * Generate a new file with transformed content of source log files. 034 * @param fileNumber an order number. Can be 'null' if a single file 035 * should be created in the directory. If not 'null', 036 * this number will be appended to the file name, 037 * for example index_001.html 038 * @param fileName the file name without extension 039 * @param reportDirectory where the new file will be created 040 * @param fileExtension for example html or txt 041 * 042 * @return the new file with context transformed from the source log file. 043 */ 044 public File generateFile(Integer fileNumber, String fileName, File reportDirectory, String fileExtension) { 045 String num = null; 046 if (fileNumber != null) { 047 num = String.format("%03d", fileNumber); 048 } 049 StringBuilder newFileName = new StringBuilder(fileName); 050 if (num != null) { 051 newFileName.append(DOT).append(num); 052 } 053 newFileName.append(DOT).append(fileExtension); 054 File file = new File(reportDirectory, newFileName.toString()); 055 logger.info("The new empty file created: \'{}\'", file.getAbsolutePath()); 056 return file; 057 } 058 059 /** 060 * Sort files in a directory from the first argument. 061 * For each {@link Application} creates its own list of files. 062 * 063 * @param directory cannot be 'null'. Can have files from different {@link Application}s.<br> 064 * Cannot contain other files. But can have directories. These directories 065 * will be processed recursively. 066 * @param applicationLogs at first invocation an empty, and it will be filled with files 067 */ 068 private void collectApplicationLogs(File directory, List<ApplicationLog> applicationLogs) { 069 Preconditions.checkNotNull(directory); 070 Preconditions.checkState(directory.isDirectory()); 071 Map<Application, Map<Date, File>> map = new HashMap<>(); 072 File[] files = Objects.requireNonNull(directory.listFiles()); 073 for (File file : files) { 074 addFileToMap(applicationLogs, map, files, file); 075 } 076 ApplicationService applicationService = ApplicationService.getInstance(); 077 for (Entry<Application, Map<Date, File>> appEntry : map.entrySet()) { 078 Application application = appEntry.getKey(); 079 ApplicationLog applicationLog = applicationService.findOrCreate(applicationLogs, application); 080 NodeFileService.getInstance().appendToNodeLogs(appEntry.getValue(), applicationLog); 081 } 082 } 083 084 private void addFileToMap(List<ApplicationLog> applicationLogs, Map<Application, Map<Date, File>> map, File[] files, File file) { 085 if (file.isFile()) { 086 if (file.getName().endsWith(".zip")) { 087 file = unzipIfNotExists(file, files); 088 } 089 Application application = FileService.getInstance().findApplication(file); 090 if (!map.containsKey(application)) { 091 map.put(application, new TreeMap<>()); 092 } 093 Date date = FileService.getInstance().findDate(file, application); 094 if (date == null) { 095 throw new SubstitutionRuntimeException("Cannot find a date in the file: " + file.getAbsolutePath()); 096 } 097 map.get(application).put(date, file); 098 } else { 099 // directories 100 if (!file.getName().endsWith(REPORT_FOLDER_EXTENSION)) { 101 collectApplicationLogs(file, applicationLogs); 102 } 103 } 104 } 105 106 /** 107 * If the second argument contains unzipped first argument, do not unzip it. 108 * Else unzip it and return a file from this zipFile. 109 * @param zipFile zipped log file 110 * @param files all files in a directory 111 * @return an unzipped file or file from files 112 */ 113 private File unzipIfNotExists(File zipFile, File[] files) { 114 try ( 115 InputStream is = new FileInputStream(zipFile); 116 ArchiveInputStream ais = new ArchiveStreamFactory().createArchiveInputStream("zip", is)) { 117 ZipArchiveEntry zipArchiveEntry = (ZipArchiveEntry) ais.getNextEntry(); 118 String zipArchiveEntryName = zipArchiveEntry.getName(); 119 for (File file : files) { 120 if (file.getName().equals(zipArchiveEntryName)) { 121 return file; 122 } 123 } 124 File outputFile = new File(zipFile.getParentFile(), zipArchiveEntryName); 125 logger.info("File {}:{} will be decompressed to {}", zipFile.getName(), zipArchiveEntryName, outputFile.getAbsolutePath()); 126 IOUtils.copy(ais, new FileOutputStream(outputFile)); 127 return outputFile; 128 } catch (Exception e) { 129 throw new SubstitutionRuntimeException("Cannot unzipIfNotExists file: " + zipFile.getAbsolutePath(), e); 130 } 131 } 132 133 @Inject 134 @java.lang.SuppressWarnings("all") 135 public FileUtilService() { 136 } 137}