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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -35,21 +35,8 @@ import java.net.*;
|
||||
* request that the RMI runtime use its socket factory instance
|
||||
* instead of the default implementation.
|
||||
*
|
||||
* <p>The default socket factory implementation performs a
|
||||
* three-tiered approach to creating client sockets. First, a direct
|
||||
* socket connection to the remote VM is attempted. If that fails
|
||||
* (due to a firewall), the runtime uses HTTP with the explicit port
|
||||
* number of the server. If the firewall does not allow this type of
|
||||
* communication, then HTTP to a cgi-bin script on the server is used
|
||||
* to POST the RMI call. The HTTP tunneling mechanisms are disabled by
|
||||
* default. This behavior is controlled by the {@code java.rmi.server.disableHttp}
|
||||
* property, whose default value is {@code true}. Setting this property's
|
||||
* value to {@code false} will enable the HTTP tunneling mechanisms.
|
||||
*
|
||||
* <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 a direct
|
||||
* socket connection to the remote host.
|
||||
*
|
||||
* <p>The default socket factory implementation creates server sockets that
|
||||
* are bound to the wildcard address, which accepts requests from all network
|
||||
@ -181,7 +168,7 @@ public abstract class RMISocketFactory
|
||||
public synchronized static RMISocketFactory getDefaultSocketFactory() {
|
||||
if (defaultSocketFactory == null) {
|
||||
defaultSocketFactory =
|
||||
new sun.rmi.transport.proxy.RMIMasterSocketFactory();
|
||||
new sun.rmi.transport.tcp.TCPDirectSocketFactory();
|
||||
}
|
||||
return defaultSocketFactory;
|
||||
}
|
||||
|
@ -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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -26,14 +26,10 @@
|
||||
package sun.rmi.transport.tcp;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
import java.rmi.*;
|
||||
import java.rmi.server.RMISocketFactory;
|
||||
import sun.rmi.runtime.Log;
|
||||
import sun.rmi.transport.*;
|
||||
import sun.rmi.transport.proxy.*;
|
||||
|
||||
public class TCPConnection implements Connection {
|
||||
|
||||
@ -120,10 +116,7 @@ public class TCPConnection implements Connection {
|
||||
*/
|
||||
public boolean isReusable()
|
||||
{
|
||||
if ((socket != null) && (socket instanceof RMISocketInfo))
|
||||
return ((RMISocketInfo) socket).isReusable();
|
||||
else
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -22,7 +22,7 @@
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package sun.rmi.transport.proxy;
|
||||
package sun.rmi.transport.tcp;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.Socket;
|
||||
@ -33,7 +33,7 @@ import java.rmi.server.RMISocketFactory;
|
||||
* RMIDirectSocketFactory creates a direct socket connection to the
|
||||
* specified port on the specified host.
|
||||
*/
|
||||
public class RMIDirectSocketFactory extends RMISocketFactory {
|
||||
public class TCPDirectSocketFactory extends RMISocketFactory {
|
||||
|
||||
public Socket createSocket(String host, int port) throws IOException
|
||||
{
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -75,7 +75,6 @@ import sun.rmi.transport.StreamRemoteCall;
|
||||
import sun.rmi.transport.Target;
|
||||
import sun.rmi.transport.Transport;
|
||||
import sun.rmi.transport.TransportConstants;
|
||||
import sun.rmi.transport.proxy.HttpReceiveSocket;
|
||||
|
||||
/**
|
||||
* TCPTransport is the socket-based implementation of the RMI Transport
|
||||
@ -711,35 +710,10 @@ public class TCPTransport extends Transport {
|
||||
? sockIn
|
||||
: new BufferedInputStream(sockIn);
|
||||
|
||||
// Read magic (or HTTP wrapper)
|
||||
bufIn.mark(4);
|
||||
// Read magic
|
||||
DataInputStream in = new DataInputStream(bufIn);
|
||||
int magic = in.readInt();
|
||||
|
||||
if (magic == POST) {
|
||||
tcpLog.log(Log.BRIEF, "decoding HTTP-wrapped call");
|
||||
|
||||
// It's really a HTTP-wrapped request. Repackage
|
||||
// the socket in a HttpReceiveSocket, reinitialize
|
||||
// sockIn and in, and reread magic.
|
||||
bufIn.reset(); // unread "POST"
|
||||
|
||||
try {
|
||||
socket = new HttpReceiveSocket(socket, bufIn, null);
|
||||
remoteHost = "0.0.0.0";
|
||||
sockIn = socket.getInputStream();
|
||||
bufIn = new BufferedInputStream(sockIn);
|
||||
in = new DataInputStream(bufIn);
|
||||
magic = in.readInt();
|
||||
|
||||
} catch (IOException e) {
|
||||
throw new RemoteException("Error HTTP-unwrapping call",
|
||||
e);
|
||||
}
|
||||
}
|
||||
// bufIn's mark will invalidate itself when it overflows
|
||||
// so it doesn't have to be turned off
|
||||
|
||||
// read and verify transport header
|
||||
short version = in.readShort();
|
||||
if (magic != TransportConstants.Magic ||
|
||||
|
@ -191,8 +191,6 @@ java/rmi/transport/rapidExportUnexport/RapidExportUnexport.java 7146541 linux-al
|
||||
|
||||
java/rmi/transport/checkLeaseInfoLeak/CheckLeaseLeak.java 7191877 generic-all
|
||||
|
||||
sun/rmi/transport/proxy/EagerHttpFallback.java 7195095 generic-all
|
||||
|
||||
java/rmi/activation/Activatable/extLoadedImpl/ext.sh 8062724 generic-all
|
||||
|
||||
sun/rmi/rmic/newrmic/equivalence/run.sh 8145980 generic-all
|
||||
|
@ -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