diff options
Diffstat (limited to 'src/main/java/org/glavo/javah/Utils.java')
-rw-r--r-- | src/main/java/org/glavo/javah/Utils.java | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/src/main/java/org/glavo/javah/Utils.java b/src/main/java/org/glavo/javah/Utils.java new file mode 100644 index 0000000..989d348 --- /dev/null +++ b/src/main/java/org/glavo/javah/Utils.java @@ -0,0 +1,134 @@ +package org.glavo.javah; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.*; +import java.util.jar.Manifest; +import java.util.regex.Pattern; + +class Utils { + static boolean isRegularClassName(String name) { + Objects.requireNonNull(name); + return !name.contains("//") + && !name.contains("..") + && name.indexOf('\\') == -1 + && name.indexOf(';') == -1 + && name.indexOf('[') == -1; + } + + static String fullClassNameOf(String name) { + Objects.requireNonNull(name); + int idx = name.indexOf('/'); + if (idx == -1) { + return name; + } + String cn = name.substring(idx + 1); + if (cn.isEmpty() || cn.indexOf('/') == -1) { + throw new IllegalArgumentException("Illegal class name: " + name); + } + return cn; + } + + static String simpleNameOf(String name) { + int idx = name.lastIndexOf('.'); + return name.substring(idx + 1); + } + + static Path searchFromPathList(List<Path> paths, String className) { + Objects.requireNonNull(paths); + Objects.requireNonNull(className); + String fp = fullClassNameOf(className).replace('.', '/') + ".class"; + for (Path path : paths) { + Objects.requireNonNull(path); + Path p = path.resolve(fp); + if (Files.isRegularFile(p)) { + return p; + } + } + return null; + } + + static List<Path> getPathsFrom(Path root) { + Objects.requireNonNull(root); + root = root.toAbsolutePath(); + if (Files.isRegularFile(root)) { + String name = root.toString().toLowerCase(); + try { + FileSystem fs = FileSystems.newFileSystem(root, null); + if (name.endsWith(".jar")) { + root = fs.getPath("/"); + } else if (name.endsWith(".jmod")) { + root = fs.getPath("/classes"); + } else { + return Collections.emptyList(); + } + } catch (IOException e) { + return Collections.emptyList(); + } + } + if (!Files.isDirectory(root)) { + return Collections.emptyList(); + } + + boolean isMultiRelease = false; + Path manifest = root.resolve("META-INF").resolve("MANIFEST.MF"); + if (Files.exists(manifest) && Files.isRegularFile(manifest)) { + try (InputStream input = Files.newInputStream(manifest)) { + isMultiRelease = Boolean.parseBoolean( + new Manifest(input).getMainAttributes().getOrDefault("Multi-Release", "false").toString() + ); + + } catch (Exception ignored) { + } + } + + if (!isMultiRelease) { + return Collections.singletonList(root); + } + LinkedList<Path> list = new LinkedList<>(); + Path mr = root.resolve("META-INF").resolve("versions"); + try { + Files.list(mr) + .filter(Utils::checkMultiReleaseVersion) + .sorted(Comparator.comparingInt(a -> Integer.parseInt(a.getFileName().toString()))) + .forEachOrdered(list::addFirst); + + } catch (IOException ignored) { + } + + list.add(root); + return list; + } + + private static final String[] MULTI_VERSIONS = {"9", "10", "11", "12", "13"}; + + private static boolean checkMultiReleaseVersion(Path p) { + Objects.requireNonNull(p); + String n = p.getFileName().toString(); + for (String version : MULTI_VERSIONS) { + if (version.equals(n)) { + return true; + } + } + return false; + } + + static Path searchFrom(List<Path> searchPaths, String name) { + Objects.requireNonNull(searchPaths); + Objects.requireNonNull(name); + + name = simpleNameOf(name).replace('.', '/') + ".class"; + + for (Path searchPath : searchPaths) { + Path p = searchPath.resolve(name); + if (Files.isRegularFile(p)) { + return p; + } + } + return null; + } +} |