8066750: Remove HTTP proxy implementation and tests from RMI

Reviewed-by: smarks
This commit is contained in:
Roger Riggs 2016-04-26 17:35:10 -04:00
parent fb8f4acea8
commit c08b6a7c8f
28 changed files with 10 additions and 3151 deletions

View File

@ -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;
}

View File

@ -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>");
}
}

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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 };
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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 + "]";
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}
}

View File

@ -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();
}

View File

@ -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();
}
}

View File

@ -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;
}
/**

View File

@ -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
{

View File

@ -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 ||

View File

@ -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

View File

@ -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 );
}
}

View File

@ -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);
}
}
}

View File

@ -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";
};

View File

@ -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();
}
}

View File

@ -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;
}
}
}

View File

@ -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
}

View File

@ -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;
}

View File

@ -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");
}
}

View File

@ -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);
}
}
}

View File

@ -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";
};