aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-core/src
diff options
context:
space:
mode:
authorJulien HENRY <julien.henry@sonarsource.com>2024-12-09 15:50:47 +0100
committerSteve Marion <steve.marion@sonarsource.com>2024-12-18 11:13:21 +0100
commit5c62ddeb419dccc7c4768d4382019c47917a6e45 (patch)
treeffdd9364b316c80cd11346f11f2a05fd5ff50303 /sonar-core/src
parent06fae8bf79ac3b3f28021abb6ffa2b4e562ff10c (diff)
downloadsonarqube-5c62ddeb419dccc7c4768d4382019c47917a6e45.tar.gz
sonarqube-5c62ddeb419dccc7c4768d4382019c47917a6e45.zip
SONAR-21354 Revert to use the sonar-classloader library
Diffstat (limited to 'sonar-core/src')
-rw-r--r--sonar-core/src/main/java/org/sonar/classloader/ClassRealm.java206
-rw-r--r--sonar-core/src/main/java/org/sonar/classloader/ClassloaderBuilder.java246
-rw-r--r--sonar-core/src/main/java/org/sonar/classloader/ClassloaderRef.java53
-rw-r--r--sonar-core/src/main/java/org/sonar/classloader/DefaultClassloaderRef.java69
-rw-r--r--sonar-core/src/main/java/org/sonar/classloader/Mask.java208
-rw-r--r--sonar-core/src/main/java/org/sonar/classloader/NullClassloaderRef.java46
-rw-r--r--sonar-core/src/main/java/org/sonar/classloader/ParentFirstStrategy.java64
-rw-r--r--sonar-core/src/main/java/org/sonar/classloader/SelfFirstStrategy.java66
-rw-r--r--sonar-core/src/main/java/org/sonar/classloader/Strategy.java35
-rw-r--r--sonar-core/src/main/java/org/sonar/classloader/StrategyContext.java52
-rw-r--r--sonar-core/src/main/java/org/sonar/classloader/package-info.java24
-rw-r--r--sonar-core/src/test/java/org/sonar/classloader/ClassloaderBuilderTest.java787
-rw-r--r--sonar-core/src/test/java/org/sonar/classloader/MaskTest.java170
13 files changed, 0 insertions, 2026 deletions
diff --git a/sonar-core/src/main/java/org/sonar/classloader/ClassRealm.java b/sonar-core/src/main/java/org/sonar/classloader/ClassRealm.java
deleted file mode 100644
index 1fa3a4d601c..00000000000
--- a/sonar-core/src/main/java/org/sonar/classloader/ClassRealm.java
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2024 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.classloader;
-
-import java.io.IOException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.List;
-import javax.annotation.CheckForNull;
-
-class ClassRealm extends URLClassLoader implements StrategyContext {
-
- private final String key;
- private Mask mask = Mask.ALL;
- private Mask exportMask = Mask.ALL;
- private ClassloaderRef parentRef = NullClassloaderRef.INSTANCE;
- private List<ClassloaderRef> siblingRefs = new ArrayList<>();
- private Strategy strategy;
-
- ClassRealm(String key, ClassLoader baseClassloader) {
- super(new URL[0], baseClassloader);
- this.key = key;
- }
-
- String getKey() {
- return key;
- }
-
- ClassRealm setMask(Mask mask) {
- this.mask = mask;
- return this;
- }
-
- Mask getExportMask() {
- return exportMask;
- }
-
- ClassRealm setExportMask(Mask exportMask) {
- this.exportMask = exportMask;
- return this;
- }
-
- ClassRealm setParent(ClassloaderRef parentRef) {
- this.parentRef = parentRef;
- return this;
- }
-
- ClassRealm addSibling(ClassloaderRef ref) {
- this.siblingRefs.add(ref);
- return this;
- }
-
- ClassRealm setStrategy(Strategy strategy) {
- this.strategy = strategy;
- return this;
- }
-
- ClassRealm addConstituent(URL url) {
- super.addURL(url);
- return this;
- }
-
- @Override
- public Class<?> loadClass(String name) throws ClassNotFoundException {
- return loadClass(name, false);
- }
-
- @Override
- protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
- if (mask.acceptClass(name)) {
- try {
- // first, try loading bootstrap classes
- return super.loadClass(name, resolve);
- } catch (ClassNotFoundException ignored) {
- // next, try loading via siblings, self and parent as controlled by strategy
- return strategy.loadClass(this, name);
- }
- }
- throw new ClassNotFoundException(String.format("Class %s is not accepted in classloader %s", name, this));
- }
-
-
- @Override
- protected Class<?> findClass(String name) throws ClassNotFoundException {
- // not supposed to be used. Replaced by loadClassFromSelf(String)
- throw new ClassNotFoundException(name);
- }
-
- @CheckForNull
- @Override
- public URL getResource(String name) {
- if (mask.acceptResource(name)) {
- return strategy.getResource(this, name);
- }
- return null;
- }
-
- @Override
- public Enumeration<URL> getResources(String name) throws IOException {
- // Important note: do not use java.util.Set as equals and hashCode methods of
- // java.net.URL perform domain name resolution. This can result in a big performance hit.
- List<URL> resources = new ArrayList<>();
- if (mask.acceptResource(name)) {
- strategy.getResources(this, name, resources);
- }
- return Collections.enumeration(resources);
- }
-
- @Override
- public Class<?> loadClassFromSelf(String name) {
- Class<?> clazz = findLoadedClass(name);
- if (clazz == null) {
- try {
- return super.findClass(name);
- } catch (ClassNotFoundException ignored) {
- // return null when class is not found, so that loading strategy
- // can try parent or sibling classloaders.
- }
- }
- return clazz;
- }
-
- @Override
- public Class<?> loadClassFromSiblings(String name) {
- for (ClassloaderRef siblingRef : siblingRefs) {
- Class<?> clazz = siblingRef.loadClassIfPresent(name);
- if (clazz != null) {
- return clazz;
- }
- }
- return null;
- }
-
- @Override
- public Class<?> loadClassFromParent(String name) {
- return parentRef.loadClassIfPresent(name);
- }
-
- @Override
- public URL loadResourceFromSelf(String name) {
- return super.findResource(name);
- }
-
- @Override
- public URL loadResourceFromSiblings(String name) {
- for (ClassloaderRef siblingRef : siblingRefs) {
- URL url = siblingRef.loadResourceIfPresent(name);
- if (url != null) {
- return url;
- }
- }
- return null;
- }
-
- @Override
- public URL loadResourceFromParent(String name) {
- return parentRef.loadResourceIfPresent(name);
- }
-
- @Override
- public void loadResourcesFromSelf(String name, Collection<URL> appendTo) {
- try {
- appendTo.addAll(Collections.list(super.findResources(name)));
- } catch (IOException e) {
- throw new IllegalStateException(String.format("Fail to load resources named '%s' from classloader %s", name, toString()), e);
- }
- }
-
- @Override
- public void loadResourcesFromSiblings(String name, Collection<URL> appendTo) {
- for (ClassloaderRef siblingRef : siblingRefs) {
- siblingRef.loadResources(name, appendTo);
- }
- }
-
- @Override
- public void loadResourcesFromParent(String name, Collection<URL> appendTo) {
- parentRef.loadResources(name, appendTo);
- }
-
- @Override
- public String toString() {
- return String.format("ClassRealm{%s}", key);
- }
-}
diff --git a/sonar-core/src/main/java/org/sonar/classloader/ClassloaderBuilder.java b/sonar-core/src/main/java/org/sonar/classloader/ClassloaderBuilder.java
deleted file mode 100644
index 5a843212fc9..00000000000
--- a/sonar-core/src/main/java/org/sonar/classloader/ClassloaderBuilder.java
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2024 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.classloader;
-
-import java.net.URL;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import static java.util.Collections.emptyList;
-
-/**
- * @since 0.1
- */
-public class ClassloaderBuilder {
- private final Map<String, ClassRealm> previouslyCreatedClassLoaders;
-
- private final Map<String, NewRealm> newRealmsByKey = new HashMap<>();
-
- public ClassloaderBuilder() {
- this(emptyList());
- }
-
- /**
- * Creates a new classloader builder that can use a collection of previously created
- * classloaders as parent or siblings when building the new classloaders.
- *
- * @param previouslyCreatedClassLoaders Collection of classloaders that can be used as a
- * parent or sibling. Must be of type {@link ClassRealm}.
- */
- public ClassloaderBuilder(Collection<ClassLoader> previouslyCreatedClassLoaders) {
- this.previouslyCreatedClassLoaders = new HashMap<>();
- for (ClassLoader cl : previouslyCreatedClassLoaders) {
- if (!(cl instanceof ClassRealm)) {
- throw new IllegalArgumentException("classloader not of type ClassRealm: " + cl);
- }
- ClassRealm classRealm = (ClassRealm) cl;
- this.previouslyCreatedClassLoaders.put(classRealm.getKey(), classRealm);
- }
- }
-
- public enum LoadingOrder {
- /**
- * Order: siblings, then parent, then self
- */
- PARENT_FIRST(ParentFirstStrategy.INSTANCE),
-
- /**
- * Order: siblings, then self, then parent
- */
- SELF_FIRST(SelfFirstStrategy.INSTANCE);
-
- private final Strategy strategy;
-
- LoadingOrder(Strategy strategy) {
- this.strategy = strategy;
- }
- }
-
- /**
- * Wrapper of {@link ClassRealm} as long as associations are not fully
- * defined
- */
- private static class NewRealm {
- private final ClassRealm realm;
-
- // key of the optional parent classloader
- private String parentKey;
-
- private final List<String> siblingKeys = new ArrayList<>();
- private final Map<String, Mask> associatedMasks = new HashMap<>();
-
- private NewRealm(ClassRealm realm) {
- this.realm = realm;
- }
- }
-
- /**
- * Declares a new classloader based on system classloader.
- */
- public ClassloaderBuilder newClassloader(String key) {
- return newClassloader(key, getSystemClassloader());
- }
-
- /**
- * Declares a new classloader based on a given parent classloader. Key must be unique. An
- * {@link IllegalArgumentException} is thrown if the key is already referenced.
- * <p/>
- * Default loading order is {@link LoadingOrder#PARENT_FIRST}.
- */
- public ClassloaderBuilder newClassloader(final String key, final ClassLoader baseClassloader) {
- if (newRealmsByKey.containsKey(key)) {
- throw new IllegalStateException(String.format("The classloader '%s' already exists. Can not create it twice.", key));
- }
- if (previouslyCreatedClassLoaders.containsKey(key)) {
- throw new IllegalStateException(String.format("The classloader '%s' already exists in the list of previously created classloaders."
- + " Can not create it twice.", key));
- }
- ClassRealm realm = AccessController.doPrivileged((PrivilegedAction<ClassRealm>) () -> new ClassRealm(key, baseClassloader));
- realm.setStrategy(LoadingOrder.PARENT_FIRST.strategy);
- newRealmsByKey.put(key, new NewRealm(realm));
- return this;
- }
-
- public ClassloaderBuilder setParent(String key, String parentKey, Mask mask) {
- NewRealm newRealm = getOrFail(key);
- newRealm.parentKey = parentKey;
- newRealm.associatedMasks.put(parentKey, mask);
- return this;
- }
-
- public ClassloaderBuilder setParent(String key, ClassLoader parent, Mask mask) {
- NewRealm newRealm = getOrFail(key);
- newRealm.realm.setParent(new DefaultClassloaderRef(parent, mask));
- return this;
- }
-
- public ClassloaderBuilder addSibling(String key, String siblingKey, Mask mask) {
- NewRealm newRealm = getOrFail(key);
- newRealm.siblingKeys.add(siblingKey);
- newRealm.associatedMasks.put(siblingKey, mask);
- return this;
- }
-
- public ClassloaderBuilder addSibling(String key, ClassLoader sibling, Mask mask) {
- NewRealm newRealm = getOrFail(key);
- newRealm.realm.addSibling(new DefaultClassloaderRef(sibling, mask));
- return this;
- }
-
- public ClassloaderBuilder addURL(String key, URL url) {
- getOrFail(key).realm.addConstituent(url);
- return this;
- }
-
- public ClassloaderBuilder setMask(String key, Mask mask) {
- getOrFail(key).realm.setMask(mask);
- return this;
- }
-
- public ClassloaderBuilder setExportMask(String key, Mask mask) {
- getOrFail(key).realm.setExportMask(mask);
- return this;
- }
-
- public ClassloaderBuilder setLoadingOrder(String key, LoadingOrder order) {
- getOrFail(key).realm.setStrategy(order.strategy);
- return this;
- }
-
- /**
- * Returns the new classloaders, grouped by keys. The parent and sibling classloaders
- * that are already existed (see {@link #setParent(String, ClassLoader, Mask)}
- * and {@link #addSibling(String, ClassLoader, Mask)} are not included into result.
- */
- public Map<String, ClassLoader> build() {
- Map<String, ClassLoader> result = new HashMap<>();
-
- // all the classloaders are created. Associations can now be resolved.
- for (Map.Entry<String, NewRealm> entry : newRealmsByKey.entrySet()) {
- NewRealm newRealm = entry.getValue();
- if (newRealm.parentKey != null) {
- ClassRealm parent = getNewOrPreviousClassloader(newRealm.parentKey);
- Mask parentMask = newRealm.associatedMasks.get(newRealm.parentKey);
- parentMask = mergeWithExportMask(parentMask, newRealm.parentKey);
- newRealm.realm.setParent(new DefaultClassloaderRef(parent, parentMask));
- }
- for (String siblingKey : newRealm.siblingKeys) {
- ClassRealm sibling = getNewOrPreviousClassloader(siblingKey);
- Mask siblingMask = newRealm.associatedMasks.get(siblingKey);
- siblingMask = mergeWithExportMask(siblingMask, siblingKey);
- newRealm.realm.addSibling(new DefaultClassloaderRef(sibling, siblingMask));
- }
- result.put(newRealm.realm.getKey(), newRealm.realm);
- }
- return result;
- }
-
- private Mask mergeWithExportMask(Mask mask, String exportKey) {
- NewRealm newRealm = newRealmsByKey.get(exportKey);
- if (newRealm != null) {
- return Mask.builder().copy(mask).merge(newRealm.realm.getExportMask()).build();
- }
- ClassRealm realm = previouslyCreatedClassLoaders.get(exportKey);
- if (realm != null) {
- return Mask.builder().copy(mask).merge(realm.getExportMask()).build();
- }
- return mask;
- }
-
- private NewRealm getOrFail(String key) {
- NewRealm newRealm = newRealmsByKey.get(key);
- if (newRealm == null) {
- throw new IllegalStateException(String.format("The classloader '%s' does not exist", key));
- }
- return newRealm;
- }
-
- private ClassRealm getNewOrPreviousClassloader(String key) {
- NewRealm newRealm = newRealmsByKey.get(key);
- if (newRealm != null) {
- return newRealm.realm;
- }
- ClassRealm previousClassloader = previouslyCreatedClassLoaders.get(key);
- if (previousClassloader != null) {
- return previousClassloader;
- }
-
- throw new IllegalStateException(String.format("The classloader '%s' does not exist", key));
- }
-
- /**
- * JRE system classloader. In Oracle JVM:
- * - ClassLoader.getSystemClassLoader() is sun.misc.Launcher$AppClassLoader. It contains app classpath.
- * - ClassLoader.getSystemClassLoader().getParent() is sun.misc.Launcher$ExtClassLoader. It is the JRE core classloader.
- */
- private static ClassLoader getSystemClassloader() {
- ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
- ClassLoader systemParent = systemClassLoader.getParent();
- if (systemParent != null) {
- systemClassLoader = systemParent;
- }
- return systemClassLoader;
- }
-}
diff --git a/sonar-core/src/main/java/org/sonar/classloader/ClassloaderRef.java b/sonar-core/src/main/java/org/sonar/classloader/ClassloaderRef.java
deleted file mode 100644
index 0443f31db7e..00000000000
--- a/sonar-core/src/main/java/org/sonar/classloader/ClassloaderRef.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2024 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.classloader;
-
-import java.net.URL;
-import java.util.Collection;
-import javax.annotation.CheckForNull;
-
-interface ClassloaderRef {
-
- /**
- * Does not throw {@link java.lang.ClassNotFoundException} but returns null
- * when class is not found
- *
- * @param name name of class, for example "org.foo.Bar"
- */
- @CheckForNull
- Class<?> loadClassIfPresent(String name);
-
- /**
- * Searches for a resource. Returns null if not found.
- *
- * @param name name of resource, for example "org/foo/Bar.class" or "org/foo/config.xml"
- */
- @CheckForNull
- URL loadResourceIfPresent(String name);
-
- /**
- * Searches for all the occurrences of a resource from hierarchy of classloaders.
- * Results are appended to the parameter "appendTo". Order of resources is given by the
- * hierarchy order of classloaders.
- *
- * @see #loadResourceIfPresent(String) for the format of resource name
- */
- void loadResources(String name, Collection<URL> appendTo);
-}
diff --git a/sonar-core/src/main/java/org/sonar/classloader/DefaultClassloaderRef.java b/sonar-core/src/main/java/org/sonar/classloader/DefaultClassloaderRef.java
deleted file mode 100644
index 722964f880b..00000000000
--- a/sonar-core/src/main/java/org/sonar/classloader/DefaultClassloaderRef.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2024 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.classloader;
-
-import java.io.IOException;
-import java.net.URL;
-import java.util.Collection;
-import java.util.Enumeration;
-
-class DefaultClassloaderRef implements ClassloaderRef {
- private final Mask mask;
- private final ClassLoader classloader;
-
- DefaultClassloaderRef(ClassLoader classloader, Mask mask) {
- this.classloader = classloader;
- this.mask = mask;
- }
-
- @Override
- public Class loadClassIfPresent(String classname) {
- if (mask.acceptClass(classname)) {
- try {
- return classloader.loadClass(classname);
- } catch (ClassNotFoundException ignored) {
- // excepted behavior. Return null if class does not exist in this classloader
- }
- }
- return null;
- }
-
- @Override
- public URL loadResourceIfPresent(String name) {
- if (mask.acceptResource(name)) {
- return classloader.getResource(name);
- }
- return null;
- }
-
- @Override
- public void loadResources(String name, Collection<URL> appendTo) {
- if (mask.acceptResource(name)) {
- try {
- Enumeration<URL> resources = classloader.getResources(name);
- while (resources.hasMoreElements()) {
- appendTo.add(resources.nextElement());
- }
- } catch (IOException e) {
- throw new IllegalStateException(String.format("Fail to load resources named '%s'", name), e);
- }
- }
- }
-}
diff --git a/sonar-core/src/main/java/org/sonar/classloader/Mask.java b/sonar-core/src/main/java/org/sonar/classloader/Mask.java
deleted file mode 100644
index e20e5756bfa..00000000000
--- a/sonar-core/src/main/java/org/sonar/classloader/Mask.java
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2024 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.classloader;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Optional;
-import java.util.Set;
-import javax.annotation.Nullable;
-
-/**
- * A mask restricts access of a classloader to resources through inclusion and exclusion patterns.
- * By default all resources/classes are visible.
- * <p/>
- * Format of inclusion/exclusion patterns is the file path separated by slashes, for example
- * "org/foo/Bar.class" or "org/foo/config.xml". Wildcard patterns are not supported. Directories must end with
- * slash, for example "org/foo/" for excluding package org.foo and its sub-packages. Add the
- * exclusion "/" to exclude everything.
- *
- * @since 0.1
- */
-public class Mask {
-
- private static final String ROOT = "/";
-
- /**
- * Accepts everything
- *
- * @since 1.1
- */
- public static final Mask ALL = Mask.builder().build();
-
- /**
- * Accepts nothing
- *
- * @since 1.1
- */
- public static final Mask NONE = Mask.builder().exclude(ROOT).build();
-
- private final Set<String> inclusions;
- private final Set<String> exclusions;
-
- private Mask(Builder builder) {
- this.inclusions = Collections.unmodifiableSet(builder.inclusions);
- this.exclusions = Collections.unmodifiableSet(builder.exclusions);
- }
-
- /**
- * Create a {@link Builder} for building immutable instances of {@link Mask}
- *
- * @since 1.1
- */
- public static Builder builder() {
- return new Builder();
- }
-
- public Set<String> getInclusions() {
- return inclusions;
- }
-
- public Set<String> getExclusions() {
- return exclusions;
- }
-
- boolean acceptClass(String classname) {
- if (inclusions.isEmpty() && exclusions.isEmpty()) {
- return true;
- }
- return acceptResource(classToResource(classname));
- }
-
- boolean acceptResource(String name) {
- boolean ok = true;
- if (!inclusions.isEmpty()) {
- ok = false;
- for (String include : inclusions) {
- if (matchPattern(name, include)) {
- ok = true;
- break;
- }
- }
- }
- if (ok) {
- for (String exclude : exclusions) {
- if (matchPattern(name, exclude)) {
- ok = false;
- break;
- }
- }
- }
- return ok;
- }
-
- private static boolean matchPattern(String name, String pattern) {
- return pattern.equals(ROOT) || (pattern.endsWith("/") && name.startsWith(pattern)) || pattern.equals(name);
- }
-
- private static String classToResource(String classname) {
- return classname.replace('.', '/') + ".class";
- }
-
-
- public static class Builder {
- private final Set<String> inclusions = new HashSet<>();
- private final Set<String> exclusions = new HashSet<>();
-
- private Builder() {
- }
-
- public Builder include(String path, String... others) {
- doInclude(path);
- for (String other : others) {
- doInclude(other);
- }
- return this;
- }
-
- public Builder exclude(String path, String... others) {
- doExclude(path);
- for (String other : others) {
- doExclude(other);
- }
- return this;
- }
-
- public Builder copy(Mask with) {
- this.inclusions.addAll(with.inclusions);
- this.exclusions.addAll(with.exclusions);
- return this;
- }
-
- public Builder merge(Mask with) {
- List<String> lowestIncludes = new ArrayList<>();
-
- if (inclusions.isEmpty()) {
- lowestIncludes.addAll(with.inclusions);
- } else if (with.inclusions.isEmpty()) {
- lowestIncludes.addAll(inclusions);
- } else {
- for (String include : inclusions) {
- for (String fromInclude : with.inclusions) {
- overlappingInclude(include, fromInclude)
- .ifPresent(lowestIncludes::add);
- }
- }
- }
- inclusions.clear();
- inclusions.addAll(lowestIncludes);
- exclusions.addAll(with.exclusions);
- return this;
- }
-
- private static Optional<String> overlappingInclude(String include, String fromInclude) {
- if (fromInclude.equals(include)) {
- return Optional.of(fromInclude);
- } else if (fromInclude.startsWith(include)) {
- return Optional.of(fromInclude);
- } else if (include.startsWith(fromInclude)) {
- return Optional.of(include);
- }
- return Optional.empty();
- }
-
- public Mask build() {
- return new Mask(this);
- }
-
- private void doInclude(@Nullable String path) {
- this.inclusions.add(validatePath(path));
- }
-
- private void doExclude(@Nullable String path) {
- this.exclusions.add(validatePath(path));
- }
-
- private static String validatePath(@Nullable String path) {
- if (path == null) {
- throw new IllegalArgumentException("Mask path must not be null");
- }
- if (path.startsWith("/") && path.length() > 1) {
- throw new IllegalArgumentException("Mask path must not start with slash: ");
- }
- if (path.contains("*")) {
- throw new IllegalArgumentException("Mask path is not a wildcard pattern and should not contain star characters (*): " + path);
- }
- return path;
- }
- }
-}
diff --git a/sonar-core/src/main/java/org/sonar/classloader/NullClassloaderRef.java b/sonar-core/src/main/java/org/sonar/classloader/NullClassloaderRef.java
deleted file mode 100644
index 68e481754bd..00000000000
--- a/sonar-core/src/main/java/org/sonar/classloader/NullClassloaderRef.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2024 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.classloader;
-
-import java.net.URL;
-import java.util.Collection;
-
-class NullClassloaderRef implements ClassloaderRef {
-
- public static final NullClassloaderRef INSTANCE = new NullClassloaderRef();
-
- private NullClassloaderRef() {
- }
-
- @Override
- public Class loadClassIfPresent(String classname) {
- return null;
- }
-
- @Override
- public URL loadResourceIfPresent(String name) {
- return null;
- }
-
- @Override
- public void loadResources(String name, Collection<URL> appendTo) {
- // do nothing
- }
-}
diff --git a/sonar-core/src/main/java/org/sonar/classloader/ParentFirstStrategy.java b/sonar-core/src/main/java/org/sonar/classloader/ParentFirstStrategy.java
deleted file mode 100644
index 54962da829b..00000000000
--- a/sonar-core/src/main/java/org/sonar/classloader/ParentFirstStrategy.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2024 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.classloader;
-
-import java.net.URL;
-import java.util.Collection;
-
-class ParentFirstStrategy implements Strategy {
- static final Strategy INSTANCE = new ParentFirstStrategy();
-
- private ParentFirstStrategy() {
- }
-
- @Override
- public Class<?> loadClass(StrategyContext context, String name) throws ClassNotFoundException {
- Class<?> clazz = context.loadClassFromSiblings(name);
- if (clazz == null) {
- clazz = context.loadClassFromParent(name);
- if (clazz == null) {
- clazz = context.loadClassFromSelf(name);
- if (clazz == null) {
- throw new ClassNotFoundException(name);
- }
- }
- }
- return clazz;
- }
-
- @Override
- public URL getResource(StrategyContext context, String name) {
- URL url = context.loadResourceFromSiblings(name);
- if (url == null) {
- url = context.loadResourceFromParent(name);
- if (url == null) {
- url = context.loadResourceFromSelf(name);
- }
- }
- return url;
- }
-
- @Override
- public void getResources(StrategyContext context, String name, Collection<URL> appendTo) {
- context.loadResourcesFromSiblings(name, appendTo);
- context.loadResourcesFromParent(name, appendTo);
- context.loadResourcesFromSelf(name, appendTo);
- }
-}
diff --git a/sonar-core/src/main/java/org/sonar/classloader/SelfFirstStrategy.java b/sonar-core/src/main/java/org/sonar/classloader/SelfFirstStrategy.java
deleted file mode 100644
index 1c990e95417..00000000000
--- a/sonar-core/src/main/java/org/sonar/classloader/SelfFirstStrategy.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2024 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.classloader;
-
-import java.net.URL;
-import java.util.Collection;
-
-class SelfFirstStrategy implements Strategy {
-
- static final SelfFirstStrategy INSTANCE = new SelfFirstStrategy();
-
- private SelfFirstStrategy() {
- // singleton instance
- }
-
- @Override
- public Class<?> loadClass(StrategyContext context, String name) throws ClassNotFoundException {
- Class<?> clazz = context.loadClassFromSiblings(name);
- if (clazz == null) {
- clazz = context.loadClassFromSelf(name);
- if (clazz == null) {
- clazz = context.loadClassFromParent(name);
- if (clazz == null) {
- throw new ClassNotFoundException(name);
- }
- }
- }
- return clazz;
- }
-
- @Override
- public URL getResource(StrategyContext context, String name) {
- URL url = context.loadResourceFromSiblings(name);
- if (url == null) {
- url = context.loadResourceFromSelf(name);
- if (url == null) {
- url = context.loadResourceFromParent(name);
- }
- }
- return url;
- }
-
- @Override
- public void getResources(StrategyContext context, String name, Collection<URL> appendTo) {
- context.loadResourcesFromSiblings(name, appendTo);
- context.loadResourcesFromSelf(name, appendTo);
- context.loadResourcesFromParent(name, appendTo);
- }
-}
diff --git a/sonar-core/src/main/java/org/sonar/classloader/Strategy.java b/sonar-core/src/main/java/org/sonar/classloader/Strategy.java
deleted file mode 100644
index a7790b174a9..00000000000
--- a/sonar-core/src/main/java/org/sonar/classloader/Strategy.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2024 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.classloader;
-
-import java.net.URL;
-import java.util.Collection;
-import javax.annotation.CheckForNull;
-
-interface Strategy {
-
- Class<?> loadClass(StrategyContext context, String name) throws ClassNotFoundException;
-
- @CheckForNull
- URL getResource(StrategyContext context, String name);
-
- void getResources(StrategyContext context, String name, Collection<URL> urls);
-
-}
diff --git a/sonar-core/src/main/java/org/sonar/classloader/StrategyContext.java b/sonar-core/src/main/java/org/sonar/classloader/StrategyContext.java
deleted file mode 100644
index 31b3b34e04c..00000000000
--- a/sonar-core/src/main/java/org/sonar/classloader/StrategyContext.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2024 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.classloader;
-
-import java.net.URL;
-import java.util.Collection;
-import javax.annotation.CheckForNull;
-
-interface StrategyContext {
-
- @CheckForNull
- Class<?> loadClassFromSiblings(String name);
-
- @CheckForNull
- Class<?> loadClassFromSelf(String name);
-
- @CheckForNull
- Class<?> loadClassFromParent(String name);
-
- @CheckForNull
- URL loadResourceFromSiblings(String name);
-
- @CheckForNull
- URL loadResourceFromSelf(String name);
-
- @CheckForNull
- URL loadResourceFromParent(String name);
-
- void loadResourcesFromSiblings(String name, Collection<URL> appendTo);
-
- void loadResourcesFromSelf(String name, Collection<URL> appendTo);
-
- void loadResourcesFromParent(String name, Collection<URL> appendTo);
-
-}
diff --git a/sonar-core/src/main/java/org/sonar/classloader/package-info.java b/sonar-core/src/main/java/org/sonar/classloader/package-info.java
deleted file mode 100644
index ccb9c13cb74..00000000000
--- a/sonar-core/src/main/java/org/sonar/classloader/package-info.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2024 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-@ParametersAreNonnullByDefault
-package org.sonar.classloader;
-
-import javax.annotation.ParametersAreNonnullByDefault;
-
diff --git a/sonar-core/src/test/java/org/sonar/classloader/ClassloaderBuilderTest.java b/sonar-core/src/test/java/org/sonar/classloader/ClassloaderBuilderTest.java
deleted file mode 100644
index 08e67eec07c..00000000000
--- a/sonar-core/src/test/java/org/sonar/classloader/ClassloaderBuilderTest.java
+++ /dev/null
@@ -1,787 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2024 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.classloader;
-
-import java.io.File;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import org.apache.commons.io.IOUtils;
-import org.junit.Test;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.Assert.fail;
-
-public class ClassloaderBuilderTest {
-
- ClassloaderBuilder sut = new ClassloaderBuilder();
-
- @Test
- public void minimal_system_classloader() throws Exception {
- // create a classloader based on system classloader
- // -> access only to JRE
- Map<String, ClassLoader> classloaders = sut.newClassloader("example").build();
-
- assertThat(classloaders).hasSize(1);
- ClassLoader classloader = classloaders.get("example");
- assertThat(classloader).hasToString("ClassRealm{example}");
- assertThat(canLoadClass(classloader, HashMap.class.getName())).isTrue();
- assertThat(canLoadClass(classloader, Test.class.getName())).isFalse();
- assertThat(canLoadClass(classloader, "A")).isFalse();
- assertThat(canLoadResource(classloader, "a.txt")).isFalse();
- }
-
- @Test
- public void previous_classloader_not_returned_again() throws Exception {
- Map<String, ClassLoader> classloaders1 = sut.newClassloader("example1").build();
- Map<String, ClassLoader> classloaders2 = new ClassloaderBuilder(classloaders1.values())
- .newClassloader("example2").build();
-
- assertThat(classloaders2).containsOnlyKeys("example2");
- }
-
- @Test
- public void fail_if_setting_attribute_to_previously_loaded_classloader() throws Exception {
- Map<String, ClassLoader> classloaders1 = sut.newClassloader("example1").build();
- ClassloaderBuilder builder = new ClassloaderBuilder(classloaders1.values())
- .newClassloader("example2");
-
- try {
- builder.setMask("example1", Mask.ALL);
- fail();
- } catch (IllegalStateException e) {
- // ok
- }
- }
-
- /**
- * Classloader based on another one (the junit env in this example). No parent-child hierarchy.
- */
- @Test
- public void base_classloader() throws Exception {
- //
- Map<String, ClassLoader> classloaders = sut.newClassloader("example", getClass().getClassLoader()).build();
-
- assertThat(classloaders).hasSize(1);
- ClassLoader classloader = classloaders.get("example");
- assertThat(canLoadClass(classloader, HashMap.class.getName())).isTrue();
- assertThat(canLoadClass(classloader, Test.class.getName())).isTrue();
- assertThat(canLoadClass(classloader, "A")).isFalse();
- assertThat(canLoadResource(classloader, "a.txt")).isFalse();
- }
-
- @Test
- public void classloader_constituents() throws Exception {
- Map<String, ClassLoader> classloaders = sut
- .newClassloader("the-cl")
- .addURL("the-cl", new File("tester/a.jar").toURL())
- .addURL("the-cl", new File("tester/b.jar").toURL())
- .build();
-
- assertThat(classloaders).hasSize(1);
- ClassLoader self = classloaders.get("the-cl");
- assertThat(canLoadClass(self, "A")).isTrue();
- assertThat(canLoadResource(self, "a.txt")).isTrue();
- assertThat(canLoadClass(self, "B")).isTrue();
- assertThat(canLoadResource(self, "b.txt")).isTrue();
- assertThat(canLoadClass(self, "C")).isFalse();
- assertThat(canLoadResource(self, "c.txt")).isFalse();
- }
-
- /**
- * Parent -> child -> grand-child classloaders. Default order strategy is parent-first
- */
- @Test
- public void parent_child_relation() throws Exception {
- // parent contains class A -> access to only A
- // child contains class B -> access to A and B
- // grand-child contains class C -> access to A, B and C
- Map<String, ClassLoader> classloaders = sut
- .newClassloader("the-parent")
- .addURL("the-parent", new File("tester/a.jar").toURL())
-
- // order of declaration is not important -> declare grand-child before child
- .newClassloader("the-grand-child")
- .addURL("the-grand-child", new File("tester/c.jar").toURL())
- .setParent("the-grand-child", "the-child", Mask.ALL)
-
- .newClassloader("the-child")
- .addURL("the-child", new File("tester/b.jar").toURL())
- .setParent("the-child", "the-parent", Mask.ALL)
-
- .build();
-
- assertThat(classloaders).hasSize(3);
-
- ClassLoader parent = classloaders.get("the-parent");
- assertThat(canLoadClass(parent, "A")).isTrue();
- assertThat(canLoadClass(parent, "B")).isFalse();
- assertThat(canLoadClass(parent, "C")).isFalse();
- assertThat(canLoadResource(parent, "a.txt")).isTrue();
- assertThat(canLoadResource(parent, "b.txt")).isFalse();
- assertThat(canLoadResource(parent, "c.txt")).isFalse();
-
- ClassLoader child = classloaders.get("the-child");
- assertThat(canLoadClass(child, "A")).isTrue();
- assertThat(canLoadClass(child, "B")).isTrue();
- assertThat(canLoadClass(child, "C")).isFalse();
- assertThat(canLoadResource(child, "a.txt")).isTrue();
- assertThat(canLoadResource(child, "b.txt")).isTrue();
- assertThat(canLoadResource(child, "c.txt")).isFalse();
-
- ClassLoader grandChild = classloaders.get("the-grand-child");
- assertThat(canLoadClass(grandChild, "A")).isTrue();
- assertThat(canLoadClass(grandChild, "B")).isTrue();
- assertThat(canLoadClass(grandChild, "C")).isTrue();
- assertThat(canLoadResource(grandChild, "a.txt")).isTrue();
- assertThat(canLoadResource(grandChild, "b.txt")).isTrue();
- assertThat(canLoadResource(grandChild, "c.txt")).isTrue();
- }
-
- /**
- * Parent classloader can be created outside {@link ClassloaderBuilder}.
- * Default ordering strategy is parent-first.
- */
- @Test
- public void existing_parent() throws Exception {
- // parent contains JUnit
- // child contains class A -> access to A and JUnit
- ClassLoader parent = getClass().getClassLoader();
- Map<String, ClassLoader> newClassloaders = sut
- .newClassloader("the-child")
- .addURL("the-child", new File("tester/a.jar").toURL())
- .setParent("the-child", parent, Mask.ALL)
- .build();
-
- assertThat(newClassloaders).hasSize(1);
- assertThat(canLoadClass(parent, Test.class.getName())).isTrue();
- assertThat(canLoadClass(parent, "A")).isFalse();
- ClassLoader child = newClassloaders.get("the-child");
- assertThat(canLoadClass(child, Test.class.getName())).isTrue();
- assertThat(canLoadClass(child, "A")).isTrue();
- }
-
- @Test
- public void parent_first_ordering() throws Exception {
- // parent contains version 1 of A
- // child contains version 2 of A
- Map<String, ClassLoader> newClassloaders = sut
- .newClassloader("the-parent")
- .addURL("the-parent", new File("tester/a.jar").toURL())
-
- .newClassloader("the-child")
- .addURL("the-child", new File("tester/a_v2.jar").toURL())
- .setParent("the-child", "the-parent", Mask.ALL)
- .build();
-
- ClassLoader parent = newClassloaders.get("the-parent");
- assertThat(canLoadMethod(parent, "A", "version1")).isTrue();
- assertThat(canLoadMethod(parent, "A", "version2")).isFalse();
- assertThat(IOUtils.toString(parent.getResource("a.txt"))).startsWith("version 1 of a.txt");
-
- ClassLoader child = newClassloaders.get("the-child");
- assertThat(canLoadMethod(child, "A", "version1")).isTrue();
- assertThat(canLoadMethod(child, "A", "version2")).isFalse();
- assertThat(IOUtils.toString(child.getResource("a.txt"))).startsWith("version 1 of a.txt");
- }
-
- /**
- * - parent contains B and version 1 of A
- * - child contains version 2 of A -> sees B and version 2 of A
- */
- @Test
- public void self_first_ordering() throws Exception {
-
- Map<String, ClassLoader> newClassloaders = sut
- .newClassloader("the-parent")
- .addURL("the-parent", new File("tester/a.jar").toURL())
- .addURL("the-parent", new File("tester/b.jar").toURL())
-
- .newClassloader("the-child")
- .addURL("the-child", new File("tester/a_v2.jar").toURL())
- .setParent("the-child", "the-parent", Mask.ALL)
- .setLoadingOrder("the-child", ClassloaderBuilder.LoadingOrder.SELF_FIRST)
- .build();
-
- ClassLoader parent = newClassloaders.get("the-parent");
- assertThat(canLoadMethod(parent, "A", "version1")).isTrue();
- assertThat(canLoadMethod(parent, "A", "version2")).isFalse();
- assertThat(IOUtils.toString(parent.getResource("a.txt"))).startsWith("version 1 of a.txt");
-
- ClassLoader child = newClassloaders.get("the-child");
- assertThat(canLoadClass(child, "B")).isTrue();
- assertThat(canLoadMethod(child, "A", "version1")).isFalse();
- assertThat(canLoadMethod(child, "A", "version2")).isTrue();
- assertThat(IOUtils.toString(child.getResource("a.txt"))).startsWith("version 2 of a.txt");
- assertThat(Collections.list(child.getResources("b.txt"))).hasSize(1);
- ArrayList<URL> resources = Collections.list(child.getResources("a.txt"));
- assertThat(resources).hasSize(2);
- assertThat(IOUtils.toString(resources.get(0))).startsWith("version 2 of a.txt");
- assertThat(IOUtils.toString(resources.get(1))).startsWith("version 1 of a.txt");
- }
-
- /**
- * Prevent a classloader from loading some resources that are available in its own constituents.
- */
- @Test
- public void self_mask() throws Exception {
- Map<String, ClassLoader> classloaders = sut
- .newClassloader("the-cl")
- .addURL("the-cl", new File("tester/a.jar").toURL())
- .addURL("the-cl", new File("tester/b.jar").toURL())
- .setMask("the-cl", Mask.builder().exclude("A.class", "a.txt").build())
- .build();
-
- ClassLoader cl = classloaders.get("the-cl");
- assertThat(canLoadClass(cl, "A")).isFalse();
- assertThat(canLoadClass(cl, "B")).isTrue();
- assertThat(canLoadResource(cl, "a.txt")).isFalse();
- assertThat(canLoadResource(cl, "b.txt")).isTrue();
- }
-
- /**
- * Partial inheritance of parent classloader
- */
- @Test
- public void parent_mask() throws Exception {
- Map<String, ClassLoader> newClassloaders = sut
- .newClassloader("the-parent")
- .addURL("the-parent", new File("tester/a.jar").toURL())
- .addURL("the-parent", new File("tester/b.jar").toURL())
-
- .newClassloader("the-child")
- .addURL("the-child", new File("tester/c.jar").toURL())
- .setParent("the-child", "the-parent", Mask.builder().exclude("A.class", "a.txt").build())
- .build();
-
- ClassLoader parent = newClassloaders.get("the-parent");
- assertThat(canLoadClass(parent, "A")).isTrue();
- assertThat(canLoadClass(parent, "B")).isTrue();
- assertThat(canLoadClass(parent, "C")).isFalse();
- assertThat(canLoadResource(parent, "a.txt")).isTrue();
- assertThat(canLoadResource(parent, "b.txt")).isTrue();
- assertThat(canLoadResource(parent, "c.txt")).isFalse();
-
- ClassLoader child = newClassloaders.get("the-child");
- assertThat(canLoadClass(child, "A")).isFalse();
- assertThat(canLoadClass(child, "B")).isTrue();
- assertThat(canLoadClass(child, "C")).isTrue();
- assertThat(canLoadResource(child, "a.txt")).isFalse();
- assertThat(canLoadResource(child, "b.txt")).isTrue();
- assertThat(canLoadResource(child, "c.txt")).isTrue();
- }
-
- /**
- * Parent classloader contains A and B, but exports only B to its children
- */
- @Test
- public void export_mask() throws Exception {
- Map<String, ClassLoader> newClassloaders = sut
- .newClassloader("the-parent")
- .addURL("the-parent", new File("tester/a.jar").toURL())
- .addURL("the-parent", new File("tester/b.jar").toURL())
- .setExportMask("the-parent", Mask.builder().exclude("A.class", "a.txt").build())
-
- .newClassloader("the-child")
- .setParent("the-child", "the-parent", Mask.ALL)
- .build();
-
- ClassLoader parent = newClassloaders.get("the-parent");
- assertThat(canLoadClass(parent, "A")).isTrue();
- assertThat(canLoadClass(parent, "B")).isTrue();
- assertThat(canLoadResource(parent, "a.txt")).isTrue();
- assertThat(canLoadResource(parent, "b.txt")).isTrue();
-
- ClassLoader child = newClassloaders.get("the-child");
- assertThat(canLoadClass(child, "A")).isFalse();
- assertThat(canLoadClass(child, "B")).isTrue();
- assertThat(canLoadResource(child, "a.txt")).isFalse();
- assertThat(canLoadResource(child, "b.txt")).isTrue();
- }
-
- /**
- * Parent classloader contains A, B and C, but exports only B and C to its children.
- * On the other side child classloader excludes B from its parent, so it benefits
- * only from C
- */
- @Test
- public void mix_of_import_and_export_masks() throws Exception {
- Map<String, ClassLoader> newClassloaders = sut
- .newClassloader("the-parent")
- .addURL("the-parent", new File("tester/a.jar").toURL())
- .addURL("the-parent", new File("tester/b.jar").toURL())
- .addURL("the-parent", new File("tester/c.jar").toURL())
- .setExportMask("the-parent", Mask.builder().exclude("A.class", "a.txt").build())
-
- .newClassloader("the-child")
- .setParent("the-child", "the-parent", Mask.builder().exclude("B.class", "b.txt").build())
- .build();
-
- ClassLoader parent = newClassloaders.get("the-parent");
- assertThat(canLoadClass(parent, "A")).isTrue();
- assertThat(canLoadClass(parent, "B")).isTrue();
- assertThat(canLoadClass(parent, "C")).isTrue();
- assertThat(canLoadResource(parent, "a.txt")).isTrue();
- assertThat(canLoadResource(parent, "b.txt")).isTrue();
- assertThat(canLoadResource(parent, "c.txt")).isTrue();
-
- ClassLoader child = newClassloaders.get("the-child");
- assertThat(canLoadClass(child, "A")).isFalse();
- assertThat(canLoadClass(child, "B")).isFalse();
- assertThat(canLoadClass(child, "C")).isTrue();
- assertThat(canLoadResource(child, "a.txt")).isFalse();
- assertThat(canLoadResource(child, "b.txt")).isFalse();
- assertThat(canLoadResource(child, "c.txt")).isTrue();
- }
-
- @Test
- public void fail_to_create_the_same_classloader_twice() throws Exception {
- sut.newClassloader("the-cl");
- try {
- sut.newClassloader("the-cl");
- fail();
- } catch (IllegalStateException e) {
- assertThat(e).hasMessage("The classloader 'the-cl' already exists. Can not create it twice.");
- }
- }
-
- @Test
- public void fail_to_create_the_same_previous_classloader_twice() throws Exception {
- Map<String, ClassLoader> classloaders1 = sut.newClassloader("the-cl").build();
- ClassloaderBuilder classloaderBuilder = new ClassloaderBuilder(classloaders1.values());
- try {
- classloaderBuilder.newClassloader("the-cl");
- fail();
- } catch (IllegalStateException e) {
- assertThat(e).hasMessage("The classloader 'the-cl' already exists in the list of previously created classloaders. " +
- "Can not create it twice.");
- }
- }
-
- @Test
- public void fail_if_missing_declaration() throws Exception {
- sut.newClassloader("the-cl");
- sut.setParent("the-cl", "missing", Mask.ALL);
- try {
- sut.build();
- fail();
- } catch (IllegalStateException e) {
- assertThat(e).hasMessage("The classloader 'missing' does not exist");
- }
- }
-
- @Test
- public void sibling() throws Exception {
- // sibling1 contains A
- // sibling2 contains B
- // child contains C -> see A, B and C
- Map<String, ClassLoader> newClassloaders = sut
- .newClassloader("sib1")
- .addURL("sib1", new File("tester/a.jar").toURL())
-
- .newClassloader("sib2")
- .addURL("sib2", new File("tester/b.jar").toURL())
-
- .newClassloader("the-child")
- .addURL("the-child", new File("tester/c.jar").toURL())
- .addSibling("the-child", "sib1", Mask.ALL)
- .addSibling("the-child", "sib2", Mask.ALL)
- .build();
-
- ClassLoader sib1 = newClassloaders.get("sib1");
- assertThat(canLoadClass(sib1, "A")).isTrue();
- assertThat(canLoadClass(sib1, "B")).isFalse();
- assertThat(canLoadClass(sib1, "C")).isFalse();
- assertThat(canLoadResource(sib1, "a.txt")).isTrue();
- assertThat(canLoadResource(sib1, "b.txt")).isFalse();
- assertThat(canLoadResource(sib1, "c.txt")).isFalse();
-
- ClassLoader sib2 = newClassloaders.get("sib2");
- assertThat(canLoadClass(sib2, "A")).isFalse();
- assertThat(canLoadClass(sib2, "B")).isTrue();
- assertThat(canLoadClass(sib2, "C")).isFalse();
- assertThat(canLoadResource(sib2, "a.txt")).isFalse();
- assertThat(canLoadResource(sib2, "b.txt")).isTrue();
- assertThat(canLoadResource(sib2, "c.txt")).isFalse();
-
- ClassLoader child = newClassloaders.get("the-child");
- assertThat(canLoadClass(child, "A")).isTrue();
- assertThat(canLoadClass(child, "B")).isTrue();
- assertThat(canLoadClass(child, "C")).isTrue();
- assertThat(canLoadResource(child, "a.txt")).isTrue();
- assertThat(canLoadResource(child, "b.txt")).isTrue();
- assertThat(canLoadResource(child, "c.txt")).isTrue();
- }
-
- /**
- * Sibling classloader can be created outside {@link ClassloaderBuilder}.
- */
- @Test
- public void existing_sibling() throws Exception {
- // sibling1 contains JUnit
- // child contains A -> see JUnit and A
- Map<String, ClassLoader> newClassloaders = sut
- .newClassloader("the-child")
- .addURL("the-child", new File("tester/a.jar").toURL())
- .addSibling("the-child", getClass().getClassLoader(), Mask.ALL)
- .build();
-
- ClassLoader child = newClassloaders.get("the-child");
- assertThat(canLoadClass(child, Test.class.getName())).isTrue();
- assertThat(canLoadClass(child, "A")).isTrue();
- }
-
- /**
- * - sibling contains A and B
- * - child contains C and excludes A from sibling -> sees only B and C
- */
- @Test
- public void sibling_mask() throws Exception {
- Map<String, ClassLoader> newClassloaders = sut
- .newClassloader("sib1")
- .addURL("sib1", new File("tester/a.jar").toURL())
- .addURL("sib1", new File("tester/b.jar").toURL())
-
- .newClassloader("the-child")
- .addURL("the-child", new File("tester/c.jar").toURL())
- .addSibling("the-child", "sib1", Mask.builder().exclude("A.class", "a.txt").build())
- .build();
-
- ClassLoader sib1 = newClassloaders.get("sib1");
- assertThat(canLoadClass(sib1, "A")).isTrue();
- assertThat(canLoadClass(sib1, "B")).isTrue();
- assertThat(canLoadResource(sib1, "a.txt")).isTrue();
- assertThat(canLoadResource(sib1, "b.txt")).isTrue();
-
- ClassLoader child = newClassloaders.get("the-child");
- assertThat(canLoadClass(child, "A")).isFalse();
- assertThat(canLoadClass(child, "B")).isTrue();
- assertThat(canLoadClass(child, "C")).isTrue();
- assertThat(canLoadResource(child, "a.txt")).isFalse();
- assertThat(canLoadResource(child, "b.txt")).isTrue();
- assertThat(canLoadResource(child, "c.txt")).isTrue();
- assertThat(Collections.list(child.getResources("a.txt"))).isEmpty();
- assertThat(Collections.list(child.getResources("b.txt"))).hasSize(1);
- assertThat(Collections.list(child.getResources("c.txt"))).hasSize(1);
- }
-
- /**
- * - sibling contains A and B but exports only B
- * - child contains C -> sees only B and C
- */
- @Test
- public void sibling_export_mask() throws Exception {
- Map<String, ClassLoader> newClassloaders = sut
- .newClassloader("sib1")
- .addURL("sib1", new File("tester/a.jar").toURL())
- .addURL("sib1", new File("tester/b.jar").toURL())
- .setExportMask("sib1", Mask.builder().include("B.class", "b.txt").build())
-
- .newClassloader("the-child")
- .addURL("the-child", new File("tester/c.jar").toURL())
- .addSibling("the-child", "sib1", Mask.ALL)
- .build();
-
- ClassLoader sib1 = newClassloaders.get("sib1");
- assertThat(canLoadClass(sib1, "A")).isTrue();
- assertThat(canLoadClass(sib1, "B")).isTrue();
- assertThat(canLoadResource(sib1, "a.txt")).isTrue();
- assertThat(canLoadResource(sib1, "b.txt")).isTrue();
-
- ClassLoader child = newClassloaders.get("the-child");
- assertThat(canLoadClass(child, "A")).isFalse();
- assertThat(canLoadClass(child, "B")).isTrue();
- assertThat(canLoadClass(child, "C")).isTrue();
- assertThat(canLoadResource(child, "a.txt")).isFalse();
- assertThat(canLoadResource(child, "b.txt")).isTrue();
- assertThat(canLoadResource(child, "c.txt")).isTrue();
- assertThat(Collections.list(child.getResources("a.txt"))).isEmpty();
- assertThat(Collections.list(child.getResources("b.txt"))).hasSize(1);
- assertThat(Collections.list(child.getResources("c.txt"))).hasSize(1);
- }
-
- /**
- * Sibling classloader is loaded previously self:
- * - sibling has version 1 of A
- * - self has version 2 of A -> sees version 1
- */
- @Test
- public void sibling_prevails_over_self() throws Exception {
- Map<String, ClassLoader> newClassloaders = sut
- .newClassloader("sib")
- .addURL("sib", new File("tester/a.jar").toURL())
-
- .newClassloader("self")
- .addURL("self", new File("tester/a_v2.jar").toURL())
- .addSibling("self", "sib", Mask.ALL)
- .build();
-
- ClassLoader sib = newClassloaders.get("sib");
- assertThat(canLoadMethod(sib, "A", "version1")).isTrue();
- assertThat(canLoadMethod(sib, "A", "version2")).isFalse();
- assertThat(IOUtils.toString(sib.getResource("a.txt"))).startsWith("version 1 of a.txt");
-
- ClassLoader self = newClassloaders.get("self");
- assertThat(canLoadMethod(self, "A", "version1")).isTrue();
- assertThat(canLoadMethod(self, "A", "version2")).isFalse();
- assertThat(IOUtils.toString(self.getResource("a.txt"))).startsWith("version 1 of a.txt");
- }
-
- /**
- * Sibling classloader is always loaded previously self, even if self-first strategy:
- * - sibling has version 1 of A
- * - self has version 2 of A -> sees version 1
- */
- @Test
- public void sibling_prevails_over_self_even_if_self_first() throws Exception {
- Map<String, ClassLoader> newClassloaders = sut
- .newClassloader("sib")
- .addURL("sib", new File("tester/a.jar").toURL())
-
- .newClassloader("self")
- .addURL("self", new File("tester/a_v2.jar").toURL())
- .addSibling("self", "sib", Mask.ALL)
- .setLoadingOrder("self", ClassloaderBuilder.LoadingOrder.SELF_FIRST)
- .build();
-
- ClassLoader sib = newClassloaders.get("sib");
- assertThat(canLoadMethod(sib, "A", "version1")).isTrue();
- assertThat(canLoadMethod(sib, "A", "version2")).isFalse();
- assertThat(IOUtils.toString(sib.getResource("a.txt"))).startsWith("version 1 of a.txt");
-
- ClassLoader self = newClassloaders.get("self");
- assertThat(canLoadMethod(self, "A", "version1")).isTrue();
- assertThat(canLoadMethod(self, "A", "version2")).isFalse();
- assertThat(IOUtils.toString(self.getResource("a.txt"))).startsWith("version 1 of a.txt");
- }
-
- /**
- * https://github.com/SonarSource/sonar-classloader/issues/1
- */
- @Test
- public void cycle_of_siblings() throws Exception {
- Map<String, ClassLoader> newClassloaders = sut
- .newClassloader("a")
- .addURL("a", new File("tester/a.jar").toURL())
-
- .newClassloader("b")
- .addURL("b", new File("tester/b.jar").toURL())
- .addSibling("a", "b", Mask.builder().include("B.class", "b.txt").build())
- .addSibling("b", "a", Mask.builder().include("A.class", "a.txt").build())
- .build();
-
- ClassLoader a = newClassloaders.get("a");
- assertThat(canLoadClass(a, "A")).isTrue();
- assertThat(canLoadClass(a, "B")).isTrue();
- assertThat(IOUtils.toString(a.getResource("a.txt"))).isNotEmpty();
- assertThat(IOUtils.toString(a.getResource("b.txt"))).isNotEmpty();
-
- ClassLoader b = newClassloaders.get("b");
- assertThat(canLoadClass(b, "A")).isTrue();
- assertThat(canLoadClass(b, "B")).isTrue();
- assertThat(IOUtils.toString(b.getResource("a.txt"))).isNotEmpty();
- assertThat(IOUtils.toString(b.getResource("b.txt"))).isNotEmpty();
- }
-
- @Test
- public void getResources_from_parent_and_siblings() throws Exception {
- Map<String, ClassLoader> newClassloaders = sut
- .newClassloader("the-parent")
- .addURL("the-parent", new File("tester/a.jar").toURL())
-
- .newClassloader("the-sib")
- .addURL("the-sib", new File("tester/b.jar").toURL())
-
- .newClassloader("the-child")
- .addURL("the-child", new File("tester/c.jar").toURL())
- .setParent("the-child", "the-parent", Mask.ALL)
- .addSibling("the-child", "the-sib", Mask.ALL)
- .build();
-
- ClassLoader parent = newClassloaders.get("the-parent");
- assertThat(Collections.list(parent.getResources("a.txt"))).hasSize(1);
- assertThat(Collections.list(parent.getResources("b.txt"))).isEmpty();
- assertThat(Collections.list(parent.getResources("c.txt"))).isEmpty();
-
- ClassLoader child = newClassloaders.get("the-child");
- assertThat(Collections.list(child.getResources("a.txt"))).hasSize(1);
- assertThat(Collections.list(child.getResources("b.txt"))).hasSize(1);
- assertThat(Collections.list(child.getResources("c.txt"))).hasSize(1);
- }
-
- @Test
- public void getResources_from_previously_loaded_parent() throws Exception {
- Map<String, ClassLoader> classloaders1 = sut
- .newClassloader("the-parent")
- .addURL("the-parent", new File("tester/a.jar").toURL())
- .build();
-
-
- Map<String, ClassLoader> classloaders2 = new ClassloaderBuilder(classloaders1.values())
- .newClassloader("the-child")
- .addURL("the-child", new File("tester/b.jar").toURL())
- .setParent("the-child", "the-parent", Mask.ALL)
- .build();
-
- ClassLoader parent = classloaders1.get("the-parent");
- assertThat(Collections.list(parent.getResources("a.txt"))).hasSize(1);
- assertThat(Collections.list(parent.getResources("b.txt"))).isEmpty();
-
- ClassLoader child = classloaders2.get("the-child");
- assertThat(Collections.list(child.getResources("a.txt"))).hasSize(1);
- assertThat(Collections.list(child.getResources("b.txt"))).hasSize(1);
- }
-
- @Test
- public void getResources_from_previously_loaded_sibling_based_on_export_mask() throws Exception {
- Map<String, ClassLoader> classloaders1 = sut
- .newClassloader("the-sib")
- .addURL("the-sib", new File("tester/a.jar").toURL())
- .setExportMask("the-sib", Mask.builder().include("A.java").build())
- .build();
-
- Map<String, ClassLoader> classloaders2 = new ClassloaderBuilder(classloaders1.values())
- .newClassloader("the-child")
- .addURL("the-child", new File("tester/b.jar").toURL())
- .addSibling("the-child", "the-sib", Mask.ALL)
- .build();
-
- ClassLoader parent = classloaders1.get("the-sib");
- assertThat(Collections.list(parent.getResources("a.txt"))).hasSize(1);
- assertThat(Collections.list(parent.getResources("A.java"))).hasSize(1);
- assertThat(Collections.list(parent.getResources("b.txt"))).isEmpty();
-
- ClassLoader child = classloaders2.get("the-child");
- assertThat(Collections.list(child.getResources("a.txt"))).isEmpty();
- assertThat(Collections.list(parent.getResources("A.java"))).hasSize(1);
- assertThat(Collections.list(child.getResources("b.txt"))).hasSize(1);
- }
-
- @Test
- public void getResources_from_previously_loaded_sibling() throws Exception {
- Map<String, ClassLoader> classloaders1 = sut
- .newClassloader("the-sib")
- .addURL("the-sib", new File("tester/a.jar").toURL())
- .build();
-
- Map<String, ClassLoader> classloaders2 = new ClassloaderBuilder(classloaders1.values())
- .newClassloader("the-child")
- .addURL("the-child", new File("tester/b.jar").toURL())
- .addSibling("the-child", "the-sib", Mask.ALL)
- .build();
-
- ClassLoader parent = classloaders1.get("the-sib");
- assertThat(Collections.list(parent.getResources("a.txt"))).hasSize(1);
- assertThat(Collections.list(parent.getResources("b.txt"))).isEmpty();
-
- ClassLoader child = classloaders2.get("the-child");
- assertThat(Collections.list(child.getResources("a.txt"))).hasSize(1);
- assertThat(Collections.list(child.getResources("b.txt"))).hasSize(1);
- }
-
- @Test
- public void getResources_multiple_versions_with_parent_first_strategy() throws Exception {
- Map<String, ClassLoader> newClassloaders = sut
- .newClassloader("the-parent")
- .addURL("the-parent", new File("tester/a.jar").toURL())
-
- .newClassloader("the-child")
- .addURL("the-child", new File("tester/a_v2.jar").toURL())
- .setParent("the-child", "the-parent", Mask.ALL)
- .build();
-
- ClassLoader parent = newClassloaders.get("the-parent");
- assertThat(Collections.list(parent.getResources("a.txt"))).hasSize(1);
-
- ClassLoader child = newClassloaders.get("the-child");
- List<URL> childResources = Collections.list(child.getResources("a.txt"));
- assertThat(childResources).hasSize(2);
- assertThat(IOUtils.toString(childResources.get(0))).startsWith("version 1 of a.txt");
- assertThat(IOUtils.toString(childResources.get(1))).startsWith("version 2 of a.txt");
- }
-
- @Test
- public void resource_not_found_in_parent_first_strategy() throws Exception {
- Map<String, ClassLoader> newClassloaders = sut
- .newClassloader("the-parent")
- .addURL("the-parent", new File("tester/a.jar").toURL())
-
- .newClassloader("the-child")
- .addURL("the-child", new File("tester/a_v2.jar").toURL())
- .setParent("the-child", "the-parent", Mask.ALL)
- .build();
-
- ClassLoader parent = newClassloaders.get("the-child");
- assertThat(parent.getResource("missing")).isNull();
- try {
- parent.loadClass("missing");
- fail();
- } catch (ClassNotFoundException e) {
- // ok
- }
- }
-
- @Test
- public void resource_not_found_in_self_first_strategy() throws Exception {
- Map<String, ClassLoader> newClassloaders = sut
- .newClassloader("the-parent")
- .addURL("the-parent", new File("tester/a.jar").toURL())
-
- .newClassloader("the-child")
- .addURL("the-child", new File("tester/a_v2.jar").toURL())
- .setParent("the-child", "the-parent", Mask.ALL)
- .setLoadingOrder("the-child", ClassloaderBuilder.LoadingOrder.SELF_FIRST)
- .build();
-
- ClassLoader parent = newClassloaders.get("the-child");
- assertThat(parent.getResource("missing")).isNull();
- try {
- parent.loadClass("missing");
- fail();
- } catch (ClassNotFoundException e) {
- // ok
- }
- }
-
- private boolean canLoadClass(ClassLoader classloader, String classname) {
- try {
- classloader.loadClass(classname);
- return true;
- } catch (ClassNotFoundException e) {
- return false;
- }
- }
-
- private boolean canLoadMethod(ClassLoader classloader, String classname, String methodName) {
- try {
- Class clazz = classloader.loadClass(classname);
- return clazz.getMethod(methodName) != null;
- } catch (Exception e) {
- return false;
- }
- }
-
- private boolean canLoadResource(ClassLoader classloader, String name) {
- return classloader.getResource(name) != null;
- }
-}
diff --git a/sonar-core/src/test/java/org/sonar/classloader/MaskTest.java b/sonar-core/src/test/java/org/sonar/classloader/MaskTest.java
deleted file mode 100644
index 85a72e0fdad..00000000000
--- a/sonar-core/src/test/java/org/sonar/classloader/MaskTest.java
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2024 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.classloader;
-
-import org.junit.jupiter.api.Test;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-class MaskTest {
-
- @Test
- void ALL_accepts_everything() throws Exception {
- assertThat(Mask.ALL.acceptClass("org.sonar.Bar")).isTrue();
- assertThat(Mask.ALL.acceptClass("Bar")).isTrue();
- }
-
- @Test
- void NONE_accepts_nothing() throws Exception {
- assertThat(Mask.NONE.acceptClass("org.sonar.Bar")).isFalse();
- assertThat(Mask.NONE.acceptClass("Bar")).isFalse();
- }
-
- @Test
- void include_class() throws Exception {
- Mask mask = Mask.builder().include("org/sonar/Bar.class").build();
- assertThat(mask.acceptClass("org.sonar.Bar")).isTrue();
- assertThat(mask.acceptClass("org.sonar.qube.Bar")).isFalse();
- assertThat(mask.acceptClass("org.sonar.Foo")).isFalse();
- assertThat(mask.acceptClass("Bar")).isFalse();
- }
-
- @Test
- void include_class_of_root_package() throws Exception {
- Mask mask = Mask.builder().include("Bar.class").build();
- assertThat(mask.acceptClass("Bar")).isTrue();
- assertThat(mask.acceptClass("Foo")).isFalse();
- }
-
- @Test
- void include_resource() throws Exception {
- Mask mask = Mask.builder().include("org/sonar/Bar.class").build();
- assertThat(mask.acceptResource("org/sonar/Bar.class")).isTrue();
- assertThat(mask.acceptResource("org/sonar/qube/Bar.class")).isFalse();
- assertThat(mask.acceptResource("org/sonar/Foo.class")).isFalse();
- assertThat(mask.acceptResource("Bar.class")).isFalse();
- }
-
- @Test
- void include_package() throws Exception {
- Mask mask = Mask.builder().include("org/sonar/", "org/other/").build();
- assertThat(mask.acceptClass("Foo")).isFalse();
- assertThat(mask.acceptClass("org.sonar.Bar")).isTrue();
- assertThat(mask.acceptClass("org.sonarqube.Foo")).isFalse();
- assertThat(mask.acceptClass("org.sonar.qube.Foo")).isTrue();
- assertThat(mask.acceptClass("Bar")).isFalse();
- }
-
- @Test
- void exclude_class() throws Exception {
- Mask mask = Mask.builder().exclude("org/sonar/Bar.class").build();
- assertThat(mask.acceptClass("org.sonar.Bar")).isFalse();
- assertThat(mask.acceptClass("org.sonar.qube.Bar")).isTrue();
- assertThat(mask.acceptClass("org.sonar.Foo")).isTrue();
- assertThat(mask.acceptClass("Bar")).isTrue();
- }
-
- @Test
- void exclude_package() throws Exception {
- Mask mask = Mask.builder().exclude("org/sonar/", "org/other/").build();
- assertThat(mask.acceptClass("Foo")).isTrue();
- assertThat(mask.acceptClass("org.sonar.Bar")).isFalse();
- assertThat(mask.acceptClass("org.sonarqube.Foo")).isTrue();
- assertThat(mask.acceptClass("org.sonar.qube.Foo")).isFalse();
- assertThat(mask.acceptClass("Bar")).isTrue();
- }
-
- @Test
- void exclusion_is_subset_of_inclusion() throws Exception {
- Mask mask = Mask.builder()
- .include("org/sonar/")
- .exclude("org/sonar/qube/")
- .build();
- assertThat(mask.acceptClass("org.sonar.Foo")).isTrue();
- assertThat(mask.acceptClass("org.sonar.Qube")).isTrue();
- assertThat(mask.acceptClass("org.sonar.qube.Foo")).isFalse();
- }
-
- @Test
- void inclusion_is_subset_of_exclusion() throws Exception {
- Mask mask = Mask.builder()
- .include("org/sonar/qube/")
- .exclude("org/sonar/")
- .build();
- assertThat(mask.acceptClass("org.sonar.Foo")).isFalse();
- assertThat(mask.acceptClass("org.sonar.Qube")).isFalse();
- assertThat(mask.acceptClass("org.sonar.qube.Foo")).isFalse();
- }
-
- @Test
- void exclude_everything() throws Exception {
- Mask mask = Mask.builder().exclude("/").build();
- assertThat(mask.acceptClass("org.sonar.Foo")).isFalse();
- assertThat(mask.acceptClass("Foo")).isFalse();
- assertThat(mask.acceptResource("config.xml")).isFalse();
- assertThat(mask.acceptResource("org/config.xml")).isFalse();
- }
-
- @Test
- void include_everything() throws Exception {
- Mask mask = Mask.builder().include("/").build();
- assertThat(mask.acceptClass("org.sonar.Foo")).isTrue();
- assertThat(mask.acceptClass("Foo")).isTrue();
- assertThat(mask.acceptResource("config.xml")).isTrue();
- assertThat(mask.acceptResource("org/config.xml")).isTrue();
- }
-
- @Test
- void merge_with_ALL() throws Exception {
- Mask mask = Mask.builder()
- .include("org/foo/")
- .exclude("org/bar/")
- .merge(Mask.ALL)
- .build();
-
- assertThat(mask.getInclusions()).containsOnly("org/foo/");
- assertThat(mask.getExclusions()).containsOnly("org/bar/");
- }
-
- @Test
- void merge_exclusions() throws Exception {
- Mask with = Mask.builder().exclude("bar/").build();
- Mask mask = Mask.builder().exclude("org/foo/").merge(with).build();
-
- assertThat(mask.getExclusions()).containsOnly("org/foo/", "bar/");
- }
-
- @Test
- void should_not_merge_disjoined_inclusions() throws Exception {
- Mask with = Mask.builder().include("org/bar/").build();
- Mask mask = Mask.builder().include("org/foo/").merge(with).build();
-
- assertThat(mask.getInclusions()).isEmpty();
- // TODO does that mean that merge result accepts everything ?
- }
-
- @Test
- void merge_inclusions() throws Exception {
- Mask with = Mask.builder().include("org/foo/sub/", "org/bar/").build();
- Mask mask = Mask.builder().include("org/foo/", "org/bar/sub/").merge(with).build();
-
- assertThat(mask.getInclusions()).containsOnly("org/foo/sub/", "org/bar/sub/");
- }
-}