package org.cagrid.trust.service.core;
import gov.nih.nci.cagrid.common.Utils;
import java.io.File;
import java.io.FileFilter;
import java.io.FileReader;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import org.cagrid.core.xml.XMLUtils;
import org.cagrid.trust.model.DateFilter;
import org.cagrid.trust.model.SyncReport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author <A href="mailto:langella@bmi.osu.edu">Stephen Langella </A>
* @author <A href="mailto:oster@bmi.osu.edu">Scott Oster </A>
* @author <A href="mailto:hastings@bmi.osu.edu">Shannon Hastings </A>
* @author <A href="mailto:David.Ervin@osumc.edu">David W. Ervin</A>
* @version $Id: ArgumentManagerTable.java,v 1.2 2004/10/15 16:35:16 langella
* Exp $
*/
public class DefaultHistoryManager implements HistoryManager {
public static final int DEFAULT_MAX_REPORTS = 150;
public static final String MAX_REPORTS_PROPERTY = "max.sync.reports";
private Logger log;
private File historyDirectory;
public DefaultHistoryManager(String historyDirectory) {
log = LoggerFactory.getLogger(this.getClass().getName());
this.historyDirectory = new File(historyDirectory);
this.historyDirectory.mkdirs();
}
public File addReport(SyncReport report) throws Exception {
File r = getFile(report.getTimeOfSync());
XMLUtils.toXMLFile(report, r);
return r;
}
public SyncReport getReport(String fileName) throws Exception {
return (SyncReport) XMLUtils.fromXMLFile(SyncReport.class, new File(fileName));
}
public SyncReport getLastReport() throws Exception {
File dir = getLastDayDir();
if (dir != null) {
File last = null;
if (dir != null && dir.exists()) {
File[] files = dir.listFiles(new FileFilter() {
public boolean accept(File pathname) {
return pathname.getName().endsWith(".xml");
}
});
if (files != null) {
sortByFilename(files);
last = files[files.length - 1];
}
}
if (last != null) {
return getReport(last.getAbsolutePath());
}
}
return null;
}
private File getLastDayDir() {
return getLastDir(getLastMonthDir());
}
private File getLastMonthDir() {
return getLastDir(getLastYearDir());
}
private File getLastYearDir() {
return getLastDir(getHistoryDirectory());
}
private File getLastDir(File dir) {
File last = null;
if (dir != null && dir.exists()) {
File[] dirs = dir.listFiles(new FileFilter() {
public boolean accept(File pathname) {
return pathname.isDirectory();
}
});
if (dirs != null) {
sortByFilename(dirs);
last = dirs[dirs.length - 1];
}
}
return last;
}
public SyncReport[] search(DateFilter startDate, DateFilter end) throws Exception {
DateFilter start = new DateFilter();
start.setDay(startDate.getDay());
start.setMonth(startDate.getMonth());
start.setYear(startDate.getYear());
SyncReport[] reports = new SyncReport[DEFAULT_MAX_REPORTS];
int checkMax = 0;
int iterator = 0;
this.incrementDate(end);
while (!start.equals(end)) {
File startDir = getDirectory(start);
if ((startDir.exists()) && (startDir.isDirectory())) {
String[] fileList = startDir.list();
checkMax = checkMax + fileList.length;
if (checkMax > DEFAULT_MAX_REPORTS)
throw new Exception();
else {
for (int i = 0; i < fileList.length; i++) {
File inputFile = new File(startDir.getAbsolutePath() + File.separator + fileList[i]);
FileReader in = new FileReader(inputFile);
if (in.read() != -1) {
reports[iterator] = this.getReport(startDir.getAbsolutePath() + File.separator + fileList[i]);
iterator++;
} else {
in.close();
throw new Exception();
}
in.close();
}
}
}
this.incrementDate(start);
}
SyncReport[] returnReports = new SyncReport[checkMax];
System.arraycopy(reports, 0, returnReports, 0, returnReports.length);
return returnReports;
}
public SyncReport[] search(DateFilter startDate, DateFilter end, File histDir) throws Exception {
DateFilter start = new DateFilter();
start.setDay(startDate.getDay());
start.setMonth(startDate.getMonth());
start.setYear(startDate.getYear());
SyncReport[] reports = new SyncReport[DEFAULT_MAX_REPORTS];
int checkMax = 0;
int iterator = 0;
this.incrementDate(end);
while (!start.equals(end)) {
File startDir = getDirectory(start, histDir);
if ((startDir.exists()) && (startDir.isDirectory())) {
String[] fileList = startDir.list();
checkMax = checkMax + fileList.length;
if (checkMax > DEFAULT_MAX_REPORTS)
throw new Exception();
else {
for (int i = 0; i < fileList.length; i++) {
File inputFile = new File(startDir.getAbsolutePath() + File.separator + fileList[i]);
FileReader in = new FileReader(inputFile);
if (in.read() != -1) {
reports[iterator] = this.getReport(startDir.getAbsolutePath() + File.separator + fileList[i]);
iterator++;
} else {
in.close();
throw new Exception();
}
in.close();
}
}
}
this.incrementDate(start);
}
SyncReport[] returnReports = new SyncReport[checkMax];
System.arraycopy(reports, 0, returnReports, 0, returnReports.length);
return returnReports;
}
private File getFile(Date timestamp) {
File dir = getDirectory(timestamp);
return new File(dir.getAbsolutePath() + File.separator + timestamp.getTime() + ".xml");
}
protected File getHistoryDirectory() {
return historyDirectory;
}
private File getDirectory(DateFilter f) {
File histDir = getHistoryDirectory();
return getDirectory(f, histDir);
}
private File getDirectory(DateFilter f, File histDir) {
String month;
String day;
if (f.getMonth() < 10) {
month = "0" + f.getMonth();
} else {
month = "" + f.getMonth();
}
if (f.getDay() < 10) {
day = "0" + f.getDay();
} else {
day = "" + f.getDay();
}
File dir = new File(histDir, f.getYear() + File.separator + month + File.separator + day);
return dir;
}
private File getDirectory(Date timestamp) {
Calendar c = new GregorianCalendar();
c.setTime(timestamp);
int year = c.get(Calendar.YEAR);
int month = c.get(Calendar.MONTH) + 1;
String strMonth = "";
if (month < 10) {
strMonth = strMonth + "0";
}
strMonth = strMonth + month;
int day = c.get(Calendar.DAY_OF_MONTH);
String dom = "";
if (day < 10) {
dom = dom + "0";
}
dom = dom + day;
File histDir = getHistoryDirectory();
File dir = new File(histDir, year + File.separator + strMonth + File.separator + dom);
dir.mkdirs();
return dir;
}
private void incrementDate(DateFilter f) {
Calendar cal = Calendar.getInstance();
// lenient calendar since the old implementation allowed
// conditions like "Feb 31st" to exist...
cal.setLenient(true);
// set up the current date
cal.set(Calendar.YEAR, f.getYear());
cal.set(Calendar.MONTH, f.getMonth() - 1);
cal.set(Calendar.DAY_OF_MONTH, f.getDay());
// move forward one day
cal.roll(Calendar.DAY_OF_MONTH, 1);
// put the date back into the DateFilter bean
f.setDay(cal.get(Calendar.DAY_OF_MONTH));
f.setMonth(cal.get(Calendar.MONTH + 1));
f.setYear(cal.get(Calendar.YEAR));
}
private void sortByFilename(File[] files) {
Comparator<File> comp = new Comparator<File>() {
public int compare(File o1, File o2) {
return o1.getName().compareTo(o2.getName());
}
};
Arrays.sort(files, comp);
}
public void prune(DateFilter filter) throws Exception {
Calendar c = new GregorianCalendar();
c.add(Calendar.YEAR, filter.getYear());
c.add(Calendar.MONTH, filter.getMonth());
c.add(Calendar.DAY_OF_MONTH, filter.getDay());
// list all the history files and dirs in date order
List<File> historyFiles = listHistoryFilesByDate();
for (File f : historyFiles) {
if (f.isFile() && f.getName().endsWith(".xml")) {
String fileName = f.getName();
int index = fileName.indexOf(".xml");
String timestamp = fileName.substring(0, index);
Date fileDate = new Date(Long.valueOf(timestamp));
if (fileDate.after(c.getTime())) {
log.debug("Pruning the report " + f.getAbsolutePath() + " the report was created on " + fileDate.toString() + " which is after the cache allowed date of " + c.getTime().toString()
+ ".");
File parent = f.getParentFile();
f.delete();
deleteIfEmpty(parent);
}
}
}
// clean up any empty directories
for (File f : historyFiles) {
if (f.exists() && f.isDirectory()) {
List<File> contents = Utils.recursiveListFiles(f, new FileFilter() {
public boolean accept(File pathname) {
return true;
}
});
boolean empty = true;
for (File content : contents) {
if (content.isFile()) {
empty = false;
}
}
if (empty) {
Utils.deleteDir(f);
}
}
}
}
private List<File> listHistoryFilesByDate() {
final File historyDir = getHistoryDirectory();
List<File> historyFiles = Utils.recursiveListFiles(historyDir, new FileFilter() {
public boolean accept(File pathname) {
return pathname.getName().endsWith(".xml") || pathname.isDirectory();
}
});
Comparator<File> comp = new Comparator<File>() {
public int compare(File o1, File o2) {
int val = 0;
try {
String rel1 = Utils.getRelativePath(historyDir, o1);
String rel2 = Utils.getRelativePath(historyDir, o2);
val = rel1.compareTo(rel2);
} catch (Exception ex) {
// uhoh
}
return val;
}
};
Collections.sort(historyFiles, comp);
return historyFiles;
}
private void deleteIfEmpty(File dir) {
if (dir.isDirectory()) {
File files[] = dir.listFiles();
if ((files == null) || (files.length == 0)) {
File parent = dir.getParentFile();
log.debug("Deleting the directory " + dir.getAbsolutePath() + " no more reports exist in the directory.");
dir.delete();
deleteIfEmpty(parent);
}
}
}
}