001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2015 ForgeRock AS. 015 */ 016package org.forgerock.audit.retention; 017 018import static org.forgerock.audit.events.handlers.FileBasedEventHandlerConfiguration.FileRotation.DEFAULT_ROTATION_FILE_SUFFIX; 019 020import java.io.File; 021import java.nio.file.Path; 022import java.util.Arrays; 023import java.util.Collections; 024import java.util.LinkedList; 025import java.util.List; 026 027import org.forgerock.audit.util.LastModifiedTimeFileComparator; 028import org.joda.time.LocalDateTime; 029import org.joda.time.format.DateTimeFormat; 030import org.joda.time.format.DateTimeFormatter; 031import org.slf4j.Logger; 032import org.slf4j.LoggerFactory; 033 034/** 035 * Creates a time stamp based file naming policy. Rotated files are renamed with a given prefix and a timestamp suffix. 036 */ 037public class TimeStampFileNamingPolicy implements FileNamingPolicy { 038 039 private static final Logger logger = LoggerFactory.getLogger(TimeStampFileNamingPolicy.class); 040 041 private final File initialFile; 042 private DateTimeFormatter suffixDateFormat; 043 private final String prefix; 044 private final TimestampFilenameFilter timestampFilenameFilter; 045 private final LastModifiedTimeFileComparator lastModifiedTimeFileComparator = new LastModifiedTimeFileComparator(); 046 047 /** 048 * Constructs a TimeStampFileNaming policy with a given initial file, a timestamp format, and a prefix string. 049 * @param initialFile The initial file that will be archived. 050 * @param timeStampFormat The timestamp format to append to the archived files. Should be a format that is 051 * understood by {@link DateTimeFormat}. 052 * @param prefix The prefix to prefix to the archived files. 053 */ 054 public TimeStampFileNamingPolicy(final File initialFile, final String timeStampFormat, final String prefix) { 055 this.initialFile = initialFile; 056 this.prefix = prefix; 057 058 if (timeStampFormat != null && timeStampFormat.trim().length() > 0) { 059 try { 060 suffixDateFormat = DateTimeFormat.forPattern(timeStampFormat); 061 } catch (IllegalArgumentException iae) { 062 logger.info("Date format invalid: {}", timeStampFormat, iae); 063 } 064 } 065 if (suffixDateFormat == null) { 066 // fallback to a default date format, so the filenames will differ 067 suffixDateFormat = DateTimeFormat.forPattern(DEFAULT_ROTATION_FILE_SUFFIX); 068 } 069 this.timestampFilenameFilter = new TimestampFilenameFilter(initialFile, prefix, suffixDateFormat); 070 } 071 072 /** 073 * Gets the initial file. 074 * @return The initial file. 075 */ 076 @Override 077 public File getInitialName() { 078 return initialFile; 079 } 080 081 /** 082 * Gets the next name for this {@link FileNamingPolicy}. The next name will be formatted with prefix first, 083 * then the initial filename and finally the timestamp will be appended. 084 * @return The next archived file according to this {@link FileNamingPolicy}. 085 */ 086 @Override 087 public File getNextName() { 088 final StringBuilder newFileName = new StringBuilder(); 089 final Path path = initialFile.toPath(); 090 091 if (prefix != null) { 092 newFileName.append(prefix); 093 } 094 095 newFileName.append(path.getFileName()); 096 097 if (suffixDateFormat != null) { 098 newFileName.append(LocalDateTime.now().toString(suffixDateFormat)); 099 } 100 101 return path.resolveSibling(newFileName.toString()).toFile(); 102 } 103 104 /** 105 * List the files in the initial file directory that match the prefix, name and suffix format. 106 * {@inheritDoc} 107 */ 108 @Override 109 public List<File> listFiles() { 110 List<File> fileList = 111 new LinkedList<>(Arrays.asList(initialFile.getParentFile().listFiles(timestampFilenameFilter))); 112 // make sure the files are sorted from oldest to newest. 113 Collections.sort(fileList, Collections.reverseOrder(lastModifiedTimeFileComparator)); 114 return fileList; 115 } 116}