package com.networknt.utility;
import com.networknt.config.Config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.nio.ByteBuffer;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import static java.io.File.separator;
import static java.nio.charset.StandardCharsets.UTF_8;
/**
* Created by steve on 26/04/17.
*/
public class NioUtils {
static final Logger logger = LoggerFactory.getLogger(NioUtils.class);
/**
* Returns a zip file system
* @param zipFilename to construct the file system from
* @param create true if the zip file should be created
* @return a zip file system
* @throws IOException
*/
private static FileSystem createZipFileSystem(String zipFilename, boolean create) throws IOException {
// convert the filename to a URI
final Path path = Paths.get(zipFilename);
if(Files.notExists(path.getParent())) {
Files.createDirectories(path.getParent());
}
final URI uri = URI.create("jar:file:" + path.toUri().getPath());
final Map<String, String> env = new HashMap<>();
if (create) {
env.put("create", "true");
}
return FileSystems.newFileSystem(uri, env);
}
/**
* Unzips the specified zip file to the specified destination directory.
* Replaces any files in the destination, if they already exist.
* @param zipFilename the name of the zip file to extract
* @param destDirname the directory to unzip to
* @throws IOException
*/
public static void unzip(String zipFilename, String destDirname)
throws IOException{
final Path destDir = Paths.get(destDirname);
//if the destination doesn't exist, create it
if(Files.notExists(destDir)){
if(logger.isDebugEnabled()) logger.debug(destDir + " does not exist. Creating...");
Files.createDirectories(destDir);
}
try (FileSystem zipFileSystem = createZipFileSystem(zipFilename, false)){
final Path root = zipFileSystem.getPath("/");
//walk the zip file tree and copy files to the destination
Files.walkFileTree(root, new SimpleFileVisitor<Path>(){
@Override
public FileVisitResult visitFile(Path file,
BasicFileAttributes attrs) throws IOException {
final Path destFile = Paths.get(destDir.toString(),
file.toString());
if(logger.isDebugEnabled()) logger.debug("Extracting file %s to %s", file, destFile);
Files.copy(file, destFile, StandardCopyOption.REPLACE_EXISTING);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult preVisitDirectory(Path dir,
BasicFileAttributes attrs) throws IOException {
final Path dirToCreate = Paths.get(destDir.toString(),
dir.toString());
if(Files.notExists(dirToCreate)){
if(logger.isDebugEnabled()) logger.debug("Creating directory %s", dirToCreate);
Files.createDirectory(dirToCreate);
}
return FileVisitResult.CONTINUE;
}
});
}
}
/**
* Creates/updates a zip file.
* @param zipFilename the name of the zip to create
* @param filenames list of filename to add to the zip
* @throws IOException
*/
public static void create(String zipFilename, String... filenames)
throws IOException {
try (FileSystem zipFileSystem = createZipFileSystem(zipFilename, true)) {
final Path root = zipFileSystem.getPath("/");
//iterate over the files we need to add
for (String filename : filenames) {
final Path src = Paths.get(filename);
//add a file to the zip file system
if(!Files.isDirectory(src)){
final Path dest = zipFileSystem.getPath(root.toString(),
src.toString());
final Path parent = dest.getParent();
if(Files.notExists(parent)){
if(logger.isDebugEnabled()) logger.debug("Creating directory %s", parent);
Files.createDirectories(parent);
}
Files.copy(src, dest, StandardCopyOption.REPLACE_EXISTING);
}
else{
//for directories, walk the file tree
Files.walkFileTree(src, new SimpleFileVisitor<Path>(){
@Override
public FileVisitResult visitFile(Path file,
BasicFileAttributes attrs) throws IOException {
final Path dest = zipFileSystem.getPath(root.toString(),
file.toString());
Files.copy(file, dest, StandardCopyOption.REPLACE_EXISTING);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult preVisitDirectory(Path dir,
BasicFileAttributes attrs) throws IOException {
final Path dirToCreate = zipFileSystem.getPath(root.toString(),
dir.toString());
if(Files.notExists(dirToCreate)){
if(logger.isDebugEnabled()) logger.debug("Creating directory %s\n", dirToCreate);
Files.createDirectories(dirToCreate);
}
return FileVisitResult.CONTINUE;
}
});
}
}
}
}
/**
* List the contents of the specified zip file
* @param zipFilename
* @throws IOException
*/
public static void list(String zipFilename) throws IOException{
if(logger.isDebugEnabled()) logger.debug("Listing Archive: %s",zipFilename);
//create the file system
try (FileSystem zipFileSystem = createZipFileSystem(zipFilename, false)) {
final Path root = zipFileSystem.getPath("/");
//walk the file tree and print out the directory and filenames
Files.walkFileTree(root, new SimpleFileVisitor<Path>(){
@Override
public FileVisitResult visitFile(Path file,
BasicFileAttributes attrs) throws IOException {
print(file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult preVisitDirectory(Path dir,
BasicFileAttributes attrs) throws IOException {
print(dir);
return FileVisitResult.CONTINUE;
}
/**
* prints out details about the specified path
* such as size and modification time
* @param file
* @throws IOException
*/
private void print(Path file) throws IOException{
final DateFormat df = new SimpleDateFormat("MM/dd/yyyy-HH:mm:ss");
final String modTime= df.format(new Date(
Files.getLastModifiedTime(file).toMillis()));
if(logger.isDebugEnabled()) {
logger.debug("%d %s %s",
Files.size(file),
modTime,
file);
}
}
});
}
}
public static void deleteOldFiles(String dirPath, int olderThanMinute) {
File folder = new File(dirPath);
if (folder.exists()) {
File[] listFiles = folder.listFiles();
long eligibleForDeletion = System.currentTimeMillis() - (olderThanMinute * 60 * 1000L);
for (File listFile: listFiles) {
if (listFile.lastModified() < eligibleForDeletion) {
if (!listFile.delete()) {
logger.error("Unable to delete file %s", listFile);
}
}
}
}
}
public static void writeJson(Path path, Object model) throws IOException {
Config.getInstance().getMapper().writerWithDefaultPrettyPrinter().writeValue(new FileOutputStream(path.toFile()), model);
}
public static ByteBuffer toByteBuffer(String s) {
ByteBuffer buffer = ByteBuffer.allocateDirect(s.length());
buffer.put(s.getBytes(UTF_8));
buffer.flip();
return buffer;
}
}