8066750: Remove HTTP proxy implementation and tests from RMI
Reviewed-by: smarks
This commit is contained in:
parent
fb8f4acea8
commit
c08b6a7c8f
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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
|
* request that the RMI runtime use its socket factory instance
|
||||||
* instead of the default implementation.
|
* instead of the default implementation.
|
||||||
*
|
*
|
||||||
* <p>The default socket factory implementation performs a
|
* <p>The default socket factory implementation creates a direct
|
||||||
* three-tiered approach to creating client sockets. First, a direct
|
* socket connection to the remote host.
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* <p><strong>Deprecated: HTTP Tunneling.</strong> <em>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.</em>
|
|
||||||
*
|
*
|
||||||
* <p>The default socket factory implementation creates server sockets that
|
* <p>The default socket factory implementation creates server sockets that
|
||||||
* are bound to the wildcard address, which accepts requests from all network
|
* 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() {
|
public synchronized static RMISocketFactory getDefaultSocketFactory() {
|
||||||
if (defaultSocketFactory == null) {
|
if (defaultSocketFactory == null) {
|
||||||
defaultSocketFactory =
|
defaultSocketFactory =
|
||||||
new sun.rmi.transport.proxy.RMIMasterSocketFactory();
|
new sun.rmi.transport.tcp.TCPDirectSocketFactory();
|
||||||
}
|
}
|
||||||
return defaultSocketFactory;
|
return defaultSocketFactory;
|
||||||
}
|
}
|
||||||
|
@ -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 <command>=<parameters>}".
|
|
||||||
*
|
|
||||||
* 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<Void>() {
|
|
||||||
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<String, CGICommandHandler> 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("<HTML>" +
|
|
||||||
"<HEAD><TITLE>Java RMI Client Error" +
|
|
||||||
"</TITLE></HEAD>" +
|
|
||||||
"<BODY>");
|
|
||||||
System.out.println("<H1>Java RMI Client Error</H1>");
|
|
||||||
System.out.println("");
|
|
||||||
System.out.println(message);
|
|
||||||
System.out.println("</BODY></HTML>");
|
|
||||||
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("<HTML>" +
|
|
||||||
"<HEAD><TITLE>Java RMI Server Error" +
|
|
||||||
"</TITLE></HEAD>" +
|
|
||||||
"<BODY>");
|
|
||||||
System.out.println("<H1>Java RMI Server Error</H1>");
|
|
||||||
System.out.println("");
|
|
||||||
System.out.println(message);
|
|
||||||
System.out.println("</BODY></HTML>");
|
|
||||||
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("<HTML>" +
|
|
||||||
"<HEAD><TITLE>Java RMI Server Hostname Info" +
|
|
||||||
"</TITLE></HEAD>" +
|
|
||||||
"<BODY>");
|
|
||||||
System.out.println("<H1>Java RMI Server Hostname Info</H1>");
|
|
||||||
System.out.println("<H2>Local host name available to Java VM:</H2>");
|
|
||||||
System.out.print("<P>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("<H2>Server host information obtained through CGI interface from HTTP server:</H2>");
|
|
||||||
System.out.println("<P>SERVER_NAME = " + CGIHandler.ServerName);
|
|
||||||
System.out.println("<P>SERVER_PORT = " + CGIHandler.ServerPort);
|
|
||||||
System.out.println("</BODY></HTML>");
|
|
||||||
}
|
|
||||||
}
|
|
@ -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. <i>backlog</i> 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();
|
|
||||||
}
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -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 };
|
|
||||||
}
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
@ -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<String>) () -> 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 + "]";
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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<String>) () -> 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>) () ->
|
|
||||||
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>) () ->
|
|
||||||
Boolean.getBoolean("sun.rmi.transport.proxy.eagerHttpFallback"));
|
|
||||||
|
|
||||||
/** table of hosts successfully connected to and the factory used */
|
|
||||||
private Hashtable<String, RMISocketFactory> 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<String> 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<RMISocketFactory> 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<String>) () -> System.getProperty("http.proxyHost"));
|
|
||||||
|
|
||||||
if (proxyHost == null)
|
|
||||||
proxyHost = java.security.AccessController.doPrivileged(
|
|
||||||
(PrivilegedAction<String>) () -> System.getProperty("proxyHost"));
|
|
||||||
|
|
||||||
boolean disable = java.security.AccessController.doPrivileged(
|
|
||||||
(PrivilegedAction<String>) () -> 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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();
|
|
||||||
}
|
|
@ -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<InetAddress>() {
|
|
||||||
@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();
|
|
||||||
}
|
|
||||||
}
|
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -26,14 +26,10 @@
|
|||||||
package sun.rmi.transport.tcp;
|
package sun.rmi.transport.tcp;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.net.SocketException;
|
|
||||||
import java.rmi.*;
|
import java.rmi.*;
|
||||||
import java.rmi.server.RMISocketFactory;
|
|
||||||
import sun.rmi.runtime.Log;
|
import sun.rmi.runtime.Log;
|
||||||
import sun.rmi.transport.*;
|
import sun.rmi.transport.*;
|
||||||
import sun.rmi.transport.proxy.*;
|
|
||||||
|
|
||||||
public class TCPConnection implements Connection {
|
public class TCPConnection implements Connection {
|
||||||
|
|
||||||
@ -120,10 +116,7 @@ public class TCPConnection implements Connection {
|
|||||||
*/
|
*/
|
||||||
public boolean isReusable()
|
public boolean isReusable()
|
||||||
{
|
{
|
||||||
if ((socket != null) && (socket instanceof RMISocketInfo))
|
return true;
|
||||||
return ((RMISocketInfo) socket).isReusable();
|
|
||||||
else
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
* or visit www.oracle.com if you need additional information or have any
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
* questions.
|
* questions.
|
||||||
*/
|
*/
|
||||||
package sun.rmi.transport.proxy;
|
package sun.rmi.transport.tcp;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
@ -33,7 +33,7 @@ import java.rmi.server.RMISocketFactory;
|
|||||||
* RMIDirectSocketFactory creates a direct socket connection to the
|
* RMIDirectSocketFactory creates a direct socket connection to the
|
||||||
* specified port on the specified host.
|
* 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
|
public Socket createSocket(String host, int port) throws IOException
|
||||||
{
|
{
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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.Target;
|
||||||
import sun.rmi.transport.Transport;
|
import sun.rmi.transport.Transport;
|
||||||
import sun.rmi.transport.TransportConstants;
|
import sun.rmi.transport.TransportConstants;
|
||||||
import sun.rmi.transport.proxy.HttpReceiveSocket;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TCPTransport is the socket-based implementation of the RMI Transport
|
* TCPTransport is the socket-based implementation of the RMI Transport
|
||||||
@ -711,35 +710,10 @@ public class TCPTransport extends Transport {
|
|||||||
? sockIn
|
? sockIn
|
||||||
: new BufferedInputStream(sockIn);
|
: new BufferedInputStream(sockIn);
|
||||||
|
|
||||||
// Read magic (or HTTP wrapper)
|
// Read magic
|
||||||
bufIn.mark(4);
|
|
||||||
DataInputStream in = new DataInputStream(bufIn);
|
DataInputStream in = new DataInputStream(bufIn);
|
||||||
int magic = in.readInt();
|
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
|
// read and verify transport header
|
||||||
short version = in.readShort();
|
short version = in.readShort();
|
||||||
if (magic != TransportConstants.Magic ||
|
if (magic != TransportConstants.Magic ||
|
||||||
|
@ -191,8 +191,6 @@ java/rmi/transport/rapidExportUnexport/RapidExportUnexport.java 7146541 linux-al
|
|||||||
|
|
||||||
java/rmi/transport/checkLeaseInfoLeak/CheckLeaseLeak.java 7191877 generic-all
|
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
|
java/rmi/activation/Activatable/extLoadedImpl/ext.sh 8062724 generic-all
|
||||||
|
|
||||||
sun/rmi/rmic/newrmic/equivalence/run.sh 8145980 generic-all
|
sun/rmi/rmic/newrmic/equivalence/run.sh 8145980 generic-all
|
||||||
|
@ -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 );
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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";
|
|
||||||
};
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
@ -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");
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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";
|
|
||||||
};
|
|
Loading…
x
Reference in New Issue
Block a user