/* ====================================================================
*
* Copyright (C) 2007 - 2015 GeoSolutions S.A.S.
* http://www.geo-solutions.it
*
* GPLv3 + Classpath exception
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.
*
* ====================================================================
*
* This software consists of voluntary contributions made by developers
* of GeoSolutions. For more information on GeoSolutions, please see
* <http://www.geo-solutions.it/>.
*
*/
package it.geosolutions.geostore.services.rest.auditing;
import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
final class AuditingFilesManager {
private static final Logger logger = Logger.getLogger(AuditingFilesManager.class);
private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
private final File outputDirectory;
private final String fileExtension;
private File outputFile;
private String currentDayTag;
private Pattern filePattern;
AuditingFilesManager(String outputDirectoryPath, String fileExtension) {
this.outputDirectory = new File(outputDirectoryPath);
this.fileExtension = fileExtension;
init();
}
File rollOutputFile() {
updateCurrentDay();
if (outputFile.exists()) {
int rollingValue = getNextRollingValue();
File rollingFile = new File(outputDirectory, getRollinFileName(rollingValue));
moveOutputFile(rollingFile);
}
createOutputFile();
return outputFile;
}
File getOutputFile() {
return outputFile;
}
String getCurrentDayTag() {
return currentDayTag;
}
void makeOutputFileExists() {
if(!outputFile.exists()) {
createOutputFile();
}
}
private void init() {
updateCurrentDay();
outputFile = new File(outputDirectory, String.format("audit-geostore.%s", fileExtension));
if (outputDirectory.exists()) {
LogUtils.info(logger, "Output directory '%s' exists.", outputDirectory.getPath());
handleExistingOutputDirectory();
} else {
LogUtils.info(logger, "Creating output directory '%s'.", outputDirectory.getPath());
try {
FileUtils.forceMkdir(outputDirectory);
} catch (Exception exception) {
throw new AuditingException(exception, "Error creating output directory '%s'.", outputDirectory);
}
}
}
private void handleExistingOutputDirectory() {
if (outputFile.exists()) {
rollOutputFile();
} else {
createOutputFile();
}
}
private void updateCurrentDay() {
String dayTag = dateFormat.format(new Date());
if (currentDayTag == null || !currentDayTag.equals(dayTag)) {
LogUtils.debug(logger, "Current day '%s' will be updates to '%s'.", currentDayTag, dayTag);
currentDayTag = dayTag;
filePattern = Pattern.compile("audit-geostore-" + currentDayTag + "-(\\d+)\\." + fileExtension + "$");
}
}
private String getRollinFileName(int nextRollingValue) {
return String.format("audit-geostore-%s-%d.%s", currentDayTag, nextRollingValue, fileExtension);
}
private void moveOutputFile(File rollingFile) {
LogUtils.info(logger, "Rolling output file '%s' to '%s'.", outputFile.getPath(), rollingFile.getPath());
try {
FileUtils.moveFile(outputFile, rollingFile);
} catch (Exception exception) {
throw new AuditingException(exception, "Error moving output file '%s' to rolling file '%s'.",
outputFile.getPath(), rollingFile.getPath());
}
}
private void createOutputFile() {
try {
LogUtils.info(logger, "Creating output file '%s'.", outputFile.getPath());
FileUtils.touch(outputFile);
} catch (Exception exception) {
throw new AuditingException(exception, "Error creating output file '%s'.", outputFile.getPath());
}
}
private int getNextRollingValue() {
List<Integer> rollingValues = getRollingValues();
int nextRollingValue = 1;
if (!rollingValues.isEmpty()) {
Collections.sort(rollingValues);
nextRollingValue = rollingValues.get(rollingValues.size() - 1) + 1;
}
LogUtils.debug(logger, "Next rolling value for day '%s' will be '%d'.", currentDayTag, nextRollingValue);
return nextRollingValue;
}
private List<Integer> getRollingValues() {
List<Integer> rollingValues = new ArrayList<Integer>();
String[] files = listOutputDirectoryFiles();
for (String file : files) {
Matcher matcher = filePattern.matcher(file);
if (matcher.matches()) {
rollingValues.add(Integer.parseInt(matcher.group(1)));
}
}
return rollingValues;
}
private String[] listOutputDirectoryFiles() {
String[] files = outputDirectory.list();
if (files == null) {
throw new AuditingException("Error listing files of output directory '%s'.", outputDirectory);
}
LogUtils.debug(logger, "Output directory current files: %s.", LogUtils.arrayToString(files));
return files;
}
}