// ================================================================================================= // Copyright 2011 Twitter, Inc. // ------------------------------------------------------------------------------------------------- // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this work except in compliance with the License. // You may obtain a copy of the License in the LICENSE file, or 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 com.twitter.common.io; import java.io.File; import java.io.IOException; import java.util.UUID; import com.google.common.base.Preconditions; import org.apache.commons.lang.SystemUtils; import com.twitter.common.base.ExceptionalClosure; import com.twitter.common.base.ExceptionalFunction; /** * Utility methods for working with files and directories. * * @author John Sirois */ public final class FileUtils { /** * A utility for creating and working with temporary files and directories. */ public static class Temporary { private static final int MAX_TMP_DIR_TRIES = 5; private final File basedir; /** * Creates a new temporary utility that creates files and directories rooted at {@code basedir}. * * @param basedir The base directory to generate temporary files and directories in. */ public Temporary(File basedir) { Preconditions.checkNotNull(basedir); Preconditions.checkArgument(basedir.exists()); this.basedir = basedir; } /** * Returns a new empty temporary directory. * * @return a file representing the newly created directory. * @throws IllegalStateException if a new temporary directory could not be created */ public File createDir() { File tempDir; int tries = 0; do { // For sanity sake, die eventually if we keep failing to pick a new unique directory name. if (++tries > MAX_TMP_DIR_TRIES) { throw new IllegalStateException("Failed to create a new temp directory in " + MAX_TMP_DIR_TRIES + " attempts, giving up"); } tempDir = new File(basedir, UUID.randomUUID().toString()); } while (!tempDir.mkdir()); return tempDir; } /** * Creates a new empty temporary file. * * @return a new empty temporary file * @throws IOException if there was a problem creating a new temporary file */ public File createFile() throws IOException { return createFile(".tempfile"); } /** * Creates a new empty temporary file with the given filename {@code suffix}. * * @param suffix The suffix for the temporary file name * @return a new empty temporary file * @throws IOException if there was a problem creating a new temporary file */ public File createFile(String suffix) throws IOException { return File.createTempFile(FileUtils.class.getName(), suffix, basedir); } /** * Creates a new temporary directory and executes the unit of {@code work} against it ensuring * the directory and its contents are removed after the work completes normally or abnormally. * * @param work The unit of work to execute against the new temporary directory. * @param <E> The type of exception this unit of work can throw. * @throws E bubbled transparently when the unit of work throws */ public <E extends Exception> void doWithDir(final ExceptionalClosure<File, E> work) throws E { Preconditions.checkNotNull(work); doWithDir(new ExceptionalFunction<File, Void, E>() { @Override public Void apply(File dir) throws E { work.execute(dir); return null; } }); } /** * Creates a new temporary directory and executes the unit of {@code work} against it ensuring * the directory and its contents are removed after the work completes normally or abnormally. * * @param work The unit of work to execute against the new temporary directory. * @param <T> The type of result this unit of work produces. * @param <E> The type of exception this unit of work can throw. * @return the result when the unit of work completes successfully * @throws E bubbled transparently when the unit of work throws */ public <T, E extends Exception> T doWithDir(ExceptionalFunction<File, T, E> work) throws E { Preconditions.checkNotNull(work); return doWithTemp(createDir(), work); } /** * Creates a new temporary file and executes the unit of {@code work} against it ensuring * the file is removed after the work completes normally or abnormally. * * @param work The unit of work to execute against the new temporary file. * @param <E> The type of exception this unit of work can throw. * @throws E bubbled transparently when the unit of work throws * @throws IOException if there was a problem creating a new temporary file */ public <E extends Exception> void doWithFile(final ExceptionalClosure<File, E> work) throws E, IOException { Preconditions.checkNotNull(work); doWithFile(new ExceptionalFunction<File, Void, E>() { @Override public Void apply(File dir) throws E { work.execute(dir); return null; } }); } /** * Creates a new temporary file and executes the unit of {@code work} against it ensuring * the file is removed after the work completes normally or abnormally. * * @param work The unit of work to execute against the new temporary file. * @param <T> The type of result this unit of work produces. * @param <E> The type of exception this unit of work can throw. * @return the result when the unit of work completes successfully * @throws E bubbled transparently when the unit of work throws * @throws IOException if there was a problem creating a new temporary file */ public <T, E extends Exception> T doWithFile(ExceptionalFunction<File, T, E> work) throws E, IOException { Preconditions.checkNotNull(work); return doWithTemp(createFile(), work); } private static <T, E extends Exception> T doWithTemp(File file, ExceptionalFunction<File, T, E> work) throws E { try { return work.apply(file); } finally { org.apache.commons.io.FileUtils.deleteQuietly(file); } } } /** * A temporary based at the default system temporary directory. */ public static final Temporary SYSTEM_TMP = new Temporary(SystemUtils.getJavaIoTmpDir()); /** * Returns a new empty temporary directory. * * @return a file representing the newly created directory. * @throws IllegalStateException if a new temporary directory could not be created */ public static File createTempDir() { return SYSTEM_TMP.createDir(); } private FileUtils() { // utility } }