From 96a4e1150e608a66998988f5d4903297ef11e977 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Fri, 7 Aug 2020 12:59:41 +0200 Subject: [PATCH] Avoid unnecessary computation of cleaned URL Closes gh-25531 --- .../springframework/core/io/UrlResource.java | 33 +++++++++++++------ 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/spring-core/src/main/java/org/springframework/core/io/UrlResource.java b/spring-core/src/main/java/org/springframework/core/io/UrlResource.java index b989384a0192..3f1dcc05ffe4 100644 --- a/spring-core/src/main/java/org/springframework/core/io/UrlResource.java +++ b/spring-core/src/main/java/org/springframework/core/io/UrlResource.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -56,7 +56,8 @@ public class UrlResource extends AbstractFileResolvingResource { /** * Cleaned URL (with normalized path), used for comparisons. */ - private final URL cleanedUrl; + @Nullable + private volatile URL cleanedUrl; /** @@ -69,7 +70,6 @@ public UrlResource(URI uri) throws MalformedURLException { Assert.notNull(uri, "URI must not be null"); this.uri = uri; this.url = uri.toURL(); - this.cleanedUrl = getCleanedUrl(this.url, uri.toString()); } /** @@ -78,9 +78,8 @@ public UrlResource(URI uri) throws MalformedURLException { */ public UrlResource(URL url) { Assert.notNull(url, "URL must not be null"); - this.url = url; - this.cleanedUrl = getCleanedUrl(this.url, url.toString()); this.uri = null; + this.url = url; } /** @@ -127,7 +126,6 @@ public UrlResource(String protocol, String location, @Nullable String fragment) try { this.uri = new URI(protocol, location, fragment); this.url = this.uri.toURL(); - this.cleanedUrl = getCleanedUrl(this.url, this.uri.toString()); } catch (URISyntaxException ex) { MalformedURLException exToThrow = new MalformedURLException(ex.getMessage()); @@ -144,7 +142,7 @@ public UrlResource(String protocol, String location, @Nullable String fragment) * @return the cleaned URL (possibly the original URL as-is) * @see org.springframework.util.StringUtils#cleanPath */ - private URL getCleanedUrl(URL originalUrl, String originalPath) { + private static URL getCleanedUrl(URL originalUrl, String originalPath) { String cleanedPath = StringUtils.cleanPath(originalPath); if (!cleanedPath.equals(originalPath)) { try { @@ -157,6 +155,21 @@ private URL getCleanedUrl(URL originalUrl, String originalPath) { return originalUrl; } + /** + * Lazily determine a cleaned URL for the given original URL. + * @see #getCleanedUrl(URL, String) + */ + private URL getCleanedUrl() { + URL cleanedUrl = this.cleanedUrl; + if (cleanedUrl != null) { + return cleanedUrl; + } + cleanedUrl = getCleanedUrl(this.url, (this.uri != null ? this.uri : this.url).toString()); + this.cleanedUrl = cleanedUrl; + return cleanedUrl; + } + + /** * This implementation opens an InputStream for the given URL. *

It sets the {@code useCaches} flag to {@code false}, @@ -262,7 +275,7 @@ protected URL createRelativeURL(String relativePath) throws MalformedURLExceptio */ @Override public String getFilename() { - return StringUtils.getFilename(this.cleanedUrl.getPath()); + return StringUtils.getFilename(getCleanedUrl().getPath()); } /** @@ -280,7 +293,7 @@ public String getDescription() { @Override public boolean equals(@Nullable Object other) { return (this == other || (other instanceof UrlResource && - this.cleanedUrl.equals(((UrlResource) other).cleanedUrl))); + getCleanedUrl().equals(((UrlResource) other).getCleanedUrl()))); } /** @@ -288,7 +301,7 @@ public boolean equals(@Nullable Object other) { */ @Override public int hashCode() { - return this.cleanedUrl.hashCode(); + return getCleanedUrl().hashCode(); } }