From 20a9ca787508388551d9a4349e738ea0c5794c81 Mon Sep 17 00:00:00 2001 From: Alexander Kouznetsov Date: Mon, 25 Apr 2016 16:29:50 -0700 Subject: [PATCH 01/18] 8154594: JFrame.setDefaultCloseOperation is prohibited in jtreg: Missing part of the fix Reviewed-by: alexsch, prr --- .../src/com/sun/swingset3/demos/button/ButtonDemo.java | 5 +++-- .../com/sun/swingset3/demos/tabbedpane/TabbedPaneDemo.java | 1 - .../src/com/sun/swingset3/demos/window/WindowDemo.java | 5 +++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/button/ButtonDemo.java b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/button/ButtonDemo.java index e3aa888e5f3..358ae49d64b 100644 --- a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/button/ButtonDemo.java +++ b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/button/ButtonDemo.java @@ -36,6 +36,7 @@ import javax.swing.SwingUtilities; import com.sun.swingset3.DemoProperties; import com.sun.swingset3.demos.JHyperlink; +import java.lang.reflect.InvocationTargetException; /** * @@ -210,10 +211,10 @@ public final class ButtonDemo extends JPanel { return panel; } - public static void main(String args[]) { + public static void main(String args[]) throws InterruptedException, InvocationTargetException { final ButtonDemo buttonDemo = new ButtonDemo(); - javax.swing.SwingUtilities.invokeLater(() -> { + javax.swing.SwingUtilities.invokeAndWait(() -> { JFrame frame = new JFrame(DEMO_TITLE); frame.add(buttonDemo); frame.pack(); diff --git a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/tabbedpane/TabbedPaneDemo.java b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/tabbedpane/TabbedPaneDemo.java index 9809d6babbe..5d023405b58 100644 --- a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/tabbedpane/TabbedPaneDemo.java +++ b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/tabbedpane/TabbedPaneDemo.java @@ -91,7 +91,6 @@ public class TabbedPaneDemo extends JPanel implements ActionListener { public static void main(String[] args) { JFrame frame = new JFrame(DEMO_TITLE); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add(new TabbedPaneDemo()); frame.setPreferredSize(new Dimension(800, 600)); frame.pack(); diff --git a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/window/WindowDemo.java b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/window/WindowDemo.java index 89b87776ba2..bbb06a1182a 100644 --- a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/window/WindowDemo.java +++ b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/window/WindowDemo.java @@ -31,6 +31,7 @@ import javax.swing.border.LineBorder; import com.sun.swingset3.DemoProperties; import com.sun.swingset3.demos.DemoUtilities; +import java.lang.reflect.InvocationTargetException; /** * @author aim @@ -145,8 +146,8 @@ public final class WindowDemo extends JPanel { } } - public static void main(String args[]) { - EventQueue.invokeLater(() -> { + public static void main(String args[]) throws InterruptedException, InvocationTargetException { + EventQueue.invokeAndWait(() -> { JFrame frame = new JFrame(); WindowDemo demo = new WindowDemo(); frame.add(demo); From 5125f7137636702fad6f2bef39c195e14aaeb83b Mon Sep 17 00:00:00 2001 From: Alexander Kouznetsov Date: Mon, 25 Apr 2016 16:34:03 -0700 Subject: [PATCH 02/18] 8154706: Sanity tests prepareBundle task doesn't produce working bundle Reviewed-by: alexsch, prr --- jdk/test/sanity/client/TEST.ROOT.template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/test/sanity/client/TEST.ROOT.template b/jdk/test/sanity/client/TEST.ROOT.template index 6881809d9f8..e703c4ce236 100644 --- a/jdk/test/sanity/client/TEST.ROOT.template +++ b/jdk/test/sanity/client/TEST.ROOT.template @@ -12,7 +12,7 @@ # A "headful" test requires a graphical environment to meaningfully # run. Tests that are not headful are "headless." -keys=screenshots +keys=2d dnd i18n intermittent randomness headful # Tests that must run in othervm mode othervm.dirs=sanity/client/SwingSet From fb8f4acea810faab05065fcb045facf0b9a4bf35 Mon Sep 17 00:00:00 2001 From: Jim Laskey Date: Tue, 26 Apr 2016 11:55:52 -0300 Subject: [PATCH 03/18] 8132994: /modules and /packages should not be parsed by the jimage parser Reviewed-by: sundar --- .../jlink/internal/ImageLocationWriter.java | 42 +++++++++++-------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageLocationWriter.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageLocationWriter.java index e66ba64210b..0faf8c95d8b 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageLocationWriter.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageLocationWriter.java @@ -61,24 +61,32 @@ public final class ImageLocationWriter extends ImageLocation { String baseName; String extensionName = ""; - int offset = fullName.indexOf('/', 1); - if (fullName.length() >= 2 && fullName.charAt(0) == '/' && offset != -1) { - moduleName = fullName.substring(1, offset); - fullName = fullName.substring(offset + 1); - } - - offset = fullName.lastIndexOf('/'); - if (1 < offset) { - parentName = fullName.substring(0, offset); - fullName = fullName.substring(offset + 1); - } - - offset = fullName.lastIndexOf('.'); - if (offset != -1) { - baseName = fullName.substring(0, offset); - extensionName = fullName.substring(offset + 1); + if (fullName.startsWith("/modules/")) { + moduleName = "modules"; + baseName = fullName.substring("/modules/".length()); + } else if ( fullName.startsWith("/packages/")) { + moduleName = "packages"; + baseName = fullName.substring("/packages/".length()); } else { - baseName = fullName; + int offset = fullName.indexOf('/', 1); + if (fullName.length() >= 2 && fullName.charAt(0) == '/' && offset != -1) { + moduleName = fullName.substring(1, offset); + fullName = fullName.substring(offset + 1); + } + + offset = fullName.lastIndexOf('/'); + if (1 < offset) { + parentName = fullName.substring(0, offset); + fullName = fullName.substring(offset + 1); + } + + offset = fullName.lastIndexOf('.'); + if (offset != -1) { + baseName = fullName.substring(0, offset); + extensionName = fullName.substring(offset + 1); + } else { + baseName = fullName; + } } return new ImageLocationWriter(strings) From c08b6a7c8fcf4250eb5ec0ffb3b617b3faa955f6 Mon Sep 17 00:00:00 2001 From: Roger Riggs Date: Tue, 26 Apr 2016 17:35:10 -0400 Subject: [PATCH 04/18] 8066750: Remove HTTP proxy implementation and tests from RMI Reviewed-by: smarks --- .../java/rmi/server/RMISocketFactory.java | 21 +- .../sun/rmi/transport/proxy/CGIHandler.java | 423 ---------------- .../proxy/HttpAwareServerSocket.java | 114 ----- .../rmi/transport/proxy/HttpInputStream.java | 205 -------- .../rmi/transport/proxy/HttpOutputStream.java | 80 --- .../transport/proxy/HttpReceiveSocket.java | 128 ----- .../transport/proxy/HttpSendInputStream.java | 161 ------ .../transport/proxy/HttpSendOutputStream.java | 105 ---- .../rmi/transport/proxy/HttpSendSocket.java | 344 ------------- .../proxy/RMIHttpToCGISocketFactory.java | 55 -- .../proxy/RMIHttpToPortSocketFactory.java | 53 -- .../proxy/RMIMasterSocketFactory.java | 468 ------------------ .../rmi/transport/proxy/RMISocketInfo.java | 39 -- .../rmi/transport/proxy/WrappedSocket.java | 192 ------- .../sun/rmi/transport/tcp/TCPConnection.java | 11 +- .../TCPDirectSocketFactory.java} | 4 +- .../sun/rmi/transport/tcp/TCPTransport.java | 30 +- jdk/test/ProblemList.txt | 2 - .../transport/httpSocket/HttpSocketTest.java | 113 ----- .../httpSocket/HttpSocketTest_Stub.java | 130 ----- .../rmi/transport/httpSocket/security.policy | 10 - .../proxy/DisableHttpDefaultValue.java | 69 --- .../transport/proxy/EagerHttpFallback.java | 73 --- .../tcp/blockAccept/BlockAcceptTest.java | 175 ------- .../transport/tcp/blockAccept/TestIface.java | 31 -- .../transport/tcp/blockAccept/TestImpl.java | 49 -- .../tcp/blockAccept/TestImpl_Stub.java | 66 --- .../transport/tcp/blockAccept/security.policy | 10 - 28 files changed, 10 insertions(+), 3151 deletions(-) delete mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/CGIHandler.java delete mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpAwareServerSocket.java delete mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpInputStream.java delete mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpOutputStream.java delete mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpReceiveSocket.java delete mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendInputStream.java delete mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendOutputStream.java delete mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendSocket.java delete mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIHttpToCGISocketFactory.java delete mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIHttpToPortSocketFactory.java delete mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIMasterSocketFactory.java delete mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMISocketInfo.java delete mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/WrappedSocket.java rename jdk/src/java.rmi/share/classes/sun/rmi/transport/{proxy/RMIDirectSocketFactory.java => tcp/TCPDirectSocketFactory.java} (94%) delete mode 100644 jdk/test/java/rmi/transport/httpSocket/HttpSocketTest.java delete mode 100644 jdk/test/java/rmi/transport/httpSocket/HttpSocketTest_Stub.java delete mode 100644 jdk/test/java/rmi/transport/httpSocket/security.policy delete mode 100644 jdk/test/sun/rmi/transport/proxy/DisableHttpDefaultValue.java delete mode 100644 jdk/test/sun/rmi/transport/proxy/EagerHttpFallback.java delete mode 100644 jdk/test/sun/rmi/transport/tcp/blockAccept/BlockAcceptTest.java delete mode 100644 jdk/test/sun/rmi/transport/tcp/blockAccept/TestIface.java delete mode 100644 jdk/test/sun/rmi/transport/tcp/blockAccept/TestImpl.java delete mode 100644 jdk/test/sun/rmi/transport/tcp/blockAccept/TestImpl_Stub.java delete mode 100644 jdk/test/sun/rmi/transport/tcp/blockAccept/security.policy diff --git a/jdk/src/java.rmi/share/classes/java/rmi/server/RMISocketFactory.java b/jdk/src/java.rmi/share/classes/java/rmi/server/RMISocketFactory.java index e69c269f81a..df3bc9fd24a 100644 --- a/jdk/src/java.rmi/share/classes/java/rmi/server/RMISocketFactory.java +++ b/jdk/src/java.rmi/share/classes/java/rmi/server/RMISocketFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, 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 @@ -35,21 +35,8 @@ import java.net.*; * request that the RMI runtime use its socket factory instance * instead of the default implementation. * - *

The default socket factory implementation performs a - * three-tiered approach to creating client sockets. First, a direct - * socket connection to the remote VM is attempted. If that fails - * (due to a firewall), the runtime uses HTTP with the explicit port - * number of the server. If the firewall does not allow this type of - * communication, then HTTP to a cgi-bin script on the server is used - * to POST the RMI call. The HTTP tunneling mechanisms are disabled by - * default. This behavior is controlled by the {@code java.rmi.server.disableHttp} - * property, whose default value is {@code true}. Setting this property's - * value to {@code false} will enable the HTTP tunneling mechanisms. - * - *

Deprecated: HTTP Tunneling. The HTTP tunneling mechanisms - * described above, specifically HTTP with an explicit port and HTTP to a - * cgi-bin script, are deprecated. These HTTP tunneling mechanisms are - * subject to removal in a future release of the platform. + *

The default socket factory implementation creates a direct + * socket connection to the remote host. * *

The default socket factory implementation creates server sockets that * are bound to the wildcard address, which accepts requests from all network @@ -181,7 +168,7 @@ public abstract class RMISocketFactory public synchronized static RMISocketFactory getDefaultSocketFactory() { if (defaultSocketFactory == null) { defaultSocketFactory = - new sun.rmi.transport.proxy.RMIMasterSocketFactory(); + new sun.rmi.transport.tcp.TCPDirectSocketFactory(); } return defaultSocketFactory; } diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/CGIHandler.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/CGIHandler.java deleted file mode 100644 index 546ccd8ea10..00000000000 --- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/CGIHandler.java +++ /dev/null @@ -1,423 +0,0 @@ -/* - * Copyright (c) 1996, 2013, 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 sun.rmi.transport.proxy; - -import java.io.*; -import java.net.*; -import java.util.Hashtable; - -/** - * CGIClientException is thrown when an error is detected - * in a client's request. - */ -class CGIClientException extends Exception { - private static final long serialVersionUID = 8147981687059865216L; - - public CGIClientException(String s) { - super(s); - } - - public CGIClientException(String s, Throwable cause) { - super(s, cause); - } -} - -/** - * CGIServerException is thrown when an error occurs here on the server. - */ -class CGIServerException extends Exception { - - private static final long serialVersionUID = 6928425456704527017L; - - public CGIServerException(String s) { - super(s); - } - - public CGIServerException(String s, Throwable cause) { - super(s, cause); - } -} - -/** - * CGICommandHandler is the interface to an object that handles a - * particular supported command. - */ -interface CGICommandHandler { - - /** - * Return the string form of the command - * to be recognized in the query string. - */ - public String getName(); - - /** - * Execute the command with the given string as parameter. - */ - public void execute(String param) throws CGIClientException, CGIServerException; -} - -/** - * The CGIHandler class contains methods for executing as a CGI program. - * The main function interprets the query string as a command of the form - * "{@code =}". - * - * This class depends on the CGI 1.0 environment variables being set as - * properties of the same name in this Java VM. - * - * All data and methods of this class are static because they are specific - * to this particular CGI process. - */ -public final class CGIHandler { - - /* get CGI parameters that we need */ - static int ContentLength; - static String QueryString; - static String RequestMethod; - static String ServerName; - static int ServerPort; - - static { - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Void run() { - ContentLength = - Integer.getInteger("CONTENT_LENGTH", 0).intValue(); - QueryString = System.getProperty("QUERY_STRING", ""); - RequestMethod = System.getProperty("REQUEST_METHOD", ""); - ServerName = System.getProperty("SERVER_NAME", ""); - ServerPort = Integer.getInteger("SERVER_PORT", 0).intValue(); - return null; - } - }); - } - - /* list of handlers for supported commands */ - private static CGICommandHandler commands[] = { - new CGIForwardCommand(), - new CGIGethostnameCommand(), - new CGIPingCommand(), - new CGITryHostnameCommand() - }; - - /* construct table mapping command strings to handlers */ - private static Hashtable commandLookup; - static { - commandLookup = new Hashtable<>(); - for (int i = 0; i < commands.length; ++ i) - commandLookup.put(commands[i].getName(), commands[i]); - } - - /* prevent instantiation of this class */ - private CGIHandler() {} - - /** - * Execute command given in query string on URL. The string before - * the first '=' is interpreted as the command name, and the string - * after the first '=' is the parameters to the command. - */ - public static void main(String args[]) - { - try { - String command, param; - int delim = QueryString.indexOf('='); - if (delim == -1) { - command = QueryString; - param = ""; - } - else { - command = QueryString.substring(0, delim); - param = QueryString.substring(delim + 1); - } - CGICommandHandler handler = - commandLookup.get(command); - if (handler != null) - try { - handler.execute(param); - } catch (CGIClientException e) { - e.printStackTrace(); - returnClientError(e.getMessage()); - } catch (CGIServerException e) { - e.printStackTrace(); - returnServerError(e.getMessage()); - } - else - returnClientError("invalid command."); - } catch (Exception e) { - e.printStackTrace(); - returnServerError("internal error: " + e.getMessage()); - } - System.exit(0); - } - - /** - * Return an HTML error message indicating there was error in - * the client's request. - */ - private static void returnClientError(String message) - { - System.out.println("Status: 400 Bad Request: " + message); - System.out.println("Content-type: text/html"); - System.out.println(""); - System.out.println("" + - "Java RMI Client Error" + - "" + - ""); - System.out.println("

Java RMI Client Error

"); - System.out.println(""); - System.out.println(message); - System.out.println(""); - System.exit(1); - } - - /** - * Return an HTML error message indicating an error occurred - * here on the server. - */ - private static void returnServerError(String message) - { - System.out.println("Status: 500 Server Error: " + message); - System.out.println("Content-type: text/html"); - System.out.println(""); - System.out.println("" + - "Java RMI Server Error" + - "" + - ""); - System.out.println("

Java RMI Server Error

"); - System.out.println(""); - System.out.println(message); - System.out.println(""); - System.exit(1); - } -} - -/** - * "forward" command: Forward request body to local port on the server, - * and send response back to client. - */ -final class CGIForwardCommand implements CGICommandHandler { - - public String getName() { - return "forward"; - } - - @SuppressWarnings("deprecation") - private String getLine (DataInputStream socketIn) throws IOException { - return socketIn.readLine(); - } - - public void execute(String param) throws CGIClientException, CGIServerException - { - if (!CGIHandler.RequestMethod.equals("POST")) - throw new CGIClientException("can only forward POST requests"); - - int port; - try { - port = Integer.parseInt(param); - } catch (NumberFormatException e) { - throw new CGIClientException("invalid port number.", e); - } - if (port <= 0 || port > 0xFFFF) - throw new CGIClientException("invalid port: " + port); - if (port < 1024) - throw new CGIClientException("permission denied for port: " + - port); - - byte buffer[]; - Socket socket; - try { - socket = new Socket(InetAddress.getLocalHost(), port); - } catch (IOException e) { - throw new CGIServerException("could not connect to local port", e); - } - - /* - * read client's request body - */ - DataInputStream clientIn = new DataInputStream(System.in); - buffer = new byte[CGIHandler.ContentLength]; - try { - clientIn.readFully(buffer); - } catch (EOFException e) { - throw new CGIClientException("unexpected EOF reading request body", e); - } catch (IOException e) { - throw new CGIClientException("error reading request body", e); - } - - /* - * send to local server in HTTP - */ - try { - DataOutputStream socketOut = - new DataOutputStream(socket.getOutputStream()); - socketOut.writeBytes("POST / HTTP/1.0\r\n"); - socketOut.writeBytes("Content-length: " + - CGIHandler.ContentLength + "\r\n\r\n"); - socketOut.write(buffer); - socketOut.flush(); - } catch (IOException e) { - throw new CGIServerException("error writing to server", e); - } - - /* - * read response - */ - DataInputStream socketIn; - try { - socketIn = new DataInputStream(socket.getInputStream()); - } catch (IOException e) { - throw new CGIServerException("error reading from server", e); - } - String key = "Content-length:".toLowerCase(); - boolean contentLengthFound = false; - String line; - int responseContentLength = -1; - do { - try { - line = getLine(socketIn); - } catch (IOException e) { - throw new CGIServerException("error reading from server", e); - } - if (line == null) - throw new CGIServerException( - "unexpected EOF reading server response"); - - if (line.toLowerCase().startsWith(key)) { - if (contentLengthFound) { - throw new CGIServerException( - "Multiple Content-length entries found."); - } else { - responseContentLength = - Integer.parseInt(line.substring(key.length()).trim()); - contentLengthFound = true; - } - } - } while ((line.length() != 0) && - (line.charAt(0) != '\r') && (line.charAt(0) != '\n')); - - if (!contentLengthFound || responseContentLength < 0) - throw new CGIServerException( - "missing or invalid content length in server response"); - buffer = new byte[responseContentLength]; - try { - socketIn.readFully(buffer); - } catch (EOFException e) { - throw new CGIServerException( - "unexpected EOF reading server response", e); - } catch (IOException e) { - throw new CGIServerException("error reading from server", e); - } - - /* - * send response back to client - */ - System.out.println("Status: 200 OK"); - System.out.println("Content-type: application/octet-stream"); - System.out.println(""); - try { - System.out.write(buffer); - } catch (IOException e) { - throw new CGIServerException("error writing response", e); - } - System.out.flush(); - } -} - -/** - * "gethostname" command: Return the host name of the server as the - * response body - */ -final class CGIGethostnameCommand implements CGICommandHandler { - - public String getName() { - return "gethostname"; - } - - public void execute(String param) - { - System.out.println("Status: 200 OK"); - System.out.println("Content-type: application/octet-stream"); - System.out.println("Content-length: " + - CGIHandler.ServerName.length()); - System.out.println(""); - System.out.print(CGIHandler.ServerName); - System.out.flush(); - } -} - -/** - * "ping" command: Return an OK status to indicate that connection - * was successful. - */ -final class CGIPingCommand implements CGICommandHandler { - - public String getName() { - return "ping"; - } - - public void execute(String param) - { - System.out.println("Status: 200 OK"); - System.out.println("Content-type: application/octet-stream"); - System.out.println("Content-length: 0"); - System.out.println(""); - } -} - -/** - * "tryhostname" command: Return a human readable message describing - * what host name is available to local Java VMs. - */ -final class CGITryHostnameCommand implements CGICommandHandler { - - public String getName() { - return "tryhostname"; - } - - public void execute(String param) - { - System.out.println("Status: 200 OK"); - System.out.println("Content-type: text/html"); - System.out.println(""); - System.out.println("" + - "Java RMI Server Hostname Info" + - "" + - ""); - System.out.println("

Java RMI Server Hostname Info

"); - System.out.println("

Local host name available to Java VM:

"); - System.out.print("

InetAddress.getLocalHost().getHostName()"); - try { - String localHostName = InetAddress.getLocalHost().getHostName(); - - System.out.println(" = " + localHostName); - } catch (UnknownHostException e) { - System.out.println(" threw java.net.UnknownHostException"); - } - - System.out.println("

Server host information obtained through CGI interface from HTTP server:

"); - System.out.println("

SERVER_NAME = " + CGIHandler.ServerName); - System.out.println("

SERVER_PORT = " + CGIHandler.ServerPort); - System.out.println(""); - } -} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpAwareServerSocket.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpAwareServerSocket.java deleted file mode 100644 index b4512fecd93..00000000000 --- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpAwareServerSocket.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (c) 1996, 2005, 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 sun.rmi.transport.proxy; - -import java.io.BufferedInputStream; -import java.io.IOException; -import java.net.ServerSocket; -import java.net.Socket; -import sun.rmi.runtime.Log; - -/** - * The HttpAwareServerSocket class extends the java.net.ServerSocket - * class. It behaves like a ServerSocket, except that if - * the first four bytes of an accepted socket are the letters "POST", - * then it returns an HttpReceiveSocket instead of a java.net.Socket. - * This means that the accept method blocks until four bytes have been - * read from the new socket's input stream. - */ -class HttpAwareServerSocket extends ServerSocket { - - /** - * Create a server socket on a specified port. - * @param port the port - * @exception IOException IO error when opening the socket. - */ - public HttpAwareServerSocket(int port) throws IOException - { - super(port); - } - - /** - * Create a server socket, bind it to the specified local port - * and listen to it. You can connect to an annonymous port by - * specifying the port number to be 0. backlog specifies - * how many connection requests the system will queue up while waiting - * for the ServerSocket to execute accept(). - * @param port the specified port - * @param backlog the number of queued connect requests pending accept - */ - public HttpAwareServerSocket(int port, int backlog) throws IOException - { - super(port, backlog); - } - - /** - * Accept a connection. This method will block until the connection - * is made and four bytes can be read from the input stream. - * If the first four bytes are "POST", then an HttpReceiveSocket is - * returned, which will handle the HTTP protocol wrapping. - * Otherwise, a WrappedSocket is returned. The input stream will be - * reset to the beginning of the transmission. - * In either case, a BufferedInputStream will already be on top of - * the underlying socket's input stream. - * @exception IOException IO error when waiting for the connection. - */ - public Socket accept() throws IOException - { - Socket socket = super.accept(); - BufferedInputStream in = - new BufferedInputStream(socket.getInputStream()); - - RMIMasterSocketFactory.proxyLog.log(Log.BRIEF, - "socket accepted (checking for POST)"); - - in.mark(4); - boolean isHttp = (in.read() == 'P') && - (in.read() == 'O') && - (in.read() == 'S') && - (in.read() == 'T'); - in.reset(); - - if (RMIMasterSocketFactory.proxyLog.isLoggable(Log.BRIEF)) { - RMIMasterSocketFactory.proxyLog.log(Log.BRIEF, - (isHttp ? "POST found, HTTP socket returned" : - "POST not found, direct socket returned")); - } - - if (isHttp) - return new HttpReceiveSocket(socket, in, null); - else - return new WrappedSocket(socket, in, null); - } - - /** - * Return the implementation address and implementation port of - * the HttpAwareServerSocket as a String. - */ - public String toString() - { - return "HttpAware" + super.toString(); - } -} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpInputStream.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpInputStream.java deleted file mode 100644 index 4b5cad95044..00000000000 --- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpInputStream.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright (c) 1996, 2014, 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 sun.rmi.transport.proxy; - -import java.io.*; - -import sun.rmi.runtime.Log; - -/** - * The HttpInputStream class assists the HttpSendSocket and HttpReceiveSocket - * classes by filtering out the header for the message as well as any - * data after its proper content length. - */ -class HttpInputStream extends FilterInputStream { - - /** bytes remaining to be read from proper content of message */ - protected int bytesLeft; - - /** bytes remaining to be read at time of last mark */ - protected int bytesLeftAtMark; - - /** - * Create new filter on a given input stream. - * @param in the InputStream to filter from - */ - @SuppressWarnings("deprecation") - public HttpInputStream(InputStream in) throws IOException - { - super(in); - - if (in.markSupported()) - in.mark(0); // prevent resetting back to old marks - - // pull out header, looking for content length - - DataInputStream dis = new DataInputStream(in); - String key = "Content-length:".toLowerCase(); - boolean contentLengthFound = false; - String line; - do { - line = dis.readLine(); - - if (RMIMasterSocketFactory.proxyLog.isLoggable(Log.VERBOSE)) { - RMIMasterSocketFactory.proxyLog.log(Log.VERBOSE, - "received header line: \"" + line + "\""); - } - - if (line == null) - throw new EOFException(); - - if (line.toLowerCase().startsWith(key)) { - if (contentLengthFound) { - throw new IOException( - "Multiple Content-length entries found."); - } else { - bytesLeft = - Integer.parseInt(line.substring(key.length()).trim()); - contentLengthFound = true; - } - } - - // The idea here is to go past the first blank line. - // Some DataInputStream.readLine() documentation specifies that - // it does include the line-terminating character(s) in the - // returned string, but it actually doesn't, so we'll cover - // all cases here... - } while ((line.length() != 0) && - (line.charAt(0) != '\r') && (line.charAt(0) != '\n')); - - if (!contentLengthFound || bytesLeft < 0) { - // This really shouldn't happen, but if it does, shoud we fail?? - // For now, just give up and let a whole lot of bytes through... - bytesLeft = Integer.MAX_VALUE; - } - bytesLeftAtMark = bytesLeft; - - if (RMIMasterSocketFactory.proxyLog.isLoggable(Log.VERBOSE)) { - RMIMasterSocketFactory.proxyLog.log(Log.VERBOSE, - "content length: " + bytesLeft); - } - } - - /** - * Returns the number of bytes that can be read with blocking. - * Make sure that this does not exceed the number of bytes remaining - * in the proper content of the message. - */ - public int available() throws IOException - { - int bytesAvailable = in.available(); - if (bytesAvailable > bytesLeft) - bytesAvailable = bytesLeft; - - return bytesAvailable; - } - - /** - * Read a byte of data from the stream. Make sure that one is available - * from the proper content of the message, else -1 is returned to - * indicate to the user that the end of the stream has been reached. - */ - public int read() throws IOException - { - if (bytesLeft > 0) { - int data = in.read(); - if (data != -1) - -- bytesLeft; - - if (RMIMasterSocketFactory.proxyLog.isLoggable(Log.VERBOSE)) { - RMIMasterSocketFactory.proxyLog.log(Log.VERBOSE, - "received byte: '" + - ((data & 0x7F) < ' ' ? " " : String.valueOf((char) data)) + - "' " + data); - } - - return data; - } - else { - RMIMasterSocketFactory.proxyLog.log(Log.VERBOSE, - "read past content length"); - - return -1; - } - } - - public int read(byte b[], int off, int len) throws IOException - { - if (bytesLeft == 0 && len > 0) { - RMIMasterSocketFactory.proxyLog.log(Log.VERBOSE, - "read past content length"); - - return -1; - } - if (len > bytesLeft) - len = bytesLeft; - int bytesRead = in.read(b, off, len); - bytesLeft -= bytesRead; - - if (RMIMasterSocketFactory.proxyLog.isLoggable(Log.VERBOSE)) { - RMIMasterSocketFactory.proxyLog.log(Log.VERBOSE, - "read " + bytesRead + " bytes, " + bytesLeft + " remaining"); - } - - return bytesRead; - } - - /** - * Mark the current position in the stream (for future calls to reset). - * Remember where we are within the proper content of the message, so - * that a reset method call can recreate our state properly. - * @param readlimit how many bytes can be read before mark becomes invalid - */ - public void mark(int readlimit) - { - in.mark(readlimit); - if (in.markSupported()) - bytesLeftAtMark = bytesLeft; - } - - /** - * Repositions the stream to the last marked position. Make sure to - * adjust our position within the proper content accordingly. - */ - public void reset() throws IOException - { - in.reset(); - bytesLeft = bytesLeftAtMark; - } - - /** - * Skips bytes of the stream. Make sure to adjust our - * position within the proper content accordingly. - * @param n number of bytes to be skipped - */ - public long skip(long n) throws IOException - { - if (n > bytesLeft) - n = bytesLeft; - long bytesSkipped = in.skip(n); - bytesLeft -= bytesSkipped; - return bytesSkipped; - } -} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpOutputStream.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpOutputStream.java deleted file mode 100644 index 5f1f2a6a680..00000000000 --- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpOutputStream.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 1996, 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 sun.rmi.transport.proxy; - -import java.io.*; - -/** - * The HttpOutputStream class assists the HttpSendSocket and HttpReceiveSocket - * classes by providing an output stream that buffers its entire input until - * closed, and then it sends the complete transmission prefixed by the end of - * an HTTP header that specifies the content length. - */ -class HttpOutputStream extends ByteArrayOutputStream { - - /** the output stream to send response to */ - protected OutputStream out; - - /** true if HTTP response has been sent */ - boolean responseSent = false; - - /** - * Begin buffering new HTTP response to be sent to a given stream. - * @param out the OutputStream to send response to - */ - public HttpOutputStream(OutputStream out) { - super(); - this.out = out; - } - - /** - * On close, send HTTP-packaged response. - */ - public synchronized void close() throws IOException { - if (!responseSent) { - /* - * If response would have zero content length, then make it - * have some arbitrary data so that certain clients will not - * fail because the "document contains no data". - */ - if (size() == 0) - write(emptyData); - - DataOutputStream dos = new DataOutputStream(out); - dos.writeBytes("Content-type: application/octet-stream\r\n"); - dos.writeBytes("Content-length: " + size() + "\r\n"); - dos.writeBytes("\r\n"); - writeTo(dos); - dos.flush(); - // Do not close the underlying stream here, because that would - // close the underlying socket and prevent reading a response. - reset(); // reset byte array - responseSent = true; - } - } - - /** data to send if the response would otherwise be empty */ - private static byte[] emptyData = { 0 }; -} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpReceiveSocket.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpReceiveSocket.java deleted file mode 100644 index c916254ffcd..00000000000 --- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpReceiveSocket.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (c) 1996, 2000, 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 sun.rmi.transport.proxy; - -import java.io.*; -import java.net.Socket; -import java.net.InetAddress; - -/** - * The HttpReceiveSocket class extends the WrappedSocket class - * by removing the HTTP protocol packaging from the input stream and - * formatting the output stream as an HTTP response. - * - * NOTES: - * - * The output stream must be explicitly closed for the output to be - * sent, since the HttpResponseOutputStream needs to buffer the entire - * transmission to be able to fill in the content-length field of - * the HTTP header. Closing this socket will do this. - * - * The constructor blocks until the HTTP protocol header - * is received. This could be fixed, but I don't think it should be a - * problem because this object would not be created unless the - * HttpAwareServerSocket has detected the beginning of the header - * anyway, so the rest should be there. - * - * This socket can only be used to process one POST and reply to it. - * Another message would be received on a newly accepted socket anyway. - */ -public class HttpReceiveSocket extends WrappedSocket implements RMISocketInfo { - - /** true if the HTTP header has pushed through the output stream yet */ - private boolean headerSent = false; - - /** - * Layer on top of a pre-existing Socket object, and use specified - * input and output streams. - * @param socket the pre-existing socket to use - * @param in the InputStream to use for this socket (can be null) - * @param out the OutputStream to use for this socket (can be null) - */ - public HttpReceiveSocket(Socket socket, InputStream in, OutputStream out) - throws IOException - { - super(socket, in, out); - - this.in = new HttpInputStream(in != null ? in : - socket.getInputStream()); - this.out = (out != null ? out : - socket.getOutputStream()); - } - - /** - * Indicate that this socket is not reusable. - */ - public boolean isReusable() - { - return false; - } - - /** - * Get the address to which this socket is connected. "null" is always - * returned (to indicate an unknown address) because the originating - * host's IP address cannot be reliably determined: both because the - * request probably went through a proxy server, and because if it was - * delivered by a local forwarder (CGI script or servlet), we do NOT - * want it to appear as if the call is coming from the local host (in - * case the remote object makes access control decisions based on the - * "client host" of a remote call; see bugid 4399040). - */ - public InetAddress getInetAddress() { - return null; - } - - /** - * Get an OutputStream for this socket. - */ - public OutputStream getOutputStream() throws IOException - { - if (!headerSent) { // could this be done in constructor?? - DataOutputStream dos = new DataOutputStream(out); - dos.writeBytes("HTTP/1.0 200 OK\r\n"); - dos.flush(); - headerSent = true; - out = new HttpOutputStream(out); - } - return out; - } - - /** - * Close the socket. - */ - public synchronized void close() throws IOException - { - getOutputStream().close(); // make sure response is sent - socket.close(); - } - - /** - * Return string representation of the socket. - */ - public String toString() - { - return "HttpReceive" + socket.toString(); - } -} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendInputStream.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendInputStream.java deleted file mode 100644 index 0c6de28c266..00000000000 --- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendInputStream.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (c) 1996, 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 sun.rmi.transport.proxy; - -import java.io.*; - -/** - * The HttpSendInputStream class is used by the HttpSendSocket class as - * a layer on the top of the InputStream it returns so that it can be - * notified of attempts to read from it. This allows the HttpSendSocket - * to know when it should push across its output message. - */ -class HttpSendInputStream extends FilterInputStream { - - /** the HttpSendSocket object that is providing this stream */ - HttpSendSocket owner; - - /** - * Create new filter on a given input stream. - * @param in the InputStream to filter from - * @param owner the HttpSendSocket that is providing this stream - */ - public HttpSendInputStream(InputStream in, HttpSendSocket owner) - throws IOException - { - super(in); - - this.owner = owner; - } - - /** - * Mark this stream as inactive for its owner socket, so the next time - * a read is attempted, the owner will be notified and a new underlying - * input stream obtained. - */ - public void deactivate() - { - in = null; - } - - /** - * Read a byte of data from the stream. - */ - public int read() throws IOException - { - if (in == null) - in = owner.readNotify(); - return in.read(); - } - - /** - * Read into an array of bytes. - * @param b the buffer into which the data is to be read - * @param off the start offset of the data - * @param len the maximum number of bytes to read - */ - public int read(byte b[], int off, int len) throws IOException - { - if (len == 0) - return 0; - if (in == null) - in = owner.readNotify(); - return in.read(b, off, len); - } - - /** - * Skip bytes of input. - * @param n the number of bytes to be skipped - */ - public long skip(long n) throws IOException - { - if (n == 0) - return 0; - if (in == null) - in = owner.readNotify(); - return in.skip(n); - } - - /** - * Return the number of bytes that can be read without blocking. - */ - public int available() throws IOException - { - if (in == null) - in = owner.readNotify(); - return in.available(); - } - - /** - * Close the stream. - */ - public void close() throws IOException - { - owner.close(); - } - - /** - * Mark the current position in the stream. - * @param readlimit how many bytes can be read before mark becomes invalid - */ - public synchronized void mark(int readlimit) - { - if (in == null) { - try { - in = owner.readNotify(); - } - catch (IOException e) { - return; - } - } - in.mark(readlimit); - } - - /** - * Reposition the stream to the last marked position. - */ - public synchronized void reset() throws IOException - { - if (in == null) - in = owner.readNotify(); - in.reset(); - } - - /** - * Return true if this stream type supports mark/reset. - */ - public boolean markSupported() - { - if (in == null) { - try { - in = owner.readNotify(); - } - catch (IOException e) { - return false; - } - } - return in.markSupported(); - } -} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendOutputStream.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendOutputStream.java deleted file mode 100644 index bc83945534f..00000000000 --- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendOutputStream.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 1996, 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 sun.rmi.transport.proxy; - -import java.io.*; - -/** - * The HttpSendOutputStream class is used by the HttpSendSocket class as - * a layer on the top of the OutputStream it returns so that it can be - * notified of attempts to write to it. This allows the HttpSendSocket - * to know when it should construct a new message. - */ -class HttpSendOutputStream extends FilterOutputStream { - - /** the HttpSendSocket object that is providing this stream */ - HttpSendSocket owner; - - /** - * Create new filter on a given output stream. - * @param out the OutputStream to filter from - * @param owner the HttpSendSocket that is providing this stream - */ - public HttpSendOutputStream(OutputStream out, HttpSendSocket owner) - throws IOException - { - super(out); - - this.owner = owner; - } - - /** - * Mark this stream as inactive for its owner socket, so the next time - * a write is attempted, the owner will be notified and a new underlying - * output stream obtained. - */ - public void deactivate() - { - out = null; - } - - /** - * Write a byte of data to the stream. - */ - public void write(int b) throws IOException - { - if (out == null) - out = owner.writeNotify(); - out.write(b); - } - - /** - * Write a subarray of bytes. - * @param b the buffer from which the data is to be written - * @param off the start offset of the data - * @param len the number of bytes to be written - */ - public void write(byte b[], int off, int len) throws IOException - { - if (len == 0) - return; - if (out == null) - out = owner.writeNotify(); - out.write(b, off, len); - } - - /** - * Flush the stream. - */ - public void flush() throws IOException - { - if (out != null) - out.flush(); - } - - /** - * Close the stream. - */ - public void close() throws IOException - { - flush(); - owner.close(); - } -} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendSocket.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendSocket.java deleted file mode 100644 index a9932be35e1..00000000000 --- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendSocket.java +++ /dev/null @@ -1,344 +0,0 @@ -/* - * Copyright (c) 1996, 2012, 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 sun.rmi.transport.proxy; - -import java.io.*; -import java.net.*; -import java.security.PrivilegedAction; - -import sun.rmi.runtime.Log; - -/** - * The HttpSendSocket class extends the java.net.Socket class - * by enclosing the data output stream in, then extracting the input - * stream from, an HTTP protocol transmission. - * - * NOTES: - * - * Since the length of the output request must be known before the - * HTTP header can be completed, all of the output is buffered by - * an HttpOutputStream object until either an attempt is made to - * read from this socket, or the socket is explicitly closed. - * - * On the first read attempt to read from this socket, the buffered - * output is sent to the destination as the body of an HTTP POST - * request. All reads will then acquire data from the body of - * the response. A subsequent attempt to write to this socket will - * throw an IOException. - */ -class HttpSendSocket extends Socket implements RMISocketInfo { - - /** the host to connect to */ - protected String host; - - /** the port to connect to */ - protected int port; - - /** the URL to forward through */ - protected URL url; - - /** the object managing this connection through the URL */ - protected URLConnection conn = null; - - /** internal input stream for this socket */ - protected InputStream in = null; - - /** internal output stream for this socket */ - protected OutputStream out = null; - - /** the notifying input stream returned to users */ - protected HttpSendInputStream inNotifier; - - /** the notifying output stream returned to users */ - protected HttpSendOutputStream outNotifier; - - /** - * Line separator string. This is the value of the line.separator - * property at the moment that the socket was created. - */ - private String lineSeparator = - java.security.AccessController.doPrivileged( - (PrivilegedAction) () -> System.getProperty("line.separator")); - - /** - * Create a stream socket and connect it to the specified port on - * the specified host. - * @param host the host - * @param port the port - */ - public HttpSendSocket(String host, int port, URL url) throws IOException - { - super((SocketImpl)null); // no underlying SocketImpl for this object - - if (RMIMasterSocketFactory.proxyLog.isLoggable(Log.VERBOSE)) { - RMIMasterSocketFactory.proxyLog.log(Log.VERBOSE, - "host = " + host + ", port = " + port + ", url = " + url); - } - - this.host = host; - this.port = port; - this.url = url; - - inNotifier = new HttpSendInputStream(null, this); - outNotifier = new HttpSendOutputStream(writeNotify(), this); - } - - /** - * Create a stream socket and connect it to the specified port on - * the specified host. - * @param host the host - * @param port the port - */ - public HttpSendSocket(String host, int port) throws IOException - { - this(host, port, new URL("http", host, port, "/")); - } - - /** - * Create a stream socket and connect it to the specified address on - * the specified port. - * @param address the address - * @param port the port - */ - public HttpSendSocket(InetAddress address, int port) throws IOException - { - this(address.getHostName(), port); - } - - /** - * Indicate that this socket is not reusable. - */ - public boolean isReusable() - { - return false; - } - - /** - * Create a new socket connection to host (or proxy), and prepare to - * send HTTP transmission. - */ - public synchronized OutputStream writeNotify() throws IOException - { - if (conn != null) { - throw new IOException("attempt to write on HttpSendSocket after " + - "request has been sent"); - } - - conn = url.openConnection(); - conn.setDoOutput(true); - conn.setUseCaches(false); - conn.setRequestProperty("Content-type", "application/octet-stream"); - - inNotifier.deactivate(); - in = null; - - return out = conn.getOutputStream(); - } - - /** - * Send HTTP output transmission and prepare to receive response. - */ - public synchronized InputStream readNotify() throws IOException - { - RMIMasterSocketFactory.proxyLog.log(Log.VERBOSE, - "sending request and activating input stream"); - - outNotifier.deactivate(); - out.close(); - out = null; - - try { - in = conn.getInputStream(); - } catch (IOException e) { - RMIMasterSocketFactory.proxyLog.log(Log.BRIEF, - "failed to get input stream, exception: ", e); - - throw new IOException("HTTP request failed"); - } - - /* - * If an HTTP error response is returned, sometimes an IOException - * is thrown, which is handled above, and other times it isn't, and - * the error response body will be available for reading. - * As a safety net to catch any such unexpected HTTP behavior, we - * verify that the content type of the response is what the - * HttpOutputStream generates: "application/octet-stream". - * (Servers' error responses will generally be "text/html".) - * Any error response body is printed to the log. - */ - String contentType = conn.getContentType(); - if (contentType == null || - !conn.getContentType().equals("application/octet-stream")) - { - if (RMIMasterSocketFactory.proxyLog.isLoggable(Log.BRIEF)) { - String message; - if (contentType == null) { - message = "missing content type in response" + - lineSeparator; - } else { - message = "invalid content type in response: " + - contentType + lineSeparator; - } - - message += "HttpSendSocket.readNotify: response body: "; - try { - BufferedReader din = new BufferedReader(new InputStreamReader(in)); - String line; - while ((line = din.readLine()) != null) - message += line + lineSeparator; - } catch (IOException e) { - } - RMIMasterSocketFactory.proxyLog.log(Log.BRIEF, message); - } - - throw new IOException("HTTP request failed"); - } - - return in; - } - - /** - * Get the address to which the socket is connected. - */ - public InetAddress getInetAddress() - { - try { - return InetAddress.getByName(host); - } catch (UnknownHostException e) { - return null; // null if couldn't resolve destination host - } - } - - /** - * Get the local address to which the socket is bound. - */ - public InetAddress getLocalAddress() - { - try { - return InetAddress.getLocalHost(); - } catch (UnknownHostException e) { - return null; // null if couldn't determine local host - } - } - - /** - * Get the remote port to which the socket is connected. - */ - public int getPort() - { - return port; - } - - /** - * Get the local port to which the socket is connected. - */ - public int getLocalPort() - { - return -1; // request not applicable to this socket type - } - - /** - * Get an InputStream for this socket. - */ - public InputStream getInputStream() throws IOException - { - return inNotifier; - } - - /** - * Get an OutputStream for this socket. - */ - public OutputStream getOutputStream() throws IOException - { - return outNotifier; - } - - /** - * Enable/disable TCP_NODELAY. - * This operation has no effect for an HttpSendSocket. - */ - public void setTcpNoDelay(boolean on) throws SocketException - { - } - - /** - * Retrieve whether TCP_NODELAY is enabled. - */ - public boolean getTcpNoDelay() throws SocketException - { - return false; // imply option is disabled - } - - /** - * Enable/disable SO_LINGER with the specified linger time. - * This operation has no effect for an HttpSendSocket. - */ - public void setSoLinger(boolean on, int val) throws SocketException - { - } - - /** - * Retrive setting for SO_LINGER. - */ - public int getSoLinger() throws SocketException - { - return -1; // imply option is disabled - } - - /** - * Enable/disable SO_TIMEOUT with the specified timeout - * This operation has no effect for an HttpSendSocket. - */ - public synchronized void setSoTimeout(int timeout) throws SocketException - { - } - - /** - * Retrive setting for SO_TIMEOUT. - */ - public synchronized int getSoTimeout() throws SocketException - { - return 0; // imply option is disabled - } - - /** - * Close the socket. - */ - public synchronized void close() throws IOException - { - if (out != null) // push out transmission if not done - out.close(); - } - - /** - * Return string representation of this pseudo-socket. - */ - public String toString() - { - return "HttpSendSocket[host=" + host + - ",port=" + port + - ",url=" + url + "]"; - } -} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIHttpToCGISocketFactory.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIHttpToCGISocketFactory.java deleted file mode 100644 index 548f584ae11..00000000000 --- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIHttpToCGISocketFactory.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 1998, 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 sun.rmi.transport.proxy; - -import java.io.IOException; -import java.net.Socket; -import java.net.ServerSocket; -import java.net.URL; -import java.rmi.server.RMISocketFactory; - -/** - * RMIHttpToCGISocketFactory creates a socket connection to the - * specified host that is comminicated within an HTTP request, - * forwarded through the default firewall proxy, to the target host's - * normal HTTP server, to a CGI program which forwards the request to - * the actual specified port on the socket. - */ -public class RMIHttpToCGISocketFactory extends RMISocketFactory { - - public Socket createSocket(String host, int port) - throws IOException - { - return new HttpSendSocket(host, port, - new URL("http", host, - "/cgi-bin/java-rmi.cgi" + - "?forward=" + port)); - } - - public ServerSocket createServerSocket(int port) throws IOException - { - return new HttpAwareServerSocket(port); - } -} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIHttpToPortSocketFactory.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIHttpToPortSocketFactory.java deleted file mode 100644 index c23df420e44..00000000000 --- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIHttpToPortSocketFactory.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 1998, 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 sun.rmi.transport.proxy; - -import java.io.IOException; -import java.net.Socket; -import java.net.ServerSocket; -import java.net.URL; -import java.rmi.server.RMISocketFactory; - -/** - * RMIHttpToPortSocketFactory creates a socket connection to the - * specified host that is communicated within an HTTP request, - * forwarded through the default firewall proxy, directly to the - * specified port. - */ -public class RMIHttpToPortSocketFactory extends RMISocketFactory { - - public Socket createSocket(String host, int port) - throws IOException - { - return new HttpSendSocket(host, port, - new URL("http", host, port, "/")); - } - - public ServerSocket createServerSocket(int port) - throws IOException - { - return new HttpAwareServerSocket(port); - } -} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIMasterSocketFactory.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIMasterSocketFactory.java deleted file mode 100644 index 8cb7cc4185f..00000000000 --- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIMasterSocketFactory.java +++ /dev/null @@ -1,468 +0,0 @@ -/* - * Copyright (c) 1996, 2013, 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 sun.rmi.transport.proxy; - -import java.io.*; -import java.net.*; -import java.security.*; -import java.util.*; -import java.rmi.server.LogStream; -import java.rmi.server.RMISocketFactory; -import sun.rmi.runtime.Log; -import sun.rmi.runtime.NewThreadAction; - -/** - * RMIMasterSocketFactory attempts to create a socket connection to the - * specified host using successively less efficient mechanisms - * until one succeeds. If the host is successfully connected to, - * the factory for the successful mechanism is stored in an internal - * hash table keyed by the host name, so that future attempts to - * connect to the same host will automatically use the same - * mechanism. - */ -@SuppressWarnings("deprecation") -public class RMIMasterSocketFactory extends RMISocketFactory { - - /** "proxy" package log level */ - static int logLevel = LogStream.parseLevel(getLogLevel()); - - private static String getLogLevel() { - return java.security.AccessController.doPrivileged( - (PrivilegedAction) () -> System.getProperty("sun.rmi.transport.proxy.logLevel")); - } - - /* proxy package log */ - static final Log proxyLog = - Log.getLog("sun.rmi.transport.tcp.proxy", - "transport", RMIMasterSocketFactory.logLevel); - - /** timeout for attemping direct socket connections */ - private static long connectTimeout = getConnectTimeout(); - - private static long getConnectTimeout() { - return java.security.AccessController.doPrivileged((PrivilegedAction) () -> - Long.getLong("sun.rmi.transport.proxy.connectTimeout", 15000)); // default: 15 seconds - } - - /** whether to fallback to HTTP on general connect failures */ - private static final boolean eagerHttpFallback = - java.security.AccessController.doPrivileged((PrivilegedAction) () -> - Boolean.getBoolean("sun.rmi.transport.proxy.eagerHttpFallback")); - - /** table of hosts successfully connected to and the factory used */ - private Hashtable successTable = - new Hashtable<>(); - - /** maximum number of hosts to remember successful connection to */ - private static final int MaxRememberedHosts = 64; - - /** list of the hosts in successTable in initial connection order */ - private Vector hostList = new Vector<>(MaxRememberedHosts); - - /** default factory for initial use for direct socket connection */ - protected RMISocketFactory initialFactory = new RMIDirectSocketFactory(); - - /** ordered list of factories to try as alternate connection - * mechanisms if a direct socket connections fails */ - protected Vector altFactoryList; - - /** - * Create a RMIMasterSocketFactory object. Establish order of - * connection mechanisms to attempt on createSocket, if a direct - * socket connection fails. - */ - public RMIMasterSocketFactory() { - altFactoryList = new Vector<>(2); - boolean setFactories = false; - - try { - String proxyHost; - proxyHost = java.security.AccessController.doPrivileged( - (PrivilegedAction) () -> System.getProperty("http.proxyHost")); - - if (proxyHost == null) - proxyHost = java.security.AccessController.doPrivileged( - (PrivilegedAction) () -> System.getProperty("proxyHost")); - - boolean disable = java.security.AccessController.doPrivileged( - (PrivilegedAction) () -> System.getProperty("java.rmi.server.disableHttp", "true")) - .equalsIgnoreCase("true"); - - if (!disable && proxyHost != null && proxyHost.length() > 0) { - setFactories = true; - } - } catch (Exception e) { - // unable to obtain the properties, so use the default behavior. - } - - if (setFactories) { - altFactoryList.addElement(new RMIHttpToPortSocketFactory()); - altFactoryList.addElement(new RMIHttpToCGISocketFactory()); - } - } - - /** - * Create a new client socket. If we remember connecting to this host - * successfully before, then use the same factory again. Otherwise, - * try using a direct socket connection and then the alternate factories - * in the order specified in altFactoryList. - */ - public Socket createSocket(String host, int port) - throws IOException - { - if (proxyLog.isLoggable(Log.BRIEF)) { - proxyLog.log(Log.BRIEF, "host: " + host + ", port: " + port); - } - - /* - * If we don't have any alternate factories to consult, short circuit - * the fallback procedure and delegate to the initial factory. - */ - if (altFactoryList.size() == 0) { - return initialFactory.createSocket(host, port); - } - - RMISocketFactory factory; - - /* - * If we remember successfully connecting to this host before, - * use the same factory. - */ - factory = successTable.get(host); - if (factory != null) { - if (proxyLog.isLoggable(Log.BRIEF)) { - proxyLog.log(Log.BRIEF, - "previously successful factory found: " + factory); - } - return factory.createSocket(host, port); - } - - /* - * Next, try a direct socket connection. Open socket in another - * thread and only wait for specified timeout, in case the socket - * would otherwise spend minutes trying an unreachable host. - */ - Socket initialSocket = null; - Socket fallbackSocket = null; - final AsyncConnector connector = - new AsyncConnector(initialFactory, host, port, - AccessController.getContext()); - // connection must be attempted with - // this thread's access control context - IOException initialFailure = null; - - try { - synchronized (connector) { - - Thread t = java.security.AccessController.doPrivileged( - new NewThreadAction(connector, "AsyncConnector", true)); - t.start(); - - try { - long now = System.currentTimeMillis(); - long deadline = now + connectTimeout; - do { - connector.wait(deadline - now); - initialSocket = checkConnector(connector); - if (initialSocket != null) - break; - now = System.currentTimeMillis(); - } while (now < deadline); - } catch (InterruptedException e) { - throw new InterruptedIOException( - "interrupted while waiting for connector"); - } - } - - // assume no route to host (for now) if no connection yet - if (initialSocket == null) - throw new NoRouteToHostException( - "connect timed out: " + host); - - proxyLog.log(Log.BRIEF, "direct socket connection successful"); - - return initialSocket; - - } catch (UnknownHostException | NoRouteToHostException e) { - initialFailure = e; - } catch (SocketException e) { - if (eagerHttpFallback) { - initialFailure = e; - } else { - throw e; - } - } finally { - if (initialFailure != null) { - - if (proxyLog.isLoggable(Log.BRIEF)) { - proxyLog.log(Log.BRIEF, - "direct socket connection failed: ", initialFailure); - } - - // Finally, try any alternate connection mechanisms. - for (int i = 0; i < altFactoryList.size(); ++ i) { - factory = altFactoryList.elementAt(i); - if (proxyLog.isLoggable(Log.BRIEF)) { - proxyLog.log(Log.BRIEF, - "trying with factory: " + factory); - } - try (Socket testSocket = - factory.createSocket(host, port)) { - // For HTTP connections, the output (POST request) must - // be sent before we verify a successful connection. - // So, sacrifice a socket for the sake of testing... - // The following sequence should verify a successful - // HTTP connection if no IOException is thrown. - InputStream in = testSocket.getInputStream(); - int b = in.read(); // probably -1 for EOF... - } catch (IOException ex) { - if (proxyLog.isLoggable(Log.BRIEF)) { - proxyLog.log(Log.BRIEF, "factory failed: ", ex); - } - - continue; - } - proxyLog.log(Log.BRIEF, "factory succeeded"); - - // factory succeeded, open new socket for caller's use - try { - fallbackSocket = factory.createSocket(host, port); - } catch (IOException ex) { // if it fails 2nd time, - } // just give up - break; - } - } - } - - synchronized (successTable) { - try { - // check once again to see if direct connection succeeded - synchronized (connector) { - initialSocket = checkConnector(connector); - } - if (initialSocket != null) { - // if we had made another one as well, clean it up... - if (fallbackSocket != null) - fallbackSocket.close(); - return initialSocket; - } - // if connector ever does get socket, it won't be used - connector.notUsed(); - } catch (UnknownHostException | NoRouteToHostException e) { - initialFailure = e; - } catch (SocketException e) { - if (eagerHttpFallback) { - initialFailure = e; - } else { - throw e; - } - } - // if we had found an alternate mechanism, go and use it - if (fallbackSocket != null) { - // remember this successful host/factory pair - rememberFactory(host, factory); - return fallbackSocket; - } - throw initialFailure; - } - } - - /** - * Remember a successful factory for connecting to host. - * Currently, excess hosts are removed from the remembered list - * using a Least Recently Created strategy. - */ - void rememberFactory(String host, RMISocketFactory factory) { - synchronized (successTable) { - while (hostList.size() >= MaxRememberedHosts) { - successTable.remove(hostList.elementAt(0)); - hostList.removeElementAt(0); - } - hostList.addElement(host); - successTable.put(host, factory); - } - } - - /** - * Check if an AsyncConnector succeeded. If not, return socket - * given to fall back to. - */ - Socket checkConnector(AsyncConnector connector) - throws IOException - { - Exception e = connector.getException(); - if (e != null) { - e.fillInStackTrace(); - /* - * The AsyncConnector implementation guaranteed that the exception - * will be either an IOException or a RuntimeException, and we can - * only throw one of those, so convince that compiler that it must - * be one of those. - */ - if (e instanceof IOException) { - throw (IOException) e; - } else if (e instanceof RuntimeException) { - throw (RuntimeException) e; - } else { - throw new Error("internal error: " + - "unexpected checked exception: " + e.toString()); - } - } - return connector.getSocket(); - } - - /** - * Create a new server socket. - */ - public ServerSocket createServerSocket(int port) throws IOException { - //return new HttpAwareServerSocket(port); - return initialFactory.createServerSocket(port); - } - - - /** - * AsyncConnector is used by RMIMasterSocketFactory to attempt socket - * connections on a separate thread. This allows RMIMasterSocketFactory - * to control how long it will wait for the connection to succeed. - */ - private class AsyncConnector implements Runnable { - - /** what factory to use to attempt connection */ - private RMISocketFactory factory; - - /** the host to connect to */ - private String host; - - /** the port to connect to */ - private int port; - - /** access control context to attempt connection within */ - private AccessControlContext acc; - - /** exception that occurred during connection, if any */ - private Exception exception = null; - - /** the connected socket, if successful */ - private Socket socket = null; - - /** socket should be closed after created, if ever */ - private boolean cleanUp = false; - - /** - * Create a new asynchronous connector object. - */ - AsyncConnector(RMISocketFactory factory, String host, int port, - AccessControlContext acc) - { - this.factory = factory; - this.host = host; - this.port = port; - this.acc = acc; - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkConnect(host, port); - } - } - - /** - * Attempt socket connection in separate thread. If successful, - * notify master waiting, - */ - public void run() { - try { - /* - * Using the privileges of the thread that wants to make the - * connection is tempting, but it will fail with applets with - * the current applet security manager because the applet - * network connection policy is not captured in the permission - * framework of the access control context we have. - * - * java.security.AccessController.beginPrivileged(acc); - */ - try { - Socket temp = factory.createSocket(host, port); - synchronized (this) { - socket = temp; - notify(); - } - rememberFactory(host, factory); - synchronized (this) { - if (cleanUp) - try { - socket.close(); - } catch (IOException e) { - } - } - } catch (Exception e) { - /* - * Note that the only exceptions which could actually have - * occurred here are IOException or RuntimeException. - */ - synchronized (this) { - exception = e; - notify(); - } - } - } finally { - /* - * See above comments for matching beginPrivileged() call that - * is also commented out. - * - * java.security.AccessController.endPrivileged(); - */ - } - } - - /** - * Get exception that occurred during connection attempt, if any. - * In the current implementation, this is guaranteed to be either - * an IOException or a RuntimeException. - */ - private synchronized Exception getException() { - return exception; - } - - /** - * Get successful socket, if any. - */ - private synchronized Socket getSocket() { - return socket; - } - - /** - * Note that this connector's socket, if ever successfully created, - * will not be used, so it should be cleaned up quickly - */ - synchronized void notUsed() { - if (socket != null) { - try { - socket.close(); - } catch (IOException e) { - } - } - cleanUp = true; - } - } -} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMISocketInfo.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMISocketInfo.java deleted file mode 100644 index 85008fb231e..00000000000 --- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMISocketInfo.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 1996, 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 sun.rmi.transport.proxy; - -/** - * RMISocketInfo is an interface that extensions of the java.net.Socket - * class may use to provide more information on its capabilities. - */ -public interface RMISocketInfo { - - /** - * Return true if this socket can be used for more than one - * RMI call. If a socket does not implement this interface, then - * it is assumed to be reusable. - */ - public boolean isReusable(); -} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/WrappedSocket.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/WrappedSocket.java deleted file mode 100644 index 7bc8503f60f..00000000000 --- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/WrappedSocket.java +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright (c) 1996, 2013, 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 sun.rmi.transport.proxy; - -import java.io.*; -import java.net.InetAddress; -import java.net.Socket; -import java.net.SocketException; -import java.security.AccessController; -import java.security.PrivilegedAction; - -/** - * The WrappedSocket class provides a general wrapper for providing an - * extended implementation of java.net.Socket that can be attached to - * a pre-existing Socket object. WrappedSocket itself provides a - * constructor for specifying alternate input or output streams to be - * returned than those of the underlying Socket. - */ -class WrappedSocket extends Socket { - - /** the underlying concrete socket */ - protected Socket socket; - - /** the input stream to return for socket */ - protected InputStream in = null; - - /** the output stream to return for socket */ - protected OutputStream out = null; - - /** - * Layer on top of a pre-existing Socket object, and use specified - * input and output streams. This allows the creator of the - * underlying socket to peek at the beginning of the input with a - * BufferedInputStream and determine which kind of socket - * to create, without consuming the input. - * @param socket the pre-existing socket to use - * @param in the InputStream to return to users (can be null) - * @param out the OutputStream to return to users (can be null) - */ - public WrappedSocket(Socket socket, InputStream in, OutputStream out) - throws IOException - { - super((java.net.SocketImpl)null); // no underlying SocketImpl for this object - this.socket = socket; - this.in = in; - this.out = out; - } - - /** - * Get the address to which the socket is connected. - */ - public InetAddress getInetAddress() - { - return socket.getInetAddress(); - } - - /** - * Get the local address to which the socket is bound. - */ - public InetAddress getLocalAddress() { - return AccessController.doPrivileged( - new PrivilegedAction() { - @Override - public InetAddress run() { - return socket.getLocalAddress(); - - } - }); - } - - /** - * Get the remote port to which the socket is connected. - */ - public int getPort() - { - return socket.getPort(); - } - - /** - * Get the local port to which the socket is connected. - */ - public int getLocalPort() - { - return socket.getLocalPort(); - } - - /** - * Get an InputStream for this socket. - */ - public InputStream getInputStream() throws IOException - { - if (in == null) - in = socket.getInputStream(); - return in; - } - - /** - * Get an OutputStream for this socket. - */ - public OutputStream getOutputStream() throws IOException - { - if (out == null) - out = socket.getOutputStream(); - return out; - } - - /** - * Enable/disable TCP_NODELAY. - */ - public void setTcpNoDelay(boolean on) throws SocketException - { - socket.setTcpNoDelay(on); - } - - /** - * Retrieve whether TCP_NODELAY is enabled. - */ - public boolean getTcpNoDelay() throws SocketException - { - return socket.getTcpNoDelay(); - } - - /** - * Enable/disable SO_LINGER with the specified linger time. - */ - public void setSoLinger(boolean on, int val) throws SocketException - { - socket.setSoLinger(on, val); - } - - /** - * Retrive setting for SO_LINGER. - */ - public int getSoLinger() throws SocketException - { - return socket.getSoLinger(); - } - - /** - * Enable/disable SO_TIMEOUT with the specified timeout - */ - public synchronized void setSoTimeout(int timeout) throws SocketException - { - socket.setSoTimeout(timeout); - } - - /** - * Retrive setting for SO_TIMEOUT. - */ - public synchronized int getSoTimeout() throws SocketException - { - return socket.getSoTimeout(); - } - - /** - * Close the socket. - */ - public synchronized void close() throws IOException - { - socket.close(); - } - - /** - * Return string representation of the socket. - */ - public String toString() - { - return "Wrapped" + socket.toString(); - } -} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPConnection.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPConnection.java index 08eb50b29a7..8b5a610005b 100644 --- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPConnection.java +++ b/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, 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,14 +26,10 @@ package sun.rmi.transport.tcp; import java.io.*; -import java.net.InetAddress; import java.net.Socket; -import java.net.SocketException; import java.rmi.*; -import java.rmi.server.RMISocketFactory; import sun.rmi.runtime.Log; import sun.rmi.transport.*; -import sun.rmi.transport.proxy.*; public class TCPConnection implements Connection { @@ -120,10 +116,7 @@ public class TCPConnection implements Connection { */ public boolean isReusable() { - if ((socket != null) && (socket instanceof RMISocketInfo)) - return ((RMISocketInfo) socket).isReusable(); - else - return true; + return true; } /** diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIDirectSocketFactory.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPDirectSocketFactory.java similarity index 94% rename from jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIDirectSocketFactory.java rename to jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPDirectSocketFactory.java index 953d47ca400..8274742ec1b 100644 --- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIDirectSocketFactory.java +++ b/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPDirectSocketFactory.java @@ -22,7 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package sun.rmi.transport.proxy; +package sun.rmi.transport.tcp; import java.io.IOException; import java.net.Socket; @@ -33,7 +33,7 @@ import java.rmi.server.RMISocketFactory; * RMIDirectSocketFactory creates a direct socket connection to the * specified port on the specified host. */ -public class RMIDirectSocketFactory extends RMISocketFactory { +public class TCPDirectSocketFactory extends RMISocketFactory { public Socket createSocket(String host, int port) throws IOException { diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPTransport.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPTransport.java index 1caa362803a..764abefb551 100644 --- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPTransport.java +++ b/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPTransport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, 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 @@ -75,7 +75,6 @@ import sun.rmi.transport.StreamRemoteCall; import sun.rmi.transport.Target; import sun.rmi.transport.Transport; import sun.rmi.transport.TransportConstants; -import sun.rmi.transport.proxy.HttpReceiveSocket; /** * TCPTransport is the socket-based implementation of the RMI Transport @@ -711,35 +710,10 @@ public class TCPTransport extends Transport { ? sockIn : new BufferedInputStream(sockIn); - // Read magic (or HTTP wrapper) - bufIn.mark(4); + // Read magic DataInputStream in = new DataInputStream(bufIn); int magic = in.readInt(); - if (magic == POST) { - tcpLog.log(Log.BRIEF, "decoding HTTP-wrapped call"); - - // It's really a HTTP-wrapped request. Repackage - // the socket in a HttpReceiveSocket, reinitialize - // sockIn and in, and reread magic. - bufIn.reset(); // unread "POST" - - try { - socket = new HttpReceiveSocket(socket, bufIn, null); - remoteHost = "0.0.0.0"; - sockIn = socket.getInputStream(); - bufIn = new BufferedInputStream(sockIn); - in = new DataInputStream(bufIn); - magic = in.readInt(); - - } catch (IOException e) { - throw new RemoteException("Error HTTP-unwrapping call", - e); - } - } - // bufIn's mark will invalidate itself when it overflows - // so it doesn't have to be turned off - // read and verify transport header short version = in.readShort(); if (magic != TransportConstants.Magic || diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index 696c9cd270f..684b0cab3ab 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -191,8 +191,6 @@ java/rmi/transport/rapidExportUnexport/RapidExportUnexport.java 7146541 linux-al java/rmi/transport/checkLeaseInfoLeak/CheckLeaseLeak.java 7191877 generic-all -sun/rmi/transport/proxy/EagerHttpFallback.java 7195095 generic-all - java/rmi/activation/Activatable/extLoadedImpl/ext.sh 8062724 generic-all sun/rmi/rmic/newrmic/equivalence/run.sh 8145980 generic-all diff --git a/jdk/test/java/rmi/transport/httpSocket/HttpSocketTest.java b/jdk/test/java/rmi/transport/httpSocket/HttpSocketTest.java deleted file mode 100644 index 8999c3d7310..00000000000 --- a/jdk/test/java/rmi/transport/httpSocket/HttpSocketTest.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 1999, 2012, 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 HttpSocket functionality test - * @author Dana Burns - * - * @library ../../testlibrary - * @modules java.rmi/sun.rmi.registry - * java.rmi/sun.rmi.server - * java.rmi/sun.rmi.transport - * java.rmi/sun.rmi.transport.proxy - * java.rmi/sun.rmi.transport.tcp - * @build TestLibrary HttpSocketTest HttpSocketTest_Stub - * @run main/othervm/policy=security.policy HttpSocketTest - */ - -/* - * This test assures remote methods can be carried out over RMI. - * After setting the RMI runtime socket factory to the http proxy version, - * a registry is created, a remote object (an instance of this class) is - * registered with it, and then it is exercised. - */ - -import java.rmi.Remote; -import java.rmi.RemoteException; -import java.rmi.Naming; -import java.rmi.RMISecurityManager; -import java.rmi.registry.LocateRegistry; -import java.rmi.registry.Registry; -import java.rmi.server.RMISocketFactory; -import java.rmi.server.UnicastRemoteObject; -import sun.rmi.transport.proxy.RMIHttpToPortSocketFactory; - -interface MyRemoteInterface extends Remote { - void setRemoteObject( Remote r ) throws RemoteException; - Remote getRemoteObject() throws RemoteException; -} - -public class HttpSocketTest extends UnicastRemoteObject - implements MyRemoteInterface -{ - private static final String NAME = "HttpSocketTest"; - - public HttpSocketTest() throws RemoteException{} - - private Remote ro; - - public static void main(String[] args) - throws Exception - { - - Registry registry = null; - - TestLibrary.suggestSecurityManager(null); - - // Set the socket factory. - System.err.println("installing socket factory"); - RMISocketFactory.setSocketFactory(new RMIHttpToPortSocketFactory()); - int registryPort = -1; - - try { - System.err.println("Starting registry"); - registry = TestLibrary.createRegistryOnUnusedPort(); - registryPort = TestLibrary.getRegistryPort(registry); - } catch (Exception e) { - TestLibrary.bomb(e); - } - - try { - registry.rebind( NAME, new HttpSocketTest() ); - MyRemoteInterface httpTest = - (MyRemoteInterface)Naming.lookup("//:" + registryPort + "/" + NAME); - httpTest.setRemoteObject( new HttpSocketTest() ); - Remote r = httpTest.getRemoteObject(); - - } catch (Exception e) { - TestLibrary.bomb(e); - } - - - } - - public void setRemoteObject( Remote ro ) throws RemoteException { - this.ro = ro; - } - - public Remote getRemoteObject() throws RemoteException { - return( this.ro ); - } - -} diff --git a/jdk/test/java/rmi/transport/httpSocket/HttpSocketTest_Stub.java b/jdk/test/java/rmi/transport/httpSocket/HttpSocketTest_Stub.java deleted file mode 100644 index 03757a3df20..00000000000 --- a/jdk/test/java/rmi/transport/httpSocket/HttpSocketTest_Stub.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (c) 1999, 2008, 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. - */ - -// Stub class generated by rmic, do not edit. -// Contents subject to change without notice. - -public final class HttpSocketTest_Stub - extends java.rmi.server.RemoteStub - implements MyRemoteInterface, java.rmi.Remote -{ - private static final java.rmi.server.Operation[] operations = { - new java.rmi.server.Operation("java.rmi.Remote getRemoteObject()"), - new java.rmi.server.Operation("void setRemoteObject(java.rmi.Remote)") - }; - - private static final long interfaceHash = 3775375480010579665L; - - private static final long serialVersionUID = 2; - - private static boolean useNewInvoke; - private static java.lang.reflect.Method $method_getRemoteObject_0; - private static java.lang.reflect.Method $method_setRemoteObject_1; - - static { - try { - java.rmi.server.RemoteRef.class.getMethod("invoke", - new java.lang.Class[] { - java.rmi.Remote.class, - java.lang.reflect.Method.class, - java.lang.Object[].class, - long.class - }); - useNewInvoke = true; - $method_getRemoteObject_0 = MyRemoteInterface.class.getMethod("getRemoteObject", new java.lang.Class[] {}); - $method_setRemoteObject_1 = MyRemoteInterface.class.getMethod("setRemoteObject", new java.lang.Class[] {java.rmi.Remote.class}); - } catch (java.lang.NoSuchMethodException e) { - useNewInvoke = false; - } - } - - // constructors - public HttpSocketTest_Stub() { - super(); - } - public HttpSocketTest_Stub(java.rmi.server.RemoteRef ref) { - super(ref); - } - - // methods from remote interfaces - - // implementation of getRemoteObject() - public java.rmi.Remote getRemoteObject() - throws java.rmi.RemoteException - { - try { - if (useNewInvoke) { - Object $result = ref.invoke(this, $method_getRemoteObject_0, null, -2578437860804964265L); - return ((java.rmi.Remote) $result); - } else { - java.rmi.server.RemoteCall call = ref.newCall((java.rmi.server.RemoteObject) this, operations, 0, interfaceHash); - ref.invoke(call); - java.rmi.Remote $result; - try { - java.io.ObjectInput in = call.getInputStream(); - $result = (java.rmi.Remote) in.readObject(); - } catch (java.io.IOException e) { - throw new java.rmi.UnmarshalException("error unmarshalling return", e); - } catch (java.lang.ClassNotFoundException e) { - throw new java.rmi.UnmarshalException("error unmarshalling return", e); - } finally { - ref.done(call); - } - return $result; - } - } catch (java.lang.RuntimeException e) { - throw e; - } catch (java.rmi.RemoteException e) { - throw e; - } catch (java.lang.Exception e) { - throw new java.rmi.UnexpectedException("undeclared checked exception", e); - } - } - - // implementation of setRemoteObject(Remote) - public void setRemoteObject(java.rmi.Remote $param_Remote_1) - throws java.rmi.RemoteException - { - try { - if (useNewInvoke) { - ref.invoke(this, $method_setRemoteObject_1, new java.lang.Object[] {$param_Remote_1}, -7518632118115022871L); - } else { - java.rmi.server.RemoteCall call = ref.newCall((java.rmi.server.RemoteObject) this, operations, 1, interfaceHash); - try { - java.io.ObjectOutput out = call.getOutputStream(); - out.writeObject($param_Remote_1); - } catch (java.io.IOException e) { - throw new java.rmi.MarshalException("error marshalling arguments", e); - } - ref.invoke(call); - ref.done(call); - } - } catch (java.lang.RuntimeException e) { - throw e; - } catch (java.rmi.RemoteException e) { - throw e; - } catch (java.lang.Exception e) { - throw new java.rmi.UnexpectedException("undeclared checked exception", e); - } - } -} diff --git a/jdk/test/java/rmi/transport/httpSocket/security.policy b/jdk/test/java/rmi/transport/httpSocket/security.policy deleted file mode 100644 index f1960c9772d..00000000000 --- a/jdk/test/java/rmi/transport/httpSocket/security.policy +++ /dev/null @@ -1,10 +0,0 @@ - -grant { - permission java.net.SocketPermission "*:1024-", "accept,connect,listen"; - permission java.lang.RuntimePermission "accessClassInPackage.sun.rmi.registry"; - permission java.lang.RuntimePermission "accessClassInPackage.sun.rmi.server"; - permission java.lang.RuntimePermission "accessClassInPackage.sun.rmi.transport"; - permission java.lang.RuntimePermission "accessClassInPackage.sun.rmi.transport.proxy"; - permission java.lang.RuntimePermission "accessClassInPackage.sun.rmi.transport.tcp"; - permission java.lang.RuntimePermission "setFactory"; -}; diff --git a/jdk/test/sun/rmi/transport/proxy/DisableHttpDefaultValue.java b/jdk/test/sun/rmi/transport/proxy/DisableHttpDefaultValue.java deleted file mode 100644 index 5449c3b8759..00000000000 --- a/jdk/test/sun/rmi/transport/proxy/DisableHttpDefaultValue.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2013, 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 - * @bug 8023862 - * @summary Verify that the default value of the java.rmi.server.disableHttp - * has been changed from false to true. - * @modules java.rmi/sun.rmi.transport.proxy - * @compile -XDignore.symbol.file DisableHttpDefaultValue.java - * - * @run main/othervm DisableHttpDefaultValue true - * @run main/othervm -Djava.rmi.server.disableHttp DisableHttpDefaultValue false - * @run main/othervm -Djava.rmi.server.disableHttp=false DisableHttpDefaultValue false - * @run main/othervm -Djava.rmi.server.disableHttp=xyzzy DisableHttpDefaultValue false - * @run main/othervm -Djava.rmi.server.disableHttp=true DisableHttpDefaultValue true - */ - -import sun.rmi.transport.proxy.RMIMasterSocketFactory; - -public class DisableHttpDefaultValue { - /** - * Subclass RMIMasterSocketFactory to get access to - * protected field altFactoryList. This list has a - * zero size if proxying is disabled. - */ - static class SocketFactory extends RMIMasterSocketFactory { - boolean proxyDisabled() { - return altFactoryList.size() == 0; - } - } - - /** - * Takes a single arg, which is the expected boolean value of - * java.rmi.server.disableHttp. - */ - public static void main(String[] args) throws Exception { - // Force there to be a proxy host, so that we are able to - // tell whether proxying is enabled or disabled. - System.setProperty("http.proxyHost", "proxy.example.com"); - - String propval = System.getProperty("java.rmi.server.disableHttp"); - String propdisp = (propval == null) ? "null" : ("\"" + propval + "\""); - boolean expected = Boolean.parseBoolean(args[0]); - boolean actual = new SocketFactory().proxyDisabled(); - System.out.printf("### prop=%s exp=%s act=%s%n", propdisp, expected, actual); - if (expected != actual) - throw new AssertionError(); - } -} diff --git a/jdk/test/sun/rmi/transport/proxy/EagerHttpFallback.java b/jdk/test/sun/rmi/transport/proxy/EagerHttpFallback.java deleted file mode 100644 index 5b5691701c7..00000000000 --- a/jdk/test/sun/rmi/transport/proxy/EagerHttpFallback.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2002, 2012, 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 - * @bug 4290727 - * @summary Verify that ConnectException will trigger HTTP fallback if - * sun.rmi.transport.proxy.eagerHttpFallback system property is set. - * - * @library ../../../../java/rmi/testlibrary - * @modules java.rmi/sun.rmi.registry - * java.rmi/sun.rmi.server - * java.rmi/sun.rmi.transport - * java.rmi/sun.rmi.transport.tcp - * @build TestLibrary - * @run main/othervm EagerHttpFallback - */ - -import java.rmi.*; -import java.rmi.registry.*; - -public class EagerHttpFallback { - - static final int INITIAL_PORT = TestLibrary.getUnusedRandomPort(); - static final int FALLBACK_PORT = TestLibrary.getUnusedRandomPort(); - - public static void main(String[] args) throws Exception { - System.setProperty("http.proxyHost", "127.0.0.1"); - System.setProperty("http.proxyPort", Integer.toString(FALLBACK_PORT)); - System.setProperty("sun.rmi.transport.proxy.eagerHttpFallback", - "true"); - LocateRegistry.createRegistry(FALLBACK_PORT); - - /* - * The call below should trigger a ConnectException in the - * RMIMasterSocketFactory when it attempts a direct connection to - * INITIAL_PORT, which no one is listening on. Since - * eagerHttpFallback is set, this ConnectException should trigger HTTP - * fallback, which will send a call through the HTTP proxy, which is - * configured to be localhost with a port behind which a registry is - * listening--so if fallback works properly, the list() call should - * succeed. - */ - try { - LocateRegistry.getRegistry(INITIAL_PORT).list(); - } catch (Exception e) { - System.err.println( - "call on registry stub with port " + INITIAL_PORT + - "did not successfully perform HTTP fallback to " + - FALLBACK_PORT); - throw e; - } - } -} diff --git a/jdk/test/sun/rmi/transport/tcp/blockAccept/BlockAcceptTest.java b/jdk/test/sun/rmi/transport/tcp/blockAccept/BlockAcceptTest.java deleted file mode 100644 index 7de92ee2c47..00000000000 --- a/jdk/test/sun/rmi/transport/tcp/blockAccept/BlockAcceptTest.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (c) 1999, 2012, 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 - * @bug 4203167 - * - * @summary RMI blocks in HttpAwareServerSocket.accept() if you telnet to it - * @author Adrian Colley - * - * @library ../../../../../java/rmi/testlibrary - * @modules java.rmi/sun.rmi.transport.proxy - * @build TestIface TestImpl TestImpl_Stub - * @run main/othervm/policy=security.policy/timeout=60 BlockAcceptTest - */ - -/* This test attempts to stymie the RMI accept loop. The accept loop in - * RMI endlessly accepts a connection, spawns a thread for it, and repeats. - * The accept() call can be replaced by a user-supplied library which - * might foolishly block indefinitely in its accept() method, which would - * prevent RMI from accepting other connections on that socket. - * - * Unfortunately, HttpAwareServerSocket (default server socket) is/was such - * a foolish thing. It reads 4 bytes to see if they're "POST" before - * returning. The bug fix is to move the HTTP stuff into the mainloop, - * which has the side effect of enabling it for non-default socketfactories. - * - * This test: - * 1. Creates an object and exports it. - * 2. Connects to the listening RMI port and sends nothing, to hold it up. - * 3. Makes a regular call, using HTTP tunnelling. - * 4. Fails to deadlock, thereby passing the test. - * - * Some runtime dependencies I'm trying to eliminate: - * 1. We don't know the port number until after exporting the object, but - * have to set it in http.proxyPort somehow. Hopefully http.proxyPort - * isn't read too soon or this test will fail with a ConnectException. - */ - -import java.rmi.*; -import java.rmi.server.RMISocketFactory; -import java.io.*; -import java.net.*; - -import sun.rmi.transport.proxy.RMIMasterSocketFactory; -import sun.rmi.transport.proxy.RMIHttpToPortSocketFactory; - -public class BlockAcceptTest -{ - public static void main(String[] args) - throws Exception - { - // Make trouble for ourselves - if (System.getSecurityManager() == null) - System.setSecurityManager(new RMISecurityManager()); - - // HTTP direct to the server port - System.setProperty("http.proxyHost", "127.0.0.1"); - - // Set the socket factory. - System.err.println("(installing HTTP-out socket factory)"); - HttpOutFactory fac = new HttpOutFactory(); - RMISocketFactory.setSocketFactory(fac); - - // Create remote object - TestImpl impl = new TestImpl(); - - // Export and get which port. - System.err.println("(exporting remote object)"); - TestIface stub = impl.export(); - try { - int port = fac.whichPort(); - - // Sanity - if (port == 0) - throw new Error("TEST FAILED: export didn't reserve a port(?)"); - - // Set the HTTP port, at last. - System.setProperty("http.proxyPort", port+""); - - // Now, connect to that port - //Thread.sleep(2000); - System.err.println("(connecting to listening port on 127.0.0.1:" + - port + ")"); - Socket DoS = new Socket("127.0.0.1", port); - // we hold the connection open until done with the test. - - // The test itself: make a remote call and see if it's blocked or - // if it works - //Thread.sleep(2000); - System.err.println("(making RMI-through-HTTP call)"); - System.err.println("(typical test failure deadlocks here)"); - String result = stub.testCall("dummy load"); - - System.err.println(" => " + result); - if (!("OK".equals(result))) - throw new Error("TEST FAILED: result not OK"); - System.err.println("Test passed."); - - // Clean up, including writing a byte to that connection just in - // case an optimizer thought of optimizing it out of existence - try { - DoS.getOutputStream().write(0); - DoS.getOutputStream().close(); - } catch (Throwable apathy) { - } - - } finally { - try { - impl.unexport(); - } catch (Throwable unmatter) { - } - } - - // Should exit here - } - - private static class HttpOutFactory - extends RMISocketFactory - { - private int servport = 0; - - public Socket createSocket(String h, int p) - throws IOException - { - return ((new RMIHttpToPortSocketFactory()).createSocket(h, p)); - } - - /** Create a server socket and remember which port it's on. - * Aborts if createServerSocket(0) is called twice, because then - * it doesn't know whether to remember the first or second port. - */ - public ServerSocket createServerSocket(int p) - throws IOException - { - ServerSocket ss; - ss = (new RMIMasterSocketFactory()).createServerSocket(p); - if (p == 0) { - if (servport != 0) { - System.err.println("TEST FAILED: " + - "Duplicate createServerSocket(0)"); - throw new Error("Test aborted (createServerSocket)"); - } - servport = ss.getLocalPort(); - } - return (ss); - } - - /** Return which port was reserved by createServerSocket(0). - * If the return value was 0, createServerSocket(0) wasn't called. - */ - public int whichPort() { - return (servport); - } - } // end class HttpOutFactory -} diff --git a/jdk/test/sun/rmi/transport/tcp/blockAccept/TestIface.java b/jdk/test/sun/rmi/transport/tcp/blockAccept/TestIface.java deleted file mode 100644 index 85bab51483d..00000000000 --- a/jdk/test/sun/rmi/transport/tcp/blockAccept/TestIface.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 1999, 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.rmi.*; - -public interface TestIface - extends Remote -{ - public String testCall(String ign) - throws RemoteException; -} diff --git a/jdk/test/sun/rmi/transport/tcp/blockAccept/TestImpl.java b/jdk/test/sun/rmi/transport/tcp/blockAccept/TestImpl.java deleted file mode 100644 index 73601a9e3b6..00000000000 --- a/jdk/test/sun/rmi/transport/tcp/blockAccept/TestImpl.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 1999, 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.rmi.*; -import java.rmi.server.*; - -public class TestImpl - extends Object - implements TestIface -{ - public TestImpl() { - } - - public TestIface export() - throws RemoteException - { - return (TestIface)UnicastRemoteObject.exportObject(this); - } - - public void unexport() - throws NoSuchObjectException - { - UnicastRemoteObject.unexportObject(this, true); - } - - public String testCall(String ign) { - return ("OK"); - } -} diff --git a/jdk/test/sun/rmi/transport/tcp/blockAccept/TestImpl_Stub.java b/jdk/test/sun/rmi/transport/tcp/blockAccept/TestImpl_Stub.java deleted file mode 100644 index 2de40012e16..00000000000 --- a/jdk/test/sun/rmi/transport/tcp/blockAccept/TestImpl_Stub.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 1999, 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. - */ - -// Stub class generated by rmic, do not edit. -// Contents subject to change without notice. - -public final class TestImpl_Stub - extends java.rmi.server.RemoteStub - implements TestIface -{ - private static final long serialVersionUID = 2; - - private static java.lang.reflect.Method $method_testCall_0; - - static { - try { - $method_testCall_0 = TestIface.class.getMethod("testCall", new java.lang.Class[] {java.lang.String.class}); - } catch (java.lang.NoSuchMethodException e) { - throw new java.lang.NoSuchMethodError( - "stub class initialization failed"); - } - } - - // constructors - public TestImpl_Stub(java.rmi.server.RemoteRef ref) { - super(ref); - } - - // methods from remote interfaces - - // implementation of testCall(String) - public java.lang.String testCall(java.lang.String $param_String_1) - throws java.rmi.RemoteException - { - try { - Object $result = ref.invoke(this, $method_testCall_0, new java.lang.Object[] {$param_String_1}, -4495720265115653109L); - return ((java.lang.String) $result); - } catch (java.lang.RuntimeException e) { - throw e; - } catch (java.rmi.RemoteException e) { - throw e; - } catch (java.lang.Exception e) { - throw new java.rmi.UnexpectedException("undeclared checked exception", e); - } - } -} diff --git a/jdk/test/sun/rmi/transport/tcp/blockAccept/security.policy b/jdk/test/sun/rmi/transport/tcp/blockAccept/security.policy deleted file mode 100644 index a8c8d0a64d8..00000000000 --- a/jdk/test/sun/rmi/transport/tcp/blockAccept/security.policy +++ /dev/null @@ -1,10 +0,0 @@ -grant { - // Take this out once we can specify -Djava.security.debug on - // the run line and figure out what else is needed - permission java.security.AllPermission; - - permission java.net.SocketPermission "*:1024-65535", "connect,listen"; - permission java.util.PropertyPermission "http.proxyHost", "write"; - permission java.util.PropertyPermission "http.proxyPort", "write"; - permission java.lang.RuntimePermission "setFactory"; -}; From 727e63cad7366b75ebe71c7269f0c3515d066a9b Mon Sep 17 00:00:00 2001 From: Roger Riggs Date: Tue, 26 Apr 2016 21:25:18 -0400 Subject: [PATCH 05/18] 8155182: fix to JDK-8066750 broke jdk9 builds Restore RMI Http Proxy support for now Reviewed-by: darcy, lancea, smarks --- .../java/rmi/server/RMISocketFactory.java | 21 +- .../sun/rmi/transport/proxy/CGIHandler.java | 423 ++++++++++++++++ .../proxy/HttpAwareServerSocket.java | 114 +++++ .../rmi/transport/proxy/HttpInputStream.java | 205 ++++++++ .../rmi/transport/proxy/HttpOutputStream.java | 80 +++ .../transport/proxy/HttpReceiveSocket.java | 128 +++++ .../transport/proxy/HttpSendInputStream.java | 161 ++++++ .../transport/proxy/HttpSendOutputStream.java | 105 ++++ .../rmi/transport/proxy/HttpSendSocket.java | 344 +++++++++++++ .../RMIDirectSocketFactory.java} | 4 +- .../proxy/RMIHttpToCGISocketFactory.java | 55 ++ .../proxy/RMIHttpToPortSocketFactory.java | 53 ++ .../proxy/RMIMasterSocketFactory.java | 468 ++++++++++++++++++ .../rmi/transport/proxy/RMISocketInfo.java | 39 ++ .../rmi/transport/proxy/WrappedSocket.java | 192 +++++++ .../sun/rmi/transport/tcp/TCPConnection.java | 11 +- .../sun/rmi/transport/tcp/TCPTransport.java | 30 +- jdk/test/ProblemList.txt | 2 + .../transport/httpSocket/HttpSocketTest.java | 113 +++++ .../httpSocket/HttpSocketTest_Stub.java | 130 +++++ .../rmi/transport/httpSocket/security.policy | 10 + .../proxy/DisableHttpDefaultValue.java | 69 +++ .../transport/proxy/EagerHttpFallback.java | 73 +++ .../tcp/blockAccept/BlockAcceptTest.java | 175 +++++++ .../transport/tcp/blockAccept/TestIface.java | 31 ++ .../transport/tcp/blockAccept/TestImpl.java | 49 ++ .../tcp/blockAccept/TestImpl_Stub.java | 66 +++ .../transport/tcp/blockAccept/security.policy | 10 + 28 files changed, 3151 insertions(+), 10 deletions(-) create mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/CGIHandler.java create mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpAwareServerSocket.java create mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpInputStream.java create mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpOutputStream.java create mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpReceiveSocket.java create mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendInputStream.java create mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendOutputStream.java create mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendSocket.java rename jdk/src/java.rmi/share/classes/sun/rmi/transport/{tcp/TCPDirectSocketFactory.java => proxy/RMIDirectSocketFactory.java} (94%) create mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIHttpToCGISocketFactory.java create mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIHttpToPortSocketFactory.java create mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIMasterSocketFactory.java create mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMISocketInfo.java create mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/WrappedSocket.java create mode 100644 jdk/test/java/rmi/transport/httpSocket/HttpSocketTest.java create mode 100644 jdk/test/java/rmi/transport/httpSocket/HttpSocketTest_Stub.java create mode 100644 jdk/test/java/rmi/transport/httpSocket/security.policy create mode 100644 jdk/test/sun/rmi/transport/proxy/DisableHttpDefaultValue.java create mode 100644 jdk/test/sun/rmi/transport/proxy/EagerHttpFallback.java create mode 100644 jdk/test/sun/rmi/transport/tcp/blockAccept/BlockAcceptTest.java create mode 100644 jdk/test/sun/rmi/transport/tcp/blockAccept/TestIface.java create mode 100644 jdk/test/sun/rmi/transport/tcp/blockAccept/TestImpl.java create mode 100644 jdk/test/sun/rmi/transport/tcp/blockAccept/TestImpl_Stub.java create mode 100644 jdk/test/sun/rmi/transport/tcp/blockAccept/security.policy diff --git a/jdk/src/java.rmi/share/classes/java/rmi/server/RMISocketFactory.java b/jdk/src/java.rmi/share/classes/java/rmi/server/RMISocketFactory.java index df3bc9fd24a..e69c269f81a 100644 --- a/jdk/src/java.rmi/share/classes/java/rmi/server/RMISocketFactory.java +++ b/jdk/src/java.rmi/share/classes/java/rmi/server/RMISocketFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2013, 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 @@ -35,8 +35,21 @@ import java.net.*; * request that the RMI runtime use its socket factory instance * instead of the default implementation. * - *

The default socket factory implementation creates a direct - * socket connection to the remote host. + *

The default socket factory implementation performs a + * three-tiered approach to creating client sockets. First, a direct + * socket connection to the remote VM is attempted. If that fails + * (due to a firewall), the runtime uses HTTP with the explicit port + * number of the server. If the firewall does not allow this type of + * communication, then HTTP to a cgi-bin script on the server is used + * to POST the RMI call. The HTTP tunneling mechanisms are disabled by + * default. This behavior is controlled by the {@code java.rmi.server.disableHttp} + * property, whose default value is {@code true}. Setting this property's + * value to {@code false} will enable the HTTP tunneling mechanisms. + * + *

Deprecated: HTTP Tunneling. The HTTP tunneling mechanisms + * described above, specifically HTTP with an explicit port and HTTP to a + * cgi-bin script, are deprecated. These HTTP tunneling mechanisms are + * subject to removal in a future release of the platform. * *

The default socket factory implementation creates server sockets that * are bound to the wildcard address, which accepts requests from all network @@ -168,7 +181,7 @@ public abstract class RMISocketFactory public synchronized static RMISocketFactory getDefaultSocketFactory() { if (defaultSocketFactory == null) { defaultSocketFactory = - new sun.rmi.transport.tcp.TCPDirectSocketFactory(); + new sun.rmi.transport.proxy.RMIMasterSocketFactory(); } return defaultSocketFactory; } diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/CGIHandler.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/CGIHandler.java new file mode 100644 index 00000000000..546ccd8ea10 --- /dev/null +++ b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/CGIHandler.java @@ -0,0 +1,423 @@ +/* + * Copyright (c) 1996, 2013, 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 sun.rmi.transport.proxy; + +import java.io.*; +import java.net.*; +import java.util.Hashtable; + +/** + * CGIClientException is thrown when an error is detected + * in a client's request. + */ +class CGIClientException extends Exception { + private static final long serialVersionUID = 8147981687059865216L; + + public CGIClientException(String s) { + super(s); + } + + public CGIClientException(String s, Throwable cause) { + super(s, cause); + } +} + +/** + * CGIServerException is thrown when an error occurs here on the server. + */ +class CGIServerException extends Exception { + + private static final long serialVersionUID = 6928425456704527017L; + + public CGIServerException(String s) { + super(s); + } + + public CGIServerException(String s, Throwable cause) { + super(s, cause); + } +} + +/** + * CGICommandHandler is the interface to an object that handles a + * particular supported command. + */ +interface CGICommandHandler { + + /** + * Return the string form of the command + * to be recognized in the query string. + */ + public String getName(); + + /** + * Execute the command with the given string as parameter. + */ + public void execute(String param) throws CGIClientException, CGIServerException; +} + +/** + * The CGIHandler class contains methods for executing as a CGI program. + * The main function interprets the query string as a command of the form + * "{@code =}". + * + * This class depends on the CGI 1.0 environment variables being set as + * properties of the same name in this Java VM. + * + * All data and methods of this class are static because they are specific + * to this particular CGI process. + */ +public final class CGIHandler { + + /* get CGI parameters that we need */ + static int ContentLength; + static String QueryString; + static String RequestMethod; + static String ServerName; + static int ServerPort; + + static { + java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Void run() { + ContentLength = + Integer.getInteger("CONTENT_LENGTH", 0).intValue(); + QueryString = System.getProperty("QUERY_STRING", ""); + RequestMethod = System.getProperty("REQUEST_METHOD", ""); + ServerName = System.getProperty("SERVER_NAME", ""); + ServerPort = Integer.getInteger("SERVER_PORT", 0).intValue(); + return null; + } + }); + } + + /* list of handlers for supported commands */ + private static CGICommandHandler commands[] = { + new CGIForwardCommand(), + new CGIGethostnameCommand(), + new CGIPingCommand(), + new CGITryHostnameCommand() + }; + + /* construct table mapping command strings to handlers */ + private static Hashtable commandLookup; + static { + commandLookup = new Hashtable<>(); + for (int i = 0; i < commands.length; ++ i) + commandLookup.put(commands[i].getName(), commands[i]); + } + + /* prevent instantiation of this class */ + private CGIHandler() {} + + /** + * Execute command given in query string on URL. The string before + * the first '=' is interpreted as the command name, and the string + * after the first '=' is the parameters to the command. + */ + public static void main(String args[]) + { + try { + String command, param; + int delim = QueryString.indexOf('='); + if (delim == -1) { + command = QueryString; + param = ""; + } + else { + command = QueryString.substring(0, delim); + param = QueryString.substring(delim + 1); + } + CGICommandHandler handler = + commandLookup.get(command); + if (handler != null) + try { + handler.execute(param); + } catch (CGIClientException e) { + e.printStackTrace(); + returnClientError(e.getMessage()); + } catch (CGIServerException e) { + e.printStackTrace(); + returnServerError(e.getMessage()); + } + else + returnClientError("invalid command."); + } catch (Exception e) { + e.printStackTrace(); + returnServerError("internal error: " + e.getMessage()); + } + System.exit(0); + } + + /** + * Return an HTML error message indicating there was error in + * the client's request. + */ + private static void returnClientError(String message) + { + System.out.println("Status: 400 Bad Request: " + message); + System.out.println("Content-type: text/html"); + System.out.println(""); + System.out.println("" + + "Java RMI Client Error" + + "" + + ""); + System.out.println("

Java RMI Client Error

"); + System.out.println(""); + System.out.println(message); + System.out.println(""); + System.exit(1); + } + + /** + * Return an HTML error message indicating an error occurred + * here on the server. + */ + private static void returnServerError(String message) + { + System.out.println("Status: 500 Server Error: " + message); + System.out.println("Content-type: text/html"); + System.out.println(""); + System.out.println("" + + "Java RMI Server Error" + + "" + + ""); + System.out.println("

Java RMI Server Error

"); + System.out.println(""); + System.out.println(message); + System.out.println(""); + System.exit(1); + } +} + +/** + * "forward" command: Forward request body to local port on the server, + * and send response back to client. + */ +final class CGIForwardCommand implements CGICommandHandler { + + public String getName() { + return "forward"; + } + + @SuppressWarnings("deprecation") + private String getLine (DataInputStream socketIn) throws IOException { + return socketIn.readLine(); + } + + public void execute(String param) throws CGIClientException, CGIServerException + { + if (!CGIHandler.RequestMethod.equals("POST")) + throw new CGIClientException("can only forward POST requests"); + + int port; + try { + port = Integer.parseInt(param); + } catch (NumberFormatException e) { + throw new CGIClientException("invalid port number.", e); + } + if (port <= 0 || port > 0xFFFF) + throw new CGIClientException("invalid port: " + port); + if (port < 1024) + throw new CGIClientException("permission denied for port: " + + port); + + byte buffer[]; + Socket socket; + try { + socket = new Socket(InetAddress.getLocalHost(), port); + } catch (IOException e) { + throw new CGIServerException("could not connect to local port", e); + } + + /* + * read client's request body + */ + DataInputStream clientIn = new DataInputStream(System.in); + buffer = new byte[CGIHandler.ContentLength]; + try { + clientIn.readFully(buffer); + } catch (EOFException e) { + throw new CGIClientException("unexpected EOF reading request body", e); + } catch (IOException e) { + throw new CGIClientException("error reading request body", e); + } + + /* + * send to local server in HTTP + */ + try { + DataOutputStream socketOut = + new DataOutputStream(socket.getOutputStream()); + socketOut.writeBytes("POST / HTTP/1.0\r\n"); + socketOut.writeBytes("Content-length: " + + CGIHandler.ContentLength + "\r\n\r\n"); + socketOut.write(buffer); + socketOut.flush(); + } catch (IOException e) { + throw new CGIServerException("error writing to server", e); + } + + /* + * read response + */ + DataInputStream socketIn; + try { + socketIn = new DataInputStream(socket.getInputStream()); + } catch (IOException e) { + throw new CGIServerException("error reading from server", e); + } + String key = "Content-length:".toLowerCase(); + boolean contentLengthFound = false; + String line; + int responseContentLength = -1; + do { + try { + line = getLine(socketIn); + } catch (IOException e) { + throw new CGIServerException("error reading from server", e); + } + if (line == null) + throw new CGIServerException( + "unexpected EOF reading server response"); + + if (line.toLowerCase().startsWith(key)) { + if (contentLengthFound) { + throw new CGIServerException( + "Multiple Content-length entries found."); + } else { + responseContentLength = + Integer.parseInt(line.substring(key.length()).trim()); + contentLengthFound = true; + } + } + } while ((line.length() != 0) && + (line.charAt(0) != '\r') && (line.charAt(0) != '\n')); + + if (!contentLengthFound || responseContentLength < 0) + throw new CGIServerException( + "missing or invalid content length in server response"); + buffer = new byte[responseContentLength]; + try { + socketIn.readFully(buffer); + } catch (EOFException e) { + throw new CGIServerException( + "unexpected EOF reading server response", e); + } catch (IOException e) { + throw new CGIServerException("error reading from server", e); + } + + /* + * send response back to client + */ + System.out.println("Status: 200 OK"); + System.out.println("Content-type: application/octet-stream"); + System.out.println(""); + try { + System.out.write(buffer); + } catch (IOException e) { + throw new CGIServerException("error writing response", e); + } + System.out.flush(); + } +} + +/** + * "gethostname" command: Return the host name of the server as the + * response body + */ +final class CGIGethostnameCommand implements CGICommandHandler { + + public String getName() { + return "gethostname"; + } + + public void execute(String param) + { + System.out.println("Status: 200 OK"); + System.out.println("Content-type: application/octet-stream"); + System.out.println("Content-length: " + + CGIHandler.ServerName.length()); + System.out.println(""); + System.out.print(CGIHandler.ServerName); + System.out.flush(); + } +} + +/** + * "ping" command: Return an OK status to indicate that connection + * was successful. + */ +final class CGIPingCommand implements CGICommandHandler { + + public String getName() { + return "ping"; + } + + public void execute(String param) + { + System.out.println("Status: 200 OK"); + System.out.println("Content-type: application/octet-stream"); + System.out.println("Content-length: 0"); + System.out.println(""); + } +} + +/** + * "tryhostname" command: Return a human readable message describing + * what host name is available to local Java VMs. + */ +final class CGITryHostnameCommand implements CGICommandHandler { + + public String getName() { + return "tryhostname"; + } + + public void execute(String param) + { + System.out.println("Status: 200 OK"); + System.out.println("Content-type: text/html"); + System.out.println(""); + System.out.println("" + + "Java RMI Server Hostname Info" + + "" + + ""); + System.out.println("

Java RMI Server Hostname Info

"); + System.out.println("

Local host name available to Java VM:

"); + System.out.print("

InetAddress.getLocalHost().getHostName()"); + try { + String localHostName = InetAddress.getLocalHost().getHostName(); + + System.out.println(" = " + localHostName); + } catch (UnknownHostException e) { + System.out.println(" threw java.net.UnknownHostException"); + } + + System.out.println("

Server host information obtained through CGI interface from HTTP server:

"); + System.out.println("

SERVER_NAME = " + CGIHandler.ServerName); + System.out.println("

SERVER_PORT = " + CGIHandler.ServerPort); + System.out.println(""); + } +} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpAwareServerSocket.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpAwareServerSocket.java new file mode 100644 index 00000000000..b4512fecd93 --- /dev/null +++ b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpAwareServerSocket.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 1996, 2005, 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 sun.rmi.transport.proxy; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.net.ServerSocket; +import java.net.Socket; +import sun.rmi.runtime.Log; + +/** + * The HttpAwareServerSocket class extends the java.net.ServerSocket + * class. It behaves like a ServerSocket, except that if + * the first four bytes of an accepted socket are the letters "POST", + * then it returns an HttpReceiveSocket instead of a java.net.Socket. + * This means that the accept method blocks until four bytes have been + * read from the new socket's input stream. + */ +class HttpAwareServerSocket extends ServerSocket { + + /** + * Create a server socket on a specified port. + * @param port the port + * @exception IOException IO error when opening the socket. + */ + public HttpAwareServerSocket(int port) throws IOException + { + super(port); + } + + /** + * Create a server socket, bind it to the specified local port + * and listen to it. You can connect to an annonymous port by + * specifying the port number to be 0. backlog specifies + * how many connection requests the system will queue up while waiting + * for the ServerSocket to execute accept(). + * @param port the specified port + * @param backlog the number of queued connect requests pending accept + */ + public HttpAwareServerSocket(int port, int backlog) throws IOException + { + super(port, backlog); + } + + /** + * Accept a connection. This method will block until the connection + * is made and four bytes can be read from the input stream. + * If the first four bytes are "POST", then an HttpReceiveSocket is + * returned, which will handle the HTTP protocol wrapping. + * Otherwise, a WrappedSocket is returned. The input stream will be + * reset to the beginning of the transmission. + * In either case, a BufferedInputStream will already be on top of + * the underlying socket's input stream. + * @exception IOException IO error when waiting for the connection. + */ + public Socket accept() throws IOException + { + Socket socket = super.accept(); + BufferedInputStream in = + new BufferedInputStream(socket.getInputStream()); + + RMIMasterSocketFactory.proxyLog.log(Log.BRIEF, + "socket accepted (checking for POST)"); + + in.mark(4); + boolean isHttp = (in.read() == 'P') && + (in.read() == 'O') && + (in.read() == 'S') && + (in.read() == 'T'); + in.reset(); + + if (RMIMasterSocketFactory.proxyLog.isLoggable(Log.BRIEF)) { + RMIMasterSocketFactory.proxyLog.log(Log.BRIEF, + (isHttp ? "POST found, HTTP socket returned" : + "POST not found, direct socket returned")); + } + + if (isHttp) + return new HttpReceiveSocket(socket, in, null); + else + return new WrappedSocket(socket, in, null); + } + + /** + * Return the implementation address and implementation port of + * the HttpAwareServerSocket as a String. + */ + public String toString() + { + return "HttpAware" + super.toString(); + } +} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpInputStream.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpInputStream.java new file mode 100644 index 00000000000..4b5cad95044 --- /dev/null +++ b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpInputStream.java @@ -0,0 +1,205 @@ +/* + * Copyright (c) 1996, 2014, 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 sun.rmi.transport.proxy; + +import java.io.*; + +import sun.rmi.runtime.Log; + +/** + * The HttpInputStream class assists the HttpSendSocket and HttpReceiveSocket + * classes by filtering out the header for the message as well as any + * data after its proper content length. + */ +class HttpInputStream extends FilterInputStream { + + /** bytes remaining to be read from proper content of message */ + protected int bytesLeft; + + /** bytes remaining to be read at time of last mark */ + protected int bytesLeftAtMark; + + /** + * Create new filter on a given input stream. + * @param in the InputStream to filter from + */ + @SuppressWarnings("deprecation") + public HttpInputStream(InputStream in) throws IOException + { + super(in); + + if (in.markSupported()) + in.mark(0); // prevent resetting back to old marks + + // pull out header, looking for content length + + DataInputStream dis = new DataInputStream(in); + String key = "Content-length:".toLowerCase(); + boolean contentLengthFound = false; + String line; + do { + line = dis.readLine(); + + if (RMIMasterSocketFactory.proxyLog.isLoggable(Log.VERBOSE)) { + RMIMasterSocketFactory.proxyLog.log(Log.VERBOSE, + "received header line: \"" + line + "\""); + } + + if (line == null) + throw new EOFException(); + + if (line.toLowerCase().startsWith(key)) { + if (contentLengthFound) { + throw new IOException( + "Multiple Content-length entries found."); + } else { + bytesLeft = + Integer.parseInt(line.substring(key.length()).trim()); + contentLengthFound = true; + } + } + + // The idea here is to go past the first blank line. + // Some DataInputStream.readLine() documentation specifies that + // it does include the line-terminating character(s) in the + // returned string, but it actually doesn't, so we'll cover + // all cases here... + } while ((line.length() != 0) && + (line.charAt(0) != '\r') && (line.charAt(0) != '\n')); + + if (!contentLengthFound || bytesLeft < 0) { + // This really shouldn't happen, but if it does, shoud we fail?? + // For now, just give up and let a whole lot of bytes through... + bytesLeft = Integer.MAX_VALUE; + } + bytesLeftAtMark = bytesLeft; + + if (RMIMasterSocketFactory.proxyLog.isLoggable(Log.VERBOSE)) { + RMIMasterSocketFactory.proxyLog.log(Log.VERBOSE, + "content length: " + bytesLeft); + } + } + + /** + * Returns the number of bytes that can be read with blocking. + * Make sure that this does not exceed the number of bytes remaining + * in the proper content of the message. + */ + public int available() throws IOException + { + int bytesAvailable = in.available(); + if (bytesAvailable > bytesLeft) + bytesAvailable = bytesLeft; + + return bytesAvailable; + } + + /** + * Read a byte of data from the stream. Make sure that one is available + * from the proper content of the message, else -1 is returned to + * indicate to the user that the end of the stream has been reached. + */ + public int read() throws IOException + { + if (bytesLeft > 0) { + int data = in.read(); + if (data != -1) + -- bytesLeft; + + if (RMIMasterSocketFactory.proxyLog.isLoggable(Log.VERBOSE)) { + RMIMasterSocketFactory.proxyLog.log(Log.VERBOSE, + "received byte: '" + + ((data & 0x7F) < ' ' ? " " : String.valueOf((char) data)) + + "' " + data); + } + + return data; + } + else { + RMIMasterSocketFactory.proxyLog.log(Log.VERBOSE, + "read past content length"); + + return -1; + } + } + + public int read(byte b[], int off, int len) throws IOException + { + if (bytesLeft == 0 && len > 0) { + RMIMasterSocketFactory.proxyLog.log(Log.VERBOSE, + "read past content length"); + + return -1; + } + if (len > bytesLeft) + len = bytesLeft; + int bytesRead = in.read(b, off, len); + bytesLeft -= bytesRead; + + if (RMIMasterSocketFactory.proxyLog.isLoggable(Log.VERBOSE)) { + RMIMasterSocketFactory.proxyLog.log(Log.VERBOSE, + "read " + bytesRead + " bytes, " + bytesLeft + " remaining"); + } + + return bytesRead; + } + + /** + * Mark the current position in the stream (for future calls to reset). + * Remember where we are within the proper content of the message, so + * that a reset method call can recreate our state properly. + * @param readlimit how many bytes can be read before mark becomes invalid + */ + public void mark(int readlimit) + { + in.mark(readlimit); + if (in.markSupported()) + bytesLeftAtMark = bytesLeft; + } + + /** + * Repositions the stream to the last marked position. Make sure to + * adjust our position within the proper content accordingly. + */ + public void reset() throws IOException + { + in.reset(); + bytesLeft = bytesLeftAtMark; + } + + /** + * Skips bytes of the stream. Make sure to adjust our + * position within the proper content accordingly. + * @param n number of bytes to be skipped + */ + public long skip(long n) throws IOException + { + if (n > bytesLeft) + n = bytesLeft; + long bytesSkipped = in.skip(n); + bytesLeft -= bytesSkipped; + return bytesSkipped; + } +} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpOutputStream.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpOutputStream.java new file mode 100644 index 00000000000..5f1f2a6a680 --- /dev/null +++ b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpOutputStream.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 1996, 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 sun.rmi.transport.proxy; + +import java.io.*; + +/** + * The HttpOutputStream class assists the HttpSendSocket and HttpReceiveSocket + * classes by providing an output stream that buffers its entire input until + * closed, and then it sends the complete transmission prefixed by the end of + * an HTTP header that specifies the content length. + */ +class HttpOutputStream extends ByteArrayOutputStream { + + /** the output stream to send response to */ + protected OutputStream out; + + /** true if HTTP response has been sent */ + boolean responseSent = false; + + /** + * Begin buffering new HTTP response to be sent to a given stream. + * @param out the OutputStream to send response to + */ + public HttpOutputStream(OutputStream out) { + super(); + this.out = out; + } + + /** + * On close, send HTTP-packaged response. + */ + public synchronized void close() throws IOException { + if (!responseSent) { + /* + * If response would have zero content length, then make it + * have some arbitrary data so that certain clients will not + * fail because the "document contains no data". + */ + if (size() == 0) + write(emptyData); + + DataOutputStream dos = new DataOutputStream(out); + dos.writeBytes("Content-type: application/octet-stream\r\n"); + dos.writeBytes("Content-length: " + size() + "\r\n"); + dos.writeBytes("\r\n"); + writeTo(dos); + dos.flush(); + // Do not close the underlying stream here, because that would + // close the underlying socket and prevent reading a response. + reset(); // reset byte array + responseSent = true; + } + } + + /** data to send if the response would otherwise be empty */ + private static byte[] emptyData = { 0 }; +} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpReceiveSocket.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpReceiveSocket.java new file mode 100644 index 00000000000..c916254ffcd --- /dev/null +++ b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpReceiveSocket.java @@ -0,0 +1,128 @@ +/* + * Copyright (c) 1996, 2000, 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 sun.rmi.transport.proxy; + +import java.io.*; +import java.net.Socket; +import java.net.InetAddress; + +/** + * The HttpReceiveSocket class extends the WrappedSocket class + * by removing the HTTP protocol packaging from the input stream and + * formatting the output stream as an HTTP response. + * + * NOTES: + * + * The output stream must be explicitly closed for the output to be + * sent, since the HttpResponseOutputStream needs to buffer the entire + * transmission to be able to fill in the content-length field of + * the HTTP header. Closing this socket will do this. + * + * The constructor blocks until the HTTP protocol header + * is received. This could be fixed, but I don't think it should be a + * problem because this object would not be created unless the + * HttpAwareServerSocket has detected the beginning of the header + * anyway, so the rest should be there. + * + * This socket can only be used to process one POST and reply to it. + * Another message would be received on a newly accepted socket anyway. + */ +public class HttpReceiveSocket extends WrappedSocket implements RMISocketInfo { + + /** true if the HTTP header has pushed through the output stream yet */ + private boolean headerSent = false; + + /** + * Layer on top of a pre-existing Socket object, and use specified + * input and output streams. + * @param socket the pre-existing socket to use + * @param in the InputStream to use for this socket (can be null) + * @param out the OutputStream to use for this socket (can be null) + */ + public HttpReceiveSocket(Socket socket, InputStream in, OutputStream out) + throws IOException + { + super(socket, in, out); + + this.in = new HttpInputStream(in != null ? in : + socket.getInputStream()); + this.out = (out != null ? out : + socket.getOutputStream()); + } + + /** + * Indicate that this socket is not reusable. + */ + public boolean isReusable() + { + return false; + } + + /** + * Get the address to which this socket is connected. "null" is always + * returned (to indicate an unknown address) because the originating + * host's IP address cannot be reliably determined: both because the + * request probably went through a proxy server, and because if it was + * delivered by a local forwarder (CGI script or servlet), we do NOT + * want it to appear as if the call is coming from the local host (in + * case the remote object makes access control decisions based on the + * "client host" of a remote call; see bugid 4399040). + */ + public InetAddress getInetAddress() { + return null; + } + + /** + * Get an OutputStream for this socket. + */ + public OutputStream getOutputStream() throws IOException + { + if (!headerSent) { // could this be done in constructor?? + DataOutputStream dos = new DataOutputStream(out); + dos.writeBytes("HTTP/1.0 200 OK\r\n"); + dos.flush(); + headerSent = true; + out = new HttpOutputStream(out); + } + return out; + } + + /** + * Close the socket. + */ + public synchronized void close() throws IOException + { + getOutputStream().close(); // make sure response is sent + socket.close(); + } + + /** + * Return string representation of the socket. + */ + public String toString() + { + return "HttpReceive" + socket.toString(); + } +} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendInputStream.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendInputStream.java new file mode 100644 index 00000000000..0c6de28c266 --- /dev/null +++ b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendInputStream.java @@ -0,0 +1,161 @@ +/* + * Copyright (c) 1996, 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 sun.rmi.transport.proxy; + +import java.io.*; + +/** + * The HttpSendInputStream class is used by the HttpSendSocket class as + * a layer on the top of the InputStream it returns so that it can be + * notified of attempts to read from it. This allows the HttpSendSocket + * to know when it should push across its output message. + */ +class HttpSendInputStream extends FilterInputStream { + + /** the HttpSendSocket object that is providing this stream */ + HttpSendSocket owner; + + /** + * Create new filter on a given input stream. + * @param in the InputStream to filter from + * @param owner the HttpSendSocket that is providing this stream + */ + public HttpSendInputStream(InputStream in, HttpSendSocket owner) + throws IOException + { + super(in); + + this.owner = owner; + } + + /** + * Mark this stream as inactive for its owner socket, so the next time + * a read is attempted, the owner will be notified and a new underlying + * input stream obtained. + */ + public void deactivate() + { + in = null; + } + + /** + * Read a byte of data from the stream. + */ + public int read() throws IOException + { + if (in == null) + in = owner.readNotify(); + return in.read(); + } + + /** + * Read into an array of bytes. + * @param b the buffer into which the data is to be read + * @param off the start offset of the data + * @param len the maximum number of bytes to read + */ + public int read(byte b[], int off, int len) throws IOException + { + if (len == 0) + return 0; + if (in == null) + in = owner.readNotify(); + return in.read(b, off, len); + } + + /** + * Skip bytes of input. + * @param n the number of bytes to be skipped + */ + public long skip(long n) throws IOException + { + if (n == 0) + return 0; + if (in == null) + in = owner.readNotify(); + return in.skip(n); + } + + /** + * Return the number of bytes that can be read without blocking. + */ + public int available() throws IOException + { + if (in == null) + in = owner.readNotify(); + return in.available(); + } + + /** + * Close the stream. + */ + public void close() throws IOException + { + owner.close(); + } + + /** + * Mark the current position in the stream. + * @param readlimit how many bytes can be read before mark becomes invalid + */ + public synchronized void mark(int readlimit) + { + if (in == null) { + try { + in = owner.readNotify(); + } + catch (IOException e) { + return; + } + } + in.mark(readlimit); + } + + /** + * Reposition the stream to the last marked position. + */ + public synchronized void reset() throws IOException + { + if (in == null) + in = owner.readNotify(); + in.reset(); + } + + /** + * Return true if this stream type supports mark/reset. + */ + public boolean markSupported() + { + if (in == null) { + try { + in = owner.readNotify(); + } + catch (IOException e) { + return false; + } + } + return in.markSupported(); + } +} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendOutputStream.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendOutputStream.java new file mode 100644 index 00000000000..bc83945534f --- /dev/null +++ b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendOutputStream.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 1996, 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 sun.rmi.transport.proxy; + +import java.io.*; + +/** + * The HttpSendOutputStream class is used by the HttpSendSocket class as + * a layer on the top of the OutputStream it returns so that it can be + * notified of attempts to write to it. This allows the HttpSendSocket + * to know when it should construct a new message. + */ +class HttpSendOutputStream extends FilterOutputStream { + + /** the HttpSendSocket object that is providing this stream */ + HttpSendSocket owner; + + /** + * Create new filter on a given output stream. + * @param out the OutputStream to filter from + * @param owner the HttpSendSocket that is providing this stream + */ + public HttpSendOutputStream(OutputStream out, HttpSendSocket owner) + throws IOException + { + super(out); + + this.owner = owner; + } + + /** + * Mark this stream as inactive for its owner socket, so the next time + * a write is attempted, the owner will be notified and a new underlying + * output stream obtained. + */ + public void deactivate() + { + out = null; + } + + /** + * Write a byte of data to the stream. + */ + public void write(int b) throws IOException + { + if (out == null) + out = owner.writeNotify(); + out.write(b); + } + + /** + * Write a subarray of bytes. + * @param b the buffer from which the data is to be written + * @param off the start offset of the data + * @param len the number of bytes to be written + */ + public void write(byte b[], int off, int len) throws IOException + { + if (len == 0) + return; + if (out == null) + out = owner.writeNotify(); + out.write(b, off, len); + } + + /** + * Flush the stream. + */ + public void flush() throws IOException + { + if (out != null) + out.flush(); + } + + /** + * Close the stream. + */ + public void close() throws IOException + { + flush(); + owner.close(); + } +} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendSocket.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendSocket.java new file mode 100644 index 00000000000..a9932be35e1 --- /dev/null +++ b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendSocket.java @@ -0,0 +1,344 @@ +/* + * Copyright (c) 1996, 2012, 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 sun.rmi.transport.proxy; + +import java.io.*; +import java.net.*; +import java.security.PrivilegedAction; + +import sun.rmi.runtime.Log; + +/** + * The HttpSendSocket class extends the java.net.Socket class + * by enclosing the data output stream in, then extracting the input + * stream from, an HTTP protocol transmission. + * + * NOTES: + * + * Since the length of the output request must be known before the + * HTTP header can be completed, all of the output is buffered by + * an HttpOutputStream object until either an attempt is made to + * read from this socket, or the socket is explicitly closed. + * + * On the first read attempt to read from this socket, the buffered + * output is sent to the destination as the body of an HTTP POST + * request. All reads will then acquire data from the body of + * the response. A subsequent attempt to write to this socket will + * throw an IOException. + */ +class HttpSendSocket extends Socket implements RMISocketInfo { + + /** the host to connect to */ + protected String host; + + /** the port to connect to */ + protected int port; + + /** the URL to forward through */ + protected URL url; + + /** the object managing this connection through the URL */ + protected URLConnection conn = null; + + /** internal input stream for this socket */ + protected InputStream in = null; + + /** internal output stream for this socket */ + protected OutputStream out = null; + + /** the notifying input stream returned to users */ + protected HttpSendInputStream inNotifier; + + /** the notifying output stream returned to users */ + protected HttpSendOutputStream outNotifier; + + /** + * Line separator string. This is the value of the line.separator + * property at the moment that the socket was created. + */ + private String lineSeparator = + java.security.AccessController.doPrivileged( + (PrivilegedAction) () -> System.getProperty("line.separator")); + + /** + * Create a stream socket and connect it to the specified port on + * the specified host. + * @param host the host + * @param port the port + */ + public HttpSendSocket(String host, int port, URL url) throws IOException + { + super((SocketImpl)null); // no underlying SocketImpl for this object + + if (RMIMasterSocketFactory.proxyLog.isLoggable(Log.VERBOSE)) { + RMIMasterSocketFactory.proxyLog.log(Log.VERBOSE, + "host = " + host + ", port = " + port + ", url = " + url); + } + + this.host = host; + this.port = port; + this.url = url; + + inNotifier = new HttpSendInputStream(null, this); + outNotifier = new HttpSendOutputStream(writeNotify(), this); + } + + /** + * Create a stream socket and connect it to the specified port on + * the specified host. + * @param host the host + * @param port the port + */ + public HttpSendSocket(String host, int port) throws IOException + { + this(host, port, new URL("http", host, port, "/")); + } + + /** + * Create a stream socket and connect it to the specified address on + * the specified port. + * @param address the address + * @param port the port + */ + public HttpSendSocket(InetAddress address, int port) throws IOException + { + this(address.getHostName(), port); + } + + /** + * Indicate that this socket is not reusable. + */ + public boolean isReusable() + { + return false; + } + + /** + * Create a new socket connection to host (or proxy), and prepare to + * send HTTP transmission. + */ + public synchronized OutputStream writeNotify() throws IOException + { + if (conn != null) { + throw new IOException("attempt to write on HttpSendSocket after " + + "request has been sent"); + } + + conn = url.openConnection(); + conn.setDoOutput(true); + conn.setUseCaches(false); + conn.setRequestProperty("Content-type", "application/octet-stream"); + + inNotifier.deactivate(); + in = null; + + return out = conn.getOutputStream(); + } + + /** + * Send HTTP output transmission and prepare to receive response. + */ + public synchronized InputStream readNotify() throws IOException + { + RMIMasterSocketFactory.proxyLog.log(Log.VERBOSE, + "sending request and activating input stream"); + + outNotifier.deactivate(); + out.close(); + out = null; + + try { + in = conn.getInputStream(); + } catch (IOException e) { + RMIMasterSocketFactory.proxyLog.log(Log.BRIEF, + "failed to get input stream, exception: ", e); + + throw new IOException("HTTP request failed"); + } + + /* + * If an HTTP error response is returned, sometimes an IOException + * is thrown, which is handled above, and other times it isn't, and + * the error response body will be available for reading. + * As a safety net to catch any such unexpected HTTP behavior, we + * verify that the content type of the response is what the + * HttpOutputStream generates: "application/octet-stream". + * (Servers' error responses will generally be "text/html".) + * Any error response body is printed to the log. + */ + String contentType = conn.getContentType(); + if (contentType == null || + !conn.getContentType().equals("application/octet-stream")) + { + if (RMIMasterSocketFactory.proxyLog.isLoggable(Log.BRIEF)) { + String message; + if (contentType == null) { + message = "missing content type in response" + + lineSeparator; + } else { + message = "invalid content type in response: " + + contentType + lineSeparator; + } + + message += "HttpSendSocket.readNotify: response body: "; + try { + BufferedReader din = new BufferedReader(new InputStreamReader(in)); + String line; + while ((line = din.readLine()) != null) + message += line + lineSeparator; + } catch (IOException e) { + } + RMIMasterSocketFactory.proxyLog.log(Log.BRIEF, message); + } + + throw new IOException("HTTP request failed"); + } + + return in; + } + + /** + * Get the address to which the socket is connected. + */ + public InetAddress getInetAddress() + { + try { + return InetAddress.getByName(host); + } catch (UnknownHostException e) { + return null; // null if couldn't resolve destination host + } + } + + /** + * Get the local address to which the socket is bound. + */ + public InetAddress getLocalAddress() + { + try { + return InetAddress.getLocalHost(); + } catch (UnknownHostException e) { + return null; // null if couldn't determine local host + } + } + + /** + * Get the remote port to which the socket is connected. + */ + public int getPort() + { + return port; + } + + /** + * Get the local port to which the socket is connected. + */ + public int getLocalPort() + { + return -1; // request not applicable to this socket type + } + + /** + * Get an InputStream for this socket. + */ + public InputStream getInputStream() throws IOException + { + return inNotifier; + } + + /** + * Get an OutputStream for this socket. + */ + public OutputStream getOutputStream() throws IOException + { + return outNotifier; + } + + /** + * Enable/disable TCP_NODELAY. + * This operation has no effect for an HttpSendSocket. + */ + public void setTcpNoDelay(boolean on) throws SocketException + { + } + + /** + * Retrieve whether TCP_NODELAY is enabled. + */ + public boolean getTcpNoDelay() throws SocketException + { + return false; // imply option is disabled + } + + /** + * Enable/disable SO_LINGER with the specified linger time. + * This operation has no effect for an HttpSendSocket. + */ + public void setSoLinger(boolean on, int val) throws SocketException + { + } + + /** + * Retrive setting for SO_LINGER. + */ + public int getSoLinger() throws SocketException + { + return -1; // imply option is disabled + } + + /** + * Enable/disable SO_TIMEOUT with the specified timeout + * This operation has no effect for an HttpSendSocket. + */ + public synchronized void setSoTimeout(int timeout) throws SocketException + { + } + + /** + * Retrive setting for SO_TIMEOUT. + */ + public synchronized int getSoTimeout() throws SocketException + { + return 0; // imply option is disabled + } + + /** + * Close the socket. + */ + public synchronized void close() throws IOException + { + if (out != null) // push out transmission if not done + out.close(); + } + + /** + * Return string representation of this pseudo-socket. + */ + public String toString() + { + return "HttpSendSocket[host=" + host + + ",port=" + port + + ",url=" + url + "]"; + } +} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPDirectSocketFactory.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIDirectSocketFactory.java similarity index 94% rename from jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPDirectSocketFactory.java rename to jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIDirectSocketFactory.java index 8274742ec1b..953d47ca400 100644 --- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPDirectSocketFactory.java +++ b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIDirectSocketFactory.java @@ -22,7 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package sun.rmi.transport.tcp; +package sun.rmi.transport.proxy; import java.io.IOException; import java.net.Socket; @@ -33,7 +33,7 @@ import java.rmi.server.RMISocketFactory; * RMIDirectSocketFactory creates a direct socket connection to the * specified port on the specified host. */ -public class TCPDirectSocketFactory extends RMISocketFactory { +public class RMIDirectSocketFactory extends RMISocketFactory { public Socket createSocket(String host, int port) throws IOException { diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIHttpToCGISocketFactory.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIHttpToCGISocketFactory.java new file mode 100644 index 00000000000..548f584ae11 --- /dev/null +++ b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIHttpToCGISocketFactory.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 1998, 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 sun.rmi.transport.proxy; + +import java.io.IOException; +import java.net.Socket; +import java.net.ServerSocket; +import java.net.URL; +import java.rmi.server.RMISocketFactory; + +/** + * RMIHttpToCGISocketFactory creates a socket connection to the + * specified host that is comminicated within an HTTP request, + * forwarded through the default firewall proxy, to the target host's + * normal HTTP server, to a CGI program which forwards the request to + * the actual specified port on the socket. + */ +public class RMIHttpToCGISocketFactory extends RMISocketFactory { + + public Socket createSocket(String host, int port) + throws IOException + { + return new HttpSendSocket(host, port, + new URL("http", host, + "/cgi-bin/java-rmi.cgi" + + "?forward=" + port)); + } + + public ServerSocket createServerSocket(int port) throws IOException + { + return new HttpAwareServerSocket(port); + } +} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIHttpToPortSocketFactory.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIHttpToPortSocketFactory.java new file mode 100644 index 00000000000..c23df420e44 --- /dev/null +++ b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIHttpToPortSocketFactory.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 1998, 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 sun.rmi.transport.proxy; + +import java.io.IOException; +import java.net.Socket; +import java.net.ServerSocket; +import java.net.URL; +import java.rmi.server.RMISocketFactory; + +/** + * RMIHttpToPortSocketFactory creates a socket connection to the + * specified host that is communicated within an HTTP request, + * forwarded through the default firewall proxy, directly to the + * specified port. + */ +public class RMIHttpToPortSocketFactory extends RMISocketFactory { + + public Socket createSocket(String host, int port) + throws IOException + { + return new HttpSendSocket(host, port, + new URL("http", host, port, "/")); + } + + public ServerSocket createServerSocket(int port) + throws IOException + { + return new HttpAwareServerSocket(port); + } +} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIMasterSocketFactory.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIMasterSocketFactory.java new file mode 100644 index 00000000000..8cb7cc4185f --- /dev/null +++ b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIMasterSocketFactory.java @@ -0,0 +1,468 @@ +/* + * Copyright (c) 1996, 2013, 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 sun.rmi.transport.proxy; + +import java.io.*; +import java.net.*; +import java.security.*; +import java.util.*; +import java.rmi.server.LogStream; +import java.rmi.server.RMISocketFactory; +import sun.rmi.runtime.Log; +import sun.rmi.runtime.NewThreadAction; + +/** + * RMIMasterSocketFactory attempts to create a socket connection to the + * specified host using successively less efficient mechanisms + * until one succeeds. If the host is successfully connected to, + * the factory for the successful mechanism is stored in an internal + * hash table keyed by the host name, so that future attempts to + * connect to the same host will automatically use the same + * mechanism. + */ +@SuppressWarnings("deprecation") +public class RMIMasterSocketFactory extends RMISocketFactory { + + /** "proxy" package log level */ + static int logLevel = LogStream.parseLevel(getLogLevel()); + + private static String getLogLevel() { + return java.security.AccessController.doPrivileged( + (PrivilegedAction) () -> System.getProperty("sun.rmi.transport.proxy.logLevel")); + } + + /* proxy package log */ + static final Log proxyLog = + Log.getLog("sun.rmi.transport.tcp.proxy", + "transport", RMIMasterSocketFactory.logLevel); + + /** timeout for attemping direct socket connections */ + private static long connectTimeout = getConnectTimeout(); + + private static long getConnectTimeout() { + return java.security.AccessController.doPrivileged((PrivilegedAction) () -> + Long.getLong("sun.rmi.transport.proxy.connectTimeout", 15000)); // default: 15 seconds + } + + /** whether to fallback to HTTP on general connect failures */ + private static final boolean eagerHttpFallback = + java.security.AccessController.doPrivileged((PrivilegedAction) () -> + Boolean.getBoolean("sun.rmi.transport.proxy.eagerHttpFallback")); + + /** table of hosts successfully connected to and the factory used */ + private Hashtable successTable = + new Hashtable<>(); + + /** maximum number of hosts to remember successful connection to */ + private static final int MaxRememberedHosts = 64; + + /** list of the hosts in successTable in initial connection order */ + private Vector hostList = new Vector<>(MaxRememberedHosts); + + /** default factory for initial use for direct socket connection */ + protected RMISocketFactory initialFactory = new RMIDirectSocketFactory(); + + /** ordered list of factories to try as alternate connection + * mechanisms if a direct socket connections fails */ + protected Vector altFactoryList; + + /** + * Create a RMIMasterSocketFactory object. Establish order of + * connection mechanisms to attempt on createSocket, if a direct + * socket connection fails. + */ + public RMIMasterSocketFactory() { + altFactoryList = new Vector<>(2); + boolean setFactories = false; + + try { + String proxyHost; + proxyHost = java.security.AccessController.doPrivileged( + (PrivilegedAction) () -> System.getProperty("http.proxyHost")); + + if (proxyHost == null) + proxyHost = java.security.AccessController.doPrivileged( + (PrivilegedAction) () -> System.getProperty("proxyHost")); + + boolean disable = java.security.AccessController.doPrivileged( + (PrivilegedAction) () -> System.getProperty("java.rmi.server.disableHttp", "true")) + .equalsIgnoreCase("true"); + + if (!disable && proxyHost != null && proxyHost.length() > 0) { + setFactories = true; + } + } catch (Exception e) { + // unable to obtain the properties, so use the default behavior. + } + + if (setFactories) { + altFactoryList.addElement(new RMIHttpToPortSocketFactory()); + altFactoryList.addElement(new RMIHttpToCGISocketFactory()); + } + } + + /** + * Create a new client socket. If we remember connecting to this host + * successfully before, then use the same factory again. Otherwise, + * try using a direct socket connection and then the alternate factories + * in the order specified in altFactoryList. + */ + public Socket createSocket(String host, int port) + throws IOException + { + if (proxyLog.isLoggable(Log.BRIEF)) { + proxyLog.log(Log.BRIEF, "host: " + host + ", port: " + port); + } + + /* + * If we don't have any alternate factories to consult, short circuit + * the fallback procedure and delegate to the initial factory. + */ + if (altFactoryList.size() == 0) { + return initialFactory.createSocket(host, port); + } + + RMISocketFactory factory; + + /* + * If we remember successfully connecting to this host before, + * use the same factory. + */ + factory = successTable.get(host); + if (factory != null) { + if (proxyLog.isLoggable(Log.BRIEF)) { + proxyLog.log(Log.BRIEF, + "previously successful factory found: " + factory); + } + return factory.createSocket(host, port); + } + + /* + * Next, try a direct socket connection. Open socket in another + * thread and only wait for specified timeout, in case the socket + * would otherwise spend minutes trying an unreachable host. + */ + Socket initialSocket = null; + Socket fallbackSocket = null; + final AsyncConnector connector = + new AsyncConnector(initialFactory, host, port, + AccessController.getContext()); + // connection must be attempted with + // this thread's access control context + IOException initialFailure = null; + + try { + synchronized (connector) { + + Thread t = java.security.AccessController.doPrivileged( + new NewThreadAction(connector, "AsyncConnector", true)); + t.start(); + + try { + long now = System.currentTimeMillis(); + long deadline = now + connectTimeout; + do { + connector.wait(deadline - now); + initialSocket = checkConnector(connector); + if (initialSocket != null) + break; + now = System.currentTimeMillis(); + } while (now < deadline); + } catch (InterruptedException e) { + throw new InterruptedIOException( + "interrupted while waiting for connector"); + } + } + + // assume no route to host (for now) if no connection yet + if (initialSocket == null) + throw new NoRouteToHostException( + "connect timed out: " + host); + + proxyLog.log(Log.BRIEF, "direct socket connection successful"); + + return initialSocket; + + } catch (UnknownHostException | NoRouteToHostException e) { + initialFailure = e; + } catch (SocketException e) { + if (eagerHttpFallback) { + initialFailure = e; + } else { + throw e; + } + } finally { + if (initialFailure != null) { + + if (proxyLog.isLoggable(Log.BRIEF)) { + proxyLog.log(Log.BRIEF, + "direct socket connection failed: ", initialFailure); + } + + // Finally, try any alternate connection mechanisms. + for (int i = 0; i < altFactoryList.size(); ++ i) { + factory = altFactoryList.elementAt(i); + if (proxyLog.isLoggable(Log.BRIEF)) { + proxyLog.log(Log.BRIEF, + "trying with factory: " + factory); + } + try (Socket testSocket = + factory.createSocket(host, port)) { + // For HTTP connections, the output (POST request) must + // be sent before we verify a successful connection. + // So, sacrifice a socket for the sake of testing... + // The following sequence should verify a successful + // HTTP connection if no IOException is thrown. + InputStream in = testSocket.getInputStream(); + int b = in.read(); // probably -1 for EOF... + } catch (IOException ex) { + if (proxyLog.isLoggable(Log.BRIEF)) { + proxyLog.log(Log.BRIEF, "factory failed: ", ex); + } + + continue; + } + proxyLog.log(Log.BRIEF, "factory succeeded"); + + // factory succeeded, open new socket for caller's use + try { + fallbackSocket = factory.createSocket(host, port); + } catch (IOException ex) { // if it fails 2nd time, + } // just give up + break; + } + } + } + + synchronized (successTable) { + try { + // check once again to see if direct connection succeeded + synchronized (connector) { + initialSocket = checkConnector(connector); + } + if (initialSocket != null) { + // if we had made another one as well, clean it up... + if (fallbackSocket != null) + fallbackSocket.close(); + return initialSocket; + } + // if connector ever does get socket, it won't be used + connector.notUsed(); + } catch (UnknownHostException | NoRouteToHostException e) { + initialFailure = e; + } catch (SocketException e) { + if (eagerHttpFallback) { + initialFailure = e; + } else { + throw e; + } + } + // if we had found an alternate mechanism, go and use it + if (fallbackSocket != null) { + // remember this successful host/factory pair + rememberFactory(host, factory); + return fallbackSocket; + } + throw initialFailure; + } + } + + /** + * Remember a successful factory for connecting to host. + * Currently, excess hosts are removed from the remembered list + * using a Least Recently Created strategy. + */ + void rememberFactory(String host, RMISocketFactory factory) { + synchronized (successTable) { + while (hostList.size() >= MaxRememberedHosts) { + successTable.remove(hostList.elementAt(0)); + hostList.removeElementAt(0); + } + hostList.addElement(host); + successTable.put(host, factory); + } + } + + /** + * Check if an AsyncConnector succeeded. If not, return socket + * given to fall back to. + */ + Socket checkConnector(AsyncConnector connector) + throws IOException + { + Exception e = connector.getException(); + if (e != null) { + e.fillInStackTrace(); + /* + * The AsyncConnector implementation guaranteed that the exception + * will be either an IOException or a RuntimeException, and we can + * only throw one of those, so convince that compiler that it must + * be one of those. + */ + if (e instanceof IOException) { + throw (IOException) e; + } else if (e instanceof RuntimeException) { + throw (RuntimeException) e; + } else { + throw new Error("internal error: " + + "unexpected checked exception: " + e.toString()); + } + } + return connector.getSocket(); + } + + /** + * Create a new server socket. + */ + public ServerSocket createServerSocket(int port) throws IOException { + //return new HttpAwareServerSocket(port); + return initialFactory.createServerSocket(port); + } + + + /** + * AsyncConnector is used by RMIMasterSocketFactory to attempt socket + * connections on a separate thread. This allows RMIMasterSocketFactory + * to control how long it will wait for the connection to succeed. + */ + private class AsyncConnector implements Runnable { + + /** what factory to use to attempt connection */ + private RMISocketFactory factory; + + /** the host to connect to */ + private String host; + + /** the port to connect to */ + private int port; + + /** access control context to attempt connection within */ + private AccessControlContext acc; + + /** exception that occurred during connection, if any */ + private Exception exception = null; + + /** the connected socket, if successful */ + private Socket socket = null; + + /** socket should be closed after created, if ever */ + private boolean cleanUp = false; + + /** + * Create a new asynchronous connector object. + */ + AsyncConnector(RMISocketFactory factory, String host, int port, + AccessControlContext acc) + { + this.factory = factory; + this.host = host; + this.port = port; + this.acc = acc; + SecurityManager security = System.getSecurityManager(); + if (security != null) { + security.checkConnect(host, port); + } + } + + /** + * Attempt socket connection in separate thread. If successful, + * notify master waiting, + */ + public void run() { + try { + /* + * Using the privileges of the thread that wants to make the + * connection is tempting, but it will fail with applets with + * the current applet security manager because the applet + * network connection policy is not captured in the permission + * framework of the access control context we have. + * + * java.security.AccessController.beginPrivileged(acc); + */ + try { + Socket temp = factory.createSocket(host, port); + synchronized (this) { + socket = temp; + notify(); + } + rememberFactory(host, factory); + synchronized (this) { + if (cleanUp) + try { + socket.close(); + } catch (IOException e) { + } + } + } catch (Exception e) { + /* + * Note that the only exceptions which could actually have + * occurred here are IOException or RuntimeException. + */ + synchronized (this) { + exception = e; + notify(); + } + } + } finally { + /* + * See above comments for matching beginPrivileged() call that + * is also commented out. + * + * java.security.AccessController.endPrivileged(); + */ + } + } + + /** + * Get exception that occurred during connection attempt, if any. + * In the current implementation, this is guaranteed to be either + * an IOException or a RuntimeException. + */ + private synchronized Exception getException() { + return exception; + } + + /** + * Get successful socket, if any. + */ + private synchronized Socket getSocket() { + return socket; + } + + /** + * Note that this connector's socket, if ever successfully created, + * will not be used, so it should be cleaned up quickly + */ + synchronized void notUsed() { + if (socket != null) { + try { + socket.close(); + } catch (IOException e) { + } + } + cleanUp = true; + } + } +} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMISocketInfo.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMISocketInfo.java new file mode 100644 index 00000000000..85008fb231e --- /dev/null +++ b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMISocketInfo.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 1996, 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 sun.rmi.transport.proxy; + +/** + * RMISocketInfo is an interface that extensions of the java.net.Socket + * class may use to provide more information on its capabilities. + */ +public interface RMISocketInfo { + + /** + * Return true if this socket can be used for more than one + * RMI call. If a socket does not implement this interface, then + * it is assumed to be reusable. + */ + public boolean isReusable(); +} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/WrappedSocket.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/WrappedSocket.java new file mode 100644 index 00000000000..7bc8503f60f --- /dev/null +++ b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/WrappedSocket.java @@ -0,0 +1,192 @@ +/* + * Copyright (c) 1996, 2013, 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 sun.rmi.transport.proxy; + +import java.io.*; +import java.net.InetAddress; +import java.net.Socket; +import java.net.SocketException; +import java.security.AccessController; +import java.security.PrivilegedAction; + +/** + * The WrappedSocket class provides a general wrapper for providing an + * extended implementation of java.net.Socket that can be attached to + * a pre-existing Socket object. WrappedSocket itself provides a + * constructor for specifying alternate input or output streams to be + * returned than those of the underlying Socket. + */ +class WrappedSocket extends Socket { + + /** the underlying concrete socket */ + protected Socket socket; + + /** the input stream to return for socket */ + protected InputStream in = null; + + /** the output stream to return for socket */ + protected OutputStream out = null; + + /** + * Layer on top of a pre-existing Socket object, and use specified + * input and output streams. This allows the creator of the + * underlying socket to peek at the beginning of the input with a + * BufferedInputStream and determine which kind of socket + * to create, without consuming the input. + * @param socket the pre-existing socket to use + * @param in the InputStream to return to users (can be null) + * @param out the OutputStream to return to users (can be null) + */ + public WrappedSocket(Socket socket, InputStream in, OutputStream out) + throws IOException + { + super((java.net.SocketImpl)null); // no underlying SocketImpl for this object + this.socket = socket; + this.in = in; + this.out = out; + } + + /** + * Get the address to which the socket is connected. + */ + public InetAddress getInetAddress() + { + return socket.getInetAddress(); + } + + /** + * Get the local address to which the socket is bound. + */ + public InetAddress getLocalAddress() { + return AccessController.doPrivileged( + new PrivilegedAction() { + @Override + public InetAddress run() { + return socket.getLocalAddress(); + + } + }); + } + + /** + * Get the remote port to which the socket is connected. + */ + public int getPort() + { + return socket.getPort(); + } + + /** + * Get the local port to which the socket is connected. + */ + public int getLocalPort() + { + return socket.getLocalPort(); + } + + /** + * Get an InputStream for this socket. + */ + public InputStream getInputStream() throws IOException + { + if (in == null) + in = socket.getInputStream(); + return in; + } + + /** + * Get an OutputStream for this socket. + */ + public OutputStream getOutputStream() throws IOException + { + if (out == null) + out = socket.getOutputStream(); + return out; + } + + /** + * Enable/disable TCP_NODELAY. + */ + public void setTcpNoDelay(boolean on) throws SocketException + { + socket.setTcpNoDelay(on); + } + + /** + * Retrieve whether TCP_NODELAY is enabled. + */ + public boolean getTcpNoDelay() throws SocketException + { + return socket.getTcpNoDelay(); + } + + /** + * Enable/disable SO_LINGER with the specified linger time. + */ + public void setSoLinger(boolean on, int val) throws SocketException + { + socket.setSoLinger(on, val); + } + + /** + * Retrive setting for SO_LINGER. + */ + public int getSoLinger() throws SocketException + { + return socket.getSoLinger(); + } + + /** + * Enable/disable SO_TIMEOUT with the specified timeout + */ + public synchronized void setSoTimeout(int timeout) throws SocketException + { + socket.setSoTimeout(timeout); + } + + /** + * Retrive setting for SO_TIMEOUT. + */ + public synchronized int getSoTimeout() throws SocketException + { + return socket.getSoTimeout(); + } + + /** + * Close the socket. + */ + public synchronized void close() throws IOException + { + socket.close(); + } + + /** + * Return string representation of the socket. + */ + public String toString() + { + return "Wrapped" + socket.toString(); + } +} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPConnection.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPConnection.java index 8b5a610005b..08eb50b29a7 100644 --- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPConnection.java +++ b/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2001, 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,10 +26,14 @@ package sun.rmi.transport.tcp; import java.io.*; +import java.net.InetAddress; import java.net.Socket; +import java.net.SocketException; import java.rmi.*; +import java.rmi.server.RMISocketFactory; import sun.rmi.runtime.Log; import sun.rmi.transport.*; +import sun.rmi.transport.proxy.*; public class TCPConnection implements Connection { @@ -116,7 +120,10 @@ public class TCPConnection implements Connection { */ public boolean isReusable() { - return true; + if ((socket != null) && (socket instanceof RMISocketInfo)) + return ((RMISocketInfo) socket).isReusable(); + else + return true; } /** diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPTransport.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPTransport.java index 764abefb551..1caa362803a 100644 --- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPTransport.java +++ b/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPTransport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2014, 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 @@ -75,6 +75,7 @@ import sun.rmi.transport.StreamRemoteCall; import sun.rmi.transport.Target; import sun.rmi.transport.Transport; import sun.rmi.transport.TransportConstants; +import sun.rmi.transport.proxy.HttpReceiveSocket; /** * TCPTransport is the socket-based implementation of the RMI Transport @@ -710,10 +711,35 @@ public class TCPTransport extends Transport { ? sockIn : new BufferedInputStream(sockIn); - // Read magic + // Read magic (or HTTP wrapper) + bufIn.mark(4); DataInputStream in = new DataInputStream(bufIn); int magic = in.readInt(); + if (magic == POST) { + tcpLog.log(Log.BRIEF, "decoding HTTP-wrapped call"); + + // It's really a HTTP-wrapped request. Repackage + // the socket in a HttpReceiveSocket, reinitialize + // sockIn and in, and reread magic. + bufIn.reset(); // unread "POST" + + try { + socket = new HttpReceiveSocket(socket, bufIn, null); + remoteHost = "0.0.0.0"; + sockIn = socket.getInputStream(); + bufIn = new BufferedInputStream(sockIn); + in = new DataInputStream(bufIn); + magic = in.readInt(); + + } catch (IOException e) { + throw new RemoteException("Error HTTP-unwrapping call", + e); + } + } + // bufIn's mark will invalidate itself when it overflows + // so it doesn't have to be turned off + // read and verify transport header short version = in.readShort(); if (magic != TransportConstants.Magic || diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index 684b0cab3ab..696c9cd270f 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -191,6 +191,8 @@ java/rmi/transport/rapidExportUnexport/RapidExportUnexport.java 7146541 linux-al java/rmi/transport/checkLeaseInfoLeak/CheckLeaseLeak.java 7191877 generic-all +sun/rmi/transport/proxy/EagerHttpFallback.java 7195095 generic-all + java/rmi/activation/Activatable/extLoadedImpl/ext.sh 8062724 generic-all sun/rmi/rmic/newrmic/equivalence/run.sh 8145980 generic-all diff --git a/jdk/test/java/rmi/transport/httpSocket/HttpSocketTest.java b/jdk/test/java/rmi/transport/httpSocket/HttpSocketTest.java new file mode 100644 index 00000000000..8999c3d7310 --- /dev/null +++ b/jdk/test/java/rmi/transport/httpSocket/HttpSocketTest.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 1999, 2012, 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 HttpSocket functionality test + * @author Dana Burns + * + * @library ../../testlibrary + * @modules java.rmi/sun.rmi.registry + * java.rmi/sun.rmi.server + * java.rmi/sun.rmi.transport + * java.rmi/sun.rmi.transport.proxy + * java.rmi/sun.rmi.transport.tcp + * @build TestLibrary HttpSocketTest HttpSocketTest_Stub + * @run main/othervm/policy=security.policy HttpSocketTest + */ + +/* + * This test assures remote methods can be carried out over RMI. + * After setting the RMI runtime socket factory to the http proxy version, + * a registry is created, a remote object (an instance of this class) is + * registered with it, and then it is exercised. + */ + +import java.rmi.Remote; +import java.rmi.RemoteException; +import java.rmi.Naming; +import java.rmi.RMISecurityManager; +import java.rmi.registry.LocateRegistry; +import java.rmi.registry.Registry; +import java.rmi.server.RMISocketFactory; +import java.rmi.server.UnicastRemoteObject; +import sun.rmi.transport.proxy.RMIHttpToPortSocketFactory; + +interface MyRemoteInterface extends Remote { + void setRemoteObject( Remote r ) throws RemoteException; + Remote getRemoteObject() throws RemoteException; +} + +public class HttpSocketTest extends UnicastRemoteObject + implements MyRemoteInterface +{ + private static final String NAME = "HttpSocketTest"; + + public HttpSocketTest() throws RemoteException{} + + private Remote ro; + + public static void main(String[] args) + throws Exception + { + + Registry registry = null; + + TestLibrary.suggestSecurityManager(null); + + // Set the socket factory. + System.err.println("installing socket factory"); + RMISocketFactory.setSocketFactory(new RMIHttpToPortSocketFactory()); + int registryPort = -1; + + try { + System.err.println("Starting registry"); + registry = TestLibrary.createRegistryOnUnusedPort(); + registryPort = TestLibrary.getRegistryPort(registry); + } catch (Exception e) { + TestLibrary.bomb(e); + } + + try { + registry.rebind( NAME, new HttpSocketTest() ); + MyRemoteInterface httpTest = + (MyRemoteInterface)Naming.lookup("//:" + registryPort + "/" + NAME); + httpTest.setRemoteObject( new HttpSocketTest() ); + Remote r = httpTest.getRemoteObject(); + + } catch (Exception e) { + TestLibrary.bomb(e); + } + + + } + + public void setRemoteObject( Remote ro ) throws RemoteException { + this.ro = ro; + } + + public Remote getRemoteObject() throws RemoteException { + return( this.ro ); + } + +} diff --git a/jdk/test/java/rmi/transport/httpSocket/HttpSocketTest_Stub.java b/jdk/test/java/rmi/transport/httpSocket/HttpSocketTest_Stub.java new file mode 100644 index 00000000000..03757a3df20 --- /dev/null +++ b/jdk/test/java/rmi/transport/httpSocket/HttpSocketTest_Stub.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 1999, 2008, 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. + */ + +// Stub class generated by rmic, do not edit. +// Contents subject to change without notice. + +public final class HttpSocketTest_Stub + extends java.rmi.server.RemoteStub + implements MyRemoteInterface, java.rmi.Remote +{ + private static final java.rmi.server.Operation[] operations = { + new java.rmi.server.Operation("java.rmi.Remote getRemoteObject()"), + new java.rmi.server.Operation("void setRemoteObject(java.rmi.Remote)") + }; + + private static final long interfaceHash = 3775375480010579665L; + + private static final long serialVersionUID = 2; + + private static boolean useNewInvoke; + private static java.lang.reflect.Method $method_getRemoteObject_0; + private static java.lang.reflect.Method $method_setRemoteObject_1; + + static { + try { + java.rmi.server.RemoteRef.class.getMethod("invoke", + new java.lang.Class[] { + java.rmi.Remote.class, + java.lang.reflect.Method.class, + java.lang.Object[].class, + long.class + }); + useNewInvoke = true; + $method_getRemoteObject_0 = MyRemoteInterface.class.getMethod("getRemoteObject", new java.lang.Class[] {}); + $method_setRemoteObject_1 = MyRemoteInterface.class.getMethod("setRemoteObject", new java.lang.Class[] {java.rmi.Remote.class}); + } catch (java.lang.NoSuchMethodException e) { + useNewInvoke = false; + } + } + + // constructors + public HttpSocketTest_Stub() { + super(); + } + public HttpSocketTest_Stub(java.rmi.server.RemoteRef ref) { + super(ref); + } + + // methods from remote interfaces + + // implementation of getRemoteObject() + public java.rmi.Remote getRemoteObject() + throws java.rmi.RemoteException + { + try { + if (useNewInvoke) { + Object $result = ref.invoke(this, $method_getRemoteObject_0, null, -2578437860804964265L); + return ((java.rmi.Remote) $result); + } else { + java.rmi.server.RemoteCall call = ref.newCall((java.rmi.server.RemoteObject) this, operations, 0, interfaceHash); + ref.invoke(call); + java.rmi.Remote $result; + try { + java.io.ObjectInput in = call.getInputStream(); + $result = (java.rmi.Remote) in.readObject(); + } catch (java.io.IOException e) { + throw new java.rmi.UnmarshalException("error unmarshalling return", e); + } catch (java.lang.ClassNotFoundException e) { + throw new java.rmi.UnmarshalException("error unmarshalling return", e); + } finally { + ref.done(call); + } + return $result; + } + } catch (java.lang.RuntimeException e) { + throw e; + } catch (java.rmi.RemoteException e) { + throw e; + } catch (java.lang.Exception e) { + throw new java.rmi.UnexpectedException("undeclared checked exception", e); + } + } + + // implementation of setRemoteObject(Remote) + public void setRemoteObject(java.rmi.Remote $param_Remote_1) + throws java.rmi.RemoteException + { + try { + if (useNewInvoke) { + ref.invoke(this, $method_setRemoteObject_1, new java.lang.Object[] {$param_Remote_1}, -7518632118115022871L); + } else { + java.rmi.server.RemoteCall call = ref.newCall((java.rmi.server.RemoteObject) this, operations, 1, interfaceHash); + try { + java.io.ObjectOutput out = call.getOutputStream(); + out.writeObject($param_Remote_1); + } catch (java.io.IOException e) { + throw new java.rmi.MarshalException("error marshalling arguments", e); + } + ref.invoke(call); + ref.done(call); + } + } catch (java.lang.RuntimeException e) { + throw e; + } catch (java.rmi.RemoteException e) { + throw e; + } catch (java.lang.Exception e) { + throw new java.rmi.UnexpectedException("undeclared checked exception", e); + } + } +} diff --git a/jdk/test/java/rmi/transport/httpSocket/security.policy b/jdk/test/java/rmi/transport/httpSocket/security.policy new file mode 100644 index 00000000000..f1960c9772d --- /dev/null +++ b/jdk/test/java/rmi/transport/httpSocket/security.policy @@ -0,0 +1,10 @@ + +grant { + permission java.net.SocketPermission "*:1024-", "accept,connect,listen"; + permission java.lang.RuntimePermission "accessClassInPackage.sun.rmi.registry"; + permission java.lang.RuntimePermission "accessClassInPackage.sun.rmi.server"; + permission java.lang.RuntimePermission "accessClassInPackage.sun.rmi.transport"; + permission java.lang.RuntimePermission "accessClassInPackage.sun.rmi.transport.proxy"; + permission java.lang.RuntimePermission "accessClassInPackage.sun.rmi.transport.tcp"; + permission java.lang.RuntimePermission "setFactory"; +}; diff --git a/jdk/test/sun/rmi/transport/proxy/DisableHttpDefaultValue.java b/jdk/test/sun/rmi/transport/proxy/DisableHttpDefaultValue.java new file mode 100644 index 00000000000..5449c3b8759 --- /dev/null +++ b/jdk/test/sun/rmi/transport/proxy/DisableHttpDefaultValue.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2013, 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 + * @bug 8023862 + * @summary Verify that the default value of the java.rmi.server.disableHttp + * has been changed from false to true. + * @modules java.rmi/sun.rmi.transport.proxy + * @compile -XDignore.symbol.file DisableHttpDefaultValue.java + * + * @run main/othervm DisableHttpDefaultValue true + * @run main/othervm -Djava.rmi.server.disableHttp DisableHttpDefaultValue false + * @run main/othervm -Djava.rmi.server.disableHttp=false DisableHttpDefaultValue false + * @run main/othervm -Djava.rmi.server.disableHttp=xyzzy DisableHttpDefaultValue false + * @run main/othervm -Djava.rmi.server.disableHttp=true DisableHttpDefaultValue true + */ + +import sun.rmi.transport.proxy.RMIMasterSocketFactory; + +public class DisableHttpDefaultValue { + /** + * Subclass RMIMasterSocketFactory to get access to + * protected field altFactoryList. This list has a + * zero size if proxying is disabled. + */ + static class SocketFactory extends RMIMasterSocketFactory { + boolean proxyDisabled() { + return altFactoryList.size() == 0; + } + } + + /** + * Takes a single arg, which is the expected boolean value of + * java.rmi.server.disableHttp. + */ + public static void main(String[] args) throws Exception { + // Force there to be a proxy host, so that we are able to + // tell whether proxying is enabled or disabled. + System.setProperty("http.proxyHost", "proxy.example.com"); + + String propval = System.getProperty("java.rmi.server.disableHttp"); + String propdisp = (propval == null) ? "null" : ("\"" + propval + "\""); + boolean expected = Boolean.parseBoolean(args[0]); + boolean actual = new SocketFactory().proxyDisabled(); + System.out.printf("### prop=%s exp=%s act=%s%n", propdisp, expected, actual); + if (expected != actual) + throw new AssertionError(); + } +} diff --git a/jdk/test/sun/rmi/transport/proxy/EagerHttpFallback.java b/jdk/test/sun/rmi/transport/proxy/EagerHttpFallback.java new file mode 100644 index 00000000000..5b5691701c7 --- /dev/null +++ b/jdk/test/sun/rmi/transport/proxy/EagerHttpFallback.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2002, 2012, 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 + * @bug 4290727 + * @summary Verify that ConnectException will trigger HTTP fallback if + * sun.rmi.transport.proxy.eagerHttpFallback system property is set. + * + * @library ../../../../java/rmi/testlibrary + * @modules java.rmi/sun.rmi.registry + * java.rmi/sun.rmi.server + * java.rmi/sun.rmi.transport + * java.rmi/sun.rmi.transport.tcp + * @build TestLibrary + * @run main/othervm EagerHttpFallback + */ + +import java.rmi.*; +import java.rmi.registry.*; + +public class EagerHttpFallback { + + static final int INITIAL_PORT = TestLibrary.getUnusedRandomPort(); + static final int FALLBACK_PORT = TestLibrary.getUnusedRandomPort(); + + public static void main(String[] args) throws Exception { + System.setProperty("http.proxyHost", "127.0.0.1"); + System.setProperty("http.proxyPort", Integer.toString(FALLBACK_PORT)); + System.setProperty("sun.rmi.transport.proxy.eagerHttpFallback", + "true"); + LocateRegistry.createRegistry(FALLBACK_PORT); + + /* + * The call below should trigger a ConnectException in the + * RMIMasterSocketFactory when it attempts a direct connection to + * INITIAL_PORT, which no one is listening on. Since + * eagerHttpFallback is set, this ConnectException should trigger HTTP + * fallback, which will send a call through the HTTP proxy, which is + * configured to be localhost with a port behind which a registry is + * listening--so if fallback works properly, the list() call should + * succeed. + */ + try { + LocateRegistry.getRegistry(INITIAL_PORT).list(); + } catch (Exception e) { + System.err.println( + "call on registry stub with port " + INITIAL_PORT + + "did not successfully perform HTTP fallback to " + + FALLBACK_PORT); + throw e; + } + } +} diff --git a/jdk/test/sun/rmi/transport/tcp/blockAccept/BlockAcceptTest.java b/jdk/test/sun/rmi/transport/tcp/blockAccept/BlockAcceptTest.java new file mode 100644 index 00000000000..7de92ee2c47 --- /dev/null +++ b/jdk/test/sun/rmi/transport/tcp/blockAccept/BlockAcceptTest.java @@ -0,0 +1,175 @@ +/* + * Copyright (c) 1999, 2012, 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 + * @bug 4203167 + * + * @summary RMI blocks in HttpAwareServerSocket.accept() if you telnet to it + * @author Adrian Colley + * + * @library ../../../../../java/rmi/testlibrary + * @modules java.rmi/sun.rmi.transport.proxy + * @build TestIface TestImpl TestImpl_Stub + * @run main/othervm/policy=security.policy/timeout=60 BlockAcceptTest + */ + +/* This test attempts to stymie the RMI accept loop. The accept loop in + * RMI endlessly accepts a connection, spawns a thread for it, and repeats. + * The accept() call can be replaced by a user-supplied library which + * might foolishly block indefinitely in its accept() method, which would + * prevent RMI from accepting other connections on that socket. + * + * Unfortunately, HttpAwareServerSocket (default server socket) is/was such + * a foolish thing. It reads 4 bytes to see if they're "POST" before + * returning. The bug fix is to move the HTTP stuff into the mainloop, + * which has the side effect of enabling it for non-default socketfactories. + * + * This test: + * 1. Creates an object and exports it. + * 2. Connects to the listening RMI port and sends nothing, to hold it up. + * 3. Makes a regular call, using HTTP tunnelling. + * 4. Fails to deadlock, thereby passing the test. + * + * Some runtime dependencies I'm trying to eliminate: + * 1. We don't know the port number until after exporting the object, but + * have to set it in http.proxyPort somehow. Hopefully http.proxyPort + * isn't read too soon or this test will fail with a ConnectException. + */ + +import java.rmi.*; +import java.rmi.server.RMISocketFactory; +import java.io.*; +import java.net.*; + +import sun.rmi.transport.proxy.RMIMasterSocketFactory; +import sun.rmi.transport.proxy.RMIHttpToPortSocketFactory; + +public class BlockAcceptTest +{ + public static void main(String[] args) + throws Exception + { + // Make trouble for ourselves + if (System.getSecurityManager() == null) + System.setSecurityManager(new RMISecurityManager()); + + // HTTP direct to the server port + System.setProperty("http.proxyHost", "127.0.0.1"); + + // Set the socket factory. + System.err.println("(installing HTTP-out socket factory)"); + HttpOutFactory fac = new HttpOutFactory(); + RMISocketFactory.setSocketFactory(fac); + + // Create remote object + TestImpl impl = new TestImpl(); + + // Export and get which port. + System.err.println("(exporting remote object)"); + TestIface stub = impl.export(); + try { + int port = fac.whichPort(); + + // Sanity + if (port == 0) + throw new Error("TEST FAILED: export didn't reserve a port(?)"); + + // Set the HTTP port, at last. + System.setProperty("http.proxyPort", port+""); + + // Now, connect to that port + //Thread.sleep(2000); + System.err.println("(connecting to listening port on 127.0.0.1:" + + port + ")"); + Socket DoS = new Socket("127.0.0.1", port); + // we hold the connection open until done with the test. + + // The test itself: make a remote call and see if it's blocked or + // if it works + //Thread.sleep(2000); + System.err.println("(making RMI-through-HTTP call)"); + System.err.println("(typical test failure deadlocks here)"); + String result = stub.testCall("dummy load"); + + System.err.println(" => " + result); + if (!("OK".equals(result))) + throw new Error("TEST FAILED: result not OK"); + System.err.println("Test passed."); + + // Clean up, including writing a byte to that connection just in + // case an optimizer thought of optimizing it out of existence + try { + DoS.getOutputStream().write(0); + DoS.getOutputStream().close(); + } catch (Throwable apathy) { + } + + } finally { + try { + impl.unexport(); + } catch (Throwable unmatter) { + } + } + + // Should exit here + } + + private static class HttpOutFactory + extends RMISocketFactory + { + private int servport = 0; + + public Socket createSocket(String h, int p) + throws IOException + { + return ((new RMIHttpToPortSocketFactory()).createSocket(h, p)); + } + + /** Create a server socket and remember which port it's on. + * Aborts if createServerSocket(0) is called twice, because then + * it doesn't know whether to remember the first or second port. + */ + public ServerSocket createServerSocket(int p) + throws IOException + { + ServerSocket ss; + ss = (new RMIMasterSocketFactory()).createServerSocket(p); + if (p == 0) { + if (servport != 0) { + System.err.println("TEST FAILED: " + + "Duplicate createServerSocket(0)"); + throw new Error("Test aborted (createServerSocket)"); + } + servport = ss.getLocalPort(); + } + return (ss); + } + + /** Return which port was reserved by createServerSocket(0). + * If the return value was 0, createServerSocket(0) wasn't called. + */ + public int whichPort() { + return (servport); + } + } // end class HttpOutFactory +} diff --git a/jdk/test/sun/rmi/transport/tcp/blockAccept/TestIface.java b/jdk/test/sun/rmi/transport/tcp/blockAccept/TestIface.java new file mode 100644 index 00000000000..85bab51483d --- /dev/null +++ b/jdk/test/sun/rmi/transport/tcp/blockAccept/TestIface.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 1999, 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.rmi.*; + +public interface TestIface + extends Remote +{ + public String testCall(String ign) + throws RemoteException; +} diff --git a/jdk/test/sun/rmi/transport/tcp/blockAccept/TestImpl.java b/jdk/test/sun/rmi/transport/tcp/blockAccept/TestImpl.java new file mode 100644 index 00000000000..73601a9e3b6 --- /dev/null +++ b/jdk/test/sun/rmi/transport/tcp/blockAccept/TestImpl.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 1999, 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.rmi.*; +import java.rmi.server.*; + +public class TestImpl + extends Object + implements TestIface +{ + public TestImpl() { + } + + public TestIface export() + throws RemoteException + { + return (TestIface)UnicastRemoteObject.exportObject(this); + } + + public void unexport() + throws NoSuchObjectException + { + UnicastRemoteObject.unexportObject(this, true); + } + + public String testCall(String ign) { + return ("OK"); + } +} diff --git a/jdk/test/sun/rmi/transport/tcp/blockAccept/TestImpl_Stub.java b/jdk/test/sun/rmi/transport/tcp/blockAccept/TestImpl_Stub.java new file mode 100644 index 00000000000..2de40012e16 --- /dev/null +++ b/jdk/test/sun/rmi/transport/tcp/blockAccept/TestImpl_Stub.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 1999, 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. + */ + +// Stub class generated by rmic, do not edit. +// Contents subject to change without notice. + +public final class TestImpl_Stub + extends java.rmi.server.RemoteStub + implements TestIface +{ + private static final long serialVersionUID = 2; + + private static java.lang.reflect.Method $method_testCall_0; + + static { + try { + $method_testCall_0 = TestIface.class.getMethod("testCall", new java.lang.Class[] {java.lang.String.class}); + } catch (java.lang.NoSuchMethodException e) { + throw new java.lang.NoSuchMethodError( + "stub class initialization failed"); + } + } + + // constructors + public TestImpl_Stub(java.rmi.server.RemoteRef ref) { + super(ref); + } + + // methods from remote interfaces + + // implementation of testCall(String) + public java.lang.String testCall(java.lang.String $param_String_1) + throws java.rmi.RemoteException + { + try { + Object $result = ref.invoke(this, $method_testCall_0, new java.lang.Object[] {$param_String_1}, -4495720265115653109L); + return ((java.lang.String) $result); + } catch (java.lang.RuntimeException e) { + throw e; + } catch (java.rmi.RemoteException e) { + throw e; + } catch (java.lang.Exception e) { + throw new java.rmi.UnexpectedException("undeclared checked exception", e); + } + } +} diff --git a/jdk/test/sun/rmi/transport/tcp/blockAccept/security.policy b/jdk/test/sun/rmi/transport/tcp/blockAccept/security.policy new file mode 100644 index 00000000000..a8c8d0a64d8 --- /dev/null +++ b/jdk/test/sun/rmi/transport/tcp/blockAccept/security.policy @@ -0,0 +1,10 @@ +grant { + // Take this out once we can specify -Djava.security.debug on + // the run line and figure out what else is needed + permission java.security.AllPermission; + + permission java.net.SocketPermission "*:1024-65535", "connect,listen"; + permission java.util.PropertyPermission "http.proxyHost", "write"; + permission java.util.PropertyPermission "http.proxyPort", "write"; + permission java.lang.RuntimePermission "setFactory"; +}; From 1af2806677f4cc6854607c45c7f65f3b12636411 Mon Sep 17 00:00:00 2001 From: Paul Sandoz Date: Tue, 26 Apr 2016 18:30:00 -0700 Subject: [PATCH 06/18] 8154556: Use java.nio.ByteOrder instead of boolean value Reviewed-by: alanb --- .../java/lang/invoke/MethodHandles.java | 68 ++++++++++--------- .../VarHandleTestAccessBoolean.java | 1 - .../VarHandles/VarHandleTestAccessByte.java | 1 - .../VarHandles/VarHandleTestAccessChar.java | 1 - .../VarHandles/VarHandleTestAccessDouble.java | 1 - .../VarHandles/VarHandleTestAccessFloat.java | 1 - .../VarHandles/VarHandleTestAccessInt.java | 1 - .../VarHandles/VarHandleTestAccessLong.java | 1 - .../VarHandles/VarHandleTestAccessShort.java | 1 - .../VarHandles/VarHandleTestAccessString.java | 1 - .../VarHandleTestByteArrayAsChar.java | 11 +-- .../VarHandleTestByteArrayAsDouble.java | 11 +-- .../VarHandleTestByteArrayAsFloat.java | 11 +-- .../VarHandleTestByteArrayAsInt.java | 15 ++-- .../VarHandleTestByteArrayAsLong.java | 11 +-- .../VarHandleTestByteArrayAsShort.java | 11 +-- ...X-VarHandleTestByteArrayView.java.template | 10 +-- 17 files changed, 81 insertions(+), 76 deletions(-) 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 6c37371a57b..12fcecd125d 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 @@ -25,34 +25,38 @@ package java.lang.invoke; -import java.lang.reflect.*; -import java.util.ArrayList; -import java.util.BitSet; -import java.util.Iterator; -import java.util.List; -import java.util.Arrays; -import java.util.Objects; -import java.security.AccessController; -import java.security.PrivilegedAction; - +import jdk.internal.org.objectweb.asm.ClassWriter; +import jdk.internal.org.objectweb.asm.Opcodes; +import jdk.internal.reflect.CallerSensitive; +import jdk.internal.reflect.Reflection; import sun.invoke.util.ValueConversions; import sun.invoke.util.VerifyAccess; import sun.invoke.util.Wrapper; -import jdk.internal.reflect.CallerSensitive; -import jdk.internal.reflect.Reflection; import sun.reflect.misc.ReflectUtil; import sun.security.util.SecurityConstants; -import java.lang.invoke.LambdaForm.BasicType; -import static java.lang.invoke.MethodHandleImpl.Intrinsic; -import static java.lang.invoke.MethodHandleNatives.Constants.*; +import java.lang.invoke.LambdaForm.BasicType; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.ReflectPermission; +import java.nio.ByteOrder; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.BitSet; +import java.util.Iterator; +import java.util.List; +import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; import java.util.stream.Stream; -import jdk.internal.org.objectweb.asm.ClassWriter; -import jdk.internal.org.objectweb.asm.Opcodes; - +import static java.lang.invoke.MethodHandleImpl.Intrinsic; +import static java.lang.invoke.MethodHandleNatives.Constants.*; import static java.lang.invoke.MethodHandleStatics.newIllegalArgumentException; import static java.lang.invoke.MethodType.methodType; @@ -2337,13 +2341,12 @@ return mh1; * * @param viewArrayClass the view array class, with a component type of * type {@code T} - * @param bigEndian true if the endianness of the view array elements, as - * stored in the underlying {@code byte} array, is big endian, otherwise - * little endian + * @param byteOrder the endianness of the view array elements, as + * stored in the underlying {@code byte} array * @return a VarHandle giving access to elements of a {@code byte[]} array * viewed as if elements corresponding to the components type of the view * array class - * @throws NullPointerException if viewArrayClass is null + * @throws NullPointerException if viewArrayClass or byteOrder is null * @throws IllegalArgumentException if viewArrayClass is not an array type * @throws UnsupportedOperationException if the component type of * viewArrayClass is not supported as a variable type @@ -2351,8 +2354,10 @@ return mh1; */ public static VarHandle byteArrayViewVarHandle(Class viewArrayClass, - boolean bigEndian) throws IllegalArgumentException { - return VarHandles.byteArrayViewHandle(viewArrayClass, bigEndian); + ByteOrder byteOrder) throws IllegalArgumentException { + Objects.requireNonNull(byteOrder); + return VarHandles.byteArrayViewHandle(viewArrayClass, + byteOrder == ByteOrder.BIG_ENDIAN); } /** @@ -2422,14 +2427,13 @@ return mh1; * * @param viewArrayClass the view array class, with a component type of * type {@code T} - * @param bigEndian true if the endianness of the view array elements, as - * stored in the underlying {@code ByteBuffer}, is big endian, otherwise - * little endian (Note this overrides the endianness of a - * {@code ByteBuffer}) + * @param byteOrder the endianness of the view array elements, as + * stored in the underlying {@code ByteBuffer} (Note this overrides the + * endianness of a {@code ByteBuffer}) * @return a VarHandle giving access to elements of a {@code ByteBuffer} * viewed as if elements corresponding to the components type of the view * array class - * @throws NullPointerException if viewArrayClass is null + * @throws NullPointerException if viewArrayClass or byteOrder is null * @throws IllegalArgumentException if viewArrayClass is not an array type * @throws UnsupportedOperationException if the component type of * viewArrayClass is not supported as a variable type @@ -2437,8 +2441,10 @@ return mh1; */ public static VarHandle byteBufferViewVarHandle(Class viewArrayClass, - boolean bigEndian) throws IllegalArgumentException { - return VarHandles.makeByteBufferViewHandle(viewArrayClass, bigEndian); + ByteOrder byteOrder) throws IllegalArgumentException { + Objects.requireNonNull(byteOrder); + return VarHandles.makeByteBufferViewHandle(viewArrayClass, + byteOrder == ByteOrder.BIG_ENDIAN); } diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java index 5590984e493..b22fc3e182a 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java @@ -106,7 +106,6 @@ public class VarHandleTestAccessBoolean extends VarHandleBaseTest { assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java index f9c9d4fc31e..088a519e920 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java @@ -106,7 +106,6 @@ public class VarHandleTestAccessByte extends VarHandleBaseTest { assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java index bd1174efc5a..18ff6542615 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java @@ -106,7 +106,6 @@ public class VarHandleTestAccessChar extends VarHandleBaseTest { assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java index d8732d239b4..36c84e2f753 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java @@ -106,7 +106,6 @@ public class VarHandleTestAccessDouble extends VarHandleBaseTest { assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java index 9976102d027..2ea2d9617be 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java @@ -106,7 +106,6 @@ public class VarHandleTestAccessFloat extends VarHandleBaseTest { assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java index c78e5cb7199..0c3d8d5c841 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java @@ -106,7 +106,6 @@ public class VarHandleTestAccessInt extends VarHandleBaseTest { assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java index f82ee67960e..a034a536468 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java @@ -106,7 +106,6 @@ public class VarHandleTestAccessLong extends VarHandleBaseTest { assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java index d235e03a7bf..4ff25cc4a5f 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java @@ -106,7 +106,6 @@ public class VarHandleTestAccessShort extends VarHandleBaseTest { assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessString.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessString.java index 61e3690447c..4272c898a4c 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessString.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessString.java @@ -106,7 +106,6 @@ public class VarHandleTestAccessString extends VarHandleBaseTest { assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java index e6941f5fa3c..c46720b738a 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java @@ -23,6 +23,7 @@ /* * @test + * @bug 8154556 * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsChar * @run testng/othervm -Diters=20000 VarHandleTestByteArrayAsChar * @run testng/othervm -Diters=20000 -XX:-TieredCompilation VarHandleTestByteArrayAsChar @@ -57,15 +58,16 @@ public class VarHandleTestByteArrayAsChar extends VarHandleBaseByteArrayTest { // Combinations of VarHandle byte[] or ByteBuffer vhss = new ArrayList<>(); for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) { + + ByteOrder bo = endianess == MemoryMode.BIG_ENDIAN + ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN; VarHandleSource aeh = new VarHandleSource( - MethodHandles.byteArrayViewVarHandle(char[].class, - endianess == MemoryMode.BIG_ENDIAN), + MethodHandles.byteArrayViewVarHandle(char[].class, bo), endianess, MemoryMode.READ_WRITE); vhss.add(aeh); VarHandleSource bbh = new VarHandleSource( - MethodHandles.byteBufferViewVarHandle(char[].class, - endianess == MemoryMode.BIG_ENDIAN), + MethodHandles.byteBufferViewVarHandle(char[].class, bo), endianess, MemoryMode.READ_WRITE); vhss.add(bbh); } @@ -93,7 +95,6 @@ public class VarHandleTestByteArrayAsChar extends VarHandleBaseByteArrayTest { assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java index ec4b843b2aa..9cee7930dee 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java @@ -23,6 +23,7 @@ /* * @test + * @bug 8154556 * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsDouble * @run testng/othervm -Diters=20000 VarHandleTestByteArrayAsDouble * @run testng/othervm -Diters=20000 -XX:-TieredCompilation VarHandleTestByteArrayAsDouble @@ -57,15 +58,16 @@ public class VarHandleTestByteArrayAsDouble extends VarHandleBaseByteArrayTest { // Combinations of VarHandle byte[] or ByteBuffer vhss = new ArrayList<>(); for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) { + + ByteOrder bo = endianess == MemoryMode.BIG_ENDIAN + ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN; VarHandleSource aeh = new VarHandleSource( - MethodHandles.byteArrayViewVarHandle(double[].class, - endianess == MemoryMode.BIG_ENDIAN), + MethodHandles.byteArrayViewVarHandle(double[].class, bo), endianess, MemoryMode.READ_WRITE); vhss.add(aeh); VarHandleSource bbh = new VarHandleSource( - MethodHandles.byteBufferViewVarHandle(double[].class, - endianess == MemoryMode.BIG_ENDIAN), + MethodHandles.byteBufferViewVarHandle(double[].class, bo), endianess, MemoryMode.READ_WRITE); vhss.add(bbh); } @@ -93,7 +95,6 @@ public class VarHandleTestByteArrayAsDouble extends VarHandleBaseByteArrayTest { assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java index 57d37cbe523..e366e84c239 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java @@ -23,6 +23,7 @@ /* * @test + * @bug 8154556 * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsFloat * @run testng/othervm -Diters=20000 VarHandleTestByteArrayAsFloat * @run testng/othervm -Diters=20000 -XX:-TieredCompilation VarHandleTestByteArrayAsFloat @@ -57,15 +58,16 @@ public class VarHandleTestByteArrayAsFloat extends VarHandleBaseByteArrayTest { // Combinations of VarHandle byte[] or ByteBuffer vhss = new ArrayList<>(); for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) { + + ByteOrder bo = endianess == MemoryMode.BIG_ENDIAN + ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN; VarHandleSource aeh = new VarHandleSource( - MethodHandles.byteArrayViewVarHandle(float[].class, - endianess == MemoryMode.BIG_ENDIAN), + MethodHandles.byteArrayViewVarHandle(float[].class, bo), endianess, MemoryMode.READ_WRITE); vhss.add(aeh); VarHandleSource bbh = new VarHandleSource( - MethodHandles.byteBufferViewVarHandle(float[].class, - endianess == MemoryMode.BIG_ENDIAN), + MethodHandles.byteBufferViewVarHandle(float[].class, bo), endianess, MemoryMode.READ_WRITE); vhss.add(bbh); } @@ -93,7 +95,6 @@ public class VarHandleTestByteArrayAsFloat extends VarHandleBaseByteArrayTest { assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java index ae66477d3b6..2831fa63210 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java @@ -23,6 +23,7 @@ /* * @test + * @bug 8154556 * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsInt * @run testng/othervm -Diters=20000 VarHandleTestByteArrayAsInt * @run testng/othervm -Diters=20000 -XX:-TieredCompilation VarHandleTestByteArrayAsInt @@ -37,10 +38,10 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.ArrayList; import java.util.Arrays; -import java.util.EnumSet; import java.util.List; -import static org.testng.Assert.*; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; public class VarHandleTestByteArrayAsInt extends VarHandleBaseByteArrayTest { static final int SIZE = Integer.BYTES; @@ -57,15 +58,16 @@ public class VarHandleTestByteArrayAsInt extends VarHandleBaseByteArrayTest { // Combinations of VarHandle byte[] or ByteBuffer vhss = new ArrayList<>(); for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) { + + ByteOrder bo = endianess == MemoryMode.BIG_ENDIAN + ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN; VarHandleSource aeh = new VarHandleSource( - MethodHandles.byteArrayViewVarHandle(int[].class, - endianess == MemoryMode.BIG_ENDIAN), + MethodHandles.byteArrayViewVarHandle(int[].class, bo), endianess, MemoryMode.READ_WRITE); vhss.add(aeh); VarHandleSource bbh = new VarHandleSource( - MethodHandles.byteBufferViewVarHandle(int[].class, - endianess == MemoryMode.BIG_ENDIAN), + MethodHandles.byteBufferViewVarHandle(int[].class, bo), endianess, MemoryMode.READ_WRITE); vhss.add(bbh); } @@ -93,7 +95,6 @@ public class VarHandleTestByteArrayAsInt extends VarHandleBaseByteArrayTest { assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java index ac08db2af5c..263245a5e72 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java @@ -23,6 +23,7 @@ /* * @test + * @bug 8154556 * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsLong * @run testng/othervm -Diters=20000 VarHandleTestByteArrayAsLong * @run testng/othervm -Diters=20000 -XX:-TieredCompilation VarHandleTestByteArrayAsLong @@ -57,15 +58,16 @@ public class VarHandleTestByteArrayAsLong extends VarHandleBaseByteArrayTest { // Combinations of VarHandle byte[] or ByteBuffer vhss = new ArrayList<>(); for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) { + + ByteOrder bo = endianess == MemoryMode.BIG_ENDIAN + ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN; VarHandleSource aeh = new VarHandleSource( - MethodHandles.byteArrayViewVarHandle(long[].class, - endianess == MemoryMode.BIG_ENDIAN), + MethodHandles.byteArrayViewVarHandle(long[].class, bo), endianess, MemoryMode.READ_WRITE); vhss.add(aeh); VarHandleSource bbh = new VarHandleSource( - MethodHandles.byteBufferViewVarHandle(long[].class, - endianess == MemoryMode.BIG_ENDIAN), + MethodHandles.byteBufferViewVarHandle(long[].class, bo), endianess, MemoryMode.READ_WRITE); vhss.add(bbh); } @@ -93,7 +95,6 @@ public class VarHandleTestByteArrayAsLong extends VarHandleBaseByteArrayTest { assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java index 9742fbd2522..3d6078e6056 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java @@ -23,6 +23,7 @@ /* * @test + * @bug 8154556 * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsShort * @run testng/othervm -Diters=20000 VarHandleTestByteArrayAsShort * @run testng/othervm -Diters=20000 -XX:-TieredCompilation VarHandleTestByteArrayAsShort @@ -57,15 +58,16 @@ public class VarHandleTestByteArrayAsShort extends VarHandleBaseByteArrayTest { // Combinations of VarHandle byte[] or ByteBuffer vhss = new ArrayList<>(); for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) { + + ByteOrder bo = endianess == MemoryMode.BIG_ENDIAN + ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN; VarHandleSource aeh = new VarHandleSource( - MethodHandles.byteArrayViewVarHandle(short[].class, - endianess == MemoryMode.BIG_ENDIAN), + MethodHandles.byteArrayViewVarHandle(short[].class, bo), endianess, MemoryMode.READ_WRITE); vhss.add(aeh); VarHandleSource bbh = new VarHandleSource( - MethodHandles.byteBufferViewVarHandle(short[].class, - endianess == MemoryMode.BIG_ENDIAN), + MethodHandles.byteBufferViewVarHandle(short[].class, bo), endianess, MemoryMode.READ_WRITE); vhss.add(bbh); } @@ -93,7 +95,6 @@ public class VarHandleTestByteArrayAsShort extends VarHandleBaseByteArrayTest { assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); diff --git a/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template b/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template index 1c323e2f195..4cdf45bad80 100644 --- a/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template +++ b/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template @@ -23,6 +23,7 @@ /* * @test + * @bug 8154556 * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAs$Type$ * @run testng/othervm -Diters=20000 VarHandleTestByteArrayAs$Type$ * @run testng/othervm -Diters=20000 -XX:-TieredCompilation VarHandleTestByteArrayAs$Type$ @@ -57,15 +58,16 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { // Combinations of VarHandle byte[] or ByteBuffer vhss = new ArrayList<>(); for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) { + + ByteOrder bo = endianess == MemoryMode.BIG_ENDIAN + ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN; VarHandleSource aeh = new VarHandleSource( - MethodHandles.byteArrayViewVarHandle($type$[].class, - endianess == MemoryMode.BIG_ENDIAN), + MethodHandles.byteArrayViewVarHandle($type$[].class, bo), endianess, MemoryMode.READ_WRITE); vhss.add(aeh); VarHandleSource bbh = new VarHandleSource( - MethodHandles.byteBufferViewVarHandle($type$[].class, - endianess == MemoryMode.BIG_ENDIAN), + MethodHandles.byteBufferViewVarHandle($type$[].class, bo), endianess, MemoryMode.READ_WRITE); vhss.add(bbh); } From 27f82bea87acd8eab8235837c0e2512291fab590 Mon Sep 17 00:00:00 2001 From: Paul Sandoz Date: Tue, 26 Apr 2016 18:42:51 -0700 Subject: [PATCH 07/18] 8154447: Exempt classes under java.util.concurrent from MH.Lookup restrictions Reviewed-by: mchung, martin --- .../java/lang/invoke/MethodHandles.java | 9 ++-- .../invoke/JavaUtilConcurrentLookupTest.java | 46 +++++++++++++++++++ .../java/util/concurrent/LookupTester.java | 37 +++++++++++++++ 3 files changed, 89 insertions(+), 3 deletions(-) create mode 100644 jdk/test/java/lang/invoke/JavaUtilConcurrentLookupTest.java create mode 100644 jdk/test/java/lang/invoke/java.base/java/util/concurrent/LookupTester.java 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 12fcecd125d..afe6aecc9f4 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 @@ -745,10 +745,13 @@ public class MethodHandles { if (name.startsWith("java.lang.invoke.")) throw newIllegalArgumentException("illegal lookupClass: "+lookupClass); - // For caller-sensitive MethodHandles.lookup() - // disallow lookup more restricted packages + // For caller-sensitive MethodHandles.lookup() disallow lookup from + // restricted packages. This a fragile and blunt approach. + // TODO replace with a more formal and less fragile mechanism + // that does not bluntly restrict classes under packages within + // java.base from looking up MethodHandles or VarHandles. if (allowedModes == ALL_MODES && lookupClass.getClassLoader() == null) { - if (name.startsWith("java.") || + if ((name.startsWith("java.") && !name.startsWith("java.util.concurrent.")) || (name.startsWith("sun.") && !name.startsWith("sun.invoke."))) { throw newIllegalArgumentException("illegal lookupClass: " + lookupClass); } diff --git a/jdk/test/java/lang/invoke/JavaUtilConcurrentLookupTest.java b/jdk/test/java/lang/invoke/JavaUtilConcurrentLookupTest.java new file mode 100644 index 00000000000..9715de8fd46 --- /dev/null +++ b/jdk/test/java/lang/invoke/JavaUtilConcurrentLookupTest.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2016, 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 Tests that Lookup can be produced from classes under java.util.concurrent + * @bug 8154447 + * @compile/module=java.base java/util/concurrent/LookupTester.java + * @run testng/othervm JavaUtilConcurrentLookupTest + */ + +import org.testng.annotations.Test; + +import java.util.concurrent.LookupTester; + +public class JavaUtilConcurrentLookupTest { + + @Test + public void testLookup() { + LookupTester.getLookup(); + } + + @Test + public void testLookupIn() { + LookupTester.getLookupIn(); + } +} diff --git a/jdk/test/java/lang/invoke/java.base/java/util/concurrent/LookupTester.java b/jdk/test/java/lang/invoke/java.base/java/util/concurrent/LookupTester.java new file mode 100644 index 00000000000..2198495fcac --- /dev/null +++ b/jdk/test/java/lang/invoke/java.base/java/util/concurrent/LookupTester.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016, 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. + */ + +package java.util.concurrent; + +import java.lang.invoke.MethodHandles; + +public class LookupTester { + public static MethodHandles.Lookup getLookup() { + return MethodHandles.lookup(); + } + + + public static MethodHandles.Lookup getLookupIn() { + return MethodHandles.lookup().in(ConcurrentHashMap.class); + } +} From 75b0c4fb9ccda0e42acfc363fd8d2d850b52cf59 Mon Sep 17 00:00:00 2001 From: Volker Simonis Date: Wed, 27 Apr 2016 09:13:51 +0200 Subject: [PATCH 08/18] 8155156: Remove remaining sun.misc.* imports from the jdk repo Reviewed-by: chegar --- .../share/classes/sun/nio/ch/AbstractPollSelectorImpl.java | 3 +-- .../java.base/unix/classes/sun/nio/ch/PollSelectorImpl.java | 3 +-- jdk/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java | 1 - 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/AbstractPollSelectorImpl.java b/jdk/src/java.base/share/classes/sun/nio/ch/AbstractPollSelectorImpl.java index 6f1f8e86f04..81fa9836a87 100644 --- a/jdk/src/java.base/share/classes/sun/nio/ch/AbstractPollSelectorImpl.java +++ b/jdk/src/java.base/share/classes/sun/nio/ch/AbstractPollSelectorImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, 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 @@ -29,7 +29,6 @@ import java.io.IOException; import java.nio.channels.*; import java.nio.channels.spi.*; import java.util.*; -import sun.misc.*; /** diff --git a/jdk/src/java.base/unix/classes/sun/nio/ch/PollSelectorImpl.java b/jdk/src/java.base/unix/classes/sun/nio/ch/PollSelectorImpl.java index 1911c3507c0..27c7a41937e 100644 --- a/jdk/src/java.base/unix/classes/sun/nio/ch/PollSelectorImpl.java +++ b/jdk/src/java.base/unix/classes/sun/nio/ch/PollSelectorImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, 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 @@ -29,7 +29,6 @@ import java.io.IOException; import java.nio.channels.*; import java.nio.channels.spi.*; import java.util.*; -import sun.misc.*; /** diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java index aa460f9f636..9ff2d7ce598 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java @@ -52,7 +52,6 @@ import sun.awt.*; import sun.awt.datatransfer.DataTransferer; import sun.font.FontConfigManager; import sun.java2d.SunGraphicsEnvironment; -import sun.misc.*; import sun.awt.util.PerformanceLogger; import sun.awt.util.ThreadGroupUtils; import sun.print.PrintJob2D; From fe4860fe5e30b4db33ad51861b1a3c7e79a78307 Mon Sep 17 00:00:00 2001 From: Michael Haupt Date: Wed, 27 Apr 2016 15:01:21 +0200 Subject: [PATCH 09/18] 8155214: java/lang/invoke/PermuteArgsTest.java fails due to exhausted code cache Reviewed-by: sundar --- jdk/test/java/lang/invoke/PermuteArgsTest.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/jdk/test/java/lang/invoke/PermuteArgsTest.java b/jdk/test/java/lang/invoke/PermuteArgsTest.java index edb9ba33bc7..a47e4d7fc54 100644 --- a/jdk/test/java/lang/invoke/PermuteArgsTest.java +++ b/jdk/test/java/lang/invoke/PermuteArgsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2016, 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 @@ -23,6 +23,7 @@ /* @test * @summary unit tests for method handles which permute their arguments + * @library /lib/testlibrary/jsr292 /lib/testlibrary * @run testng/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyDependencies -ea -esa -DPermuteArgsTest.MAX_ARITY=8 test.java.lang.invoke.PermuteArgsTest */ /* Examples of manual runs: @@ -36,6 +37,8 @@ package test.java.lang.invoke; import org.testng.*; import org.testng.annotations.*; +import com.oracle.testlibrary.jsr292.CodeCacheOverflowProcessor; + import java.util.*; import java.lang.reflect.*; @@ -122,9 +125,15 @@ public class PermuteArgsTest { } new PermuteArgsTest().test(); } + static int testCases; + @Test public void test() throws Throwable { + CodeCacheOverflowProcessor.runMHTest(this::test0); + } + + public void test0() throws Throwable { testCases = 0; Lookup lookup = lookup(); for (Method m : lookup.lookupClass().getDeclaredMethods()) { From 1e0d1458a251c5696d9b613c7bb03472eb44065f Mon Sep 17 00:00:00 2001 From: Daniel Fuchs Date: Wed, 27 Apr 2016 18:04:16 +0200 Subject: [PATCH 10/18] 8148568: LoggerFinder.getLogger and LoggerFinder.getLocalizedLogger should take a Module argument instead of a Class Changes System.LoggerFinder methods to take a Module argument instead of a Class. Reviewed-by: mchung --- .../share/classes/java/lang/System.java | 67 +++++++++-------- .../internal/logger/DefaultLoggerFinder.java | 33 ++++++--- .../jdk/internal/logger/LazyLoggers.java | 73 ++++++++++--------- .../sun/util/logging/PlatformLogger.java | 9 ++- .../classes/java/util/logging/LogManager.java | 48 ++++++++---- .../classes/java/util/logging/Logger.java | 27 ++++--- .../logging/internal/LoggingProviderImpl.java | 20 ++--- .../Logger/custom/CustomLoggerTest.java | 53 ++++++++++---- .../BaseLoggerFinder.java | 3 +- .../BaseLoggerFinderTest.java | 32 ++++---- .../TestLoggerFinder.java | 5 +- .../DefaultLoggerFinderTest.java | 32 ++++---- .../BaseDefaultLoggerFinderTest.java | 16 ++-- .../BaseLoggerBridgeTest.java | 27 ++++--- .../BasePlatformLoggerTest.java | 10 ++- .../BootstrapLoggerAPIsTest.java | 4 +- .../BootstrapLogger/BootstrapLoggerTest.java | 5 +- .../LoggerBridgeTest/LoggerBridgeTest.java | 41 +++++++---- .../LoggerFinderLoaderTest.java | 9 ++- .../PlatformLoggerBridgeTest.java | 7 +- .../internal/api/LoggerFinderAPITest.java | 6 +- .../backend/LoggerFinderBackendTest.java | 39 +++++----- .../DefaultLoggerBridgeTest.java | 19 ++--- .../DefaultPlatformLoggerTest.java | 5 +- .../sun/util/logging/PlatformLoggerTest.java | 2 +- 25 files changed, 342 insertions(+), 250 deletions(-) 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 2ddd37f5da1..d6e80e71908 100644 --- a/jdk/src/java.base/share/classes/java/lang/System.java +++ b/jdk/src/java.base/share/classes/java/lang/System.java @@ -1155,8 +1155,9 @@ public final class System { * @param level the log message level. * @param msg the string message (or a key in the message catalog, if * this logger is a {@link - * LoggerFinder#getLocalizedLogger(java.lang.String, java.util.ResourceBundle, java.lang.Class) - * localized logger}); can be {@code null}. + * LoggerFinder#getLocalizedLogger(java.lang.String, + * java.util.ResourceBundle, java.lang.reflect.Module) localized logger}); + * can be {@code null}. * * @throws NullPointerException if {@code level} is {@code null}. */ @@ -1222,8 +1223,9 @@ public final class System { * @param level the log message level. * @param msg the string message (or a key in the message catalog, if * this logger is a {@link - * LoggerFinder#getLocalizedLogger(java.lang.String, java.util.ResourceBundle, java.lang.Class) - * localized logger}); can be {@code null}. + * LoggerFinder#getLocalizedLogger(java.lang.String, + * java.util.ResourceBundle, java.lang.reflect.Module) localized logger}); + * can be {@code null}. * @param thrown a {@code Throwable} associated with the log message; * can be {@code null}. * @@ -1270,8 +1272,9 @@ public final class System { * @param format the string message format in {@link * java.text.MessageFormat} format, (or a key in the message * catalog, if this logger is a {@link - * LoggerFinder#getLocalizedLogger(java.lang.String, java.util.ResourceBundle, java.lang.Class) - * localized logger}); can be {@code null}. + * LoggerFinder#getLocalizedLogger(java.lang.String, + * java.util.ResourceBundle, java.lang.reflect.Module) localized logger}); + * can be {@code null}. * @param params an optional list of parameters to the message (may be * none). * @@ -1453,30 +1456,30 @@ public final class System { /** * Returns an instance of {@link Logger Logger} - * for the given {@code caller}. + * for the given {@code module}. * * @param name the name of the logger. - * @param caller the class for which the logger is being requested. + * @param module the module for which the logger is being requested. * - * @return a {@link Logger logger} suitable for the given caller's - * use. + * @return a {@link Logger logger} suitable for use within the given + * module. * @throws NullPointerException if {@code name} is {@code null} or - * {@code caller} is {@code null}. + * {@code module} is {@code null}. * @throws SecurityException if a security manager is present and its * {@code checkPermission} method doesn't allow the * {@code RuntimePermission("loggerFinder")}. */ - public abstract Logger getLogger(String name, /* Module */ Class caller); + public abstract Logger getLogger(String name, Module module); /** * Returns a localizable instance of {@link Logger Logger} - * for the given {@code caller}. + * for the given {@code module}. * The returned logger will use the provided resource bundle for * message localization. * * @implSpec By default, this method calls {@link - * #getLogger(java.lang.String, java.lang.Class) - * this.getLogger(name, caller)} to obtain a logger, then wraps that + * #getLogger(java.lang.String, java.lang.reflect.Module) + * this.getLogger(name, module)} to obtain a logger, then wraps that * logger in a {@link Logger} instance where all methods that do not * take a {@link ResourceBundle} as parameter are redirected to one * which does - passing the given {@code bundle} for @@ -1499,19 +1502,19 @@ public final class System { * * @param name the name of the logger. * @param bundle a resource bundle; can be {@code null}. - * @param caller the class for which the logger is being requested. + * @param module the module for which the logger is being requested. * @return an instance of {@link Logger Logger} which will use the * provided resource bundle for message localization. * * @throws NullPointerException if {@code name} is {@code null} or - * {@code caller} is {@code null}. + * {@code module} is {@code null}. * @throws SecurityException if a security manager is present and its * {@code checkPermission} method doesn't allow the * {@code RuntimePermission("loggerFinder")}. */ public Logger getLocalizedLogger(String name, ResourceBundle bundle, - /* Module */ Class caller) { - return new LocalizedLoggerWrapper<>(getLogger(name, caller), bundle); + Module module) { + return new LocalizedLoggerWrapper<>(getLogger(name, module), bundle); } /** @@ -1558,12 +1561,13 @@ public final class System { * * @implSpec * Instances returned by this method route messages to loggers - * obtained by calling {@link LoggerFinder#getLogger(java.lang.String, java.lang.Class) - * LoggerFinder.getLogger(name, caller)}. + * obtained by calling {@link LoggerFinder#getLogger(java.lang.String, + * java.lang.reflect.Module) LoggerFinder.getLogger(name, module)}, where + * {@code module} is the caller's module. * * @apiNote * This method may defer calling the {@link - * LoggerFinder#getLogger(java.lang.String, java.lang.Class) + * LoggerFinder#getLogger(java.lang.String, java.lang.reflect.Module) * LoggerFinder.getLogger} method to create an actual logger supplied by * the logging backend, for instance, to allow loggers to be obtained during * the system initialization time. @@ -1579,7 +1583,7 @@ public final class System { public static Logger getLogger(String name) { Objects.requireNonNull(name); final Class caller = Reflection.getCallerClass(); - return LazyLoggers.getLogger(name, caller); + return LazyLoggers.getLogger(name, caller.getModule()); } /** @@ -1591,8 +1595,9 @@ public final class System { * @implSpec * The returned logger will perform message localization as specified * by {@link LoggerFinder#getLocalizedLogger(java.lang.String, - * java.util.ResourceBundle, java.lang.Class) - * LoggerFinder.getLocalizedLogger(name, bundle, caller}. + * java.util.ResourceBundle, java.lang.reflect.Module) + * LoggerFinder.getLocalizedLogger(name, bundle, module}, where + * {@code module} is the caller's module. * * @apiNote * This method is intended to be used after the system is fully initialized. @@ -1624,12 +1629,14 @@ public final class System { // Bootstrap sensitive classes in the JDK do not use resource bundles // when logging. This could be revisited later, if it needs to. if (sm != null) { - return AccessController.doPrivileged((PrivilegedAction) - () -> LoggerFinder.accessProvider().getLocalizedLogger(name, rb, caller), - null, - LoggerFinder.LOGGERFINDER_PERMISSION); + final PrivilegedAction pa = + () -> LoggerFinder.accessProvider() + .getLocalizedLogger(name, rb, caller.getModule()); + return AccessController.doPrivileged(pa, null, + LoggerFinder.LOGGERFINDER_PERMISSION); } - return LoggerFinder.accessProvider().getLocalizedLogger(name, rb, caller); + return LoggerFinder.accessProvider() + .getLocalizedLogger(name, rb, caller.getModule()); } /** diff --git a/jdk/src/java.base/share/classes/jdk/internal/logger/DefaultLoggerFinder.java b/jdk/src/java.base/share/classes/jdk/internal/logger/DefaultLoggerFinder.java index da255a3e2b8..e24fcad2bd4 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/logger/DefaultLoggerFinder.java +++ b/jdk/src/java.base/share/classes/jdk/internal/logger/DefaultLoggerFinder.java @@ -33,6 +33,9 @@ import java.util.function.Function; import java.lang.System.LoggerFinder; import java.lang.System.Logger; import java.lang.ref.ReferenceQueue; +import java.lang.reflect.Module; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.Collection; import java.util.ResourceBundle; @@ -129,41 +132,49 @@ public class DefaultLoggerFinder extends LoggerFinder { return w; } - final static SharedLoggers system = new SharedLoggers(); final static SharedLoggers application = new SharedLoggers(); } + public static boolean isSystem(Module m) { + ClassLoader cl = AccessController.doPrivileged(new PrivilegedAction<>() { + @Override + public ClassLoader run() { + return m.getClassLoader(); + } + }); + return cl == null; + } + @Override - public final Logger getLogger(String name, /* Module */ Class caller) { + public final Logger getLogger(String name, Module module) { checkPermission(); - return demandLoggerFor(name, caller); + return demandLoggerFor(name, module); } @Override public final Logger getLocalizedLogger(String name, ResourceBundle bundle, - /* Module */ Class caller) { - return super.getLocalizedLogger(name, bundle, caller); + Module module) { + return super.getLocalizedLogger(name, bundle, module); } - - /** - * Returns a {@link Logger logger} suitable for the caller usage. + * Returns a {@link Logger logger} suitable for use within the + * given {@code module}. * * @implSpec The default implementation for this method is to return a * simple logger that will print all messages of INFO level and above * to the console. That simple logger is not configurable. * * @param name The name of the logger. - * @param caller The class on behalf of which the logger is created. + * @param module The module on behalf of which the logger is created. * @return A {@link Logger logger} suitable for the application usage. * @throws SecurityException if the calling code does not have the * {@code RuntimePermission("loggerFinder")}. */ - protected Logger demandLoggerFor(String name, /* Module */ Class caller) { + protected Logger demandLoggerFor(String name, Module module) { checkPermission(); - if (caller.getClassLoader() == null) { + if (isSystem(module)) { return SharedLoggers.system.get(SimpleConsoleLogger::makeSimpleLogger, name); } else { return SharedLoggers.application.get(SimpleConsoleLogger::makeSimpleLogger, name); diff --git a/jdk/src/java.base/share/classes/jdk/internal/logger/LazyLoggers.java b/jdk/src/java.base/share/classes/jdk/internal/logger/LazyLoggers.java index 04b64ea98b1..6c65426ca8e 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/logger/LazyLoggers.java +++ b/jdk/src/java.base/share/classes/jdk/internal/logger/LazyLoggers.java @@ -31,6 +31,7 @@ import java.util.function.BiFunction; import java.lang.System.LoggerFinder; import java.lang.System.Logger; import java.lang.ref.WeakReference; +import java.lang.reflect.Module; import java.util.Objects; import jdk.internal.misc.VM; import sun.util.logging.PlatformLogger; @@ -59,15 +60,15 @@ public final class LazyLoggers { * A factory method to create an SPI logger. * Usually, this will be something like LazyLoggers::getSystemLogger. */ - final BiFunction, L> loggerSupplier; + final BiFunction loggerSupplier; - public LazyLoggerFactories(BiFunction, L> loggerSupplier) { + public LazyLoggerFactories(BiFunction loggerSupplier) { this(Objects.requireNonNull(loggerSupplier), (Void)null); } - private LazyLoggerFactories(BiFunction, L> loggerSupplier, + private LazyLoggerFactories(BiFunction loggerSupplier, Void unused) { this.loggerSupplier = loggerSupplier; } @@ -107,8 +108,8 @@ public final class LazyLoggers { // The factories that will be used to create the logger lazyly final LazyLoggerFactories factories; - // We need to pass the actual caller when creating the logger. - private final WeakReference> callerRef; + // We need to pass the actual caller module when creating the logger. + private final WeakReference moduleRef; // The name of the logger that will be created lazyly final String name; @@ -121,17 +122,17 @@ public final class LazyLoggers { private LazyLoggerAccessor(String name, LazyLoggerFactories factories, - Class caller) { + Module module) { this(Objects.requireNonNull(name), Objects.requireNonNull(factories), - Objects.requireNonNull(caller), null); + Objects.requireNonNull(module), null); } private LazyLoggerAccessor(String name, LazyLoggerFactories factories, - Class caller, Void unused) { + Module module, Void unused) { this.name = name; this.factories = factories; - this.callerRef = new WeakReference>(caller); + this.moduleRef = new WeakReference<>(module); } /** @@ -270,12 +271,12 @@ public final class LazyLoggers { // Creates the wrapped logger by invoking the SPI. Logger createLogger() { - final Class caller = callerRef.get(); - if (caller == null) { - throw new IllegalStateException("The class for which this logger" + final Module module = moduleRef.get(); + if (module == null) { + throw new IllegalStateException("The module for which this logger" + " was created has been garbage collected"); } - return this.factories.loggerSupplier.apply(name, caller); + return this.factories.loggerSupplier.apply(name, module); } /** @@ -289,8 +290,8 @@ public final class LazyLoggers { * @return A new LazyLoggerAccessor. */ public static LazyLoggerAccessor makeAccessor(String name, - LazyLoggerFactories factories, Class caller) { - return new LazyLoggerAccessor(name, factories, caller); + LazyLoggerFactories factories, Module module) { + return new LazyLoggerAccessor(name, factories, module); } } @@ -346,11 +347,11 @@ public final class LazyLoggers { // Avoid using lambda here as lazy loggers could be created early // in the bootstrap sequence... - private static final BiFunction, Logger> loggerSupplier = + private static final BiFunction loggerSupplier = new BiFunction<>() { @Override - public Logger apply(String name, Class caller) { - return LazyLoggers.getLoggerFromFinder(name, caller); + public Logger apply(String name, Module module) { + return LazyLoggers.getLoggerFromFinder(name, module); } }; @@ -367,8 +368,8 @@ public final class LazyLoggers { // logger provider until the VM has finished booting. // private static final class JdkLazyLogger extends LazyLoggerWrapper { - JdkLazyLogger(String name, Class caller) { - this(LazyLoggerAccessor.makeAccessor(name, factories, caller), + JdkLazyLogger(String name, Module module) { + this(LazyLoggerAccessor.makeAccessor(name, factories, module), (Void)null); } private JdkLazyLogger(LazyLoggerAccessor holder, Void unused) { @@ -380,16 +381,16 @@ public final class LazyLoggers { * Gets a logger from the LoggerFinder. Creates the actual concrete * logger. * @param name name of the logger - * @param caller class on behalf of which the logger is created + * @param module module on behalf of which the logger is created * @return The logger returned by the LoggerFinder. */ - static Logger getLoggerFromFinder(String name, Class caller) { + static Logger getLoggerFromFinder(String name, Module module) { final SecurityManager sm = System.getSecurityManager(); if (sm == null) { - return accessLoggerFinder().getLogger(name, caller); + return accessLoggerFinder().getLogger(name, module); } else { return AccessController.doPrivileged((PrivilegedAction) - () -> {return accessLoggerFinder().getLogger(name, caller);}, + () -> {return accessLoggerFinder().getLogger(name, module);}, null, LOGGERFINDER_PERMISSION); } } @@ -398,22 +399,22 @@ public final class LazyLoggers { * Returns a (possibly lazy) Logger for the caller. * * @param name the logger name - * @param caller The class on behalf of which the logger is created. - * If the caller is not loaded from the Boot ClassLoader, + * @param module The module on behalf of which the logger is created. + * If the module is not loaded from the Boot ClassLoader, * the LoggerFinder is accessed and the logger returned - * by {@link LoggerFinder#getLogger(java.lang.String, java.lang.Class)} + * by {@link LoggerFinder#getLogger(java.lang.String, java.lang.reflect.Module)} * is returned to the caller directly. * Otherwise, the logger returned by - * {@link #getLazyLogger(java.lang.String, java.lang.Class)} + * {@link #getLazyLogger(java.lang.String, java.lang.reflect.Module)} * is returned to the caller. * * @return a (possibly lazy) Logger instance. */ - public static final Logger getLogger(String name, Class caller) { - if (caller.getClassLoader() == null) { - return getLazyLogger(name, caller); + public static final Logger getLogger(String name, Module module) { + if (DefaultLoggerFinder.isSystem(module)) { + return getLazyLogger(name, module); } else { - return getLoggerFromFinder(name, caller); + return getLoggerFromFinder(name, module); } } @@ -423,10 +424,10 @@ public final class LazyLoggers { * returned by {@link BootstrapLogger#useLazyLoggers()}. * * @param name the logger name - * @param caller the class on behalf of which the logger is created. + * @param module the module on behalf of which the logger is created. * @return a (possibly lazy) Logger instance. */ - public static final Logger getLazyLogger(String name, Class caller) { + public static final Logger getLazyLogger(String name, Module module) { // BootstrapLogger has the logic to determine whether a LazyLogger // should be used. Usually, it is worth it only if: @@ -438,10 +439,10 @@ public final class LazyLoggers { // configuration, we're not going to delay the creation of loggers... final boolean useLazyLogger = BootstrapLogger.useLazyLoggers(); if (useLazyLogger) { - return new JdkLazyLogger(name, caller); + return new JdkLazyLogger(name, module); } else { // Directly invoke the LoggerFinder. - return getLoggerFromFinder(name, caller); + return getLoggerFromFinder(name, module); } } diff --git a/jdk/src/java.base/share/classes/sun/util/logging/PlatformLogger.java b/jdk/src/java.base/share/classes/sun/util/logging/PlatformLogger.java index 655dc96a299..e8df610c4c1 100644 --- a/jdk/src/java.base/share/classes/sun/util/logging/PlatformLogger.java +++ b/jdk/src/java.base/share/classes/sun/util/logging/PlatformLogger.java @@ -286,12 +286,15 @@ public class PlatformLogger { } if (log == null) { log = new PlatformLogger(PlatformLogger.Bridge.convert( - // We pass PlatformLogger.class rather than the actual caller + // We pass PlatformLogger.class.getModule() (java.base) + // rather than the actual module of the caller // because we want PlatformLoggers to be system loggers: we // won't need to resolve any resource bundles anyway. // Note: Many unit tests depend on the fact that - // PlatformLogger.getLoggerFromFinder is not caller sensitive. - LazyLoggers.getLazyLogger(name, PlatformLogger.class))); + // PlatformLogger.getLoggerFromFinder is not caller + // sensitive, and this strategy ensure that the tests + // still pass. + LazyLoggers.getLazyLogger(name, PlatformLogger.class.getModule()))); loggers.put(name, new WeakReference<>(log)); } return log; 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 e15add5a4f8..6d0cc8de4d6 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 @@ -43,6 +43,8 @@ import java.util.stream.Stream; import jdk.internal.misc.JavaAWTAccess; import jdk.internal.misc.SharedSecrets; import sun.util.logging.internal.LoggingProviderImpl; +import java.lang.reflect.Module; +import static jdk.internal.logger.DefaultLoggerFinder.isSystem; /** * There is a single global LogManager object that is used to @@ -503,10 +505,16 @@ public class LogManager { // as a LogManager subclass may override the addLogger, getLogger, // readConfiguration, and other methods. Logger demandLogger(String name, String resourceBundleName, Class caller) { + final Module module = caller == null ? null : caller.getModule(); + return demandLogger(name, resourceBundleName, module); + } + + Logger demandLogger(String name, String resourceBundleName, Module module) { Logger result = getLogger(name); if (result == null) { // only allocate the new logger once - Logger newLogger = new Logger(name, resourceBundleName, caller, this, false); + Logger newLogger = new Logger(name, resourceBundleName, + module == null ? null : module, this, false); do { if (addLogger(newLogger)) { // We successfully added the new Logger that we @@ -532,9 +540,14 @@ public class LogManager { } Logger demandSystemLogger(String name, String resourceBundleName, Class caller) { + final Module module = caller == null ? null : caller.getModule(); + return demandSystemLogger(name, resourceBundleName, module); + } + + Logger demandSystemLogger(String name, String resourceBundleName, Module module) { // Add a system logger in the system context's namespace final Logger sysLogger = getSystemContext() - .demandLogger(name, resourceBundleName, caller); + .demandLogger(name, resourceBundleName, module); // Add the system logger to the LogManager's namespace if not exist // so that there is only one single logger of the given name. @@ -619,11 +632,11 @@ public class LogManager { return global; } - Logger demandLogger(String name, String resourceBundleName, Class caller) { + Logger demandLogger(String name, String resourceBundleName, Module module) { // a LogManager subclass may have its own implementation to add and // get a Logger. So delegate to the LogManager to do the work. final LogManager owner = getOwner(); - return owner.demandLogger(name, resourceBundleName, caller); + return owner.demandLogger(name, resourceBundleName, module); } @@ -907,11 +920,13 @@ public class LogManager { // one single logger of the given name. System loggers are visible // to applications unless a logger of the same name has been added. @Override - Logger demandLogger(String name, String resourceBundleName, Class caller) { + Logger demandLogger(String name, String resourceBundleName, + Module module) { Logger result = findLogger(name); if (result == null) { // only allocate the new system logger once - Logger newLogger = new Logger(name, resourceBundleName, caller, getOwner(), true); + Logger newLogger = new Logger(name, resourceBundleName, + module, getOwner(), true); do { if (addLocalLogger(newLogger)) { // We successfully added the new Logger that we @@ -2622,18 +2637,18 @@ public class LogManager { } /** - * Demands a logger on behalf of the given {@code caller}. + * Demands a logger on behalf of the given {@code module}. *

- * If a named logger suitable for the given caller is found + * If a named logger suitable for the given module is found * returns it. - * Otherwise, creates a new logger suitable for the given caller. + * Otherwise, creates a new logger suitable for the given module. * * @param name The logger name. - * @param caller The caller on which behalf the logger is created/retrieved. - * @return A logger for the given {@code caller}. + * @param module The module on which behalf the logger is created/retrieved. + * @return A logger for the given {@code module}. * * @throws NullPointerException if {@code name} is {@code null} - * or {@code caller} is {@code null}. + * or {@code module} is {@code null}. * @throws IllegalArgumentException if {@code manager} is not the default * LogManager. * @throws SecurityException if a security manager is present and the @@ -2641,7 +2656,7 @@ public class LogManager { * {@link LoggingPermission LoggingPermission("demandLogger", null)}. */ @Override - public Logger demandLoggerFor(LogManager manager, String name, /* Module */ Class caller) { + public Logger demandLoggerFor(LogManager manager, String name, Module module) { if (manager != getLogManager()) { // having LogManager as parameter just ensures that the // caller will have initialized the LogManager before reaching @@ -2649,15 +2664,16 @@ public class LogManager { throw new IllegalArgumentException("manager"); } Objects.requireNonNull(name); + Objects.requireNonNull(module); SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(controlPermission); } - if (caller.getClassLoader() == null) { + if (isSystem(module)) { return manager.demandSystemLogger(name, - Logger.SYSTEM_LOGGER_RB_NAME, caller); + Logger.SYSTEM_LOGGER_RB_NAME, module); } else { - return manager.demandLogger(name, null, caller); + return manager.demandLogger(name, null, module); } } 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 d8ada0c4c08..ca055b06af1 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 @@ -40,6 +40,7 @@ import java.util.concurrent.CopyOnWriteArrayList; import java.util.function.Supplier; import jdk.internal.reflect.CallerSensitive; import jdk.internal.reflect.Reflection; +import static jdk.internal.logger.DefaultLoggerFinder.isSystem; /** * A Logger object is used to log messages for a specific @@ -379,7 +380,8 @@ public class Logger { this(name, resourceBundleName, null, LogManager.getLogManager(), false); } - Logger(String name, String resourceBundleName, Class caller, LogManager manager, boolean isSystemLogger) { + Logger(String name, String resourceBundleName, Module caller, + LogManager manager, boolean isSystemLogger) { this.manager = manager; this.isSystemLogger = isSystemLogger; setupResourceInfo(resourceBundleName, caller); @@ -387,10 +389,7 @@ public class Logger { levelValue = Level.INFO.intValue(); } - private void setCallerModuleRef(Class caller) { - Module callerModule = ((caller != null) - ? caller.getModule() - : null); + private void setCallerModuleRef(Module callerModule) { if (callerModule != null) { this.callerModuleRef = new WeakReference<>(callerModule); } @@ -618,7 +617,7 @@ public class Logger { // all loggers in the system context will default to // the system logger's resource bundle - therefore the caller won't // be needed and can be null. - Logger result = manager.demandSystemLogger(name, SYSTEM_LOGGER_RB_NAME, null); + Logger result = manager.demandSystemLogger(name, SYSTEM_LOGGER_RB_NAME, (Module)null); return result; } @@ -681,8 +680,10 @@ public class Logger { LogManager manager = LogManager.getLogManager(); // cleanup some Loggers that have been GC'ed manager.drainLoggerRefQueueBounded(); + final Class callerClass = Reflection.getCallerClass(); + final Module module = callerClass.getModule(); Logger result = new Logger(null, resourceBundleName, - Reflection.getCallerClass(), manager, false); + module, manager, false); result.anonymous = true; Logger root = manager.getLogger(""); result.doSetParent(root); @@ -2046,6 +2047,11 @@ public class Logger { } } + private void setupResourceInfo(String name, Class caller) { + final Module module = caller == null ? null : caller.getModule(); + setupResourceInfo(name, module); + } + // Private utility method to initialize our one entry // resource bundle name cache and the callers Module // Note: for consistency reasons, we are careful to check @@ -2053,7 +2059,7 @@ public class Logger { // resourceBundleName field. // Synchronized to prevent races in setting the fields. private synchronized void setupResourceInfo(String name, - Class callerClass) { + Module callerModule) { final LoggerBundle lb = loggerBundle; if (lb.resourceBundleName != null) { // this Logger already has a ResourceBundle @@ -2072,8 +2078,9 @@ public class Logger { return; } - setCallerModuleRef(callerClass); - if (isSystemLogger && (callerClass != null && callerClass.getClassLoader() != null)) { + setCallerModuleRef(callerModule); + + if (isSystemLogger && (callerModule != null && !isSystem(callerModule))) { checkPermission(); } diff --git a/jdk/src/java.logging/share/classes/sun/util/logging/internal/LoggingProviderImpl.java b/jdk/src/java.logging/share/classes/sun/util/logging/internal/LoggingProviderImpl.java index 4fcf40d2daa..1ccf2cf7c92 100644 --- a/jdk/src/java.logging/share/classes/sun/util/logging/internal/LoggingProviderImpl.java +++ b/jdk/src/java.logging/share/classes/sun/util/logging/internal/LoggingProviderImpl.java @@ -32,6 +32,7 @@ import java.util.ResourceBundle; import java.util.function.Supplier; import java.lang.System.LoggerFinder; import java.lang.System.Logger; +import java.lang.reflect.Module; import java.util.Objects; import java.util.logging.LogManager; import jdk.internal.logger.DefaultLoggerFinder; @@ -398,21 +399,20 @@ public final class LoggingProviderImpl extends DefaultLoggerFinder { } /** - * Creates a java.util.logging.Logger for the given caller. + * Creates a java.util.logging.Logger for the given module. * @param name the logger name. - * @param caller the caller for which the logger should be created. - * @return a Logger suitable for use in the given caller. + * @param module the module for which the logger should be created. + * @return a Logger suitable for use in the given module. */ private static java.util.logging.Logger demandJULLoggerFor(final String name, - /* Module */ - final Class caller) { + Module module) { final LogManager manager = LogManager.getLogManager(); final SecurityManager sm = System.getSecurityManager(); if (sm == null) { - return logManagerAccess.demandLoggerFor(manager, name, caller); + return logManagerAccess.demandLoggerFor(manager, name, module); } else { final PrivilegedAction pa = - () -> logManagerAccess.demandLoggerFor(manager, name, caller); + () -> logManagerAccess.demandLoggerFor(manager, name, module); return AccessController.doPrivileged(pa, null, LOGGING_CONTROL_PERMISSION); } } @@ -429,17 +429,17 @@ public final class LoggingProviderImpl extends DefaultLoggerFinder { * {@code RuntimePermission("loggerFinder")}. */ @Override - protected Logger demandLoggerFor(String name, /* Module */ Class caller) { + protected Logger demandLoggerFor(String name, Module module) { final SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(LOGGERFINDER_PERMISSION); } - return JULWrapper.of(demandJULLoggerFor(name,caller)); + return JULWrapper.of(demandJULLoggerFor(name,module)); } public static interface LogManagerAccess { java.util.logging.Logger demandLoggerFor(LogManager manager, - String name, /* Module */ Class caller); + String name, Module module); } // Hook for tests diff --git a/jdk/test/java/lang/System/Logger/custom/CustomLoggerTest.java b/jdk/test/java/lang/System/Logger/custom/CustomLoggerTest.java index 2506905ec7c..d1653ca5f1e 100644 --- a/jdk/test/java/lang/System/Logger/custom/CustomLoggerTest.java +++ b/jdk/test/java/lang/System/Logger/custom/CustomLoggerTest.java @@ -46,6 +46,8 @@ import java.lang.System.LoggerFinder; import java.lang.System.Logger; import java.lang.System.Logger.Level; import java.util.stream.Stream; +import java.lang.reflect.Module; +import java.security.AllPermission; /** * @test @@ -70,6 +72,12 @@ public class CustomLoggerTest { return new AtomicBoolean(false); } }; + static final ThreadLocal allowAll = new ThreadLocal() { + @Override + protected AtomicBoolean initialValue() { + return new AtomicBoolean(false); + } + }; public static class MyBundle extends ResourceBundle { @@ -241,7 +249,7 @@ public class CustomLoggerTest { } @Override - public Logger getLogger(String name, Class caller) { + public Logger getLogger(String name, Module caller) { // We should check the permission to obey the API contract, but // what happens if we don't? // This is the main difference compared with what we test in @@ -251,8 +259,13 @@ public class CustomLoggerTest { sm.checkPermission(SimplePolicy.LOGGERFINDER_PERMISSION); } - PrivilegedAction pa = () -> caller.getClassLoader(); - ClassLoader callerLoader = AccessController.doPrivileged(pa); + final boolean before = allowAll.get().getAndSet(true); + final ClassLoader callerLoader; + try { + callerLoader = caller.getClassLoader(); + } finally { + allowAll.get().set(before); + } if (callerLoader == null) { return system.computeIfAbsent(name, (n) -> new LoggerImpl(n)); } else { @@ -267,7 +280,7 @@ public class CustomLoggerTest { static void setSecurityManager() { if (System.getSecurityManager() == null) { - Policy.setPolicy(new SimplePolicy(allowControl)); + Policy.setPolicy(new SimplePolicy(allowControl, allowAll)); System.setSecurityManager(new SecurityManager()); } } @@ -284,9 +297,9 @@ public class CustomLoggerTest { BaseLoggerFinder provider = BaseLoggerFinder.class.cast(LoggerFinder.getLoggerFinder()); BaseLoggerFinder.LoggerImpl appSink = - BaseLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", CustomLoggerTest.class)); + BaseLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", CustomLoggerTest.class.getModule())); BaseLoggerFinder.LoggerImpl sysSink = - BaseLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", Thread.class)); + BaseLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", Thread.class.getModule())); Stream.of(args).map(TestCases::valueOf).forEach((testCase) -> { @@ -695,34 +708,46 @@ public class CustomLoggerTest { static final RuntimePermission LOGGERFINDER_PERMISSION = new RuntimePermission("loggerFinder"); final Permissions permissions; + final Permissions controlPermissions; final Permissions allPermissions; final ThreadLocal allowControl; - public SimplePolicy(ThreadLocal allowControl) { + final ThreadLocal allowAll; + public SimplePolicy(ThreadLocal allowControl, ThreadLocal allowAll) { this.allowControl = allowControl; + this.allowAll = allowAll; permissions = new Permissions(); // these are used for configuring the test itself... + controlPermissions = new Permissions(); + controlPermissions.add(LOGGERFINDER_PERMISSION); + + // these are used for simulating a doPrivileged call from + // a class in the BCL allPermissions = new Permissions(); - allPermissions.add(LOGGERFINDER_PERMISSION); + allPermissions.add(new AllPermission()); + + } + + Permissions permissions() { + if (allowAll.get().get()) return allPermissions; + if (allowControl.get().get()) return controlPermissions; + return permissions; } @Override public boolean implies(ProtectionDomain domain, Permission permission) { - if (allowControl.get().get()) return allPermissions.implies(permission); - return permissions.implies(permission); + return permissions().implies(permission); } @Override public PermissionCollection getPermissions(CodeSource codesource) { - return new PermissionsBuilder().addAll(allowControl.get().get() - ? allPermissions : permissions).toPermissions(); + return new PermissionsBuilder().addAll(permissions()).toPermissions(); } @Override public PermissionCollection getPermissions(ProtectionDomain domain) { - return new PermissionsBuilder().addAll(allowControl.get().get() - ? allPermissions : permissions).toPermissions(); + return new PermissionsBuilder().addAll(permissions()).toPermissions(); } } } diff --git a/jdk/test/java/lang/System/LoggerFinder/BaseLoggerFinderTest/BaseLoggerFinder.java b/jdk/test/java/lang/System/LoggerFinder/BaseLoggerFinderTest/BaseLoggerFinder.java index 30daa232248..3db7cef65f8 100644 --- a/jdk/test/java/lang/System/LoggerFinder/BaseLoggerFinderTest/BaseLoggerFinder.java +++ b/jdk/test/java/lang/System/LoggerFinder/BaseLoggerFinderTest/BaseLoggerFinder.java @@ -25,13 +25,14 @@ import java.security.AccessController; import java.security.PrivilegedAction; import java.lang.System.LoggerFinder; import java.lang.System.Logger; +import java.lang.reflect.Module; public class BaseLoggerFinder extends LoggerFinder implements TestLoggerFinder { static final RuntimePermission LOGGERFINDER_PERMISSION = new RuntimePermission("loggerFinder"); @Override - public Logger getLogger(String name, Class caller) { + public Logger getLogger(String name, Module caller) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(LOGGERFINDER_PERMISSION); diff --git a/jdk/test/java/lang/System/LoggerFinder/BaseLoggerFinderTest/BaseLoggerFinderTest.java b/jdk/test/java/lang/System/LoggerFinder/BaseLoggerFinderTest/BaseLoggerFinderTest.java index 2cb57d78559..b3805919e53 100644 --- a/jdk/test/java/lang/System/LoggerFinder/BaseLoggerFinderTest/BaseLoggerFinderTest.java +++ b/jdk/test/java/lang/System/LoggerFinder/BaseLoggerFinderTest/BaseLoggerFinderTest.java @@ -182,8 +182,8 @@ public class BaseLoggerFinderTest { TestLoggerFinder.LoggerImpl appLogger1 = null; try { appLogger1 = - TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", BaseLoggerFinderTest.class)); - loggerDescMap.put(appLogger1, "provider.getLogger(\"foo\", BaseLoggerFinderTest.class)"); + TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", BaseLoggerFinderTest.class.getModule())); + loggerDescMap.put(appLogger1, "provider.getLogger(\"foo\", BaseLoggerFinderTest.class.getModule())"); if (!hasRequiredPermissions) { throw new RuntimeException("Managed to obtain a logger without permission"); } @@ -199,8 +199,8 @@ public class BaseLoggerFinderTest { allowControl.get().set(true); try { appLogger1 = - TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", BaseLoggerFinderTest.class)); - loggerDescMap.put(appLogger1, "provider.getLogger(\"foo\", BaseLoggerFinderTest.class)"); + TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", BaseLoggerFinderTest.class.getModule())); + loggerDescMap.put(appLogger1, "provider.getLogger(\"foo\", BaseLoggerFinderTest.class.getModule())"); } finally { allowControl.get().set(old); } @@ -208,8 +208,8 @@ public class BaseLoggerFinderTest { TestLoggerFinder.LoggerImpl sysLogger1 = null; try { - sysLogger1 = TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", Thread.class)); - loggerDescMap.put(sysLogger1, "provider.getLogger(\"foo\", Thread.class)"); + sysLogger1 = TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", Thread.class.getModule())); + loggerDescMap.put(sysLogger1, "provider.getLogger(\"foo\", Thread.class.getModule())"); if (!hasRequiredPermissions) { throw new RuntimeException("Managed to obtain a system logger without permission"); } @@ -224,8 +224,8 @@ public class BaseLoggerFinderTest { final boolean old = allowControl.get().get(); allowControl.get().set(true); try { - sysLogger1 = TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", Thread.class)); - loggerDescMap.put(sysLogger1, "provider.getLogger(\"foo\", Thread.class)"); + sysLogger1 = TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", Thread.class.getModule())); + loggerDescMap.put(sysLogger1, "provider.getLogger(\"foo\", Thread.class.getModule())"); } finally { allowControl.get().set(old); } @@ -254,8 +254,8 @@ public class BaseLoggerFinderTest { // callers and non system callers Logger appLogger2 = null; try { - appLogger2 = provider.getLocalizedLogger("foo", loggerBundle, BaseLoggerFinderTest.class); - loggerDescMap.put(appLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, BaseLoggerFinderTest.class)"); + appLogger2 = provider.getLocalizedLogger("foo", loggerBundle, BaseLoggerFinderTest.class.getModule()); + loggerDescMap.put(appLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, BaseLoggerFinderTest.class.getModule())"); if (!hasRequiredPermissions) { throw new RuntimeException("Managed to obtain a logger without permission"); } @@ -270,8 +270,8 @@ public class BaseLoggerFinderTest { final boolean old = allowControl.get().get(); allowControl.get().set(true); try { - appLogger2 = provider.getLocalizedLogger("foo", loggerBundle, BaseLoggerFinderTest.class); - loggerDescMap.put(appLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, BaseLoggerFinderTest.class)"); + appLogger2 = provider.getLocalizedLogger("foo", loggerBundle, BaseLoggerFinderTest.class.getModule()); + loggerDescMap.put(appLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, BaseLoggerFinderTest.class.getModule())"); } finally { allowControl.get().set(old); } @@ -279,8 +279,8 @@ public class BaseLoggerFinderTest { Logger sysLogger2 = null; try { - sysLogger2 = provider.getLocalizedLogger("foo", loggerBundle, Thread.class); - loggerDescMap.put(sysLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, Thread.class)"); + sysLogger2 = provider.getLocalizedLogger("foo", loggerBundle, Thread.class.getModule()); + loggerDescMap.put(sysLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, Thread.class.getModule())"); if (!hasRequiredPermissions) { throw new RuntimeException("Managed to obtain a system logger without permission"); } @@ -295,8 +295,8 @@ public class BaseLoggerFinderTest { final boolean old = allowControl.get().get(); allowControl.get().set(true); try { - sysLogger2 = provider.getLocalizedLogger("foo", loggerBundle, Thread.class); - loggerDescMap.put(sysLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, Thread.class))"); + sysLogger2 = provider.getLocalizedLogger("foo", loggerBundle, Thread.class.getModule()); + loggerDescMap.put(sysLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, Thread.class.getModule()))"); } finally { allowControl.get().set(old); } diff --git a/jdk/test/java/lang/System/LoggerFinder/BaseLoggerFinderTest/TestLoggerFinder.java b/jdk/test/java/lang/System/LoggerFinder/BaseLoggerFinderTest/TestLoggerFinder.java index 716f8b8faec..cb86e513f90 100644 --- a/jdk/test/java/lang/System/LoggerFinder/BaseLoggerFinderTest/TestLoggerFinder.java +++ b/jdk/test/java/lang/System/LoggerFinder/BaseLoggerFinderTest/TestLoggerFinder.java @@ -30,6 +30,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicLong; import java.util.function.Supplier; import java.lang.System.Logger; +import java.lang.reflect.Module; /** * What our test provider needs to implement. @@ -176,6 +177,6 @@ public interface TestLoggerFinder { } } - public Logger getLogger(String name, Class caller); - public Logger getLocalizedLogger(String name, ResourceBundle bundle, Class caller); + public Logger getLogger(String name, Module caller); + public Logger getLocalizedLogger(String name, ResourceBundle bundle, Module caller); } diff --git a/jdk/test/java/lang/System/LoggerFinder/DefaultLoggerFinderTest/DefaultLoggerFinderTest.java b/jdk/test/java/lang/System/LoggerFinder/DefaultLoggerFinderTest/DefaultLoggerFinderTest.java index 50c789b5d60..43150eb0f00 100644 --- a/jdk/test/java/lang/System/LoggerFinder/DefaultLoggerFinderTest/DefaultLoggerFinderTest.java +++ b/jdk/test/java/lang/System/LoggerFinder/DefaultLoggerFinderTest/DefaultLoggerFinderTest.java @@ -364,8 +364,8 @@ public class DefaultLoggerFinderTest { Logger appLogger1 = null; try { - appLogger1 = provider.getLogger("foo", DefaultLoggerFinderTest.class); - loggerDescMap.put(appLogger1, "provider.getApplicationLogger(\"foo\")"); + appLogger1 = provider.getLogger("foo", DefaultLoggerFinderTest.class.getModule()); + loggerDescMap.put(appLogger1, "provider.getLogger(\"foo\", DefaultLoggerFinderTest.class.getModule())"); if (!hasRequiredPermissions) { throw new RuntimeException("Managed to obtain a logger without permission"); } @@ -380,8 +380,8 @@ public class DefaultLoggerFinderTest { boolean old = allowControl.get().get(); allowControl.get().set(true); try { - appLogger1 =provider.getLogger("foo", DefaultLoggerFinderTest.class); - loggerDescMap.put(appLogger1, "provider.getApplicationLogger(\"foo\")"); + appLogger1 =provider.getLogger("foo", DefaultLoggerFinderTest.class.getModule()); + loggerDescMap.put(appLogger1, "provider.getLogger(\"foo\", DefaultLoggerFinderTest.class.getModule())"); } finally { allowControl.get().set(old); } @@ -389,8 +389,8 @@ public class DefaultLoggerFinderTest { Logger sysLogger1 = null; try { - sysLogger1 = provider.getLogger("foo", Thread.class); - loggerDescMap.put(sysLogger1, "provider.getSystemLogger(\"foo\")"); + sysLogger1 = provider.getLogger("foo", Thread.class.getModule()); + loggerDescMap.put(sysLogger1, "provider.getLogger(\"foo\", Thread.class.getModule())"); if (!hasRequiredPermissions) { throw new RuntimeException("Managed to obtain a system logger without permission"); } @@ -405,8 +405,8 @@ public class DefaultLoggerFinderTest { boolean old = allowControl.get().get(); allowControl.get().set(true); try { - sysLogger1 = provider.getLogger("foo", Thread.class); - loggerDescMap.put(sysLogger1, "provider.getSystemLogger(\"foo\")"); + sysLogger1 = provider.getLogger("foo", Thread.class.getModule()); + loggerDescMap.put(sysLogger1, "provider.getLogger(\"foo\", Thread.class.getModule())"); } finally { allowControl.get().set(old); } @@ -417,8 +417,8 @@ public class DefaultLoggerFinderTest { Logger appLogger2 = null; try { - appLogger2 = provider.getLocalizedLogger("foo", loggerBundle, DefaultLoggerFinderTest.class); - loggerDescMap.put(appLogger2, "provider.getLocalizedApplicationLogger(\"foo\", loggerBundle)"); + appLogger2 = provider.getLocalizedLogger("foo", loggerBundle, DefaultLoggerFinderTest.class.getModule()); + loggerDescMap.put(appLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, DefaultLoggerFinderTest.class.getModule())"); if (!hasRequiredPermissions) { throw new RuntimeException("Managed to obtain a logger without permission"); } @@ -433,8 +433,8 @@ public class DefaultLoggerFinderTest { boolean old = allowControl.get().get(); allowControl.get().set(true); try { - appLogger2 = provider.getLocalizedLogger("foo", loggerBundle, DefaultLoggerFinderTest.class); - loggerDescMap.put(appLogger2, "provider.getLocalizedApplicationLogger(\"foo\", loggerBundle)"); + appLogger2 = provider.getLocalizedLogger("foo", loggerBundle, DefaultLoggerFinderTest.class.getModule()); + loggerDescMap.put(appLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, DefaultLoggerFinderTest.class.getModule())"); } finally { allowControl.get().set(old); } @@ -442,8 +442,8 @@ public class DefaultLoggerFinderTest { Logger sysLogger2 = null; try { - sysLogger2 = provider.getLocalizedLogger("foo", loggerBundle, Thread.class); - loggerDescMap.put(sysLogger2, "provider.getLocalizedSystemLogger(\"foo\", loggerBundle)"); + sysLogger2 = provider.getLocalizedLogger("foo", loggerBundle, Thread.class.getModule()); + loggerDescMap.put(sysLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, Thread.class.getModule())"); if (!hasRequiredPermissions) { throw new RuntimeException("Managed to obtain a system logger without permission"); } @@ -458,8 +458,8 @@ public class DefaultLoggerFinderTest { boolean old = allowControl.get().get(); allowControl.get().set(true); try { - sysLogger2 = provider.getLocalizedLogger("foo", loggerBundle, Thread.class); - loggerDescMap.put(sysLogger2, "provider.getLocalizedSystemLogger(\"foo\", loggerBundle)"); + sysLogger2 = provider.getLocalizedLogger("foo", loggerBundle, Thread.class.getModule()); + loggerDescMap.put(sysLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, Thread.class.getModule())"); } finally { allowControl.get().set(old); } diff --git a/jdk/test/java/lang/System/LoggerFinder/internal/BaseDefaultLoggerFinderTest/BaseDefaultLoggerFinderTest.java b/jdk/test/java/lang/System/LoggerFinder/internal/BaseDefaultLoggerFinderTest/BaseDefaultLoggerFinderTest.java index ddf1be7731c..ab80d0f8bc6 100644 --- a/jdk/test/java/lang/System/LoggerFinder/internal/BaseDefaultLoggerFinderTest/BaseDefaultLoggerFinderTest.java +++ b/jdk/test/java/lang/System/LoggerFinder/internal/BaseDefaultLoggerFinderTest/BaseDefaultLoggerFinderTest.java @@ -55,6 +55,7 @@ import java.util.function.Function; import jdk.internal.logger.DefaultLoggerFinder; import jdk.internal.logger.SimpleConsoleLogger; import sun.util.logging.PlatformLogger; +import java.lang.reflect.Module; /** * @test @@ -112,10 +113,10 @@ public class BaseDefaultLoggerFinderTest { public final static AtomicLong sequencer = new AtomicLong(); - public Logger getLogger(String name, Class caller); - public Logger getLocalizedLogger(String name, ResourceBundle bundle, Class caller); - void setLevel(Logger logger, Level level, Class caller); - void setLevel(Logger logger, PlatformLogger.Level level, Class caller); + public Logger getLogger(String name, Module caller); + public Logger getLocalizedLogger(String name, ResourceBundle bundle, Module caller); + void setLevel(Logger logger, Level level, Module caller); + void setLevel(Logger logger, PlatformLogger.Level level, Module caller); PlatformLogger.Bridge asPlatformLoggerBridge(Logger logger); } @@ -130,7 +131,7 @@ public class BaseDefaultLoggerFinderTest { } @Override - public void setLevel(Logger logger, Level level, Class caller) { + public void setLevel(Logger logger, Level level, Module caller) { PrivilegedAction pa = () -> { setLevel(logger, PlatformLogger.toPlatformLevel(level), caller); return null; @@ -139,7 +140,7 @@ public class BaseDefaultLoggerFinderTest { } @Override - public void setLevel(Logger logger, PlatformLogger.Level level, Class caller) { + public void setLevel(Logger logger, PlatformLogger.Level level, Module caller) { PrivilegedAction pa = () -> demandLoggerFor(logger.getName(), caller); Logger impl = AccessController.doPrivileged(pa); SimpleConsoleLogger.class.cast(impl) @@ -606,11 +607,12 @@ public class BaseDefaultLoggerFinderTest { String name, ResourceBundle loggerBundle, Logger logger, - Class caller) { + Class callerClass) { System.out.println("Testing " + loggerDescMap.get(logger) + " [" + logger +"]"); AtomicLong sequencer = TestLoggerFinder.sequencer; + Module caller = callerClass.getModule(); Foo foo = new Foo(); String fooMsg = foo.toString(); for (Level loggerLevel : Level.values()) { diff --git a/jdk/test/java/lang/System/LoggerFinder/internal/BaseLoggerBridgeTest/BaseLoggerBridgeTest.java b/jdk/test/java/lang/System/LoggerFinder/internal/BaseLoggerBridgeTest/BaseLoggerBridgeTest.java index 5319f0e5fbf..d28481c305f 100644 --- a/jdk/test/java/lang/System/LoggerFinder/internal/BaseLoggerBridgeTest/BaseLoggerBridgeTest.java +++ b/jdk/test/java/lang/System/LoggerFinder/internal/BaseLoggerBridgeTest/BaseLoggerBridgeTest.java @@ -47,6 +47,7 @@ import java.lang.System.LoggerFinder; import java.lang.System.Logger; import java.lang.System.Logger.Level; import java.util.stream.Stream; +import java.lang.reflect.Module; /** * @test @@ -209,8 +210,6 @@ public class BaseLoggerBridgeTest { return Arrays.deepToString(toArray(false)); } - - @Override public boolean equals(Object obj) { return obj instanceof LogEvent @@ -342,15 +341,15 @@ public class BaseLoggerBridgeTest { } - public Logger getLogger(String name, Class caller); - public Logger getLocalizedLogger(String name, ResourceBundle bundle, Class caller); + public Logger getLogger(String name, Module caller); + public Logger getLocalizedLogger(String name, ResourceBundle bundle, Module caller); } public static class BaseLoggerFinder extends LoggerFinder implements TestLoggerFinder { static final RuntimePermission LOGGERFINDER_PERMISSION = new RuntimePermission("loggerFinder"); @Override - public Logger getLogger(String name, Class caller) { + public Logger getLogger(String name, Module caller) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(LOGGERFINDER_PERMISSION); @@ -375,7 +374,7 @@ public class BaseLoggerBridgeTest { } } - static Logger getLogger(String name, Class caller) { + static Logger getLogger(String name, Module caller) { boolean old = allowAll.get().get(); allowAccess.get().set(true); try { @@ -465,7 +464,7 @@ public class BaseLoggerBridgeTest { TestLoggerFinder.LoggerImpl appSink = null; try { - appSink = TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", BaseLoggerBridgeTest.class)); + appSink = TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", BaseLoggerBridgeTest.class.getModule())); if (!hasRequiredPermissions) { throw new RuntimeException("Managed to obtain a system logger without permission"); } @@ -480,7 +479,7 @@ public class BaseLoggerBridgeTest { boolean old = allowControl.get().get(); allowControl.get().set(true); try { - appSink = TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", BaseLoggerBridgeTest.class)); + appSink = TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", BaseLoggerBridgeTest.class.getModule())); } finally { allowControl.get().set(old); } @@ -489,7 +488,7 @@ public class BaseLoggerBridgeTest { TestLoggerFinder.LoggerImpl sysSink = null; try { - sysSink = TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", Thread.class)); + sysSink = TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", Thread.class.getModule())); if (!hasRequiredPermissions) { throw new RuntimeException("Managed to obtain a system logger without permission"); } @@ -527,13 +526,13 @@ public class BaseLoggerBridgeTest { Logger sysLogger1 = null; try { - sysLogger1 = getLogger("foo", Thread.class); + sysLogger1 = getLogger("foo", Thread.class.getModule()); loggerDescMap.put(sysLogger1, - "jdk.internal.logger.LazyLoggers.getLogger(\"foo\", Thread.class)"); + "jdk.internal.logger.LazyLoggers.getLogger(\"foo\", Thread.class.getModule())"); if (!hasRequiredPermissions) { // check that the provider would have thrown an exception - provider.getLogger("foo", Thread.class); + provider.getLogger("foo", Thread.class.getModule()); throw new RuntimeException("Managed to obtain a system logger without permission"); } } catch (AccessControlException acx) { @@ -572,8 +571,8 @@ public class BaseLoggerBridgeTest { Logger sysLogger2 = null; try { - sysLogger2 = provider.getLocalizedLogger("foo", loggerBundle, Thread.class); - loggerDescMap.put(sysLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, Thread.class)"); + sysLogger2 = provider.getLocalizedLogger("foo", loggerBundle, Thread.class.getModule()); + loggerDescMap.put(sysLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, Thread.class.getModule())"); if (!hasRequiredPermissions) { throw new RuntimeException("Managed to obtain a system logger without permission"); } diff --git a/jdk/test/java/lang/System/LoggerFinder/internal/BasePlatformLoggerTest/BasePlatformLoggerTest.java b/jdk/test/java/lang/System/LoggerFinder/internal/BasePlatformLoggerTest/BasePlatformLoggerTest.java index da8c2d73b16..a9e441f9d7c 100644 --- a/jdk/test/java/lang/System/LoggerFinder/internal/BasePlatformLoggerTest/BasePlatformLoggerTest.java +++ b/jdk/test/java/lang/System/LoggerFinder/internal/BasePlatformLoggerTest/BasePlatformLoggerTest.java @@ -47,6 +47,7 @@ import java.lang.System.Logger.Level; import java.security.AccessControlException; import java.util.stream.Stream; import sun.util.logging.PlatformLogger; +import java.lang.reflect.Module; /** * @test @@ -327,12 +328,12 @@ public class BasePlatformLoggerTest { } } - public Logger getLogger(String name, Class caller); + public Logger getLogger(String name, Module caller); } public static class BaseLoggerFinder extends LoggerFinder implements TestLoggerFinder { @Override - public Logger getLogger(String name, Class caller) { + public Logger getLogger(String name, Module caller) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(LOGGERFINDER_PERMISSION); @@ -433,7 +434,7 @@ public class BasePlatformLoggerTest { try { allowControl.get().set(true); appSink = TestLoggerFinder.LoggerImpl.class.cast( - provider.getLogger("foo", BasePlatformLoggerTest.class)); + provider.getLogger("foo", BasePlatformLoggerTest.class.getModule())); } finally { allowControl.get().set(before); } @@ -442,7 +443,8 @@ public class BasePlatformLoggerTest { before = allowControl.get().get(); try { allowControl.get().set(true); - sysSink = TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", Thread.class)); + sysSink = TestLoggerFinder.LoggerImpl.class.cast( + provider.getLogger("foo", Thread.class.getModule())); } finally { allowControl.get().set(before); } diff --git a/jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerAPIsTest.java b/jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerAPIsTest.java index 7c62eb9a763..bedd6117ae8 100644 --- a/jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerAPIsTest.java +++ b/jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerAPIsTest.java @@ -30,7 +30,7 @@ import java.util.Enumeration; import java.util.List; import java.util.ResourceBundle; import java.util.Set; - +import java.lang.reflect.Module; import jdk.internal.logger.BootstrapLogger; import jdk.internal.logger.LazyLoggers; @@ -69,7 +69,7 @@ public class BootstrapLoggerAPIsTest { } final Logger LOGGER = - LazyLoggers.getLogger("foo.bar", Thread.class); + LazyLoggers.getLogger("foo.bar", Thread.class.getModule()); final sun.util.logging.PlatformLogger.Level PLATFORM_LEVEL = sun.util.logging.PlatformLogger.Level.SEVERE; final MyResources BUNDLE = new MyResources(); diff --git a/jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerTest.java b/jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerTest.java index 033a7d97315..e2f6d4b009d 100644 --- a/jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerTest.java +++ b/jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerTest.java @@ -43,6 +43,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import jdk.internal.logger.BootstrapLogger; import jdk.internal.logger.LazyLoggers; +import java.lang.reflect.Module; /* * @test @@ -105,7 +106,7 @@ public class BootstrapLoggerTest { if (BootstrapLogger.isBooted()) { throw new RuntimeException("VM should not be booted!"); } - Logger logger = LazyLoggers.getLogger("foo.bar", Thread.class); + Logger logger = LazyLoggers.getLogger("foo.bar", Thread.class.getModule()); if (test != TestCase.NO_SECURITY) { LogStream.err.println("Setting security manager"); @@ -261,7 +262,7 @@ public class BootstrapLoggerTest { SimplePolicy.allowAll.set(Boolean.TRUE); try { bazbaz = java.lang.System.LoggerFinder - .getLoggerFinder().getLogger("foo.bar.baz.baz", BootstrapLoggerTest.class); + .getLoggerFinder().getLogger("foo.bar.baz.baz", BootstrapLoggerTest.class.getModule()); } finally { SimplePolicy.allowAll.set(Boolean.FALSE); } diff --git a/jdk/test/java/lang/System/LoggerFinder/internal/LoggerBridgeTest/LoggerBridgeTest.java b/jdk/test/java/lang/System/LoggerFinder/internal/LoggerBridgeTest/LoggerBridgeTest.java index c3f5e98d39c..be5ad125518 100644 --- a/jdk/test/java/lang/System/LoggerFinder/internal/LoggerBridgeTest/LoggerBridgeTest.java +++ b/jdk/test/java/lang/System/LoggerFinder/internal/LoggerBridgeTest/LoggerBridgeTest.java @@ -51,6 +51,7 @@ import java.lang.System.Logger; import java.lang.System.Logger.Level; import java.util.stream.Stream; import sun.util.logging.PlatformLogger; +import java.lang.reflect.Module; /** * @test @@ -164,6 +165,7 @@ public class LoggerBridgeTest { null, null, level, bundle, key, thrown, params); } + public static LogEvent of(long sequenceNumber, boolean isLoggable, String name, sun.util.logging.PlatformLogger.Level level, ResourceBundle bundle, @@ -231,7 +233,7 @@ public class LoggerBridgeTest { try { // Preload classes before the security manager is on. providerClass = ClassLoader.getSystemClassLoader().loadClass("LoggerBridgeTest$LogProducerFinder"); - ((LoggerFinder)providerClass.newInstance()).getLogger("foo", providerClass); + ((LoggerFinder)providerClass.newInstance()).getLogger("foo", providerClass.getModule()); } catch (Exception ex) { throw new ExceptionInInitializerError(ex); } @@ -415,7 +417,7 @@ public class LoggerBridgeTest { } @Override - public Logger getLogger(String name, Class caller) { + public Logger getLogger(String name, Module caller) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(LOGGERFINDER_PERMISSION); @@ -430,6 +432,15 @@ public class LoggerBridgeTest { } } + static ClassLoader getClassLoader(Module m) { + final boolean before = allowAll.get().getAndSet(true); + try { + return m.getClassLoader(); + } finally { + allowAll.get().set(before); + } + } + static final sun.util.logging.PlatformLogger.Level[] julLevels = { sun.util.logging.PlatformLogger.Level.ALL, sun.util.logging.PlatformLogger.Level.FINEST, @@ -497,14 +508,14 @@ public class LoggerBridgeTest { try { Class bridgeClass = Class.forName("jdk.internal.logger.LazyLoggers"); lazyGetLogger = bridgeClass.getDeclaredMethod("getLogger", - String.class, Class.class); + String.class, Module.class); lazyGetLogger.setAccessible(true); } catch (Throwable ex) { throw new ExceptionInInitializerError(ex); } } - static Logger getLogger(LoggerFinder provider, String name, Class caller) { + static Logger getLogger(LoggerFinder provider, String name, Module caller) { Logger logger; try { logger = Logger.class.cast(lazyGetLogger.invoke(null, name, caller)); @@ -522,14 +533,14 @@ public class LoggerBridgeTest { // The method above does not throw exception... // call the provider here to verify that an exception would have // been thrown by the provider. - if (logger != null && caller == Thread.class) { + if (logger != null && caller == Thread.class.getModule()) { Logger log = provider.getLogger(name, caller); } return logger; } - static Logger getLogger(LoggerFinder provider, String name, ResourceBundle bundle, Class caller) { - if (caller.getClassLoader() != null) { + static Logger getLogger(LoggerFinder provider, String name, ResourceBundle bundle, Module caller) { + if (getClassLoader(caller) != null) { return System.getLogger(name,bundle); } else { return provider.getLocalizedLogger(name, bundle, caller); @@ -614,12 +625,12 @@ public class LoggerBridgeTest { Logger appLogger1 = System.getLogger("foo"); - loggerDescMap.put(appLogger1, "LogProducer.getApplicationLogger(\"foo\")"); + loggerDescMap.put(appLogger1, "System.getLogger(\"foo\")"); Logger sysLogger1 = null; try { - sysLogger1 = getLogger(provider, "foo", Thread.class); - loggerDescMap.put(sysLogger1, "LogProducer.getSystemLogger(\"foo\")"); + sysLogger1 = getLogger(provider, "foo", Thread.class.getModule()); + loggerDescMap.put(sysLogger1, "provider.getLogger(\"foo\", Thread.class.getModule())"); if (!hasRequiredPermissions) { throw new RuntimeException("Managed to obtain a system logger without permission"); } @@ -636,12 +647,12 @@ public class LoggerBridgeTest { Logger appLogger2 = System.getLogger("foo", loggerBundle); - loggerDescMap.put(appLogger2, "LogProducer.getApplicationLogger(\"foo\", loggerBundle)"); + loggerDescMap.put(appLogger2, "System.getLogger(\"foo\", loggerBundle)"); Logger sysLogger2 = null; try { - sysLogger2 = getLogger(provider, "foo", loggerBundle, Thread.class); - loggerDescMap.put(sysLogger2, "provider.getSystemLogger(\"foo\", loggerBundle)"); + sysLogger2 = getLogger(provider, "foo", loggerBundle, Thread.class.getModule()); + loggerDescMap.put(sysLogger2, "provider.getLogger(\"foo\", loggerBundle, Thread.class.getModule())"); if (!hasRequiredPermissions) { throw new RuntimeException("Managed to obtain a system logger without permission"); } @@ -671,9 +682,9 @@ public class LoggerBridgeTest { allowControl.get().set(true); try { appSink = LogProducerFinder.LoggerImpl.class.cast( - provider.getLogger("foo", LoggerBridgeTest.class)); + provider.getLogger("foo", LoggerBridgeTest.class.getModule())); sysSink = LogProducerFinder.LoggerImpl.class.cast( - provider.getLogger("foo", Thread.class)); + provider.getLogger("foo", Thread.class.getModule())); } finally { allowControl.get().set(old); } diff --git a/jdk/test/java/lang/System/LoggerFinder/internal/LoggerFinderLoaderTest/LoggerFinderLoaderTest.java b/jdk/test/java/lang/System/LoggerFinder/internal/LoggerFinderLoaderTest/LoggerFinderLoaderTest.java index 98418430a71..6343a90312c 100644 --- a/jdk/test/java/lang/System/LoggerFinder/internal/LoggerFinderLoaderTest/LoggerFinderLoaderTest.java +++ b/jdk/test/java/lang/System/LoggerFinder/internal/LoggerFinderLoaderTest/LoggerFinderLoaderTest.java @@ -53,6 +53,7 @@ import java.util.ServiceConfigurationError; import java.util.ServiceLoader; import java.util.concurrent.atomic.AtomicReference; import jdk.internal.logger.SimpleConsoleLogger; +import java.lang.reflect.Module; /** * @test @@ -166,8 +167,8 @@ public class LoggerFinderLoaderTest { } - public Logger getLogger(String name, Class caller); - public Logger getLocalizedLogger(String name, ResourceBundle bundle, Class caller); + public Logger getLogger(String name, Module caller); + public Logger getLocalizedLogger(String name, ResourceBundle bundle, Module caller); } public static class BaseLoggerFinder extends LoggerFinder implements TestLoggerFinder { @@ -187,7 +188,7 @@ public class LoggerFinderLoaderTest { @Override - public Logger getLogger(String name, Class caller) { + public Logger getLogger(String name, Module caller) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(LOGGERFINDER_PERMISSION); @@ -210,7 +211,7 @@ public class LoggerFinderLoaderTest { throw new ServiceConfigurationError("Should not come here"); } @Override - public Logger getLogger(String name, Class caller) { + public Logger getLogger(String name, Module caller) { throw new ServiceConfigurationError("Should not come here"); } } diff --git a/jdk/test/java/lang/System/LoggerFinder/internal/PlatformLoggerBridgeTest/PlatformLoggerBridgeTest.java b/jdk/test/java/lang/System/LoggerFinder/internal/PlatformLoggerBridgeTest/PlatformLoggerBridgeTest.java index 1300c9b2ecd..9576e17bed6 100644 --- a/jdk/test/java/lang/System/LoggerFinder/internal/PlatformLoggerBridgeTest/PlatformLoggerBridgeTest.java +++ b/jdk/test/java/lang/System/LoggerFinder/internal/PlatformLoggerBridgeTest/PlatformLoggerBridgeTest.java @@ -49,6 +49,7 @@ import java.lang.System.Logger; import java.lang.System.Logger.Level; import java.util.stream.Stream; import sun.util.logging.PlatformLogger; +import java.lang.reflect.Module; /** * @test @@ -94,7 +95,7 @@ public class PlatformLoggerBridgeTest { try { // Preload classes before the security manager is on. providerClass = ClassLoader.getSystemClassLoader().loadClass("PlatformLoggerBridgeTest$LogProducerFinder"); - ((LoggerFinder)providerClass.newInstance()).getLogger("foo", providerClass); + ((LoggerFinder)providerClass.newInstance()).getLogger("foo", providerClass.getModule()); } catch (Exception ex) { throw new ExceptionInInitializerError(ex); } @@ -415,7 +416,7 @@ public class PlatformLoggerBridgeTest { } @Override - public Logger getLogger(String name, Class caller) { + public Logger getLogger(String name, Module caller) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(LOGGERFINDER_PERMISSION); @@ -598,7 +599,7 @@ public class PlatformLoggerBridgeTest { allowControl.get().set(true); try { sysSink = LogProducerFinder.LoggerImpl.class.cast( - provider.getLogger("foo", Thread.class)); + provider.getLogger("foo", Thread.class.getModule())); } finally { allowControl.get().set(old); } diff --git a/jdk/test/java/lang/System/LoggerFinder/internal/api/LoggerFinderAPITest.java b/jdk/test/java/lang/System/LoggerFinder/internal/api/LoggerFinderAPITest.java index e3752b5721c..572695458f1 100644 --- a/jdk/test/java/lang/System/LoggerFinder/internal/api/LoggerFinderAPITest.java +++ b/jdk/test/java/lang/System/LoggerFinder/internal/api/LoggerFinderAPITest.java @@ -469,12 +469,12 @@ public class LoggerFinderAPITest { errors.append(test.testGetLoggerOverriddenOnSpi()); java.lang.System.Logger julLogger = java.lang.System.LoggerFinder.getLoggerFinder() - .getLogger("foo", LoggerFinderAPITest.class); + .getLogger("foo", LoggerFinderAPITest.class.getModule()); errors.append(test.testDefaultJULLogger(julLogger)); if (errors.length() > 0) throw new RuntimeException(errors.toString()); java.lang.System.Logger julSystemLogger = java.lang.System.LoggerFinder.getLoggerFinder() - .getLogger("bar", Thread.class); + .getLogger("bar", Thread.class.getModule()); errors.append(test.testDefaultJULLogger(julSystemLogger)); if (errors.length() > 0) throw new RuntimeException(errors.toString()); java.lang.System.Logger julLocalizedLogger = @@ -482,7 +482,7 @@ public class LoggerFinderAPITest { System.getLogger("baz", bundleLocalized); java.lang.System.Logger julLocalizedSystemLogger = java.lang.System.LoggerFinder.getLoggerFinder() - .getLocalizedLogger("oof", bundleLocalized, Thread.class); + .getLocalizedLogger("oof", bundleLocalized, Thread.class.getModule()); final String error = errors.toString(); if (!error.isEmpty()) throw new RuntimeException(error); for (java.lang.System.Logger logger : new java.lang.System.Logger[] { diff --git a/jdk/test/java/lang/System/LoggerFinder/internal/backend/LoggerFinderBackendTest.java b/jdk/test/java/lang/System/LoggerFinder/internal/backend/LoggerFinderBackendTest.java index 226f2f7cf30..eb3f07c3ec3 100644 --- a/jdk/test/java/lang/System/LoggerFinder/internal/backend/LoggerFinderBackendTest.java +++ b/jdk/test/java/lang/System/LoggerFinder/internal/backend/LoggerFinderBackendTest.java @@ -77,6 +77,7 @@ import java.util.logging.LogManager; import java.util.logging.LogRecord; import java.util.logging.Logger; import sun.util.logging.internal.LoggingProviderImpl; +import java.lang.reflect.Module; /** * @author danielfuchs @@ -1506,7 +1507,7 @@ public class LoggerFinderBackendTest { Logger getBackendLogger(String name) { if (isSystem) { return LoggingProviderImpl.getLogManagerAccess().demandLoggerFor( - LogManager.getLogManager(), name, Thread.class); + LogManager.getLogManager(), name, Thread.class.getModule()); } else { return Logger.getLogger(name); } @@ -1699,7 +1700,7 @@ public class LoggerFinderBackendTest { Collections.synchronizedMap(new HashMap<>()); @Override - public java.lang.System.Logger getLogger(String name, Class caller) { + public java.lang.System.Logger getLogger(String name, Module caller) { ClassLoader callerLoader = caller.getClassLoader(); if (callerLoader == null) { systemLoggers.putIfAbsent(name, new CustomLogger(name)); @@ -1827,8 +1828,8 @@ public class LoggerFinderBackendTest { public void setLevel(java.lang.System.Logger logger, Level level) { final CustomLoggerFinder.CustomLogger l = (CustomLoggerFinder.CustomLogger) - (isSystem ? provider.getLogger(logger.getName(), Thread.class) : - provider.getLogger(logger.getName(), LoggerFinderBackendTest.class)); + (isSystem ? provider.getLogger(logger.getName(), Thread.class.getModule()) : + provider.getLogger(logger.getName(), LoggerFinderBackendTest.class.getModule())); l.setLevel(provider.fromJul(level)); } @Override @@ -1840,8 +1841,8 @@ public class LoggerFinderBackendTest { CustomLoggerFinder.CustomLevel getLevel(java.lang.System.Logger logger) { final CustomLoggerFinder.CustomLogger l = (CustomLoggerFinder.CustomLogger) - (isSystem ? provider.getLogger(logger.getName(), Thread.class) : - provider.getLogger(logger.getName(), LoggerFinderBackendTest.class)); + (isSystem ? provider.getLogger(logger.getName(), Thread.class.getModule()) : + provider.getLogger(logger.getName(), LoggerFinderBackendTest.class.getModule())); return l.level; } @@ -1962,7 +1963,7 @@ public class LoggerFinderBackendTest { try { Class lazyLoggers = jdk.internal.logger.LazyLoggers.class; getLazyLogger = lazyLoggers.getMethod("getLazyLogger", - String.class, Class.class); + String.class, Module.class); getLazyLogger.setAccessible(true); Class loggerFinderLoader = Class.forName("java.lang.System$LoggerFinder"); @@ -1973,7 +1974,7 @@ public class LoggerFinderBackendTest { } } - static java.lang.System.Logger getSystemLogger(String name, Class caller) throws Exception { + static java.lang.System.Logger getSystemLogger(String name, Module caller) throws Exception { try { return java.lang.System.Logger.class.cast(getLazyLogger.invoke(null, name, caller)); } catch (InvocationTargetException x) { @@ -1986,7 +1987,7 @@ public class LoggerFinderBackendTest { } } static java.lang.System.Logger getSystemLogger(String name, - ResourceBundle bundle, Class caller) throws Exception { + ResourceBundle bundle, Module caller) throws Exception { try { LoggerFinder provider = LoggerFinder.class.cast(accessLoggerFinder.invoke(null)); return provider.getLocalizedLogger(name, bundle, caller); @@ -2047,14 +2048,14 @@ public class LoggerFinderBackendTest { final BackendTester tester = factory.createBackendTester(false); final java.lang.System.Logger logger = java.lang.System.LoggerFinder.getLoggerFinder() - .getLogger("foo", LoggerFinderBackendTest.class); + .getLogger("foo", LoggerFinderBackendTest.class.getModule()); testLogger(tester, logger, nb); // Test a simple system logger with JUL backend final java.lang.System.Logger system = java.lang.System.LoggerFinder.getLoggerFinder() - .getLogger("bar", Thread.class); + .getLogger("bar", Thread.class.getModule()); final BackendTester systemTester = factory.createBackendTester(true); testLogger(systemTester, system, nb); @@ -2062,7 +2063,7 @@ public class LoggerFinderBackendTest { // JUL backend final java.lang.System.Logger noBundleLogger = java.lang.System.LoggerFinder.getLoggerFinder() - .getLocalizedLogger("baz", null, LoggerFinderBackendTest.class); + .getLocalizedLogger("baz", null, LoggerFinderBackendTest.class.getModule()); final BackendTester noBundleTester = factory.createBackendTester(false, spiLoggerClass); testLogger(noBundleTester, noBundleLogger, nb); @@ -2071,7 +2072,7 @@ public class LoggerFinderBackendTest { // backend final java.lang.System.Logger noBundleSysLogger = java.lang.System.LoggerFinder.getLoggerFinder() - .getLocalizedLogger("oof", null, Thread.class); + .getLocalizedLogger("oof", null, Thread.class.getModule()); final BackendTester noBundleSysTester = factory.createBackendTester(true, spiLoggerClass); testLogger(noBundleSysTester, noBundleSysLogger, nb); @@ -2085,14 +2086,14 @@ public class LoggerFinderBackendTest { System.out.println("System.Loggers.getLogger(\"baz\", null): got expected " + x); } final java.lang.System.Logger noBundleExtensionLogger = - getSystemLogger("baz", null, LoggerFinderBackendTest.class); + getSystemLogger("baz", null, LoggerFinderBackendTest.class.getModule()); final BackendTester noBundleExtensionTester = factory.createBackendTester(false, jdkLoggerClass); testLogger(noBundleExtensionTester, noBundleExtensionLogger, nb); // Test a simple system logger with JUL backend final java.lang.System.Logger sysExtensionLogger = - getSystemLogger("oof", Thread.class); + getSystemLogger("oof", Thread.class.getModule()); final BackendTester sysExtensionTester = factory.createBackendTester(true, jdkLoggerClass); testLogger(sysExtensionTester, sysExtensionLogger, nb); @@ -2100,7 +2101,7 @@ public class LoggerFinderBackendTest { // Test a localized system logger with null resource bundle and JUL // backend final java.lang.System.Logger noBundleSysExtensionLogger = - getSystemLogger("oof", null, Thread.class); + getSystemLogger("oof", null, Thread.class.getModule()); final BackendTester noBundleSysExtensionTester = factory.createBackendTester(true, jdkLoggerClass); testLogger(noBundleSysExtensionTester, noBundleSysExtensionLogger, nb); @@ -2127,7 +2128,7 @@ public class LoggerFinderBackendTest { ResourceBundle.getBundle(ResourceBundeLocalized.class.getName()); final java.lang.System.Logger bundleLogger = java.lang.System.LoggerFinder.getLoggerFinder() - .getLocalizedLogger("toto", bundle, LoggerFinderBackendTest.class); + .getLocalizedLogger("toto", bundle, LoggerFinderBackendTest.class.getModule()); final BackendTester bundleTester = factory.createBackendTester(false, spiLoggerClass, bundle); testLogger(bundleTester, bundleLogger, nb); @@ -2135,7 +2136,7 @@ public class LoggerFinderBackendTest { // Test a localized system logger with resource bundle and JUL backend final java.lang.System.Logger bundleSysLogger = java.lang.System.LoggerFinder.getLoggerFinder() - .getLocalizedLogger("titi", bundle, Thread.class); + .getLocalizedLogger("titi", bundle, Thread.class.getModule()); final BackendTester bundleSysTester = factory.createBackendTester(true, spiLoggerClass, bundle); testLogger(bundleSysTester, bundleSysLogger, nb); @@ -2151,7 +2152,7 @@ public class LoggerFinderBackendTest { // Test a localized Jdk system logger with resource bundle and JUL // backend final java.lang.System.Logger bundleExtensionSysLogger = - getSystemLogger("titu", bundle, Thread.class); + getSystemLogger("titu", bundle, Thread.class.getModule()); final BackendTester bundleExtensionSysTester = factory.createBackendTester(true, jdkLoggerClass, bundle); testLogger(bundleExtensionSysTester, bundleExtensionSysLogger, nb); diff --git a/jdk/test/java/lang/System/LoggerFinder/jdk/DefaultLoggerBridgeTest/DefaultLoggerBridgeTest.java b/jdk/test/java/lang/System/LoggerFinder/jdk/DefaultLoggerBridgeTest/DefaultLoggerBridgeTest.java index 6f15819fcd2..7118101cada 100644 --- a/jdk/test/java/lang/System/LoggerFinder/jdk/DefaultLoggerBridgeTest/DefaultLoggerBridgeTest.java +++ b/jdk/test/java/lang/System/LoggerFinder/jdk/DefaultLoggerBridgeTest/DefaultLoggerBridgeTest.java @@ -48,6 +48,7 @@ import java.lang.System.LoggerFinder; import java.lang.System.Logger; import java.util.stream.Stream; import sun.util.logging.internal.LoggingProviderImpl; +import java.lang.reflect.Module; /** * @test @@ -246,7 +247,7 @@ public class DefaultLoggerBridgeTest { } } - static Logger getLogger(String name, Class caller) { + static Logger getLogger(String name, Module caller) { boolean old = allowAccess.get().get(); allowAccess.get().set(true); try { @@ -311,8 +312,8 @@ public class DefaultLoggerBridgeTest { ResourceBundle.getBundle(MyLoggerBundle.class.getName()); final Map loggerDescMap = new HashMap<>(); - Logger sysLogger1a = getLogger("foo", Thread.class); - loggerDescMap.put(sysLogger1a, "jdk.internal.logger.LazyLoggers.getLogger(\"foo\", Thread.class)"); + Logger sysLogger1a = getLogger("foo", Thread.class.getModule()); + loggerDescMap.put(sysLogger1a, "jdk.internal.logger.LazyLoggers.getLogger(\"foo\", Thread.class.getModule())"); Logger appLogger1 = System.getLogger("foo"); loggerDescMap.put(appLogger1, "System.getLogger(\"foo\")"); @@ -341,9 +342,9 @@ public class DefaultLoggerBridgeTest { Logger sysLogger1b = null; try { - sysLogger1b = provider.getLogger("foo", Thread.class); + sysLogger1b = provider.getLogger("foo", Thread.class.getModule()); if (sysLogger1b != sysLogger1a) { - loggerDescMap.put(sysLogger1b, "provider.getLogger(\"foo\", Thread.class)"); + loggerDescMap.put(sysLogger1b, "provider.getLogger(\"foo\", Thread.class.getModule())"); } if (!hasRequiredPermissions) { throw new RuntimeException("Managed to obtain a system logger without permission"); @@ -367,8 +368,8 @@ public class DefaultLoggerBridgeTest { Logger sysLogger2 = null; try { - sysLogger2 = provider.getLocalizedLogger("foo", loggerBundle, Thread.class); - loggerDescMap.put(sysLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, Thread.class)"); + sysLogger2 = provider.getLocalizedLogger("foo", loggerBundle, Thread.class.getModule()); + loggerDescMap.put(sysLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, Thread.class.getModule())"); if (!hasRequiredPermissions) { throw new RuntimeException("Managed to obtain a system logger without permission"); } @@ -396,9 +397,9 @@ public class DefaultLoggerBridgeTest { allowAll.get().set(true); try { sysSink = LoggingProviderImpl.getLogManagerAccess().demandLoggerFor( - LogManager.getLogManager(), "foo", Thread.class); + LogManager.getLogManager(), "foo", Thread.class.getModule()); appSink = LoggingProviderImpl.getLogManagerAccess().demandLoggerFor( - LogManager.getLogManager(), "foo", DefaultLoggerBridgeTest.class); + LogManager.getLogManager(), "foo", DefaultLoggerBridgeTest.class.getModule()); if (appSink == sysSink) { throw new RuntimeException("identical backend loggers"); } diff --git a/jdk/test/java/lang/System/LoggerFinder/jdk/DefaultPlatformLoggerTest/DefaultPlatformLoggerTest.java b/jdk/test/java/lang/System/LoggerFinder/jdk/DefaultPlatformLoggerTest/DefaultPlatformLoggerTest.java index 2eb64d0743d..99b7ee38b2a 100644 --- a/jdk/test/java/lang/System/LoggerFinder/jdk/DefaultPlatformLoggerTest/DefaultPlatformLoggerTest.java +++ b/jdk/test/java/lang/System/LoggerFinder/jdk/DefaultPlatformLoggerTest/DefaultPlatformLoggerTest.java @@ -44,6 +44,7 @@ import java.util.logging.LogRecord; import java.lang.System.LoggerFinder; import sun.util.logging.PlatformLogger; import sun.util.logging.internal.LoggingProviderImpl; +import java.lang.reflect.Module; /** * @test @@ -244,9 +245,9 @@ public class DefaultPlatformLoggerTest { LoggerFinder provider = LoggerFinder.getLoggerFinder(); java.util.logging.Logger appSink = LoggingProviderImpl.getLogManagerAccess() .demandLoggerFor(LogManager.getLogManager(), "foo", - DefaultPlatformLoggerTest.class); + DefaultPlatformLoggerTest.class.getModule()); java.util.logging.Logger sysSink = LoggingProviderImpl.getLogManagerAccess() - .demandLoggerFor(LogManager.getLogManager(),"foo", Thread.class); + .demandLoggerFor(LogManager.getLogManager(),"foo", Thread.class.getModule()); appSink.addHandler(new MyHandler()); sysSink.addHandler(new MyHandler()); appSink.setUseParentHandlers(VERBOSE); diff --git a/jdk/test/sun/util/logging/PlatformLoggerTest.java b/jdk/test/sun/util/logging/PlatformLoggerTest.java index 0bf94d64a5a..530a2acea8a 100644 --- a/jdk/test/sun/util/logging/PlatformLoggerTest.java +++ b/jdk/test/sun/util/logging/PlatformLoggerTest.java @@ -197,7 +197,7 @@ public class PlatformLoggerTest { // create a brand new java logger Logger javaLogger = sun.util.logging.internal.LoggingProviderImpl.getLogManagerAccess() .demandLoggerFor(LogManager.getLogManager(), - logger.getName()+"."+level.getName(), Thread.class); + logger.getName()+"."+level.getName(), Thread.class.getModule()); // Set a non standard java.util.logging.Level on the java logger // (except for OFF & ALL - which will remain unchanged) From 607d8e443b0914fe25113e6af23e745b683aef7c Mon Sep 17 00:00:00 2001 From: Volker Simonis Date: Wed, 27 Apr 2016 18:52:32 +0200 Subject: [PATCH 11/18] 8155236: AIX: fix dectection of Xrender extension Reviewed-by: prr --- .../libawt_xawt/java2d/x11/XRBackendNative.c | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/jdk/src/java.desktop/unix/native/libawt_xawt/java2d/x11/XRBackendNative.c b/jdk/src/java.desktop/unix/native/libawt_xawt/java2d/x11/XRBackendNative.c index 733606ec444..f408b0178ea 100644 --- a/jdk/src/java.desktop/unix/native/libawt_xawt/java2d/x11/XRBackendNative.c +++ b/jdk/src/java.desktop/unix/native/libawt_xawt/java2d/x11/XRBackendNative.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, 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 @@ -72,8 +72,8 @@ typedef struct _XRadialGradient { #include -#if defined(__solaris__) || defined(_AIX) -/* Solaris 10 and AIX will not have these symbols at runtime */ +#if defined(__solaris__) +/* Solaris 10 will not have these symbols at compile time */ typedef Picture (*XRenderCreateLinearGradientFuncType) (Display *dpy, @@ -147,7 +147,22 @@ static jboolean IsXRenderAvailable(jboolean verbose, jboolean ignoreLinuxVersion return JNI_FALSE; } -#if defined(__solaris__) || defined(_AIX) +#if defined(_AIX) + // On AIX we have to use a special syntax because the shared libraries are packed in + // multi-architecture archives. We first try to load the system default libXrender + // which is contained in the 'X11.base.lib' fileset starting with AIX 6.1 + xrenderlib = dlopen("libXrender.a(shr_64.o)", RTLD_GLOBAL | RTLD_LAZY | RTLD_MEMBER); + if (xrenderlib == NULL) { + // If the latter wasn't successful, we also try to load the version under /opt/freeware + // This may be downloaded from the "AIX Toolbox for Linux Applications" even for AIX 5.3 + xrenderlib = dlopen("libXrender.a(libXrender.so.0)", RTLD_GLOBAL | RTLD_LAZY | RTLD_MEMBER); + } + if (xrenderlib != NULL) { + dlclose(xrenderlib); + } else { + available = JNI_FALSE; + } +#elif defined(__solaris__) xrenderlib = dlopen("libXrender.so",RTLD_GLOBAL|RTLD_LAZY); if (xrenderlib != NULL) { From 0b7775586ffeb3a549e06b297a2ec14a7a139d30 Mon Sep 17 00:00:00 2001 From: Michael Haupt Date: Wed, 27 Apr 2016 20:18:49 +0200 Subject: [PATCH 12/18] 8155106: MHs.Lookup.findConstructor returns handles for array classes Reviewed-by: shade, sundar --- .../java/lang/invoke/MethodHandleImpl.java | 7 +- .../java/lang/invoke/MethodHandles.java | 24 +++++ .../lang/invoke/ArrayConstructorTest.java | 91 +++++++++++++++++++ 3 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 jdk/test/java/lang/invoke/ArrayConstructorTest.java diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java index a108836ce51..782eff613ae 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java @@ -25,6 +25,7 @@ package java.lang.invoke; +import java.lang.reflect.Array; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.Arrays; @@ -1892,7 +1893,8 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; MH_tryFinallyExec = 12, MH_tryFinallyVoidExec = 13, MH_decrementCounter = 14, - MH_LIMIT = 15; + MH_Array_newInstance = 15, + MH_LIMIT = 16; static MethodHandle getConstantHandle(int idx) { MethodHandle handle = HANDLES[idx]; @@ -1965,6 +1967,9 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; case MH_decrementCounter: return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "decrementCounter", MethodType.methodType(int.class, int.class)); + case MH_Array_newInstance: + return IMPL_LOOKUP.findStatic(Array.class, "newInstance", + MethodType.methodType(Object.class, Class.class, int.class)); } } catch (ReflectiveOperationException ex) { throw newInternalError(ex); 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 afe6aecc9f4..c3a97a178a3 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 @@ -1010,6 +1010,9 @@ assertEquals("[x, y, z]", pb.command().toString()); * @throws NullPointerException if any argument is null */ public MethodHandle findConstructor(Class refc, MethodType type) throws NoSuchMethodException, IllegalAccessException { + if (refc.isArray()) { + throw new NoSuchMethodException("no constructor for array class: " + refc.getName()); + } String name = ""; MemberName ctor = resolveOrFail(REF_newInvokeSpecial, refc, name, type); return getDirectConstructor(refc, ctor); @@ -2220,6 +2223,27 @@ return mh1; static final Lookup PUBLIC_LOOKUP = new Lookup(PUBLIC_LOOKUP_CLASS, Lookup.PUBLIC); } + /** + * Produces a method handle constructing arrays of a desired type. + * The return type of the method handle will be the array type. + * The type of its sole argument will be {@code int}, which specifies the size of the array. + * @param arrayClass an array type + * @return a method handle which can create arrays of the given type + * @throws NullPointerException if the argument is {@code null} + * @throws IllegalArgumentException if {@code arrayClass} is not an array type + * @see java.lang.reflect.Array#newInstance(Class, int) + * @since 9 + */ + public static + MethodHandle arrayConstructor(Class arrayClass) throws IllegalArgumentException { + if (!arrayClass.isArray()) { + throw newIllegalArgumentException("not an array class: " + arrayClass.getName()); + } + MethodHandle ani = MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_Array_newInstance). + bindTo(arrayClass.getComponentType()); + return ani.asType(ani.type().changeReturnType(arrayClass)); + } + /** * Produces a method handle giving read access to elements of an array. * The type of the method handle will have a return type of the array's diff --git a/jdk/test/java/lang/invoke/ArrayConstructorTest.java b/jdk/test/java/lang/invoke/ArrayConstructorTest.java new file mode 100644 index 00000000000..9d0ae66188e --- /dev/null +++ b/jdk/test/java/lang/invoke/ArrayConstructorTest.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2016, 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. + */ + +/* @test + * @bug 8155106 + * @run testng/othervm -ea -esa test.java.lang.invoke.ArrayConstructorTest + */ +package test.java.lang.invoke; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; + +import static java.lang.invoke.MethodType.methodType; + +import static org.testng.AssertJUnit.*; + +import org.testng.annotations.*; + + +public class ArrayConstructorTest { + + static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); + + @Test + public static void testFindConstructorArray() { + boolean caught = false; + try { + MethodHandle h = LOOKUP.findConstructor(Object[].class, methodType(void.class)); + } catch (NoSuchMethodException nsme) { + assertEquals("no constructor for array class: [Ljava.lang.Object;", nsme.getMessage()); + caught = true; + } catch (Exception e) { + throw new AssertionError("unexpected exception: " + e); + } + assertTrue(caught); + } + + @DataProvider + static Object[][] arrayConstructorNegative() { + return new Object[][]{ + {String.class, IllegalArgumentException.class, "not an array class: java.lang.String"}, + {null, NullPointerException.class, null} + }; + } + + @Test(dataProvider = "arrayConstructorNegative") + public static void testArrayConstructorNegative(Class clazz, Class exceptionClass, String message) { + boolean caught = false; + try { + MethodHandle h = MethodHandles.arrayConstructor(clazz); + } catch (Exception e) { + assertEquals(exceptionClass, e.getClass()); + if (message != null) { + assertEquals(message, e.getMessage()); + } + caught = true; + } + assertTrue(caught); + } + + @Test + public static void testArrayConstructor() throws Throwable { + MethodHandle h = MethodHandles.arrayConstructor(String[].class); + assertEquals(methodType(String[].class, int.class), h.type()); + String[] a = (String[]) h.invoke(17); + assertEquals(17, a.length); + } + +} From f3402815334ce329c28f04836fcf96fe8b360f54 Mon Sep 17 00:00:00 2001 From: Mandy Chung Date: Wed, 27 Apr 2016 12:06:51 -0700 Subject: [PATCH 13/18] 8154905: Rename jdk.jvmstat.rmi to jdk.jstatd Reviewed-by: alanb, sundar --- ...Launcher-jdk.jvmstat.rmi.gmk => Launcher-jdk.jstatd.gmk} | 0 .../share/classes/module-info.java | 2 +- .../classes/sun/jvmstat/monitor/remote/RemoteHost.java | 0 .../share/classes/sun/jvmstat/monitor/remote/RemoteVm.java | 0 .../share/classes/sun/jvmstat/monitor/remote/package.html | 0 .../monitor/protocol/rmi/MonitoredHostProvider.java | 0 .../monitor/protocol/rmi/MonitoredHostRmiService.java | 0 .../perfdata/monitor/protocol/rmi/PerfDataBuffer.java | 0 .../perfdata/monitor/protocol/rmi/RemoteMonitoredVm.java | 0 .../perfdata/monitor/protocol/rmi/RemoteVmManager.java | 0 .../sun/jvmstat/perfdata/monitor/protocol/rmi/package.html | 0 .../share/classes/sun/tools/jstatd/Jstatd.java | 0 .../share/classes/sun/tools/jstatd/RemoteHostImpl.java | 0 .../share/classes/sun/tools/jstatd/RemoteVmImpl.java | 0 jdk/src/jdk.jvmstat/share/classes/module-info.java | 6 +++--- 15 files changed, 4 insertions(+), 4 deletions(-) rename jdk/make/launcher/{Launcher-jdk.jvmstat.rmi.gmk => Launcher-jdk.jstatd.gmk} (100%) rename jdk/src/{jdk.jvmstat.rmi => jdk.jstatd}/share/classes/module-info.java (98%) rename jdk/src/{jdk.jvmstat.rmi => jdk.jstatd}/share/classes/sun/jvmstat/monitor/remote/RemoteHost.java (100%) rename jdk/src/{jdk.jvmstat.rmi => jdk.jstatd}/share/classes/sun/jvmstat/monitor/remote/RemoteVm.java (100%) rename jdk/src/{jdk.jvmstat.rmi => jdk.jstatd}/share/classes/sun/jvmstat/monitor/remote/package.html (100%) rename jdk/src/{jdk.jvmstat.rmi => jdk.jstatd}/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/MonitoredHostProvider.java (100%) rename jdk/src/{jdk.jvmstat.rmi => jdk.jstatd}/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/MonitoredHostRmiService.java (100%) rename jdk/src/{jdk.jvmstat.rmi => jdk.jstatd}/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/PerfDataBuffer.java (100%) rename jdk/src/{jdk.jvmstat.rmi => jdk.jstatd}/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/RemoteMonitoredVm.java (100%) rename jdk/src/{jdk.jvmstat.rmi => jdk.jstatd}/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/RemoteVmManager.java (100%) rename jdk/src/{jdk.jvmstat.rmi => jdk.jstatd}/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/package.html (100%) rename jdk/src/{jdk.jvmstat.rmi => jdk.jstatd}/share/classes/sun/tools/jstatd/Jstatd.java (100%) rename jdk/src/{jdk.jvmstat.rmi => jdk.jstatd}/share/classes/sun/tools/jstatd/RemoteHostImpl.java (100%) rename jdk/src/{jdk.jvmstat.rmi => jdk.jstatd}/share/classes/sun/tools/jstatd/RemoteVmImpl.java (100%) diff --git a/jdk/make/launcher/Launcher-jdk.jvmstat.rmi.gmk b/jdk/make/launcher/Launcher-jdk.jstatd.gmk similarity index 100% rename from jdk/make/launcher/Launcher-jdk.jvmstat.rmi.gmk rename to jdk/make/launcher/Launcher-jdk.jstatd.gmk diff --git a/jdk/src/jdk.jvmstat.rmi/share/classes/module-info.java b/jdk/src/jdk.jstatd/share/classes/module-info.java similarity index 98% rename from jdk/src/jdk.jvmstat.rmi/share/classes/module-info.java rename to jdk/src/jdk.jstatd/share/classes/module-info.java index 01ed37c3210..1f8a86e214d 100644 --- a/jdk/src/jdk.jvmstat.rmi/share/classes/module-info.java +++ b/jdk/src/jdk.jstatd/share/classes/module-info.java @@ -23,7 +23,7 @@ * questions. */ -module jdk.jvmstat.rmi { +module jdk.jstatd { requires java.rmi; requires jdk.jvmstat; diff --git a/jdk/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/monitor/remote/RemoteHost.java b/jdk/src/jdk.jstatd/share/classes/sun/jvmstat/monitor/remote/RemoteHost.java similarity index 100% rename from jdk/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/monitor/remote/RemoteHost.java rename to jdk/src/jdk.jstatd/share/classes/sun/jvmstat/monitor/remote/RemoteHost.java diff --git a/jdk/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/monitor/remote/RemoteVm.java b/jdk/src/jdk.jstatd/share/classes/sun/jvmstat/monitor/remote/RemoteVm.java similarity index 100% rename from jdk/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/monitor/remote/RemoteVm.java rename to jdk/src/jdk.jstatd/share/classes/sun/jvmstat/monitor/remote/RemoteVm.java diff --git a/jdk/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/monitor/remote/package.html b/jdk/src/jdk.jstatd/share/classes/sun/jvmstat/monitor/remote/package.html similarity index 100% rename from jdk/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/monitor/remote/package.html rename to jdk/src/jdk.jstatd/share/classes/sun/jvmstat/monitor/remote/package.html diff --git a/jdk/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/MonitoredHostProvider.java b/jdk/src/jdk.jstatd/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/MonitoredHostProvider.java similarity index 100% rename from jdk/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/MonitoredHostProvider.java rename to jdk/src/jdk.jstatd/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/MonitoredHostProvider.java diff --git a/jdk/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/MonitoredHostRmiService.java b/jdk/src/jdk.jstatd/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/MonitoredHostRmiService.java similarity index 100% rename from jdk/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/MonitoredHostRmiService.java rename to jdk/src/jdk.jstatd/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/MonitoredHostRmiService.java diff --git a/jdk/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/PerfDataBuffer.java b/jdk/src/jdk.jstatd/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/PerfDataBuffer.java similarity index 100% rename from jdk/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/PerfDataBuffer.java rename to jdk/src/jdk.jstatd/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/PerfDataBuffer.java diff --git a/jdk/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/RemoteMonitoredVm.java b/jdk/src/jdk.jstatd/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/RemoteMonitoredVm.java similarity index 100% rename from jdk/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/RemoteMonitoredVm.java rename to jdk/src/jdk.jstatd/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/RemoteMonitoredVm.java diff --git a/jdk/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/RemoteVmManager.java b/jdk/src/jdk.jstatd/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/RemoteVmManager.java similarity index 100% rename from jdk/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/RemoteVmManager.java rename to jdk/src/jdk.jstatd/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/RemoteVmManager.java diff --git a/jdk/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/package.html b/jdk/src/jdk.jstatd/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/package.html similarity index 100% rename from jdk/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/package.html rename to jdk/src/jdk.jstatd/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/package.html diff --git a/jdk/src/jdk.jvmstat.rmi/share/classes/sun/tools/jstatd/Jstatd.java b/jdk/src/jdk.jstatd/share/classes/sun/tools/jstatd/Jstatd.java similarity index 100% rename from jdk/src/jdk.jvmstat.rmi/share/classes/sun/tools/jstatd/Jstatd.java rename to jdk/src/jdk.jstatd/share/classes/sun/tools/jstatd/Jstatd.java diff --git a/jdk/src/jdk.jvmstat.rmi/share/classes/sun/tools/jstatd/RemoteHostImpl.java b/jdk/src/jdk.jstatd/share/classes/sun/tools/jstatd/RemoteHostImpl.java similarity index 100% rename from jdk/src/jdk.jvmstat.rmi/share/classes/sun/tools/jstatd/RemoteHostImpl.java rename to jdk/src/jdk.jstatd/share/classes/sun/tools/jstatd/RemoteHostImpl.java diff --git a/jdk/src/jdk.jvmstat.rmi/share/classes/sun/tools/jstatd/RemoteVmImpl.java b/jdk/src/jdk.jstatd/share/classes/sun/tools/jstatd/RemoteVmImpl.java similarity index 100% rename from jdk/src/jdk.jvmstat.rmi/share/classes/sun/tools/jstatd/RemoteVmImpl.java rename to jdk/src/jdk.jstatd/share/classes/sun/tools/jstatd/RemoteVmImpl.java diff --git a/jdk/src/jdk.jvmstat/share/classes/module-info.java b/jdk/src/jdk.jvmstat/share/classes/module-info.java index 2510a362931..d0038c242b2 100644 --- a/jdk/src/jdk.jvmstat/share/classes/module-info.java +++ b/jdk/src/jdk.jvmstat/share/classes/module-info.java @@ -28,12 +28,12 @@ module jdk.jvmstat { jdk.attach, jdk.jcmd, jdk.jconsole, - jdk.jvmstat.rmi; + jdk.jstatd; exports sun.jvmstat.monitor.event to jdk.jcmd, - jdk.jvmstat.rmi; + jdk.jstatd; exports sun.jvmstat.perfdata.monitor to - jdk.jvmstat.rmi; + jdk.jstatd; uses sun.jvmstat.monitor.MonitoredHostService; provides sun.jvmstat.monitor.MonitoredHostService with sun.jvmstat.perfdata.monitor.protocol.file.MonitoredHostFileService; From 07cef26155dee0957073ebaf2d57f745d0a32c5c Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Wed, 27 Apr 2016 20:36:02 +0100 Subject: [PATCH 14/18] 8044773: Refactor jdk.net API so that it can be moved out of the base module Reviewed-by: alanb, erikj, mchung --- jdk/make/lib/Lib-jdk.net.gmk | 51 +++ jdk/make/mapfiles/libextnet/mapfile-vers | 34 ++ jdk/make/mapfiles/libnet/mapfile-vers | 4 - .../tools/module/GenModuleInfoSource.java | 2 +- .../jdk/net/ExtendedSocketOptions.java | 61 ---- .../java.base/share/classes/module-info.java | 4 +- .../classes/sun/net/ExtendedOptionsImpl.java | 92 ----- .../sun/net/ext/ExtendedSocketOptions.java | 110 ++++++ .../nio/ch/AsynchronousSocketChannelImpl.java | 8 +- .../sun/nio/ch/DatagramChannelImpl.java | 8 +- .../share/classes/sun/nio/ch/Net.java | 25 +- .../classes/sun/nio/ch/SocketChannelImpl.java | 9 +- .../java/net/PlainDatagramSocketImpl.java | 44 +-- .../classes/java/net/PlainSocketImpl.java | 47 ++- .../unix/native/libnet/ExtendedOptionsImpl.c | 344 ------------------ .../unix/native/libnet/net_util_md.h | 41 --- .../jdk/net/ExtendedSocketOptions.java | 212 +++++++++++ .../classes/jdk/net/NetworkPermission.java | 0 .../share/classes/jdk/net/SocketFlow.java | 81 +++-- .../share/classes/jdk/net/Sockets.java | 33 +- .../share/classes/jdk/net/package-info.java | 0 .../jdk.net/share/classes/module-info.java | 29 ++ .../jdk/net/SolarisSocketOptions.java} | 67 ++-- .../native/libextnet/SolarisSocketOptions.c | 176 +++++++++ .../native/libextnet/SolarisSocketOptions.h | 79 ++++ .../share/classes/module-info.java | 1 + .../java/net/SocketOption/OptionsTest.java | 25 +- .../SocketOption/UnsupportedOptionsTest.java | 52 ++- .../DatagramChannel/SocketOptionTests.java | 4 +- .../SocketOptionTests.java | 4 +- .../SocketChannel/SocketOptionTests.java | 4 +- .../jdk/net/SocketFlow/SocketFlowBasic.java | 93 +++++ jdk/test/jdk/net/Sockets/Test.java | 165 +++++---- 33 files changed, 1096 insertions(+), 813 deletions(-) create mode 100644 jdk/make/lib/Lib-jdk.net.gmk create mode 100644 jdk/make/mapfiles/libextnet/mapfile-vers delete mode 100644 jdk/src/java.base/share/classes/jdk/net/ExtendedSocketOptions.java delete mode 100644 jdk/src/java.base/share/classes/sun/net/ExtendedOptionsImpl.java create mode 100644 jdk/src/java.base/share/classes/sun/net/ext/ExtendedSocketOptions.java delete mode 100644 jdk/src/java.base/unix/native/libnet/ExtendedOptionsImpl.c create mode 100644 jdk/src/jdk.net/share/classes/jdk/net/ExtendedSocketOptions.java rename jdk/src/{java.base => jdk.net}/share/classes/jdk/net/NetworkPermission.java (100%) rename jdk/src/{java.base => jdk.net}/share/classes/jdk/net/SocketFlow.java (69%) rename jdk/src/{java.base => jdk.net}/share/classes/jdk/net/Sockets.java (94%) rename jdk/src/{java.base => jdk.net}/share/classes/jdk/net/package-info.java (100%) create mode 100644 jdk/src/jdk.net/share/classes/module-info.java rename jdk/src/{java.base/windows/native/libnet/ExtendedOptionsImpl.c => jdk.net/solaris/classes/jdk/net/SolarisSocketOptions.java} (52%) create mode 100644 jdk/src/jdk.net/solaris/native/libextnet/SolarisSocketOptions.c create mode 100644 jdk/src/jdk.net/solaris/native/libextnet/SolarisSocketOptions.h create mode 100644 jdk/test/jdk/net/SocketFlow/SocketFlowBasic.java diff --git a/jdk/make/lib/Lib-jdk.net.gmk b/jdk/make/lib/Lib-jdk.net.gmk new file mode 100644 index 00000000000..69c789b2f08 --- /dev/null +++ b/jdk/make/lib/Lib-jdk.net.gmk @@ -0,0 +1,51 @@ +# +# Copyright (c) 2016, 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. +# + +include LibCommon.gmk + +################################################################################ + +ifeq ($(OPENJDK_TARGET_OS), solaris) + + $(eval $(call SetupNativeCompilation, BUILD_LIBEXTNET, \ + LIBRARY := extnet, \ + OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \ + SRC := $(JDK_TOPDIR)/src/jdk.net/solaris/native/libextnet, \ + OPTIMIZATION := LOW, \ + CFLAGS := $(CFLAGS_JDKLIB) -I$(SUPPORT_OUTPUTDIR)/headers/jdk.net, \ + MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libextnet/mapfile-vers, \ + LDFLAGS := $(LDFLAGS_JDKLIB) \ + $(call SET_SHARED_LIBRARY_ORIGIN), \ + LIBS := -lsocket -lc -ljava, \ + OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libextnet, \ + )) + + $(BUILD_LIBEXTNET): $(call FindLib, java.base, java) + + TARGETS += $(BUILD_LIBEXTNET) +endif + + +################################################################################ diff --git a/jdk/make/mapfiles/libextnet/mapfile-vers b/jdk/make/mapfiles/libextnet/mapfile-vers new file mode 100644 index 00000000000..5dbc5b960aa --- /dev/null +++ b/jdk/make/mapfiles/libextnet/mapfile-vers @@ -0,0 +1,34 @@ +# +# Copyright (c) 2016, 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. +# + +SUNWprivate_1.1 { + global: + Java_jdk_net_SolarisSocketOptions_init; + Java_jdk_net_SolarisSocketOptions_setFlowOption; + Java_jdk_net_SolarisSocketOptions_getFlowOption; + Java_jdk_net_SolarisSocketOptions_flowSupported; + local: + *; +}; diff --git a/jdk/make/mapfiles/libnet/mapfile-vers b/jdk/make/mapfiles/libnet/mapfile-vers index 82247780181..92816bfa87d 100644 --- a/jdk/make/mapfiles/libnet/mapfile-vers +++ b/jdk/make/mapfiles/libnet/mapfile-vers @@ -98,10 +98,6 @@ SUNWprivate_1.1 { Java_sun_net_sdp_SdpSupport_create0; Java_sun_net_spi_DefaultProxySelector_init; Java_sun_net_spi_DefaultProxySelector_getSystemProxy; - Java_sun_net_ExtendedOptionsImpl_init; - Java_sun_net_ExtendedOptionsImpl_setFlowOption; - Java_sun_net_ExtendedOptionsImpl_getFlowOption; - Java_sun_net_ExtendedOptionsImpl_flowSupported; NET_AllocSockaddr; NET_SockaddrToInetAddress; NET_SockaddrEqualsInetAddress; diff --git a/jdk/make/src/classes/build/tools/module/GenModuleInfoSource.java b/jdk/make/src/classes/build/tools/module/GenModuleInfoSource.java index f2f404e9a0b..e7d932d1141 100644 --- a/jdk/make/src/classes/build/tools/module/GenModuleInfoSource.java +++ b/jdk/make/src/classes/build/tools/module/GenModuleInfoSource.java @@ -52,7 +52,7 @@ public class GenModuleInfoSource { "Usage: GenModuleInfoSource [option] -o \n" + "Options are:\n" + " -exports \n" + - " -exports /\n" + + " -exports [/]\n" + " -uses \n" + " -provides /\n"; diff --git a/jdk/src/java.base/share/classes/jdk/net/ExtendedSocketOptions.java b/jdk/src/java.base/share/classes/jdk/net/ExtendedSocketOptions.java deleted file mode 100644 index 12af5aff7ee..00000000000 --- a/jdk/src/java.base/share/classes/jdk/net/ExtendedSocketOptions.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2014, 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.net; - -import java.net.SocketOption; - -/** - * Defines extended socket options, beyond those defined in - * {@link java.net.StandardSocketOptions}. These options may be platform - * specific. - * - * @since 1.8 - */ -public final class ExtendedSocketOptions { - - private static class ExtSocketOption implements SocketOption { - private final String name; - private final Class type; - ExtSocketOption(String name, Class type) { - this.name = name; - this.type = type; - } - @Override public String name() { return name; } - @Override public Class type() { return type; } - @Override public String toString() { return name; } - } - - private ExtendedSocketOptions() {} - - /** - * Service level properties. When a security manager is installed, - * setting or getting this option requires a {@link NetworkPermission} - * {@code ("setOption.SO_FLOW_SLA")} or {@code "getOption.SO_FLOW_SLA"} - * respectively. - */ - public static final SocketOption SO_FLOW_SLA = new - ExtSocketOption("SO_FLOW_SLA", SocketFlow.class); -} diff --git a/jdk/src/java.base/share/classes/module-info.java b/jdk/src/java.base/share/classes/module-info.java index 942c0582ea0..12ad93f6a6d 100644 --- a/jdk/src/java.base/share/classes/module-info.java +++ b/jdk/src/java.base/share/classes/module-info.java @@ -83,8 +83,6 @@ module java.base { // see JDK-8144062 exports jdk; - // see JDK-8044773 - exports jdk.net; // the service types defined by the APIs in this module @@ -194,6 +192,8 @@ module java.base { jdk.jvmstat; exports sun.net to java.httpclient; + exports sun.net.ext to + jdk.net; exports sun.net.dns to java.security.jgss, jdk.naming.dns; diff --git a/jdk/src/java.base/share/classes/sun/net/ExtendedOptionsImpl.java b/jdk/src/java.base/share/classes/sun/net/ExtendedOptionsImpl.java deleted file mode 100644 index 8fbcdd7b49d..00000000000 --- a/jdk/src/java.base/share/classes/sun/net/ExtendedOptionsImpl.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2014, 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 sun.net; - -import java.net.*; -import jdk.net.*; -import java.io.IOException; -import java.io.FileDescriptor; -import java.security.PrivilegedAction; -import java.security.AccessController; -import java.lang.reflect.Field; -import java.util.Set; -import java.util.HashSet; -import java.util.HashMap; -import java.util.Collections; - -/** - * Contains the native implementation for extended socket options - * together with some other static utilities - */ -public class ExtendedOptionsImpl { - - static { - AccessController.doPrivileged((PrivilegedAction)() -> { - System.loadLibrary("net"); - return null; - }); - init(); - } - - private ExtendedOptionsImpl() {} - - public static void checkSetOptionPermission(SocketOption option) { - SecurityManager sm = System.getSecurityManager(); - if (sm == null) { - return; - } - String check = "setOption." + option.name(); - sm.checkPermission(new NetworkPermission(check)); - } - - public static void checkGetOptionPermission(SocketOption option) { - SecurityManager sm = System.getSecurityManager(); - if (sm == null) { - return; - } - String check = "getOption." + option.name(); - sm.checkPermission(new NetworkPermission(check)); - } - - public static void checkValueType(Object value, Class type) { - if (!type.isAssignableFrom(value.getClass())) { - String s = "Found: " + value.getClass().toString() + " Expected: " - + type.toString(); - throw new IllegalArgumentException(s); - } - } - - private static native void init(); - - /* - * Extension native implementations - * - * SO_FLOW_SLA - */ - public static native void setFlowOption(FileDescriptor fd, SocketFlow f); - public static native void getFlowOption(FileDescriptor fd, SocketFlow f); - public static native boolean flowSupported(); -} diff --git a/jdk/src/java.base/share/classes/sun/net/ext/ExtendedSocketOptions.java b/jdk/src/java.base/share/classes/sun/net/ext/ExtendedSocketOptions.java new file mode 100644 index 00000000000..a3300c3c0e9 --- /dev/null +++ b/jdk/src/java.base/share/classes/sun/net/ext/ExtendedSocketOptions.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2016, 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 sun.net.ext; + +import java.io.FileDescriptor; +import java.net.SocketException; +import java.net.SocketOption; +import java.util.Collections; +import java.util.Set; + +/** + * Defines the infrastructure to support extended socket options, beyond those + * defined in {@link java.net.StandardSocketOptions}. + * + * Extended socket options are accessed through the jdk.net API, which is in + * the jdk.net module. + */ +public abstract class ExtendedSocketOptions { + + private final Set> options; + + /** Tells whether or not the option is supported. */ + public final boolean isOptionSupported(SocketOption option) { + return options().contains(option); + } + + /** Return the, possibly empty, set of extended socket options available. */ + public final Set> options() { return options; } + + /** Sets the value of a socket option, for the given socket. */ + public abstract void setOption(FileDescriptor fd, SocketOption option, Object value) + throws SocketException; + + /** Returns the value of a socket option, for the given socket. */ + public abstract Object getOption(FileDescriptor fd, SocketOption option) + throws SocketException; + + protected ExtendedSocketOptions(Set> options) { + this.options = options; + } + + private static volatile ExtendedSocketOptions instance; + + public static final ExtendedSocketOptions getInstance() { return instance; } + + /** Registers support for extended socket options. Invoked by the jdk.net module. */ + public static final void register(ExtendedSocketOptions extOptions) { + if (instance != null) + throw new InternalError("Attempting to reregister extended options"); + + instance = extOptions; + } + + static { + try { + // If the class is present, it will be initialized which + // triggers registration of the extended socket options. + Class c = Class.forName("jdk.net.ExtendedSocketOptions"); + } catch (ClassNotFoundException e) { + // the jdk.net module is not present => no extended socket options + instance = new NoExtendedSocketOptions(); + } + } + + static final class NoExtendedSocketOptions extends ExtendedSocketOptions { + + NoExtendedSocketOptions() { + super(Collections.>emptySet()); + } + + @Override + public void setOption(FileDescriptor fd, SocketOption option, Object value) + throws SocketException + { + throw new UnsupportedOperationException( + "no extended options: " + option.name()); + } + + @Override + public Object getOption(FileDescriptor fd, SocketOption option) + throws SocketException + { + throw new UnsupportedOperationException( + "no extended options: " + option.name()); + } + } +} diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java b/jdk/src/java.base/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java index 36b3c1b7ab9..1faf49b8578 100644 --- a/jdk/src/java.base/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java +++ b/jdk/src/java.base/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java @@ -39,7 +39,7 @@ import java.util.Collections; import java.util.concurrent.*; import java.util.concurrent.locks.*; import sun.net.NetHooks; -import sun.net.ExtendedOptionsImpl; +import sun.net.ext.ExtendedSocketOptions; /** * Base implementation of AsynchronousSocketChannel @@ -512,9 +512,9 @@ abstract class AsynchronousSocketChannelImpl set.add(StandardSocketOptions.SO_REUSEPORT); } set.add(StandardSocketOptions.TCP_NODELAY); - if (ExtendedOptionsImpl.flowSupported()) { - set.add(jdk.net.ExtendedSocketOptions.SO_FLOW_SLA); - } + ExtendedSocketOptions extendedOptions = + ExtendedSocketOptions.getInstance(); + set.addAll(extendedOptions.options()); return Collections.unmodifiableSet(set); } } diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java b/jdk/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java index 77d14619222..f063e13ac13 100644 --- a/jdk/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java +++ b/jdk/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java @@ -33,7 +33,7 @@ import java.nio.channels.*; import java.nio.channels.spi.*; import java.util.*; import sun.net.ResourceManager; -import sun.net.ExtendedOptionsImpl; +import sun.net.ext.ExtendedSocketOptions; /** * An implementation of DatagramChannels. @@ -306,9 +306,9 @@ class DatagramChannelImpl set.add(StandardSocketOptions.IP_MULTICAST_IF); set.add(StandardSocketOptions.IP_MULTICAST_TTL); set.add(StandardSocketOptions.IP_MULTICAST_LOOP); - if (ExtendedOptionsImpl.flowSupported()) { - set.add(jdk.net.ExtendedSocketOptions.SO_FLOW_SLA); - } + ExtendedSocketOptions extendedOptions = + ExtendedSocketOptions.getInstance(); + set.addAll(extendedOptions.options()); return Collections.unmodifiableSet(set); } } diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/Net.java b/jdk/src/java.base/share/classes/sun/nio/ch/Net.java index 9a5c4dcb6f8..59d3167745b 100644 --- a/jdk/src/java.base/share/classes/sun/nio/ch/Net.java +++ b/jdk/src/java.base/share/classes/sun/nio/ch/Net.java @@ -27,15 +27,13 @@ package sun.nio.ch; import java.io.*; import java.net.*; -import jdk.net.*; import java.nio.channels.*; import java.util.*; import java.security.AccessController; import java.security.PrivilegedAction; -import sun.net.ExtendedOptionsImpl; +import sun.net.ext.ExtendedSocketOptions; import sun.security.action.GetPropertyAction; - public class Net { private Net() { } @@ -281,6 +279,9 @@ public class Net { // -- Socket options + static final ExtendedSocketOptions extendedOptions = + ExtendedSocketOptions.getInstance(); + static void setSocketOption(FileDescriptor fd, ProtocolFamily family, SocketOption name, Object value) throws IOException @@ -291,12 +292,8 @@ public class Net { // only simple values supported by this method Class type = name.type(); - if (type == SocketFlow.class) { - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new NetworkPermission("setOption.SO_FLOW_SLA")); - } - ExtendedOptionsImpl.setFlowOption(fd, (SocketFlow)value); + if (extendedOptions.isOptionSupported(name)) { + extendedOptions.setOption(fd, name, value); return; } @@ -353,14 +350,8 @@ public class Net { { Class type = name.type(); - if (type == SocketFlow.class) { - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new NetworkPermission("getOption.SO_FLOW_SLA")); - } - SocketFlow flow = SocketFlow.create(); - ExtendedOptionsImpl.getFlowOption(fd, flow); - return flow; + if (extendedOptions.isOptionSupported(name)) { + return extendedOptions.getOption(fd, name); } // only simple values supported by this method diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java b/jdk/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java index c4644920c3e..856e0cf2fb6 100644 --- a/jdk/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java +++ b/jdk/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java @@ -33,8 +33,7 @@ import java.nio.channels.*; import java.nio.channels.spi.*; import java.util.*; import sun.net.NetHooks; -import sun.net.ExtendedOptionsImpl; - +import sun.net.ext.ExtendedSocketOptions; /** * An implementation of SocketChannels @@ -242,9 +241,9 @@ class SocketChannelImpl // additional options required by socket adaptor set.add(StandardSocketOptions.IP_TOS); set.add(ExtendedSocketOption.SO_OOBINLINE); - if (ExtendedOptionsImpl.flowSupported()) { - set.add(jdk.net.ExtendedSocketOptions.SO_FLOW_SLA); - } + ExtendedSocketOptions extendedOptions = + ExtendedSocketOptions.getInstance(); + set.addAll(extendedOptions.options()); return Collections.unmodifiableSet(set); } } diff --git a/jdk/src/java.base/unix/classes/java/net/PlainDatagramSocketImpl.java b/jdk/src/java.base/unix/classes/java/net/PlainDatagramSocketImpl.java index f7c65931613..32640dff272 100644 --- a/jdk/src/java.base/unix/classes/java/net/PlainDatagramSocketImpl.java +++ b/jdk/src/java.base/unix/classes/java/net/PlainDatagramSocketImpl.java @@ -27,9 +27,7 @@ package java.net; import java.io.IOException; import java.util.Set; import java.util.HashSet; -import java.util.Collections; -import jdk.net.*; -import static sun.net.ExtendedOptionsImpl.*; +import sun.net.ext.ExtendedSocketOptions; /* * On Unix systems we simply delegate to native methods. @@ -43,8 +41,11 @@ class PlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl init(); } + static final ExtendedSocketOptions extendedOptions = + ExtendedSocketOptions.getInstance(); + protected void setOption(SocketOption name, T value) throws IOException { - if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) { + if (!extendedOptions.isOptionSupported(name)) { if (!name.equals(StandardSocketOptions.SO_REUSEPORT)) { super.setOption(name, value); } else { @@ -55,21 +56,16 @@ class PlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl } } } else { - if (!flowSupported()) { - throw new UnsupportedOperationException("unsupported option"); - } if (isClosed()) { throw new SocketException("Socket closed"); } - checkSetOptionPermission(name); - checkValueType(value, SocketFlow.class); - setFlowOption(getFileDescriptor(), (SocketFlow)value); + extendedOptions.setOption(fd, name, value); } } @SuppressWarnings("unchecked") protected T getOption(SocketOption name) throws IOException { - if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) { + if (!extendedOptions.isOptionSupported(name)) { if (!name.equals(StandardSocketOptions.SO_REUSEPORT)) { return super.getOption(name); } else { @@ -79,31 +75,23 @@ class PlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl throw new UnsupportedOperationException("unsupported option"); } } + } else { + if (isClosed()) { + throw new SocketException("Socket closed"); + } + return (T) extendedOptions.getOption(fd, name); } - if (!flowSupported()) { - throw new UnsupportedOperationException("unsupported option"); - } - if (isClosed()) { - throw new SocketException("Socket closed"); - } - checkGetOptionPermission(name); - SocketFlow flow = SocketFlow.create(); - getFlowOption(getFileDescriptor(), flow); - return (T)flow; } protected Set> supportedOptions() { - HashSet> options = new HashSet<>( - super.supportedOptions()); - - if (flowSupported()) { - options.add(ExtendedSocketOptions.SO_FLOW_SLA); - } + HashSet> options = new HashSet<>(super.supportedOptions()); + options.addAll(extendedOptions.options()); return options; } protected void socketSetOption(int opt, Object val) throws SocketException { - if (opt == SocketOptions.SO_REUSEPORT && !supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) { + if (opt == SocketOptions.SO_REUSEPORT && + !supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) { throw new UnsupportedOperationException("unsupported option"); } try { diff --git a/jdk/src/java.base/unix/classes/java/net/PlainSocketImpl.java b/jdk/src/java.base/unix/classes/java/net/PlainSocketImpl.java index 2ec573ea5a9..4a5f2b5ddd6 100644 --- a/jdk/src/java.base/unix/classes/java/net/PlainSocketImpl.java +++ b/jdk/src/java.base/unix/classes/java/net/PlainSocketImpl.java @@ -28,10 +28,7 @@ import java.io.IOException; import java.io.FileDescriptor; import java.util.Set; import java.util.HashSet; -import java.util.Collections; -import jdk.net.*; - -import static sun.net.ExtendedOptionsImpl.*; +import sun.net.ext.ExtendedSocketOptions; /* * On Unix systems we simply delegate to native methods. @@ -57,8 +54,11 @@ class PlainSocketImpl extends AbstractPlainSocketImpl this.fd = fd; } + static final ExtendedSocketOptions extendedOptions = + ExtendedSocketOptions.getInstance(); + protected void setOption(SocketOption name, T value) throws IOException { - if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) { + if (!extendedOptions.isOptionSupported(name)) { if (!name.equals(StandardSocketOptions.SO_REUSEPORT)) { super.setOption(name, value); } else { @@ -69,21 +69,19 @@ class PlainSocketImpl extends AbstractPlainSocketImpl } } } else { - if (getSocket() == null || !flowSupported()) { + if (getSocket() == null) { throw new UnsupportedOperationException("unsupported option"); } if (isClosedOrPending()) { throw new SocketException("Socket closed"); } - checkSetOptionPermission(name); - checkValueType(value, SocketFlow.class); - setFlowOption(getFileDescriptor(), (SocketFlow)value); + extendedOptions.setOption(fd, name, value); } } @SuppressWarnings("unchecked") protected T getOption(SocketOption name) throws IOException { - if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) { + if (!extendedOptions.isOptionSupported(name)) { if (!name.equals(StandardSocketOptions.SO_REUSEPORT)) { return super.getOption(name); } else { @@ -93,31 +91,28 @@ class PlainSocketImpl extends AbstractPlainSocketImpl throw new UnsupportedOperationException("unsupported option"); } } + } else { + if (getSocket() == null) { + throw new UnsupportedOperationException("unsupported option"); + } + if (isClosedOrPending()) { + throw new SocketException("Socket closed"); + } + return (T) extendedOptions.getOption(fd, name); } - if (getSocket() == null || !flowSupported()) { - throw new UnsupportedOperationException("unsupported option"); - } - if (isClosedOrPending()) { - throw new SocketException("Socket closed"); - } - checkGetOptionPermission(name); - SocketFlow flow = SocketFlow.create(); - getFlowOption(getFileDescriptor(), flow); - return (T)flow; } protected Set> supportedOptions() { - HashSet> options = new HashSet<>( - super.supportedOptions()); - - if (getSocket() != null && flowSupported()) { - options.add(ExtendedSocketOptions.SO_FLOW_SLA); + HashSet> options = new HashSet<>(super.supportedOptions()); + if (getSocket() != null) { + options.addAll(extendedOptions.options()); } return options; } protected void socketSetOption(int opt, boolean b, Object val) throws SocketException { - if (opt == SocketOptions.SO_REUSEPORT && !supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) { + if (opt == SocketOptions.SO_REUSEPORT && + !supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) { throw new UnsupportedOperationException("unsupported option"); } try { diff --git a/jdk/src/java.base/unix/native/libnet/ExtendedOptionsImpl.c b/jdk/src/java.base/unix/native/libnet/ExtendedOptionsImpl.c deleted file mode 100644 index 116d2e97d92..00000000000 --- a/jdk/src/java.base/unix/native/libnet/ExtendedOptionsImpl.c +++ /dev/null @@ -1,344 +0,0 @@ -/* - * Copyright (c) 2014, 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. - */ - -#include -#include - -#include "net_util.h" -#include "jdk_net_SocketFlow.h" - -static jclass sf_status_class; /* Status enum type */ - -static jfieldID sf_status; -static jfieldID sf_priority; -static jfieldID sf_bandwidth; - -static jfieldID sf_fd_fdID; /* FileDescriptor.fd */ - -/* References to the literal enum values */ - -static jobject sfs_NOSTATUS; -static jobject sfs_OK; -static jobject sfs_NOPERMISSION; -static jobject sfs_NOTCONNECTED; -static jobject sfs_NOTSUPPORTED; -static jobject sfs_ALREADYCREATED; -static jobject sfs_INPROGRESS; -static jobject sfs_OTHER; - -static jobject getEnumField(JNIEnv *env, char *name); -static void setStatus(JNIEnv *env, jobject obj, int errval); - -/* OS specific code is implemented in these three functions */ - -static jboolean flowSupported0() ; - -/* - * Class: sun_net_ExtendedOptionsImpl - * Method: init - * Signature: ()V - */ -JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_init - (JNIEnv *env, jclass UNUSED) -{ - static int initialized = 0; - jclass c; - - /* Global class references */ - - if (initialized) { - return; - } - - c = (*env)->FindClass(env, "jdk/net/SocketFlow$Status"); - CHECK_NULL(c); - sf_status_class = (*env)->NewGlobalRef(env, c); - CHECK_NULL(sf_status_class); - - /* int "fd" field of java.io.FileDescriptor */ - - c = (*env)->FindClass(env, "java/io/FileDescriptor"); - CHECK_NULL(c); - sf_fd_fdID = (*env)->GetFieldID(env, c, "fd", "I"); - CHECK_NULL(sf_fd_fdID); - - - /* SocketFlow fields */ - - c = (*env)->FindClass(env, "jdk/net/SocketFlow"); - CHECK_NULL(c); - - /* status */ - - sf_status = (*env)->GetFieldID(env, c, "status", - "Ljdk/net/SocketFlow$Status;"); - CHECK_NULL(sf_status); - - /* priority */ - - sf_priority = (*env)->GetFieldID(env, c, "priority", "I"); - CHECK_NULL(sf_priority); - - /* bandwidth */ - - sf_bandwidth = (*env)->GetFieldID(env, c, "bandwidth", "J"); - CHECK_NULL(sf_bandwidth); - - /* Initialize the static enum values */ - - sfs_NOSTATUS = getEnumField(env, "NO_STATUS"); - CHECK_NULL(sfs_NOSTATUS); - sfs_OK = getEnumField(env, "OK"); - CHECK_NULL(sfs_OK); - sfs_NOPERMISSION = getEnumField(env, "NO_PERMISSION"); - CHECK_NULL(sfs_NOPERMISSION); - sfs_NOTCONNECTED = getEnumField(env, "NOT_CONNECTED"); - CHECK_NULL(sfs_NOTCONNECTED); - sfs_NOTSUPPORTED = getEnumField(env, "NOT_SUPPORTED"); - CHECK_NULL(sfs_NOTSUPPORTED); - sfs_ALREADYCREATED = getEnumField(env, "ALREADY_CREATED"); - CHECK_NULL(sfs_ALREADYCREATED); - sfs_INPROGRESS = getEnumField(env, "IN_PROGRESS"); - CHECK_NULL(sfs_INPROGRESS); - sfs_OTHER = getEnumField(env, "OTHER"); - CHECK_NULL(sfs_OTHER); - initialized = JNI_TRUE; -} - -static jobject getEnumField(JNIEnv *env, char *name) -{ - jobject f; - jfieldID fID = (*env)->GetStaticFieldID(env, sf_status_class, name, - "Ljdk/net/SocketFlow$Status;"); - CHECK_NULL_RETURN(fID, NULL); - - f = (*env)->GetStaticObjectField(env, sf_status_class, fID); - CHECK_NULL_RETURN(f, NULL); - f = (*env)->NewGlobalRef(env, f); - CHECK_NULL_RETURN(f, NULL); - return f; -} - -/* - * Retrieve the int file-descriptor from a public socket type object. - * Gets impl, then the FileDescriptor from the impl, and then the fd - * from that. - */ -static int getFD(JNIEnv *env, jobject fileDesc) { - return (*env)->GetIntField(env, fileDesc, sf_fd_fdID); -} - -/** - * Sets the status field of a SocketFlow to one of the - * canned enum values - */ -static void setStatus (JNIEnv *env, jobject obj, int errval) -{ - switch (errval) { - case 0: /* OK */ - (*env)->SetObjectField(env, obj, sf_status, sfs_OK); - break; - case EPERM: - (*env)->SetObjectField(env, obj, sf_status, sfs_NOPERMISSION); - break; - case ENOTCONN: - (*env)->SetObjectField(env, obj, sf_status, sfs_NOTCONNECTED); - break; - case EOPNOTSUPP: - (*env)->SetObjectField(env, obj, sf_status, sfs_NOTSUPPORTED); - break; - case EALREADY: - (*env)->SetObjectField(env, obj, sf_status, sfs_ALREADYCREATED); - break; - case EINPROGRESS: - (*env)->SetObjectField(env, obj, sf_status, sfs_INPROGRESS); - break; - default: - (*env)->SetObjectField(env, obj, sf_status, sfs_OTHER); - break; - } -} - -#ifdef __solaris__ - -/* - * Class: sun_net_ExtendedOptionsImpl - * Method: setFlowOption - * Signature: (Ljava/io/FileDescriptor;Ljdk/net/SocketFlow;)V - */ -JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_setFlowOption - (JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow) -{ - int fd = getFD(env, fileDesc); - - if (fd < 0) { - NET_ERROR(env, JNU_JAVANETPKG "SocketException", "socket closed"); - return; - } else { - sock_flow_props_t props; - jlong bandwidth; - int rv; - - jint priority = (*env)->GetIntField(env, flow, sf_priority); - memset(&props, 0, sizeof(props)); - props.sfp_version = SOCK_FLOW_PROP_VERSION1; - - if (priority != jdk_net_SocketFlow_UNSET) { - props.sfp_mask |= SFP_PRIORITY; - props.sfp_priority = priority; - } - bandwidth = (*env)->GetLongField(env, flow, sf_bandwidth); - if (bandwidth > -1) { - props.sfp_mask |= SFP_MAXBW; - props.sfp_maxbw = (uint64_t) bandwidth; - } - rv = setsockopt(fd, SOL_SOCKET, SO_FLOW_SLA, &props, sizeof(props)); - if (rv < 0) { - if (errno == ENOPROTOOPT) { - JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", - "unsupported socket option"); - } else if (errno == EACCES || errno == EPERM) { - NET_ERROR(env, JNU_JAVANETPKG "SocketException", - "Permission denied"); - } else { - NET_ERROR(env, JNU_JAVANETPKG "SocketException", - "set option SO_FLOW_SLA failed"); - } - return; - } - setStatus(env, flow, props.sfp_status); - } -} - -/* - * Class: sun_net_ExtendedOptionsImpl - * Method: getFlowOption - * Signature: (Ljava/io/FileDescriptor;Ljdk/net/SocketFlow;)V - */ -JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_getFlowOption - (JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow) -{ - int fd = getFD(env, fileDesc); - - if (fd < 0) { - NET_ERROR(env, JNU_JAVANETPKG "SocketException", "socket closed"); - return; - } else { - sock_flow_props_t props; - int status; - socklen_t sz = sizeof(props); - - int rv = getsockopt(fd, SOL_SOCKET, SO_FLOW_SLA, &props, &sz); - if (rv < 0) { - if (errno == ENOPROTOOPT) { - JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", - "unsupported socket option"); - } else if (errno == EACCES || errno == EPERM) { - NET_ERROR(env, JNU_JAVANETPKG "SocketException", - "Permission denied"); - } else { - NET_ERROR(env, JNU_JAVANETPKG "SocketException", - "set option SO_FLOW_SLA failed"); - } - return; - } - /* first check status to see if flow exists */ - status = props.sfp_status; - setStatus(env, flow, status); - if (status == 0) { /* OK */ - /* can set the other fields now */ - if (props.sfp_mask & SFP_PRIORITY) { - (*env)->SetIntField(env, flow, sf_priority, props.sfp_priority); - } - if (props.sfp_mask & SFP_MAXBW) { - (*env)->SetLongField(env, flow, sf_bandwidth, - (jlong)props.sfp_maxbw); - } - } - } -} - -static jboolean flowsupported; -static jboolean flowsupported_set = JNI_FALSE; - -static jboolean flowSupported0() -{ - /* Do a simple dummy call, and try to figure out from that */ - sock_flow_props_t props; - int rv, s; - if (flowsupported_set) { - return flowsupported; - } - s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); - if (s < 0) { - flowsupported = JNI_FALSE; - flowsupported_set = JNI_TRUE; - return JNI_FALSE; - } - memset(&props, 0, sizeof(props)); - props.sfp_version = SOCK_FLOW_PROP_VERSION1; - props.sfp_mask |= SFP_PRIORITY; - props.sfp_priority = SFP_PRIO_NORMAL; - rv = setsockopt(s, SOL_SOCKET, SO_FLOW_SLA, &props, sizeof(props)); - if (rv != 0 && errno == ENOPROTOOPT) { - rv = JNI_FALSE; - } else { - rv = JNI_TRUE; - } - close(s); - flowsupported = rv; - flowsupported_set = JNI_TRUE; - return flowsupported; -} - -#else /* __solaris__ */ - -/* Non Solaris. Functionality is not supported. So, throw UnsupportedOpExc */ - -JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_setFlowOption - (JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow) -{ - JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", - "unsupported socket option"); -} - -JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_getFlowOption - (JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow) -{ - JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", - "unsupported socket option"); -} - -static jboolean flowSupported0() { - return JNI_FALSE; -} - -#endif /* __solaris__ */ - -JNIEXPORT jboolean JNICALL Java_sun_net_ExtendedOptionsImpl_flowSupported - (JNIEnv *env, jclass UNUSED) -{ - return flowSupported0(); -} diff --git a/jdk/src/java.base/unix/native/libnet/net_util_md.h b/jdk/src/java.base/unix/native/libnet/net_util_md.h index f440bd8ae6a..3a8c9f4d48e 100644 --- a/jdk/src/java.base/unix/native/libnet/net_util_md.h +++ b/jdk/src/java.base/unix/native/libnet/net_util_md.h @@ -120,47 +120,6 @@ int getDefaultIPv6Interface(struct in6_addr *target_addr); #ifdef __solaris__ int net_getParam(char *driver, char *param); - -#ifndef SO_FLOW_SLA -#define SO_FLOW_SLA 0x1018 - -#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4 -#pragma pack(4) #endif -/* - * Used with the setsockopt(SO_FLOW_SLA, ...) call to set - * per socket service level properties. - * When the application uses per-socket API, we will enforce the properties - * on both outbound and inbound packets. - * - * For now, only priority and maxbw are supported in SOCK_FLOW_PROP_VERSION1. - */ -typedef struct sock_flow_props_s { - int sfp_version; - uint32_t sfp_mask; - int sfp_priority; /* flow priority */ - uint64_t sfp_maxbw; /* bandwidth limit in bps */ - int sfp_status; /* flow create status for getsockopt */ -} sock_flow_props_t; - -#define SOCK_FLOW_PROP_VERSION1 1 - -/* bit mask values for sfp_mask */ -#define SFP_MAXBW 0x00000001 /* Flow Bandwidth Limit */ -#define SFP_PRIORITY 0x00000008 /* Flow priority */ - -/* possible values for sfp_priority */ -#define SFP_PRIO_NORMAL 1 -#define SFP_PRIO_HIGH 2 - -#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4 -#pragma pack() -#endif /* _LONG_LONG_ALIGNMENT */ - -#endif /* SO_FLOW_SLA */ -#endif /* __solaris__ */ - -JNIEXPORT jboolean JNICALL NET_IsFlowSupported(); - #endif /* NET_UTILS_MD_H */ diff --git a/jdk/src/jdk.net/share/classes/jdk/net/ExtendedSocketOptions.java b/jdk/src/jdk.net/share/classes/jdk/net/ExtendedSocketOptions.java new file mode 100644 index 00000000000..bcae6ce2251 --- /dev/null +++ b/jdk/src/jdk.net/share/classes/jdk/net/ExtendedSocketOptions.java @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2014, 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.net; + +import java.io.FileDescriptor; +import java.net.SocketException; +import java.net.SocketOption; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Collections; +import java.util.Set; +import jdk.internal.misc.JavaIOFileDescriptorAccess; +import jdk.internal.misc.SharedSecrets; + +/** + * Defines extended socket options, beyond those defined in + * {@link java.net.StandardSocketOptions}. These options may be platform + * specific. + * + * @since 1.8 + */ +public final class ExtendedSocketOptions { + + private static class ExtSocketOption implements SocketOption { + private final String name; + private final Class type; + ExtSocketOption(String name, Class type) { + this.name = name; + this.type = type; + } + @Override public String name() { return name; } + @Override public Class type() { return type; } + @Override public String toString() { return name; } + } + + private ExtendedSocketOptions() { } + + /** + * Service level properties. When a security manager is installed, + * setting or getting this option requires a {@link NetworkPermission} + * {@code ("setOption.SO_FLOW_SLA")} or {@code "getOption.SO_FLOW_SLA"} + * respectively. + */ + public static final SocketOption SO_FLOW_SLA = new + ExtSocketOption("SO_FLOW_SLA", SocketFlow.class); + + + private static final PlatformSocketOptions platformSocketOptions = + PlatformSocketOptions.get(); + + private static final boolean flowSupported = + platformSocketOptions.flowSupported(); + + private static final Set> extendedOptions = options(); + + static Set> options() { + if (flowSupported) + return Set.of(SO_FLOW_SLA); + else + return Collections.>emptySet(); + } + + static { + // Registers the extended socket options with the base module. + sun.net.ext.ExtendedSocketOptions.register( + new sun.net.ext.ExtendedSocketOptions(extendedOptions) { + + @Override + public void setOption(FileDescriptor fd, + SocketOption option, + Object value) + throws SocketException + { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + sm.checkPermission(new NetworkPermission("setOption." + option.name())); + + if (fd == null || !fd.valid()) + throw new SocketException("socket closed"); + + if (option == SO_FLOW_SLA) { + assert flowSupported; + SocketFlow flow = checkValueType(value, option.type()); + setFlowOption(fd, flow); + } else { + throw new InternalError("Unexpected option " + option); + } + } + + @Override + public Object getOption(FileDescriptor fd, + SocketOption option) + throws SocketException + { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + sm.checkPermission(new NetworkPermission("getOption." + option.name())); + + if (fd == null || !fd.valid()) + throw new SocketException("socket closed"); + + if (option == SO_FLOW_SLA) { + assert flowSupported; + SocketFlow flow = SocketFlow.create(); + getFlowOption(fd, flow); + return flow; + } else { + throw new InternalError("Unexpected option " + option); + } + } + }); + } + + @SuppressWarnings("unchecked") + private static T checkValueType(Object value, Class type) { + if (!type.isAssignableFrom(value.getClass())) { + String s = "Found: " + value.getClass() + ", Expected: " + type; + throw new IllegalArgumentException(s); + } + return (T) value; + } + + private static final JavaIOFileDescriptorAccess fdAccess = + SharedSecrets.getJavaIOFileDescriptorAccess(); + + private static void setFlowOption(FileDescriptor fd, SocketFlow f) + throws SocketException + { + int status = platformSocketOptions.setFlowOption(fdAccess.get(fd), + f.priority(), + f.bandwidth()); + f.status(status); // augment the given flow with the status + } + + private static void getFlowOption(FileDescriptor fd, SocketFlow f) + throws SocketException + { + int status = platformSocketOptions.getFlowOption(fdAccess.get(fd), f); + f.status(status); // augment the given flow with the status + } + + static class PlatformSocketOptions { + + protected PlatformSocketOptions() {} + + @SuppressWarnings("unchecked") + private static PlatformSocketOptions newInstance(String cn) { + Class c; + try { + c = (Class)Class.forName(cn); + return c.getConstructor(new Class[] { }).newInstance(); + } catch (ReflectiveOperationException x) { + throw new AssertionError(x); + } + } + + private static PlatformSocketOptions create() { + String osname = AccessController.doPrivileged( + new PrivilegedAction() { + public String run() { + return System.getProperty("os.name"); + } + }); + if ("SunOS".equals(osname)) + return newInstance("jdk.net.SolarisSocketOptions"); + return new PlatformSocketOptions(); + } + + private static final PlatformSocketOptions instance = create(); + + static PlatformSocketOptions get() { + return instance; + } + + int setFlowOption(int fd, int priority, long bandwidth) + throws SocketException + { + throw new UnsupportedOperationException("unsupported socket option"); + } + + int getFlowOption(int fd, SocketFlow f) throws SocketException { + throw new UnsupportedOperationException("unsupported socket option"); + } + + boolean flowSupported() { + return false; + } + } +} diff --git a/jdk/src/java.base/share/classes/jdk/net/NetworkPermission.java b/jdk/src/jdk.net/share/classes/jdk/net/NetworkPermission.java similarity index 100% rename from jdk/src/java.base/share/classes/jdk/net/NetworkPermission.java rename to jdk/src/jdk.net/share/classes/jdk/net/NetworkPermission.java diff --git a/jdk/src/java.base/share/classes/jdk/net/SocketFlow.java b/jdk/src/jdk.net/share/classes/jdk/net/SocketFlow.java similarity index 69% rename from jdk/src/java.base/share/classes/jdk/net/SocketFlow.java rename to jdk/src/jdk.net/share/classes/jdk/net/SocketFlow.java index 12d1ed386d1..91c62cfa3d4 100644 --- a/jdk/src/java.base/share/classes/jdk/net/SocketFlow.java +++ b/jdk/src/jdk.net/share/classes/jdk/net/SocketFlow.java @@ -47,17 +47,18 @@ import java.lang.annotation.Native; */ public class SocketFlow { - private static final int UNSET = -1; + @Native public static final int UNSET = -1; @Native public static final int NORMAL_PRIORITY = 1; @Native public static final int HIGH_PRIORITY = 2; - private int priority = NORMAL_PRIORITY; - - private long bandwidth = UNSET; - - private Status status = Status.NO_STATUS; - - private SocketFlow() {} + @Native private static final int NO_STATUS_VALUE = 0; + @Native private static final int OK_VALUE = 1; + @Native private static final int NO_PERMISSION_VALUE = 2; + @Native private static final int NOT_CONNECTED_VALUE = 3; + @Native private static final int NOT_SUPPORTED_VALUE = 4; + @Native private static final int ALREADY_CREATED_VALUE = 5; + @Native private static final int IN_PROGRESS_VALUE = 6; + @Native private static final int OTHER_VALUE = 7; /** * Enumeration of the return values from the SO_FLOW_SLA @@ -72,37 +73,56 @@ public class SocketFlow { * Set or get socket option has not been called yet. Status * values can only be retrieved after calling set or get. */ - NO_STATUS, + NO_STATUS(NO_STATUS_VALUE), /** * Flow successfully created. */ - OK, + OK(OK_VALUE), /** * Caller has no permission to create flow. */ - NO_PERMISSION, + NO_PERMISSION(NO_PERMISSION_VALUE), /** * Flow can not be created because socket is not connected. */ - NOT_CONNECTED, + NOT_CONNECTED(NOT_CONNECTED_VALUE), /** * Flow creation not supported for this socket. */ - NOT_SUPPORTED, + NOT_SUPPORTED(NOT_SUPPORTED_VALUE), /** * A flow already exists with identical attributes. */ - ALREADY_CREATED, + ALREADY_CREATED(ALREADY_CREATED_VALUE), /** * A flow is being created. */ - IN_PROGRESS, + IN_PROGRESS(IN_PROGRESS_VALUE), /** * Some other unspecified error. */ - OTHER + OTHER(OTHER_VALUE); + + private final int value; + Status(int value) { this.value = value; } + + static Status from(int value) { + if (value == NO_STATUS.value) return NO_STATUS; + else if (value == OK.value) return OK; + else if (value == NO_PERMISSION.value) return NO_PERMISSION; + else if (value == NOT_CONNECTED.value) return NOT_CONNECTED; + else if (value == NOT_SUPPORTED.value) return NOT_SUPPORTED; + else if (value == ALREADY_CREATED.value) return ALREADY_CREATED; + else if (value == IN_PROGRESS.value) return IN_PROGRESS; + else if (value == OTHER.value) return OTHER; + else throw new InternalError("Unknown value: " + value); + } } + private int priority = NORMAL_PRIORITY; + private long bandwidth = UNSET; + private Status status = Status.NO_STATUS; + /** * Creates a new SocketFlow that can be used to set the SO_FLOW_SLA * socket option and create a socket flow. @@ -111,6 +131,8 @@ public class SocketFlow { return new SocketFlow(); } + private SocketFlow() { } + /** * Sets this SocketFlow's priority. Must be either NORMAL_PRIORITY * HIGH_PRIORITY. If not set, a flow's priority is normal. @@ -119,9 +141,8 @@ public class SocketFlow { * HIGH_PRIORITY. */ public SocketFlow priority(int priority) { - if (priority != NORMAL_PRIORITY && priority != HIGH_PRIORITY) { - throw new IllegalArgumentException("invalid priority"); - } + if (priority != NORMAL_PRIORITY && priority != HIGH_PRIORITY) + throw new IllegalArgumentException("invalid priority :" + priority); this.priority = priority; return this; } @@ -133,11 +154,9 @@ public class SocketFlow { * @throws IllegalArgumentException if bandwidth is less than zero. */ public SocketFlow bandwidth(long bandwidth) { - if (bandwidth < 0) { - throw new IllegalArgumentException("invalid bandwidth"); - } else { - this.bandwidth = bandwidth; - } + if (bandwidth < 0) + throw new IllegalArgumentException("invalid bandwidth: " + bandwidth); + this.bandwidth = bandwidth; return this; } @@ -164,4 +183,18 @@ public class SocketFlow { public Status status() { return status; } + + void status(int status) { + this.status = Status.from(status); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(super.toString()); + sb.append(" [ priority=").append(priority()) + .append(", bandwidth=").append(bandwidth()) + .append(", status=").append(status()) + .append(" ]"); + return sb.toString(); + } } diff --git a/jdk/src/java.base/share/classes/jdk/net/Sockets.java b/jdk/src/jdk.net/share/classes/jdk/net/Sockets.java similarity index 94% rename from jdk/src/java.base/share/classes/jdk/net/Sockets.java rename to jdk/src/jdk.net/share/classes/jdk/net/Sockets.java index a8b78b044d8..983fe38956f 100644 --- a/jdk/src/java.base/share/classes/jdk/net/Sockets.java +++ b/jdk/src/jdk.net/share/classes/jdk/net/Sockets.java @@ -27,15 +27,12 @@ package jdk.net; import java.net.*; import java.io.IOException; -import java.io.FileDescriptor; -import java.security.PrivilegedAction; -import java.security.AccessController; -import java.lang.reflect.Field; -import java.util.Set; -import java.util.HashSet; -import java.util.HashMap; import java.util.Collections; -import sun.net.ExtendedOptionsImpl; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import jdk.net.ExtendedSocketOptions.PlatformSocketOptions; /** * Defines static methods to set and get socket options defined by the @@ -57,12 +54,8 @@ import sun.net.ExtendedOptionsImpl; */ public class Sockets { - private static final HashMap,Set>> - options = new HashMap<>(); - - static { - initOptionSets(); - } + private static final Map,Set>> + options = optionSets(); private Sockets() {} @@ -259,14 +252,16 @@ public class Sockets { */ static boolean isReusePortAvailable() { if (!checkedReusePort) { - isReusePortAvailable = isReusePortAvailable0(); + Set> s = new Socket().supportedOptions(); + isReusePortAvailable = s.contains(StandardSocketOptions.SO_REUSEPORT); checkedReusePort = true; } return isReusePortAvailable; } - private static void initOptionSets() { - boolean flowsupported = ExtendedOptionsImpl.flowSupported(); + private static Map,Set>> optionSets() { + Map,Set>> options = new HashMap<>(); + boolean flowsupported = PlatformSocketOptions.get().flowSupported(); boolean reuseportsupported = isReusePortAvailable(); // Socket @@ -333,7 +328,7 @@ public class Sockets { } set = Collections.unmodifiableSet(set); options.put(MulticastSocket.class, set); - } - private static native boolean isReusePortAvailable0(); + return Collections.unmodifiableMap(options); + } } diff --git a/jdk/src/java.base/share/classes/jdk/net/package-info.java b/jdk/src/jdk.net/share/classes/jdk/net/package-info.java similarity index 100% rename from jdk/src/java.base/share/classes/jdk/net/package-info.java rename to jdk/src/jdk.net/share/classes/jdk/net/package-info.java diff --git a/jdk/src/jdk.net/share/classes/module-info.java b/jdk/src/jdk.net/share/classes/module-info.java new file mode 100644 index 00000000000..95fb57915a8 --- /dev/null +++ b/jdk/src/jdk.net/share/classes/module-info.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2016, 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. + */ + +module jdk.net { + exports jdk.net; +} + diff --git a/jdk/src/java.base/windows/native/libnet/ExtendedOptionsImpl.c b/jdk/src/jdk.net/solaris/classes/jdk/net/SolarisSocketOptions.java similarity index 52% rename from jdk/src/java.base/windows/native/libnet/ExtendedOptionsImpl.c rename to jdk/src/jdk.net/solaris/classes/jdk/net/SolarisSocketOptions.java index 2bd955cd13e..1381f22014b 100644 --- a/jdk/src/java.base/windows/native/libnet/ExtendedOptionsImpl.c +++ b/jdk/src/jdk.net/solaris/classes/jdk/net/SolarisSocketOptions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -23,43 +23,34 @@ * questions. */ -#include -#include +package jdk.net; -#include "net_util.h" +import java.net.SocketException; +import java.security.AccessController; +import java.security.PrivilegedAction; +import jdk.net.ExtendedSocketOptions.PlatformSocketOptions; -/* - * Class: sun_net_ExtendedOptionsImpl - * Method: init - * Signature: ()V - */ -JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_init - (JNIEnv *env, jclass UNUSED) -{ -} - -/* Non Solaris. Functionality is not supported. So, throw UnsupportedOpExc */ - -JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_setFlowOption - (JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow) -{ - JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", - "unsupported socket option"); -} - -JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_getFlowOption - (JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow) -{ - JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", - "unsupported socket option"); -} - -static jboolean flowSupported0() { - return JNI_FALSE; -} - -JNIEXPORT jboolean JNICALL Java_sun_net_ExtendedOptionsImpl_flowSupported - (JNIEnv *env, jclass UNUSED) -{ - return JNI_FALSE; +class SolarisSocketOptions extends PlatformSocketOptions { + + public SolarisSocketOptions() { } + + @Override native int setFlowOption(int fd, int priority, long bandwidth) + throws SocketException; + + @Override native int getFlowOption(int fd, SocketFlow f) + throws SocketException; + + @Override native boolean flowSupported(); + + private static native void init(); + + static { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + System.loadLibrary("extnet"); + return null; + } + }); + init(); + } } diff --git a/jdk/src/jdk.net/solaris/native/libextnet/SolarisSocketOptions.c b/jdk/src/jdk.net/solaris/native/libextnet/SolarisSocketOptions.c new file mode 100644 index 00000000000..96d6ed96088 --- /dev/null +++ b/jdk/src/jdk.net/solaris/native/libextnet/SolarisSocketOptions.c @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2014, 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. + */ + + +#include "SolarisSocketOptions.h" + +static jfieldID sf_priority; +static jfieldID sf_bandwidth; + +static int initialized = 0; + +/* + * Class: jdk_net_SolarisSocketOptions + * Method: init + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_jdk_net_SolarisSocketOptions_init + (JNIEnv *env, jclass unused) +{ + if (!initialized) { + jclass c = (*env)->FindClass(env, "jdk/net/SocketFlow"); + CHECK_NULL(c); + sf_priority = (*env)->GetFieldID(env, c, "priority", "I"); + CHECK_NULL(sf_priority); + sf_bandwidth = (*env)->GetFieldID(env, c, "bandwidth", "J"); + CHECK_NULL(sf_bandwidth); + initialized = 1; + } +} + +/** Return the Status value. */ +static jint toStatus(int errval) +{ + switch (errval) { + case 0: return jdk_net_SocketFlow_OK_VALUE; + case EPERM: return jdk_net_SocketFlow_NO_PERMISSION_VALUE; + case ENOTCONN: return jdk_net_SocketFlow_NOT_CONNECTED_VALUE; + case EOPNOTSUPP: return jdk_net_SocketFlow_NOT_SUPPORTED_VALUE; + case EALREADY: return jdk_net_SocketFlow_ALREADY_CREATED_VALUE; + case EINPROGRESS: return jdk_net_SocketFlow_IN_PROGRESS_VALUE; + default: return jdk_net_SocketFlow_OTHER_VALUE; + } +} + +void throwByNameWithLastError + (JNIEnv *env, const char *name, const char *defaultDetail) +{ + char defaultMsg[255]; + sprintf(defaultMsg, "errno: %d, %s", errno, defaultDetail); + JNU_ThrowByNameWithLastError(env, name, defaultMsg); +} + +/* + * Class: jdk_net_SolarisSocketOptions + * Method: setFlowOption0 + * Signature: (IIJ)I + */ +JNIEXPORT jint JNICALL Java_jdk_net_SolarisSocketOptions_setFlowOption + (JNIEnv *env, jobject unused, jint fd, jint priority, jlong bandwidth) +{ + int rv; + sock_flow_props_t props; + memset(&props, 0, sizeof(props)); + props.sfp_version = SOCK_FLOW_PROP_VERSION1; + + if (priority != jdk_net_SocketFlow_UNSET) { + props.sfp_mask |= SFP_PRIORITY; + props.sfp_priority = priority; + } + if (bandwidth > jdk_net_SocketFlow_UNSET) { + props.sfp_mask |= SFP_MAXBW; + props.sfp_maxbw = (uint64_t) bandwidth; + } + + rv = setsockopt(fd, SOL_SOCKET, SO_FLOW_SLA, &props, sizeof(props)); + + if (rv < 0) { + if (errno == ENOPROTOOPT) { + JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", + "unsupported socket option"); + } else if (errno == EACCES || errno == EPERM) { + JNU_ThrowByName(env, "java/net/SocketException", "Permission denied"); + } else { + throwByNameWithLastError(env, "java/net/SocketException", + "set option SO_FLOW_SLA failed"); + } + return 0; + } + return toStatus(props.sfp_status); +} + +/* + * Class: jdk_net_SolarisSocketOptions + * Method: getFlowOption0 + * Signature: (ILjdk/net/SocketFlow;)I + */ +JNIEXPORT jint JNICALL Java_jdk_net_SolarisSocketOptions_getFlowOption + (JNIEnv *env, jobject unused, jint fd, jobject flow) +{ + sock_flow_props_t props; + socklen_t sz = sizeof(props); + + int rv = getsockopt(fd, SOL_SOCKET, SO_FLOW_SLA, &props, &sz); + + if (rv < 0) { + if (errno == ENOPROTOOPT) { + JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", + "unsupported socket option"); + } else if (errno == EACCES || errno == EPERM) { + JNU_ThrowByName(env, "java/net/SocketException", "Permission denied"); + } else { + throwByNameWithLastError(env, "java/net/SocketException", + "get option SO_FLOW_SLA failed"); + } + return -1; + } + /* first check status to see if flow exists */ + if (props.sfp_status == 0) { /* OK */ + /* can set the other fields now */ + if (props.sfp_mask & SFP_PRIORITY) { + (*env)->SetIntField(env, flow, sf_priority, props.sfp_priority); + } + if (props.sfp_mask & SFP_MAXBW) { + (*env)->SetLongField(env, flow, sf_bandwidth, + (jlong)props.sfp_maxbw); + } + } + return toStatus(props.sfp_status); +} + +JNIEXPORT jboolean JNICALL Java_jdk_net_SolarisSocketOptions_flowSupported + (JNIEnv *env, jobject unused) +{ + /* Do a simple dummy call, and try to figure out from that */ + sock_flow_props_t props; + int rv, s; + + s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (s < 0) { + return JNI_FALSE; + } + memset(&props, 0, sizeof(props)); + props.sfp_version = SOCK_FLOW_PROP_VERSION1; + props.sfp_mask |= SFP_PRIORITY; + props.sfp_priority = SFP_PRIO_NORMAL; + rv = setsockopt(s, SOL_SOCKET, SO_FLOW_SLA, &props, sizeof(props)); + if (rv != 0 && errno == ENOPROTOOPT) { + rv = JNI_FALSE; + } else { + rv = JNI_TRUE; + } + close(s); + return rv; +} diff --git a/jdk/src/jdk.net/solaris/native/libextnet/SolarisSocketOptions.h b/jdk/src/jdk.net/solaris/native/libextnet/SolarisSocketOptions.h new file mode 100644 index 00000000000..81c65544680 --- /dev/null +++ b/jdk/src/jdk.net/solaris/native/libextnet/SolarisSocketOptions.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2016, 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. + */ + +#ifndef SOLARIS_SOCKET_OPTIONS_H +#define SOLARIS_SOCKET_OPTIONS_H + +#include +#include +#include +#include +#include + +#include "jni_util.h" +#include "jdk_net_SocketFlow.h" +#include "SolarisSocketOptions.h" +#include "jdk_net_SolarisSocketOptions.h" + +#ifndef SO_FLOW_SLA +#define SO_FLOW_SLA 0x1018 + +#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4 +#pragma pack(4) +#endif + +/* + * Used with the setsockopt(SO_FLOW_SLA, ...) call to set + * per socket service level properties. + * When the application uses per-socket API, we will enforce the properties + * on both outbound and inbound packets. + * + * For now, only priority and maxbw are supported in SOCK_FLOW_PROP_VERSION1. + */ +typedef struct sock_flow_props_s { + int sfp_version; + uint32_t sfp_mask; + int sfp_priority; /* flow priority */ + uint64_t sfp_maxbw; /* bandwidth limit in bps */ + int sfp_status; /* flow create status for getsockopt */ +} sock_flow_props_t; + +#define SOCK_FLOW_PROP_VERSION1 1 + +/* bit mask values for sfp_mask */ +#define SFP_MAXBW 0x00000001 /* Flow Bandwidth Limit */ +#define SFP_PRIORITY 0x00000008 /* Flow priority */ + +/* possible values for sfp_priority */ +#define SFP_PRIO_NORMAL 1 +#define SFP_PRIO_HIGH 2 + +#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4 +#pragma pack() +#endif /* _LONG_LONG_ALIGNMENT */ + +#endif /* SO_FLOW_SLA */ + +#endif /* SOLARIS_SOCKET_OPTIONS_H */ diff --git a/jdk/src/jdk.policytool/share/classes/module-info.java b/jdk/src/jdk.policytool/share/classes/module-info.java index aedfc91554a..f972e1cd15a 100644 --- a/jdk/src/jdk.policytool/share/classes/module-info.java +++ b/jdk/src/jdk.policytool/share/classes/module-info.java @@ -28,6 +28,7 @@ module jdk.policytool { requires java.logging; requires java.management; requires java.sql; + requires jdk.net; requires java.security.jgss; requires jdk.security.jgss; } diff --git a/jdk/test/java/net/SocketOption/OptionsTest.java b/jdk/test/java/net/SocketOption/OptionsTest.java index 5b109d533ac..81f33f73b9f 100644 --- a/jdk/test/java/net/SocketOption/OptionsTest.java +++ b/jdk/test/java/net/SocketOption/OptionsTest.java @@ -23,11 +23,13 @@ /* * @test - * @bug 8036979 8072384 + * @bug 8036979 8072384 8044773 * @run main/othervm -Xcheck:jni OptionsTest * @run main/othervm -Xcheck:jni -Djava.net.preferIPv4Stack=true OptionsTest + * @run main/othervm -Djdk.launcher.limitmods=java.base OptionsTest */ +import java.lang.reflect.Method; import java.net.*; import java.util.*; @@ -43,7 +45,7 @@ public class OptionsTest { } Object option; Object testValue; - }; + } // The tests set the option using the new API, read back the set value // which could be diferent, and then use the legacy get API to check @@ -223,8 +225,7 @@ public class OptionsTest { } else if (option.equals(StandardSocketOptions.SO_REUSEPORT) && reuseport) { return Boolean.valueOf(socket.getOption(StandardSocketOptions.SO_REUSEPORT)); } else if (option.equals(StandardSocketOptions.IP_TOS)) { - return Integer.valueOf(jdk.net.Sockets.getOption( - socket, StandardSocketOptions.IP_TOS)); + return getServerSocketTrafficClass(socket); } else { throw new RuntimeException("unexecpted socket option"); } @@ -281,4 +282,20 @@ public class OptionsTest { doDgSocketTests(); doMcSocketTests(); } + + // Reflectively access jdk.net.Sockets.getOption so that the test can run + // without the jdk.net module. + static Object getServerSocketTrafficClass(ServerSocket ss) throws Exception { + try { + Class c = Class.forName("jdk.net.Sockets"); + Method m = c.getDeclaredMethod("getOption", ServerSocket.class, SocketOption.class); + return m.invoke(null, ss, StandardSocketOptions.IP_TOS); + } catch (ClassNotFoundException e) { + // Ok, jdk.net module not present, just fall back + System.out.println("jdk.net module not present, falling back."); + return Integer.valueOf(ss.getOption(StandardSocketOptions.IP_TOS)); + } catch (ReflectiveOperationException e) { + throw new AssertionError(e); + } + } } diff --git a/jdk/test/java/net/SocketOption/UnsupportedOptionsTest.java b/jdk/test/java/net/SocketOption/UnsupportedOptionsTest.java index 074f7644b9d..0ab43f6ff27 100644 --- a/jdk/test/java/net/SocketOption/UnsupportedOptionsTest.java +++ b/jdk/test/java/net/SocketOption/UnsupportedOptionsTest.java @@ -21,34 +21,48 @@ * questions. */ -import jdk.net.ExtendedSocketOptions; - import java.io.IOException; +import java.lang.reflect.Field; import java.net.*; +import java.util.ArrayList; +import java.util.List; /* * @test - * @bug 8143554 - * @run main UnsupportedOptionsTest + * @bug 8143554 8044773 * @summary Test checks that UnsupportedOperationException for unsupported * SOCKET_OPTIONS is thrown by both getOption() and setOption() methods. + * @run main UnsupportedOptionsTest + * @run main/othervm -Djdk.launcher.limitmods=java.base UnsupportedOptionsTest */ + public class UnsupportedOptionsTest { - private static final SocketOption[] SOCKET_OPTIONS = { - StandardSocketOptions.IP_MULTICAST_IF, - StandardSocketOptions.IP_MULTICAST_LOOP, - StandardSocketOptions.IP_MULTICAST_TTL, - StandardSocketOptions.IP_TOS, - StandardSocketOptions.SO_BROADCAST, - StandardSocketOptions.SO_KEEPALIVE, - StandardSocketOptions.SO_LINGER, - StandardSocketOptions.SO_RCVBUF, - StandardSocketOptions.SO_REUSEADDR, - StandardSocketOptions.SO_SNDBUF, - StandardSocketOptions.TCP_NODELAY, - ExtendedSocketOptions.SO_FLOW_SLA - }; + private static final List> socketOptions = new ArrayList<>(); + + static { + socketOptions.add(StandardSocketOptions.IP_MULTICAST_IF); + socketOptions.add(StandardSocketOptions.IP_MULTICAST_LOOP); + socketOptions.add(StandardSocketOptions.IP_MULTICAST_TTL); + socketOptions.add(StandardSocketOptions.IP_TOS); + socketOptions.add(StandardSocketOptions.SO_BROADCAST); + socketOptions.add(StandardSocketOptions.SO_KEEPALIVE); + socketOptions.add(StandardSocketOptions.SO_LINGER); + socketOptions.add(StandardSocketOptions.SO_RCVBUF); + socketOptions.add(StandardSocketOptions.SO_REUSEADDR); + socketOptions.add(StandardSocketOptions.SO_SNDBUF); + socketOptions.add(StandardSocketOptions.TCP_NODELAY); + + try { + Class c = Class.forName("jdk.net.ExtendedSocketOptions"); + Field field = c.getField("SO_FLOW_SLA"); + socketOptions.add((SocketOption)field.get(null)); + } catch (ClassNotFoundException e) { + // ignore, jdk.net module not present + } catch (ReflectiveOperationException e) { + throw new AssertionError(e); + } + } public static void main(String[] args) throws IOException { Socket s = new Socket(); @@ -56,7 +70,7 @@ public class UnsupportedOptionsTest { DatagramSocket ds = new DatagramSocket(); MulticastSocket ms = new MulticastSocket(); - for (SocketOption option : SOCKET_OPTIONS) { + for (SocketOption option : socketOptions) { if (!s.supportedOptions().contains(option)) { testUnsupportedSocketOption(s, option); } diff --git a/jdk/test/java/nio/channels/DatagramChannel/SocketOptionTests.java b/jdk/test/java/nio/channels/DatagramChannel/SocketOptionTests.java index 40aef3282ac..00281647f17 100644 --- a/jdk/test/java/nio/channels/DatagramChannel/SocketOptionTests.java +++ b/jdk/test/java/nio/channels/DatagramChannel/SocketOptionTests.java @@ -22,8 +22,10 @@ */ /* @test - * @bug 4640544 + * @bug 4640544 8044773 * @summary Unit test for setOption/getOption/options methods + * @run main SocketOptionTests + * @run main/othervm -Djdk.launcher.limitmods=java.base SocketOptionTests */ import java.nio.*; diff --git a/jdk/test/java/nio/channels/ServerSocketChannel/SocketOptionTests.java b/jdk/test/java/nio/channels/ServerSocketChannel/SocketOptionTests.java index 0a3aa9dee32..a0b2b6a8e82 100644 --- a/jdk/test/java/nio/channels/ServerSocketChannel/SocketOptionTests.java +++ b/jdk/test/java/nio/channels/ServerSocketChannel/SocketOptionTests.java @@ -22,9 +22,11 @@ */ /* @test - * @bug 4640544 + * @bug 4640544 8044773 * @summary Unit test for ServerSocketChannel setOption/getOption/options * methods. + * @run main SocketOptionTests + * @run main/othervm -Djdk.launcher.limitmods=java.base SocketOptionTests */ import java.nio.*; diff --git a/jdk/test/java/nio/channels/SocketChannel/SocketOptionTests.java b/jdk/test/java/nio/channels/SocketChannel/SocketOptionTests.java index f1cb496afea..74f87c71623 100644 --- a/jdk/test/java/nio/channels/SocketChannel/SocketOptionTests.java +++ b/jdk/test/java/nio/channels/SocketChannel/SocketOptionTests.java @@ -22,9 +22,11 @@ */ /* @test - * @bug 4640544 + * @bug 4640544 8044773 * @summary Unit test to check SocketChannel setOption/getOption/options * methods. + * @run main SocketOptionTests + * @run main/othervm -Djdk.launcher.limitmods=java.base SocketOptionTests */ import java.nio.*; diff --git a/jdk/test/jdk/net/SocketFlow/SocketFlowBasic.java b/jdk/test/jdk/net/SocketFlow/SocketFlowBasic.java new file mode 100644 index 00000000000..ca02ad931d6 --- /dev/null +++ b/jdk/test/jdk/net/SocketFlow/SocketFlowBasic.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2016, 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 + * @bug 8765432 + * @summary Basic test for SocketFlow API + * @run testng SocketFlowBasic + */ + +import jdk.net.SocketFlow; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; +import static jdk.net.SocketFlow.*; +import static org.testng.Assert.*; + +public class SocketFlowBasic { + + @DataProvider + public Object[][] validPriorities() { + return new Object[][] { {HIGH_PRIORITY}, {NORMAL_PRIORITY} }; + } + + @Test(dataProvider = "validPriorities") + public void priority(long validPriority) { + SocketFlow flow = SocketFlow.create(); + flow.bandwidth(validPriority); + long bandwidth = flow.bandwidth(); + assertTrue(bandwidth == validPriority, "Expected " + validPriority + ", got" + bandwidth); + } + + @DataProvider + public Object[][] invalidPriorities() { + return new Object[][] { {HIGH_PRIORITY+10}, {NORMAL_PRIORITY-10000} }; + } + + @Test(dataProvider = "invalidPriorities", expectedExceptions = IllegalArgumentException.class) + public void priority(int invalidPriority) { + SocketFlow flow = SocketFlow.create(); + flow.priority(invalidPriority); + } + + @DataProvider + public Object[][] positiveBandwidth() { + return new Object[][] { {0}, {100}, {Integer.MAX_VALUE}, {Long.MAX_VALUE} }; + } + + @Test(dataProvider = "positiveBandwidth") + public void bandwidth(long posBandwidth) { + SocketFlow flow = SocketFlow.create(); + flow.bandwidth(posBandwidth); + long bandwidth = flow.bandwidth(); + assertTrue(bandwidth == posBandwidth, "Expected " + posBandwidth + ", got" + bandwidth); + } + + + @DataProvider + public Object[][] negativeBandwidth() { + return new Object[][] { {-1}, {-100}, {Integer.MIN_VALUE}, {Long.MIN_VALUE} }; + } + + @Test(dataProvider = "negativeBandwidth", expectedExceptions = IllegalArgumentException.class) + public void invalidBandwidth(long negBandwidth) { + SocketFlow flow = SocketFlow.create(); + flow.bandwidth(negBandwidth); + } + + @Test + public void status() { + SocketFlow flow = SocketFlow.create(); + assertTrue(flow.status() == Status.NO_STATUS); + } +} diff --git a/jdk/test/jdk/net/Sockets/Test.java b/jdk/test/jdk/net/Sockets/Test.java index bf3758c5bae..8bb03c54919 100644 --- a/jdk/test/jdk/net/Sockets/Test.java +++ b/jdk/test/jdk/net/Sockets/Test.java @@ -23,8 +23,9 @@ /* * @test - * @bug 8032808 - * @run main/othervm -Xcheck:jni Test + * @bug 8032808 8044773 + * @modules jdk.net + * @run main/othervm -Xcheck:jni Test success * @run main/othervm/policy=policy.fail -Xcheck:jni Test fail * @run main/othervm/policy=policy.success -Xcheck:jni Test success */ @@ -35,15 +36,13 @@ import java.nio.channels.*; import java.util.concurrent.*; import java.util.Set; import jdk.net.*; +import static java.lang.System.out; public class Test { - static boolean security; - static boolean success; + interface Runner { void run() throws Exception; } - interface Runner { - public void run() throws Exception; - } + static boolean expectSuccess; public static void main(String[] args) throws Exception { @@ -52,95 +51,107 @@ public class Test { Sockets.supportedOptions(Socket.class); - security = System.getSecurityManager() != null; - success = security && args[0].equals("success"); + expectSuccess = args[0].equals("success"); // Main thing is to check for JNI problems // Doesn't matter if current system does not support the option // and currently setting the option with the loopback interface // doesn't work either - System.out.println ("Security Manager enabled: " + security); - if (security) { - System.out.println ("Success expected: " + success); + boolean sm = System.getSecurityManager() != null; + out.println("Security Manager enabled: " + sm); + out.println("Success expected: " + expectSuccess); + + SocketFlow flowIn = SocketFlow.create() + .bandwidth(1000) + .priority(SocketFlow.HIGH_PRIORITY); + + try (ServerSocket ss = new ServerSocket(0); + DatagramSocket dg = new DatagramSocket(0)) { + + int tcp_port = ss.getLocalPort(); + final InetAddress loop = InetAddress.getByName("127.0.0.1"); + final InetSocketAddress loopad = new InetSocketAddress(loop, tcp_port); + + final int udp_port = dg.getLocalPort(); + + // If option not available, end test + Set> options = dg.supportedOptions(); + if (!options.contains(ExtendedSocketOptions.SO_FLOW_SLA)) { + System.out.println("SO_FLOW_SLA not supported"); + return; + } + + final Socket s = new Socket("127.0.0.1", tcp_port); + final SocketChannel sc = SocketChannel.open(); + sc.connect(new InetSocketAddress("127.0.0.1", tcp_port)); + + doTest("Sockets.setOption Socket", () -> { + out.println(flowIn); + Sockets.setOption(s, ExtendedSocketOptions.SO_FLOW_SLA, flowIn); + out.println(flowIn); + }); + doTest("Sockets.getOption Socket",() -> { + Sockets.getOption(s, ExtendedSocketOptions.SO_FLOW_SLA); + out.println(flowIn); + }); + doTest("Sockets.setOption SocketChannel",() -> + sc.setOption(ExtendedSocketOptions.SO_FLOW_SLA, flowIn) + ); + doTest("Sockets.getOption SocketChannel",() -> + sc.getOption(ExtendedSocketOptions.SO_FLOW_SLA) + ); + doTest("Sockets.setOption DatagramSocket",() -> { + try (DatagramSocket dg1 = new DatagramSocket(0)) { + dg1.connect(loop, udp_port); + Sockets.setOption(dg1, ExtendedSocketOptions.SO_FLOW_SLA, flowIn); + } + }); + doTest("Sockets.setOption DatagramSocket 2", () -> { + try (DatagramChannel dg2 = DatagramChannel.open()) { + dg2.bind(new InetSocketAddress(loop, 0)); + dg2.connect(new InetSocketAddress(loop, udp_port)); + dg2.setOption(ExtendedSocketOptions.SO_FLOW_SLA, flowIn); + } + }); + doTest("Sockets.setOption MulticastSocket", () -> { + try (MulticastSocket mc1 = new MulticastSocket(0)) { + mc1.connect(loop, udp_port); + Sockets.setOption(mc1, ExtendedSocketOptions.SO_FLOW_SLA, flowIn); + } + }); + doTest("Sockets.setOption AsynchronousSocketChannel", () -> { + try (AsynchronousSocketChannel asc = AsynchronousSocketChannel.open()) { + Future f = asc.connect(loopad); + f.get(); + asc.setOption(ExtendedSocketOptions.SO_FLOW_SLA, flowIn); + } + }); } - - final SocketFlow flowIn = SocketFlow.create() - .bandwidth(1000) - .priority(SocketFlow.HIGH_PRIORITY); - - ServerSocket ss = new ServerSocket(0); - int tcp_port = ss.getLocalPort(); - final InetAddress loop = InetAddress.getByName("127.0.0.1"); - final InetSocketAddress loopad = new InetSocketAddress(loop, tcp_port); - - DatagramSocket dg = new DatagramSocket(0); - final int udp_port = dg.getLocalPort(); - - // If option not available, end test - Set> options = dg.supportedOptions(); - if (!options.contains(ExtendedSocketOptions.SO_FLOW_SLA)) { - System.out.println("SO_FLOW_SLA not supported"); - return; - } - - final Socket s = new Socket("127.0.0.1", tcp_port); - final SocketChannel sc = SocketChannel.open(); - sc.connect (new InetSocketAddress("127.0.0.1", tcp_port)); - - doTest(()->{ - Sockets.setOption(s, ExtendedSocketOptions.SO_FLOW_SLA, flowIn); - }); - doTest(()->{ - Sockets.getOption(s, ExtendedSocketOptions.SO_FLOW_SLA); - }); - doTest(()->{ - sc.setOption(ExtendedSocketOptions.SO_FLOW_SLA, flowIn); - }); - doTest(()->{ - sc.getOption(ExtendedSocketOptions.SO_FLOW_SLA); - }); - doTest(()->{ - DatagramSocket dg1 = new DatagramSocket(0); - dg1.connect(loop, udp_port); - Sockets.setOption(dg1, ExtendedSocketOptions.SO_FLOW_SLA, flowIn); - }); - doTest(()->{ - DatagramChannel dg2 = DatagramChannel.open(); - dg2.bind(new InetSocketAddress(loop, 0)); - dg2.connect(new InetSocketAddress(loop, udp_port)); - dg2.setOption(ExtendedSocketOptions.SO_FLOW_SLA, flowIn); - }); - doTest(()->{ - MulticastSocket mc1 = new MulticastSocket(0); - mc1.connect(loop, udp_port); - Sockets.setOption(mc1, ExtendedSocketOptions.SO_FLOW_SLA, flowIn); - }); - doTest(()->{ - AsynchronousSocketChannel asc = AsynchronousSocketChannel.open(); - Future f = asc.connect(loopad); - f.get(); - asc.setOption(ExtendedSocketOptions.SO_FLOW_SLA, flowIn); - }); } - static void doTest(Runner func) throws Exception { + static void doTest(String message, Runner func) throws Exception { + out.println(message); try { func.run(); - if (security && !success) { - throw new RuntimeException("Test failed"); + if (expectSuccess) { + out.println("Completed as expected"); + } else { + throw new RuntimeException("Operation succeeded, but expected SecurityException"); } } catch (SecurityException e) { - if (success) { - throw new RuntimeException("Test failed"); + if (expectSuccess) { + throw new RuntimeException("Unexpected SecurityException", e); + } else { + out.println("Caught expected: " + e); } } catch (UnsupportedOperationException e) { - System.out.println (e); + System.out.println(e); } catch (IOException e) { // Probably a permission error, but we're not // going to check unless a specific permission exception // is defined. - System.out.println (e); + System.out.println(e); } } } From 2ef07f57fa9561cee6ed0155d52b5172650b1076 Mon Sep 17 00:00:00 2001 From: Alexander Kouznetsov Date: Wed, 27 Apr 2016 17:47:17 -0700 Subject: [PATCH 15/18] 8154381: SwingSet tests are not auto closed in jtreg Reviewed-by: alexsch --- .../nbproject/genfiles.properties | 2 +- .../nbproject/project.properties | 2 +- .../client_sanity/nbproject/project.xml | 2 +- .../src/ButtonDemoScreenshotTest.java | 24 ++-- .../client/SwingSet/src/ButtonDemoTest.java | 44 ++++---- .../client/SwingSet/src/ComboBoxDemoTest.java | 19 ++-- .../client/SwingSet/src/ListDemoTest.java | 83 +++++++------- .../SwingSet/src/OptionPaneDemoTest.java | 31 +++--- .../SwingSet/src/ProgressBarDemoTest.java | 27 ++--- .../SwingSet/src/ScrollPaneDemoTest.java | 105 +++++++++--------- .../client/SwingSet/src/SpinnerDemoTest.java | 20 ++-- .../SwingSet/src/SplitPaneDemoTest.java | 38 ++++--- .../SwingSet/src/TabbedPaneDemoTest.java | 18 +-- .../SwingSet/src/TextFieldDemoTest.java | 18 +-- .../SwingSet/src/ToggleButtonDemoTest.java | 58 +++++----- .../client/SwingSet/src/TreeDemoTest.java | 81 +++++++------- .../client/SwingSet/src/WindowDemoTest.java | 32 +++--- .../src/org/jemmy2ext/JemmyExt.java | 23 ++-- .../src/org/jtregext/GuiTestListener.java | 72 ++++++++++++ .../demos/tabbedpane/TabbedPaneDemo.java | 6 +- 20 files changed, 395 insertions(+), 310 deletions(-) rename jdk/test/sanity/client/lib/{Jemmy2Ext => Extensions}/src/org/jemmy2ext/JemmyExt.java (97%) create mode 100644 jdk/test/sanity/client/lib/Extensions/src/org/jtregext/GuiTestListener.java diff --git a/jdk/make/netbeans/client_sanity/nbproject/genfiles.properties b/jdk/make/netbeans/client_sanity/nbproject/genfiles.properties index fc956fd5f2e..48d69459d3f 100644 --- a/jdk/make/netbeans/client_sanity/nbproject/genfiles.properties +++ b/jdk/make/netbeans/client_sanity/nbproject/genfiles.properties @@ -3,6 +3,6 @@ build.xml.script.CRC32=f902e8b8 build.xml.stylesheet.CRC32=8064a381@1.75.2.48 # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. -nbproject/build-impl.xml.data.CRC32=55414227 +nbproject/build-impl.xml.data.CRC32=16caf60f nbproject/build-impl.xml.script.CRC32=c12f9d04 nbproject/build-impl.xml.stylesheet.CRC32=05530350@1.79.1.48 diff --git a/jdk/make/netbeans/client_sanity/nbproject/project.properties b/jdk/make/netbeans/client_sanity/nbproject/project.properties index a43ee024fd8..f3e9384ce3f 100644 --- a/jdk/make/netbeans/client_sanity/nbproject/project.properties +++ b/jdk/make/netbeans/client_sanity/nbproject/project.properties @@ -76,4 +76,4 @@ source.encoding=UTF-8 src.src.dir=..\\..\\..\\test\\sanity\\client\\SwingSet\\src src.src2.dir=..\\..\\..\\test\\sanity\\client\\lib\\SwingSet3\\src src.src3.dir=..\\..\\..\\test\\sanity\\client\\lib\\jemmy\\src -src.src4.dir=..\\..\\..\\test\\sanity\\client\\lib\\Jemmy2Ext\\src +src.src4.dir=..\\..\\..\\test\\sanity\\client\\lib\\Extensions\\src diff --git a/jdk/make/netbeans/client_sanity/nbproject/project.xml b/jdk/make/netbeans/client_sanity/nbproject/project.xml index fccac4ecf31..554dc3073d5 100644 --- a/jdk/make/netbeans/client_sanity/nbproject/project.xml +++ b/jdk/make/netbeans/client_sanity/nbproject/project.xml @@ -6,7 +6,7 @@ SanityTests - + diff --git a/jdk/test/sanity/client/SwingSet/src/ButtonDemoScreenshotTest.java b/jdk/test/sanity/client/SwingSet/src/ButtonDemoScreenshotTest.java index b6959ac150a..61022339fc2 100644 --- a/jdk/test/sanity/client/SwingSet/src/ButtonDemoScreenshotTest.java +++ b/jdk/test/sanity/client/SwingSet/src/ButtonDemoScreenshotTest.java @@ -21,6 +21,8 @@ * questions. */ +import com.sun.swingset3.demos.button.ButtonDemo; +import org.jtregext.GuiTestListener; import java.awt.Point; import java.awt.Robot; import java.awt.event.InputEvent; @@ -32,6 +34,7 @@ import org.netbeans.jemmy.operators.JFrameOperator; import static org.jemmy2ext.JemmyExt.*; import org.testng.annotations.Test; import static com.sun.swingset3.demos.button.ButtonDemo.*; +import org.testng.annotations.Listeners; /* * @test @@ -41,31 +44,30 @@ import static com.sun.swingset3.demos.button.ButtonDemo.*; * image is different from initial button image. * * @library /sanity/client/lib/jemmy/src - * @library /sanity/client/lib/Jemmy2Ext/src + * @library /sanity/client/lib/Extensions/src * @library /sanity/client/lib/SwingSet3/src * @build org.jemmy2ext.JemmyExt * @build com.sun.swingset3.demos.button.ButtonDemo * @run testng ButtonDemoScreenshotTest */ +@Listeners(GuiTestListener.class) public class ButtonDemoScreenshotTest { private static final int BUTTON_COUNT = 6; // TODO: Decide about "open browser" buttons (value was 8 originally) @Test public void test() throws Exception { - captureDebugInfoOnFail(() -> { - Robot rob = new Robot(); + Robot rob = new Robot(); - new ClassReference(com.sun.swingset3.demos.button.ButtonDemo.class.getCanonicalName()).startApplication(); + new ClassReference(ButtonDemo.class.getCanonicalName()).startApplication(); - JFrameOperator mainFrame = new JFrameOperator(DEMO_TITLE); - waitImageIsStill(rob, mainFrame); + JFrameOperator mainFrame = new JFrameOperator(DEMO_TITLE); + waitImageIsStill(rob, mainFrame); - // Check all the buttons - for (int i = 0; i < BUTTON_COUNT; i++) { - checkButton(mainFrame, i, rob); - } - }); + // Check all the buttons + for (int i = 0; i < BUTTON_COUNT; i++) { + checkButton(mainFrame, i, rob); + } } public void checkButton(JFrameOperator jfo, int i, Robot rob) { diff --git a/jdk/test/sanity/client/SwingSet/src/ButtonDemoTest.java b/jdk/test/sanity/client/SwingSet/src/ButtonDemoTest.java index 3d0d8f1afea..da540dbb648 100644 --- a/jdk/test/sanity/client/SwingSet/src/ButtonDemoTest.java +++ b/jdk/test/sanity/client/SwingSet/src/ButtonDemoTest.java @@ -21,6 +21,7 @@ * questions. */ +import org.jtregext.GuiTestListener; import com.sun.swingset3.demos.JHyperlink; import com.sun.swingset3.demos.button.ButtonDemo; import java.util.concurrent.ArrayBlockingQueue; @@ -38,7 +39,7 @@ import org.netbeans.jemmy.operators.JFrameOperator; import static com.sun.swingset3.demos.button.ButtonDemo.*; import org.jemmy2ext.JemmyExt; import org.jemmy2ext.JemmyExt.MultiThreadedTryCatch; -import static org.jemmy2ext.JemmyExt.captureDebugInfoOnFail; +import org.testng.annotations.Listeners; /* * @test @@ -48,12 +49,13 @@ import static org.jemmy2ext.JemmyExt.captureDebugInfoOnFail; * on buttons before and after click. * * @library /sanity/client/lib/jemmy/src - * @library /sanity/client/lib/Jemmy2Ext/src + * @library /sanity/client/lib/Extensions/src * @library /sanity/client/lib/SwingSet3/src * @build org.jemmy2ext.JemmyExt * @build com.sun.swingset3.demos.button.ButtonDemo * @run testng ButtonDemoTest */ +@Listeners(GuiTestListener.class) public class ButtonDemoTest { private static final String[] BUTTON_TEXT_AFTER = { @@ -92,34 +94,30 @@ public class ButtonDemoTest { @Test public void test() throws Exception { - captureDebugInfoOnFail(() -> { + new ClassReference(ButtonDemo.class.getCanonicalName()).startApplication(); - new ClassReference(ButtonDemo.class.getCanonicalName()).startApplication(); + JFrameOperator mainFrame = new JFrameOperator(DEMO_TITLE); + mainFrame.setComparator(EXACT_STRING_COMPARATOR); - JFrameOperator mainFrame = new JFrameOperator(DEMO_TITLE); - mainFrame.setComparator(EXACT_STRING_COMPARATOR); + // Check all the buttons + for (int i = 0; i < BUTTON_TOOLTIP.length; i++) { + String tooltip = BUTTON_TOOLTIP[i]; - // Check all the buttons - for (int i = 0; i < BUTTON_TOOLTIP.length; i++) { - String tooltip = BUTTON_TOOLTIP[i]; + JButtonOperator button = new JButtonOperator(mainFrame, new ByToolTipChooser(tooltip)); - JButtonOperator button = new JButtonOperator(mainFrame, new ByToolTipChooser(tooltip)); + assertEquals(BUTTON_TEXT_BEFORE[i], button.getText()); - assertEquals(BUTTON_TEXT_BEFORE[i], button.getText()); - - // Two buttons are hyperlinks, we don't want to click them - if (!button.getSource().getClass().equals(JHyperlink.class)) { - checkButton(button); - } - - if (BUTTON_TEXT_AFTER.length > i) { - assertEquals(BUTTON_TEXT_AFTER[i], button.getText()); - } else { - assertEquals(BUTTON_TEXT_BEFORE[i], button.getText()); - } + // Two buttons are hyperlinks, we don't want to click them + if (!button.getSource().getClass().equals(JHyperlink.class)) { + checkButton(button); } - }); + if (BUTTON_TEXT_AFTER.length > i) { + assertEquals(BUTTON_TEXT_AFTER[i], button.getText()); + } else { + assertEquals(BUTTON_TEXT_BEFORE[i], button.getText()); + } + } } private void checkButton(JButtonOperator button) throws Exception { diff --git a/jdk/test/sanity/client/SwingSet/src/ComboBoxDemoTest.java b/jdk/test/sanity/client/SwingSet/src/ComboBoxDemoTest.java index 303bbd681f1..790bc9d3711 100644 --- a/jdk/test/sanity/client/SwingSet/src/ComboBoxDemoTest.java +++ b/jdk/test/sanity/client/SwingSet/src/ComboBoxDemoTest.java @@ -21,6 +21,7 @@ * questions. */ +import org.jtregext.GuiTestListener; import com.sun.swingset3.demos.combobox.ComboBoxDemo; import static org.testng.AssertJUnit.*; import org.testng.annotations.Test; @@ -28,7 +29,7 @@ import org.netbeans.jemmy.ClassReference; import org.netbeans.jemmy.operators.JComboBoxOperator; import org.netbeans.jemmy.operators.JFrameOperator; import static com.sun.swingset3.demos.combobox.ComboBoxDemo.*; -import static org.jemmy2ext.JemmyExt.captureDebugInfoOnFail; +import org.testng.annotations.Listeners; /* * @test @@ -37,12 +38,13 @@ import static org.jemmy2ext.JemmyExt.captureDebugInfoOnFail; * each value of each ComboBox. * * @library /sanity/client/lib/jemmy/src - * @library /sanity/client/lib/Jemmy2Ext/src + * @library /sanity/client/lib/Extensions/src * @library /sanity/client/lib/SwingSet3/src * @build org.jemmy2ext.JemmyExt * @build com.sun.swingset3.demos.combobox.ComboBoxDemo * @run testng ComboBoxDemoTest */ +@Listeners(GuiTestListener.class) public class ComboBoxDemoTest { private static enum ComboBoxInfo { @@ -61,14 +63,13 @@ public class ComboBoxDemoTest { @Test public void test() throws Exception { - captureDebugInfoOnFail(() -> { - new ClassReference(ComboBoxDemo.class.getCanonicalName()).startApplication(); - JFrameOperator frame = new JFrameOperator(DEMO_TITLE); - for (ComboBoxInfo comboBoxInfo : ComboBoxInfo.values()) { - comboBoxChecker(frame, comboBoxInfo); - } - }); + new ClassReference(ComboBoxDemo.class.getCanonicalName()).startApplication(); + + JFrameOperator frame = new JFrameOperator(DEMO_TITLE); + for (ComboBoxInfo comboBoxInfo : ComboBoxInfo.values()) { + comboBoxChecker(frame, comboBoxInfo); + } } private void comboBoxChecker(JFrameOperator jfo, ComboBoxInfo comboBoxInfo) { diff --git a/jdk/test/sanity/client/SwingSet/src/ListDemoTest.java b/jdk/test/sanity/client/SwingSet/src/ListDemoTest.java index c24399e526b..c977385b9bb 100644 --- a/jdk/test/sanity/client/SwingSet/src/ListDemoTest.java +++ b/jdk/test/sanity/client/SwingSet/src/ListDemoTest.java @@ -21,6 +21,7 @@ * questions. */ +import org.jtregext.GuiTestListener; import com.sun.swingset3.demos.list.ListDemo; import static com.sun.swingset3.demos.list.ListDemo.DEMO_TITLE; import static org.testng.AssertJUnit.*; @@ -30,7 +31,7 @@ import org.netbeans.jemmy.ClassReference; import org.netbeans.jemmy.operators.JCheckBoxOperator; import org.netbeans.jemmy.operators.JFrameOperator; import org.netbeans.jemmy.operators.JListOperator; -import static org.jemmy2ext.JemmyExt.captureDebugInfoOnFail; +import org.testng.annotations.Listeners; /* * @test @@ -40,64 +41,64 @@ import static org.jemmy2ext.JemmyExt.captureDebugInfoOnFail; * list. * * @library /sanity/client/lib/jemmy/src - * @library /sanity/client/lib/Jemmy2Ext/src + * @library /sanity/client/lib/Extensions/src * @library /sanity/client/lib/SwingSet3/src * @build org.jemmy2ext.JemmyExt * @build com.sun.swingset3.demos.list.ListDemo * @run testng ListDemoTest */ +@Listeners(GuiTestListener.class) public class ListDemoTest { private static final int CHECKBOX_COUNT = 50; @Test public void test() throws Exception { - captureDebugInfoOnFail(() -> { - new ClassReference(ListDemo.class.getCanonicalName()).startApplication(); - JFrameOperator frame = new JFrameOperator(DEMO_TITLE); - JListOperator listOp = new JListOperator(frame); + new ClassReference(ListDemo.class.getCanonicalName()).startApplication(); - // Check *NO* Prefix and Suffixes Marked - for (int i = 0; i < CHECKBOX_COUNT; i++) { - JCheckBoxOperator checkBox = getJCheckBoxOperator(frame, i); + JFrameOperator frame = new JFrameOperator(DEMO_TITLE); + JListOperator listOp = new JListOperator(frame); + + // Check *NO* Prefix and Suffixes Marked + for (int i = 0; i < CHECKBOX_COUNT; i++) { + JCheckBoxOperator checkBox = getJCheckBoxOperator(frame, i); + checkBox.changeSelection(false); + } + System.out.println("######## Number of Items = " + listOp.getModel().getSize()); + assertEquals("Select None number of items is correct", 0, listOp.getModel().getSize()); + + // Check *ALL* Prefix and Suffixes Marked + for (int i = 0; i < CHECKBOX_COUNT; i++) { + JCheckBoxOperator checkBox = getJCheckBoxOperator(frame, i); + checkBox.changeSelection(true); + } + System.out.println("######## Number of Items = " + listOp.getModel().getSize()); + assertEquals("Select All number of items is correct", CHECKBOX_COUNT / 2 * CHECKBOX_COUNT / 2, listOp.getModel().getSize()); + + // Check *ALL* Prefix and *NO* Suffixes Marked + for (int i = 0; i < CHECKBOX_COUNT; i++) { + JCheckBoxOperator checkBox = getJCheckBoxOperator(frame, i); + if (i < CHECKBOX_COUNT / 2) { + checkBox.changeSelection(true); + } else { checkBox.changeSelection(false); } - System.out.println("######## Number of Items = " + listOp.getModel().getSize()); - assertEquals("Select None number of items is correct", 0, listOp.getModel().getSize()); + } + System.out.println("######## Number of Items = " + listOp.getModel().getSize()); + assertEquals("Select All Prefixes and NO Suffixes number of items is correct", 0, listOp.getModel().getSize()); - // Check *ALL* Prefix and Suffixes Marked - for (int i = 0; i < CHECKBOX_COUNT; i++) { - JCheckBoxOperator checkBox = getJCheckBoxOperator(frame, i); + // Check *NO* Prefix and *ALL* Suffixes Marked + for (int i = 0; i < CHECKBOX_COUNT; i++) { + JCheckBoxOperator checkBox = getJCheckBoxOperator(frame, i); + if (i < CHECKBOX_COUNT / 2) { + checkBox.changeSelection(false); + } else { checkBox.changeSelection(true); } - System.out.println("######## Number of Items = " + listOp.getModel().getSize()); - assertEquals("Select All number of items is correct", CHECKBOX_COUNT / 2 * CHECKBOX_COUNT / 2, listOp.getModel().getSize()); - - // Check *ALL* Prefix and *NO* Suffixes Marked - for (int i = 0; i < CHECKBOX_COUNT; i++) { - JCheckBoxOperator checkBox = getJCheckBoxOperator(frame, i); - if (i < CHECKBOX_COUNT / 2) { - checkBox.changeSelection(true); - } else { - checkBox.changeSelection(false); - } - } - System.out.println("######## Number of Items = " + listOp.getModel().getSize()); - assertEquals("Select All Prefixes and NO Suffixes number of items is correct", 0, listOp.getModel().getSize()); - - // Check *NO* Prefix and *ALL* Suffixes Marked - for (int i = 0; i < CHECKBOX_COUNT; i++) { - JCheckBoxOperator checkBox = getJCheckBoxOperator(frame, i); - if (i < CHECKBOX_COUNT / 2) { - checkBox.changeSelection(false); - } else { - checkBox.changeSelection(true); - } - } - System.out.println("######## Number of Items = " + listOp.getModel().getSize()); - assertEquals("Select NO Prefixes and All Suffixes number of items is correct", 0, listOp.getModel().getSize()); - }); + } + System.out.println("######## Number of Items = " + listOp.getModel().getSize()); + assertEquals("Select NO Prefixes and All Suffixes number of items is correct", 0, listOp.getModel().getSize()); } private JCheckBoxOperator getJCheckBoxOperator(JFrameOperator frame, int index) { diff --git a/jdk/test/sanity/client/SwingSet/src/OptionPaneDemoTest.java b/jdk/test/sanity/client/SwingSet/src/OptionPaneDemoTest.java index 2cecfe72637..9ac377f7d2a 100644 --- a/jdk/test/sanity/client/SwingSet/src/OptionPaneDemoTest.java +++ b/jdk/test/sanity/client/SwingSet/src/OptionPaneDemoTest.java @@ -21,10 +21,10 @@ * questions. */ +import org.jtregext.GuiTestListener; import com.sun.swingset3.demos.optionpane.OptionPaneDemo; import static com.sun.swingset3.demos.optionpane.OptionPaneDemo.*; import javax.swing.UIManager; -import static org.jemmy2ext.JemmyExt.*; import static org.testng.AssertJUnit.*; import org.testng.annotations.Test; import org.netbeans.jemmy.ClassReference; @@ -34,6 +34,7 @@ import org.netbeans.jemmy.operators.JDialogOperator; import org.netbeans.jemmy.operators.JFrameOperator; import org.netbeans.jemmy.operators.JLabelOperator; import org.netbeans.jemmy.operators.JTextFieldOperator; +import org.testng.annotations.Listeners; /* @@ -43,12 +44,13 @@ import org.netbeans.jemmy.operators.JTextFieldOperator; * and choosing different options in them. * * @library /sanity/client/lib/jemmy/src - * @library /sanity/client/lib/Jemmy2Ext/src + * @library /sanity/client/lib/Extensions/src * @library /sanity/client/lib/SwingSet3/src * @build org.jemmy2ext.JemmyExt * @build com.sun.swingset3.demos.optionpane.OptionPaneDemo * @run testng OptionPaneDemoTest */ +@Listeners(GuiTestListener.class) public class OptionPaneDemoTest { public static final String SOME_TEXT_TO_TYPE = "I am some text"; @@ -59,21 +61,20 @@ public class OptionPaneDemoTest { public static final String TEXT_TO_TYPE = "Hooray! I'm a textField"; public static final String NO = "No"; public static final String YES = "Yes"; - public static final String SELECT_AN__OPTION = UIManager.getString("OptionPane.titleText"); + public static final String SELECT_AN_OPTION = UIManager.getString("OptionPane.titleText"); @Test public void test() throws Exception { - captureDebugInfoOnFail(() -> { - new ClassReference(OptionPaneDemo.class.getCanonicalName()).startApplication(); - JFrameOperator frame = new JFrameOperator(DEMO_TITLE); + new ClassReference(OptionPaneDemo.class.getCanonicalName()).startApplication(); - showInputDialog(frame); - showWarningDialog(frame); - showMessageDialog(frame); - showComponentDialog(frame); - showConfirmationDialog(frame); - }); + JFrameOperator frame = new JFrameOperator(DEMO_TITLE); + + showInputDialog(frame); + showWarningDialog(frame); + showMessageDialog(frame); + showComponentDialog(frame); + showConfirmationDialog(frame); } public void showInputDialog(JFrameOperator jfo) throws Exception { @@ -286,7 +287,7 @@ public class OptionPaneDemoTest { { new JButtonOperator(jfo, CONFIRM_BUTTON).pushNoBlock(); - JDialogOperator jdo = new JDialogOperator(SELECT_AN__OPTION); + JDialogOperator jdo = new JDialogOperator(SELECT_AN_OPTION); new JButtonOperator(jdo, YES).pushNoBlock(); JDialogOperator jdo1 = new JDialogOperator(MESSAGE); @@ -306,7 +307,7 @@ public class OptionPaneDemoTest { { new JButtonOperator(jfo, CONFIRM_BUTTON).pushNoBlock(); - JDialogOperator jdo = new JDialogOperator(SELECT_AN__OPTION); + JDialogOperator jdo = new JDialogOperator(SELECT_AN_OPTION); new JButtonOperator(jdo, NO).pushNoBlock(); JDialogOperator jdo1 = new JDialogOperator(MESSAGE); @@ -326,7 +327,7 @@ public class OptionPaneDemoTest { { new JButtonOperator(jfo, CONFIRM_BUTTON).pushNoBlock(); - JDialogOperator jdo = new JDialogOperator(SELECT_AN__OPTION); + JDialogOperator jdo = new JDialogOperator(SELECT_AN_OPTION); assertTrue("Show Confirmation Dialog Cancel Option", jdo.isShowing()); diff --git a/jdk/test/sanity/client/SwingSet/src/ProgressBarDemoTest.java b/jdk/test/sanity/client/SwingSet/src/ProgressBarDemoTest.java index 411d05cd1b7..b705974274f 100644 --- a/jdk/test/sanity/client/SwingSet/src/ProgressBarDemoTest.java +++ b/jdk/test/sanity/client/SwingSet/src/ProgressBarDemoTest.java @@ -21,6 +21,7 @@ * questions. */ +import org.jtregext.GuiTestListener; import com.sun.swingset3.demos.progressbar.ProgressBarDemo; import static com.sun.swingset3.demos.progressbar.ProgressBarDemo.*; import java.awt.Component; @@ -31,7 +32,7 @@ import org.netbeans.jemmy.ComponentChooser; import org.netbeans.jemmy.operators.JButtonOperator; import org.netbeans.jemmy.operators.JFrameOperator; import org.netbeans.jemmy.operators.JProgressBarOperator; -import static org.jemmy2ext.JemmyExt.captureDebugInfoOnFail; +import org.testng.annotations.Listeners; /* * @test @@ -40,31 +41,31 @@ import static org.jemmy2ext.JemmyExt.captureDebugInfoOnFail; * buttons and checking the progress bar and the buttons state. * * @library /sanity/client/lib/jemmy/src - * @library /sanity/client/lib/Jemmy2Ext/src + * @library /sanity/client/lib/Extensions/src * @library /sanity/client/lib/SwingSet3/src * @build org.jemmy2ext.JemmyExt * @build com.sun.swingset3.demos.progressbar.ProgressBarDemo * @run testng ProgressBarDemoTest */ +@Listeners(GuiTestListener.class) public class ProgressBarDemoTest { @Test public void test() throws Exception { - captureDebugInfoOnFail(() -> { - new ClassReference(ProgressBarDemo.class.getCanonicalName()).startApplication(); - JFrameOperator frame = new JFrameOperator(DEMO_TITLE); + new ClassReference(ProgressBarDemo.class.getCanonicalName()).startApplication(); - JButtonOperator startButton = new JButtonOperator(frame, START_BUTTON); - JButtonOperator stopButton = new JButtonOperator(frame, STOP_BUTTON); - JProgressBarOperator jpbo = new JProgressBarOperator(frame); + JFrameOperator frame = new JFrameOperator(DEMO_TITLE); - // Check that progress completes and corect enable/disable of start/stop buttons - checkCompleteProgress(frame, startButton, stopButton, jpbo); + JButtonOperator startButton = new JButtonOperator(frame, START_BUTTON); + JButtonOperator stopButton = new JButtonOperator(frame, STOP_BUTTON); + JProgressBarOperator jpbo = new JProgressBarOperator(frame); - // Check progess bar progression and start/stop button disabled/enabled states - checkStartStop(frame, startButton, stopButton, jpbo); - }); + // Check that progress completes and corect enable/disable of start/stop buttons + checkCompleteProgress(frame, startButton, stopButton, jpbo); + + // Check progess bar progression and start/stop button disabled/enabled states + checkStartStop(frame, startButton, stopButton, jpbo); } // Check that progress completes and corect enable/disable of start/stop buttons diff --git a/jdk/test/sanity/client/SwingSet/src/ScrollPaneDemoTest.java b/jdk/test/sanity/client/SwingSet/src/ScrollPaneDemoTest.java index bd88904f875..2023eff16a3 100644 --- a/jdk/test/sanity/client/SwingSet/src/ScrollPaneDemoTest.java +++ b/jdk/test/sanity/client/SwingSet/src/ScrollPaneDemoTest.java @@ -21,6 +21,7 @@ * questions. */ +import org.jtregext.GuiTestListener; import com.sun.swingset3.demos.scrollpane.ScrollPaneDemo; import static com.sun.swingset3.demos.scrollpane.ScrollPaneDemo.DEMO_TITLE; import static org.testng.AssertJUnit.*; @@ -28,7 +29,7 @@ import org.testng.annotations.Test; import org.netbeans.jemmy.ClassReference; import org.netbeans.jemmy.operators.JFrameOperator; import org.netbeans.jemmy.operators.JScrollPaneOperator; -import static org.jemmy2ext.JemmyExt.captureDebugInfoOnFail; +import org.testng.annotations.Listeners; /* * @test @@ -37,73 +38,73 @@ import static org.jemmy2ext.JemmyExt.captureDebugInfoOnFail; * to left and to right and checking scroll bar values. * * @library /sanity/client/lib/jemmy/src - * @library /sanity/client/lib/Jemmy2Ext/src + * @library /sanity/client/lib/Extensions/src * @library /sanity/client/lib/SwingSet3/src * @build org.jemmy2ext.JemmyExt * @build com.sun.swingset3.demos.scrollpane.ScrollPaneDemo * @run testng ScrollPaneDemoTest */ +@Listeners(GuiTestListener.class) public class ScrollPaneDemoTest { @Test public void test() throws Exception { - captureDebugInfoOnFail(() -> { - new ClassReference(ScrollPaneDemo.class.getName()).startApplication(); - JFrameOperator frame = new JFrameOperator(DEMO_TITLE); - JScrollPaneOperator jspo = new JScrollPaneOperator(frame); + new ClassReference(ScrollPaneDemo.class.getName()).startApplication(); - // Set initial scrollbar positions - int initialVerticalValue = jspo.getVerticalScrollBar().getValue(); - int initialHorizontalValue = jspo.getHorizontalScrollBar().getValue(); + JFrameOperator frame = new JFrameOperator(DEMO_TITLE); + JScrollPaneOperator jspo = new JScrollPaneOperator(frame); - System.out.println("Initial Vertical Value = " + jspo.getVerticalScrollBar().getValue()); - System.out.println("Initial HoriZontal Value = " + jspo.getHorizontalScrollBar().getValue()); + // Set initial scrollbar positions + int initialVerticalValue = jspo.getVerticalScrollBar().getValue(); + int initialHorizontalValue = jspo.getHorizontalScrollBar().getValue(); - // Check scroll to Bottom - { - jspo.scrollToBottom(); - int currentValue = jspo.getVerticalScrollBar().getValue(); - System.out.println("Final Value = " + currentValue); - assertTrue("Scroll to Bottom of Pane " - + "(initialVerticalValue, actual value: " + initialVerticalValue + " " - + "< currentValue, actual value = " + currentValue + ")", - initialVerticalValue < currentValue); - } + System.out.println("Initial Vertical Value = " + jspo.getVerticalScrollBar().getValue()); + System.out.println("Initial HoriZontal Value = " + jspo.getHorizontalScrollBar().getValue()); - // Check scroll to Top - { - jspo.scrollToTop(); - int currentValue = jspo.getVerticalScrollBar().getValue(); - System.out.println("Top Scroll Final Value = " + currentValue); - assertTrue("Scroll to Top of Pane " - + "(initialVerticalValue, actual value: " + initialVerticalValue + " " - + "> currentValue, actual value = " + currentValue + ")", - initialVerticalValue > currentValue); - } + // Check scroll to Bottom + { + jspo.scrollToBottom(); + int currentValue = jspo.getVerticalScrollBar().getValue(); + System.out.println("Final Value = " + currentValue); + assertTrue("Scroll to Bottom of Pane " + + "(initialVerticalValue, actual value: " + initialVerticalValue + " " + + "< currentValue, actual value = " + currentValue + ")", + initialVerticalValue < currentValue); + } - // Check scroll to Left - { - jspo.scrollToLeft(); - int currentValue = jspo.getHorizontalScrollBar().getValue(); - System.out.println("Scroll to Left Final Value = " + currentValue); - assertTrue("Scroll to Left of Pane " - + "(initialHorizontalValue, actual value: " + initialHorizontalValue + " " - + "> currentValue, actual value = " + currentValue + ")", - initialHorizontalValue > currentValue); - } + // Check scroll to Top + { + jspo.scrollToTop(); + int currentValue = jspo.getVerticalScrollBar().getValue(); + System.out.println("Top Scroll Final Value = " + currentValue); + assertTrue("Scroll to Top of Pane " + + "(initialVerticalValue, actual value: " + initialVerticalValue + " " + + "> currentValue, actual value = " + currentValue + ")", + initialVerticalValue > currentValue); + } - // Check scroll to Right - { - jspo.scrollToRight(); - int currentValue = jspo.getHorizontalScrollBar().getValue(); - System.out.println("Scroll to Right Final Value = " + currentValue); - assertTrue("Scroll to Right of Pane " - + "(initialHorizontalValue, actual value: " + initialHorizontalValue + " " - + "< currentValue, actual value = " + currentValue + ")", - initialHorizontalValue < currentValue); - } - }); + // Check scroll to Left + { + jspo.scrollToLeft(); + int currentValue = jspo.getHorizontalScrollBar().getValue(); + System.out.println("Scroll to Left Final Value = " + currentValue); + assertTrue("Scroll to Left of Pane " + + "(initialHorizontalValue, actual value: " + initialHorizontalValue + " " + + "> currentValue, actual value = " + currentValue + ")", + initialHorizontalValue > currentValue); + } + + // Check scroll to Right + { + jspo.scrollToRight(); + int currentValue = jspo.getHorizontalScrollBar().getValue(); + System.out.println("Scroll to Right Final Value = " + currentValue); + assertTrue("Scroll to Right of Pane " + + "(initialHorizontalValue, actual value: " + initialHorizontalValue + " " + + "< currentValue, actual value = " + currentValue + ")", + initialHorizontalValue < currentValue); + } } } diff --git a/jdk/test/sanity/client/SwingSet/src/SpinnerDemoTest.java b/jdk/test/sanity/client/SwingSet/src/SpinnerDemoTest.java index 89585adb6ad..1b44efa73af 100644 --- a/jdk/test/sanity/client/SwingSet/src/SpinnerDemoTest.java +++ b/jdk/test/sanity/client/SwingSet/src/SpinnerDemoTest.java @@ -21,6 +21,7 @@ * questions. */ +import org.jtregext.GuiTestListener; import com.sun.swingset3.demos.spinner.SpinnerDemo; import static com.sun.swingset3.demos.spinner.SpinnerDemo.DEMO_TITLE; import java.text.DecimalFormat; @@ -30,7 +31,7 @@ import org.netbeans.jemmy.ClassReference; import org.netbeans.jemmy.operators.JFrameOperator; import org.netbeans.jemmy.operators.JSpinnerOperator; import org.netbeans.jemmy.operators.JTextFieldOperator; -import static org.jemmy2ext.JemmyExt.captureDebugInfoOnFail; +import org.testng.annotations.Listeners; /* * @test @@ -39,12 +40,13 @@ import static org.jemmy2ext.JemmyExt.captureDebugInfoOnFail; * the spinner button and checking text field value. * * @library /sanity/client/lib/jemmy/src - * @library /sanity/client/lib/Jemmy2Ext/src + * @library /sanity/client/lib/Extensions/src * @library /sanity/client/lib/SwingSet3/src * @build org.jemmy2ext.JemmyExt * @build com.sun.swingset3.demos.spinner.SpinnerDemo * @run testng SpinnerDemoTest */ +@Listeners(GuiTestListener.class) public class SpinnerDemoTest { private static final int SPINNERS_COUNT = 9; @@ -52,16 +54,14 @@ public class SpinnerDemoTest { @Test public void test() throws Exception { - captureDebugInfoOnFail(() -> { - new ClassReference(SpinnerDemo.class.getCanonicalName()).startApplication(); + new ClassReference(SpinnerDemo.class.getCanonicalName()).startApplication(); - JFrameOperator frame = new JFrameOperator(DEMO_TITLE); + JFrameOperator frame = new JFrameOperator(DEMO_TITLE); - // Check changing different spinners - for (int i = 0; i < SPINNERS_COUNT; i++) { - changeValues(frame, i); - } - }); + // Check changing different spinners + for (int i = 0; i < SPINNERS_COUNT; i++) { + changeValues(frame, i); + } } private void changeValues(JFrameOperator jfo, int spinnerIndex) throws Exception { diff --git a/jdk/test/sanity/client/SwingSet/src/SplitPaneDemoTest.java b/jdk/test/sanity/client/SwingSet/src/SplitPaneDemoTest.java index 2a242cc3f16..9993d100316 100644 --- a/jdk/test/sanity/client/SwingSet/src/SplitPaneDemoTest.java +++ b/jdk/test/sanity/client/SwingSet/src/SplitPaneDemoTest.java @@ -21,6 +21,7 @@ * questions. */ +import org.jtregext.GuiTestListener; import com.sun.swingset3.demos.splitpane.SplitPaneDemo; import static com.sun.swingset3.demos.splitpane.SplitPaneDemo.*; import java.awt.event.KeyEvent; @@ -35,6 +36,7 @@ import org.netbeans.jemmy.operators.JRadioButtonOperator; import org.netbeans.jemmy.operators.JSplitPaneOperator; import org.netbeans.jemmy.operators.JTextFieldOperator; import static org.jemmy2ext.JemmyExt.*; +import org.testng.annotations.Listeners; /* * @test @@ -44,39 +46,39 @@ import static org.jemmy2ext.JemmyExt.*; * and changing the divider orientation. * * @library /sanity/client/lib/jemmy/src - * @library /sanity/client/lib/Jemmy2Ext/src + * @library /sanity/client/lib/Extensions/src * @library /sanity/client/lib/SwingSet3/src * @build org.jemmy2ext.JemmyExt * @build com.sun.swingset3.demos.splitpane.SplitPaneDemo * @run testng SplitPaneDemoTest */ +@Listeners(GuiTestListener.class) public class SplitPaneDemoTest { @Test public void test() throws Exception { - captureDebugInfoOnFail(() -> { - new ClassReference(SplitPaneDemo.class.getCanonicalName()).startApplication(); - JFrameOperator frame = new JFrameOperator(DEMO_TITLE); + new ClassReference(SplitPaneDemo.class.getCanonicalName()).startApplication(); - JSplitPaneOperator splitPane = new JSplitPaneOperator(frame); + JFrameOperator frame = new JFrameOperator(DEMO_TITLE); - // Toggle OneTouch Expandable - checkOneTouch(frame, splitPane, true); - checkOneTouch(frame, splitPane, false); + JSplitPaneOperator splitPane = new JSplitPaneOperator(frame); - // Check changing divider size to minimum and maximum values - changeDividerSize(frame, splitPane, 50); - changeDividerSize(frame, splitPane, 6); + // Toggle OneTouch Expandable + checkOneTouch(frame, splitPane, true); + checkOneTouch(frame, splitPane, false); - // Check moving the divider - checkDividerMoves(frame, splitPane, false); - checkDividerMoves(frame, splitPane, true); + // Check changing divider size to minimum and maximum values + changeDividerSize(frame, splitPane, 50); + changeDividerSize(frame, splitPane, 6); - // Check different minumum Day/Night sizes - changeMinimumSizes(frame, splitPane, 100); - changeMinimumSizes(frame, splitPane, 0); - }); + // Check moving the divider + checkDividerMoves(frame, splitPane, false); + checkDividerMoves(frame, splitPane, true); + + // Check different minumum Day/Night sizes + changeMinimumSizes(frame, splitPane, 100); + changeMinimumSizes(frame, splitPane, 0); } // Check for different day and night minimum size diff --git a/jdk/test/sanity/client/SwingSet/src/TabbedPaneDemoTest.java b/jdk/test/sanity/client/SwingSet/src/TabbedPaneDemoTest.java index d3d8d28245f..9b2e16b7776 100644 --- a/jdk/test/sanity/client/SwingSet/src/TabbedPaneDemoTest.java +++ b/jdk/test/sanity/client/SwingSet/src/TabbedPaneDemoTest.java @@ -21,6 +21,7 @@ * questions. */ +import org.jtregext.GuiTestListener; import com.sun.swingset3.demos.tabbedpane.TabbedPaneDemo; import static com.sun.swingset3.demos.tabbedpane.TabbedPaneDemo.*; import static org.jemmy2ext.JemmyExt.getLabeledContainerOperator; @@ -31,7 +32,7 @@ import org.netbeans.jemmy.operators.ContainerOperator; import org.netbeans.jemmy.operators.JFrameOperator; import org.netbeans.jemmy.operators.JRadioButtonOperator; import org.netbeans.jemmy.operators.JTabbedPaneOperator; -import static org.jemmy2ext.JemmyExt.captureDebugInfoOnFail; +import org.testng.annotations.Listeners; /* * @test @@ -40,25 +41,24 @@ import static org.jemmy2ext.JemmyExt.captureDebugInfoOnFail; * positions, opening each tab and verifying the the tab gets selected. * * @library /sanity/client/lib/jemmy/src - * @library /sanity/client/lib/Jemmy2Ext/src + * @library /sanity/client/lib/Extensions/src * @library /sanity/client/lib/SwingSet3/src * @build org.jemmy2ext.JemmyExt * @build com.sun.swingset3.demos.tabbedpane.TabbedPaneDemo * @run testng TabbedPaneDemoTest */ +@Listeners(GuiTestListener.class) public class TabbedPaneDemoTest { @Test public void test() throws Exception { - captureDebugInfoOnFail(() -> { - new ClassReference(TabbedPaneDemo.class.getCanonicalName()).startApplication(); + new ClassReference(TabbedPaneDemo.class.getCanonicalName()).startApplication(); - JFrameOperator mainFrame = new JFrameOperator(DEMO_TITLE); + JFrameOperator mainFrame = new JFrameOperator(DEMO_TITLE); - for (String tp : new String[]{TOP, LEFT, BOTTOM, RIGHT}) { - testTabs(mainFrame, tp); - } - }); + for (String tp : new String[]{TOP, LEFT, BOTTOM, RIGHT}) { + testTabs(mainFrame, tp); + } } public void testTabs(JFrameOperator mainFrame, String tabPlacement) throws Exception { diff --git a/jdk/test/sanity/client/SwingSet/src/TextFieldDemoTest.java b/jdk/test/sanity/client/SwingSet/src/TextFieldDemoTest.java index 4d38ce38a38..b46abaaf691 100644 --- a/jdk/test/sanity/client/SwingSet/src/TextFieldDemoTest.java +++ b/jdk/test/sanity/client/SwingSet/src/TextFieldDemoTest.java @@ -21,6 +21,7 @@ * questions. */ +import org.jtregext.GuiTestListener; import com.sun.swingset3.demos.textfield.JHistoryTextField; import com.sun.swingset3.demos.textfield.TextFieldDemo; import static com.sun.swingset3.demos.textfield.TextFieldDemo.*; @@ -41,6 +42,7 @@ import org.netbeans.jemmy.operators.JFrameOperator; import org.netbeans.jemmy.operators.JLabelOperator; import org.netbeans.jemmy.operators.JPasswordFieldOperator; import org.netbeans.jemmy.operators.JTextFieldOperator; +import org.testng.annotations.Listeners; /* * @test @@ -49,25 +51,25 @@ import org.netbeans.jemmy.operators.JTextFieldOperator; * checking that app reacts accordingly. * * @library /sanity/client/lib/jemmy/src - * @library /sanity/client/lib/Jemmy2Ext/src + * @library /sanity/client/lib/Extensions/src * @library /sanity/client/lib/SwingSet3/src * @build org.jemmy2ext.JemmyExt * @build com.sun.swingset3.demos.textfield.TextFieldDemo * @run testng TextFieldDemoTest */ +@Listeners(GuiTestListener.class) public class TextFieldDemoTest { @Test public void test() throws Exception { - captureDebugInfoOnFail(() -> { - new ClassReference(TextFieldDemo.class.getCanonicalName()).startApplication(); - JFrameOperator frame = new JFrameOperator(DEMO_TITLE); + new ClassReference(TextFieldDemo.class.getCanonicalName()).startApplication(); - historyTextField(frame); - dateTextField(frame); - passwordField(frame); - }); + JFrameOperator frame = new JFrameOperator(DEMO_TITLE); + + historyTextField(frame); + dateTextField(frame); + passwordField(frame); } private void historyTextField(JFrameOperator jfo) throws Exception { diff --git a/jdk/test/sanity/client/SwingSet/src/ToggleButtonDemoTest.java b/jdk/test/sanity/client/SwingSet/src/ToggleButtonDemoTest.java index c240540739e..2f1b6f01a9f 100644 --- a/jdk/test/sanity/client/SwingSet/src/ToggleButtonDemoTest.java +++ b/jdk/test/sanity/client/SwingSet/src/ToggleButtonDemoTest.java @@ -21,6 +21,7 @@ * questions. */ +import org.jtregext.GuiTestListener; import com.sun.swingset3.DemoProperties; import com.sun.swingset3.demos.togglebutton.DirectionPanel; import com.sun.swingset3.demos.togglebutton.LayoutControlPanel; @@ -40,7 +41,7 @@ import org.netbeans.jemmy.operators.JCheckBoxOperator; import org.netbeans.jemmy.operators.JFrameOperator; import org.netbeans.jemmy.operators.JRadioButtonOperator; import org.netbeans.jemmy.operators.JTabbedPaneOperator; -import static org.jemmy2ext.JemmyExt.captureDebugInfoOnFail; +import org.testng.annotations.Listeners; /* * @test @@ -53,50 +54,49 @@ import static org.jemmy2ext.JemmyExt.captureDebugInfoOnFail; * selected. * * @library /sanity/client/lib/jemmy/src - * @library /sanity/client/lib/Jemmy2Ext/src + * @library /sanity/client/lib/Extensions/src * @library /sanity/client/lib/SwingSet3/src * @build org.jemmy2ext.JemmyExt * @build com.sun.swingset3.demos.togglebutton.ToggleButtonDemo * @run testng ToggleButtonDemoTest */ +@Listeners(GuiTestListener.class) public class ToggleButtonDemoTest { @Test public void test() throws Exception { - captureDebugInfoOnFail(() -> { - new ClassReference(ToggleButtonDemo.class.getCanonicalName()).startApplication(); + new ClassReference(ToggleButtonDemo.class.getCanonicalName()).startApplication(); - JFrameOperator mainFrame = new JFrameOperator(ToggleButtonDemo.class.getAnnotation(DemoProperties.class).value()); - JTabbedPaneOperator tabPane = new JTabbedPaneOperator(mainFrame); + JFrameOperator mainFrame = new JFrameOperator(ToggleButtonDemo.class.getAnnotation(DemoProperties.class).value()); + JTabbedPaneOperator tabPane = new JTabbedPaneOperator(mainFrame); - // Radio Button Toggles - testRadioButtons(getBorderTitledJPanelOperator(mainFrame, TEXT_RADIO_BUTTONS), 3, null); - testRadioButtons(getBorderTitledJPanelOperator(mainFrame, IMAGE_RADIO_BUTTONS), 3, null); - testRadioButtons(getLabeledContainerOperator(mainFrame, PAD_AMOUNT), 3, (t, i) -> DEFAULT.equals(t)); + // Radio Button Toggles + testRadioButtons(getBorderTitledJPanelOperator(mainFrame, TEXT_RADIO_BUTTONS), 3, null); + testRadioButtons(getBorderTitledJPanelOperator(mainFrame, IMAGE_RADIO_BUTTONS), 3, null); + testRadioButtons(getLabeledContainerOperator(mainFrame, PAD_AMOUNT), 3, (t, i) -> DEFAULT.equals(t)); - // switch to the Check Boxes Tab - tabPane.selectPage(CHECK_BOXES); + // switch to the Check Boxes Tab + tabPane.selectPage(CHECK_BOXES); - // Check Box Toggles - ContainerOperator textCheckBoxesJPanel = getBorderTitledJPanelOperator(mainFrame, TEXT_CHECKBOXES); - testCheckBox(textCheckBoxesJPanel, CHECK1, false); - testCheckBox(textCheckBoxesJPanel, CHECK2, false); - testCheckBox(textCheckBoxesJPanel, CHECK3, false); + // Check Box Toggles + ContainerOperator textCheckBoxesJPanel = getBorderTitledJPanelOperator(mainFrame, TEXT_CHECKBOXES); + testCheckBox(textCheckBoxesJPanel, CHECK1, false); + testCheckBox(textCheckBoxesJPanel, CHECK2, false); + testCheckBox(textCheckBoxesJPanel, CHECK3, false); - ContainerOperator imageCheckBoxesJPanel = getBorderTitledJPanelOperator(mainFrame, IMAGE_CHECKBOXES); - testCheckBox(imageCheckBoxesJPanel, CHECK1, false); - testCheckBox(imageCheckBoxesJPanel, CHECK2, false); - testCheckBox(imageCheckBoxesJPanel, CHECK3, false); + ContainerOperator imageCheckBoxesJPanel = getBorderTitledJPanelOperator(mainFrame, IMAGE_CHECKBOXES); + testCheckBox(imageCheckBoxesJPanel, CHECK1, false); + testCheckBox(imageCheckBoxesJPanel, CHECK2, false); + testCheckBox(imageCheckBoxesJPanel, CHECK3, false); - ContainerOperator displayOptionsContainer = getLabeledContainerOperator(mainFrame, DISPLAY_OPTIONS); - testCheckBox(displayOptionsContainer, PAINT_BORDER, false); - testCheckBox(displayOptionsContainer, PAINT_FOCUS, true); - testCheckBox(displayOptionsContainer, ENABLED, true); - testCheckBox(displayOptionsContainer, CONTENT_FILLED, true); + ContainerOperator displayOptionsContainer = getLabeledContainerOperator(mainFrame, DISPLAY_OPTIONS); + testCheckBox(displayOptionsContainer, PAINT_BORDER, false); + testCheckBox(displayOptionsContainer, PAINT_FOCUS, true); + testCheckBox(displayOptionsContainer, ENABLED, true); + testCheckBox(displayOptionsContainer, CONTENT_FILLED, true); - // Direction Button Toggles - testToggleButtons(mainFrame); - }); + // Direction Button Toggles + testToggleButtons(mainFrame); } /** diff --git a/jdk/test/sanity/client/SwingSet/src/TreeDemoTest.java b/jdk/test/sanity/client/SwingSet/src/TreeDemoTest.java index b558d6fb96c..31166c12918 100644 --- a/jdk/test/sanity/client/SwingSet/src/TreeDemoTest.java +++ b/jdk/test/sanity/client/SwingSet/src/TreeDemoTest.java @@ -21,6 +21,7 @@ * questions. */ +import org.jtregext.GuiTestListener; import com.sun.swingset3.demos.tree.TreeDemo; import static com.sun.swingset3.demos.tree.TreeDemo.DEMO_TITLE; import javax.swing.tree.TreePath; @@ -29,7 +30,7 @@ import org.testng.annotations.Test; import org.netbeans.jemmy.ClassReference; import org.netbeans.jemmy.operators.JFrameOperator; import org.netbeans.jemmy.operators.JTreeOperator; -import static org.jemmy2ext.JemmyExt.captureDebugInfoOnFail; +import org.testng.annotations.Listeners; /* * @test @@ -42,67 +43,67 @@ import static org.jemmy2ext.JemmyExt.captureDebugInfoOnFail; * vertically (as ScrollPane allows it). * * @library /sanity/client/lib/jemmy/src - * @library /sanity/client/lib/Jemmy2Ext/src + * @library /sanity/client/lib/Extensions/src * @library /sanity/client/lib/SwingSet3/src * @build org.jemmy2ext.JemmyExt * @build com.sun.swingset3.demos.tree.TreeDemo * @run testng TreeDemoTest */ +@Listeners(GuiTestListener.class) public class TreeDemoTest { @Test public void test() throws Exception { - captureDebugInfoOnFail(() -> { - new ClassReference(TreeDemo.class.getCanonicalName()).startApplication(); - JFrameOperator frame = new JFrameOperator(DEMO_TITLE); + new ClassReference(TreeDemo.class.getCanonicalName()).startApplication(); - JTreeOperator tree = new JTreeOperator(frame); + JFrameOperator frame = new JFrameOperator(DEMO_TITLE); - assertEquals("Initial number of rows in the tree", 4, tree.getRowCount()); + JTreeOperator tree = new JTreeOperator(frame); - int initialTreeHeight = tree.getHeight(); + assertEquals("Initial number of rows in the tree", 4, tree.getRowCount()); - // expand all nodes - int expandsCount = 0; - for (int i = 0; i < tree.getRowCount(); i++) { - TreePath tp = tree.getPathForRow(i); - if (tree.getChildCount(tp) > 0 && !tree.isExpanded(tp)) { - tree.expandRow(i); - expandsCount++; - } + int initialTreeHeight = tree.getHeight(); + + // expand all nodes + int expandsCount = 0; + for (int i = 0; i < tree.getRowCount(); i++) { + TreePath tp = tree.getPathForRow(i); + if (tree.getChildCount(tp) > 0 && !tree.isExpanded(tp)) { + tree.expandRow(i); + expandsCount++; } + } - assertEquals("Number of rows expanded", 75, expandsCount); - assertEquals("Number of rows in the tree after expanding all of them", - 616, tree.getRowCount()); + assertEquals("Number of rows expanded", 75, expandsCount); + assertEquals("Number of rows in the tree after expanding all of them", + 616, tree.getRowCount()); - int expandedTreeHeight = tree.getHeight(); - assertTrue("Expanded tree height has increased, current " - + expandedTreeHeight + " > initial " + initialTreeHeight, - expandedTreeHeight > initialTreeHeight); + int expandedTreeHeight = tree.getHeight(); + assertTrue("Expanded tree height has increased, current " + + expandedTreeHeight + " > initial " + initialTreeHeight, + expandedTreeHeight > initialTreeHeight); - // collapse all nodes - int collapsesCount = 0; - for (int i = tree.getRowCount() - 1; i >= 0; i--) { - TreePath tp = tree.getPathForRow(i); - if (tree.getChildCount(tp) > 0 && tree.isExpanded(tp)) { - tree.collapseRow(i); - collapsesCount++; - } + // collapse all nodes + int collapsesCount = 0; + for (int i = tree.getRowCount() - 1; i >= 0; i--) { + TreePath tp = tree.getPathForRow(i); + if (tree.getChildCount(tp) > 0 && tree.isExpanded(tp)) { + tree.collapseRow(i); + collapsesCount++; } + } - assertEquals("Number of rows collapsed", 76, collapsesCount); - assertEquals("Number of rows in the tree after collapsing all of them", - 1, tree.getRowCount()); + assertEquals("Number of rows collapsed", 76, collapsesCount); + assertEquals("Number of rows in the tree after collapsing all of them", + 1, tree.getRowCount()); - int collapsedTreeHeight = tree.getHeight(); - assertTrue("Collpased tree height is not longer than initial, " - + "current " + collapsedTreeHeight + " <= initial " - + initialTreeHeight, - collapsedTreeHeight <= initialTreeHeight); + int collapsedTreeHeight = tree.getHeight(); + assertTrue("Collpased tree height is not longer than initial, " + + "current " + collapsedTreeHeight + " <= initial " + + initialTreeHeight, + collapsedTreeHeight <= initialTreeHeight); - }); } } diff --git a/jdk/test/sanity/client/SwingSet/src/WindowDemoTest.java b/jdk/test/sanity/client/SwingSet/src/WindowDemoTest.java index ef0fb850360..57b3ead00a3 100644 --- a/jdk/test/sanity/client/SwingSet/src/WindowDemoTest.java +++ b/jdk/test/sanity/client/SwingSet/src/WindowDemoTest.java @@ -21,6 +21,7 @@ * questions. */ +import org.jtregext.GuiTestListener; import com.sun.swingset3.demos.window.WindowDemo; import static com.sun.swingset3.demos.window.WindowDemo.*; import static org.jemmy2ext.JemmyExt.*; @@ -31,6 +32,7 @@ import org.netbeans.jemmy.operators.JButtonOperator; import org.netbeans.jemmy.operators.JFrameOperator; import org.netbeans.jemmy.operators.JLabelOperator; import org.netbeans.jemmy.operators.WindowOperator; +import org.testng.annotations.Listeners; /* * @test @@ -40,37 +42,37 @@ import org.netbeans.jemmy.operators.WindowOperator; * when the "Show JWindow..." button is clicked. * * @library /sanity/client/lib/jemmy/src - * @library /sanity/client/lib/Jemmy2Ext/src + * @library /sanity/client/lib/Extensions/src * @library /sanity/client/lib/SwingSet3/src * @build org.jemmy2ext.JemmyExt * @build com.sun.swingset3.demos.window.WindowDemo * @run testng WindowDemoTest */ +@Listeners(GuiTestListener.class) public class WindowDemoTest { @Test public void test() throws Exception { - captureDebugInfoOnFail(() -> { - new ClassReference(WindowDemo.class.getCanonicalName()).startApplication(); - JFrameOperator frame = new JFrameOperator(); + new ClassReference(WindowDemo.class.getCanonicalName()).startApplication(); - assertEquals("Only one JWindow is shown", 1, getJWindowCount()); + JFrameOperator frame = new JFrameOperator(); - WindowOperator window = new WindowOperator(getJWindow()); + assertEquals("Only one JWindow is shown", 1, getJWindowCount()); - assertTrue("JFrame is showing", frame.isShowing()); - assertFalse("JFrame is not iconified", isIconified(frame)); - assertTrue("JWindow is showing", window.isShowing()); + WindowOperator window = new WindowOperator(getJWindow()); - final String labelText = I_HAVE_NO_SYSTEM_BORDER; - JLabelOperator jLabelOperator = new JLabelOperator(window, labelText); - assertEquals("JWindow contains the label with corresponding text", labelText, jLabelOperator.getText()); + assertTrue("JFrame is showing", frame.isShowing()); + assertFalse("JFrame is not iconified", isIconified(frame)); + assertTrue("JWindow is showing", window.isShowing()); - new JButtonOperator(frame, SHOW_J_WINDOW).push(); + final String labelText = I_HAVE_NO_SYSTEM_BORDER; + JLabelOperator jLabelOperator = new JLabelOperator(window, labelText); + assertEquals("JWindow contains the label with corresponding text", labelText, jLabelOperator.getText()); - assertEquals("Only one JWindow is shown", 1, getJWindowCount()); - }); + new JButtonOperator(frame, SHOW_J_WINDOW).push(); + + assertEquals("Only one JWindow is shown", 1, getJWindowCount()); } } diff --git a/jdk/test/sanity/client/lib/Jemmy2Ext/src/org/jemmy2ext/JemmyExt.java b/jdk/test/sanity/client/lib/Extensions/src/org/jemmy2ext/JemmyExt.java similarity index 97% rename from jdk/test/sanity/client/lib/Jemmy2Ext/src/org/jemmy2ext/JemmyExt.java rename to jdk/test/sanity/client/lib/Extensions/src/org/jemmy2ext/JemmyExt.java index fe0431b684e..f2d344f4c3f 100644 --- a/jdk/test/sanity/client/lib/Jemmy2Ext/src/org/jemmy2ext/JemmyExt.java +++ b/jdk/test/sanity/client/lib/Extensions/src/org/jemmy2ext/JemmyExt.java @@ -258,20 +258,19 @@ public class JemmyExt { } /** - * Wraps the test code so that in case of any failure as much information as - * possible is captured - * - * @param r test code Runnable - * @throws Exception whatever exception the test may throw + * Dispose all AWT/Swing windows causing event thread to stop */ - public static void captureDebugInfoOnFail(RunnableWithException r) throws Exception { - // TODO: Remove this once https://bugs.openjdk.java.net/browse/JDK-8151671 is fixed + public static void disposeAllWindows() { + System.out.println("disposeAllWindows"); try { - r.run(); - System.out.println("TEST PASSED"); - } catch (Throwable t) { - captureAll(); - throw t; + EventQueue.invokeAndWait(() -> { + Window[] windows = Window.getWindows(); + for (Window w : windows) { + w.dispose(); + } + }); + } catch (InterruptedException | InvocationTargetException ex) { + Logger.getLogger(JemmyExt.class.getName()).log(Level.SEVERE, "Failed to dispose all windows", ex); } } diff --git a/jdk/test/sanity/client/lib/Extensions/src/org/jtregext/GuiTestListener.java b/jdk/test/sanity/client/lib/Extensions/src/org/jtregext/GuiTestListener.java new file mode 100644 index 00000000000..407fd52d292 --- /dev/null +++ b/jdk/test/sanity/client/lib/Extensions/src/org/jtregext/GuiTestListener.java @@ -0,0 +1,72 @@ +package org.jtregext; + +/* + * Copyright (c) 2016, 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 org.jemmy2ext.JemmyExt; +import static org.jemmy2ext.JemmyExt.captureAll; +import org.testng.ITestContext; +import org.testng.ITestListener; +import org.testng.ITestResult; + +// TODO: Remove this once https://bugs.openjdk.java.net/browse/JDK-8151671 is fixed +public class GuiTestListener implements ITestListener { + + private void afterTest() { + JemmyExt.disposeAllWindows(); + } + + @Override + public void onTestStart(ITestResult result) { + } + + @Override + public void onTestSuccess(ITestResult result) { + System.out.println("TEST PASSED"); + afterTest(); + } + + @Override + public void onTestFailure(ITestResult result) { + captureAll(); + afterTest(); + } + + @Override + public void onTestSkipped(ITestResult result) { + } + + @Override + public void onTestFailedButWithinSuccessPercentage(ITestResult result) { + } + + @Override + public void onStart(ITestContext context) { + } + + @Override + public void onFinish(ITestContext context) { + } + +} diff --git a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/tabbedpane/TabbedPaneDemo.java b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/tabbedpane/TabbedPaneDemo.java index 5d023405b58..84336d822c2 100644 --- a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/tabbedpane/TabbedPaneDemo.java +++ b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/tabbedpane/TabbedPaneDemo.java @@ -204,7 +204,9 @@ public class TabbedPaneDemo extends JPanel implements ActionListener { } public void go() { - animator = new javax.swing.Timer(22 + 22 + 22, this); + if (animator == null) { + animator = new javax.swing.Timer(22 + 22 + 22, this); + } animator.start(); } @@ -246,7 +248,7 @@ public class TabbedPaneDemo extends JPanel implements ActionListener { @Override public void actionPerformed(ActionEvent e) { - if (isVisible()) { + if (isShowing()) { repaint(); } else { animator.stop(); From 560adadb050cf54561f212ab0bd46d8a975112c8 Mon Sep 17 00:00:00 2001 From: Felix Yang Date: Thu, 28 Apr 2016 12:38:22 +0800 Subject: [PATCH 16/18] 8154733: Fix module dependencies missed in java.rmi tests Reviewed-by: alanb, amlu --- jdk/test/java/rmi/TEST.properties | 1 + jdk/test/java/rmi/reliability/benchmark/bench/serial/Main.java | 3 ++- jdk/test/sun/rmi/TEST.properties | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 jdk/test/java/rmi/TEST.properties create mode 100644 jdk/test/sun/rmi/TEST.properties diff --git a/jdk/test/java/rmi/TEST.properties b/jdk/test/java/rmi/TEST.properties new file mode 100644 index 00000000000..d4bbfc905b9 --- /dev/null +++ b/jdk/test/java/rmi/TEST.properties @@ -0,0 +1 @@ +modules = java.rmi diff --git a/jdk/test/java/rmi/reliability/benchmark/bench/serial/Main.java b/jdk/test/java/rmi/reliability/benchmark/bench/serial/Main.java index 8f9b715867f..5e6358dba7f 100644 --- a/jdk/test/java/rmi/reliability/benchmark/bench/serial/Main.java +++ b/jdk/test/java/rmi/reliability/benchmark/bench/serial/Main.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, 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,6 +26,7 @@ * @summary The Serialization benchmark test. This java class is used to run the * test under JTREG. * @library ../../ + * @modules java.desktop * @build bench.BenchInfo bench.HtmlReporter bench.Util bench.Benchmark * @build bench.Reporter bench.XmlReporter bench.ConfigFormatException * @build bench.Harness bench.TextReporter diff --git a/jdk/test/sun/rmi/TEST.properties b/jdk/test/sun/rmi/TEST.properties new file mode 100644 index 00000000000..d4bbfc905b9 --- /dev/null +++ b/jdk/test/sun/rmi/TEST.properties @@ -0,0 +1 @@ +modules = java.rmi From 1f74d8cba8fc3961285b61074b562b3a04dc1bd4 Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Thu, 28 Apr 2016 09:33:18 +0100 Subject: [PATCH 17/18] 8155578: OpenJDK build failed after JDK-8044773 Reviewed-by: alanb --- jdk/src/java.base/share/classes/module-info.java | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/src/java.base/share/classes/module-info.java b/jdk/src/java.base/share/classes/module-info.java index 12ad93f6a6d..a597253d168 100644 --- a/jdk/src/java.base/share/classes/module-info.java +++ b/jdk/src/java.base/share/classes/module-info.java @@ -166,6 +166,7 @@ module java.base { java.sql, java.xml, jdk.charsets, + jdk.net, jdk.scripting.nashorn, jdk.unsupported, jdk.vm.ci; From 552f7b32c16bca29540c09940a9a93d85778d222 Mon Sep 17 00:00:00 2001 From: Chris Bensen Date: Thu, 28 Apr 2016 08:28:48 -0700 Subject: [PATCH 18/18] 8150990: Add helper class in jdk.jlink for packager use to avoid coordination with FX and JDK builds Reviewed-by: alanb, mchung, kcr, sundar --- .../packager/AppRuntimeImageBuilder.java | 146 ++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/packager/AppRuntimeImageBuilder.java diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/packager/AppRuntimeImageBuilder.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/packager/AppRuntimeImageBuilder.java new file mode 100644 index 00000000000..fb785da54b7 --- /dev/null +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/packager/AppRuntimeImageBuilder.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2016, 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.tools.jlink.internal.packager; + + +import jdk.tools.jlink.Jlink; +import jdk.tools.jlink.builder.ImageBuilder; +import jdk.tools.jlink.plugin.Plugin; +import jdk.tools.jlink.builder.*; +import jdk.tools.jlink.plugin.Pool; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintWriter; +import java.io.StringReader; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.ResourceBundle; +import java.util.Set; +import java.util.StringTokenizer; +import java.util.TreeSet; +import java.util.stream.Collectors; + +/** + * AppRuntimeImageBuilder is a private API used only by the Java Packager to generate + * a Java runtime image using jlink. AppRuntimeImageBuilder encapsulates the + * arguments that jlink requires to generate this image. To create the image call the + * build() method. + */ +public final class AppRuntimeImageBuilder { + private Path outputDir = null; + private List modulePath = null; + private Set addModules = null; + private Set limitModules = null; + private String excludeFileList = null; + private Map userArguments = null; + private Boolean stripNativeCommands = null; + + public AppRuntimeImageBuilder() {} + + public void setOutputDir(Path value) { + outputDir = value; + } + + public void setModulePath(List value) { + modulePath = value; + } + + public void setAddModules(Set value) { + addModules = value; + } + + public void setLimitModules(Set value) { + limitModules = value; + } + + public void setExcludeFileList(String value) { + excludeFileList = value; + } + + public void setStripNativeCommands(boolean value) { + stripNativeCommands = value; + } + + public void setUserArguments(Map value) { + userArguments = value; + } + + public void build() throws IOException { + // jlink main arguments + Jlink.JlinkConfiguration jlinkConfig = new Jlink.JlinkConfiguration( + new File("").toPath(), // Unused + modulePath, addModules, limitModules); + + // plugin configuration + List plugins = new ArrayList(); + + if (stripNativeCommands) { + plugins.add(Jlink.newPlugin( + "strip-native-commands", + Collections.singletonMap("strip-native-commands", "on"), + null)); + } + + if (excludeFileList != null && !excludeFileList.isEmpty()) { + plugins.add(Jlink.newPlugin( + "exclude-files", + Collections.singletonMap("exclude-files", excludeFileList), + null)); + } + + // add user supplied jlink arguments + for (Map.Entry entry : userArguments.entrySet()) { + String key = entry.getKey(); + String value = entry.getValue(); + plugins.add(Jlink.newPlugin(key, + Collections.singletonMap(key, value), + null)); + } + + plugins.add(Jlink.newPlugin("installed-modules", Collections.emptyMap(), null)); + + // build the image + Jlink.PluginsConfiguration pluginConfig = new Jlink.PluginsConfiguration( + plugins, new DefaultImageBuilder(true, outputDir), null); + Jlink jlink = new Jlink(); + jlink.build(jlinkConfig, pluginConfig); + } +}