1 package org.quartz.jobs; 2 3 import java.io.File ; 4 import java.io.FileFilter ; 5 import java.text.ParseException ; 6 import java.text.SimpleDateFormat ; 7 import java.util.ArrayList ; 8 import java.util.Calendar ; 9 import java.util.Date ; 10 import java.util.GregorianCalendar ; 11 import java.util.Iterator ; 12 import java.util.List ; 13 import java.util.regex.Matcher ; 14 import java.util.regex.Pattern ; 15 16 import org.apache.commons.logging.Log; 17 import org.apache.commons.logging.LogFactory; 18 import org.quartz.Job; 19 import org.quartz.JobDataMap; 20 import org.quartz.JobExecutionContext; 21 import org.quartz.JobExecutionException; 22 23 37 public class LogCleanerJob implements Job { 38 private static final Log logWriter = LogFactory.getLog(LogCleanerJob.class); 39 40 public static final String DATAMAP_KEY_LOG_DIR = "log-dir"; 41 public static final String DATAMAP_KEY_DELETE_IF_AGE_GREATER_THAN_DAYS = "delete-if-age-greater-than-days"; 42 public static final String DATAMAP_KEY_DATE_IN_FILENAME_REGEX = "date-in-filename-regex"; 43 public static final String DATAMAP_KEY_FILENAME_SIMPLE_DATE_FORMAT_PATTERN = "filename-simple-date-format-pattern"; 44 public static final String DATAMAP_KEY_DELETE_EMPTY_DIRS = "delete-empty-dirs"; 45 46 102 public void execute(JobExecutionContext context) throws JobExecutionException { 103 final JobDataMap jobDataMap = context.getMergedJobDataMap(); 104 105 if (jobDataMap == null || jobDataMap.isEmpty()) { 106 throw new JobExecutionException("the job data map is null or empty"); 107 } 108 109 final String logDir = jobDataMap.getString(DATAMAP_KEY_LOG_DIR); 110 111 if (logDir == null || logDir.trim().length() == 0) { 112 throw new JobExecutionException(DATAMAP_KEY_LOG_DIR + " is null or empty"); 113 } 114 115 final File logDirFile = new File (logDir); 116 117 if (!logDirFile.isDirectory()) { 118 throw new JobExecutionException(DATAMAP_KEY_LOG_DIR + " is not a directory"); 119 } 120 121 final int deleteIfAgeGreaterThanDays = jobDataMap.getIntFromString(DATAMAP_KEY_DELETE_IF_AGE_GREATER_THAN_DAYS); 122 123 final GregorianCalendar gc = new GregorianCalendar (); 124 gc.add(Calendar.DAY_OF_MONTH, - deleteIfAgeGreaterThanDays); 125 final Date deleteIfBeforeThisDate = gc.getTime(); 126 127 final String dateInFileNameRegex = jobDataMap.getString(DATAMAP_KEY_DATE_IN_FILENAME_REGEX); 128 129 if (dateInFileNameRegex == null || dateInFileNameRegex.trim().length() == 0) { 130 throw new JobExecutionException(DATAMAP_KEY_DATE_IN_FILENAME_REGEX + " is null or empty"); 131 } 132 133 final String dateFormatterPattern = jobDataMap.getString(DATAMAP_KEY_FILENAME_SIMPLE_DATE_FORMAT_PATTERN); 134 135 if (dateFormatterPattern == null || dateFormatterPattern.trim().length() == 0) { 136 throw new JobExecutionException(DATAMAP_KEY_FILENAME_SIMPLE_DATE_FORMAT_PATTERN + " is null or empty"); 137 } 138 139 deleteSelectedFiles(logDirFile, deleteIfBeforeThisDate, dateInFileNameRegex, dateFormatterPattern); 140 141 if (jobDataMap.getBooleanValueFromString(DATAMAP_KEY_DELETE_EMPTY_DIRS)) { 142 deleteEmptyDirsRecursively(logDirFile); 143 } 144 } 145 146 private static void deleteSelectedFiles(File baseDir, Date deleteIfBeforeThisDate, String dateInFileNameRegex, String dateFormatterPattern) throws JobExecutionException { 147 logWriter.debug("deleteSelectedFiles: baseDir=" + baseDir + ", deleteIfBeforeThisDate=" + deleteIfBeforeThisDate + ", dateInFileNameRegex=" + dateInFileNameRegex + ", dateFormatterPattern=" + dateFormatterPattern); 148 final List fileList = getFileListRecursively(baseDir); 149 final Iterator fileListIterator = fileList.iterator(); 150 final Pattern p = Pattern.compile(dateInFileNameRegex); 151 final SimpleDateFormat format = new SimpleDateFormat (dateFormatterPattern); 152 long successfullyDeletedFileCount = 0L; 153 long failedToDeleteFileCount = 0L; 154 long notToBeDeletedFileCount = 0L; 155 156 try { 157 while (fileListIterator.hasNext()) { 158 final File f = (File ) fileListIterator.next(); 159 final String fileName = f.getName(); 160 final Matcher m = p.matcher(fileName); 161 162 if (m.matches() && m.groupCount() == 1) { 163 logWriter.debug("fileName matches: fileName=" + fileName); 164 final String dateString = m.group(1); 165 logWriter.debug("inferred date from fileName: dateString=" + dateString); 166 final Date parsedDate = format.parse(dateString); 167 logWriter.debug("inferred date as parsed by SimpleDateFormat: parsedDate=" + parsedDate); 168 169 if (parsedDate.before(deleteIfBeforeThisDate)) { 170 logWriter.debug("file's date is before specified trigger date, file will be deleted: file=" + f + ", deleteIfBeforeThisDate=" + deleteIfBeforeThisDate); 171 if (f.delete()) { 172 successfullyDeletedFileCount++; 173 logWriter.info("successfully deleted file because it was older than specified date: file=" + f + ", deleteIfBeforeThisDate=" + deleteIfBeforeThisDate); 174 } else { 175 failedToDeleteFileCount++; 176 logWriter.warn("unable to delete file: file=" + f.toString()); 177 } 178 } else { 179 notToBeDeletedFileCount++; 180 logWriter.debug("file's date is after specified trigger date, file will NOT be deleted: file=" + f + ", deleteIfBeforeThisDate=" + deleteIfBeforeThisDate); 181 } 182 } 183 } 184 } catch (ParseException ex) { 185 throw new JobExecutionException("error parsing file date", ex, false); 186 } 187 logWriter.debug("deleteSelectedFiles: successfullyDeletedFileCount=" + successfullyDeletedFileCount + ", failedToDeleteFileCount=" + failedToDeleteFileCount + ", notToBeDeletedFileCount=" + notToBeDeletedFileCount); 188 } 189 190 private static List getFileListRecursively(File baseDir) { 191 final List fileList = new ArrayList (); 192 getFileListRecursively(baseDir, fileList); 193 return fileList; 194 } 195 196 private static void getFileListRecursively(File baseDir, List fileList) { 197 if (!baseDir.isDirectory()) { 198 return; 199 } 200 201 final File [] fileArray = baseDir.listFiles(); 202 203 if (fileArray == null || fileArray.length == 0) { 204 return; 205 } 206 207 for (int i = 0; i < fileArray.length; i++) { 208 if (fileArray[i].isDirectory()) { 209 getFileListRecursively(fileArray[i], fileList); } else if (fileArray[i].isFile()) { 211 fileList.add(fileArray[i]); 212 } 213 } 214 } 215 216 private static void deleteEmptyDirsRecursively(File baseDir) { 217 logWriter.debug("deleteEmptyDirsRecursively: baseDir=" + baseDir); 218 219 final List dirList = new ArrayList (); 220 getDirListRecursively(baseDir, dirList); 221 final Iterator i = dirList.iterator(); 222 long successfullyDeletedDirCount = 0L; 223 long failedToDeleteDirCount = 0L; 224 long notToBeDeletedDirCount = 0L; 225 226 while (i.hasNext()) { 227 final File dir = (File ) i.next(); 228 if (isEmptyDir(dir)) { 229 if (dir.delete()) { 230 successfullyDeletedDirCount++; 231 logWriter.info("successfully deleted empty dir: dir=" + dir); 232 } else { 233 failedToDeleteDirCount++; 234 logWriter.warn("unable to delete empty dir: dir=" + dir); 235 } 236 } else { 237 notToBeDeletedDirCount++; 238 logWriter.debug("the directory is not empty and will not be deleted: dir=" + dir); 239 } 240 } 241 logWriter.debug("deleteEmptyDirsRecursively: successfullyDeletedDirCount=" + successfullyDeletedDirCount + ", failedToDeleteDirCount=" + failedToDeleteDirCount + ", notToBeDeletedDirCount=" + notToBeDeletedDirCount); 242 } 243 244 private static void getDirListRecursively(File baseDir, List dirList) { 245 if (!baseDir.isDirectory()) { 246 return; 247 } 248 249 final File [] dirArray = baseDir.listFiles(new FileFilter () { 250 public boolean accept(File pathname) { 251 return pathname.isDirectory(); 252 } 253 }); 254 255 if (dirArray == null || dirArray.length == 0) { 256 return; 257 } 258 259 for (int i = 0; i < dirArray.length; i++) { 260 dirList.add(dirArray[i]); 261 getDirListRecursively(dirArray[i], dirList); } 263 } 264 265 private static boolean isEmptyDir(File dir) { 266 if (!dir.isDirectory()) { 267 return false; 268 } 269 final File [] fileArray = dir.listFiles(); 270 return fileArray != null && fileArray.length == 0; 271 } 272 273 } 274 | Popular Tags |