package org.araqne.log.api; import java.io.Closeable; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; public class LogFileHelper implements Closeable { public static final SimpleDateFormat logDateFormat = new SimpleDateFormat("yyyyMMdd HHmmss"); private String filePathFormat; private ArrayList<SimpleDateFormat> placeHolderFormats = new ArrayList<SimpleDateFormat>(); private File writerFile = null; private PrintWriter writer = null; private static Pattern placeHolderPattern = Pattern.compile("%%d\\{([^\\}]*)\\}"); private int fileDurationHour; public LogFileHelper(String format, int fileDurationHour) throws IllegalArgumentException { this.fileDurationHour = fileDurationHour; parse(format); } private void parse(String format) { // sanitize input format = Pattern.compile("%(.)").matcher(format).replaceAll("%%$1"); Matcher matcher = placeHolderPattern.matcher(format); StringBuilder builder = new StringBuilder(); int start = 0; int lastEnd = 0; while (matcher.find(start)) { builder.append(format.substring(start, matcher.start())); SimpleDateFormat f = new SimpleDateFormat(matcher.group(1)); placeHolderFormats.add(f); builder.append("%s"); lastEnd = matcher.end(); start = lastEnd; } builder.append(format.substring(lastEnd)); // sanitize input filePathFormat = builder.toString(); } public PrintWriter getWriter(Date date) throws FileNotFoundException { File curr = getCurrentFile(date); if (!curr.equals(writerFile)) { writerFile = curr; openNewWriter(writerFile); } return writer; } private void openNewWriter(File f) throws FileNotFoundException { if (writer != null) { System.out.println("file closed\n"); writer.close(); } writer = new PrintWriter(new FileOutputStream(f)); } @Override public void close() throws IOException { if (writer != null) { System.out.println("file closed\n"); writer.close(); } } public File getCurrentFile(Date date) { Date floored = floored(date, fileDurationHour); List<String> dateStrs = new ArrayList<String>(); for (SimpleDateFormat s : placeHolderFormats) { dateStrs.add(s.format(floored)); } return new File(String.format(filePathFormat, dateStrs.toArray())); } private Date floored(Date d, int durationHour) { Calendar cal = Calendar.getInstance(); cal.setTime(d); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); cal.set(Calendar.HOUR, cal.get(Calendar.HOUR) / durationHour * durationHour); return cal.getTime(); } public static void logicTest(String[] args) { // memo: (?:[^;]+;){3}([^;]+); String format = "/var/log/some_app/%d{yyyy-MM-dd}/some_prefix-%d{H}.log"; format = Pattern.compile("%(.)").matcher(format).replaceAll("%%$1"); System.out.println(format); Pattern placeHolderPattern = Pattern.compile("%%d\\{([^\\}]*)\\}"); Matcher matcher = placeHolderPattern.matcher(format); ArrayList<SimpleDateFormat> phf = new ArrayList<SimpleDateFormat>(); StringBuilder builder = new StringBuilder(); int start = 0; int lastEnd = 0; while (matcher.find(start)) { builder.append(format.substring(start, matcher.start())); phf.add(new SimpleDateFormat(matcher.group(1))); builder.append("%s"); lastEnd = matcher.end(); start = lastEnd; } builder.append(format.substring(lastEnd)); String formatStr = builder.toString(); System.out.println(formatStr); for (SimpleDateFormat f : phf) { System.out.println(f.toPattern()); } List<String> dateStrs = new ArrayList<String>(); Calendar cal = Calendar.getInstance(); cal.set(2013, 2, 2, 20, 14); // listFilesFrom Date d = cal.getTime(); Date current = new Date(); int cnt = 0; while (d.before(current) && cnt++ < 5) { dateStrs.clear(); for (SimpleDateFormat s : phf) { dateStrs.add(s.format(d)); } System.out.println(String.format(formatStr, dateStrs.toArray())); d.setTime(d.getTime() + 1000 * 60 * 60 * 2); } } public File[] listFilesFrom(Date startTime, Date current, boolean onlyExists) { ArrayList<File> files = new ArrayList<File>(); Date d = floored(startTime, fileDurationHour); while (d.before(current)) { ArrayList<String> dateStrs = new ArrayList<String>(); for (SimpleDateFormat s : placeHolderFormats) { dateStrs.add(s.format(d)); } File f = new File(String.format(filePathFormat, dateStrs.toArray())); if (!onlyExists || f.exists()) files.add(f); d.setTime(d.getTime() + fileDurationHour * 60 * 60 * 1000); } return files.toArray(new File[files.size()]); } }