176 lines
8.3 KiB
Java
176 lines
8.3 KiB
Java
package io.gitlab.jfronny.inceptum.common.api;
|
|
|
|
import io.gitlab.jfronny.commons.HttpUtils;
|
|
import io.gitlab.jfronny.inceptum.common.Net;
|
|
import io.gitlab.jfronny.inceptum.common.Utils;
|
|
import io.gitlab.jfronny.inceptum.common.model.maven.*;
|
|
import org.jetbrains.annotations.Nullable;
|
|
import org.w3c.dom.*;
|
|
import org.xml.sax.SAXException;
|
|
|
|
import javax.xml.parsers.*;
|
|
import javax.xml.stream.XMLStreamException;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.net.URISyntaxException;
|
|
import java.nio.file.Path;
|
|
import java.util.*;
|
|
|
|
public class MavenApi {
|
|
private static final DocumentBuilder FACTORY;
|
|
private static final Set<String> RUNTIME_SCOPES = Set.of("compile", "runtime");
|
|
|
|
static {
|
|
try {
|
|
FACTORY = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
|
} catch (ParserConfigurationException e) {
|
|
throw new RuntimeException("Could not create document builder", e);
|
|
}
|
|
}
|
|
|
|
public static Path downloadLibrary(String repo, ArtifactMeta meta) throws IOException, URISyntaxException {
|
|
Path res = meta.localPath;
|
|
Net.downloadFile(Utils.join("/", repo, meta.getJarPath(true)), res);
|
|
return res;
|
|
}
|
|
|
|
public static Pom getPom(String repo, ArtifactMeta meta) throws IOException, SAXException, URISyntaxException, XMLStreamException {
|
|
try (InputStream is = HttpUtils.get(Utils.join("/", repo, meta.pomPath)).sendInputStream()) {
|
|
Document doc = FACTORY.parse(is);
|
|
doc.documentElement.normalize();
|
|
if (!"project".equals(doc.documentElement.nodeName)) throw new IOException("Illegal document name");
|
|
String modelVersion = null;
|
|
String groupId = null;
|
|
String artifactId = null;
|
|
String version = null;
|
|
String packaging = null;
|
|
List<MavenDependency> dependencies = null;
|
|
String classifier = null;
|
|
for (Node node : doc.documentElement.childNodes) {
|
|
switch (node.nodeName) {
|
|
case "modelVersion" -> modelVersion = node.textContent;
|
|
case "parent" -> {
|
|
// Dirty hack to get slf4j working: simply assume the groupId and version of the parent is also the groupId of this
|
|
if (groupId == null) {
|
|
for (Node child : node.childNodes) {
|
|
switch (child.nodeName) {
|
|
case "groupId" -> {
|
|
if (groupId == null) {
|
|
groupId = child.textContent;
|
|
}
|
|
}
|
|
case "version" -> {
|
|
if (version == null) {
|
|
version = child.textContent;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
case "groupId" -> groupId = node.textContent;
|
|
case "artifactId" -> {
|
|
artifactId = node.textContent;
|
|
}
|
|
case "version" -> {
|
|
version = node.textContent;
|
|
}
|
|
case "packaging" -> packaging = node.textContent;
|
|
case "dependencies" -> {
|
|
dependencies = new LinkedList<>();
|
|
for (Node dep : node.childNodes) {
|
|
MavenDependency resolved = parseDependency(dep);
|
|
if (resolved != null) {
|
|
dependencies.add(resolved);
|
|
}
|
|
}
|
|
}
|
|
case "classifier" -> classifier = node.textContent;
|
|
default -> {}
|
|
}
|
|
}
|
|
if (modelVersion == null) throw new IOException("Pom lacks modelVersion");
|
|
if (groupId == null) throw new IOException("Pom lacks groupId");
|
|
if (artifactId == null) throw new IOException("Pom lacks artifactId");
|
|
if (version == null) throw new IOException("Pom lacks version");
|
|
return new Pom(modelVersion, groupId, artifactId, version, classifier, null, packaging, dependencies);
|
|
}
|
|
}
|
|
|
|
private static @Nullable MavenDependency parseDependency(Node doc) throws IOException {
|
|
String groupId = null;
|
|
String artifactId = null;
|
|
String version = null;
|
|
String scope = null;
|
|
for (Node node : doc.childNodes) {
|
|
switch (node.nodeName) {
|
|
case "groupId" -> groupId = node.textContent;
|
|
case "artifactId" -> artifactId = node.textContent;
|
|
case "version" -> version = node.textContent;
|
|
case "scope" -> {
|
|
scope = node.textContent;
|
|
if (!RUNTIME_SCOPES.contains(scope)) return null;
|
|
}
|
|
case "optional" -> {
|
|
if (node.textContent.equals("true")) return null;
|
|
}
|
|
}
|
|
}
|
|
if (groupId == null) throw new IOException("Pom lacks groupId");
|
|
if (artifactId == null) throw new IOException("Pom lacks artifactId");
|
|
if (version == null) {
|
|
if (groupId.equals("org.lwjgl")) {
|
|
// Lwjgl uses a shared bom for versions which I don't want to support
|
|
// The required modules are explicit dependencies of launcher-imgui anyway
|
|
return null;
|
|
}
|
|
throw new IOException("Dependency " + groupId + ":" + artifactId + " lacks version");
|
|
}
|
|
if (scope == null) throw new IOException("Pom lacks scope");
|
|
return new MavenDependency(groupId, artifactId, version, scope);
|
|
}
|
|
|
|
public static ArtifactMeta getMetadata(String repo, String artifact) throws IOException, SAXException, URISyntaxException {
|
|
ArtifactMeta sourceMeta = ArtifactMeta.parse(artifact);
|
|
try (InputStream is = HttpUtils.get(Utils.join("/", repo, sourceMeta.metadataPath)).sendInputStream()) {
|
|
Document doc = FACTORY.parse(is);
|
|
doc.documentElement.normalize();
|
|
if (!"metadata".equals(doc.documentElement.nodeName)) throw new IOException("Illegal document name");
|
|
String groupId = null;
|
|
String artifactId = null;
|
|
String version = null;
|
|
String snapshotVersion = null;
|
|
for (Node node : doc.documentElement.childNodes) {
|
|
switch (node.nodeName) {
|
|
case "groupId" -> groupId = node.textContent;
|
|
case "artifactId" -> artifactId = node.textContent;
|
|
case "version" -> version = node.textContent;
|
|
case "versioning" -> {
|
|
for (Node node1 : node.childNodes) {
|
|
if (node1.nodeName.equals("snapshot")) {
|
|
String timestamp = null;
|
|
String buildNumber = null;
|
|
for (Node node2 : node1.childNodes) {
|
|
switch (node2.nodeName) {
|
|
case "timestamp" -> timestamp = node2.textContent;
|
|
case "buildNumber" -> buildNumber = node2.textContent;
|
|
default -> {}
|
|
}
|
|
}
|
|
if (timestamp == null) throw new IOException("Pom snapshots lack timestamp");
|
|
if (buildNumber == null) throw new IOException("Pom snapshots lack buildNumber");
|
|
snapshotVersion = timestamp + '-' + buildNumber;
|
|
}
|
|
}
|
|
}
|
|
default -> {}
|
|
}
|
|
}
|
|
if (groupId == null) throw new IOException("Pom lacks groupId");
|
|
if (artifactId == null) throw new IOException("Pom lacks artifactId");
|
|
if (version == null) throw new IOException("Pom lacks version");
|
|
return new ArtifactMeta(groupId, artifactId, version, sourceMeta.classifier, snapshotVersion);
|
|
}
|
|
}
|
|
}
|