From f09c156565b61129bedc501b2eb43db17a4273bb Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 27 Jul 2017 18:04:46 +0000 Subject: [PATCH 01/33] Added tag jdk-9+180 for changeset cf6820c6f184 --- .hgtags-top-repo | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags-top-repo b/.hgtags-top-repo index 7de83411416..07b5d344916 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -422,3 +422,4 @@ b25838a28195f4b6dab34668411eedd2d366a16c jdk-9+169 a4371edb589c60db01142e45c317adb9ccbcb083 jdk-9+177 ec4159ebe7050fcc5dcee8a2d150cf948ecc97db jdk-9+178 252475ccfd84cc249f8d6faf4b7806b5e2c384ce jdk-9+179 +d2982a786f53814367698e63efe6349c9128e1db jdk-9+180 From 0c004999da04d1d9a17fbf712dbd179a4d4d9a37 Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 27 Jul 2017 18:04:47 +0000 Subject: [PATCH 02/33] Added tag jdk-9+180 for changeset 52aba14d5a8e --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 3afcce0f7c6..3e06b395fe6 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -582,3 +582,4 @@ e64b1cb48d6e7703928a9d1da106fc27f8cb65fd jdk-9+173 1ca8f038fceb88c640badf9bd18905205bc63b43 jdk-9+177 9d032191f82fca5ba0aac98682f69c4ff0f1283d jdk-9+178 d2661aa42bff322badbe6c1337fc638d2e0f5730 jdk-9+179 +d7baadc223e790c08bc69bf7e553bce65b4e7e40 jdk-9+180 From c95f91e83bd856ca039969a829fa3069e7d0be74 Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 27 Jul 2017 18:04:47 +0000 Subject: [PATCH 03/33] Added tag jdk-9+180 for changeset 03207b7f16e6 --- corba/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/corba/.hgtags b/corba/.hgtags index c70104da520..688de6cbf1b 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -422,3 +422,4 @@ dc78a3dd6b3a4f11cdae8a3e3d160e6a78bc7838 jdk-9+175 c72e9d3823f04cb3ef3166646dfea9e4c2769133 jdk-9+177 9c1e9712648921ae389d623042d22561fad82d75 jdk-9+178 24390da83c5ee9e23ceafbcaff4460a01e37bb3a jdk-9+179 +6ce6cb8ff41c71c49f23b15e0f0468aca5d52b17 jdk-9+180 From 9b84cfb7f6f599a39da22268c1ba0cd3ee4a90e0 Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 27 Jul 2017 18:04:48 +0000 Subject: [PATCH 04/33] Added tag jdk-9+180 for changeset c3e45a079573 --- jdk/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/.hgtags b/jdk/.hgtags index 9126335d0c5..df28072c0e4 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -422,3 +422,4 @@ e6c4f6ef717d104dba880e2dae538690c993b46f jdk-9+175 80acf577b7d0b886fb555c9916552844f6cc72af jdk-9+177 443025bee731eb2225371b92c1c74b519b7baf33 jdk-9+178 06df1ce4b9b887d05ce6a13f4def3547e434dd1a jdk-9+179 +4feab1acec6a9c3620a19ff379a65ab8618d0e2a jdk-9+180 From c27877713e1cb15212caff7a2cf2655331877088 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Thu, 3 Aug 2017 18:56:59 +0000 Subject: [PATCH 05/33] Added tag jdk-9+181 for changeset 35dc62e43188 --- jdk/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/.hgtags b/jdk/.hgtags index df28072c0e4..eca17387148 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -423,3 +423,4 @@ e6c4f6ef717d104dba880e2dae538690c993b46f jdk-9+175 443025bee731eb2225371b92c1c74b519b7baf33 jdk-9+178 06df1ce4b9b887d05ce6a13f4def3547e434dd1a jdk-9+179 4feab1acec6a9c3620a19ff379a65ab8618d0e2a jdk-9+180 +bd66ea2fdde3d60a73b5272263a7b8b0ca926a33 jdk-9+181 From 36378834a9ffa98066a4d7b6097e7adcdb8fc6b7 Mon Sep 17 00:00:00 2001 From: Daniel Fuchs Date: Tue, 8 Aug 2017 12:32:41 +0100 Subject: [PATCH 06/33] 8185852: HttpConnection should resolve addresses before SocketChannel.connect() is called HttpConnection checks whether the proxy address is resolved and if not attempts to resolve it before creating the underlying connection that connects to the proxy. Reviewed-by: chegar --- .../jdk/incubator/http/HttpConnection.java | 6 + jdk/test/java/net/httpclient/ProxyTest.java | 346 ++++++++++++++++++ 2 files changed, 352 insertions(+) create mode 100644 jdk/test/java/net/httpclient/ProxyTest.java diff --git a/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/HttpConnection.java b/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/HttpConnection.java index 96bd67f969e..a520390ba2d 100644 --- a/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/HttpConnection.java +++ b/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/HttpConnection.java @@ -154,6 +154,12 @@ abstract class HttpConnection implements Closeable { { HttpConnection c = null; InetSocketAddress proxy = request.proxy(client); + if (proxy != null && proxy.isUnresolved()) { + // The default proxy selector may select a proxy whose + // address is unresolved. We must resolve the address + // before using it to connect. + proxy = new InetSocketAddress(proxy.getHostString(), proxy.getPort()); + } boolean secure = request.secure(); ConnectionPool pool = client.connectionPool(); String[] alpn = null; diff --git a/jdk/test/java/net/httpclient/ProxyTest.java b/jdk/test/java/net/httpclient/ProxyTest.java new file mode 100644 index 00000000000..8dc90dfb1a1 --- /dev/null +++ b/jdk/test/java/net/httpclient/ProxyTest.java @@ -0,0 +1,346 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import com.sun.net.httpserver.HttpContext; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; +import com.sun.net.httpserver.HttpsConfigurator; +import com.sun.net.httpserver.HttpsParameters; +import com.sun.net.httpserver.HttpsServer; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.io.Writer; +import java.net.HttpURLConnection; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.net.ProxySelector; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.charset.StandardCharsets; +import java.security.NoSuchAlgorithmException; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSession; +import jdk.incubator.http.HttpClient; +import jdk.incubator.http.HttpRequest; +import jdk.incubator.http.HttpResponse; +import jdk.testlibrary.SimpleSSLContext; + +/** + * @test + * @bug 8185852 + * @summary verifies that passing a proxy with an unresolved address does + * not cause java.nio.channels.UnresolvedAddressException + * @modules jdk.incubator.httpclient + * @library /lib/testlibrary/ + * @build jdk.testlibrary.SimpleSSLContext ProxyTest + * @run main/othervm ProxyTest + * @author danielfuchs + */ +public class ProxyTest { + + static { + try { + HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() { + public boolean verify(String hostname, SSLSession session) { + return true; + } + }); + SSLContext.setDefault(new SimpleSSLContext().get()); + } catch (IOException ex) { + throw new ExceptionInInitializerError(ex); + } + } + + static final String RESPONSE = "

Hello World!"; + static final String PATH = "/foo/"; + + static HttpServer createHttpsServer() throws IOException, NoSuchAlgorithmException { + HttpsServer server = com.sun.net.httpserver.HttpsServer.create(); + HttpContext context = server.createContext(PATH); + context.setHandler(new HttpHandler() { + @Override + public void handle(HttpExchange he) throws IOException { + he.getResponseHeaders().add("encoding", "UTF-8"); + he.sendResponseHeaders(200, RESPONSE.length()); + he.getResponseBody().write(RESPONSE.getBytes(StandardCharsets.UTF_8)); + he.close(); + } + }); + + server.setHttpsConfigurator(new Configurator(SSLContext.getDefault())); + server.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0); + return server; + } + + public static void main(String[] args) + throws IOException, + URISyntaxException, + NoSuchAlgorithmException, + InterruptedException + { + HttpServer server = createHttpsServer(); + server.start(); + try { + test(server, HttpClient.Version.HTTP_1_1); + // test(server, HttpClient.Version.HTTP_2); + } finally { + server.stop(0); + System.out.println("Server stopped"); + } + } + + public static void test(HttpServer server, HttpClient.Version version) + throws IOException, + URISyntaxException, + NoSuchAlgorithmException, + InterruptedException + { + System.out.println("Server is: " + server.getAddress().toString()); + System.out.println("Verifying communication with server"); + URI uri = new URI("https:/" + server.getAddress().toString() + PATH + "x"); + try (InputStream is = uri.toURL().openConnection().getInputStream()) { + String resp = new String(is.readAllBytes(), StandardCharsets.UTF_8); + System.out.println(resp); + if (!RESPONSE.equals(resp)) { + throw new AssertionError("Unexpected response from server"); + } + } + System.out.println("Communication with server OK"); + + TunnelingProxy proxy = new TunnelingProxy(server); + proxy.start(); + try { + System.out.println("Proxy started"); + Proxy p = new Proxy(Proxy.Type.HTTP, + InetSocketAddress.createUnresolved("localhost", proxy.getAddress().getPort())); + System.out.println("Verifying communication with proxy"); + HttpURLConnection conn = (HttpURLConnection)uri.toURL().openConnection(p); + try (InputStream is = conn.getInputStream()) { + String resp = new String(is.readAllBytes(), StandardCharsets.UTF_8); + System.out.println(resp); + if (!RESPONSE.equals(resp)) { + throw new AssertionError("Unexpected response from proxy"); + } + } + System.out.println("Communication with proxy OK"); + System.out.println("\nReal test begins here."); + System.out.println("Setting up request with HttpClient for version: " + + version.name()); + ProxySelector ps = ProxySelector.of( + InetSocketAddress.createUnresolved("localhost", proxy.getAddress().getPort())); + HttpClient client = HttpClient.newBuilder() + .version(version) + .proxy(ps) + .build(); + HttpRequest request = HttpRequest.newBuilder() + .uri(uri) + .GET() + .build(); + + System.out.println("Sending request with HttpClient"); + HttpResponse response + = client.send(request, HttpResponse.BodyHandler.asString()); + System.out.println("Got response"); + String resp = response.body(); + System.out.println("Received: " + resp); + if (!RESPONSE.equals(resp)) { + throw new AssertionError("Unexpected response"); + } + } finally { + System.out.println("Stopping proxy"); + proxy.stop(); + System.out.println("Proxy stopped"); + } + } + + static class TunnelingProxy { + final Thread accept; + final ServerSocket ss; + final boolean DEBUG = false; + final HttpServer serverImpl; + TunnelingProxy(HttpServer serverImpl) throws IOException { + this.serverImpl = serverImpl; + ss = new ServerSocket(); + accept = new Thread(this::accept); + } + + void start() throws IOException { + ss.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); + accept.start(); + } + + // Pipe the input stream to the output stream. + private synchronized Thread pipe(InputStream is, OutputStream os, char tag) { + return new Thread("TunnelPipe("+tag+")") { + @Override + public void run() { + try { + try { + int c; + while ((c = is.read()) != -1) { + os.write(c); + os.flush(); + // if DEBUG prints a + or a - for each transferred + // character. + if (DEBUG) System.out.print(tag); + } + is.close(); + } finally { + os.close(); + } + } catch (IOException ex) { + if (DEBUG) ex.printStackTrace(System.out); + } + } + }; + } + + public InetSocketAddress getAddress() { + return new InetSocketAddress(ss.getInetAddress(), ss.getLocalPort()); + } + + // This is a bit shaky. It doesn't handle continuation + // lines, but our client shouldn't send any. + // Read a line from the input stream, swallowing the final + // \r\n sequence. Stops at the first \n, doesn't complain + // if it wasn't preceded by '\r'. + // + String readLine(InputStream r) throws IOException { + StringBuilder b = new StringBuilder(); + int c; + while ((c = r.read()) != -1) { + if (c == '\n') break; + b.appendCodePoint(c); + } + if (b.codePointAt(b.length() -1) == '\r') { + b.delete(b.length() -1, b.length()); + } + return b.toString(); + } + + public void accept() { + Socket clientConnection = null; + try { + while (true) { + System.out.println("Tunnel: Waiting for client"); + Socket previous = clientConnection; + try { + clientConnection = ss.accept(); + } catch (IOException io) { + if (DEBUG) io.printStackTrace(System.out); + break; + } finally { + // we have only 1 client at a time, so it is safe + // to close the previous connection here + if (previous != null) previous.close(); + } + System.out.println("Tunnel: Client accepted"); + Socket targetConnection = null; + InputStream ccis = clientConnection.getInputStream(); + OutputStream ccos = clientConnection.getOutputStream(); + Writer w = new OutputStreamWriter(ccos, "UTF-8"); + PrintWriter pw = new PrintWriter(w); + System.out.println("Tunnel: Reading request line"); + String requestLine = readLine(ccis); + System.out.println("Tunnel: Request status line: " + requestLine); + if (requestLine.startsWith("CONNECT ")) { + // We should probably check that the next word following + // CONNECT is the host:port of our HTTPS serverImpl. + // Some improvement for a followup! + + // Read all headers until we find the empty line that + // signals the end of all headers. + while(!requestLine.equals("")) { + System.out.println("Tunnel: Reading header: " + + (requestLine = readLine(ccis))); + } + + // Open target connection + targetConnection = new Socket( + serverImpl.getAddress().getAddress(), + serverImpl.getAddress().getPort()); + + // Then send the 200 OK response to the client + System.out.println("Tunnel: Sending " + + "HTTP/1.1 200 OK\r\n\r\n"); + pw.print("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n"); + pw.flush(); + } else { + // This should not happen. + throw new IOException("Tunnel: Unexpected status line: " + + requestLine); + } + + // Pipe the input stream of the client connection to the + // output stream of the target connection and conversely. + // Now the client and target will just talk to each other. + System.out.println("Tunnel: Starting tunnel pipes"); + Thread t1 = pipe(ccis, targetConnection.getOutputStream(), '+'); + Thread t2 = pipe(targetConnection.getInputStream(), ccos, '-'); + t1.start(); + t2.start(); + + // We have only 1 client... wait until it has finished before + // accepting a new connection request. + // System.out.println("Tunnel: Waiting for pipes to close"); + // t1.join(); + // t2.join(); + System.out.println("Tunnel: Done - waiting for next client"); + } + } catch (Throwable ex) { + try { + ss.close(); + } catch (IOException ex1) { + ex.addSuppressed(ex1); + } + ex.printStackTrace(System.err); + } + } + + void stop() throws IOException { + ss.close(); + } + + } + + static class Configurator extends HttpsConfigurator { + public Configurator(SSLContext ctx) { + super(ctx); + } + + @Override + public void configure (HttpsParameters params) { + params.setSSLParameters (getSSLContext().getSupportedSSLParameters()); + } + } + +} From 43ead07d44b05a199ed455cc83a36a8b1f33af27 Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Tue, 8 Aug 2017 21:37:38 +0800 Subject: [PATCH 07/33] 8185934: keytool shows "Signature algorithm: SHA1withECDSA, -1-bit key" Reviewed-by: mullan --- .../share/classes/sun/security/tools/keytool/Main.java | 10 ++++++++-- .../classes/sun/security/tools/keytool/Resources.java | 1 + .../classes/sun/security/tools/jarsigner/Main.java | 8 ++++++-- .../sun/security/tools/jarsigner/Resources.java | 1 + 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java b/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java index ec5e59c07fc..dac650b1451 100644 --- a/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java +++ b/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java @@ -3071,8 +3071,14 @@ public final class Main { private String withWeak(PublicKey key) { if (DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, key)) { - return String.format(rb.getString("key.bit"), - KeyUtil.getKeySize(key), key.getAlgorithm()); + int kLen = KeyUtil.getKeySize(key); + if (kLen >= 0) { + return String.format(rb.getString("key.bit"), + kLen, key.getAlgorithm()); + } else { + return String.format( + rb.getString("unknown.size.1"), key.getAlgorithm()); + } } else { return String.format(rb.getString("key.bit.weak"), KeyUtil.getKeySize(key), key.getAlgorithm()); diff --git a/jdk/src/java.base/share/classes/sun/security/tools/keytool/Resources.java b/jdk/src/java.base/share/classes/sun/security/tools/keytool/Resources.java index a78eb6bc3e6..9bdd95cbda0 100644 --- a/jdk/src/java.base/share/classes/sun/security/tools/keytool/Resources.java +++ b/jdk/src/java.base/share/classes/sun/security/tools/keytool/Resources.java @@ -462,6 +462,7 @@ public class Resources extends java.util.ListResourceBundle { {"with.weak", "%s (weak)"}, {"key.bit", "%d-bit %s key"}, {"key.bit.weak", "%d-bit %s key (weak)"}, + {"unknown.size.1", "unknown size %s key"}, {".PATTERN.printX509Cert.with.weak", "Owner: {0}\nIssuer: {1}\nSerial number: {2}\nValid from: {3} until: {4}\nCertificate fingerprints:\n\t SHA1: {5}\n\t SHA256: {6}\nSignature algorithm name: {7}\nSubject Public Key Algorithm: {8}\nVersion: {9}"}, {"PKCS.10.with.weak", diff --git a/jdk/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java b/jdk/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java index cb86682f7da..12d4e1ba380 100644 --- a/jdk/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java +++ b/jdk/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java @@ -1088,8 +1088,12 @@ public class Main { private String withWeak(PublicKey key) { if (DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, key)) { - return String.format( - rb.getString("key.bit"), KeyUtil.getKeySize(key)); + int kLen = KeyUtil.getKeySize(key); + if (kLen >= 0) { + return String.format(rb.getString("key.bit"), kLen); + } else { + return rb.getString("unknown.size"); + } } else { seeWeak = true; return String.format( diff --git a/jdk/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources.java b/jdk/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources.java index 26e0553ebb2..ebdd79d792e 100644 --- a/jdk/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources.java +++ b/jdk/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources.java @@ -164,6 +164,7 @@ public class Resources extends java.util.ListResourceBundle { {"with.weak", "%s (weak)"}, {"key.bit", "%d-bit key"}, {"key.bit.weak", "%d-bit key (weak)"}, + {"unknown.size", "unknown size"}, {"jarsigner.", "jarsigner: "}, {"signature.filename.must.consist.of.the.following.characters.A.Z.0.9.or.", From 74419eb34a83fe6502f0ba360b3d9821bfbe9e8e Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Tue, 8 Aug 2017 12:01:02 -0700 Subject: [PATCH 08/33] 8185867: fix a11y and html issues in jdk.jdi docs Reviewed-by: alanb --- .../com/sun/jdi/InvalidModuleException.java | 1 - .../classes/com/sun/jdi/JDIPermission.java | 14 +- .../share/classes/com/sun/jdi/Type.java | 109 +++++----- .../share/classes/com/sun/jdi/Value.java | 201 ++++++++++-------- .../com/sun/jdi/VirtualMachineManager.java | 17 +- .../com/sun/jdi/doc-files/signature.html | 38 ++-- 6 files changed, 207 insertions(+), 173 deletions(-) diff --git a/jdk/src/jdk.jdi/share/classes/com/sun/jdi/InvalidModuleException.java b/jdk/src/jdk.jdi/share/classes/com/sun/jdi/InvalidModuleException.java index 5351594c952..422a7cbfce8 100644 --- a/jdk/src/jdk.jdi/share/classes/com/sun/jdi/InvalidModuleException.java +++ b/jdk/src/jdk.jdi/share/classes/com/sun/jdi/InvalidModuleException.java @@ -28,7 +28,6 @@ package com.sun.jdi; /** * Thrown to indicate that the requested module is invalid * or became invalid after the module was unloaded. - *

* * @since 9 */ diff --git a/jdk/src/jdk.jdi/share/classes/com/sun/jdi/JDIPermission.java b/jdk/src/jdk.jdi/share/classes/com/sun/jdi/JDIPermission.java index 8f9b4da9980..2c80497d3f1 100644 --- a/jdk/src/jdk.jdi/share/classes/com/sun/jdi/JDIPermission.java +++ b/jdk/src/jdk.jdi/share/classes/com/sun/jdi/JDIPermission.java @@ -40,17 +40,20 @@ package com.sun.jdi; * permission allows, and discusses the risks of granting code the * permission. * - * + *
* + * * - * - * - * + * + * + * * + * * + * * - * + * * @@ -59,6 +62,7 @@ package com.sun.jdi; * misbehave. * * + * * *
Table shows permission target name, what the * permission allows, and associated risks
Permission Target NameWhat the Permission AllowsRisks of Allowing this PermissionPermission Target NameWhat the Permission AllowsRisks of Allowing this Permission
virtualMachineManagervirtualMachineManagerAbility to inspect and modify the JDI objects in the * {@code VirtualMachineManager} *
* diff --git a/jdk/src/jdk.jdi/share/classes/com/sun/jdi/Type.java b/jdk/src/jdk.jdi/share/classes/com/sun/jdi/Type.java index 50ad02747e8..0eb7eae3e0e 100644 --- a/jdk/src/jdk.jdi/share/classes/com/sun/jdi/Type.java +++ b/jdk/src/jdk.jdi/share/classes/com/sun/jdi/Type.java @@ -43,79 +43,86 @@ package com.sun.jdi; * {@link ArrayType#componentType()} * *

- * The following table illustrates which subinterfaces of Type + * The following tables illustrate which subinterfaces of Type * are used to mirror types in the target VM -- - * - * - * - * - * - * - * + *
Maps each type declared in target to a mirrored - * instance of a subinterface of PrimitiveType or ReferenceType"
Subinterfaces of {@link PrimitiveType}
Type declared in target asIs mirrored as an instance of
+ * + * * - * - * + * + * + * + * * - * - * + * + * * - * - * + * + * * - * - * + * + * * - * - * + * + * * - * - * + * + * * - * - * + * + * * - * - * + * + * * - * - * - * - * - * - * - * - * + * + * * - * - * - * + * + * + * + *
Subinterfaces of {@link PrimitiveType}
boolean {@link BooleanType}Type declared in target asIs mirrored as an instance of
byte{@link ByteType}boolean {@link BooleanType}
char{@link CharType}byte{@link ByteType}
double{@link DoubleType}char{@link CharType}
float{@link FloatType}double{@link DoubleType}
int{@link IntegerType}float{@link FloatType}
long{@link LongType}int{@link IntegerType}
short{@link ShortType}long{@link LongType}
void{@link VoidType}
Subinterfaces of {@link ReferenceType}
Type declared in target asFor exampleIs mirrored as an instance ofshort{@link ShortType}
a classDate{@link ClassType}void{@link VoidType}
+ * + * + * + * * - * - * - * + * + * + * + * + * * - * - * - * + * + * + * * - * - * - * + * + * + * + * + * + * + * + * + * + * * - * - * - * + * * - * - * - * + * + * *
Subinterfaces of {@link ReferenceType}
an interfaceRunnable{@link InterfaceType}Type declared in target asFor exampleIs mirrored as an instance of
an array {@link ArrayType}a classDate{@link ClassType}
an arrayint[]{@link ArrayType} whose + * an interfaceRunnable{@link InterfaceType}
an array(any){@link ArrayType}
int[]{@link ArrayType} whose * {@link ArrayType#componentType() componentType()} is * {@link IntegerType}
an arrayDate[]{@link ArrayType} whose + * + * Date[]{@link ArrayType} whose * {@link ArrayType#componentType() componentType()} is * {@link ClassType}
an arrayRunnable[]{@link ArrayType} whose + * + * Runnable[]{@link ArrayType} whose * {@link ArrayType#componentType() componentType()} is * {@link InterfaceType}
* * @see PrimitiveType Subinterface PrimitiveType diff --git a/jdk/src/jdk.jdi/share/classes/com/sun/jdi/Value.java b/jdk/src/jdk.jdi/share/classes/com/sun/jdi/Value.java index 99568fe60bc..42afbc2bfdf 100644 --- a/jdk/src/jdk.jdi/share/classes/com/sun/jdi/Value.java +++ b/jdk/src/jdk.jdi/share/classes/com/sun/jdi/Value.java @@ -33,7 +33,7 @@ import com.sun.jdi.event.ModificationWatchpointEvent; * value hierarchy encompassing primitive values and object values. *

* Some examples of where values may be accessed: - *

+ *
layout
* *
{@link ObjectReference#getValue(Field) * ObjectReference.getValue(Field)} @@ -52,117 +52,130 @@ import com.sun.jdi.event.ModificationWatchpointEvent; * - returned with an event *
*

- * The following table illustrates which subinterfaces of Value + * The following tables illustrate which subinterfaces of Value * are used to mirror values in the target VM -- - * - * - * - * - * - * - * - * - * + *
Maps each kind of value to a mirrored - * instance of a subinterface of Value
Subinterfaces of {@link PrimitiveValue}
Kind of valueFor example -
expression in target
Is mirrored as an
instance of
{@link Type} of value
{@link #type() Value.type()}
+ * + * * - * - * - * - * + * + * + * + * + * + * * - * - * - * - * + * + * + * + * * - * - * - * - * + * + * + * + * * - * - * - * - * + * + * + * + * * - * - * - * - * + * + * + * + * * - * - * - * - * + * + * + * + * * - * - * - * - * + * + * + * + * * - * - * - * - * + * + * + * + * * - * - * - * - * - * - * - * - * - * - * - * + * + * + * + * * - * - * - * - * + * + * + * + * + * + *
Subinterfaces of {@link PrimitiveValue}
a boolean {@code true} {@link BooleanValue} {@link BooleanType}Kind of valueFor example -
expression in target
Is mirrored as an
instance of
{@link Type} of value
{@link #type() Value.type()}
a byte {@code (byte)4} {@link ByteValue} {@link ByteType}a boolean{@code true}{@link BooleanValue}{@link BooleanType}
a char {@code 'a'} {@link CharValue} {@link CharType}a byte{@code (byte)4}{@link ByteValue}{@link ByteType}
a double {@code 3.1415926} {@link DoubleValue} {@link DoubleType}a char{@code 'a'}{@link CharValue}{@link CharType}
a float {@code 2.5f} {@link FloatValue} {@link FloatType}a double{@code 3.1415926}{@link DoubleValue}{@link DoubleType}
an int {@code 22} {@link IntegerValue} {@link IntegerType}a float{@code 2.5f}{@link FloatValue}{@link FloatType}
a long {@code 1024L} {@link LongValue} {@link LongType}an int{@code 22}{@link IntegerValue}{@link IntegerType}
a short {@code (short)12} {@link ShortValue} {@link ShortType}a long{@code 1024L}{@link LongValue}{@link LongType}
a void {@link VoidValue} {@link VoidType}
Subinterfaces of {@link ObjectReference}
Kind of valueFor example -
expression in target
Is mirrored as an
instance of
{@link Type} of value
{@link #type() Value.type()}
a short{@code (short)12}{@link ShortValue}{@link ShortType}
a class instance {@code this} {@link ObjectReference} {@link ClassType}a void{@link VoidValue}{@link VoidType}
+ * + * + * + * * - * - * - * - * + * + * + * + * + * + * * - * - * - * - * + * + * + * + * * - * - * - * - * + * + * + * + * * - * - * - * - * + * + * + * + * * - * - * - * - * + * + * + * + * * - * - * - * - * - * - * - * - * - * - * - * + * + * + * + * * - * - * - * - * + * + * + * + * + * + * + * + * + * + * + *
Subinterfaces of {@link ObjectReference}
an array {@code new int[5]} {@link ArrayReference} {@link ArrayType}Kind of valueFor example -
expression in target
Is mirrored as an
instance of
{@link Type} of value
{@link #type() Value.type()}
a string {@code "hello"} {@link StringReference} {@link ClassType}a class instance{@code this}{@link ObjectReference}{@link ClassType}
a thread {@code Thread.currentThread()} {@link ThreadReference} {@link ClassType}an array{@code new int[5]}{@link ArrayReference}{@link ArrayType}
a thread group {@code Thread.currentThread()}
  {@code .getThreadGroup()}
{@link ThreadGroupReference} {@link ClassType}a string{@code "hello"}{@link StringReference}{@link ClassType}
a {@code java.lang.Class}
instance
{@code this.getClass()} {@link ClassObjectReference} {@link ClassType}a thread{@code Thread.currentThread()}{@link ThreadReference}{@link ClassType}
a class loader {@code this.getClass()}
  {@code .getClassLoader()}
{@link ClassLoaderReference} {@link ClassType}
Other
Kind of valueFor example -
expression in target
Is mirrored as{@link Type} of valuea thread group{@code Thread.currentThread()}
  {@code .getThreadGroup()}
{@link ThreadGroupReference}{@link ClassType}
null {@code null} {@code null} n/aa {@code java.lang.Class}
instance
{@code this.getClass()}{@link ClassObjectReference}{@link ClassType}
a class loader{@code this.getClass()}
  {@code .getClassLoader()}
{@link ClassLoaderReference}{@link ClassType}
+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * *
Other values
Kind of valueFor example -
expression in target
Is mirrored as{@link Type} of value
null{@code null}{@code null}n/a
* * @author Robert Field diff --git a/jdk/src/jdk.jdi/share/classes/com/sun/jdi/VirtualMachineManager.java b/jdk/src/jdk.jdi/share/classes/com/sun/jdi/VirtualMachineManager.java index ae3c5ffd016..2431f6c02ed 100644 --- a/jdk/src/jdk.jdi/share/classes/com/sun/jdi/VirtualMachineManager.java +++ b/jdk/src/jdk.jdi/share/classes/com/sun/jdi/VirtualMachineManager.java @@ -59,13 +59,16 @@ import com.sun.jdi.event.VMStartEvent; * Some {@link Connector} implementations may require slightly * different handling than presented below. * - * + *
* + * * - * - * + * + * + * + * * - * + * * * * * - * + * * * * - * + * * * * - * + * * + *
Four scenarios for connecting a debugger to a virtual machine"
ScenarioDescriptionScenarioDescription
Debugger launches target VM (simplest, most-common scenario)Debugger launches target VM (simplest, most-common scenario)Debugger calls the {@link LaunchingConnector#launch(java.util.Map)} * method of the default connector, obtained with {@link #defaultConnector}. The @@ -86,7 +89,7 @@ import com.sun.jdi.event.VMStartEvent; *
Debugger attaches to previously-running VMDebugger attaches to previously-running VM *
    *
  • @@ -113,7 +116,7 @@ import com.sun.jdi.event.VMStartEvent; *
Target VM attaches to previously-running debuggerTarget VM attaches to previously-running debugger *
    *
  • @@ -146,7 +149,7 @@ import com.sun.jdi.event.VMStartEvent; *
Target VM launches debugger (sometimes called "Just-In-Time" debugging)Target VM launches debugger (sometimes called "Just-In-Time" debugging) *
    *
  • diff --git a/jdk/src/jdk.jdi/share/classes/com/sun/jdi/doc-files/signature.html b/jdk/src/jdk.jdi/share/classes/com/sun/jdi/doc-files/signature.html index 75bb46c1c32..8c7d4f95398 100644 --- a/jdk/src/jdk.jdi/share/classes/com/sun/jdi/doc-files/signature.html +++ b/jdk/src/jdk.jdi/share/classes/com/sun/jdi/doc-files/signature.html @@ -1,34 +1,42 @@ - + JDI Type Signatures + +
    - - + + + +
    JDI Type Signatures
    Type Signature -Java Type -
    Zboolean -
    Bbyte -
    Cchar -
    Sshort -
    Iint -
    Jlong -
    Ffloat -
    Ddouble -
    L fully-qualified-class +
    JDI Type Signatures
    Type Signature +Java Type +
    Zboolean +
    Bbyte +
    Cchar +
    Sshort +
    Iint +
    Jlong +
    Ffloat +
    Ddouble +
    L fully-qualified-class ; fully-qualified-class -
    [ type +
    [ type type[] -
    +
    ( arg-types ) ret-type method type (including constructors) +

    For example, the Java method: From 7be03f32008a9fa56fe907c42451e408d9c8dd08 Mon Sep 17 00:00:00 2001 From: Abhijit Saha Date: Tue, 8 Aug 2017 22:11:12 +0000 Subject: [PATCH 09/33] Added tag jdk-10+19 for changeset 22316369c9b0 --- jdk/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/.hgtags b/jdk/.hgtags index 012f8dd2e2a..23d7344f3c1 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -441,3 +441,4 @@ e069834e2c518a7bc2ffadc8c7e3cd7ec69fa8a0 jdk-10+15 06df1ce4b9b887d05ce6a13f4def3547e434dd1a jdk-9+179 d93f2fd542b7d7855c2cd49ae15ebcc3d441a83b jdk-10+17 c4b709bad6c5d29294124de5e74e1e2ac84fcf1f jdk-10+18 +b561eeca30decc6258b4aca8bb23beffbb6e2f7d jdk-10+19 From 880c64b6af69125d9a048354b34756a030c3c0d8 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Wed, 9 Aug 2017 15:39:50 -0700 Subject: [PATCH 10/33] 8185984: fix a11y and html issues in java.logging module Reviewed-by: dfuchs, mchung --- .../classes/java/util/logging/LogManager.java | 21 ++++++++++++------- .../classes/java/util/logging/Logger.java | 6 +++--- .../java/util/logging/SimpleFormatter.java | 2 +- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/jdk/src/java.logging/share/classes/java/util/logging/LogManager.java b/jdk/src/java.logging/share/classes/java/util/logging/LogManager.java index 74bda0a928f..31c5e74c624 100644 --- a/jdk/src/java.logging/share/classes/java/util/logging/LogManager.java +++ b/jdk/src/java.logging/share/classes/java/util/logging/LogManager.java @@ -1887,13 +1887,17 @@ public class LogManager { * The registered {@linkplain #addConfigurationListener configuration * listeners} will be invoked after the configuration is successfully updated. *

    - * + *
    Updating configuration properties
    + * + * * - * - * + * + * * + * + * * - * + * * * - * + * * * * - * + * * * * - * + * * * * - * + * * * + * *
    Updating configuration properties
    PropertyResulting BehaviorPropertyResulting Behavior
    {@code .level}{@code .level} *
      *
    • If the resulting configuration defines a level for a logger and @@ -1914,7 +1918,7 @@ public class LogManager { *
    *
    {@code .useParentHandlers}{@code .useParentHandlers} *
      *
    • If either the resulting or the old value for the useParentHandlers @@ -1928,7 +1932,7 @@ public class LogManager { *
    {@code .handlers}{@code .handlers} *
      *
    • If the resulting configuration defines a list of handlers for a @@ -1952,7 +1956,7 @@ public class LogManager { *
    {@code .*}{@code .*} *
      *
    • Properties configured/changed on handler classes will only affect @@ -1964,7 +1968,7 @@ public class LogManager { *
    {@code config} and any other property{@code config} and any other property *
      *
    • The resulting value for these property will be stored in the @@ -1974,6 +1978,7 @@ public class LogManager { *
    *
    *

    * Example mapper functions: diff --git a/jdk/src/java.logging/share/classes/java/util/logging/Logger.java b/jdk/src/java.logging/share/classes/java/util/logging/Logger.java index dea269302d2..6a1d4b5bc30 100644 --- a/jdk/src/java.logging/share/classes/java/util/logging/Logger.java +++ b/jdk/src/java.logging/share/classes/java/util/logging/Logger.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1497,7 +1497,7 @@ public class Logger { * The {@code msg} string is localized using the given resource bundle. * If the resource bundle is {@code null}, then the {@code msg} string is not * localized. - *

    + * * @param level One of the message level identifiers, e.g., {@code SEVERE} * @param bundle Resource bundle to localize {@code msg}; * can be {@code null}. @@ -1614,7 +1614,7 @@ public class Logger { * processed specially by output {@code Formatter} objects and is not treated * as a formatting parameter to the {@code LogRecord} {@code message} * property. - *

    + * * @param level One of the message level identifiers, e.g., {@code SEVERE} * @param bundle Resource bundle to localize {@code msg}; * can be {@code null}. diff --git a/jdk/src/java.logging/share/classes/java/util/logging/SimpleFormatter.java b/jdk/src/java.logging/share/classes/java/util/logging/SimpleFormatter.java index fe81640654b..2324940502e 100644 --- a/jdk/src/java.logging/share/classes/java/util/logging/SimpleFormatter.java +++ b/jdk/src/java.logging/share/classes/java/util/logging/SimpleFormatter.java @@ -41,7 +41,7 @@ import jdk.internal.logger.SurrogateLogger; * The {@code SimpleFormatter} is initialized with the * format string * specified in the {@code java.util.logging.SimpleFormatter.format} - * property to {@linkplain #format format} the log messages. + * property to {@linkplain #format(LogRecord) format} the log messages. * This property can be defined * in the {@linkplain LogManager#getProperty logging properties} * configuration file From 9f28d43df598d07815a3b78a192a203607733168 Mon Sep 17 00:00:00 2001 From: Doug Lea Date: Wed, 9 Aug 2017 17:30:51 -0700 Subject: [PATCH 11/33] 8185830: ConcurrentSkipListSet.clone() fails with UnsupportedOperationException Reviewed-by: martin, psandoz, plevart --- .../concurrent/ConcurrentSkipListSet.java | 27 ++++++++++--------- .../tck/ConcurrentSkipListSetTest.java | 20 +++++++++++++- 2 files changed, 33 insertions(+), 14 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java index 8149d0877dd..82e4b987781 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java @@ -35,8 +35,7 @@ package java.util.concurrent; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.VarHandle; +import java.lang.reflect.Field; import java.util.AbstractSet; import java.util.Collection; import java.util.Collections; @@ -506,19 +505,21 @@ public class ConcurrentSkipListSet : ((ConcurrentSkipListMap.SubMap)m).new SubMapKeyIterator(); } - // Support for resetting map in clone + /** Initializes map field; for use in clone. */ private void setMap(ConcurrentNavigableMap map) { - MAP.setVolatile(this, map); - } - - // VarHandle mechanics - private static final VarHandle MAP; - static { + Field mapField = java.security.AccessController.doPrivileged( + (java.security.PrivilegedAction) () -> { + try { + Field f = ConcurrentSkipListSet.class + .getDeclaredField("m"); + f.setAccessible(true); + return f; + } catch (ReflectiveOperationException e) { + throw new Error(e); + }}); try { - MethodHandles.Lookup l = MethodHandles.lookup(); - MAP = l.findVarHandle(ConcurrentSkipListSet.class, "m", - ConcurrentNavigableMap.class); - } catch (ReflectiveOperationException e) { + mapField.set(this, map); + } catch (IllegalAccessException e) { throw new Error(e); } } diff --git a/jdk/test/java/util/concurrent/tck/ConcurrentSkipListSetTest.java b/jdk/test/java/util/concurrent/tck/ConcurrentSkipListSetTest.java index cb28b6ae0e7..97331e63501 100644 --- a/jdk/test/java/util/concurrent/tck/ConcurrentSkipListSetTest.java +++ b/jdk/test/java/util/concurrent/tck/ConcurrentSkipListSetTest.java @@ -553,7 +553,25 @@ public class ConcurrentSkipListSetTest extends JSR166TestCase { } /** - * A deserialized serialized set has same elements + * A cloned set equals original + */ + public void testClone() { + ConcurrentSkipListSet x = populatedSet(SIZE); + ConcurrentSkipListSet y = x.clone(); + + assertNotSame(x, y); + assertEquals(x.size(), y.size()); + assertEquals(x, y); + assertEquals(y, x); + while (!x.isEmpty()) { + assertFalse(y.isEmpty()); + assertEquals(x.pollFirst(), y.pollFirst()); + } + assertTrue(y.isEmpty()); + } + + /** + * A deserialized/reserialized set equals original */ public void testSerialization() throws Exception { NavigableSet x = populatedSet(SIZE); From 2f31db126d5500e17ff2d79facb701ba5541e2ed Mon Sep 17 00:00:00 2001 From: Doug Lea Date: Wed, 9 Aug 2017 17:40:38 -0700 Subject: [PATCH 12/33] 8185099: Miscellaneous changes imported from jsr166 CVS 2017-08 Reviewed-by: martin, psandoz --- .../classes/java/util/concurrent/Flow.java | 4 +- .../util/concurrent/ThreadPoolExecutor.java | 8 ++-- .../tck/ArrayBlockingQueueTest.java | 2 +- .../util/concurrent/tck/ArrayDequeTest.java | 2 +- .../util/concurrent/tck/ArrayListTest.java | 24 ++++++++++ .../concurrent/tck/AtomicBooleanTest.java | 2 +- .../tck/AtomicIntegerArrayTest.java | 2 +- .../concurrent/tck/AtomicIntegerTest.java | 2 +- .../concurrent/tck/AtomicLongArrayTest.java | 2 +- .../util/concurrent/tck/AtomicLongTest.java | 2 +- .../tck/AtomicReferenceArrayTest.java | 2 +- .../concurrent/tck/AtomicReferenceTest.java | 2 +- .../tck/ConcurrentHashMap8Test.java | 2 +- .../concurrent/tck/ConcurrentHashMapTest.java | 2 +- .../tck/ConcurrentLinkedDequeTest.java | 2 +- .../tck/ConcurrentLinkedQueueTest.java | 2 +- .../tck/ConcurrentSkipListMapTest.java | 22 ++++++++- .../tck/ConcurrentSkipListSubMapTest.java | 4 +- .../tck/ConcurrentSkipListSubSetTest.java | 4 +- .../tck/CopyOnWriteArrayListTest.java | 2 +- .../tck/CopyOnWriteArraySetTest.java | 2 +- .../util/concurrent/tck/DoubleAdderTest.java | 2 +- .../util/concurrent/tck/JSR166TestCase.java | 47 ------------------- .../tck/LinkedBlockingDequeTest.java | 2 +- .../tck/LinkedBlockingQueueTest.java | 2 +- .../tck/LinkedTransferQueueTest.java | 2 +- .../util/concurrent/tck/LongAdderTest.java | 2 +- .../tck/PriorityBlockingQueueTest.java | 2 +- .../concurrent/tck/PriorityQueueTest.java | 2 +- .../concurrent/tck/SynchronousQueueTest.java | 2 +- .../tck/ThreadLocalRandom8Test.java | 4 +- .../tck/ThreadPoolExecutorSubclassTest.java | 4 +- .../util/concurrent/tck/TimeUnitTest.java | 2 +- .../java/util/concurrent/tck/TreeMapTest.java | 2 +- .../java/util/concurrent/tck/TreeSetTest.java | 2 +- .../util/concurrent/tck/TreeSubMapTest.java | 4 +- .../util/concurrent/tck/TreeSubSetTest.java | 4 +- 37 files changed, 89 insertions(+), 92 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/Flow.java b/jdk/src/java.base/share/classes/java/util/concurrent/Flow.java index 65e994350ce..1aefaea43b0 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/Flow.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/Flow.java @@ -85,9 +85,9 @@ package java.util.concurrent; * this.executor = executor; * } * public synchronized void request(long n) { - * if (n != 0 && !completed) { + * if (!completed) { * completed = true; - * if (n < 0) { + * if (n <= 0) { * IllegalArgumentException ex = new IllegalArgumentException(); * executor.execute(() -> subscriber.onError(ex)); * } else { diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ThreadPoolExecutor.java b/jdk/src/java.base/share/classes/java/util/concurrent/ThreadPoolExecutor.java index 1b3b866b25c..21221005f52 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/ThreadPoolExecutor.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/ThreadPoolExecutor.java @@ -576,7 +576,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService { private static final RuntimePermission shutdownPerm = new RuntimePermission("modifyThread"); - /* The context to be used when executing the finalizer, or null. */ + /** The context to be used when executing the finalizer, or null. */ private final AccessControlContext acc; /** @@ -1314,9 +1314,9 @@ public class ThreadPoolExecutor extends AbstractExecutorService { throw new IllegalArgumentException(); if (workQueue == null || threadFactory == null || handler == null) throw new NullPointerException(); - this.acc = System.getSecurityManager() == null ? - null : - AccessController.getContext(); + this.acc = (System.getSecurityManager() == null) + ? null + : AccessController.getContext(); this.corePoolSize = corePoolSize; this.maximumPoolSize = maximumPoolSize; this.workQueue = workQueue; diff --git a/jdk/test/java/util/concurrent/tck/ArrayBlockingQueueTest.java b/jdk/test/java/util/concurrent/tck/ArrayBlockingQueueTest.java index 589037bd511..a2744c2646f 100644 --- a/jdk/test/java/util/concurrent/tck/ArrayBlockingQueueTest.java +++ b/jdk/test/java/util/concurrent/tck/ArrayBlockingQueueTest.java @@ -903,7 +903,7 @@ public class ArrayBlockingQueueTest extends JSR166TestCase { } /** - * A deserialized serialized queue has same elements in same order + * A deserialized/reserialized queue has same elements in same order */ public void testSerialization() throws Exception { Queue x = populatedQueue(SIZE); diff --git a/jdk/test/java/util/concurrent/tck/ArrayDequeTest.java b/jdk/test/java/util/concurrent/tck/ArrayDequeTest.java index 344b63c9b79..4ea7ee7a475 100644 --- a/jdk/test/java/util/concurrent/tck/ArrayDequeTest.java +++ b/jdk/test/java/util/concurrent/tck/ArrayDequeTest.java @@ -939,7 +939,7 @@ public class ArrayDequeTest extends JSR166TestCase { } /** - * A deserialized serialized deque has same elements in same order + * A deserialized/reserialized deque has same elements in same order */ public void testSerialization() throws Exception { Queue x = populatedDeque(SIZE); diff --git a/jdk/test/java/util/concurrent/tck/ArrayListTest.java b/jdk/test/java/util/concurrent/tck/ArrayListTest.java index 535f04d34b5..203c04c6ea9 100644 --- a/jdk/test/java/util/concurrent/tck/ArrayListTest.java +++ b/jdk/test/java/util/concurrent/tck/ArrayListTest.java @@ -33,6 +33,7 @@ */ import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import junit.framework.Test; @@ -61,4 +62,27 @@ public class ArrayListTest extends JSR166TestCase { CollectionTest.testSuite(new SubListImplementation())); } + /** + * A cloned list equals original + */ + public void testClone() throws Exception { + ArrayList x = new ArrayList<>(); + x.add(1); + x.add(2); + x.add(3); + ArrayList y = (ArrayList) x.clone(); + + assertNotSame(y, x); + assertEquals(x, y); + assertEquals(y, x); + assertEquals(x.size(), y.size()); + assertEquals(x.toString(), y.toString()); + assertTrue(Arrays.equals(x.toArray(), y.toArray())); + while (!x.isEmpty()) { + assertFalse(y.isEmpty()); + assertEquals(x.remove(0), y.remove(0)); + } + assertTrue(y.isEmpty()); + } + } diff --git a/jdk/test/java/util/concurrent/tck/AtomicBooleanTest.java b/jdk/test/java/util/concurrent/tck/AtomicBooleanTest.java index be136357ff1..05a196ca724 100644 --- a/jdk/test/java/util/concurrent/tck/AtomicBooleanTest.java +++ b/jdk/test/java/util/concurrent/tck/AtomicBooleanTest.java @@ -147,7 +147,7 @@ public class AtomicBooleanTest extends JSR166TestCase { } /** - * a deserialized serialized atomic holds same value + * a deserialized/reserialized atomic holds same value */ public void testSerialization() throws Exception { AtomicBoolean x = new AtomicBoolean(); diff --git a/jdk/test/java/util/concurrent/tck/AtomicIntegerArrayTest.java b/jdk/test/java/util/concurrent/tck/AtomicIntegerArrayTest.java index e12284063f1..cdcf0061667 100644 --- a/jdk/test/java/util/concurrent/tck/AtomicIntegerArrayTest.java +++ b/jdk/test/java/util/concurrent/tck/AtomicIntegerArrayTest.java @@ -342,7 +342,7 @@ public class AtomicIntegerArrayTest extends JSR166TestCase { } /** - * a deserialized serialized array holds same values + * a deserialized/reserialized array holds same values in same order */ public void testSerialization() throws Exception { AtomicIntegerArray x = new AtomicIntegerArray(SIZE); diff --git a/jdk/test/java/util/concurrent/tck/AtomicIntegerTest.java b/jdk/test/java/util/concurrent/tck/AtomicIntegerTest.java index d148788d792..6f3546038bc 100644 --- a/jdk/test/java/util/concurrent/tck/AtomicIntegerTest.java +++ b/jdk/test/java/util/concurrent/tck/AtomicIntegerTest.java @@ -218,7 +218,7 @@ public class AtomicIntegerTest extends JSR166TestCase { } /** - * a deserialized serialized atomic holds same value + * a deserialized/reserialized atomic holds same value */ public void testSerialization() throws Exception { AtomicInteger x = new AtomicInteger(); diff --git a/jdk/test/java/util/concurrent/tck/AtomicLongArrayTest.java b/jdk/test/java/util/concurrent/tck/AtomicLongArrayTest.java index b312388dd6a..72d0e0677ab 100644 --- a/jdk/test/java/util/concurrent/tck/AtomicLongArrayTest.java +++ b/jdk/test/java/util/concurrent/tck/AtomicLongArrayTest.java @@ -341,7 +341,7 @@ public class AtomicLongArrayTest extends JSR166TestCase { } /** - * a deserialized serialized array holds same values + * a deserialized/reserialized array holds same values in same order */ public void testSerialization() throws Exception { AtomicLongArray x = new AtomicLongArray(SIZE); diff --git a/jdk/test/java/util/concurrent/tck/AtomicLongTest.java b/jdk/test/java/util/concurrent/tck/AtomicLongTest.java index f5191af99e6..c41a861ce09 100644 --- a/jdk/test/java/util/concurrent/tck/AtomicLongTest.java +++ b/jdk/test/java/util/concurrent/tck/AtomicLongTest.java @@ -220,7 +220,7 @@ public class AtomicLongTest extends JSR166TestCase { } /** - * a deserialized serialized atomic holds same value + * a deserialized/reserialized atomic holds same value */ public void testSerialization() throws Exception { AtomicLong x = new AtomicLong(); diff --git a/jdk/test/java/util/concurrent/tck/AtomicReferenceArrayTest.java b/jdk/test/java/util/concurrent/tck/AtomicReferenceArrayTest.java index 019446cc14d..8a9cf20a2ca 100644 --- a/jdk/test/java/util/concurrent/tck/AtomicReferenceArrayTest.java +++ b/jdk/test/java/util/concurrent/tck/AtomicReferenceArrayTest.java @@ -220,7 +220,7 @@ public class AtomicReferenceArrayTest extends JSR166TestCase { } /** - * a deserialized serialized array holds same values + * a deserialized/reserialized array holds same values in same order */ public void testSerialization() throws Exception { AtomicReferenceArray x = new AtomicReferenceArray(SIZE); diff --git a/jdk/test/java/util/concurrent/tck/AtomicReferenceTest.java b/jdk/test/java/util/concurrent/tck/AtomicReferenceTest.java index eb8c0b7b565..f46bd786c8f 100644 --- a/jdk/test/java/util/concurrent/tck/AtomicReferenceTest.java +++ b/jdk/test/java/util/concurrent/tck/AtomicReferenceTest.java @@ -143,7 +143,7 @@ public class AtomicReferenceTest extends JSR166TestCase { } /** - * a deserialized serialized atomic holds same value + * a deserialized/reserialized atomic holds same value */ public void testSerialization() throws Exception { AtomicReference x = new AtomicReference(); diff --git a/jdk/test/java/util/concurrent/tck/ConcurrentHashMap8Test.java b/jdk/test/java/util/concurrent/tck/ConcurrentHashMap8Test.java index e0d9f81a7f1..e5c75b13516 100644 --- a/jdk/test/java/util/concurrent/tck/ConcurrentHashMap8Test.java +++ b/jdk/test/java/util/concurrent/tck/ConcurrentHashMap8Test.java @@ -570,7 +570,7 @@ public class ConcurrentHashMap8Test extends JSR166TestCase { } /** - * A deserialized serialized set is equal + * A deserialized/reserialized set equals original */ public void testSerialization() throws Exception { int size = 20; diff --git a/jdk/test/java/util/concurrent/tck/ConcurrentHashMapTest.java b/jdk/test/java/util/concurrent/tck/ConcurrentHashMapTest.java index 729a6e3d146..007d3b6798d 100644 --- a/jdk/test/java/util/concurrent/tck/ConcurrentHashMapTest.java +++ b/jdk/test/java/util/concurrent/tck/ConcurrentHashMapTest.java @@ -811,7 +811,7 @@ public class ConcurrentHashMapTest extends JSR166TestCase { } /** - * A deserialized map equals original + * A deserialized/reserialized map equals original */ public void testSerialization() throws Exception { Map x = map5(); diff --git a/jdk/test/java/util/concurrent/tck/ConcurrentLinkedDequeTest.java b/jdk/test/java/util/concurrent/tck/ConcurrentLinkedDequeTest.java index 65a73621ef3..4ad7303b1f7 100644 --- a/jdk/test/java/util/concurrent/tck/ConcurrentLinkedDequeTest.java +++ b/jdk/test/java/util/concurrent/tck/ConcurrentLinkedDequeTest.java @@ -889,7 +889,7 @@ public class ConcurrentLinkedDequeTest extends JSR166TestCase { } /** - * A deserialized serialized deque has same elements in same order + * A deserialized/reserialized deque has same elements in same order */ public void testSerialization() throws Exception { Queue x = populatedDeque(SIZE); diff --git a/jdk/test/java/util/concurrent/tck/ConcurrentLinkedQueueTest.java b/jdk/test/java/util/concurrent/tck/ConcurrentLinkedQueueTest.java index f2cbc950ce1..e78ba3f20ca 100644 --- a/jdk/test/java/util/concurrent/tck/ConcurrentLinkedQueueTest.java +++ b/jdk/test/java/util/concurrent/tck/ConcurrentLinkedQueueTest.java @@ -538,7 +538,7 @@ public class ConcurrentLinkedQueueTest extends JSR166TestCase { } /** - * A deserialized serialized queue has same elements in same order + * A deserialized/reserialized queue has same elements in same order */ public void testSerialization() throws Exception { Queue x = populatedQueue(SIZE); diff --git a/jdk/test/java/util/concurrent/tck/ConcurrentSkipListMapTest.java b/jdk/test/java/util/concurrent/tck/ConcurrentSkipListMapTest.java index 0b1faad2824..fdd9892f09a 100644 --- a/jdk/test/java/util/concurrent/tck/ConcurrentSkipListMapTest.java +++ b/jdk/test/java/util/concurrent/tck/ConcurrentSkipListMapTest.java @@ -828,7 +828,24 @@ public class ConcurrentSkipListMapTest extends JSR166TestCase { } /** - * A deserialized map equals original + * A cloned map equals original + */ + public void testClone() { + ConcurrentSkipListMap x = map5(); + ConcurrentSkipListMap y = x.clone(); + + assertNotSame(x, y); + assertEquals(x.size(), y.size()); + assertEquals(x.toString(), y.toString()); + assertEquals(x, y); + assertEquals(y, x); + y.clear(); + assertTrue(y.isEmpty()); + assertFalse(x.equals(y)); + } + + /** + * A deserialized/reserialized map equals original */ public void testSerialization() throws Exception { NavigableMap x = map5(); @@ -839,6 +856,9 @@ public class ConcurrentSkipListMapTest extends JSR166TestCase { assertEquals(x.toString(), y.toString()); assertEquals(x, y); assertEquals(y, x); + y.clear(); + assertTrue(y.isEmpty()); + assertFalse(x.equals(y)); } /** diff --git a/jdk/test/java/util/concurrent/tck/ConcurrentSkipListSubMapTest.java b/jdk/test/java/util/concurrent/tck/ConcurrentSkipListSubMapTest.java index ddc82f78a56..e3f6c577cf2 100644 --- a/jdk/test/java/util/concurrent/tck/ConcurrentSkipListSubMapTest.java +++ b/jdk/test/java/util/concurrent/tck/ConcurrentSkipListSubMapTest.java @@ -625,7 +625,7 @@ public class ConcurrentSkipListSubMapTest extends JSR166TestCase { } /** - * A deserialized map equals original + * A deserialized/reserialized map equals original */ public void testSerialization() throws Exception { NavigableMap x = map5(); @@ -1299,7 +1299,7 @@ public class ConcurrentSkipListSubMapTest extends JSR166TestCase { } /** - * A deserialized map equals original + * A deserialized/reserialized map equals original */ public void testDescendingSerialization() throws Exception { NavigableMap x = dmap5(); diff --git a/jdk/test/java/util/concurrent/tck/ConcurrentSkipListSubSetTest.java b/jdk/test/java/util/concurrent/tck/ConcurrentSkipListSubSetTest.java index 19d34cc01e1..3cc968f4b1b 100644 --- a/jdk/test/java/util/concurrent/tck/ConcurrentSkipListSubSetTest.java +++ b/jdk/test/java/util/concurrent/tck/ConcurrentSkipListSubSetTest.java @@ -503,7 +503,7 @@ public class ConcurrentSkipListSubSetTest extends JSR166TestCase { } /** - * A deserialized serialized set has same elements + * A deserialized/reserialized set equals original */ public void testSerialization() throws Exception { NavigableSet x = populatedSet(SIZE); @@ -1002,7 +1002,7 @@ public class ConcurrentSkipListSubSetTest extends JSR166TestCase { } /** - * A deserialized serialized set has same elements + * A deserialized/reserialized set equals original */ public void testDescendingSerialization() throws Exception { NavigableSet x = dset5(); diff --git a/jdk/test/java/util/concurrent/tck/CopyOnWriteArrayListTest.java b/jdk/test/java/util/concurrent/tck/CopyOnWriteArrayListTest.java index 2b13e130701..5e04d4cc4dd 100644 --- a/jdk/test/java/util/concurrent/tck/CopyOnWriteArrayListTest.java +++ b/jdk/test/java/util/concurrent/tck/CopyOnWriteArrayListTest.java @@ -774,7 +774,7 @@ public class CopyOnWriteArrayListTest extends JSR166TestCase { } /** - * a deserialized serialized list is equal + * a deserialized/reserialized list equals original */ public void testSerialization() throws Exception { List x = populatedArray(SIZE); diff --git a/jdk/test/java/util/concurrent/tck/CopyOnWriteArraySetTest.java b/jdk/test/java/util/concurrent/tck/CopyOnWriteArraySetTest.java index 2595589cc78..c28051a9b68 100644 --- a/jdk/test/java/util/concurrent/tck/CopyOnWriteArraySetTest.java +++ b/jdk/test/java/util/concurrent/tck/CopyOnWriteArraySetTest.java @@ -403,7 +403,7 @@ public class CopyOnWriteArraySetTest extends JSR166TestCase { } /** - * A deserialized serialized set is equal + * A deserialized/reserialized set equals original */ public void testSerialization() throws Exception { Set x = populatedSet(SIZE); diff --git a/jdk/test/java/util/concurrent/tck/DoubleAdderTest.java b/jdk/test/java/util/concurrent/tck/DoubleAdderTest.java index fc7d1f47834..ba3fbc4a455 100644 --- a/jdk/test/java/util/concurrent/tck/DoubleAdderTest.java +++ b/jdk/test/java/util/concurrent/tck/DoubleAdderTest.java @@ -89,7 +89,7 @@ public class DoubleAdderTest extends JSR166TestCase { } /** - * a deserialized serialized adder holds same value + * a deserialized/reserialized adder holds same value */ public void testSerialization() throws Exception { DoubleAdder x = new DoubleAdder(); diff --git a/jdk/test/java/util/concurrent/tck/JSR166TestCase.java b/jdk/test/java/util/concurrent/tck/JSR166TestCase.java index f01acb4c6d7..2b25238201a 100644 --- a/jdk/test/java/util/concurrent/tck/JSR166TestCase.java +++ b/jdk/test/java/util/concurrent/tck/JSR166TestCase.java @@ -1142,53 +1142,6 @@ public class JSR166TestCase extends TestCase { fail("timed out waiting for thread to enter thread state " + expected); } - /** - * Checks that thread does not terminate within the default - * millisecond delay of {@code timeoutMillis()}. - * TODO: REMOVEME - */ - void assertThreadStaysAlive(Thread thread) { - assertThreadStaysAlive(thread, timeoutMillis()); - } - - /** - * Checks that thread does not terminate within the given millisecond delay. - * TODO: REMOVEME - */ - void assertThreadStaysAlive(Thread thread, long millis) { - try { - // No need to optimize the failing case via Thread.join. - delay(millis); - assertTrue(thread.isAlive()); - } catch (InterruptedException fail) { - threadFail("Unexpected InterruptedException"); - } - } - - /** - * Checks that the threads do not terminate within the default - * millisecond delay of {@code timeoutMillis()}. - * TODO: REMOVEME - */ - void assertThreadsStayAlive(Thread... threads) { - assertThreadsStayAlive(timeoutMillis(), threads); - } - - /** - * Checks that the threads do not terminate within the given millisecond delay. - * TODO: REMOVEME - */ - void assertThreadsStayAlive(long millis, Thread... threads) { - try { - // No need to optimize the failing case via Thread.join. - delay(millis); - for (Thread thread : threads) - assertTrue(thread.isAlive()); - } catch (InterruptedException fail) { - threadFail("Unexpected InterruptedException"); - } - } - /** * Checks that future.get times out, with the default timeout of * {@code timeoutMillis()}. diff --git a/jdk/test/java/util/concurrent/tck/LinkedBlockingDequeTest.java b/jdk/test/java/util/concurrent/tck/LinkedBlockingDequeTest.java index bc611770605..5388fbaa1a9 100644 --- a/jdk/test/java/util/concurrent/tck/LinkedBlockingDequeTest.java +++ b/jdk/test/java/util/concurrent/tck/LinkedBlockingDequeTest.java @@ -1800,7 +1800,7 @@ public class LinkedBlockingDequeTest extends JSR166TestCase { } /** - * A deserialized serialized deque has same elements in same order + * A deserialized/reserialized deque has same elements in same order */ public void testSerialization() throws Exception { Queue x = populatedDeque(SIZE); diff --git a/jdk/test/java/util/concurrent/tck/LinkedBlockingQueueTest.java b/jdk/test/java/util/concurrent/tck/LinkedBlockingQueueTest.java index 596f30dad2f..b880ea28724 100644 --- a/jdk/test/java/util/concurrent/tck/LinkedBlockingQueueTest.java +++ b/jdk/test/java/util/concurrent/tck/LinkedBlockingQueueTest.java @@ -823,7 +823,7 @@ public class LinkedBlockingQueueTest extends JSR166TestCase { } /** - * A deserialized serialized queue has same elements in same order + * A deserialized/reserialized queue has same elements in same order */ public void testSerialization() throws Exception { Queue x = populatedQueue(SIZE); diff --git a/jdk/test/java/util/concurrent/tck/LinkedTransferQueueTest.java b/jdk/test/java/util/concurrent/tck/LinkedTransferQueueTest.java index 401b0da9025..4e972676bfb 100644 --- a/jdk/test/java/util/concurrent/tck/LinkedTransferQueueTest.java +++ b/jdk/test/java/util/concurrent/tck/LinkedTransferQueueTest.java @@ -674,7 +674,7 @@ public class LinkedTransferQueueTest extends JSR166TestCase { } /** - * A deserialized serialized queue has same elements in same order + * A deserialized/reserialized queue has same elements in same order */ public void testSerialization() throws Exception { Queue x = populatedQueue(SIZE); diff --git a/jdk/test/java/util/concurrent/tck/LongAdderTest.java b/jdk/test/java/util/concurrent/tck/LongAdderTest.java index 4f0d5e07f75..c4c16a81a3d 100644 --- a/jdk/test/java/util/concurrent/tck/LongAdderTest.java +++ b/jdk/test/java/util/concurrent/tck/LongAdderTest.java @@ -111,7 +111,7 @@ public class LongAdderTest extends JSR166TestCase { } /** - * a deserialized serialized adder holds same value + * a deserialized/reserialized adder holds same value */ public void testSerialization() throws Exception { LongAdder x = new LongAdder(); diff --git a/jdk/test/java/util/concurrent/tck/PriorityBlockingQueueTest.java b/jdk/test/java/util/concurrent/tck/PriorityBlockingQueueTest.java index 603a66ff4a4..0279a6f03b2 100644 --- a/jdk/test/java/util/concurrent/tck/PriorityBlockingQueueTest.java +++ b/jdk/test/java/util/concurrent/tck/PriorityBlockingQueueTest.java @@ -686,7 +686,7 @@ public class PriorityBlockingQueueTest extends JSR166TestCase { } /** - * A deserialized serialized queue has same elements + * A deserialized/reserialized queue has same elements */ public void testSerialization() throws Exception { Queue x = populatedQueue(SIZE); diff --git a/jdk/test/java/util/concurrent/tck/PriorityQueueTest.java b/jdk/test/java/util/concurrent/tck/PriorityQueueTest.java index 81e8d770e51..179e9cda0b0 100644 --- a/jdk/test/java/util/concurrent/tck/PriorityQueueTest.java +++ b/jdk/test/java/util/concurrent/tck/PriorityQueueTest.java @@ -522,7 +522,7 @@ public class PriorityQueueTest extends JSR166TestCase { } /** - * A deserialized serialized queue has same elements + * A deserialized/reserialized queue has same elements */ public void testSerialization() throws Exception { Queue x = populatedQueue(SIZE); diff --git a/jdk/test/java/util/concurrent/tck/SynchronousQueueTest.java b/jdk/test/java/util/concurrent/tck/SynchronousQueueTest.java index 521dd8950cb..0a431d286a8 100644 --- a/jdk/test/java/util/concurrent/tck/SynchronousQueueTest.java +++ b/jdk/test/java/util/concurrent/tck/SynchronousQueueTest.java @@ -557,7 +557,7 @@ public class SynchronousQueueTest extends JSR166TestCase { } /** - * a deserialized serialized queue is usable + * a deserialized/reserialized queue is usable */ public void testSerialization() { final SynchronousQueue x = new SynchronousQueue(); diff --git a/jdk/test/java/util/concurrent/tck/ThreadLocalRandom8Test.java b/jdk/test/java/util/concurrent/tck/ThreadLocalRandom8Test.java index eef34d34149..dcf83eeefeb 100644 --- a/jdk/test/java/util/concurrent/tck/ThreadLocalRandom8Test.java +++ b/jdk/test/java/util/concurrent/tck/ThreadLocalRandom8Test.java @@ -260,8 +260,8 @@ public class ThreadLocalRandom8Test extends JSR166TestCase { } /** - * A deserialized ThreadLocalRandom is always identical to - * ThreadLocalRandom.current() + * A deserialized/reserialized ThreadLocalRandom is always + * identical to ThreadLocalRandom.current() */ public void testSerialization() { assertSame( diff --git a/jdk/test/java/util/concurrent/tck/ThreadPoolExecutorSubclassTest.java b/jdk/test/java/util/concurrent/tck/ThreadPoolExecutorSubclassTest.java index cf877007875..74c8abdee4f 100644 --- a/jdk/test/java/util/concurrent/tck/ThreadPoolExecutorSubclassTest.java +++ b/jdk/test/java/util/concurrent/tck/ThreadPoolExecutorSubclassTest.java @@ -1319,8 +1319,8 @@ public class ThreadPoolExecutorSubclassTest extends JSR166TestCase { public void testMaximumPoolSizeIllegalArgumentException2() { final ThreadPoolExecutor p = new CustomTPE(2, 3, - LONG_DELAY_MS, - MILLISECONDS,new ArrayBlockingQueue(10)); + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); try (PoolCleaner cleaner = cleaner(p)) { try { p.setMaximumPoolSize(-1); diff --git a/jdk/test/java/util/concurrent/tck/TimeUnitTest.java b/jdk/test/java/util/concurrent/tck/TimeUnitTest.java index 6e9aaa8bf4b..df924e3151c 100644 --- a/jdk/test/java/util/concurrent/tck/TimeUnitTest.java +++ b/jdk/test/java/util/concurrent/tck/TimeUnitTest.java @@ -623,7 +623,7 @@ public class TimeUnitTest extends JSR166TestCase { } /** - * a deserialized serialized unit is the same instance + * a deserialized/reserialized unit is the same instance */ public void testSerialization() throws Exception { for (TimeUnit x : TimeUnit.values()) diff --git a/jdk/test/java/util/concurrent/tck/TreeMapTest.java b/jdk/test/java/util/concurrent/tck/TreeMapTest.java index ada561ea119..bd24e32e951 100644 --- a/jdk/test/java/util/concurrent/tck/TreeMapTest.java +++ b/jdk/test/java/util/concurrent/tck/TreeMapTest.java @@ -633,7 +633,7 @@ public class TreeMapTest extends JSR166TestCase { } /** - * A deserialized map equals original + * A deserialized/reserialized map equals original */ public void testSerialization() throws Exception { NavigableMap x = map5(); diff --git a/jdk/test/java/util/concurrent/tck/TreeSetTest.java b/jdk/test/java/util/concurrent/tck/TreeSetTest.java index 55b28d613d9..4d3fe24815a 100644 --- a/jdk/test/java/util/concurrent/tck/TreeSetTest.java +++ b/jdk/test/java/util/concurrent/tck/TreeSetTest.java @@ -549,7 +549,7 @@ public class TreeSetTest extends JSR166TestCase { } /** - * A deserialized serialized set has same elements + * A deserialized/reserialized set equals original */ public void testSerialization() throws Exception { NavigableSet x = populatedSet(SIZE); diff --git a/jdk/test/java/util/concurrent/tck/TreeSubMapTest.java b/jdk/test/java/util/concurrent/tck/TreeSubMapTest.java index 1b5fa424b1c..05e876292b8 100644 --- a/jdk/test/java/util/concurrent/tck/TreeSubMapTest.java +++ b/jdk/test/java/util/concurrent/tck/TreeSubMapTest.java @@ -460,7 +460,7 @@ public class TreeSubMapTest extends JSR166TestCase { } /** - * A deserialized map equals original + * A deserialized/reserialized map equals original */ public void testSerialization() throws Exception { NavigableMap x = map5(); @@ -987,7 +987,7 @@ public class TreeSubMapTest extends JSR166TestCase { } /** - * A deserialized map equals original + * A deserialized/reserialized map equals original */ public void testDescendingSerialization() throws Exception { NavigableMap x = dmap5(); diff --git a/jdk/test/java/util/concurrent/tck/TreeSubSetTest.java b/jdk/test/java/util/concurrent/tck/TreeSubSetTest.java index a0f2b96ee57..10e37e9f7b4 100644 --- a/jdk/test/java/util/concurrent/tck/TreeSubSetTest.java +++ b/jdk/test/java/util/concurrent/tck/TreeSubSetTest.java @@ -500,7 +500,7 @@ public class TreeSubSetTest extends JSR166TestCase { } /** - * A deserialized serialized set has same elements + * A deserialized/reserialized set equals original */ public void testSerialization() throws Exception { NavigableSet x = populatedSet(SIZE); @@ -988,7 +988,7 @@ public class TreeSubSetTest extends JSR166TestCase { } /** - * A deserialized serialized set has same elements + * A deserialized/reserialized set equals original */ public void testDescendingSerialization() throws Exception { NavigableSet x = dset5(); From 330008fbf2dc20c05c558227579081bd4db26b5f Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Thu, 10 Aug 2017 15:21:17 -0700 Subject: [PATCH 13/33] 8185994: Fix a11y and HTML issues in the java.base/java.io and java.base/java.nio packages Reviewed-by: bpb, smarks --- .../share/classes/java/io/DataInput.java | 101 ++++++----- .../java/nio/channels/package-info.java | 166 ++++++++++-------- .../java/nio/charset/package-info.java | 29 +-- .../classes/java/nio/file/FileSystem.java | 24 +-- .../share/classes/java/nio/file/Files.java | 17 +- .../java/nio/file/attribute/package-info.java | 60 ++++--- .../share/classes/java/nio/package-info.java | 61 ++++--- 7 files changed, 253 insertions(+), 205 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/io/DataInput.java b/jdk/src/java.base/share/classes/java/io/DataInput.java index 70f78a6a068..86d8d3eb9fd 100644 --- a/jdk/src/java.base/share/classes/java/io/DataInput.java +++ b/jdk/src/java.base/share/classes/java/io/DataInput.java @@ -54,83 +54,90 @@ package java.io; * Unicode strings in a format that is a slight modification of UTF-8. * (For information regarding the standard UTF-8 format, see section * 3.9 Unicode Encoding Forms of The Unicode Standard, Version - * 4.0). - * Note that in the following table, the most significant bit appears in the - * far left-hand column. + * 4.0) * - *

    - * - * + *
      + *
    • Characters in the range {@code '\u005Cu0001'} to + * {@code '\u005Cu007F'} are represented by a single byte. + *
    • The null character {@code '\u005Cu0000'} and characters + * in the range {@code '\u005Cu0080'} to {@code '\u005Cu07FF'} are + * represented by a pair of bytes. + *
    • Characters in the range {@code '\u005Cu0800'} + * to {@code '\u005CuFFFF'} are represented by three bytes. + *
    + * + *
    Bit values and bytes
    + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * * * - * - * - * - * - * - * - * - * + * + * * * - * - * - * - * - * - * - * - * + * + * * * - * + * + * * * - * - * - * - * - * - * - * - * + * + * * * - * + * + * * * - * + * + * * * *
    Encoding of UTF-8 values
    ValueByteBit Values
    7 6 5 4 3 2 1 0
    - * All characters in the range {@code '\u005Cu0001'} to - * {@code '\u005Cu007F'} are represented by a single byte:
    Bit Values
    Byte 1 + * {@code \u005Cu0001} to {@code \u005Cu007F} 1 0 - * bits 6-0 + * bits 6-0 *
    - * The null character {@code '\u005Cu0000'} and characters - * in the range {@code '\u005Cu0080'} to {@code '\u005Cu07FF'} are - * represented by a pair of bytes:
    Bit Values
    Byte 1 + * {@code \u005Cu0000},
    + * {@code \u005Cu0080} to {@code \u005Cu07FF}
    1 1 * 1 * 0 - * bits 10-6 + * bits 10-6 *
    Byte 2 2 1 * 0 - * bits 5-0 + * bits 5-0 *
    - * {@code char} values in the range {@code '\u005Cu0800'} - * to {@code '\u005CuFFFF'} are represented by three bytes:
    Bit Values
    Byte 1 + * {@code \u005Cu0800} to {@code \u005CuFFFF} 1 1 * 1 * 1 * 0 - * bits 15-12 + * bits 15-12 *
    Byte 2 2 1 * 0 - * bits 11-6 + * bits 11-6 *
    Byte 3 3 1 * 0 - * bits 5-0 + * bits 5-0 *
    - *
    + * *

    * The differences between this format and the * standard UTF-8 format are the following: diff --git a/jdk/src/java.base/share/classes/java/nio/channels/package-info.java b/jdk/src/java.base/share/classes/java/nio/channels/package-info.java index d29ae67590f..0dc410ddd76 100644 --- a/jdk/src/java.base/share/classes/java/nio/channels/package-info.java +++ b/jdk/src/java.base/share/classes/java/nio/channels/package-info.java @@ -30,46 +30,50 @@ * * * - *

    + *
    * - * - * - * + * + * + * + * + * + * * - * + * * - * - * - * + * + * + * * - * - * - * - * - * + * + * + * + * + * * - * + * * - * + * * - * + * * - * + * * - * + * * - *
    Lists channels and their descriptions
    ChannelsDescription
    {@link java.nio.channels.Channel}
    ChannelsDescription
    {@link java.nio.channels.Channel}A nexus for I/O operations
    - *   {@link java.nio.channels.ReadableByteChannel}
    + * {@link java.nio.channels.ReadableByteChannel}Can read into a buffer
    - *     {@link java.nio.channels.ScatteringByteChannel}  Can read into a sequence of buffers
    - *   {@link java.nio.channels.WritableByteChannel}
    + * {@link java.nio.channels.ScatteringByteChannel}Can read into a sequence of buffers
    + * {@link java.nio.channels.WritableByteChannel}Can write from a buffer
    - *     {@link java.nio.channels.GatheringByteChannel}Can write from a sequence of buffers
    - *   {@link java.nio.channels.ByteChannel}Can read/write to/from a buffer
    - *     {@link java.nio.channels.SeekableByteChannel}
    + * {@link java.nio.channels.GatheringByteChannel}Can write from a sequence of buffers
    + * {@link java.nio.channels.ByteChannel}Can read/write to/from a buffer
    + * {@link java.nio.channels.SeekableByteChannel}A {@code ByteChannel} connected to an entity that contains a variable-length * sequence of bytes
    - *   {@link java.nio.channels.AsynchronousChannel}
    + * {@link java.nio.channels.AsynchronousChannel}Supports asynchronous I/O operations.
    - *     {@link java.nio.channels.AsynchronousByteChannel}
    + * {@link java.nio.channels.AsynchronousByteChannel}Can read and write bytes asynchronously
    - *   {@link java.nio.channels.NetworkChannel}
    + * {@link java.nio.channels.NetworkChannel}A channel to a network socket
    - *     {@link java.nio.channels.MulticastChannel}
    + * {@link java.nio.channels.MulticastChannel}Can join Internet Protocol (IP) multicast groups
    {@link java.nio.channels.Channels}
    {@link java.nio.channels.Channels}Utility methods for channel/stream interoperation
    + *
* *

A channel represents an open connection to an entity such as a * hardware device, a file, a network socket, or a program component that is @@ -122,21 +126,25 @@ * be constructed that uses a given charset to encode characters into bytes and * write them to a given writable byte channel. * - *

+ *
* - * - * - * + * + * + * + * + * + * * - * + * * - * - * - *
* Lists file channels and their descriptions
File channelsDescription
- * {@link java.nio.channels.FileChannel}
File channelsDescription
+ * {@link java.nio.channels.FileChannel}Reads, writes, maps, and manipulates files
- * {@link java.nio.channels.FileLock}
+ * {@link java.nio.channels.FileLock}A lock on a (region of a) file
- * {@link java.nio.MappedByteBuffer}  A direct byte buffer mapped to a region of a file
+ * + * {@link java.nio.MappedByteBuffer} + * A direct byte buffer mapped to a region of a file + * + * * *

The {@link java.nio.channels.FileChannel} class supports the usual * operations of reading bytes from, and writing bytes to, a channel connected to @@ -156,36 +164,40 @@ * class. * * - *

+ *
* - * - * - * + * + * + * + * + * + * * - * + * * - * + * * - * + * * - * + * * - * + * * - * + * * - * - * - * - * - *
* Lists multiplexed, non-blocking channels and their descriptions
Multiplexed, non-blocking I/ODescription
{@link java.nio.channels.SelectableChannel}
Multiplexed, non-blocking I/ODescription
{@link java.nio.channels.SelectableChannel}A channel that can be multiplexed
- *   {@link java.nio.channels.DatagramChannel}
+ * {@link java.nio.channels.DatagramChannel}A channel to a datagram-oriented socket
- *   {@link java.nio.channels.Pipe.SinkChannel}
+ * {@link java.nio.channels.Pipe.SinkChannel}The write end of a pipe
- *   {@link java.nio.channels.Pipe.SourceChannel}
+ * {@link java.nio.channels.Pipe.SourceChannel}The read end of a pipe
- *   {@link java.nio.channels.ServerSocketChannel}  
+ * {@link java.nio.channels.ServerSocketChannel}A channel to a stream-oriented listening socket
- *   {@link java.nio.channels.SocketChannel}
+ * {@link java.nio.channels.SocketChannel}A channel for a stream-oriented connecting socket
{@link java.nio.channels.Selector}
{@link java.nio.channels.Selector}A multiplexor of selectable channels
{@link java.nio.channels.SelectionKey}A token representing the registration
of a channel - * with a selector
{@link java.nio.channels.Pipe}Two channels that form a unidirectional pipe
+ * {@link java.nio.channels.SelectionKey} + * A token representing the registration of a channel + * with a selector + * {@link java.nio.channels.Pipe} + * Two channels that form a unidirectional pipe + * + * * *

Multiplexed, non-blocking I/O, which is much more scalable than * thread-oriented, blocking I/O, is provided by selectors, selectable @@ -251,27 +263,31 @@ * * * - *

+ *
* - * - * + * + * + * + * + * + * * - * + * * - * + * * - * + * * - * + * * - *
* Lists asynchronous channels and their descriptions
- * Asynchronous I/ODescription
- * {@link java.nio.channels.AsynchronousFileChannel}
Asynchronous I/ODescription
+ * {@link java.nio.channels.AsynchronousFileChannel}An asynchronous channel for reading, writing, and manipulating a file
- * {@link java.nio.channels.AsynchronousSocketChannel}
+ * {@link java.nio.channels.AsynchronousSocketChannel}An asynchronous channel to a stream-oriented connecting socket
- * {@link java.nio.channels.AsynchronousServerSocketChannel}  
+ * {@link java.nio.channels.AsynchronousServerSocketChannel}An asynchronous channel to a stream-oriented listening socket
- * {@link java.nio.channels.CompletionHandler}
+ * {@link java.nio.channels.CompletionHandler}A handler for consuming the result of an asynchronous operation
- * {@link java.nio.channels.AsynchronousChannelGroup}
+ * {@link java.nio.channels.AsynchronousChannelGroup}A grouping of asynchronous channels for the purpose of resource sharing
+ * + * * *

{@link java.nio.channels.AsynchronousChannel Asynchronous channels} are a * special type of channel capable of asynchronous I/O operations. Asynchronous diff --git a/jdk/src/java.base/share/classes/java/nio/charset/package-info.java b/jdk/src/java.base/share/classes/java/nio/charset/package-info.java index 80141dc8b6a..046606a57db 100644 --- a/jdk/src/java.base/share/classes/java/nio/charset/package-info.java +++ b/jdk/src/java.base/share/classes/java/nio/charset/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,22 +27,25 @@ * Defines charsets, decoders, and encoders, for translating between * bytes and Unicode characters. * - *

+ *
* - * - * - * - * + * + * + * + * + * + * + * * - * + * * - * + * * - * - * - * - *
Summary of charsets, decoders, and encoders in this package
Class nameDescriptiPath - *
{@link java.nio.charset.Charset}A named mapping between characters
and bytes
{@link java.nio.charset.CharsetDecoder}
Class nameDescription + *
{@link java.nio.charset.Charset}A named mapping between characters and bytes
{@link java.nio.charset.CharsetDecoder}Decodes bytes into characters
{@link java.nio.charset.CharsetEncoder}
{@link java.nio.charset.CharsetEncoder}Encodes characters into bytes
{@link java.nio.charset.CoderResult}
{@link java.nio.charset.CoderResult}Describes coder results
{@link java.nio.charset.CodingErrorAction}Describes actions to take when
coding errors are detected
+ * {@link java.nio.charset.CodingErrorAction} + * Describes actions to take when coding errors are detected + * + * * *

A charset is named mapping between sequences of * sixteen-bit Unicode characters and sequences of bytes, in the sense diff --git a/jdk/src/java.base/share/classes/java/nio/file/FileSystem.java b/jdk/src/java.base/share/classes/java/nio/file/FileSystem.java index 0fd5be4fcf0..27bca11922e 100644 --- a/jdk/src/java.base/share/classes/java/nio/file/FileSystem.java +++ b/jdk/src/java.base/share/classes/java/nio/file/FileSystem.java @@ -314,45 +314,49 @@ public abstract class FileSystem * representation of the path is matched using a limited pattern language * that resembles regular expressions but with a simpler syntax. For example: * - *

- * + *
* + * + * + * + * * * - * + * * * * - * + * * * * - * + * * * * - * + * * * * - * * * - * * * - * * * *
Pattern Language
Example + * Description + *
{@code *.java}{@code *.java}Matches a path that represents a file name ending in {@code .java}
{@code *.*}{@code *.*}Matches file names containing a dot
{@code *.{java,class}}{@code *.{java,class}}Matches file names ending with {@code .java} or {@code .class}
{@code foo.?}{@code foo.?}Matches file names starting with {@code foo.} and a single * character extension
/home/*/* + * /home/*/* * Matches /home/gus/data on UNIX platforms
/home/** + * /home/** * Matches /home/gus and * /home/gus/data on UNIX platforms
C:\\* + * C:\\* * Matches C:\foo and C:\bar on the Windows * platform (note that the backslash is escaped; as a string literal in the * Java Language the pattern would be "C:\\\\*")
- *
* *

The following rules are used to interpret glob patterns: * diff --git a/jdk/src/java.base/share/classes/java/nio/file/Files.java b/jdk/src/java.base/share/classes/java/nio/file/Files.java index 09bce16a844..f5dbba9c358 100644 --- a/jdk/src/java.base/share/classes/java/nio/file/Files.java +++ b/jdk/src/java.base/share/classes/java/nio/file/Files.java @@ -1923,30 +1923,33 @@ public final class Files { *

The following examples demonstrate possible values for the {@code * attributes} parameter: * - *

- * + *
* + * + * + * * * - * + * * * * - * + * * * * - * + * * * * - * + * * * * *
Possible values
Example + * Description + *
{@code "*"} {@code "*"} Read all {@link BasicFileAttributes basic-file-attributes}.
{@code "size,lastModifiedTime,lastAccessTime"} {@code "size,lastModifiedTime,lastAccessTime"} Reads the file size, last modified time, and last access time * attributes.
{@code "posix:*"} {@code "posix:*"} Read all {@link PosixFileAttributes POSIX-file-attributes}.
{@code "posix:permissions,owner,size"} {@code "posix:permissions,owner,size"} Reads the POSIX file permissions, owner, and file size.
- *
* *

The {@code options} array may be used to indicate how symbolic links * are handled for the case that the file is a symbolic link. By default, diff --git a/jdk/src/java.base/share/classes/java/nio/file/attribute/package-info.java b/jdk/src/java.base/share/classes/java/nio/file/attribute/package-info.java index 11f5d6e2720..911d38a9bea 100644 --- a/jdk/src/java.base/share/classes/java/nio/file/attribute/package-info.java +++ b/jdk/src/java.base/share/classes/java/nio/file/attribute/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,43 +26,47 @@ /** * Interfaces and classes providing access to file and file system attributes. * - *

+ *
* - * - * - * + * + * + * + * + * + * * - * + * * - * + * * - * + * * - * + * * - * + * * - * + * * - * + * * - * + * * - *
Attribute views
Attribute viewsDescription
{@link java.nio.file.attribute.AttributeView}
Attribute viewsDescription
{@link java.nio.file.attribute.AttributeView}Can read or update non-opaque values associated with objects in a file system
- *   {@link java.nio.file.attribute.FileAttributeView}
+ * {@link java.nio.file.attribute.FileAttributeView}Can read or update file attributes
- *      - * {@link java.nio.file.attribute.BasicFileAttributeView}  
+ * + * {@link java.nio.file.attribute.BasicFileAttributeView}Can read or update a basic set of file attributes
- *        - * {@link java.nio.file.attribute.PosixFileAttributeView}  
+ * + * {@link java.nio.file.attribute.PosixFileAttributeView}Can read or update POSIX defined file attributes
- *        - * {@link java.nio.file.attribute.DosFileAttributeView}  
+ * + * {@link java.nio.file.attribute.DosFileAttributeView}Can read or update FAT file attributes
- *      - * {@link java.nio.file.attribute.FileOwnerAttributeView}  
+ * + * {@link java.nio.file.attribute.FileOwnerAttributeView}Can read or update the owner of a file
- *       - * {@link java.nio.file.attribute.AclFileAttributeView}  
+ * + * {@link java.nio.file.attribute.AclFileAttributeView}Can read or update Access Control Lists
- *      - * {@link java.nio.file.attribute.UserDefinedFileAttributeView}  
+ * + * {@link java.nio.file.attribute.UserDefinedFileAttributeView}Can read or update user-defined file attributes
- *   {@link java.nio.file.attribute.FileStoreAttributeView}
+ * {@link java.nio.file.attribute.FileStoreAttributeView}Can read or update file system attributes
+ * + * * *

An attribute view provides a read-only or updatable view of the non-opaque * values, or metadata, associated with objects in a file system. diff --git a/jdk/src/java.base/share/classes/java/nio/package-info.java b/jdk/src/java.base/share/classes/java/nio/package-info.java index 9fa17c945e0..c743a058fc7 100644 --- a/jdk/src/java.base/share/classes/java/nio/package-info.java +++ b/jdk/src/java.base/share/classes/java/nio/package-info.java @@ -48,7 +48,7 @@ *

  • Selectors and selection keys, which * together with
    selectable channels define a multiplexed, - * non-blocking
    I/O
     facility.

  • + * non-blocking
    I/O facility.

    * * * @@ -62,33 +62,44 @@ * * * - *
    + *
    * - * - * - * + * + * + * + * + * + * * - * - * - * + * clear, flip, rewind, and mark/reset + * + * + * * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    Description of the various buffers
    BuffersDescription
    {@link java.nio.Buffer}
    BuffersDescription
    {@link java.nio.Buffer}Position, limit, and capacity; - *
    clear, flip, rewind, and mark/reset
      {@link java.nio.ByteBuffer}Get/put, compact, views; allocate, wrap
    - *     {@link java.nio.MappedByteBuffer}  
    + * {@link java.nio.ByteBuffer}Get/put, compact, views; allocate, wrap
    + * {@link java.nio.MappedByteBuffer}A byte buffer mapped to a file
      {@link java.nio.CharBuffer}Get/put, compact; allocate, wrap
      {@link java.nio.DoubleBuffer}    ' '
      {@link java.nio.FloatBuffer}    ' '
      {@link java.nio.IntBuffer}    ' '
      {@link java.nio.LongBuffer}    ' '
      {@link java.nio.ShortBuffer}    ' '
    {@link java.nio.ByteOrder}Typesafe enumeration for byte orders
    + * + * {@link java.nio.CharBuffer} + * Get/put, compact; allocate, wrap + * + * {@link java.nio.DoubleBuffer} + * Get/put, compact; allocate, wrap + * + * {@link java.nio.FloatBuffer} + * Get/put, compact; allocate, wrap + * + * {@link java.nio.IntBuffer} + * Get/put, compact; allocate, wrap + * + * {@link java.nio.LongBuffer} + * Get/put, compact; allocate, wrap + * + * {@link java.nio.ShortBuffer} + * Get/put, compact; allocate, wrap + * {@link java.nio.ByteOrder} + * Typesafe enumeration for byte orders + * + * * *

    A buffer is a container for a fixed amount of data of a * specific primitive type. In addition to its content a buffer has a From c79d52b1030de135b2d7afcba57db6c0f76c854b Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Thu, 10 Aug 2017 15:23:03 -0700 Subject: [PATCH 14/33] 8186052: Fix a11y and HTML issues in the java.base/java.lang[.*] packages Reviewed-by: smarks --- .../share/classes/java/lang/Character.java | 17 +++-- .../share/classes/java/lang/Class.java | 26 +++---- .../share/classes/java/lang/Double.java | 26 +++---- .../share/classes/java/lang/Float.java | 24 +++--- .../share/classes/java/lang/String.java | 73 ++++++++++--------- .../share/classes/java/lang/System.java | 42 ++++++----- .../share/classes/java/lang/Thread.java | 6 +- .../java/lang/invoke/LambdaMetafactory.java | 12 +-- .../java/lang/invoke/MethodHandle.java | 6 +- .../java/lang/invoke/MethodHandles.java | 31 ++++---- .../java/lang/invoke/package-info.java | 45 +++++++----- .../java/lang/reflect/AnnotatedElement.java | 40 ++++++---- 12 files changed, 186 insertions(+), 162 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/Character.java b/jdk/src/java.base/share/classes/java/lang/Character.java index fd6682e6196..e2c65b1567f 100644 --- a/jdk/src/java.base/share/classes/java/lang/Character.java +++ b/jdk/src/java.base/share/classes/java/lang/Character.java @@ -9566,18 +9566,23 @@ class Character implements java.io.Serializable, Comparable { * Determines if the specified character is ISO-LATIN-1 white space. * This method returns {@code true} for the following five * characters only: - * + *
    * + * + * * - * + * * - * + * * - * + * * - * + * * - * + * * * *
    truechars
    Character + * Code + * Name + *
    {@code '\t'} {@code U+0009}
    {@code '\t'} {@code U+0009}{@code HORIZONTAL TABULATION}
    {@code '\n'} {@code U+000A}
    {@code '\n'} {@code U+000A}{@code NEW LINE}
    {@code '\f'} {@code U+000C}
    {@code '\f'} {@code U+000C}{@code FORM FEED}
    {@code '\r'} {@code U+000D}
    {@code '\r'} {@code U+000D}{@code CARRIAGE RETURN}
    {@code ' '} {@code U+0020}
    {@code ' '} {@code U+0020}{@code SPACE}
    diff --git a/jdk/src/java.base/share/classes/java/lang/Class.java b/jdk/src/java.base/share/classes/java/lang/Class.java index 81dd846c26a..54415e990f2 100644 --- a/jdk/src/java.base/share/classes/java/lang/Class.java +++ b/jdk/src/java.base/share/classes/java/lang/Class.java @@ -728,22 +728,22 @@ public final class Class implements java.io.Serializable, * one or more '{@code [}' characters representing the depth of the array * nesting. The encoding of element type names is as follows: * - *

    + *
    * * - * - * - * + * *
    Element types and encodings
    Element Type Encoding + *
    Element Type Encoding *
    boolean Z - *
    byte B - *
    char C - *
    class or interface - * Lclassname; - *
    double D - *
    float F - *
    int I - *
    long J - *
    short S + *
    boolean Z + *
    byte B + *
    char C + *
    class or interface + * Lclassname; + *
    double D + *
    float F + *
    int I + *
    long J + *
    short S *
    * diff --git a/jdk/src/java.base/share/classes/java/lang/Double.java b/jdk/src/java.base/share/classes/java/lang/Double.java index a7aa0a0f626..52bf32c8153 100644 --- a/jdk/src/java.base/share/classes/java/lang/Double.java +++ b/jdk/src/java.base/share/classes/java/lang/Double.java @@ -255,25 +255,25 @@ public final class Double extends Number implements Comparable { * * * - * + *
    * * - * + * * - * - * - * - * - * - * - * - * + * + * + * + * + * + * + * + * * - * + * * - * + * * - * + * * * *
    Examples
    Floating-point ValueHexadecimal String
    Floating-point ValueHexadecimal String
    {@code 1.0} {@code 0x1.0p0}
    {@code -1.0} {@code -0x1.0p0}
    {@code 2.0} {@code 0x1.0p1}
    {@code 3.0} {@code 0x1.8p1}
    {@code 0.5} {@code 0x1.0p-1}
    {@code 0.25} {@code 0x1.0p-2}
    {@code Double.MAX_VALUE}
    {@code 1.0} {@code 0x1.0p0}
    {@code -1.0} {@code -0x1.0p0}
    {@code 2.0} {@code 0x1.0p1}
    {@code 3.0} {@code 0x1.8p1}
    {@code 0.5} {@code 0x1.0p-1}
    {@code 0.25} {@code 0x1.0p-2}
    {@code Double.MAX_VALUE}{@code 0x1.fffffffffffffp1023}
    {@code Minimum Normal Value}
    {@code Minimum Normal Value}{@code 0x1.0p-1022}
    {@code Maximum Subnormal Value}
    {@code Maximum Subnormal Value}{@code 0x0.fffffffffffffp-1022}
    {@code Double.MIN_VALUE}
    {@code Double.MIN_VALUE}{@code 0x0.0000000000001p-1022}
    diff --git a/jdk/src/java.base/share/classes/java/lang/Float.java b/jdk/src/java.base/share/classes/java/lang/Float.java index 77c1d1671d5..52cb2c09b79 100644 --- a/jdk/src/java.base/share/classes/java/lang/Float.java +++ b/jdk/src/java.base/share/classes/java/lang/Float.java @@ -256,25 +256,25 @@ public final class Float extends Number implements Comparable { * * * - * + *
    * * - * + * * * - * - * - * - * - * - * - * + * + * + * + * + * + * + * * - * + * * - * + * * - * + * * * *
    Examples
    Floating-point ValueHexadecimal String
    Floating-point ValueHexadecimal String
    {@code 1.0} {@code 0x1.0p0}
    {@code -1.0} {@code -0x1.0p0}
    {@code 2.0} {@code 0x1.0p1}
    {@code 3.0} {@code 0x1.8p1}
    {@code 0.5} {@code 0x1.0p-1}
    {@code 0.25} {@code 0x1.0p-2}
    {@code Float.MAX_VALUE}
    {@code 1.0} {@code 0x1.0p0}
    {@code -1.0} {@code -0x1.0p0}
    {@code 2.0} {@code 0x1.0p1}
    {@code 3.0} {@code 0x1.8p1}
    {@code 0.5} {@code 0x1.0p-1}
    {@code 0.25} {@code 0x1.0p-2}
    {@code Float.MAX_VALUE}{@code 0x1.fffffep127}
    {@code Minimum Normal Value}
    {@code Minimum Normal Value}{@code 0x1.0p-126}
    {@code Maximum Subnormal Value}
    {@code Maximum Subnormal Value}{@code 0x0.fffffep-126}
    {@code Float.MIN_VALUE}
    {@code Float.MIN_VALUE}{@code 0x0.000002p-126}
    diff --git a/jdk/src/java.base/share/classes/java/lang/String.java b/jdk/src/java.base/share/classes/java/lang/String.java index 6d06764c1b4..a41a4200b39 100644 --- a/jdk/src/java.base/share/classes/java/lang/String.java +++ b/jdk/src/java.base/share/classes/java/lang/String.java @@ -2208,29 +2208,29 @@ public final class String * Split example showing regex, limit, and result * * - * Regex - * Limit - * Result + * Regex + * Limit + * Result * * * - * : - * 2 + * : + * 2 * {@code { "boo", "and:foo" }} - * : - * 5 + * + * 5 * {@code { "boo", "and", "foo" }} - * : - * -2 + * + * -2 * {@code { "boo", "and", "foo" }} - * o - * 5 + * o + * 5 * {@code { "b", "", ":and:f", "", "" }} - * o - * -2 + * + * -2 * {@code { "b", "", ":and:f", "", "" }} - * o - * 0 + * + * 0 * {@code { "b", "", ":and:f" }} * * @@ -2336,14 +2336,14 @@ public final class String * Split examples showing regex and result * * - * Regex - * Result + * Regex + * Result * * * - * : + * : * {@code { "boo", "and", "foo" }} - * o + * o * {@code { "b", "", ":and:f" }} * * @@ -2460,36 +2460,37 @@ public final class String * Lowercase mapping examples showing language code of locale, upper case, lower case, and description * * - * Language Code of Locale - * Upper Case - * Lower Case - * Description + * Language Code of Locale + * Upper Case + * Lower Case + * Description * * * * * tr (Turkish) - * \u0130 + * \u0130 * \u0069 * capital letter I with dot above -> small letter i * * * tr (Turkish) - * \u0049 + * \u0049 * \u0131 * capital letter I -> small letter dotless i * * * (all) - * French Fries + * French Fries * french fries * lowercased all chars in String * * * (all) - * capiotacapchi + * + * capiotacapchi * capthetacapupsil - * capsigma + * capsigma * iotachi * thetaupsilon * sigma @@ -2546,34 +2547,34 @@ public final class String * Examples of locale-sensitive and 1:M case mappings. Shows Language code of locale, lower case, upper case, and description. * * - * Language Code of Locale - * Lower Case - * Upper Case - * Description + * Language Code of Locale + * Lower Case + * Upper Case + * Description * * * * * tr (Turkish) - * \u0069 + * \u0069 * \u0130 * small letter i -> capital letter I with dot above * * * tr (Turkish) - * \u0131 + * \u0131 * \u0049 * small letter dotless i -> capital letter I * * * (all) - * \u00df + * \u00df * \u0053 \u0053 * small letter sharp s -> two letters: SS * * * (all) - * Fahrvergnügen + * Fahrvergnügen * FAHRVERGNÜGEN * * diff --git a/jdk/src/java.base/share/classes/java/lang/System.java b/jdk/src/java.base/share/classes/java/lang/System.java index 995b2c4e90f..8388dce7562 100644 --- a/jdk/src/java.base/share/classes/java/lang/System.java +++ b/jdk/src/java.base/share/classes/java/lang/System.java @@ -583,7 +583,7 @@ public final class System { * system properties, a set of system properties is first created and * initialized. This set of system properties always includes values * for the following keys: - * + *
    * * * @@ -1049,26 +1049,28 @@ public final class System { * of corresponding severity. *
    The mapping is as follows: *

    - *
    Shows property keys and associated values
    Key
    + *
    * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * *
    System.Logger Severity Level Mapping
    System.Logger Levels{@link Logger.Level#ALL ALL}{@link Logger.Level#TRACE TRACE}{@link Logger.Level#DEBUG DEBUG}{@link Logger.Level#INFO INFO}{@link Logger.Level#WARNING WARNING}{@link Logger.Level#ERROR ERROR}{@link Logger.Level#OFF OFF}
    java.util.logging Levels{@link java.util.logging.Level#ALL ALL}{@link java.util.logging.Level#FINER FINER}{@link java.util.logging.Level#FINE FINE}{@link java.util.logging.Level#INFO INFO}{@link java.util.logging.Level#WARNING WARNING}{@link java.util.logging.Level#SEVERE SEVERE}{@link java.util.logging.Level#OFF OFF}
    System.Logger Levelsjava.util.logging Levels
    {@link Logger.Level#ALL ALL}{@link java.util.logging.Level#ALL ALL}
    {@link Logger.Level#TRACE TRACE}{@link java.util.logging.Level#FINER FINER}
    {@link Logger.Level#DEBUG DEBUG}{@link java.util.logging.Level#FINE FINE}
    {@link Logger.Level#INFO INFO}{@link java.util.logging.Level#INFO INFO}
    {@link Logger.Level#WARNING WARNING}{@link java.util.logging.Level#WARNING WARNING}
    {@link Logger.Level#ERROR ERROR}{@link java.util.logging.Level#SEVERE SEVERE}
    {@link Logger.Level#OFF OFF}{@link java.util.logging.Level#OFF OFF}
    * * @since 9 diff --git a/jdk/src/java.base/share/classes/java/lang/Thread.java b/jdk/src/java.base/share/classes/java/lang/Thread.java index 8ecc90dd964..5d25df81906 100644 --- a/jdk/src/java.base/share/classes/java/lang/Thread.java +++ b/jdk/src/java.base/share/classes/java/lang/Thread.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -347,7 +347,7 @@ class Thread implements Runnable { * the calling thread indicates to the runtime that it is busy-waiting. * The runtime may take action to improve the performance of invoking * spin-wait loop constructions. - *

    + * * @apiNote * As an example consider a method in a class that spins in a loop until * some flag is set outside of that method. A call to the {@code onSpinWait} @@ -373,7 +373,7 @@ class Thread implements Runnable { * method was not called at all. However on some architectures the Java * Virtual Machine may issue the processor instructions to address such * code patterns in a more beneficial way. - *

    + * * @since 9 */ @HotSpotIntrinsicCandidate diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/LambdaMetafactory.java b/jdk/src/java.base/share/classes/java/lang/invoke/LambdaMetafactory.java index 95719763b0f..b9bfd64432c 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/LambdaMetafactory.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/LambdaMetafactory.java @@ -149,24 +149,24 @@ import java.util.Arrays; * capture argument (corresponding to the receiver) must be non-null. * *

    A type Q is considered adaptable to S as follows: - * + *
    * * - * + * * * * - * + * * * * * - * + * * * * * - * + * * * * - * + * * * diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandle.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandle.java index 6e913a84fd9..1c8eb5a1a9e 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandle.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -889,7 +889,7 @@ assertEquals("[A, B, C]", (String) caToString2.invokeExact('A', "BC".toCharArray *

    * This method behaves very much like {@link #asSpreader(Class, int)}, but accepts an additional {@code spreadArgPos} * argument to indicate at which position in the parameter list the spreading should take place. - *

    + * * @apiNote Example: *

    {@code
         MethodHandle compare = LOOKUP.findStatic(Objects.class, "compare", methodType(int.class, Object.class, Object.class, Comparator.class));
    @@ -1094,7 +1094,7 @@ assertEquals("[123]", (String) longsToString.invokeExact((long)123));
          * This method behaves very much like {@link #asCollector(Class, int)}, but differs in that its {@code
          * collectArgPos} argument indicates at which position in the parameter list arguments should be collected. This
          * index is zero-based.
    -     * 

    + * * @apiNote Examples: *

    {@code
         StringWriter swr = new StringWriter();
    diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
    index 45ccb909490..3671ab11833 100644
    --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
    +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
    @@ -3353,7 +3353,7 @@ assert((int)twice.invokeExact(21) == 42);
          * That is, it returns a zero primitive value, a {@code null}, or {@code void}.
          * 

    The returned method handle is equivalent to * {@code dropArguments(zero(type.returnType()), 0, type.parameterList())}. - *

    + * * @apiNote Given a predicate and target, a useful "if-then" construct can be produced as * {@code guardWithTest(pred, target, empty(target.type())}. * @param type the type of the desired method handle @@ -3676,7 +3676,7 @@ assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z")); * Given these assumptions, the result of an invocation of {@code dropArgumentsToMatch} will have the parameter type * list {@code S..., P..., M..., A...}, with the {@code P} and {@code A} types inserted as if by * {@link #dropArguments(MethodHandle, int, Class[])}. - *

    + * * @apiNote * Two method handles whose argument lists are "effectively identical" (i.e., identical in a common prefix) may be * mutually converted to a common type by two calls to {@code dropArgumentsToMatch}, as follows: @@ -4169,7 +4169,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); * position in the parameter list at which folding takes place. The argument controlling this, {@code pos}, is a * zero-based index. The aforementioned method {@link #foldArguments(MethodHandle, MethodHandle)} assumes position * 0. - *

    + * * @apiNote Example: *

    {@code
         import static java.lang.invoke.MethodHandles.*;
    @@ -4698,7 +4698,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
          * Note that the parameter type lists {@code (V...)} and {@code (A...)} have been expanded
          * to their full length, even though individual clause functions may neglect to take them all.
          * As noted above, missing parameters are filled in as if by {@link #dropArgumentsToMatch}.
    -     * 

    + * * @apiNote Example: *

    {@code
          * // iterative implementation of the factorial function as a loop handle
    @@ -4991,7 +4991,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
          *   return v;
          * }
          * }
    - *

    + * * @apiNote Example: *

    {@code
          * // implement the zip function for lists as a loop handle
    @@ -5010,7 +5010,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
          * assertEquals(zipped, (List) loop.invoke(a.iterator(), b.iterator()));
          * }
    * - *

    + * * @apiNote The implementation of this method can be expressed as follows: *

    {@code
          * MethodHandle whileLoop(MethodHandle init, MethodHandle pred, MethodHandle body) {
    @@ -5104,7 +5104,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
          *   return v;
          * }
          * }
    - *

    + * * @apiNote Example: *

    {@code
          * // int i = 0; while (i < limit) { ++i; } return i; => limit
    @@ -5116,7 +5116,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
          * assertEquals(23, loop.invoke(23));
          * }
    * - *

    + * * @apiNote The implementation of this method can be expressed as follows: *

    {@code
          * MethodHandle doWhileLoop(MethodHandle init, MethodHandle body, MethodHandle pred) {
    @@ -5248,7 +5248,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
          *   return v;
          * }
          * }
    - *

    + * * @apiNote Example with a fully conformant body method: *

    {@code
          * // String s = "Lambdaman!"; for (int i = 0; i < 13; ++i) { s = "na " + s; } return s;
    @@ -5260,7 +5260,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
          * MethodHandle loop = MethodHandles.countedLoop(fit13, start, MH_step);
          * assertEquals("na na na na na na na na na na na na na Lambdaman!", loop.invoke("Lambdaman!"));
          * }
    - *

    + * * @apiNote Example with the simplest possible body method type, * and passing the number of iterations to the loop invocation: *

    {@code
    @@ -5273,7 +5273,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
          * MethodHandle loop = MethodHandles.countedLoop(count, start, MH_step);  // (v, i) -> "na " + v
          * assertEquals("na na na na na na na na na na na na na Lambdaman!", loop.invoke(13, "Lambdaman!"));
          * }
    - *

    + * * @apiNote Example that treats the number of iterations, string to append to, and string to append * as loop parameters: *

    {@code
    @@ -5286,7 +5286,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
          * MethodHandle loop = MethodHandles.countedLoop(count, start, MH_step);  // (v, i, _, pre, _) -> pre + " " + v
          * assertEquals("na na na na na na na na na na na na na Lambdaman!", loop.invoke(13, "na", "Lambdaman!"));
          * }
    - *

    + * * @apiNote Example that illustrates the usage of {@link #dropArgumentsToMatch(MethodHandle, int, List, int)} * to enforce a loop type: *

    {@code
    @@ -5301,7 +5301,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
          * MethodHandle loop = MethodHandles.countedLoop(count, start, body);  // (v, i, pre, _, _) -> pre + " " + v
          * assertEquals("na na na na na na na na na na na na na Lambdaman!", loop.invoke("na", 13, "Lambdaman!"));
          * }
    - *

    + * * @apiNote The implementation of this method can be expressed as follows: *

    {@code
          * MethodHandle countedLoop(MethodHandle iterations, MethodHandle init, MethodHandle body) {
    @@ -5406,7 +5406,6 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
          * }
          * }
    * - *

    * @apiNote The implementation of this method can be expressed as follows: *

    {@code
          * MethodHandle countedLoop(MethodHandle start, MethodHandle end, MethodHandle init, MethodHandle body) {
    @@ -5607,7 +5606,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
          *   return v;
          * }
          * }
    - *

    + * * @apiNote Example: *

    {@code
          * // get an iterator from a list
    @@ -5622,7 +5621,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
          * List reversedList = Arrays.asList("e", "d", "c", "b", "a");
          * assertEquals(reversedList, (List) loop.invoke(list));
          * }
    - *

    + * * @apiNote The implementation of this method can be expressed approximately as follows: *

    {@code
          * MethodHandle iteratedLoop(MethodHandle iterator, MethodHandle init, MethodHandle body) {
    diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/package-info.java b/jdk/src/java.base/share/classes/java/lang/invoke/package-info.java
    index 7e4ce134ec0..e59b5ec9f43 100644
    --- a/jdk/src/java.base/share/classes/java/lang/invoke/package-info.java
    +++ b/jdk/src/java.base/share/classes/java/lang/invoke/package-info.java
    @@ -165,28 +165,33 @@
      * 

    * Given these rules, here are examples of legal bootstrap method declarations, * given various numbers {@code N} of extra arguments. - * The first rows (marked {@code *}) will work for any number of extra arguments. - *

    adaptable types
    QSLink-time checksInvocation-time checks
    QSLink-time checksInvocation-time checks
    PrimitivePrimitivePrimitivePrimitiveQ can be converted to S via a primitive widening conversionNone
    PrimitiveReferencePrimitiveReferenceS is a supertype of the Wrapper(Q)Cast from Wrapper(Q) to S
    ReferencePrimitiveReferencePrimitivefor parameter types: Q is a primitive wrapper and Primitive(Q) * can be widened to S *
    for return types: If Q is a primitive wrapper, check that @@ -175,7 +175,7 @@ import java.util.Arrays; * for example Number for numeric types
    ReferenceReferenceReferenceReferencefor parameter types: S is a supertype of Q *
    for return types: none
    Cast from Q to S
    + * The first row (marked {@code *}) will work for any number of extra arguments. + *
    * - * - * - * - * - * - * - * - * + * + * + * + * + * + * - * - * - * - * + * + * *
    Static argument types
    NSample bootstrap method
    *CallSite bootstrap(Lookup caller, String name, MethodType type, Object... args)
    * - * CallSite bootstrap(Object... args)
    * - * CallSite bootstrap(Object caller, Object... nameAndTypeWithArgs)
    0 - * CallSite bootstrap(Lookup caller, String name, MethodType type)
    0 - * CallSite bootstrap(Lookup caller, Object... nameAndType)
    1 + *
    NSample bootstrap method
    * + *
      + *
    • CallSite bootstrap(Lookup caller, String name, MethodType type, Object... args) + *
    • CallSite bootstrap(Object... args) + *
    • CallSite bootstrap(Object caller, Object... nameAndTypeWithArgs) + *
    0 + *
      + *
    • CallSite bootstrap(Lookup caller, String name, MethodType type) + *
    • CallSite bootstrap(Lookup caller, Object... nameAndType) + *
    1 * CallSite bootstrap(Lookup caller, String name, MethodType type, Object arg)
    2 - * CallSite bootstrap(Lookup caller, String name, MethodType type, Object... args)
    2 - * CallSite bootstrap(Lookup caller, String name, MethodType type, String... args)
    2CallSite bootstrap(Lookup caller, String name, MethodType type, String x, int y)
    2 + *
      + *
    • CallSite bootstrap(Lookup caller, String name, MethodType type, Object... args) + *
    • CallSite bootstrap(Lookup caller, String name, MethodType type, String... args) + *
    • CallSite bootstrap(Lookup caller, String name, MethodType type, String x, int y) + *
    * The last example assumes that the extra arguments are of type * {@code CONSTANT_String} and {@code CONSTANT_Integer}, respectively. diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedElement.java b/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedElement.java index fd15669931b..c466c82f90c 100644 --- a/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedElement.java +++ b/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedElement.java @@ -108,27 +108,39 @@ import sun.reflect.annotation.AnnotationType; * * * - * - * + * + * + * + * + * + * + * + * * * - * + * + * * - * + * + * * - * + * + * * - * + * + * * - * + * + * * - * + * + * * * *
    Overview of kind of presence detected by different AnnotatedElement methods
    Kind of Presence
    MethodDirectly PresentIndirectly PresentPresentAssociated
    MethodKind of Presence
    Return TypeSignatureDirectly PresentIndirectly PresentPresentAssociated
    {@code T}{@link #getAnnotation(Class) getAnnotation(Class<T>)} - * X
    {@code T}{@link #getAnnotation(Class) getAnnotation(Class<T>)} + * X
    {@code Annotation[]}{@link #getAnnotations getAnnotations()} - * X
    {@code Annotation[]}{@link #getAnnotations getAnnotations()} + * X
    {@code T[]}{@link #getAnnotationsByType(Class) getAnnotationsByType(Class<T>)} - * X
    {@code T[]}{@link #getAnnotationsByType(Class) getAnnotationsByType(Class<T>)} + * X
    {@code T}{@link #getDeclaredAnnotation(Class) getDeclaredAnnotation(Class<T>)} - * X
    {@code T}{@link #getDeclaredAnnotation(Class) getDeclaredAnnotation(Class<T>)} + * X
    {@code Annotation[]}{@link #getDeclaredAnnotations getDeclaredAnnotations()} - * X
    {@code Annotation[]}{@link #getDeclaredAnnotations getDeclaredAnnotations()} + * X
    {@code T[]}{@link #getDeclaredAnnotationsByType(Class) getDeclaredAnnotationsByType(Class<T>)} - * XX
    {@code T[]}{@link #getDeclaredAnnotationsByType(Class) getDeclaredAnnotationsByType(Class<T>)} + * XX
    From 1b9cc2f7a257f09e4ed2192a0653e28b6a097d25 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Fri, 11 Aug 2017 14:07:14 -0700 Subject: [PATCH 15/33] 8186153: Fix a11y and HTML issues in the java.math, java.text and java.time packages Reviewed-by: lancea, bpb --- .../share/classes/java/math/BigDecimal.java | 18 +- .../share/classes/java/math/RoundingMode.java | 264 +++++++++--------- .../classes/java/text/MessageFormat.java | 126 ++++----- .../java/time/chrono/HijrahChronology.java | 30 +- .../classes/java/time/chrono/IsoEra.java | 16 +- .../classes/java/time/chrono/MinguoEra.java | 18 +- .../java/time/chrono/ThaiBuddhistEra.java | 18 +- .../java/time/format/DateTimeFormatter.java | 100 +++---- .../classes/java/time/temporal/IsoFields.java | 16 +- .../java/time/temporal/WeekFields.java | 24 +- 10 files changed, 315 insertions(+), 315 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/math/BigDecimal.java b/jdk/src/java.base/share/classes/java/math/BigDecimal.java index f4e1f4985d6..cffed200b4e 100644 --- a/jdk/src/java.base/share/classes/java/math/BigDecimal.java +++ b/jdk/src/java.base/share/classes/java/math/BigDecimal.java @@ -120,18 +120,18 @@ import java.util.Arrays; * preferred scale for representing a result. The preferred * scale for each operation is listed in the table below. * - * - * + *
    Preferred Scales for Results of Arithmetic Operations - *
    + * * - * + * * * - * - * - * - * - * + * + * + * + * + * * *
    Preferred Scales for Results of Arithmetic Operations + *
    OperationPreferred Scale of Result
    OperationPreferred Scale of Result
    Addmax(addend.scale(), augend.scale())
    Subtractmax(minuend.scale(), subtrahend.scale())
    Multiplymultiplier.scale() + multiplicand.scale()
    Dividedividend.scale() - divisor.scale()
    Square rootradicand.scale()/2
    Addmax(addend.scale(), augend.scale())
    Subtractmax(minuend.scale(), subtrahend.scale())
    Multiplymultiplier.scale() + multiplicand.scale()
    Dividedividend.scale() - divisor.scale()
    Square rootradicand.scale()/2
    * diff --git a/jdk/src/java.base/share/classes/java/math/RoundingMode.java b/jdk/src/java.base/share/classes/java/math/RoundingMode.java index 79ecce36e7f..b4c37f66ed8 100644 --- a/jdk/src/java.base/share/classes/java/math/RoundingMode.java +++ b/jdk/src/java.base/share/classes/java/math/RoundingMode.java @@ -51,13 +51,13 @@ package java.math; * proper {@code MathContext}. A summary table showing the results * of these rounding operations for all rounding modes appears below. * - * + *
    * * - * * - * + * * * * @@ -66,18 +66,18 @@ package java.math; * * * - * + * * - * - * - * - * - * - * - * - * - * - * + * + * + * + * + * + * + * + * + * + * * *
    Summary of Rounding Operations Under Different Rounding Modes
    Result of rounding input to one digit with the given + *
    Input NumberResult of rounding input to one digit with the given * rounding mode
    Input Number {@code UP}{@code UP}{@code DOWN}{@code CEILING}{@code FLOOR}{@code HALF_EVEN}{@code UNNECESSARY}
    5.5 6 5 6 5 6 5 6 throw {@code ArithmeticException}
    2.5 3 2 3 2 3 2 2 throw {@code ArithmeticException}
    1.6 2 1 2 1 2 2 2 throw {@code ArithmeticException}
    1.1 2 1 2 1 1 1 1 throw {@code ArithmeticException}
    1.0 1 1 1 1 1 1 1 1
    -1.0 -1 -1 -1 -1 -1 -1 -1 -1
    -1.1 -2 -1 -1 -2 -1 -1 -1 throw {@code ArithmeticException}
    -1.6 -2 -1 -1 -2 -2 -2 -2 throw {@code ArithmeticException}
    -2.5 -3 -2 -2 -3 -3 -2 -2 throw {@code ArithmeticException}
    -5.5 -6 -5 -5 -6 -6 -5 -6 throw {@code ArithmeticException}
    5.5 6 5 6 5 6 5 6 throw {@code ArithmeticException}
    2.5 3 2 3 2 3 2 2 throw {@code ArithmeticException}
    1.6 2 1 2 1 2 2 2 throw {@code ArithmeticException}
    1.1 2 1 2 1 1 1 1 throw {@code ArithmeticException}
    1.0 1 1 1 1 1 1 1 1
    -1.0 -1 -1 -1 -1 -1 -1 -1 -1
    -1.1 -2 -1 -1 -2 -1 -1 -1 throw {@code ArithmeticException}
    -1.6 -2 -1 -1 -2 -2 -2 -2 throw {@code ArithmeticException}
    -2.5 -3 -2 -2 -3 -3 -2 -2 throw {@code ArithmeticException}
    -5.5 -6 -5 -5 -6 -6 -5 -6 throw {@code ArithmeticException}
    * @@ -104,23 +104,23 @@ public enum RoundingMode { * value. * *

    Example: - * - * + *
    Rounding mode UP Examples
    + * * - * - * + * - * - * - * - * - * - * - * - * - * - * - * + * + * + * + * + * + * + * + * + * + * + * * *
    Rounding mode UP Examples
    Input NumberInput rounded to one digit
    with {@code UP} rounding + *
    Input NumberInput rounded to one digit
    with {@code UP} rounding *
    5.5 6
    2.5 3
    1.6 2
    1.1 2
    1.0 1
    -1.0 -1
    -1.1 -2
    -1.6 -2
    -2.5 -3
    -5.5 -6
    5.5 6
    2.5 3
    1.6 2
    1.1 2
    1.0 1
    -1.0 -1
    -1.1 -2
    -1.6 -2
    -2.5 -3
    -5.5 -6
    */ @@ -132,23 +132,23 @@ public enum RoundingMode { * rounding mode never increases the magnitude of the calculated value. * *

    Example: - * - * + *
    Rounding mode DOWN Examples
    + * * - * - * + * - * - * - * - * - * - * - * - * - * - * - * + * + * + * + * + * + * + * + * + * + * + * * *
    Rounding mode DOWN Examples
    Input NumberInput rounded to one digit
    with {@code DOWN} rounding + *
    Input NumberInput rounded to one digit
    with {@code DOWN} rounding *
    5.5 5
    2.5 2
    1.6 1
    1.1 1
    1.0 1
    -1.0 -1
    -1.1 -1
    -1.6 -1
    -2.5 -2
    -5.5 -5
    5.5 5
    2.5 2
    1.6 1
    1.1 1
    1.0 1
    -1.0 -1
    -1.1 -1
    -1.6 -1
    -2.5 -2
    -5.5 -5
    */ @@ -161,23 +161,23 @@ public enum RoundingMode { * that this rounding mode never decreases the calculated value. * *

    Example: - * - * + *
    Rounding mode CEILING Examples
    + * * * * - * - * - * - * - * - * - * - * - * - * - * + * + * + * + * + * + * + * + * + * + * + * * *
    Rounding mode CEILING Examples
    Input NumberInput rounded to one digit
    with {@code CEILING} rounding *
    5.5 6
    2.5 3
    1.6 2
    1.1 2
    1.0 1
    -1.0 -1
    -1.1 -1
    -1.6 -1
    -2.5 -2
    -5.5 -5
    5.5 6
    2.5 3
    1.6 2
    1.1 2
    1.0 1
    -1.0 -1
    -1.1 -1
    -1.6 -1
    -2.5 -2
    -5.5 -5
    */ @@ -190,23 +190,23 @@ public enum RoundingMode { * this rounding mode never increases the calculated value. * *

    Example: - * - * + *
    Rounding mode FLOOR Examples
    + * * - * - * + * - * - * - * - * - * - * - * - * - * - * - * + * + * + * + * + * + * + * + * + * + * + * * *
    Rounding mode FLOOR Examples
    Input NumberInput rounded to one digit
    with {@code FLOOR} rounding + *
    Input NumberInput rounded to one digit
    with {@code FLOOR} rounding *
    5.5 5
    2.5 2
    1.6 1
    1.1 1
    1.0 1
    -1.0 -1
    -1.1 -2
    -1.6 -2
    -2.5 -3
    -5.5 -6
    5.5 5
    2.5 2
    1.6 1
    1.1 1
    1.0 1
    -1.0 -1
    -1.1 -2
    -1.6 -2
    -2.5 -3
    -5.5 -6
    */ @@ -221,23 +221,23 @@ public enum RoundingMode { * mode commonly taught at school. * *

    Example: - * - * + *
    Rounding mode HALF_UP Examples
    + * * - * - * + * - * - * - * - * - * - * - * - * - * - * - * + * + * + * + * + * + * + * + * + * + * + * * *
    Rounding mode HALF_UP Examples
    Input NumberInput rounded to one digit
    with {@code HALF_UP} rounding + *
    Input NumberInput rounded to one digit
    with {@code HALF_UP} rounding *
    5.5 6
    2.5 3
    1.6 2
    1.1 1
    1.0 1
    -1.0 -1
    -1.1 -1
    -1.6 -2
    -2.5 -3
    -5.5 -6
    5.5 6
    2.5 3
    1.6 2
    1.1 1
    1.0 1
    -1.0 -1
    -1.1 -1
    -1.6 -2
    -2.5 -3
    -5.5 -6
    */ @@ -251,23 +251,23 @@ public enum RoundingMode { * {@code RoundingMode.DOWN}. * *

    Example: - * - * + *
    Rounding mode HALF_DOWN Examples
    + * * - * - * + * - * - * - * - * - * - * - * - * - * - * - * + * + * + * + * + * + * + * + * + * + * + * * *
    Rounding mode HALF_DOWN Examples
    Input NumberInput rounded to one digit
    with {@code HALF_DOWN} rounding + *
    Input NumberInput rounded to one digit
    with {@code HALF_DOWN} rounding *
    5.5 5
    2.5 2
    1.6 2
    1.1 1
    1.0 1
    -1.0 -1
    -1.1 -1
    -1.6 -2
    -2.5 -2
    -5.5 -5
    5.5 5
    2.5 2
    1.6 2
    1.1 1
    1.0 1
    -1.0 -1
    -1.1 -1
    -1.6 -2
    -2.5 -2
    -5.5 -5
    */ @@ -288,23 +288,23 @@ public enum RoundingMode { * arithmetic in Java. * *

    Example: - * - * + *
    Rounding mode HALF_EVEN Examples
    + * * - * - * + * - * - * - * - * - * - * - * - * - * - * - * + * + * + * + * + * + * + * + * + * + * + * * *
    Rounding mode HALF_EVEN Examples
    Input NumberInput rounded to one digit
    with {@code HALF_EVEN} rounding + *
    Input NumberInput rounded to one digit
    with {@code HALF_EVEN} rounding *
    5.5 6
    2.5 2
    1.6 2
    1.1 1
    1.0 1
    -1.0 -1
    -1.1 -1
    -1.6 -2
    -2.5 -2
    -5.5 -6
    5.5 6
    2.5 2
    1.6 2
    1.1 1
    1.0 1
    -1.0 -1
    -1.1 -1
    -1.6 -2
    -2.5 -2
    -5.5 -6
    */ @@ -316,23 +316,23 @@ public enum RoundingMode { * specified on an operation that yields an inexact result, an * {@code ArithmeticException} is thrown. *

    Example: - * - * + *
    Rounding mode UNNECESSARY Examples
    + * * - * - * + * - * - * - * - * - * - * - * - * - * - * - * + * + * + * + * + * + * + * + * + * + * + * * *
    Rounding mode UNNECESSARY Examples
    Input NumberInput rounded to one digit
    with {@code UNNECESSARY} rounding + *
    Input NumberInput rounded to one digit
    with {@code UNNECESSARY} rounding *
    5.5 throw {@code ArithmeticException}
    2.5 throw {@code ArithmeticException}
    1.6 throw {@code ArithmeticException}
    1.1 throw {@code ArithmeticException}
    1.0 1
    -1.0 -1
    -1.1 throw {@code ArithmeticException}
    -1.6 throw {@code ArithmeticException}
    -2.5 throw {@code ArithmeticException}
    -5.5 throw {@code ArithmeticException}
    5.5 throw {@code ArithmeticException}
    2.5 throw {@code ArithmeticException}
    1.6 throw {@code ArithmeticException}
    1.1 throw {@code ArithmeticException}
    1.0 1
    -1.0 -1
    -1.1 throw {@code ArithmeticException}
    -1.6 throw {@code ArithmeticException}
    -2.5 throw {@code ArithmeticException}
    -5.5 throw {@code ArithmeticException}
    */ diff --git a/jdk/src/java.base/share/classes/java/text/MessageFormat.java b/jdk/src/java.base/share/classes/java/text/MessageFormat.java index b80eb054f51..dfed999a5df 100644 --- a/jdk/src/java.base/share/classes/java/text/MessageFormat.java +++ b/jdk/src/java.base/share/classes/java/text/MessageFormat.java @@ -150,73 +150,73 @@ import java.util.Locale; * Shows how FormatType and FormatStyle values map to Format instances * * - * FormatType - * FormatStyle - * Subformat Created + * FormatType + * FormatStyle + * Subformat Created * * * - * (none) - * (none) - * null + * (none) + * (none) + * {@code null} * - * number - * (none) - * {@link NumberFormat#getInstance(Locale) NumberFormat.getInstance}{@code (getLocale())} + * {@code number} + * (none) + * {@link NumberFormat#getInstance(Locale) NumberFormat.getInstance}{@code (getLocale())} * - * integer - * {@link NumberFormat#getIntegerInstance(Locale) NumberFormat.getIntegerInstance}{@code (getLocale())} + * {@code integer} + * {@link NumberFormat#getIntegerInstance(Locale) NumberFormat.getIntegerInstance}{@code (getLocale())} * - * currency - * {@link NumberFormat#getCurrencyInstance(Locale) NumberFormat.getCurrencyInstance}{@code (getLocale())} + * {@code currency} + * {@link NumberFormat#getCurrencyInstance(Locale) NumberFormat.getCurrencyInstance}{@code (getLocale())} * - * percent - * {@link NumberFormat#getPercentInstance(Locale) NumberFormat.getPercentInstance}{@code (getLocale())} + * {@code percent} + * {@link NumberFormat#getPercentInstance(Locale) NumberFormat.getPercentInstance}{@code (getLocale())} * - * SubformatPattern - * {@code new} {@link DecimalFormat#DecimalFormat(String,DecimalFormatSymbols) DecimalFormat}{@code (subformatPattern,} {@link DecimalFormatSymbols#getInstance(Locale) DecimalFormatSymbols.getInstance}{@code (getLocale()))} + * SubformatPattern + * {@code new} {@link DecimalFormat#DecimalFormat(String,DecimalFormatSymbols) DecimalFormat}{@code (subformatPattern,} {@link DecimalFormatSymbols#getInstance(Locale) DecimalFormatSymbols.getInstance}{@code (getLocale()))} * - * date - * (none) - * {@link DateFormat#getDateInstance(int,Locale) DateFormat.getDateInstance}{@code (}{@link DateFormat#DEFAULT}{@code , getLocale())} + * {@code date} + * (none) + * {@link DateFormat#getDateInstance(int,Locale) DateFormat.getDateInstance}{@code (}{@link DateFormat#DEFAULT}{@code , getLocale())} * - * short - * {@link DateFormat#getDateInstance(int,Locale) DateFormat.getDateInstance}{@code (}{@link DateFormat#SHORT}{@code , getLocale())} + * {@code short} + * {@link DateFormat#getDateInstance(int,Locale) DateFormat.getDateInstance}{@code (}{@link DateFormat#SHORT}{@code , getLocale())} * - * medium - * {@link DateFormat#getDateInstance(int,Locale) DateFormat.getDateInstance}{@code (}{@link DateFormat#DEFAULT}{@code , getLocale())} + * {@code medium} + * {@link DateFormat#getDateInstance(int,Locale) DateFormat.getDateInstance}{@code (}{@link DateFormat#DEFAULT}{@code , getLocale())} * - * long - * {@link DateFormat#getDateInstance(int,Locale) DateFormat.getDateInstance}{@code (}{@link DateFormat#LONG}{@code , getLocale())} + * {@code long} + * {@link DateFormat#getDateInstance(int,Locale) DateFormat.getDateInstance}{@code (}{@link DateFormat#LONG}{@code , getLocale())} * - * full - * {@link DateFormat#getDateInstance(int,Locale) DateFormat.getDateInstance}{@code (}{@link DateFormat#FULL}{@code , getLocale())} + * {@code full} + * {@link DateFormat#getDateInstance(int,Locale) DateFormat.getDateInstance}{@code (}{@link DateFormat#FULL}{@code , getLocale())} * - * SubformatPattern - * {@code new} {@link SimpleDateFormat#SimpleDateFormat(String,Locale) SimpleDateFormat}{@code (subformatPattern, getLocale())} + * SubformatPattern + * {@code new} {@link SimpleDateFormat#SimpleDateFormat(String,Locale) SimpleDateFormat}{@code (subformatPattern, getLocale())} * - * time - * (none) - * {@link DateFormat#getTimeInstance(int,Locale) DateFormat.getTimeInstance}{@code (}{@link DateFormat#DEFAULT}{@code , getLocale())} + * {@code time} + * (none) + * {@link DateFormat#getTimeInstance(int,Locale) DateFormat.getTimeInstance}{@code (}{@link DateFormat#DEFAULT}{@code , getLocale())} * - * short - * {@link DateFormat#getTimeInstance(int,Locale) DateFormat.getTimeInstance}{@code (}{@link DateFormat#SHORT}{@code , getLocale())} + * {@code short} + * {@link DateFormat#getTimeInstance(int,Locale) DateFormat.getTimeInstance}{@code (}{@link DateFormat#SHORT}{@code , getLocale())} * - * medium - * {@link DateFormat#getTimeInstance(int,Locale) DateFormat.getTimeInstance}{@code (}{@link DateFormat#DEFAULT}{@code , getLocale())} + * {@code medium} + * {@link DateFormat#getTimeInstance(int,Locale) DateFormat.getTimeInstance}{@code (}{@link DateFormat#DEFAULT}{@code , getLocale())} * - * long - * {@link DateFormat#getTimeInstance(int,Locale) DateFormat.getTimeInstance}{@code (}{@link DateFormat#LONG}{@code , getLocale())} + * {@code long} + * {@link DateFormat#getTimeInstance(int,Locale) DateFormat.getTimeInstance}{@code (}{@link DateFormat#LONG}{@code , getLocale())} * - * full - * {@link DateFormat#getTimeInstance(int,Locale) DateFormat.getTimeInstance}{@code (}{@link DateFormat#FULL}{@code , getLocale())} + * {@code full} + * {@link DateFormat#getTimeInstance(int,Locale) DateFormat.getTimeInstance}{@code (}{@link DateFormat#FULL}{@code , getLocale())} * - * SubformatPattern - * {@code new} {@link SimpleDateFormat#SimpleDateFormat(String,Locale) SimpleDateFormat}{@code (subformatPattern, getLocale())} + * SubformatPattern + * {@code new} {@link SimpleDateFormat#SimpleDateFormat(String,Locale) SimpleDateFormat}{@code (subformatPattern, getLocale())} * - * choice - * SubformatPattern - * {@code new} {@link ChoiceFormat#ChoiceFormat(String) ChoiceFormat}{@code (subformatPattern)} + * {@code choice} + * SubformatPattern + * {@code new} {@link ChoiceFormat#ChoiceFormat(String) ChoiceFormat}{@code (subformatPattern)} * * * @@ -776,44 +776,40 @@ public class MessageFormat extends Format { * Examples of subformat,argument,and formatted text * * - * Subformat - * Argument - * Formatted Text + * Subformat + * Argument + * Formatted Text * * * - * any - * unavailable + * any + * unavailable * "{" + argumentIndex + "}" * - * any - * null + * null * "null" * - * instanceof ChoiceFormat - * any + * instanceof ChoiceFormat + * any * subformat.format(argument).indexOf('{') >= 0 ?
    * (new MessageFormat(subformat.format(argument), getLocale())).format(argument) : * subformat.format(argument)
    * - * != null - * any + * != null + * any * subformat.format(argument) * - * null - * instanceof Number + * null + * instanceof Number * NumberFormat.getInstance(getLocale()).format(argument) * - * null - * instanceof Date + * instanceof Date * DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, getLocale()).format(argument) * - * null - * instanceof String + * instanceof String * argument * - * null - * any + * any * argument.toString() * * diff --git a/jdk/src/java.base/share/classes/java/time/chrono/HijrahChronology.java b/jdk/src/java.base/share/classes/java/time/chrono/HijrahChronology.java index 0ec1b591bc2..bc702a44d07 100644 --- a/jdk/src/java.base/share/classes/java/time/chrono/HijrahChronology.java +++ b/jdk/src/java.base/share/classes/java/time/chrono/HijrahChronology.java @@ -103,19 +103,19 @@ import sun.util.logging.PlatformLogger; * *

    * CLDR and LDML identify variants: - * + *
    * * * - * - * - * - * + * + * + * + * * * * * - * + * * * * @@ -148,38 +148,38 @@ import sun.util.logging.PlatformLogger; *

    * The Hijrah property resource is a set of properties that describe the calendar. * The syntax is defined by {@code java.util.Properties#load(Reader)}. - *

    Variants of Hijrah Calendars
    Chronology IDCalendar TypeLocale extension, see {@link java.util.Locale}DescriptionChronology IDCalendar TypeLocale extension, see {@link java.util.Locale}Description
    Hijrah-umalquraHijrah-umalquraislamic-umalquraca-islamic-umalquraIslamic - Umm Al-Qura calendar of Saudi Arabia
    + *
    * * * - * - * - * + * + * + * * * * * - * + * * * * * - * + * * * * * - * + * * * * * - * + * * * * * - * + * * *
    Configuration of Hijrah Calendar
    Property Name Property value Description Property NameProperty valueDescription
    ididChronology Id, for example, "Hijrah-umalqura"The Id of the calendar in common usage
    typetypeCalendar type, for example, "islamic-umalqura"LDML defines the calendar types
    versionversionVersion, for example: "1.8.0_1"The version of the Hijrah variant data
    iso-startiso-startISO start date, formatted as {@code yyyy-MM-dd}, for example: "1900-04-30"The ISO date of the first day of the minimum Hijrah year.
    yyyy - a numeric 4 digit year, for example "1434"yyyy - a numeric 4 digit year, for example "1434"The value is a sequence of 12 month lengths, * for example: "29 30 29 30 29 30 30 30 29 30 29 29"The lengths of the 12 months of the year separated by whitespace. diff --git a/jdk/src/java.base/share/classes/java/time/chrono/IsoEra.java b/jdk/src/java.base/share/classes/java/time/chrono/IsoEra.java index 702fabdf920..887d76f72b6 100644 --- a/jdk/src/java.base/share/classes/java/time/chrono/IsoEra.java +++ b/jdk/src/java.base/share/classes/java/time/chrono/IsoEra.java @@ -70,27 +70,27 @@ import java.time.DateTimeException; * A definition has therefore been created with two eras - 'Current era' (CE) for * years on or after 0001-01-01 (ISO), and 'Before current era' (BCE) for years before that. * - * + *
    * * * - * - * - * + * + * + * * * * * - * + * * * - * + * * * - * + * * * - * + * * * *
    ISO years and eras
    year-of-eraeraproleptic-yearyear-of-eraeraproleptic-year
    2CE22CE2
    1CE11CE1
    1BCE01BCE0
    2BCE-12BCE-1
    diff --git a/jdk/src/java.base/share/classes/java/time/chrono/MinguoEra.java b/jdk/src/java.base/share/classes/java/time/chrono/MinguoEra.java index edac0ec02e7..9c227884994 100644 --- a/jdk/src/java.base/share/classes/java/time/chrono/MinguoEra.java +++ b/jdk/src/java.base/share/classes/java/time/chrono/MinguoEra.java @@ -71,28 +71,28 @@ import java.time.DateTimeException; * All previous years, zero or earlier in the proleptic count or one and greater * in the year-of-era count, are part of the 'Before Republic of China' era. * - * + *
    * * * - * - * - * - * + * + * + * + * * * * * - * + * * * - * + * * * - * + * * * - * + * * * *
    Minguo years and eras
    year-of-eraeraproleptic-yearISO proleptic-yearyear-of-eraeraproleptic-yearISO proleptic-year
    2ROC219132ROC21913
    1ROC119121ROC11912
    1BEFORE_ROC019111BEFORE_ROC01911
    2BEFORE_ROC-119102BEFORE_ROC-11910
    diff --git a/jdk/src/java.base/share/classes/java/time/chrono/ThaiBuddhistEra.java b/jdk/src/java.base/share/classes/java/time/chrono/ThaiBuddhistEra.java index 53cb5d870be..46c0f112bd5 100644 --- a/jdk/src/java.base/share/classes/java/time/chrono/ThaiBuddhistEra.java +++ b/jdk/src/java.base/share/classes/java/time/chrono/ThaiBuddhistEra.java @@ -71,28 +71,28 @@ import java.time.DateTimeException; * All previous years, zero or earlier in the proleptic count or one and greater * in the year-of-era count, are part of the 'Before Buddhist' era. * - * + *
    * * * - * - * - * - * + * + * + * + * * * * * - * + * * * - * + * * * - * + * * * - * + * * * *
    Buddhist years and eras
    year-of-eraeraproleptic-yearISO proleptic-yearyear-of-eraeraproleptic-yearISO proleptic-year
    2BE2-5422BE2-542
    1BE1-5431BE1-543
    1BEFORE_BE0-5441BEFORE_BE0-544
    2BEFORE_BE-1-5452BEFORE_BE-1-545
    diff --git a/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatter.java b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatter.java index 7315a9a3544..79d2f061508 100644 --- a/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatter.java +++ b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatter.java @@ -150,13 +150,13 @@ import java.util.Set; * implementation of {@code java.text.Format}. * *

    Predefined Formatters

    - * + *
    * * * - * - * - * + * + * + * * * * @@ -276,56 +276,60 @@ import java.util.Set; *

    * All letters 'A' to 'Z' and 'a' to 'z' are reserved as pattern letters. The * following pattern letters are defined: - *

    - *  Symbol  Meaning                     Presentation      Examples
    - *  ------  -------                     ------------      -------
    - *   G       era                         text              AD; Anno Domini; A
    - *   u       year                        year              2004; 04
    - *   y       year-of-era                 year              2004; 04
    - *   D       day-of-year                 number            189
    - *   M/L     month-of-year               number/text       7; 07; Jul; July; J
    - *   d       day-of-month                number            10
    - *   g       modified-julian-day         number            2451334
    + * 
    Predefined Formatters
    FormatterDescriptionExampleFormatterDescriptionExample
    + * + * + * + * + * + * + * + * + * + * + * + * * - * Q/q quarter-of-year number/text 3; 03; Q3; 3rd quarter - * Y week-based-year year 1996; 96 - * w week-of-week-based-year number 27 - * W week-of-month number 4 - * E day-of-week text Tue; Tuesday; T - * e/c localized day-of-week number/text 2; 02; Tue; Tuesday; T - * F day-of-week-in-month number 3 + * + * + * + * + * + * + * * - * a am-pm-of-day text PM - * h clock-hour-of-am-pm (1-12) number 12 - * K hour-of-am-pm (0-11) number 0 - * k clock-hour-of-day (1-24) number 24 + * + * + * + * * - * H hour-of-day (0-23) number 0 - * m minute-of-hour number 30 - * s second-of-minute number 55 - * S fraction-of-second fraction 978 - * A milli-of-day number 1234 - * n nano-of-second number 987654321 - * N nano-of-day number 1234000000 + * + * + * + * + * + * + * * - * V time-zone ID zone-id America/Los_Angeles; Z; -08:30 - * v generic time-zone name zone-name Pacific Time; PT - * z time-zone name zone-name Pacific Standard Time; PST - * O localized zone-offset offset-O GMT+8; GMT+08:00; UTC-08:00 - * X zone-offset 'Z' for zero offset-X Z; -08; -0830; -08:30; -083015; -08:30:15 - * x zone-offset offset-x +0000; -08; -0830; -08:30; -083015; -08:30:15 - * Z zone-offset offset-Z +0000; -0800; -08:00 + * + * + * + * + * + * + * * - * p pad next pad modifier 1 + * * - * ' escape for text delimiter - * '' single quote literal ' - * [ optional section start - * ] optional section end - * # reserved for future use - * { reserved for future use - * } reserved for future use - * + * + * + * + * + * + * + * + * + *
    Pattern Letters and Symbols
    Symbol Meaning Presentation Examples
    G era text AD; Anno Domini; A
    u year year 2004; 04
    y year-of-era year 2004; 04
    D day-of-year number 189
    M/L month-of-year number/text 7; 07; Jul; July; J
    d day-of-month number 10
    g modified-julian-day number 2451334
    Q/q quarter-of-year number/text 3; 03; Q3; 3rd quarter
    Y week-based-year year 1996; 96
    w week-of-week-based-year number 27
    W week-of-month number 4
    E day-of-week text Tue; Tuesday; T
    e/c localized day-of-week number/text 2; 02; Tue; Tuesday; T
    F day-of-week-in-month number 3
    a am-pm-of-day text PM
    h clock-hour-of-am-pm (1-12) number 12
    K hour-of-am-pm (0-11) number 0
    k clock-hour-of-day (1-24) number 24
    H hour-of-day (0-23) number 0
    m minute-of-hour number 30
    s second-of-minute number 55
    S fraction-of-second fraction 978
    A milli-of-day number 1234
    n nano-of-second number 987654321
    N nano-of-day number 1234000000
    V time-zone ID zone-id America/Los_Angeles; Z; -08:30
    v generic time-zone name zone-name Pacific Time; PT
    z time-zone name zone-name Pacific Standard Time; PST
    O localized zone-offset offset-O GMT+8; GMT+08:00; UTC-08:00
    X zone-offset 'Z' for zero offset-X Z; -08; -0830; -08:30; -083015; -08:30:15
    x zone-offset offset-x +0000; -08; -0830; -08:30; -083015; -08:30:15
    Z zone-offset offset-Z +0000; -0800; -08:00
    p pad next pad modifier 1
    ' escape for text delimiter
    '' single quote literal '
    [ optional section start
    ] optional section end
    # reserved for future use
    { reserved for future use
    } reserved for future use
    *

    * The count of pattern letters determines the format. *

    diff --git a/jdk/src/java.base/share/classes/java/time/temporal/IsoFields.java b/jdk/src/java.base/share/classes/java/time/temporal/IsoFields.java index 9740a9defc0..0b910830126 100644 --- a/jdk/src/java.base/share/classes/java/time/temporal/IsoFields.java +++ b/jdk/src/java.base/share/classes/java/time/temporal/IsoFields.java @@ -136,18 +136,18 @@ import sun.util.locale.provider.LocaleResources; *

    * For example: * - * + *
    * * - * + * * * - * - * - * - * - * - * + * + * + * + * + * + * * *
    Examples of Week based Years
    DateDay-of-weekField values
    DateDay-of-weekField values
    2008-12-28SundayWeek 52 of week-based-year 2008
    2008-12-29MondayWeek 1 of week-based-year 2009
    2008-12-31WednesdayWeek 1 of week-based-year 2009
    2009-01-01ThursdayWeek 1 of week-based-year 2009
    2009-01-04SundayWeek 1 of week-based-year 2009
    2009-01-05MondayWeek 2 of week-based-year 2009
    2008-12-28SundayWeek 52 of week-based-year 2008
    2008-12-29MondayWeek 1 of week-based-year 2009
    2008-12-31WednesdayWeek 1 of week-based-year 2009
    2009-01-01ThursdayWeek 1 of week-based-year 2009
    2009-01-04SundayWeek 1 of week-based-year 2009
    2009-01-05MondayWeek 2 of week-based-year 2009
    * diff --git a/jdk/src/java.base/share/classes/java/time/temporal/WeekFields.java b/jdk/src/java.base/share/classes/java/time/temporal/WeekFields.java index 2f13368d28f..60478772d9f 100644 --- a/jdk/src/java.base/share/classes/java/time/temporal/WeekFields.java +++ b/jdk/src/java.base/share/classes/java/time/temporal/WeekFields.java @@ -130,17 +130,17 @@ import sun.util.locale.provider.LocaleResources; * * * - * - * + * + * * * - * + * * - * + * * - * + * * - * + * * * *
    Examples of WeekFields
    DateDay-of-weekFirst day: Monday
    Minimal days: 4
    First day: Monday
    Minimal days: 5
    DateDay-of-weekFirst day: Monday
    Minimal days: 4
    First day: Monday
    Minimal days: 5
    2008-12-31Wednesday
    2008-12-31WednesdayWeek 5 of December 2008Week 5 of December 2008
    2009-01-01Thursday
    2009-01-01ThursdayWeek 1 of January 2009Week 0 of January 2009
    2009-01-04Sunday
    2009-01-04SundayWeek 1 of January 2009Week 0 of January 2009
    2009-01-05Monday
    2009-01-05MondayWeek 2 of January 2009Week 1 of January 2009
    @@ -164,17 +164,17 @@ import sun.util.locale.provider.LocaleResources; * * * - * - * + * + * * * - * + * * - * + * * - * + * * - * + * * * *
    Examples of WeekFields for week-based-year
    DateDay-of-weekFirst day: Monday
    Minimal days: 4
    First day: Monday
    Minimal days: 5
    DateDay-of-weekFirst day: Monday
    Minimal days: 4
    First day: Monday
    Minimal days: 5
    2008-12-31Wednesday
    2008-12-31WednesdayWeek 1 of 2009Week 53 of 2008
    2009-01-01Thursday
    2009-01-01ThursdayWeek 1 of 2009Week 53 of 2008
    2009-01-04Sunday
    2009-01-04SundayWeek 1 of 2009Week 53 of 2008
    2009-01-05Monday
    2009-01-05MondayWeek 2 of 2009Week 1 of 2009
    From 577dc3fca285ea8086098d236b4159f0d4e9a739 Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Fri, 11 Aug 2017 15:44:44 -0700 Subject: [PATCH 16/33] 8186157: (scanner) Modify java/util/Scanner/ScanTest.java to fail if Engilsh Locale unavailable Fail if the English locale is not available on the system Reviewed-by: lancea --- jdk/test/java/util/Scanner/ScanTest.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/jdk/test/java/util/Scanner/ScanTest.java b/jdk/test/java/util/Scanner/ScanTest.java index 0f1abcbd8b5..44ee2b0b463 100644 --- a/jdk/test/java/util/Scanner/ScanTest.java +++ b/jdk/test/java/util/Scanner/ScanTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,7 +59,14 @@ public class ScanTest { !"ja".equals(lang)) { //Before we have resource to improve the test to be ready for //arbitrary locale, force the default locale to be "English" - //for now. + //for now. First we check whether the "English" locale is + //available on the system as it could be absent due to varying + //configurations. + if (!Arrays.asList(Locale.getAvailableLocales()) + .contains(Locale.ENGLISH)) { + throw new RuntimeException + ("The \"English\" Locale is unavailable on this system"); + } Locale.setDefault(Locale.ENGLISH); } skipTest(); From 34afeced211cd7115e2529b043c1e57dfa1291fe Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Fri, 28 Jul 2017 14:06:28 +0200 Subject: [PATCH 17/33] 8185500: [TESTBUG] Add keywords headful/printer in java/awt and javax tests Add new keyword 'printer'. Some minor test fixes to show headless exception. Add some @requires windows. Reviewed-by: serb, mbaesken --- jdk/test/TEST.ROOT | 6 ++-- .../DefaultMenuBar/DefaultMenuBarTest.java | 5 ++-- .../ScreenMenu/ScreenMenuMemoryLeakTest.java | 7 +++-- .../awt/Choice/ChoiceHiDpi/ChoiceTest.java | 5 ++-- .../DesktopGtkLoadTest.java | 6 ++-- .../Dialog/CloseDialog/CloseDialogTest.java | 4 ++- .../Modal/NestedModalDialogTest.java | 24 ++++++++------- .../Modeless/NestedModelessDialogTest.java | 24 ++++++++------- .../DisplayChangedTest.java | 30 ++++++++----------- .../EmbeddedFrameGrabTest.java | 27 ++++++++--------- .../LoopRobustness/LoopRobustness.html | 3 +- .../awt/EventQueue/6980209/bug6980209.java | 14 +++++---- .../FileDialogIconTest.java | 10 ++++--- .../FocusEmbeddedFrameTest.java | 29 +++++++++--------- .../ButtonGroupLayoutTraversalTest.java | 16 +++++----- .../RequestFocusByCauseTest.java | 20 +++++++------ .../java/awt/FontClass/HelvLtOblTest.java | 5 ++-- .../FontClass/SurrogateTest/SuppCharTest.java | 5 ++-- .../awt/Frame/8158918/SetExtendedState.java | 6 ++-- .../DecoratedFrameInsetsTest.java | 5 ++-- .../ExceptionOnSetExtendedStateTest.java | 16 +++++----- .../MaximizedByPlatform.java | 10 ++++--- .../NormalToIconifiedTest.java | 5 ++-- .../MaximizedMovedWindow.java | 6 ++-- .../SetMaximizedBounds.java | 6 ++-- .../Frame/WindowDragTest/WindowDragTest.java | 21 ++++++------- .../CurrentDisplayModeTest.java | 3 +- .../DisplayModes/CompareToXrandrTest.java | 3 +- .../DefaultPolicyChange_Swing.java | 17 ++++++----- .../java/awt/MenuBar/8007006/bug8007006.java | 5 ++-- .../FullscreenEnterEventTest.java | 6 ++-- .../HiDPIMouseClick/HiDPIRobotMouseClick.java | 7 +++-- .../HiDPIRobotScreenCaptureTest.java | 7 +++-- .../ScrollbarMouseWheelTest.java | 4 ++- .../FullScreenAfterSplash.java | 4 ++- .../unix/UnixMultiResolutionSplashTest.java | 4 ++- .../AutoScrollOnSelectAndAppend.java | 15 +++++----- .../OverScrollTest/OverScrollTest.java | 15 +++++----- .../OverScrollTest/OverScrollTest.java | 15 +++++----- .../GetScreenLocationTest.java | 3 +- .../SetWindowLocationByPlatformTest.java | 7 +++-- .../IOExceptionIfEncodedURLTest.java | 21 ++++++------- .../IOExceptionIfEncodedURLTest.sh | 1 + .../MultiResolutionDragImageTest.java | 3 +- .../HTMLDataFlavors/HTMLDataFlavorTest.java | 26 ++++++++-------- .../event/KeyEvent/8020209/bug8020209.java | 5 ++-- .../DeadKey/DeadKeyMacOSXInputText.java | 6 ++-- .../event/KeyEvent/DeadKey/deadKeyMacOSX.java | 5 ++-- .../awt/font/TextLayout/TestSinhalaChar.java | 4 ++- .../HiDPIPropertiesWindowsTest.java | 6 ++-- .../java/awt/im/6396526/IMLookAndFeel.java | 11 +++---- jdk/test/java/awt/im/8041990/bug8041990.java | 17 ++++++----- .../awt/image/MultiResolutionImageTest.java | 4 ++- .../multiresolution/Corrupted2XImageTest.java | 5 ++-- .../MultiResolutionToolkitImageTest.java | 4 ++- .../awt/keyboard/AllKeyCode/AllKeyCode.java | 15 +++++----- .../AltPlusNumberKeyCombinationsTest.java | 19 ++++++------ .../awt/print/PrinterJob/CheckPrivilege.java | 3 +- .../awt/print/PrinterJob/ExceptionTest.java | 1 + .../ImagePrinting/NullClipARGB.java | 3 +- .../java/awt/print/PrinterJob/Margins.java | 3 +- .../java/awt/print/PrinterJob/PaintText.java | 3 +- .../awt/print/PrinterJob/PrintCrashTest.java | 3 +- .../awt/print/PrinterJob/PrintTextPane.java | 15 +++++----- .../awt/print/PrinterJob/PrtException.java | 16 +++++----- jdk/test/javax/print/CheckDupFlavor.java | 6 ++-- jdk/test/javax/print/PrintSE/PrintSE.sh | 7 +++-- .../javax/print/attribute/AttributeTest.java | 6 ++-- .../print/attribute/GetCopiesSupported.java | 16 +++++----- .../print/attribute/SidesPageRangesTest.java | 9 ++++-- .../attribute/SupportedPrintableAreas.java | 5 ++-- .../JButton/8151303/PressedIconTest.java | 4 ++- .../6567433/UpdateUIRecursionTest.java | 6 ++-- .../swing/JComboBox/8019180/Test8019180.java | 5 ++-- .../8041909/ActionListenerExceptionTest.java | 14 +++++---- .../WindowsComboBoxSizeTest.java | 3 +- .../swing/JComponent/4337267/bug4337267.java | 5 ++-- .../swing/JComponent/8043610/bug8043610.java | 19 ++++++------ .../swing/JDialog/6639507/bug6639507.java | 15 ++++++---- .../JFileChooser/6713352/bug6713352.java | 18 ++++++----- .../JFileChooser/6817933/Test6817933.java | 6 ++-- .../JFileChooser/8010718/bug8010718.java | 4 ++- .../JFileChooser/8013442/Test8013442.java | 5 ++-- .../8152677/SelectAllFilesFilterTest.java | 5 ++-- .../swing/JFrame/8016356/bug8016356.java | 21 +++++++------ .../NSTexturedJFrame/NSTexturedJFrame.java | 4 ++- .../6288609/TestJInternalFrameDispose.java | 6 ++-- .../JInternalFrame/8075314/bug8075314.java | 21 ++++++------- .../8145060/TestJInternalFrameMinimize.java | 4 ++- .../8160248/JInternalFrameDraggingTest.java | 4 ++- .../DockIconRepaint/DockIconRepaint.java | 4 ++- .../swing/JInternalFrame/Test6325652.java | 5 ++-- .../JList/6567433/UpdateUIRecursionTest.java | 6 ++-- .../javax/swing/JList/8161483/Bug8161483.java | 9 +++--- .../javax/swing/JMenu/6538132/bug6538132.java | 22 ++++++++------ .../javax/swing/JMenu/8067346/bug8067346.java | 15 ++++++---- .../8139169/ScreenMenuBarInputTwice.java | 7 +++-- .../JMenuItem/8152981/MenuItemIconTest.java | 6 ++-- .../CloseOnMouseClickPropertyTest.java | 9 ++++-- .../ActionListenerCalledTwiceTest.java | 4 ++- .../ClickMenuTestManual.java | 7 +++-- .../swing/JOptionPane/8081019/bug8081019.java | 3 +- .../swing/JPopupMenu/6217905/bug6217905.java | 23 +++++++------- .../swing/JPopupMenu/7154841/bug7154841.java | 19 ++++++------ .../swing/JTabbedPane/7170310/bug7170310.java | 6 ++-- .../JTable/6567433/UpdateUIRecursionTest.java | 6 ++-- .../6567433/UpdateUIRecursionTest.java | 6 ++-- .../swing/JTextArea/6940863/bug6940863.java | 7 +++-- .../ScrollbarFlicker/ScrollFlickerTest.java | 6 ++-- .../JTree/6567433/UpdateUIRecursionTest.java | 6 ++-- .../ProgressMonitorEscapeKeyPress.java | 6 ++-- .../swing/Security/6938813/bug6938813.java | 3 +- .../ToolTipManager/7123767/bug7123767.java | 5 ++-- .../UnninstallUIMemoryLeaks.java | 5 ++-- .../plaf/aqua/CustomComboBoxFocusTest.java | 20 +++++++------ .../swing/plaf/basic/6866751/bug6866751.java | 17 ++++++----- .../BasicComboPopup/8154069/Bug8154069.java | 5 ++-- .../basic/BasicHTML/4960629/bug4960629.java | 18 ++++++----- .../plaf/basic/BasicLabelUI/bug7172652.java | 21 +++++++------ .../8041642/ScrollBarThumbVisibleTest.java | 16 +++++----- .../plaf/windows/6921687/bug6921687.java | 8 +++-- .../WrongAltProcessing.java | 15 ++++++---- .../swing/system/6799345/TestShutdown.java | 20 +++++++------ .../javax/swing/text/FlowView/LayoutTest.java | 18 ++++++----- .../GlyphPainter2/6427244/bug6427244.java | 20 +++++++------ .../8142966/SwingFontMetricsTest.java | 3 +- .../swing/text/View/8015853/bug8015853.java | 5 ++-- .../javax/swing/text/html/Test4783068.java | 12 ++++---- .../ImageConsumerUnregisterTest.java | 6 ++-- .../IAEforEmptyFrameTest.java | 6 ++-- .../sun/java2d/xrender/HugeGradientTest.java | 4 ++- 131 files changed, 735 insertions(+), 521 deletions(-) diff --git a/jdk/test/TEST.ROOT b/jdk/test/TEST.ROOT index 41cb9e82c8d..ccf4c295d14 100644 --- a/jdk/test/TEST.ROOT +++ b/jdk/test/TEST.ROOT @@ -10,9 +10,11 @@ # randomness tests. # # A "headful" test requires a graphical environment to meaningfully -# run. Tests that are not headful are "headless." +# run. Tests that are not headful are "headless". +# A test flagged with key "printer" requires a printer to succeed, else +# throws a PrinterException or the like. -keys=2d dnd i18n intermittent randomness headful +keys=2d dnd headful i18n intermittent printer randomness # Tests that must run in othervm mode othervm.dirs=java/awt java/beans javax/accessibility javax/imageio javax/sound javax/print javax/management com/sun/awt sun/awt sun/java2d sun/pisces javax/xml/jaxp/testng/validation java/lang/ProcessHandle diff --git a/jdk/test/com/apple/eawt/DefaultMenuBar/DefaultMenuBarTest.java b/jdk/test/com/apple/eawt/DefaultMenuBar/DefaultMenuBarTest.java index b5257e60957..9f87d7c5572 100644 --- a/jdk/test/com/apple/eawt/DefaultMenuBar/DefaultMenuBarTest.java +++ b/jdk/test/com/apple/eawt/DefaultMenuBar/DefaultMenuBarTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,8 +21,9 @@ * questions. */ -/* +/** * @test + * @key headful * @bug 8007267 * @summary [macosx] com.apple.eawt.Application.setDefaultMenuBar is not working * @requires (os.family == "mac") diff --git a/jdk/test/com/apple/laf/ScreenMenu/ScreenMenuMemoryLeakTest.java b/jdk/test/com/apple/laf/ScreenMenu/ScreenMenuMemoryLeakTest.java index 26071d4bb7b..9971967bbb6 100644 --- a/jdk/test/com/apple/laf/ScreenMenu/ScreenMenuMemoryLeakTest.java +++ b/jdk/test/com/apple/laf/ScreenMenu/ScreenMenuMemoryLeakTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -20,13 +20,16 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -/* + +/** * @test + * @key headful * @bug 8158325 * @summary Memory leak in com.apple.laf.ScreenMenu: removed JMenuItems are still referenced * @requires (os.family == "mac") * @run main/timeout=300/othervm -Xmx16m ScreenMenuMemoryLeakTest */ + import java.awt.EventQueue; import java.lang.ref.WeakReference; import java.lang.reflect.InvocationTargetException; diff --git a/jdk/test/java/awt/Choice/ChoiceHiDpi/ChoiceTest.java b/jdk/test/java/awt/Choice/ChoiceHiDpi/ChoiceTest.java index fd23b478ca0..09e7e08dd8f 100644 --- a/jdk/test/java/awt/Choice/ChoiceHiDpi/ChoiceTest.java +++ b/jdk/test/java/awt/Choice/ChoiceHiDpi/ChoiceTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,8 +21,9 @@ * questions. */ -/* +/** * @test + * @key headful * @bug 8144594 * @summary HiDPI: awt.Choice looks improperly (Win 8) * @run main ChoiceTest diff --git a/jdk/test/java/awt/Desktop/DesktopGtkLoadTest/DesktopGtkLoadTest.java b/jdk/test/java/awt/Desktop/DesktopGtkLoadTest/DesktopGtkLoadTest.java index 5769f88938f..4b86476e7a0 100644 --- a/jdk/test/java/awt/Desktop/DesktopGtkLoadTest/DesktopGtkLoadTest.java +++ b/jdk/test/java/awt/Desktop/DesktopGtkLoadTest/DesktopGtkLoadTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,7 +21,9 @@ * questions. */ -/* @test +/** + * @test + * @key headful * @bug 8157827 * @summary AWT_Desktop/Automated/Exceptions/BasicTest loads incorrect GTK * version when jdk.gtk.version=3 diff --git a/jdk/test/java/awt/Dialog/CloseDialog/CloseDialogTest.java b/jdk/test/java/awt/Dialog/CloseDialog/CloseDialogTest.java index 3053d793043..4db2d52e4ea 100644 --- a/jdk/test/java/awt/Dialog/CloseDialog/CloseDialogTest.java +++ b/jdk/test/java/awt/Dialog/CloseDialog/CloseDialogTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,11 +30,13 @@ import java.util.concurrent.atomic.AtomicReference; /** * @test + * @key headful * @bug 8043705 * @summary Can't exit color chooser dialog when running as an applet * @modules java.desktop/sun.awt * @run main CloseDialogTest */ + public class CloseDialogTest { private static volatile Frame frame; diff --git a/jdk/test/java/awt/Dialog/NestedDialogs/Modal/NestedModalDialogTest.java b/jdk/test/java/awt/Dialog/NestedDialogs/Modal/NestedModalDialogTest.java index 80c0dbb2f6c..7d32c5dd3d3 100644 --- a/jdk/test/java/awt/Dialog/NestedDialogs/Modal/NestedModalDialogTest.java +++ b/jdk/test/java/awt/Dialog/NestedDialogs/Modal/NestedModalDialogTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,17 +21,19 @@ * questions. */ - /* - @test 8155740 - @summary See : Events: actionPerformed() method not - called when it is button is clicked (system load related) - @summary com.apple.junit.java.awt.Frame - @library ../../../regtesthelpers - @build VisibilityValidator - @build Util - @build Waypoint - @run main NestedModalDialogTest +/** + * @test 8155740 + * @key headful + * @summary See : Events: actionPerformed() method not + * called when it is button is clicked (system load related) + * @summary com.apple.junit.java.awt.Frame + * @library ../../../regtesthelpers + * @build VisibilityValidator + * @build Util + * @build Waypoint + * @run main NestedModalDialogTest */ + ////////////////////////////////////////////////////////////////////////////// // NestedModalDialogTest.java // The test launches a parent frame. From this parent frame it launches a modal diff --git a/jdk/test/java/awt/Dialog/NestedDialogs/Modeless/NestedModelessDialogTest.java b/jdk/test/java/awt/Dialog/NestedDialogs/Modeless/NestedModelessDialogTest.java index 853ff02e615..d41079d1f79 100644 --- a/jdk/test/java/awt/Dialog/NestedDialogs/Modeless/NestedModelessDialogTest.java +++ b/jdk/test/java/awt/Dialog/NestedDialogs/Modeless/NestedModelessDialogTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,17 +21,19 @@ * questions. */ - /* - @test 8155740 - @summary See : Events: actionPerformed() method not - called when it is button is clicked (system load related) - @summary com.apple.junit.java.awt.Frame - @library ../../../regtesthelpers - @build VisibilityValidator - @build Util - @build Waypoint - @run main NestedModelessDialogTest +/** + * @test 8155740 + * @key headful + * @summary See : Events: actionPerformed() method not + * called when it is button is clicked (system load related) + * @summary com.apple.junit.java.awt.Frame + * @library ../../../regtesthelpers + * @build VisibilityValidator + * @build Util + * @build Waypoint + * @run main NestedModelessDialogTest -Xlog:exception */ + ///////////////////////////////////////////////////////////////////////////// // NestedModelessDialogTest.java // The test launches a parent frame. From this parent frame it launches a modal diff --git a/jdk/test/java/awt/EmbeddedFrame/DisplayChangedTest/DisplayChangedTest.java b/jdk/test/java/awt/EmbeddedFrame/DisplayChangedTest/DisplayChangedTest.java index 082681bd69b..daf9d29fbb4 100644 --- a/jdk/test/java/awt/EmbeddedFrame/DisplayChangedTest/DisplayChangedTest.java +++ b/jdk/test/java/awt/EmbeddedFrame/DisplayChangedTest/DisplayChangedTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,24 +21,20 @@ * questions. */ -/* - @test - @bug 4980592 8171363 - @summary switching user in XP causes an NPE in - sun.awt.windows.WWindowPeer.displayChanged - @requires (os.family == "windows") - @modules java.desktop/java.awt.peer - @modules java.desktop/sun.awt.windows:open - @modules java.desktop/sun.awt - @author son@sparc.spb.su: area=embedded - @run main DisplayChangedTest - */ /** - * DisplayChangedTest.java - * - * summary: switching user in XP causes an NPE in - * sun.awt.windows.WWindowPeer.displayChanged + * @test + * @key headful + * @bug 4980592 8171363 + * @summary switching user in XP causes an NPE in + * sun.awt.windows.WWindowPeer.displayChanged + * @requires (os.family == "windows") + * @modules java.desktop/java.awt.peer + * @modules java.desktop/sun.awt.windows:open + * @modules java.desktop/sun.awt + * @author son@sparc.spb.su: area=embedded + * @run main DisplayChangedTest */ + import java.awt.Frame; import java.awt.Dialog; import java.awt.TextArea; diff --git a/jdk/test/java/awt/EmbeddedFrame/EmbeddedFrameGrabTest/EmbeddedFrameGrabTest.java b/jdk/test/java/awt/EmbeddedFrame/EmbeddedFrameGrabTest/EmbeddedFrameGrabTest.java index 5249dca3b14..e7fb0b8c6a0 100644 --- a/jdk/test/java/awt/EmbeddedFrame/EmbeddedFrameGrabTest/EmbeddedFrameGrabTest.java +++ b/jdk/test/java/awt/EmbeddedFrame/EmbeddedFrameGrabTest/EmbeddedFrameGrabTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,22 +21,19 @@ * questions. */ -/* - @test - @bug 6345003 8171363 - @summary grab problems with EmbeddedFrame - @requires (os.family == "windows") - @modules java.desktop/java.awt.peer - @modules java.desktop/sun.awt - @modules java.desktop/sun.awt.windows:open - @author Oleg.Semenov@sun.com area=EmbeddedFrame - @run main EmbeddedFrameGrabTest - */ /** - * EmbeddedFrameGrabTest.java - * - * summary: grab problems with EmbeddedFrame + * @test + * @key headful + * @bug 6345003 8171363 + * @summary grab problems with EmbeddedFrame + * @requires (os.family == "windows") + * @modules java.desktop/java.awt.peer + * @modules java.desktop/sun.awt + * @modules java.desktop/sun.awt.windows:open + * @author Oleg.Semenov@sun.com area=EmbeddedFrame + * @run main EmbeddedFrameGrabTest */ + import java.awt.Frame; import java.awt.peer.FramePeer; import javax.swing.JComboBox; diff --git a/jdk/test/java/awt/EventDispatchThread/LoopRobustness/LoopRobustness.html b/jdk/test/java/awt/EventDispatchThread/LoopRobustness/LoopRobustness.html index 8f5e722fb68..1a1808de681 100644 --- a/jdk/test/java/awt/EventDispatchThread/LoopRobustness/LoopRobustness.html +++ b/jdk/test/java/awt/EventDispatchThread/LoopRobustness/LoopRobustness.html @@ -1,5 +1,5 @@ - + Networking Properties @@ -35,7 +35,7 @@ alter the mechanisms and behavior of the various classes of the java.net package. Some are checked only once at startup of the VM, and therefore are best set using the -D option of the java command, while others have a more dynamic nature and can also be changed using -the System.setProperty() API. +the System.setProperty() API. The purpose of this document is to list and detail all of these properties.

    If there is no special note, a property value is checked every time it is used.

    diff --git a/jdk/src/java.base/share/classes/javax/net/ssl/SSLEngine.java b/jdk/src/java.base/share/classes/javax/net/ssl/SSLEngine.java index b765128cd85..3eec4282ba6 100644 --- a/jdk/src/java.base/share/classes/javax/net/ssl/SSLEngine.java +++ b/jdk/src/java.base/share/classes/javax/net/ssl/SSLEngine.java @@ -1292,7 +1292,7 @@ public abstract class SSLEngine { * href="http://www.ietf.org/rfc/rfc7301.txt"> RFC 7301 , the * Application-Layer Protocol Negotiation (ALPN), can negotiate * application-level values between peers. - *

    + * * @implSpec * The implementation in this class throws * {@code UnsupportedOperationException} and performs no other action. @@ -1317,7 +1317,7 @@ public abstract class SSLEngine { * Like {@link #getHandshakeSession()}, * a connection may be in the middle of a handshake. The * application protocol may or may not yet be available. - *

    + * * @implSpec * The implementation in this class throws * {@code UnsupportedOperationException} and performs no other action. diff --git a/jdk/src/java.base/share/classes/javax/net/ssl/SSLParameters.java b/jdk/src/java.base/share/classes/javax/net/ssl/SSLParameters.java index 19b05f9de8a..1c3c947035e 100644 --- a/jdk/src/java.base/share/classes/javax/net/ssl/SSLParameters.java +++ b/jdk/src/java.base/share/classes/javax/net/ssl/SSLParameters.java @@ -646,7 +646,7 @@ public class SSLParameters { * requested by the peer, the underlying protocol will determine what * action to take. (For example, ALPN will send a * {@code "no_application_protocol"} alert and terminate the connection.) - *

    + * * @implSpec * This method will make a copy of the {@code protocols} array. * diff --git a/jdk/src/java.base/share/classes/javax/net/ssl/SSLSocket.java b/jdk/src/java.base/share/classes/javax/net/ssl/SSLSocket.java index 6f8e20d9538..ccaea95b167 100644 --- a/jdk/src/java.base/share/classes/javax/net/ssl/SSLSocket.java +++ b/jdk/src/java.base/share/classes/javax/net/ssl/SSLSocket.java @@ -702,7 +702,7 @@ public abstract class SSLSocket extends Socket * href="http://www.ietf.org/rfc/rfc7301.txt"> RFC 7301 , the * Application-Layer Protocol Negotiation (ALPN), can negotiate * application-level values between peers. - *

    + * * @implSpec * The implementation in this class throws * {@code UnsupportedOperationException} and performs no other action. @@ -727,7 +727,7 @@ public abstract class SSLSocket extends Socket * Like {@link #getHandshakeSession()}, * a connection may be in the middle of a handshake. The * application protocol may or may not yet be available. - *

    + * * @implSpec * The implementation in this class throws * {@code UnsupportedOperationException} and performs no other action. From b6f3d9355790197c9edbcc1828c7903ec02f2925 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Mon, 14 Aug 2017 13:57:15 -0700 Subject: [PATCH 26/33] 8186160: Fix a11y issues in java.security package Reviewed-by: wetmore --- .../classes/java/security/DrbgParameters.java | 14 +++++----- .../share/classes/java/security/Provider.java | 14 +++++----- .../java/security/cert/X509Extension.java | 28 +++++++++---------- 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/security/DrbgParameters.java b/jdk/src/java.base/share/classes/java/security/DrbgParameters.java index 05723baa916..4dba498faf1 100644 --- a/jdk/src/java.base/share/classes/java/security/DrbgParameters.java +++ b/jdk/src/java.base/share/classes/java/security/DrbgParameters.java @@ -263,18 +263,18 @@ public class DrbgParameters { * Capability effective = ((DrbgParametes.Initiate) s.getParameters()) * .getCapability(); * - * + *
    * * * - * - * + * + * * * - * - * - * - * + * + * + * + * * *
    requested and effective capabilities
    Requested ValuePossible Effective ValuesRequested ValuePossible Effective Values
    NONENONE, RESEED_ONLY, PR_AND_RESEED
    RESEED_ONLYRESEED_ONLY, PR_AND_RESEED
    PR_AND_RESEEDPR_AND_RESEED
    NONENONE, RESEED_ONLY, PR_AND_RESEED
    RESEED_ONLYRESEED_ONLY, PR_AND_RESEED
    PR_AND_RESEEDPR_AND_RESEED
    *

    diff --git a/jdk/src/java.base/share/classes/java/security/Provider.java b/jdk/src/java.base/share/classes/java/security/Provider.java index cf20bfec3ac..83ce4ff9aa2 100644 --- a/jdk/src/java.base/share/classes/java/security/Provider.java +++ b/jdk/src/java.base/share/classes/java/security/Provider.java @@ -61,19 +61,19 @@ import java.util.function.Function; * security framework. Services of this type cannot be added, removed, * or modified by applications. * The following attributes are automatically placed in each Provider object: - * + *
    * * - * + * * - * - * + * + * * - * + * * - * + * * - * + * * * *
    Attributes Automatically Placed in a Provider Object
    NameValue
    NameValue
    {@code Provider.id name}
    {@code Provider.id name}{@code String.valueOf(provider.getName())}
    {@code Provider.id version}
    {@code Provider.id version}{@code String.valueOf(provider.getVersionStr())}
    {@code Provider.id info}
    {@code Provider.id info}{@code String.valueOf(provider.getInfo())}
    {@code Provider.id className}
    {@code Provider.id className}{@code provider.getClass().getName()}
    diff --git a/jdk/src/java.base/share/classes/java/security/cert/X509Extension.java b/jdk/src/java.base/share/classes/java/security/cert/X509Extension.java index b7533a2c697..b8aa25fb9ca 100644 --- a/jdk/src/java.base/share/classes/java/security/cert/X509Extension.java +++ b/jdk/src/java.base/share/classes/java/security/cert/X509Extension.java @@ -153,33 +153,33 @@ public interface X509Extension { * by periods. * *

    For example:
    - * + *
    * * * - * - * + * + * * - * - * + * + * * - * + * * - * + * * - * + * * - * + * * - * + * * - * + * * - * + * * - * + * * - * + * * * *
    Examples of OIDs and extension names
    OID (Object Identifier)Extension Name
    OID (Object Identifier)Extension Name
    2.5.29.14
    2.5.29.14SubjectKeyIdentifier
    2.5.29.15
    2.5.29.15KeyUsage
    2.5.29.16
    2.5.29.16PrivateKeyUsage
    2.5.29.17
    2.5.29.17SubjectAlternativeName
    2.5.29.18
    2.5.29.18IssuerAlternativeName
    2.5.29.19
    2.5.29.19BasicConstraints
    2.5.29.30
    2.5.29.30NameConstraints
    2.5.29.33
    2.5.29.33PolicyMappings
    2.5.29.35
    2.5.29.35AuthorityKeyIdentifier
    2.5.29.36
    2.5.29.36PolicyConstraints
    From 925357af091b9df9740e6dac2235b975cc1e6353 Mon Sep 17 00:00:00 2001 From: Liam Miller-Cushon Date: Mon, 14 Aug 2017 17:19:31 -0700 Subject: [PATCH 27/33] 8184940: JDK 9 rejects zip files where the modified day or month is 0 Reviewed-by: martin --- .../share/classes/java/util/zip/ZipUtils.java | 25 +++- .../share/classes/jdk/nio/zipfs/ZipUtils.java | 25 +++- jdk/test/java/util/zip/ZipFile/ZeroDate.java | 112 ++++++++++++++++ jdk/test/jdk/nio/zipfs/ZeroDate.java | 120 ++++++++++++++++++ 4 files changed, 268 insertions(+), 14 deletions(-) create mode 100644 jdk/test/java/util/zip/ZipFile/ZeroDate.java create mode 100644 jdk/test/jdk/nio/zipfs/ZeroDate.java diff --git a/jdk/src/java.base/share/classes/java/util/zip/ZipUtils.java b/jdk/src/java.base/share/classes/java/util/zip/ZipUtils.java index 8c682a813b6..e618ef18a78 100644 --- a/jdk/src/java.base/share/classes/java/util/zip/ZipUtils.java +++ b/jdk/src/java.base/share/classes/java/util/zip/ZipUtils.java @@ -81,13 +81,24 @@ class ZipUtils { * Converts DOS time to Java time (number of milliseconds since epoch). */ public static long dosToJavaTime(long dtime) { - LocalDateTime ldt = LocalDateTime.of( - (int) (((dtime >> 25) & 0x7f) + 1980), - (int) ((dtime >> 21) & 0x0f), - (int) ((dtime >> 16) & 0x1f), - (int) ((dtime >> 11) & 0x1f), - (int) ((dtime >> 5) & 0x3f), - (int) ((dtime << 1) & 0x3e)); + int year; + int month; + int day; + int hour = (int) ((dtime >> 11) & 0x1f); + int minute = (int) ((dtime >> 5) & 0x3f); + int second = (int) ((dtime << 1) & 0x3e); + if ((dtime >> 16) == 0) { + // Interpret the 0 DOS date as 1979-11-30 for compatibility with + // other implementations. + year = 1979; + month = 11; + day = 30; + } else { + year = (int) (((dtime >> 25) & 0x7f) + 1980); + month = (int) ((dtime >> 21) & 0x0f); + day = (int) ((dtime >> 16) & 0x1f); + } + LocalDateTime ldt = LocalDateTime.of(year, month, day, hour, minute, second); return TimeUnit.MILLISECONDS.convert(ldt.toEpochSecond( ZoneId.systemDefault().getRules().getOffset(ldt)), TimeUnit.SECONDS); } diff --git a/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipUtils.java b/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipUtils.java index b87a63d87cb..3c45090dbe2 100644 --- a/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipUtils.java +++ b/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipUtils.java @@ -106,13 +106,24 @@ class ZipUtils { * Converts DOS time to Java time (number of milliseconds since epoch). */ public static long dosToJavaTime(long dtime) { - LocalDateTime ldt = LocalDateTime.of( - (int) (((dtime >> 25) & 0x7f) + 1980), - (int) ((dtime >> 21) & 0x0f), - (int) ((dtime >> 16) & 0x1f), - (int) ((dtime >> 11) & 0x1f), - (int) ((dtime >> 5) & 0x3f), - (int) ((dtime << 1) & 0x3e)); + int year; + int month; + int day; + int hour = (int) ((dtime >> 11) & 0x1f); + int minute = (int) ((dtime >> 5) & 0x3f); + int second = (int) ((dtime << 1) & 0x3e); + if ((dtime >> 16) == 0) { + // Interpret the 0 DOS date as 1979-11-30 for compatibility with + // other implementations. + year = 1979; + month = 11; + day = 30; + } else { + year = (int) (((dtime >> 25) & 0x7f) + 1980); + month = (int) ((dtime >> 21) & 0x0f); + day = (int) ((dtime >> 16) & 0x1f); + } + LocalDateTime ldt = LocalDateTime.of(year, month, day, hour, minute, second); return TimeUnit.MILLISECONDS.convert(ldt.toEpochSecond( ZoneId.systemDefault().getRules().getOffset(ldt)), TimeUnit.SECONDS); } diff --git a/jdk/test/java/util/zip/ZipFile/ZeroDate.java b/jdk/test/java/util/zip/ZipFile/ZeroDate.java new file mode 100644 index 00000000000..aef545002e0 --- /dev/null +++ b/jdk/test/java/util/zip/ZipFile/ZeroDate.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import static java.util.zip.ZipFile.CENOFF; +import static java.util.zip.ZipFile.CENTIM; +import static java.util.zip.ZipFile.ENDHDR; +import static java.util.zip.ZipFile.ENDOFF; +import static java.util.zip.ZipFile.LOCTIM; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.time.Instant; +import java.time.LocalDate; +import java.time.ZoneId; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; +import java.util.zip.ZipOutputStream; + +/* @test + * @bug 8184940 + * @summary JDK 9 rejects zip files where the modified day or month is 0 + * @author Liam Miller-Cushon + */ +public class ZeroDate { + + public static void main(String[] args) throws Exception { + // create a zip file, and read it in as a byte array + Path path = Files.createTempFile("bad", ".zip"); + try (OutputStream os = Files.newOutputStream(path); + ZipOutputStream zos = new ZipOutputStream(os)) { + ZipEntry e = new ZipEntry("x"); + zos.putNextEntry(e); + zos.write((int) 'x'); + } + int len = (int) Files.size(path); + byte[] data = new byte[len]; + try (InputStream is = Files.newInputStream(path)) { + is.read(data); + } + Files.delete(path); + + // year, month, day are zero + testDate(data.clone(), 0, LocalDate.of(1979, 11, 30)); + // only year is zero + testDate(data.clone(), 0 << 25 | 4 << 21 | 5 << 16, LocalDate.of(1980, 4, 5)); + } + + private static void testDate(byte[] data, int date, LocalDate expected) throws IOException { + // set the datetime + int endpos = data.length - ENDHDR; + int cenpos = u16(data, endpos + ENDOFF); + int locpos = u16(data, cenpos + CENOFF); + writeU32(data, cenpos + CENTIM, date); + writeU32(data, locpos + LOCTIM, date); + + // ensure that the archive is still readable, and the date is 1979-11-30 + Path path = Files.createTempFile("out", ".zip"); + try (OutputStream os = Files.newOutputStream(path)) { + os.write(data); + } + try (ZipFile zf = new ZipFile(path.toFile())) { + ZipEntry ze = zf.entries().nextElement(); + Instant actualInstant = ze.getLastModifiedTime().toInstant(); + Instant expectedInstant = + expected.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant(); + if (!actualInstant.equals(expectedInstant)) { + throw new AssertionError( + String.format("actual: %s, expected: %s", actualInstant, expectedInstant)); + } + } finally { + Files.delete(path); + } + } + + static int u8(byte[] data, int offset) { + return data[offset] & 0xff; + } + + static int u16(byte[] data, int offset) { + return u8(data, offset) + (u8(data, offset + 1) << 8); + } + + private static void writeU32(byte[] data, int pos, int value) { + data[pos] = (byte) (value & 0xff); + data[pos + 1] = (byte) ((value >> 8) & 0xff); + data[pos + 2] = (byte) ((value >> 16) & 0xff); + data[pos + 3] = (byte) ((value >> 24) & 0xff); + } +} diff --git a/jdk/test/jdk/nio/zipfs/ZeroDate.java b/jdk/test/jdk/nio/zipfs/ZeroDate.java new file mode 100644 index 00000000000..1a65c9b39b6 --- /dev/null +++ b/jdk/test/jdk/nio/zipfs/ZeroDate.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import static java.util.zip.ZipFile.CENOFF; +import static java.util.zip.ZipFile.CENTIM; +import static java.util.zip.ZipFile.ENDHDR; +import static java.util.zip.ZipFile.ENDOFF; +import static java.util.zip.ZipFile.LOCTIM; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URI; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.attribute.BasicFileAttributes; +import java.time.Instant; +import java.time.LocalDate; +import java.time.ZoneId; +import java.util.Collections; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +/* @test + * @bug 8184940 + * @summary JDK 9 rejects zip files where the modified day or month is 0 + * @author Liam Miller-Cushon + */ +public class ZeroDate { + + public static void main(String[] args) throws Exception { + // create a zip file, and read it in as a byte array + Path path = Files.createTempFile("bad", ".zip"); + try (OutputStream os = Files.newOutputStream(path); + ZipOutputStream zos = new ZipOutputStream(os)) { + ZipEntry e = new ZipEntry("x"); + zos.putNextEntry(e); + zos.write((int) 'x'); + } + int len = (int) Files.size(path); + byte[] data = new byte[len]; + try (InputStream is = Files.newInputStream(path)) { + is.read(data); + } + Files.delete(path); + + // year, month, day are zero + testDate(data.clone(), 0, LocalDate.of(1979, 11, 30)); + // only year is zero + testDate(data.clone(), 0 << 25 | 4 << 21 | 5 << 16, LocalDate.of(1980, 4, 5)); + } + + private static void testDate(byte[] data, int date, LocalDate expected) throws IOException { + // set the datetime + int endpos = data.length - ENDHDR; + int cenpos = u16(data, endpos + ENDOFF); + int locpos = u16(data, cenpos + CENOFF); + writeU32(data, cenpos + CENTIM, date); + writeU32(data, locpos + LOCTIM, date); + + // ensure that the archive is still readable, and the date is 1979-11-30 + Path path = Files.createTempFile("out", ".zip"); + try (OutputStream os = Files.newOutputStream(path)) { + os.write(data); + } + URI uri = URI.create("jar:file://" + path.toAbsolutePath()); + try (FileSystem fs = FileSystems.newFileSystem(uri, Collections.emptyMap())) { + Path entry = fs.getPath("x"); + Instant actualInstant = + Files.readAttributes(entry, BasicFileAttributes.class) + .lastModifiedTime() + .toInstant(); + Instant expectedInstant = + expected.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant(); + if (!actualInstant.equals(expectedInstant)) { + throw new AssertionError( + String.format("actual: %s, expected: %s", actualInstant, expectedInstant)); + } + } finally { + Files.delete(path); + } + } + + static int u8(byte[] data, int offset) { + return data[offset] & 0xff; + } + + static int u16(byte[] data, int offset) { + return u8(data, offset) + (u8(data, offset + 1) << 8); + } + + private static void writeU32(byte[] data, int pos, int value) { + data[pos] = (byte) (value & 0xff); + data[pos + 1] = (byte) ((value >> 8) & 0xff); + data[pos + 2] = (byte) ((value >> 16) & 0xff); + data[pos + 3] = (byte) ((value >> 24) & 0xff); + } +} From f413915e196bb834016724f63937d2119afa7a9a Mon Sep 17 00:00:00 2001 From: John Jiang Date: Mon, 14 Aug 2017 21:24:45 -0700 Subject: [PATCH 28/33] 8185620: MSCAPI test leaves too many entries in keystore Deletes the added entries before exiting Reviewed-by: vinnie --- .../sun/security/mscapi/SmallPrimeExponentP.java | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/jdk/test/sun/security/mscapi/SmallPrimeExponentP.java b/jdk/test/sun/security/mscapi/SmallPrimeExponentP.java index 38d37966f23..535d32d5310 100644 --- a/jdk/test/sun/security/mscapi/SmallPrimeExponentP.java +++ b/jdk/test/sun/security/mscapi/SmallPrimeExponentP.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -55,6 +55,9 @@ public class SmallPrimeExponentP { CertAndKeyGen ckg = new CertAndKeyGen("RSA", "SHA1withRSA"); ckg.setRandom(new MySecureRandom(seed)); + String alias = "anything"; + int count = 0; + boolean see63 = false; boolean see65 = false; while (!see63 || !see65) { @@ -78,12 +81,19 @@ public class SmallPrimeExponentP { see65 = true; } } - ks.setKeyEntry("anything", k, null, new X509Certificate[]{ + ks.setKeyEntry(alias, k, null, new X509Certificate[]{ ckg.getSelfCertificate(new X500Name("CN=Me"), 1000) }); + count++; } } - ks.store(null, null); + + // Because of JDK-8185844, it has to reload the key store after + // deleting an entry. + for (int i = 0; i < count; i++) { + ks.deleteEntry(alias); + ks.load(null, null); + } } static class MySecureRandom extends SecureRandom { From 55fe55c4ff83fb65ac59628b017ae6acd913611f Mon Sep 17 00:00:00 2001 From: John Jiang Date: Tue, 15 Aug 2017 19:19:50 -0700 Subject: [PATCH 29/33] 8179614: Test for jarsigner on verifying jars that are signed and timestamped by other JDK releases A test on checking the compatibility on jarsigner cross different JDK releases Reviewed-by: mullan --- .../compatibility/Compatibility.java | 1183 +++++++++++++++++ .../compatibility/DetailsOutputStream.java | 79 ++ .../jarsigner/compatibility/HtmlHelper.java | 102 ++ .../jarsigner/compatibility/JdkUtils.java | 61 + .../compatibility/PhaseOutputStream.java | 162 +++ .../tools/jarsigner/compatibility/README | 215 +++ .../jarsigner/compatibility/java.security | 2 + 7 files changed, 1804 insertions(+) create mode 100644 jdk/test/sun/security/tools/jarsigner/compatibility/Compatibility.java create mode 100644 jdk/test/sun/security/tools/jarsigner/compatibility/DetailsOutputStream.java create mode 100644 jdk/test/sun/security/tools/jarsigner/compatibility/HtmlHelper.java create mode 100644 jdk/test/sun/security/tools/jarsigner/compatibility/JdkUtils.java create mode 100644 jdk/test/sun/security/tools/jarsigner/compatibility/PhaseOutputStream.java create mode 100644 jdk/test/sun/security/tools/jarsigner/compatibility/README create mode 100644 jdk/test/sun/security/tools/jarsigner/compatibility/java.security diff --git a/jdk/test/sun/security/tools/jarsigner/compatibility/Compatibility.java b/jdk/test/sun/security/tools/jarsigner/compatibility/Compatibility.java new file mode 100644 index 00000000000..a285a0257c5 --- /dev/null +++ b/jdk/test/sun/security/tools/jarsigner/compatibility/Compatibility.java @@ -0,0 +1,1183 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary This test is used to verify the compatibility on jarsigner cross + * different JDK releases. It also can be used to check jar signing (w/ + * and w/o TSA) and verifying on some specific key algorithms and digest + * algorithms. + * Note that, this is a manual test. For more details about the test and + * its usages, please look through README. + * + * @modules java.base/sun.security.pkcs + * java.base/sun.security.timestamp + * java.base/sun.security.tools.keytool + * java.base/sun.security.util + * java.base/sun.security.x509 + * @library /test/lib /lib/testlibrary ../warnings + * @compile -source 1.6 -target 1.6 JdkUtils.java + * @run main/manual/othervm Compatibility + */ + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintStream; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.util.JarUtils; + +public class Compatibility { + + private static final String TEST_JAR_NAME = "test.jar"; + + private static final String TEST_SRC = System.getProperty("test.src"); + private static final String TEST_CLASSES = System.getProperty("test.classes"); + private static final String TEST_JDK = System.getProperty("test.jdk"); + private static final String TEST_JARSIGNER = jarsignerPath(TEST_JDK); + + private static final String PROXY_HOST = System.getProperty("proxyHost"); + private static final String PROXY_PORT = System.getProperty("proxyPort", "80"); + + // An alternative security properties file. + // The test provides a default one, which only contains two lines: + // jdk.certpath.disabledAlgorithms=MD2, MD5 + // jdk.jar.disabledAlgorithms=MD2, MD5 + private static final String JAVA_SECURITY = System.getProperty( + "javaSecurityFile", TEST_SRC + "/java.security"); + + private static final String PASSWORD = "testpass"; + private static final String KEYSTORE = "testKeystore"; + + private static final String RSA = "RSA"; + private static final String DSA = "DSA"; + private static final String EC = "EC"; + private static final String[] KEY_ALGORITHMS = new String[] { + RSA, + DSA, + EC}; + + private static final String SHA1 = "SHA-1"; + private static final String SHA256 = "SHA-256"; + private static final String SHA512 = "SHA-512"; + private static final String DEFAULT = "DEFAULT"; + private static final String[] DIGEST_ALGORITHMS = new String[] { + SHA1, + SHA256, + SHA512, + DEFAULT}; + + private static final boolean[] EXPIRED = new boolean[] { + false, + true}; + + private static final Calendar CALENDAR = Calendar.getInstance(); + private static final DateFormat DATE_FORMAT + = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); + + // The certificate validity period in minutes. The default value is 1440 + // minutes, namely 1 day. + private static final int CERT_VALIDITY + = Integer.valueOf(System.getProperty("certValidity", "1440")); + static { + if (CERT_VALIDITY < 1 || CERT_VALIDITY > 1440) { + throw new RuntimeException( + "certValidity if out of range [1, 1440]: " + CERT_VALIDITY); + } + } + + // If true, an additional verifying will be triggered after all of + // valid certificates expire. The default value is false. + public static final boolean DELAY_VERIFY + = Boolean.valueOf(System.getProperty("delayVerify", "false")); + + private static long lastCertStartTime; + + private static DetailsOutputStream detailsOutput; + + public static void main(String[] args) throws Throwable { + // Backups stdout and stderr. + PrintStream origStdOut = System.out; + PrintStream origStdErr = System.err; + + detailsOutput = new DetailsOutputStream(); + + // Redirects the system output to a custom one. + PrintStream printStream = new PrintStream(detailsOutput); + System.setOut(printStream); + System.setErr(printStream); + + List tsaList = tsaInfoList(); + if (tsaList.size() == 0) { + throw new RuntimeException("TSA service is mandatory."); + } + + List jdkInfoList = jdkInfoList(); + List certList = createCertificates(jdkInfoList); + createJar(); + List signItems = test(jdkInfoList, tsaList, certList); + + boolean failed = generateReport(tsaList, signItems); + + // Restores the original stdout and stderr. + System.setOut(origStdOut); + System.setErr(origStdErr); + + if (failed) { + throw new RuntimeException("At least one test case failed. " + + "Please check the failed row(s) in report.html " + + "or failedReport.html."); + } + } + + // Creates a jar file that contains an empty file. + private static void createJar() throws IOException { + String testFile = "test"; + new File(testFile).createNewFile(); + JarUtils.createJar(TEST_JAR_NAME, testFile); + } + + // Creates a key store that includes a set of valid/expired certificates + // with various algorithms. + private static List createCertificates(List jdkInfoList) + throws Throwable { + List certList = new ArrayList(); + Set expiredCertFilter = new HashSet(); + + for(JdkInfo jdkInfo : jdkInfoList) { + for(String keyAlgorithm : KEY_ALGORITHMS) { + for(String digestAlgorithm : DIGEST_ALGORITHMS) { + for(int keySize : keySizes(keyAlgorithm)) { + for(boolean expired : EXPIRED) { + // It creates only one expired certificate for one + // key algorithm. + if (expired + && !expiredCertFilter.add(keyAlgorithm)) { + continue; + } + + CertInfo certInfo = new CertInfo( + jdkInfo.version, + keyAlgorithm, + digestAlgorithm, + keySize, + expired); + if (!certList.contains(certInfo)) { + String alias = createCertificate( + jdkInfo.jdkPath, certInfo); + if (alias != null) { + certList.add(certInfo); + } + } + } + } + } + } + } + + return certList; + } + + // Creates/Updates a key store that adds a certificate with specific algorithm. + private static String createCertificate(String jdkPath, CertInfo certInfo) + throws Throwable { + String alias = certInfo.alias(); + + List arguments = new ArrayList(); + arguments.add("-J-Djava.security.properties=" + JAVA_SECURITY); + arguments.add("-v"); + arguments.add("-storetype"); + arguments.add("jks"); + arguments.add("-genkey"); + arguments.add("-keyalg"); + arguments.add(certInfo.keyAlgorithm); + String sigalg = sigalg(certInfo.digestAlgorithm, certInfo.keyAlgorithm); + if (sigalg != null) { + arguments.add("-sigalg"); + arguments.add(sigalg); + } + if (certInfo.keySize != 0) { + arguments.add("-keysize"); + arguments.add(certInfo.keySize + ""); + } + arguments.add("-dname"); + arguments.add("CN=Test"); + arguments.add("-alias"); + arguments.add(alias); + arguments.add("-keypass"); + arguments.add(PASSWORD); + arguments.add("-storepass"); + arguments.add(PASSWORD); + + arguments.add("-startdate"); + arguments.add(startDate(certInfo.expired)); + arguments.add("-validity"); + arguments.add("1"); + arguments.add("-keystore"); + arguments.add(KEYSTORE); + + OutputAnalyzer outputAnalyzer = execTool( + jdkPath + "/bin/keytool", + arguments.toArray(new String[arguments.size()])); + if (outputAnalyzer.getExitValue() == 0 + && !outputAnalyzer.getOutput().matches("[Ee]xception")) { + return alias; + } else { + return null; + } + } + + private static String sigalg(String digestAlgorithm, String keyAlgorithm) { + if (digestAlgorithm == DEFAULT) { + return null; + } + + String keyName = keyAlgorithm == EC ? "ECDSA" : keyAlgorithm; + return digestAlgorithm.replace("-", "") + "with" + keyName; + } + + // The validity period of a certificate always be 1 day. For creating an + // expired certificate, the start date is the time before 1 day, then the + // certificate expires immediately. And for creating a valid certificate, + // the start date is the time before (1 day - CERT_VALIDITY minutes), then + // the certificate will expires in CERT_VALIDITY minutes. + private static String startDate(boolean expiredCert) { + CALENDAR.setTime(new Date()); + CALENDAR.add(Calendar.DAY_OF_MONTH, -1); + if (!expiredCert) { + CALENDAR.add(Calendar.MINUTE, CERT_VALIDITY); + } + Date startDate = CALENDAR.getTime(); + lastCertStartTime = startDate.getTime(); + return DATE_FORMAT.format(startDate); + } + + // Retrieves JDK info from the file which is specified by property jdkListFile, + // or from property jdkList if jdkListFile is not available. + private static List jdkInfoList() throws Throwable { + String[] jdkList = list("jdkList"); + if (jdkList.length == 0) { + jdkList = new String[] { TEST_JDK }; + } + + List jdkInfoList = new ArrayList(); + for (String jdkPath : jdkList) { + JdkInfo jdkInfo = new JdkInfo(jdkPath); + // The JDK version must be unique. + if (!jdkInfoList.contains(jdkInfo)) { + jdkInfoList.add(jdkInfo); + } else { + System.out.println("The JDK version is duplicate: " + jdkPath); + } + } + return jdkInfoList; + } + + // Retrieves TSA info from the file which is specified by property tsaListFile, + // or from property tsaList if tsaListFile is not available. + private static List tsaInfoList() throws IOException { + String[] tsaList = list("tsaList"); + + List tsaInfoList = new ArrayList(); + for (int i = 0; i < tsaList.length; i++) { + String[] values = tsaList[i].split(";digests="); + + String[] digests = new String[0]; + if (values.length == 2) { + digests = values[1].split(","); + } + + TsaInfo bufTsa = new TsaInfo(i, values[0]); + + for (String digest : digests) { + bufTsa.addDigest(digest); + } + + tsaInfoList.add(bufTsa); + } + + return tsaInfoList; + } + + private static String[] list(String listProp) + throws IOException { + String listFileProp = listProp + "File"; + String listFile = System.getProperty(listFileProp); + if (!isEmpty(listFile)) { + System.out.println(listFileProp + "=" + listFile); + List list = new ArrayList(); + BufferedReader reader = new BufferedReader( + new FileReader(listFile)); + String line; + while ((line = reader.readLine()) != null) { + String item = line.trim(); + if (!item.isEmpty()) { + list.add(item); + } + } + reader.close(); + return list.toArray(new String[list.size()]); + } + + String list = System.getProperty(listProp); + System.out.println(listProp + "=" + list); + return !isEmpty(list) ? list.split("#") : new String[0]; + } + + private static boolean isEmpty(String str) { + return str == null || str.isEmpty(); + } + + // A JDK (signer) signs a jar with a variety of algorithms, and then all of + // JDKs (verifiers), including the signer itself, try to verify the signed + // jars respectively. + private static List test(List jdkInfoList, + List tsaInfoList, List certList) + throws Throwable { + detailsOutput.transferPhase(); + List signItems = signing(jdkInfoList, tsaInfoList, certList); + + detailsOutput.transferPhase(); + for (SignItem signItem : signItems) { + for (JdkInfo verifierInfo : jdkInfoList) { + // JDK 6 doesn't support EC + if (!verifierInfo.isJdk6() + || signItem.certInfo.keyAlgorithm != EC) { + verifying(signItem, VerifyItem.build(verifierInfo)); + } + } + } + + if (DELAY_VERIFY) { + detailsOutput.transferPhase(); + System.out.print("Waiting for delay verifying"); + long lastCertExpirationTime = lastCertStartTime + 24 * 60 * 60 * 1000; + while (System.currentTimeMillis() < lastCertExpirationTime) { + TimeUnit.SECONDS.sleep(30); + System.out.print("."); + } + System.out.println(); + + System.out.println("Delay verifying starts"); + for (SignItem signItem : signItems) { + for (VerifyItem verifyItem : signItem.verifyItems) { + verifying(signItem, verifyItem); + } + } + } + + detailsOutput.transferPhase(); + + return signItems; + } + + private static List signing(List jdkInfos, + List tsaList, List certList) throws Throwable { + List signItems = new ArrayList(); + + Set signFilter = new HashSet(); + + for (JdkInfo signerInfo : jdkInfos) { + for (String keyAlgorithm : KEY_ALGORITHMS) { + // JDK 6 doesn't support EC + if (signerInfo.isJdk6() && keyAlgorithm == EC) { + continue; + } + + for (String digestAlgorithm : DIGEST_ALGORITHMS) { + String sigalg = sigalg(digestAlgorithm, keyAlgorithm); + // If the signature algorithm is not supported by the JDK, + // it cannot try to sign jar with this algorithm. + if (sigalg != null && !signerInfo.isSupportedSigalg(sigalg)) { + continue; + } + + // If the JDK doesn't support option -tsadigestalg, the + // associated cases just be ignored. + if (digestAlgorithm != DEFAULT + && !signerInfo.supportsTsadigestalg) { + continue; + } + + for (int keySize : keySizes(keyAlgorithm)) { + for (boolean expired : EXPIRED) { + CertInfo certInfo = new CertInfo( + signerInfo.version, + keyAlgorithm, + digestAlgorithm, + keySize, + expired); + if (!certList.contains(certInfo)) { + continue; + } + + String tsadigestalg = digestAlgorithm != DEFAULT + ? digestAlgorithm + : null; + + for (TsaInfo tsaInfo : tsaList) { + // It has to ignore the digest algorithm, which + // is not supported by the TSA server. + if(!tsaInfo.isDigestSupported(tsadigestalg)) { + continue; + } + + String tsaUrl = tsaInfo.tsaUrl; + if (TsaFilter.filter( + signerInfo.version, + digestAlgorithm, + expired, + tsaInfo.index)) { + tsaUrl = null; + } + + String signedJar = "JDK_" + + signerInfo.version + "-CERT_" + + certInfo + + (tsaUrl == null + ? "" + : "-TSA_" + tsaInfo.index); + + // It has to ignore the same jar signing. + if (!signFilter.add(signedJar)) { + continue; + } + + SignItem signItem = SignItem.build() + .certInfo(certInfo) + .version(signerInfo.version) + .signatureAlgorithm(sigalg) + .tsaDigestAlgorithm( + tsaUrl == null + ? null + : tsadigestalg) + .tsaIndex( + tsaUrl == null + ? -1 + : tsaInfo.index) + .signedJar(signedJar); + String signingId = signingId(signItem); + detailsOutput.writeAnchorName(signingId, + "Signing: " + signingId); + + OutputAnalyzer signOA = signJar( + signerInfo.jarsignerPath, + sigalg, + tsadigestalg, + tsaUrl, + certInfo.alias(), + signedJar); + Status signingStatus = signingStatus(signOA); + signItem.status(signingStatus); + + if (signingStatus != Status.ERROR) { + // Using the testing JDK, which is specified + // by jtreg option "-jdk", to verify the + // signed jar and extract the signature + // algorithm and timestamp digest algorithm. + String output = verifyJar(TEST_JARSIGNER, + signedJar).getOutput(); + signItem.extractedSignatureAlgorithm( + extract(output, + " *Signature algorithm.*", + ".*: |,.*")); + signItem.extractedTsaDigestAlgorithm( + extract(output, + " *Timestamp digest algorithm.*", + ".*: ")); + } + + signItems.add(signItem); + } + } + } + } + } + } + + return signItems; + } + + private static void verifying(SignItem signItem, VerifyItem verifyItem) + throws Throwable { + boolean delayVerify = verifyItem.status == Status.NONE; + String verifyingId = verifyingId(signItem, verifyItem, !delayVerify); + detailsOutput.writeAnchorName(verifyingId, "Verifying: " + verifyingId); + + OutputAnalyzer verifyOA = verifyJar(verifyItem.jdkInfo.jarsignerPath, + signItem.signedJar); + Status verifyingStatus = verifyingStatus(verifyOA); + + // It checks if the default timestamp digest algorithm is SHA-256. + if (verifyingStatus != Status.ERROR + && signItem.tsaDigestAlgorithm == null) { + verifyingStatus = signItem.extractedTsaDigestAlgorithm != null + && !signItem.extractedTsaDigestAlgorithm.matches("SHA-?256") + ? Status.ERROR + : verifyingStatus; + if (verifyingStatus == Status.ERROR) { + System.out.println("The default tsa digest is not SHA-256: " + + signItem.extractedTsaDigestAlgorithm); + } + } + + if (delayVerify) { + signItem.addVerifyItem(verifyItem.status(verifyingStatus)); + } else { + verifyItem.delayStatus(verifyingStatus); + } + } + + // Return key sizes according to the specified key algorithm. + private static int[] keySizes(String keyAlgorithm) { + if (keyAlgorithm == RSA || keyAlgorithm == DSA) { + return new int[] { 1024, 2048, 0 }; + } else if (keyAlgorithm == EC) { + return new int[] { 384, 571, 0 }; + } + + return null; + } + + // Determines the status of signing. + private static Status signingStatus(OutputAnalyzer outputAnalyzer) { + if (outputAnalyzer.getExitValue() == 0) { + if (outputAnalyzer.getOutput().contains(Test.WARNING)) { + return Status.WARNING; + } else { + return Status.NORMAL; + } + } else { + return Status.ERROR; + } + } + + // Determines the status of verifying. + private static Status verifyingStatus(OutputAnalyzer outputAnalyzer) { + if (outputAnalyzer.getExitValue() == 0) { + String output = outputAnalyzer.getOutput(); + if (!output.contains(Test.JAR_VERIFIED)) { + return Status.ERROR; + } else if (output.contains(Test.WARNING)) { + return Status.WARNING; + } else { + return Status.NORMAL; + } + } else { + return Status.ERROR; + } + } + + // Extracts string from text by specified patterns. + private static String extract(String text, String linePattern, + String replacePattern) { + Matcher lineMatcher = Pattern.compile(linePattern).matcher(text); + if (lineMatcher.find()) { + String line = lineMatcher.group(0); + return line.replaceAll(replacePattern, ""); + } else { + return null; + } + } + + // Using specified jarsigner to sign the pre-created jar with specified + // algorithms. + private static OutputAnalyzer signJar(String jarsignerPath, String sigalg, + String tsadigestalg, String tsa, String alias, String signedJar) + throws Throwable { + List arguments = new ArrayList(); + + if (PROXY_HOST != null && PROXY_PORT != null) { + arguments.add("-J-Dhttp.proxyHost=" + PROXY_HOST); + arguments.add("-J-Dhttp.proxyPort=" + PROXY_PORT); + arguments.add("-J-Dhttps.proxyHost=" + PROXY_HOST); + arguments.add("-J-Dhttps.proxyPort=" + PROXY_PORT); + } + arguments.add("-J-Djava.security.properties=" + JAVA_SECURITY); + arguments.add("-debug"); + arguments.add("-verbose"); + if (sigalg != null) { + arguments.add("-sigalg"); + arguments.add(sigalg); + } + if (tsa != null) { + arguments.add("-tsa"); + arguments.add(tsa); + } + if (tsadigestalg != null) { + arguments.add("-tsadigestalg"); + arguments.add(tsadigestalg); + } + arguments.add("-keystore"); + arguments.add(KEYSTORE); + arguments.add("-storepass"); + arguments.add(PASSWORD); + arguments.add("-signedjar"); + arguments.add(signedJar + ".jar"); + arguments.add(TEST_JAR_NAME); + arguments.add(alias); + + OutputAnalyzer outputAnalyzer = execTool( + jarsignerPath, + arguments.toArray(new String[arguments.size()])); + return outputAnalyzer; + } + + // Using specified jarsigner to verify the signed jar. + private static OutputAnalyzer verifyJar(String jarsignerPath, + String signedJar) throws Throwable { + OutputAnalyzer outputAnalyzer = execTool( + jarsignerPath, + "-J-Djava.security.properties=" + JAVA_SECURITY, + "-debug", + "-verbose", + "-certs", + "-keystore", KEYSTORE, + "-verify", signedJar + ".jar"); + return outputAnalyzer; + } + + // Generates the test result report. + private static boolean generateReport(List tsaList, + List signItems) throws IOException { + System.out.println("Report is being generated..."); + + StringBuilder report = new StringBuilder(); + report.append(HtmlHelper.startHtml()); + report.append(HtmlHelper.startPre()); + // Generates TSA URLs + report.append("TSA list:\n"); + for(TsaInfo tsaInfo : tsaList) { + report.append( + String.format("%d=%s%n", tsaInfo.index, tsaInfo.tsaUrl)); + } + report.append(HtmlHelper.endPre()); + + report.append(HtmlHelper.startTable()); + // Generates report headers. + List headers = new ArrayList(); + headers.add("[Certificate]"); + headers.add("[Signer JDK]"); + headers.add("[Signature Algorithm]"); + headers.add("[TSA Digest]"); + headers.add("[TSA]"); + headers.add("[Signing Status]"); + headers.add("[Verifier JDK]"); + headers.add("[Verifying Status]"); + if (DELAY_VERIFY) { + headers.add("[Delay Verifying Status]"); + } + headers.add("[Failed]"); + report.append(HtmlHelper.htmlRow( + headers.toArray(new String[headers.size()]))); + + StringBuilder failedReport = new StringBuilder(report.toString()); + + boolean failed = false; + + // Generates report rows. + for (SignItem signItem : signItems) { + for (VerifyItem verifyItem : signItem.verifyItems) { + String reportRow = reportRow(signItem, verifyItem); + report.append(reportRow); + boolean isFailedCase = isFailed(signItem, verifyItem); + if (isFailedCase) { + failedReport.append(reportRow); + } + failed = failed || isFailedCase; + } + } + + report.append(HtmlHelper.endTable()); + report.append(HtmlHelper.endHtml()); + generateFile("report.html", report.toString()); + if (failed) { + failedReport.append(HtmlHelper.endTable()); + failedReport.append(HtmlHelper.endPre()); + failedReport.append(HtmlHelper.endHtml()); + generateFile("failedReport.html", failedReport.toString()); + } + + System.out.println("Report is generated."); + return failed; + } + + private static void generateFile(String path, String content) + throws IOException { + FileWriter writer = new FileWriter(new File(path)); + writer.write(content); + writer.close(); + } + + private static String jarsignerPath(String jdkPath) { + return jdkPath + "/bin/jarsigner"; + } + + // Executes the specified function on JdkUtils by the specified JDK. + private static String execJdkUtils(String jdkPath, String method, + String... args) throws Throwable { + String[] cmd = new String[args.length + 5]; + cmd[0] = jdkPath + "/bin/java"; + cmd[1] = "-cp"; + cmd[2] = TEST_CLASSES; + cmd[3] = JdkUtils.class.getName(); + cmd[4] = method; + System.arraycopy(args, 0, cmd, 5, args.length); + return ProcessTools.executeCommand(cmd).getOutput(); + } + + // Executes the specified JDK tools, such as keytool and jarsigner, and + // ensures the output is in US English. + private static OutputAnalyzer execTool(String toolPath, String... args) + throws Throwable { + String[] cmd = new String[args.length + 4]; + cmd[0] = toolPath; + cmd[1] = "-J-Duser.language=en"; + cmd[2] = "-J-Duser.country=US"; + cmd[3] = "-J-Djava.security.egd=file:/dev/./urandom"; + System.arraycopy(args, 0, cmd, 4, args.length); + return ProcessTools.executeCommand(cmd); + } + + private static class JdkInfo { + + private final String jdkPath; + private final String jarsignerPath; + private final String version; + private final boolean supportsTsadigestalg; + + private Map sigalgMap = new HashMap(); + + private JdkInfo(String jdkPath) throws Throwable { + this.jdkPath = jdkPath; + version = execJdkUtils(jdkPath, JdkUtils.M_JAVA_RUNTIME_VERSION); + if (version == null || version.trim().isEmpty()) { + throw new RuntimeException( + "Cannot determine the JDK version: " + jdkPath); + } + jarsignerPath = jarsignerPath(jdkPath); + supportsTsadigestalg = execTool(jarsignerPath, "-help") + .getOutput().contains("-tsadigestalg"); + } + + private boolean isSupportedSigalg(String sigalg) throws Throwable { + if (!sigalgMap.containsKey(sigalg)) { + boolean isSupported = "true".equalsIgnoreCase( + execJdkUtils( + jdkPath, + JdkUtils.M_IS_SUPPORTED_SIGALG, + sigalg)); + sigalgMap.put(sigalg, isSupported); + } + + return sigalgMap.get(sigalg); + } + + private boolean isJdk6() { + return version.startsWith("1.6"); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + ((version == null) ? 0 : version.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + JdkInfo other = (JdkInfo) obj; + if (version == null) { + if (other.version != null) + return false; + } else if (!version.equals(other.version)) + return false; + return true; + } + } + + private static class TsaInfo { + + private final int index; + private final String tsaUrl; + private Set digestList = new HashSet(); + + private TsaInfo(int index, String tsa) { + this.index = index; + this.tsaUrl = tsa; + } + + private void addDigest(String digest) { + if (!ignore(digest)) { + digestList.add(digest); + } + } + + private static boolean ignore(String digest) { + return !SHA1.equalsIgnoreCase(digest) + && !SHA256.equalsIgnoreCase(digest) + && !SHA512.equalsIgnoreCase(digest); + } + + private boolean isDigestSupported(String digest) { + return digest == null || digestList.isEmpty() + || digestList.contains(digest); + } + } + + private static class CertInfo { + + private final String jdkVersion; + private final String keyAlgorithm; + private final String digestAlgorithm; + private final int keySize; + private final boolean expired; + + private CertInfo(String jdkVersion, String keyAlgorithm, + String digestAlgorithm, int keySize, boolean expired) { + this.jdkVersion = jdkVersion; + this.keyAlgorithm = keyAlgorithm; + this.digestAlgorithm = digestAlgorithm; + this.keySize = keySize; + this.expired = expired; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + ((digestAlgorithm == null) ? 0 : digestAlgorithm.hashCode()); + result = prime * result + (expired ? 1231 : 1237); + result = prime * result + + ((jdkVersion == null) ? 0 : jdkVersion.hashCode()); + result = prime * result + + ((keyAlgorithm == null) ? 0 : keyAlgorithm.hashCode()); + result = prime * result + keySize; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + CertInfo other = (CertInfo) obj; + if (digestAlgorithm == null) { + if (other.digestAlgorithm != null) + return false; + } else if (!digestAlgorithm.equals(other.digestAlgorithm)) + return false; + if (expired != other.expired) + return false; + if (jdkVersion == null) { + if (other.jdkVersion != null) + return false; + } else if (!jdkVersion.equals(other.jdkVersion)) + return false; + if (keyAlgorithm == null) { + if (other.keyAlgorithm != null) + return false; + } else if (!keyAlgorithm.equals(other.keyAlgorithm)) + return false; + if (keySize != other.keySize) + return false; + return true; + } + + private String alias() { + return jdkVersion + "_" + toString(); + } + + @Override + public String toString() { + return keyAlgorithm + "_" + digestAlgorithm + + (keySize == 0 ? "" : "_" + keySize) + + (expired ? "_Expired" : ""); + } + } + + // It does only one timestamping for the same JDK, digest algorithm and + // TSA service with an arbitrary valid/expired certificate. + private static class TsaFilter { + + private static final Set SET = new HashSet(); + + private static boolean filter(String signerVersion, + String digestAlgorithm, boolean expiredCert, int tsaIndex) { + return !SET.add(new Condition(signerVersion, digestAlgorithm, + expiredCert, tsaIndex)); + } + + private static class Condition { + + private final String signerVersion; + private final String digestAlgorithm; + private final boolean expiredCert; + private final int tsaIndex; + + private Condition(String signerVersion, String digestAlgorithm, + boolean expiredCert, int tsaIndex) { + this.signerVersion = signerVersion; + this.digestAlgorithm = digestAlgorithm; + this.expiredCert = expiredCert; + this.tsaIndex = tsaIndex; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + ((digestAlgorithm == null) ? 0 : digestAlgorithm.hashCode()); + result = prime * result + (expiredCert ? 1231 : 1237); + result = prime * result + + ((signerVersion == null) ? 0 : signerVersion.hashCode()); + result = prime * result + tsaIndex; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Condition other = (Condition) obj; + if (digestAlgorithm == null) { + if (other.digestAlgorithm != null) + return false; + } else if (!digestAlgorithm.equals(other.digestAlgorithm)) + return false; + if (expiredCert != other.expiredCert) + return false; + if (signerVersion == null) { + if (other.signerVersion != null) + return false; + } else if (!signerVersion.equals(other.signerVersion)) + return false; + if (tsaIndex != other.tsaIndex) + return false; + return true; + } + }} + + private static enum Status { + + // No action due to pre-action fails. + NONE, + + // jar is signed/verified with error + ERROR, + + // jar is signed/verified with warning + WARNING, + + // jar is signed/verified without any warning and error + NORMAL + } + + private static class SignItem { + + private CertInfo certInfo; + private String version; + private String signatureAlgorithm; + // Signature algorithm that is extracted from verification output. + private String extractedSignatureAlgorithm; + private String tsaDigestAlgorithm; + // TSA digest algorithm that is extracted from verification output. + private String extractedTsaDigestAlgorithm; + private int tsaIndex; + private Status status; + private String signedJar; + + private List verifyItems = new ArrayList(); + + private static SignItem build() { + return new SignItem(); + } + + private SignItem certInfo(CertInfo certInfo) { + this.certInfo = certInfo; + return this; + } + + private SignItem version(String version) { + this.version = version; + return this; + } + + private SignItem signatureAlgorithm(String signatureAlgorithm) { + this.signatureAlgorithm = signatureAlgorithm; + return this; + } + + private SignItem extractedSignatureAlgorithm( + String extractedSignatureAlgorithm) { + this.extractedSignatureAlgorithm = extractedSignatureAlgorithm; + return this; + } + + private SignItem tsaDigestAlgorithm(String tsaDigestAlgorithm) { + this.tsaDigestAlgorithm = tsaDigestAlgorithm; + return this; + } + + private SignItem extractedTsaDigestAlgorithm( + String extractedTsaDigestAlgorithm) { + this.extractedTsaDigestAlgorithm = extractedTsaDigestAlgorithm; + return this; + } + + private SignItem tsaIndex(int tsaIndex) { + this.tsaIndex = tsaIndex; + return this; + } + + private SignItem status(Status status) { + this.status = status; + return this; + } + + private SignItem signedJar(String signedJar) { + this.signedJar = signedJar; + return this; + } + + private void addVerifyItem(VerifyItem verifyItem) { + verifyItems.add(verifyItem); + } + } + + private static class VerifyItem { + + private JdkInfo jdkInfo; + private Status status = Status.NONE; + private Status delayStatus = Status.NONE; + + private static VerifyItem build(JdkInfo jdkInfo) { + VerifyItem verifyItem = new VerifyItem(); + verifyItem.jdkInfo = jdkInfo; + return verifyItem; + } + + private VerifyItem status(Status status) { + this.status = status; + return this; + } + + private VerifyItem delayStatus(Status status) { + this.delayStatus = status; + return this; + } + } + + // The identifier for a specific signing. + private static String signingId(SignItem signItem) { + return signItem.signedJar; + } + + // The identifier for a specific verifying. + private static String verifyingId(SignItem signItem, VerifyItem verifyItem, + boolean delayVerify) { + return "S_" + signingId(signItem) + "-" + (delayVerify ? "DV" : "V") + + "_" + verifyItem.jdkInfo.version; + } + + private static String reportRow(SignItem signItem, VerifyItem verifyItem) { + List values = new ArrayList(); + values.add(signItem.certInfo.toString()); + values.add(signItem.version); + values.add(null2Default(signItem.signatureAlgorithm, + signItem.extractedSignatureAlgorithm)); + values.add(signItem.tsaIndex == -1 + ? "" + : null2Default(signItem.tsaDigestAlgorithm, + signItem.extractedTsaDigestAlgorithm)); + values.add(signItem.tsaIndex == -1 ? "" : signItem.tsaIndex + ""); + values.add(HtmlHelper.anchorLink( + PhaseOutputStream.fileName(PhaseOutputStream.Phase.SIGNING), + signingId(signItem), + signItem.status.toString())); + values.add(verifyItem.jdkInfo.version); + values.add(HtmlHelper.anchorLink( + PhaseOutputStream.fileName(PhaseOutputStream.Phase.VERIFYING), + verifyingId(signItem, verifyItem, false), + verifyItem.status.toString())); + if (DELAY_VERIFY) { + values.add(HtmlHelper.anchorLink( + PhaseOutputStream.fileName( + PhaseOutputStream.Phase.DELAY_VERIFYING), + verifyingId(signItem, verifyItem, true), + verifyItem.delayStatus.toString())); + } + values.add(isFailed(signItem, verifyItem) ? "X" : ""); + return HtmlHelper.htmlRow(values.toArray(new String[values.size()])); + } + + private static boolean isFailed(SignItem signItem, + VerifyItem verifyItem) { + return signItem.status == Status.ERROR + || verifyItem.status == Status.ERROR + || verifyItem.delayStatus == Status.ERROR; + } + + // If a value is null, then displays the default value or N/A. + private static String null2Default(String value, String defaultValue) { + return value == null + ? DEFAULT + "(" + (defaultValue == null + ? "N/A" + : defaultValue) + ")" + : value; + } +} diff --git a/jdk/test/sun/security/tools/jarsigner/compatibility/DetailsOutputStream.java b/jdk/test/sun/security/tools/jarsigner/compatibility/DetailsOutputStream.java new file mode 100644 index 00000000000..f125322c37b --- /dev/null +++ b/jdk/test/sun/security/tools/jarsigner/compatibility/DetailsOutputStream.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; + +/* + * A custom output stream that redirects the testing outputs to a file, called + * details.out. It also calls another output stream to save some outputs to + * other files. + */ +public class DetailsOutputStream extends FileOutputStream { + + private PhaseOutputStream phaseOutputStream = new PhaseOutputStream(); + + public DetailsOutputStream() throws FileNotFoundException { + super("details.out", true); + } + + public void transferPhase() throws IOException { + if (phaseOutputStream.isCorePhase()) { + phaseOutputStream.write(HtmlHelper.endHtml()); + phaseOutputStream.write(HtmlHelper.endPre()); + } + + phaseOutputStream.transfer(); + + if (phaseOutputStream.isCorePhase()) { + phaseOutputStream.write(HtmlHelper.startHtml()); + phaseOutputStream.write(HtmlHelper.startPre()); + } + } + + @Override + public void write(byte[] b) throws IOException { + super.write(b); + phaseOutputStream.write(b); + } + + @Override + public void write(int b) throws IOException { + super.write(b); + phaseOutputStream.write(b); + } + + @Override + public void write(byte b[], int off, int len) throws IOException { + super.write(b, off, len); + phaseOutputStream.write(b, off, len); + } + + public void writeAnchorName(String name, String text) throws IOException { + super.write((text).getBytes()); + super.write('\n'); + phaseOutputStream.write(HtmlHelper.anchorName(name, text)); + phaseOutputStream.write('\n'); + } +} diff --git a/jdk/test/sun/security/tools/jarsigner/compatibility/HtmlHelper.java b/jdk/test/sun/security/tools/jarsigner/compatibility/HtmlHelper.java new file mode 100644 index 00000000000..d00cf02f0d5 --- /dev/null +++ b/jdk/test/sun/security/tools/jarsigner/compatibility/HtmlHelper.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * A helper that is used for creating HTML elements. + */ +public class HtmlHelper { + + private static final String STYLE + = "style=\"font-family: Courier New; " + + "font-size: 12px; " + + "white-space: pre-wrap\""; + + public static String htmlRow(String... values) { + StringBuilder row = new StringBuilder(); + row.append(startTr()); + for (String value : values) { + row.append(startTd()); + row.append(value); + row.append(endTd()); + } + row.append(endTr()); + return row.toString(); + } + + public static String startHtml() { + return startTag("html"); + } + + public static String endHtml() { + return endTag("html"); + } + + public static String startPre() { + return startTag("pre " + STYLE); + } + + public static String endPre() { + return endTag("pre"); + } + + public static String startTable() { + return startTag("table " + STYLE); + } + + public static String endTable() { + return endTag("table"); + } + + public static String startTr() { + return startTag("tr"); + } + + public static String endTr() { + return endTag("tr"); + } + + public static String startTd() { + return startTag("td"); + } + + public static String endTd() { + return endTag("td"); + } + + public static String startTag(String tag) { + return "<" + tag + ">"; + } + + public static String endTag(String tag) { + return ""; + } + + public static String anchorName(String name, String text) { + return "" + text + ""; + } + + public static String anchorLink(String file, String anchorName, + String text) { + return "" + text + ""; + } +} diff --git a/jdk/test/sun/security/tools/jarsigner/compatibility/JdkUtils.java b/jdk/test/sun/security/tools/jarsigner/compatibility/JdkUtils.java new file mode 100644 index 00000000000..cd990161b92 --- /dev/null +++ b/jdk/test/sun/security/tools/jarsigner/compatibility/JdkUtils.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.security.NoSuchAlgorithmException; +import java.security.Signature; + +/* + * This class is used for returning some specific JDK information. + */ +public class JdkUtils { + + static final String M_JAVA_RUNTIME_VERSION = "javaRuntimeVersion"; + static final String M_IS_SUPPORTED_SIGALG = "isSupportedSigalg"; + + // Returns the JDK build version. + static String javaRuntimeVersion() { + return System.getProperty("java.runtime.version"); + } + + // Checks if the specified signature algorithm is supported by the JDK. + static boolean isSupportedSigalg(String sigalg) { + boolean isSupported = false; + try { + isSupported = Signature.getInstance(sigalg) != null; + } catch (NoSuchAlgorithmException e) { } + + if (!isSupported) { + System.out.println(sigalg + " is not supported yet."); + } + + return isSupported; + } + + public static void main(String[] args) { + if (M_JAVA_RUNTIME_VERSION.equals(args[0])) { + System.out.print(javaRuntimeVersion()); + } else if (M_IS_SUPPORTED_SIGALG.equals(args[0])) { + System.out.print(isSupportedSigalg(args[1])); + } + } +} diff --git a/jdk/test/sun/security/tools/jarsigner/compatibility/PhaseOutputStream.java b/jdk/test/sun/security/tools/jarsigner/compatibility/PhaseOutputStream.java new file mode 100644 index 00000000000..f99822ca1f8 --- /dev/null +++ b/jdk/test/sun/security/tools/jarsigner/compatibility/PhaseOutputStream.java @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/* + * A custom output stream that saves the testing details to different files + * according to the current testing phase. + */ +public class PhaseOutputStream extends OutputStream { + + public enum Phase { + PRE_SIGNING, // before jar signing + SIGNING, // jar signing + VERIFYING, // jar verifying + DELAY_VERIFYING, // jar verifying after certificates expire + POST_VERIFYING; // after jar verifying + } + + private OutputStream signingOut = null; + private OutputStream verifyingOut = null; + private OutputStream delayVerifyingOut = null; + + private Phase currentPhase = Phase.PRE_SIGNING; + + public void transfer() { + switch (currentPhase) { + case PRE_SIGNING: + currentPhase = Phase.SIGNING; + break; + case SIGNING: + currentPhase = Phase.VERIFYING; + break; + case VERIFYING: + currentPhase = Compatibility.DELAY_VERIFY + ? Phase.DELAY_VERIFYING + : Phase.POST_VERIFYING; + break; + case DELAY_VERIFYING: + currentPhase = Phase.POST_VERIFYING; + break; + case POST_VERIFYING: + currentPhase = Phase.POST_VERIFYING; + break; + } + } + + // The core phases are SIGNING, VERIFYING and DELAY_VERIFYING. + public boolean isCorePhase() { + return currentPhase != PhaseOutputStream.Phase.PRE_SIGNING + && currentPhase != PhaseOutputStream.Phase.POST_VERIFYING; + } + + public Phase currentPhase() { + return currentPhase; + } + + @Override + public void write(int b) throws IOException { + OutputStream output = phaseOut(); + if (output != null) { + output.write(b); + } + } + + @Override + public void write(byte[] b) throws IOException { + OutputStream output = phaseOut(); + if (output != null) { + output.write(b); + } + } + + @Override + public void write(byte[] b, int off, int len) throws IOException { + OutputStream output = phaseOut(); + if (output != null) { + output.write(b, off, len); + } + } + + public void write(String str) throws IOException { + write(str.getBytes()); + } + + private OutputStream phaseOut() throws FileNotFoundException { + switch (currentPhase) { + case SIGNING: + return signingOut == null + ? signingOut = createOutput(Phase.SIGNING) + : signingOut; + case VERIFYING: + return verifyingOut == null + ? verifyingOut = createOutput(Phase.VERIFYING) + : verifyingOut; + case DELAY_VERIFYING: + return delayVerifyingOut == null + ? delayVerifyingOut = createOutput(Phase.DELAY_VERIFYING) + : delayVerifyingOut; + default: + return null; + } + } + + @Override + public void flush() throws IOException { + flush(signingOut); + flush(verifyingOut); + flush(delayVerifyingOut); + } + + private void flush(OutputStream output) throws IOException { + if (output != null) { + output.flush(); + } + } + + @Override + public void close() throws IOException { + close(signingOut); + close(verifyingOut); + close(delayVerifyingOut); + } + + private void close(OutputStream output) throws IOException { + if (output != null) { + output.close(); + } + } + + private static OutputStream createOutput(Phase phase) + throws FileNotFoundException { + return new FileOutputStream(fileName(phase), true); + } + + public static String fileName(Phase phase) { + return phase.name() + ".html"; + } +} diff --git a/jdk/test/sun/security/tools/jarsigner/compatibility/README b/jdk/test/sun/security/tools/jarsigner/compatibility/README new file mode 100644 index 00000000000..7868788c2e6 --- /dev/null +++ b/jdk/test/sun/security/tools/jarsigner/compatibility/README @@ -0,0 +1,215 @@ +# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. + +##### Summary ##### +This test is used to verify the compatibility on jarsigner cross different JDK +releases. It also can be used to check jar signing (w/ and w/o TSA) and verifying +on some specific key algorithms and digest algorithms. + +##### Output ##### +The test will generate a report, at JTwork/scratch/report.html, to display the +key parameters for signing and the status of signing and verifying. And it will +generate another report, at JTwork/scratch/failedReport.html, to collect all of +failed cases. + +Please note that, the test may output a great deal of logs if the jdk list and +TSA list are big, and that would lead to jtreg output overflow. So, it redirects +stdout and stderr to file JTwork/scratch/details.out. + +##### Report Columns ##### +Certificate + Certificate identifier. The identifier consists of specific attributes of + the certificate. Generally, the naming convention is: + KeyAlgorithm_DigestAlgorithm_[KeySize][_Expired] + +Signer JDK + The JDK version that signs jar. + +Signature Algorithm + The signature algorithm used by signing. + +TSA Digest + The timestamp digest algorithm used by signing. + +TSA + TSA URL index. All of TSA URLs and their indices can be found at the top + of this report. + +Signing Status + Signing process result status. The status are the followings: + [1]NONE, no action. + [2]NORMAL, no any error and warning. + [3]WARNING, no any error but some warnings raise. + [4]ERROR, some errors raise. + +Verifier JDK + The JDK version that verifies signed jars. + +Verifying Status + Verifying process result status. The status are the same as those for + "Status of Signing". + +Delay Verifying Status + Delay verifying process result status. The status are the same as those + for "Status of Signing". + +Failed + It highlights which case fails. The failed cases (rows) are marked with + letter X. + +##### Usages ##### +jtreg [-options] \ + -jdk: + [-DproxyHost= \ + -DproxyPort= \ + -DtsaListFile= \ + -DtsaList= \ + -DjdkListFile= \ + -DjdkList= \ + -DjavaSecurityFile= \ + -DdelayVerify= \ + -DcertValidity=<[1, 1440]>] \ + /jdk/test/sun/security/tools/jarsigner/compatibility/Compatibility.java + +Besides the common jtreg options, like -jdk, this test introduces a set of +properties for receiving users' inputs and making the test more flexible. These +properties are: +proxyHost= + This property indicates proxy host. + +proxyPort= + This property indicates proxy port. The default value is 80. + +tsaListFile= + This property indicates a local file, which contains a set of TSA URLs and + the supported digest algorithms (by optional parameter digests). The format + of the file content looks like the below, + http://path/to/tsa1 + http://path/to/tsa2;digests=SHA-1,SHA-256 + https://path/to/tsa3 + ... + + If a TSA line does not list the supported digest algorithms, that means + the TSA supports SHA-1, SHA-256 and SHA-512. Because the test only focus + on SHA-1, SHA-256 and SHA-512. So, if other digest algorithms, like SHA-224 + and SHA-384, are listed, they just be ignored. + +tsaList= + This property directly lists a set of TSAs in command. "#" is the delimiter. + Note that, if both of tsaListFile and tsaList are specified, only property + jdkListFile is selected. If neither of tsaListFile and tsaList is specified, + the test will fails immediately. + +jdkListFile= + This property indicates a local file, which contains a set of local JDK + paths. The style of the file content looks like the below, + /path/to/jdk1 + /path/to/jdk2 + /path/to/jdk3 + ... + +jdkList= + This property directly lists a set of local JDK paths in command. "#" is + the delimiter. + Note that, if both of jdkListFile and jdkList are specified, only property + jdkListFile is selected. If neither of jdkListFile nor jdkList is specified, + the testing JDK, which is specified by jtreg option -jdk will be used as + the only one JDK in the JDK list. + +javaSecurityFile= + This property indicates an alternative java security properties file. The + default file is the path of file java.scurity that is distributed with + this test. + +delayVerify= + This property indicates if doing an additional verifying after all of valid + certificates expire. The default value is false. + +certValidity=<[1, 1440]> + This property indicates the remaining validity period in minutes for valid + certificates. The value range is [1, 1440]. The default value is 1440. + Note that, if delayVerify is false, this property doesn't take effect. + +The testing JDK, which is specified by jtreg option "-jdk", should include the +fix for JDK-8163304. Otherwise, the signature algorithm and timestamp digest +algorithm cannot be extracted from verification output. And this JDK should +support as many as possible signature algorithms. Anyway the latest JDK build +is always recommended. + +##### Examples ##### +$ cat /path/to/jdkList +/path/to/jdk6u171-b05 +/path/to/jdk7u161-b05 +/path/to/jdk8u144-b01 +/path/to/jdk9-179 + +$ cat /path/to/tsaList +http://timestamp.comodoca.com/rfc3161 +http://sha256timestamp.ws.symantec.com/sha256/timestamp +http://tsa.starfieldtech.com +http://timestamp.entrust.net/TSS/RFC3161sha1TS;digests=SHA-1,SHA-256 +http://timestamp.entrust.net/TSS/RFC3161sha2TS;digests=SHA-1,SHA-256 +http://rfc3161timestamp.globalsign.com/advanced;digests=SHA-256,SHA-512 +http://rfc3161timestamp.globalsign.com/standard +http://timestamp.globalsign.com/scripts/timstamp.dll +http://timestamp.globalsign.com/?signature=sha2;digests=SHA-256,SHA-512 +http://timestamp.digicert.com +http://time.certum.pl +http://tsa.swisssign.net +http://zeitstempel.dfn.de +https://tsp.iaik.tugraz.at/tsp/TspRequest + +$ jtreg -va -nr -timeout:100 \ + -jdk:/path/to/latest/jdk \ + -DproxyHost= -DproxyPort= \ + -DjdkListFile=/path/to/jdkList \ + -DtsaListFile=/path/to/tsaList \ + -DdelayVerify=true -DcertValidity=60 \ + /jdk/test/sun/security/tools/jarsigner/compatibility/Compatibility.java + +The above is a comprehensive usage example. File "jdkList" lists the paths of +testing JDK builds, and file "tsaList" lists the URLs of TSA services. Some TSAs, +like http://timestamp.entrust.net/TSS/RFC3161sha1TS, specify the supported digest +algorithms. Other TSAs, which don't specify parameter digests, are regarded to +support SHA-1, SHA-256 and SHA-512. The test uses a proxy to access TSA services. +And it enables delay verifying and set the certificate validity period to 60 +minutes. So, after the first verification is done, the test will wait for all +of valid certificates expire and then does verification again. + +If don't want to provide such JDK list and TSA list files, the test allows to +specify JDKs and TSAs (via properties jdkList and tsaList respectively) in the +command directly, like the below style, +$ jtreg -va -nr -timeout:100 \ + -jdk:/path/to/latest/jdk \ + -DproxyHost= -DproxyPort= \ + -DjdkList=/path/to/jdk6u171-b05#/path/to/jdk7u161-b05#/path/to/jdk8u144-b01#/path/to/jdk9-179 \ + -DtsaList=http://timestamp.comodoca.com/rfc3161#http://timestamp.entrust.net/TSS/RFC3161sha1TS;digests=SHA-1,SHA-256 \ + -DdelayVerify=true -DcertValidity=60 \ + /jdk/test/sun/security/tools/jarsigner/compatibility/Compatibility.java + +Furthermore, here introduces one of the simplest usages. It doesn't specify any +JDK list, so the testing JDK, which is specified by jtreg option "-jdk", will +be tested. And it doesn't apply delay verifying, and no proxy is used, and use +only one TSA. Now, the command is pretty simple and looks like the followings, +$ jtreg -va -nr -timeout:100 \ + -jdk:/path/to/latest/jdk \ + -DtsaList=http://timestamp.comodoca.com/rfc3161 \ + /jdk/test/sun/security/tools/jarsigner/compatibility/Compatibility.java \ No newline at end of file diff --git a/jdk/test/sun/security/tools/jarsigner/compatibility/java.security b/jdk/test/sun/security/tools/jarsigner/compatibility/java.security new file mode 100644 index 00000000000..b8623c1f3db --- /dev/null +++ b/jdk/test/sun/security/tools/jarsigner/compatibility/java.security @@ -0,0 +1,2 @@ +jdk.certpath.disabledAlgorithms=MD2, MD5 +jdk.jar.disabledAlgorithms=MD2, MD5 \ No newline at end of file From 997d77996c628ab6be2edfd23b5f635a59f32681 Mon Sep 17 00:00:00 2001 From: Daniel Fuchs Date: Wed, 16 Aug 2017 10:55:05 +0100 Subject: [PATCH 30/33] 8181422: ClassCastException in HTTP Client Added missing AsyncSSLTunnelConnection Reviewed-by: michaelm --- .../http/AbstractAsyncSSLConnection.java | 85 +++++ .../incubator/http/AsyncSSLConnection.java | 44 +-- .../http/AsyncSSLTunnelConnection.java | 206 +++++++++++ .../jdk/incubator/http/ExchangeImpl.java | 4 +- .../jdk/incubator/http/Http2Connection.java | 21 +- .../jdk/incubator/http/HttpConnection.java | 7 +- .../http/PlainTunnelingConnection.java | 41 ++- .../jdk/incubator/http/SSLConnection.java | 4 +- .../incubator/http/SSLTunnelConnection.java | 13 + jdk/test/java/net/httpclient/ProxyTest.java | 11 +- .../java/net/httpclient/http2/ProxyTest2.java | 323 ++++++++++++++++++ .../http2/server/Http2TestServer.java | 12 +- .../server/Http2TestServerConnection.java | 11 +- 13 files changed, 725 insertions(+), 57 deletions(-) create mode 100644 jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/AbstractAsyncSSLConnection.java create mode 100644 jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/AsyncSSLTunnelConnection.java create mode 100644 jdk/test/java/net/httpclient/http2/ProxyTest2.java diff --git a/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/AbstractAsyncSSLConnection.java b/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/AbstractAsyncSSLConnection.java new file mode 100644 index 00000000000..07223e61f25 --- /dev/null +++ b/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/AbstractAsyncSSLConnection.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.incubator.http; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.util.concurrent.CompletableFuture; +import javax.net.ssl.SSLEngine; +import jdk.incubator.http.internal.common.ExceptionallyCloseable; + + +/** + * Asynchronous version of SSLConnection. + * + * There are two concrete implementations of this class: AsyncSSLConnection + * and AsyncSSLTunnelConnection. + * This abstraction is useful when downgrading from HTTP/2 to HTTP/1.1 over + * an SSL connection. See ExchangeImpl::get in the case where an ALPNException + * is thrown. + * + * Note: An AsyncSSLConnection wraps a PlainHttpConnection, while an + * AsyncSSLTunnelConnection wraps a PlainTunnelingConnection. + * If both these wrapped classes where made to inherit from a + * common abstraction then it might be possible to merge + * AsyncSSLConnection and AsyncSSLTunnelConnection back into + * a single class - and simply use different factory methods to + * create different wrappees, but this is left up for further cleanup. + * + */ +abstract class AbstractAsyncSSLConnection extends HttpConnection + implements AsyncConnection, ExceptionallyCloseable { + + + AbstractAsyncSSLConnection(InetSocketAddress addr, HttpClientImpl client) { + super(addr, client); + } + + abstract SSLEngine getEngine(); + abstract AsyncSSLDelegate sslDelegate(); + abstract HttpConnection plainConnection(); + abstract HttpConnection downgrade(); + + @Override + final boolean isSecure() { + return true; + } + + // Blocking read functions not used here + @Override + protected final ByteBuffer readImpl() throws IOException { + throw new UnsupportedOperationException("Not supported."); + } + + // whenReceivedResponse only used in HTTP/1.1 (Http1Exchange) + // AbstractAsyncSSLConnection is only used with HTTP/2 + @Override + final CompletableFuture whenReceivingResponse() { + throw new UnsupportedOperationException("Not supported."); + } + +} diff --git a/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/AsyncSSLConnection.java b/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/AsyncSSLConnection.java index b1e6063951f..f6c095526ee 100644 --- a/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/AsyncSSLConnection.java +++ b/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/AsyncSSLConnection.java @@ -35,14 +35,12 @@ import java.util.function.Supplier; import javax.net.ssl.SSLEngine; import jdk.incubator.http.internal.common.ByteBufferReference; -import jdk.incubator.http.internal.common.ExceptionallyCloseable; import jdk.incubator.http.internal.common.Utils; /** * Asynchronous version of SSLConnection. */ -class AsyncSSLConnection extends HttpConnection - implements AsyncConnection, ExceptionallyCloseable { +class AsyncSSLConnection extends AbstractAsyncSSLConnection { final AsyncSSLDelegate sslDelegate; final PlainHttpConnection plainConnection; @@ -61,15 +59,14 @@ class AsyncSSLConnection extends HttpConnection plainConnection.configureMode(mode); } - private CompletableFuture configureModeAsync(Void ignore) { - CompletableFuture cf = new CompletableFuture<>(); - try { - configureMode(Mode.ASYNC); - cf.complete(null); - } catch (Throwable t) { - cf.completeExceptionally(t); - } - return cf; + @Override + PlainHttpConnection plainConnection() { + return plainConnection; + } + + @Override + AsyncSSLDelegate sslDelegate() { + return sslDelegate; } @Override @@ -91,11 +88,6 @@ class AsyncSSLConnection extends HttpConnection return plainConnection.connected() && sslDelegate.connected(); } - @Override - boolean isSecure() { - return true; - } - @Override boolean isProxied() { return false; @@ -172,6 +164,7 @@ class AsyncSSLConnection extends HttpConnection plainConnection.channel().shutdownOutput(); } + @Override SSLEngine getEngine() { return sslDelegate.getEngine(); } @@ -184,18 +177,6 @@ class AsyncSSLConnection extends HttpConnection plainConnection.setAsyncCallbacks(sslDelegate::asyncReceive, errorReceiver, sslDelegate::getNetBuffer); } - // Blocking read functions not used here - - @Override - protected ByteBuffer readImpl() throws IOException { - throw new UnsupportedOperationException("Not supported."); - } - - @Override - CompletableFuture whenReceivingResponse() { - throw new UnsupportedOperationException("Not supported."); - } - @Override public void startReading() { plainConnection.startReading(); @@ -206,4 +187,9 @@ class AsyncSSLConnection extends HttpConnection public void stopAsyncReading() { plainConnection.stopAsyncReading(); } + + @Override + SSLConnection downgrade() { + return new SSLConnection(this); + } } diff --git a/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/AsyncSSLTunnelConnection.java b/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/AsyncSSLTunnelConnection.java new file mode 100644 index 00000000000..7afb87f5191 --- /dev/null +++ b/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/AsyncSSLTunnelConnection.java @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.incubator.http; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.SocketChannel; +import java.util.concurrent.CompletableFuture; +import java.util.function.Consumer; +import java.util.function.Supplier; +import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLParameters; +import jdk.incubator.http.internal.common.ByteBufferReference; +import jdk.incubator.http.internal.common.Utils; + +/** + * An SSL tunnel built on a Plain (CONNECT) TCP tunnel. + */ +class AsyncSSLTunnelConnection extends AbstractAsyncSSLConnection { + + final PlainTunnelingConnection plainConnection; + final AsyncSSLDelegate sslDelegate; + final String serverName; + + @Override + public void connect() throws IOException, InterruptedException { + plainConnection.connect(); + configureMode(Mode.ASYNC); + startReading(); + sslDelegate.connect(); + } + + @Override + boolean connected() { + return plainConnection.connected() && sslDelegate.connected(); + } + + @Override + public CompletableFuture connectAsync() { + throw new InternalError(); + } + + AsyncSSLTunnelConnection(InetSocketAddress addr, + HttpClientImpl client, + String[] alpn, + InetSocketAddress proxy) + { + super(addr, client); + this.serverName = Utils.getServerName(addr); + this.plainConnection = new PlainTunnelingConnection(addr, proxy, client); + this.sslDelegate = new AsyncSSLDelegate(plainConnection, client, alpn, serverName); + } + + @Override + synchronized void configureMode(Mode mode) throws IOException { + super.configureMode(mode); + plainConnection.configureMode(mode); + } + + @Override + SSLParameters sslParameters() { + return sslDelegate.getSSLParameters(); + } + + @Override + public String toString() { + return "AsyncSSLTunnelConnection: " + super.toString(); + } + + @Override + PlainTunnelingConnection plainConnection() { + return plainConnection; + } + + @Override + AsyncSSLDelegate sslDelegate() { + return sslDelegate; + } + + @Override + ConnectionPool.CacheKey cacheKey() { + return ConnectionPool.cacheKey(address, plainConnection.proxyAddr); + } + + @Override + long write(ByteBuffer[] buffers, int start, int number) throws IOException { + //debugPrint("Send", buffers, start, number); + ByteBuffer[] bufs = Utils.reduce(buffers, start, number); + long n = Utils.remaining(bufs); + sslDelegate.writeAsync(ByteBufferReference.toReferences(bufs)); + sslDelegate.flushAsync(); + return n; + } + + @Override + long write(ByteBuffer buffer) throws IOException { + //debugPrint("Send", buffer); + long n = buffer.remaining(); + sslDelegate.writeAsync(ByteBufferReference.toReferences(buffer)); + sslDelegate.flushAsync(); + return n; + } + + @Override + public void writeAsync(ByteBufferReference[] buffers) throws IOException { + sslDelegate.writeAsync(buffers); + } + + @Override + public void writeAsyncUnordered(ByteBufferReference[] buffers) throws IOException { + sslDelegate.writeAsyncUnordered(buffers); + } + + @Override + public void flushAsync() throws IOException { + sslDelegate.flushAsync(); + } + + @Override + public void close() { + Utils.close(sslDelegate, plainConnection.channel()); + } + + @Override + void shutdownInput() throws IOException { + plainConnection.channel().shutdownInput(); + } + + @Override + void shutdownOutput() throws IOException { + plainConnection.channel().shutdownOutput(); + } + + @Override + SocketChannel channel() { + return plainConnection.channel(); + } + + @Override + boolean isProxied() { + return true; + } + + @Override + public void setAsyncCallbacks(Consumer asyncReceiver, + Consumer errorReceiver, + Supplier readBufferSupplier) { + sslDelegate.setAsyncCallbacks(asyncReceiver, errorReceiver, readBufferSupplier); + plainConnection.setAsyncCallbacks(sslDelegate::asyncReceive, errorReceiver, sslDelegate::getNetBuffer); + } + + @Override + public void startReading() { + plainConnection.startReading(); + sslDelegate.startReading(); + } + + @Override + public void stopAsyncReading() { + plainConnection.stopAsyncReading(); + } + + @Override + public void enableCallback() { + sslDelegate.enableCallback(); + } + + @Override + public void closeExceptionally(Throwable cause) throws IOException { + Utils.close(cause, sslDelegate, plainConnection.channel()); + } + + @Override + SSLEngine getEngine() { + return sslDelegate.getEngine(); + } + + @Override + SSLTunnelConnection downgrade() { + return new SSLTunnelConnection(this); + } +} diff --git a/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/ExchangeImpl.java b/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/ExchangeImpl.java index 27b6c1964f4..3d41179d903 100644 --- a/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/ExchangeImpl.java +++ b/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/ExchangeImpl.java @@ -82,9 +82,9 @@ abstract class ExchangeImpl { c = c2.getConnectionFor(request); } catch (Http2Connection.ALPNException e) { // failed to negotiate "h2" - AsyncSSLConnection as = e.getConnection(); + AbstractAsyncSSLConnection as = e.getConnection(); as.stopAsyncReading(); - SSLConnection sslc = new SSLConnection(as); + HttpConnection sslc = as.downgrade(); ExchangeImpl ex = new Http1Exchange<>(exchange, sslc); return ex; } diff --git a/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/Http2Connection.java b/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/Http2Connection.java index 275325f8b29..8e42022c286 100644 --- a/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/Http2Connection.java +++ b/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/Http2Connection.java @@ -211,12 +211,13 @@ class Http2Connection { this.hpackIn = new Decoder(clientSettings.getParameter(HEADER_TABLE_SIZE)); this.windowUpdater = new ConnectionWindowUpdateSender(this, client.getReceiveBufferSize()); } - /** - * Case 1) Create from upgraded HTTP/1.1 connection. - * Is ready to use. Will not be SSL. exchange is the Exchange - * that initiated the connection, whose response will be delivered - * on a Stream. - */ + + /** + * Case 1) Create from upgraded HTTP/1.1 connection. + * Is ready to use. Will not be SSL. exchange is the Exchange + * that initiated the connection, whose response will be delivered + * on a Stream. + */ Http2Connection(HttpConnection connection, Http2ClientImpl client2, Exchange exchange, @@ -280,7 +281,7 @@ class Http2Connection { * Throws an IOException if h2 was not negotiated */ private void checkSSLConfig() throws IOException { - AsyncSSLConnection aconn = (AsyncSSLConnection)connection; + AbstractAsyncSSLConnection aconn = (AbstractAsyncSSLConnection)connection; SSLEngine engine = aconn.getEngine(); String alpn = engine.getApplicationProtocol(); if (alpn == null || !alpn.equals("h2")) { @@ -906,14 +907,14 @@ class Http2Connection { */ static final class ALPNException extends IOException { private static final long serialVersionUID = 23138275393635783L; - final AsyncSSLConnection connection; + final AbstractAsyncSSLConnection connection; - ALPNException(String msg, AsyncSSLConnection connection) { + ALPNException(String msg, AbstractAsyncSSLConnection connection) { super(msg); this.connection = connection; } - AsyncSSLConnection getConnection() { + AbstractAsyncSSLConnection getConnection() { return connection; } } diff --git a/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/HttpConnection.java b/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/HttpConnection.java index a520390ba2d..d81d3950374 100644 --- a/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/HttpConnection.java +++ b/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/HttpConnection.java @@ -34,7 +34,6 @@ import java.nio.channels.SocketChannel; import java.util.concurrent.CompletableFuture; import jdk.incubator.http.internal.common.ByteBufferReference; -import jdk.incubator.http.internal.common.Utils; /** * Wraps socket channel layer and takes care of SSL also. @@ -136,7 +135,11 @@ abstract class HttpConnection implements Closeable { String[] alpn, boolean isHttp2, HttpClientImpl client) { if (proxy != null) { - return new SSLTunnelConnection(addr, client, proxy); + if (!isHttp2) { + return new SSLTunnelConnection(addr, client, proxy); + } else { + return new AsyncSSLTunnelConnection(addr, client, alpn, proxy); + } } else if (!isHttp2) { return new SSLConnection(addr, client, alpn); } else { diff --git a/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/PlainTunnelingConnection.java b/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/PlainTunnelingConnection.java index d133df1e250..c167c53f2b3 100644 --- a/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/PlainTunnelingConnection.java +++ b/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/PlainTunnelingConnection.java @@ -34,12 +34,15 @@ import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.concurrent.CompletableFuture; +import java.util.function.Consumer; +import java.util.function.Supplier; /** * A plain text socket tunnel through a proxy. Uses "CONNECT" but does not - * encrypt. Used by WebSocket. Subclassed in SSLTunnelConnection for encryption. + * encrypt. Used by WebSocket, as well as HTTP over SSL + Proxy. + * Wrapped in SSLTunnelConnection or AsyncSSLTunnelConnection for encryption. */ -class PlainTunnelingConnection extends HttpConnection { +class PlainTunnelingConnection extends HttpConnection implements AsyncConnection { final PlainHttpConnection delegate; protected final InetSocketAddress proxyAddr; @@ -116,17 +119,17 @@ class PlainTunnelingConnection extends HttpConnection { } @Override - void writeAsync(ByteBufferReference[] buffers) throws IOException { + public void writeAsync(ByteBufferReference[] buffers) throws IOException { delegate.writeAsync(buffers); } @Override - void writeAsyncUnordered(ByteBufferReference[] buffers) throws IOException { + public void writeAsyncUnordered(ByteBufferReference[] buffers) throws IOException { delegate.writeAsyncUnordered(buffers); } @Override - void flushAsync() throws IOException { + public void flushAsync() throws IOException { delegate.flushAsync(); } @@ -165,4 +168,32 @@ class PlainTunnelingConnection extends HttpConnection { boolean isProxied() { return true; } + + @Override + public void setAsyncCallbacks(Consumer asyncReceiver, + Consumer errorReceiver, + Supplier readBufferSupplier) { + delegate.setAsyncCallbacks(asyncReceiver, errorReceiver, readBufferSupplier); + } + + @Override + public void startReading() { + delegate.startReading(); + } + + @Override + public void stopAsyncReading() { + delegate.stopAsyncReading(); + } + + @Override + public void enableCallback() { + delegate.enableCallback(); + } + + @Override + synchronized void configureMode(Mode mode) throws IOException { + super.configureMode(mode); + delegate.configureMode(mode); + } } diff --git a/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/SSLConnection.java b/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/SSLConnection.java index 790d98b7fa0..9eb6a37e250 100644 --- a/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/SSLConnection.java +++ b/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/SSLConnection.java @@ -77,8 +77,8 @@ class SSLConnection extends HttpConnection { */ SSLConnection(AsyncSSLConnection c) { super(c.address, c.client); - this.delegate = c.plainConnection; - AsyncSSLDelegate adel = c.sslDelegate; + this.delegate = c.plainConnection(); + AsyncSSLDelegate adel = c.sslDelegate(); this.sslDelegate = new SSLDelegate(adel.engine, delegate.channel(), client, adel.serverName); this.alpn = adel.alpn; this.serverName = adel.serverName; diff --git a/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/SSLTunnelConnection.java b/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/SSLTunnelConnection.java index fcd71728b5b..d5cade109b7 100644 --- a/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/SSLTunnelConnection.java +++ b/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/SSLTunnelConnection.java @@ -85,6 +85,19 @@ class SSLTunnelConnection extends HttpConnection { delegate = new PlainTunnelingConnection(addr, proxy, client); } + /** + * Create an SSLTunnelConnection from an existing connected AsyncSSLTunnelConnection. + * Used when downgrading from HTTP/2 to HTTP/1.1 + */ + SSLTunnelConnection(AsyncSSLTunnelConnection c) { + super(c.address, c.client); + this.delegate = c.plainConnection(); + AsyncSSLDelegate adel = c.sslDelegate(); + this.sslDelegate = new SSLDelegate(adel.engine, delegate.channel(), client, adel.serverName); + this.serverName = adel.serverName; + connected = c.connected(); + } + @Override SSLParameters sslParameters() { return sslDelegate.getSSLParameters(); diff --git a/jdk/test/java/net/httpclient/ProxyTest.java b/jdk/test/java/net/httpclient/ProxyTest.java index 8dc90dfb1a1..f6590d89f17 100644 --- a/jdk/test/java/net/httpclient/ProxyTest.java +++ b/jdk/test/java/net/httpclient/ProxyTest.java @@ -56,9 +56,12 @@ import jdk.testlibrary.SimpleSSLContext; /** * @test - * @bug 8185852 - * @summary verifies that passing a proxy with an unresolved address does - * not cause java.nio.channels.UnresolvedAddressException + * @bug 8185852 8181422 + * @summary Verifies that passing a proxy with an unresolved address does + * not cause java.nio.channels.UnresolvedAddressException. + * Verifies that downgrading from HTTP/2 to HTTP/1.1 works through + * an SSL Tunnel connection when the client is HTTP/2 and the server + * and proxy are HTTP/1.1 * @modules jdk.incubator.httpclient * @library /lib/testlibrary/ * @build jdk.testlibrary.SimpleSSLContext ProxyTest @@ -111,7 +114,7 @@ public class ProxyTest { server.start(); try { test(server, HttpClient.Version.HTTP_1_1); - // test(server, HttpClient.Version.HTTP_2); + test(server, HttpClient.Version.HTTP_2); } finally { server.stop(0); System.out.println("Server stopped"); diff --git a/jdk/test/java/net/httpclient/http2/ProxyTest2.java b/jdk/test/java/net/httpclient/http2/ProxyTest2.java new file mode 100644 index 00000000000..3a06bd304e1 --- /dev/null +++ b/jdk/test/java/net/httpclient/http2/ProxyTest2.java @@ -0,0 +1,323 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import com.sun.net.httpserver.HttpContext; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; +import com.sun.net.httpserver.HttpsConfigurator; +import com.sun.net.httpserver.HttpsParameters; +import com.sun.net.httpserver.HttpsServer; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.io.Writer; +import java.net.HttpURLConnection; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.net.ProxySelector; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.charset.StandardCharsets; +import java.security.NoSuchAlgorithmException; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSession; +import jdk.incubator.http.HttpClient; +import jdk.incubator.http.HttpRequest; +import jdk.incubator.http.HttpResponse; +import jdk.testlibrary.SimpleSSLContext; +import java.util.concurrent.*; + +/** + * @test + * @bug 8181422 + * @summary Verifies that you can access an HTTP/2 server over HTTPS by + * tunnelling through an HTTP/1.1 proxy. + * @modules jdk.incubator.httpclient + * @library /lib/testlibrary server + * @modules jdk.incubator.httpclient/jdk.incubator.http.internal.common + * jdk.incubator.httpclient/jdk.incubator.http.internal.frame + * jdk.incubator.httpclient/jdk.incubator.http.internal.hpack + * @build jdk.testlibrary.SimpleSSLContext ProxyTest2 + * @run main/othervm ProxyTest2 + * @author danielfuchs + */ +public class ProxyTest2 { + + static { + try { + HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() { + public boolean verify(String hostname, SSLSession session) { + return true; + } + }); + SSLContext.setDefault(new SimpleSSLContext().get()); + } catch (IOException ex) { + throw new ExceptionInInitializerError(ex); + } + } + + static final String RESPONSE = "

    Hello World!"; + static final String PATH = "/foo/"; + + static Http2TestServer createHttpsServer(ExecutorService exec) throws Exception { + Http2TestServer server = new Http2TestServer(true, 0, exec, SSLContext.getDefault()); + server.addHandler(new Http2Handler() { + @Override + public void handle(Http2TestExchange he) throws IOException { + he.getResponseHeaders().addHeader("encoding", "UTF-8"); + he.sendResponseHeaders(200, RESPONSE.length()); + he.getResponseBody().write(RESPONSE.getBytes(StandardCharsets.UTF_8)); + he.close(); + } + }, PATH); + + return server; + } + + public static void main(String[] args) + throws Exception + { + ExecutorService exec = Executors.newCachedThreadPool(); + Http2TestServer server = createHttpsServer(exec); + server.start(); + try { + // Http2TestServer over HTTPS does not support HTTP/1.1 + // => only test with a HTTP/2 client + test(server, HttpClient.Version.HTTP_2); + } finally { + server.stop(); + exec.shutdown(); + System.out.println("Server stopped"); + } + } + + public static void test(Http2TestServer server, HttpClient.Version version) + throws Exception + { + System.out.println("Server is: " + server.getAddress().toString()); + URI uri = new URI("https://localhost:" + server.getAddress().getPort() + PATH + "x"); + TunnelingProxy proxy = new TunnelingProxy(server); + proxy.start(); + try { + System.out.println("Proxy started"); + Proxy p = new Proxy(Proxy.Type.HTTP, + InetSocketAddress.createUnresolved("localhost", proxy.getAddress().getPort())); + System.out.println("Setting up request with HttpClient for version: " + + version.name() + "URI=" + uri); + ProxySelector ps = ProxySelector.of( + InetSocketAddress.createUnresolved("localhost", proxy.getAddress().getPort())); + HttpClient client = HttpClient.newBuilder() + .version(version) + .proxy(ps) + .build(); + HttpRequest request = HttpRequest.newBuilder() + .uri(uri) + .GET() + .build(); + + System.out.println("Sending request with HttpClient"); + HttpResponse response + = client.send(request, HttpResponse.BodyHandler.asString()); + System.out.println("Got response"); + String resp = response.body(); + System.out.println("Received: " + resp); + if (!RESPONSE.equals(resp)) { + throw new AssertionError("Unexpected response"); + } + } finally { + System.out.println("Stopping proxy"); + proxy.stop(); + System.out.println("Proxy stopped"); + } + } + + static class TunnelingProxy { + final Thread accept; + final ServerSocket ss; + final boolean DEBUG = false; + final Http2TestServer serverImpl; + TunnelingProxy(Http2TestServer serverImpl) throws IOException { + this.serverImpl = serverImpl; + ss = new ServerSocket(); + accept = new Thread(this::accept); + } + + void start() throws IOException { + ss.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); + accept.start(); + } + + // Pipe the input stream to the output stream. + private synchronized Thread pipe(InputStream is, OutputStream os, char tag) { + return new Thread("TunnelPipe("+tag+")") { + @Override + public void run() { + try { + try { + int c; + while ((c = is.read()) != -1) { + os.write(c); + os.flush(); + // if DEBUG prints a + or a - for each transferred + // character. + if (DEBUG) System.out.print(tag); + } + is.close(); + } finally { + os.close(); + } + } catch (IOException ex) { + if (DEBUG) ex.printStackTrace(System.out); + } + } + }; + } + + public InetSocketAddress getAddress() { + return new InetSocketAddress(ss.getInetAddress(), ss.getLocalPort()); + } + + // This is a bit shaky. It doesn't handle continuation + // lines, but our client shouldn't send any. + // Read a line from the input stream, swallowing the final + // \r\n sequence. Stops at the first \n, doesn't complain + // if it wasn't preceded by '\r'. + // + String readLine(InputStream r) throws IOException { + StringBuilder b = new StringBuilder(); + int c; + while ((c = r.read()) != -1) { + if (c == '\n') break; + b.appendCodePoint(c); + } + if (b.codePointAt(b.length() -1) == '\r') { + b.delete(b.length() -1, b.length()); + } + return b.toString(); + } + + public void accept() { + Socket clientConnection = null; + try { + while (true) { + System.out.println("Tunnel: Waiting for client"); + Socket previous = clientConnection; + try { + clientConnection = ss.accept(); + } catch (IOException io) { + if (DEBUG) io.printStackTrace(System.out); + break; + } finally { + // we have only 1 client at a time, so it is safe + // to close the previous connection here + if (previous != null) previous.close(); + } + System.out.println("Tunnel: Client accepted"); + Socket targetConnection = null; + InputStream ccis = clientConnection.getInputStream(); + OutputStream ccos = clientConnection.getOutputStream(); + Writer w = new OutputStreamWriter(ccos, "UTF-8"); + PrintWriter pw = new PrintWriter(w); + System.out.println("Tunnel: Reading request line"); + String requestLine = readLine(ccis); + System.out.println("Tunnel: Request status line: " + requestLine); + if (requestLine.startsWith("CONNECT ")) { + // We should probably check that the next word following + // CONNECT is the host:port of our HTTPS serverImpl. + // Some improvement for a followup! + + // Read all headers until we find the empty line that + // signals the end of all headers. + while(!requestLine.equals("")) { + System.out.println("Tunnel: Reading header: " + + (requestLine = readLine(ccis))); + } + + // Open target connection + targetConnection = new Socket( + serverImpl.getAddress().getAddress(), + serverImpl.getAddress().getPort()); + + // Then send the 200 OK response to the client + System.out.println("Tunnel: Sending " + + "HTTP/1.1 200 OK\r\n\r\n"); + pw.print("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n"); + pw.flush(); + } else { + // This should not happen. + throw new IOException("Tunnel: Unexpected status line: " + + requestLine); + } + + // Pipe the input stream of the client connection to the + // output stream of the target connection and conversely. + // Now the client and target will just talk to each other. + System.out.println("Tunnel: Starting tunnel pipes"); + Thread t1 = pipe(ccis, targetConnection.getOutputStream(), '+'); + Thread t2 = pipe(targetConnection.getInputStream(), ccos, '-'); + t1.start(); + t2.start(); + + // We have only 1 client... wait until it has finished before + // accepting a new connection request. + // System.out.println("Tunnel: Waiting for pipes to close"); + t1.join(); + t2.join(); + System.out.println("Tunnel: Done - waiting for next client"); + } + } catch (Throwable ex) { + try { + ss.close(); + } catch (IOException ex1) { + ex.addSuppressed(ex1); + } + ex.printStackTrace(System.err); + } + } + + void stop() throws IOException { + ss.close(); + } + + } + + static class Configurator extends HttpsConfigurator { + public Configurator(SSLContext ctx) { + super(ctx); + } + + @Override + public void configure (HttpsParameters params) { + params.setSSLParameters (getSSLContext().getSupportedSSLParameters()); + } + } + +} diff --git a/jdk/test/java/net/httpclient/http2/server/Http2TestServer.java b/jdk/test/java/net/httpclient/http2/server/Http2TestServer.java index 4a56e9beb4f..6889cf7aec8 100644 --- a/jdk/test/java/net/httpclient/http2/server/Http2TestServer.java +++ b/jdk/test/java/net/httpclient/http2/server/Http2TestServer.java @@ -201,7 +201,17 @@ public class Http2TestServer implements AutoCloseable { InetSocketAddress addr = (InetSocketAddress) socket.getRemoteSocketAddress(); Http2TestServerConnection c = new Http2TestServerConnection(this, socket); connections.put(addr, c); - c.run(); + try { + c.run(); + } catch(Throwable e) { + // we should not reach here, but if we do + // the connection might not have been closed + // and if so then the client might wait + // forever. + connections.remove(addr, c); + c.close(); + throw e; + } } } catch (Throwable e) { if (!stopping) { diff --git a/jdk/test/java/net/httpclient/http2/server/Http2TestServerConnection.java b/jdk/test/java/net/httpclient/http2/server/Http2TestServerConnection.java index 57698291ef1..5645c200692 100644 --- a/jdk/test/java/net/httpclient/http2/server/Http2TestServerConnection.java +++ b/jdk/test/java/net/httpclient/http2/server/Http2TestServerConnection.java @@ -133,10 +133,10 @@ public class Http2TestServerConnection { } void close() { + stopping = true; streams.forEach((i, q) -> { q.close(); }); - stopping = true; try { socket.close(); // TODO: put a reset on each stream @@ -557,7 +557,14 @@ public class Http2TestServerConnection { void writeLoop() { try { while (!stopping) { - Http2Frame frame = outputQ.take(); + Http2Frame frame; + try { + frame = outputQ.take(); + } catch(IOException x) { + if (stopping && x.getCause() instanceof InterruptedException) { + break; + } else throw x; + } if (frame instanceof ResponseHeaders) { ResponseHeaders rh = (ResponseHeaders)frame; HeadersFrame hf = new HeadersFrame(rh.streamid(), rh.getFlags(), encodeHeaders(rh.headers)); From ce6e379b4ed1df135613f6da8e41ed582d5c1fad Mon Sep 17 00:00:00 2001 From: Phil Race Date: Wed, 16 Aug 2017 11:29:58 -0700 Subject: [PATCH 31/33] 8186259: IOExceptionIfEncodedURLTest.sh versus IOExceptionIfEncodedURLTest.java Reviewed-by: tbell --- .../IOExceptionIfEncodedURLTest.java | 11 ----------- .../IOExceptionIfEncodedURLTest.sh | 2 +- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/jdk/test/java/awt/appletviewer/IOExceptionIfEncodedURLTest/IOExceptionIfEncodedURLTest.java b/jdk/test/java/awt/appletviewer/IOExceptionIfEncodedURLTest/IOExceptionIfEncodedURLTest.java index 0db61d6db50..fc3945a7827 100644 --- a/jdk/test/java/awt/appletviewer/IOExceptionIfEncodedURLTest/IOExceptionIfEncodedURLTest.java +++ b/jdk/test/java/awt/appletviewer/IOExceptionIfEncodedURLTest/IOExceptionIfEncodedURLTest.java @@ -21,17 +21,6 @@ * questions. */ -/** - * @test - * @key headful - * @bug 6193279 - * @summary REGRESSION: AppletViewer throws IOException when path is encoded URL - * @author Dmitry Cherepanov: area=appletviewer - * @run compile IOExceptionIfEncodedURLTest.java - * @run main IOExceptionIfEncodedURLTest - * @run shell IOExceptionIfEncodedURLTest.sh - */ - import java.applet.Applet; import sun.net.www.ParseUtil; import java.io.File; diff --git a/jdk/test/java/awt/appletviewer/IOExceptionIfEncodedURLTest/IOExceptionIfEncodedURLTest.sh b/jdk/test/java/awt/appletviewer/IOExceptionIfEncodedURLTest/IOExceptionIfEncodedURLTest.sh index 619b57e0632..ddc86922a83 100644 --- a/jdk/test/java/awt/appletviewer/IOExceptionIfEncodedURLTest/IOExceptionIfEncodedURLTest.sh +++ b/jdk/test/java/awt/appletviewer/IOExceptionIfEncodedURLTest/IOExceptionIfEncodedURLTest.sh @@ -25,7 +25,7 @@ # # @test IOExceptionIfEncodedURLTest.sh # @key headful -# @bug 6193279 6619458 8137087 +# @bug 6193279 6619458 8137087 8186259 # @summary REGRESSION: AppletViewer throws IOException when path is encoded URL # @author Dmitry Cherepanov: area=appletviewer # @modules java.base/sun.net.www From fd1b70775855a45486639ba19179a7a927ac24b3 Mon Sep 17 00:00:00 2001 From: Xueming Shen Date: Wed, 16 Aug 2017 13:15:45 -0700 Subject: [PATCH 32/33] 8186227: jdk/nio/zipfs/ZeroDate.java fails on Windows with "IllegalArgumentException: Illegal character in opaque part at index 13" Reviewed-by: rriggs --- jdk/test/jdk/nio/zipfs/ZeroDate.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jdk/test/jdk/nio/zipfs/ZeroDate.java b/jdk/test/jdk/nio/zipfs/ZeroDate.java index 1a65c9b39b6..f8624064783 100644 --- a/jdk/test/jdk/nio/zipfs/ZeroDate.java +++ b/jdk/test/jdk/nio/zipfs/ZeroDate.java @@ -44,7 +44,7 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; /* @test - * @bug 8184940 + * @bug 8184940 8186227 * @summary JDK 9 rejects zip files where the modified day or month is 0 * @author Liam Miller-Cushon */ @@ -85,7 +85,7 @@ public class ZeroDate { try (OutputStream os = Files.newOutputStream(path)) { os.write(data); } - URI uri = URI.create("jar:file://" + path.toAbsolutePath()); + URI uri = URI.create("jar:" + path.toUri()); try (FileSystem fs = FileSystems.newFileSystem(uri, Collections.emptyMap())) { Path entry = fs.getPath("x"); Instant actualInstant = From f1c5dd9a930391c18abc1e270a773e585b1c88a8 Mon Sep 17 00:00:00 2001 From: Roger Riggs Date: Wed, 16 Aug 2017 16:46:51 -0400 Subject: [PATCH 33/33] 8185346: Relax RMI Registry Serial Filter to allow arrays of any type Registry filter should allow arrays of any type Reviewed-by: dfuchs, smarks, coffeys --- .../classes/java/io/ObjectInputFilter.java | 38 +++++++++++++++++-- .../misc/JavaObjectInputFilterAccess.java | 38 +++++++++++++++++++ .../jdk/internal/misc/SharedSecrets.java | 13 +++++++ .../share/conf/security/java.security | 28 +++++++++++++- .../sun/rmi/registry/RegistryImpl.java | 21 ++++------ .../serialFilter/RegistryFilterTest.java | 18 +++------ 6 files changed, 124 insertions(+), 32 deletions(-) create mode 100644 jdk/src/java.base/share/classes/jdk/internal/misc/JavaObjectInputFilterAccess.java diff --git a/jdk/src/java.base/share/classes/java/io/ObjectInputFilter.java b/jdk/src/java.base/share/classes/java/io/ObjectInputFilter.java index 534e1b2b8de..a45b655f8e7 100644 --- a/jdk/src/java.base/share/classes/java/io/ObjectInputFilter.java +++ b/jdk/src/java.base/share/classes/java/io/ObjectInputFilter.java @@ -34,6 +34,7 @@ import java.util.Objects; import java.util.Optional; import java.util.function.Function; +import jdk.internal.misc.SharedSecrets; /** * Filter classes, array lengths, and graph metrics during deserialization. @@ -265,6 +266,9 @@ public interface ObjectInputFilter { return null; }); configLog = (configuredFilter != null) ? System.getLogger("java.io.serialization") : null; + + // Setup shared secrets for RegistryImpl to use. + SharedSecrets.setJavaObjectInputFilterAccess(Config::createFilter2); } /** @@ -370,7 +374,20 @@ public interface ObjectInputFilter { */ public static ObjectInputFilter createFilter(String pattern) { Objects.requireNonNull(pattern, "pattern"); - return Global.createFilter(pattern); + return Global.createFilter(pattern, true); + } + + /** + * Returns an ObjectInputFilter from a string of patterns that + * checks only the length for arrays, not the component type. + * + * @param pattern the pattern string to parse; not null + * @return a filter to check a class being deserialized; + * {@code null} if no patterns + */ + static ObjectInputFilter createFilter2(String pattern) { + Objects.requireNonNull(pattern, "pattern"); + return Global.createFilter(pattern, false); } /** @@ -404,20 +421,26 @@ public interface ObjectInputFilter { * Maximum length of any array. */ private long maxArrayLength; + /** + * True to check the component type for arrays. + */ + private final boolean checkComponentType; /** * Returns an ObjectInputFilter from a string of patterns. * * @param pattern the pattern string to parse + * @param checkComponentType true if the filter should check + * the component type of arrays * @return a filter to check a class being deserialized; * {@code null} if no patterns * @throws IllegalArgumentException if the parameter is malformed * if the pattern is missing the name, the long value * is not a number or is negative. */ - static ObjectInputFilter createFilter(String pattern) { + static ObjectInputFilter createFilter(String pattern, boolean checkComponentType) { try { - return new Global(pattern); + return new Global(pattern, checkComponentType); } catch (UnsupportedOperationException uoe) { // no non-empty patterns return null; @@ -428,12 +451,15 @@ public interface ObjectInputFilter { * Construct a new filter from the pattern String. * * @param pattern a pattern string of filters + * @param checkComponentType true if the filter should check + * the component type of arrays * @throws IllegalArgumentException if the pattern is malformed * @throws UnsupportedOperationException if there are no non-empty patterns */ - private Global(String pattern) { + private Global(String pattern, boolean checkComponentType) { boolean hasLimits = false; this.pattern = pattern; + this.checkComponentType = checkComponentType; maxArrayLength = Long.MAX_VALUE; // Default values are unlimited maxDepth = Long.MAX_VALUE; @@ -595,6 +621,10 @@ public interface ObjectInputFilter { // array length is too big return Status.REJECTED; } + if (!checkComponentType) { + // As revised; do not check the component type for arrays + return Status.UNDECIDED; + } do { // Arrays are decided based on the component type clazz = clazz.getComponentType(); diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaObjectInputFilterAccess.java b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaObjectInputFilterAccess.java new file mode 100644 index 00000000000..5edb4c778e4 --- /dev/null +++ b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaObjectInputFilterAccess.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.internal.misc; + +import java.io.ObjectInputFilter; + +/** + * Access to the alternative ObjectInputFilter.Config.createFilter2 for RMI. + */ +public interface JavaObjectInputFilterAccess { + /** + * Creates a filter from the pattern. + */ + ObjectInputFilter createFilter2(String pattern); +} diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java b/jdk/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java index cd54d422c21..0f60833ec78 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java +++ b/jdk/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java @@ -25,6 +25,7 @@ package jdk.internal.misc; +import java.io.ObjectInputFilter; import java.lang.module.ModuleDescriptor; import java.util.ResourceBundle; import java.util.jar.JarFile; @@ -70,6 +71,7 @@ public class SharedSecrets { private static JavaAWTFontAccess javaAWTFontAccess; private static JavaBeansAccess javaBeansAccess; private static JavaObjectInputStreamAccess javaObjectInputStreamAccess; + private static JavaObjectInputFilterAccess javaObjectInputFilterAccess; private static JavaIORandomAccessFileAccess javaIORandomAccessFileAccess; public static JavaUtilJarAccess javaUtilJarAccess() { @@ -315,6 +317,17 @@ public class SharedSecrets { javaObjectInputStreamAccess = access; } + public static JavaObjectInputFilterAccess getJavaObjectInputFilterAccess() { + if (javaObjectInputFilterAccess == null) { + unsafe.ensureClassInitialized(ObjectInputFilter.Config.class); + } + return javaObjectInputFilterAccess; + } + + public static void setJavaObjectInputFilterAccess(JavaObjectInputFilterAccess access) { + javaObjectInputFilterAccess = access; + } + public static void setJavaIORandomAccessFileAccess(JavaIORandomAccessFileAccess jirafa) { javaIORandomAccessFileAccess = jirafa; } diff --git a/jdk/src/java.base/share/conf/security/java.security b/jdk/src/java.base/share/conf/security/java.security index 5ddf6198819..2ea7c3616d3 100644 --- a/jdk/src/java.base/share/conf/security/java.security +++ b/jdk/src/java.base/share/conf/security/java.security @@ -951,12 +951,36 @@ jdk.xml.dsig.secureValidationPolicy=\ # # The filter pattern uses the same format as jdk.serialFilter. # This filter can override the builtin filter if additional types need to be -# allowed or rejected from the RMI Registry. +# allowed or rejected from the RMI Registry or to decrease limits but not +# to increase limits. +# If the limits (maxdepth, maxrefs, or maxbytes) are exceeded, the object is rejected. +# +# Each non-array type is allowed or rejected if it matches one of the patterns, +# evaluated from left to right, and is otherwise allowed. Arrays of any +# component type, including subarrays and arrays of primitives, are allowed. +# +# Array construction of any component type, including subarrays and arrays of +# primitives, are allowed unless the length is greater than the maxarray limit. +# The filter is applied to each array element. # # Note: This property is currently used by the JDK Reference implementation. # It is not guaranteed to be examined and used by other implementations. # -#sun.rmi.registry.registryFilter=pattern;pattern +# The built-in filter allows subclasses of allowed classes and +# can approximately be represented as the pattern: +# +#sun.rmi.registry.registryFilter=\ +# maxarray=1000000;\ +# maxdepth=20;\ +# java.lang.String;\ +# java.lang.Number;\ +# java.lang.reflect.Proxy;\ +# java.rmi.Remote;\ +# sun.rmi.server.UnicastRef;\ +# sun.rmi.server.RMIClientSocketFactory;\ +# sun.rmi.server.RMIServerSocketFactory;\ +# java.rmi.activation.ActivationID;\ +# java.rmi.server.UID # # RMI Distributed Garbage Collector (DGC) Serial Filter # diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/registry/RegistryImpl.java b/jdk/src/java.rmi/share/classes/sun/rmi/registry/RegistryImpl.java index af012faeb78..f6f486f80a5 100644 --- a/jdk/src/java.rmi/share/classes/sun/rmi/registry/RegistryImpl.java +++ b/jdk/src/java.rmi/share/classes/sun/rmi/registry/RegistryImpl.java @@ -28,7 +28,6 @@ package sun.rmi.registry; import java.io.ObjectInputFilter; import java.nio.file.Path; import java.nio.file.Paths; -import java.rmi.server.LogStream; import java.security.PrivilegedAction; import java.security.Security; import java.util.ArrayList; @@ -58,6 +57,7 @@ import java.security.Permissions; import java.security.ProtectionDomain; import java.text.MessageFormat; +import jdk.internal.misc.SharedSecrets; import sun.rmi.runtime.Log; import sun.rmi.server.UnicastRef; import sun.rmi.server.UnicastServerRef; @@ -109,7 +109,7 @@ public class RegistryImpl extends java.rmi.server.RemoteServer private static final int REGISTRY_MAX_DEPTH = 20; /** Registry maximum array size in remote invocations. **/ - private static final int REGISTRY_MAX_ARRAY_SIZE = 10000; + private static final int REGISTRY_MAX_ARRAY_SIZE = 1_000_000; /** * The registryFilter created from the value of the {@code "sun.rmi.registry.registryFilter"} @@ -130,7 +130,7 @@ public class RegistryImpl extends java.rmi.server.RemoteServer props = Security.getProperty(REGISTRY_FILTER_PROPNAME); } if (props != null) { - filter = ObjectInputFilter.Config.createFilter(props); + filter = SharedSecrets.getJavaObjectInputFilterAccess().createFilter2(props); Log regLog = Log.getLog("sun.rmi.registry", "registry", -1); if (regLog.isLoggable(Log.BRIEF)) { regLog.log(Log.BRIEF, "registryFilter = " + filter); @@ -451,17 +451,10 @@ public class RegistryImpl extends java.rmi.server.RemoteServer Class clazz = filterInfo.serialClass(); if (clazz != null) { if (clazz.isArray()) { - if (filterInfo.arrayLength() >= 0 && filterInfo.arrayLength() > REGISTRY_MAX_ARRAY_SIZE) { - return ObjectInputFilter.Status.REJECTED; - } - do { - // Arrays are allowed depending on the component type - clazz = clazz.getComponentType(); - } while (clazz.isArray()); - } - if (clazz.isPrimitive()) { - // Arrays of primitives are allowed - return ObjectInputFilter.Status.ALLOWED; + // Arrays are REJECTED only if they exceed the limit + return (filterInfo.arrayLength() >= 0 && filterInfo.arrayLength() > REGISTRY_MAX_ARRAY_SIZE) + ? ObjectInputFilter.Status.REJECTED + : ObjectInputFilter.Status.UNDECIDED; } if (String.class == clazz || java.lang.Number.class.isAssignableFrom(clazz) diff --git a/jdk/test/java/rmi/registry/serialFilter/RegistryFilterTest.java b/jdk/test/java/rmi/registry/serialFilter/RegistryFilterTest.java index 2d5562fed61..33f5f5aada3 100644 --- a/jdk/test/java/rmi/registry/serialFilter/RegistryFilterTest.java +++ b/jdk/test/java/rmi/registry/serialFilter/RegistryFilterTest.java @@ -35,7 +35,6 @@ import java.security.Security; import java.util.Objects; import org.testng.Assert; -import org.testng.TestNG; import org.testng.annotations.BeforeSuite; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -65,21 +64,14 @@ public class RegistryFilterTest { static final int REGISTRY_MAX_DEPTH = 20; - static final int REGISTRY_MAX_ARRAY = 10000; + static final int REGISTRY_MAX_ARRAY = 1_000_000; static final String registryFilter = System.getProperty("sun.rmi.registry.registryFilter", Security.getProperty("sun.rmi.registry.registryFilter")); - @DataProvider(name = "bindAllowed") - static Object[][] bindAllowedObjects() { - Object[][] objects = { - }; - return objects; - } - /** - * Data RMI Regiry bind test. + * Data RMI Registry bind test. * - name * - Object * - true/false if object is blacklisted by a filter (implicit or explicit) @@ -90,9 +82,11 @@ public class RegistryFilterTest { Object[][] data = { { "byte[max]", new XX(new byte[REGISTRY_MAX_ARRAY]), false }, { "String", new XX("now is the time"), false}, - { "String[]", new XX(new String[3]), false}, - { "Long[4]", new XX(new Long[4]), registryFilter != null }, + { "String[3]", new XX(new String[3]), false}, + { "Long[4]", new XX(new Long[4]), false }, + { "Object[REGISTRY_MAX_ARRAY]", new XX(new Object[REGISTRY_MAX_ARRAY]), false }, { "rej-byte[toobig]", new XX(new byte[REGISTRY_MAX_ARRAY + 1]), true }, + { "rej-Object[toobig]", new XX(new Object[REGISTRY_MAX_ARRAY + 1]), true }, { "rej-MarshalledObject", createMarshalledObject(), true }, { "rej-RejectableClass", new RejectableClass(), registryFilter != null}, };