/*
* Copyright 2015-2017 the original author or authors.
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v1.0 which
* accompanies this distribution and is available at
*
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.junit.jupiter.extensions;
import java.io.IOException;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import org.junit.jupiter.api.extension.AfterEachCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.ExtensionContext.Namespace;
import org.junit.jupiter.api.extension.ParameterContext;
import org.junit.jupiter.api.extension.ParameterResolutionException;
import org.junit.jupiter.api.extension.ParameterResolver;
import org.junit.jupiter.api.extension.TestExtensionContext;
/**
* @since 1.0
*/
public class TempDirectory implements AfterEachCallback, ParameterResolver {
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Root {
}
private static final String KEY = "tempDirectory";
@Override
public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
return parameterContext.getParameter().isAnnotationPresent(Root.class)
&& parameterContext.getParameter().getType() == Path.class;
}
@Override
public Object resolveParameter(ParameterContext parameterContext, ExtensionContext context) {
return getLocalStore(context).getOrComputeIfAbsent(KEY, key -> createTempDirectory(context));
}
@Override
public void afterEach(TestExtensionContext context) throws Exception {
Path tempDirectory = (Path) getLocalStore(context).get(KEY);
if (tempDirectory != null) {
delete(tempDirectory);
}
}
private ExtensionContext.Store getLocalStore(ExtensionContext context) {
return context.getStore(localNamespace(context));
}
private Namespace localNamespace(ExtensionContext context) {
return Namespace.create(TempDirectory.class, context);
}
private Path createTempDirectory(ExtensionContext context) {
try {
String tempDirName;
if (context.getTestMethod().isPresent()) {
tempDirName = context.getTestMethod().get().getName();
}
else if (context.getTestClass().isPresent()) {
tempDirName = context.getTestClass().get().getName();
}
else {
tempDirName = context.getDisplayName();
}
return Files.createTempDirectory(tempDirName);
}
catch (IOException e) {
throw new ParameterResolutionException("Could not create temp directory", e);
}
}
private void delete(Path tempDirectory) throws IOException {
Files.walkFileTree(tempDirectory, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
return deleteAndContinue(file);
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
return deleteAndContinue(dir);
}
private FileVisitResult deleteAndContinue(Path path) throws IOException {
Files.delete(path);
return FileVisitResult.CONTINUE;
}
});
}
}