Skip to content

Commit

Permalink
Avoid direct URL construction and URL equality checks
Browse files Browse the repository at this point in the history
Closes gh-29486
  • Loading branch information
jhoeller committed Nov 14, 2022
1 parent 0b21c16 commit aaeb5eb
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 59 deletions.
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2022 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.
Expand All @@ -18,7 +18,6 @@

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;

Expand All @@ -30,6 +29,7 @@
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.lang.Nullable;
import org.springframework.util.ResourceUtils;

/**
* {@code EntityResolver} implementation that tries to resolve entity references
Expand Down Expand Up @@ -82,7 +82,7 @@ public InputSource resolveEntity(@Nullable String publicId, @Nullable String sys
String resourcePath = null;
try {
String decodedSystemId = URLDecoder.decode(systemId, StandardCharsets.UTF_8);
String givenUrl = new URL(decodedSystemId).toString();
String givenUrl = ResourceUtils.toURL(decodedSystemId).toString();
String systemRootUrl = new File("").toURI().toURL().toString();
// Try relative to resource base if currently in system root.
if (givenUrl.startsWith(systemRootUrl)) {
Expand Down Expand Up @@ -116,7 +116,7 @@ else if (systemId.endsWith(DTD_SUFFIX) || systemId.endsWith(XSD_SUFFIX)) {
url = "https:" + url.substring(5);
}
try {
source = new InputSource(new URL(url).openStream());
source = new InputSource(ResourceUtils.toURL(url).openStream());
source.setPublicId(publicId);
source.setSystemId(systemId);
}
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2022 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.
Expand Down Expand Up @@ -77,7 +77,7 @@ public void setAsText(String text) throws IllegalArgumentException {
boolean nioPathCandidate = !text.startsWith(ResourceUtils.CLASSPATH_URL_PREFIX);
if (nioPathCandidate && !text.startsWith("/")) {
try {
URI uri = new URI(text);
URI uri = ResourceUtils.toURI(text);
if (uri.getScheme() != null) {
nioPathCandidate = false;
// Let's try NIO file system providers via Paths.get(URI)
Expand Down
Expand Up @@ -162,7 +162,7 @@ else if (location.startsWith(CLASSPATH_URL_PREFIX)) {
else {
try {
// Try to parse the location as a URL...
URL url = new URL(location);
URL url = ResourceUtils.toURL(location);
return (ResourceUtils.isFileURL(url) ? new FileUrlResource(url) : new UrlResource(url));
}
catch (MalformedURLException ex) {
Expand Down
Expand Up @@ -31,6 +31,7 @@

import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ResourceUtils;
import org.springframework.util.StringUtils;

/**
Expand All @@ -57,10 +58,10 @@ public class UrlResource extends AbstractFileResolvingResource {
private final URL url;

/**
* Cleaned URL (with normalized path), used for comparisons.
* Cleaned URL String (with normalized path), used for comparisons.
*/
@Nullable
private volatile URL cleanedUrl;
private volatile String cleanedUrl;


/**
Expand Down Expand Up @@ -97,8 +98,8 @@ public UrlResource(URI uri) throws MalformedURLException {
public UrlResource(String path) throws MalformedURLException {
Assert.notNull(path, "Path must not be null");
this.uri = null;
this.url = new URL(path);
this.cleanedUrl = getCleanedUrl(this.url, path);
this.url = ResourceUtils.toURL(path);
this.cleanedUrl = StringUtils.cleanPath(path);
}

/**
Expand Down Expand Up @@ -144,7 +145,7 @@ public UrlResource(String protocol, String location, @Nullable String fragment)
* Create a new {@code UrlResource} from the given {@link URI}.
* <p>This factory method is a convenience for {@link #UrlResource(URI)} that
* catches any {@link MalformedURLException} and rethrows it wrapped in an
* {@link UncheckedIOException}; suitable for use in {@link java.util.Stream}
* {@link UncheckedIOException}; suitable for use in {@link java.util.stream.Stream}
* and {@link java.util.Optional} APIs or other scenarios when a checked
* {@link IOException} is undesirable.
* @param uri a URI
Expand All @@ -165,7 +166,7 @@ public static UrlResource from(URI uri) throws UncheckedIOException {
* Create a new {@code UrlResource} from the given URL path.
* <p>This factory method is a convenience for {@link #UrlResource(String)}
* that catches any {@link MalformedURLException} and rethrows it wrapped in an
* {@link UncheckedIOException}; suitable for use in {@link java.util.Stream}
* {@link UncheckedIOException}; suitable for use in {@link java.util.stream.Stream}
* and {@link java.util.Optional} APIs or other scenarios when a checked
* {@link IOException} is undesirable.
* @param path a URL path
Expand All @@ -183,36 +184,16 @@ public static UrlResource from(String path) throws UncheckedIOException {
}


/**
* Determine a cleaned URL for the given original URL.
* @param originalUrl the original URL
* @param originalPath the original URL path
* @return the cleaned URL (possibly the original URL as-is)
* @see org.springframework.util.StringUtils#cleanPath
*/
private static URL getCleanedUrl(URL originalUrl, String originalPath) {
String cleanedPath = StringUtils.cleanPath(originalPath);
if (!cleanedPath.equals(originalPath)) {
try {
return new URL(cleanedPath);
}
catch (MalformedURLException ex) {
// Cleaned URL path cannot be converted to URL -> take original URL.
}
}
return originalUrl;
}

/**
* Lazily determine a cleaned URL for the given original URL.
* @see #getCleanedUrl(URL, String)
*/
private URL getCleanedUrl() {
URL cleanedUrl = this.cleanedUrl;
private String getCleanedUrl() {
String cleanedUrl = this.cleanedUrl;
if (cleanedUrl != null) {
return cleanedUrl;
}
cleanedUrl = getCleanedUrl(this.url, (this.uri != null ? this.uri : this.url).toString());
String originalPath = (this.uri != null ? this.uri : this.url).toString();
cleanedUrl = StringUtils.cleanPath(originalPath);
this.cleanedUrl = cleanedUrl;
return cleanedUrl;
}
Expand Down Expand Up @@ -305,16 +286,13 @@ public Resource createRelative(String relativePath) throws MalformedURLException
* A leading slash will get dropped; a "#" symbol will get encoded.
* @since 5.2
* @see #createRelative(String)
* @see java.net.URL#URL(java.net.URL, String)
* @see ResourceUtils#toRelativeURL(URL, String)
*/
protected URL createRelativeURL(String relativePath) throws MalformedURLException {
if (relativePath.startsWith("/")) {
relativePath = relativePath.substring(1);
}
// # can appear in filenames, java.net.URL should not treat it as a fragment
relativePath = StringUtils.replace(relativePath, "#", "%23");
// Use the URL constructor for applying the relative path as a URL spec
return new URL(this.url, relativePath);
return ResourceUtils.toRelativeURL(this.url, relativePath);
}

/**
Expand All @@ -324,17 +302,18 @@ protected URL createRelativeURL(String relativePath) throws MalformedURLExceptio
* @see java.net.URLDecoder#decode(String, java.nio.charset.Charset)
*/
@Override
@Nullable
public String getFilename() {
String filename = StringUtils.getFilename(getCleanedUrl().getPath());
return URLDecoder.decode(filename, StandardCharsets.UTF_8);
String filename = StringUtils.getFilename(this.uri != null ? this.uri.getPath() : this.url.getPath());
return (filename != null ? URLDecoder.decode(filename, StandardCharsets.UTF_8) : null);
}

/**
* This implementation returns a description that includes the URL.
*/
@Override
public String getDescription() {
return "URL [" + this.url + "]";
return "URL [" + (this.uri != null ? this.uri : this.url) + "]";
}


Expand Down
Expand Up @@ -24,6 +24,7 @@

import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ResourceUtils;

/**
* JBoss VFS based {@link Resource} implementation.
Expand Down Expand Up @@ -115,7 +116,7 @@ public Resource createRelative(String relativePath) throws IOException {
}
}

return new VfsResource(VfsUtils.getRelative(new URL(getURL(), relativePath)));
return new VfsResource(VfsUtils.getRelative(ResourceUtils.toRelativeURL(getURL(), relativePath)));
}

@Override
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2022 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.
Expand Down Expand Up @@ -109,7 +109,7 @@ public static boolean isUrl(@Nullable String resourceLocation) {
return true;
}
try {
new URL(resourceLocation);
toURL(resourceLocation);
return true;
}
catch (MalformedURLException ex) {
Expand Down Expand Up @@ -141,7 +141,7 @@ public static URL getURL(String resourceLocation) throws FileNotFoundException {
}
try {
// try URL
return new URL(resourceLocation);
return toURL(resourceLocation);
}
catch (MalformedURLException ex) {
// no URL -> treat as file path
Expand Down Expand Up @@ -181,7 +181,7 @@ public static File getFile(String resourceLocation) throws FileNotFoundException
}
try {
// try URL
return getFile(new URL(resourceLocation));
return getFile(toURL(resourceLocation));
}
catch (MalformedURLException ex) {
// no URL -> treat as file path
Expand Down Expand Up @@ -311,15 +311,15 @@ public static URL extractJarFileURL(URL jarUrl) throws MalformedURLException {
if (separatorIndex != -1) {
String jarFile = urlFile.substring(0, separatorIndex);
try {
return new URL(jarFile);
return toURL(jarFile);
}
catch (MalformedURLException ex) {
// Probably no protocol in original jar URL, like "jar:C:/mypath/myjar.jar".
// This usually indicates that the jar file resides in the file system.
if (!jarFile.startsWith("/")) {
jarFile = "/" + jarFile;
}
return new URL(FILE_URL_PREFIX + jarFile);
return toURL(FILE_URL_PREFIX + jarFile);
}
}
else {
Expand All @@ -346,11 +346,11 @@ public static URL extractArchiveURL(URL jarUrl) throws MalformedURLException {
// Tomcat's "war:file:...mywar.war*/WEB-INF/lib/myjar.jar!/myentry.txt"
String warFile = urlFile.substring(0, endIndex);
if (URL_PROTOCOL_WAR.equals(jarUrl.getProtocol())) {
return new URL(warFile);
return toURL(warFile);
}
int startIndex = warFile.indexOf(WAR_URL_PREFIX);
if (startIndex != -1) {
return new URL(warFile.substring(startIndex + WAR_URL_PREFIX.length()));
return toURL(warFile.substring(startIndex + WAR_URL_PREFIX.length()));
}
}

Expand Down Expand Up @@ -381,6 +381,53 @@ public static URI toURI(String location) throws URISyntaxException {
return new URI(StringUtils.replace(location, " ", "%20"));
}

/**
* Create a URL instance for the given location String,
* going through URI construction and then URL conversion.
* @param location the location String to convert into a URL instance
* @return the URL instance
* @throws MalformedURLException if the location wasn't a valid URL
* @since 6.0
*/
public static URL toURL(String location) throws MalformedURLException {
// Not fully equivalent - but to be moved in the given direction
// since JDK 20 deprecates all direct java.net.URL constructors.
/*
try {
return toURI(location).toURL();
}
catch (URISyntaxException ex) {
MalformedURLException exToThrow = new MalformedURLException(ex.getMessage());
exToThrow.initCause(ex);
throw exToThrow;
}
*/

return new URL(location);
}

/**
* Create a URL instance for the given root URL and relative path,
* going through URI construction and then URL conversion.
* @param root the root URL to start from
* @param relativePath the relative path to apply
* @return the relative URL instance
* @throws MalformedURLException if the end result is not a valid URL
* @since 6.0
*/
public static URL toRelativeURL(URL root, String relativePath) throws MalformedURLException {
// # can appear in filenames, java.net.URL should not treat it as a fragment
relativePath = StringUtils.replace(relativePath, "#", "%23");

// Not fully equivalent - but to be moved in the given direction
// since JDK 20 deprecates all direct java.net.URL constructors.
/*
return toURL(StringUtils.applyRelativePath(root.toString(), relativePath));
*/

return new URL(root, relativePath);
}

/**
* Set the {@link URLConnection#setUseCaches "useCaches"} flag on the
* given connection, preferring {@code false} but leaving the
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2022 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.
Expand Down Expand Up @@ -312,7 +312,7 @@ protected void parseJarFiles(Element persistenceUnit, SpringPersistenceUnitInfo
// relative to the persistence unit root, according to the JPA spec
URL rootUrl = unitInfo.getPersistenceUnitRootUrl();
if (rootUrl != null) {
unitInfo.addJarFileUrl(new URL(rootUrl, value));
unitInfo.addJarFileUrl(ResourceUtils.toRelativeURL(rootUrl, value));
}
else {
logger.warn("Cannot resolve jar-file entry [" + value + "] in persistence unit '" +
Expand Down Expand Up @@ -363,7 +363,7 @@ static URL determinePersistenceUnitRootUrl(Resource resource) throws IOException
if (persistenceUnitRoot.endsWith("/")) {
persistenceUnitRoot = persistenceUnitRoot.substring(0, persistenceUnitRoot.length() - 1);
}
return new URL(persistenceUnitRoot);
return ResourceUtils.toURL(persistenceUnitRoot);
}

}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2022 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.
Expand Down Expand Up @@ -101,6 +101,7 @@
import org.springframework.util.ClassUtils;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.ResourceUtils;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.StaxUtils;

Expand Down Expand Up @@ -985,7 +986,7 @@ public String addMtomAttachment(DataHandler dataHandler, String elementNamespace

private String getHost(String elementNamespace, DataHandler dataHandler) {
try {
URI uri = new URI(elementNamespace);
URI uri = ResourceUtils.toURI(elementNamespace);
return uri.getHost();
}
catch (URISyntaxException ex) {
Expand Down

0 comments on commit aaeb5eb

Please sign in to comment.