FileManager.java
/*
* Copyright 2015-2016 Providence Authors
*
* 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.providence.generator.util;
import net.morimekta.util.FileUtil;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import static java.nio.file.StandardOpenOption.CREATE;
import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;
import static java.nio.file.StandardOpenOption.WRITE;
/**
* @author Stein Eldar Johnsen
* @since 19.09.15
*/
public class FileManager {
private final Path root;
private final Set<Path> generatedFiles;
private final Map<Path, Long> modificationTimeMap;
public FileManager(Path root) {
this.root = root;
this.generatedFiles = new HashSet<>();
this.modificationTimeMap = new HashMap<>();
}
@FunctionalInterface
public interface CreateHandler {
void create(OutputStream out) throws IOException;
}
public void createIfMissingOrOutdated(Path programFile,
String subPath,
String fileName,
CreateHandler create) throws IOException {
Path outputFile = absolutePath(subPath, fileName);
if (Files.exists(outputFile)) {
long programModified = getLastModifiedTime(programFile);
long outputModified = getLastModifiedTime(outputFile);
if (programModified < outputModified) {
return;
}
}
try (OutputStream out = createInternal(outputFile);
BufferedOutputStream buf = new BufferedOutputStream(out)) {
try {
create.create(buf);
} finally {
buf.flush();
}
}
}
private long getLastModifiedTime(Path path) throws IOException {
try {
return modificationTimeMap.computeIfAbsent(path, p -> {
try {
return Files.getLastModifiedTime(path).toMillis();
} catch (IOException e) {
throw new UncheckedIOException(e);
}
});
} catch (UncheckedIOException e) {
throw e.getCause();
}
}
private Path relativePath(Path path) {
return path.relativize(root);
}
private Path absolutePath(String path, String name) throws IOException {
Path tmp = root;
if (path != null) {
tmp = tmp.resolve(path);
}
tmp = tmp.resolve(name);
return FileUtil.readCanonicalPath(tmp);
}
private OutputStream createInternal(Path file) throws IOException {
if (generatedFiles.contains(file)) {
throw new IOException("File " + relativePath(file) + " already created.");
}
Files.createDirectories(file.getParent());
generatedFiles.add(file);
return Files.newOutputStream(file, WRITE, CREATE, TRUNCATE_EXISTING);
}
}