package io.gitlab.jfronny.inceptum.util; import io.gitlab.jfronny.inceptum.Inceptum; import io.gitlab.jfronny.inceptum.model.OSType; import java.awt.*; import java.io.*; import java.lang.reflect.Type; import java.net.URI; import java.nio.charset.StandardCharsets; import java.nio.file.*; import java.nio.file.attribute.BasicFileAttributes; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Arrays; import java.util.Formatter; import java.util.function.Function; import java.util.regex.Pattern; public class Utils { public static final Pattern VALID_FILENAME = Pattern.compile("[a-zA-Z0-9_\\-.][a-zA-Z0-9 _\\-.]*[a-zA-Z0-9_\\-.]"); public static String hash(byte[] data) { Formatter formatter = new Formatter(); try { for (byte b : MessageDigest.getInstance("SHA-1").digest(data)) formatter.format("%02x", b); } catch (NoSuchAlgorithmException e) { throw new RuntimeException("Could not hash using SHA1", e); } return formatter.toString(); } public static byte[] downloadData(String url) throws IOException { try (InputStream is = HttpUtils.get(url).sendInputStream()) { return is.readAllBytes(); } } public static byte[] downloadData(String url, String sha1) throws IOException { byte[] buf = downloadData(url); if (sha1 == null) return buf; if (!Utils.hash(buf).equals(sha1)) throw new IOException("Invalid hash"); return buf; } public static T downloadObject(String url, Class type) throws IOException { return downloadObject(url, () -> HttpUtils.get(url).sendString(), s -> Inceptum.GSON.fromJson(s, type)); } public static T downloadObject(String url, Type type) throws IOException { return downloadObject(url, () -> HttpUtils.get(url).sendString(), s -> Inceptum.GSON.fromJson(s, type)); } public static T downloadObject(String url, String sha1, Class type) throws IOException { return downloadObject(url, () -> downloadString(url, sha1), s -> Inceptum.GSON.fromJson(s, type)); } private static T downloadObject(String url, ThrowingSupplier sourceString, Function builder) throws IOException { Path cache = Inceptum.CACHE_DIR.resolve(Integer.toString(url.hashCode())); if (Files.exists(cache)) return builder.apply(Files.readString(cache)); try { String download = sourceString.get(); Files.writeString(cache, download); return builder.apply(download); } catch (IOException e) { throw new IOException("Could not download object and no cache exists", e); } } public static T loadObject(Path file, Class type) throws IOException { try (BufferedReader br = Files.newBufferedReader(file)) { return Inceptum.GSON.fromJson(br, type); } } public static T loadObject(Path file, Type type) throws IOException { try (BufferedReader br = Files.newBufferedReader(file)) { return Inceptum.GSON.fromJson(br, type); } } public static void writeObject(Path file, T object) throws IOException { try (BufferedWriter bw = Files.newBufferedWriter(file, StandardOpenOption.CREATE, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING)) { Inceptum.GSON.toJson(object, bw); } } public static String downloadString(String url, String sha1) throws IOException { return new String(downloadData(url, sha1), StandardCharsets.UTF_8); } public static void downloadFile(String url, Path path) throws IOException { Files.write(path, downloadData(url)); } public static void downloadFile(String url, String sha1, Path path) throws IOException { Files.write(path, downloadData(url, sha1)); } public static void clearDirectory(Path path) throws IOException { if (!Files.exists(path)) return; try { Files.list(path).forEach(p -> { if (Files.isDirectory(p)) { try { deleteRecursive(p); } catch (IOException e) { throw new RuntimeException(e); } } else { try { Files.delete(p); } catch (IOException e) { throw new RuntimeException(e); } } }); } catch (Throwable t) { throw new IOException("Could not clear directory", t); } } public static void deleteRecursive(Path path) throws IOException { Files.walkFileTree(path, new SimpleFileVisitor<>() { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { FileVisitResult fv = super.visitFile(file, attrs); if (fv != FileVisitResult.CONTINUE) return fv; Files.delete(file); return FileVisitResult.CONTINUE; } @Override public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { FileVisitResult fv = super.postVisitDirectory(dir, exc); if (fv != FileVisitResult.CONTINUE) return fv; Files.delete(dir); return FileVisitResult.CONTINUE; } }); } public static void copyRecursive(Path source, Path destination) throws IOException { copyRecursive(source, destination, StandardCopyOption.COPY_ATTRIBUTES); } public static void copyRecursive(Path source, Path destination, CopyOption... copyOptions) throws IOException { if (!Files.exists(destination)) Files.createDirectories(destination); if(Files.isDirectory(source)) { /*Files.walk(source) .forEach(sourcePath -> { try { Path destinationPath = destination.resolve(source.getFileName().toString()); Path targetPath = destinationPath.resolve(source.relativize(sourcePath).toString()); Files.copy(sourcePath, targetPath, copyOptions); } catch (IOException e) { Inceptum.LOGGER.error("Could not recursively copy", e); } });*/ Files.list(source).forEach(sourcePath -> { try { copyRecursive(sourcePath, destination.resolve(sourcePath.getFileName().toString()), copyOptions); } catch (IOException e) { Inceptum.LOGGER.error("Could not recursively copy", e); } }); } else if(Files.exists(source)) { Path target = destination.resolve(source.getFileName().toString()); if (!Files.exists(target) || Arrays.asList(copyOptions).contains(StandardCopyOption.REPLACE_EXISTING)) Files.copy(source, target, copyOptions); } else { throw new FileNotFoundException(source.toAbsolutePath().toString()); } } public static void openWebBrowser(URI uri) { try { if (OSCheck.OS == OSType.LINUX && JvmUtils.executableInPath("xdg-open")) { Runtime.getRuntime().exec("xdg-open " + uri); } else if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) { Desktop.getDesktop().browse(uri); } } catch (Exception e) { Inceptum.LOGGER.error("Error opening web browser!", e); } } }