Fix regression in ClassPathResource descriptions
ClassPathResource.getDescription() now returns consistent, meaningful results for all variants of ClassPathResource's constructors. Issue: SPR-9413
This commit is contained in:
parent
500a4dd995
commit
b50f6e19a6
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2010 the original author or authors.
|
* Copyright 2002-2012 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -35,6 +35,7 @@ import org.springframework.util.StringUtils;
|
||||||
* Always supports resolution as URL.
|
* Always supports resolution as URL.
|
||||||
*
|
*
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
|
* @author Sam Brannen
|
||||||
* @since 28.12.2003
|
* @since 28.12.2003
|
||||||
* @see java.lang.ClassLoader#getResourceAsStream(String)
|
* @see java.lang.ClassLoader#getResourceAsStream(String)
|
||||||
* @see java.lang.Class#getResourceAsStream(String)
|
* @see java.lang.Class#getResourceAsStream(String)
|
||||||
|
@ -108,7 +109,6 @@ public class ClassPathResource extends AbstractFileResolvingResource {
|
||||||
this.clazz = clazz;
|
this.clazz = clazz;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the path for this resource (as resource path within the class path).
|
* Return the path for this resource (as resource path within the class path).
|
||||||
*/
|
*/
|
||||||
|
@ -123,7 +123,6 @@ public class ClassPathResource extends AbstractFileResolvingResource {
|
||||||
return (this.classLoader != null ? this.classLoader : this.clazz.getClassLoader());
|
return (this.classLoader != null ? this.classLoader : this.clazz.getClassLoader());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This implementation checks for the resolution of a resource URL.
|
* This implementation checks for the resolution of a resource URL.
|
||||||
* @see java.lang.ClassLoader#getResource(String)
|
* @see java.lang.ClassLoader#getResource(String)
|
||||||
|
@ -155,8 +154,7 @@ public class ClassPathResource extends AbstractFileResolvingResource {
|
||||||
is = this.classLoader.getResourceAsStream(this.path);
|
is = this.classLoader.getResourceAsStream(this.path);
|
||||||
}
|
}
|
||||||
if (is == null) {
|
if (is == null) {
|
||||||
throw new FileNotFoundException(
|
throw new FileNotFoundException(getDescription() + " cannot be opened because it does not exist");
|
||||||
getDescription() + " cannot be opened because it does not exist");
|
|
||||||
}
|
}
|
||||||
return is;
|
return is;
|
||||||
}
|
}
|
||||||
|
@ -176,8 +174,7 @@ public class ClassPathResource extends AbstractFileResolvingResource {
|
||||||
url = this.classLoader.getResource(this.path);
|
url = this.classLoader.getResource(this.path);
|
||||||
}
|
}
|
||||||
if (url == null) {
|
if (url == null) {
|
||||||
throw new FileNotFoundException(
|
throw new FileNotFoundException(getDescription() + " cannot be resolved to URL because it does not exist");
|
||||||
getDescription() + " cannot be resolved to URL because it does not exist");
|
|
||||||
}
|
}
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
@ -209,17 +206,22 @@ public class ClassPathResource extends AbstractFileResolvingResource {
|
||||||
public String getDescription() {
|
public String getDescription() {
|
||||||
StringBuilder builder = new StringBuilder("class path resource [");
|
StringBuilder builder = new StringBuilder("class path resource [");
|
||||||
|
|
||||||
if (this.clazz != null) {
|
String pathToUse = path;
|
||||||
|
|
||||||
|
if (this.clazz != null && !pathToUse.startsWith("/")) {
|
||||||
builder.append(ClassUtils.classPackageAsResourcePath(this.clazz));
|
builder.append(ClassUtils.classPackageAsResourcePath(this.clazz));
|
||||||
builder.append('/');
|
builder.append('/');
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.append(this.path);
|
if (pathToUse.startsWith("/")) {
|
||||||
|
pathToUse = pathToUse.substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.append(pathToUse);
|
||||||
builder.append(']');
|
builder.append(']');
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This implementation compares the underlying class path locations.
|
* This implementation compares the underlying class path locations.
|
||||||
*/
|
*/
|
||||||
|
@ -230,9 +232,9 @@ public class ClassPathResource extends AbstractFileResolvingResource {
|
||||||
}
|
}
|
||||||
if (obj instanceof ClassPathResource) {
|
if (obj instanceof ClassPathResource) {
|
||||||
ClassPathResource otherRes = (ClassPathResource) obj;
|
ClassPathResource otherRes = (ClassPathResource) obj;
|
||||||
return (this.path.equals(otherRes.path) &&
|
return (this.path.equals(otherRes.path)
|
||||||
ObjectUtils.nullSafeEquals(this.classLoader, otherRes.classLoader) &&
|
&& ObjectUtils.nullSafeEquals(this.classLoader, otherRes.classLoader) && ObjectUtils.nullSafeEquals(
|
||||||
ObjectUtils.nullSafeEquals(this.clazz, otherRes.clazz));
|
this.clazz, otherRes.clazz));
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2010 the original author or authors.
|
* Copyright 2002-2012 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -17,24 +17,59 @@
|
||||||
package org.springframework.core.io;
|
package org.springframework.core.io;
|
||||||
|
|
||||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertThat;
|
import static org.junit.Assert.assertThat;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
import static org.junit.internal.matchers.StringContains.containsString;
|
import static org.junit.internal.matchers.StringContains.containsString;
|
||||||
|
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit tests cornering bug SPR-6888.
|
* Unit tests that serve as regression tests for the bugs described in SPR-6888
|
||||||
|
* and SPR-9413.
|
||||||
*
|
*
|
||||||
* @author Chris Beams
|
* @author Chris Beams
|
||||||
|
* @author Sam Brannen
|
||||||
*/
|
*/
|
||||||
public class ClassPathResourceTests {
|
public class ClassPathResourceTests {
|
||||||
|
|
||||||
private static final String PACKAGE_PATH = "org/springframework/core/io";
|
private static final String PACKAGE_PATH = "org/springframework/core/io";
|
||||||
private static final String RESOURCE_NAME = "notexist.xml";
|
private static final String NONEXISTENT_RESOURCE_NAME = "nonexistent.xml";
|
||||||
private static final String FQ_RESOURCE_PATH = PACKAGE_PATH + '/' + RESOURCE_NAME;
|
private static final String FQ_RESOURCE_PATH = PACKAGE_PATH + '/' + NONEXISTENT_RESOURCE_NAME;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Absolute path version of {@link #FQ_RESOURCE_PATH}.
|
||||||
|
*/
|
||||||
|
private static final String FQ_RESOURCE_PATH_WITH_LEADING_SLASH = '/' + FQ_RESOURCE_PATH;
|
||||||
|
|
||||||
|
private static final Pattern DESCRIPTION_PATTERN = Pattern.compile("^class path resource \\[(.+?)\\]$");
|
||||||
|
|
||||||
|
|
||||||
|
private void assertDescriptionContainsExpectedPath(ClassPathResource resource, String expectedPath) {
|
||||||
|
Matcher matcher = DESCRIPTION_PATTERN.matcher(resource.getDescription());
|
||||||
|
assertTrue(matcher.matches());
|
||||||
|
assertEquals(1, matcher.groupCount());
|
||||||
|
String match = matcher.group(1);
|
||||||
|
|
||||||
|
assertEquals(expectedPath, match);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertExceptionContainsFullyQualifiedPath(ClassPathResource resource) {
|
||||||
|
try {
|
||||||
|
resource.getInputStream();
|
||||||
|
fail("FileNotFoundException expected for resource: " + resource);
|
||||||
|
}
|
||||||
|
catch (IOException ex) {
|
||||||
|
assertThat(ex, instanceOf(FileNotFoundException.class));
|
||||||
|
assertThat(ex.getMessage(), containsString(FQ_RESOURCE_PATH));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void stringConstructorRaisesExceptionWithFullyQualifiedPath() {
|
public void stringConstructorRaisesExceptionWithFullyQualifiedPath() {
|
||||||
|
@ -43,21 +78,48 @@ public class ClassPathResourceTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void classLiteralConstructorRaisesExceptionWithFullyQualifiedPath() {
|
public void classLiteralConstructorRaisesExceptionWithFullyQualifiedPath() {
|
||||||
assertExceptionContainsFullyQualifiedPath(new ClassPathResource(RESOURCE_NAME, this.getClass()));
|
assertExceptionContainsFullyQualifiedPath(new ClassPathResource(NONEXISTENT_RESOURCE_NAME, this.getClass()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void classLoaderConstructorRaisesExceptionWithFullyQualifiedPath() {
|
public void classLoaderConstructorRaisesExceptionWithFullyQualifiedPath() {
|
||||||
assertExceptionContainsFullyQualifiedPath(new ClassPathResource(FQ_RESOURCE_PATH, this.getClass().getClassLoader()));
|
assertExceptionContainsFullyQualifiedPath(new ClassPathResource(FQ_RESOURCE_PATH,
|
||||||
|
this.getClass().getClassLoader()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertExceptionContainsFullyQualifiedPath(ClassPathResource resource) {
|
@Test
|
||||||
try {
|
public void getDescriptionWithStringConstructor() {
|
||||||
resource.getInputStream();
|
assertDescriptionContainsExpectedPath(new ClassPathResource(FQ_RESOURCE_PATH), FQ_RESOURCE_PATH);
|
||||||
fail("FileNotFoundException expected for resource: " + resource);
|
|
||||||
} catch (IOException ex) {
|
|
||||||
assertThat(ex, instanceOf(FileNotFoundException.class));
|
|
||||||
assertThat(ex.getMessage(), containsString(FQ_RESOURCE_PATH));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getDescriptionWithStringConstructorAndLeadingSlash() {
|
||||||
|
assertDescriptionContainsExpectedPath(new ClassPathResource(FQ_RESOURCE_PATH_WITH_LEADING_SLASH),
|
||||||
|
FQ_RESOURCE_PATH);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getDescriptionWithClassLiteralConstructor() {
|
||||||
|
assertDescriptionContainsExpectedPath(new ClassPathResource(NONEXISTENT_RESOURCE_NAME, this.getClass()),
|
||||||
|
FQ_RESOURCE_PATH);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getDescriptionWithClassLiteralConstructorAndLeadingSlash() {
|
||||||
|
assertDescriptionContainsExpectedPath(
|
||||||
|
new ClassPathResource(FQ_RESOURCE_PATH_WITH_LEADING_SLASH, this.getClass()), FQ_RESOURCE_PATH);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getDescriptionWithClassLoaderConstructor() {
|
||||||
|
assertDescriptionContainsExpectedPath(
|
||||||
|
new ClassPathResource(FQ_RESOURCE_PATH, this.getClass().getClassLoader()), FQ_RESOURCE_PATH);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getDescriptionWithClassLoaderConstructorAndLeadingSlash() {
|
||||||
|
assertDescriptionContainsExpectedPath(new ClassPathResource(FQ_RESOURCE_PATH_WITH_LEADING_SLASH,
|
||||||
|
this.getClass().getClassLoader()), FQ_RESOURCE_PATH);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue