TemporaryAssetFolder.java
/*
* Copyright (c) 2017, Stein Eldar Johnsen
*
* 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 net.morimekta.file;
import java.io.BufferedInputStream;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collection;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.nio.file.Files.newOutputStream;
import static java.nio.file.StandardOpenOption.APPEND;
import static java.nio.file.StandardOpenOption.CREATE;
import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;
/**
* A temporary asset folder where an arbitrary number of files can be added
* to and should guarantee complete cleanup on close. Example usage:
*
* <pre>{@code
* try (TemporaryAssetFolder tmp = new TemporaryAssetFolder(base)) {
* // do stuff
* }
* // is all deleted.
* }</pre>
* <p>
* This will create a temp folder into the base directory for each run, where
* any number of files or sub-folders can be added. All of it will be removed
* immediately on close.
*/
public class TemporaryAssetFolder implements Closeable {
private static final String PARENT_DIR = "..";
private final Path path;
public TemporaryAssetFolder() throws IOException {
this(Paths.get("/tmp/"));
}
public TemporaryAssetFolder(Path baseTempDirectory) throws IOException {
this(baseTempDirectory, "tmp");
}
public TemporaryAssetFolder(Path baseTempDirectory, String prefix) throws IOException {
path = Files.createTempDirectory(baseTempDirectory, prefix);
}
// --- list files ---
public Collection<Path> list() throws IOException {
return FileUtil.list(path);
}
public Collection<Path> list(boolean recursive) throws IOException {
return FileUtil.list(path, recursive);
}
// ---
public Path getPath() {
return path;
}
public File getFile() {
return getPath().toFile();
}
public Path resolvePath(String name) {
if (name.startsWith(File.separator)) {
throw new IllegalArgumentException("Absolute path not allowed in file name");
} else if (name.contains(File.separator + PARENT_DIR + File.separator) ||
name.startsWith(PARENT_DIR + File.separator)) {
throw new IllegalArgumentException("Up path not allowed in file name");
}
return getPath().resolve(name);
}
public File resolveFile(String name) {
return resolvePath(name).toFile();
}
// --- Add content
public Path put(String name, byte[] content) throws IOException {
Path file = resolvePath(name);
Path parent = file.getParent();
if (parent != null) {
Files.createDirectories(parent);
}
return Files.write(file, content, TRUNCATE_EXISTING, CREATE);
}
public Path put(String name, CharSequence content) throws IOException {
Path file = resolvePath(name);
Path parent = file.getParent();
if (parent != null) {
Files.createDirectories(parent);
}
return Files.writeString(file, content, TRUNCATE_EXISTING, CREATE);
}
public OutputStream getOutputStream(String name) throws IOException {
return getOutputStream(name, false);
}
public OutputStream getOutputStream(String name, boolean append) throws IOException {
Path file = resolvePath(name);
Path parent = file.getParent();
if (parent != null) {
Files.createDirectories(parent);
}
return newOutputStream(file, CREATE, append ? APPEND : TRUNCATE_EXISTING);
}
public Writer getWriter(String name) throws IOException {
return getWriter(name, false);
}
public Writer getWriter(String name, boolean append) throws IOException {
return new OutputStreamWriter(getOutputStream(name, append), UTF_8);
}
// --- Get Content ---
public String getString(String name) throws IOException {
return new String(getBytes(name), UTF_8);
}
public byte[] getBytes(String name) throws IOException {
try (InputStream in = getInputStream(name);
BufferedInputStream bis = new BufferedInputStream(in)) {
return bis.readAllBytes();
}
}
public Reader getReader(String name) throws IOException {
return new InputStreamReader(getInputStream(name), UTF_8);
}
public InputStream getInputStream(String name) throws IOException {
return Files.newInputStream(resolvePath(name));
}
@Override
public void close() throws IOException {
FileUtil.deleteRecursively(path);
}
}