11/*
2- * Copyright (c) 2002, 2022 , Oracle and/or its affiliates. All rights reserved.
2+ * Copyright (c) 2002, 2025 , Oracle and/or its affiliates. All rights reserved.
33 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44 *
55 * This code is free software; you can redistribute it and/or modify it
2525 * @test
2626 * @bug 8190312
2727 * @summary test redirected URLs for -link
28- * @library /tools/lib ../../lib
29- * @library /test/lib
28+ * @library /tools/lib ../../lib /test/lib
3029 * @modules jdk.compiler/com.sun.tools.javac.api
3130 * jdk.compiler/com.sun.tools.javac.main
3231 * jdk.javadoc/jdk.javadoc.internal.api
3332 * jdk.javadoc/jdk.javadoc.internal.tool
3433 * @build toolbox.ToolBox toolbox.JavacTask javadoc.tester.*
3534 * @build jtreg.SkippedException
36- * @build jdk.test.lib.Platform
35+ * @build jdk.test.lib.Platform jdk.test.lib.net.SimpleSSLContext jdk.test.lib.net.URIBuilder
3736 * @run main TestRedirectLinks
3837 */
3938
4039import java .io .File ;
4140import java .io .IOException ;
42- import java .io .InputStream ;
4341import java .io .OutputStream ;
4442import java .net .HttpURLConnection ;
4543import java .net .InetAddress ;
4644import java .net .InetSocketAddress ;
45+ import java .net .URISyntaxException ;
4746import java .net .URL ;
4847import java .net .URLConnection ;
4948import java .net .UnknownHostException ;
5049import java .nio .file .Files ;
5150import java .nio .file .Path ;
52- import java .security .KeyStore ;
5351import java .time .Duration ;
5452import java .time .Instant ;
5553
5654import javax .net .ssl .HostnameVerifier ;
5755import javax .net .ssl .HttpsURLConnection ;
58- import javax .net .ssl .KeyManagerFactory ;
5956import javax .net .ssl .SSLContext ;
6057import javax .net .ssl .SSLSocketFactory ;
61- import javax .net .ssl .TrustManagerFactory ;
6258
6359import com .sun .net .httpserver .HttpExchange ;
6460import com .sun .net .httpserver .HttpServer ;
6561import com .sun .net .httpserver .HttpsConfigurator ;
6662import com .sun .net .httpserver .HttpsServer ;
6763
6864import javadoc .tester .JavadocTester ;
65+ import jdk .test .lib .net .SimpleSSLContext ;
66+ import jdk .test .lib .net .URIBuilder ;
6967import toolbox .JavacTask ;
7068import toolbox .ToolBox ;
7169
7270import jdk .test .lib .Platform ;
7371import jtreg .SkippedException ;
7472
7573public class TestRedirectLinks extends JavadocTester {
74+ // represents the HTTP response body length when the response contains no body
75+ private static final int NO_RESPONSE_BODY = -1 ;
76+
7677 /**
7778 * The entry point of the test.
7879 * @param args the array of command line arguments.
@@ -206,17 +207,28 @@ public void testWithServers() throws Exception {
206207
207208 // start web servers
208209 // use loopback address to avoid any issues if proxy is in use
209- InetAddress localHost = InetAddress .getLoopbackAddress ();
210+ InetAddress loopback = InetAddress .getLoopbackAddress ();
210211 try {
211- oldServer = HttpServer .create (new InetSocketAddress (localHost , 0 ), 0 );
212- String oldURL = "http:/" + oldServer .getAddress ();
212+ oldServer = HttpServer .create (new InetSocketAddress (loopback , 0 ), 0 );
213+ String oldURL = URIBuilder .newBuilder ()
214+ .scheme ("http" )
215+ .loopback ()
216+ .port (oldServer .getAddress ().getPort ())
217+ .build ().toString ();
213218 oldServer .createContext ("/" , this ::handleOldRequest );
214219 out .println ("Starting old server (" + oldServer .getClass ().getSimpleName () + ") on " + oldURL );
215220 oldServer .start ();
216221
217222 SSLContext sslContext = new SimpleSSLContext ().get ();
218- newServer = HttpsServer .create (new InetSocketAddress (localHost , 0 ), 0 );
219- String newURL = "https:/" + newServer .getAddress ();
223+ if (sslContext == null ) {
224+ throw new AssertionError ("Could not create a SSLContext" );
225+ }
226+ newServer = HttpsServer .create (new InetSocketAddress (loopback , 0 ), 0 );
227+ String newURL = URIBuilder .newBuilder ()
228+ .scheme ("https" )
229+ .loopback ()
230+ .port (newServer .getAddress ().getPort ())
231+ .build ().toString ();
220232 newServer .setHttpsConfigurator (new HttpsConfigurator (sslContext ));
221233 newServer .createContext ("/" , this ::handleNewRequest );
222234 out .println ("Starting new server (" + newServer .getClass ().getSimpleName () + ") on " + newURL );
@@ -240,7 +252,7 @@ public void testWithServers() throws Exception {
240252 javadoc ("-d" , "api" ,
241253 "--module-source-path" , src .toString (),
242254 "--module-path" , libModules .toString (),
243- "-link" , "http:/" + oldServer . getAddress () ,
255+ "-link" , oldURL ,
244256 "--module" , "mC" ,
245257 "-Xdoclint:none" );
246258
@@ -281,10 +293,19 @@ private void handleOldRequest(HttpExchange x) throws IOException {
281293 + x .getRequestMethod () + " "
282294 + x .getRequestURI ());
283295 String newProtocol = (newServer instanceof HttpsServer ) ? "https" : "http" ;
284- String redirectTo = newProtocol + ":/" + newServer .getAddress () + x .getRequestURI ();
296+ String redirectTo ;
297+ try {
298+ redirectTo = URIBuilder .newBuilder ().scheme (newProtocol )
299+ .host (newServer .getAddress ().getAddress ())
300+ .port (newServer .getAddress ().getPort ())
301+ .path (x .getRequestURI ().getPath ())
302+ .build ().toString ();
303+ } catch (URISyntaxException e ) {
304+ throw new IOException (e );
305+ }
285306 out .println (" redirect to: " + redirectTo );
286307 x .getResponseHeaders ().add ("Location" , redirectTo );
287- x .sendResponseHeaders (HttpURLConnection .HTTP_MOVED_PERM , 0 );
308+ x .sendResponseHeaders (HttpURLConnection .HTTP_MOVED_PERM , NO_RESPONSE_BODY );
288309 x .getResponseBody ().close ();
289310 }
290311
@@ -305,64 +326,8 @@ private void handleNewRequest(HttpExchange x) throws IOException {
305326 responseStream .write (bytes );
306327 }
307328 } else {
308- x .sendResponseHeaders (HttpURLConnection .HTTP_NOT_FOUND , 0 );
329+ x .sendResponseHeaders (HttpURLConnection .HTTP_NOT_FOUND , NO_RESPONSE_BODY );
309330 x .getResponseBody ().close ();
310331 }
311332 }
312-
313- /**
314- * Creates a simple usable SSLContext for an HttpsServer using
315- * a default keystore in the test tree.
316- * <p>
317- * This class is based on
318- * test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/SimpleSSLContext.java
319- */
320- static class SimpleSSLContext {
321-
322- private final SSLContext ssl ;
323-
324- /**
325- * Loads default keystore.
326- */
327- SimpleSSLContext () throws Exception {
328- Path p = Path .of (System .getProperty ("test.src" , "." )).toAbsolutePath ();
329- while (!Files .exists (p .resolve ("TEST.ROOT" ))) {
330- p = p .getParent ();
331- if (p == null ) {
332- throw new IOException ("can't find TEST.ROOT" );
333- }
334- }
335-
336- System .err .println ("Test suite root: " + p );
337- Path testKeys = p .resolve ("../lib/jdk/test/lib/net/testkeys" ).normalize ();
338- if (!Files .exists (testKeys )) {
339- throw new IOException ("can't find testkeys" );
340- }
341- System .err .println ("Test keys: " + testKeys );
342-
343- try (InputStream fis = Files .newInputStream (testKeys )) {
344- ssl = init (fis );
345- }
346- }
347-
348- private SSLContext init (InputStream i ) throws Exception {
349- char [] passphrase = "passphrase" .toCharArray ();
350- KeyStore ks = KeyStore .getInstance ("PKCS12" );
351- ks .load (i , passphrase );
352-
353- KeyManagerFactory kmf = KeyManagerFactory .getInstance ("PKIX" );
354- kmf .init (ks , passphrase );
355-
356- TrustManagerFactory tmf = TrustManagerFactory .getInstance ("PKIX" );
357- tmf .init (ks );
358-
359- SSLContext ssl = SSLContext .getInstance ("TLS" );
360- ssl .init (kmf .getKeyManagers (), tmf .getTrustManagers (), null );
361- return ssl ;
362- }
363-
364- SSLContext get () {
365- return ssl ;
366- }
367- }
368333}
0 commit comments