org.apache.ode.utils.fs.TempFileManager.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.ode.utils.fs.TempFileManager.java

Source

/*
 * 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.ode.utils.fs;

import org.apache.ode.utils.GUID;
import org.apache.ode.utils.SystemUtils;

import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.SortedSet;
import java.util.TreeSet;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Convenience class for managing temporary files and cleanup on JVM exit.
 */
public class TempFileManager {

    private static final Log __log = LogFactory.getLog(TempFileManager.class);

    private static TempFileManager __singleton;
    private static File __baseDir;
    private static File __workDir;

    private SortedSet<File> _registeredFiles = new TreeSet<File>(Collections.reverseOrder(null));

    private static synchronized TempFileManager getInstance() {
        if (__singleton == null) {
            __singleton = new TempFileManager();
        }
        return __singleton;
    }

    private TempFileManager() {
        super();

        if (__baseDir == null) {
            String tmpDirPath = null;
            try {
                tmpDirPath = SystemUtils.javaTemporaryDirectory();
            } catch (SecurityException se) {
                __log.error("Unable to read system property for temporary directory setting; "
                        + "will use default configuration.");
                tmpDirPath = "";
            }

            File tmpDir = new File(tmpDirPath);
            if (tmpDir.exists()) {
                __baseDir = tmpDir;
            } else {
                throw new IllegalStateException("Odd system configuration - temporary working directory "
                        + tmpDirPath + " does not exist.");
            }
        }

        try {
            File odeTmp = new File(__baseDir, "ode-" + new GUID().toString());
            if (odeTmp.mkdir()) {
                __workDir = odeTmp;
                __log.debug("Set working directory to: " + __workDir.getAbsolutePath());
                this._registerTemporaryFile(__workDir);
            } else {
                throw new IllegalStateException(
                        "Unable to create temporary working directory in " + __baseDir.getPath());
            }
        } catch (SecurityException se) {
            throw new IllegalStateException(
                    "The security configuration is preventing the creation of a " + "temporary working directory.",
                    se);
        }

    }

    /**
     * <p>
     * Set the working temporary directory.  This method can only be invoked when
     * the singleton instance is uninitialized, and the <code>File</code> passed in
     * must be both a directory and writable.
     * </p>
     * @param f the temporary working directory
     */
    public static synchronized void setWorkingDirectory(File f) {
        if (__singleton == null) {
            if (f == null) {
                __baseDir = null;
            } else {
                if (f.isDirectory() && f.canWrite()) {
                    __baseDir = f;
                    if (__log.isDebugEnabled()) {
                        __log.debug("Setting base working directory: " + f);
                    }
                } else {
                    throw new IllegalArgumentException("Not a writeable directory: " + f);
                }
            }
        }
        // cannot set working directory after an instance has been created;
        // call cleanup() first.
        else {
            String msg;
            if (__baseDir != null) {
                msg = "Already initialized in base directory: " + __baseDir.getPath();
            } else {
                msg = "Already initialized, but no base directory set.";
            }
            throw new IllegalStateException(msg);
        }
    }

    /**
     * <p>
     * Get a temporary file, if possible, and register it for cleanup later.  In the
     * event that a temporary file cannot be created, the method will attempt to
     * create a file in the current working directory instead.
     * </p>
     *
     * @param handle a prefix to use in naming the file; probably only useful for
     * debugging.
     * @return the temporary file.
     */
    public static synchronized File getTemporaryFile(String handle) {
        return getTemporaryFile(handle, __workDir);
    }

    public static synchronized File getTemporaryFile(String handle, File parent) {
        // force initialization if necessary
        if (__singleton == null) {
            getInstance();
        }

        if (handle == null) {
            handle = "temp-";
        }

        if (parent == null) {
            parent = (__workDir != null ? __workDir : __baseDir);
        }

        File tmp;
        try {
            tmp = File.createTempFile(handle + Long.toHexString(System.currentTimeMillis()), ".tmp", parent);
        } catch (IOException ioe) {
            __log.error("Unable to create temporary file in working directory "
                    + (parent == null ? "<null>; " : (parent.getPath() + "; "))
                    + "falling back to current working directory.", ioe);
            tmp = new File(handle + new GUID().toString());
        }

        registerTemporaryFile(tmp);
        return tmp;
    }

    /**
     * <p>
     * Get a temporary working directory.
     * </p>
     *
     * @param handle a prefix to use in naming the directory.
     * @return the temp directory.
     * @see #getTemporaryFile(String)
     */
    public static synchronized File getTemporaryDirectory(String handle) {
        return getTemporaryDirectory(handle, null);
    }

    public static synchronized File getTemporaryDirectory(String handle, File parent) {
        File f = getTemporaryFile(handle, parent);
        f.delete();
        f.mkdirs();
        return f;
    }

    /*
     * Register an externally created file/directory for later cleanup.
     */
    public static synchronized void registerTemporaryFile(File f) {
        getInstance()._registerTemporaryFile(f);
    }

    private synchronized void _registerTemporaryFile(File f) {
        _registeredFiles.add(f);
        if (__log.isDebugEnabled()) {
            __log.debug("Registered temporary file: " + f.getPath());
        }
    }

    /**
     * <p>
     * Clear out the temporary working directory.  This can be called by, e.g.,
     * a commandline tool or other client when it is known that all temporary
     * files can be deleted.
     * </p>
     */
    public static synchronized void cleanup() {
        if (__singleton != null) {
            __singleton._cleanup();
            __singleton = null;
        } else {
            __log.debug("No cleanup necessary.");
        }
    }

    @SuppressWarnings("unchecked")
    private synchronized void _cleanup() {
        try {
            // collect all subdirectory contents that still exist, ordered files-first
            SortedSet<File> allFiles = new TreeSet(Collections.reverseOrder(null));
            for (File f : _registeredFiles) {
                if (f.exists()) {
                    allFiles.addAll(FileUtils.directoryEntriesInPath(f));
                }
            }

            if (__log.isDebugEnabled()) {
                __log.debug("cleaning up " + allFiles.size() + " files.");
            }

            // now delete all files
            for (File f : allFiles) {
                if (__log.isDebugEnabled()) {
                    __log.debug("deleting: " + f.getAbsolutePath());
                }
                if (f.exists() && !f.delete()) {
                    __log.error("Unable to delete file " + f.getAbsolutePath()
                            + "; this may be caused by a descriptor leak and should be reported.");
                    // fall back to deletion on VM shutdown
                    f.deleteOnExit();
                }
            }
        } finally {
            _registeredFiles.clear();
            __workDir = null;
            __log.debug("cleanup done.");
        }
    }

}