/*
* RESTHeart - the Web API for MongoDB
* Copyright (C) SoftInstigate Srl
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.restheart.utils;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.HashMap;
import java.util.Map;
import org.restheart.Bootstrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author Andrea Di Cesare {@literal <andrea@softinstigate.com>}
*/
public class ResourcesExtractor {
private static final Logger logger = LoggerFactory.getLogger(ResourcesExtractor.class);
/**
*
* @param resourcePath
* @return
* @throws URISyntaxException
*/
public static boolean isResourceInJar(String resourcePath) throws URISyntaxException {
URI uri = Bootstrapper.class.getClassLoader().getResource(resourcePath).toURI();
return uri.toString().startsWith("jar:");
}
/**
*
* @param resourcePath
* @param tempDir
* @throws URISyntaxException
* @throws IOException
*/
public static void deleteTempDir(String resourcePath, File tempDir) throws URISyntaxException, IOException {
if (isResourceInJar(resourcePath) && tempDir.exists()) {
delete(tempDir);
}
}
/**
*
* @param resourcePath
* @return
* @throws IOException
* @throws URISyntaxException
* @throws IllegalStateException
*/
public static File extract(String resourcePath) throws IOException, URISyntaxException, IllegalStateException {
//File jarFile = new File(ResourcesExtractor.class.getProtectionDomain().getCodeSource().getLocation().getPath());
if (Bootstrapper.class.getClassLoader().getResource(resourcePath) == null) {
logger.warn("no resource to extract from path {}", resourcePath);
throw new IllegalStateException("no resource to extract from path " + resourcePath);
}
URI uri = Bootstrapper.class.getClassLoader().getResource(resourcePath).toURI();
if (isResourceInJar(resourcePath)) {
FileSystem fs = null;
File ret = null;
try {
// used when run as a JAR file
Path destinationDir = Files.createTempDirectory("restheart-");
ret = destinationDir.toFile();
Map<String, String> env = new HashMap<>();
env.put("create", "false");
fs = FileSystems.newFileSystem(uri, env);
Path sourceDir = fs.getPath(resourcePath);
Files.walkFileTree(sourceDir, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
return copy(file);
}
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
return copy(dir);
}
private FileVisitResult copy(Path fileOrDir) throws IOException {
if (fileOrDir.equals(sourceDir)) {
return FileVisitResult.CONTINUE;
}
Path destination = Paths.get(destinationDir.toString(), fileOrDir.toString().replaceAll(resourcePath + "/", ""));
Files.copy(fileOrDir, destination, StandardCopyOption.REPLACE_EXISTING);
return FileVisitResult.CONTINUE;
}
});
} finally {
if (fs != null) {
fs.close();
}
}
return ret;
} else {
// used when run from an expanded folder
return new File(uri);
}
}
private static void delete(File file) throws IOException {
if (file.isDirectory()) {
//directory is empty, then delete it
if (file.list().length == 0) {
boolean deleted = file.delete();
if (!deleted) {
logger.warn("failted to delete directory " + file.getPath());
}
} else {
//list all the directory contents
String files[] = file.list();
for (String temp : files) {
//construct the file structure
File fileDelete = new File(file, temp);
//recursive delete
delete(fileDelete);
}
//check the directory again, if empty then delete it
if (file.list().length == 0) {
boolean deleted = file.delete();
if (!deleted) {
logger.warn("failted to delete file " + file.getPath());
}
}
}
} else {
//if file, then delete it
boolean deleted = file.delete();
if (!deleted) {
logger.warn("failted to delete file " + file.getPath());
}
}
}
private ResourcesExtractor() {
}
}