Skip to content

Commit

Permalink
Move classloader-related logic to new :classloaders subproject (gradl…
Browse files Browse the repository at this point in the history
  • Loading branch information
reinsch82 authored Feb 14, 2025
2 parents 6a69728 + ba7a281 commit df5bc23
Show file tree
Hide file tree
Showing 82 changed files with 302 additions and 70 deletions.
7 changes: 7 additions & 0 deletions .teamcity/subprojects.json
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,13 @@
"functionalTests": false,
"crossVersionTests": false
},
{
"name": "classloaders",
"path": "platforms/core-runtime/classloaders",
"unitTests": false,
"functionalTests": false,
"crossVersionTests": false
},
{
"name": "cli",
"path": "platforms/core-runtime/cli",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ dependencies {
// TODO - it might be good to allow projects to contribute state to save and restore, rather than have this project know about everything
implementation(projects.buildEvents)
implementation(projects.buildOption)
implementation(projects.classloaders)
implementation(projects.coreKotlinExtensions)
implementation(projects.coreSerializationCodecs)
implementation(projects.dependencyManagementSerializationCodecs)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ plugins {
description = "Kotlin DSL Provider Plugins"

dependencies {
api(projects.baseServices)
api(projects.classloaders)
api(projects.core)
api(projects.coreApi)
api(projects.kotlinDsl)
Expand All @@ -18,6 +18,7 @@ dependencies {
api(libs.inject)
api(libs.kotlinStdlib)

implementation(projects.baseServices)
implementation(projects.concurrent)
implementation(projects.functional)
implementation(projects.fileCollections)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ dependencies {
api(projects.core)
api(libs.kotlinStdlib)

implementation(projects.classloaders)
implementation(projects.serviceLookup)
implementation(projects.stdlibJavaExtensions)
implementation(projects.time)
Expand Down
1 change: 1 addition & 0 deletions platforms/core-configuration/kotlin-dsl/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ description = "Kotlin DSL Provider"
dependencies {
api(projects.buildProcessServices)
api(projects.baseServices)
api(projects.classloaders)
api(projects.core)
api(projects.coreApi)
api(projects.concurrent)
Expand Down
1 change: 1 addition & 0 deletions platforms/core-configuration/model-core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ dependencies {

implementation(projects.baseServicesGroovy)
implementation(projects.baseAsm)
implementation(projects.classloaders)
implementation(projects.logging)
implementation(projects.problemsApi)
implementation(projects.serviceProvider)
Expand Down
1 change: 1 addition & 0 deletions platforms/core-execution/worker-main/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ dependencies {
api(projects.native)
api(libs.jsr305)

implementation(projects.classloaders)
implementation(projects.concurrent)
implementation(projects.enterpriseLogging)
implementation(projects.serviceProvider)
Expand Down
1 change: 1 addition & 0 deletions platforms/core-execution/workers/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ description = "Infrastructure for starting and managing worker processes"
dependencies {
api(projects.baseServices)
api(projects.buildOperations)
api(projects.classloaders)
api(projects.concurrent)
api(projects.core)
api(projects.coreApi)
Expand Down
8 changes: 4 additions & 4 deletions platforms/core-runtime/base-services/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,17 @@ tasks.named<JavaCompile>("jmhCompileGeneratedClasses") {
moduleIdentity.createBuildReceipt()

dependencies {
api(projects.buildOperations)
api(projects.classloaders)
api(projects.concurrent)
api(projects.stdlibJavaExtensions)
api(projects.fileTemp)
api(projects.serviceLookup)
api(projects.hashing)
api(projects.buildOperations)
api(projects.serviceLookup)
api(projects.stdlibJavaExtensions)
api(libs.inject)
api(libs.jsr305)
api(libs.guava)

implementation(projects.io)
implementation(projects.time)
implementation(projects.baseAsm)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package org.gradle.internal.classloader


import org.gradle.test.precondition.Requires
import org.gradle.test.preconditions.UnitTestPreconditions
import org.junit.Before
Expand Down Expand Up @@ -344,7 +345,7 @@ class FilteringClassLoaderTest extends Specification {
void "spec is copied correctly"() {
given:
def parent = Mock(ClassLoader, useObjenesis: false)
def spec = new FilteringClassLoader.Spec([ 'allow.ClassName' ], [ 'allowPackage' ], [ 'allowPackagePrefix' ], [ 'allowPackageResource' ], [ 'allowResource' ], [ 'disallow.ClassName' ], [ 'disallowPackage' ])
def spec = new FilteringClassLoader.Spec(['allow.ClassName' ], ['allowPackage' ], ['allowPackagePrefix' ], ['allowPackageResource' ], ['allowResource' ], ['disallow.ClassName' ], ['disallowPackage' ])
def filteringClassLoader = new FilteringClassLoader(parent, spec)
def visitor = Mock(ClassLoaderVisitor)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ plugins {
description = "Services and types used to setup a build process from a Gradle distribution."

dependencies {
api(projects.classloaders)
api(projects.stdlibJavaExtensions)
api(projects.baseServices)
api(libs.jsr305)

implementation(projects.baseServices)

implementation(libs.guava)

testImplementation(libs.asm)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public ClassPath findClassPath(String name) {
if (name.equals("DEPENDENCIES-EXTENSION-COMPILER")) {
ClassPath classpath = ClassPath.EMPTY;
classpath = classpath.plus(moduleRegistry.getModule("gradle-base-services").getImplementationClasspath());
classpath = classpath.plus(moduleRegistry.getModule("gradle-classloaders").getImplementationClasspath());
classpath = classpath.plus(moduleRegistry.getModule("gradle-core-api").getImplementationClasspath());
classpath = classpath.plus(moduleRegistry.getModule("gradle-core").getImplementationClasspath());
classpath = classpath.plus(moduleRegistry.getModule("gradle-stdlib-java-extensions").getImplementationClasspath());
Expand Down
1 change: 1 addition & 0 deletions platforms/core-runtime/build-state/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ description = "Types for build process and session state management"

dependencies {
api(projects.baseServices)
api(projects.classloaders)
api(projects.core)
api(projects.daemonProtocol)
api(projects.instrumentationAgentServices)
Expand Down
40 changes: 40 additions & 0 deletions platforms/core-runtime/classloaders/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright 2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

plugins {
id("gradlebuild.distribution.implementation-java")
}

description = "Tools to handle classloaders"

gradlebuildJava.usedInWorkers()

dependencies {
api(projects.hashing)
api(projects.stdlibJavaExtensions)

api(libs.jsr305)

implementation(projects.baseAsm)
implementation(projects.concurrent)
implementation(projects.io)

implementation(libs.commonsIo)
implementation(libs.commonsLang)
implementation(libs.guava)

compileOnly(libs.errorProneAnnotations)
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public class CachingClassLoader extends ClassLoader implements DelegatingClassLo

static {
try {
//noinspection Since15
ClassLoader.registerAsParallelCapable();
} catch (NoSuchMethodError ignore) {
// Not supported on Java 6
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,12 @@

package org.gradle.internal.classloader;

import org.gradle.internal.util.Trie;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashSet;
Expand Down Expand Up @@ -52,6 +51,7 @@ public class FilteringClassLoader extends ClassLoader implements ClassLoaderHier
SYSTEM_PACKAGES.add(p.getName());
}
try {
//noinspection Since15
ClassLoader.registerAsParallelCapable();
} catch (NoSuchMethodError ignore) {
// Not supported on Java 6
Expand Down Expand Up @@ -181,7 +181,7 @@ private boolean classAllowed(String className) {
|| (packagePrefixes.contains(DEFAULT_PACKAGE + ".") && isInDefaultPackage(className));
}

private boolean isInDefaultPackage(String className) {
private static boolean isInDefaultPackage(String className) {
return !className.contains(".");
}

Expand Down Expand Up @@ -233,12 +233,12 @@ private static void addAll(Collection<String> collection, Iterable<String> eleme
*/
public boolean isEmpty() {
return classNames.isEmpty()
&& packageNames.isEmpty()
&& packagePrefixes.isEmpty()
&& resourcePrefixes.isEmpty()
&& resourceNames.isEmpty()
&& disallowedClassNames.isEmpty()
&& disallowedPackagePrefixes.isEmpty();
&& packageNames.isEmpty()
&& packagePrefixes.isEmpty()
&& resourcePrefixes.isEmpty()
&& resourceNames.isEmpty()
&& disallowedClassNames.isEmpty()
&& disallowedPackagePrefixes.isEmpty();
}

/**
Expand Down Expand Up @@ -355,7 +355,7 @@ public Set<String> getDisallowedPackagePrefixes() {
}
}

private static class TrieSet implements Iterable<String> {
public static class TrieSet implements Iterable<String> {
private final Trie trie;
private final Set<String> set;

Expand All @@ -378,4 +378,130 @@ public Iterator<String> iterator() {
return set.iterator();
}
}

/**
* Move the Trie class in :base-services to :functional once we can use Java 8 and delete this class.
*/
public static class Trie implements Comparable<Trie> {
private final char chr;
private final boolean terminal;
private final Trie[] transitions;

public static Trie from(Iterable<String> words) {
Builder builder = new Builder();
for (String word : words) {
builder.addWord(word);
}
return builder.build();
}

private Trie(char chr, boolean terminal, Trie[] transitions) {
this.chr = chr;
this.terminal = terminal;
this.transitions = transitions;
}

@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(chr).append(terminal ? "(terminal)\n" : "\n");
sb.append("Next: ");
for (Trie transition : transitions) {
sb.append(transition.chr).append(" ");
}
sb.append("\n");
return sb.toString();
}

@Override
public int compareTo(@Nonnull Trie o) {
return chr - o.chr;
}

/**
* Checks if the trie contains the given character sequence or any prefixes of the sequence.
*/
public boolean find(CharSequence seq) {
if (seq.length() == 0) {
return false;
}
int idx = 0;
Trie cur = this;
while (idx < seq.length()) {
char c = seq.charAt(idx);
boolean found = false;
for (Trie transition : cur.transitions) {
if (transition.chr == c) {
cur = transition;
idx++;
found = true;
if (idx == seq.length()) {
return cur.terminal;
}
break;
} else if (transition.chr > c) {
return false;
}
}
if (!found) {
return cur.terminal;
}
}
return cur.terminal;
}

public static class Builder {
private final char chr;
private final List<Builder> transitions = new ArrayList<Builder>();

private boolean terminal;

public Builder() {
chr = '\0';
}

private Builder(char chr) {
this.chr = chr;
}

private Builder addTransition(char c, boolean terminal) {
Builder b = null;
for (Builder transition : transitions) {
if (transition.chr == c) {
b = transition;
break;
}
}
if (b == null) {
b = new Builder(c);
transitions.add(b);
}
b.terminal |= terminal;
return b;
}

public void addWord(String word) {
Trie.Builder cur = this;
char[] chars = word.toCharArray();
for (int i = 0; i < chars.length; i++) {
char c = chars[i];
cur = cur.addTransition(c, i == chars.length - 1);
}
}

public Trie build() {
Trie[] transitions = new Trie[this.transitions.size()];
for (int i = 0; i < this.transitions.size(); i++) {
Builder transition = this.transitions.get(i);
transitions[i] = transition.build();
}
Arrays.sort(transitions);
return new Trie(chr, terminal, transitions);
}
}
}

public interface Action<T> {
void execute(T target);
}
}
Loading

0 comments on commit df5bc23

Please sign in to comment.