Browse Source

Ensure ClassPathResources with same path and ClassLoader are equal

Prior to this commit, if two ClassPathResource instances were
constructed differently (one from an absolute path and one from a path
relative to a Class) but had the same absolute path and the same
ClassLoader, they were effectively equal, but ClassPathResource#equals
returned false.

This commit addresses this by revising the logic in
ClassPathResource#equals accordingly.

Closes gh-29263
pull/29282/head
Sam Brannen 4 years ago
parent
commit
a380ca2750
  1. 12
      spring-core/src/main/java/org/springframework/core/io/ClassPathResource.java
  2. 25
      spring-core/src/test/java/org/springframework/core/io/ClassPathResourceTests.java

12
spring-core/src/main/java/org/springframework/core/io/ClassPathResource.java

@ -24,7 +24,6 @@ import java.net.URL; @@ -24,7 +24,6 @@ import java.net.URL;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
/**
@ -271,9 +270,14 @@ public class ClassPathResource extends AbstractFileResolvingResource { @@ -271,9 +270,14 @@ public class ClassPathResource extends AbstractFileResolvingResource {
if (!(other instanceof ClassPathResource otherRes)) {
return false;
}
return (this.path.equals(otherRes.path) &&
ObjectUtils.nullSafeEquals(this.classLoader, otherRes.classLoader) &&
ObjectUtils.nullSafeEquals(this.clazz, otherRes.clazz));
if (!this.absolutePath.equals(otherRes.absolutePath)) {
return false;
}
ClassLoader thisClassLoader =
(this.classLoader != null ? this.classLoader : this.clazz.getClassLoader());
ClassLoader otherClassLoader =
(otherRes.classLoader != null ? otherRes.classLoader : otherRes.clazz.getClassLoader());
return thisClassLoader.equals(otherClassLoader);
}
/**

25
spring-core/src/test/java/org/springframework/core/io/ClassPathResourceTests.java

@ -30,6 +30,8 @@ import org.junit.jupiter.api.Nested; @@ -30,6 +30,8 @@ import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import org.springframework.core.OverridingClassLoader;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.junit.jupiter.api.io.CleanupMode.NEVER;
@ -79,6 +81,29 @@ class ClassPathResourceTests { @@ -79,6 +81,29 @@ class ClassPathResourceTests {
assertThat(resource2).isEqualTo(resource1);
}
@Test
void resourcesWithEquivalentAbsolutePathsFromTheSameClassLoaderAreEqual() {
Resource resource1 = new ClassPathResource("Resource.class", getClass());
Resource resource2 = new ClassPathResource("org/springframework/core/io/Resource.class", getClass().getClassLoader());
assertThat(resource1).isEqualTo(resource2);
assertThat(resource2).isEqualTo(resource1);
}
@Test
void resourcesWithEquivalentAbsolutePathsFromDifferentClassLoadersAreNotEqual() {
class SimpleThrowawayClassLoader extends OverridingClassLoader {
SimpleThrowawayClassLoader(ClassLoader parent) {
super(parent);
}
}
Resource resource1 = new ClassPathResource("Resource.class", getClass());
Resource resource2 = new ClassPathResource("org/springframework/core/io/Resource.class",
new SimpleThrowawayClassLoader(getClass().getClassLoader()));
assertThat(resource1).isNotEqualTo(resource2);
assertThat(resource2).isNotEqualTo(resource1);
}
@Test
void relativeResourcesAreEqual() throws Exception {
Resource resource = new ClassPathResource("dir/");

Loading…
Cancel
Save