Skip to content

Commit

Permalink
🚧 wip(stage1): started work on the Dependency management engine
Browse files Browse the repository at this point in the history
Signed-off-by: xtrm <oss@xtrm.me>
  • Loading branch information
xtrm-en committed Jun 25, 2024
1 parent 200c365 commit 1cd0de2
Show file tree
Hide file tree
Showing 20 changed files with 685 additions and 24 deletions.
Original file line number Diff line number Diff line change
@@ -1,11 +1,23 @@
package org.polyfrost.oneconfig.loader;

/**
* A loader metadata container trait.
* A loader metadata trait, describing information about a specific loader and/or loader stage.
* <p>
* Note that this is regarding OneConfig Loader's metadata, not an underlying game modloader.
*
* @author xtrm
*/
public interface IMetaHolder {
/**
* @return the loader's name
*/
String getName();

/**
* @return the loader's version
*/
String getVersion();

/**
* Creates a {@link IMetaHolder} instance from the given params.
*
Expand All @@ -26,18 +38,4 @@ public String getVersion() {
}
};
}

/**
* Returns the loader's name.
*
* @return the loader's name
*/
String getName();

/**
* Returns the loader's version.
*
* @return the loader's version
*/
String getVersion();
}
1 change: 1 addition & 0 deletions stage1/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ sourceSets {

dependencies {
implementation(project(":common"))
include("cc.polyfrost:polyio:0.0.13")
"legacyCompileOnly"("net.minecraft:launchwrapper:1.12")
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
import java.nio.file.Path;

/**
* {@link Capabilities} implementation for initialization through legacy entrypoints.
* {@link Capabilities} implementation for initialization through legacy entrypoints, which all use
* <a href="https://github.com/Mojang/LegacyLauncher">LaunchWrapper</a>.
*
* @author xtrm
* @since 1.1.0
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,39 @@
package org.polyfrost.oneconfig.loader.stage1;

import lombok.SneakyThrows;
import org.polyfrost.oneconfig.loader.LoaderBase;
import org.polyfrost.oneconfig.loader.stage1.dependency.DependencyManager;
import org.polyfrost.oneconfig.loader.stage1.dependency.maven.MavenDependencyManager;
import org.polyfrost.oneconfig.loader.stage1.dependency.model.Artifact;
import org.polyfrost.oneconfig.loader.stage1.util.SystemProperties;
import org.polyfrost.oneconfig.loader.stage1.util.XDG;

/**
* @author xtrm
* @since 1.1.0
*/
public class Stage1Loader extends LoaderBase {
private final XDG.ApplicationStore applicationStore;
private final DependencyManager<MavenArtifact> dependencyManager;

@SneakyThrows
public Stage1Loader(Capabilities capabilities) {
super(
"stage1",
Stage1Loader.class.getPackage().getImplementationVersion(),
capabilities
);
this.applicationStore = XDG.provideApplicationStore("Polyfrost/OneConfig/loader");
this.dependencyManager = new MavenDependencyManager(
applicationStore,
SystemProperties.REPOSITORY_URL.get()
);
}

@Override
public void load() {
// Fetch oneconfig version info
Artifact oneconfigArtifact = dependencyManager.fetchArtifact();
// Lookup dependencies metadata
// Download to cache
// Delegate everything to OneConfig
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.polyfrost.oneconfig.loader.stage1.dependency;

import org.polyfrost.oneconfig.loader.stage1.dependency.model.Artifact;
import org.polyfrost.oneconfig.loader.stage1.dependency.model.ArtifactDeclaration;

/**
*
* @param <T>
*
* @author xtrm
* @since 1.1.0
*/
public interface DependencyManager<A extends Artifact, D extends ArtifactDeclaration> {
A buildArtifact(String groupId, String artifactId, String version);
D resolveArtifact(A artifact);
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.polyfrost.oneconfig.loader.stage1.dependency.cache;

import java.nio.file.Path;

/**
* @author xtrm
* @since 1.1.0
*/
public interface CachingSolution {
boolean canBeCached(Path path);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package org.polyfrost.oneconfig.loader.stage1.dependency.maven;

import lombok.Data;
import org.polyfrost.oneconfig.loader.stage1.dependency.model.Artifact;

import java.nio.file.Path;
import java.nio.file.Paths;

/**
* @author xtrm
* @since 1.1.0
*/
public @Data class MavenArtifact implements Artifact {
private final String groupId;
private final String artifactId;
private final String version;
private final String classifier;
private final String extension;

@Override
public String getDeclaration() {
return String.format(
"%s:%s:%s",
groupId, artifactId, version
) + (classifier == null ? "" : ":" + classifier)
+ (extension == null ? "" : "@" + extension);
}

@Override
public Path getRelativePath() {
return Paths.get(
groupId.replace('.', '/'),
artifactId,
version,
getFileName()
);
}

@Override
public String getFileName() {
return artifactId + "-" + version
+ (classifier == null ? "" : "-" + classifier)
+ "." + (extension == null ? "jar" : extension);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package org.polyfrost.oneconfig.loader.stage1.dependency.maven;

import lombok.Data;
import org.polyfrost.oneconfig.loader.stage1.dependency.DependencyManager;
import org.polyfrost.oneconfig.loader.stage1.dependency.model.Artifact;
import org.polyfrost.oneconfig.loader.stage1.dependency.model.ArtifactDeclaration;
import org.polyfrost.oneconfig.loader.stage1.dependency.model.ArtifactDependency;

import java.util.ArrayList;
import java.util.List;

/**
* @author xtrm
* @since 1.1.0
*/
public @Data class MavenArtifactDeclaration implements ArtifactDeclaration {
private final MavenArtifact artifact;
private final List<MavenArtifactDependency> dependencies = new ArrayList<>();

void resolveDependencies(DependencyManager<Artifact, ArtifactDeclaration> dependencyManager) {
for (MavenArtifactDependency dependency : dependencies) {
MavenArtifactDeclaration declaration = dependency.getDeclaration();
if (declaration == null) {
declaration = (MavenArtifactDeclaration) dependencyManager.resolveArtifact(dependency.getDeclaration().getArtifact());
dependency.setDeclaration(declaration);
declaration.resolveDependencies(dependencyManager);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package org.polyfrost.oneconfig.loader.stage1.dependency.maven;

import lombok.Getter;
import org.polyfrost.oneconfig.loader.stage1.dependency.DependencyManager;
import org.polyfrost.oneconfig.loader.stage1.dependency.cache.CachingSolution;
import org.polyfrost.oneconfig.loader.stage1.dependency.maven.cache.MavenCachingSolution;
import org.polyfrost.oneconfig.loader.stage1.util.XDG;

import java.net.URI;
import java.nio.file.Path;

/**
* @author xtrm
* @since 1.1.0
*/
@Getter
public class MavenDependencyManager implements DependencyManager<MavenArtifact, MavenArtifactDeclaration> {
private final XDG.ApplicationStore store;
private final URI repository;
private final CachingSolution cache;

public MavenDependencyManager(XDG.ApplicationStore store, URI repository) {
this.store = store;
this.repository = repository;
this.cache = new MavenCachingSolution(store, repository);
}

@Override
public MavenArtifact buildArtifact(String groupId, String artifactId, String version) {
return new MavenArtifact(groupId, artifactId, version, null, "jar");
}

@Override
public MavenArtifactDeclaration resolveArtifact(MavenArtifact artifact) {
Path dataDir = store.getDataDir();
Path localLibraries = dataDir.resolve("libraries");

Path artifactRelativePath = artifact.getRelativePath();
Path localArtifactPath = localLibraries.resolve(artifactRelativePath);

Path localPomFile = localLibraries.resolve(artifactRelativePath.toString().replace(artifact.getExtension(), "pom"));
Path remotePomFile = repository
if (localPomFile.toFile().exists()) {
return new MavenArtifactDeclaration(artifact);
}
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package org.polyfrost.oneconfig.loader.stage1.dependency.maven.cache;

import lombok.RequiredArgsConstructor;
import org.polyfrost.oneconfig.loader.stage1.dependency.cache.CachingSolution;
import org.polyfrost.oneconfig.loader.stage1.util.XDG;
import org.polyfrost.oneconfig.loader.utils.RequestHelper;

import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import java.nio.file.Path;

/**
* @author xtrm
* @since 1.1.0
*/
@RequiredArgsConstructor
public class MavenCachingSolution extends RequestHelper implements CachingSolution {
private static final String[] CHECKSUM_EXT = new String[]{"sha512", "sha256", "sha1", "md5"};
private final XDG.ApplicationStore store;
private final URI remoteUrl;

@Override
public boolean canBeCached(Path path) {
String fileName = path.getFileName().toString();
if (!fileName.endsWith(".pom") && !fileName.endsWith(".jar")) {
return false;
}
// check on the remote server if any signature file exist
for (String checksumExtension : CHECKSUM_EXT) {
Path checksumPath = path.resolveSibling(fileName + "." + checksumExtension);
URI checksumUri = remoteUrl.resolve(checksumPath.toString());
// if the checksum file exists, then the file can be cached
URL url;
try {
url = checksumUri.toURL();
} catch (Exception e) {
continue;
}
if (urlExists(url)) {
System.out.println("File " + path + " can be cached (found " + url + ")");
return true;
}
}
System.out.println("File " + path + " cannot be cached");
return false;
}

private boolean urlExists(URL url) {
try {
URLConnection connection = establishConnection(url);
connection.connect();
long contentLength = connection.getContentLengthLong();
int responseCode = 200;
if (connection instanceof HttpURLConnection) {
responseCode = ((HttpURLConnection) connection).getResponseCode();
}
connection.getInputStream().close();
connection.getOutputStream().close();
return (responseCode >= 200 && responseCode < 300) && contentLength > 0;
} catch (Exception e) {
return false;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package org.polyfrost.oneconfig.loader.stage1.dependency.model;

import org.jetbrains.annotations.Nullable;

import java.nio.file.Path;

/**
* A generic artifact, part of the dependency resolution system.
*
* @author xtrm
* @since 1.1.0
*/
public interface Artifact {
/**
* @return the artifact's group ID
*/
String getGroupId();

/**
* @return the artifact's name/ID
*/
String getArtifactId();

/**
* @return the artifact's version
*/
String getVersion();

/**
* @return the artifact's classifier (usually {@code null})
*/
@Nullable String getClassifier();

/**
* @return the artifact's extension (usually {@code jar})
*/
String getExtension();

/**
* @return a service-specific declaration of the artifact
*/
String getDeclaration();

/**
* @return the relative path of the artifact
*/
Path getRelativePath();

/**
* @return the file name of the artifact
*/
String getFileName();
}
Loading

0 comments on commit 1cd0de2

Please sign in to comment.