This is an automated email from the ASF dual-hosted git repository.

sanjaydutt pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/solr.git


The following commit(s) were added to refs/heads/main by this push:
     new 2a56bfc2d8b SOLR-17321:  Remove Deprecated URL ctors in Preparation 
for Java 21 (#2501)
2a56bfc2d8b is described below

commit 2a56bfc2d8b48d1c93d683515569e2e97acf2077
Author: Sanjay Dutt <[email protected]>
AuthorDate: Fri Jun 21 20:24:03 2024 +0530

    SOLR-17321:  Remove Deprecated URL ctors in Preparation for Java 21 (#2501)
    
    * Switch to URI
    * Added URL to the forbidden API
    
    -------------
    
    Co-authored-by:  Uwe Schindler <[email protected]>
    Co-authored-by: David Smiley <[email protected]>
---
 gradle/validation/forbidden-apis/defaults.all.txt  |  3 ++
 solr/CHANGES.txt                                   |  4 ++
 .../src/java/org/apache/solr/cli/PostTool.java     | 60 ++++++++++------------
 .../java/org/apache/solr/cli/RunExampleTool.java   |  6 +--
 .../core/src/java/org/apache/solr/cli/SolrCLI.java |  3 +-
 .../src/java/org/apache/solr/cli/StatusTool.java   |  4 +-
 .../solr/handler/admin/AdminHandlersProxy.java     |  6 +--
 .../packagemanager/DefaultPackageRepository.java   |  7 +--
 .../solr/packagemanager/RepositoryManager.java     |  4 +-
 .../solr/schema/OpenExchangeRatesOrgProvider.java  |  4 +-
 .../apache/solr/security/AllowListUrlChecker.java  |  8 +--
 .../org/apache/solr/security/SolrNodeKeyPair.java  |  5 +-
 .../apache/solr/servlet/SolrRequestParsers.java    |  4 +-
 .../update/processor/URLClassifyProcessor.java     |  2 +-
 .../src/test/org/apache/solr/cli/PostToolTest.java | 38 ++++++++------
 .../org/apache/solr/cloud/OverseerRolesTest.java   |  4 +-
 .../solr/cloud/TestPullReplicaErrorHandling.java   | 19 ++++---
 .../apache/solr/cloud/TestRequestForwarding.java   | 10 +++-
 .../apache/solr/handler/ReplicationTestHelper.java |  5 +-
 .../solr/handler/TestReplicationHandler.java       |  3 +-
 .../solr/handler/TestReplicationHandlerBackup.java |  3 +-
 .../apache/solr/request/TestRemoteStreaming.java   |  4 +-
 .../transform/TestSubQueryTransformerDistrib.java  | 14 ++---
 .../solr/security/AuditLoggerIntegrationTest.java  |  4 +-
 .../apache/solr/servlet/HttpSolrCallCloudTest.java |  5 +-
 .../apache/solr/security/jwt/JWTIssuerConfig.java  |  7 +--
 .../security/jwt/JWTAuthPluginIntegrationTest.java |  7 +--
 .../apache/solr/client/solrj/util/ClientUtils.java |  8 +--
 .../solr/client/solrj/TestSolrJErrorHandling.java  |  3 +-
 .../client/solrj/embedded/JettyWebappTest.java     |  4 +-
 .../solrj/impl/CloudHttp2SolrClientTest.java       |  6 +--
 .../client/solrj/impl/CloudSolrClientTest.java     |  6 +--
 .../apache/solr/common/util/ContentStreamTest.java | 13 ++---
 .../org/apache/solr/embedded/JettySolrRunner.java  | 14 +++--
 .../apache/solr/handler/BackupRestoreUtils.java    |  3 +-
 .../apache/solr/handler/TestRestoreCoreUtil.java   |  3 +-
 36 files changed, 168 insertions(+), 135 deletions(-)

diff --git a/gradle/validation/forbidden-apis/defaults.all.txt 
b/gradle/validation/forbidden-apis/defaults.all.txt
index a7647ddbcb7..f1220bfcd05 100644
--- a/gradle/validation/forbidden-apis/defaults.all.txt
+++ b/gradle/validation/forbidden-apis/defaults.all.txt
@@ -83,3 +83,6 @@ java.util.logging.**
 
 @defaultMessage Use List.sort(Comparator) instead of Collections.sort(List, 
Comparator) please.
 java.util.Collections#sort(java.util.List, java.util.Comparator)
+
+@defaultMessage Use URI.toURL() to construct an instance of URL.
+java.net.URL#<init>(**)
\ No newline at end of file
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 7164de994ff..ca642e9bbc3 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -182,6 +182,10 @@ Other Changes
 
 * SOLR-16503: Use Jetty HTTP2 for SyncStrategy and PeerSyncWithLeader for 
"recovery" operations (Sanjay Dutt, David Smiley)
 
+* SOLR-16796: Include cyclonedx SBOMs with maven artifacts (Arnout Engelen, 
Houston Putman, Kevin Risden)
+
+* SOLR-17321: Remove Deprecated URL and replace it with URI in Preparation for 
Java 21 (Sanjay Dutt, David Smiley, Uwe Schindler)
+
 ==================  9.6.1 ==================
 Bug Fixes
 ---------------------
diff --git a/solr/core/src/java/org/apache/solr/cli/PostTool.java 
b/solr/core/src/java/org/apache/solr/cli/PostTool.java
index 45eb73c6408..1181910b2a4 100644
--- a/solr/core/src/java/org/apache/solr/cli/PostTool.java
+++ b/solr/core/src/java/org/apache/solr/cli/PostTool.java
@@ -98,7 +98,7 @@ public class PostTool extends ToolBase {
   int recursive = 0;
   int delay = 0;
   String fileTypes = PostTool.DEFAULT_FILE_TYPES;
-  URL solrUpdateUrl;
+  URI solrUpdateUrl;
   String credentials;
   OutputStream out = null;
   String type;
@@ -256,10 +256,10 @@ public class PostTool extends ToolBase {
     solrUpdateUrl = null;
     if (cli.hasOption("url")) {
       String url = cli.getOptionValue("url");
-      solrUpdateUrl = new URL(url);
+      solrUpdateUrl = new URI(url);
     } else if (cli.hasOption("c")) {
       String url = SolrCLI.getDefaultSolrUrl() + "/solr/" + 
cli.getOptionValue("c") + "/update";
-      solrUpdateUrl = new URL(url);
+      solrUpdateUrl = new URI(url);
     } else {
       throw new IllegalArgumentException(
           "Must specify either -url or -c parameter to post documents.");
@@ -389,7 +389,7 @@ public class PostTool extends ToolBase {
       numPagesPosted = postWebPages(args, 0, out);
       info(numPagesPosted + " web pages indexed.");
 
-    } catch (MalformedURLException e) {
+    } catch (URISyntaxException e) {
       warn("Wrong URL trying to append /extract to " + solrUpdateUrl);
     }
   }
@@ -515,7 +515,7 @@ public class PostTool extends ToolBase {
         postFile(srcFile, out, type);
         Thread.sleep(delay * 1000L);
         filesPosted++;
-      } catch (InterruptedException | MalformedURLException e) {
+      } catch (InterruptedException | URISyntaxException e) {
         throw new RuntimeException(e);
       }
     }
@@ -623,8 +623,8 @@ public class PostTool extends ToolBase {
         PostTool.PageFetcherResult result = pageFetcher.readPageFromUrl(url);
         if (result.httpStatus == 200) {
           url = (result.redirectUrl != null) ? result.redirectUrl : url;
-          URL postUrl =
-              new URL(
+          URI postUri =
+              new URI(
                   appendParam(
                       solrUpdateUrl.toString(),
                       "literal.id="
@@ -638,7 +638,7 @@ public class PostTool extends ToolBase {
                   null,
                   out,
                   result.contentType,
-                  postUrl);
+                  postUri);
           if (success) {
             info("POSTed web resource " + url + " (depth: " + level + ")");
             Thread.sleep(delay * 1000L);
@@ -651,7 +651,7 @@ public class PostTool extends ToolBase {
                       new ByteArrayInputStream(
                           content.array(), content.arrayOffset(), 
content.limit()),
                       result.contentType,
-                      postUrl);
+                      postUri);
               subStack.addAll(children);
             }
           } else {
@@ -782,10 +782,10 @@ public class PostTool extends ToolBase {
   }
 
   /** Opens the file and posts its contents to the solrUrl, writes to response 
to output. */
-  public void postFile(File file, OutputStream output, String type) throws 
MalformedURLException {
+  public void postFile(File file, OutputStream output, String type) throws 
URISyntaxException {
     InputStream is = null;
 
-    URL url = solrUpdateUrl;
+    URI uri = solrUpdateUrl;
     String suffix = "";
     if (auto) {
       if (type == null) {
@@ -797,7 +797,7 @@ public class PostTool extends ToolBase {
       if (type.equals("application/json") && 
!PostTool.FORMAT_SOLR.equals(format)) {
         suffix = "/json/docs";
         String urlStr = appendUrlPath(solrUpdateUrl, suffix).toString();
-        url = new URL(urlStr);
+        uri = new URI(urlStr);
       } else if (type.equals("application/xml")
           || type.equals("text/csv")
           || type.equals("application/json")) {
@@ -815,7 +815,7 @@ public class PostTool extends ToolBase {
           urlStr =
               appendParam(urlStr, "literal.id=" + 
URLEncoder.encode(file.getAbsolutePath(), UTF_8));
         }
-        url = new URL(urlStr);
+        uri = new URI(urlStr);
       }
     } else {
       if (type == null) {
@@ -838,7 +838,7 @@ public class PostTool extends ToolBase {
                 + " to [base]"
                 + suffix);
         is = new FileInputStream(file);
-        postData(is, file.length(), output, type, url);
+        postData(is, file.length(), output, type, uri);
       } catch (IOException e) {
         warn("Can't open/read file: " + file);
       } finally {
@@ -856,18 +856,13 @@ public class PostTool extends ToolBase {
   /**
    * Appends to the path of the URL
    *
-   * @param url the URL
+   * @param uri the URI
    * @param append the path to append
    * @return the final URL version
    */
-  protected static URL appendUrlPath(URL url, String append) throws 
MalformedURLException {
-    return new URL(
-        url.getProtocol()
-            + "://"
-            + url.getAuthority()
-            + url.getPath()
-            + append
-            + (url.getQuery() != null ? "?" + url.getQuery() : ""));
+  protected static URI appendUrlPath(URI uri, String append) throws 
URISyntaxException {
+    var newPath = uri.getPath() + append;
+    return new URI(uri.getScheme(), uri.getAuthority(), newPath, 
uri.getQuery(), uri.getFragment());
   }
 
   /**
@@ -890,7 +885,7 @@ public class PostTool extends ToolBase {
    * @return true if success
    */
   public boolean postData(
-      InputStream data, Long length, OutputStream output, String type, URL 
url) {
+      InputStream data, Long length, OutputStream output, String type, URI 
uri) {
     if (dryRun) {
       return true;
     }
@@ -902,7 +897,7 @@ public class PostTool extends ToolBase {
     HttpURLConnection urlConnection = null;
     try {
       try {
-        urlConnection = (HttpURLConnection) url.openConnection();
+        urlConnection = (HttpURLConnection) (uri.toURL()).openConnection();
         try {
           urlConnection.setRequestMethod("POST");
         } catch (ProtocolException e) {
@@ -1200,9 +1195,9 @@ public class PostTool extends ToolBase {
         disallows = new ArrayList<>();
         URL urlRobot;
         try {
-          urlRobot = new URL(strRobot);
+          urlRobot = new URI(strRobot).toURL();
           disallows = parseRobotsTxt(urlRobot.openStream());
-        } catch (MalformedURLException e) {
+        } catch (URISyntaxException | MalformedURLException e) {
           return true; // We cannot trust this robots URL, should not happen
         } catch (IOException e) {
           // There is no robots.txt, will cache an empty disallow list
@@ -1250,17 +1245,16 @@ public class PostTool extends ToolBase {
      * @param url the URL of the web page
      * @param is the input stream of the page
      * @param type the content-type
-     * @param postUrl the URL (typically /solr/extract) in order to pull out 
links
+     * @param postUri the URI (typically /solr/extract) in order to pull out 
links
      * @return a set of URIs parsed from the page
      */
-    protected Set<URI> getLinksFromWebPage(URL url, InputStream is, String 
type, URL postUrl) {
+    protected Set<URI> getLinksFromWebPage(URL url, InputStream is, String 
type, URI postUri) {
       Set<URI> linksFromPage = new HashSet<>();
 
       try {
         ByteArrayOutputStream os = new ByteArrayOutputStream();
-        URL extractUrl = new URL(appendParam(postUrl.toString(), 
"extractOnly=true"));
-        extractUrl = new URL(appendParam(extractUrl.toString(), "wt=xml"));
-        boolean success = postData(is, null, os, type, extractUrl);
+        URI extractUri = new URI(appendParam(postUri.toString(), 
"extractOnly=true"));
+        boolean success = postData(is, null, os, type, extractUri);
         if (success) {
           Document d = makeDom(os.toByteArray());
           String innerXml = getXP(d, "/response/str/text()[1]", false);
@@ -1279,7 +1273,7 @@ public class PostTool extends ToolBase {
             }
           }
         }
-      } catch (MalformedURLException e) {
+      } catch (URISyntaxException e) {
         warn("Malformed URL " + url);
       } catch (IOException e) {
         warn("IOException opening URL " + url + ": " + e.getMessage());
diff --git a/solr/core/src/java/org/apache/solr/cli/RunExampleTool.java 
b/solr/core/src/java/org/apache/solr/cli/RunExampleTool.java
index c4e5e78ecde..73ff1dd8772 100644
--- a/solr/core/src/java/org/apache/solr/cli/RunExampleTool.java
+++ b/solr/core/src/java/org/apache/solr/cli/RunExampleTool.java
@@ -22,7 +22,7 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.PrintStream;
 import java.net.Socket;
-import java.net.URL;
+import java.net.URI;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.util.Arrays;
@@ -890,7 +890,7 @@ public class RunExampleTool extends ToolBase {
     StatusTool statusTool = new StatusTool();
     if (verbose) echo("\nChecking status of Solr at " + solrUrl + " ...");
 
-    URL solrURL = new URL(solrUrl);
+    URI solrURI = new URI(solrUrl);
     Map<String, Object> nodeStatus =
         statusTool.waitToSeeSolrUp(solrUrl, credentials, maxWaitSecs, 
TimeUnit.SECONDS);
     nodeStatus.put("baseUrl", solrUrl);
@@ -900,7 +900,7 @@ public class RunExampleTool extends ToolBase {
     if (verbose)
       echo(
           "\nSolr is running on "
-              + solrURL.getPort()
+              + solrURI.getPort()
               + " in "
               + mode
               + " mode with status:\n"
diff --git a/solr/core/src/java/org/apache/solr/cli/SolrCLI.java 
b/solr/core/src/java/org/apache/solr/cli/SolrCLI.java
index 191fb48bda4..93fdbf3697c 100755
--- a/solr/core/src/java/org/apache/solr/cli/SolrCLI.java
+++ b/solr/core/src/java/org/apache/solr/cli/SolrCLI.java
@@ -28,6 +28,7 @@ import java.io.File;
 import java.io.IOException;
 import java.lang.invoke.MethodHandles;
 import java.net.SocketException;
+import java.net.URI;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -359,7 +360,7 @@ public class SolrCLI implements CLIO {
     Set<String> classes = new TreeSet<>();
     if (path.startsWith("file:") && path.contains("!")) {
       String[] split = path.split("!");
-      URL jar = new URL(split[0]);
+      URL jar = new URI(split[0]).toURL();
       try (ZipInputStream zip = new ZipInputStream(jar.openStream())) {
         ZipEntry entry;
         while ((entry = zip.getNextEntry()) != null) {
diff --git a/solr/core/src/java/org/apache/solr/cli/StatusTool.java 
b/solr/core/src/java/org/apache/solr/cli/StatusTool.java
index a201fc42641..840539c69c4 100644
--- a/solr/core/src/java/org/apache/solr/cli/StatusTool.java
+++ b/solr/core/src/java/org/apache/solr/cli/StatusTool.java
@@ -18,7 +18,7 @@
 package org.apache.solr.cli;
 
 import java.io.PrintStream;
-import java.net.URL;
+import java.net.URI;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
@@ -94,7 +94,7 @@ public class StatusTool extends ToolBase {
     int maxWaitSecs = Integer.parseInt(cli.getOptionValue("maxWaitSecs", "0"));
     String solrUrl = SolrCLI.normalizeSolrUrl(cli);
     if (maxWaitSecs > 0) {
-      int solrPort = (new URL(solrUrl)).getPort();
+      int solrPort = new URI(solrUrl).getPort();
       echo("Waiting up to " + maxWaitSecs + " seconds to see Solr running on 
port " + solrPort);
       try {
         waitToSeeSolrUp(
diff --git 
a/solr/core/src/java/org/apache/solr/handler/admin/AdminHandlersProxy.java 
b/solr/core/src/java/org/apache/solr/handler/admin/AdminHandlersProxy.java
index cd278fd095a..2d5b8d9f6f2 100644
--- a/solr/core/src/java/org/apache/solr/handler/admin/AdminHandlersProxy.java
+++ b/solr/core/src/java/org/apache/solr/handler/admin/AdminHandlersProxy.java
@@ -19,7 +19,7 @@ package org.apache.solr.handler.admin;
 
 import java.io.IOException;
 import java.lang.invoke.MethodHandles;
-import java.net.URL;
+import java.net.URI;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -133,8 +133,8 @@ public class AdminHandlersProxy {
       String nodeName, String endpoint, SolrParams params, ZkController 
zkController)
       throws IOException, SolrServerException {
     log.debug("Proxying {} request to node {}", endpoint, nodeName);
-    URL baseUrl = new 
URL(zkController.zkStateReader.getBaseUrlForNodeName(nodeName));
-    HttpSolrClient solr = new 
HttpSolrClient.Builder(baseUrl.toString()).build();
+    URI baseUri = 
URI.create(zkController.zkStateReader.getBaseUrlForNodeName(nodeName));
+    HttpSolrClient solr = new 
HttpSolrClient.Builder(baseUri.toString()).build();
     SolrRequest<?> proxyReq = new GenericSolrRequest(SolrRequest.METHOD.GET, 
endpoint, params);
     HttpSolrClient.HttpUriRequestResponse proxyResp = 
solr.httpUriRequest(proxyReq);
     return new Pair<>(proxyResp.future, solr);
diff --git 
a/solr/core/src/java/org/apache/solr/packagemanager/DefaultPackageRepository.java
 
b/solr/core/src/java/org/apache/solr/packagemanager/DefaultPackageRepository.java
index 820391804e1..62d241d8bce 100644
--- 
a/solr/core/src/java/org/apache/solr/packagemanager/DefaultPackageRepository.java
+++ 
b/solr/core/src/java/org/apache/solr/packagemanager/DefaultPackageRepository.java
@@ -20,6 +20,7 @@ package org.apache.solr.packagemanager;
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import java.io.IOException;
 import java.lang.invoke.MethodHandles;
+import java.net.URI;
 import java.net.URL;
 import java.nio.file.Files;
 import java.nio.file.Path;
@@ -86,9 +87,9 @@ public class DefaultPackageRepository extends 
PackageRepository {
     Path tmpDirectory = Files.createTempDirectory("solr-packages");
     tmpDirectory.toFile().deleteOnExit();
     URL url =
-        new URL(
-            new URL(repositoryURL.endsWith("/") ? repositoryURL : 
repositoryURL + "/"),
-            artifactName);
+        URI.create(repositoryURL.endsWith("/") ? repositoryURL : repositoryURL 
+ "/")
+            .resolve(artifactName)
+            .toURL();
     String fileName = FilenameUtils.getName(url.getPath());
     Path destination = tmpDirectory.resolve(fileName);
 
diff --git 
a/solr/core/src/java/org/apache/solr/packagemanager/RepositoryManager.java 
b/solr/core/src/java/org/apache/solr/packagemanager/RepositoryManager.java
index 4e3be7b16c6..09c0a209172 100644
--- a/solr/core/src/java/org/apache/solr/packagemanager/RepositoryManager.java
+++ b/solr/core/src/java/org/apache/solr/packagemanager/RepositoryManager.java
@@ -24,7 +24,7 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.UnsupportedEncodingException;
 import java.lang.invoke.MethodHandles;
-import java.net.URL;
+import java.net.URI;
 import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
@@ -133,7 +133,7 @@ public class RepositoryManager {
           true);
     }
 
-    try (InputStream is = new URL(uri + "/publickey.der").openStream()) {
+    try (InputStream is = new URI(uri + 
"/publickey.der").toURL().openStream()) {
       addKey(is.readAllBytes(), repoName + ".der");
     }
   }
diff --git 
a/solr/core/src/java/org/apache/solr/schema/OpenExchangeRatesOrgProvider.java 
b/solr/core/src/java/org/apache/solr/schema/OpenExchangeRatesOrgProvider.java
index 6438af1ffe6..fcc64b111eb 100644
--- 
a/solr/core/src/java/org/apache/solr/schema/OpenExchangeRatesOrgProvider.java
+++ 
b/solr/core/src/java/org/apache/solr/schema/OpenExchangeRatesOrgProvider.java
@@ -20,7 +20,7 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.lang.invoke.MethodHandles;
-import java.net.URL;
+import java.net.URI;
 import java.nio.charset.StandardCharsets;
 import java.util.HashMap;
 import java.util.Map;
@@ -151,7 +151,7 @@ public class OpenExchangeRatesOrgProvider implements 
ExchangeRateProvider {
     try {
       log.debug("Reloading exchange rates from {}", ratesFileLocation);
       try {
-        ratesJsonStream = (new URL(ratesFileLocation)).openStream();
+        ratesJsonStream = (new URI(ratesFileLocation).toURL()).openStream();
       } catch (Exception e) {
         ratesJsonStream = resourceLoader.openResource(ratesFileLocation);
       }
diff --git 
a/solr/core/src/java/org/apache/solr/security/AllowListUrlChecker.java 
b/solr/core/src/java/org/apache/solr/security/AllowListUrlChecker.java
index 1354fde0ec7..9bcede9b060 100644
--- a/solr/core/src/java/org/apache/solr/security/AllowListUrlChecker.java
+++ b/solr/core/src/java/org/apache/solr/security/AllowListUrlChecker.java
@@ -20,7 +20,7 @@ package org.apache.solr.security;
 import com.google.common.annotations.VisibleForTesting;
 import java.lang.invoke.MethodHandles;
 import java.net.MalformedURLException;
-import java.net.URL;
+import java.net.URI;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
@@ -191,16 +191,16 @@ public class AllowListUrlChecker {
     // Parse the host and port.
     // It doesn't really matter which protocol we set here because we are not 
going to use it.
     url = url.trim();
-    URL u;
+    URI u;
     Matcher protocolMatcher = PROTOCOL_PATTERN.matcher(url);
     if (protocolMatcher.matches()) {
       // Replace any protocol unsupported by URL.
       if (!protocolMatcher.group(1).startsWith("http")) {
         url = "http" + protocolMatcher.group(2);
       }
-      u = new URL(url);
+      u = URI.create(url);
     } else {
-      u = new URL("http://"; + url);
+      u = URI.create("http://"; + url);
     }
     if (u.getHost() == null || u.getPort() < 0) {
       throw new MalformedURLException("Invalid host or port in '" + url + "'");
diff --git a/solr/core/src/java/org/apache/solr/security/SolrNodeKeyPair.java 
b/solr/core/src/java/org/apache/solr/security/SolrNodeKeyPair.java
index 1e93667c5d9..8db42492354 100644
--- a/solr/core/src/java/org/apache/solr/security/SolrNodeKeyPair.java
+++ b/solr/core/src/java/org/apache/solr/security/SolrNodeKeyPair.java
@@ -18,7 +18,7 @@
 package org.apache.solr.security;
 
 import java.io.IOException;
-import java.net.URL;
+import java.net.URI;
 import java.security.spec.InvalidKeySpecException;
 import org.apache.solr.common.util.StrUtils;
 import org.apache.solr.core.CloudConfig;
@@ -55,7 +55,8 @@ public class SolrNodeKeyPair {
     }
 
     try {
-      return new CryptoKeys.RSAKeyPair(new URL(privateKey), new 
URL(publicKey));
+      return new CryptoKeys.RSAKeyPair(
+          URI.create(privateKey).toURL(), URI.create(publicKey).toURL());
     } catch (IOException | InvalidKeySpecException e) {
       throw new RuntimeException("Bad PublicKeyHandler configuration.", e);
     }
diff --git a/solr/core/src/java/org/apache/solr/servlet/SolrRequestParsers.java 
b/solr/core/src/java/org/apache/solr/servlet/SolrRequestParsers.java
index 91d7e2b2498..38a45c71a91 100644
--- a/solr/core/src/java/org/apache/solr/servlet/SolrRequestParsers.java
+++ b/solr/core/src/java/org/apache/solr/servlet/SolrRequestParsers.java
@@ -24,7 +24,7 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.PushbackInputStream;
 import java.lang.invoke.MethodHandles;
-import java.net.URL;
+import java.net.URI;
 import java.nio.ByteBuffer;
 import java.nio.charset.CharacterCodingException;
 import java.nio.charset.Charset;
@@ -212,7 +212,7 @@ public class SolrRequestParsers {
         throw new SolrException(ErrorCode.BAD_REQUEST, "Remote Streaming is 
disabled.");
       }
       for (final String url : strs) {
-        ContentStreamBase stream = new ContentStreamBase.URLStream(new 
URL(url));
+        ContentStreamBase stream = new 
ContentStreamBase.URLStream(URI.create(url).toURL());
         if (contentType != null) {
           stream.setContentType(contentType);
         }
diff --git 
a/solr/core/src/java/org/apache/solr/update/processor/URLClassifyProcessor.java 
b/solr/core/src/java/org/apache/solr/update/processor/URLClassifyProcessor.java
index f26450442e4..91ecc1adad1 100644
--- 
a/solr/core/src/java/org/apache/solr/update/processor/URLClassifyProcessor.java
+++ 
b/solr/core/src/java/org/apache/solr/update/processor/URLClassifyProcessor.java
@@ -198,7 +198,7 @@ public class URLClassifyProcessor extends 
UpdateRequestProcessor {
     // NOTE: Do we want to make sure this URL is normalized? (Christian thinks 
we should)
     String urlString = url.toString();
     String lps = landingPageSuffix(url);
-    return new URL(urlString.replaceFirst("/" + lps + "$", "/"));
+    return URI.create(urlString.replaceFirst("/" + lps + "$", "/")).toURL();
   }
 
   /**
diff --git a/solr/core/src/test/org/apache/solr/cli/PostToolTest.java 
b/solr/core/src/test/org/apache/solr/cli/PostToolTest.java
index 5d8b9720f6b..a6e60f84bed 100644
--- a/solr/core/src/test/org/apache/solr/cli/PostToolTest.java
+++ b/solr/core/src/test/org/apache/solr/cli/PostToolTest.java
@@ -171,19 +171,24 @@ public class PostToolTest extends SolrCloudTestCase {
 
     assertEquals(
         "http://[ff01::114]/index.html";,
-        webPostTool.computeFullUrl(new URL("http://[ff01::114]/";), 
"/index.html"));
+        webPostTool.computeFullUrl(URI.create("http://[ff01::114]/";).toURL(), 
"/index.html"));
     assertEquals(
         "http://[ff01::114]/index.html";,
-        webPostTool.computeFullUrl(new URL("http://[ff01::114]/foo/bar/";), 
"/index.html"));
+        webPostTool.computeFullUrl(
+            URI.create("http://[ff01::114]/foo/bar/";).toURL(), "/index.html"));
     assertEquals(
         "http://[ff01::114]/fil.html";,
-        webPostTool.computeFullUrl(new 
URL("http://[ff01::114]/foo.htm?baz#hello";), "fil.html"));
+        webPostTool.computeFullUrl(
+            URI.create("http://[ff01::114]/foo.htm?baz#hello";).toURL(), 
"fil.html"));
     //    TODO: How to know what is the base if URL path ends with "foo"??
     //    assertEquals("http://[ff01::114]/fil.html";, t_web.computeFullUrl(new
     // URL("http://[ff01::114]/foo?baz#hello";), "fil.html"));
-    assertNull(webPostTool.computeFullUrl(new URL("http://[ff01::114]/";), 
"fil.jpg"));
-    assertNull(webPostTool.computeFullUrl(new URL("http://[ff01::114]/";), 
"mailto:[email protected]";));
-    assertNull(webPostTool.computeFullUrl(new URL("http://[ff01::114]/";), 
"ftp://server/file";));
+    
assertNull(webPostTool.computeFullUrl(URI.create("http://[ff01::114]/";).toURL(),
 "fil.jpg"));
+    assertNull(
+        webPostTool.computeFullUrl(
+            URI.create("http://[ff01::114]/";).toURL(), 
"mailto:[email protected]";));
+    assertNull(
+        webPostTool.computeFullUrl(URI.create("http://[ff01::114]/";).toURL(), 
"ftp://server/file";));
   }
 
   @Test
@@ -210,10 +215,10 @@ public class PostToolTest extends SolrCloudTestCase {
   }
 
   @Test
-  public void testAppendUrlPath() throws MalformedURLException {
+  public void testAppendUrlPath() throws URISyntaxException {
     assertEquals(
-        new URL("http://[ff01::114]/a?foo=bar";),
-        PostTool.appendUrlPath(new URL("http://[ff01::114]?foo=bar";), "/a"));
+        URI.create("http://[ff01::114]/a?foo=bar";),
+        PostTool.appendUrlPath(URI.create("http://[ff01::114]?foo=bar";), 
"/a"));
   }
 
   @Test
@@ -231,7 +236,7 @@ public class PostToolTest extends SolrCloudTestCase {
     PostTool postTool = new PostTool();
     postTool.recursive = 0;
     postTool.dryRun = true;
-    postTool.solrUpdateUrl = new URL("http://localhost:8983/solr/fake/update";);
+    postTool.solrUpdateUrl = 
URI.create("http://localhost:8983/solr/fake/update";);
     File dir = getFile("exampledocs");
     int num = postTool.postFiles(new String[] {dir.toString()}, 0, null, null);
     assertEquals(2, num);
@@ -253,7 +258,7 @@ public class PostToolTest extends SolrCloudTestCase {
     PostTool postTool = new PostTool();
     postTool.recursive = 1; // This is the default
     postTool.dryRun = true;
-    postTool.solrUpdateUrl = new URL("http://localhost:8983/solr/fake/update";);
+    postTool.solrUpdateUrl = 
URI.create("http://localhost:8983/solr/fake/update";);
     File dir = getFile("exampledocs");
     int num = postTool.postFiles(new String[] {dir.toString()}, 0, null, null);
     assertEquals(2, num);
@@ -264,7 +269,7 @@ public class PostToolTest extends SolrCloudTestCase {
     PostTool postTool = new PostTool();
     postTool.pageFetcher = new MockPageFetcher();
     postTool.dryRun = true;
-    postTool.solrUpdateUrl = new 
URL("http://user:password@localhost:5150/solr/fake/update";);
+    postTool.solrUpdateUrl = 
URI.create("http://user:password@localhost:5150/solr/fake/update";);
 
     // Uses mock pageFetcher
     postTool.delay = 0;
@@ -289,8 +294,11 @@ public class PostToolTest extends SolrCloudTestCase {
     postTool.pageFetcher = new MockPageFetcher();
     postTool.dryRun = true;
 
-    assertFalse(postTool.pageFetcher.isDisallowedByRobots(new 
URL("http://[ff01::114]/";)));
-    assertTrue(postTool.pageFetcher.isDisallowedByRobots(new 
URL("http://[ff01::114]/disallowed";)));
+    assertFalse(
+        
postTool.pageFetcher.isDisallowedByRobots(URI.create("http://[ff01::114]/";).toURL()));
+    assertTrue(
+        postTool.pageFetcher.isDisallowedByRobots(
+            URI.create("http://[ff01::114]/disallowed";).toURL()));
     assertEquals(
         "There should be two entries parsed from robots.txt",
         2,
@@ -368,7 +376,7 @@ public class PostToolTest extends SolrCloudTestCase {
     }
 
     @Override
-    public Set<URI> getLinksFromWebPage(URL url, InputStream is, String type, 
URL postUrl) {
+    public Set<URI> getLinksFromWebPage(URL url, InputStream is, String type, 
URI postUri) {
       Set<URI> s = linkMap.get(PostTool.normalizeUrlEnding(url.toString()));
       if (s == null) {
         s = new HashSet<>();
diff --git a/solr/core/src/test/org/apache/solr/cloud/OverseerRolesTest.java 
b/solr/core/src/test/org/apache/solr/cloud/OverseerRolesTest.java
index 8ebe618e660..3da6970e1f6 100644
--- a/solr/core/src/test/org/apache/solr/cloud/OverseerRolesTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/OverseerRolesTest.java
@@ -20,7 +20,7 @@ import static 
org.apache.solr.cloud.OverseerCollectionConfigSetProcessor.getLead
 import static 
org.apache.solr.cloud.OverseerTaskProcessor.getSortedElectionNodes;
 
 import java.lang.invoke.MethodHandles;
-import java.net.URL;
+import java.net.URI;
 import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
@@ -75,7 +75,7 @@ public class OverseerRolesTest extends SolrCloudTestCase {
 
   private JettySolrRunner getOverseerJetty() throws Exception {
     String overseer = getLeaderNode(zkClient());
-    URL overseerUrl = new URL("http://"; + overseer.substring(0, 
overseer.indexOf('_')));
+    URI overseerUrl = URI.create("http://"; + overseer.substring(0, 
overseer.indexOf('_')));
     int hostPort = overseerUrl.getPort();
     for (JettySolrRunner jetty : cluster.getJettySolrRunners()) {
       try {
diff --git 
a/solr/core/src/test/org/apache/solr/cloud/TestPullReplicaErrorHandling.java 
b/solr/core/src/test/org/apache/solr/cloud/TestPullReplicaErrorHandling.java
index dd0363c16ac..9906d3041f1 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestPullReplicaErrorHandling.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestPullReplicaErrorHandling.java
@@ -19,7 +19,6 @@ package org.apache.solr.cloud;
 import java.io.IOException;
 import java.lang.invoke.MethodHandles;
 import java.net.URI;
-import java.net.URL;
 import java.util.ArrayList;
 import java.util.EnumSet;
 import java.util.HashMap;
@@ -325,24 +324,24 @@ public class TestPullReplicaErrorHandling extends 
SolrCloudTestCase {
   protected JettySolrRunner getJettyForReplica(Replica replica) throws 
Exception {
     String replicaBaseUrl = replica.getStr(ZkStateReader.BASE_URL_PROP);
     assertNotNull(replicaBaseUrl);
-    URL baseUrl = new URL(replicaBaseUrl);
+    URI baseUri = URI.create(replicaBaseUrl);
 
-    JettySolrRunner proxy = jettys.get(baseUrl.toURI());
-    assertNotNull("No proxy found for " + baseUrl + "!", proxy);
+    JettySolrRunner proxy = jettys.get(baseUri);
+    assertNotNull("No proxy found for " + baseUri + "!", proxy);
     return proxy;
   }
 
   protected SocketProxy getProxyForReplica(Replica replica) throws Exception {
     String replicaBaseUrl = replica.getStr(ZkStateReader.BASE_URL_PROP);
     assertNotNull(replicaBaseUrl);
-    URL baseUrl = new URL(replicaBaseUrl);
+    URI baseUri = URI.create(replicaBaseUrl);
 
-    SocketProxy proxy = proxies.get(baseUrl.toURI());
-    if (proxy == null && !baseUrl.toExternalForm().endsWith("/")) {
-      baseUrl = new URL(baseUrl.toExternalForm() + "/");
-      proxy = proxies.get(baseUrl.toURI());
+    SocketProxy proxy = proxies.get(baseUri);
+    if (proxy == null && !baseUri.toString().endsWith("/")) {
+      baseUri = URI.create(baseUri.toString() + "/");
+      proxy = proxies.get(baseUri);
     }
-    assertNotNull("No proxy found for " + baseUrl + "!", proxy);
+    assertNotNull("No proxy found for " + baseUri + "!", proxy);
     return proxy;
   }
 
diff --git 
a/solr/core/src/test/org/apache/solr/cloud/TestRequestForwarding.java 
b/solr/core/src/test/org/apache/solr/cloud/TestRequestForwarding.java
index a4854134f93..c672da3f4f2 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestRequestForwarding.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestRequestForwarding.java
@@ -16,11 +16,13 @@
  */
 package org.apache.solr.cloud;
 
+import java.net.MalformedURLException;
 import java.net.URL;
 import org.apache.solr.SolrTestCaseJ4;
 import org.apache.solr.SolrTestCaseJ4.SuppressSSL;
 import org.apache.solr.client.solrj.request.CollectionAdminRequest;
 import org.apache.solr.client.solrj.response.CollectionAdminResponse;
+import org.apache.solr.common.util.SuppressForbidden;
 import org.apache.solr.embedded.JettyConfig;
 import org.apache.solr.embedded.JettySolrRunner;
 import org.junit.Test;
@@ -60,7 +62,7 @@ public class TestRequestForwarding extends SolrTestCaseJ4 {
       };
       for (String q : queryStrings) {
         try {
-          URL url = new URL(jettySolrRunner.getBaseUrl().toString() + 
"/collection1/select?" + q);
+          URL url = createURL(jettySolrRunner.getBaseUrl().toString() + 
"/collection1/select?" + q);
           url.openStream(); // Shouldn't throw any errors
         } catch (Exception ex) {
           throw new RuntimeException("Query '" + q + "' failed, ", ex);
@@ -69,6 +71,12 @@ public class TestRequestForwarding extends SolrTestCaseJ4 {
     }
   }
 
+  // Restricting the Scope of Forbidden API
+  @SuppressForbidden(reason = "java.net.URL#<init> deprecated since Java 20")
+  private URL createURL(String url) throws MalformedURLException {
+    return new URL(url);
+  }
+
   private void createCollection(String name, String config) throws Exception {
     CollectionAdminResponse response;
     CollectionAdminRequest.Create create =
diff --git 
a/solr/core/src/test/org/apache/solr/handler/ReplicationTestHelper.java 
b/solr/core/src/test/org/apache/solr/handler/ReplicationTestHelper.java
index a9c81429467..edd68727f87 100644
--- a/solr/core/src/test/org/apache/solr/handler/ReplicationTestHelper.java
+++ b/solr/core/src/test/org/apache/solr/handler/ReplicationTestHelper.java
@@ -22,6 +22,7 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.Writer;
 import java.lang.invoke.MethodHandles;
+import java.net.URI;
 import java.net.URL;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
@@ -156,7 +157,7 @@ public final class ReplicationTestHelper {
     // String leaderUrl = buildUrl(pJettyPort) + "/" + DEFAULT_TEST_CORENAME +
     // ReplicationHandler.PATH+"?command=" + pCommand;
     String url = baseUrl + ReplicationHandler.PATH + "?command=" + pCommand;
-    URL u = new URL(url);
+    URL u = URI.create(url).toURL();
     InputStream stream = u.openStream();
     stream.close();
   }
@@ -227,7 +228,7 @@ public final class ReplicationTestHelper {
             + "?wait=true&command=fetchindex&leaderUrl="
             + srcUrl
             + ReplicationHandler.PATH;
-    url = new URL(leaderUrl);
+    url = URI.create(leaderUrl).toURL();
     stream = url.openStream();
     stream.close();
   }
diff --git 
a/solr/core/src/test/org/apache/solr/handler/TestReplicationHandler.java 
b/solr/core/src/test/org/apache/solr/handler/TestReplicationHandler.java
index c35f5c88069..8f424e97803 100644
--- a/solr/core/src/test/org/apache/solr/handler/TestReplicationHandler.java
+++ b/solr/core/src/test/org/apache/solr/handler/TestReplicationHandler.java
@@ -28,6 +28,7 @@ import java.io.FilenameFilter;
 import java.io.IOException;
 import java.io.InputStream;
 import java.lang.invoke.MethodHandles;
+import java.net.URI;
 import java.net.URL;
 import java.nio.file.Paths;
 import java.util.Arrays;
@@ -844,7 +845,7 @@ public class TestReplicationHandler extends SolrTestCaseJ4 {
             + "/"
             + DEFAULT_TEST_CORENAME
             + ReplicationHandler.PATH;
-    URL url = new URL(leaderUrl);
+    URL url = new URI(leaderUrl).toURL();
     InputStream stream = url.openStream();
     stream.close();
 
diff --git 
a/solr/core/src/test/org/apache/solr/handler/TestReplicationHandlerBackup.java 
b/solr/core/src/test/org/apache/solr/handler/TestReplicationHandlerBackup.java
index a85416727e6..418ce1d6551 100644
--- 
a/solr/core/src/test/org/apache/solr/handler/TestReplicationHandlerBackup.java
+++ 
b/solr/core/src/test/org/apache/solr/handler/TestReplicationHandlerBackup.java
@@ -20,6 +20,7 @@ import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.lang.invoke.MethodHandles;
+import java.net.URI;
 import java.net.URL;
 import java.nio.file.DirectoryStream;
 import java.nio.file.Files;
@@ -260,7 +261,7 @@ public class TestReplicationHandlerBackup extends 
SolrJettyTestBase {
             + "?wt=xml&command="
             + cmd
             + params;
-    URL url = new URL(leaderUrl);
+    URL url = URI.create(leaderUrl).toURL();
     try (InputStream stream = url.openStream()) {
       assert stream != null;
     }
diff --git 
a/solr/core/src/test/org/apache/solr/request/TestRemoteStreaming.java 
b/solr/core/src/test/org/apache/solr/request/TestRemoteStreaming.java
index 486b3396afd..8fb2da411d9 100644
--- a/solr/core/src/test/org/apache/solr/request/TestRemoteStreaming.java
+++ b/solr/core/src/test/org/apache/solr/request/TestRemoteStreaming.java
@@ -21,7 +21,7 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.StringWriter;
-import java.net.URL;
+import java.net.URI;
 import java.net.URLEncoder;
 import java.nio.charset.StandardCharsets;
 import org.apache.lucene.tests.util.LuceneTestCase;
@@ -83,7 +83,7 @@ public class TestRemoteStreaming extends SolrJettyTestBase {
   }
 
   private String attemptHttpGet(String getUrl) throws IOException {
-    Object obj = new URL(getUrl).getContent();
+    Object obj = URI.create(getUrl).toURL().getContent();
     if (obj instanceof InputStream) {
       try (InputStream inputStream = (InputStream) obj) {
         StringWriter strWriter = new StringWriter();
diff --git 
a/solr/core/src/test/org/apache/solr/response/transform/TestSubQueryTransformerDistrib.java
 
b/solr/core/src/test/org/apache/solr/response/transform/TestSubQueryTransformerDistrib.java
index c45541a8764..5d626446e58 100644
--- 
a/solr/core/src/test/org/apache/solr/response/transform/TestSubQueryTransformerDistrib.java
+++ 
b/solr/core/src/test/org/apache/solr/response/transform/TestSubQueryTransformerDistrib.java
@@ -23,6 +23,7 @@ import static 
org.apache.solr.security.Sha256AuthenticationProvider.getSaltedHas
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.net.URI;
 import java.net.URL;
 import java.net.URLConnection;
 import java.nio.charset.StandardCharsets;
@@ -209,12 +210,13 @@ public class TestSubQueryTransformerDistrib extends 
SolrCloudTestCase {
 
     params.set("wt", "json");
     final URL node =
-        new URL(
-            cluster.getRandomJetty(random()).getBaseUrl().toString()
-                + "/"
-                + people
-                + "/select"
-                + params.toQueryString());
+        URI.create(
+                cluster.getRandomJetty(random()).getBaseUrl().toString()
+                    + "/"
+                    + people
+                    + "/select"
+                    + params.toQueryString())
+            .toURL();
 
     final URLConnection urlConnectionWithoutAuth = node.openConnection();
     assertThrows(Exception.class, () -> 
urlConnectionWithoutAuth.getInputStream());
diff --git 
a/solr/core/src/test/org/apache/solr/security/AuditLoggerIntegrationTest.java 
b/solr/core/src/test/org/apache/solr/security/AuditLoggerIntegrationTest.java
index 47886c25380..6f800b34f54 100644
--- 
a/solr/core/src/test/org/apache/solr/security/AuditLoggerIntegrationTest.java
+++ 
b/solr/core/src/test/org/apache/solr/security/AuditLoggerIntegrationTest.java
@@ -39,7 +39,7 @@ import java.io.InputStreamReader;
 import java.lang.invoke.MethodHandles;
 import java.net.ServerSocket;
 import java.net.Socket;
-import java.net.URL;
+import java.net.URI;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.util.ArrayList;
@@ -257,7 +257,7 @@ public class AuditLoggerIntegrationTest extends 
SolrCloudAuthTestCase {
     expectThrows(
         FileNotFoundException.class,
         () -> {
-          try (InputStream is = new URL(baseUrl + "/node/foo").openStream()) {
+          try (InputStream is = URI.create(baseUrl + 
"/node/foo").toURL().openStream()) {
             new String(is.readAllBytes(), StandardCharsets.UTF_8);
           }
         });
diff --git 
a/solr/core/src/test/org/apache/solr/servlet/HttpSolrCallCloudTest.java 
b/solr/core/src/test/org/apache/solr/servlet/HttpSolrCallCloudTest.java
index 5af1ead66ef..7fff377d3a3 100644
--- a/solr/core/src/test/org/apache/solr/servlet/HttpSolrCallCloudTest.java
+++ b/solr/core/src/test/org/apache/solr/servlet/HttpSolrCallCloudTest.java
@@ -18,7 +18,7 @@
 package org.apache.solr.servlet;
 
 import java.net.HttpURLConnection;
-import java.net.URL;
+import java.net.URI;
 import java.util.HashSet;
 import java.util.Set;
 import javax.servlet.ReadListener;
@@ -67,7 +67,8 @@ public class HttpSolrCallCloudTest extends SolrCloudTestCase {
   public void testWrongUtf8InQ() throws Exception {
     var baseUrl = cluster.getJettySolrRunner(0).getBaseUrl();
     var request =
-        new URL(baseUrl.toString() + "/" + COLLECTION + "/select?q=%C0"); // 
Illegal UTF-8 string
+        URI.create(baseUrl.toString() + "/" + COLLECTION + "/select?q=%C0")
+            .toURL(); // Illegal UTF-8 string
     var connection = (HttpURLConnection) request.openConnection();
     assertEquals(400, connection.getResponseCode());
   }
diff --git 
a/solr/modules/jwt-auth/src/java/org/apache/solr/security/jwt/JWTIssuerConfig.java
 
b/solr/modules/jwt-auth/src/java/org/apache/solr/security/jwt/JWTIssuerConfig.java
index 752bfd60780..7e479be74d4 100644
--- 
a/solr/modules/jwt-auth/src/java/org/apache/solr/security/jwt/JWTIssuerConfig.java
+++ 
b/solr/modules/jwt-auth/src/java/org/apache/solr/security/jwt/JWTIssuerConfig.java
@@ -24,6 +24,7 @@ import java.io.InputStream;
 import java.lang.invoke.MethodHandles;
 import java.net.InetAddress;
 import java.net.MalformedURLException;
+import java.net.URI;
 import java.net.URL;
 import java.nio.charset.Charset;
 import java.nio.charset.StandardCharsets;
@@ -118,7 +119,7 @@ public class JWTIssuerConfig {
     }
     if (wellKnownUrl != null) {
       try {
-        wellKnownDiscoveryConfig = fetchWellKnown(new URL(wellKnownUrl));
+        wellKnownDiscoveryConfig = 
fetchWellKnown(URI.create(wellKnownUrl).toURL());
       } catch (MalformedURLException e) {
         throw new SolrException(
             SolrException.ErrorCode.SERVER_ERROR,
@@ -469,7 +470,7 @@ public class JWTIssuerConfig {
     private HttpsJwks create(String url) {
       final URL jwksUrl;
       try {
-        jwksUrl = new URL(url);
+        jwksUrl = URI.create(url).toURL();
         checkAllowOutboundHttpConnections(PARAM_JWKS_URL, jwksUrl);
       } catch (MalformedURLException e) {
         throw new SolrException(
@@ -506,7 +507,7 @@ public class JWTIssuerConfig {
     }
 
     public static WellKnownDiscoveryConfig parse(String urlString) throws 
MalformedURLException {
-      return parse(new URL(urlString), null);
+      return parse(URI.create(urlString).toURL(), null);
     }
 
     /**
diff --git 
a/solr/modules/jwt-auth/src/test/org/apache/solr/security/jwt/JWTAuthPluginIntegrationTest.java
 
b/solr/modules/jwt-auth/src/test/org/apache/solr/security/jwt/JWTAuthPluginIntegrationTest.java
index ef7fe35d4f5..3bb08460218 100644
--- 
a/solr/modules/jwt-auth/src/test/org/apache/solr/security/jwt/JWTAuthPluginIntegrationTest.java
+++ 
b/solr/modules/jwt-auth/src/test/org/apache/solr/security/jwt/JWTAuthPluginIntegrationTest.java
@@ -26,6 +26,7 @@ import java.io.InputStreamReader;
 import java.io.OutputStream;
 import java.net.HttpURLConnection;
 import java.net.InetAddress;
+import java.net.URI;
 import java.net.URL;
 import java.nio.charset.Charset;
 import java.nio.charset.StandardCharsets;
@@ -389,7 +390,7 @@ public class JWTAuthPluginIntegrationTest extends 
SolrCloudAuthTestCase {
   }
 
   private Pair<String, Integer> get(String url, String token) throws 
IOException {
-    URL createUrl = new URL(url);
+    URL createUrl = URI.create(url).toURL();
     HttpURLConnection createConn = (HttpURLConnection) 
createUrl.openConnection();
     if (token != null) createConn.setRequestProperty("Authorization", "Bearer 
" + token);
     BufferedReader br2 =
@@ -402,7 +403,7 @@ public class JWTAuthPluginIntegrationTest extends 
SolrCloudAuthTestCase {
   }
 
   private Map<String, String> getHeaders(String url, String token) throws 
IOException {
-    URL createUrl = new URL(url);
+    URL createUrl = URI.create(url).toURL();
     HttpURLConnection conn = (HttpURLConnection) createUrl.openConnection();
     if (token != null) conn.setRequestProperty("Authorization", "Bearer " + 
token);
     conn.connect();
@@ -415,7 +416,7 @@ public class JWTAuthPluginIntegrationTest extends 
SolrCloudAuthTestCase {
   }
 
   private Pair<String, Integer> post(String url, String json, String token) 
throws IOException {
-    URL createUrl = new URL(url);
+    URL createUrl = URI.create(url).toURL();
     HttpURLConnection con = (HttpURLConnection) createUrl.openConnection();
     con.setRequestMethod("POST");
     con.setRequestProperty(HttpHeaders.CONTENT_TYPE, 
ContentType.APPLICATION_JSON.getMimeType());
diff --git 
a/solr/solrj/src/java/org/apache/solr/client/solrj/util/ClientUtils.java 
b/solr/solrj/src/java/org/apache/solr/client/solrj/util/ClientUtils.java
index d0cc138a8ad..568bd7e5a77 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/util/ClientUtils.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/util/ClientUtils.java
@@ -20,7 +20,7 @@ import java.io.IOException;
 import java.io.StringWriter;
 import java.io.Writer;
 import java.net.MalformedURLException;
-import java.net.URL;
+import java.net.URI;
 import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
@@ -103,9 +103,9 @@ public class ClientUtils {
   }
 
   private static String changeV2RequestEndpoint(String basePath) throws 
MalformedURLException {
-    URL oldURL = new URL(basePath);
-    String newPath = oldURL.getPath().replaceFirst("/solr", "/api");
-    return new URL(oldURL.getProtocol(), oldURL.getHost(), oldURL.getPort(), 
newPath).toString();
+    URI oldURI = URI.create(basePath);
+    String newPath = oldURI.getPath().replaceFirst("/solr", "/api");
+    return oldURI.resolve(newPath).toString();
   }
 
   // ------------------------------------------------------------------------
diff --git 
a/solr/solrj/src/test/org/apache/solr/client/solrj/TestSolrJErrorHandling.java 
b/solr/solrj/src/test/org/apache/solr/client/solrj/TestSolrJErrorHandling.java
index 0941775980d..68ba3e42606 100644
--- 
a/solr/solrj/src/test/org/apache/solr/client/solrj/TestSolrJErrorHandling.java
+++ 
b/solr/solrj/src/test/org/apache/solr/client/solrj/TestSolrJErrorHandling.java
@@ -24,6 +24,7 @@ import java.io.OutputStreamWriter;
 import java.lang.invoke.MethodHandles;
 import java.net.HttpURLConnection;
 import java.net.Socket;
+import java.net.URI;
 import java.net.URL;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
@@ -280,7 +281,7 @@ public class TestSolrJErrorHandling extends 
SolrJettyTestBase {
     String urlString = getCoreUrl() + "/update";
 
     HttpURLConnection conn = null;
-    URL url = new URL(urlString);
+    URL url = URI.create(urlString).toURL();
 
     conn = (HttpURLConnection) url.openConnection();
     conn.setRequestMethod("POST");
diff --git 
a/solr/solrj/src/test/org/apache/solr/client/solrj/embedded/JettyWebappTest.java
 
b/solr/solrj/src/test/org/apache/solr/client/solrj/embedded/JettyWebappTest.java
index 61968db2e4d..024b79b5c1d 100644
--- 
a/solr/solrj/src/test/org/apache/solr/client/solrj/embedded/JettyWebappTest.java
+++ 
b/solr/solrj/src/test/org/apache/solr/client/solrj/embedded/JettyWebappTest.java
@@ -18,7 +18,7 @@ package org.apache.solr.client.solrj.embedded;
 
 import java.io.File;
 import java.io.InputStream;
-import java.net.URL;
+import java.net.URI;
 import java.util.Locale;
 import java.util.Random;
 import org.apache.http.Header;
@@ -89,7 +89,7 @@ public class JettyWebappTest extends SolrTestCaseJ4 {
   public void testAdminUI() throws Exception {
     // Not an extensive test, but it does connect to Solr and verify the Admin 
ui shows up.
     String adminPath = "http://127.0.0.1:"; + port + "/solr/";
-    try (InputStream is = new URL(adminPath).openStream()) {
+    try (InputStream is = URI.create(adminPath).toURL().openStream()) {
       assertNotNull(is.readAllBytes()); // real error will be an exception
     }
 
diff --git 
a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudHttp2SolrClientTest.java
 
b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudHttp2SolrClientTest.java
index 0b82d36a31d..474ebb8a177 100644
--- 
a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudHttp2SolrClientTest.java
+++ 
b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudHttp2SolrClientTest.java
@@ -20,7 +20,7 @@ import static 
org.apache.solr.client.solrj.impl.CloudSolrClient.RouteResponse;
 
 import java.io.IOException;
 import java.lang.invoke.MethodHandles;
-import java.net.URL;
+import java.net.URI;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -499,8 +499,8 @@ public class CloudHttp2SolrClientTest extends 
SolrCloudTestCase {
     // Make sure the distributed queries were directed to a single node only
     Set<Integer> ports = new HashSet<Integer>();
     for (String shardAddr : shardAddresses) {
-      URL url = new URL(shardAddr);
-      ports.add(url.getPort());
+      URI uri = URI.create(shardAddr);
+      ports.add(uri.getPort());
     }
 
     // This assertion would hold true as long as every shard has a core on 
each node
diff --git 
a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrClientTest.java
 
b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrClientTest.java
index f0246b53fc8..e40e126254c 100644
--- 
a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrClientTest.java
+++ 
b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrClientTest.java
@@ -20,7 +20,7 @@ import static 
org.apache.solr.client.solrj.SolrRequest.METHOD.POST;
 
 import java.io.IOException;
 import java.lang.invoke.MethodHandles;
-import java.net.URL;
+import java.net.URI;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -491,8 +491,8 @@ public class CloudSolrClientTest extends SolrCloudTestCase {
     // Make sure the distributed queries were directed to a single node only
     Set<Integer> ports = new HashSet<Integer>();
     for (String shardAddr : shardAddresses) {
-      URL url = new URL(shardAddr);
-      ports.add(url.getPort());
+      URI uri = URI.create(shardAddr);
+      ports.add(uri.getPort());
     }
 
     // This assertion would hold true as long as every shard has a core on 
each node
diff --git 
a/solr/solrj/src/test/org/apache/solr/common/util/ContentStreamTest.java 
b/solr/solrj/src/test/org/apache/solr/common/util/ContentStreamTest.java
index fdb5f4176c9..cc4fd1b156c 100644
--- a/solr/solrj/src/test/org/apache/solr/common/util/ContentStreamTest.java
+++ b/solr/solrj/src/test/org/apache/solr/common/util/ContentStreamTest.java
@@ -23,7 +23,6 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.Reader;
-import java.net.URL;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Paths;
 import java.util.zip.GZIPInputStream;
@@ -101,8 +100,7 @@ public class ContentStreamTest extends SolrTestCaseJ4 {
       is.transferTo(os);
     }
 
-    ContentStreamBase stream =
-        new ContentStreamBase.URLStream(new URL(file.toURI().toASCIIString()));
+    ContentStreamBase stream = new 
ContentStreamBase.URLStream(file.toURI().toURL());
 
     try (InputStream s = stream.getStream();
         FileInputStream fis = new FileInputStream(file);
@@ -133,8 +131,7 @@ public class ContentStreamTest extends SolrTestCaseJ4 {
       is.transferTo(zos);
     }
 
-    ContentStreamBase stream =
-        new ContentStreamBase.URLStream(new URL(file.toURI().toASCIIString()));
+    ContentStreamBase stream = new 
ContentStreamBase.URLStream(file.toURI().toURL());
     try (InputStream s = stream.getStream();
         FileInputStream fis = new FileInputStream(file);
         GZIPInputStream zis = new GZIPInputStream(fis);
@@ -160,8 +157,7 @@ public class ContentStreamTest extends SolrTestCaseJ4 {
       is.transferTo(zos);
     }
 
-    ContentStreamBase stream =
-        new ContentStreamBase.URLStream(new URL(file.toURI().toASCIIString()));
+    ContentStreamBase stream = new 
ContentStreamBase.URLStream(file.toURI().toURL());
     try (InputStream s = stream.getStream();
         FileInputStream fis = new FileInputStream(file);
         GZIPInputStream zis = new GZIPInputStream(fis);
@@ -187,8 +183,7 @@ public class ContentStreamTest extends SolrTestCaseJ4 {
       is.transferTo(zos);
     }
 
-    ContentStreamBase stream =
-        new ContentStreamBase.URLStream(new URL(file.toURI().toASCIIString()));
+    ContentStreamBase stream = new 
ContentStreamBase.URLStream(file.toURI().toURL());
     try (InputStream s = stream.getStream();
         FileInputStream fis = new FileInputStream(file);
         GZIPInputStream zis = new GZIPInputStream(fis);
diff --git 
a/solr/test-framework/src/java/org/apache/solr/embedded/JettySolrRunner.java 
b/solr/test-framework/src/java/org/apache/solr/embedded/JettySolrRunner.java
index 31bc572bf14..9c033827241 100644
--- a/solr/test-framework/src/java/org/apache/solr/embedded/JettySolrRunner.java
+++ b/solr/test-framework/src/java/org/apache/solr/embedded/JettySolrRunner.java
@@ -26,6 +26,8 @@ import java.io.PrintStream;
 import java.lang.invoke.MethodHandles;
 import java.net.BindException;
 import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
 import java.net.URL;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
@@ -782,7 +784,9 @@ public class JettySolrRunner {
   /** Returns a base URL like {@code http://localhost:8983/solr} */
   public URL getBaseUrl() {
     try {
-      return new URL(protocol, host, jettyPort, "/solr");
+      return new URI(protocol, null, host, jettyPort, "/solr", null, 
null).toURL();
+    } catch (URISyntaxException e) {
+      throw new RuntimeException(e);
     } catch (MalformedURLException e) {
       throw new RuntimeException(e);
     }
@@ -790,9 +794,11 @@ public class JettySolrRunner {
 
   public URL getBaseURLV2() {
     try {
-      return new URL(protocol, host, jettyPort, "/api");
+      return new URI(protocol, null, host, jettyPort, "/api", null, 
null).toURL();
     } catch (MalformedURLException e) {
       throw new RuntimeException(e);
+    } catch (URISyntaxException e) {
+      throw new RuntimeException(e);
     }
   }
 
@@ -802,9 +808,11 @@ public class JettySolrRunner {
    */
   public URL getProxyBaseUrl() {
     try {
-      return new URL(protocol, host, getLocalPort(), "/solr");
+      return new URI(protocol, null, host, getLocalPort(), "/solr", null, 
null).toURL();
     } catch (MalformedURLException e) {
       throw new RuntimeException(e);
+    } catch (URISyntaxException e) {
+      throw new RuntimeException(e);
     }
   }
 
diff --git 
a/solr/test-framework/src/java/org/apache/solr/handler/BackupRestoreUtils.java 
b/solr/test-framework/src/java/org/apache/solr/handler/BackupRestoreUtils.java
index 10456e4984e..200709ef9a2 100644
--- 
a/solr/test-framework/src/java/org/apache/solr/handler/BackupRestoreUtils.java
+++ 
b/solr/test-framework/src/java/org/apache/solr/handler/BackupRestoreUtils.java
@@ -20,6 +20,7 @@ package org.apache.solr.handler;
 import java.io.IOException;
 import java.io.InputStream;
 import java.lang.invoke.MethodHandles;
+import java.net.URI;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.List;
@@ -109,7 +110,7 @@ public class BackupRestoreUtils extends SolrTestCase {
   }
 
   static void executeHttpRequest(String requestUrl) throws IOException {
-    URL url = new URL(requestUrl);
+    URL url = URI.create(requestUrl).toURL();
     try (InputStream stream = url.openStream()) {
       assert stream != null;
     }
diff --git 
a/solr/test-framework/src/java/org/apache/solr/handler/TestRestoreCoreUtil.java 
b/solr/test-framework/src/java/org/apache/solr/handler/TestRestoreCoreUtil.java
index de275b8ec94..cd52cf2e68b 100644
--- 
a/solr/test-framework/src/java/org/apache/solr/handler/TestRestoreCoreUtil.java
+++ 
b/solr/test-framework/src/java/org/apache/solr/handler/TestRestoreCoreUtil.java
@@ -18,6 +18,7 @@ package org.apache.solr.handler;
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.net.URI;
 import java.net.URL;
 import java.nio.charset.StandardCharsets;
 import java.util.regex.Matcher;
@@ -35,7 +36,7 @@ public class TestRestoreCoreUtil {
             + ReplicationHandler.CMD_RESTORE_STATUS;
     final Pattern pException = Pattern.compile("<str 
name=\"exception\">(.*?)</str>");
 
-    URL url = new URL(leaderUrl);
+    URL url = URI.create(leaderUrl).toURL();
     try (InputStream stream = url.openStream()) {
       String response = new String(stream.readAllBytes(), 
StandardCharsets.UTF_8);
       Matcher matcher = pException.matcher(response);

Reply via email to