/* * FileManager.java February 2008 * * Copyright (C) 2008, Niall Gallagher <niallg@users.sf.net> * * Licensed 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.simpleframework.util.buffer; import java.io.File; import java.io.FileFilter; import java.io.IOException; import org.simpleframework.util.thread.Daemon; /** * The <code>FileManager</code> object is used to create files that are to be * used for file buffers. All files created by this are created in the * <code>java.io.tmpdir</code> path. Temporary files created in this directory * last for five minutes before being deleted. This ensures that if the server * is running for a long period of time the file system is not exhausted. * * @author Niall Gallagher */ class FileManager extends Daemon implements FileFilter { /** * This is the prefix for the temporary files created. */ private String prefix; /** * This is the duration the files created will exist for. */ private long duration; /** * This determines whether the file system should clean up. */ private volatile boolean dead; /** * Constructor for the <code>FileManager</code> object. This will create a * thread that runs every five minutes and cleans up files that have been * created for buffers. Due to the period of time polled, files could exist * for up to ten minutes. * * @param prefix * this is the file name prefix for the files */ public FileManager(String prefix) { this(prefix, 300000); } /** * Constructor for the <code>FileManager</code> object. This will create a * thread that runs every five minutes and cleans up files that have been * created for buffers. Due to the period of time polled, files could exist * for up to ten minutes. * * @param prefix * this is the file name prefix for the files * @param duration * this is the duration the files exist for */ public FileManager(String prefix, long duration) { this.duration = duration; this.prefix = prefix; this.start(); } /** * This will create a temporary file which can be used as a buffer for * <code>FileBuffer</code> objects. The file returned by this method will be * created before it is returned, which ensures it can be used as a means to * buffer bytes. All files are created in the <code>java.io.tmpdir</code> * location, which represents the underlying file system temporary file * destination. * * @return this returns a created temporary file for buffers */ public File create() throws IOException { return this.create(this.prefix); } /** * This will create a temporary file which can be used as a buffer for * <code>FileBuffer</code> objects. The file returned by this method will be * created before it is returned, which ensures it can be used as a means to * buffer bytes. All files are created in the <code>java.io.tmpdir</code> * location, which represents the underlying file system temporary file * destination. * * @param prefix * this is the prefix of the file to be created * * @return this returns a created temporary file for buffers */ private File create(String prefix) throws IOException { File file = File.createTempFile(prefix, null); if (!file.exists()) { file.createNewFile(); } return file; } /** * This is the run method that will periodically poll the file file system * for temporary buffer files. If files matching the pattern are found and * have not been modified in the duration period of time then they will be * deleted to ensure that the file system is not exhausted during a long * server execution. */ @Override public void run() { while (!this.dead) { try { Thread.sleep(this.duration); this.clean(); } catch (Exception e) { continue; } } } /** * When this method is invoked the files that match the pattern of the * temporary files are evaluated for deletion. Only those files that have * not been modified in the duration period can be deleted. This ensures the * file system is not exhausted. */ private void clean() throws IOException { File path = this.create(); if (!path.isDirectory()) { path = path.getParentFile(); } this.clean(path); } /** * When this method is invoked the files that match the pattern of the * temporary files are evaluated for deletion. Only those files that have * not been modified in the duration period can be deleted. This ensures the * file system is not exhausted. * * @param path * this is the path of the file to be evaluated */ private void clean(File path) throws IOException { File[] list = path.listFiles(this); for (File next : list) { next.delete(); } } /** * This determines if the file provided is an acceptable file for deletion. * Acceptable files are those that match the pattern of files created by * this file system object. If the file is a matching file then it is a * candidate for deletion. * * @param file * this is the file to evaluate for deletion * * @return this returns true if the file matches the pattern */ @Override public boolean accept(File file) { String name = file.getName(); if (file.isDirectory()) return false; return this.accept(file, name); } /** * This determines if the file provided is an acceptable file for deletion. * Acceptable files are those that match the pattern of files created by * this file system object. If the file is a matching file then it is a * candidate for deletion. * * @param file * this is the file to evaluate for deletion * @param name * this is the name of the file to be evaluated * * @return this returns true if the file matches the pattern */ private boolean accept(File file, String name) { long time = System.currentTimeMillis(); long modified = file.lastModified(); if ((modified + this.duration) > time) return false; return name.startsWith(this.prefix); } /** * This method is used to close the allocator so that resources that are * occupied by the allocator can be freed. This will allow the allocator to * be created and closed repeatedly in a single process without holding on * to resources such as mapped file buffers or threads. */ public void close() throws IOException { if (!this.dead) { this.dead = true; this.interrupt(); this.clean(); } } }