jdk/test/sun/net/www/protocol/jar/MultiReleaseJarURLConnection.java
changeset 37785 daf6dcc73e9d
parent 36236 eec5770c5b01
child 38432 892603099bb0
equal deleted inserted replaced
37784:d1c957a6806f 37785:daf6dcc73e9d
    24 /*
    24 /*
    25  * @test
    25  * @test
    26  * @bug 8132734
    26  * @bug 8132734
    27  * @summary Test that URL connections to multi-release jars can be runtime versioned
    27  * @summary Test that URL connections to multi-release jars can be runtime versioned
    28  * @library /lib/testlibrary/java/util/jar
    28  * @library /lib/testlibrary/java/util/jar
    29  * @build Compiler JarBuilder CreateMultiReleaseTestJars
    29  * @build Compiler JarBuilder CreateMultiReleaseTestJars SimpleHttpServer
    30  * @run testng MultiReleaseJarURLConnection
    30  * @run testng MultiReleaseJarURLConnection
    31  */
    31  */
    32 
    32 
    33 import java.io.IOException;
    33 import java.io.IOException;
    34 import java.io.InputStream;
    34 import java.io.InputStream;
       
    35 import java.lang.invoke.MethodHandle;
       
    36 import java.lang.invoke.MethodHandles;
       
    37 import java.lang.invoke.MethodType;
    35 import java.net.JarURLConnection;
    38 import java.net.JarURLConnection;
    36 import java.net.URL;
    39 import java.net.URL;
       
    40 import java.net.URLClassLoader;
    37 import java.net.URLConnection;
    41 import java.net.URLConnection;
    38 import java.nio.file.Files;
    42 import java.nio.file.Files;
    39 import java.nio.file.Paths;
    43 import java.nio.file.Paths;
    40 import java.util.jar.JarFile;
    44 import java.util.jar.JarFile;
       
    45 
       
    46 import jdk.Version;
    41 
    47 
    42 import org.testng.Assert;
    48 import org.testng.Assert;
    43 import org.testng.annotations.AfterClass;
    49 import org.testng.annotations.AfterClass;
    44 import org.testng.annotations.BeforeClass;
    50 import org.testng.annotations.BeforeClass;
    45 import org.testng.annotations.DataProvider;
    51 import org.testng.annotations.DataProvider;
    46 import org.testng.annotations.Test;
    52 import org.testng.annotations.Test;
    47 
    53 
    48 public class MultiReleaseJarURLConnection {
    54 public class MultiReleaseJarURLConnection {
    49     String userdir = System.getProperty("user.dir",".");
    55     String userdir = System.getProperty("user.dir",".");
    50     String file = userdir + "/signed-multi-release.jar";
    56     String unversioned = userdir + "/unversioned.jar";
       
    57     String unsigned = userdir + "/multi-release.jar";
       
    58     String signed = userdir + "/signed-multi-release.jar";
       
    59     SimpleHttpServer server;
    51 
    60 
    52     @BeforeClass
    61     @BeforeClass
    53     public void initialize() throws Exception {
    62     public void initialize() throws Exception {
    54         CreateMultiReleaseTestJars creator = new CreateMultiReleaseTestJars();
    63         CreateMultiReleaseTestJars creator = new CreateMultiReleaseTestJars();
    55         creator.compileEntries();
    64         creator.compileEntries();
       
    65         creator.buildUnversionedJar();
    56         creator.buildMultiReleaseJar();
    66         creator.buildMultiReleaseJar();
    57         creator.buildSignedMultiReleaseJar();
    67         creator.buildSignedMultiReleaseJar();
       
    68 
       
    69         server = new SimpleHttpServer();
       
    70         server.start();
       
    71 
    58     }
    72     }
    59 
    73 
    60     @AfterClass
    74     @AfterClass
    61     public void close() throws IOException {
    75     public void close() throws IOException {
    62         Files.delete(Paths.get(userdir, "multi-release.jar"));
    76         // Windows requires server to stop before file is deleted
    63         Files.delete(Paths.get(userdir, "signed-multi-release.jar"));
    77         if (server != null)
       
    78             server.stop();
       
    79         Files.delete(Paths.get(unversioned));
       
    80         Files.delete(Paths.get(unsigned));
       
    81         Files.delete(Paths.get(signed));
    64     }
    82     }
    65 
    83 
    66     @DataProvider(name = "data")
    84     @DataProvider(name = "data")
    67     public Object[][] createData() {
    85     public Object[][] createData() {
    68         return new Object[][]{
    86         return new Object[][]{
    69                 {"unsigned file", userdir + "/multi-release.jar"},
    87                 {"unversioned", unversioned},
    70                 {"signed file", userdir + "/signed-multi-release.jar"},
    88                 {"unsigned", unsigned},
       
    89                 {"signed", signed}
    71         };
    90         };
    72     }
    91     }
    73 
    92 
    74     @Test(dataProvider = "data")
    93     @Test(dataProvider = "data")
    75     public void testRuntimeVersioning(String ignore, String file) throws Exception {
    94     public void testRuntimeVersioning(String style, String file) throws Exception {
    76         String urlFile = "jar:file:" + file + "!/";
    95         String urlFile = "jar:file:" + file + "!/";
    77         String urlEntry = urlFile + "version/Version.java";
    96         String baseUrlEntry = urlFile + "version/Version.java";
    78 
    97         String rtreturn = "return " + Version.current().major();
    79         Assert.assertTrue(readAndCompare(new URL(urlEntry), "return 8"));
    98 
    80         // #runtime is "magic"
    99         Assert.assertTrue(readAndCompare(new URL(baseUrlEntry), "return 8"));
    81         Assert.assertTrue(readAndCompare(new URL(urlEntry + "#runtime"), "return 9"));
   100         // #runtime is "magic" for a multi-release jar, but not for unversioned jar
       
   101         Assert.assertTrue(readAndCompare(new URL(baseUrlEntry + "#runtime"),
       
   102                 style.equals("unversioned") ? "return 8" : rtreturn));
    82         // #fragment or any other fragment is not magic
   103         // #fragment or any other fragment is not magic
    83         Assert.assertTrue(readAndCompare(new URL(urlEntry + "#fragment"), "return 8"));
   104         Assert.assertTrue(readAndCompare(new URL(baseUrlEntry + "#fragment"), "return 8"));
    84         // cached entities not affected
   105         // cached entities not affected
    85         Assert.assertTrue(readAndCompare(new URL(urlEntry), "return 8"));
   106         Assert.assertTrue(readAndCompare(new URL(baseUrlEntry), "return 8"));
       
   107 
       
   108         // the following tests will not work with unversioned jars
       
   109         if (style.equals("unversioned")) return;
       
   110 
       
   111         // direct access to versioned entry
       
   112         String versUrlEntry = urlFile + "META-INF/versions/" + Version.current().major()
       
   113                 + "/version/Version.java";
       
   114         Assert.assertTrue(readAndCompare(new URL(versUrlEntry), rtreturn));
       
   115         // adding any fragment does not change things
       
   116         Assert.assertTrue(readAndCompare(new URL(versUrlEntry + "#runtime"), rtreturn));
       
   117         Assert.assertTrue(readAndCompare(new URL(versUrlEntry + "#fragment"), rtreturn));
       
   118 
       
   119         // it really doesn't change things
       
   120         versUrlEntry = urlFile + "META-INF/versions/10/version/Version.java";
       
   121         Assert.assertTrue(readAndCompare(new URL(versUrlEntry), "return 10"));
       
   122         Assert.assertTrue(readAndCompare(new URL(versUrlEntry + "#runtime"), "return 10"));
       
   123         Assert.assertTrue(readAndCompare(new URL(versUrlEntry + "#fragment"), "return 10"));
    86     }
   124     }
    87 
   125 
    88     @Test(dataProvider = "data")
   126     @Test(dataProvider = "data")
    89     public void testCachedJars(String ignore, String file) throws Exception {
   127     public void testCachedJars(String style, String file) throws Exception {
    90         String urlFile = "jar:file:" + file + "!/";
   128         String urlFile = "jar:file:" + file + "!/";
    91 
   129 
    92         URL rootUrl = new URL(urlFile);
   130         URL rootUrl = new URL(urlFile);
    93         JarURLConnection juc = (JarURLConnection)rootUrl.openConnection();
   131         JarURLConnection juc = (JarURLConnection)rootUrl.openConnection();
    94         JarFile rootJar = juc.getJarFile();
   132         JarFile rootJar = juc.getJarFile();
    96 
   134 
    97         URL runtimeUrl = new URL(urlFile + "#runtime");
   135         URL runtimeUrl = new URL(urlFile + "#runtime");
    98         juc = (JarURLConnection)runtimeUrl.openConnection();
   136         juc = (JarURLConnection)runtimeUrl.openConnection();
    99         JarFile runtimeJar = juc.getJarFile();
   137         JarFile runtimeJar = juc.getJarFile();
   100         JarFile.Release runtime = runtimeJar.getVersion();
   138         JarFile.Release runtime = runtimeJar.getVersion();
   101         Assert.assertNotEquals(root, runtime);
   139         if (style.equals("unversioned")) {
       
   140             Assert.assertEquals(root, runtime);
       
   141         } else {
       
   142             Assert.assertNotEquals(root, runtime);
       
   143         }
   102 
   144 
   103         juc = (JarURLConnection)rootUrl.openConnection();
   145         juc = (JarURLConnection)rootUrl.openConnection();
   104         JarFile jar = juc.getJarFile();
   146         JarFile jar = juc.getJarFile();
   105         Assert.assertEquals(jar.getVersion(), root);
   147         Assert.assertEquals(jar.getVersion(), root);
   106         Assert.assertEquals(jar, rootJar);
   148         Assert.assertEquals(jar, rootJar);
   112 
   154 
   113         rootJar.close();
   155         rootJar.close();
   114         runtimeJar.close();
   156         runtimeJar.close();
   115         jar.close(); // probably not needed
   157         jar.close(); // probably not needed
   116     }
   158     }
       
   159 
       
   160     @DataProvider(name = "resourcedata")
       
   161     public Object[][] createResourceData() throws Exception {
       
   162         return new Object[][]{
       
   163                 {"unversioned", Paths.get(unversioned).toUri().toURL()},
       
   164                 {"unsigned", Paths.get(unsigned).toUri().toURL()},
       
   165                 {"signed", Paths.get(signed).toUri().toURL()},
       
   166                 {"unversioned", new URL("file:" + unversioned)},
       
   167                 {"unsigned", new URL("file:" + unsigned)},
       
   168                 {"signed", new URL("file:" + signed)},
       
   169                 {"unversioned", new URL("jar:file:" + unversioned + "!/")},
       
   170                 {"unsigned", new URL("jar:file:" + unsigned + "!/")},
       
   171                 {"signed", new URL("jar:file:" + signed + "!/")},
       
   172                 // external jar received via http protocol
       
   173                 {"http", new URL("jar:http://localhost:" + server.getPort() + "/multi-release.jar!/")},
       
   174                 {"http", new URL("http://localhost:" + server.getPort() + "/multi-release.jar")},
       
   175 
       
   176         };
       
   177     }
       
   178 
       
   179     @Test(dataProvider = "resourcedata")
       
   180     public void testResources(String style, URL url) throws Throwable {
       
   181         //System.out.println("  testing " + style + " url: " + url);
       
   182         URL[] urls = {url};
       
   183         URLClassLoader cldr = new URLClassLoader(urls);
       
   184         Class<?> vcls = cldr.loadClass("version.Version");
       
   185 
       
   186         // verify we are loading a runtime versioned class
       
   187         MethodType mt = MethodType.methodType(int.class);
       
   188         MethodHandle mh = MethodHandles.lookup().findVirtual(vcls, "getVersion", mt);
       
   189         Assert.assertEquals((int)mh.invoke(vcls.newInstance()),
       
   190                 style.equals("unversioned") ? 8 : Version.current().major());
       
   191 
       
   192         // now get a resource and verify that we don't have a fragment attached
       
   193         URL vclsUrl = vcls.getResource("/version/Version.class");
       
   194         String fragment = vclsUrl.getRef();
       
   195         Assert.assertNull(fragment);
       
   196 
       
   197         // and verify that the the url is a reified pointer to the runtime entry
       
   198         String rep = vclsUrl.toString();
       
   199         //System.out.println("    getResource(\"/version/Version.class\") returned: " + rep);
       
   200         if (style.equals("http")) {
       
   201             Assert.assertTrue(rep.startsWith("jar:http:"));
       
   202         } else {
       
   203             Assert.assertTrue(rep.startsWith("jar:file:"));
       
   204         }
       
   205         String suffix;
       
   206         if (style.equals("unversioned")) {
       
   207             suffix = ".jar!/version/Version.class";
       
   208         } else {
       
   209             suffix = ".jar!/META-INF/versions/" + Version.current().major()
       
   210                     + "/version/Version.class";
       
   211         }
       
   212         Assert.assertTrue(rep.endsWith(suffix));
       
   213         cldr.close();
       
   214     }
       
   215 
   117 
   216 
   118     private boolean readAndCompare(URL url, String match) throws Exception {
   217     private boolean readAndCompare(URL url, String match) throws Exception {
   119         boolean result;
   218         boolean result;
   120         // necessary to do it this way, instead of openStream(), so we can
   219         // necessary to do it this way, instead of openStream(), so we can
   121         // close underlying JarFile, otherwise windows can't delete the file
   220         // close underlying JarFile, otherwise windows can't delete the file