io.mvnpm.esbuild.util.JarInspector Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of esbuild-java Show documentation
Show all versions of esbuild-java Show documentation
Small wrapper around esbuild to be able to use it in Java
The newest version!
package io.mvnpm.esbuild.util;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Properties;
import java.util.Queue;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.mvnpm.esbuild.install.InstallException;
import io.mvnpm.esbuild.model.WebDependency;
import io.mvnpm.importmap.ImportsDataBinding;
public class JarInspector {
private static final ObjectMapper objectMapper = new ObjectMapper();
private static final Logger logger = Logger.getLogger(JarInspector.class.getName());
public static final String PACKAGE_JSON = "package.json";
public static final String IMPORTMAP_JSON = "importmap.json";
public static final String POM_PROPERTIES = "pom.properties";
private static final String MAVEN_ROOT = "META-INF/maven";
private static final String MVNPM_PACKAGING_VERSION_KEY = "mvnpm.packagingVersion";
private static final Set COMPATIBLE_MVNPM_PACKAGING_VERSIONS = Set.of("1");
public static final String MVNPM_MORE_ARCHIVE = "META-INF/.more.tgz";
private static final Map> PACKAGE_DIRS = Map.of(
WebDependency.WebDependencyType.MVNPM, List.of("META-INF/resources/_static", ""),
WebDependency.WebDependencyType.WEBJARS, List.of("META-INF/resources/webjars"));
private static final List MULTIPLE_GROUP_IDS = List.of("org.mvnpm.at.mvnpm"); // Group Ids that can contain
// multiple package.jsons
// TODO: Allow this to be
// configured
public static Path findMvnpmMoreArchive(Path dir) {
final Path moreArchive = dir.resolve(MVNPM_MORE_ARCHIVE);
if (Files.exists(moreArchive)) {
return moreArchive;
}
return null;
}
public static Map findPackageNameAndRoot(String id, Path extractDir, WebDependency.WebDependencyType type) {
Path dir = getPackageRootPath(extractDir, type);
if (dir == null) {
return Map.of();
}
Properties properties = getProperties(id, extractDir, type);
String groupId = properties.getProperty("groupId", "");
boolean shouldDoMultiple = MULTIPLE_GROUP_IDS.contains(groupId);
// First try package.json
Map found = findPackageNameAndRootWithPackage(dir, shouldDoMultiple);
// If this is mvnpm and we could not find package.json we can try another way
if (found.isEmpty() && type.equals(WebDependency.WebDependencyType.MVNPM)) {
found = findPackageNameAndRootWithImportMap(extractDir, properties);
}
return found;
}
private static Path getPackageRootPath(Path extractDir, WebDependency.WebDependencyType type) {
if (!PACKAGE_DIRS.containsKey(type)) {
throw new RuntimeException("Invalid BundleType: " + type);
}
for (String packageDir : PACKAGE_DIRS.get(type)) {
Path dir = extractDir.resolve(packageDir);
if (Files.isDirectory(dir)) {
return dir;
}
}
return null;
}
private static Properties getProperties(String id, Path extractDir, WebDependency.WebDependencyType type) {
Properties properties = new Properties();
if (type.equals(WebDependency.WebDependencyType.MVNPM)) { // Only mvnpm support composite
properties = getPomProperties(extractDir);
}
final String mvnpmPackagingVersion = properties.getProperty(MVNPM_PACKAGING_VERSION_KEY);
if (mvnpmPackagingVersion != null) {
final String[] split = mvnpmPackagingVersion.split("\\.");
if (split.length > 0 && !COMPATIBLE_MVNPM_PACKAGING_VERSIONS.contains(split[0])) {
throw new InstallException(
"This version of esbuild-java is not compatible with this artifact packaging structure: " + id
+ " (upgrade the version of esbuild-java or use a previous version of this package).",
id);
}
}
return properties;
}
private static Map findPackageNameAndRootWithPackage(Path root, boolean shouldDoMultiple) {
Map paths = new HashMap<>();
List foundFiles = searchFiles(root, PACKAGE_JSON, shouldDoMultiple);
for (Path path : foundFiles) {
String packageName = readPackageName(path);
paths.putIfAbsent(packageName, path.getParent());
}
return paths;
}
private static Map findPackageNameAndRootWithImportMap(Path root, Properties properties) {
Optional importMapJson = searchFile(root, IMPORTMAP_JSON);
if (importMapJson.isPresent()) {
try {
Path importMap = importMapJson.get();
String json = new String(Files.readAllBytes(importMap));
Map imports = ImportsDataBinding.toImports(json).getImports();
// Find the first directory one
String packageName = readPackageName(properties);
String artifactId = properties.getProperty("artifactId");
String version = properties.getProperty("version");
Path fullExtractedRoot = null;
String fullExtractedMain = null;
for (Map.Entry ie : imports.entrySet()) {
if (ie.getKey().endsWith("/") && fullExtractedRoot == null) {
Path resources = importMap.getParent().resolve("resources");
Path packageRoot = Path.of(resources.toString(), toRelativeDir(ie.getValue(), artifactId));
fullExtractedRoot = root.resolve(packageRoot);
} else if (fullExtractedMain == null) {
fullExtractedMain = ie.getValue();
}
}
String main = toRelativeMain(fullExtractedRoot.toString(), fullExtractedMain);
PackageJsonCreator.createPackageJson(fullExtractedRoot, packageName, version, main);
return Map.of(packageName, fullExtractedRoot);
} catch (IOException ex) {
throw new UncheckedIOException(ex);
}
}
return Map.of();
}
private static String toRelativeDir(String path, String artifactId) {
if (!path.endsWith(artifactId + "/")) { // Could be in a sub folder
path = path.substring(0, path.indexOf(artifactId) + artifactId.length() + 1);
}
return path;
}
private static String toRelativeMain(String root, String main) {
root = root.substring(root.indexOf("_static"));
Path rootPath = Paths.get(root);
if (main.startsWith("/"))
main = main.substring(1);
return rootPath.relativize(Paths.get(main)).toString();
}
private static String readPackageName(Properties properties) {
String groupId = properties.getProperty("groupId");
if (groupId.equals("org.mvnpm")) {
groupId = "";
} else {
groupId = groupId.substring(10); // Cut out org.mvnpm
groupId = groupId.replaceFirst("at.", "@");
groupId = groupId + "/";
}
return groupId + properties.getProperty("artifactId");
}
private static String readPackageName(Path path) {
try {
JsonNode object = objectMapper.readTree(path.toFile());
return object.get("name").asText();
} catch (IOException ex) {
throw new UncheckedIOException(ex);
}
}
private static Properties getPomProperties(Path extractDir) {
Properties properties = new Properties();
Path metaInfMavenDir = extractDir.resolve(MAVEN_ROOT);
if (!Files.isDirectory(metaInfMavenDir)) {
return properties;
}
Optional maybePomProperties = searchFile(extractDir.resolve(MAVEN_ROOT), POM_PROPERTIES);
if (maybePomProperties.isPresent()) {
Path pomProperties = maybePomProperties.get();
try {
properties.load(Files.newInputStream(pomProperties));
} catch (IOException ex) {
logger.log(Level.WARNING, "could not read properties ''{0}''", pomProperties);
}
}
return properties;
}
/**
* Find the first match recursively
*
* @param rootPath starting
* @param targetFileName file we are looking for
* @return the Path to the found file
*/
private static Optional searchFile(Path rootPath, final String targetFileName) {
List found = searchFiles(rootPath, targetFileName, false);
if (!found.isEmpty()) {
return Optional.of(found.get(0));
}
return Optional.empty();
}
private static List searchFiles(Path rootPath, final String targetFileName, boolean multiple) {
List found = new ArrayList<>();
Queue queue = new LinkedList<>();
queue.add(rootPath);
while (!queue.isEmpty()) {
Path currentPath = queue.poll();
try (DirectoryStream stream = Files.newDirectoryStream(currentPath)) {
for (Path entry : stream) {
if (Files.isDirectory(entry)) {
queue.add(entry);
} else if (entry.getFileName().toString().equals(targetFileName)) {
found.add(entry);
if (!multiple)
return found;
}
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
return found;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy