All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.maven.surefire.api.util.TempFileManager Maven / Gradle / Ivy

Go to download

API used in Surefire and Failsafe MOJO, Booter, Common and test framework providers.

There is a newer version: 3.5.2
Show newest version
/*
 * 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.maven.surefire.api.util;

import java.io.File;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Management of temporary files in surefire with support for sub directories of the system's directory
 * of temporary files.
* The {@link File#createTempFile(String, String)} API creates rather meaningless file names and * only in the system's temp directory.
* This class creates temp files from a prefix, a unique date/timestamp, a short file id and suffix. * It also helps you organize temporary files into sub-directories, * and thus avoid bloating the temp directory root.
* Apart from that, this class works in much the same way as {@link File#createTempFile(String, String)} * and {@link File#deleteOnExit()}, and can be used as a drop-in replacement. * * @author Markus Spann */ public final class TempFileManager { private static final Map INSTANCES = new LinkedHashMap<>(); /** An id unique across all file managers used as part of the temporary file's base name. */ private static final AtomicInteger FILE_ID = new AtomicInteger(1); private static final String SUFFIX_TMP = ".tmp"; private static Thread shutdownHook; /** The temporary directory or sub-directory under which temporary files are created. */ private final File tempDir; /** The fixed base name used between prefix and suffix of temporary files created by this class. */ private final String baseName; /** List of successfully created temporary files. */ private final List tempFiles; /** Temporary files are delete on JVM exit if true. */ private boolean deleteOnExit; private TempFileManager(File tempDir) { this.tempDir = tempDir; this.baseName = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS").format(LocalDateTime.now()); this.tempFiles = new ArrayList<>(); } private static File calcTempDir(String subDirName) { String tempDirName = subDirName == null ? null : subDirName.trim().isEmpty() ? null : subDirName.trim(); File tempDirCandidate = tempDirName == null ? new File(getJavaIoTmpDir()) : new File(getJavaIoTmpDir(), tempDirName); return tempDirCandidate; } public static TempFileManager instance() { return instance((File) null); } /** * Creates an instance using a subdirectory of the system's temporary directory. * @param subDirName name of subdirectory * @return instance */ public static TempFileManager instance(String subDirName) { return instance(calcTempDir(subDirName)); } public static synchronized TempFileManager instance(File tempDir) { // on creation of the first instance, register a shutdown hook to delete temporary files of all managers if (shutdownHook == null) { ThreadGroup tg = Thread.currentThread().getThreadGroup(); while (tg.getParent() != null) { tg = tg.getParent(); } shutdownHook = new Thread( tg, TempFileManager::shutdownAll, TempFileManager.class.getSimpleName() + "-ShutdownHook"); Runtime.getRuntime().addShutdownHook(shutdownHook); } return INSTANCES.computeIfAbsent(tempDir == null ? new File(getJavaIoTmpDir()) : tempDir, TempFileManager::new); } public synchronized void deleteAll() { tempFiles.forEach(File::delete); tempFiles.clear(); tempDir.delete(); } static void shutdownAll() { INSTANCES.values().stream().filter(TempFileManager::isDeleteOnExit).forEach(TempFileManager::deleteAll); } /** * Returns the temporary directory or sub-directory under which temporary files are created. * * @return temporary directory */ public File getTempDir() { return tempDir; } /** * Creates a new, uniquely-named temporary file in this object's {@link #tempDir} * with user-defined prefix and suffix (both may be null or empty and won't be trimmed). *

* This method behaves similarly to {@link java.io.File#createTempFile(String, String)} and * may be used as a drop-in replacement.
* This method is {@code synchronized} to help ensure uniqueness of temporary files. * * @param prefix optional file name prefix * @param suffix optional file name suffix * @return file object */ public synchronized File createTempFile(String prefix, String suffix) { // use only the file name from the supplied prefix prefix = prefix == null ? "" : (new File(prefix)).getName(); suffix = suffix == null ? "" : suffix; String name = String.join("-", prefix, baseName + "_" + FILE_ID.getAndIncrement()) + suffix; File tempFile = new File(tempDir, name); if (!name.equals(tempFile.getName())) { throw new UncheckedIOException(new IOException("Unable to create temporary file " + tempFile)); } if (tempFile.exists() || tempFiles.contains(tempFile)) { // temporary file already exists? Try another name return createTempFile(prefix, suffix); } else { // create temporary directory if (!tempDir.exists()) { if (!tempDir.mkdirs()) { throw new UncheckedIOException( new IOException("Unable to create temporary directory " + tempDir.getAbsolutePath())); } } try { tempFile.createNewFile(); } catch (IOException ex) { throw new UncheckedIOException("Unable to create temporary file " + tempFile.getAbsolutePath(), ex); } tempFiles.add(tempFile); return tempFile; } } public File createTempFile(String prefix) { return createTempFile(prefix, SUFFIX_TMP); } public boolean isDeleteOnExit() { return deleteOnExit; } /** * Instructs this file manager to delete its temporary files during JVM shutdown.
* This status can be turned on and off unlike {@link File#deleteOnExit()}. * * @param deleteOnExit delete the file in a shutdown hook on JVM exit */ public void setDeleteOnExit(boolean deleteOnExit) { this.deleteOnExit = deleteOnExit; } @Override public String toString() { return String.format( "%s[tempDir=%s, deleteOnExit=%s, baseName=%s, tempFiles=%d]", getClass().getSimpleName(), tempDir, deleteOnExit, baseName, tempFiles.size()); } /** * Returns the value of system property {@code java.io.tmpdir}, the system's temp directory. * * @return path to system temp directory */ public static String getJavaIoTmpDir() { String tmpDir = System.getProperty("java.io.tmpdir"); if (!tmpDir.endsWith(File.separator)) { tmpDir += File.separatorChar; } return tmpDir; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy