001// Generated by delombok at Sat May 11 08:17:52 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 035 * @param fileNumber an order number. Can be 'null' if a single file 036 037 * should be created in the directory. If not 'null', 038 039 * this number will be appended to the file name, 040 041 * for example index_001.html 042 043 * @param fileName the file name without extension 044 045 * @param reportDirectory where the new file will be created 046 047 * @param fileExtension for example html or txt 048 049 * 050 051 * @return the new file with context transformed from the source log file. 052 */ 053 public File generateFile(Integer fileNumber, String fileName, File reportDirectory, String fileExtension) { 054 String num = null; 055 if (fileNumber != null) { 056 num = String.format("%03d", fileNumber); 057 } 058 StringBuilder newFileName = new StringBuilder(fileName); 059 if (num != null) { 060 newFileName.append(DOT).append(num); 061 } 062 newFileName.append(DOT).append(fileExtension); 063 File file = new File(reportDirectory, newFileName.toString()); 064 logger.info("The new empty file created: \'{}\'", file.getAbsolutePath()); 065 return file; 066 } 067 068 /** 069 * Sort files in a directory from the first argument. 070 071 * For each {@link Application} creates its own list of files. 072 073 * 074 075 * @param directory cannot be 'null'. Can have files from different {@link Application}s.<br> 076 077 * Cannot contain other files. But can have directories. These directories 078 079 * will be processed recursively. 080 081 * @param applicationLogs at first invocation an empty, and it will be filled with files 082 */ 083 private void collectApplicationLogs(File directory, List<ApplicationLog> applicationLogs) { 084 Preconditions.checkNotNull(directory); 085 Preconditions.checkState(directory.isDirectory()); 086 Map<Application, Map<Date, File>> map = new HashMap<>(); 087 File[] files = Objects.requireNonNull(directory.listFiles()); 088 for (File file : files) { 089 addFileToMap(applicationLogs, map, files, file); 090 } 091 ApplicationService applicationService = ApplicationService.getInstance(); 092 for (Entry<Application, Map<Date, File>> appEntry : map.entrySet()) { 093 Application application = appEntry.getKey(); 094 ApplicationLog applicationLog = applicationService.findOrCreate(applicationLogs, application); 095 NodeFileService.getInstance().appendToNodeLogs(appEntry.getValue(), applicationLog); 096 } 097 } 098 099 private void addFileToMap(List<ApplicationLog> applicationLogs, Map<Application, Map<Date, File>> map, File[] files, File file) { 100 if (file.isFile()) { 101 if (file.getName().endsWith(".zip")) { 102 file = unzipIfNotExists(file, files); 103 } 104 Application application = FileService.getInstance().findApplication(file); 105 if (!map.containsKey(application)) { 106 map.put(application, new TreeMap<>()); 107 } 108 Date date = FileService.getInstance().findDate(file, application); 109 if (date == null) { 110 throw new SubstitutionRuntimeException("Cannot find a date in the file: " + file.getAbsolutePath()); 111 } 112 map.get(application).put(date, file); 113 } else { 114 // directories 115 if (!file.getName().endsWith(REPORT_FOLDER_EXTENSION)) { 116 collectApplicationLogs(file, applicationLogs); 117 } 118 } 119 } 120 121 /** 122 * If the second argument contains unzipped first argument, do not unzip it. 123 124 * Else unzip it and return a file from this zipFile. 125 126 * @param zipFile zipped log file 127 128 * @param files all files in a directory 129 130 * @return an unzipped file or file from files 131 */ 132 private File unzipIfNotExists(File zipFile, File[] files) { 133 try ( 134 InputStream is = new FileInputStream(zipFile); 135 ArchiveInputStream ais = new ArchiveStreamFactory().createArchiveInputStream("zip", is)) { 136 ZipArchiveEntry zipArchiveEntry = (ZipArchiveEntry) ais.getNextEntry(); 137 String zipArchiveEntryName = zipArchiveEntry.getName(); 138 for (File file : files) { 139 if (file.getName().equals(zipArchiveEntryName)) { 140 return file; 141 } 142 } 143 File outputFile = new File(zipFile.getParentFile(), zipArchiveEntryName); 144 logger.info("File {}:{} will be decompressed to {}", zipFile.getName(), zipArchiveEntryName, outputFile.getAbsolutePath()); 145 IOUtils.copy(ais, new FileOutputStream(outputFile)); 146 return outputFile; 147 } catch (Exception e) { 148 throw new SubstitutionRuntimeException("Cannot unzipIfNotExists file: " + zipFile.getAbsolutePath(), e); 149 } 150 } 151 152 @Inject 153 @java.lang.SuppressWarnings("all") 154 public FileUtilService() { 155 } 156}