Skip to content

Commit

Permalink
Make sure the result from QCL.getElementsWithResource(name) does not …
Browse files Browse the repository at this point in the history
…include duplicates
  • Loading branch information
aloubyansky committed Nov 6, 2024
1 parent 3742ca0 commit e8e1551
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -356,9 +356,7 @@ public QuarkusClassLoader createDeploymentClassLoader() {
if (configuredClassLoading.isRemovedArtifact(dependency.getKey())) {
continue;
}
if (dependency.isRuntimeCp() && dependency.isJar() &&
(dependency.isReloadable() && appModel.getReloadableWorkspaceDependencies().contains(dependency.getKey()) ||
configuredClassLoading.isReloadableArtifact(dependency.getKey()))) {
if (isReloadableRuntimeDependency(dependency)) {
processCpElement(dependency, element -> addCpElement(builder, dependency, element));
}
}
Expand All @@ -368,6 +366,12 @@ public QuarkusClassLoader createDeploymentClassLoader() {
return builder.build();
}

private boolean isReloadableRuntimeDependency(ResolvedDependency dependency) {
return dependency.isRuntimeCp() && dependency.isJar() &&
(dependency.isReloadable() && appModel.getReloadableWorkspaceDependencies().contains(dependency.getKey()) ||
configuredClassLoading.isReloadableArtifact(dependency.getKey()));
}

public String getClassLoaderNameSuffix() {
return quarkusBootstrap.getBaseName() != null ? " for " + quarkusBootstrap.getBaseName() : "";
}
Expand Down Expand Up @@ -405,9 +409,7 @@ public QuarkusClassLoader createRuntimeClassLoader(ClassLoader base, Map<String,
if (configuredClassLoading.isRemovedArtifact(dependency.getKey())) {
continue;
}
if (dependency.isRuntimeCp() && dependency.isJar() &&
(dependency.isReloadable() && appModel.getReloadableWorkspaceDependencies().contains(dependency.getKey()) ||
configuredClassLoading.isReloadableArtifact(dependency.getKey()))) {
if (isReloadableRuntimeDependency(dependency)) {
processCpElement(dependency, element -> addCpElement(builder, dependency, element));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -625,22 +625,69 @@ public List<ClassPathElement> getElementsWithResource(String name) {
public List<ClassPathElement> getElementsWithResource(String name, boolean localOnly) {
ensureOpen(name);

boolean parentFirst = parentFirst(name, getClassPathResourceIndex());
final boolean parentFirst = parentFirst(name, getClassPathResourceIndex());

List<ClassPathElement> ret = new ArrayList<>();
List<ClassPathElement> result = List.of();

if (parentFirst && !localOnly && parent instanceof QuarkusClassLoader) {
ret.addAll(((QuarkusClassLoader) parent).getElementsWithResource(name));
if (parentFirst && !localOnly && parent instanceof QuarkusClassLoader parentQcl) {
result = parentQcl.getElementsWithResource(name);
}

List<ClassPathElement> classPathElements = getClassPathResourceIndex().getClassPathElements(name);
ret.addAll(classPathElements);
result = unify(result, getClassPathResourceIndex().getClassPathElements(name));

if (!parentFirst && !localOnly && parent instanceof QuarkusClassLoader) {
ret.addAll(((QuarkusClassLoader) parent).getElementsWithResource(name));
if (!parentFirst && !localOnly && parent instanceof QuarkusClassLoader parentQcl) {
result = unify(result, parentQcl.getElementsWithResource(name));
}

return ret;
return result;
}

/**
* Returns a list containing elements from two lists eliminating duplicates. Elements from the first list
* will appear in the result before elements from the second list.
* <p>
* The current implementation assumes that none of the lists contains duplicates on their own but some elements
* may be present in both lists.
*
* @param list1 first list
* @param list2 second list
* @return resulting list
*/
private static List<ClassPathElement> unify(List<ClassPathElement> list1, List<ClassPathElement> list2) {
if (list1.isEmpty()) {
return list2;
}
if (list2.isEmpty()) {
return list1;
}
final List<ClassPathElement> result = new ArrayList<>(list1.size() + list2.size());
// it looks like in most cases list1 (representing elements from the parent cl) contains only one element
if (list1.size() == 1) {
final ClassPathElement firstCpe = list1.get(0);
result.add(firstCpe);
for (var cpe : list2) {
if (cpe != firstCpe) {
result.add(cpe);
}
}
return result;
}
result.addAll(list1);
for (var cpe : list2) {
if (!containsReference(list1, cpe)) {
result.add(cpe);
}
}
return result;
}

private static boolean containsReference(List<ClassPathElement> list, ClassPathElement cpe) {
for (var i : list) {
if (i == cpe) {
return true;
}
}
return false;
}

public Set<String> getReloadableClassNames() {
Expand Down Expand Up @@ -902,6 +949,10 @@ public QuarkusClassLoader build() {
return new QuarkusClassLoader(this);
}

@Override
public String toString() {
return "QuarkusClassLoader.Builder:" + name + "@" + Integer.toHexString(hashCode());
}
}

public ClassLoader parent() {
Expand Down

0 comments on commit e8e1551

Please sign in to comment.