Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,11 @@ group = 'cpw.mods'
version = gradleutils.version
logger.lifecycle('Version: ' + version)

ext.asmVersion = 9.3
dependencies {
api("org.ow2.asm:asm:${asmVersion}")
api("org.ow2.asm:asm-tree:${asmVersion}")
api("org.ow2.asm:asm-commons:${asmVersion}")
api("org.ow2.asm:asm:${project.asm_version}")
api("org.ow2.asm:asm-tree:${project.asm_version}")
api("org.ow2.asm:asm-commons:${project.asm_version}")
implementation("org.jetbrains:annotations:${project.jb_annotations_version}")
testImplementation('org.junit.jupiter:junit-jupiter-api:5.8.+')
testRuntimeOnly('org.junit.jupiter:junit-jupiter-engine:5.8.+')
}
Expand Down
2 changes: 2 additions & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
asm_version=9.3
jb_annotations_version=22.0.0
8 changes: 4 additions & 4 deletions sjh-jmh/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ dependencies {
implementation('org.junit.jupiter:junit-jupiter-engine:5.8.+')
implementation('org.apache.logging.log4j:log4j-core:2.17.1')
implementation('org.apache.logging.log4j:log4j-api:2.17.1')
implementation('org.ow2.asm:asm:9.3')
implementation('org.ow2.asm:asm-tree:9.3')
implementation('org.ow2.asm:asm-commons:9.3')
implementation("org.ow2.asm:asm:${project.asm_version}")
implementation("org.ow2.asm:asm-tree:${project.asm_version}")
implementation("org.ow2.asm:asm-commons:${project.asm_version}")
implementation('org.openjdk.jmh:jmh-core:1.35')
jmhOnly('org.openjdk.jmh:jmh-core:1.35')
jmhOnly('org.openjdk.jmh:jmh-generator-annprocess:1.35')
Expand Down Expand Up @@ -42,4 +42,4 @@ task jmh(type: JavaExec, dependsOn: sourceSets.main.output) {
args '-f', '1' // forks
args '-rff', project.file("${rootProject.buildDir}/jmh_results.txt") // results file
args 'cpw.mods.niofs.union.benchmarks.UnionFileSystemBenchmark'
}
}
55 changes: 55 additions & 0 deletions src/main/java/cpw/mods/jarhandling/JarContents.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package cpw.mods.jarhandling;

import org.jetbrains.annotations.ApiStatus;

import java.net.URI;
import java.nio.file.Path;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.jar.Manifest;

/**
* Access to the contents of a list of {@link Path}s, interpreted as a jar file.
* Typically used to build the {@linkplain JarMetadata metadata} for a {@link SecureJar}.
*
* <p>Create with {@link JarContentsBuilder}.
* Convert to a full jar with {@link SecureJar#from(JarContents)}.
*/
@ApiStatus.NonExtendable
public interface JarContents {
/**
* @see SecureJar#getPrimaryPath()
*/
Path getPrimaryPath();

/**
* Looks for a file in the jar.
*/
Optional<URI> findFile(String name);

/**
* {@return the manifest of the jar}
* Empty if no manifest is present in the jar.
*/
Manifest getManifest();

/**
* {@return all the packages in the jar}
* (Every folder containing a {@code .class} file is considered a package.)
*/
Set<String> getPackages();

/**
* {@return all the packages in the jar, with some root packages excluded}
*
* <p>This can be used to skip scanning of folders that are known to not contain code,
* but would be expensive to go through.
*/
Set<String> getPackagesExcluding(String... excludedRootPackages);

/**
* Parses the {@code META-INF/services} files in the jar, and returns the list of service providers.
*/
List<SecureJar.Provider> getMetaInfServices();
}
58 changes: 58 additions & 0 deletions src/main/java/cpw/mods/jarhandling/JarContentsBuilder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package cpw.mods.jarhandling;

import cpw.mods.jarhandling.impl.JarContentsImpl;
import cpw.mods.niofs.union.UnionPathFilter;
import org.jetbrains.annotations.Nullable;

import java.nio.file.Path;
import java.util.Objects;
import java.util.function.Supplier;
import java.util.jar.Manifest;

/**
* Builder for {@link JarContents}.
*/
public final class JarContentsBuilder {
private Path[] paths = new Path[0];
private Supplier<Manifest> defaultManifest = Manifest::new;
@Nullable
private UnionPathFilter pathFilter = null;

public JarContentsBuilder() {}

/**
* Sets the root paths for the files of this jar.
*/
public JarContentsBuilder paths(Path... paths) {
this.paths = paths;
return this;
}

/**
* Overrides the default manifest for this jar.
* The default manifest is only used when the jar does not provide a manifest already.
*/
public JarContentsBuilder defaultManifest(Supplier<Manifest> manifest) {
Objects.requireNonNull(manifest);

this.defaultManifest = manifest;
return this;
}

/**
* Overrides the path filter for this jar, to exclude some entries from the underlying file system.
*
* @see UnionPathFilter
*/
public JarContentsBuilder pathFilter(@Nullable UnionPathFilter pathFilter) {
this.pathFilter = pathFilter;
return this;
}

/**
* Builds the jar.
*/
public JarContents build() {
return new JarContentsImpl(paths, defaultManifest, pathFilter == null ? null : pathFilter::test);
}
}
42 changes: 35 additions & 7 deletions src/main/java/cpw/mods/jarhandling/JarMetadata.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,25 +33,31 @@ public interface JarMetadata {
"volatile","const","float","native","super","while");
Pattern KEYWORD_PARTS = Pattern.compile("(?<=^|\\.)(" + String.join("|", ILLEGAL_KEYWORDS) + ")(?=\\.|$)");

static JarMetadata from(final SecureJar jar, final Path... path) {
if (path.length==0) throw new IllegalArgumentException("Need at least one path");
/**
* Builds the jar metadata for a jar following the normal rules for Java jars.
*
* <p>If the jar has a {@code module-info.class} file, the module info is read from there.
* Otherwise, the jar is an automatic module, whose name is optionally derived
* from {@code Automatic-Module-Name} in the manifest.
*/
static JarMetadata from(JarContents jar) {
final var pkgs = jar.getPackages();
var mi = jar.moduleDataProvider().findFile("module-info.class");
var mi = jar.findFile("module-info.class");
if (mi.isPresent()) {
return new ModuleJarMetadata(mi.get(), pkgs);
} else {
var providers = jar.getProviders();
var fileCandidate = fromFileName(path[0], pkgs, providers);
var aname = jar.moduleDataProvider().getManifest().getMainAttributes().getValue("Automatic-Module-Name");
var providers = jar.getMetaInfServices();
var fileCandidate = fromFileName(jar.getPrimaryPath(), pkgs, providers);
var aname = jar.getManifest().getMainAttributes().getValue("Automatic-Module-Name");
if (aname != null) {
return new SimpleJarMetadata(aname, fileCandidate.version(), pkgs, providers);
} else {
return fileCandidate;
}
}
}
static SimpleJarMetadata fromFileName(final Path path, final Set<String> pkgs, final List<SecureJar.Provider> providers) {

static SimpleJarMetadata fromFileName(final Path path, final Set<String> pkgs, final List<SecureJar.Provider> providers) {
// detect Maven-like paths
Path versionMaybe = path.getParent();
if (versionMaybe != null)
Expand Down Expand Up @@ -137,4 +143,26 @@ private static String cleanModuleName(String mn) {

return mn;
}

/**
* @deprecated Use {@link #from(JarContents)} instead.
*/
@Deprecated(forRemoval = true, since = "2.1.16")
static JarMetadata from(final SecureJar jar, final Path... path) {
if (path.length==0) throw new IllegalArgumentException("Need at least one path");
final var pkgs = jar.getPackages();
var mi = jar.moduleDataProvider().findFile("module-info.class");
if (mi.isPresent()) {
return new ModuleJarMetadata(mi.get(), pkgs);
} else {
var providers = jar.getProviders();
var fileCandidate = fromFileName(path[0], pkgs, providers);
var aname = jar.moduleDataProvider().getManifest().getMainAttributes().getValue("Automatic-Module-Name");
if (aname != null) {
return new SimpleJarMetadata(aname, fileCandidate.version(), pkgs, providers);
} else {
return fileCandidate;
}
}
}
}
Loading