Polishing

This commit is contained in:
Juergen Hoeller 2015-09-08 18:11:30 +02:00
parent 5c22002d21
commit 52fdfd59ab
11 changed files with 44 additions and 43 deletions

View File

@ -16,13 +16,9 @@
package org.springframework.test.util; package org.springframework.test.util;
import static org.hamcrest.MatcherAssert.*;
import static org.springframework.test.util.AssertionErrors.*;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.util.Collections; import java.util.Collections;
import java.util.Map; import java.util.Map;
import javax.xml.namespace.QName; import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilderFactory;
@ -42,6 +38,9 @@ import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.util.xml.SimpleNamespaceContext; import org.springframework.util.xml.SimpleNamespaceContext;
import static org.hamcrest.MatcherAssert.*;
import static org.springframework.test.util.AssertionErrors.*;
/** /**
* A helper class for applying assertions via XPath expressions. * A helper class for applying assertions via XPath expressions.
* *
@ -113,7 +112,7 @@ public class XpathExpectationsHelper {
factory.setNamespaceAware(this.hasNamespaces); factory.setNamespaceAware(this.hasNamespaces);
DocumentBuilder documentBuilder = factory.newDocumentBuilder(); DocumentBuilder documentBuilder = factory.newDocumentBuilder();
InputSource inputSource = new InputSource(new ByteArrayInputStream(xml)); InputSource inputSource = new InputSource(new ByteArrayInputStream(xml));
if(StringUtils.hasText(encoding)) { if (StringUtils.hasText(encoding)) {
inputSource.setEncoding(encoding); inputSource.setEncoding(encoding);
} }
return documentBuilder.parse(inputSource); return documentBuilder.parse(inputSource);

View File

@ -30,12 +30,12 @@ import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.util.Assert; import org.springframework.util.Assert;
/** /**
* Response extractor that uses the given {@linkplain HttpMessageConverter entity * Response extractor that uses the given {@linkplain HttpMessageConverter entity converters}
* converters} to convert the response into a type {@code T}. * to convert the response into a type {@code T}.
* *
* @author Arjen Poutsma * @author Arjen Poutsma
* @see RestTemplate
* @since 3.0 * @since 3.0
* @see RestTemplate
*/ */
public class HttpMessageConverterExtractor<T> implements ResponseExtractor<T> { public class HttpMessageConverterExtractor<T> implements ResponseExtractor<T> {
@ -47,19 +47,18 @@ public class HttpMessageConverterExtractor<T> implements ResponseExtractor<T> {
private final Log logger; private final Log logger;
/** /**
* Creates a new instance of the {@code HttpMessageConverterExtractor} with the given * Create a new instance of the {@code HttpMessageConverterExtractor} with the given response
* response type and message converters. The given converters must support the response * type and message converters. The given converters must support the response type.
* type.
*/ */
public HttpMessageConverterExtractor(Class<T> responseType, List<HttpMessageConverter<?>> messageConverters) { public HttpMessageConverterExtractor(Class<T> responseType, List<HttpMessageConverter<?>> messageConverters) {
this((Type) responseType, messageConverters); this((Type) responseType, messageConverters);
} }
/** /**
* Creates a new instance of the {@code HttpMessageConverterExtractor} with the given * Creates a new instance of the {@code HttpMessageConverterExtractor} with the given response
* response type and message converters. The given converters must support the response * type and message converters. The given converters must support the response type.
* type.
*/ */
public HttpMessageConverterExtractor(Type responseType, List<HttpMessageConverter<?>> messageConverters) { public HttpMessageConverterExtractor(Type responseType, List<HttpMessageConverter<?>> messageConverters) {
this(responseType, messageConverters, LogFactory.getLog(HttpMessageConverterExtractor.class)); this(responseType, messageConverters, LogFactory.getLog(HttpMessageConverterExtractor.class));
@ -75,10 +74,10 @@ public class HttpMessageConverterExtractor<T> implements ResponseExtractor<T> {
this.logger = logger; this.logger = logger;
} }
@Override
@SuppressWarnings({ "unchecked", "rawtypes" })
public T extractData(ClientHttpResponse response) throws IOException {
@Override
@SuppressWarnings({"unchecked", "rawtypes"})
public T extractData(ClientHttpResponse response) throws IOException {
MessageBodyClientHttpResponseWrapper responseWrapper = new MessageBodyClientHttpResponseWrapper(response); MessageBodyClientHttpResponseWrapper responseWrapper = new MessageBodyClientHttpResponseWrapper(response);
if (!responseWrapper.hasMessageBody() || responseWrapper.hasEmptyMessageBody()) { if (!responseWrapper.hasMessageBody() || responseWrapper.hasEmptyMessageBody()) {
return null; return null;
@ -106,9 +105,9 @@ public class HttpMessageConverterExtractor<T> implements ResponseExtractor<T> {
} }
} }
} }
throw new RestClientException(
"Could not extract response: no suitable HttpMessageConverter found for response type [" + throw new RestClientException("Could not extract response: no suitable HttpMessageConverter found " +
this.responseType + "] and content type [" + contentType + "]"); "for response type [" + this.responseType + "] and content type [" + contentType + "]");
} }
private MediaType getContentType(ClientHttpResponse response) { private MediaType getContentType(ClientHttpResponse response) {

View File

@ -310,7 +310,7 @@ class ResourcesBeanDefinitionParser implements BeanDefinitionParser {
} }
if (isAutoRegistration) { if (isAutoRegistration) {
if(isWebJarsAssetLocatorPresent) { if (isWebJarsAssetLocatorPresent) {
RootBeanDefinition webJarsResolverDef = new RootBeanDefinition(WebJarsResourceResolver.class); RootBeanDefinition webJarsResolverDef = new RootBeanDefinition(WebJarsResourceResolver.class);
webJarsResolverDef.setSource(source); webJarsResolverDef.setSource(source);
webJarsResolverDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); webJarsResolverDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);

View File

@ -45,6 +45,7 @@ public class ResourceChainRegistration {
private static final boolean isWebJarsAssetLocatorPresent = ClassUtils.isPresent( private static final boolean isWebJarsAssetLocatorPresent = ClassUtils.isPresent(
"org.webjars.WebJarAssetLocator", ResourceChainRegistration.class.getClassLoader()); "org.webjars.WebJarAssetLocator", ResourceChainRegistration.class.getClassLoader());
private final List<ResourceResolver> resolvers = new ArrayList<ResourceResolver>(4); private final List<ResourceResolver> resolvers = new ArrayList<ResourceResolver>(4);
private final List<ResourceTransformer> transformers = new ArrayList<ResourceTransformer>(4); private final List<ResourceTransformer> transformers = new ArrayList<ResourceTransformer>(4);
@ -103,7 +104,7 @@ public class ResourceChainRegistration {
protected List<ResourceResolver> getResourceResolvers() { protected List<ResourceResolver> getResourceResolvers() {
if (!this.hasPathResolver) { if (!this.hasPathResolver) {
List<ResourceResolver> result = new ArrayList<ResourceResolver>(this.resolvers); List<ResourceResolver> result = new ArrayList<ResourceResolver>(this.resolvers);
if(isWebJarsAssetLocatorPresent) { if (isWebJarsAssetLocatorPresent) {
result.add(new WebJarsResourceResolver()); result.add(new WebJarsResourceResolver());
} }
result.add(new PathResourceResolver()); result.add(new PathResourceResolver());

View File

@ -86,9 +86,9 @@ public class CachingResourceResolver extends AbstractResourceResolver {
protected String computeKey(HttpServletRequest request, String requestPath) { protected String computeKey(HttpServletRequest request, String requestPath) {
StringBuilder key = new StringBuilder(RESOLVED_RESOURCE_CACHE_KEY_PREFIX); StringBuilder key = new StringBuilder(RESOLVED_RESOURCE_CACHE_KEY_PREFIX);
key.append(requestPath); key.append(requestPath);
if(request != null) { if (request != null) {
String encoding = request.getHeader("Accept-Encoding"); String encoding = request.getHeader("Accept-Encoding");
if(encoding != null && encoding.contains("gzip")) { if (encoding != null && encoding.contains("gzip")) {
key.append("+encoding=gzip"); key.append("+encoding=gzip");
} }
} }

View File

@ -161,8 +161,10 @@ public class PathResourceResolver extends AbstractResourceResolver {
if (!resource.getClass().equals(location.getClass())) { if (!resource.getClass().equals(location.getClass())) {
return false; return false;
} }
String resourcePath; String resourcePath;
String locationPath; String locationPath;
if (resource instanceof UrlResource) { if (resource instanceof UrlResource) {
resourcePath = resource.getURL().toExternalForm(); resourcePath = resource.getURL().toExternalForm();
locationPath = StringUtils.cleanPath(location.getURL().toString()); locationPath = StringUtils.cleanPath(location.getURL().toString());
@ -179,13 +181,15 @@ public class PathResourceResolver extends AbstractResourceResolver {
resourcePath = resource.getURL().getPath(); resourcePath = resource.getURL().getPath();
locationPath = StringUtils.cleanPath(location.getURL().getPath()); locationPath = StringUtils.cleanPath(location.getURL().getPath());
} }
if(locationPath.equals(resourcePath)) {
if (locationPath.equals(resourcePath)) {
return true; return true;
} }
locationPath = (locationPath.endsWith("/") || locationPath.isEmpty() ? locationPath : locationPath + "/"); locationPath = (locationPath.endsWith("/") || locationPath.isEmpty() ? locationPath : locationPath + "/");
if (!resourcePath.startsWith(locationPath)) { if (!resourcePath.startsWith(locationPath)) {
return false; return false;
} }
if (resourcePath.contains("%")) { if (resourcePath.contains("%")) {
// Use URLDecoder (vs UriUtils) to preserve potentially decoded UTF-8 chars... // Use URLDecoder (vs UriUtils) to preserve potentially decoded UTF-8 chars...
if (URLDecoder.decode(resourcePath, "UTF-8").contains("../")) { if (URLDecoder.decode(resourcePath, "UTF-8").contains("../")) {
@ -195,6 +199,7 @@ public class PathResourceResolver extends AbstractResourceResolver {
return false; return false;
} }
} }
return true; return true;
} }

View File

@ -416,7 +416,7 @@ public class ResourceHttpRequestHandler extends WebContentGenerator
*/ */
protected void setETagHeader(HttpServletRequest request, HttpServletResponse response) { protected void setETagHeader(HttpServletRequest request, HttpServletResponse response) {
String versionString = (String) request.getAttribute(VersionResourceResolver.RESOURCE_VERSION_ATTRIBUTE); String versionString = (String) request.getAttribute(VersionResourceResolver.RESOURCE_VERSION_ATTRIBUTE);
if(versionString != null) { if (versionString != null) {
response.setHeader(HttpHeaders.ETAG, "\"" + versionString + "\""); response.setHeader(HttpHeaders.ETAG, "\"" + versionString + "\"");
} }
} }

View File

@ -36,7 +36,6 @@ import org.springframework.util.PathMatcher;
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping; import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
import org.springframework.web.util.UrlPathHelper; import org.springframework.web.util.UrlPathHelper;
/** /**
* A central component to use to obtain the public URL path that clients should * A central component to use to obtain the public URL path that clients should
* use to access a static resource. * use to access a static resource.
@ -130,7 +129,7 @@ public class ResourceUrlProvider implements ApplicationListener<ContextRefreshed
if (this.handlerMap.isEmpty() && logger.isDebugEnabled()) { if (this.handlerMap.isEmpty() && logger.isDebugEnabled()) {
logger.debug("No resource handling mappings found"); logger.debug("No resource handling mappings found");
} }
if(!this.handlerMap.isEmpty()) { if (!this.handlerMap.isEmpty()) {
this.autodetect = false; this.autodetect = false;
} }
} }

View File

@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.web.servlet.resource; package org.springframework.web.servlet.resource;
import java.util.ArrayList; import java.util.ArrayList;
@ -167,7 +168,7 @@ public class VersionResourceResolver extends AbstractResourceResolver {
if (logger.isTraceEnabled()) { if (logger.isTraceEnabled()) {
logger.trace("resource matches extracted version"); logger.trace("resource matches extracted version");
} }
if(request != null) { if (request != null) {
request.setAttribute(VersionResourceResolver.RESOURCE_VERSION_ATTRIBUTE, candidateVersion); request.setAttribute(VersionResourceResolver.RESOURCE_VERSION_ATTRIBUTE, candidateVersion);
} }
return baseResource; return baseResource;

View File

@ -25,18 +25,18 @@ import org.webjars.WebJarAssetLocator;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
/** /**
* A {@code ResourceResolver} that delegates to the chain to locate a resource * A {@code ResourceResolver} that delegates to the chain to locate a resource and then
* and then attempts to find a matching versioned resource contained in a WebJar JAR file. * attempts to find a matching versioned resource contained in a WebJar JAR file.
* *
* <p>This allows WebJars.org users to write version agnostic paths in their templates, * <p>This allows WebJars.org users to write version agnostic paths in their templates,
* like {@code <script src="/jquery/jquery.min.js"/>}. * like {@code <script src="/jquery/jquery.min.js"/>}.
* This path will be resolved to the unique version {@code <script src="/jquery/1.2.0/jquery.min.js"/>}, * This path will be resolved to the unique version {@code <script src="/jquery/1.2.0/jquery.min.js"/>},
* which is a better fit for HTTP caching and version management in applications. * which is a better fit for HTTP caching and version management in applications.
* *
* <p>This also resolves Resources for version agnostic HTTP requests {@code "GET /jquery/jquery.min.js"}. * <p>This also resolves resources for version agnostic HTTP requests {@code "GET /jquery/jquery.min.js"}.
* *
* <p>This resolver requires the "org.webjars:webjars-locator" library on classpath, and is automatically * <p>This resolver requires the "org.webjars:webjars-locator" library on classpath,
* registered if that library is present. * and is automatically registered if that library is present.
* *
* @author Brian Clozel * @author Brian Clozel
* @since 4.2 * @since 4.2
@ -49,12 +49,7 @@ public class WebJarsResourceResolver extends AbstractResourceResolver {
private final static int WEBJARS_LOCATION_LENGTH = WEBJARS_LOCATION.length(); private final static int WEBJARS_LOCATION_LENGTH = WEBJARS_LOCATION.length();
private final WebJarAssetLocator webJarAssetLocator; private final WebJarAssetLocator webJarAssetLocator = new WebJarAssetLocator();
public WebJarsResourceResolver() {
this.webJarAssetLocator = new WebJarAssetLocator();
}
@Override @Override
@ -64,7 +59,7 @@ public class WebJarsResourceResolver extends AbstractResourceResolver {
Resource resolved = chain.resolveResource(request, requestPath, locations); Resource resolved = chain.resolveResource(request, requestPath, locations);
if (resolved == null) { if (resolved == null) {
String webJarResourcePath = findWebJarResourcePath(requestPath); String webJarResourcePath = findWebJarResourcePath(requestPath);
if(webJarResourcePath != null) { if (webJarResourcePath != null) {
return chain.resolveResource(request, webJarResourcePath, locations); return chain.resolveResource(request, webJarResourcePath, locations);
} }
} }
@ -78,7 +73,7 @@ public class WebJarsResourceResolver extends AbstractResourceResolver {
String path = chain.resolveUrlPath(resourceUrlPath, locations); String path = chain.resolveUrlPath(resourceUrlPath, locations);
if (path == null) { if (path == null) {
String webJarResourcePath = findWebJarResourcePath(resourceUrlPath); String webJarResourcePath = findWebJarResourcePath(resourceUrlPath);
if(webJarResourcePath != null) { if (webJarResourcePath != null) {
return chain.resolveUrlPath(webJarResourcePath, locations); return chain.resolveUrlPath(webJarResourcePath, locations);
} }
} }

View File

@ -208,7 +208,7 @@ public class UrlTag extends HtmlEscapingAwareTag implements ParamAware {
url.append(request.getContextPath()); url.append(request.getContextPath());
} }
else { else {
if(this.context.endsWith("/")) { if (this.context.endsWith("/")) {
url.append(this.context.substring(0, this.context.length() - 1)); url.append(this.context.substring(0, this.context.length() - 1));
} }
else { else {
@ -315,10 +315,12 @@ public class UrlTag extends HtmlEscapingAwareTag implements ParamAware {
return uri; return uri;
} }
/** /**
* Internal enum that classifies URLs by type. * Internal enum that classifies URLs by type.
*/ */
private enum UrlType { private enum UrlType {
CONTEXT_RELATIVE, RELATIVE, ABSOLUTE CONTEXT_RELATIVE, RELATIVE, ABSOLUTE
} }