/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.jackrabbit.core.journal; import java.io.File; import java.io.FilenameFilter; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Represents a log file that can be rotated. */ public class RotatingLogFile implements Comparable<RotatingLogFile> { /** * Logger. */ private static Logger log = LoggerFactory.getLogger(RotatingLogFile.class); /** * Log extension. */ private static final String LOG_EXTENSION = "log"; /** * Parent directory. */ private final File directory; /** * Basename. */ private final String basename; /** * Backing file. */ private final File file; /** * Version number. */ private int version; /** * Create a new instance of this class. * * @param file file itself * @throws IllegalArgumentException if the filename is malformed */ private RotatingLogFile(File directory, String basename, File file) throws IllegalArgumentException { this.directory = directory; this.basename = basename; this.file = file; parseName(); } /** * Parse the file name, ensuring that the file is actually made up * of the components we expect. * * @throws IllegalArgumentException if the name is malformed */ private void parseName() throws IllegalArgumentException { String name = file.getName(); int sep1 = name.indexOf('.'); if (sep1 == -1) { throw new IllegalArgumentException("no dot in filename."); } if (!basename.equals(name.substring(0, sep1))) { throw new IllegalArgumentException("name does not start with " + basename + "."); } int sep2 = name.indexOf('.', sep1 + 1); if (sep2 == -1) { sep2 = name.length(); } if (!LOG_EXTENSION.equals(name.substring(sep1 + 1, sep2))) { throw new IllegalArgumentException("name does not contain " + LOG_EXTENSION + "."); } if (sep2 < name.length()) { String versionS = name.substring(sep2 + 1); try { version = Integer.parseInt(versionS); } catch (NumberFormatException e) { throw new IllegalArgumentException( "extension is not a number: " + versionS); } } } /** * Return the backing file. */ public File getFile() { return file; } /** * Rotate this file. */ public void rotate() { String newName = basename + "." + LOG_EXTENSION + "." + String.valueOf(version + 1); file.renameTo(new File(directory, newName)); } /** * Compares this log file to another file. It will return * a negative number if this log file has a smaller version, * a positive number if this log file a bigger version * and <code>0</code> if they have the same version. */ public int compareTo(RotatingLogFile o) { return version - o.version; } /** * List all log files inside some directory. The list returned is * guaranteed to be in descending order, i.e. it is safe to rotate * every file in turn without accidentally overwriting another one. * * @param directory parent directory * @param basename basename expected * @return array of log files found */ public static RotatingLogFile[] listFiles(File directory, final String basename) { File[] files = directory.listFiles(new FilenameFilter() { public boolean accept(File dir, String name) { return name.startsWith(basename + "."); } }); ArrayList<RotatingLogFile> l = new ArrayList<RotatingLogFile>(); for (int i = 0; i < files.length; i++) { File file = files[i]; try { l.add(new RotatingLogFile(directory, basename, file)); } catch (IllegalArgumentException e) { log.warn("Bogusly named journal file, skipped: " + files[i] + ", reason: " + e.getMessage()); } } RotatingLogFile[] logFiles = new RotatingLogFile[l.size()]; l.toArray(logFiles); Arrays.sort(logFiles, new Comparator<RotatingLogFile>() { public int compare(RotatingLogFile o1, RotatingLogFile o2) { return o2.compareTo(o1); } }); return logFiles; } }