/* | |
* 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.axis2.deployment.util; | |
import java.io.ByteArrayOutputStream; | |
import java.io.File; | |
import java.io.FileFilter; | |
import java.io.IOException; | |
import java.io.PrintStream; | |
import java.util.logging.Level; | |
import java.util.logging.Logger; | |
/** | |
* Generates and properly cleans up temporary files. Similar to {@link | |
* File#createTempFile(java.lang.String, java.lang.String)}, this class provides a static method to | |
* create temporary files. The temporary files will be created in a special directory to be cleaned | |
* up the next time this class is loaded by the JVM. This functionality is required because Win32 | |
* platforms will not allow the JVM to delete files that are open. This causes problems with items | |
* such as JARs that get opened by a URLClassLoader and can therefore not be deleted by the JVM | |
* (including deleteOnExit). | |
* <p/> | |
* The caller should not need to create an instance of this class, although it is possible. Simply | |
* use the static methods to perform the required operations. Note that all files created by this | |
* class should be considered as deleted at JVM exit (although the actual deletion may be delayed). | |
* If persistent temporary files are required, use {@link java.io.File} instead. | |
* <p/> | |
* Refer to Sun bugs 4171239 and 4950148 for more details. | |
* <p/> | |
* Thanks to Mike Pilone for this code, which was sourced from | |
* http://www.devx.com/Java/Article/22018/ and contributed to Apache. | |
*/ | |
public class TempFileManager { | |
/** | |
* Creates a temporary file in the proper directory to allow for cleanup after execution. This | |
* method delegates to {@link File#createTempFile(java.lang.String, java.lang.String, | |
* java.io.File)} so refer to it for more documentation. Any file created using this method should | |
* be considered as deleted at JVM exit; therefore, do not use this method to create files that | |
* need to be persistent between application runs. | |
* | |
* @param prefix the prefix string used in generating the file name; must be at least three | |
* characters long | |
* @param suffix the suffix string to be used in generating the file's name; may be null, in which | |
* case the suffix ".tmp" will be used | |
* @return an abstract pathname denoting a newly created empty file | |
* @throws IOException if a file could not be created | |
*/ | |
@SuppressWarnings({"ResultOfMethodCallIgnored"}) | |
public static File createTempFile(String prefix, String suffix) | |
throws IOException { | |
// Check to see if you have already initialized a temp directory | |
// for this class. | |
if (sTmpDir == null) { | |
// Initialize your temp directory. You use the java temp directory | |
// property, so you are sure to find the files on the next run. | |
String tmpDirName = System.getProperty("java.io.tmpdir"); | |
File tmpDir = File.createTempFile(TEMP_DIR_PREFIX, ".tmp", | |
new File(tmpDirName)); | |
// Delete the file if one was automatically created by the JVM. | |
// You are going to use the name of the file as a directory name, | |
// so you do not want the file laying around. | |
tmpDir.delete(); | |
// Create a lock before creating the directory so | |
// there is no race condition with another application trying | |
// to clean your temp dir. | |
File lockFile = new File(tmpDirName, tmpDir.getName() + ".lck"); | |
lockFile.createNewFile(); | |
// Set the lock file to delete on exit so it is properly cleaned | |
// by the JVM. This will allow the TempFileManager to clean | |
// the overall temp directory next time. | |
lockFile.deleteOnExit(); | |
// Make a temp directory that you will use for all future requests. | |
if (!tmpDir.mkdirs()) { | |
throw new IOException("Unable to create temporary directory:" | |
+ tmpDir.getAbsolutePath()); | |
} | |
sTmpDir = tmpDir; | |
} | |
// Generate a temp file for the user in your temp directory | |
// and return it. | |
return File.createTempFile(prefix, suffix, sTmpDir); | |
} | |
/** | |
* Utility method to load the TempFileManager at any time and allow it to clean the temporary | |
* files that may be left from previous instances | |
* | |
* @param args command line arguments are currently not supported | |
*/ | |
public static void main(String[] args) { | |
// Although the JVM will load the class in order to | |
// run the main method, this gives a little clarity to | |
// what is happening and why we want the main method. | |
try { | |
// This will load the TempFileManager, which will | |
// cause the static block to execute, cleaning | |
// any old temp files. | |
Class.forName(TempFileManager.class.getName()); | |
} | |
catch (ClassNotFoundException ex) { | |
ex.printStackTrace(); | |
} | |
} | |
/** | |
* Deletes all of the files in the given directory, recursing into any sub directories found. Also | |
* deletes the root directory. | |
* | |
* @param rootDir the root directory to be recursively deleted | |
* @throws IOException if any file or directory could not be deleted | |
*/ | |
private static void recursiveDelete(File rootDir) | |
throws IOException { | |
// Select all the files | |
File[] files = rootDir.listFiles(); | |
if (files != null) { | |
for (File file : files) { | |
// If the file is a directory, we will | |
// recursively call delete on it. | |
if (file.isDirectory()) { | |
recursiveDelete(file); | |
} else { | |
// It is just a file so we are safe to | |
// delete it | |
if (!file.delete()) { | |
throw new IOException("Could not delete: " + file.getAbsolutePath()); | |
} | |
} | |
} | |
} | |
// Finally, delete the root directory now | |
// that all of the files in the directory have | |
// been properly deleted. | |
if (!rootDir.delete()) { | |
throw new IOException("Could not delete: " + rootDir.getAbsolutePath()); | |
} | |
} | |
/** The prefix for the temp directory in the system temp directory */ | |
private final static String TEMP_DIR_PREFIX = "axis2-tmp-"; | |
/** The temp directory to generate all files in */ | |
private static File sTmpDir = null; | |
/** | |
* Static block used to clean up any old temp directories found -- the JVM | |
* will run this block when a class loader loads the class. | |
*/ | |
static { | |
// Clean up any old temp directories by listing | |
// all of the files, using a filter that will | |
// return only directories that start with your | |
// prefix. | |
FileFilter tmpDirFilter = | |
new FileFilter() { | |
public boolean accept(File pathname) { | |
return (pathname.isDirectory() && | |
pathname.getName().startsWith(TEMP_DIR_PREFIX)); | |
} | |
}; | |
// Get the system temp directory and filter the files. | |
String tmpDirName = System.getProperty("java.io.tmpdir"); | |
File tmpDir = new File(tmpDirName); | |
File[] tmpFiles = tmpDir.listFiles(tmpDirFilter); | |
// Find all the files that do not have a lock by | |
// checking if the lock file exists. | |
if (tmpFiles != null) { | |
for (File tmpFile : tmpFiles) { | |
// Create a file to represent the lock and test. | |
File lockFile = new File(tmpFile.getParent(), tmpFile.getName() + ".lck"); | |
if (!lockFile.exists()) { | |
// Delete the contents of the directory since | |
// it is no longer locked. | |
Logger.getLogger("default").log(Level.FINE, | |
"TempFileManager::deleting old temp directory " + | |
tmpFile); | |
try { | |
recursiveDelete(tmpFile); | |
} | |
catch (IOException ex) { | |
// You log at a fine level since not being able to delete | |
// the temp directory should not stop the application | |
// from performing correctly. However, if the application | |
// generates a lot of temp files, this could become | |
// a disk space problem and the level should be raised. | |
Logger.getLogger("default").log(Level.INFO, | |
"TempFileManager::unable to delete " + | |
tmpFile.getAbsolutePath()); | |
// Print the exception. | |
ByteArrayOutputStream ostream = new ByteArrayOutputStream(); | |
ex.printStackTrace(new PrintStream(ostream)); | |
Logger.getLogger("default").log(Level.FINE, ostream.toString()); | |
} | |
} | |
} | |
} | |
} | |
} |