8187443: Forest Consolidation: Move files to unified layout

Reviewed-by: darcy, ihse
This commit is contained in:
Erik Joelsson 2017-09-12 19:03:39 +02:00
parent 270fe13182
commit 3789983e89
56923 changed files with 3 additions and 15727 deletions

View file

@ -0,0 +1,421 @@
/*
* Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.net;
import java.io.FileDescriptor;
import java.io.IOException;
import java.security.AccessController;
import sun.net.ResourceManager;
import java.util.Set;
import java.util.HashSet;
import java.util.Collections;
import sun.security.action.GetPropertyAction;
/**
* Abstract datagram and multicast socket implementation base class.
* Note: This is not a public class, so that applets cannot call
* into the implementation directly and hence cannot bypass the
* security checks present in the DatagramSocket and MulticastSocket
* classes.
*
* @author Pavani Diwanji
*/
abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl
{
/* timeout value for receive() */
int timeout = 0;
boolean connected = false;
private int trafficClass = 0;
protected InetAddress connectedAddress = null;
private int connectedPort = -1;
private static final String os =
GetPropertyAction.privilegedGetProperty("os.name");
/**
* flag set if the native connect() call not to be used
*/
private static final boolean connectDisabled = os.contains("OS X");
/**
* Load net library into runtime.
*/
static {
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<>() {
public Void run() {
System.loadLibrary("net");
return null;
}
});
}
private static volatile boolean checkedReusePort;
private static volatile boolean isReusePortAvailable;
/**
* Tells whether SO_REUSEPORT is supported.
*/
static boolean isReusePortAvailable() {
if (!checkedReusePort) {
isReusePortAvailable = isReusePortAvailable0();
checkedReusePort = true;
}
return isReusePortAvailable;
}
/**
* Returns a set of SocketOptions supported by this impl and by this impl's
* socket (Socket or ServerSocket)
*
* @return a Set of SocketOptions
*/
@Override
protected Set<SocketOption<?>> supportedOptions() {
Set<SocketOption<?>> options;
if (isReusePortAvailable()) {
options = new HashSet<>();
options.addAll(super.supportedOptions());
options.add(StandardSocketOptions.SO_REUSEPORT);
options = Collections.unmodifiableSet(options);
} else {
options = super.supportedOptions();
}
return options;
}
/**
* Creates a datagram socket
*/
protected synchronized void create() throws SocketException {
ResourceManager.beforeUdpCreate();
fd = new FileDescriptor();
try {
datagramSocketCreate();
} catch (SocketException ioe) {
ResourceManager.afterUdpClose();
fd = null;
throw ioe;
}
}
/**
* Binds a datagram socket to a local port.
*/
protected synchronized void bind(int lport, InetAddress laddr)
throws SocketException {
bind0(lport, laddr);
}
protected abstract void bind0(int lport, InetAddress laddr)
throws SocketException;
/**
* Sends a datagram packet. The packet contains the data and the
* destination address to send the packet to.
* @param p the packet to be sent.
*/
protected abstract void send(DatagramPacket p) throws IOException;
/**
* Connects a datagram socket to a remote destination. This associates the remote
* address with the local socket so that datagrams may only be sent to this destination
* and received from this destination.
* @param address the remote InetAddress to connect to
* @param port the remote port number
*/
protected void connect(InetAddress address, int port) throws SocketException {
connect0(address, port);
connectedAddress = address;
connectedPort = port;
connected = true;
}
/**
* Disconnects a previously connected socket. Does nothing if the socket was
* not connected already.
*/
protected void disconnect() {
disconnect0(connectedAddress.holder().getFamily());
connected = false;
connectedAddress = null;
connectedPort = -1;
}
/**
* Peek at the packet to see who it is from.
* @param i the address to populate with the sender address
*/
protected abstract int peek(InetAddress i) throws IOException;
protected abstract int peekData(DatagramPacket p) throws IOException;
/**
* Receive the datagram packet.
* @param p the packet to receive into
*/
protected synchronized void receive(DatagramPacket p)
throws IOException {
receive0(p);
}
protected abstract void receive0(DatagramPacket p)
throws IOException;
/**
* Set the TTL (time-to-live) option.
* @param ttl TTL to be set.
*/
protected abstract void setTimeToLive(int ttl) throws IOException;
/**
* Get the TTL (time-to-live) option.
*/
protected abstract int getTimeToLive() throws IOException;
/**
* Set the TTL (time-to-live) option.
* @param ttl TTL to be set.
*/
@Deprecated
protected abstract void setTTL(byte ttl) throws IOException;
/**
* Get the TTL (time-to-live) option.
*/
@Deprecated
protected abstract byte getTTL() throws IOException;
/**
* Join the multicast group.
* @param inetaddr multicast address to join.
*/
protected void join(InetAddress inetaddr) throws IOException {
join(inetaddr, null);
}
/**
* Leave the multicast group.
* @param inetaddr multicast address to leave.
*/
protected void leave(InetAddress inetaddr) throws IOException {
leave(inetaddr, null);
}
/**
* Join the multicast group.
* @param mcastaddr multicast address to join.
* @param netIf specifies the local interface to receive multicast
* datagram packets
* @throws IllegalArgumentException if mcastaddr is null or is a
* SocketAddress subclass not supported by this socket
* @since 1.4
*/
protected void joinGroup(SocketAddress mcastaddr, NetworkInterface netIf)
throws IOException {
if (mcastaddr == null || !(mcastaddr instanceof InetSocketAddress))
throw new IllegalArgumentException("Unsupported address type");
join(((InetSocketAddress)mcastaddr).getAddress(), netIf);
}
protected abstract void join(InetAddress inetaddr, NetworkInterface netIf)
throws IOException;
/**
* Leave the multicast group.
* @param mcastaddr multicast address to leave.
* @param netIf specified the local interface to leave the group at
* @throws IllegalArgumentException if mcastaddr is null or is a
* SocketAddress subclass not supported by this socket
* @since 1.4
*/
protected void leaveGroup(SocketAddress mcastaddr, NetworkInterface netIf)
throws IOException {
if (mcastaddr == null || !(mcastaddr instanceof InetSocketAddress))
throw new IllegalArgumentException("Unsupported address type");
leave(((InetSocketAddress)mcastaddr).getAddress(), netIf);
}
protected abstract void leave(InetAddress inetaddr, NetworkInterface netIf)
throws IOException;
/**
* Close the socket.
*/
protected void close() {
if (fd != null) {
datagramSocketClose();
ResourceManager.afterUdpClose();
fd = null;
}
}
protected boolean isClosed() {
return (fd == null) ? true : false;
}
@SuppressWarnings("deprecation")
protected void finalize() {
close();
}
/**
* set a value - since we only support (setting) binary options
* here, o must be a Boolean
*/
public void setOption(int optID, Object o) throws SocketException {
if (isClosed()) {
throw new SocketException("Socket Closed");
}
switch (optID) {
/* check type safety b4 going native. These should never
* fail, since only java.Socket* has access to
* PlainSocketImpl.setOption().
*/
case SO_TIMEOUT:
if (o == null || !(o instanceof Integer)) {
throw new SocketException("bad argument for SO_TIMEOUT");
}
int tmp = ((Integer) o).intValue();
if (tmp < 0)
throw new IllegalArgumentException("timeout < 0");
timeout = tmp;
return;
case IP_TOS:
if (o == null || !(o instanceof Integer)) {
throw new SocketException("bad argument for IP_TOS");
}
trafficClass = ((Integer)o).intValue();
break;
case SO_REUSEADDR:
if (o == null || !(o instanceof Boolean)) {
throw new SocketException("bad argument for SO_REUSEADDR");
}
break;
case SO_BROADCAST:
if (o == null || !(o instanceof Boolean)) {
throw new SocketException("bad argument for SO_BROADCAST");
}
break;
case SO_BINDADDR:
throw new SocketException("Cannot re-bind Socket");
case SO_RCVBUF:
case SO_SNDBUF:
if (o == null || !(o instanceof Integer) ||
((Integer)o).intValue() < 0) {
throw new SocketException("bad argument for SO_SNDBUF or " +
"SO_RCVBUF");
}
break;
case IP_MULTICAST_IF:
if (o == null || !(o instanceof InetAddress))
throw new SocketException("bad argument for IP_MULTICAST_IF");
break;
case IP_MULTICAST_IF2:
if (o == null || !(o instanceof NetworkInterface))
throw new SocketException("bad argument for IP_MULTICAST_IF2");
break;
case IP_MULTICAST_LOOP:
if (o == null || !(o instanceof Boolean))
throw new SocketException("bad argument for IP_MULTICAST_LOOP");
break;
case SO_REUSEPORT:
if (o == null || !(o instanceof Boolean)) {
throw new SocketException("bad argument for SO_REUSEPORT");
}
if (!supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) {
throw new UnsupportedOperationException("unsupported option");
}
break;
default:
throw new SocketException("invalid option: " + optID);
}
socketSetOption(optID, o);
}
/*
* get option's state - set or not
*/
public Object getOption(int optID) throws SocketException {
if (isClosed()) {
throw new SocketException("Socket Closed");
}
Object result;
switch (optID) {
case SO_TIMEOUT:
result = timeout;
break;
case IP_TOS:
result = socketGetOption(optID);
if ( ((Integer)result).intValue() == -1) {
result = trafficClass;
}
break;
case SO_BINDADDR:
case IP_MULTICAST_IF:
case IP_MULTICAST_IF2:
case SO_RCVBUF:
case SO_SNDBUF:
case IP_MULTICAST_LOOP:
case SO_REUSEADDR:
case SO_BROADCAST:
result = socketGetOption(optID);
break;
case SO_REUSEPORT:
if (!supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) {
throw new UnsupportedOperationException("unsupported option");
}
result = socketGetOption(optID);
break;
default:
throw new SocketException("invalid option: " + optID);
}
return result;
}
protected abstract void datagramSocketCreate() throws SocketException;
protected abstract void datagramSocketClose();
protected abstract void socketSetOption(int opt, Object val)
throws SocketException;
protected abstract Object socketGetOption(int opt) throws SocketException;
protected abstract void connect0(InetAddress address, int port) throws SocketException;
protected abstract void disconnect0(int family);
protected boolean nativeConnectDisabled() {
return connectDisabled;
}
abstract int dataAvailable();
private static native boolean isReusePortAvailable0();
}

View file

@ -0,0 +1,779 @@
/*
* Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.net;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.FileDescriptor;
import sun.net.ConnectionResetException;
import sun.net.NetHooks;
import sun.net.ResourceManager;
import java.util.Set;
import java.util.HashSet;
import java.util.Collections;
/**
* Default Socket Implementation. This implementation does
* not implement any security checks.
* Note this class should <b>NOT</b> be public.
*
* @author Steven B. Byrne
*/
abstract class AbstractPlainSocketImpl extends SocketImpl
{
/* instance variable for SO_TIMEOUT */
int timeout; // timeout in millisec
// traffic class
private int trafficClass;
private boolean shut_rd = false;
private boolean shut_wr = false;
private SocketInputStream socketInputStream = null;
private SocketOutputStream socketOutputStream = null;
/* number of threads using the FileDescriptor */
protected int fdUseCount = 0;
/* lock when increment/decrementing fdUseCount */
protected final Object fdLock = new Object();
/* indicates a close is pending on the file descriptor */
protected boolean closePending = false;
/* indicates connection reset state */
private int CONNECTION_NOT_RESET = 0;
private int CONNECTION_RESET_PENDING = 1;
private int CONNECTION_RESET = 2;
private int resetState;
private final Object resetLock = new Object();
/* whether this Socket is a stream (TCP) socket or not (UDP)
*/
protected boolean stream;
/**
* Load net library into runtime.
*/
static {
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<>() {
public Void run() {
System.loadLibrary("net");
return null;
}
});
}
private static volatile boolean checkedReusePort;
private static volatile boolean isReusePortAvailable;
/**
* Tells whether SO_REUSEPORT is supported.
*/
static boolean isReusePortAvailable() {
if (!checkedReusePort) {
isReusePortAvailable = isReusePortAvailable0();
checkedReusePort = true;
}
return isReusePortAvailable;
}
/**
* Returns a set of SocketOptions supported by this impl and by this impl's
* socket (Socket or ServerSocket)
*
* @return a Set of SocketOptions
*/
@Override
protected Set<SocketOption<?>> supportedOptions() {
Set<SocketOption<?>> options;
if (isReusePortAvailable()) {
options = new HashSet<>();
options.addAll(super.supportedOptions());
options.add(StandardSocketOptions.SO_REUSEPORT);
options = Collections.unmodifiableSet(options);
} else {
options = super.supportedOptions();
}
return options;
}
/**
* Creates a socket with a boolean that specifies whether this
* is a stream socket (true) or an unconnected UDP socket (false).
*/
protected synchronized void create(boolean stream) throws IOException {
this.stream = stream;
if (!stream) {
ResourceManager.beforeUdpCreate();
// only create the fd after we know we will be able to create the socket
fd = new FileDescriptor();
try {
socketCreate(false);
} catch (IOException ioe) {
ResourceManager.afterUdpClose();
fd = null;
throw ioe;
}
} else {
fd = new FileDescriptor();
socketCreate(true);
}
if (socket != null)
socket.setCreated();
if (serverSocket != null)
serverSocket.setCreated();
}
/**
* Creates a socket and connects it to the specified port on
* the specified host.
* @param host the specified host
* @param port the specified port
*/
protected void connect(String host, int port)
throws UnknownHostException, IOException
{
boolean connected = false;
try {
InetAddress address = InetAddress.getByName(host);
this.port = port;
this.address = address;
connectToAddress(address, port, timeout);
connected = true;
} finally {
if (!connected) {
try {
close();
} catch (IOException ioe) {
/* Do nothing. If connect threw an exception then
it will be passed up the call stack */
}
}
}
}
/**
* Creates a socket and connects it to the specified address on
* the specified port.
* @param address the address
* @param port the specified port
*/
protected void connect(InetAddress address, int port) throws IOException {
this.port = port;
this.address = address;
try {
connectToAddress(address, port, timeout);
return;
} catch (IOException e) {
// everything failed
close();
throw e;
}
}
/**
* Creates a socket and connects it to the specified address on
* the specified port.
* @param address the address
* @param timeout the timeout value in milliseconds, or zero for no timeout.
* @throws IOException if connection fails
* @throws IllegalArgumentException if address is null or is a
* SocketAddress subclass not supported by this socket
* @since 1.4
*/
protected void connect(SocketAddress address, int timeout)
throws IOException {
boolean connected = false;
try {
if (address == null || !(address instanceof InetSocketAddress))
throw new IllegalArgumentException("unsupported address type");
InetSocketAddress addr = (InetSocketAddress) address;
if (addr.isUnresolved())
throw new UnknownHostException(addr.getHostName());
this.port = addr.getPort();
this.address = addr.getAddress();
connectToAddress(this.address, port, timeout);
connected = true;
} finally {
if (!connected) {
try {
close();
} catch (IOException ioe) {
/* Do nothing. If connect threw an exception then
it will be passed up the call stack */
}
}
}
}
private void connectToAddress(InetAddress address, int port, int timeout) throws IOException {
if (address.isAnyLocalAddress()) {
doConnect(InetAddress.getLocalHost(), port, timeout);
} else {
doConnect(address, port, timeout);
}
}
public void setOption(int opt, Object val) throws SocketException {
if (isClosedOrPending()) {
throw new SocketException("Socket Closed");
}
boolean on = true;
switch (opt) {
/* check type safety b4 going native. These should never
* fail, since only java.Socket* has access to
* PlainSocketImpl.setOption().
*/
case SO_LINGER:
if (val == null || (!(val instanceof Integer) && !(val instanceof Boolean)))
throw new SocketException("Bad parameter for option");
if (val instanceof Boolean) {
/* true only if disabling - enabling should be Integer */
on = false;
}
break;
case SO_TIMEOUT:
if (val == null || (!(val instanceof Integer)))
throw new SocketException("Bad parameter for SO_TIMEOUT");
int tmp = ((Integer) val).intValue();
if (tmp < 0)
throw new IllegalArgumentException("timeout < 0");
timeout = tmp;
break;
case IP_TOS:
if (val == null || !(val instanceof Integer)) {
throw new SocketException("bad argument for IP_TOS");
}
trafficClass = ((Integer)val).intValue();
break;
case SO_BINDADDR:
throw new SocketException("Cannot re-bind socket");
case TCP_NODELAY:
if (val == null || !(val instanceof Boolean))
throw new SocketException("bad parameter for TCP_NODELAY");
on = ((Boolean)val).booleanValue();
break;
case SO_SNDBUF:
case SO_RCVBUF:
if (val == null || !(val instanceof Integer) ||
!(((Integer)val).intValue() > 0)) {
throw new SocketException("bad parameter for SO_SNDBUF " +
"or SO_RCVBUF");
}
break;
case SO_KEEPALIVE:
if (val == null || !(val instanceof Boolean))
throw new SocketException("bad parameter for SO_KEEPALIVE");
on = ((Boolean)val).booleanValue();
break;
case SO_OOBINLINE:
if (val == null || !(val instanceof Boolean))
throw new SocketException("bad parameter for SO_OOBINLINE");
on = ((Boolean)val).booleanValue();
break;
case SO_REUSEADDR:
if (val == null || !(val instanceof Boolean))
throw new SocketException("bad parameter for SO_REUSEADDR");
on = ((Boolean)val).booleanValue();
break;
case SO_REUSEPORT:
if (val == null || !(val instanceof Boolean))
throw new SocketException("bad parameter for SO_REUSEPORT");
if (!supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT))
throw new UnsupportedOperationException("unsupported option");
on = ((Boolean)val).booleanValue();
break;
default:
throw new SocketException("unrecognized TCP option: " + opt);
}
socketSetOption(opt, on, val);
}
public Object getOption(int opt) throws SocketException {
if (isClosedOrPending()) {
throw new SocketException("Socket Closed");
}
if (opt == SO_TIMEOUT) {
return timeout;
}
int ret = 0;
/*
* The native socketGetOption() knows about 3 options.
* The 32 bit value it returns will be interpreted according
* to what we're asking. A return of -1 means it understands
* the option but its turned off. It will raise a SocketException
* if "opt" isn't one it understands.
*/
switch (opt) {
case TCP_NODELAY:
ret = socketGetOption(opt, null);
return Boolean.valueOf(ret != -1);
case SO_OOBINLINE:
ret = socketGetOption(opt, null);
return Boolean.valueOf(ret != -1);
case SO_LINGER:
ret = socketGetOption(opt, null);
return (ret == -1) ? Boolean.FALSE: (Object)(ret);
case SO_REUSEADDR:
ret = socketGetOption(opt, null);
return Boolean.valueOf(ret != -1);
case SO_BINDADDR:
InetAddressContainer in = new InetAddressContainer();
ret = socketGetOption(opt, in);
return in.addr;
case SO_SNDBUF:
case SO_RCVBUF:
ret = socketGetOption(opt, null);
return ret;
case IP_TOS:
try {
ret = socketGetOption(opt, null);
if (ret == -1) { // ipv6 tos
return trafficClass;
} else {
return ret;
}
} catch (SocketException se) {
// TODO - should make better effort to read TOS or TCLASS
return trafficClass; // ipv6 tos
}
case SO_KEEPALIVE:
ret = socketGetOption(opt, null);
return Boolean.valueOf(ret != -1);
case SO_REUSEPORT:
if (!supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) {
throw new UnsupportedOperationException("unsupported option");
}
ret = socketGetOption(opt, null);
return Boolean.valueOf(ret != -1);
// should never get here
default:
return null;
}
}
/**
* The workhorse of the connection operation. Tries several times to
* establish a connection to the given <host, port>. If unsuccessful,
* throws an IOException indicating what went wrong.
*/
synchronized void doConnect(InetAddress address, int port, int timeout) throws IOException {
synchronized (fdLock) {
if (!closePending && (socket == null || !socket.isBound())) {
NetHooks.beforeTcpConnect(fd, address, port);
}
}
try {
acquireFD();
try {
socketConnect(address, port, timeout);
/* socket may have been closed during poll/select */
synchronized (fdLock) {
if (closePending) {
throw new SocketException ("Socket closed");
}
}
// If we have a ref. to the Socket, then sets the flags
// created, bound & connected to true.
// This is normally done in Socket.connect() but some
// subclasses of Socket may call impl.connect() directly!
if (socket != null) {
socket.setBound();
socket.setConnected();
}
} finally {
releaseFD();
}
} catch (IOException e) {
close();
throw e;
}
}
/**
* Binds the socket to the specified address of the specified local port.
* @param address the address
* @param lport the port
*/
protected synchronized void bind(InetAddress address, int lport)
throws IOException
{
synchronized (fdLock) {
if (!closePending && (socket == null || !socket.isBound())) {
NetHooks.beforeTcpBind(fd, address, lport);
}
}
socketBind(address, lport);
if (socket != null)
socket.setBound();
if (serverSocket != null)
serverSocket.setBound();
}
/**
* Listens, for a specified amount of time, for connections.
* @param count the amount of time to listen for connections
*/
protected synchronized void listen(int count) throws IOException {
socketListen(count);
}
/**
* Accepts connections.
* @param s the connection
*/
protected void accept(SocketImpl s) throws IOException {
acquireFD();
try {
socketAccept(s);
} finally {
releaseFD();
}
}
/**
* Gets an InputStream for this socket.
*/
protected synchronized InputStream getInputStream() throws IOException {
synchronized (fdLock) {
if (isClosedOrPending())
throw new IOException("Socket Closed");
if (shut_rd)
throw new IOException("Socket input is shutdown");
if (socketInputStream == null)
socketInputStream = new SocketInputStream(this);
}
return socketInputStream;
}
void setInputStream(SocketInputStream in) {
socketInputStream = in;
}
/**
* Gets an OutputStream for this socket.
*/
protected synchronized OutputStream getOutputStream() throws IOException {
synchronized (fdLock) {
if (isClosedOrPending())
throw new IOException("Socket Closed");
if (shut_wr)
throw new IOException("Socket output is shutdown");
if (socketOutputStream == null)
socketOutputStream = new SocketOutputStream(this);
}
return socketOutputStream;
}
void setFileDescriptor(FileDescriptor fd) {
this.fd = fd;
}
void setAddress(InetAddress address) {
this.address = address;
}
void setPort(int port) {
this.port = port;
}
void setLocalPort(int localport) {
this.localport = localport;
}
/**
* Returns the number of bytes that can be read without blocking.
*/
protected synchronized int available() throws IOException {
if (isClosedOrPending()) {
throw new IOException("Stream closed.");
}
/*
* If connection has been reset or shut down for input, then return 0
* to indicate there are no buffered bytes.
*/
if (isConnectionReset() || shut_rd) {
return 0;
}
/*
* If no bytes available and we were previously notified
* of a connection reset then we move to the reset state.
*
* If are notified of a connection reset then check
* again if there are bytes buffered on the socket.
*/
int n = 0;
try {
n = socketAvailable();
if (n == 0 && isConnectionResetPending()) {
setConnectionReset();
}
} catch (ConnectionResetException exc1) {
setConnectionResetPending();
try {
n = socketAvailable();
if (n == 0) {
setConnectionReset();
}
} catch (ConnectionResetException exc2) {
}
}
return n;
}
/**
* Closes the socket.
*/
protected void close() throws IOException {
synchronized(fdLock) {
if (fd != null) {
if (!stream) {
ResourceManager.afterUdpClose();
}
if (fdUseCount == 0) {
if (closePending) {
return;
}
closePending = true;
/*
* We close the FileDescriptor in two-steps - first the
* "pre-close" which closes the socket but doesn't
* release the underlying file descriptor. This operation
* may be lengthy due to untransmitted data and a long
* linger interval. Once the pre-close is done we do the
* actual socket to release the fd.
*/
try {
socketPreClose();
} finally {
socketClose();
}
fd = null;
return;
} else {
/*
* If a thread has acquired the fd and a close
* isn't pending then use a deferred close.
* Also decrement fdUseCount to signal the last
* thread that releases the fd to close it.
*/
if (!closePending) {
closePending = true;
fdUseCount--;
socketPreClose();
}
}
}
}
}
void reset() throws IOException {
if (fd != null) {
socketClose();
}
fd = null;
super.reset();
}
/**
* Shutdown read-half of the socket connection;
*/
protected void shutdownInput() throws IOException {
if (fd != null) {
socketShutdown(SHUT_RD);
if (socketInputStream != null) {
socketInputStream.setEOF(true);
}
shut_rd = true;
}
}
/**
* Shutdown write-half of the socket connection;
*/
protected void shutdownOutput() throws IOException {
if (fd != null) {
socketShutdown(SHUT_WR);
shut_wr = true;
}
}
protected boolean supportsUrgentData () {
return true;
}
protected void sendUrgentData (int data) throws IOException {
if (fd == null) {
throw new IOException("Socket Closed");
}
socketSendUrgentData (data);
}
/**
* Cleans up if the user forgets to close it.
*/
@SuppressWarnings("deprecation")
protected void finalize() throws IOException {
close();
}
/*
* "Acquires" and returns the FileDescriptor for this impl
*
* A corresponding releaseFD is required to "release" the
* FileDescriptor.
*/
FileDescriptor acquireFD() {
synchronized (fdLock) {
fdUseCount++;
return fd;
}
}
/*
* "Release" the FileDescriptor for this impl.
*
* If the use count goes to -1 then the socket is closed.
*/
void releaseFD() {
synchronized (fdLock) {
fdUseCount--;
if (fdUseCount == -1) {
if (fd != null) {
try {
socketClose();
} catch (IOException e) {
} finally {
fd = null;
}
}
}
}
}
public boolean isConnectionReset() {
synchronized (resetLock) {
return (resetState == CONNECTION_RESET);
}
}
public boolean isConnectionResetPending() {
synchronized (resetLock) {
return (resetState == CONNECTION_RESET_PENDING);
}
}
public void setConnectionReset() {
synchronized (resetLock) {
resetState = CONNECTION_RESET;
}
}
public void setConnectionResetPending() {
synchronized (resetLock) {
if (resetState == CONNECTION_NOT_RESET) {
resetState = CONNECTION_RESET_PENDING;
}
}
}
/*
* Return true if already closed or close is pending
*/
public boolean isClosedOrPending() {
/*
* Lock on fdLock to ensure that we wait if a
* close is in progress.
*/
synchronized (fdLock) {
if (closePending || (fd == null)) {
return true;
} else {
return false;
}
}
}
/*
* Return the current value of SO_TIMEOUT
*/
public int getTimeout() {
return timeout;
}
/*
* "Pre-close" a socket by dup'ing the file descriptor - this enables
* the socket to be closed without releasing the file descriptor.
*/
private void socketPreClose() throws IOException {
socketClose0(true);
}
/*
* Close the socket (and release the file descriptor).
*/
protected void socketClose() throws IOException {
socketClose0(false);
}
abstract void socketCreate(boolean isServer) throws IOException;
abstract void socketConnect(InetAddress address, int port, int timeout)
throws IOException;
abstract void socketBind(InetAddress address, int port)
throws IOException;
abstract void socketListen(int count)
throws IOException;
abstract void socketAccept(SocketImpl s)
throws IOException;
abstract int socketAvailable()
throws IOException;
abstract void socketClose0(boolean useDeferredClose)
throws IOException;
abstract void socketShutdown(int howto)
throws IOException;
abstract void socketSetOption(int cmd, boolean on, Object value)
throws SocketException;
abstract int socketGetOption(int opt, Object iaContainerObj) throws SocketException;
abstract void socketSendUrgentData(int data)
throws IOException;
public static final int SHUT_RD = 0;
public static final int SHUT_WR = 1;
private static native boolean isReusePortAvailable0();
}

View file

@ -0,0 +1,575 @@
/*
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.net;
import sun.net.www.protocol.http.AuthenticatorKeys;
/**
* The class Authenticator represents an object that knows how to obtain
* authentication for a network connection. Usually, it will do this
* by prompting the user for information.
* <p>
* Applications use this class by overriding {@link
* #getPasswordAuthentication()} in a sub-class. This method will
* typically use the various getXXX() accessor methods to get information
* about the entity requesting authentication. It must then acquire a
* username and password either by interacting with the user or through
* some other non-interactive means. The credentials are then returned
* as a {@link PasswordAuthentication} return value.
* <p>
* An instance of this concrete sub-class is then registered
* with the system by calling {@link #setDefault(Authenticator)}.
* When authentication is required, the system will invoke one of the
* requestPasswordAuthentication() methods which in turn will call the
* getPasswordAuthentication() method of the registered object.
* <p>
* All methods that request authentication have a default implementation
* that fails.
*
* @see java.net.Authenticator#setDefault(java.net.Authenticator)
* @see java.net.Authenticator#getPasswordAuthentication()
*
* @author Bill Foote
* @since 1.2
*/
// There are no abstract methods, but to be useful the user must
// subclass.
public abstract
class Authenticator {
// The system-wide authenticator object. See setDefault().
private static volatile Authenticator theAuthenticator;
private String requestingHost;
private InetAddress requestingSite;
private int requestingPort;
private String requestingProtocol;
private String requestingPrompt;
private String requestingScheme;
private URL requestingURL;
private RequestorType requestingAuthType;
private final String key = AuthenticatorKeys.computeKey(this);
/**
* The type of the entity requesting authentication.
*
* @since 1.5
*/
public enum RequestorType {
/**
* Entity requesting authentication is a HTTP proxy server.
*/
PROXY,
/**
* Entity requesting authentication is a HTTP origin server.
*/
SERVER
}
private void reset() {
requestingHost = null;
requestingSite = null;
requestingPort = -1;
requestingProtocol = null;
requestingPrompt = null;
requestingScheme = null;
requestingURL = null;
requestingAuthType = RequestorType.SERVER;
}
/**
* Sets the authenticator that will be used by the networking code
* when a proxy or an HTTP server asks for authentication.
* <p>
* First, if there is a security manager, its {@code checkPermission}
* method is called with a
* {@code NetPermission("setDefaultAuthenticator")} permission.
* This may result in a java.lang.SecurityException.
*
* @param a The authenticator to be set. If a is {@code null} then
* any previously set authenticator is removed.
*
* @throws SecurityException
* if a security manager exists and its
* {@code checkPermission} method doesn't allow
* setting the default authenticator.
*
* @see SecurityManager#checkPermission
* @see java.net.NetPermission
*/
public static synchronized void setDefault(Authenticator a) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
NetPermission setDefaultPermission
= new NetPermission("setDefaultAuthenticator");
sm.checkPermission(setDefaultPermission);
}
theAuthenticator = a;
}
/**
* Gets the default authenticator.
* First, if there is a security manager, its {@code checkPermission}
* method is called with a
* {@code NetPermission("requestPasswordAuthentication")} permission.
* This may result in a java.lang.SecurityException.
* Then the default authenticator, if set, is returned.
* Otherwise, {@code null} is returned.
*
* @return The default authenticator, if set, {@code null} otherwise.
*
* @throws SecurityException
* if a security manager exists and its
* {@code checkPermission} method doesn't allow
* requesting password authentication.
* @since 9
* @see SecurityManager#checkPermission
* @see java.net.NetPermission
*/
public static Authenticator getDefault() {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
NetPermission requestPermission
= new NetPermission("requestPasswordAuthentication");
sm.checkPermission(requestPermission);
}
return theAuthenticator;
}
/**
* Ask the authenticator that has been registered with the system
* for a password.
* <p>
* First, if there is a security manager, its {@code checkPermission}
* method is called with a
* {@code NetPermission("requestPasswordAuthentication")} permission.
* This may result in a java.lang.SecurityException.
*
* @param addr The InetAddress of the site requesting authorization,
* or null if not known.
* @param port the port for the requested connection
* @param protocol The protocol that's requesting the connection
* ({@link java.net.Authenticator#getRequestingProtocol()})
* @param prompt A prompt string for the user
* @param scheme The authentication scheme
*
* @return The username/password, or null if one can't be gotten.
*
* @throws SecurityException
* if a security manager exists and its
* {@code checkPermission} method doesn't allow
* the password authentication request.
*
* @see SecurityManager#checkPermission
* @see java.net.NetPermission
*/
public static PasswordAuthentication requestPasswordAuthentication(
InetAddress addr,
int port,
String protocol,
String prompt,
String scheme) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
NetPermission requestPermission
= new NetPermission("requestPasswordAuthentication");
sm.checkPermission(requestPermission);
}
Authenticator a = theAuthenticator;
if (a == null) {
return null;
} else {
synchronized(a) {
a.reset();
a.requestingSite = addr;
a.requestingPort = port;
a.requestingProtocol = protocol;
a.requestingPrompt = prompt;
a.requestingScheme = scheme;
return a.getPasswordAuthentication();
}
}
}
/**
* Ask the authenticator that has been registered with the system
* for a password. This is the preferred method for requesting a password
* because the hostname can be provided in cases where the InetAddress
* is not available.
* <p>
* First, if there is a security manager, its {@code checkPermission}
* method is called with a
* {@code NetPermission("requestPasswordAuthentication")} permission.
* This may result in a java.lang.SecurityException.
*
* @param host The hostname of the site requesting authentication.
* @param addr The InetAddress of the site requesting authentication,
* or null if not known.
* @param port the port for the requested connection.
* @param protocol The protocol that's requesting the connection
* ({@link java.net.Authenticator#getRequestingProtocol()})
* @param prompt A prompt string for the user which identifies the authentication realm.
* @param scheme The authentication scheme
*
* @return The username/password, or null if one can't be gotten.
*
* @throws SecurityException
* if a security manager exists and its
* {@code checkPermission} method doesn't allow
* the password authentication request.
*
* @see SecurityManager#checkPermission
* @see java.net.NetPermission
* @since 1.4
*/
public static PasswordAuthentication requestPasswordAuthentication(
String host,
InetAddress addr,
int port,
String protocol,
String prompt,
String scheme) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
NetPermission requestPermission
= new NetPermission("requestPasswordAuthentication");
sm.checkPermission(requestPermission);
}
Authenticator a = theAuthenticator;
if (a == null) {
return null;
} else {
synchronized(a) {
a.reset();
a.requestingHost = host;
a.requestingSite = addr;
a.requestingPort = port;
a.requestingProtocol = protocol;
a.requestingPrompt = prompt;
a.requestingScheme = scheme;
return a.getPasswordAuthentication();
}
}
}
/**
* Ask the authenticator that has been registered with the system
* for a password.
* <p>
* First, if there is a security manager, its {@code checkPermission}
* method is called with a
* {@code NetPermission("requestPasswordAuthentication")} permission.
* This may result in a java.lang.SecurityException.
*
* @param host The hostname of the site requesting authentication.
* @param addr The InetAddress of the site requesting authorization,
* or null if not known.
* @param port the port for the requested connection
* @param protocol The protocol that's requesting the connection
* ({@link java.net.Authenticator#getRequestingProtocol()})
* @param prompt A prompt string for the user
* @param scheme The authentication scheme
* @param url The requesting URL that caused the authentication
* @param reqType The type (server or proxy) of the entity requesting
* authentication.
*
* @return The username/password, or null if one can't be gotten.
*
* @throws SecurityException
* if a security manager exists and its
* {@code checkPermission} method doesn't allow
* the password authentication request.
*
* @see SecurityManager#checkPermission
* @see java.net.NetPermission
*
* @since 1.5
*/
public static PasswordAuthentication requestPasswordAuthentication(
String host,
InetAddress addr,
int port,
String protocol,
String prompt,
String scheme,
URL url,
RequestorType reqType) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
NetPermission requestPermission
= new NetPermission("requestPasswordAuthentication");
sm.checkPermission(requestPermission);
}
Authenticator a = theAuthenticator;
if (a == null) {
return null;
} else {
synchronized(a) {
a.reset();
a.requestingHost = host;
a.requestingSite = addr;
a.requestingPort = port;
a.requestingProtocol = protocol;
a.requestingPrompt = prompt;
a.requestingScheme = scheme;
a.requestingURL = url;
a.requestingAuthType = reqType;
return a.getPasswordAuthentication();
}
}
}
/**
* Ask the given {@code authenticator} for a password. If the given
* {@code authenticator} is null, the authenticator, if any, that has been
* registered with the system using {@link #setDefault(java.net.Authenticator)
* setDefault} is used.
* <p>
* First, if there is a security manager, its {@code checkPermission}
* method is called with a
* {@code NetPermission("requestPasswordAuthentication")} permission.
* This may result in a java.lang.SecurityException.
*
* @param authenticator the authenticator, or {@code null}.
* @param host The hostname of the site requesting authentication.
* @param addr The InetAddress of the site requesting authorization,
* or null if not known.
* @param port the port for the requested connection
* @param protocol The protocol that's requesting the connection
* ({@link java.net.Authenticator#getRequestingProtocol()})
* @param prompt A prompt string for the user
* @param scheme The authentication scheme
* @param url The requesting URL that caused the authentication
* @param reqType The type (server or proxy) of the entity requesting
* authentication.
*
* @return The username/password, or {@code null} if one can't be gotten.
*
* @throws SecurityException
* if a security manager exists and its
* {@code checkPermission} method doesn't allow
* the password authentication request.
*
* @see SecurityManager#checkPermission
* @see java.net.NetPermission
*
* @since 9
*/
public static PasswordAuthentication requestPasswordAuthentication(
Authenticator authenticator,
String host,
InetAddress addr,
int port,
String protocol,
String prompt,
String scheme,
URL url,
RequestorType reqType) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
NetPermission requestPermission
= new NetPermission("requestPasswordAuthentication");
sm.checkPermission(requestPermission);
}
Authenticator a = authenticator == null ? theAuthenticator : authenticator;
if (a == null) {
return null;
} else {
return a.requestPasswordAuthenticationInstance(host,
addr,
port,
protocol,
prompt,
scheme,
url,
reqType);
}
}
/**
* Ask this authenticator for a password.
*
* @param host The hostname of the site requesting authentication.
* @param addr The InetAddress of the site requesting authorization,
* or null if not known.
* @param port the port for the requested connection
* @param protocol The protocol that's requesting the connection
* ({@link java.net.Authenticator#getRequestingProtocol()})
* @param prompt A prompt string for the user
* @param scheme The authentication scheme
* @param url The requesting URL that caused the authentication
* @param reqType The type (server or proxy) of the entity requesting
* authentication.
*
* @return The username/password, or null if one can't be gotten
*
* @since 9
*/
public PasswordAuthentication
requestPasswordAuthenticationInstance(String host,
InetAddress addr,
int port,
String protocol,
String prompt,
String scheme,
URL url,
RequestorType reqType) {
synchronized (this) {
this.reset();
this.requestingHost = host;
this.requestingSite = addr;
this.requestingPort = port;
this.requestingProtocol = protocol;
this.requestingPrompt = prompt;
this.requestingScheme = scheme;
this.requestingURL = url;
this.requestingAuthType = reqType;
return this.getPasswordAuthentication();
}
}
/**
* Gets the {@code hostname} of the
* site or proxy requesting authentication, or {@code null}
* if not available.
*
* @return the hostname of the connection requiring authentication, or null
* if it's not available.
* @since 1.4
*/
protected final String getRequestingHost() {
return requestingHost;
}
/**
* Gets the {@code InetAddress} of the
* site requesting authorization, or {@code null}
* if not available.
*
* @return the InetAddress of the site requesting authorization, or null
* if it's not available.
*/
protected final InetAddress getRequestingSite() {
return requestingSite;
}
/**
* Gets the port number for the requested connection.
* @return an {@code int} indicating the
* port for the requested connection.
*/
protected final int getRequestingPort() {
return requestingPort;
}
/**
* Give the protocol that's requesting the connection. Often this
* will be based on a URL, but in a future JDK it could be, for
* example, "SOCKS" for a password-protected SOCKS5 firewall.
*
* @return the protocol, optionally followed by "/version", where
* version is a version number.
*
* @see java.net.URL#getProtocol()
*/
protected final String getRequestingProtocol() {
return requestingProtocol;
}
/**
* Gets the prompt string given by the requestor.
*
* @return the prompt string given by the requestor (realm for
* http requests)
*/
protected final String getRequestingPrompt() {
return requestingPrompt;
}
/**
* Gets the scheme of the requestor (the HTTP scheme
* for an HTTP firewall, for example).
*
* @return the scheme of the requestor
*
*/
protected final String getRequestingScheme() {
return requestingScheme;
}
/**
* Called when password authorization is needed. Subclasses should
* override the default implementation, which returns null.
* @return The PasswordAuthentication collected from the
* user, or null if none is provided.
*/
protected PasswordAuthentication getPasswordAuthentication() {
return null;
}
/**
* Returns the URL that resulted in this
* request for authentication.
*
* @since 1.5
*
* @return the requesting URL
*
*/
protected URL getRequestingURL () {
return requestingURL;
}
/**
* Returns whether the requestor is a Proxy or a Server.
*
* @since 1.5
*
* @return the authentication type of the requestor
*
*/
protected RequestorType getRequestorType () {
return requestingAuthType;
}
static String getKey(Authenticator a) {
return a.key;
}
static {
AuthenticatorKeys.setAuthenticatorKeyAccess(Authenticator::getKey);
}
}

View file

@ -0,0 +1,54 @@
/*
* Copyright (c) 1996, 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. 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 java.net;
/**
* Signals that an error occurred while attempting to bind a
* socket to a local address and port. Typically, the port is
* in use, or the requested local address could not be assigned.
*
* @since 1.1
*/
public class BindException extends SocketException {
private static final long serialVersionUID = -5945005768251722951L;
/**
* Constructs a new BindException with the specified detail
* message as to why the bind error occurred.
* A detail message is a String that gives a specific
* description of this error.
* @param msg the detail message
*/
public BindException(String msg) {
super(msg);
}
/**
* Construct a new BindException with no detailed message.
*/
public BindException() {}
}

View file

@ -0,0 +1,63 @@
/*
* Copyright (c) 2003, 2004, 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 java.net;
import java.io.OutputStream;
import java.io.IOException;
/**
* Represents channels for storing resources in the
* ResponseCache. Instances of such a class provide an
* OutputStream object which is called by protocol handlers to
* store the resource data into the cache, and also an abort() method
* which allows a cache store operation to be interrupted and
* abandoned. If an IOException is encountered while reading the
* response or writing to the cache, the current cache store operation
* will be aborted.
*
* @author Yingxian Wang
* @since 1.5
*/
public abstract class CacheRequest {
/**
* Returns an OutputStream to which the response body can be
* written.
*
* @return an OutputStream to which the response body can
* be written
* @throws IOException if an I/O error occurs while
* writing the response body
*/
public abstract OutputStream getBody() throws IOException;
/**
* Aborts the attempt to cache the response. If an IOException is
* encountered while reading the response or writing to the cache,
* the current cache store operation will be abandoned.
*/
public abstract void abort();
}

View file

@ -0,0 +1,64 @@
/*
* Copyright (c) 2003, 2004, 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 java.net;
import java.io.InputStream;
import java.util.Map;
import java.util.List;
import java.io.IOException;
/**
* Represent channels for retrieving resources from the
* ResponseCache. Instances of such a class provide an
* InputStream that returns the entity body, and also a
* getHeaders() method which returns the associated response headers.
*
* @author Yingxian Wang
* @since 1.5
*/
public abstract class CacheResponse {
/**
* Returns the response headers as a Map.
*
* @return An immutable Map from response header field names to
* lists of field values. The status line has null as its
* field name.
* @throws IOException if an I/O error occurs
* while getting the response headers
*/
public abstract Map<String, List<String>> getHeaders() throws IOException;
/**
* Returns the response body as an InputStream.
*
* @return an InputStream from which the response body can
* be accessed
* @throws IOException if an I/O error occurs while
* getting the response body
*/
public abstract InputStream getBody() throws IOException;
}

View file

@ -0,0 +1,54 @@
/*
* Copyright (c) 1996, 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. 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 java.net;
/**
* Signals that an error occurred while attempting to connect a
* socket to a remote address and port. Typically, the connection
* was refused remotely (e.g., no process is listening on the
* remote address/port).
*
* @since 1.1
*/
public class ConnectException extends SocketException {
private static final long serialVersionUID = 3831404271622369215L;
/**
* Constructs a new ConnectException with the specified detail
* message as to why the connect error occurred.
* A detail message is a String that gives a specific
* description of this error.
* @param msg the detail message
*/
public ConnectException(String msg) {
super(msg);
}
/**
* Construct a new ConnectException with no detailed message.
*/
public ConnectException() {}
}

View file

@ -0,0 +1,125 @@
/*
* Copyright (c) 1995, 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 java.net;
import java.io.IOException;
/**
* The abstract class {@code ContentHandler} is the superclass
* of all classes that read an {@code Object} from a
* {@code URLConnection}.
* <p>
* An application does not generally call the
* {@code getContent} method in this class directly. Instead, an
* application calls the {@code getContent} method in class
* {@code URL} or in {@code URLConnection}.
* The application's content handler factory (an instance of a class that
* implements the interface {@code ContentHandlerFactory} set up by a call to
* {@link URLConnection#setContentHandlerFactory(ContentHandlerFactory)
* setContentHandlerFactory} is called with a {@code String} giving the
* MIME type of the object being received on the socket. The factory returns an
* instance of a subclass of {@code ContentHandler}, and its
* {@code getContent} method is called to create the object.
* <p>
* If no content handler could be {@linkplain URLConnection#getContent() found},
* URLConnection will look for a content handler in a user-definable set of places.
* Users can define a vertical-bar delimited set of class prefixes
* to search through by defining the <i>{@link java.net.URLConnection#contentPathProp}</i>
* property. The class name must be of the form:
* <blockquote>
* <i>{package-prefix}.{major}.{minor}</i>
* <p>
* where <i>{major}.{minor}</i> is formed by taking the
* content-type string, replacing all slash characters with a
* {@code period} ('.'), and all other non-alphanumeric characters
* with the underscore character '{@code _}'. The alphanumeric
* characters are specifically the 26 uppercase ASCII letters
* '{@code A}' through '{@code Z}', the 26 lowercase ASCII
* letters '{@code a}' through '{@code z}', and the 10 ASCII
* digits '{@code 0}' through '{@code 9}'.
* <p>
* e.g.
* YoyoDyne.experimental.text.plain
* </blockquote>
* If no user-defined content handler is found, then the system
* tries to load a specific <i>content-type</i> handler from one
* of the built-in handlers, if one exists.
* <p>
* If the loading of the content handler class would be performed by
* a classloader that is outside of the delegation chain of the caller,
* the JVM will need the RuntimePermission "getClassLoader".
*
* @author James Gosling
* @see java.net.ContentHandler#getContent(java.net.URLConnection)
* @see java.net.ContentHandlerFactory
* @see java.net.URL#getContent()
* @see java.net.URLConnection
* @see java.net.URLConnection#getContent()
* @see java.net.URLConnection#setContentHandlerFactory(java.net.ContentHandlerFactory)
* @since 1.0
*/
public abstract class ContentHandler {
/**
* Given a URL connect stream positioned at the beginning of the
* representation of an object, this method reads that stream and
* creates an object from it.
*
* @param urlc a URL connection.
* @return the object read by the {@code ContentHandler}.
* @exception IOException if an I/O error occurs while reading the object.
*/
public abstract Object getContent(URLConnection urlc) throws IOException;
/**
* Given a URL connect stream positioned at the beginning of the
* representation of an object, this method reads that stream and
* creates an object that matches one of the types specified.
*
* The default implementation of this method should call
* {@link #getContent(URLConnection)}
* and screen the return type for a match of the suggested types.
*
* @param urlc a URL connection.
* @param classes an array of types requested
* @return the object read by the {@code ContentHandler} that is
* the first match of the suggested types or
* {@code null} if none of the requested are supported.
* @exception IOException if an I/O error occurs while reading the object.
* @since 1.3
*/
@SuppressWarnings("rawtypes")
public Object getContent(URLConnection urlc, Class[] classes) throws IOException {
Object obj = getContent(urlc);
for (Class<?> c : classes) {
if (c.isInstance(obj)) {
return obj;
}
}
return null;
}
}

View file

@ -0,0 +1,55 @@
/*
* Copyright (c) 1995, 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 java.net;
/**
* This interface defines a factory for content handlers. An
* implementation of this interface should map a MIME type into an
* instance of {@code ContentHandler}.
* <p>
* This interface is used by the {@code URLStreamHandler} class
* to create a {@code ContentHandler} for a MIME type.
*
* @author James Gosling
* @see java.net.ContentHandler
* @see java.net.URLStreamHandler
* @since 1.0
*/
public interface ContentHandlerFactory {
/**
* Creates a new {@code ContentHandler} to read an object from
* a {@code URLStreamHandler}.
*
* @param mimetype the MIME type for which a content handler is desired.
*
* @return a new {@code ContentHandler} to read an object from a
* {@code URLStreamHandler}.
* @see java.net.ContentHandler
* @see java.net.URLStreamHandler
*/
ContentHandler createContentHandler(String mimetype);
}

View file

@ -0,0 +1,150 @@
/*
* Copyright (c) 2003, 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 java.net;
import java.util.Map;
import java.util.List;
import java.io.IOException;
import sun.security.util.SecurityConstants;
/**
* A CookieHandler object provides a callback mechanism to hook up a
* HTTP state management policy implementation into the HTTP protocol
* handler. The HTTP state management mechanism specifies a way to
* create a stateful session with HTTP requests and responses.
*
* <p>A system-wide CookieHandler that to used by the HTTP protocol
* handler can be registered by doing a
* CookieHandler.setDefault(CookieHandler). The currently registered
* CookieHandler can be retrieved by calling
* CookieHandler.getDefault().
*
* For more information on HTTP state management, see <a
* href="http://www.ietf.org/rfc/rfc2965.txt"><i>RFC&nbsp;2965: HTTP
* State Management Mechanism</i></a>
*
* @author Yingxian Wang
* @since 1.5
*/
public abstract class CookieHandler {
/**
* The system-wide cookie handler that will apply cookies to the
* request headers and manage cookies from the response headers.
*
* @see setDefault(CookieHandler)
* @see getDefault()
*/
private static CookieHandler cookieHandler;
/**
* Gets the system-wide cookie handler.
*
* @return the system-wide cookie handler; A null return means
* there is no system-wide cookie handler currently set.
* @throws SecurityException
* If a security manager has been installed and it denies
* {@link NetPermission}{@code ("getCookieHandler")}
* @see #setDefault(CookieHandler)
*/
public static synchronized CookieHandler getDefault() {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(SecurityConstants.GET_COOKIEHANDLER_PERMISSION);
}
return cookieHandler;
}
/**
* Sets (or unsets) the system-wide cookie handler.
*
* Note: non-standard http protocol handlers may ignore this setting.
*
* @param cHandler The HTTP cookie handler, or
* {@code null} to unset.
* @throws SecurityException
* If a security manager has been installed and it denies
* {@link NetPermission}{@code ("setCookieHandler")}
* @see #getDefault()
*/
public static synchronized void setDefault(CookieHandler cHandler) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(SecurityConstants.SET_COOKIEHANDLER_PERMISSION);
}
cookieHandler = cHandler;
}
/**
* Gets all the applicable cookies from a cookie cache for the
* specified uri in the request header.
*
* <P>The {@code URI} passed as an argument specifies the intended use for
* the cookies. In particular the scheme should reflect whether the cookies
* will be sent over http, https or used in another context like javascript.
* The host part should reflect either the destination of the cookies or
* their origin in the case of javascript.</P>
* <P>It is up to the implementation to take into account the {@code URI} and
* the cookies attributes and security settings to determine which ones
* should be returned.</P>
*
* <P>HTTP protocol implementers should make sure that this method is
* called after all request headers related to choosing cookies
* are added, and before the request is sent.</P>
*
* @param uri a {@code URI} representing the intended use for the
* cookies
* @param requestHeaders - a Map from request header
* field names to lists of field values representing
* the current request headers
* @return an immutable map from state management headers, with
* field names "Cookie" or "Cookie2" to a list of
* cookies containing state information
*
* @throws IOException if an I/O error occurs
* @throws IllegalArgumentException if either argument is null
* @see #put(URI, Map)
*/
public abstract Map<String, List<String>>
get(URI uri, Map<String, List<String>> requestHeaders)
throws IOException;
/**
* Sets all the applicable cookies, examples are response header
* fields that are named Set-Cookie2, present in the response
* headers into a cookie cache.
*
* @param uri a {@code URI} where the cookies come from
* @param responseHeaders an immutable map from field names to
* lists of field values representing the response
* header fields returned
* @throws IOException if an I/O error occurs
* @throws IllegalArgumentException if either argument is null
* @see #get(URI, Map)
*/
public abstract void
put(URI uri, Map<String, List<String>> responseHeaders)
throws IOException;
}

View file

@ -0,0 +1,445 @@
/*
* Copyright (c) 2005, 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 java.net;
import java.util.Map;
import java.util.List;
import java.util.Collections;
import java.util.Comparator;
import java.io.IOException;
import sun.util.logging.PlatformLogger;
/**
* CookieManager provides a concrete implementation of {@link CookieHandler},
* which separates the storage of cookies from the policy surrounding accepting
* and rejecting cookies. A CookieManager is initialized with a {@link CookieStore}
* which manages storage, and a {@link CookiePolicy} object, which makes
* policy decisions on cookie acceptance/rejection.
*
* <p> The HTTP cookie management in java.net package looks like:
* <blockquote>
* <pre>{@code
* use
* CookieHandler <------- HttpURLConnection
* ^
* | impl
* | use
* CookieManager -------> CookiePolicy
* | use
* |--------> HttpCookie
* | ^
* | | use
* | use |
* |--------> CookieStore
* ^
* | impl
* |
* Internal in-memory implementation
* }</pre>
* <ul>
* <li>
* CookieHandler is at the core of cookie management. User can call
* CookieHandler.setDefault to set a concrete CookieHanlder implementation
* to be used.
* </li>
* <li>
* CookiePolicy.shouldAccept will be called by CookieManager.put to see whether
* or not one cookie should be accepted and put into cookie store. User can use
* any of three pre-defined CookiePolicy, namely ACCEPT_ALL, ACCEPT_NONE and
* ACCEPT_ORIGINAL_SERVER, or user can define his own CookiePolicy implementation
* and tell CookieManager to use it.
* </li>
* <li>
* CookieStore is the place where any accepted HTTP cookie is stored in.
* If not specified when created, a CookieManager instance will use an internal
* in-memory implementation. Or user can implements one and tell CookieManager
* to use it.
* </li>
* <li>
* Currently, only CookieStore.add(URI, HttpCookie) and CookieStore.get(URI)
* are used by CookieManager. Others are for completeness and might be needed
* by a more sophisticated CookieStore implementation, e.g. a NetscapeCookieStore.
* </li>
* </ul>
* </blockquote>
*
* <p>There're various ways user can hook up his own HTTP cookie management behavior, e.g.
* <blockquote>
* <ul>
* <li>Use CookieHandler.setDefault to set a brand new {@link CookieHandler} implementation
* <li>Let CookieManager be the default {@link CookieHandler} implementation,
* but implement user's own {@link CookieStore} and {@link CookiePolicy}
* and tell default CookieManager to use them:
* <blockquote><pre>
* // this should be done at the beginning of an HTTP session
* CookieHandler.setDefault(new CookieManager(new MyCookieStore(), new MyCookiePolicy()));
* </pre></blockquote>
* <li>Let CookieManager be the default {@link CookieHandler} implementation, but
* use customized {@link CookiePolicy}:
* <blockquote><pre>
* // this should be done at the beginning of an HTTP session
* CookieHandler.setDefault(new CookieManager());
* // this can be done at any point of an HTTP session
* ((CookieManager)CookieHandler.getDefault()).setCookiePolicy(new MyCookiePolicy());
* </pre></blockquote>
* </ul>
* </blockquote>
*
* <p>The implementation conforms to <a href="http://www.ietf.org/rfc/rfc2965.txt">RFC 2965</a>, section 3.3.
*
* @see CookiePolicy
* @author Edward Wang
* @since 1.6
*/
public class CookieManager extends CookieHandler
{
/* ---------------- Fields -------------- */
private CookiePolicy policyCallback;
private CookieStore cookieJar = null;
/* ---------------- Ctors -------------- */
/**
* Create a new cookie manager.
*
* <p>This constructor will create new cookie manager with default
* cookie store and accept policy. The effect is same as
* {@code CookieManager(null, null)}.
*/
public CookieManager() {
this(null, null);
}
/**
* Create a new cookie manager with specified cookie store and cookie policy.
*
* @param store a {@code CookieStore} to be used by cookie manager.
* if {@code null}, cookie manager will use a default one,
* which is an in-memory CookieStore implementation.
* @param cookiePolicy a {@code CookiePolicy} instance
* to be used by cookie manager as policy callback.
* if {@code null}, ACCEPT_ORIGINAL_SERVER will
* be used.
*/
public CookieManager(CookieStore store,
CookiePolicy cookiePolicy)
{
// use default cookie policy if not specify one
policyCallback = (cookiePolicy == null) ? CookiePolicy.ACCEPT_ORIGINAL_SERVER
: cookiePolicy;
// if not specify CookieStore to use, use default one
if (store == null) {
cookieJar = new InMemoryCookieStore();
} else {
cookieJar = store;
}
}
/* ---------------- Public operations -------------- */
/**
* To set the cookie policy of this cookie manager.
*
* <p> A instance of {@code CookieManager} will have
* cookie policy ACCEPT_ORIGINAL_SERVER by default. Users always
* can call this method to set another cookie policy.
*
* @param cookiePolicy the cookie policy. Can be {@code null}, which
* has no effects on current cookie policy.
*/
public void setCookiePolicy(CookiePolicy cookiePolicy) {
if (cookiePolicy != null) policyCallback = cookiePolicy;
}
/**
* To retrieve current cookie store.
*
* @return the cookie store currently used by cookie manager.
*/
public CookieStore getCookieStore() {
return cookieJar;
}
public Map<String, List<String>>
get(URI uri, Map<String, List<String>> requestHeaders)
throws IOException
{
// pre-condition check
if (uri == null || requestHeaders == null) {
throw new IllegalArgumentException("Argument is null");
}
// if there's no default CookieStore, no way for us to get any cookie
if (cookieJar == null)
return Map.of();
boolean secureLink = "https".equalsIgnoreCase(uri.getScheme());
List<HttpCookie> cookies = new java.util.ArrayList<>();
String path = uri.getPath();
if (path == null || path.isEmpty()) {
path = "/";
}
for (HttpCookie cookie : cookieJar.get(uri)) {
// apply path-matches rule (RFC 2965 sec. 3.3.4)
// and check for the possible "secure" tag (i.e. don't send
// 'secure' cookies over unsecure links)
if (pathMatches(path, cookie.getPath()) &&
(secureLink || !cookie.getSecure())) {
// Enforce httponly attribute
if (cookie.isHttpOnly()) {
String s = uri.getScheme();
if (!"http".equalsIgnoreCase(s) && !"https".equalsIgnoreCase(s)) {
continue;
}
}
// Let's check the authorize port list if it exists
String ports = cookie.getPortlist();
if (ports != null && !ports.isEmpty()) {
int port = uri.getPort();
if (port == -1) {
port = "https".equals(uri.getScheme()) ? 443 : 80;
}
if (isInPortList(ports, port)) {
cookies.add(cookie);
}
} else {
cookies.add(cookie);
}
}
}
// apply sort rule (RFC 2965 sec. 3.3.4)
List<String> cookieHeader = sortByPath(cookies);
return Map.of("Cookie", cookieHeader);
}
public void
put(URI uri, Map<String, List<String>> responseHeaders)
throws IOException
{
// pre-condition check
if (uri == null || responseHeaders == null) {
throw new IllegalArgumentException("Argument is null");
}
// if there's no default CookieStore, no need to remember any cookie
if (cookieJar == null)
return;
PlatformLogger logger = PlatformLogger.getLogger("java.net.CookieManager");
for (String headerKey : responseHeaders.keySet()) {
// RFC 2965 3.2.2, key must be 'Set-Cookie2'
// we also accept 'Set-Cookie' here for backward compatibility
if (headerKey == null
|| !(headerKey.equalsIgnoreCase("Set-Cookie2")
|| headerKey.equalsIgnoreCase("Set-Cookie")
)
)
{
continue;
}
for (String headerValue : responseHeaders.get(headerKey)) {
try {
List<HttpCookie> cookies;
try {
cookies = HttpCookie.parse(headerValue);
} catch (IllegalArgumentException e) {
// Bogus header, make an empty list and log the error
cookies = java.util.Collections.emptyList();
if (logger.isLoggable(PlatformLogger.Level.SEVERE)) {
logger.severe("Invalid cookie for " + uri + ": " + headerValue);
}
}
for (HttpCookie cookie : cookies) {
if (cookie.getPath() == null) {
// If no path is specified, then by default
// the path is the directory of the page/doc
String path = uri.getPath();
if (!path.endsWith("/")) {
int i = path.lastIndexOf('/');
if (i > 0) {
path = path.substring(0, i + 1);
} else {
path = "/";
}
}
cookie.setPath(path);
}
// As per RFC 2965, section 3.3.1:
// Domain Defaults to the effective request-host. (Note that because
// there is no dot at the beginning of effective request-host,
// the default Domain can only domain-match itself.)
if (cookie.getDomain() == null) {
String host = uri.getHost();
if (host != null && !host.contains("."))
host += ".local";
cookie.setDomain(host);
}
String ports = cookie.getPortlist();
if (ports != null) {
int port = uri.getPort();
if (port == -1) {
port = "https".equals(uri.getScheme()) ? 443 : 80;
}
if (ports.isEmpty()) {
// Empty port list means this should be restricted
// to the incoming URI port
cookie.setPortlist("" + port );
if (shouldAcceptInternal(uri, cookie)) {
cookieJar.add(uri, cookie);
}
} else {
// Only store cookies with a port list
// IF the URI port is in that list, as per
// RFC 2965 section 3.3.2
if (isInPortList(ports, port) &&
shouldAcceptInternal(uri, cookie)) {
cookieJar.add(uri, cookie);
}
}
} else {
if (shouldAcceptInternal(uri, cookie)) {
cookieJar.add(uri, cookie);
}
}
}
} catch (IllegalArgumentException e) {
// invalid set-cookie header string
// no-op
}
}
}
}
/* ---------------- Private operations -------------- */
// to determine whether or not accept this cookie
private boolean shouldAcceptInternal(URI uri, HttpCookie cookie) {
try {
return policyCallback.shouldAccept(uri, cookie);
} catch (Exception ignored) { // pretect against malicious callback
return false;
}
}
private static boolean isInPortList(String lst, int port) {
int i = lst.indexOf(',');
int val = -1;
while (i > 0) {
try {
val = Integer.parseInt(lst, 0, i, 10);
if (val == port) {
return true;
}
} catch (NumberFormatException numberFormatException) {
}
lst = lst.substring(i+1);
i = lst.indexOf(',');
}
if (!lst.isEmpty()) {
try {
val = Integer.parseInt(lst);
if (val == port) {
return true;
}
} catch (NumberFormatException numberFormatException) {
}
}
return false;
}
/*
* path-matches algorithm, as defined by RFC 2965
*/
private boolean pathMatches(String path, String pathToMatchWith) {
if (path == pathToMatchWith)
return true;
if (path == null || pathToMatchWith == null)
return false;
if (path.startsWith(pathToMatchWith))
return true;
return false;
}
/*
* sort cookies with respect to their path: those with more specific Path attributes
* precede those with less specific, as defined in RFC 2965 sec. 3.3.4
*/
private List<String> sortByPath(List<HttpCookie> cookies) {
Collections.sort(cookies, new CookiePathComparator());
List<String> cookieHeader = new java.util.ArrayList<>();
for (HttpCookie cookie : cookies) {
// Netscape cookie spec and RFC 2965 have different format of Cookie
// header; RFC 2965 requires a leading $Version="1" string while Netscape
// does not.
// The workaround here is to add a $Version="1" string in advance
if (cookies.indexOf(cookie) == 0 && cookie.getVersion() > 0) {
cookieHeader.add("$Version=\"1\"");
}
cookieHeader.add(cookie.toString());
}
return cookieHeader;
}
static class CookiePathComparator implements Comparator<HttpCookie> {
public int compare(HttpCookie c1, HttpCookie c2) {
if (c1 == c2) return 0;
if (c1 == null) return -1;
if (c2 == null) return 1;
// path rule only applies to the cookies with same name
if (!c1.getName().equals(c2.getName())) return 0;
// those with more specific Path attributes precede those with less specific
if (c1.getPath().startsWith(c2.getPath()))
return -1;
else if (c2.getPath().startsWith(c1.getPath()))
return 1;
else
return 0;
}
}
}

View file

@ -0,0 +1,78 @@
/*
* Copyright (c) 2005, 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 java.net;
/**
* CookiePolicy implementations decide which cookies should be accepted
* and which should be rejected. Three pre-defined policy implementations
* are provided, namely ACCEPT_ALL, ACCEPT_NONE and ACCEPT_ORIGINAL_SERVER.
*
* <p>See RFC 2965 sec. 3.3 and 7 for more detail.
*
* @author Edward Wang
* @since 1.6
*/
public interface CookiePolicy {
/**
* One pre-defined policy which accepts all cookies.
*/
public static final CookiePolicy ACCEPT_ALL = new CookiePolicy(){
public boolean shouldAccept(URI uri, HttpCookie cookie) {
return true;
}
};
/**
* One pre-defined policy which accepts no cookies.
*/
public static final CookiePolicy ACCEPT_NONE = new CookiePolicy(){
public boolean shouldAccept(URI uri, HttpCookie cookie) {
return false;
}
};
/**
* One pre-defined policy which only accepts cookies from original server.
*/
public static final CookiePolicy ACCEPT_ORIGINAL_SERVER = new CookiePolicy(){
public boolean shouldAccept(URI uri, HttpCookie cookie) {
if (uri == null || cookie == null)
return false;
return HttpCookie.domainMatches(cookie.getDomain(), uri.getHost());
}
};
/**
* Will be called to see whether or not this cookie should be accepted.
*
* @param uri the URI to consult accept policy with
* @param cookie the HttpCookie object in question
* @return {@code true} if this cookie should be accepted;
* otherwise, {@code false}
*/
public boolean shouldAccept(URI uri, HttpCookie cookie);
}

View file

@ -0,0 +1,129 @@
/*
* Copyright (c) 2005, 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 java.net;
import java.util.List;
import java.util.Map;
/**
* A CookieStore object represents a storage for cookie. Can store and retrieve
* cookies.
*
* <p>{@link CookieManager} will call {@code CookieStore.add} to save cookies
* for every incoming HTTP response, and call {@code CookieStore.get} to
* retrieve cookie for every outgoing HTTP request. A CookieStore
* is responsible for removing HttpCookie instances which have expired.
*
* @author Edward Wang
* @since 1.6
*/
public interface CookieStore {
/**
* Adds one HTTP cookie to the store. This is called for every
* incoming HTTP response.
*
* <p>A cookie to store may or may not be associated with an URI. If it
* is not associated with an URI, the cookie's domain and path attribute
* will indicate where it comes from. If it is associated with an URI and
* its domain and path attribute are not specified, given URI will indicate
* where this cookie comes from.
*
* <p>If a cookie corresponding to the given URI already exists,
* then it is replaced with the new one.
*
* @param uri the uri this cookie associated with.
* if {@code null}, this cookie will not be associated
* with an URI
* @param cookie the cookie to store
*
* @throws NullPointerException if {@code cookie} is {@code null}
*
* @see #get
*
*/
public void add(URI uri, HttpCookie cookie);
/**
* Retrieve cookies associated with given URI, or whose domain matches the
* given URI. Only cookies that have not expired are returned.
* This is called for every outgoing HTTP request.
*
* @return an immutable list of HttpCookie,
* return empty list if no cookies match the given URI
*
* @param uri the uri associated with the cookies to be returned
*
* @throws NullPointerException if {@code uri} is {@code null}
*
* @see #add
*
*/
public List<HttpCookie> get(URI uri);
/**
* Get all not-expired cookies in cookie store.
*
* @return an immutable list of http cookies;
* return empty list if there's no http cookie in store
*/
public List<HttpCookie> getCookies();
/**
* Get all URIs which identify the cookies in this cookie store.
*
* @return an immutable list of URIs;
* return empty list if no cookie in this cookie store
* is associated with an URI
*/
public List<URI> getURIs();
/**
* Remove a cookie from store.
*
* @param uri the uri this cookie associated with.
* if {@code null}, the cookie to be removed is not associated
* with an URI when added; if not {@code null}, the cookie
* to be removed is associated with the given URI when added.
* @param cookie the cookie to remove
*
* @return {@code true} if this store contained the specified cookie
*
* @throws NullPointerException if {@code cookie} is {@code null}
*/
public boolean remove(URI uri, HttpCookie cookie);
/**
* Remove all cookies in this cookie store.
*
* @return {@code true} if this store changed as a result of the call
*/
public boolean removeAll();
}

View file

@ -0,0 +1,388 @@
/*
* Copyright (c) 1995, 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 java.net;
/**
* This class represents a datagram packet.
* <p>
* Datagram packets are used to implement a connectionless packet
* delivery service. Each message is routed from one machine to
* another based solely on information contained within that packet.
* Multiple packets sent from one machine to another might be routed
* differently, and might arrive in any order. Packet delivery is
* not guaranteed.
*
* @author Pavani Diwanji
* @author Benjamin Renaud
* @since 1.0
*/
public final
class DatagramPacket {
/**
* Perform class initialization
*/
static {
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<>() {
public Void run() {
System.loadLibrary("net");
return null;
}
});
init();
}
/*
* The fields of this class are package-private since DatagramSocketImpl
* classes needs to access them.
*/
byte[] buf;
int offset;
int length;
int bufLength;
InetAddress address;
int port;
/**
* Constructs a {@code DatagramPacket} for receiving packets of
* length {@code length}, specifying an offset into the buffer.
* <p>
* The {@code length} argument must be less than or equal to
* {@code buf.length}.
*
* @param buf buffer for holding the incoming datagram.
* @param offset the offset for the buffer
* @param length the number of bytes to read.
*
* @since 1.2
*/
public DatagramPacket(byte buf[], int offset, int length) {
setData(buf, offset, length);
this.address = null;
this.port = -1;
}
/**
* Constructs a {@code DatagramPacket} for receiving packets of
* length {@code length}.
* <p>
* The {@code length} argument must be less than or equal to
* {@code buf.length}.
*
* @param buf buffer for holding the incoming datagram.
* @param length the number of bytes to read.
*/
public DatagramPacket(byte buf[], int length) {
this (buf, 0, length);
}
/**
* Constructs a datagram packet for sending packets of length
* {@code length} with offset {@code ioffset}to the
* specified port number on the specified host. The
* {@code length} argument must be less than or equal to
* {@code buf.length}.
*
* @param buf the packet data.
* @param offset the packet data offset.
* @param length the packet data length.
* @param address the destination address.
* @param port the destination port number.
* @see java.net.InetAddress
*
* @since 1.2
*/
public DatagramPacket(byte buf[], int offset, int length,
InetAddress address, int port) {
setData(buf, offset, length);
setAddress(address);
setPort(port);
}
/**
* Constructs a datagram packet for sending packets of length
* {@code length} with offset {@code ioffset}to the
* specified port number on the specified host. The
* {@code length} argument must be less than or equal to
* {@code buf.length}.
*
* @param buf the packet data.
* @param offset the packet data offset.
* @param length the packet data length.
* @param address the destination socket address.
* @throws IllegalArgumentException if address type is not supported
* @see java.net.InetAddress
*
* @since 1.4
*/
public DatagramPacket(byte buf[], int offset, int length, SocketAddress address) {
setData(buf, offset, length);
setSocketAddress(address);
}
/**
* Constructs a datagram packet for sending packets of length
* {@code length} to the specified port number on the specified
* host. The {@code length} argument must be less than or equal
* to {@code buf.length}.
*
* @param buf the packet data.
* @param length the packet length.
* @param address the destination address.
* @param port the destination port number.
* @see java.net.InetAddress
*/
public DatagramPacket(byte buf[], int length,
InetAddress address, int port) {
this(buf, 0, length, address, port);
}
/**
* Constructs a datagram packet for sending packets of length
* {@code length} to the specified port number on the specified
* host. The {@code length} argument must be less than or equal
* to {@code buf.length}.
*
* @param buf the packet data.
* @param length the packet length.
* @param address the destination address.
* @throws IllegalArgumentException if address type is not supported
* @since 1.4
* @see java.net.InetAddress
*/
public DatagramPacket(byte buf[], int length, SocketAddress address) {
this(buf, 0, length, address);
}
/**
* Returns the IP address of the machine to which this datagram is being
* sent or from which the datagram was received.
*
* @return the IP address of the machine to which this datagram is being
* sent or from which the datagram was received.
* @see java.net.InetAddress
* @see #setAddress(java.net.InetAddress)
*/
public synchronized InetAddress getAddress() {
return address;
}
/**
* Returns the port number on the remote host to which this datagram is
* being sent or from which the datagram was received.
*
* @return the port number on the remote host to which this datagram is
* being sent or from which the datagram was received.
* @see #setPort(int)
*/
public synchronized int getPort() {
return port;
}
/**
* Returns the data buffer. The data received or the data to be sent
* starts from the {@code offset} in the buffer,
* and runs for {@code length} long.
*
* @return the buffer used to receive or send data
* @see #setData(byte[], int, int)
*/
public synchronized byte[] getData() {
return buf;
}
/**
* Returns the offset of the data to be sent or the offset of the
* data received.
*
* @return the offset of the data to be sent or the offset of the
* data received.
*
* @since 1.2
*/
public synchronized int getOffset() {
return offset;
}
/**
* Returns the length of the data to be sent or the length of the
* data received.
*
* @return the length of the data to be sent or the length of the
* data received.
* @see #setLength(int)
*/
public synchronized int getLength() {
return length;
}
/**
* Set the data buffer for this packet. This sets the
* data, length and offset of the packet.
*
* @param buf the buffer to set for this packet
*
* @param offset the offset into the data
*
* @param length the length of the data
* and/or the length of the buffer used to receive data
*
* @exception NullPointerException if the argument is null
*
* @see #getData
* @see #getOffset
* @see #getLength
*
* @since 1.2
*/
public synchronized void setData(byte[] buf, int offset, int length) {
/* this will check to see if buf is null */
if (length < 0 || offset < 0 ||
(length + offset) < 0 ||
((length + offset) > buf.length)) {
throw new IllegalArgumentException("illegal length or offset");
}
this.buf = buf;
this.length = length;
this.bufLength = length;
this.offset = offset;
}
/**
* Sets the IP address of the machine to which this datagram
* is being sent.
* @param iaddr the {@code InetAddress}
* @since 1.1
* @see #getAddress()
*/
public synchronized void setAddress(InetAddress iaddr) {
address = iaddr;
}
/**
* Sets the port number on the remote host to which this datagram
* is being sent.
* @param iport the port number
* @since 1.1
* @see #getPort()
*/
public synchronized void setPort(int iport) {
if (iport < 0 || iport > 0xFFFF) {
throw new IllegalArgumentException("Port out of range:"+ iport);
}
port = iport;
}
/**
* Sets the SocketAddress (usually IP address + port number) of the remote
* host to which this datagram is being sent.
*
* @param address the {@code SocketAddress}
* @throws IllegalArgumentException if address is null or is a
* SocketAddress subclass not supported by this socket
*
* @since 1.4
* @see #getSocketAddress
*/
public synchronized void setSocketAddress(SocketAddress address) {
if (address == null || !(address instanceof InetSocketAddress))
throw new IllegalArgumentException("unsupported address type");
InetSocketAddress addr = (InetSocketAddress) address;
if (addr.isUnresolved())
throw new IllegalArgumentException("unresolved address");
setAddress(addr.getAddress());
setPort(addr.getPort());
}
/**
* Gets the SocketAddress (usually IP address + port number) of the remote
* host that this packet is being sent to or is coming from.
*
* @return the {@code SocketAddress}
* @since 1.4
* @see #setSocketAddress
*/
public synchronized SocketAddress getSocketAddress() {
return new InetSocketAddress(getAddress(), getPort());
}
/**
* Set the data buffer for this packet. With the offset of
* this DatagramPacket set to 0, and the length set to
* the length of {@code buf}.
*
* @param buf the buffer to set for this packet.
*
* @exception NullPointerException if the argument is null.
*
* @see #getLength
* @see #getData
*
* @since 1.1
*/
public synchronized void setData(byte[] buf) {
if (buf == null) {
throw new NullPointerException("null packet buffer");
}
this.buf = buf;
this.offset = 0;
this.length = buf.length;
this.bufLength = buf.length;
}
/**
* Set the length for this packet. The length of the packet is
* the number of bytes from the packet's data buffer that will be
* sent, or the number of bytes of the packet's data buffer that
* will be used for receiving data. The length must be lesser or
* equal to the offset plus the length of the packet's buffer.
*
* @param length the length to set for this packet.
*
* @exception IllegalArgumentException if the length is negative
* of if the length is greater than the packet's data buffer
* length.
*
* @see #getLength
* @see #setData
*
* @since 1.1
*/
public synchronized void setLength(int length) {
if ((length + offset) > buf.length || length < 0 ||
(length + offset) < 0) {
throw new IllegalArgumentException("illegal length");
}
this.length = length;
this.bufLength = this.length;
}
/**
* Perform class load-time initializations.
*/
private static native void init();
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,387 @@
/*
* 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
* 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 java.net;
import java.io.FileDescriptor;
import java.io.IOException;
import java.util.Set;
/**
* Abstract datagram and multicast socket implementation base class.
* @author Pavani Diwanji
* @since 1.1
*/
public abstract class DatagramSocketImpl implements SocketOptions {
/**
* The local port number.
*/
protected int localPort;
/**
* The file descriptor object.
*/
protected FileDescriptor fd;
/**
* The DatagramSocket or MulticastSocket
* that owns this impl
*/
DatagramSocket socket;
void setDatagramSocket(DatagramSocket socket) {
this.socket = socket;
}
DatagramSocket getDatagramSocket() {
return socket;
}
int dataAvailable() {
// default impl returns zero, which disables the calling
// functionality
return 0;
}
/**
* Creates a datagram socket.
* @exception SocketException if there is an error in the
* underlying protocol, such as a TCP error.
*/
protected abstract void create() throws SocketException;
/**
* Binds a datagram socket to a local port and address.
* @param lport the local port
* @param laddr the local address
* @exception SocketException if there is an error in the
* underlying protocol, such as a TCP error.
*/
protected abstract void bind(int lport, InetAddress laddr) throws SocketException;
/**
* Sends a datagram packet. The packet contains the data and the
* destination address to send the packet to.
* @param p the packet to be sent.
* @exception IOException if an I/O exception occurs while sending the
* datagram packet.
* @exception PortUnreachableException may be thrown if the socket is connected
* to a currently unreachable destination. Note, there is no guarantee that
* the exception will be thrown.
*/
protected abstract void send(DatagramPacket p) throws IOException;
/**
* Connects a datagram socket to a remote destination. This associates the remote
* address with the local socket so that datagrams may only be sent to this destination
* and received from this destination. This may be overridden to call a native
* system connect.
*
* <p>If the remote destination to which the socket is connected does not
* exist, or is otherwise unreachable, and if an ICMP destination unreachable
* packet has been received for that address, then a subsequent call to
* send or receive may throw a PortUnreachableException.
* Note, there is no guarantee that the exception will be thrown.
* @param address the remote InetAddress to connect to
* @param port the remote port number
* @exception SocketException may be thrown if the socket cannot be
* connected to the remote destination
* @since 1.4
*/
protected void connect(InetAddress address, int port) throws SocketException {}
/**
* Disconnects a datagram socket from its remote destination.
* @since 1.4
*/
protected void disconnect() {}
/**
* Peek at the packet to see who it is from. Updates the specified {@code InetAddress}
* to the address which the packet came from.
* @param i an InetAddress object
* @return the port number which the packet came from.
* @exception IOException if an I/O exception occurs
* @exception PortUnreachableException may be thrown if the socket is connected
* to a currently unreachable destination. Note, there is no guarantee that the
* exception will be thrown.
*/
protected abstract int peek(InetAddress i) throws IOException;
/**
* Peek at the packet to see who it is from. The data is copied into the specified
* {@code DatagramPacket}. The data is returned,
* but not consumed, so that a subsequent peekData/receive operation
* will see the same data.
* @param p the Packet Received.
* @return the port number which the packet came from.
* @exception IOException if an I/O exception occurs
* @exception PortUnreachableException may be thrown if the socket is connected
* to a currently unreachable destination. Note, there is no guarantee that the
* exception will be thrown.
* @since 1.4
*/
protected abstract int peekData(DatagramPacket p) throws IOException;
/**
* Receive the datagram packet.
* @param p the Packet Received.
* @exception IOException if an I/O exception occurs
* while receiving the datagram packet.
* @exception PortUnreachableException may be thrown if the socket is connected
* to a currently unreachable destination. Note, there is no guarantee that the
* exception will be thrown.
*/
protected abstract void receive(DatagramPacket p) throws IOException;
/**
* Set the TTL (time-to-live) option.
* @param ttl a byte specifying the TTL value
*
* @deprecated use setTimeToLive instead.
* @exception IOException if an I/O exception occurs while setting
* the time-to-live option.
* @see #getTTL()
*/
@Deprecated
protected abstract void setTTL(byte ttl) throws IOException;
/**
* Retrieve the TTL (time-to-live) option.
*
* @exception IOException if an I/O exception occurs
* while retrieving the time-to-live option
* @deprecated use getTimeToLive instead.
* @return a byte representing the TTL value
* @see #setTTL(byte)
*/
@Deprecated
protected abstract byte getTTL() throws IOException;
/**
* Set the TTL (time-to-live) option.
* @param ttl an {@code int} specifying the time-to-live value
* @exception IOException if an I/O exception occurs
* while setting the time-to-live option.
* @see #getTimeToLive()
*/
protected abstract void setTimeToLive(int ttl) throws IOException;
/**
* Retrieve the TTL (time-to-live) option.
* @exception IOException if an I/O exception occurs
* while retrieving the time-to-live option
* @return an {@code int} representing the time-to-live value
* @see #setTimeToLive(int)
*/
protected abstract int getTimeToLive() throws IOException;
/**
* Join the multicast group.
* @param inetaddr multicast address to join.
* @exception IOException if an I/O exception occurs
* while joining the multicast group.
*/
protected abstract void join(InetAddress inetaddr) throws IOException;
/**
* Leave the multicast group.
* @param inetaddr multicast address to leave.
* @exception IOException if an I/O exception occurs
* while leaving the multicast group.
*/
protected abstract void leave(InetAddress inetaddr) throws IOException;
/**
* Join the multicast group.
* @param mcastaddr address to join.
* @param netIf specifies the local interface to receive multicast
* datagram packets
* @throws IOException if an I/O exception occurs while joining
* the multicast group
* @since 1.4
*/
protected abstract void joinGroup(SocketAddress mcastaddr,
NetworkInterface netIf)
throws IOException;
/**
* Leave the multicast group.
* @param mcastaddr address to leave.
* @param netIf specified the local interface to leave the group at
* @throws IOException if an I/O exception occurs while leaving
* the multicast group
* @since 1.4
*/
protected abstract void leaveGroup(SocketAddress mcastaddr,
NetworkInterface netIf)
throws IOException;
/**
* Close the socket.
*/
protected abstract void close();
/**
* Gets the local port.
* @return an {@code int} representing the local port value
*/
protected int getLocalPort() {
return localPort;
}
/**
* Gets the datagram socket file descriptor.
* @return a {@code FileDescriptor} object representing the datagram socket
* file descriptor
*/
protected FileDescriptor getFileDescriptor() {
return fd;
}
/**
* Called to set a socket option.
*
* @param <T> The type of the socket option value
* @param name The socket option
*
* @param value The value of the socket option. A value of {@code null}
* may be valid for some options.
*
* @throws UnsupportedOperationException if the DatagramSocketImpl does not
* support the option
*
* @throws NullPointerException if name is {@code null}
* @throws IOException if an I/O problem occurs while attempting to set the option
* @since 9
*/
protected <T> void setOption(SocketOption<T> name, T value) throws IOException {
if (name == StandardSocketOptions.SO_SNDBUF) {
setOption(SocketOptions.SO_SNDBUF, value);
} else if (name == StandardSocketOptions.SO_RCVBUF) {
setOption(SocketOptions.SO_RCVBUF, value);
} else if (name == StandardSocketOptions.SO_REUSEADDR) {
setOption(SocketOptions.SO_REUSEADDR, value);
} else if (name == StandardSocketOptions.SO_REUSEPORT &&
supportedOptions().contains(name)) {
setOption(SocketOptions.SO_REUSEPORT, value);
} else if (name == StandardSocketOptions.IP_TOS) {
setOption(SocketOptions.IP_TOS, value);
} else if (name == StandardSocketOptions.IP_MULTICAST_IF &&
(getDatagramSocket() instanceof MulticastSocket)) {
setOption(SocketOptions.IP_MULTICAST_IF2, value);
} else if (name == StandardSocketOptions.IP_MULTICAST_TTL &&
(getDatagramSocket() instanceof MulticastSocket)) {
if (! (value instanceof Integer)) {
throw new IllegalArgumentException("not an integer");
}
setTimeToLive((Integer)value);
} else if (name == StandardSocketOptions.IP_MULTICAST_LOOP &&
(getDatagramSocket() instanceof MulticastSocket)) {
setOption(SocketOptions.IP_MULTICAST_LOOP, value);
} else {
throw new UnsupportedOperationException("unsupported option");
}
}
/**
* Called to get a socket option.
*
* @return the socket option
* @param <T> The type of the socket option value
* @param name The socket option
*
* @throws UnsupportedOperationException if the DatagramSocketImpl does not
* support the option
*
* @throws NullPointerException if name is {@code null}
* @throws IOException if an I/O problem occurs while attempting to set the option
*
* @since 9
*/
@SuppressWarnings("unchecked")
protected <T> T getOption(SocketOption<T> name) throws IOException {
if (name == StandardSocketOptions.SO_SNDBUF) {
return (T) getOption(SocketOptions.SO_SNDBUF);
} else if (name == StandardSocketOptions.SO_RCVBUF) {
return (T) getOption(SocketOptions.SO_RCVBUF);
} else if (name == StandardSocketOptions.SO_REUSEADDR) {
return (T) getOption(SocketOptions.SO_REUSEADDR);
} else if (name == StandardSocketOptions.SO_REUSEPORT &&
supportedOptions().contains(name)) {
return (T) getOption(SocketOptions.SO_REUSEPORT);
} else if (name == StandardSocketOptions.IP_TOS) {
return (T) getOption(SocketOptions.IP_TOS);
} else if (name == StandardSocketOptions.IP_MULTICAST_IF &&
(getDatagramSocket() instanceof MulticastSocket)) {
return (T) getOption(SocketOptions.IP_MULTICAST_IF2);
} else if (name == StandardSocketOptions.IP_MULTICAST_TTL &&
(getDatagramSocket() instanceof MulticastSocket)) {
Integer ttl = getTimeToLive();
return (T)ttl;
} else if (name == StandardSocketOptions.IP_MULTICAST_LOOP &&
(getDatagramSocket() instanceof MulticastSocket)) {
return (T) getOption(SocketOptions.IP_MULTICAST_LOOP);
} else {
throw new UnsupportedOperationException("unsupported option");
}
}
private static final Set<SocketOption<?>> dgSocketOptions;
private static final Set<SocketOption<?>> mcSocketOptions;
static {
dgSocketOptions = Set.of(StandardSocketOptions.SO_SNDBUF,
StandardSocketOptions.SO_RCVBUF,
StandardSocketOptions.SO_REUSEADDR,
StandardSocketOptions.IP_TOS);
mcSocketOptions = Set.of(StandardSocketOptions.SO_SNDBUF,
StandardSocketOptions.SO_RCVBUF,
StandardSocketOptions.SO_REUSEADDR,
StandardSocketOptions.IP_TOS,
StandardSocketOptions.IP_MULTICAST_IF,
StandardSocketOptions.IP_MULTICAST_TTL,
StandardSocketOptions.IP_MULTICAST_LOOP);
}
/**
* Returns a set of SocketOptions supported by this impl
* and by this impl's socket (DatagramSocket or MulticastSocket)
*
* @return a Set of SocketOptions
*
* @since 9
*/
protected Set<SocketOption<?>> supportedOptions() {
if (getDatagramSocket() instanceof MulticastSocket) {
return mcSocketOptions;
} else {
return dgSocketOptions;
}
}
}

View file

@ -0,0 +1,46 @@
/*
* Copyright (c) 1999, 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 java.net;
/**
* This interface defines a factory for datagram socket implementations. It
* is used by the classes {@code DatagramSocket} to create actual socket
* implementations.
*
* @author Yingxian Wang
* @see java.net.DatagramSocket
* @since 1.3
*/
public
interface DatagramSocketImplFactory {
/**
* Creates a new {@code DatagramSocketImpl} instance.
*
* @return a new instance of {@code DatagramSocketImpl}.
* @see java.net.DatagramSocketImpl
*/
DatagramSocketImpl createDatagramSocketImpl();
}

View file

@ -0,0 +1,44 @@
/*
* 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 java.net;
/**
* A simple interface which provides a mechanism to map
* between a file name and a MIME type string.
*
* @author Steven B. Byrne
* @since 1.1
*/
public interface FileNameMap {
/**
* Gets the MIME type for the specified file name.
* @param fileName the specified file name
* @return a {@code String} indicating the MIME
* type for the specified file name.
*/
public String getContentTypeFor(String fileName);
}

View file

@ -0,0 +1,283 @@
/*
* 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. 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 java.net;
import java.net.*;
import java.util.Formatter;
import java.util.Locale;
import sun.net.util.IPAddressUtil;
/**
* Parses a string containing a host/domain name and port range
*/
class HostPortrange {
String hostname;
String scheme;
int[] portrange;
boolean wildcard;
boolean literal;
boolean ipv6, ipv4;
static final int PORT_MIN = 0;
static final int PORT_MAX = (1 << 16) -1;
boolean equals(HostPortrange that) {
return this.hostname.equals(that.hostname)
&& this.portrange[0] == that.portrange[0]
&& this.portrange[1] == that.portrange[1]
&& this.wildcard == that.wildcard
&& this.literal == that.literal;
}
public int hashCode() {
return hostname.hashCode() + portrange[0] + portrange[1];
}
HostPortrange(String scheme, String str) {
// Parse the host name. A name has up to three components, the
// hostname, a port number, or two numbers representing a port
// range. "www.sun.com:8080-9090" is a valid host name.
// With IPv6 an address can be 2010:836B:4179::836B:4179
// An IPv6 address needs to be enclose in []
// For ex: [2010:836B:4179::836B:4179]:8080-9090
// Refer to RFC 2732 for more information.
// first separate string into two fields: hoststr, portstr
String hoststr, portstr = null;
this.scheme = scheme;
// check for IPv6 address
if (str.charAt(0) == '[') {
ipv6 = literal = true;
int rb = str.indexOf(']');
if (rb != -1) {
hoststr = str.substring(1, rb);
} else {
throw new IllegalArgumentException("invalid IPv6 address: " + str);
}
int sep = str.indexOf(':', rb + 1);
if (sep != -1 && str.length() > sep) {
portstr = str.substring(sep + 1);
}
// need to normalize hoststr now
byte[] ip = IPAddressUtil.textToNumericFormatV6(hoststr);
if (ip == null) {
throw new IllegalArgumentException("illegal IPv6 address");
}
StringBuilder sb = new StringBuilder();
Formatter formatter = new Formatter(sb, Locale.US);
formatter.format("%02x%02x:%02x%02x:%02x%02x:%02x"
+ "%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6], ip[7], ip[8],
ip[9], ip[10], ip[11], ip[12], ip[13], ip[14], ip[15]);
hostname = sb.toString();
} else {
// not IPv6 therefore ':' is the port separator
int sep = str.indexOf(':');
if (sep != -1 && str.length() > sep) {
hoststr = str.substring(0, sep);
portstr = str.substring(sep + 1);
} else {
hoststr = sep == -1 ? str : str.substring(0, sep);
}
// is this a domain wildcard specification?
if (hoststr.lastIndexOf('*') > 0) {
throw new IllegalArgumentException("invalid host wildcard specification");
} else if (hoststr.startsWith("*")) {
wildcard = true;
if (hoststr.equals("*")) {
hoststr = "";
} else if (hoststr.startsWith("*.")) {
hoststr = toLowerCase(hoststr.substring(1));
} else {
throw new IllegalArgumentException("invalid host wildcard specification");
}
} else {
// check if ipv4 (if rightmost label a number)
// The normal way to specify ipv4 is 4 decimal labels
// but actually three, two or single label formats valid also
// So, we recognise ipv4 by just testing the rightmost label
// being a number.
int lastdot = hoststr.lastIndexOf('.');
if (lastdot != -1 && (hoststr.length() > 1)) {
boolean ipv4 = true;
for (int i = lastdot + 1, len = hoststr.length(); i < len; i++) {
char c = hoststr.charAt(i);
if (c < '0' || c > '9') {
ipv4 = false;
break;
}
}
this.ipv4 = this.literal = ipv4;
if (ipv4) {
byte[] ip = IPAddressUtil.textToNumericFormatV4(hoststr);
if (ip == null) {
throw new IllegalArgumentException("illegal IPv4 address");
}
StringBuilder sb = new StringBuilder();
Formatter formatter = new Formatter(sb, Locale.US);
formatter.format("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
hoststr = sb.toString();
} else {
// regular domain name
hoststr = toLowerCase(hoststr);
}
}
}
hostname = hoststr;
}
try {
portrange = parsePort(portstr);
} catch (Exception e) {
throw new IllegalArgumentException("invalid port range: " + portstr);
}
}
static final int CASE_DIFF = 'A' - 'a';
/**
* Convert to lower case, and check that all chars are ascii
* alphanumeric, '-' or '.' only.
*/
static String toLowerCase(String s) {
int len = s.length();
StringBuilder sb = null;
for (int i=0; i<len; i++) {
char c = s.charAt(i);
if ((c >= 'a' && c <= 'z') || (c == '.')) {
if (sb != null)
sb.append(c);
} else if ((c >= '0' && c <= '9') || (c == '-')) {
if (sb != null)
sb.append(c);
} else if (c >= 'A' && c <= 'Z') {
if (sb == null) {
sb = new StringBuilder(len);
sb.append(s, 0, i);
}
sb.append((char)(c - CASE_DIFF));
} else {
throw new IllegalArgumentException("Invalid characters in hostname");
}
}
return sb == null ? s : sb.toString();
}
public boolean literal() {
return literal;
}
public boolean ipv4Literal() {
return ipv4;
}
public boolean ipv6Literal() {
return ipv6;
}
public String hostname() {
return hostname;
}
public int[] portrange() {
return portrange;
}
/**
* returns true if the hostname part started with *
* hostname returns the remaining part of the host component
* eg "*.foo.com" -> ".foo.com" or "*" -> ""
*
* @return
*/
public boolean wildcard() {
return wildcard;
}
// these shouldn't leak outside the implementation
static final int[] HTTP_PORT = {80, 80};
static final int[] HTTPS_PORT = {443, 443};
static final int[] NO_PORT = {-1, -1};
int[] defaultPort() {
if (scheme.equals("http")) {
return HTTP_PORT;
} else if (scheme.equals("https")) {
return HTTPS_PORT;
}
return NO_PORT;
}
int[] parsePort(String port)
{
if (port == null || port.equals("")) {
return defaultPort();
}
if (port.equals("*")) {
return new int[] {PORT_MIN, PORT_MAX};
}
try {
int dash = port.indexOf('-');
if (dash == -1) {
int p = Integer.parseInt(port);
return new int[] {p, p};
} else {
String low = port.substring(0, dash);
String high = port.substring(dash+1);
int l,h;
if (low.equals("")) {
l = PORT_MIN;
} else {
l = Integer.parseInt(low);
}
if (high.equals("")) {
h = PORT_MAX;
} else {
h = Integer.parseInt(high);
}
if (l < 0 || h < 0 || h<l) {
return defaultPort();
}
return new int[] {l, h};
}
} catch (IllegalArgumentException e) {
return defaultPort();
}
}
}

View file

@ -0,0 +1,210 @@
/*
* Copyright (c) 2010, 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 java.net;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* Basic SocketImpl that relies on the internal HTTP protocol handler
* implementation to perform the HTTP tunneling and authentication. The
* sockets impl is swapped out and replaced with the socket from the HTTP
* handler after the tunnel is successfully setup.
*
* @since 1.8
*/
/*package*/ class HttpConnectSocketImpl extends PlainSocketImpl {
private static final String httpURLClazzStr =
"sun.net.www.protocol.http.HttpURLConnection";
private static final String netClientClazzStr = "sun.net.NetworkClient";
private static final String doTunnelingStr = "doTunneling";
private static final Field httpField;
private static final Field serverSocketField;
private static final Method doTunneling;
private final String server;
private InetSocketAddress external_address;
private HashMap<Integer, Object> optionsMap = new HashMap<>();
static {
try {
Class<?> httpClazz = Class.forName(httpURLClazzStr, true, null);
httpField = httpClazz.getDeclaredField("http");
doTunneling = httpClazz.getDeclaredMethod(doTunnelingStr);
Class<?> netClientClazz = Class.forName(netClientClazzStr, true, null);
serverSocketField = netClientClazz.getDeclaredField("serverSocket");
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<>() {
public Void run() {
httpField.setAccessible(true);
serverSocketField.setAccessible(true);
return null;
}
});
} catch (ReflectiveOperationException x) {
throw new InternalError("Should not reach here", x);
}
}
HttpConnectSocketImpl(String server, int port) {
this.server = server;
this.port = port;
}
HttpConnectSocketImpl(Proxy proxy) {
SocketAddress a = proxy.address();
if ( !(a instanceof InetSocketAddress) )
throw new IllegalArgumentException("Unsupported address type");
InetSocketAddress ad = (InetSocketAddress) a;
server = ad.getHostString();
port = ad.getPort();
}
@Override
protected void connect(SocketAddress endpoint, int timeout)
throws IOException
{
if (endpoint == null || !(endpoint instanceof InetSocketAddress))
throw new IllegalArgumentException("Unsupported address type");
final InetSocketAddress epoint = (InetSocketAddress)endpoint;
final String destHost = epoint.isUnresolved() ? epoint.getHostName()
: epoint.getAddress().getHostAddress();
final int destPort = epoint.getPort();
SecurityManager security = System.getSecurityManager();
if (security != null)
security.checkConnect(destHost, destPort);
// Connect to the HTTP proxy server
String urlString = "http://" + destHost + ":" + destPort;
Socket httpSocket = privilegedDoTunnel(urlString, timeout);
// Success!
external_address = epoint;
// close the original socket impl and release its descriptor
close();
// update the Sockets impl to the impl from the http Socket
AbstractPlainSocketImpl psi = (AbstractPlainSocketImpl) httpSocket.impl;
this.getSocket().impl = psi;
// best effort is made to try and reset options previously set
Set<Map.Entry<Integer,Object>> options = optionsMap.entrySet();
try {
for(Map.Entry<Integer,Object> entry : options) {
psi.setOption(entry.getKey(), entry.getValue());
}
} catch (IOException x) { /* gulp! */ }
}
@Override
public void setOption(int opt, Object val) throws SocketException {
super.setOption(opt, val);
if (external_address != null)
return; // we're connected, just return
// store options so that they can be re-applied to the impl after connect
optionsMap.put(opt, val);
}
private Socket privilegedDoTunnel(final String urlString,
final int timeout)
throws IOException
{
try {
return java.security.AccessController.doPrivileged(
new java.security.PrivilegedExceptionAction<>() {
public Socket run() throws IOException {
return doTunnel(urlString, timeout);
}
});
} catch (java.security.PrivilegedActionException pae) {
throw (IOException) pae.getException();
}
}
private Socket doTunnel(String urlString, int connectTimeout)
throws IOException
{
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(server, port));
URL destURL = new URL(urlString);
HttpURLConnection conn = (HttpURLConnection) destURL.openConnection(proxy);
conn.setConnectTimeout(connectTimeout);
conn.setReadTimeout(this.timeout);
conn.connect();
doTunneling(conn);
try {
Object httpClient = httpField.get(conn);
return (Socket) serverSocketField.get(httpClient);
} catch (IllegalAccessException x) {
throw new InternalError("Should not reach here", x);
}
}
private void doTunneling(HttpURLConnection conn) {
try {
doTunneling.invoke(conn);
} catch (ReflectiveOperationException x) {
throw new InternalError("Should not reach here", x);
}
}
@Override
protected InetAddress getInetAddress() {
if (external_address != null)
return external_address.getAddress();
else
return super.getInetAddress();
}
@Override
protected int getPort() {
if (external_address != null)
return external_address.getPort();
else
return super.getPort();
}
@Override
protected int getLocalPort() {
if (socket != null)
return super.getLocalPort();
if (external_address != null)
return external_address.getPort();
else
return super.getLocalPort();
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,99 @@
/*
* Copyright (c) 2004, 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 java.net;
import java.io.IOException;
/**
* Thrown to indicate that a HTTP request needs to be retried
* but cannot be retried automatically, due to streaming mode
* being enabled.
*
* @author Michael McMahon
* @since 1.5
*/
public
class HttpRetryException extends IOException {
private static final long serialVersionUID = -9186022286469111381L;
private int responseCode;
private String location;
/**
* Constructs a new {@code HttpRetryException} from the
* specified response code and exception detail message
*
* @param detail the detail message.
* @param code the HTTP response code from server.
*/
public HttpRetryException(String detail, int code) {
super(detail);
responseCode = code;
}
/**
* Constructs a new {@code HttpRetryException} with detail message
* responseCode and the contents of the Location response header field.
*
* @param detail the detail message.
* @param code the HTTP response code from server.
* @param location the URL to be redirected to
*/
public HttpRetryException(String detail, int code, String location) {
super (detail);
responseCode = code;
this.location = location;
}
/**
* Returns the http response code
*
* @return The http response code.
*/
public int responseCode() {
return responseCode;
}
/**
* Returns a string explaining why the http request could
* not be retried.
*
* @return The reason string
*/
public String getReason() {
return super.getMessage();
}
/**
* Returns the value of the Location header field if the
* error resulted from redirection.
*
* @return The location string
*/
public String getLocation() {
return location;
}
}

View file

@ -0,0 +1,864 @@
/*
* 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
* 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 java.net;
import java.io.InputStream;
import java.io.IOException;
import java.security.Permission;
import java.util.Date;
/**
* A URLConnection with support for HTTP-specific features. See
* <A HREF="http://www.w3.org/pub/WWW/Protocols/"> the spec </A> for
* details.
* <p>
*
* Each HttpURLConnection instance is used to make a single request
* but the underlying network connection to the HTTP server may be
* transparently shared by other instances. Calling the close() methods
* on the InputStream or OutputStream of an HttpURLConnection
* after a request may free network resources associated with this
* instance but has no effect on any shared persistent connection.
* Calling the disconnect() method may close the underlying socket
* if a persistent connection is otherwise idle at that time.
*
* <P>The HTTP protocol handler has a few settings that can be accessed through
* System Properties. This covers
* <a href="doc-files/net-properties.html#Proxies">Proxy settings</a> as well as
* <a href="doc-files/net-properties.html#MiscHTTP"> various other settings</a>.
* </P>
* <p>
* <b>Security permissions</b>
* <p>
* If a security manager is installed, and if a method is called which results in an
* attempt to open a connection, the caller must possess either:
* <ul><li>a "connect" {@link SocketPermission} to the host/port combination of the
* destination URL or</li>
* <li>a {@link URLPermission} that permits this request.</li>
* </ul><p>
* If automatic redirection is enabled, and this request is redirected to another
* destination, then the caller must also have permission to connect to the
* redirected host/URL.
*
* @see java.net.HttpURLConnection#disconnect()
* @since 1.1
*/
public abstract class HttpURLConnection extends URLConnection {
/* instance variables */
/**
* The HTTP method (GET,POST,PUT,etc.).
*/
protected String method = "GET";
/**
* The chunk-length when using chunked encoding streaming mode for output.
* A value of {@code -1} means chunked encoding is disabled for output.
* @since 1.5
*/
protected int chunkLength = -1;
/**
* The fixed content-length when using fixed-length streaming mode.
* A value of {@code -1} means fixed-length streaming mode is disabled
* for output.
*
* <P> <B>NOTE:</B> {@link #fixedContentLengthLong} is recommended instead
* of this field, as it allows larger content lengths to be set.
*
* @since 1.5
*/
protected int fixedContentLength = -1;
/**
* The fixed content-length when using fixed-length streaming mode.
* A value of {@code -1} means fixed-length streaming mode is disabled
* for output.
*
* @since 1.7
*/
protected long fixedContentLengthLong = -1;
/**
* Supplies an {@link java.net.Authenticator Authenticator} to be used
* when authentication is requested through the HTTP protocol for
* this {@code HttpURLConnection}.
* If no authenticator is supplied, the
* {@linkplain Authenticator#setDefault(java.net.Authenticator) default
* authenticator} will be used.
*
* @implSpec The default behavior of this method is to unconditionally
* throw {@link UnsupportedOperationException}. Concrete
* implementations of {@code HttpURLConnection}
* which support supplying an {@code Authenticator} for a
* specific {@code HttpURLConnection} instance should
* override this method to implement a different behavior.
*
* @implNote Depending on authentication schemes, an implementation
* may or may not need to use the provided authenticator
* to obtain a password. For instance, an implementation that
* relies on third-party security libraries may still invoke the
* default authenticator if these libraries are configured
* to do so.
* Likewise, an implementation that supports transparent
* NTLM authentication may let the system attempt
* to connect using the system user credentials first,
* before invoking the provided authenticator.
* <br>
* However, if an authenticator is specifically provided,
* then the underlying connection may only be reused for
* {@code HttpURLConnection} instances which share the same
* {@code Authenticator} instance, and authentication information,
* if cached, may only be reused for an {@code HttpURLConnection}
* sharing that same {@code Authenticator}.
*
* @param auth The {@code Authenticator} that should be used by this
* {@code HttpURLConnection}.
*
* @throws UnsupportedOperationException if setting an Authenticator is
* not supported by the underlying implementation.
* @throws IllegalStateException if URLConnection is already connected.
* @throws NullPointerException if the supplied {@code auth} is {@code null}.
* @since 9
*/
public void setAuthenticator(Authenticator auth) {
throw new UnsupportedOperationException("Supplying an authenticator"
+ " is not supported by " + this.getClass());
}
/**
* Returns the key for the {@code n}<sup>th</sup> header field.
* Some implementations may treat the {@code 0}<sup>th</sup>
* header field as special, i.e. as the status line returned by the HTTP
* server. In this case, {@link #getHeaderField(int) getHeaderField(0)} returns the status
* line, but {@code getHeaderFieldKey(0)} returns null.
*
* @param n an index, where {@code n >=0}.
* @return the key for the {@code n}<sup>th</sup> header field,
* or {@code null} if the key does not exist.
*/
public String getHeaderFieldKey (int n) {
return null;
}
/**
* This method is used to enable streaming of a HTTP request body
* without internal buffering, when the content length is known in
* advance.
* <p>
* An exception will be thrown if the application
* attempts to write more data than the indicated
* content-length, or if the application closes the OutputStream
* before writing the indicated amount.
* <p>
* When output streaming is enabled, authentication
* and redirection cannot be handled automatically.
* A HttpRetryException will be thrown when reading
* the response if authentication or redirection are required.
* This exception can be queried for the details of the error.
* <p>
* This method must be called before the URLConnection is connected.
* <p>
* <B>NOTE:</B> {@link #setFixedLengthStreamingMode(long)} is recommended
* instead of this method as it allows larger content lengths to be set.
*
* @param contentLength The number of bytes which will be written
* to the OutputStream.
*
* @throws IllegalStateException if URLConnection is already connected
* or if a different streaming mode is already enabled.
*
* @throws IllegalArgumentException if a content length less than
* zero is specified.
*
* @see #setChunkedStreamingMode(int)
* @since 1.5
*/
public void setFixedLengthStreamingMode (int contentLength) {
if (connected) {
throw new IllegalStateException ("Already connected");
}
if (chunkLength != -1) {
throw new IllegalStateException ("Chunked encoding streaming mode set");
}
if (contentLength < 0) {
throw new IllegalArgumentException ("invalid content length");
}
fixedContentLength = contentLength;
}
/**
* This method is used to enable streaming of a HTTP request body
* without internal buffering, when the content length is known in
* advance.
*
* <P> An exception will be thrown if the application attempts to write
* more data than the indicated content-length, or if the application
* closes the OutputStream before writing the indicated amount.
*
* <P> When output streaming is enabled, authentication and redirection
* cannot be handled automatically. A {@linkplain HttpRetryException} will
* be thrown when reading the response if authentication or redirection
* are required. This exception can be queried for the details of the
* error.
*
* <P> This method must be called before the URLConnection is connected.
*
* <P> The content length set by invoking this method takes precedence
* over any value set by {@link #setFixedLengthStreamingMode(int)}.
*
* @param contentLength
* The number of bytes which will be written to the OutputStream.
*
* @throws IllegalStateException
* if URLConnection is already connected or if a different
* streaming mode is already enabled.
*
* @throws IllegalArgumentException
* if a content length less than zero is specified.
*
* @since 1.7
*/
public void setFixedLengthStreamingMode(long contentLength) {
if (connected) {
throw new IllegalStateException("Already connected");
}
if (chunkLength != -1) {
throw new IllegalStateException(
"Chunked encoding streaming mode set");
}
if (contentLength < 0) {
throw new IllegalArgumentException("invalid content length");
}
fixedContentLengthLong = contentLength;
}
/* Default chunk size (including chunk header) if not specified;
* we want to keep this in sync with the one defined in
* sun.net.www.http.ChunkedOutputStream
*/
private static final int DEFAULT_CHUNK_SIZE = 4096;
/**
* This method is used to enable streaming of a HTTP request body
* without internal buffering, when the content length is <b>not</b>
* known in advance. In this mode, chunked transfer encoding
* is used to send the request body. Note, not all HTTP servers
* support this mode.
* <p>
* When output streaming is enabled, authentication
* and redirection cannot be handled automatically.
* A HttpRetryException will be thrown when reading
* the response if authentication or redirection are required.
* This exception can be queried for the details of the error.
* <p>
* This method must be called before the URLConnection is connected.
*
* @param chunklen The number of bytes to write in each chunk.
* If chunklen is less than or equal to zero, a default
* value will be used.
*
* @throws IllegalStateException if URLConnection is already connected
* or if a different streaming mode is already enabled.
*
* @see #setFixedLengthStreamingMode(int)
* @since 1.5
*/
public void setChunkedStreamingMode (int chunklen) {
if (connected) {
throw new IllegalStateException ("Can't set streaming mode: already connected");
}
if (fixedContentLength != -1 || fixedContentLengthLong != -1) {
throw new IllegalStateException ("Fixed length streaming mode set");
}
chunkLength = chunklen <=0? DEFAULT_CHUNK_SIZE : chunklen;
}
/**
* Returns the value for the {@code n}<sup>th</sup> header field.
* Some implementations may treat the {@code 0}<sup>th</sup>
* header field as special, i.e. as the status line returned by the HTTP
* server.
* <p>
* This method can be used in conjunction with the
* {@link #getHeaderFieldKey getHeaderFieldKey} method to iterate through all
* the headers in the message.
*
* @param n an index, where {@code n>=0}.
* @return the value of the {@code n}<sup>th</sup> header field,
* or {@code null} if the value does not exist.
* @see java.net.HttpURLConnection#getHeaderFieldKey(int)
*/
public String getHeaderField(int n) {
return null;
}
/**
* An {@code int} representing the three digit HTTP Status-Code.
* <ul>
* <li> 1xx: Informational
* <li> 2xx: Success
* <li> 3xx: Redirection
* <li> 4xx: Client Error
* <li> 5xx: Server Error
* </ul>
*/
protected int responseCode = -1;
/**
* The HTTP response message.
*/
protected String responseMessage = null;
/* static variables */
/* do we automatically follow redirects? The default is true. */
private static boolean followRedirects = true;
/**
* If {@code true}, the protocol will automatically follow redirects.
* If {@code false}, the protocol will not automatically follow
* redirects.
* <p>
* This field is set by the {@code setInstanceFollowRedirects}
* method. Its value is returned by the {@code getInstanceFollowRedirects}
* method.
* <p>
* Its default value is based on the value of the static followRedirects
* at HttpURLConnection construction time.
*
* @see java.net.HttpURLConnection#setInstanceFollowRedirects(boolean)
* @see java.net.HttpURLConnection#getInstanceFollowRedirects()
* @see java.net.HttpURLConnection#setFollowRedirects(boolean)
*/
protected boolean instanceFollowRedirects = followRedirects;
/* valid HTTP methods */
private static final String[] methods = {
"GET", "POST", "HEAD", "OPTIONS", "PUT", "DELETE", "TRACE"
};
/**
* Constructor for the HttpURLConnection.
* @param u the URL
*/
protected HttpURLConnection (URL u) {
super(u);
}
/**
* Sets whether HTTP redirects (requests with response code 3xx) should
* be automatically followed by this class. True by default. Applets
* cannot change this variable.
* <p>
* If there is a security manager, this method first calls
* the security manager's {@code checkSetFactory} method
* to ensure the operation is allowed.
* This could result in a SecurityException.
*
* @param set a {@code boolean} indicating whether or not
* to follow HTTP redirects.
* @exception SecurityException if a security manager exists and its
* {@code checkSetFactory} method doesn't
* allow the operation.
* @see SecurityManager#checkSetFactory
* @see #getFollowRedirects()
*/
public static void setFollowRedirects(boolean set) {
SecurityManager sec = System.getSecurityManager();
if (sec != null) {
// seems to be the best check here...
sec.checkSetFactory();
}
followRedirects = set;
}
/**
* Returns a {@code boolean} indicating
* whether or not HTTP redirects (3xx) should
* be automatically followed.
*
* @return {@code true} if HTTP redirects should
* be automatically followed, {@code false} if not.
* @see #setFollowRedirects(boolean)
*/
public static boolean getFollowRedirects() {
return followRedirects;
}
/**
* Sets whether HTTP redirects (requests with response code 3xx) should
* be automatically followed by this {@code HttpURLConnection}
* instance.
* <p>
* The default value comes from followRedirects, which defaults to
* true.
*
* @param followRedirects a {@code boolean} indicating
* whether or not to follow HTTP redirects.
*
* @see java.net.HttpURLConnection#instanceFollowRedirects
* @see #getInstanceFollowRedirects
* @since 1.3
*/
public void setInstanceFollowRedirects(boolean followRedirects) {
instanceFollowRedirects = followRedirects;
}
/**
* Returns the value of this {@code HttpURLConnection}'s
* {@code instanceFollowRedirects} field.
*
* @return the value of this {@code HttpURLConnection}'s
* {@code instanceFollowRedirects} field.
* @see java.net.HttpURLConnection#instanceFollowRedirects
* @see #setInstanceFollowRedirects(boolean)
* @since 1.3
*/
public boolean getInstanceFollowRedirects() {
return instanceFollowRedirects;
}
/**
* Set the method for the URL request, one of:
* <UL>
* <LI>GET
* <LI>POST
* <LI>HEAD
* <LI>OPTIONS
* <LI>PUT
* <LI>DELETE
* <LI>TRACE
* </UL> are legal, subject to protocol restrictions. The default
* method is GET.
*
* @param method the HTTP method
* @exception ProtocolException if the method cannot be reset or if
* the requested method isn't valid for HTTP.
* @exception SecurityException if a security manager is set and the
* method is "TRACE", but the "allowHttpTrace"
* NetPermission is not granted.
* @see #getRequestMethod()
*/
public void setRequestMethod(String method) throws ProtocolException {
if (connected) {
throw new ProtocolException("Can't reset method: already connected");
}
// This restriction will prevent people from using this class to
// experiment w/ new HTTP methods using java. But it should
// be placed for security - the request String could be
// arbitrarily long.
for (int i = 0; i < methods.length; i++) {
if (methods[i].equals(method)) {
if (method.equals("TRACE")) {
SecurityManager s = System.getSecurityManager();
if (s != null) {
s.checkPermission(new NetPermission("allowHttpTrace"));
}
}
this.method = method;
return;
}
}
throw new ProtocolException("Invalid HTTP method: " + method);
}
/**
* Get the request method.
* @return the HTTP request method
* @see #setRequestMethod(java.lang.String)
*/
public String getRequestMethod() {
return method;
}
/**
* Gets the status code from an HTTP response message.
* For example, in the case of the following status lines:
* <PRE>
* HTTP/1.0 200 OK
* HTTP/1.0 401 Unauthorized
* </PRE>
* It will return 200 and 401 respectively.
* Returns -1 if no code can be discerned
* from the response (i.e., the response is not valid HTTP).
* @throws IOException if an error occurred connecting to the server.
* @return the HTTP Status-Code, or -1
*/
public int getResponseCode() throws IOException {
/*
* We're got the response code already
*/
if (responseCode != -1) {
return responseCode;
}
/*
* Ensure that we have connected to the server. Record
* exception as we need to re-throw it if there isn't
* a status line.
*/
Exception exc = null;
try {
getInputStream();
} catch (Exception e) {
exc = e;
}
/*
* If we can't a status-line then re-throw any exception
* that getInputStream threw.
*/
String statusLine = getHeaderField(0);
if (statusLine == null) {
if (exc != null) {
if (exc instanceof RuntimeException)
throw (RuntimeException)exc;
else
throw (IOException)exc;
}
return -1;
}
/*
* Examine the status-line - should be formatted as per
* section 6.1 of RFC 2616 :-
*
* Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase
*
* If status line can't be parsed return -1.
*/
if (statusLine.startsWith("HTTP/1.")) {
int codePos = statusLine.indexOf(' ');
if (codePos > 0) {
int phrasePos = statusLine.indexOf(' ', codePos+1);
if (phrasePos > 0 && phrasePos < statusLine.length()) {
responseMessage = statusLine.substring(phrasePos+1);
}
// deviation from RFC 2616 - don't reject status line
// if SP Reason-Phrase is not included.
if (phrasePos < 0)
phrasePos = statusLine.length();
try {
responseCode = Integer.parseInt
(statusLine.substring(codePos+1, phrasePos));
return responseCode;
} catch (NumberFormatException e) { }
}
}
return -1;
}
/**
* Gets the HTTP response message, if any, returned along with the
* response code from a server. From responses like:
* <PRE>
* HTTP/1.0 200 OK
* HTTP/1.0 404 Not Found
* </PRE>
* Extracts the Strings "OK" and "Not Found" respectively.
* Returns null if none could be discerned from the responses
* (the result was not valid HTTP).
* @throws IOException if an error occurred connecting to the server.
* @return the HTTP response message, or {@code null}
*/
public String getResponseMessage() throws IOException {
getResponseCode();
return responseMessage;
}
@SuppressWarnings("deprecation")
public long getHeaderFieldDate(String name, long Default) {
String dateString = getHeaderField(name);
try {
if (dateString.indexOf("GMT") == -1) {
dateString = dateString+" GMT";
}
return Date.parse(dateString);
} catch (Exception e) {
}
return Default;
}
/**
* Indicates that other requests to the server
* are unlikely in the near future. Calling disconnect()
* should not imply that this HttpURLConnection
* instance can be reused for other requests.
*/
public abstract void disconnect();
/**
* Indicates if the connection is going through a proxy.
* @return a boolean indicating if the connection is
* using a proxy.
*/
public abstract boolean usingProxy();
/**
* Returns a {@link SocketPermission} object representing the
* permission necessary to connect to the destination host and port.
*
* @exception IOException if an error occurs while computing
* the permission.
*
* @return a {@code SocketPermission} object representing the
* permission necessary to connect to the destination
* host and port.
*/
public Permission getPermission() throws IOException {
int port = url.getPort();
port = port < 0 ? 80 : port;
String host = url.getHost() + ":" + port;
Permission permission = new SocketPermission(host, "connect");
return permission;
}
/**
* Returns the error stream if the connection failed
* but the server sent useful data nonetheless. The
* typical example is when an HTTP server responds
* with a 404, which will cause a FileNotFoundException
* to be thrown in connect, but the server sent an HTML
* help page with suggestions as to what to do.
*
* <p>This method will not cause a connection to be initiated. If
* the connection was not connected, or if the server did not have
* an error while connecting or if the server had an error but
* no error data was sent, this method will return null. This is
* the default.
*
* @return an error stream if any, null if there have been no
* errors, the connection is not connected or the server sent no
* useful data.
*/
public InputStream getErrorStream() {
return null;
}
/**
* The response codes for HTTP, as of version 1.1.
*/
// REMIND: do we want all these??
// Others not here that we do want??
/* 2XX: generally "OK" */
/**
* HTTP Status-Code 200: OK.
*/
public static final int HTTP_OK = 200;
/**
* HTTP Status-Code 201: Created.
*/
public static final int HTTP_CREATED = 201;
/**
* HTTP Status-Code 202: Accepted.
*/
public static final int HTTP_ACCEPTED = 202;
/**
* HTTP Status-Code 203: Non-Authoritative Information.
*/
public static final int HTTP_NOT_AUTHORITATIVE = 203;
/**
* HTTP Status-Code 204: No Content.
*/
public static final int HTTP_NO_CONTENT = 204;
/**
* HTTP Status-Code 205: Reset Content.
*/
public static final int HTTP_RESET = 205;
/**
* HTTP Status-Code 206: Partial Content.
*/
public static final int HTTP_PARTIAL = 206;
/* 3XX: relocation/redirect */
/**
* HTTP Status-Code 300: Multiple Choices.
*/
public static final int HTTP_MULT_CHOICE = 300;
/**
* HTTP Status-Code 301: Moved Permanently.
*/
public static final int HTTP_MOVED_PERM = 301;
/**
* HTTP Status-Code 302: Temporary Redirect.
*/
public static final int HTTP_MOVED_TEMP = 302;
/**
* HTTP Status-Code 303: See Other.
*/
public static final int HTTP_SEE_OTHER = 303;
/**
* HTTP Status-Code 304: Not Modified.
*/
public static final int HTTP_NOT_MODIFIED = 304;
/**
* HTTP Status-Code 305: Use Proxy.
*/
public static final int HTTP_USE_PROXY = 305;
/* 4XX: client error */
/**
* HTTP Status-Code 400: Bad Request.
*/
public static final int HTTP_BAD_REQUEST = 400;
/**
* HTTP Status-Code 401: Unauthorized.
*/
public static final int HTTP_UNAUTHORIZED = 401;
/**
* HTTP Status-Code 402: Payment Required.
*/
public static final int HTTP_PAYMENT_REQUIRED = 402;
/**
* HTTP Status-Code 403: Forbidden.
*/
public static final int HTTP_FORBIDDEN = 403;
/**
* HTTP Status-Code 404: Not Found.
*/
public static final int HTTP_NOT_FOUND = 404;
/**
* HTTP Status-Code 405: Method Not Allowed.
*/
public static final int HTTP_BAD_METHOD = 405;
/**
* HTTP Status-Code 406: Not Acceptable.
*/
public static final int HTTP_NOT_ACCEPTABLE = 406;
/**
* HTTP Status-Code 407: Proxy Authentication Required.
*/
public static final int HTTP_PROXY_AUTH = 407;
/**
* HTTP Status-Code 408: Request Time-Out.
*/
public static final int HTTP_CLIENT_TIMEOUT = 408;
/**
* HTTP Status-Code 409: Conflict.
*/
public static final int HTTP_CONFLICT = 409;
/**
* HTTP Status-Code 410: Gone.
*/
public static final int HTTP_GONE = 410;
/**
* HTTP Status-Code 411: Length Required.
*/
public static final int HTTP_LENGTH_REQUIRED = 411;
/**
* HTTP Status-Code 412: Precondition Failed.
*/
public static final int HTTP_PRECON_FAILED = 412;
/**
* HTTP Status-Code 413: Request Entity Too Large.
*/
public static final int HTTP_ENTITY_TOO_LARGE = 413;
/**
* HTTP Status-Code 414: Request-URI Too Large.
*/
public static final int HTTP_REQ_TOO_LONG = 414;
/**
* HTTP Status-Code 415: Unsupported Media Type.
*/
public static final int HTTP_UNSUPPORTED_TYPE = 415;
/* 5XX: server error */
/**
* HTTP Status-Code 500: Internal Server Error.
* @deprecated it is misplaced and shouldn't have existed.
*/
@Deprecated
public static final int HTTP_SERVER_ERROR = 500;
/**
* HTTP Status-Code 500: Internal Server Error.
*/
public static final int HTTP_INTERNAL_ERROR = 500;
/**
* HTTP Status-Code 501: Not Implemented.
*/
public static final int HTTP_NOT_IMPLEMENTED = 501;
/**
* HTTP Status-Code 502: Bad Gateway.
*/
public static final int HTTP_BAD_GATEWAY = 502;
/**
* HTTP Status-Code 503: Service Unavailable.
*/
public static final int HTTP_UNAVAILABLE = 503;
/**
* HTTP Status-Code 504: Gateway Timeout.
*/
public static final int HTTP_GATEWAY_TIMEOUT = 504;
/**
* HTTP Status-Code 505: HTTP Version Not Supported.
*/
public static final int HTTP_VERSION = 505;
}

View file

@ -0,0 +1,499 @@
/*
* Copyright (c) 2005, 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 java.net;
import java.io.InputStream;
import java.io.IOException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import sun.net.idn.StringPrep;
import sun.net.idn.Punycode;
import sun.text.normalizer.UCharacterIterator;
/**
* Provides methods to convert internationalized domain names (IDNs) between
* a normal Unicode representation and an ASCII Compatible Encoding (ACE) representation.
* Internationalized domain names can use characters from the entire range of
* Unicode, while traditional domain names are restricted to ASCII characters.
* ACE is an encoding of Unicode strings that uses only ASCII characters and
* can be used with software (such as the Domain Name System) that only
* understands traditional domain names.
*
* <p>Internationalized domain names are defined in <a href="http://www.ietf.org/rfc/rfc3490.txt">RFC 3490</a>.
* RFC 3490 defines two operations: ToASCII and ToUnicode. These 2 operations employ
* <a href="http://www.ietf.org/rfc/rfc3491.txt">Nameprep</a> algorithm, which is a
* profile of <a href="http://www.ietf.org/rfc/rfc3454.txt">Stringprep</a>, and
* <a href="http://www.ietf.org/rfc/rfc3492.txt">Punycode</a> algorithm to convert
* domain name string back and forth.
*
* <p>The behavior of aforementioned conversion process can be adjusted by various flags:
* <ul>
* <li>If the ALLOW_UNASSIGNED flag is used, the domain name string to be converted
* can contain code points that are unassigned in Unicode 3.2, which is the
* Unicode version on which IDN conversion is based. If the flag is not used,
* the presence of such unassigned code points is treated as an error.
* <li>If the USE_STD3_ASCII_RULES flag is used, ASCII strings are checked against <a href="http://www.ietf.org/rfc/rfc1122.txt">RFC 1122</a> and <a href="http://www.ietf.org/rfc/rfc1123.txt">RFC 1123</a>.
* It is an error if they don't meet the requirements.
* </ul>
* These flags can be logically OR'ed together.
*
* <p>The security consideration is important with respect to internationalization
* domain name support. For example, English domain names may be <i>homographed</i>
* - maliciously misspelled by substitution of non-Latin letters.
* <a href="http://www.unicode.org/reports/tr36/">Unicode Technical Report #36</a>
* discusses security issues of IDN support as well as possible solutions.
* Applications are responsible for taking adequate security measures when using
* international domain names.
*
* @author Edward Wang
* @since 1.6
*
*/
public final class IDN {
/**
* Flag to allow processing of unassigned code points
*/
public static final int ALLOW_UNASSIGNED = 0x01;
/**
* Flag to turn on the check against STD-3 ASCII rules
*/
public static final int USE_STD3_ASCII_RULES = 0x02;
/**
* Translates a string from Unicode to ASCII Compatible Encoding (ACE),
* as defined by the ToASCII operation of <a href="http://www.ietf.org/rfc/rfc3490.txt">RFC 3490</a>.
*
* <p>ToASCII operation can fail. ToASCII fails if any step of it fails.
* If ToASCII operation fails, an IllegalArgumentException will be thrown.
* In this case, the input string should not be used in an internationalized domain name.
*
* <p> A label is an individual part of a domain name. The original ToASCII operation,
* as defined in RFC 3490, only operates on a single label. This method can handle
* both label and entire domain name, by assuming that labels in a domain name are
* always separated by dots. The following characters are recognized as dots:
* &#0092;u002E (full stop), &#0092;u3002 (ideographic full stop), &#0092;uFF0E (fullwidth full stop),
* and &#0092;uFF61 (halfwidth ideographic full stop). if dots are
* used as label separators, this method also changes all of them to &#0092;u002E (full stop)
* in output translated string.
*
* @param input the string to be processed
* @param flag process flag; can be 0 or any logical OR of possible flags
*
* @return the translated {@code String}
*
* @throws IllegalArgumentException if the input string doesn't conform to RFC 3490 specification
*/
public static String toASCII(String input, int flag)
{
int p = 0, q = 0;
StringBuilder out = new StringBuilder();
if (isRootLabel(input)) {
return ".";
}
while (p < input.length()) {
q = searchDots(input, p);
out.append(toASCIIInternal(input.substring(p, q), flag));
if (q != (input.length())) {
// has more labels, or keep the trailing dot as at present
out.append('.');
}
p = q + 1;
}
return out.toString();
}
/**
* Translates a string from Unicode to ASCII Compatible Encoding (ACE),
* as defined by the ToASCII operation of <a href="http://www.ietf.org/rfc/rfc3490.txt">RFC 3490</a>.
*
* <p> This convenience method works as if by invoking the
* two-argument counterpart as follows:
* <blockquote>
* {@link #toASCII(String, int) toASCII}(input,&nbsp;0);
* </blockquote>
*
* @param input the string to be processed
*
* @return the translated {@code String}
*
* @throws IllegalArgumentException if the input string doesn't conform to RFC 3490 specification
*/
public static String toASCII(String input) {
return toASCII(input, 0);
}
/**
* Translates a string from ASCII Compatible Encoding (ACE) to Unicode,
* as defined by the ToUnicode operation of <a href="http://www.ietf.org/rfc/rfc3490.txt">RFC 3490</a>.
*
* <p>ToUnicode never fails. In case of any error, the input string is returned unmodified.
*
* <p> A label is an individual part of a domain name. The original ToUnicode operation,
* as defined in RFC 3490, only operates on a single label. This method can handle
* both label and entire domain name, by assuming that labels in a domain name are
* always separated by dots. The following characters are recognized as dots:
* &#0092;u002E (full stop), &#0092;u3002 (ideographic full stop), &#0092;uFF0E (fullwidth full stop),
* and &#0092;uFF61 (halfwidth ideographic full stop).
*
* @param input the string to be processed
* @param flag process flag; can be 0 or any logical OR of possible flags
*
* @return the translated {@code String}
*/
public static String toUnicode(String input, int flag) {
int p = 0, q = 0;
StringBuilder out = new StringBuilder();
if (isRootLabel(input)) {
return ".";
}
while (p < input.length()) {
q = searchDots(input, p);
out.append(toUnicodeInternal(input.substring(p, q), flag));
if (q != (input.length())) {
// has more labels, or keep the trailing dot as at present
out.append('.');
}
p = q + 1;
}
return out.toString();
}
/**
* Translates a string from ASCII Compatible Encoding (ACE) to Unicode,
* as defined by the ToUnicode operation of <a href="http://www.ietf.org/rfc/rfc3490.txt">RFC 3490</a>.
*
* <p> This convenience method works as if by invoking the
* two-argument counterpart as follows:
* <blockquote>
* {@link #toUnicode(String, int) toUnicode}(input,&nbsp;0);
* </blockquote>
*
* @param input the string to be processed
*
* @return the translated {@code String}
*/
public static String toUnicode(String input) {
return toUnicode(input, 0);
}
/* ---------------- Private members -------------- */
// ACE Prefix is "xn--"
private static final String ACE_PREFIX = "xn--";
private static final int ACE_PREFIX_LENGTH = ACE_PREFIX.length();
private static final int MAX_LABEL_LENGTH = 63;
// single instance of nameprep
private static StringPrep namePrep = null;
static {
InputStream stream = null;
try {
final String IDN_PROFILE = "uidna.spp";
if (System.getSecurityManager() != null) {
stream = AccessController.doPrivileged(new PrivilegedAction<>() {
public InputStream run() {
return StringPrep.class.getResourceAsStream(IDN_PROFILE);
}
});
} else {
stream = StringPrep.class.getResourceAsStream(IDN_PROFILE);
}
namePrep = new StringPrep(stream);
stream.close();
} catch (IOException e) {
// should never reach here
assert false;
}
}
/* ---------------- Private operations -------------- */
//
// to suppress the default zero-argument constructor
//
private IDN() {}
//
// toASCII operation; should only apply to a single label
//
private static String toASCIIInternal(String label, int flag)
{
// step 1
// Check if the string contains code points outside the ASCII range 0..0x7c.
boolean isASCII = isAllASCII(label);
StringBuffer dest;
// step 2
// perform the nameprep operation; flag ALLOW_UNASSIGNED is used here
if (!isASCII) {
UCharacterIterator iter = UCharacterIterator.getInstance(label);
try {
dest = namePrep.prepare(iter, flag);
} catch (java.text.ParseException e) {
throw new IllegalArgumentException(e);
}
} else {
dest = new StringBuffer(label);
}
// step 8, move forward to check the smallest number of the code points
// the length must be inside 1..63
if (dest.length() == 0) {
throw new IllegalArgumentException(
"Empty label is not a legal name");
}
// step 3
// Verify the absence of non-LDH ASCII code points
// 0..0x2c, 0x2e..0x2f, 0x3a..0x40, 0x5b..0x60, 0x7b..0x7f
// Verify the absence of leading and trailing hyphen
boolean useSTD3ASCIIRules = ((flag & USE_STD3_ASCII_RULES) != 0);
if (useSTD3ASCIIRules) {
for (int i = 0; i < dest.length(); i++) {
int c = dest.charAt(i);
if (isNonLDHAsciiCodePoint(c)) {
throw new IllegalArgumentException(
"Contains non-LDH ASCII characters");
}
}
if (dest.charAt(0) == '-' ||
dest.charAt(dest.length() - 1) == '-') {
throw new IllegalArgumentException(
"Has leading or trailing hyphen");
}
}
if (!isASCII) {
// step 4
// If all code points are inside 0..0x7f, skip to step 8
if (!isAllASCII(dest.toString())) {
// step 5
// verify the sequence does not begin with ACE prefix
if(!startsWithACEPrefix(dest)){
// step 6
// encode the sequence with punycode
try {
dest = Punycode.encode(dest, null);
} catch (java.text.ParseException e) {
throw new IllegalArgumentException(e);
}
dest = toASCIILower(dest);
// step 7
// prepend the ACE prefix
dest.insert(0, ACE_PREFIX);
} else {
throw new IllegalArgumentException("The input starts with the ACE Prefix");
}
}
}
// step 8
// the length must be inside 1..63
if (dest.length() > MAX_LABEL_LENGTH) {
throw new IllegalArgumentException("The label in the input is too long");
}
return dest.toString();
}
//
// toUnicode operation; should only apply to a single label
//
private static String toUnicodeInternal(String label, int flag) {
boolean[] caseFlags = null;
StringBuffer dest;
// step 1
// find out if all the codepoints in input are ASCII
boolean isASCII = isAllASCII(label);
if(!isASCII){
// step 2
// perform the nameprep operation; flag ALLOW_UNASSIGNED is used here
try {
UCharacterIterator iter = UCharacterIterator.getInstance(label);
dest = namePrep.prepare(iter, flag);
} catch (Exception e) {
// toUnicode never fails; if any step fails, return the input string
return label;
}
} else {
dest = new StringBuffer(label);
}
// step 3
// verify ACE Prefix
if(startsWithACEPrefix(dest)) {
// step 4
// Remove the ACE Prefix
String temp = dest.substring(ACE_PREFIX_LENGTH, dest.length());
try {
// step 5
// Decode using punycode
StringBuffer decodeOut = Punycode.decode(new StringBuffer(temp), null);
// step 6
// Apply toASCII
String toASCIIOut = toASCII(decodeOut.toString(), flag);
// step 7
// verify
if (toASCIIOut.equalsIgnoreCase(dest.toString())) {
// step 8
// return output of step 5
return decodeOut.toString();
}
} catch (Exception ignored) {
// no-op
}
}
// just return the input
return label;
}
//
// LDH stands for "letter/digit/hyphen", with characters restricted to the
// 26-letter Latin alphabet <A-Z a-z>, the digits <0-9>, and the hyphen
// <->.
// Non LDH refers to characters in the ASCII range, but which are not
// letters, digits or the hypen.
//
// non-LDH = 0..0x2C, 0x2E..0x2F, 0x3A..0x40, 0x5B..0x60, 0x7B..0x7F
//
private static boolean isNonLDHAsciiCodePoint(int ch){
return (0x0000 <= ch && ch <= 0x002C) ||
(0x002E <= ch && ch <= 0x002F) ||
(0x003A <= ch && ch <= 0x0040) ||
(0x005B <= ch && ch <= 0x0060) ||
(0x007B <= ch && ch <= 0x007F);
}
//
// search dots in a string and return the index of that character;
// or if there is no dots, return the length of input string
// dots might be: \u002E (full stop), \u3002 (ideographic full stop), \uFF0E (fullwidth full stop),
// and \uFF61 (halfwidth ideographic full stop).
//
private static int searchDots(String s, int start) {
int i;
for (i = start; i < s.length(); i++) {
if (isLabelSeparator(s.charAt(i))) {
break;
}
}
return i;
}
//
// to check if a string is a root label, ".".
//
private static boolean isRootLabel(String s) {
return (s.length() == 1 && isLabelSeparator(s.charAt(0)));
}
//
// to check if a character is a label separator, i.e. a dot character.
//
private static boolean isLabelSeparator(char c) {
return (c == '.' || c == '\u3002' || c == '\uFF0E' || c == '\uFF61');
}
//
// to check if a string only contains US-ASCII code point
//
private static boolean isAllASCII(String input) {
boolean isASCII = true;
for (int i = 0; i < input.length(); i++) {
int c = input.charAt(i);
if (c > 0x7F) {
isASCII = false;
break;
}
}
return isASCII;
}
//
// to check if a string starts with ACE-prefix
//
private static boolean startsWithACEPrefix(StringBuffer input){
boolean startsWithPrefix = true;
if(input.length() < ACE_PREFIX_LENGTH){
return false;
}
for(int i = 0; i < ACE_PREFIX_LENGTH; i++){
if(toASCIILower(input.charAt(i)) != ACE_PREFIX.charAt(i)){
startsWithPrefix = false;
}
}
return startsWithPrefix;
}
private static char toASCIILower(char ch){
if('A' <= ch && ch <= 'Z'){
return (char)(ch + 'a' - 'A');
}
return ch;
}
private static StringBuffer toASCIILower(StringBuffer input){
StringBuffer dest = new StringBuffer();
for(int i = 0; i < input.length();i++){
dest.append(toASCIILower(input.charAt(i)));
}
return dest;
}
}

View file

@ -0,0 +1,398 @@
/*
* Copyright (c) 2005, 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 java.net;
import java.net.URI;
import java.net.CookieStore;
import java.net.HttpCookie;
import java.net.URISyntaxException;
import java.util.List;
import java.util.Map;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Collections;
import java.util.Iterator;
import java.util.concurrent.locks.ReentrantLock;
/**
* A simple in-memory java.net.CookieStore implementation
*
* @author Edward Wang
* @since 1.6
*/
class InMemoryCookieStore implements CookieStore {
// the in-memory representation of cookies
private List<HttpCookie> cookieJar = null;
// the cookies are indexed by its domain and associated uri (if present)
// CAUTION: when a cookie removed from main data structure (i.e. cookieJar),
// it won't be cleared in domainIndex & uriIndex. Double-check the
// presence of cookie when retrieve one form index store.
private Map<String, List<HttpCookie>> domainIndex = null;
private Map<URI, List<HttpCookie>> uriIndex = null;
// use ReentrantLock instead of syncronized for scalability
private ReentrantLock lock = null;
/**
* The default ctor
*/
public InMemoryCookieStore() {
cookieJar = new ArrayList<>();
domainIndex = new HashMap<>();
uriIndex = new HashMap<>();
lock = new ReentrantLock(false);
}
/**
* Add one cookie into cookie store.
*/
public void add(URI uri, HttpCookie cookie) {
// pre-condition : argument can't be null
if (cookie == null) {
throw new NullPointerException("cookie is null");
}
lock.lock();
try {
// remove the ole cookie if there has had one
cookieJar.remove(cookie);
// add new cookie if it has a non-zero max-age
if (cookie.getMaxAge() != 0) {
cookieJar.add(cookie);
// and add it to domain index
if (cookie.getDomain() != null) {
addIndex(domainIndex, cookie.getDomain(), cookie);
}
if (uri != null) {
// add it to uri index, too
addIndex(uriIndex, getEffectiveURI(uri), cookie);
}
}
} finally {
lock.unlock();
}
}
/**
* Get all cookies, which:
* 1) given uri domain-matches with, or, associated with
* given uri when added to the cookie store.
* 3) not expired.
* See RFC 2965 sec. 3.3.4 for more detail.
*/
public List<HttpCookie> get(URI uri) {
// argument can't be null
if (uri == null) {
throw new NullPointerException("uri is null");
}
List<HttpCookie> cookies = new ArrayList<>();
boolean secureLink = "https".equalsIgnoreCase(uri.getScheme());
lock.lock();
try {
// check domainIndex first
getInternal1(cookies, domainIndex, uri.getHost(), secureLink);
// check uriIndex then
getInternal2(cookies, uriIndex, getEffectiveURI(uri), secureLink);
} finally {
lock.unlock();
}
return cookies;
}
/**
* Get all cookies in cookie store, except those have expired
*/
public List<HttpCookie> getCookies() {
List<HttpCookie> rt;
lock.lock();
try {
Iterator<HttpCookie> it = cookieJar.iterator();
while (it.hasNext()) {
if (it.next().hasExpired()) {
it.remove();
}
}
} finally {
rt = Collections.unmodifiableList(cookieJar);
lock.unlock();
}
return rt;
}
/**
* Get all URIs, which are associated with at least one cookie
* of this cookie store.
*/
public List<URI> getURIs() {
List<URI> uris = new ArrayList<>();
lock.lock();
try {
Iterator<URI> it = uriIndex.keySet().iterator();
while (it.hasNext()) {
URI uri = it.next();
List<HttpCookie> cookies = uriIndex.get(uri);
if (cookies == null || cookies.size() == 0) {
// no cookies list or an empty list associated with
// this uri entry, delete it
it.remove();
}
}
} finally {
uris.addAll(uriIndex.keySet());
lock.unlock();
}
return uris;
}
/**
* Remove a cookie from store
*/
public boolean remove(URI uri, HttpCookie ck) {
// argument can't be null
if (ck == null) {
throw new NullPointerException("cookie is null");
}
boolean modified = false;
lock.lock();
try {
modified = cookieJar.remove(ck);
} finally {
lock.unlock();
}
return modified;
}
/**
* Remove all cookies in this cookie store.
*/
public boolean removeAll() {
lock.lock();
try {
if (cookieJar.isEmpty()) {
return false;
}
cookieJar.clear();
domainIndex.clear();
uriIndex.clear();
} finally {
lock.unlock();
}
return true;
}
/* ---------------- Private operations -------------- */
/*
* This is almost the same as HttpCookie.domainMatches except for
* one difference: It won't reject cookies when the 'H' part of the
* domain contains a dot ('.').
* I.E.: RFC 2965 section 3.3.2 says that if host is x.y.domain.com
* and the cookie domain is .domain.com, then it should be rejected.
* However that's not how the real world works. Browsers don't reject and
* some sites, like yahoo.com do actually expect these cookies to be
* passed along.
* And should be used for 'old' style cookies (aka Netscape type of cookies)
*/
private boolean netscapeDomainMatches(String domain, String host)
{
if (domain == null || host == null) {
return false;
}
// if there's no embedded dot in domain and domain is not .local
boolean isLocalDomain = ".local".equalsIgnoreCase(domain);
int embeddedDotInDomain = domain.indexOf('.');
if (embeddedDotInDomain == 0) {
embeddedDotInDomain = domain.indexOf('.', 1);
}
if (!isLocalDomain && (embeddedDotInDomain == -1 || embeddedDotInDomain == domain.length() - 1)) {
return false;
}
// if the host name contains no dot and the domain name is .local
int firstDotInHost = host.indexOf('.');
if (firstDotInHost == -1 && isLocalDomain) {
return true;
}
int domainLength = domain.length();
int lengthDiff = host.length() - domainLength;
if (lengthDiff == 0) {
// if the host name and the domain name are just string-compare euqal
return host.equalsIgnoreCase(domain);
} else if (lengthDiff > 0) {
// need to check H & D component
String H = host.substring(0, lengthDiff);
String D = host.substring(lengthDiff);
return (D.equalsIgnoreCase(domain));
} else if (lengthDiff == -1) {
// if domain is actually .host
return (domain.charAt(0) == '.' &&
host.equalsIgnoreCase(domain.substring(1)));
}
return false;
}
private void getInternal1(List<HttpCookie> cookies, Map<String, List<HttpCookie>> cookieIndex,
String host, boolean secureLink) {
// Use a separate list to handle cookies that need to be removed so
// that there is no conflict with iterators.
ArrayList<HttpCookie> toRemove = new ArrayList<>();
for (Map.Entry<String, List<HttpCookie>> entry : cookieIndex.entrySet()) {
String domain = entry.getKey();
List<HttpCookie> lst = entry.getValue();
for (HttpCookie c : lst) {
if ((c.getVersion() == 0 && netscapeDomainMatches(domain, host)) ||
(c.getVersion() == 1 && HttpCookie.domainMatches(domain, host))) {
if ((cookieJar.indexOf(c) != -1)) {
// the cookie still in main cookie store
if (!c.hasExpired()) {
// don't add twice and make sure it's the proper
// security level
if ((secureLink || !c.getSecure()) &&
!cookies.contains(c)) {
cookies.add(c);
}
} else {
toRemove.add(c);
}
} else {
// the cookie has beed removed from main store,
// so also remove it from domain indexed store
toRemove.add(c);
}
}
}
// Clear up the cookies that need to be removed
for (HttpCookie c : toRemove) {
lst.remove(c);
cookieJar.remove(c);
}
toRemove.clear();
}
}
// @param cookies [OUT] contains the found cookies
// @param cookieIndex the index
// @param comparator the prediction to decide whether or not
// a cookie in index should be returned
private <T> void getInternal2(List<HttpCookie> cookies,
Map<T, List<HttpCookie>> cookieIndex,
Comparable<T> comparator, boolean secureLink)
{
for (T index : cookieIndex.keySet()) {
if (comparator.compareTo(index) == 0) {
List<HttpCookie> indexedCookies = cookieIndex.get(index);
// check the list of cookies associated with this domain
if (indexedCookies != null) {
Iterator<HttpCookie> it = indexedCookies.iterator();
while (it.hasNext()) {
HttpCookie ck = it.next();
if (cookieJar.indexOf(ck) != -1) {
// the cookie still in main cookie store
if (!ck.hasExpired()) {
// don't add twice
if ((secureLink || !ck.getSecure()) &&
!cookies.contains(ck))
cookies.add(ck);
} else {
it.remove();
cookieJar.remove(ck);
}
} else {
// the cookie has beed removed from main store,
// so also remove it from domain indexed store
it.remove();
}
}
} // end of indexedCookies != null
} // end of comparator.compareTo(index) == 0
} // end of cookieIndex iteration
}
// add 'cookie' indexed by 'index' into 'indexStore'
private <T> void addIndex(Map<T, List<HttpCookie>> indexStore,
T index,
HttpCookie cookie)
{
if (index != null) {
List<HttpCookie> cookies = indexStore.get(index);
if (cookies != null) {
// there may already have the same cookie, so remove it first
cookies.remove(cookie);
cookies.add(cookie);
} else {
cookies = new ArrayList<>();
cookies.add(cookie);
indexStore.put(index, cookies);
}
}
}
//
// for cookie purpose, the effective uri should only be http://host
// the path will be taken into account when path-match algorithm applied
//
private URI getEffectiveURI(URI uri) {
URI effectiveURI = null;
try {
effectiveURI = new URI("http",
uri.getHost(),
null, // path component
null, // query component
null // fragment component
);
} catch (URISyntaxException ignored) {
effectiveURI = uri;
}
return effectiveURI;
}
}

View file

@ -0,0 +1,368 @@
/*
* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* 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 java.net;
import java.io.ObjectStreamException;
/**
* This class represents an Internet Protocol version 4 (IPv4) address.
* Defined by <a href="http://www.ietf.org/rfc/rfc790.txt">
* <i>RFC&nbsp;790: Assigned Numbers</i></a>,
* <a href="http://www.ietf.org/rfc/rfc1918.txt">
* <i>RFC&nbsp;1918: Address Allocation for Private Internets</i></a>,
* and <a href="http://www.ietf.org/rfc/rfc2365.txt"><i>RFC&nbsp;2365:
* Administratively Scoped IP Multicast</i></a>
*
* <h3> <a id="format">Textual representation of IP addresses</a> </h3>
*
* Textual representation of IPv4 address used as input to methods
* takes one of the following forms:
*
* <blockquote><ul style="list-style-type:none">
* <li>{@code d.d.d.d}</li>
* <li>{@code d.d.d}</li>
* <li>{@code d.d}</li>
* <li>{@code d}</li>
* </ul></blockquote>
*
* <p> When four parts are specified, each is interpreted as a byte of
* data and assigned, from left to right, to the four bytes of an IPv4
* address.
* <p> When a three part address is specified, the last part is
* interpreted as a 16-bit quantity and placed in the right most two
* bytes of the network address. This makes the three part address
* format convenient for specifying Class B net- work addresses as
* 128.net.host.
*
* <p> When a two part address is supplied, the last part is
* interpreted as a 24-bit quantity and placed in the right most three
* bytes of the network address. This makes the two part address
* format convenient for specifying Class A network addresses as
* net.host.
*
* <p> When only one part is given, the value is stored directly in
* the network address without any byte rearrangement.
*
* <p> For methods that return a textual representation as output
* value, the first form, i.e. a dotted-quad string, is used.
*
* <h4> The Scope of a Multicast Address </h4>
*
* Historically the IPv4 TTL field in the IP header has doubled as a
* multicast scope field: a TTL of 0 means node-local, 1 means
* link-local, up through 32 means site-local, up through 64 means
* region-local, up through 128 means continent-local, and up through
* 255 are global. However, the administrative scoping is preferred.
* Please refer to <a href="http://www.ietf.org/rfc/rfc2365.txt">
* <i>RFC&nbsp;2365: Administratively Scoped IP Multicast</i></a>
* @since 1.4
*/
public final
class Inet4Address extends InetAddress {
static final int INADDRSZ = 4;
/** use serialVersionUID from InetAddress, but Inet4Address instance
* is always replaced by an InetAddress instance before being
* serialized */
private static final long serialVersionUID = 3286316764910316507L;
/*
* Perform initializations.
*/
static {
init();
}
Inet4Address() {
super();
holder().hostName = null;
holder().address = 0;
holder().family = IPv4;
}
Inet4Address(String hostName, byte addr[]) {
holder().hostName = hostName;
holder().family = IPv4;
if (addr != null) {
if (addr.length == INADDRSZ) {
int address = addr[3] & 0xFF;
address |= ((addr[2] << 8) & 0xFF00);
address |= ((addr[1] << 16) & 0xFF0000);
address |= ((addr[0] << 24) & 0xFF000000);
holder().address = address;
}
}
holder().originalHostName = hostName;
}
Inet4Address(String hostName, int address) {
holder().hostName = hostName;
holder().family = IPv4;
holder().address = address;
holder().originalHostName = hostName;
}
/**
* Replaces the object to be serialized with an InetAddress object.
*
* @return the alternate object to be serialized.
*
* @throws ObjectStreamException if a new object replacing this
* object could not be created
*/
private Object writeReplace() throws ObjectStreamException {
// will replace the to be serialized 'this' object
InetAddress inet = new InetAddress();
inet.holder().hostName = holder().getHostName();
inet.holder().address = holder().getAddress();
/**
* Prior to 1.4 an InetAddress was created with a family
* based on the platform AF_INET value (usually 2).
* For compatibility reasons we must therefore write the
* the InetAddress with this family.
*/
inet.holder().family = 2;
return inet;
}
/**
* Utility routine to check if the InetAddress is an
* IP multicast address. IP multicast address is a Class D
* address i.e first four bits of the address are 1110.
* @return a {@code boolean} indicating if the InetAddress is
* an IP multicast address
*/
public boolean isMulticastAddress() {
return ((holder().getAddress() & 0xf0000000) == 0xe0000000);
}
/**
* Utility routine to check if the InetAddress is a wildcard address.
* @return a {@code boolean} indicating if the Inetaddress is
* a wildcard address.
*/
public boolean isAnyLocalAddress() {
return holder().getAddress() == 0;
}
/**
* Utility routine to check if the InetAddress is a loopback address.
*
* @return a {@code boolean} indicating if the InetAddress is
* a loopback address; or false otherwise.
*/
public boolean isLoopbackAddress() {
/* 127.x.x.x */
byte[] byteAddr = getAddress();
return byteAddr[0] == 127;
}
/**
* Utility routine to check if the InetAddress is an link local address.
*
* @return a {@code boolean} indicating if the InetAddress is
* a link local address; or false if address is not a link local unicast address.
*/
public boolean isLinkLocalAddress() {
// link-local unicast in IPv4 (169.254.0.0/16)
// defined in "Documenting Special Use IPv4 Address Blocks
// that have been Registered with IANA" by Bill Manning
// draft-manning-dsua-06.txt
int address = holder().getAddress();
return (((address >>> 24) & 0xFF) == 169)
&& (((address >>> 16) & 0xFF) == 254);
}
/**
* Utility routine to check if the InetAddress is a site local address.
*
* @return a {@code boolean} indicating if the InetAddress is
* a site local address; or false if address is not a site local unicast address.
*/
public boolean isSiteLocalAddress() {
// refer to RFC 1918
// 10/8 prefix
// 172.16/12 prefix
// 192.168/16 prefix
int address = holder().getAddress();
return (((address >>> 24) & 0xFF) == 10)
|| ((((address >>> 24) & 0xFF) == 172)
&& (((address >>> 16) & 0xF0) == 16))
|| ((((address >>> 24) & 0xFF) == 192)
&& (((address >>> 16) & 0xFF) == 168));
}
/**
* Utility routine to check if the multicast address has global scope.
*
* @return a {@code boolean} indicating if the address has
* is a multicast address of global scope, false if it is not
* of global scope or it is not a multicast address
*/
public boolean isMCGlobal() {
// 224.0.1.0 to 238.255.255.255
byte[] byteAddr = getAddress();
return ((byteAddr[0] & 0xff) >= 224 && (byteAddr[0] & 0xff) <= 238 ) &&
!((byteAddr[0] & 0xff) == 224 && byteAddr[1] == 0 &&
byteAddr[2] == 0);
}
/**
* Utility routine to check if the multicast address has node scope.
*
* @return a {@code boolean} indicating if the address has
* is a multicast address of node-local scope, false if it is not
* of node-local scope or it is not a multicast address
*/
public boolean isMCNodeLocal() {
// unless ttl == 0
return false;
}
/**
* Utility routine to check if the multicast address has link scope.
*
* @return a {@code boolean} indicating if the address has
* is a multicast address of link-local scope, false if it is not
* of link-local scope or it is not a multicast address
*/
public boolean isMCLinkLocal() {
// 224.0.0/24 prefix and ttl == 1
int address = holder().getAddress();
return (((address >>> 24) & 0xFF) == 224)
&& (((address >>> 16) & 0xFF) == 0)
&& (((address >>> 8) & 0xFF) == 0);
}
/**
* Utility routine to check if the multicast address has site scope.
*
* @return a {@code boolean} indicating if the address has
* is a multicast address of site-local scope, false if it is not
* of site-local scope or it is not a multicast address
*/
public boolean isMCSiteLocal() {
// 239.255/16 prefix or ttl < 32
int address = holder().getAddress();
return (((address >>> 24) & 0xFF) == 239)
&& (((address >>> 16) & 0xFF) == 255);
}
/**
* Utility routine to check if the multicast address has organization scope.
*
* @return a {@code boolean} indicating if the address has
* is a multicast address of organization-local scope,
* false if it is not of organization-local scope
* or it is not a multicast address
*/
public boolean isMCOrgLocal() {
// 239.192 - 239.195
int address = holder().getAddress();
return (((address >>> 24) & 0xFF) == 239)
&& (((address >>> 16) & 0xFF) >= 192)
&& (((address >>> 16) & 0xFF) <= 195);
}
/**
* Returns the raw IP address of this {@code InetAddress}
* object. The result is in network byte order: the highest order
* byte of the address is in {@code getAddress()[0]}.
*
* @return the raw IP address of this object.
*/
public byte[] getAddress() {
int address = holder().getAddress();
byte[] addr = new byte[INADDRSZ];
addr[0] = (byte) ((address >>> 24) & 0xFF);
addr[1] = (byte) ((address >>> 16) & 0xFF);
addr[2] = (byte) ((address >>> 8) & 0xFF);
addr[3] = (byte) (address & 0xFF);
return addr;
}
/**
* Returns the IP address string in textual presentation form.
*
* @return the raw IP address in a string format.
*/
public String getHostAddress() {
return numericToTextFormat(getAddress());
}
/**
* Returns a hashcode for this IP address.
*
* @return a hash code value for this IP address.
*/
public int hashCode() {
return holder().getAddress();
}
/**
* Compares this object against the specified object.
* The result is {@code true} if and only if the argument is
* not {@code null} and it represents the same IP address as
* this object.
* <p>
* Two instances of {@code InetAddress} represent the same IP
* address if the length of the byte arrays returned by
* {@code getAddress} is the same for both, and each of the
* array components is the same for the byte arrays.
*
* @param obj the object to compare against.
* @return {@code true} if the objects are the same;
* {@code false} otherwise.
* @see java.net.InetAddress#getAddress()
*/
public boolean equals(Object obj) {
return (obj != null) && (obj instanceof Inet4Address) &&
(((InetAddress)obj).holder().getAddress() == holder().getAddress());
}
// Utilities
/**
* Converts IPv4 binary address into a string suitable for presentation.
*
* @param src a byte array representing an IPv4 numeric address
* @return a String representing the IPv4 address in
* textual representation format
*/
static String numericToTextFormat(byte[] src)
{
return (src[0] & 0xff) + "." + (src[1] & 0xff) + "." + (src[2] & 0xff) + "." + (src[3] & 0xff);
}
/**
* Perform class load-time initializations.
*/
private static native void init();
}

View file

@ -0,0 +1,74 @@
/*
* Copyright (c) 2002, 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 java.net;
import java.io.IOException;
/*
* Package private implementation of InetAddressImpl for IPv4.
*
* @since 1.4
*/
class Inet4AddressImpl implements InetAddressImpl {
public native String getLocalHostName() throws UnknownHostException;
public native InetAddress[]
lookupAllHostAddr(String hostname) throws UnknownHostException;
public native String getHostByAddr(byte[] addr) throws UnknownHostException;
private native boolean isReachable0(byte[] addr, int timeout, byte[] ifaddr, int ttl) throws IOException;
public synchronized InetAddress anyLocalAddress() {
if (anyLocalAddress == null) {
anyLocalAddress = new Inet4Address(); // {0x00,0x00,0x00,0x00}
anyLocalAddress.holder().hostName = "0.0.0.0";
}
return anyLocalAddress;
}
public synchronized InetAddress loopbackAddress() {
if (loopbackAddress == null) {
byte[] loopback = {0x7f,0x00,0x00,0x01};
loopbackAddress = new Inet4Address("localhost", loopback);
}
return loopbackAddress;
}
public boolean isReachable(InetAddress addr, int timeout, NetworkInterface netif, int ttl) throws IOException {
byte[] ifaddr = null;
if (netif != null) {
/*
* Let's make sure we use an address of the proper family
*/
java.util.Enumeration<InetAddress> it = netif.getInetAddresses();
InetAddress inetaddr = null;
while (!(inetaddr instanceof Inet4Address) &&
it.hasMoreElements())
inetaddr = it.nextElement();
if (inetaddr instanceof Inet4Address)
ifaddr = inetaddr.getAddress();
}
return isReachable0(addr.getAddress(), timeout, ifaddr, ttl);
}
private InetAddress anyLocalAddress;
private InetAddress loopbackAddress;
}

View file

@ -0,0 +1,921 @@
/*
* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* 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 java.net;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamField;
import java.util.Enumeration;
import java.util.Arrays;
/**
* This class represents an Internet Protocol version 6 (IPv6) address.
* Defined by <a href="http://www.ietf.org/rfc/rfc2373.txt">
* <i>RFC&nbsp;2373: IP Version 6 Addressing Architecture</i></a>.
*
* <h3> <a id="format">Textual representation of IP addresses</a> </h3>
*
* Textual representation of IPv6 address used as input to methods
* takes one of the following forms:
*
* <ol>
* <li><p> <a id="lform">The preferred form</a> is x:x:x:x:x:x:x:x,
* where the 'x's are
* the hexadecimal values of the eight 16-bit pieces of the
* address. This is the full form. For example,
*
* <blockquote><ul style="list-style-type:none">
* <li>{@code 1080:0:0:0:8:800:200C:417A}</li>
* </ul></blockquote>
*
* <p> Note that it is not necessary to write the leading zeros in
* an individual field. However, there must be at least one numeral
* in every field, except as described below.</li>
*
* <li><p> Due to some methods of allocating certain styles of IPv6
* addresses, it will be common for addresses to contain long
* strings of zero bits. In order to make writing addresses
* containing zero bits easier, a special syntax is available to
* compress the zeros. The use of "::" indicates multiple groups
* of 16-bits of zeros. The "::" can only appear once in an address.
* The "::" can also be used to compress the leading and/or trailing
* zeros in an address. For example,
*
* <blockquote><ul style="list-style-type:none">
* <li>{@code 1080::8:800:200C:417A}</li>
* </ul></blockquote>
*
* <li><p> An alternative form that is sometimes more convenient
* when dealing with a mixed environment of IPv4 and IPv6 nodes is
* x:x:x:x:x:x:d.d.d.d, where the 'x's are the hexadecimal values
* of the six high-order 16-bit pieces of the address, and the 'd's
* are the decimal values of the four low-order 8-bit pieces of the
* standard IPv4 representation address, for example,
*
* <blockquote><ul style="list-style-type:none">
* <li>{@code ::FFFF:129.144.52.38}</li>
* <li>{@code ::129.144.52.38}</li>
* </ul></blockquote>
*
* <p> where "::FFFF:d.d.d.d" and "::d.d.d.d" are, respectively, the
* general forms of an IPv4-mapped IPv6 address and an
* IPv4-compatible IPv6 address. Note that the IPv4 portion must be
* in the "d.d.d.d" form. The following forms are invalid:
*
* <blockquote><ul style="list-style-type:none">
* <li>{@code ::FFFF:d.d.d}</li>
* <li>{@code ::FFFF:d.d}</li>
* <li>{@code ::d.d.d}</li>
* <li>{@code ::d.d}</li>
* </ul></blockquote>
*
* <p> The following form:
*
* <blockquote><ul style="list-style-type:none">
* <li>{@code ::FFFF:d}</li>
* </ul></blockquote>
*
* <p> is valid, however it is an unconventional representation of
* the IPv4-compatible IPv6 address,
*
* <blockquote><ul style="list-style-type:none">
* <li>{@code ::255.255.0.d}</li>
* </ul></blockquote>
*
* <p> while "::d" corresponds to the general IPv6 address
* "0:0:0:0:0:0:0:d".</li>
* </ol>
*
* <p> For methods that return a textual representation as output
* value, the full form is used. Inet6Address will return the full
* form because it is unambiguous when used in combination with other
* textual data.
*
* <h4> Special IPv6 address </h4>
*
* <blockquote>
* <table class="borderless">
* <caption style="display:none">Description of IPv4-mapped address</caption>
* <tr><th style="vertical-align:top; padding-right:2px"><i>IPv4-mapped address</i></th>
* <td>Of the form ::ffff:w.x.y.z, this IPv6 address is used to
* represent an IPv4 address. It allows the native program to
* use the same address data structure and also the same
* socket when communicating with both IPv4 and IPv6 nodes.
*
* <p>In InetAddress and Inet6Address, it is used for internal
* representation; it has no functional role. Java will never
* return an IPv4-mapped address. These classes can take an
* IPv4-mapped address as input, both in byte array and text
* representation. However, it will be converted into an IPv4
* address.</td></tr>
* </table></blockquote>
*
* <h4><a id="scoped">Textual representation of IPv6 scoped addresses</a></h4>
*
* <p> The textual representation of IPv6 addresses as described above can be
* extended to specify IPv6 scoped addresses. This extension to the basic
* addressing architecture is described in [draft-ietf-ipngwg-scoping-arch-04.txt].
*
* <p> Because link-local and site-local addresses are non-global, it is possible
* that different hosts may have the same destination address and may be
* reachable through different interfaces on the same originating system. In
* this case, the originating system is said to be connected to multiple zones
* of the same scope. In order to disambiguate which is the intended destination
* zone, it is possible to append a zone identifier (or <i>scope_id</i>) to an
* IPv6 address.
*
* <p> The general format for specifying the <i>scope_id</i> is the following:
*
* <blockquote><i>IPv6-address</i>%<i>scope_id</i></blockquote>
* <p> The IPv6-address is a literal IPv6 address as described above.
* The <i>scope_id</i> refers to an interface on the local system, and it can be
* specified in two ways.
* <ol><li><i>As a numeric identifier.</i> This must be a positive integer
* that identifies the particular interface and scope as understood by the
* system. Usually, the numeric values can be determined through administration
* tools on the system. Each interface may have multiple values, one for each
* scope. If the scope is unspecified, then the default value used is zero.</li>
* <li><i>As a string.</i> This must be the exact string that is returned by
* {@link java.net.NetworkInterface#getName()} for the particular interface in
* question. When an Inet6Address is created in this way, the numeric scope-id
* is determined at the time the object is created by querying the relevant
* NetworkInterface.</li></ol>
*
* <p> Note also, that the numeric <i>scope_id</i> can be retrieved from
* Inet6Address instances returned from the NetworkInterface class. This can be
* used to find out the current scope ids configured on the system.
* @since 1.4
*/
public final
class Inet6Address extends InetAddress {
static final int INADDRSZ = 16;
/*
* cached scope_id - for link-local address use only.
*/
private transient int cached_scope_id; // 0
private class Inet6AddressHolder {
private Inet6AddressHolder() {
ipaddress = new byte[INADDRSZ];
}
private Inet6AddressHolder(
byte[] ipaddress, int scope_id, boolean scope_id_set,
NetworkInterface ifname, boolean scope_ifname_set)
{
this.ipaddress = ipaddress;
this.scope_id = scope_id;
this.scope_id_set = scope_id_set;
this.scope_ifname_set = scope_ifname_set;
this.scope_ifname = ifname;
}
/**
* Holds a 128-bit (16 bytes) IPv6 address.
*/
byte[] ipaddress;
/**
* scope_id. The scope specified when the object is created. If the object
* is created with an interface name, then the scope_id is not determined
* until the time it is needed.
*/
int scope_id; // 0
/**
* This will be set to true when the scope_id field contains a valid
* integer scope_id.
*/
boolean scope_id_set; // false
/**
* scoped interface. scope_id is derived from this as the scope_id of the first
* address whose scope is the same as this address for the named interface.
*/
NetworkInterface scope_ifname; // null
/**
* set if the object is constructed with a scoped
* interface instead of a numeric scope id.
*/
boolean scope_ifname_set; // false;
void setAddr(byte addr[]) {
if (addr.length == INADDRSZ) { // normal IPv6 address
System.arraycopy(addr, 0, ipaddress, 0, INADDRSZ);
}
}
void init(byte addr[], int scope_id) {
setAddr(addr);
if (scope_id >= 0) {
this.scope_id = scope_id;
this.scope_id_set = true;
}
}
void init(byte addr[], NetworkInterface nif)
throws UnknownHostException
{
setAddr(addr);
if (nif != null) {
this.scope_id = deriveNumericScope(ipaddress, nif);
this.scope_id_set = true;
this.scope_ifname = nif;
this.scope_ifname_set = true;
}
}
String getHostAddress() {
String s = numericToTextFormat(ipaddress);
if (scope_ifname != null) { /* must check this first */
s = s + "%" + scope_ifname.getName();
} else if (scope_id_set) {
s = s + "%" + scope_id;
}
return s;
}
public boolean equals(Object o) {
if (! (o instanceof Inet6AddressHolder)) {
return false;
}
Inet6AddressHolder that = (Inet6AddressHolder)o;
return Arrays.equals(this.ipaddress, that.ipaddress);
}
public int hashCode() {
if (ipaddress != null) {
int hash = 0;
int i=0;
while (i<INADDRSZ) {
int j=0;
int component=0;
while (j<4 && i<INADDRSZ) {
component = (component << 8) + ipaddress[i];
j++;
i++;
}
hash += component;
}
return hash;
} else {
return 0;
}
}
boolean isIPv4CompatibleAddress() {
if ((ipaddress[0] == 0x00) && (ipaddress[1] == 0x00) &&
(ipaddress[2] == 0x00) && (ipaddress[3] == 0x00) &&
(ipaddress[4] == 0x00) && (ipaddress[5] == 0x00) &&
(ipaddress[6] == 0x00) && (ipaddress[7] == 0x00) &&
(ipaddress[8] == 0x00) && (ipaddress[9] == 0x00) &&
(ipaddress[10] == 0x00) && (ipaddress[11] == 0x00)) {
return true;
}
return false;
}
boolean isMulticastAddress() {
return ((ipaddress[0] & 0xff) == 0xff);
}
boolean isAnyLocalAddress() {
byte test = 0x00;
for (int i = 0; i < INADDRSZ; i++) {
test |= ipaddress[i];
}
return (test == 0x00);
}
boolean isLoopbackAddress() {
byte test = 0x00;
for (int i = 0; i < 15; i++) {
test |= ipaddress[i];
}
return (test == 0x00) && (ipaddress[15] == 0x01);
}
boolean isLinkLocalAddress() {
return ((ipaddress[0] & 0xff) == 0xfe
&& (ipaddress[1] & 0xc0) == 0x80);
}
boolean isSiteLocalAddress() {
return ((ipaddress[0] & 0xff) == 0xfe
&& (ipaddress[1] & 0xc0) == 0xc0);
}
boolean isMCGlobal() {
return ((ipaddress[0] & 0xff) == 0xff
&& (ipaddress[1] & 0x0f) == 0x0e);
}
boolean isMCNodeLocal() {
return ((ipaddress[0] & 0xff) == 0xff
&& (ipaddress[1] & 0x0f) == 0x01);
}
boolean isMCLinkLocal() {
return ((ipaddress[0] & 0xff) == 0xff
&& (ipaddress[1] & 0x0f) == 0x02);
}
boolean isMCSiteLocal() {
return ((ipaddress[0] & 0xff) == 0xff
&& (ipaddress[1] & 0x0f) == 0x05);
}
boolean isMCOrgLocal() {
return ((ipaddress[0] & 0xff) == 0xff
&& (ipaddress[1] & 0x0f) == 0x08);
}
}
private final transient Inet6AddressHolder holder6;
private static final long serialVersionUID = 6880410070516793377L;
// Perform native initialization
static { init(); }
Inet6Address() {
super();
holder.init(null, IPv6);
holder6 = new Inet6AddressHolder();
}
/* checking of value for scope_id should be done by caller
* scope_id must be >= 0, or -1 to indicate not being set
*/
Inet6Address(String hostName, byte addr[], int scope_id) {
holder.init(hostName, IPv6);
holder6 = new Inet6AddressHolder();
holder6.init(addr, scope_id);
}
Inet6Address(String hostName, byte addr[]) {
holder6 = new Inet6AddressHolder();
try {
initif (hostName, addr, null);
} catch (UnknownHostException e) {} /* cant happen if ifname is null */
}
Inet6Address (String hostName, byte addr[], NetworkInterface nif)
throws UnknownHostException
{
holder6 = new Inet6AddressHolder();
initif (hostName, addr, nif);
}
Inet6Address (String hostName, byte addr[], String ifname)
throws UnknownHostException
{
holder6 = new Inet6AddressHolder();
initstr (hostName, addr, ifname);
}
/**
* Create an Inet6Address in the exact manner of {@link
* InetAddress#getByAddress(String,byte[])} except that the IPv6 scope_id is
* set to the value corresponding to the given interface for the address
* type specified in {@code addr}. The call will fail with an
* UnknownHostException if the given interface does not have a numeric
* scope_id assigned for the given address type (eg. link-local or site-local).
* See <a href="Inet6Address.html#scoped">here</a> for a description of IPv6
* scoped addresses.
*
* @param host the specified host
* @param addr the raw IP address in network byte order
* @param nif an interface this address must be associated with.
* @return an Inet6Address object created from the raw IP address.
* @throws UnknownHostException
* if IP address is of illegal length, or if the interface does not
* have a numeric scope_id assigned for the given address type.
*
* @since 1.5
*/
public static Inet6Address getByAddress(String host, byte[] addr,
NetworkInterface nif)
throws UnknownHostException
{
if (host != null && host.length() > 0 && host.charAt(0) == '[') {
if (host.charAt(host.length()-1) == ']') {
host = host.substring(1, host.length() -1);
}
}
if (addr != null) {
if (addr.length == Inet6Address.INADDRSZ) {
return new Inet6Address(host, addr, nif);
}
}
throw new UnknownHostException("addr is of illegal length");
}
/**
* Create an Inet6Address in the exact manner of {@link
* InetAddress#getByAddress(String,byte[])} except that the IPv6 scope_id is
* set to the given numeric value. The scope_id is not checked to determine
* if it corresponds to any interface on the system.
* See <a href="Inet6Address.html#scoped">here</a> for a description of IPv6
* scoped addresses.
*
* @param host the specified host
* @param addr the raw IP address in network byte order
* @param scope_id the numeric scope_id for the address.
* @return an Inet6Address object created from the raw IP address.
* @throws UnknownHostException if IP address is of illegal length.
*
* @since 1.5
*/
public static Inet6Address getByAddress(String host, byte[] addr,
int scope_id)
throws UnknownHostException
{
if (host != null && host.length() > 0 && host.charAt(0) == '[') {
if (host.charAt(host.length()-1) == ']') {
host = host.substring(1, host.length() -1);
}
}
if (addr != null) {
if (addr.length == Inet6Address.INADDRSZ) {
return new Inet6Address(host, addr, scope_id);
}
}
throw new UnknownHostException("addr is of illegal length");
}
private void initstr(String hostName, byte addr[], String ifname)
throws UnknownHostException
{
try {
NetworkInterface nif = NetworkInterface.getByName (ifname);
if (nif == null) {
throw new UnknownHostException ("no such interface " + ifname);
}
initif (hostName, addr, nif);
} catch (SocketException e) {
throw new UnknownHostException ("SocketException thrown" + ifname);
}
}
private void initif(String hostName, byte addr[], NetworkInterface nif)
throws UnknownHostException
{
int family = -1;
holder6.init(addr, nif);
if (addr.length == INADDRSZ) { // normal IPv6 address
family = IPv6;
}
holder.init(hostName, family);
}
/* check the two Ipv6 addresses and return false if they are both
* non global address types, but not the same.
* (ie. one is sitelocal and the other linklocal)
* return true otherwise.
*/
private static boolean isDifferentLocalAddressType(
byte[] thisAddr, byte[] otherAddr) {
if (Inet6Address.isLinkLocalAddress(thisAddr) &&
!Inet6Address.isLinkLocalAddress(otherAddr)) {
return false;
}
if (Inet6Address.isSiteLocalAddress(thisAddr) &&
!Inet6Address.isSiteLocalAddress(otherAddr)) {
return false;
}
return true;
}
private static int deriveNumericScope (byte[] thisAddr, NetworkInterface ifc) throws UnknownHostException {
Enumeration<InetAddress> addresses = ifc.getInetAddresses();
while (addresses.hasMoreElements()) {
InetAddress addr = addresses.nextElement();
if (!(addr instanceof Inet6Address)) {
continue;
}
Inet6Address ia6_addr = (Inet6Address)addr;
/* check if site or link local prefixes match */
if (!isDifferentLocalAddressType(thisAddr, ia6_addr.getAddress())){
/* type not the same, so carry on searching */
continue;
}
/* found a matching address - return its scope_id */
return ia6_addr.getScopeId();
}
throw new UnknownHostException ("no scope_id found");
}
private int deriveNumericScope (String ifname) throws UnknownHostException {
Enumeration<NetworkInterface> en;
try {
en = NetworkInterface.getNetworkInterfaces();
} catch (SocketException e) {
throw new UnknownHostException ("could not enumerate local network interfaces");
}
while (en.hasMoreElements()) {
NetworkInterface ifc = en.nextElement();
if (ifc.getName().equals (ifname)) {
return deriveNumericScope(holder6.ipaddress, ifc);
}
}
throw new UnknownHostException ("No matching address found for interface : " +ifname);
}
/**
* @serialField ipaddress byte[]
* @serialField scope_id int
* @serialField scope_id_set boolean
* @serialField scope_ifname_set boolean
* @serialField ifname String
*/
private static final ObjectStreamField[] serialPersistentFields = {
new ObjectStreamField("ipaddress", byte[].class),
new ObjectStreamField("scope_id", int.class),
new ObjectStreamField("scope_id_set", boolean.class),
new ObjectStreamField("scope_ifname_set", boolean.class),
new ObjectStreamField("ifname", String.class)
};
private static final jdk.internal.misc.Unsafe UNSAFE
= jdk.internal.misc.Unsafe.getUnsafe();
private static final long FIELDS_OFFSET = UNSAFE.objectFieldOffset(
Inet6Address.class, "holder6");
/**
* restore the state of this object from stream
* including the scope information, only if the
* scoped interface name is valid on this system
*/
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException {
NetworkInterface scope_ifname = null;
if (getClass().getClassLoader() != null) {
throw new SecurityException ("invalid address type");
}
ObjectInputStream.GetField gf = s.readFields();
byte[] ipaddress = (byte[])gf.get("ipaddress", null);
int scope_id = gf.get("scope_id", -1);
boolean scope_id_set = gf.get("scope_id_set", false);
boolean scope_ifname_set = gf.get("scope_ifname_set", false);
String ifname = (String)gf.get("ifname", null);
if (ifname != null && !"".equals (ifname)) {
try {
scope_ifname = NetworkInterface.getByName(ifname);
if (scope_ifname == null) {
/* the interface does not exist on this system, so we clear
* the scope information completely */
scope_id_set = false;
scope_ifname_set = false;
scope_id = 0;
} else {
scope_ifname_set = true;
try {
scope_id = deriveNumericScope (ipaddress, scope_ifname);
} catch (UnknownHostException e) {
// typically should not happen, but it may be that
// the machine being used for deserialization has
// the same interface name but without IPv6 configured.
}
}
} catch (SocketException e) {}
}
/* if ifname was not supplied, then the numeric info is used */
ipaddress = ipaddress.clone();
// Check that our invariants are satisfied
if (ipaddress.length != INADDRSZ) {
throw new InvalidObjectException("invalid address length: "+
ipaddress.length);
}
if (holder.getFamily() != IPv6) {
throw new InvalidObjectException("invalid address family type");
}
Inet6AddressHolder h = new Inet6AddressHolder(
ipaddress, scope_id, scope_id_set, scope_ifname, scope_ifname_set
);
UNSAFE.putObject(this, FIELDS_OFFSET, h);
}
/**
* default behavior is overridden in order to write the
* scope_ifname field as a String, rather than a NetworkInterface
* which is not serializable
*/
private synchronized void writeObject(ObjectOutputStream s)
throws IOException
{
String ifname = null;
if (holder6.scope_ifname != null) {
ifname = holder6.scope_ifname.getName();
holder6.scope_ifname_set = true;
}
ObjectOutputStream.PutField pfields = s.putFields();
pfields.put("ipaddress", holder6.ipaddress);
pfields.put("scope_id", holder6.scope_id);
pfields.put("scope_id_set", holder6.scope_id_set);
pfields.put("scope_ifname_set", holder6.scope_ifname_set);
pfields.put("ifname", ifname);
s.writeFields();
}
/**
* Utility routine to check if the InetAddress is an IP multicast
* address. 11111111 at the start of the address identifies the
* address as being a multicast address.
*
* @return a {@code boolean} indicating if the InetAddress is an IP
* multicast address
*/
@Override
public boolean isMulticastAddress() {
return holder6.isMulticastAddress();
}
/**
* Utility routine to check if the InetAddress is a wildcard address.
*
* @return a {@code boolean} indicating if the Inetaddress is
* a wildcard address.
*/
@Override
public boolean isAnyLocalAddress() {
return holder6.isAnyLocalAddress();
}
/**
* Utility routine to check if the InetAddress is a loopback address.
*
* @return a {@code boolean} indicating if the InetAddress is a loopback
* address; or false otherwise.
*/
@Override
public boolean isLoopbackAddress() {
return holder6.isLoopbackAddress();
}
/**
* Utility routine to check if the InetAddress is an link local address.
*
* @return a {@code boolean} indicating if the InetAddress is a link local
* address; or false if address is not a link local unicast address.
*/
@Override
public boolean isLinkLocalAddress() {
return holder6.isLinkLocalAddress();
}
/* static version of above */
static boolean isLinkLocalAddress(byte[] ipaddress) {
return ((ipaddress[0] & 0xff) == 0xfe
&& (ipaddress[1] & 0xc0) == 0x80);
}
/**
* Utility routine to check if the InetAddress is a site local address.
*
* @return a {@code boolean} indicating if the InetAddress is a site local
* address; or false if address is not a site local unicast address.
*/
@Override
public boolean isSiteLocalAddress() {
return holder6.isSiteLocalAddress();
}
/* static version of above */
static boolean isSiteLocalAddress(byte[] ipaddress) {
return ((ipaddress[0] & 0xff) == 0xfe
&& (ipaddress[1] & 0xc0) == 0xc0);
}
/**
* Utility routine to check if the multicast address has global scope.
*
* @return a {@code boolean} indicating if the address has is a multicast
* address of global scope, false if it is not of global scope or
* it is not a multicast address
*/
@Override
public boolean isMCGlobal() {
return holder6.isMCGlobal();
}
/**
* Utility routine to check if the multicast address has node scope.
*
* @return a {@code boolean} indicating if the address has is a multicast
* address of node-local scope, false if it is not of node-local
* scope or it is not a multicast address
*/
@Override
public boolean isMCNodeLocal() {
return holder6.isMCNodeLocal();
}
/**
* Utility routine to check if the multicast address has link scope.
*
* @return a {@code boolean} indicating if the address has is a multicast
* address of link-local scope, false if it is not of link-local
* scope or it is not a multicast address
*/
@Override
public boolean isMCLinkLocal() {
return holder6.isMCLinkLocal();
}
/**
* Utility routine to check if the multicast address has site scope.
*
* @return a {@code boolean} indicating if the address has is a multicast
* address of site-local scope, false if it is not of site-local
* scope or it is not a multicast address
*/
@Override
public boolean isMCSiteLocal() {
return holder6.isMCSiteLocal();
}
/**
* Utility routine to check if the multicast address has organization scope.
*
* @return a {@code boolean} indicating if the address has is a multicast
* address of organization-local scope, false if it is not of
* organization-local scope or it is not a multicast address
*/
@Override
public boolean isMCOrgLocal() {
return holder6.isMCOrgLocal();
}
/**
* Returns the raw IP address of this {@code InetAddress} object. The result
* is in network byte order: the highest order byte of the address is in
* {@code getAddress()[0]}.
*
* @return the raw IP address of this object.
*/
@Override
public byte[] getAddress() {
return holder6.ipaddress.clone();
}
/**
* Returns the numeric scopeId, if this instance is associated with
* an interface. If no scoped_id is set, the returned value is zero.
*
* @return the scopeId, or zero if not set.
*
* @since 1.5
*/
public int getScopeId() {
return holder6.scope_id;
}
/**
* Returns the scoped interface, if this instance was created with
* with a scoped interface.
*
* @return the scoped interface, or null if not set.
* @since 1.5
*/
public NetworkInterface getScopedInterface() {
return holder6.scope_ifname;
}
/**
* Returns the IP address string in textual presentation. If the instance
* was created specifying a scope identifier then the scope id is appended
* to the IP address preceded by a "%" (per-cent) character. This can be
* either a numeric value or a string, depending on which was used to create
* the instance.
*
* @return the raw IP address in a string format.
*/
@Override
public String getHostAddress() {
return holder6.getHostAddress();
}
/**
* Returns a hashcode for this IP address.
*
* @return a hash code value for this IP address.
*/
@Override
public int hashCode() {
return holder6.hashCode();
}
/**
* Compares this object against the specified object. The result is {@code
* true} if and only if the argument is not {@code null} and it represents
* the same IP address as this object.
*
* <p> Two instances of {@code InetAddress} represent the same IP address
* if the length of the byte arrays returned by {@code getAddress} is the
* same for both, and each of the array components is the same for the byte
* arrays.
*
* @param obj the object to compare against.
*
* @return {@code true} if the objects are the same; {@code false} otherwise.
*
* @see java.net.InetAddress#getAddress()
*/
@Override
public boolean equals(Object obj) {
if (obj == null || !(obj instanceof Inet6Address))
return false;
Inet6Address inetAddr = (Inet6Address)obj;
return holder6.equals(inetAddr.holder6);
}
/**
* Utility routine to check if the InetAddress is an
* IPv4 compatible IPv6 address.
*
* @return a {@code boolean} indicating if the InetAddress is an IPv4
* compatible IPv6 address; or false if address is IPv4 address.
*/
public boolean isIPv4CompatibleAddress() {
return holder6.isIPv4CompatibleAddress();
}
// Utilities
private static final int INT16SZ = 2;
/**
* Convert IPv6 binary address into presentation (printable) format.
*
* @param src a byte array representing the IPv6 numeric address
* @return a String representing an IPv6 address in
* textual representation format
*/
static String numericToTextFormat(byte[] src) {
StringBuilder sb = new StringBuilder(39);
for (int i = 0; i < (INADDRSZ / INT16SZ); i++) {
sb.append(Integer.toHexString(((src[i<<1]<<8) & 0xff00)
| (src[(i<<1)+1] & 0xff)));
if (i < (INADDRSZ / INT16SZ) -1 ) {
sb.append(":");
}
}
return sb.toString();
}
/**
* Perform class load-time initializations.
*/
private static native void init();
}

View file

@ -0,0 +1,121 @@
/*
* Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.net;
import java.io.IOException;
import static java.net.InetAddress.PREFER_IPV6_VALUE;
import static java.net.InetAddress.PREFER_SYSTEM_VALUE;
/*
* Package private implementation of InetAddressImpl for dual
* IPv4/IPv6 stack.
* <p>
* If InetAddress.preferIPv6Address is true then anyLocalAddress(),
* loopbackAddress(), and localHost() will return IPv6 addresses,
* otherwise IPv4 addresses.
*
* @since 1.4
*/
class Inet6AddressImpl implements InetAddressImpl {
public native String getLocalHostName() throws UnknownHostException;
public native InetAddress[] lookupAllHostAddr(String hostname)
throws UnknownHostException;
public native String getHostByAddr(byte[] addr) throws UnknownHostException;
private native boolean isReachable0(byte[] addr, int scope, int timeout,
byte[] inf, int ttl, int if_scope)
throws IOException;
public boolean isReachable(InetAddress addr, int timeout,
NetworkInterface netif, int ttl)
throws IOException
{
byte[] ifaddr = null;
int scope = -1;
int netif_scope = -1;
if (netif != null) {
/*
* Let's make sure we bind to an address of the proper family.
* Which means same family as addr because at this point it could
* be either an IPv6 address or an IPv4 address (case of a dual
* stack system).
*/
java.util.Enumeration<InetAddress> it = netif.getInetAddresses();
InetAddress inetaddr = null;
while (it.hasMoreElements()) {
inetaddr = it.nextElement();
if (inetaddr.getClass().isInstance(addr)) {
ifaddr = inetaddr.getAddress();
if (inetaddr instanceof Inet6Address) {
netif_scope = ((Inet6Address) inetaddr).getScopeId();
}
break;
}
}
if (ifaddr == null) {
// Interface doesn't support the address family of
// the destination
return false;
}
}
if (addr instanceof Inet6Address)
scope = ((Inet6Address) addr).getScopeId();
return isReachable0(addr.getAddress(), scope, timeout, ifaddr, ttl, netif_scope);
}
public synchronized InetAddress anyLocalAddress() {
if (anyLocalAddress == null) {
if (InetAddress.preferIPv6Address == PREFER_IPV6_VALUE ||
InetAddress.preferIPv6Address == PREFER_SYSTEM_VALUE) {
anyLocalAddress = new Inet6Address();
anyLocalAddress.holder().hostName = "::";
} else {
anyLocalAddress = (new Inet4AddressImpl()).anyLocalAddress();
}
}
return anyLocalAddress;
}
public synchronized InetAddress loopbackAddress() {
if (loopbackAddress == null) {
if (InetAddress.preferIPv6Address == PREFER_IPV6_VALUE ||
InetAddress.preferIPv6Address == PREFER_SYSTEM_VALUE) {
byte[] loopback =
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
loopbackAddress = new Inet6Address("localhost", loopback);
} else {
loopbackAddress = (new Inet4AddressImpl()).loopbackAddress();
}
}
return loopbackAddress;
}
private InetAddress anyLocalAddress;
private InetAddress loopbackAddress;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,30 @@
/*
* 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. 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 java.net;
class InetAddressContainer {
InetAddress addr;
}

View file

@ -0,0 +1,48 @@
/*
* Copyright (c) 2002, 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 java.net;
import java.io.IOException;
/*
* Package private interface to "implementation" used by
* {@link InetAddress}.
* <p>
* See {@link java.net.Inet4AddressImp} and
* {@link java.net.Inet6AddressImp}.
*
* @since 1.4
*/
interface InetAddressImpl {
String getLocalHostName() throws UnknownHostException;
InetAddress[]
lookupAllHostAddr(String hostname) throws UnknownHostException;
String getHostByAddr(byte[] addr) throws UnknownHostException;
InetAddress anyLocalAddress();
InetAddress loopbackAddress();
boolean isReachable(InetAddress addr, int timeout, NetworkInterface netif,
int ttl) throws IOException;
}

View file

@ -0,0 +1,411 @@
/*
* Copyright (c) 2000, 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 java.net;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamException;
import java.io.ObjectStreamField;
/**
*
* This class implements an IP Socket Address (IP address + port number)
* It can also be a pair (hostname + port number), in which case an attempt
* will be made to resolve the hostname. If resolution fails then the address
* is said to be <I>unresolved</I> but can still be used on some circumstances
* like connecting through a proxy.
* <p>
* It provides an immutable object used by sockets for binding, connecting, or
* as returned values.
* <p>
* The <i>wildcard</i> is a special local IP address. It usually means "any"
* and can only be used for {@code bind} operations.
*
* @see java.net.Socket
* @see java.net.ServerSocket
* @since 1.4
*/
public class InetSocketAddress
extends SocketAddress
{
// Private implementation class pointed to by all public methods.
private static class InetSocketAddressHolder {
// The hostname of the Socket Address
private String hostname;
// The IP address of the Socket Address
private InetAddress addr;
// The port number of the Socket Address
private int port;
private InetSocketAddressHolder(String hostname, InetAddress addr, int port) {
this.hostname = hostname;
this.addr = addr;
this.port = port;
}
private int getPort() {
return port;
}
private InetAddress getAddress() {
return addr;
}
private String getHostName() {
if (hostname != null)
return hostname;
if (addr != null)
return addr.getHostName();
return null;
}
private String getHostString() {
if (hostname != null)
return hostname;
if (addr != null) {
if (addr.holder().getHostName() != null)
return addr.holder().getHostName();
else
return addr.getHostAddress();
}
return null;
}
private boolean isUnresolved() {
return addr == null;
}
@Override
public String toString() {
if (isUnresolved()) {
return hostname + ":" + port;
} else {
return addr.toString() + ":" + port;
}
}
@Override
public final boolean equals(Object obj) {
if (obj == null || !(obj instanceof InetSocketAddressHolder))
return false;
InetSocketAddressHolder that = (InetSocketAddressHolder)obj;
boolean sameIP;
if (addr != null)
sameIP = addr.equals(that.addr);
else if (hostname != null)
sameIP = (that.addr == null) &&
hostname.equalsIgnoreCase(that.hostname);
else
sameIP = (that.addr == null) && (that.hostname == null);
return sameIP && (port == that.port);
}
@Override
public final int hashCode() {
if (addr != null)
return addr.hashCode() + port;
if (hostname != null)
return hostname.toLowerCase().hashCode() + port;
return port;
}
}
private final transient InetSocketAddressHolder holder;
private static final long serialVersionUID = 5076001401234631237L;
private static int checkPort(int port) {
if (port < 0 || port > 0xFFFF)
throw new IllegalArgumentException("port out of range:" + port);
return port;
}
private static String checkHost(String hostname) {
if (hostname == null)
throw new IllegalArgumentException("hostname can't be null");
return hostname;
}
/**
* Creates a socket address where the IP address is the wildcard address
* and the port number a specified value.
* <p>
* A valid port value is between 0 and 65535.
* A port number of {@code zero} will let the system pick up an
* ephemeral port in a {@code bind} operation.
*
* @param port The port number
* @throws IllegalArgumentException if the port parameter is outside the specified
* range of valid port values.
*/
public InetSocketAddress(int port) {
this(InetAddress.anyLocalAddress(), port);
}
/**
*
* Creates a socket address from an IP address and a port number.
* <p>
* A valid port value is between 0 and 65535.
* A port number of {@code zero} will let the system pick up an
* ephemeral port in a {@code bind} operation.
* <P>
* A {@code null} address will assign the <i>wildcard</i> address.
*
* @param addr The IP address
* @param port The port number
* @throws IllegalArgumentException if the port parameter is outside the specified
* range of valid port values.
*/
public InetSocketAddress(InetAddress addr, int port) {
holder = new InetSocketAddressHolder(
null,
addr == null ? InetAddress.anyLocalAddress() : addr,
checkPort(port));
}
/**
*
* Creates a socket address from a hostname and a port number.
* <p>
* An attempt will be made to resolve the hostname into an InetAddress.
* If that attempt fails, the address will be flagged as <I>unresolved</I>.
* <p>
* If there is a security manager, its {@code checkConnect} method
* is called with the host name as its argument to check the permission
* to resolve it. This could result in a SecurityException.
* <P>
* A valid port value is between 0 and 65535.
* A port number of {@code zero} will let the system pick up an
* ephemeral port in a {@code bind} operation.
*
* @param hostname the Host name
* @param port The port number
* @throws IllegalArgumentException if the port parameter is outside the range
* of valid port values, or if the hostname parameter is {@code null}.
* @throws SecurityException if a security manager is present and
* permission to resolve the host name is
* denied.
* @see #isUnresolved()
*/
public InetSocketAddress(String hostname, int port) {
checkHost(hostname);
InetAddress addr = null;
String host = null;
try {
addr = InetAddress.getByName(hostname);
} catch(UnknownHostException e) {
host = hostname;
}
holder = new InetSocketAddressHolder(host, addr, checkPort(port));
}
// private constructor for creating unresolved instances
private InetSocketAddress(int port, String hostname) {
holder = new InetSocketAddressHolder(hostname, null, port);
}
/**
*
* Creates an unresolved socket address from a hostname and a port number.
* <p>
* No attempt will be made to resolve the hostname into an InetAddress.
* The address will be flagged as <I>unresolved</I>.
* <p>
* A valid port value is between 0 and 65535.
* A port number of {@code zero} will let the system pick up an
* ephemeral port in a {@code bind} operation.
*
* @param host the Host name
* @param port The port number
* @throws IllegalArgumentException if the port parameter is outside
* the range of valid port values, or if the hostname
* parameter is {@code null}.
* @see #isUnresolved()
* @return an {@code InetSocketAddress} representing the unresolved
* socket address
* @since 1.5
*/
public static InetSocketAddress createUnresolved(String host, int port) {
return new InetSocketAddress(checkPort(port), checkHost(host));
}
/**
* @serialField hostname String
* @serialField addr InetAddress
* @serialField port int
*/
private static final ObjectStreamField[] serialPersistentFields = {
new ObjectStreamField("hostname", String.class),
new ObjectStreamField("addr", InetAddress.class),
new ObjectStreamField("port", int.class)};
private void writeObject(ObjectOutputStream out)
throws IOException
{
// Don't call defaultWriteObject()
ObjectOutputStream.PutField pfields = out.putFields();
pfields.put("hostname", holder.hostname);
pfields.put("addr", holder.addr);
pfields.put("port", holder.port);
out.writeFields();
}
private void readObject(ObjectInputStream in)
throws IOException, ClassNotFoundException
{
// Don't call defaultReadObject()
ObjectInputStream.GetField oisFields = in.readFields();
final String oisHostname = (String)oisFields.get("hostname", null);
final InetAddress oisAddr = (InetAddress)oisFields.get("addr", null);
final int oisPort = oisFields.get("port", -1);
// Check that our invariants are satisfied
checkPort(oisPort);
if (oisHostname == null && oisAddr == null)
throw new InvalidObjectException("hostname and addr " +
"can't both be null");
InetSocketAddressHolder h = new InetSocketAddressHolder(oisHostname,
oisAddr,
oisPort);
UNSAFE.putObject(this, FIELDS_OFFSET, h);
}
private void readObjectNoData()
throws ObjectStreamException
{
throw new InvalidObjectException("Stream data required");
}
private static final jdk.internal.misc.Unsafe UNSAFE
= jdk.internal.misc.Unsafe.getUnsafe();
private static final long FIELDS_OFFSET
= UNSAFE.objectFieldOffset(InetSocketAddress.class, "holder");
/**
* Gets the port number.
*
* @return the port number.
*/
public final int getPort() {
return holder.getPort();
}
/**
*
* Gets the {@code InetAddress}.
*
* @return the InetAdress or {@code null} if it is unresolved.
*/
public final InetAddress getAddress() {
return holder.getAddress();
}
/**
* Gets the {@code hostname}.
* Note: This method may trigger a name service reverse lookup if the
* address was created with a literal IP address.
*
* @return the hostname part of the address.
*/
public final String getHostName() {
return holder.getHostName();
}
/**
* Returns the hostname, or the String form of the address if it
* doesn't have a hostname (it was created using a literal).
* This has the benefit of <b>not</b> attempting a reverse lookup.
*
* @return the hostname, or String representation of the address.
* @since 1.7
*/
public final String getHostString() {
return holder.getHostString();
}
/**
* Checks whether the address has been resolved or not.
*
* @return {@code true} if the hostname couldn't be resolved into
* an {@code InetAddress}.
*/
public final boolean isUnresolved() {
return holder.isUnresolved();
}
/**
* Constructs a string representation of this InetSocketAddress.
* This String is constructed by calling toString() on the InetAddress
* and concatenating the port number (with a colon). If the address
* is unresolved then the part before the colon will only contain the hostname.
*
* @return a string representation of this object.
*/
@Override
public String toString() {
return holder.toString();
}
/**
* Compares this object against the specified object.
* The result is {@code true} if and only if the argument is
* not {@code null} and it represents the same address as
* this object.
* <p>
* Two instances of {@code InetSocketAddress} represent the same
* address if both the InetAddresses (or hostnames if it is unresolved) and port
* numbers are equal.
* If both addresses are unresolved, then the hostname and the port number
* are compared.
*
* Note: Hostnames are case insensitive. e.g. "FooBar" and "foobar" are
* considered equal.
*
* @param obj the object to compare against.
* @return {@code true} if the objects are the same;
* {@code false} otherwise.
* @see java.net.InetAddress#equals(java.lang.Object)
*/
@Override
public final boolean equals(Object obj) {
if (obj == null || !(obj instanceof InetSocketAddress))
return false;
return holder.equals(((InetSocketAddress) obj).holder);
}
/**
* Returns a hashcode for this socket address.
*
* @return a hash code value for this socket address.
*/
@Override
public final int hashCode() {
return holder.hashCode();
}
}

View file

@ -0,0 +1,134 @@
/*
* Copyright (c) 2005, 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 java.net;
/**
* This class represents a Network Interface address. In short it's an
* IP address, a subnet mask and a broadcast address when the address is
* an IPv4 one. An IP address and a network prefix length in the case
* of IPv6 address.
*
* @see java.net.NetworkInterface
* @since 1.6
*/
public class InterfaceAddress {
private InetAddress address = null;
private Inet4Address broadcast = null;
private short maskLength = 0;
/*
* Package private constructor. Can't be built directly, instances are
* obtained through the NetworkInterface class.
*/
InterfaceAddress() {
}
/**
* Returns an {@code InetAddress} for this address.
*
* @return the {@code InetAddress} for this address.
*/
public InetAddress getAddress() {
return address;
}
/**
* Returns an {@code InetAddress} for the broadcast address
* for this InterfaceAddress.
* <p>
* Only IPv4 networks have broadcast address therefore, in the case
* of an IPv6 network, {@code null} will be returned.
*
* @return the {@code InetAddress} representing the broadcast
* address or {@code null} if there is no broadcast address.
*/
public InetAddress getBroadcast() {
return broadcast;
}
/**
* Returns the network prefix length for this address. This is also known
* as the subnet mask in the context of IPv4 addresses.
* Typical IPv4 values would be 8 (255.0.0.0), 16 (255.255.0.0)
* or 24 (255.255.255.0). <p>
* Typical IPv6 values would be 128 (::1/128) or 10 (fe80::203:baff:fe27:1243/10)
*
* @return a {@code short} representing the prefix length for the
* subnet of that address.
*/
public short getNetworkPrefixLength() {
return maskLength;
}
/**
* Compares this object against the specified object.
* The result is {@code true} if and only if the argument is
* not {@code null} and it represents the same interface address as
* this object.
* <p>
* Two instances of {@code InterfaceAddress} represent the same
* address if the InetAddress, the prefix length and the broadcast are
* the same for both.
*
* @param obj the object to compare against.
* @return {@code true} if the objects are the same;
* {@code false} otherwise.
* @see java.net.InterfaceAddress#hashCode()
*/
public boolean equals(Object obj) {
if (!(obj instanceof InterfaceAddress)) {
return false;
}
InterfaceAddress cmp = (InterfaceAddress) obj;
if ( !(address == null ? cmp.address == null : address.equals(cmp.address)) )
return false;
if ( !(broadcast == null ? cmp.broadcast == null : broadcast.equals(cmp.broadcast)) )
return false;
if (maskLength != cmp.maskLength)
return false;
return true;
}
/**
* Returns a hashcode for this Interface address.
*
* @return a hash code value for this Interface address.
*/
public int hashCode() {
return address.hashCode() + ((broadcast != null) ? broadcast.hashCode() : 0) + maskLength;
}
/**
* Converts this Interface address to a {@code String}. The
* string returned is of the form: InetAddress / prefix length [ broadcast address ].
*
* @return a string representation of this Interface address.
*/
public String toString() {
return address + "/" + maskLength + " [" + broadcast + "]";
}
}

View file

@ -0,0 +1,317 @@
/*
* Copyright (c) 1997, 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 java.net;
import java.io.IOException;
import java.util.jar.JarFile;
import java.util.jar.JarEntry;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
import java.security.Permission;
import sun.net.www.ParseUtil;
/**
* A URL Connection to a Java ARchive (JAR) file or an entry in a JAR
* file.
*
* <p>The syntax of a JAR URL is:
*
* <pre>
* jar:&lt;url&gt;!/{entry}
* </pre>
*
* <p>for example:
*
* <p>{@code jar:http://www.foo.com/bar/baz.jar!/COM/foo/Quux.class}
*
* <p>Jar URLs should be used to refer to a JAR file or entries in
* a JAR file. The example above is a JAR URL which refers to a JAR
* entry. If the entry name is omitted, the URL refers to the whole
* JAR file:
*
* {@code jar:http://www.foo.com/bar/baz.jar!/}
*
* <p>Users should cast the generic URLConnection to a
* JarURLConnection when they know that the URL they created is a JAR
* URL, and they need JAR-specific functionality. For example:
*
* <pre>
* URL url = new URL("jar:file:/home/duke/duke.jar!/");
* JarURLConnection jarConnection = (JarURLConnection)url.openConnection();
* Manifest manifest = jarConnection.getManifest();
* </pre>
*
* <p>JarURLConnection instances can only be used to read from JAR files.
* It is not possible to get a {@link java.io.OutputStream} to modify or write
* to the underlying JAR file using this class.
* <p>Examples:
*
* <dl>
*
* <dt>A Jar entry
* <dd>{@code jar:http://www.foo.com/bar/baz.jar!/COM/foo/Quux.class}
*
* <dt>A Jar file
* <dd>{@code jar:http://www.foo.com/bar/baz.jar!/}
*
* <dt>A Jar directory
* <dd>{@code jar:http://www.foo.com/bar/baz.jar!/COM/foo/}
*
* </dl>
*
* <p>{@code !/} is referred to as the <em>separator</em>.
*
* <p>When constructing a JAR url via {@code new URL(context, spec)},
* the following rules apply:
*
* <ul>
*
* <li>if there is no context URL and the specification passed to the
* URL constructor doesn't contain a separator, the URL is considered
* to refer to a JarFile.
*
* <li>if there is a context URL, the context URL is assumed to refer
* to a JAR file or a Jar directory.
*
* <li>if the specification begins with a '/', the Jar directory is
* ignored, and the spec is considered to be at the root of the Jar
* file.
*
* <p>Examples:
*
* <dl>
*
* <dt>context: <b>jar:http://www.foo.com/bar/jar.jar!/</b>,
* spec:<b>baz/entry.txt</b>
*
* <dd>url:<b>jar:http://www.foo.com/bar/jar.jar!/baz/entry.txt</b>
*
* <dt>context: <b>jar:http://www.foo.com/bar/jar.jar!/baz</b>,
* spec:<b>entry.txt</b>
*
* <dd>url:<b>jar:http://www.foo.com/bar/jar.jar!/baz/entry.txt</b>
*
* <dt>context: <b>jar:http://www.foo.com/bar/jar.jar!/baz</b>,
* spec:<b>/entry.txt</b>
*
* <dd>url:<b>jar:http://www.foo.com/bar/jar.jar!/entry.txt</b>
*
* </dl>
*
* </ul>
*
* @see java.net.URL
* @see java.net.URLConnection
*
* @see java.util.jar.JarFile
* @see java.util.jar.JarInputStream
* @see java.util.jar.Manifest
* @see java.util.zip.ZipEntry
*
* @author Benjamin Renaud
* @since 1.2
*/
public abstract class JarURLConnection extends URLConnection {
private URL jarFileURL;
private String entryName;
/**
* The connection to the JAR file URL, if the connection has been
* initiated. This should be set by connect.
*/
protected URLConnection jarFileURLConnection;
/**
* Creates the new JarURLConnection to the specified URL.
* @param url the URL
* @throws MalformedURLException if no legal protocol
* could be found in a specification string or the
* string could not be parsed.
*/
protected JarURLConnection(URL url) throws MalformedURLException {
super(url);
parseSpecs(url);
}
/* get the specs for a given url out of the cache, and compute and
* cache them if they're not there.
*/
private void parseSpecs(URL url) throws MalformedURLException {
String spec = url.getFile();
int separator = spec.indexOf("!/");
/*
* REMIND: we don't handle nested JAR URLs
*/
if (separator == -1) {
throw new MalformedURLException("no !/ found in url spec:" + spec);
}
jarFileURL = new URL(spec.substring(0, separator++));
/*
* The url argument may have had a runtime fragment appended, so
* we need to add a runtime fragment to the jarFileURL to enable
* runtime versioning when the underlying jar file is opened.
*/
if ("runtime".equals(url.getRef())) {
jarFileURL = new URL(jarFileURL, "#runtime");
}
entryName = null;
/* if ! is the last letter of the innerURL, entryName is null */
if (++separator != spec.length()) {
entryName = spec.substring(separator, spec.length());
entryName = ParseUtil.decode (entryName);
}
}
/**
* Returns the URL for the Jar file for this connection.
*
* @return the URL for the Jar file for this connection.
*/
public URL getJarFileURL() {
return jarFileURL;
}
/**
* Return the entry name for this connection. This method
* returns null if the JAR file URL corresponding to this
* connection points to a JAR file and not a JAR file entry.
*
* @return the entry name for this connection, if any.
*/
public String getEntryName() {
return entryName;
}
/**
* Return the JAR file for this connection.
*
* @return the JAR file for this connection. If the connection is
* a connection to an entry of a JAR file, the JAR file object is
* returned
*
* @exception IOException if an IOException occurs while trying to
* connect to the JAR file for this connection.
*
* @see #connect
*/
public abstract JarFile getJarFile() throws IOException;
/**
* Returns the Manifest for this connection, or null if none.
*
* @return the manifest object corresponding to the JAR file object
* for this connection.
*
* @exception IOException if getting the JAR file for this
* connection causes an IOException to be thrown.
*
* @see #getJarFile
*/
public Manifest getManifest() throws IOException {
return getJarFile().getManifest();
}
/**
* Return the JAR entry object for this connection, if any. This
* method returns null if the JAR file URL corresponding to this
* connection points to a JAR file and not a JAR file entry.
*
* @return the JAR entry object for this connection, or null if
* the JAR URL for this connection points to a JAR file.
*
* @exception IOException if getting the JAR file for this
* connection causes an IOException to be thrown.
*
* @see #getJarFile
* @see #getJarEntry
*/
public JarEntry getJarEntry() throws IOException {
return getJarFile().getJarEntry(entryName);
}
/**
* Return the Attributes object for this connection if the URL
* for it points to a JAR file entry, null otherwise.
*
* @return the Attributes object for this connection if the URL
* for it points to a JAR file entry, null otherwise.
*
* @exception IOException if getting the JAR entry causes an
* IOException to be thrown.
*
* @see #getJarEntry
*/
public Attributes getAttributes() throws IOException {
JarEntry e = getJarEntry();
return e != null ? e.getAttributes() : null;
}
/**
* Returns the main Attributes for the JAR file for this
* connection.
*
* @return the main Attributes for the JAR file for this
* connection.
*
* @exception IOException if getting the manifest causes an
* IOException to be thrown.
*
* @see #getJarFile
* @see #getManifest
*/
public Attributes getMainAttributes() throws IOException {
Manifest man = getManifest();
return man != null ? man.getMainAttributes() : null;
}
/**
* Return the Certificate object for this connection if the URL
* for it points to a JAR file entry, null otherwise. This method
* can only be called once
* the connection has been completely verified by reading
* from the input stream until the end of the stream has been
* reached. Otherwise, this method will return {@code null}
*
* @return the Certificate object for this connection if the URL
* for it points to a JAR file entry, null otherwise.
*
* @exception IOException if getting the JAR entry causes an
* IOException to be thrown.
*
* @see #getJarEntry
*/
public java.security.cert.Certificate[] getCertificates()
throws IOException
{
JarEntry e = getJarEntry();
return e != null ? e.getCertificates() : null;
}
}

View file

@ -0,0 +1,56 @@
/*
* Copyright (c) 1995, 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 java.net;
import java.io.IOException;
/**
* Thrown to indicate that a malformed URL has occurred. Either no
* legal protocol could be found in a specification string or the
* string could not be parsed.
*
* @author Arthur van Hoff
* @since 1.0
*/
public class MalformedURLException extends IOException {
private static final long serialVersionUID = -182787522200415866L;
/**
* Constructs a {@code MalformedURLException} with no detail message.
*/
public MalformedURLException() {
}
/**
* Constructs a {@code MalformedURLException} with the
* specified detail message.
*
* @param msg the detail message.
*/
public MalformedURLException(String msg) {
super(msg);
}
}

View file

@ -0,0 +1,735 @@
/*
* Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.net;
import java.io.IOException;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Set;
/**
* The multicast datagram socket class is useful for sending
* and receiving IP multicast packets. A MulticastSocket is
* a (UDP) DatagramSocket, with additional capabilities for
* joining "groups" of other multicast hosts on the internet.
* <P>
* A multicast group is specified by a class D IP address
* and by a standard UDP port number. Class D IP addresses
* are in the range <CODE>224.0.0.0</CODE> to <CODE>239.255.255.255</CODE>,
* inclusive. The address 224.0.0.0 is reserved and should not be used.
* <P>
* One would join a multicast group by first creating a MulticastSocket
* with the desired port, then invoking the
* <CODE>joinGroup(InetAddress groupAddr)</CODE>
* method:
* <PRE>
* // join a Multicast group and send the group salutations
* ...
* String msg = "Hello";
* InetAddress group = InetAddress.getByName("228.5.6.7");
* MulticastSocket s = new MulticastSocket(6789);
* s.joinGroup(group);
* DatagramPacket hi = new DatagramPacket(msg.getBytes(), msg.length(),
* group, 6789);
* s.send(hi);
* // get their responses!
* byte[] buf = new byte[1000];
* DatagramPacket recv = new DatagramPacket(buf, buf.length);
* s.receive(recv);
* ...
* // OK, I'm done talking - leave the group...
* s.leaveGroup(group);
* </PRE>
*
* When one sends a message to a multicast group, <B>all</B> subscribing
* recipients to that host and port receive the message (within the
* time-to-live range of the packet, see below). The socket needn't
* be a member of the multicast group to send messages to it.
* <P>
* When a socket subscribes to a multicast group/port, it receives
* datagrams sent by other hosts to the group/port, as do all other
* members of the group and port. A socket relinquishes membership
* in a group by the leaveGroup(InetAddress addr) method. <B>
* Multiple MulticastSocket's</B> may subscribe to a multicast group
* and port concurrently, and they will all receive group datagrams.
* <P>
* Currently applets are not allowed to use multicast sockets.
*
* @author Pavani Diwanji
* @since 1.1
*/
public
class MulticastSocket extends DatagramSocket {
/**
* Used on some platforms to record if an outgoing interface
* has been set for this socket.
*/
private boolean interfaceSet;
/**
* Create a multicast socket.
*
* <p>
* If there is a security manager, its {@code checkListen} method is first
* called with 0 as its argument to ensure the operation is allowed. This
* could result in a SecurityException.
* <p>
* When the socket is created the
* {@link DatagramSocket#setReuseAddress(boolean)} method is called to
* enable the SO_REUSEADDR socket option.
*
* @exception IOException if an I/O exception occurs while creating the
* MulticastSocket
* @exception SecurityException if a security manager exists and its
* {@code checkListen} method doesn't allow the operation.
* @see SecurityManager#checkListen
* @see java.net.DatagramSocket#setReuseAddress(boolean)
* @see java.net.DatagramSocketImpl#setOption(SocketOption, Object)
*/
public MulticastSocket() throws IOException {
this(new InetSocketAddress(0));
}
/**
* Create a multicast socket and bind it to a specific port.
*
* <p>If there is a security manager,
* its {@code checkListen} method is first called
* with the {@code port} argument
* as its argument to ensure the operation is allowed.
* This could result in a SecurityException.
* <p>
* When the socket is created the
* {@link DatagramSocket#setReuseAddress(boolean)} method is
* called to enable the SO_REUSEADDR socket option.
*
* @param port port to use
* @exception IOException if an I/O exception occurs
* while creating the MulticastSocket
* @exception SecurityException if a security manager exists and its
* {@code checkListen} method doesn't allow the operation.
* @see SecurityManager#checkListen
* @see java.net.DatagramSocket#setReuseAddress(boolean)
*/
public MulticastSocket(int port) throws IOException {
this(new InetSocketAddress(port));
}
/**
* Create a MulticastSocket bound to the specified socket address.
* <p>
* Or, if the address is {@code null}, create an unbound socket.
*
* <p>If there is a security manager,
* its {@code checkListen} method is first called
* with the SocketAddress port as its argument to ensure the operation is allowed.
* This could result in a SecurityException.
* <p>
* When the socket is created the
* {@link DatagramSocket#setReuseAddress(boolean)} method is
* called to enable the SO_REUSEADDR socket option.
*
* @param bindaddr Socket address to bind to, or {@code null} for
* an unbound socket.
* @exception IOException if an I/O exception occurs
* while creating the MulticastSocket
* @exception SecurityException if a security manager exists and its
* {@code checkListen} method doesn't allow the operation.
* @see SecurityManager#checkListen
* @see java.net.DatagramSocket#setReuseAddress(boolean)
*
* @since 1.4
*/
public MulticastSocket(SocketAddress bindaddr) throws IOException {
super((SocketAddress) null);
// Enable SO_REUSEADDR before binding
setReuseAddress(true);
if (bindaddr != null) {
try {
bind(bindaddr);
} finally {
if (!isBound()) {
close();
}
}
}
}
/**
* The lock on the socket's TTL. This is for set/getTTL and
* send(packet,ttl).
*/
private Object ttlLock = new Object();
/**
* The lock on the socket's interface - used by setInterface
* and getInterface
*/
private Object infLock = new Object();
/**
* The "last" interface set by setInterface on this MulticastSocket
*/
private InetAddress infAddress = null;
/**
* Set the default time-to-live for multicast packets sent out
* on this {@code MulticastSocket} in order to control the
* scope of the multicasts.
*
* <p>The ttl is an <b>unsigned</b> 8-bit quantity, and so <B>must</B> be
* in the range {@code 0 <= ttl <= 0xFF }.
*
* @param ttl the time-to-live
* @exception IOException if an I/O exception occurs
* while setting the default time-to-live value
* @deprecated use the setTimeToLive method instead, which uses
* <b>int</b> instead of <b>byte</b> as the type for ttl.
* @see #getTTL()
*/
@Deprecated
public void setTTL(byte ttl) throws IOException {
if (isClosed())
throw new SocketException("Socket is closed");
getImpl().setTTL(ttl);
}
/**
* Set the default time-to-live for multicast packets sent out
* on this {@code MulticastSocket} in order to control the
* scope of the multicasts.
*
* <P> The ttl <B>must</B> be in the range {@code 0 <= ttl <=
* 255} or an {@code IllegalArgumentException} will be thrown.
* Multicast packets sent with a TTL of {@code 0} are not transmitted
* on the network but may be delivered locally.
*
* @param ttl
* the time-to-live
*
* @throws IOException
* if an I/O exception occurs while setting the
* default time-to-live value
*
* @see #getTimeToLive()
*/
public void setTimeToLive(int ttl) throws IOException {
if (ttl < 0 || ttl > 255) {
throw new IllegalArgumentException("ttl out of range");
}
if (isClosed())
throw new SocketException("Socket is closed");
getImpl().setTimeToLive(ttl);
}
/**
* Get the default time-to-live for multicast packets sent out on
* the socket.
*
* @exception IOException if an I/O exception occurs
* while getting the default time-to-live value
* @return the default time-to-live value
* @deprecated use the getTimeToLive method instead, which returns
* an <b>int</b> instead of a <b>byte</b>.
* @see #setTTL(byte)
*/
@Deprecated
public byte getTTL() throws IOException {
if (isClosed())
throw new SocketException("Socket is closed");
return getImpl().getTTL();
}
/**
* Get the default time-to-live for multicast packets sent out on
* the socket.
* @exception IOException if an I/O exception occurs while
* getting the default time-to-live value
* @return the default time-to-live value
* @see #setTimeToLive(int)
*/
public int getTimeToLive() throws IOException {
if (isClosed())
throw new SocketException("Socket is closed");
return getImpl().getTimeToLive();
}
/**
* Joins a multicast group. Its behavior may be affected by
* {@code setInterface} or {@code setNetworkInterface}.
*
* <p>If there is a security manager, this method first
* calls its {@code checkMulticast} method
* with the {@code mcastaddr} argument
* as its argument.
*
* @param mcastaddr is the multicast address to join
*
* @exception IOException if there is an error joining, or when the address
* is not a multicast address, or the platform does not support
* multicasting
* @exception SecurityException if a security manager exists and its
* {@code checkMulticast} method doesn't allow the join.
*
* @see SecurityManager#checkMulticast(InetAddress)
*/
public void joinGroup(InetAddress mcastaddr) throws IOException {
if (isClosed()) {
throw new SocketException("Socket is closed");
}
checkAddress(mcastaddr, "joinGroup");
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkMulticast(mcastaddr);
}
if (!mcastaddr.isMulticastAddress()) {
throw new SocketException("Not a multicast address");
}
/**
* required for some platforms where it's not possible to join
* a group without setting the interface first.
*/
NetworkInterface defaultInterface = NetworkInterface.getDefault();
if (!interfaceSet && defaultInterface != null) {
setNetworkInterface(defaultInterface);
}
getImpl().join(mcastaddr);
}
/**
* Leave a multicast group. Its behavior may be affected by
* {@code setInterface} or {@code setNetworkInterface}.
*
* <p>If there is a security manager, this method first
* calls its {@code checkMulticast} method
* with the {@code mcastaddr} argument
* as its argument.
*
* @param mcastaddr is the multicast address to leave
* @exception IOException if there is an error leaving
* or when the address is not a multicast address.
* @exception SecurityException if a security manager exists and its
* {@code checkMulticast} method doesn't allow the operation.
*
* @see SecurityManager#checkMulticast(InetAddress)
*/
public void leaveGroup(InetAddress mcastaddr) throws IOException {
if (isClosed()) {
throw new SocketException("Socket is closed");
}
checkAddress(mcastaddr, "leaveGroup");
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkMulticast(mcastaddr);
}
if (!mcastaddr.isMulticastAddress()) {
throw new SocketException("Not a multicast address");
}
getImpl().leave(mcastaddr);
}
/**
* Joins the specified multicast group at the specified interface.
*
* <p>If there is a security manager, this method first
* calls its {@code checkMulticast} method
* with the {@code mcastaddr} argument
* as its argument.
*
* @param mcastaddr is the multicast address to join
* @param netIf specifies the local interface to receive multicast
* datagram packets, or <i>null</i> to defer to the interface set by
* {@link MulticastSocket#setInterface(InetAddress)} or
* {@link MulticastSocket#setNetworkInterface(NetworkInterface)}
*
* @exception IOException if there is an error joining, or when the address
* is not a multicast address, or the platform does not support
* multicasting
* @exception SecurityException if a security manager exists and its
* {@code checkMulticast} method doesn't allow the join.
* @throws IllegalArgumentException if mcastaddr is null or is a
* SocketAddress subclass not supported by this socket
*
* @see SecurityManager#checkMulticast(InetAddress)
* @since 1.4
*/
public void joinGroup(SocketAddress mcastaddr, NetworkInterface netIf)
throws IOException {
if (isClosed())
throw new SocketException("Socket is closed");
if (mcastaddr == null || !(mcastaddr instanceof InetSocketAddress))
throw new IllegalArgumentException("Unsupported address type");
if (oldImpl)
throw new UnsupportedOperationException();
checkAddress(((InetSocketAddress)mcastaddr).getAddress(), "joinGroup");
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkMulticast(((InetSocketAddress)mcastaddr).getAddress());
}
if (!((InetSocketAddress)mcastaddr).getAddress().isMulticastAddress()) {
throw new SocketException("Not a multicast address");
}
getImpl().joinGroup(mcastaddr, netIf);
}
/**
* Leave a multicast group on a specified local interface.
*
* <p>If there is a security manager, this method first
* calls its {@code checkMulticast} method
* with the {@code mcastaddr} argument
* as its argument.
*
* @param mcastaddr is the multicast address to leave
* @param netIf specifies the local interface or <i>null</i> to defer
* to the interface set by
* {@link MulticastSocket#setInterface(InetAddress)} or
* {@link MulticastSocket#setNetworkInterface(NetworkInterface)}
* @exception IOException if there is an error leaving
* or when the address is not a multicast address.
* @exception SecurityException if a security manager exists and its
* {@code checkMulticast} method doesn't allow the operation.
* @throws IllegalArgumentException if mcastaddr is null or is a
* SocketAddress subclass not supported by this socket
*
* @see SecurityManager#checkMulticast(InetAddress)
* @since 1.4
*/
public void leaveGroup(SocketAddress mcastaddr, NetworkInterface netIf)
throws IOException {
if (isClosed())
throw new SocketException("Socket is closed");
if (mcastaddr == null || !(mcastaddr instanceof InetSocketAddress))
throw new IllegalArgumentException("Unsupported address type");
if (oldImpl)
throw new UnsupportedOperationException();
checkAddress(((InetSocketAddress)mcastaddr).getAddress(), "leaveGroup");
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkMulticast(((InetSocketAddress)mcastaddr).getAddress());
}
if (!((InetSocketAddress)mcastaddr).getAddress().isMulticastAddress()) {
throw new SocketException("Not a multicast address");
}
getImpl().leaveGroup(mcastaddr, netIf);
}
/**
* Set the multicast network interface used by methods
* whose behavior would be affected by the value of the
* network interface. Useful for multihomed hosts.
* @param inf the InetAddress
* @exception SocketException if there is an error in
* the underlying protocol, such as a TCP error.
* @see #getInterface()
*/
public void setInterface(InetAddress inf) throws SocketException {
if (isClosed()) {
throw new SocketException("Socket is closed");
}
checkAddress(inf, "setInterface");
synchronized (infLock) {
getImpl().setOption(SocketOptions.IP_MULTICAST_IF, inf);
infAddress = inf;
interfaceSet = true;
}
}
/**
* Retrieve the address of the network interface used for
* multicast packets.
*
* @return An {@code InetAddress} representing
* the address of the network interface used for
* multicast packets.
*
* @exception SocketException if there is an error in
* the underlying protocol, such as a TCP error.
*
* @see #setInterface(java.net.InetAddress)
*/
public InetAddress getInterface() throws SocketException {
if (isClosed()) {
throw new SocketException("Socket is closed");
}
synchronized (infLock) {
InetAddress ia =
(InetAddress)getImpl().getOption(SocketOptions.IP_MULTICAST_IF);
/**
* No previous setInterface or interface can be
* set using setNetworkInterface
*/
if (infAddress == null) {
return ia;
}
/**
* Same interface set with setInterface?
*/
if (ia.equals(infAddress)) {
return ia;
}
/**
* Different InetAddress from what we set with setInterface
* so enumerate the current interface to see if the
* address set by setInterface is bound to this interface.
*/
try {
NetworkInterface ni = NetworkInterface.getByInetAddress(ia);
Enumeration<InetAddress> addrs = ni.getInetAddresses();
while (addrs.hasMoreElements()) {
InetAddress addr = addrs.nextElement();
if (addr.equals(infAddress)) {
return infAddress;
}
}
/**
* No match so reset infAddress to indicate that the
* interface has changed via means
*/
infAddress = null;
return ia;
} catch (Exception e) {
return ia;
}
}
}
/**
* Specify the network interface for outgoing multicast datagrams
* sent on this socket.
*
* @param netIf the interface
* @exception SocketException if there is an error in
* the underlying protocol, such as a TCP error.
* @see #getNetworkInterface()
* @since 1.4
*/
public void setNetworkInterface(NetworkInterface netIf)
throws SocketException {
synchronized (infLock) {
getImpl().setOption(SocketOptions.IP_MULTICAST_IF2, netIf);
infAddress = null;
interfaceSet = true;
}
}
/**
* Get the multicast network interface set.
*
* @exception SocketException if there is an error in
* the underlying protocol, such as a TCP error.
* @return the multicast {@code NetworkInterface} currently set
* @see #setNetworkInterface(NetworkInterface)
* @since 1.4
*/
public NetworkInterface getNetworkInterface() throws SocketException {
NetworkInterface ni
= (NetworkInterface)getImpl().getOption(SocketOptions.IP_MULTICAST_IF2);
if ((ni.getIndex() == 0) || (ni.getIndex() == -1)) {
InetAddress[] addrs = new InetAddress[1];
addrs[0] = InetAddress.anyLocalAddress();
return new NetworkInterface(addrs[0].getHostName(), 0, addrs);
} else {
return ni;
}
}
/**
* Disable/Enable local loopback of multicast datagrams
* The option is used by the platform's networking code as a hint
* for setting whether multicast data will be looped back to
* the local socket.
*
* <p>Because this option is a hint, applications that want to
* verify what loopback mode is set to should call
* {@link #getLoopbackMode()}
* @param disable {@code true} to disable the LoopbackMode
* @throws SocketException if an error occurs while setting the value
* @since 1.4
* @see #getLoopbackMode
*/
public void setLoopbackMode(boolean disable) throws SocketException {
getImpl().setOption(SocketOptions.IP_MULTICAST_LOOP, Boolean.valueOf(disable));
}
/**
* Get the setting for local loopback of multicast datagrams.
*
* @throws SocketException if an error occurs while getting the value
* @return true if the LoopbackMode has been disabled
* @since 1.4
* @see #setLoopbackMode
*/
public boolean getLoopbackMode() throws SocketException {
return ((Boolean)getImpl().getOption(SocketOptions.IP_MULTICAST_LOOP)).booleanValue();
}
/**
* Sends a datagram packet to the destination, with a TTL (time-
* to-live) other than the default for the socket. This method
* need only be used in instances where a particular TTL is desired;
* otherwise it is preferable to set a TTL once on the socket, and
* use that default TTL for all packets. This method does <B>not
* </B> alter the default TTL for the socket. Its behavior may be
* affected by {@code setInterface}.
*
* <p>If there is a security manager, this method first performs some
* security checks. First, if {@code p.getAddress().isMulticastAddress()}
* is true, this method calls the
* security manager's {@code checkMulticast} method
* with {@code p.getAddress()} and {@code ttl} as its arguments.
* If the evaluation of that expression is false,
* this method instead calls the security manager's
* {@code checkConnect} method with arguments
* {@code p.getAddress().getHostAddress()} and
* {@code p.getPort()}. Each call to a security manager method
* could result in a SecurityException if the operation is not allowed.
*
* @param p is the packet to be sent. The packet should contain
* the destination multicast ip address and the data to be sent.
* One does not need to be the member of the group to send
* packets to a destination multicast address.
* @param ttl optional time to live for multicast packet.
* default ttl is 1.
*
* @exception IOException is raised if an error occurs i.e
* error while setting ttl.
* @exception SecurityException if a security manager exists and its
* {@code checkMulticast} or {@code checkConnect}
* method doesn't allow the send.
*
* @deprecated Use the following code or its equivalent instead:
* ......
* int ttl = mcastSocket.getTimeToLive();
* mcastSocket.setTimeToLive(newttl);
* mcastSocket.send(p);
* mcastSocket.setTimeToLive(ttl);
* ......
*
* @see DatagramSocket#send
* @see DatagramSocket#receive
* @see SecurityManager#checkMulticast(java.net.InetAddress, byte)
* @see SecurityManager#checkConnect
*/
@Deprecated
public void send(DatagramPacket p, byte ttl)
throws IOException {
if (isClosed())
throw new SocketException("Socket is closed");
checkAddress(p.getAddress(), "send");
synchronized(ttlLock) {
synchronized(p) {
if (connectState == ST_NOT_CONNECTED) {
// Security manager makes sure that the multicast address
// is allowed one and that the ttl used is less
// than the allowed maxttl.
SecurityManager security = System.getSecurityManager();
if (security != null) {
if (p.getAddress().isMulticastAddress()) {
security.checkMulticast(p.getAddress(), ttl);
} else {
security.checkConnect(p.getAddress().getHostAddress(),
p.getPort());
}
}
} else {
// we're connected
InetAddress packetAddress = null;
packetAddress = p.getAddress();
if (packetAddress == null) {
p.setAddress(connectedAddress);
p.setPort(connectedPort);
} else if ((!packetAddress.equals(connectedAddress)) ||
p.getPort() != connectedPort) {
throw new SecurityException("connected address and packet address" +
" differ");
}
}
byte dttl = getTTL();
try {
if (ttl != dttl) {
// set the ttl
getImpl().setTTL(ttl);
}
// call the datagram method to send
getImpl().send(p);
} finally {
// set it back to default
if (ttl != dttl) {
getImpl().setTTL(dttl);
}
}
} // synch p
} //synch ttl
} //method
private static Set<SocketOption<?>> options;
private static boolean optionsSet = false;
@Override
public Set<SocketOption<?>> supportedOptions() {
synchronized (MulticastSocket.class) {
if (optionsSet) {
return options;
}
try {
DatagramSocketImpl impl = getImpl();
options = Collections.unmodifiableSet(impl.supportedOptions());
} catch (SocketException ex) {
options = Collections.emptySet();
}
optionsSet = true;
return options;
}
}
}

View file

@ -0,0 +1,210 @@
/*
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.net;
import java.security.*;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.StringTokenizer;
/**
* This class is for various network permissions.
* A NetPermission contains a name (also referred to as a "target name") but
* no actions list; you either have the named permission
* or you don't.
* <P>
* The target name is the name of the network permission (see below). The naming
* convention follows the hierarchical property naming convention.
* Also, an asterisk
* may appear at the end of the name, following a ".", or by itself, to
* signify a wildcard match. For example: "foo.*" and "*" signify a wildcard
* match, while "*foo" and "a*b" do not.
* <P>
* The following table lists all the possible NetPermission target names,
* and for each provides a description of what the permission allows
* and a discussion of the risks of granting code the permission.
*
* <table class="striped">
* <caption style="display:none">Permission target name, what the permission allows, and associated risks</caption>
* <thead>
* <tr>
* <th scope="col">Permission Target Name</th>
* <th scope="col">What the Permission Allows</th>
* <th scope="col">Risks of Allowing this Permission</th>
* </tr>
* </thead>
* <tbody>
* <tr>
* <th scope="row">allowHttpTrace</th>
* <td>The ability to use the HTTP TRACE method in HttpURLConnection.</td>
* <td>Malicious code using HTTP TRACE could get access to security sensitive
* information in the HTTP headers (such as cookies) that it might not
* otherwise have access to.</td>
* </tr>
*
* <tr>
* <th scope="row">getCookieHandler</th>
* <td>The ability to get the cookie handler that processes highly
* security sensitive cookie information for an Http session.</td>
* <td>Malicious code can get a cookie handler to obtain access to
* highly security sensitive cookie information. Some web servers
* use cookies to save user private information such as access
* control information, or to track user browsing habit.</td>
* </tr>
*
* <tr>
* <th scope="row">getNetworkInformation</th>
* <td>The ability to retrieve all information about local network interfaces.</td>
* <td>Malicious code can read information about network hardware such as
* MAC addresses, which could be used to construct local IPv6 addresses.</td>
* </tr>
*
* <tr>
* <th scope="row">getProxySelector</th>
* <td>The ability to get the proxy selector used to make decisions
* on which proxies to use when making network connections.</td>
* <td>Malicious code can get a ProxySelector to discover proxy
* hosts and ports on internal networks, which could then become
* targets for attack.</td>
* </tr>
*
* <tr>
* <th scope="row">getResponseCache</th>
* <td>The ability to get the response cache that provides
* access to a local response cache.</td>
* <td>Malicious code getting access to the local response cache
* could access security sensitive information.</td>
* </tr>
*
* <tr>
* <th scope="row">requestPasswordAuthentication</th>
* <td>The ability
* to ask the authenticator registered with the system for
* a password</td>
* <td>Malicious code may steal this password.</td>
* </tr>
*
* <tr>
* <th scope="row">setCookieHandler</th>
* <td>The ability to set the cookie handler that processes highly
* security sensitive cookie information for an Http session.</td>
* <td>Malicious code can set a cookie handler to obtain access to
* highly security sensitive cookie information. Some web servers
* use cookies to save user private information such as access
* control information, or to track user browsing habit.</td>
* </tr>
*
* <tr>
* <th scope="row">setDefaultAuthenticator</th>
* <td>The ability to set the
* way authentication information is retrieved when
* a proxy or HTTP server asks for authentication</td>
* <td>Malicious
* code can set an authenticator that monitors and steals user
* authentication input as it retrieves the input from the user.</td>
* </tr>
*
* <tr>
* <th scope="row">setProxySelector</th>
* <td>The ability to set the proxy selector used to make decisions
* on which proxies to use when making network connections.</td>
* <td>Malicious code can set a ProxySelector that directs network
* traffic to an arbitrary network host.</td>
* </tr>
*
* <tr>
* <th scope="row">setResponseCache</th>
* <td>The ability to set the response cache that provides access to
* a local response cache.</td>
* <td>Malicious code getting access to the local response cache
* could access security sensitive information, or create false
* entries in the response cache.</td>
* </tr>
*
* <tr>
* <th scope="row">specifyStreamHandler</th>
* <td>The ability
* to specify a stream handler when constructing a URL</td>
* <td>Malicious code may create a URL with resources that it would
* normally not have access to (like file:/foo/fum/), specifying a
* stream handler that gets the actual bytes from someplace it does
* have access to. Thus it might be able to trick the system into
* creating a ProtectionDomain/CodeSource for a class even though
* that class really didn't come from that location.</td>
* </tr>
</tbody>
* </table>
*
* @see java.security.BasicPermission
* @see java.security.Permission
* @see java.security.Permissions
* @see java.security.PermissionCollection
* @see java.lang.SecurityManager
*
*
* @author Marianne Mueller
* @author Roland Schemers
* @since 1.2
*/
public final class NetPermission extends BasicPermission {
private static final long serialVersionUID = -8343910153355041693L;
/**
* Creates a new NetPermission with the specified name.
* The name is the symbolic name of the NetPermission, such as
* "setDefaultAuthenticator", etc. An asterisk
* may appear at the end of the name, following a ".", or by itself, to
* signify a wildcard match.
*
* @param name the name of the NetPermission.
*
* @throws NullPointerException if {@code name} is {@code null}.
* @throws IllegalArgumentException if {@code name} is empty.
*/
public NetPermission(String name)
{
super(name);
}
/**
* Creates a new NetPermission object with the specified name.
* The name is the symbolic name of the NetPermission, and the
* actions String is currently unused and should be null.
*
* @param name the name of the NetPermission.
* @param actions should be null.
*
* @throws NullPointerException if {@code name} is {@code null}.
* @throws IllegalArgumentException if {@code name} is empty.
*/
public NetPermission(String name, String actions)
{
super(name, actions);
}
}

View file

@ -0,0 +1,627 @@
/*
* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* 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 java.net;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.NoSuchElementException;
import java.security.AccessController;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
/**
* This class represents a Network Interface made up of a name,
* and a list of IP addresses assigned to this interface.
* It is used to identify the local interface on which a multicast group
* is joined.
*
* Interfaces are normally known by names such as "le0".
*
* @since 1.4
*/
public final class NetworkInterface {
private String name;
private String displayName;
private int index;
private InetAddress addrs[];
private InterfaceAddress bindings[];
private NetworkInterface childs[];
private NetworkInterface parent = null;
private boolean virtual = false;
private static final NetworkInterface defaultInterface;
private static final int defaultIndex; /* index of defaultInterface */
static {
AccessController.doPrivileged(
new java.security.PrivilegedAction<>() {
public Void run() {
System.loadLibrary("net");
return null;
}
});
init();
defaultInterface = DefaultInterface.getDefault();
if (defaultInterface != null) {
defaultIndex = defaultInterface.getIndex();
} else {
defaultIndex = 0;
}
}
/**
* Returns an NetworkInterface object with index set to 0 and name to null.
* Setting such an interface on a MulticastSocket will cause the
* kernel to choose one interface for sending multicast packets.
*
*/
NetworkInterface() {
}
NetworkInterface(String name, int index, InetAddress[] addrs) {
this.name = name;
this.index = index;
this.addrs = addrs;
}
/**
* Get the name of this network interface.
*
* @return the name of this network interface
*/
public String getName() {
return name;
}
/**
* Get an Enumeration with all or a subset of the InetAddresses bound to
* this network interface.
* <p>
* If there is a security manager, its {@code checkConnect}
* method is called for each InetAddress. Only InetAddresses where
* the {@code checkConnect} doesn't throw a SecurityException
* will be returned in the Enumeration. However, if the caller has the
* {@link NetPermission}("getNetworkInformation") permission, then all
* InetAddresses are returned.
*
* @return an Enumeration object with all or a subset of the InetAddresses
* bound to this network interface
* @see #inetAddresses()
*/
public Enumeration<InetAddress> getInetAddresses() {
return enumerationFromArray(getCheckedInetAddresses());
}
/**
* Get a Stream of all or a subset of the InetAddresses bound to this
* network interface.
* <p>
* If there is a security manager, its {@code checkConnect}
* method is called for each InetAddress. Only InetAddresses where
* the {@code checkConnect} doesn't throw a SecurityException will be
* returned in the Stream. However, if the caller has the
* {@link NetPermission}("getNetworkInformation") permission, then all
* InetAddresses are returned.
*
* @return a Stream object with all or a subset of the InetAddresses
* bound to this network interface
* @since 9
*/
public Stream<InetAddress> inetAddresses() {
return streamFromArray(getCheckedInetAddresses());
}
private InetAddress[] getCheckedInetAddresses() {
InetAddress[] local_addrs = new InetAddress[addrs.length];
boolean trusted = true;
SecurityManager sec = System.getSecurityManager();
if (sec != null) {
try {
sec.checkPermission(new NetPermission("getNetworkInformation"));
} catch (SecurityException e) {
trusted = false;
}
}
int i = 0;
for (int j = 0; j < addrs.length; j++) {
try {
if (!trusted) {
sec.checkConnect(addrs[j].getHostAddress(), -1);
}
local_addrs[i++] = addrs[j];
} catch (SecurityException e) { }
}
return Arrays.copyOf(local_addrs, i);
}
/**
* Get a List of all or a subset of the {@code InterfaceAddresses}
* of this network interface.
* <p>
* If there is a security manager, its {@code checkConnect}
* method is called with the InetAddress for each InterfaceAddress.
* Only InterfaceAddresses where the {@code checkConnect} doesn't throw
* a SecurityException will be returned in the List.
*
* @return a {@code List} object with all or a subset of the
* InterfaceAddresss of this network interface
* @since 1.6
*/
public java.util.List<InterfaceAddress> getInterfaceAddresses() {
java.util.List<InterfaceAddress> lst = new java.util.ArrayList<>(1);
if (bindings != null) {
SecurityManager sec = System.getSecurityManager();
for (int j=0; j<bindings.length; j++) {
try {
if (sec != null) {
sec.checkConnect(bindings[j].getAddress().getHostAddress(), -1);
}
lst.add(bindings[j]);
} catch (SecurityException e) { }
}
}
return lst;
}
/**
* Get an Enumeration with all the subinterfaces (also known as virtual
* interfaces) attached to this network interface.
* <p>
* For instance eth0:1 will be a subinterface to eth0.
*
* @return an Enumeration object with all of the subinterfaces
* of this network interface
* @see #subInterfaces()
* @since 1.6
*/
public Enumeration<NetworkInterface> getSubInterfaces() {
return enumerationFromArray(childs);
}
/**
* Get a Stream of all subinterfaces (also known as virtual
* interfaces) attached to this network interface.
*
* @return a Stream object with all of the subinterfaces
* of this network interface
* @since 9
*/
public Stream<NetworkInterface> subInterfaces() {
return streamFromArray(childs);
}
/**
* Returns the parent NetworkInterface of this interface if this is
* a subinterface, or {@code null} if it is a physical
* (non virtual) interface or has no parent.
*
* @return The {@code NetworkInterface} this interface is attached to.
* @since 1.6
*/
public NetworkInterface getParent() {
return parent;
}
/**
* Returns the index of this network interface. The index is an integer greater
* or equal to zero, or {@code -1} for unknown. This is a system specific value
* and interfaces with the same name can have different indexes on different
* machines.
*
* @return the index of this network interface or {@code -1} if the index is
* unknown
* @see #getByIndex(int)
* @since 1.7
*/
public int getIndex() {
return index;
}
/**
* Get the display name of this network interface.
* A display name is a human readable String describing the network
* device.
*
* @return a non-empty string representing the display name of this network
* interface, or null if no display name is available.
*/
public String getDisplayName() {
/* strict TCK conformance */
return "".equals(displayName) ? null : displayName;
}
/**
* Searches for the network interface with the specified name.
*
* @param name
* The name of the network interface.
*
* @return A {@code NetworkInterface} with the specified name,
* or {@code null} if there is no network interface
* with the specified name.
*
* @throws SocketException
* If an I/O error occurs.
*
* @throws NullPointerException
* If the specified name is {@code null}.
*/
public static NetworkInterface getByName(String name) throws SocketException {
if (name == null)
throw new NullPointerException();
return getByName0(name);
}
/**
* Get a network interface given its index.
*
* @param index an integer, the index of the interface
* @return the NetworkInterface obtained from its index, or {@code null} if
* there is no interface with such an index on the system
* @throws SocketException if an I/O error occurs.
* @throws IllegalArgumentException if index has a negative value
* @see #getIndex()
* @since 1.7
*/
public static NetworkInterface getByIndex(int index) throws SocketException {
if (index < 0)
throw new IllegalArgumentException("Interface index can't be negative");
return getByIndex0(index);
}
/**
* Convenience method to search for a network interface that
* has the specified Internet Protocol (IP) address bound to
* it.
* <p>
* If the specified IP address is bound to multiple network
* interfaces it is not defined which network interface is
* returned.
*
* @param addr
* The {@code InetAddress} to search with.
*
* @return A {@code NetworkInterface}
* or {@code null} if there is no network interface
* with the specified IP address.
*
* @throws SocketException
* If an I/O error occurs.
*
* @throws NullPointerException
* If the specified address is {@code null}.
*/
public static NetworkInterface getByInetAddress(InetAddress addr) throws SocketException {
if (addr == null) {
throw new NullPointerException();
}
if (!(addr instanceof Inet4Address || addr instanceof Inet6Address)) {
throw new IllegalArgumentException ("invalid address type");
}
return getByInetAddress0(addr);
}
/**
* Returns an {@code Enumeration} of all the interfaces on this machine. The
* {@code Enumeration} contains at least one element, possibly representing
* a loopback interface that only supports communication between entities on
* this machine.
*
* @apiNote this method can be used in combination with
* {@link #getInetAddresses()} to obtain all IP addresses for this node
*
* @return an Enumeration of NetworkInterfaces found on this machine
* @exception SocketException if an I/O error occurs,
* or if the platform does not have at least one configured
* network interface.
* @see #networkInterfaces()
*/
public static Enumeration<NetworkInterface> getNetworkInterfaces()
throws SocketException {
NetworkInterface[] netifs = getAll();
if (netifs != null && netifs.length > 0) {
return enumerationFromArray(netifs);
} else {
throw new SocketException("No network interfaces configured");
}
}
/**
* Returns a {@code Stream} of all the interfaces on this machine. The
* {@code Stream} contains at least one interface, possibly representing a
* loopback interface that only supports communication between entities on
* this machine.
*
* @apiNote this method can be used in combination with
* {@link #inetAddresses()}} to obtain a stream of all IP addresses for
* this node, for example:
* <pre> {@code
* Stream<InetAddress> addrs = NetworkInterface.networkInterfaces()
* .flatMap(NetworkInterface::inetAddresses);
* }</pre>
*
* @return a Stream of NetworkInterfaces found on this machine
* @exception SocketException if an I/O error occurs,
* or if the platform does not have at least one configured
* network interface.
* @since 9
*/
public static Stream<NetworkInterface> networkInterfaces()
throws SocketException {
NetworkInterface[] netifs = getAll();
if (netifs != null && netifs.length > 0) {
return streamFromArray(netifs);
} else {
throw new SocketException("No network interfaces configured");
}
}
private static <T> Enumeration<T> enumerationFromArray(T[] a) {
return new Enumeration<>() {
int i = 0;
@Override
public T nextElement() {
if (i < a.length) {
return a[i++];
} else {
throw new NoSuchElementException();
}
}
@Override
public boolean hasMoreElements() {
return i < a.length;
}
};
}
private static <T> Stream<T> streamFromArray(T[] a) {
return StreamSupport.stream(
Spliterators.spliterator(
a,
Spliterator.DISTINCT | Spliterator.IMMUTABLE | Spliterator.NONNULL),
false);
}
private static native NetworkInterface[] getAll()
throws SocketException;
private static native NetworkInterface getByName0(String name)
throws SocketException;
private static native NetworkInterface getByIndex0(int index)
throws SocketException;
private static native NetworkInterface getByInetAddress0(InetAddress addr)
throws SocketException;
/**
* Returns whether a network interface is up and running.
*
* @return {@code true} if the interface is up and running.
* @exception SocketException if an I/O error occurs.
* @since 1.6
*/
public boolean isUp() throws SocketException {
return isUp0(name, index);
}
/**
* Returns whether a network interface is a loopback interface.
*
* @return {@code true} if the interface is a loopback interface.
* @exception SocketException if an I/O error occurs.
* @since 1.6
*/
public boolean isLoopback() throws SocketException {
return isLoopback0(name, index);
}
/**
* Returns whether a network interface is a point to point interface.
* A typical point to point interface would be a PPP connection through
* a modem.
*
* @return {@code true} if the interface is a point to point
* interface.
* @exception SocketException if an I/O error occurs.
* @since 1.6
*/
public boolean isPointToPoint() throws SocketException {
return isP2P0(name, index);
}
/**
* Returns whether a network interface supports multicasting or not.
*
* @return {@code true} if the interface supports Multicasting.
* @exception SocketException if an I/O error occurs.
* @since 1.6
*/
public boolean supportsMulticast() throws SocketException {
return supportsMulticast0(name, index);
}
/**
* Returns the hardware address (usually MAC) of the interface if it
* has one and if it can be accessed given the current privileges.
* If a security manager is set, then the caller must have
* the permission {@link NetPermission}("getNetworkInformation").
*
* @return a byte array containing the address, or {@code null} if
* the address doesn't exist, is not accessible or a security
* manager is set and the caller does not have the permission
* NetPermission("getNetworkInformation")
*
* @exception SocketException if an I/O error occurs.
* @since 1.6
*/
public byte[] getHardwareAddress() throws SocketException {
SecurityManager sec = System.getSecurityManager();
if (sec != null) {
try {
sec.checkPermission(new NetPermission("getNetworkInformation"));
} catch (SecurityException e) {
if (!getInetAddresses().hasMoreElements()) {
// don't have connect permission to any local address
return null;
}
}
}
for (InetAddress addr : addrs) {
if (addr instanceof Inet4Address) {
return getMacAddr0(((Inet4Address)addr).getAddress(), name, index);
}
}
return getMacAddr0(null, name, index);
}
/**
* Returns the Maximum Transmission Unit (MTU) of this interface.
*
* @return the value of the MTU for that interface.
* @exception SocketException if an I/O error occurs.
* @since 1.6
*/
public int getMTU() throws SocketException {
return getMTU0(name, index);
}
/**
* Returns whether this interface is a virtual interface (also called
* subinterface).
* Virtual interfaces are, on some systems, interfaces created as a child
* of a physical interface and given different settings (like address or
* MTU). Usually the name of the interface will the name of the parent
* followed by a colon (:) and a number identifying the child since there
* can be several virtual interfaces attached to a single physical
* interface.
*
* @return {@code true} if this interface is a virtual interface.
* @since 1.6
*/
public boolean isVirtual() {
return virtual;
}
private static native boolean isUp0(String name, int ind) throws SocketException;
private static native boolean isLoopback0(String name, int ind) throws SocketException;
private static native boolean supportsMulticast0(String name, int ind) throws SocketException;
private static native boolean isP2P0(String name, int ind) throws SocketException;
private static native byte[] getMacAddr0(byte[] inAddr, String name, int ind) throws SocketException;
private static native int getMTU0(String name, int ind) throws SocketException;
/**
* Compares this object against the specified object.
* The result is {@code true} if and only if the argument is
* not {@code null} and it represents the same NetworkInterface
* as this object.
* <p>
* Two instances of {@code NetworkInterface} represent the same
* NetworkInterface if both name and addrs are the same for both.
*
* @param obj the object to compare against.
* @return {@code true} if the objects are the same;
* {@code false} otherwise.
* @see java.net.InetAddress#getAddress()
*/
public boolean equals(Object obj) {
if (!(obj instanceof NetworkInterface)) {
return false;
}
NetworkInterface that = (NetworkInterface)obj;
if (this.name != null ) {
if (!this.name.equals(that.name)) {
return false;
}
} else {
if (that.name != null) {
return false;
}
}
if (this.addrs == null) {
return that.addrs == null;
} else if (that.addrs == null) {
return false;
}
/* Both addrs not null. Compare number of addresses */
if (this.addrs.length != that.addrs.length) {
return false;
}
InetAddress[] thatAddrs = that.addrs;
int count = thatAddrs.length;
for (int i=0; i<count; i++) {
boolean found = false;
for (int j=0; j<count; j++) {
if (addrs[i].equals(thatAddrs[j])) {
found = true;
break;
}
}
if (!found) {
return false;
}
}
return true;
}
public int hashCode() {
return name == null? 0: name.hashCode();
}
public String toString() {
String result = "name:";
result += name == null? "null": name;
if (displayName != null) {
result += " (" + displayName + ")";
}
return result;
}
private static native void init();
/**
* Returns the default network interface of this system
*
* @return the default interface
*/
static NetworkInterface getDefault() {
return defaultInterface;
}
}

View file

@ -0,0 +1,54 @@
/*
* Copyright (c) 1996, 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. 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 java.net;
/**
* Signals that an error occurred while attempting to connect a
* socket to a remote address and port. Typically, the remote
* host cannot be reached because of an intervening firewall, or
* if an intermediate router is down.
*
* @since 1.1
*/
public class NoRouteToHostException extends SocketException {
private static final long serialVersionUID = -1897550894873493790L;
/**
* Constructs a new NoRouteToHostException with the specified detail
* message as to why the remote host cannot be reached.
* A detail message is a String that gives a specific
* description of this error.
* @param msg the detail message
*/
public NoRouteToHostException(String msg) {
super(msg);
}
/**
* Construct a new NoRouteToHostException with no detailed message.
*/
public NoRouteToHostException() {}
}

View file

@ -0,0 +1,81 @@
/*
* Copyright (c) 1997, 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 java.net;
/**
* The class PasswordAuthentication is a data holder that is used by
* Authenticator. It is simply a repository for a user name and a password.
*
* @see java.net.Authenticator
* @see java.net.Authenticator#getPasswordAuthentication()
*
* @author Bill Foote
* @since 1.2
*/
public final class PasswordAuthentication {
private String userName;
private char[] password;
/**
* Creates a new {@code PasswordAuthentication} object from the given
* user name and password.
*
* <p> Note that the given user password is cloned before it is stored in
* the new {@code PasswordAuthentication} object.
*
* @param userName the user name
* @param password the user's password
*/
public PasswordAuthentication(String userName, char[] password) {
this.userName = userName;
this.password = password.clone();
}
/**
* Returns the user name.
*
* @return the user name
*/
public String getUserName() {
return userName;
}
/**
* Returns the user password.
*
* <p> Note that this method returns a reference to the password. It is
* the caller's responsibility to zero out the password information after
* it is no longer needed.
*
* @return the password
*/
public char[] getPassword() {
return password;
}
}

View file

@ -0,0 +1,52 @@
/*
* Copyright (c) 2001, 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 java.net;
/**
* Signals that an ICMP Port Unreachable message has been
* received on a connected datagram.
*
* @since 1.4
*/
public class PortUnreachableException extends SocketException {
private static final long serialVersionUID = 8462541992376507323L;
/**
* Constructs a new {@code PortUnreachableException} with a
* detail message.
* @param msg the detail message
*/
public PortUnreachableException(String msg) {
super(msg);
}
/**
* Construct a new {@code PortUnreachableException} with no
* detailed message.
*/
public PortUnreachableException() {}
}

View file

@ -0,0 +1,56 @@
/*
* Copyright (c) 1995, 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 java.net;
import java.io.IOException;
/**
* Thrown to indicate that there is an error in the underlying
* protocol, such as a TCP error.
*
* @author Chris Warth
* @since 1.0
*/
public
class ProtocolException extends IOException {
private static final long serialVersionUID = -6098449442062388080L;
/**
* Constructs a new {@code ProtocolException} with the
* specified detail message.
*
* @param message the detail message.
*/
public ProtocolException(String message) {
super(message);
}
/**
* Constructs a new {@code ProtocolException} with no detail message.
*/
public ProtocolException() {
}
}

View file

@ -0,0 +1,41 @@
/*
* Copyright (c) 2007, 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 java.net;
/**
* Represents a family of communication protocols.
*
* @since 1.7
*/
public interface ProtocolFamily {
/**
* Returns the name of the protocol family.
*
* @return the name of the protocol family
*/
String name();
}

View file

@ -0,0 +1,171 @@
/*
* Copyright (c) 2003, 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 java.net;
/**
* This class represents a proxy setting, typically a type (http, socks) and
* a socket address.
* A {@code Proxy} is an immutable object.
*
* @see java.net.ProxySelector
* @author Yingxian Wang
* @author Jean-Christophe Collet
* @since 1.5
*/
public class Proxy {
/**
* Represents the proxy type.
*
* @since 1.5
*/
public enum Type {
/**
* Represents a direct connection, or the absence of a proxy.
*/
DIRECT,
/**
* Represents proxy for high level protocols such as HTTP or FTP.
*/
HTTP,
/**
* Represents a SOCKS (V4 or V5) proxy.
*/
SOCKS
};
private Type type;
private SocketAddress sa;
/**
* A proxy setting that represents a {@code DIRECT} connection,
* basically telling the protocol handler not to use any proxying.
* Used, for instance, to create sockets bypassing any other global
* proxy settings (like SOCKS):
* <P>
* {@code Socket s = new Socket(Proxy.NO_PROXY);}
*
*/
public static final Proxy NO_PROXY = new Proxy();
// Creates the proxy that represents a {@code DIRECT} connection.
private Proxy() {
type = Type.DIRECT;
sa = null;
}
/**
* Creates an entry representing a PROXY connection.
* Certain combinations are illegal. For instance, for types Http, and
* Socks, a SocketAddress <b>must</b> be provided.
* <P>
* Use the {@code Proxy.NO_PROXY} constant
* for representing a direct connection.
*
* @param type the {@code Type} of the proxy
* @param sa the {@code SocketAddress} for that proxy
* @throws IllegalArgumentException when the type and the address are
* incompatible
*/
public Proxy(Type type, SocketAddress sa) {
if ((type == Type.DIRECT) || !(sa instanceof InetSocketAddress))
throw new IllegalArgumentException("type " + type + " is not compatible with address " + sa);
this.type = type;
this.sa = sa;
}
/**
* Returns the proxy type.
*
* @return a Type representing the proxy type
*/
public Type type() {
return type;
}
/**
* Returns the socket address of the proxy, or
* {@code null} if its a direct connection.
*
* @return a {@code SocketAddress} representing the socket end
* point of the proxy
*/
public SocketAddress address() {
return sa;
}
/**
* Constructs a string representation of this Proxy.
* This String is constructed by calling toString() on its type
* and concatenating " @ " and the toString() result from its address
* if its type is not {@code DIRECT}.
*
* @return a string representation of this object.
*/
public String toString() {
if (type() == Type.DIRECT)
return "DIRECT";
return type() + " @ " + address();
}
/**
* Compares this object against the specified object.
* The result is {@code true} if and only if the argument is
* not {@code null} and it represents the same proxy as
* this object.
* <p>
* Two instances of {@code Proxy} represent the same
* address if both the SocketAddresses and type are equal.
*
* @param obj the object to compare against.
* @return {@code true} if the objects are the same;
* {@code false} otherwise.
* @see java.net.InetSocketAddress#equals(java.lang.Object)
*/
public final boolean equals(Object obj) {
if (obj == null || !(obj instanceof Proxy))
return false;
Proxy p = (Proxy) obj;
if (p.type() == type()) {
if (address() == null) {
return (p.address() == null);
} else
return address().equals(p.address());
}
return false;
}
/**
* Returns a hashcode for this Proxy.
*
* @return a hash code value for this Proxy.
*/
public final int hashCode() {
if (address() == null)
return type().hashCode();
return type().hashCode() + address().hashCode();
}
}

View file

@ -0,0 +1,212 @@
/*
* Copyright (c) 2003, 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 java.net;
import java.io.IOException;
import java.util.List;
import sun.security.util.SecurityConstants;
/**
* Selects the proxy server to use, if any, when connecting to the
* network resource referenced by a URL. A proxy selector is a
* concrete sub-class of this class and is registered by invoking the
* {@link java.net.ProxySelector#setDefault setDefault} method. The
* currently registered proxy selector can be retrieved by calling
* {@link java.net.ProxySelector#getDefault getDefault} method.
*
* <p> When a proxy selector is registered, for instance, a subclass
* of URLConnection class should call the {@link #select select}
* method for each URL request so that the proxy selector can decide
* if a direct, or proxied connection should be used. The {@link
* #select select} method returns an iterator over a collection with
* the preferred connection approach.
*
* <p> If a connection cannot be established to a proxy (PROXY or
* SOCKS) servers then the caller should call the proxy selector's
* {@link #connectFailed connectFailed} method to notify the proxy
* selector that the proxy server is unavailable. </p>
*
* <P>The default proxy selector does enforce a
* <a href="doc-files/net-properties.html#Proxies">set of System Properties</a>
* related to proxy settings.</P>
*
* @author Yingxian Wang
* @author Jean-Christophe Collet
* @since 1.5
*/
public abstract class ProxySelector {
/**
* The system wide proxy selector that selects the proxy server to
* use, if any, when connecting to a remote object referenced by
* an URL.
*
* @see #setDefault(ProxySelector)
*/
private static ProxySelector theProxySelector;
static {
try {
Class<?> c = Class.forName("sun.net.spi.DefaultProxySelector");
if (c != null && ProxySelector.class.isAssignableFrom(c)) {
@SuppressWarnings("deprecation")
ProxySelector tmp = (ProxySelector) c.newInstance();
theProxySelector = tmp;
}
} catch (Exception e) {
theProxySelector = null;
}
}
/**
* Gets the system-wide proxy selector.
*
* @throws SecurityException
* If a security manager has been installed and it denies
* {@link NetPermission}{@code ("getProxySelector")}
* @see #setDefault(ProxySelector)
* @return the system-wide {@code ProxySelector}
* @since 1.5
*/
public static ProxySelector getDefault() {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(SecurityConstants.GET_PROXYSELECTOR_PERMISSION);
}
return theProxySelector;
}
/**
* Sets (or unsets) the system-wide proxy selector.
*
* Note: non-standard protocol handlers may ignore this setting.
*
* @param ps The HTTP proxy selector, or
* {@code null} to unset the proxy selector.
*
* @throws SecurityException
* If a security manager has been installed and it denies
* {@link NetPermission}{@code ("setProxySelector")}
*
* @see #getDefault()
* @since 1.5
*/
public static void setDefault(ProxySelector ps) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(SecurityConstants.SET_PROXYSELECTOR_PERMISSION);
}
theProxySelector = ps;
}
/**
* Selects all the applicable proxies based on the protocol to
* access the resource with and a destination address to access
* the resource at.
* The format of the URI is defined as follow:
* <UL>
* <LI>http URI for http connections</LI>
* <LI>https URI for https connections
* <LI>{@code socket://host:port}<br>
* for tcp client sockets connections</LI>
* </UL>
*
* @param uri
* The URI that a connection is required to
*
* @return a List of Proxies. Each element in the
* the List is of type
* {@link java.net.Proxy Proxy};
* when no proxy is available, the list will
* contain one element of type
* {@link java.net.Proxy Proxy}
* that represents a direct connection.
* @throws IllegalArgumentException if the argument is null
*/
public abstract List<Proxy> select(URI uri);
/**
* Called to indicate that a connection could not be established
* to a proxy/socks server. An implementation of this method can
* temporarily remove the proxies or reorder the sequence of
* proxies returned by {@link #select(URI)}, using the address
* and the IOException caught when trying to connect.
*
* @param uri
* The URI that the proxy at sa failed to serve.
* @param sa
* The socket address of the proxy/SOCKS server
*
* @param ioe
* The I/O exception thrown when the connect failed.
* @throws IllegalArgumentException if either argument is null
*/
public abstract void connectFailed(URI uri, SocketAddress sa, IOException ioe);
/**
* Returns a ProxySelector which uses the given proxy address for all HTTP
* and HTTPS requests. If proxy is {@code null} then proxying is disabled.
*
* @param proxyAddress
* The address of the proxy
*
* @return a ProxySelector
*
* @since 9
*/
public static ProxySelector of(InetSocketAddress proxyAddress) {
return new StaticProxySelector(proxyAddress);
}
static class StaticProxySelector extends ProxySelector {
private static final List<Proxy> NO_PROXY_LIST = List.of(Proxy.NO_PROXY);
final List<Proxy> list;
StaticProxySelector(InetSocketAddress address){
Proxy p;
if (address == null) {
p = Proxy.NO_PROXY;
} else {
p = new Proxy(Proxy.Type.HTTP, address);
}
list = List.of(p);
}
@Override
public void connectFailed(URI uri, SocketAddress sa, IOException e) {
/* ignore */
}
@Override
public synchronized List<Proxy> select(URI uri) {
String scheme = uri.getScheme().toLowerCase();
if (scheme.equals("http") || scheme.equals("https")) {
return list;
} else {
return NO_PROXY_LIST;
}
}
}
}

View file

@ -0,0 +1,163 @@
/*
* Copyright (c) 2003, 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 java.net;
import java.io.IOException;
import java.util.Map;
import java.util.List;
import sun.security.util.SecurityConstants;
/**
* Represents implementations of URLConnection caches. An instance of
* such a class can be registered with the system by doing
* ResponseCache.setDefault(ResponseCache), and the system will call
* this object in order to:
*
* <ul><li>store resource data which has been retrieved from an
* external source into the cache</li>
* <li>try to fetch a requested resource that may have been
* stored in the cache</li>
* </ul>
*
* The ResponseCache implementation decides which resources
* should be cached, and for how long they should be cached. If a
* request resource cannot be retrieved from the cache, then the
* protocol handlers will fetch the resource from its original
* location.
*
* The settings for URLConnection#useCaches controls whether the
* protocol is allowed to use a cached response.
*
* For more information on HTTP caching, see <a
* href="http://www.ietf.org/rfc/rfc2616.txt"><i>RFC&nbsp;2616: Hypertext
* Transfer Protocol -- HTTP/1.1</i></a>
*
* @author Yingxian Wang
* @since 1.5
*/
public abstract class ResponseCache {
/**
* The system wide cache that provides access to a url
* caching mechanism.
*
* @see #setDefault(ResponseCache)
* @see #getDefault()
*/
private static ResponseCache theResponseCache;
/**
* Gets the system-wide response cache.
*
* @throws SecurityException
* If a security manager has been installed and it denies
* {@link NetPermission}{@code ("getResponseCache")}
*
* @see #setDefault(ResponseCache)
* @return the system-wide {@code ResponseCache}
* @since 1.5
*/
public static synchronized ResponseCache getDefault() {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(SecurityConstants.GET_RESPONSECACHE_PERMISSION);
}
return theResponseCache;
}
/**
* Sets (or unsets) the system-wide cache.
*
* Note: non-standard procotol handlers may ignore this setting.
*
* @param responseCache The response cache, or
* {@code null} to unset the cache.
*
* @throws SecurityException
* If a security manager has been installed and it denies
* {@link NetPermission}{@code ("setResponseCache")}
*
* @see #getDefault()
* @since 1.5
*/
public static synchronized void setDefault(ResponseCache responseCache) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(SecurityConstants.SET_RESPONSECACHE_PERMISSION);
}
theResponseCache = responseCache;
}
/**
* Retrieve the cached response based on the requesting uri,
* request method and request headers. Typically this method is
* called by the protocol handler before it sends out the request
* to get the network resource. If a cached response is returned,
* that resource is used instead.
*
* @param uri a {@code URI} used to reference the requested
* network resource
* @param rqstMethod a {@code String} representing the request
* method
* @param rqstHeaders - a Map from request header
* field names to lists of field values representing
* the current request headers
* @return a {@code CacheResponse} instance if available
* from cache, or null otherwise
* @throws IOException if an I/O error occurs
* @throws IllegalArgumentException if any one of the arguments is null
*
* @see java.net.URLConnection#setUseCaches(boolean)
* @see java.net.URLConnection#getUseCaches()
* @see java.net.URLConnection#setDefaultUseCaches(boolean)
* @see java.net.URLConnection#getDefaultUseCaches()
*/
public abstract CacheResponse
get(URI uri, String rqstMethod, Map<String, List<String>> rqstHeaders)
throws IOException;
/**
* The protocol handler calls this method after a resource has
* been retrieved, and the ResponseCache must decide whether or
* not to store the resource in its cache. If the resource is to
* be cached, then put() must return a CacheRequest object which
* contains an OutputStream that the protocol handler will
* use to write the resource into the cache. If the resource is
* not to be cached, then put must return null.
*
* @param uri a {@code URI} used to reference the requested
* network resource
* @param conn - a URLConnection instance that is used to fetch
* the response to be cached
* @return a {@code CacheRequest} for recording the
* response to be cached. Null return indicates that
* the caller does not intend to cache the response.
* @throws IOException if an I/O error occurs
* @throws IllegalArgumentException if any one of the arguments is
* null
*/
public abstract CacheRequest put(URI uri, URLConnection conn) throws IOException;
}

View file

@ -0,0 +1,108 @@
/*
* Copyright (c) 2003, 2004, 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 java.net;
import java.security.cert.Certificate;
import javax.net.ssl.SSLPeerUnverifiedException;
import java.security.Principal;
import java.util.List;
/**
* Represents a cache response originally retrieved through secure
* means, such as TLS.
*
* @since 1.5
*/
public abstract class SecureCacheResponse extends CacheResponse {
/**
* Returns the cipher suite in use on the original connection that
* retrieved the network resource.
*
* @return a string representing the cipher suite
*/
public abstract String getCipherSuite();
/**
* Returns the certificate chain that were sent to the server during
* handshaking of the original connection that retrieved the
* network resource. Note: This method is useful only
* when using certificate-based cipher suites.
*
* @return an immutable List of Certificate representing the
* certificate chain that was sent to the server. If no
* certificate chain was sent, null will be returned.
* @see #getLocalPrincipal()
*/
public abstract List<Certificate> getLocalCertificateChain();
/**
* Returns the server's certificate chain, which was established as
* part of defining the session in the original connection that
* retrieved the network resource, from cache. Note: This method
* can be used only when using certificate-based cipher suites;
* using it with non-certificate-based cipher suites, such as
* Kerberos, will throw an SSLPeerUnverifiedException.
*
* @return an immutable List of Certificate representing the server's
* certificate chain.
* @throws SSLPeerUnverifiedException if the peer is not verified.
* @see #getPeerPrincipal()
*/
public abstract List<Certificate> getServerCertificateChain()
throws SSLPeerUnverifiedException;
/**
* Returns the server's principal which was established as part of
* defining the session during the original connection that
* retrieved the network resource.
*
* @return the server's principal. Returns an X500Principal of the
* end-entity certiticate for X509-based cipher suites, and
* KerberosPrincipal for Kerberos cipher suites.
*
* @throws SSLPeerUnverifiedException if the peer was not verified.
*
* @see #getServerCertificateChain()
* @see #getLocalPrincipal()
*/
public abstract Principal getPeerPrincipal()
throws SSLPeerUnverifiedException;
/**
* Returns the principal that was sent to the server during
* handshaking in the original connection that retrieved the
* network resource.
*
* @return the principal sent to the server. Returns an X500Principal
* of the end-entity certificate for X509-based cipher suites, and
* KerberosPrincipal for Kerberos cipher suites. If no principal was
* sent, then null is returned.
*
* @see #getLocalCertificateChain()
* @see #getPeerPrincipal()
*/
public abstract Principal getLocalPrincipal();
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,45 @@
/*
* Copyright (c) 2000, 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 java.net;
/**
*
* This class represents a Socket Address with no protocol attachment.
* As an abstract class, it is meant to be subclassed with a specific,
* protocol dependent, implementation.
* <p>
* It provides an immutable object used by sockets for binding, connecting, or
* as returned values.
*
* @see java.net.Socket
* @see java.net.ServerSocket
* @since 1.4
*/
public abstract class SocketAddress implements java.io.Serializable {
static final long serialVersionUID = 5215720748342549866L;
}

View file

@ -0,0 +1,55 @@
/*
* Copyright (c) 1995, 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 java.net;
import java.io.IOException;
/**
* Thrown to indicate that there is an error creating or accessing a Socket.
*
* @author Jonathan Payne
* @since 1.0
*/
public
class SocketException extends IOException {
private static final long serialVersionUID = -5935874303556886934L;
/**
* Constructs a new {@code SocketException} with the
* specified detail message.
*
* @param msg the detail message.
*/
public SocketException(String msg) {
super(msg);
}
/**
* Constructs a new {@code SocketException} with no detail message.
*/
public SocketException() {
}
}

View file

@ -0,0 +1,479 @@
/*
* Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.net;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.FileDescriptor;
import java.util.Set;
/**
* The abstract class {@code SocketImpl} is a common superclass
* of all classes that actually implement sockets. It is used to
* create both client and server sockets.
* <p>
* A "plain" socket implements these methods exactly as
* described, without attempting to go through a firewall or proxy.
*
* @author unascribed
* @since 1.0
*/
public abstract class SocketImpl implements SocketOptions {
/**
* The actual Socket object.
*/
Socket socket = null;
ServerSocket serverSocket = null;
/**
* The file descriptor object for this socket.
*/
protected FileDescriptor fd;
/**
* The IP address of the remote end of this socket.
*/
protected InetAddress address;
/**
* The port number on the remote host to which this socket is connected.
*/
protected int port;
/**
* The local port number to which this socket is connected.
*/
protected int localport;
/**
* Creates either a stream or a datagram socket.
*
* @param stream if {@code true}, create a stream socket;
* otherwise, create a datagram socket.
* @exception IOException if an I/O error occurs while creating the
* socket.
*/
protected abstract void create(boolean stream) throws IOException;
/**
* Connects this socket to the specified port on the named host.
*
* @param host the name of the remote host.
* @param port the port number.
* @exception IOException if an I/O error occurs when connecting to the
* remote host.
*/
protected abstract void connect(String host, int port) throws IOException;
/**
* Connects this socket to the specified port number on the specified host.
*
* @param address the IP address of the remote host.
* @param port the port number.
* @exception IOException if an I/O error occurs when attempting a
* connection.
*/
protected abstract void connect(InetAddress address, int port) throws IOException;
/**
* Connects this socket to the specified port number on the specified host.
* A timeout of zero is interpreted as an infinite timeout. The connection
* will then block until established or an error occurs.
*
* @param address the Socket address of the remote host.
* @param timeout the timeout value, in milliseconds, or zero for no timeout.
* @exception IOException if an I/O error occurs when attempting a
* connection.
* @since 1.4
*/
protected abstract void connect(SocketAddress address, int timeout) throws IOException;
/**
* Binds this socket to the specified local IP address and port number.
*
* @param host an IP address that belongs to a local interface.
* @param port the port number.
* @exception IOException if an I/O error occurs when binding this socket.
*/
protected abstract void bind(InetAddress host, int port) throws IOException;
/**
* Sets the maximum queue length for incoming connection indications
* (a request to connect) to the {@code count} argument. If a
* connection indication arrives when the queue is full, the
* connection is refused.
*
* @param backlog the maximum length of the queue.
* @exception IOException if an I/O error occurs when creating the queue.
*/
protected abstract void listen(int backlog) throws IOException;
/**
* Accepts a connection.
*
* @param s the accepted connection.
* @exception IOException if an I/O error occurs when accepting the
* connection.
*/
protected abstract void accept(SocketImpl s) throws IOException;
/**
* Returns an input stream for this socket.
*
* @return a stream for reading from this socket.
* @exception IOException if an I/O error occurs when creating the
* input stream.
*/
protected abstract InputStream getInputStream() throws IOException;
/**
* Returns an output stream for this socket.
*
* @return an output stream for writing to this socket.
* @exception IOException if an I/O error occurs when creating the
* output stream.
*/
protected abstract OutputStream getOutputStream() throws IOException;
/**
* Returns the number of bytes that can be read from this socket
* without blocking.
*
* @return the number of bytes that can be read from this socket
* without blocking.
* @exception IOException if an I/O error occurs when determining the
* number of bytes available.
*/
protected abstract int available() throws IOException;
/**
* Closes this socket.
*
* @exception IOException if an I/O error occurs when closing this socket.
*/
protected abstract void close() throws IOException;
/**
* Places the input stream for this socket at "end of stream".
* Any data sent to this socket is acknowledged and then
* silently discarded.
*
* If you read from a socket input stream after invoking this method on the
* socket, the stream's {@code available} method will return 0, and its
* {@code read} methods will return {@code -1} (end of stream).
*
* @exception IOException if an I/O error occurs when shutting down this
* socket.
* @see java.net.Socket#shutdownOutput()
* @see java.net.Socket#close()
* @see java.net.Socket#setSoLinger(boolean, int)
* @since 1.3
*/
protected void shutdownInput() throws IOException {
throw new IOException("Method not implemented!");
}
/**
* Disables the output stream for this socket.
* For a TCP socket, any previously written data will be sent
* followed by TCP's normal connection termination sequence.
*
* If you write to a socket output stream after invoking
* shutdownOutput() on the socket, the stream will throw
* an IOException.
*
* @exception IOException if an I/O error occurs when shutting down this
* socket.
* @see java.net.Socket#shutdownInput()
* @see java.net.Socket#close()
* @see java.net.Socket#setSoLinger(boolean, int)
* @since 1.3
*/
protected void shutdownOutput() throws IOException {
throw new IOException("Method not implemented!");
}
/**
* Returns the value of this socket's {@code fd} field.
*
* @return the value of this socket's {@code fd} field.
* @see java.net.SocketImpl#fd
*/
protected FileDescriptor getFileDescriptor() {
return fd;
}
/**
* Returns the value of this socket's {@code address} field.
*
* @return the value of this socket's {@code address} field.
* @see java.net.SocketImpl#address
*/
protected InetAddress getInetAddress() {
return address;
}
/**
* Returns the value of this socket's {@code port} field.
*
* @return the value of this socket's {@code port} field.
* @see java.net.SocketImpl#port
*/
protected int getPort() {
return port;
}
/**
* Returns whether or not this SocketImpl supports sending
* urgent data. By default, false is returned
* unless the method is overridden in a sub-class
*
* @return true if urgent data supported
* @see java.net.SocketImpl#address
* @since 1.4
*/
protected boolean supportsUrgentData () {
return false; // must be overridden in sub-class
}
/**
* Send one byte of urgent data on the socket.
* The byte to be sent is the low eight bits of the parameter
* @param data The byte of data to send
* @exception IOException if there is an error
* sending the data.
* @since 1.4
*/
protected abstract void sendUrgentData (int data) throws IOException;
/**
* Returns the value of this socket's {@code localport} field.
*
* @return the value of this socket's {@code localport} field.
* @see java.net.SocketImpl#localport
*/
protected int getLocalPort() {
return localport;
}
void setSocket(Socket soc) {
this.socket = soc;
}
Socket getSocket() {
return socket;
}
void setServerSocket(ServerSocket soc) {
this.serverSocket = soc;
}
ServerSocket getServerSocket() {
return serverSocket;
}
/**
* Returns the address and port of this socket as a {@code String}.
*
* @return a string representation of this socket.
*/
public String toString() {
return "Socket[addr=" + getInetAddress() +
",port=" + getPort() + ",localport=" + getLocalPort() + "]";
}
void reset() throws IOException {
address = null;
port = 0;
localport = 0;
}
/**
* Sets performance preferences for this socket.
*
* <p> Sockets use the TCP/IP protocol by default. Some implementations
* may offer alternative protocols which have different performance
* characteristics than TCP/IP. This method allows the application to
* express its own preferences as to how these tradeoffs should be made
* when the implementation chooses from the available protocols.
*
* <p> Performance preferences are described by three integers
* whose values indicate the relative importance of short connection time,
* low latency, and high bandwidth. The absolute values of the integers
* are irrelevant; in order to choose a protocol the values are simply
* compared, with larger values indicating stronger preferences. Negative
* values represent a lower priority than positive values. If the
* application prefers short connection time over both low latency and high
* bandwidth, for example, then it could invoke this method with the values
* {@code (1, 0, 0)}. If the application prefers high bandwidth above low
* latency, and low latency above short connection time, then it could
* invoke this method with the values {@code (0, 1, 2)}.
*
* By default, this method does nothing, unless it is overridden in a
* a sub-class.
*
* @param connectionTime
* An {@code int} expressing the relative importance of a short
* connection time
*
* @param latency
* An {@code int} expressing the relative importance of low
* latency
*
* @param bandwidth
* An {@code int} expressing the relative importance of high
* bandwidth
*
* @since 1.5
*/
protected void setPerformancePreferences(int connectionTime,
int latency,
int bandwidth)
{
/* Not implemented yet */
}
/**
* Called to set a socket option.
*
* @param <T> The type of the socket option value
* @param name The socket option
*
* @param value The value of the socket option. A value of {@code null}
* may be valid for some options.
*
* @throws UnsupportedOperationException if the SocketImpl does not
* support the option
*
* @throws IOException if an I/O error occurs, or if the socket is closed.
*
* @since 9
*/
protected <T> void setOption(SocketOption<T> name, T value) throws IOException {
if (name == StandardSocketOptions.SO_KEEPALIVE &&
(getSocket() != null)) {
setOption(SocketOptions.SO_KEEPALIVE, value);
} else if (name == StandardSocketOptions.SO_SNDBUF &&
(getSocket() != null)) {
setOption(SocketOptions.SO_SNDBUF, value);
} else if (name == StandardSocketOptions.SO_RCVBUF) {
setOption(SocketOptions.SO_RCVBUF, value);
} else if (name == StandardSocketOptions.SO_REUSEADDR) {
setOption(SocketOptions.SO_REUSEADDR, value);
} else if (name == StandardSocketOptions.SO_REUSEPORT &&
supportedOptions().contains(name)) {
setOption(SocketOptions.SO_REUSEPORT, value);
} else if (name == StandardSocketOptions.SO_LINGER &&
(getSocket() != null)) {
setOption(SocketOptions.SO_LINGER, value);
} else if (name == StandardSocketOptions.IP_TOS) {
setOption(SocketOptions.IP_TOS, value);
} else if (name == StandardSocketOptions.TCP_NODELAY &&
(getSocket() != null)) {
setOption(SocketOptions.TCP_NODELAY, value);
} else {
throw new UnsupportedOperationException("unsupported option");
}
}
/**
* Called to get a socket option.
*
* @param <T> The type of the socket option value
* @param name The socket option
*
* @return the value of the named option
*
* @throws UnsupportedOperationException if the SocketImpl does not
* support the option.
*
* @throws IOException if an I/O error occurs, or if the socket is closed.
*
* @since 9
*/
@SuppressWarnings("unchecked")
protected <T> T getOption(SocketOption<T> name) throws IOException {
if (name == StandardSocketOptions.SO_KEEPALIVE &&
(getSocket() != null)) {
return (T)getOption(SocketOptions.SO_KEEPALIVE);
} else if (name == StandardSocketOptions.SO_SNDBUF &&
(getSocket() != null)) {
return (T)getOption(SocketOptions.SO_SNDBUF);
} else if (name == StandardSocketOptions.SO_RCVBUF) {
return (T)getOption(SocketOptions.SO_RCVBUF);
} else if (name == StandardSocketOptions.SO_REUSEADDR) {
return (T)getOption(SocketOptions.SO_REUSEADDR);
} else if (name == StandardSocketOptions.SO_REUSEPORT &&
supportedOptions().contains(name)) {
return (T)getOption(SocketOptions.SO_REUSEPORT);
} else if (name == StandardSocketOptions.SO_LINGER &&
(getSocket() != null)) {
return (T)getOption(SocketOptions.SO_LINGER);
} else if (name == StandardSocketOptions.IP_TOS) {
return (T)getOption(SocketOptions.IP_TOS);
} else if (name == StandardSocketOptions.TCP_NODELAY &&
(getSocket() != null)) {
return (T)getOption(SocketOptions.TCP_NODELAY);
} else {
throw new UnsupportedOperationException("unsupported option");
}
}
private static final Set<SocketOption<?>> socketOptions;
private static final Set<SocketOption<?>> serverSocketOptions;
static {
socketOptions = Set.of(StandardSocketOptions.SO_KEEPALIVE,
StandardSocketOptions.SO_SNDBUF,
StandardSocketOptions.SO_RCVBUF,
StandardSocketOptions.SO_REUSEADDR,
StandardSocketOptions.SO_LINGER,
StandardSocketOptions.IP_TOS,
StandardSocketOptions.TCP_NODELAY);
serverSocketOptions = Set.of(StandardSocketOptions.SO_RCVBUF,
StandardSocketOptions.SO_REUSEADDR,
StandardSocketOptions.IP_TOS);
}
/**
* Returns a set of SocketOptions supported by this impl
* and by this impl's socket (Socket or ServerSocket)
*
* @return a Set of SocketOptions
*
* @since 9
*/
protected Set<SocketOption<?>> supportedOptions() {
if (getSocket() != null) {
return socketOptions;
} else {
return serverSocketOptions;
}
}
}

View file

@ -0,0 +1,48 @@
/*
* Copyright (c) 1995, 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 java.net;
/**
* This interface defines a factory for socket implementations. It
* is used by the classes {@code Socket} and
* {@code ServerSocket} to create actual socket
* implementations.
*
* @author Arthur van Hoff
* @see java.net.Socket
* @see java.net.ServerSocket
* @since 1.0
*/
public
interface SocketImplFactory {
/**
* Creates a new {@code SocketImpl} instance.
*
* @return a new instance of {@code SocketImpl}.
* @see java.net.SocketImpl
*/
SocketImpl createSocketImpl();
}

View file

@ -0,0 +1,293 @@
/*
* Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.net;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import sun.net.ConnectionResetException;
/**
* This stream extends FileInputStream to implement a
* SocketInputStream. Note that this class should <b>NOT</b> be
* public.
*
* @author Jonathan Payne
* @author Arthur van Hoff
*/
class SocketInputStream extends FileInputStream
{
static {
init();
}
private boolean eof;
private AbstractPlainSocketImpl impl = null;
private byte temp[];
private Socket socket = null;
/**
* Creates a new SocketInputStream. Can only be called
* by a Socket. This method needs to hang on to the owner Socket so
* that the fd will not be closed.
* @param impl the implemented socket input stream
*/
SocketInputStream(AbstractPlainSocketImpl impl) throws IOException {
super(impl.getFileDescriptor());
this.impl = impl;
socket = impl.getSocket();
}
/**
* Returns the unique {@link java.nio.channels.FileChannel FileChannel}
* object associated with this file input stream.</p>
*
* The {@code getChannel} method of {@code SocketInputStream}
* returns {@code null} since it is a socket based stream.</p>
*
* @return the file channel associated with this file input stream
*
* @since 1.4
* @spec JSR-51
*/
public final FileChannel getChannel() {
return null;
}
/**
* Reads into an array of bytes at the specified offset using
* the received socket primitive.
* @param fd the FileDescriptor
* @param b the buffer into which the data is read
* @param off the start offset of the data
* @param len the maximum number of bytes read
* @param timeout the read timeout in ms
* @return the actual number of bytes read, -1 is
* returned when the end of the stream is reached.
* @exception IOException If an I/O error has occurred.
*/
private native int socketRead0(FileDescriptor fd,
byte b[], int off, int len,
int timeout)
throws IOException;
// wrap native call to allow instrumentation
/**
* Reads into an array of bytes at the specified offset using
* the received socket primitive.
* @param fd the FileDescriptor
* @param b the buffer into which the data is read
* @param off the start offset of the data
* @param len the maximum number of bytes read
* @param timeout the read timeout in ms
* @return the actual number of bytes read, -1 is
* returned when the end of the stream is reached.
* @exception IOException If an I/O error has occurred.
*/
private int socketRead(FileDescriptor fd,
byte b[], int off, int len,
int timeout)
throws IOException {
return socketRead0(fd, b, off, len, timeout);
}
/**
* Reads into a byte array data from the socket.
* @param b the buffer into which the data is read
* @return the actual number of bytes read, -1 is
* returned when the end of the stream is reached.
* @exception IOException If an I/O error has occurred.
*/
public int read(byte b[]) throws IOException {
return read(b, 0, b.length);
}
/**
* Reads into a byte array <i>b</i> at offset <i>off</i>,
* <i>length</i> bytes of data.
* @param b the buffer into which the data is read
* @param off the start offset of the data
* @param length the maximum number of bytes read
* @return the actual number of bytes read, -1 is
* returned when the end of the stream is reached.
* @exception IOException If an I/O error has occurred.
*/
public int read(byte b[], int off, int length) throws IOException {
return read(b, off, length, impl.getTimeout());
}
int read(byte b[], int off, int length, int timeout) throws IOException {
int n;
// EOF already encountered
if (eof) {
return -1;
}
// connection reset
if (impl.isConnectionReset()) {
throw new SocketException("Connection reset");
}
// bounds check
if (length <= 0 || off < 0 || length > b.length - off) {
if (length == 0) {
return 0;
}
throw new ArrayIndexOutOfBoundsException("length == " + length
+ " off == " + off + " buffer length == " + b.length);
}
boolean gotReset = false;
// acquire file descriptor and do the read
FileDescriptor fd = impl.acquireFD();
try {
n = socketRead(fd, b, off, length, timeout);
if (n > 0) {
return n;
}
} catch (ConnectionResetException rstExc) {
gotReset = true;
} finally {
impl.releaseFD();
}
/*
* We receive a "connection reset" but there may be bytes still
* buffered on the socket
*/
if (gotReset) {
impl.setConnectionResetPending();
impl.acquireFD();
try {
n = socketRead(fd, b, off, length, timeout);
if (n > 0) {
return n;
}
} catch (ConnectionResetException rstExc) {
} finally {
impl.releaseFD();
}
}
/*
* If we get here we are at EOF, the socket has been closed,
* or the connection has been reset.
*/
if (impl.isClosedOrPending()) {
throw new SocketException("Socket closed");
}
if (impl.isConnectionResetPending()) {
impl.setConnectionReset();
}
if (impl.isConnectionReset()) {
throw new SocketException("Connection reset");
}
eof = true;
return -1;
}
/**
* Reads a single byte from the socket.
*/
public int read() throws IOException {
if (eof) {
return -1;
}
temp = new byte[1];
int n = read(temp, 0, 1);
if (n <= 0) {
return -1;
}
return temp[0] & 0xff;
}
/**
* Skips n bytes of input.
* @param numbytes the number of bytes to skip
* @return the actual number of bytes skipped.
* @exception IOException If an I/O error has occurred.
*/
public long skip(long numbytes) throws IOException {
if (numbytes <= 0) {
return 0;
}
long n = numbytes;
int buflen = (int) Math.min(1024, n);
byte data[] = new byte[buflen];
while (n > 0) {
int r = read(data, 0, (int) Math.min((long) buflen, n));
if (r < 0) {
break;
}
n -= r;
}
return numbytes - n;
}
/**
* Returns the number of bytes that can be read without blocking.
* @return the number of immediately available bytes
*/
public int available() throws IOException {
return impl.available();
}
/**
* Closes the stream.
*/
private boolean closing = false;
public void close() throws IOException {
// Prevent recursion. See BugId 4484411
if (closing)
return;
closing = true;
if (socket != null) {
if (!socket.isClosed())
socket.close();
} else
impl.close();
closing = false;
}
void setEOF(boolean eof) {
this.eof = eof;
}
/**
* Overrides finalize, the fd is closed by the Socket.
*/
@SuppressWarnings("deprecation")
protected void finalize() {}
/**
* Perform class load-time initializations.
*/
private static native void init();
}

View file

@ -0,0 +1,59 @@
/*
* Copyright (c) 2007, 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 java.net;
/**
* A socket option associated with a socket.
*
* <p> In the {@link java.nio.channels channels} package, the {@link
* java.nio.channels.NetworkChannel} interface defines the {@link
* java.nio.channels.NetworkChannel#setOption(SocketOption,Object) setOption}
* and {@link java.nio.channels.NetworkChannel#getOption(SocketOption) getOption}
* methods to set and query the channel's socket options.
*
* @param <T> The type of the socket option value.
*
* @since 1.7
*
* @see StandardSocketOptions
*/
public interface SocketOption<T> {
/**
* Returns the name of the socket option.
*
* @return the name of the socket option
*/
String name();
/**
* Returns the type of the socket option value.
*
* @return the type of the socket option value
*/
Class<T> type();
}

View file

@ -0,0 +1,343 @@
/*
* 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
* 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 java.net;
import java.lang.annotation.Native;
/**
* Interface of methods to get/set socket options. This interface is
* implemented by: <B>SocketImpl</B> and <B>DatagramSocketImpl</B>.
* Subclasses of these should override the methods
* of this interface in order to support their own options.
* <P>
* The methods and constants which specify options in this interface are
* for implementation only. If you're not subclassing SocketImpl or
* DatagramSocketImpl, <B>you won't use these directly.</B> There are
* type-safe methods to get/set each of these options in Socket, ServerSocket,
* DatagramSocket and MulticastSocket.
*
* @author David Brown
* @since 1.1
*/
public interface SocketOptions {
/**
* Enable/disable the option specified by <I>optID</I>. If the option
* is to be enabled, and it takes an option-specific "value", this is
* passed in <I>value</I>. The actual type of value is option-specific,
* and it is an error to pass something that isn't of the expected type:
* <BR><PRE>
* SocketImpl s;
* ...
* s.setOption(SO_LINGER, new Integer(10));
* // OK - set SO_LINGER w/ timeout of 10 sec.
* s.setOption(SO_LINGER, new Double(10));
* // ERROR - expects java.lang.Integer
*</PRE>
* If the requested option is binary, it can be set using this method by
* a java.lang.Boolean:
* <BR><PRE>
* s.setOption(TCP_NODELAY, Boolean.TRUE);
* // OK - enables TCP_NODELAY, a binary option
* </PRE>
* <BR>
* Any option can be disabled using this method with a Boolean.FALSE:
* <BR><PRE>
* s.setOption(TCP_NODELAY, Boolean.FALSE);
* // OK - disables TCP_NODELAY
* s.setOption(SO_LINGER, Boolean.FALSE);
* // OK - disables SO_LINGER
* </PRE>
* <BR>
* For an option that has a notion of on and off, and requires
* a non-boolean parameter, setting its value to anything other than
* <I>Boolean.FALSE</I> implicitly enables it.
* <BR>
* Throws SocketException if the option is unrecognized,
* the socket is closed, or some low-level error occurred
* <BR>
* @param optID identifies the option
* @param value the parameter of the socket option
* @throws SocketException if the option is unrecognized,
* the socket is closed, or some low-level error occurred
* @see #getOption(int)
*/
public void
setOption(int optID, Object value) throws SocketException;
/**
* Fetch the value of an option.
* Binary options will return java.lang.Boolean.TRUE
* if enabled, java.lang.Boolean.FALSE if disabled, e.g.:
* <BR><PRE>
* SocketImpl s;
* ...
* Boolean noDelay = (Boolean)(s.getOption(TCP_NODELAY));
* if (noDelay.booleanValue()) {
* // true if TCP_NODELAY is enabled...
* ...
* }
* </PRE>
* <P>
* For options that take a particular type as a parameter,
* getOption(int) will return the parameter's value, else
* it will return java.lang.Boolean.FALSE:
* <PRE>
* Object o = s.getOption(SO_LINGER);
* if (o instanceof Integer) {
* System.out.print("Linger time is " + ((Integer)o).intValue());
* } else {
* // the true type of o is java.lang.Boolean.FALSE;
* }
* </PRE>
*
* @param optID an {@code int} identifying the option to fetch
* @return the value of the option
* @throws SocketException if the socket is closed
* @throws SocketException if <I>optID</I> is unknown along the
* protocol stack (including the SocketImpl)
* @see #setOption(int, java.lang.Object)
*/
public Object getOption(int optID) throws SocketException;
/**
* The java-supported BSD-style options.
*/
/**
* Disable Nagle's algorithm for this connection. Written data
* to the network is not buffered pending acknowledgement of
* previously written data.
*<P>
* Valid for TCP only: SocketImpl.
*
* @see Socket#setTcpNoDelay
* @see Socket#getTcpNoDelay
*/
@Native public static final int TCP_NODELAY = 0x0001;
/**
* Fetch the local address binding of a socket (this option cannot
* be "set" only "gotten", since sockets are bound at creation time,
* and so the locally bound address cannot be changed). The default local
* address of a socket is INADDR_ANY, meaning any local address on a
* multi-homed host. A multi-homed host can use this option to accept
* connections to only one of its addresses (in the case of a
* ServerSocket or DatagramSocket), or to specify its return address
* to the peer (for a Socket or DatagramSocket). The parameter of
* this option is an InetAddress.
* <P>
* This option <B>must</B> be specified in the constructor.
* <P>
* Valid for: SocketImpl, DatagramSocketImpl
*
* @see Socket#getLocalAddress
* @see DatagramSocket#getLocalAddress
*/
@Native public static final int SO_BINDADDR = 0x000F;
/** Sets SO_REUSEADDR for a socket. This is used only for MulticastSockets
* in java, and it is set by default for MulticastSockets.
* <P>
* Valid for: DatagramSocketImpl
*/
@Native public static final int SO_REUSEADDR = 0x04;
/** Sets SO_REUSEPORT for a socket. This option enables and disables
* the ability to have multiple sockets listen to the same address
* and port.
* <P>
* Valid for: SocketImpl, DatagramSocketImpl
*
* @since 9
* @see StandardSocketOptions#SO_REUSEPORT
*/
@Native public static final int SO_REUSEPORT = 0x0E;
/**
* Sets SO_BROADCAST for a socket. This option enables and disables
* the ability of the process to send broadcast messages. It is supported
* for only datagram sockets and only on networks that support
* the concept of a broadcast message (e.g. Ethernet, token ring, etc.),
* and it is set by default for DatagramSockets.
* @since 1.4
*/
@Native public static final int SO_BROADCAST = 0x0020;
/** Set which outgoing interface on which to send multicast packets.
* Useful on hosts with multiple network interfaces, where applications
* want to use other than the system default. Takes/returns an InetAddress.
* <P>
* Valid for Multicast: DatagramSocketImpl
*
* @see MulticastSocket#setInterface(InetAddress)
* @see MulticastSocket#getInterface()
*/
@Native public static final int IP_MULTICAST_IF = 0x10;
/** Same as above. This option is introduced so that the behaviour
* with IP_MULTICAST_IF will be kept the same as before, while
* this new option can support setting outgoing interfaces with either
* IPv4 and IPv6 addresses.
*
* NOTE: make sure there is no conflict with this
* @see MulticastSocket#setNetworkInterface(NetworkInterface)
* @see MulticastSocket#getNetworkInterface()
* @since 1.4
*/
@Native public static final int IP_MULTICAST_IF2 = 0x1f;
/**
* This option enables or disables local loopback of multicast datagrams.
* This option is enabled by default for Multicast Sockets.
* @since 1.4
*/
@Native public static final int IP_MULTICAST_LOOP = 0x12;
/**
* This option sets the type-of-service or traffic class field
* in the IP header for a TCP or UDP socket.
* @since 1.4
*/
@Native public static final int IP_TOS = 0x3;
/**
* Specify a linger-on-close timeout. This option disables/enables
* immediate return from a <B>close()</B> of a TCP Socket. Enabling
* this option with a non-zero Integer <I>timeout</I> means that a
* <B>close()</B> will block pending the transmission and acknowledgement
* of all data written to the peer, at which point the socket is closed
* <I>gracefully</I>. Upon reaching the linger timeout, the socket is
* closed <I>forcefully</I>, with a TCP RST. Enabling the option with a
* timeout of zero does a forceful close immediately. If the specified
* timeout value exceeds 65,535 it will be reduced to 65,535.
* <P>
* Valid only for TCP: SocketImpl
*
* @see Socket#setSoLinger
* @see Socket#getSoLinger
*/
@Native public static final int SO_LINGER = 0x0080;
/** Set a timeout on blocking Socket operations:
* <PRE>
* ServerSocket.accept();
* SocketInputStream.read();
* DatagramSocket.receive();
* </PRE>
*
* <P> The option must be set prior to entering a blocking
* operation to take effect. If the timeout expires and the
* operation would continue to block,
* <B>java.io.InterruptedIOException</B> is raised. The Socket is
* not closed in this case.
*
* <P> Valid for all sockets: SocketImpl, DatagramSocketImpl
*
* @see Socket#setSoTimeout
* @see ServerSocket#setSoTimeout
* @see DatagramSocket#setSoTimeout
*/
@Native public static final int SO_TIMEOUT = 0x1006;
/**
* Set a hint the size of the underlying buffers used by the
* platform for outgoing network I/O. When used in set, this is a
* suggestion to the kernel from the application about the size of
* buffers to use for the data to be sent over the socket. When
* used in get, this must return the size of the buffer actually
* used by the platform when sending out data on this socket.
*
* Valid for all sockets: SocketImpl, DatagramSocketImpl
*
* @see Socket#setSendBufferSize
* @see Socket#getSendBufferSize
* @see DatagramSocket#setSendBufferSize
* @see DatagramSocket#getSendBufferSize
*/
@Native public static final int SO_SNDBUF = 0x1001;
/**
* Set a hint the size of the underlying buffers used by the
* platform for incoming network I/O. When used in set, this is a
* suggestion to the kernel from the application about the size of
* buffers to use for the data to be received over the
* socket. When used in get, this must return the size of the
* buffer actually used by the platform when receiving in data on
* this socket.
*
* Valid for all sockets: SocketImpl, DatagramSocketImpl
*
* @see Socket#setReceiveBufferSize
* @see Socket#getReceiveBufferSize
* @see DatagramSocket#setReceiveBufferSize
* @see DatagramSocket#getReceiveBufferSize
*/
@Native public static final int SO_RCVBUF = 0x1002;
/**
* When the keepalive option is set for a TCP socket and no data
* has been exchanged across the socket in either direction for
* 2 hours (NOTE: the actual value is implementation dependent),
* TCP automatically sends a keepalive probe to the peer. This probe is a
* TCP segment to which the peer must respond.
* One of three responses is expected:
* 1. The peer responds with the expected ACK. The application is not
* notified (since everything is OK). TCP will send another probe
* following another 2 hours of inactivity.
* 2. The peer responds with an RST, which tells the local TCP that
* the peer host has crashed and rebooted. The socket is closed.
* 3. There is no response from the peer. The socket is closed.
*
* The purpose of this option is to detect if the peer host crashes.
*
* Valid only for TCP socket: SocketImpl
*
* @see Socket#setKeepAlive
* @see Socket#getKeepAlive
*/
@Native public static final int SO_KEEPALIVE = 0x0008;
/**
* When the OOBINLINE option is set, any TCP urgent data received on
* the socket will be received through the socket input stream.
* When the option is disabled (which is the default) urgent data
* is silently discarded.
*
* @see Socket#setOOBInline
* @see Socket#getOOBInline
*/
@Native public static final int SO_OOBINLINE = 0x1003;
}

View file

@ -0,0 +1,186 @@
/*
* Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.net;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
/**
* This stream extends FileOutputStream to implement a
* SocketOutputStream. Note that this class should <b>NOT</b> be
* public.
*
* @author Jonathan Payne
* @author Arthur van Hoff
*/
class SocketOutputStream extends FileOutputStream
{
static {
init();
}
private AbstractPlainSocketImpl impl = null;
private byte temp[] = new byte[1];
private Socket socket = null;
/**
* Creates a new SocketOutputStream. Can only be called
* by a Socket. This method needs to hang on to the owner Socket so
* that the fd will not be closed.
* @param impl the socket output stream inplemented
*/
SocketOutputStream(AbstractPlainSocketImpl impl) throws IOException {
super(impl.getFileDescriptor());
this.impl = impl;
socket = impl.getSocket();
}
/**
* Returns the unique {@link java.nio.channels.FileChannel FileChannel}
* object associated with this file output stream. </p>
*
* The {@code getChannel} method of {@code SocketOutputStream}
* returns {@code null} since it is a socket based stream.</p>
*
* @return the file channel associated with this file output stream
*
* @since 1.4
* @spec JSR-51
*/
public final FileChannel getChannel() {
return null;
}
/**
* Writes to the socket.
* @param fd the FileDescriptor
* @param b the data to be written
* @param off the start offset in the data
* @param len the number of bytes that are written
* @exception IOException If an I/O error has occurred.
*/
private native void socketWrite0(FileDescriptor fd, byte[] b, int off,
int len) throws IOException;
/**
* Writes to the socket with appropriate locking of the
* FileDescriptor.
* @param b the data to be written
* @param off the start offset in the data
* @param len the number of bytes that are written
* @exception IOException If an I/O error has occurred.
*/
private void socketWrite(byte b[], int off, int len) throws IOException {
if (len <= 0 || off < 0 || len > b.length - off) {
if (len == 0) {
return;
}
throw new ArrayIndexOutOfBoundsException("len == " + len
+ " off == " + off + " buffer length == " + b.length);
}
FileDescriptor fd = impl.acquireFD();
try {
socketWrite0(fd, b, off, len);
} catch (SocketException se) {
if (se instanceof sun.net.ConnectionResetException) {
impl.setConnectionResetPending();
se = new SocketException("Connection reset");
}
if (impl.isClosedOrPending()) {
throw new SocketException("Socket closed");
} else {
throw se;
}
} finally {
impl.releaseFD();
}
}
/**
* Writes a byte to the socket.
* @param b the data to be written
* @exception IOException If an I/O error has occurred.
*/
public void write(int b) throws IOException {
temp[0] = (byte)b;
socketWrite(temp, 0, 1);
}
/**
* Writes the contents of the buffer <i>b</i> to the socket.
* @param b the data to be written
* @exception SocketException If an I/O error has occurred.
*/
public void write(byte b[]) throws IOException {
socketWrite(b, 0, b.length);
}
/**
* Writes <i>length</i> bytes from buffer <i>b</i> starting at
* offset <i>len</i>.
* @param b the data to be written
* @param off the start offset in the data
* @param len the number of bytes that are written
* @exception SocketException If an I/O error has occurred.
*/
public void write(byte b[], int off, int len) throws IOException {
socketWrite(b, off, len);
}
/**
* Closes the stream.
*/
private boolean closing = false;
public void close() throws IOException {
// Prevent recursion. See BugId 4484411
if (closing)
return;
closing = true;
if (socket != null) {
if (!socket.isClosed())
socket.close();
} else
impl.close();
closing = false;
}
/**
* Overrides finalize, the fd is closed by the Socket.
*/
@SuppressWarnings("deprecation")
protected void finalize() {}
/**
* Perform class load-time initializations.
*/
private static native void init();
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,50 @@
/*
* Copyright (c) 2000, 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. 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 java.net;
/**
* Signals that a timeout has occurred on a socket read or accept.
*
* @since 1.4
*/
public class SocketTimeoutException extends java.io.InterruptedIOException {
private static final long serialVersionUID = -8846654841826352300L;
/**
* Constructs a new SocketTimeoutException with a detail
* message.
* @param msg the detail message
*/
public SocketTimeoutException(String msg) {
super(msg);
}
/**
* Construct a new SocketTimeoutException with no detailed message.
*/
public SocketTimeoutException() {}
}

View file

@ -0,0 +1,58 @@
/*
* Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* 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 java.net;
/**
* Constants used by the SOCKS protocol implementation.
*/
interface SocksConsts {
static final int PROTO_VERS4 = 4;
static final int PROTO_VERS = 5;
static final int DEFAULT_PORT = 1080;
static final int NO_AUTH = 0;
static final int GSSAPI = 1;
static final int USER_PASSW = 2;
static final int NO_METHODS = -1;
static final int CONNECT = 1;
static final int BIND = 2;
static final int UDP_ASSOC = 3;
static final int IPV4 = 1;
static final int DOMAIN_NAME = 3;
static final int IPV6 = 4;
static final int REQUEST_OK = 0;
static final int GENERAL_FAILURE = 1;
static final int NOT_ALLOWED = 2;
static final int NET_UNREACHABLE = 3;
static final int HOST_UNREACHABLE = 4;
static final int CONN_REFUSED = 5;
static final int TTL_EXPIRED = 6;
static final int CMD_NOT_SUPPORTED = 7;
static final int ADDR_TYPE_NOT_SUP = 8;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,45 @@
/*
* Copyright (c) 2007, 2009, 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 java.net;
/**
* Defines the standard families of communication protocols.
*
* @since 1.7
*/
public enum StandardProtocolFamily implements ProtocolFamily {
/**
* Internet Protocol Version 4 (IPv4)
*/
INET,
/**
* Internet Protocol Version 6 (IPv6)
*/
INET6
}

View file

@ -0,0 +1,390 @@
/*
* Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.net;
/**
* Defines the <em>standard</em> socket options.
*
* <p> The {@link SocketOption#name name} of each socket option defined by this
* class is its field name.
*
* <p> In this release, the socket options defined here are used by {@link
* java.nio.channels.NetworkChannel network} channels in the {@link
* java.nio.channels channels} package.
*
* @since 1.7
*/
public final class StandardSocketOptions {
private StandardSocketOptions() { }
// -- SOL_SOCKET --
/**
* Allow transmission of broadcast datagrams.
*
* <p> The value of this socket option is a {@code Boolean} that represents
* whether the option is enabled or disabled. The option is specific to
* datagram-oriented sockets sending to {@link java.net.Inet4Address IPv4}
* broadcast addresses. When the socket option is enabled then the socket
* can be used to send <em>broadcast datagrams</em>.
*
* <p> The initial value of this socket option is {@code FALSE}. The socket
* option may be enabled or disabled at any time. Some operating systems may
* require that the Java virtual machine be started with implementation
* specific privileges to enable this option or send broadcast datagrams.
*
* @see <a href="http://www.ietf.org/rfc/rfc919.txt">RFC&nbsp;929:
* Broadcasting Internet Datagrams</a>
* @see DatagramSocket#setBroadcast
*/
public static final SocketOption<Boolean> SO_BROADCAST =
new StdSocketOption<Boolean>("SO_BROADCAST", Boolean.class);
/**
* Keep connection alive.
*
* <p> The value of this socket option is a {@code Boolean} that represents
* whether the option is enabled or disabled. When the {@code SO_KEEPALIVE}
* option is enabled the operating system may use a <em>keep-alive</em>
* mechanism to periodically probe the other end of a connection when the
* connection is otherwise idle. The exact semantics of the keep alive
* mechanism is system dependent and therefore unspecified.
*
* <p> The initial value of this socket option is {@code FALSE}. The socket
* option may be enabled or disabled at any time.
*
* @see <a href="http://www.ietf.org/rfc/rfc1122.txt">RFC&nbsp;1122
* Requirements for Internet Hosts -- Communication Layers</a>
* @see Socket#setKeepAlive
*/
public static final SocketOption<Boolean> SO_KEEPALIVE =
new StdSocketOption<Boolean>("SO_KEEPALIVE", Boolean.class);
/**
* The size of the socket send buffer.
*
* <p> The value of this socket option is an {@code Integer} that is the
* size of the socket send buffer in bytes. The socket send buffer is an
* output buffer used by the networking implementation. It may need to be
* increased for high-volume connections. The value of the socket option is
* a <em>hint</em> to the implementation to size the buffer and the actual
* size may differ. The socket option can be queried to retrieve the actual
* size.
*
* <p> For datagram-oriented sockets, the size of the send buffer may limit
* the size of the datagrams that may be sent by the socket. Whether
* datagrams larger than the buffer size are sent or discarded is system
* dependent.
*
* <p> The initial/default size of the socket send buffer and the range of
* allowable values is system dependent although a negative size is not
* allowed. An attempt to set the socket send buffer to larger than its
* maximum size causes it to be set to its maximum size.
*
* <p> An implementation allows this socket option to be set before the
* socket is bound or connected. Whether an implementation allows the
* socket send buffer to be changed after the socket is bound is system
* dependent.
*
* @see Socket#setSendBufferSize
*/
public static final SocketOption<Integer> SO_SNDBUF =
new StdSocketOption<Integer>("SO_SNDBUF", Integer.class);
/**
* The size of the socket receive buffer.
*
* <p> The value of this socket option is an {@code Integer} that is the
* size of the socket receive buffer in bytes. The socket receive buffer is
* an input buffer used by the networking implementation. It may need to be
* increased for high-volume connections or decreased to limit the possible
* backlog of incoming data. The value of the socket option is a
* <em>hint</em> to the implementation to size the buffer and the actual
* size may differ.
*
* <p> For datagram-oriented sockets, the size of the receive buffer may
* limit the size of the datagrams that can be received. Whether datagrams
* larger than the buffer size can be received is system dependent.
* Increasing the socket receive buffer may be important for cases where
* datagrams arrive in bursts faster than they can be processed.
*
* <p> In the case of stream-oriented sockets and the TCP/IP protocol, the
* size of the socket receive buffer may be used when advertising the size
* of the TCP receive window to the remote peer.
*
* <p> The initial/default size of the socket receive buffer and the range
* of allowable values is system dependent although a negative size is not
* allowed. An attempt to set the socket receive buffer to larger than its
* maximum size causes it to be set to its maximum size.
*
* <p> An implementation allows this socket option to be set before the
* socket is bound or connected. Whether an implementation allows the
* socket receive buffer to be changed after the socket is bound is system
* dependent.
*
* @see <a href="http://www.ietf.org/rfc/rfc1323.txt">RFC&nbsp;1323: TCP
* Extensions for High Performance</a>
* @see Socket#setReceiveBufferSize
* @see ServerSocket#setReceiveBufferSize
*/
public static final SocketOption<Integer> SO_RCVBUF =
new StdSocketOption<Integer>("SO_RCVBUF", Integer.class);
/**
* Re-use address.
*
* <p> The value of this socket option is a {@code Boolean} that represents
* whether the option is enabled or disabled. The exact semantics of this
* socket option are socket type and system dependent.
*
* <p> In the case of stream-oriented sockets, this socket option will
* usually determine whether the socket can be bound to a socket address
* when a previous connection involving that socket address is in the
* <em>TIME_WAIT</em> state. On implementations where the semantics differ,
* and the socket option is not required to be enabled in order to bind the
* socket when a previous connection is in this state, then the
* implementation may choose to ignore this option.
*
* <p> For datagram-oriented sockets the socket option is used to allow
* multiple programs bind to the same address. This option should be enabled
* when the socket is to be used for Internet Protocol (IP) multicasting.
*
* <p> An implementation allows this socket option to be set before the
* socket is bound or connected. Changing the value of this socket option
* after the socket is bound has no effect. The default value of this
* socket option is system dependent.
*
* @see <a href="http://www.ietf.org/rfc/rfc793.txt">RFC&nbsp;793: Transmission
* Control Protocol</a>
* @see ServerSocket#setReuseAddress
*/
public static final SocketOption<Boolean> SO_REUSEADDR =
new StdSocketOption<Boolean>("SO_REUSEADDR", Boolean.class);
/**
* Re-use port.
*
* <p> The value of this socket option is a {@code Boolean} that represents
* whether the option is enabled or disabled. The exact semantics of this
* socket option are socket type and system dependent.
*
* <p> In the case of stream-oriented sockets, this socket option usually allows
* multiple listening sockets to be bound to both same address
* and same port.
*
* <p> For datagram-oriented sockets the socket option usually allows
* multiple UDP sockets to be bound to the same address and port.
*
* <p> An implementation allows this socket option to be set before the
* socket is bound or connected. Changing the value of this socket option
* after the socket is bound has no effect.
*
* @since 9
*/
public static final SocketOption<Boolean> SO_REUSEPORT =
new StdSocketOption<Boolean>("SO_REUSEPORT", Boolean.class);
/**
* Linger on close if data is present.
*
* <p> The value of this socket option is an {@code Integer} that controls
* the action taken when unsent data is queued on the socket and a method
* to close the socket is invoked. If the value of the socket option is zero
* or greater, then it represents a timeout value, in seconds, known as the
* <em>linger interval</em>. The linger interval is the timeout for the
* {@code close} method to block while the operating system attempts to
* transmit the unsent data or it decides that it is unable to transmit the
* data. If the value of the socket option is less than zero then the option
* is disabled. In that case the {@code close} method does not wait until
* unsent data is transmitted; if possible the operating system will transmit
* any unsent data before the connection is closed.
*
* <p> This socket option is intended for use with sockets that are configured
* in {@link java.nio.channels.SelectableChannel#isBlocking() blocking} mode
* only. The behavior of the {@code close} method when this option is
* enabled on a non-blocking socket is not defined.
*
* <p> The initial value of this socket option is a negative value, meaning
* that the option is disabled. The option may be enabled, or the linger
* interval changed, at any time. The maximum value of the linger interval
* is system dependent. Setting the linger interval to a value that is
* greater than its maximum value causes the linger interval to be set to
* its maximum value.
*
* @see Socket#setSoLinger
*/
public static final SocketOption<Integer> SO_LINGER =
new StdSocketOption<Integer>("SO_LINGER", Integer.class);
// -- IPPROTO_IP --
/**
* The Type of Service (ToS) octet in the Internet Protocol (IP) header.
*
* <p> The value of this socket option is an {@code Integer} representing
* the value of the ToS octet in IP packets sent by sockets to an {@link
* StandardProtocolFamily#INET IPv4} socket. The interpretation of the ToS
* octet is network specific and is not defined by this class. Further
* information on the ToS octet can be found in <a
* href="http://www.ietf.org/rfc/rfc1349.txt">RFC&nbsp;1349</a> and <a
* href="http://www.ietf.org/rfc/rfc2474.txt">RFC&nbsp;2474</a>. The value
* of the socket option is a <em>hint</em>. An implementation may ignore the
* value, or ignore specific values.
*
* <p> The initial/default value of the TOS field in the ToS octet is
* implementation specific but will typically be {@code 0}. For
* datagram-oriented sockets the option may be configured at any time after
* the socket has been bound. The new value of the octet is used when sending
* subsequent datagrams. It is system dependent whether this option can be
* queried or changed prior to binding the socket.
*
* <p> The behavior of this socket option on a stream-oriented socket, or an
* {@link StandardProtocolFamily#INET6 IPv6} socket, is not defined in this
* release.
*
* @see DatagramSocket#setTrafficClass
*/
public static final SocketOption<Integer> IP_TOS =
new StdSocketOption<Integer>("IP_TOS", Integer.class);
/**
* The network interface for Internet Protocol (IP) multicast datagrams.
*
* <p> The value of this socket option is a {@link NetworkInterface} that
* represents the outgoing interface for multicast datagrams sent by the
* datagram-oriented socket. For {@link StandardProtocolFamily#INET6 IPv6}
* sockets then it is system dependent whether setting this option also
* sets the outgoing interface for multicast datagrams sent to IPv4
* addresses.
*
* <p> The initial/default value of this socket option may be {@code null}
* to indicate that outgoing interface will be selected by the operating
* system, typically based on the network routing tables. An implementation
* allows this socket option to be set after the socket is bound. Whether
* the socket option can be queried or changed prior to binding the socket
* is system dependent.
*
* @see java.nio.channels.MulticastChannel
* @see MulticastSocket#setInterface
*/
public static final SocketOption<NetworkInterface> IP_MULTICAST_IF =
new StdSocketOption<NetworkInterface>("IP_MULTICAST_IF", NetworkInterface.class);
/**
* The <em>time-to-live</em> for Internet Protocol (IP) multicast datagrams.
*
* <p> The value of this socket option is an {@code Integer} in the range
* {@code 0 <= value <= 255}. It is used to control the scope of multicast
* datagrams sent by the datagram-oriented socket.
* In the case of an {@link StandardProtocolFamily#INET IPv4} socket
* the option is the time-to-live (TTL) on multicast datagrams sent by the
* socket. Datagrams with a TTL of zero are not transmitted on the network
* but may be delivered locally. In the case of an {@link
* StandardProtocolFamily#INET6 IPv6} socket the option is the
* <em>hop limit</em> which is number of <em>hops</em> that the datagram can
* pass through before expiring on the network. For IPv6 sockets it is
* system dependent whether the option also sets the <em>time-to-live</em>
* on multicast datagrams sent to IPv4 addresses.
*
* <p> The initial/default value of the time-to-live setting is typically
* {@code 1}. An implementation allows this socket option to be set after
* the socket is bound. Whether the socket option can be queried or changed
* prior to binding the socket is system dependent.
*
* @see java.nio.channels.MulticastChannel
* @see MulticastSocket#setTimeToLive
*/
public static final SocketOption<Integer> IP_MULTICAST_TTL =
new StdSocketOption<Integer>("IP_MULTICAST_TTL", Integer.class);
/**
* Loopback for Internet Protocol (IP) multicast datagrams.
*
* <p> The value of this socket option is a {@code Boolean} that controls
* the <em>loopback</em> of multicast datagrams. The value of the socket
* option represents if the option is enabled or disabled.
*
* <p> The exact semantics of this socket options are system dependent.
* In particular, it is system dependent whether the loopback applies to
* multicast datagrams sent from the socket or received by the socket.
* For {@link StandardProtocolFamily#INET6 IPv6} sockets then it is
* system dependent whether the option also applies to multicast datagrams
* sent to IPv4 addresses.
*
* <p> The initial/default value of this socket option is {@code TRUE}. An
* implementation allows this socket option to be set after the socket is
* bound. Whether the socket option can be queried or changed prior to
* binding the socket is system dependent.
*
* @see java.nio.channels.MulticastChannel
* @see MulticastSocket#setLoopbackMode
*/
public static final SocketOption<Boolean> IP_MULTICAST_LOOP =
new StdSocketOption<Boolean>("IP_MULTICAST_LOOP", Boolean.class);
// -- IPPROTO_TCP --
/**
* Disable the Nagle algorithm.
*
* <p> The value of this socket option is a {@code Boolean} that represents
* whether the option is enabled or disabled. The socket option is specific to
* stream-oriented sockets using the TCP/IP protocol. TCP/IP uses an algorithm
* known as <em>The Nagle Algorithm</em> to coalesce short segments and
* improve network efficiency.
*
* <p> The default value of this socket option is {@code FALSE}. The
* socket option should only be enabled in cases where it is known that the
* coalescing impacts performance. The socket option may be enabled at any
* time. In other words, the Nagle Algorithm can be disabled. Once the option
* is enabled, it is system dependent whether it can be subsequently
* disabled. If it cannot, then invoking the {@code setOption} method to
* disable the option has no effect.
*
* @see <a href="http://www.ietf.org/rfc/rfc1122.txt">RFC&nbsp;1122:
* Requirements for Internet Hosts -- Communication Layers</a>
* @see Socket#setTcpNoDelay
*/
public static final SocketOption<Boolean> TCP_NODELAY =
new StdSocketOption<Boolean>("TCP_NODELAY", Boolean.class);
private static class StdSocketOption<T> implements SocketOption<T> {
private final String name;
private final Class<T> type;
StdSocketOption(String name, Class<T> type) {
this.name = name;
this.type = type;
}
@Override public String name() { return name; }
@Override public Class<T> type() { return type; }
@Override public String toString() { return name; }
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,135 @@
/*
* Copyright (c) 2000, 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 java.net;
/**
* Checked exception thrown to indicate that a string could not be parsed as a
* URI reference.
*
* @author Mark Reinhold
* @see URI
* @since 1.4
*/
public class URISyntaxException
extends Exception
{
private static final long serialVersionUID = 2137979680897488891L;
private String input;
private int index;
/**
* Constructs an instance from the given input string, reason, and error
* index.
*
* @param input The input string
* @param reason A string explaining why the input could not be parsed
* @param index The index at which the parse error occurred,
* or {@code -1} if the index is not known
*
* @throws NullPointerException
* If either the input or reason strings are {@code null}
*
* @throws IllegalArgumentException
* If the error index is less than {@code -1}
*/
public URISyntaxException(String input, String reason, int index) {
super(reason);
if ((input == null) || (reason == null))
throw new NullPointerException();
if (index < -1)
throw new IllegalArgumentException();
this.input = input;
this.index = index;
}
/**
* Constructs an instance from the given input string and reason. The
* resulting object will have an error index of {@code -1}.
*
* @param input The input string
* @param reason A string explaining why the input could not be parsed
*
* @throws NullPointerException
* If either the input or reason strings are {@code null}
*/
public URISyntaxException(String input, String reason) {
this(input, reason, -1);
}
/**
* Returns the input string.
*
* @return The input string
*/
public String getInput() {
return input;
}
/**
* Returns a string explaining why the input string could not be parsed.
*
* @return The reason string
*/
public String getReason() {
return super.getMessage();
}
/**
* Returns an index into the input string of the position at which the
* parse error occurred, or {@code -1} if this position is not known.
*
* @return The error index
*/
public int getIndex() {
return index;
}
/**
* Returns a string describing the parse error. The resulting string
* consists of the reason string followed by a colon character
* ({@code ':'}), a space, and the input string. If the error index is
* defined then the string {@code " at index "} followed by the index, in
* decimal, is inserted after the reason string and before the colon
* character.
*
* @return A string describing the parse error
*/
public String getMessage() {
StringBuilder sb = new StringBuilder();
sb.append(getReason());
if (index > -1) {
sb.append(" at index ");
sb.append(index);
}
sb.append(": ");
sb.append(input);
return sb.toString();
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,892 @@
/*
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.net;
import java.io.Closeable;
import java.io.File;
import java.io.FilePermission;
import java.io.IOException;
import java.io.InputStream;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.CodeSigner;
import java.security.CodeSource;
import java.security.Permission;
import java.security.PermissionCollection;
import java.security.PrivilegedAction;
import java.security.PrivilegedExceptionAction;
import java.security.SecureClassLoader;
import java.util.Enumeration;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.jar.Attributes;
import java.util.jar.Attributes.Name;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import jdk.internal.loader.Resource;
import jdk.internal.loader.URLClassPath;
import jdk.internal.misc.JavaNetURLClassLoaderAccess;
import jdk.internal.misc.SharedSecrets;
import jdk.internal.perf.PerfCounter;
import sun.net.www.ParseUtil;
import sun.security.util.SecurityConstants;
/**
* This class loader is used to load classes and resources from a search
* path of URLs referring to both JAR files and directories. Any {@code jar:}
* scheme URL (see {@link java.net.JarURLConnection}) is assumed to refer to a
* JAR file. Any {@code file:} scheme URL that ends with a '/' is assumed to
* refer to a directory. Otherwise, the URL is assumed to refer to a JAR file
* which will be opened as needed.
* <p>
* This class loader supports the loading of classes and resources from the
* contents of a <a href="../util/jar/JarFile.html#multirelease">multi-release</a>
* JAR file that is referred to by a given URL.
* <p>
* The AccessControlContext of the thread that created the instance of
* URLClassLoader will be used when subsequently loading classes and
* resources.
* <p>
* The classes that are loaded are by default granted permission only to
* access the URLs specified when the URLClassLoader was created.
*
* @author David Connelly
* @since 1.2
*/
public class URLClassLoader extends SecureClassLoader implements Closeable {
/* The search path for classes and resources */
private final URLClassPath ucp;
/* The context to be used when loading classes and resources */
private final AccessControlContext acc;
/**
* Constructs a new URLClassLoader for the given URLs. The URLs will be
* searched in the order specified for classes and resources after first
* searching in the specified parent class loader. Any {@code jar:}
* scheme URL is assumed to refer to a JAR file. Any {@code file:} scheme
* URL that ends with a '/' is assumed to refer to a directory. Otherwise,
* the URL is assumed to refer to a JAR file which will be downloaded and
* opened as needed.
*
* <p>If there is a security manager, this method first
* calls the security manager's {@code checkCreateClassLoader} method
* to ensure creation of a class loader is allowed.
*
* @param urls the URLs from which to load classes and resources
* @param parent the parent class loader for delegation
* @exception SecurityException if a security manager exists and its
* {@code checkCreateClassLoader} method doesn't allow
* creation of a class loader.
* @exception NullPointerException if {@code urls} is {@code null}.
* @see SecurityManager#checkCreateClassLoader
*/
public URLClassLoader(URL[] urls, ClassLoader parent) {
super(parent);
// this is to make the stack depth consistent with 1.1
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkCreateClassLoader();
}
this.acc = AccessController.getContext();
this.ucp = new URLClassPath(urls, acc);
}
URLClassLoader(String name, URL[] urls, ClassLoader parent,
AccessControlContext acc) {
super(name, parent);
// this is to make the stack depth consistent with 1.1
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkCreateClassLoader();
}
this.acc = acc;
this.ucp = new URLClassPath(urls, acc);
}
/**
* Constructs a new URLClassLoader for the specified URLs using the
* default delegation parent {@code ClassLoader}. The URLs will
* be searched in the order specified for classes and resources after
* first searching in the parent class loader. Any URL that ends with
* a '/' is assumed to refer to a directory. Otherwise, the URL is
* assumed to refer to a JAR file which will be downloaded and opened
* as needed.
*
* <p>If there is a security manager, this method first
* calls the security manager's {@code checkCreateClassLoader} method
* to ensure creation of a class loader is allowed.
*
* @param urls the URLs from which to load classes and resources
*
* @exception SecurityException if a security manager exists and its
* {@code checkCreateClassLoader} method doesn't allow
* creation of a class loader.
* @exception NullPointerException if {@code urls} is {@code null}.
* @see SecurityManager#checkCreateClassLoader
*/
public URLClassLoader(URL[] urls) {
super();
// this is to make the stack depth consistent with 1.1
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkCreateClassLoader();
}
this.acc = AccessController.getContext();
this.ucp = new URLClassPath(urls, acc);
}
URLClassLoader(URL[] urls, AccessControlContext acc) {
super();
// this is to make the stack depth consistent with 1.1
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkCreateClassLoader();
}
this.acc = acc;
this.ucp = new URLClassPath(urls, acc);
}
/**
* Constructs a new URLClassLoader for the specified URLs, parent
* class loader, and URLStreamHandlerFactory. The parent argument
* will be used as the parent class loader for delegation. The
* factory argument will be used as the stream handler factory to
* obtain protocol handlers when creating new jar URLs.
*
* <p>If there is a security manager, this method first
* calls the security manager's {@code checkCreateClassLoader} method
* to ensure creation of a class loader is allowed.
*
* @param urls the URLs from which to load classes and resources
* @param parent the parent class loader for delegation
* @param factory the URLStreamHandlerFactory to use when creating URLs
*
* @exception SecurityException if a security manager exists and its
* {@code checkCreateClassLoader} method doesn't allow
* creation of a class loader.
* @exception NullPointerException if {@code urls} is {@code null}.
* @see SecurityManager#checkCreateClassLoader
*/
public URLClassLoader(URL[] urls, ClassLoader parent,
URLStreamHandlerFactory factory) {
super(parent);
// this is to make the stack depth consistent with 1.1
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkCreateClassLoader();
}
this.acc = AccessController.getContext();
this.ucp = new URLClassPath(urls, factory, acc);
}
/**
* Constructs a new named {@code URLClassLoader} for the specified URLs.
* The URLs will be searched in the order specified for classes
* and resources after first searching in the specified parent class loader.
* Any URL that ends with a '/' is assumed to refer to a directory.
* Otherwise, the URL is assumed to refer to a JAR file which will be
* downloaded and opened as needed.
*
* @param name class loader name; or {@code null} if not named
* @param urls the URLs from which to load classes and resources
* @param parent the parent class loader for delegation
*
* @throws IllegalArgumentException if the given name is empty.
* @throws NullPointerException if {@code urls} is {@code null}.
*
* @throws SecurityException if a security manager exists and its
* {@link SecurityManager#checkCreateClassLoader()} method doesn't
* allow creation of a class loader.
*
* @since 9
* @spec JPMS
*/
public URLClassLoader(String name,
URL[] urls,
ClassLoader parent) {
super(name, parent);
// this is to make the stack depth consistent with 1.1
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkCreateClassLoader();
}
this.acc = AccessController.getContext();
this.ucp = new URLClassPath(urls, acc);
}
/**
* Constructs a new named {@code URLClassLoader} for the specified URLs,
* parent class loader, and URLStreamHandlerFactory.
* The parent argument will be used as the parent class loader for delegation.
* The factory argument will be used as the stream handler factory to
* obtain protocol handlers when creating new jar URLs.
*
* @param name class loader name; or {@code null} if not named
* @param urls the URLs from which to load classes and resources
* @param parent the parent class loader for delegation
* @param factory the URLStreamHandlerFactory to use when creating URLs
*
* @throws IllegalArgumentException if the given name is empty.
* @throws NullPointerException if {@code urls} is {@code null}.
*
* @throws SecurityException if a security manager exists and its
* {@code checkCreateClassLoader} method doesn't allow
* creation of a class loader.
*
* @since 9
* @spec JPMS
*/
public URLClassLoader(String name, URL[] urls, ClassLoader parent,
URLStreamHandlerFactory factory) {
super(name, parent);
// this is to make the stack depth consistent with 1.1
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkCreateClassLoader();
}
this.acc = AccessController.getContext();
this.ucp = new URLClassPath(urls, factory, acc);
}
/* A map (used as a set) to keep track of closeable local resources
* (either JarFiles or FileInputStreams). We don't care about
* Http resources since they don't need to be closed.
*
* If the resource is coming from a jar file
* we keep a (weak) reference to the JarFile object which can
* be closed if URLClassLoader.close() called. Due to jar file
* caching there will typically be only one JarFile object
* per underlying jar file.
*
* For file resources, which is probably a less common situation
* we have to keep a weak reference to each stream.
*/
private WeakHashMap<Closeable,Void>
closeables = new WeakHashMap<>();
/**
* Returns an input stream for reading the specified resource.
* If this loader is closed, then any resources opened by this method
* will be closed.
*
* <p> The search order is described in the documentation for {@link
* #getResource(String)}. </p>
*
* @param name
* The resource name
*
* @return An input stream for reading the resource, or {@code null}
* if the resource could not be found
*
* @throws NullPointerException If {@code name} is {@code null}
*
* @since 1.7
*/
public InputStream getResourceAsStream(String name) {
Objects.requireNonNull(name);
URL url = getResource(name);
try {
if (url == null) {
return null;
}
URLConnection urlc = url.openConnection();
InputStream is = urlc.getInputStream();
if (urlc instanceof JarURLConnection) {
JarURLConnection juc = (JarURLConnection)urlc;
JarFile jar = juc.getJarFile();
synchronized (closeables) {
if (!closeables.containsKey(jar)) {
closeables.put(jar, null);
}
}
} else if (urlc instanceof sun.net.www.protocol.file.FileURLConnection) {
synchronized (closeables) {
closeables.put(is, null);
}
}
return is;
} catch (IOException e) {
return null;
}
}
/**
* Closes this URLClassLoader, so that it can no longer be used to load
* new classes or resources that are defined by this loader.
* Classes and resources defined by any of this loader's parents in the
* delegation hierarchy are still accessible. Also, any classes or resources
* that are already loaded, are still accessible.
* <p>
* In the case of jar: and file: URLs, it also closes any files
* that were opened by it. If another thread is loading a
* class when the {@code close} method is invoked, then the result of
* that load is undefined.
* <p>
* The method makes a best effort attempt to close all opened files,
* by catching {@link IOException}s internally. Unchecked exceptions
* and errors are not caught. Calling close on an already closed
* loader has no effect.
*
* @exception IOException if closing any file opened by this class loader
* resulted in an IOException. Any such exceptions are caught internally.
* If only one is caught, then it is re-thrown. If more than one exception
* is caught, then the second and following exceptions are added
* as suppressed exceptions of the first one caught, which is then re-thrown.
*
* @exception SecurityException if a security manager is set, and it denies
* {@link RuntimePermission}{@code ("closeClassLoader")}
*
* @since 1.7
*/
public void close() throws IOException {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkPermission(new RuntimePermission("closeClassLoader"));
}
List<IOException> errors = ucp.closeLoaders();
// now close any remaining streams.
synchronized (closeables) {
Set<Closeable> keys = closeables.keySet();
for (Closeable c : keys) {
try {
c.close();
} catch (IOException ioex) {
errors.add(ioex);
}
}
closeables.clear();
}
if (errors.isEmpty()) {
return;
}
IOException firstex = errors.remove(0);
// Suppress any remaining exceptions
for (IOException error: errors) {
firstex.addSuppressed(error);
}
throw firstex;
}
/**
* Appends the specified URL to the list of URLs to search for
* classes and resources.
* <p>
* If the URL specified is {@code null} or is already in the
* list of URLs, or if this loader is closed, then invoking this
* method has no effect.
*
* @param url the URL to be added to the search path of URLs
*/
protected void addURL(URL url) {
ucp.addURL(url);
}
/**
* Returns the search path of URLs for loading classes and resources.
* This includes the original list of URLs specified to the constructor,
* along with any URLs subsequently appended by the addURL() method.
* @return the search path of URLs for loading classes and resources.
*/
public URL[] getURLs() {
return ucp.getURLs();
}
/**
* Finds and loads the class with the specified name from the URL search
* path. Any URLs referring to JAR files are loaded and opened as needed
* until the class is found.
*
* @param name the name of the class
* @return the resulting class
* @exception ClassNotFoundException if the class could not be found,
* or if the loader is closed.
* @exception NullPointerException if {@code name} is {@code null}.
*/
protected Class<?> findClass(final String name)
throws ClassNotFoundException
{
final Class<?> result;
try {
result = AccessController.doPrivileged(
new PrivilegedExceptionAction<>() {
public Class<?> run() throws ClassNotFoundException {
String path = name.replace('.', '/').concat(".class");
Resource res = ucp.getResource(path, false);
if (res != null) {
try {
return defineClass(name, res);
} catch (IOException e) {
throw new ClassNotFoundException(name, e);
}
} else {
return null;
}
}
}, acc);
} catch (java.security.PrivilegedActionException pae) {
throw (ClassNotFoundException) pae.getException();
}
if (result == null) {
throw new ClassNotFoundException(name);
}
return result;
}
/*
* Retrieve the package using the specified package name.
* If non-null, verify the package using the specified code
* source and manifest.
*/
private Package getAndVerifyPackage(String pkgname,
Manifest man, URL url) {
Package pkg = getDefinedPackage(pkgname);
if (pkg != null) {
// Package found, so check package sealing.
if (pkg.isSealed()) {
// Verify that code source URL is the same.
if (!pkg.isSealed(url)) {
throw new SecurityException(
"sealing violation: package " + pkgname + " is sealed");
}
} else {
// Make sure we are not attempting to seal the package
// at this code source URL.
if ((man != null) && isSealed(pkgname, man)) {
throw new SecurityException(
"sealing violation: can't seal package " + pkgname +
": already loaded");
}
}
}
return pkg;
}
/*
* Defines a Class using the class bytes obtained from the specified
* Resource. The resulting Class must be resolved before it can be
* used.
*/
private Class<?> defineClass(String name, Resource res) throws IOException {
long t0 = System.nanoTime();
int i = name.lastIndexOf('.');
URL url = res.getCodeSourceURL();
if (i != -1) {
String pkgname = name.substring(0, i);
// Check if package already loaded.
Manifest man = res.getManifest();
if (getAndVerifyPackage(pkgname, man, url) == null) {
try {
if (man != null) {
definePackage(pkgname, man, url);
} else {
definePackage(pkgname, null, null, null, null, null, null, null);
}
} catch (IllegalArgumentException iae) {
// parallel-capable class loaders: re-verify in case of a
// race condition
if (getAndVerifyPackage(pkgname, man, url) == null) {
// Should never happen
throw new AssertionError("Cannot find package " +
pkgname);
}
}
}
}
// Now read the class bytes and define the class
java.nio.ByteBuffer bb = res.getByteBuffer();
if (bb != null) {
// Use (direct) ByteBuffer:
CodeSigner[] signers = res.getCodeSigners();
CodeSource cs = new CodeSource(url, signers);
PerfCounter.getReadClassBytesTime().addElapsedTimeFrom(t0);
return defineClass(name, bb, cs);
} else {
byte[] b = res.getBytes();
// must read certificates AFTER reading bytes.
CodeSigner[] signers = res.getCodeSigners();
CodeSource cs = new CodeSource(url, signers);
PerfCounter.getReadClassBytesTime().addElapsedTimeFrom(t0);
return defineClass(name, b, 0, b.length, cs);
}
}
/**
* Defines a new package by name in this {@code URLClassLoader}.
* The attributes contained in the specified {@code Manifest}
* will be used to obtain package version and sealing information.
* For sealed packages, the additional URL specifies the code source URL
* from which the package was loaded.
*
* @param name the package name
* @param man the {@code Manifest} containing package version and sealing
* information
* @param url the code source url for the package, or null if none
* @throws IllegalArgumentException if the package name is
* already defined by this class loader
* @return the newly defined {@code Package} object
*
* @revised 9
* @spec JPMS
*/
protected Package definePackage(String name, Manifest man, URL url) {
String path = name.replace('.', '/').concat("/");
String specTitle = null, specVersion = null, specVendor = null;
String implTitle = null, implVersion = null, implVendor = null;
String sealed = null;
URL sealBase = null;
Attributes attr = man.getAttributes(path);
if (attr != null) {
specTitle = attr.getValue(Name.SPECIFICATION_TITLE);
specVersion = attr.getValue(Name.SPECIFICATION_VERSION);
specVendor = attr.getValue(Name.SPECIFICATION_VENDOR);
implTitle = attr.getValue(Name.IMPLEMENTATION_TITLE);
implVersion = attr.getValue(Name.IMPLEMENTATION_VERSION);
implVendor = attr.getValue(Name.IMPLEMENTATION_VENDOR);
sealed = attr.getValue(Name.SEALED);
}
attr = man.getMainAttributes();
if (attr != null) {
if (specTitle == null) {
specTitle = attr.getValue(Name.SPECIFICATION_TITLE);
}
if (specVersion == null) {
specVersion = attr.getValue(Name.SPECIFICATION_VERSION);
}
if (specVendor == null) {
specVendor = attr.getValue(Name.SPECIFICATION_VENDOR);
}
if (implTitle == null) {
implTitle = attr.getValue(Name.IMPLEMENTATION_TITLE);
}
if (implVersion == null) {
implVersion = attr.getValue(Name.IMPLEMENTATION_VERSION);
}
if (implVendor == null) {
implVendor = attr.getValue(Name.IMPLEMENTATION_VENDOR);
}
if (sealed == null) {
sealed = attr.getValue(Name.SEALED);
}
}
if ("true".equalsIgnoreCase(sealed)) {
sealBase = url;
}
return definePackage(name, specTitle, specVersion, specVendor,
implTitle, implVersion, implVendor, sealBase);
}
/*
* Returns true if the specified package name is sealed according to the
* given manifest.
*/
private boolean isSealed(String name, Manifest man) {
String path = name.replace('.', '/').concat("/");
Attributes attr = man.getAttributes(path);
String sealed = null;
if (attr != null) {
sealed = attr.getValue(Name.SEALED);
}
if (sealed == null) {
if ((attr = man.getMainAttributes()) != null) {
sealed = attr.getValue(Name.SEALED);
}
}
return "true".equalsIgnoreCase(sealed);
}
/**
* Finds the resource with the specified name on the URL search path.
*
* @param name the name of the resource
* @return a {@code URL} for the resource, or {@code null}
* if the resource could not be found, or if the loader is closed.
*/
public URL findResource(final String name) {
/*
* The same restriction to finding classes applies to resources
*/
URL url = AccessController.doPrivileged(
new PrivilegedAction<>() {
public URL run() {
return ucp.findResource(name, true);
}
}, acc);
return url != null ? URLClassPath.checkURL(url) : null;
}
/**
* Returns an Enumeration of URLs representing all of the resources
* on the URL search path having the specified name.
*
* @param name the resource name
* @exception IOException if an I/O exception occurs
* @return an {@code Enumeration} of {@code URL}s
* If the loader is closed, the Enumeration will be empty.
*/
public Enumeration<URL> findResources(final String name)
throws IOException
{
final Enumeration<URL> e = ucp.findResources(name, true);
return new Enumeration<>() {
private URL url = null;
private boolean next() {
if (url != null) {
return true;
}
do {
URL u = AccessController.doPrivileged(
new PrivilegedAction<>() {
public URL run() {
if (!e.hasMoreElements())
return null;
return e.nextElement();
}
}, acc);
if (u == null)
break;
url = URLClassPath.checkURL(u);
} while (url == null);
return url != null;
}
public URL nextElement() {
if (!next()) {
throw new NoSuchElementException();
}
URL u = url;
url = null;
return u;
}
public boolean hasMoreElements() {
return next();
}
};
}
/**
* Returns the permissions for the given codesource object.
* The implementation of this method first calls super.getPermissions
* and then adds permissions based on the URL of the codesource.
* <p>
* If the protocol of this URL is "jar", then the permission granted
* is based on the permission that is required by the URL of the Jar
* file.
* <p>
* If the protocol is "file" and there is an authority component, then
* permission to connect to and accept connections from that authority
* may be granted. If the protocol is "file"
* and the path specifies a file, then permission to read that
* file is granted. If protocol is "file" and the path is
* a directory, permission is granted to read all files
* and (recursively) all files and subdirectories contained in
* that directory.
* <p>
* If the protocol is not "file", then permission
* to connect to and accept connections from the URL's host is granted.
* @param codesource the codesource
* @exception NullPointerException if {@code codesource} is {@code null}.
* @return the permissions granted to the codesource
*/
protected PermissionCollection getPermissions(CodeSource codesource)
{
PermissionCollection perms = super.getPermissions(codesource);
URL url = codesource.getLocation();
Permission p;
URLConnection urlConnection;
try {
urlConnection = url.openConnection();
p = urlConnection.getPermission();
} catch (java.io.IOException ioe) {
p = null;
urlConnection = null;
}
if (p instanceof FilePermission) {
// if the permission has a separator char on the end,
// it means the codebase is a directory, and we need
// to add an additional permission to read recursively
String path = p.getName();
if (path.endsWith(File.separator)) {
path += "-";
p = new FilePermission(path, SecurityConstants.FILE_READ_ACTION);
}
} else if ((p == null) && (url.getProtocol().equals("file"))) {
String path = url.getFile().replace('/', File.separatorChar);
path = ParseUtil.decode(path);
if (path.endsWith(File.separator))
path += "-";
p = new FilePermission(path, SecurityConstants.FILE_READ_ACTION);
} else {
/**
* Not loading from a 'file:' URL so we want to give the class
* permission to connect to and accept from the remote host
* after we've made sure the host is the correct one and is valid.
*/
URL locUrl = url;
if (urlConnection instanceof JarURLConnection) {
locUrl = ((JarURLConnection)urlConnection).getJarFileURL();
}
String host = locUrl.getHost();
if (host != null && (host.length() > 0))
p = new SocketPermission(host,
SecurityConstants.SOCKET_CONNECT_ACCEPT_ACTION);
}
// make sure the person that created this class loader
// would have this permission
if (p != null) {
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
final Permission fp = p;
AccessController.doPrivileged(new PrivilegedAction<>() {
public Void run() throws SecurityException {
sm.checkPermission(fp);
return null;
}
}, acc);
}
perms.add(p);
}
return perms;
}
/**
* Creates a new instance of URLClassLoader for the specified
* URLs and parent class loader. If a security manager is
* installed, the {@code loadClass} method of the URLClassLoader
* returned by this method will invoke the
* {@code SecurityManager.checkPackageAccess} method before
* loading the class.
*
* @param urls the URLs to search for classes and resources
* @param parent the parent class loader for delegation
* @exception NullPointerException if {@code urls} is {@code null}.
* @return the resulting class loader
*/
public static URLClassLoader newInstance(final URL[] urls,
final ClassLoader parent) {
// Save the caller's context
final AccessControlContext acc = AccessController.getContext();
// Need a privileged block to create the class loader
URLClassLoader ucl = AccessController.doPrivileged(
new PrivilegedAction<>() {
public URLClassLoader run() {
return new FactoryURLClassLoader(null, urls, parent, acc);
}
});
return ucl;
}
/**
* Creates a new instance of URLClassLoader for the specified
* URLs and default parent class loader. If a security manager is
* installed, the {@code loadClass} method of the URLClassLoader
* returned by this method will invoke the
* {@code SecurityManager.checkPackageAccess} before
* loading the class.
*
* @param urls the URLs to search for classes and resources
* @exception NullPointerException if {@code urls} is {@code null}.
* @return the resulting class loader
*/
public static URLClassLoader newInstance(final URL[] urls) {
// Save the caller's context
final AccessControlContext acc = AccessController.getContext();
// Need a privileged block to create the class loader
URLClassLoader ucl = AccessController.doPrivileged(
new PrivilegedAction<>() {
public URLClassLoader run() {
return new FactoryURLClassLoader(urls, acc);
}
});
return ucl;
}
static {
SharedSecrets.setJavaNetURLClassLoaderAccess(
new JavaNetURLClassLoaderAccess() {
@Override
public AccessControlContext getAccessControlContext(URLClassLoader u) {
return u.acc;
}
}
);
ClassLoader.registerAsParallelCapable();
}
}
final class FactoryURLClassLoader extends URLClassLoader {
static {
ClassLoader.registerAsParallelCapable();
}
FactoryURLClassLoader(String name, URL[] urls, ClassLoader parent,
AccessControlContext acc) {
super(name, urls, parent, acc);
}
FactoryURLClassLoader(URL[] urls, AccessControlContext acc) {
super(urls, acc);
}
public final Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
// First check if we have permission to access the package. This
// should go away once we've added support for exported packages.
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
int i = name.lastIndexOf('.');
if (i != -1) {
sm.checkPackageAccess(name.substring(0, i));
}
}
return super.loadClass(name, resolve);
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,207 @@
/*
* Copyright (c) 1998, 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 java.net;
import java.io.*;
/**
* Utility class for HTML form decoding. This class contains static methods
* for decoding a String from the <CODE>application/x-www-form-urlencoded</CODE>
* MIME format.
* <p>
* The conversion process is the reverse of that used by the URLEncoder class. It is assumed
* that all characters in the encoded string are one of the following:
* &quot;{@code a}&quot; through &quot;{@code z}&quot;,
* &quot;{@code A}&quot; through &quot;{@code Z}&quot;,
* &quot;{@code 0}&quot; through &quot;{@code 9}&quot;, and
* &quot;{@code -}&quot;, &quot;{@code _}&quot;,
* &quot;{@code .}&quot;, and &quot;{@code *}&quot;. The
* character &quot;{@code %}&quot; is allowed but is interpreted
* as the start of a special escaped sequence.
* <p>
* The following rules are applied in the conversion:
*
* <ul>
* <li>The alphanumeric characters &quot;{@code a}&quot; through
* &quot;{@code z}&quot;, &quot;{@code A}&quot; through
* &quot;{@code Z}&quot; and &quot;{@code 0}&quot;
* through &quot;{@code 9}&quot; remain the same.
* <li>The special characters &quot;{@code .}&quot;,
* &quot;{@code -}&quot;, &quot;{@code *}&quot;, and
* &quot;{@code _}&quot; remain the same.
* <li>The plus sign &quot;{@code +}&quot; is converted into a
* space character &quot; &nbsp; &quot; .
* <li>A sequence of the form "<i>{@code %xy}</i>" will be
* treated as representing a byte where <i>xy</i> is the two-digit
* hexadecimal representation of the 8 bits. Then, all substrings
* that contain one or more of these byte sequences consecutively
* will be replaced by the character(s) whose encoding would result
* in those consecutive bytes.
* The encoding scheme used to decode these characters may be specified,
* or if unspecified, the default encoding of the platform will be used.
* </ul>
* <p>
* There are two possible ways in which this decoder could deal with
* illegal strings. It could either leave illegal characters alone or
* it could throw an {@link java.lang.IllegalArgumentException}.
* Which approach the decoder takes is left to the
* implementation.
*
* @author Mark Chamness
* @author Michael McCloskey
* @since 1.2
*/
public class URLDecoder {
// The platform default encoding
static String dfltEncName = URLEncoder.dfltEncName;
/**
* Decodes a {@code x-www-form-urlencoded} string.
* The platform's default encoding is used to determine what characters
* are represented by any consecutive sequences of the form
* "<i>{@code %xy}</i>".
* @param s the {@code String} to decode
* @deprecated The resulting string may vary depending on the platform's
* default encoding. Instead, use the decode(String,String) method
* to specify the encoding.
* @return the newly decoded {@code String}
*/
@Deprecated
public static String decode(String s) {
String str = null;
try {
str = decode(s, dfltEncName);
} catch (UnsupportedEncodingException e) {
// The system should always have the platform default
}
return str;
}
/**
* Decodes an {@code application/x-www-form-urlencoded} string using
* a specific encoding scheme.
* The supplied encoding is used to determine
* what characters are represented by any consecutive sequences of the
* form "<i>{@code %xy}</i>".
* <p>
* <em><strong>Note:</strong> The <a href=
* "http://www.w3.org/TR/html40/appendix/notes.html#non-ascii-chars">
* World Wide Web Consortium Recommendation</a> states that
* UTF-8 should be used. Not doing so may introduce
* incompatibilities.</em>
*
* @param s the {@code String} to decode
* @param enc The name of a supported
* <a href="../lang/package-summary.html#charenc">character
* encoding</a>.
* @return the newly decoded {@code String}
* @exception UnsupportedEncodingException
* If character encoding needs to be consulted, but
* named character encoding is not supported
* @see URLEncoder#encode(java.lang.String, java.lang.String)
* @since 1.4
*/
public static String decode(String s, String enc)
throws UnsupportedEncodingException{
boolean needToChange = false;
int numChars = s.length();
StringBuilder sb = new StringBuilder(numChars > 500 ? numChars / 2 : numChars);
int i = 0;
if (enc.length() == 0) {
throw new UnsupportedEncodingException ("URLDecoder: empty string enc parameter");
}
char c;
byte[] bytes = null;
while (i < numChars) {
c = s.charAt(i);
switch (c) {
case '+':
sb.append(' ');
i++;
needToChange = true;
break;
case '%':
/*
* Starting with this instance of %, process all
* consecutive substrings of the form %xy. Each
* substring %xy will yield a byte. Convert all
* consecutive bytes obtained this way to whatever
* character(s) they represent in the provided
* encoding.
*/
try {
// (numChars-i)/3 is an upper bound for the number
// of remaining bytes
if (bytes == null)
bytes = new byte[(numChars-i)/3];
int pos = 0;
while ( ((i+2) < numChars) &&
(c=='%')) {
int v = Integer.parseInt(s, i + 1, i + 3, 16);
if (v < 0)
throw new IllegalArgumentException("URLDecoder: Illegal hex characters in escape (%) pattern - negative value");
bytes[pos++] = (byte) v;
i+= 3;
if (i < numChars)
c = s.charAt(i);
}
// A trailing, incomplete byte encoding such as
// "%x" will cause an exception to be thrown
if ((i < numChars) && (c=='%'))
throw new IllegalArgumentException(
"URLDecoder: Incomplete trailing escape (%) pattern");
sb.append(new String(bytes, 0, pos, enc));
} catch (NumberFormatException e) {
throw new IllegalArgumentException(
"URLDecoder: Illegal hex characters in escape (%) pattern - "
+ e.getMessage());
}
needToChange = true;
break;
default:
sb.append(c);
i++;
break;
}
}
return (needToChange? sb.toString() : s);
}
}

View file

@ -0,0 +1,283 @@
/*
* Copyright (c) 1995, 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 java.net;
import java.io.UnsupportedEncodingException;
import java.io.CharArrayWriter;
import java.nio.charset.Charset;
import java.nio.charset.IllegalCharsetNameException;
import java.nio.charset.UnsupportedCharsetException ;
import java.util.BitSet;
import sun.security.action.GetPropertyAction;
/**
* Utility class for HTML form encoding. This class contains static methods
* for converting a String to the <CODE>application/x-www-form-urlencoded</CODE> MIME
* format. For more information about HTML form encoding, consult the HTML
* <A HREF="http://www.w3.org/TR/html4/">specification</A>.
*
* <p>
* When encoding a String, the following rules apply:
*
* <ul>
* <li>The alphanumeric characters &quot;{@code a}&quot; through
* &quot;{@code z}&quot;, &quot;{@code A}&quot; through
* &quot;{@code Z}&quot; and &quot;{@code 0}&quot;
* through &quot;{@code 9}&quot; remain the same.
* <li>The special characters &quot;{@code .}&quot;,
* &quot;{@code -}&quot;, &quot;{@code *}&quot;, and
* &quot;{@code _}&quot; remain the same.
* <li>The space character &quot; &nbsp; &quot; is
* converted into a plus sign &quot;{@code +}&quot;.
* <li>All other characters are unsafe and are first converted into
* one or more bytes using some encoding scheme. Then each byte is
* represented by the 3-character string
* &quot;<i>{@code %xy}</i>&quot;, where <i>xy</i> is the
* two-digit hexadecimal representation of the byte.
* The recommended encoding scheme to use is UTF-8. However,
* for compatibility reasons, if an encoding is not specified,
* then the default encoding of the platform is used.
* </ul>
*
* <p>
* For example using UTF-8 as the encoding scheme the string &quot;The
* string &#252;@foo-bar&quot; would get converted to
* &quot;The+string+%C3%BC%40foo-bar&quot; because in UTF-8 the character
* &#252; is encoded as two bytes C3 (hex) and BC (hex), and the
* character @ is encoded as one byte 40 (hex).
*
* @author Herb Jellinek
* @since 1.0
*/
public class URLEncoder {
static BitSet dontNeedEncoding;
static final int caseDiff = ('a' - 'A');
static String dfltEncName = null;
static {
/* The list of characters that are not encoded has been
* determined as follows:
*
* RFC 2396 states:
* -----
* Data characters that are allowed in a URI but do not have a
* reserved purpose are called unreserved. These include upper
* and lower case letters, decimal digits, and a limited set of
* punctuation marks and symbols.
*
* unreserved = alphanum | mark
*
* mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")"
*
* Unreserved characters can be escaped without changing the
* semantics of the URI, but this should not be done unless the
* URI is being used in a context that does not allow the
* unescaped character to appear.
* -----
*
* It appears that both Netscape and Internet Explorer escape
* all special characters from this list with the exception
* of "-", "_", ".", "*". While it is not clear why they are
* escaping the other characters, perhaps it is safest to
* assume that there might be contexts in which the others
* are unsafe if not escaped. Therefore, we will use the same
* list. It is also noteworthy that this is consistent with
* O'Reilly's "HTML: The Definitive Guide" (page 164).
*
* As a last note, Intenet Explorer does not encode the "@"
* character which is clearly not unreserved according to the
* RFC. We are being consistent with the RFC in this matter,
* as is Netscape.
*
*/
dontNeedEncoding = new BitSet(256);
int i;
for (i = 'a'; i <= 'z'; i++) {
dontNeedEncoding.set(i);
}
for (i = 'A'; i <= 'Z'; i++) {
dontNeedEncoding.set(i);
}
for (i = '0'; i <= '9'; i++) {
dontNeedEncoding.set(i);
}
dontNeedEncoding.set(' '); /* encoding a space to a + is done
* in the encode() method */
dontNeedEncoding.set('-');
dontNeedEncoding.set('_');
dontNeedEncoding.set('.');
dontNeedEncoding.set('*');
dfltEncName = GetPropertyAction.privilegedGetProperty("file.encoding");
}
/**
* You can't call the constructor.
*/
private URLEncoder() { }
/**
* Translates a string into {@code x-www-form-urlencoded}
* format. This method uses the platform's default encoding
* as the encoding scheme to obtain the bytes for unsafe characters.
*
* @param s {@code String} to be translated.
* @deprecated The resulting string may vary depending on the platform's
* default encoding. Instead, use the encode(String,String)
* method to specify the encoding.
* @return the translated {@code String}.
*/
@Deprecated
public static String encode(String s) {
String str = null;
try {
str = encode(s, dfltEncName);
} catch (UnsupportedEncodingException e) {
// The system should always have the platform default
}
return str;
}
/**
* Translates a string into {@code application/x-www-form-urlencoded}
* format using a specific encoding scheme. This method uses the
* supplied encoding scheme to obtain the bytes for unsafe
* characters.
* <p>
* <em><strong>Note:</strong> The <a href=
* "http://www.w3.org/TR/html40/appendix/notes.html#non-ascii-chars">
* World Wide Web Consortium Recommendation</a> states that
* UTF-8 should be used. Not doing so may introduce
* incompatibilities.</em>
*
* @param s {@code String} to be translated.
* @param enc The name of a supported
* <a href="../lang/package-summary.html#charenc">character
* encoding</a>.
* @return the translated {@code String}.
* @exception UnsupportedEncodingException
* If the named encoding is not supported
* @see URLDecoder#decode(java.lang.String, java.lang.String)
* @since 1.4
*/
public static String encode(String s, String enc)
throws UnsupportedEncodingException {
boolean needToChange = false;
StringBuilder out = new StringBuilder(s.length());
Charset charset;
CharArrayWriter charArrayWriter = new CharArrayWriter();
if (enc == null)
throw new NullPointerException("charsetName");
try {
charset = Charset.forName(enc);
} catch (IllegalCharsetNameException e) {
throw new UnsupportedEncodingException(enc);
} catch (UnsupportedCharsetException e) {
throw new UnsupportedEncodingException(enc);
}
for (int i = 0; i < s.length();) {
int c = (int) s.charAt(i);
//System.out.println("Examining character: " + c);
if (dontNeedEncoding.get(c)) {
if (c == ' ') {
c = '+';
needToChange = true;
}
//System.out.println("Storing: " + c);
out.append((char)c);
i++;
} else {
// convert to external encoding before hex conversion
do {
charArrayWriter.write(c);
/*
* If this character represents the start of a Unicode
* surrogate pair, then pass in two characters. It's not
* clear what should be done if a byte reserved in the
* surrogate pairs range occurs outside of a legal
* surrogate pair. For now, just treat it as if it were
* any other character.
*/
if (c >= 0xD800 && c <= 0xDBFF) {
/*
System.out.println(Integer.toHexString(c)
+ " is high surrogate");
*/
if ( (i+1) < s.length()) {
int d = (int) s.charAt(i+1);
/*
System.out.println("\tExamining "
+ Integer.toHexString(d));
*/
if (d >= 0xDC00 && d <= 0xDFFF) {
/*
System.out.println("\t"
+ Integer.toHexString(d)
+ " is low surrogate");
*/
charArrayWriter.write(d);
i++;
}
}
}
i++;
} while (i < s.length() && !dontNeedEncoding.get((c = (int) s.charAt(i))));
charArrayWriter.flush();
String str = new String(charArrayWriter.toCharArray());
byte[] ba = str.getBytes(charset);
for (int j = 0; j < ba.length; j++) {
out.append('%');
char ch = Character.forDigit((ba[j] >> 4) & 0xF, 16);
// converting to use uppercase letter as part of
// the hex value if ch is a letter.
if (Character.isLetter(ch)) {
ch -= caseDiff;
}
out.append(ch);
ch = Character.forDigit(ba[j] & 0xF, 16);
if (Character.isLetter(ch)) {
ch -= caseDiff;
}
out.append(ch);
}
charArrayWriter.reset();
needToChange = true;
}
}
return (needToChange? out.toString() : s);
}
}

View file

@ -0,0 +1,549 @@
/*
* Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* 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 java.net;
import java.io.ObjectInputStream;
import java.io.IOException;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
import java.security.Permission;
/**
* Represents permission to access a resource or set of resources defined by a
* given url, and for a given set of user-settable request methods
* and request headers. The <i>name</i> of the permission is the url string.
* The <i>actions</i> string is a concatenation of the request methods and headers.
* The range of method and header names is not restricted by this class.
* <p><b>The url</b><p>
* The url string has the following expected structure.
* <pre>
* scheme : // authority [ / path ]
* </pre>
* <i>scheme</i> will typically be http or https, but is not restricted by this
* class.
* <i>authority</i> is specified as:
* <pre>
* authority = [ userinfo @ ] hostrange [ : portrange ]
* portrange = portnumber | -portnumber | portnumber-[portnumber] | *
* hostrange = ([*.] dnsname) | IPv4address | IPv6address
* </pre>
* <i>dnsname</i> is a standard DNS host or domain name, ie. one or more labels
* separated by ".". <i>IPv4address</i> is a standard literal IPv4 address and
* <i>IPv6address</i> is as defined in <a href="http://www.ietf.org/rfc/rfc2732.txt">
* RFC 2732</a>. Literal IPv6 addresses must however, be enclosed in '[]' characters.
* The <i>dnsname</i> specification can be preceded by "*." which means
* the name will match any hostname whose right-most domain labels are the same as
* this name. For example, "*.oracle.com" matches "foo.bar.oracle.com"
* <p>
* <i>portrange</i> is used to specify a port number, or a bounded or unbounded range of ports
* that this permission applies to. If portrange is absent or invalid, then a default
* port number is assumed if the scheme is {@code http} (default 80) or {@code https}
* (default 443). No default is assumed for other schemes. A wildcard may be specified
* which means all ports.
* <p>
* <i>userinfo</i> is optional. A userinfo component if present, is ignored when
* creating a URLPermission, and has no effect on any other methods defined by this class.
* <p>
* The <i>path</i> component comprises a sequence of path segments,
* separated by '/' characters. <i>path</i> may also be empty. The path is specified
* in a similar way to the path in {@link java.io.FilePermission}. There are
* three different ways as the following examples show:
* <table class="striped">
* <caption>URL Examples</caption>
* <thead>
* <tr><th scope="col">Example url</th><th scope="col">Description</th></tr>
* </thead>
* <tbody style="text-align:left">
* <tr><th scope="row" style="white-space:nowrap;">http://www.oracle.com/a/b/c.html</th>
* <td>A url which identifies a specific (single) resource</td>
* </tr>
* <tr><th scope="row">http://www.oracle.com/a/b/*</th>
* <td>The '*' character refers to all resources in the same "directory" - in
* other words all resources with the same number of path components, and
* which only differ in the final path component, represented by the '*'.
* </td>
* </tr>
* <tr><th scope="row">http://www.oracle.com/a/b/-</th>
* <td>The '-' character refers to all resources recursively below the
* preceding path (eg. http://www.oracle.com/a/b/c/d/e.html matches this
* example).
* </td>
* </tr>
* </tbody>
* </table>
* <p>
* The '*' and '-' may only be specified in the final segment of a path and must be
* the only character in that segment. Any query or fragment components of the
* url are ignored when constructing URLPermissions.
* <p>
* As a special case, urls of the form, "scheme:*" are accepted to
* mean any url of the given scheme.
* <p>
* The <i>scheme</i> and <i>authority</i> components of the url string are handled
* without regard to case. This means {@link #equals(Object)},
* {@link #hashCode()} and {@link #implies(Permission)} are case insensitive with respect
* to these components. If the <i>authority</i> contains a literal IP address,
* then the address is normalized for comparison. The path component is case sensitive.
* <p><b>The actions string</b><p>
* The actions string of a URLPermission is a concatenation of the <i>method list</i>
* and the <i>request headers list</i>. These are lists of the permitted request
* methods and permitted request headers of the permission (respectively). The two lists
* are separated by a colon ':' character and elements of each list are comma separated.
* Some examples are:
* <ul>
* <li>"POST,GET,DELETE"
* <li>"GET:X-Foo-Request,X-Bar-Request"
* <li>"POST,GET:Header1,Header2"
* </ul>
* <p>
* The first example specifies the methods: POST, GET and DELETE, but no request headers.
* The second example specifies one request method and two headers. The third
* example specifies two request methods, and two headers.
* <p>
* The colon separator need not be present if the request headers list is empty.
* No white-space is permitted in the actions string. The action strings supplied to
* the URLPermission constructors are case-insensitive and are normalized by converting
* method names to upper-case and header names to the form defines in RFC2616 (lower case
* with initial letter of each word capitalized). Either list can contain a wild-card '*'
* character which signifies all request methods or headers respectively.
* <p>
* Note. Depending on the context of use, some request methods and headers may be permitted
* at all times, and others may not be permitted at any time. For example, the
* HTTP protocol handler might disallow certain headers such as Content-Length
* from being set by application code, regardless of whether the security policy
* in force, permits it.
*
* @since 1.8
*/
public final class URLPermission extends Permission {
private static final long serialVersionUID = -2702463814894478682L;
private transient String scheme;
private transient String ssp; // scheme specific part
private transient String path;
private transient List<String> methods;
private transient List<String> requestHeaders;
private transient Authority authority;
// serialized field
private String actions;
/**
* Creates a new URLPermission from a url string and which permits the given
* request methods and user-settable request headers.
* The name of the permission is the url string it was created with. Only the scheme,
* authority and path components of the url are used internally. Any fragment or query
* components are ignored. The permissions action string is as specified above.
*
* @param url the url string
*
* @param actions the actions string
*
* @exception IllegalArgumentException if url is invalid or if actions contains white-space.
*/
public URLPermission(String url, String actions) {
super(url);
init(actions);
}
private void init(String actions) {
parseURI(getName());
int colon = actions.indexOf(':');
if (actions.lastIndexOf(':') != colon) {
throw new IllegalArgumentException(
"Invalid actions string: \"" + actions + "\"");
}
String methods, headers;
if (colon == -1) {
methods = actions;
headers = "";
} else {
methods = actions.substring(0, colon);
headers = actions.substring(colon+1);
}
List<String> l = normalizeMethods(methods);
Collections.sort(l);
this.methods = Collections.unmodifiableList(l);
l = normalizeHeaders(headers);
Collections.sort(l);
this.requestHeaders = Collections.unmodifiableList(l);
this.actions = actions();
}
/**
* Creates a URLPermission with the given url string and unrestricted
* methods and request headers by invoking the two argument
* constructor as follows: URLPermission(url, "*:*")
*
* @param url the url string
*
* @throws IllegalArgumentException if url does not result in a valid {@link URI}
*/
public URLPermission(String url) {
this(url, "*:*");
}
/**
* Returns the normalized method list and request
* header list, in the form:
* <pre>
* "method-names : header-names"
* </pre>
* <p>
* where method-names is the list of methods separated by commas
* and header-names is the list of permitted headers separated by commas.
* There is no white space in the returned String. If header-names is empty
* then the colon separator may not be present.
*/
public String getActions() {
return actions;
}
/**
* Checks if this URLPermission implies the given permission.
* Specifically, the following checks are done as if in the
* following sequence:
* <ul>
* <li>if 'p' is not an instance of URLPermission return false</li>
* <li>if any of p's methods are not in this's method list, and if
* this's method list is not equal to "*", then return false.</li>
* <li>if any of p's headers are not in this's request header list, and if
* this's request header list is not equal to "*", then return false.</li>
* <li>if this's url scheme is not equal to p's url scheme return false</li>
* <li>if the scheme specific part of this's url is '*' return true</li>
* <li>if the set of hosts defined by p's url hostrange is not a subset of
* this's url hostrange then return false. For example, "*.foo.oracle.com"
* is a subset of "*.oracle.com". "foo.bar.oracle.com" is not
* a subset of "*.foo.oracle.com"</li>
* <li>if the portrange defined by p's url is not a subset of the
* portrange defined by this's url then return false.
* <li>if the path or paths specified by p's url are contained in the
* set of paths specified by this's url, then return true
* <li>otherwise, return false</li>
* </ul>
* <p>Some examples of how paths are matched are shown below:
* <table class="plain">
* <caption>Examples of Path Matching</caption>
* <thead>
* <tr><th scope="col">this's path</th><th scope="col">p's path</th><th>match</th></tr>
* </thead>
* <tbody style="text-align:left">
* <tr><th scope="row">/a/b</th><th scope="row">/a/b</th><td>yes</td></tr>
* <tr><th scope="row" rowspan="3">/a/b/*</th><th scope="row">/a/b/c</th><td>yes</td></tr>
* <tr> <th scope="row">/a/b/c/d</th><td>no</td></tr>
* <tr> <th scope="row">/a/b/c/-</th><td>no</td></tr>
* <tr><th scope="row" rowspan="3">/a/b/-</th><th scope="row">/a/b/c/d</th><td>yes</td></tr>
* <tr> <th scope="row">/a/b/c/d/e</th><td>yes</td></tr>
* <tr> <th scope="row">/a/b/c/*</th><td>yes</td></tr>
* </tbody>
* </table>
*/
public boolean implies(Permission p) {
if (! (p instanceof URLPermission)) {
return false;
}
URLPermission that = (URLPermission)p;
if (this.methods.isEmpty() && !that.methods.isEmpty()) {
return false;
}
if (!this.methods.isEmpty() &&
!this.methods.get(0).equals("*") &&
Collections.indexOfSubList(this.methods,
that.methods) == -1) {
return false;
}
if (this.requestHeaders.isEmpty() && !that.requestHeaders.isEmpty()) {
return false;
}
if (!this.requestHeaders.isEmpty() &&
!this.requestHeaders.get(0).equals("*") &&
Collections.indexOfSubList(this.requestHeaders,
that.requestHeaders) == -1) {
return false;
}
if (!this.scheme.equals(that.scheme)) {
return false;
}
if (this.ssp.equals("*")) {
return true;
}
if (!this.authority.implies(that.authority)) {
return false;
}
if (this.path == null) {
return that.path == null;
}
if (that.path == null) {
return false;
}
if (this.path.endsWith("/-")) {
String thisprefix = this.path.substring(0, this.path.length() - 1);
return that.path.startsWith(thisprefix);
}
if (this.path.endsWith("/*")) {
String thisprefix = this.path.substring(0, this.path.length() - 1);
if (!that.path.startsWith(thisprefix)) {
return false;
}
String thatsuffix = that.path.substring(thisprefix.length());
// suffix must not contain '/' chars
if (thatsuffix.indexOf('/') != -1) {
return false;
}
if (thatsuffix.equals("-")) {
return false;
}
return true;
}
return this.path.equals(that.path);
}
/**
* Returns true if, this.getActions().equals(p.getActions())
* and p's url equals this's url. Returns false otherwise.
*/
public boolean equals(Object p) {
if (!(p instanceof URLPermission)) {
return false;
}
URLPermission that = (URLPermission)p;
if (!this.scheme.equals(that.scheme)) {
return false;
}
if (!this.getActions().equals(that.getActions())) {
return false;
}
if (!this.authority.equals(that.authority)) {
return false;
}
if (this.path != null) {
return this.path.equals(that.path);
} else {
return that.path == null;
}
}
/**
* Returns a hashcode calculated from the hashcode of the
* actions String and the url string.
*/
public int hashCode() {
return getActions().hashCode()
+ scheme.hashCode()
+ authority.hashCode()
+ (path == null ? 0 : path.hashCode());
}
private List<String> normalizeMethods(String methods) {
List<String> l = new ArrayList<>();
StringBuilder b = new StringBuilder();
for (int i=0; i<methods.length(); i++) {
char c = methods.charAt(i);
if (c == ',') {
String s = b.toString();
if (s.length() > 0)
l.add(s);
b = new StringBuilder();
} else if (c == ' ' || c == '\t') {
throw new IllegalArgumentException(
"White space not allowed in methods: \"" + methods + "\"");
} else {
if (c >= 'a' && c <= 'z') {
c += 'A' - 'a';
}
b.append(c);
}
}
String s = b.toString();
if (s.length() > 0)
l.add(s);
return l;
}
private List<String> normalizeHeaders(String headers) {
List<String> l = new ArrayList<>();
StringBuilder b = new StringBuilder();
boolean capitalizeNext = true;
for (int i=0; i<headers.length(); i++) {
char c = headers.charAt(i);
if (c >= 'a' && c <= 'z') {
if (capitalizeNext) {
c += 'A' - 'a';
capitalizeNext = false;
}
b.append(c);
} else if (c == ' ' || c == '\t') {
throw new IllegalArgumentException(
"White space not allowed in headers: \"" + headers + "\"");
} else if (c == '-') {
capitalizeNext = true;
b.append(c);
} else if (c == ',') {
String s = b.toString();
if (s.length() > 0)
l.add(s);
b = new StringBuilder();
capitalizeNext = true;
} else {
capitalizeNext = false;
b.append(c);
}
}
String s = b.toString();
if (s.length() > 0)
l.add(s);
return l;
}
private void parseURI(String url) {
int len = url.length();
int delim = url.indexOf(':');
if (delim == -1 || delim + 1 == len) {
throw new IllegalArgumentException(
"Invalid URL string: \"" + url + "\"");
}
scheme = url.substring(0, delim).toLowerCase();
this.ssp = url.substring(delim + 1);
if (!ssp.startsWith("//")) {
if (!ssp.equals("*")) {
throw new IllegalArgumentException(
"Invalid URL string: \"" + url + "\"");
}
this.authority = new Authority(scheme, "*");
return;
}
String authpath = ssp.substring(2);
delim = authpath.indexOf('/');
String auth;
if (delim == -1) {
this.path = "";
auth = authpath;
} else {
auth = authpath.substring(0, delim);
this.path = authpath.substring(delim);
}
this.authority = new Authority(scheme, auth.toLowerCase());
}
private String actions() {
// The colon separator is optional when the request headers list is
// empty.This implementation chooses to include it even when the request
// headers list is empty.
return String.join(",", methods) + ":" + String.join(",", requestHeaders);
}
/**
* restore the state of this object from stream
*/
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException {
ObjectInputStream.GetField fields = s.readFields();
String actions = (String)fields.get("actions", null);
init(actions);
}
static class Authority {
HostPortrange p;
Authority(String scheme, String authority) {
int at = authority.indexOf('@');
if (at == -1) {
p = new HostPortrange(scheme, authority);
} else {
p = new HostPortrange(scheme, authority.substring(at+1));
}
}
boolean implies(Authority other) {
return impliesHostrange(other) && impliesPortrange(other);
}
private boolean impliesHostrange(Authority that) {
String thishost = this.p.hostname();
String thathost = that.p.hostname();
if (p.wildcard() && thishost.equals("")) {
// this "*" implies all others
return true;
}
if (that.p.wildcard() && thathost.equals("")) {
// that "*" can only be implied by this "*"
return false;
}
if (thishost.equals(thathost)) {
// covers all cases of literal IP addresses and fixed
// domain names.
return true;
}
if (this.p.wildcard()) {
// this "*.foo.com" implies "bub.bar.foo.com"
return thathost.endsWith(thishost);
}
return false;
}
private boolean impliesPortrange(Authority that) {
int[] thisrange = this.p.portrange();
int[] thatrange = that.p.portrange();
if (thisrange[0] == -1) {
/* port not specified non http/s URL */
return true;
}
return thisrange[0] <= thatrange[0] &&
thisrange[1] >= thatrange[1];
}
boolean equals(Authority that) {
return this.p.equals(that.p);
}
public int hashCode() {
return p.hashCode();
}
}
}

View file

@ -0,0 +1,596 @@
/*
* Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.net;
import java.io.IOException;
import java.io.InputStream;
import java.io.File;
import java.io.OutputStream;
import java.util.Hashtable;
import sun.net.util.IPAddressUtil;
import sun.net.www.ParseUtil;
/**
* The abstract class {@code URLStreamHandler} is the common
* superclass for all stream protocol handlers. A stream protocol
* handler knows how to make a connection for a particular protocol
* type, such as {@code http} or {@code https}.
* <p>
* In most cases, an instance of a {@code URLStreamHandler}
* subclass is not created directly by an application. Rather, the
* first time a protocol name is encountered when constructing a
* {@code URL}, the appropriate stream protocol handler is
* automatically loaded.
*
* @author James Gosling
* @see java.net.URL#URL(java.lang.String, java.lang.String, int, java.lang.String)
* @since 1.0
*/
public abstract class URLStreamHandler {
/**
* Opens a connection to the object referenced by the
* {@code URL} argument.
* This method should be overridden by a subclass.
*
* <p>If for the handler's protocol (such as HTTP or JAR), there
* exists a public, specialized URLConnection subclass belonging
* to one of the following packages or one of their subpackages:
* java.lang, java.io, java.util, java.net, the connection
* returned will be of that subclass. For example, for HTTP an
* HttpURLConnection will be returned, and for JAR a
* JarURLConnection will be returned.
*
* @param u the URL that this connects to.
* @return a {@code URLConnection} object for the {@code URL}.
* @exception IOException if an I/O error occurs while opening the
* connection.
*/
protected abstract URLConnection openConnection(URL u) throws IOException;
/**
* Same as openConnection(URL), except that the connection will be
* made through the specified proxy; Protocol handlers that do not
* support proxying will ignore the proxy parameter and make a
* normal connection.
*
* Calling this method preempts the system's default
* {@link java.net.ProxySelector ProxySelector} settings.
*
* @param u the URL that this connects to.
* @param p the proxy through which the connection will be made.
* If direct connection is desired, Proxy.NO_PROXY
* should be specified.
* @return a {@code URLConnection} object for the {@code URL}.
* @exception IOException if an I/O error occurs while opening the
* connection.
* @exception IllegalArgumentException if either u or p is null,
* or p has the wrong type.
* @exception UnsupportedOperationException if the subclass that
* implements the protocol doesn't support this method.
* @since 1.5
*/
protected URLConnection openConnection(URL u, Proxy p) throws IOException {
throw new UnsupportedOperationException("Method not implemented.");
}
/**
* Parses the string representation of a {@code URL} into a
* {@code URL} object.
* <p>
* If there is any inherited context, then it has already been
* copied into the {@code URL} argument.
* <p>
* The {@code parseURL} method of {@code URLStreamHandler}
* parses the string representation as if it were an
* {@code http} specification. Most URL protocol families have a
* similar parsing. A stream protocol handler for a protocol that has
* a different syntax must override this routine.
*
* @param u the {@code URL} to receive the result of parsing
* the spec.
* @param spec the {@code String} representing the URL that
* must be parsed.
* @param start the character index at which to begin parsing. This is
* just past the '{@code :}' (if there is one) that
* specifies the determination of the protocol name.
* @param limit the character position to stop parsing at. This is the
* end of the string or the position of the
* "{@code #}" character, if present. All information
* after the sharp sign indicates an anchor.
*/
protected void parseURL(URL u, String spec, int start, int limit) {
// These fields may receive context content if this was relative URL
String protocol = u.getProtocol();
String authority = u.getAuthority();
String userInfo = u.getUserInfo();
String host = u.getHost();
int port = u.getPort();
String path = u.getPath();
String query = u.getQuery();
// This field has already been parsed
String ref = u.getRef();
boolean isRelPath = false;
boolean queryOnly = false;
// FIX: should not assume query if opaque
// Strip off the query part
if (start < limit) {
int queryStart = spec.indexOf('?');
queryOnly = queryStart == start;
if ((queryStart != -1) && (queryStart < limit)) {
query = spec.substring(queryStart+1, limit);
if (limit > queryStart)
limit = queryStart;
spec = spec.substring(0, queryStart);
}
}
int i = 0;
// Parse the authority part if any
boolean isUNCName = (start <= limit - 4) &&
(spec.charAt(start) == '/') &&
(spec.charAt(start + 1) == '/') &&
(spec.charAt(start + 2) == '/') &&
(spec.charAt(start + 3) == '/');
if (!isUNCName && (start <= limit - 2) && (spec.charAt(start) == '/') &&
(spec.charAt(start + 1) == '/')) {
start += 2;
i = spec.indexOf('/', start);
if (i < 0 || i > limit) {
i = spec.indexOf('?', start);
if (i < 0 || i > limit)
i = limit;
}
host = authority = spec.substring(start, i);
int ind = authority.indexOf('@');
if (ind != -1) {
if (ind != authority.lastIndexOf('@')) {
// more than one '@' in authority. This is not server based
userInfo = null;
host = null;
} else {
userInfo = authority.substring(0, ind);
host = authority.substring(ind+1);
}
} else {
userInfo = null;
}
if (host != null) {
// If the host is surrounded by [ and ] then its an IPv6
// literal address as specified in RFC2732
if (host.length()>0 && (host.charAt(0) == '[')) {
if ((ind = host.indexOf(']')) > 2) {
String nhost = host ;
host = nhost.substring(0,ind+1);
if (!IPAddressUtil.
isIPv6LiteralAddress(host.substring(1, ind))) {
throw new IllegalArgumentException(
"Invalid host: "+ host);
}
port = -1 ;
if (nhost.length() > ind+1) {
if (nhost.charAt(ind+1) == ':') {
++ind ;
// port can be null according to RFC2396
if (nhost.length() > (ind + 1)) {
port = Integer.parseInt(nhost, ind + 1,
nhost.length(), 10);
}
} else {
throw new IllegalArgumentException(
"Invalid authority field: " + authority);
}
}
} else {
throw new IllegalArgumentException(
"Invalid authority field: " + authority);
}
} else {
ind = host.indexOf(':');
port = -1;
if (ind >= 0) {
// port can be null according to RFC2396
if (host.length() > (ind + 1)) {
port = Integer.parseInt(host, ind + 1,
host.length(), 10);
}
host = host.substring(0, ind);
}
}
} else {
host = "";
}
if (port < -1)
throw new IllegalArgumentException("Invalid port number :" +
port);
start = i;
// If the authority is defined then the path is defined by the
// spec only; See RFC 2396 Section 5.2.4.
if (authority != null && authority.length() > 0)
path = "";
}
if (host == null) {
host = "";
}
// Parse the file path if any
if (start < limit) {
if (spec.charAt(start) == '/') {
path = spec.substring(start, limit);
} else if (path != null && path.length() > 0) {
isRelPath = true;
int ind = path.lastIndexOf('/');
String seperator = "";
if (ind == -1 && authority != null)
seperator = "/";
path = path.substring(0, ind + 1) + seperator +
spec.substring(start, limit);
} else {
String seperator = (authority != null) ? "/" : "";
path = seperator + spec.substring(start, limit);
}
} else if (queryOnly && path != null) {
int ind = path.lastIndexOf('/');
if (ind < 0)
ind = 0;
path = path.substring(0, ind) + "/";
}
if (path == null)
path = "";
if (isRelPath) {
// Remove embedded /./
while ((i = path.indexOf("/./")) >= 0) {
path = path.substring(0, i) + path.substring(i + 2);
}
// Remove embedded /../ if possible
i = 0;
while ((i = path.indexOf("/../", i)) >= 0) {
/*
* A "/../" will cancel the previous segment and itself,
* unless that segment is a "/../" itself
* i.e. "/a/b/../c" becomes "/a/c"
* but "/../../a" should stay unchanged
*/
if (i > 0 && (limit = path.lastIndexOf('/', i - 1)) >= 0 &&
(path.indexOf("/../", limit) != 0)) {
path = path.substring(0, limit) + path.substring(i + 3);
i = 0;
} else {
i = i + 3;
}
}
// Remove trailing .. if possible
while (path.endsWith("/..")) {
i = path.indexOf("/..");
if ((limit = path.lastIndexOf('/', i - 1)) >= 0) {
path = path.substring(0, limit+1);
} else {
break;
}
}
// Remove starting .
if (path.startsWith("./") && path.length() > 2)
path = path.substring(2);
// Remove trailing .
if (path.endsWith("/."))
path = path.substring(0, path.length() -1);
}
setURL(u, protocol, host, port, authority, userInfo, path, query, ref);
}
/**
* Returns the default port for a URL parsed by this handler. This method
* is meant to be overidden by handlers with default port numbers.
* @return the default port for a {@code URL} parsed by this handler.
* @since 1.3
*/
protected int getDefaultPort() {
return -1;
}
/**
* Provides the default equals calculation. May be overidden by handlers
* for other protocols that have different requirements for equals().
* This method requires that none of its arguments is null. This is
* guaranteed by the fact that it is only called by java.net.URL class.
* @param u1 a URL object
* @param u2 a URL object
* @return {@code true} if the two urls are
* considered equal, ie. they refer to the same
* fragment in the same file.
* @since 1.3
*/
protected boolean equals(URL u1, URL u2) {
String ref1 = u1.getRef();
String ref2 = u2.getRef();
return (ref1 == ref2 || (ref1 != null && ref1.equals(ref2))) &&
sameFile(u1, u2);
}
/**
* Provides the default hash calculation. May be overidden by handlers for
* other protocols that have different requirements for hashCode
* calculation.
* @param u a URL object
* @return an {@code int} suitable for hash table indexing
* @since 1.3
*/
protected int hashCode(URL u) {
int h = 0;
// Generate the protocol part.
String protocol = u.getProtocol();
if (protocol != null)
h += protocol.hashCode();
// Generate the host part.
InetAddress addr = getHostAddress(u);
if (addr != null) {
h += addr.hashCode();
} else {
String host = u.getHost();
if (host != null)
h += host.toLowerCase().hashCode();
}
// Generate the file part.
String file = u.getFile();
if (file != null)
h += file.hashCode();
// Generate the port part.
if (u.getPort() == -1)
h += getDefaultPort();
else
h += u.getPort();
// Generate the ref part.
String ref = u.getRef();
if (ref != null)
h += ref.hashCode();
return h;
}
/**
* Compare two urls to see whether they refer to the same file,
* i.e., having the same protocol, host, port, and path.
* This method requires that none of its arguments is null. This is
* guaranteed by the fact that it is only called indirectly
* by java.net.URL class.
* @param u1 a URL object
* @param u2 a URL object
* @return true if u1 and u2 refer to the same file
* @since 1.3
*/
protected boolean sameFile(URL u1, URL u2) {
// Compare the protocols.
if (!((u1.getProtocol() == u2.getProtocol()) ||
(u1.getProtocol() != null &&
u1.getProtocol().equalsIgnoreCase(u2.getProtocol()))))
return false;
// Compare the files.
if (!(u1.getFile() == u2.getFile() ||
(u1.getFile() != null && u1.getFile().equals(u2.getFile()))))
return false;
// Compare the ports.
int port1, port2;
port1 = (u1.getPort() != -1) ? u1.getPort() : u1.handler.getDefaultPort();
port2 = (u2.getPort() != -1) ? u2.getPort() : u2.handler.getDefaultPort();
if (port1 != port2)
return false;
// Compare the hosts.
if (!hostsEqual(u1, u2))
return false;
return true;
}
/**
* Get the IP address of our host. An empty host field or a DNS failure
* will result in a null return.
*
* @param u a URL object
* @return an {@code InetAddress} representing the host
* IP address.
* @since 1.3
*/
protected synchronized InetAddress getHostAddress(URL u) {
if (u.hostAddress != null)
return u.hostAddress;
String host = u.getHost();
if (host == null || host.equals("")) {
return null;
} else {
try {
u.hostAddress = InetAddress.getByName(host);
} catch (UnknownHostException ex) {
return null;
} catch (SecurityException se) {
return null;
}
}
return u.hostAddress;
}
/**
* Compares the host components of two URLs.
* @param u1 the URL of the first host to compare
* @param u2 the URL of the second host to compare
* @return {@code true} if and only if they
* are equal, {@code false} otherwise.
* @since 1.3
*/
protected boolean hostsEqual(URL u1, URL u2) {
InetAddress a1 = getHostAddress(u1);
InetAddress a2 = getHostAddress(u2);
// if we have internet address for both, compare them
if (a1 != null && a2 != null) {
return a1.equals(a2);
// else, if both have host names, compare them
} else if (u1.getHost() != null && u2.getHost() != null)
return u1.getHost().equalsIgnoreCase(u2.getHost());
else
return u1.getHost() == null && u2.getHost() == null;
}
/**
* Converts a {@code URL} of a specific protocol to a
* {@code String}.
*
* @param u the URL.
* @return a string representation of the {@code URL} argument.
*/
protected String toExternalForm(URL u) {
// pre-compute length of StringBuffer
int len = u.getProtocol().length() + 1;
if (u.getAuthority() != null && u.getAuthority().length() > 0)
len += 2 + u.getAuthority().length();
if (u.getPath() != null) {
len += u.getPath().length();
}
if (u.getQuery() != null) {
len += 1 + u.getQuery().length();
}
if (u.getRef() != null)
len += 1 + u.getRef().length();
StringBuilder result = new StringBuilder(len);
result.append(u.getProtocol());
result.append(":");
if (u.getAuthority() != null && u.getAuthority().length() > 0) {
result.append("//");
result.append(u.getAuthority());
}
if (u.getPath() != null) {
result.append(u.getPath());
}
if (u.getQuery() != null) {
result.append('?');
result.append(u.getQuery());
}
if (u.getRef() != null) {
result.append("#");
result.append(u.getRef());
}
return result.toString();
}
/**
* Sets the fields of the {@code URL} argument to the indicated values.
* Only classes derived from URLStreamHandler are able
* to use this method to set the values of the URL fields.
*
* @param u the URL to modify.
* @param protocol the protocol name.
* @param host the remote host value for the URL.
* @param port the port on the remote machine.
* @param authority the authority part for the URL.
* @param userInfo the userInfo part of the URL.
* @param path the path component of the URL.
* @param query the query part for the URL.
* @param ref the reference.
* @exception SecurityException if the protocol handler of the URL is
* different from this one
* @since 1.3
*/
protected void setURL(URL u, String protocol, String host, int port,
String authority, String userInfo, String path,
String query, String ref) {
if (this != u.handler) {
throw new SecurityException("handler for url different from " +
"this handler");
}
// ensure that no one can reset the protocol on a given URL.
u.set(u.getProtocol(), host, port, authority, userInfo, path, query, ref);
}
/**
* Sets the fields of the {@code URL} argument to the indicated values.
* Only classes derived from URLStreamHandler are able
* to use this method to set the values of the URL fields.
*
* @param u the URL to modify.
* @param protocol the protocol name. This value is ignored since 1.2.
* @param host the remote host value for the URL.
* @param port the port on the remote machine.
* @param file the file.
* @param ref the reference.
* @exception SecurityException if the protocol handler of the URL is
* different from this one
* @deprecated Use setURL(URL, String, String, int, String, String, String,
* String);
*/
@Deprecated
protected void setURL(URL u, String protocol, String host, int port,
String file, String ref) {
/*
* Only old URL handlers call this, so assume that the host
* field might contain "user:passwd@host". Fix as necessary.
*/
String authority = null;
String userInfo = null;
if (host != null && host.length() != 0) {
authority = (port == -1) ? host : host + ":" + port;
int at = host.lastIndexOf('@');
if (at != -1) {
userInfo = host.substring(0, at);
host = host.substring(at+1);
}
}
/*
* Assume file might contain query part. Fix as necessary.
*/
String path = null;
String query = null;
if (file != null) {
int q = file.lastIndexOf('?');
if (q != -1) {
query = file.substring(q+1);
path = file.substring(0, q);
} else
path = file;
}
setURL(u, protocol, host, port, authority, userInfo, path, query, ref);
}
}

View file

@ -0,0 +1,53 @@
/*
* Copyright (c) 1995, 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 java.net;
/**
* This interface defines a factory for {@code URL} stream
* protocol handlers.
*
* <p> A URL stream handler factory is used as specified in the
* {@linkplain java.net.URL#URL(String,String,int,String) URL constructor}.
*
* @author Arthur van Hoff
* @see java.net.URL
* @see java.net.URLStreamHandler
* @since 1.0
*/
public interface URLStreamHandlerFactory {
/**
* Creates a new {@code URLStreamHandler} instance with the specified
* protocol.
*
* @param protocol the protocol ("{@code ftp}",
* "{@code http}", "{@code nntp}", etc.).
* @return a {@code URLStreamHandler} for the specific protocol, or {@code
* null} if this factory cannot create a handler for the specific
* protocol
* @see java.net.URLStreamHandler
*/
URLStreamHandler createURLStreamHandler(String protocol);
}

View file

@ -0,0 +1,56 @@
/*
* Copyright (c) 1995, 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 java.net;
import java.io.IOException;
/**
* Thrown to indicate that the IP address of a host could not be determined.
*
* @author Jonathan Payne
* @since 1.0
*/
public
class UnknownHostException extends IOException {
private static final long serialVersionUID = -4639126076052875403L;
/**
* Constructs a new {@code UnknownHostException} with the
* specified detail message.
*
* @param message the detail message.
*/
public UnknownHostException(String message) {
super(message);
}
/**
* Constructs a new {@code UnknownHostException} with no detail
* message.
*/
public UnknownHostException() {
}
}

View file

@ -0,0 +1,58 @@
/*
* Copyright (c) 1995, 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 java.net;
import java.io.IOException;
/**
* Thrown to indicate that an unknown service exception has
* occurred. Either the MIME type returned by a URL connection does
* not make sense, or the application is attempting to write to a
* read-only URL connection.
*
* @author unascribed
* @since 1.0
*/
public class UnknownServiceException extends IOException {
private static final long serialVersionUID = -4169033248853639508L;
/**
* Constructs a new {@code UnknownServiceException} with no
* detail message.
*/
public UnknownServiceException() {
}
/**
* Constructs a new {@code UnknownServiceException} with the
* specified detail message.
*
* @param msg the detail message.
*/
public UnknownServiceException(String msg) {
super(msg);
}
}

View file

@ -0,0 +1,244 @@
<!DOCTYPE HTML>
<!--
Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
This code is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License version 2 only, as
published by the Free Software Foundation. Oracle designates this
particular file as subject to the "Classpath" exception as provided
by Oracle in the LICENSE file that accompanied this code.
This code is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
version 2 for more details (a copy is included in the LICENSE file that
accompanied this code).
You should have received a copy of the GNU General Public License version
2 along with this work; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
or visit www.oracle.com if you need additional information or have any
questions.
-->
<HTML lang="EN">
<HEAD>
<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=iso-8859-1">
<TITLE>Networking Properties</TITLE>
</HEAD>
<BODY LANG="en-US" DIR="LTR">
<H1 style="text-align:center">Networking Properties</H1>
<P>There are a few standard system properties used to
alter the mechanisms and behavior of the various classes of the
java.net package. Some are checked only once at startup of the VM,
and therefore are best set using the -D option of the java command,
while others have a more dynamic nature and can also be changed using
the <a href="../../lang/System.html#setProperty-java.lang.String-java.lang.String-">System.setProperty()</a> API.
The purpose of this document is to list
and detail all of these properties.</P>
<P>If there is no special note, a property value is checked every time it is used.</P>
<a id="Ipv4IPv6"></a>
<H2>IPv4 / IPv6</H2>
<UL>
<LI><P><B>java.net.preferIPv4Stack</B> (default: false)<BR>
If IPv6 is available on the operating system the
underlying native socket will be, by default, an IPv6 socket which
lets applications connect to, and accept connections from, both
IPv4 and IPv6 hosts. However, in the case an application would
rather use IPv4 only sockets, then this property can be set to <B>true</B>.
The implication is that it will not be possible for the application
to communicate with IPv6 only hosts.</P>
<LI><P><B>java.net.preferIPv6Addresses</B> (default: false)<BR>
When dealing with a host which has both IPv4
and IPv6 addresses, and if IPv6 is available on the operating
system, the default behavior is to prefer using IPv4 addresses over
IPv6 ones. This is to ensure backward compatibility, for example
applications that depend on the representation of an IPv4 address
(e.g. 192.168.1.1). This property can be set to <B>true</B> to
change that preference and use IPv6 addresses over IPv4 ones where
possible, or <B>system</B> to preserve the order of the addresses as
returned by the operating system.</P>
</UL>
<P>Both of these properties are checked only once, at startup.</P>
<a id="Proxies"></a>
<H2>Proxies</H2>
<P>A proxy server allows indirect connection to network services and
is used mainly for security (to get through firewalls) and
performance reasons (proxies often do provide caching mechanisms).
The following properties allow for configuration of the various type
of proxies.</P>
<UL>
<LI><P>HTTP</P>
<P>The following proxy settings are used by the HTTP protocol handler.</P>
<UL>
<LI><P><B>http.proxyHost</B> (default: &lt;none&gt;)<BR>
The hostname, or address, of the proxy server
</P>
<LI><P><B>http.proxyPort</B> (default: 80)<BR>
The port number of the proxy server.</P>
<LI><P><B>http.nonProxyHosts</B> (default: localhost|127.*|[::1])<BR>
Indicates the hosts that should be accessed without going
through the proxy. Typically this defines internal hosts.
The value of this property is a list of hosts,
separated by the '|' character. In addition the wildcard
character '*' can be used for pattern matching. For example
<code>-Dhttp.nonProxyHosts=&rdquo;*.foo.com|localhost&rdquo;</code>
will indicate that every hosts in the foo.com domain and the
localhost should be accessed directly even if a proxy server is
specified.</P>
<P>The default value excludes all common variations of the loopback address.</P>
</UL>
<LI><P>HTTPS<BR>This is HTTP over SSL, a secure version of HTTP
mainly used when confidentiality (like on payment sites) is needed.</P>
<P>The following proxy settings are used by the HTTPS protocol handler.</P>
<UL>
<LI><P><B>https.proxyHost</B>(default: &lt;none&gt;)<BR>
The hostname, or address, of the proxy server
</P>
<LI><P><B>https.proxyPort</B> (default: 443)<BR>
The port number of the proxy server.</P>
<P>The HTTPS protocol handler will use the same nonProxyHosts
property as the HTTP protocol.</P>
</UL>
<LI><P>FTP</P>
<P>The following proxy settings are used by the FTP protocol handler.</P>
<UL>
<LI><P><B>ftp.proxyHost</B>(default: &lt;none&gt;)<BR>
The hostname, or address, of the proxy server
</P>
<LI><P><B>ftp.proxyPort</B> (default: 80)<BR>
The port number of the proxy server.</P>
<LI><P><B>ftp.nonProxyHosts</B> (default: localhost|127.*|[::1])<BR>
Indicates the hosts that should be accessed without going
through the proxy. Typically this defines internal hosts.
The value of this property is a list of hosts, separated by
the '|' character. In addition the wildcard character
'*' can be used for pattern matching. For example
<code>-Dhttp.nonProxyHosts=&rdquo;*.foo.com|localhost&rdquo;</code>
will indicate that every hosts in the foo.com domain and the
localhost should be accessed directly even if a proxy server is
specified.</P>
<P>The default value excludes all common variations of the loopback address.</P>
</UL>
<LI><P>SOCKS<BR>This is another type of proxy. It allows for lower
level type of tunneling since it works at the TCP level. In effect,
in the Java(tm) platform setting a SOCKS proxy server will result in
all TCP connections to go through that proxy, unless other proxies
are specified. If SOCKS is supported by a Java SE implementation, the
following properties will be used:</P>
<UL>
<LI><P><B>socksProxyHost</B> (default: &lt;none&gt;)<BR>
The hostname, or address, of the proxy server.</P>
<LI><P><B>socksProxyPort</B> (default: 1080)<BR>
The port number of the proxy server.</P>
<LI><P><B>socksProxyVersion</B> (default: 5)<BR>
The version of the SOCKS protocol supported by the server. The
default is <code>5</code> indicating SOCKS V5, alternatively
<code>4</code> can be specified for SOCKS V4. Setting the property
to values other than these leads to unspecified behavior.</P>
<LI><P><B>java.net.socks.username</B> (default: &lt;none&gt;)<BR>
Username to use if the SOCKSv5 server asks for authentication
and no java.net.Authenticator instance was found.</P>
<LI><P><B>java.net.socks.password</B> (default: &lt;none&gt;)<BR>
Password to use if the SOCKSv5 server asks for authentication
and no java.net.Authenticator instance was found.</P>
<P>Note that if no authentication is provided with either the above
properties or an Authenticator, and the proxy requires one, then
the <B>user.name</B> property will be used with no password.</P>
</UL>
<LI><P><B>java.net.useSystemProxies</B> (default: false)<BR>
On Windows systems, macOS systems and on Gnome systems it is possible to
tell the java.net stack, setting this property to <B>true</B>, to use
the system proxy settings (both these systems let you set proxies
globally through their user interface). Note that this property is
checked only once at startup.</P>
</UL>
<a id="MiscHTTP"></a>
<H2>Misc HTTP properties</H2>
<UL>
<LI><P><B>http.agent</B> (default: &ldquo;Java/&lt;version&gt;&rdquo;)<BR>
Defines the string sent in the User-Agent request header in http
requests. Note that the string &ldquo;Java/&lt;version&gt;&rdquo; will
be appended to the one provided in the property (e.g. if
-Dhttp.agent=&rdquo;foobar&rdquo; is used, the User-Agent header will
contain &ldquo;foobar Java/1.5.0&rdquo; if the version of the VM is
1.5.0). This property is checked only once at startup.</P>
<LI><P><B>http.keepalive</B> (default: true)<BR>
Indicates if persistent connections should be supported. They improve
performance by allowing the underlying socket connection to be reused
for multiple http requests. If this is set to true then persistent
connections will be requested with HTTP 1.1 servers.</P>
<LI><P><B>http.maxConnections</B> (default: 5)<BR>
If HTTP keepalive is enabled (see above) this value determines the
maximum number of idle connections that will be simultaneously kept
alive, per destination.</P>
<LI><P><B>http.maxRedirects</B> (default: 20)<BR>
This integer value determines the maximum number, for a given request,
of HTTP redirects that will be automatically followed by the
protocol handler.</P>
<LI><P><B>http.auth.digest.validateServer</B> (default: false)</P>
<LI><P><B>http.auth.digest.validateProxy</B> (default: false)</P>
<LI><P><B>http.auth.digest.cnonceRepeat</B> (default: 5)</P>
<P>These 3 properties modify the behavior of the HTTP digest
authentication mechanism. Digest authentication provides a limited
ability for the server to authenticate itself to the client (i.e.
By proving it knows the user's password). However not all HTTP
servers support this capability and by default it is turned off. The
first two properties can be set to true to enforce this check for
authentication with either an origin or proxy server, respectively.</P>
<P>It is usually not necessary to change the third property. It
determines how many times a cnonce value is re-used. This can be
useful when the MD5-sess algorithm is being used. Increasing this
value reduces the computational overhead on both client and server
by reducing the amount of material that has to be hashed for each
HTTP request.</P>
<LI><P><B>http.auth.ntlm.domain</B> (default: &lt;none&gt;)<BR>
NTLM is another authentication scheme. It uses the
java.net.Authenticator class to acquire usernames and passwords when
they are needed. However NTLM also needs the NT domain name. There are
3 options for specifying that domain:</P>
<OL>
<LI><P>Do not specify it. In some environments the domain is
actually not required and the application does not have to specify
it.</P>
<LI><P>The domain name can be encoded within the username by
prefixing the domain name, followed by a back-slash '\' before the
username. With this method existing applications that use the
authenticator class do not need to be modified, as long as users
are made aware that this notation must be used.</P>
<LI><P>If a domain name is not specified as in method 2) and these
property is defined, then its value will be used a the domain
name.</P>
</OL>
</UL>
<P>All these properties are checked only once at startup.</P>
<a id="AddressCache"></a>
<H2>Address Cache</H2>
<P>The java.net package, when doing name resolution, uses an address
cache for both security and performance reasons. Any address
resolution attempt, be it forward (name to IP address) or reverse (IP
address to name), will have its result cached, whether it was
successful or not, so that subsequent identical requests will not
have to access the naming service. These properties allow for some
tuning on how the cache is operating.</P>
<UL>
<LI><P><B>networkaddress.cache.ttl</B> (default: see below)<BR>
Value is an integer corresponding to the number of seconds successful
name lookups will be kept in the cache. A value of -1, or any other
negative value for that matter, indicates a &ldquo;cache forever&rdquo;
policy, while a value of 0 (zero) means no caching. The default value
is -1 (forever) if a security manager is installed, and implementation
specific when no security manager is installed.</P>
<LI><P><B>networkaddress.cache.negative.ttl</B> (default: 10)<BR>
Value is an integer corresponding to the number of seconds an
unsuccessful name lookup will be kept in the cache. A value of -1,
or any negative value, means &ldquo;cache forever&rdquo;, while a
value of 0 (zero) means no caching.</P>
</UL>
<P>Since these 2 properties are part of the security policy, they are
not set by either the -D option or the System.setProperty() API,
instead they are set as security properties.</P>
</BODY>
</HTML>

View file

@ -0,0 +1,160 @@
/*
* Copyright (c) 1998, 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.
*/
/**
* Provides the classes for implementing networking applications.
*
* <p> The java.net package can be roughly divided in two sections:</p>
* <ul>
* <li><p><i>A Low Level API</i>, which deals with the
* following abstractions:</p>
* <ul>
* <li><p><i>Addresses</i>, which are networking identifiers,
* like IP addresses.</p></li>
* <li><p><i>Sockets</i>, which are basic bidirectional data communication
* mechanisms.</p></li>
* <li><p><i>Interfaces</i>, which describe network interfaces. </p></li>
* </ul></li>
* <li> <p><i>A High Level API</i>, which deals with the following
* abstractions:</p>
* <ul>
* <li><p><i>URIs</i>, which represent
* Universal Resource Identifiers.</p></li>
* <li><p><i>URLs</i>, which represent
* Universal Resource Locators.</p></li>
* <li><p><i>Connections</i>, which represents connections to the resource
* pointed to by <i>URLs</i>.</p></li>
* </ul></li>
* </ul>
* <h2>Addresses</h2>
* <p>Addresses are used throughout the java.net APIs as either host
* identifiers, or socket endpoint identifiers.</p>
* <p>The {@link java.net.InetAddress} class is the abstraction representing an
* IP (Internet Protocol) address. It has two subclasses:
* <ul>
* <li>{@link java.net.Inet4Address} for IPv4 addresses.</li>
* <li>{@link java.net.Inet6Address} for IPv6 addresses.</li>
* </ul>
* <p>But, in most cases, there is no need to deal directly with the subclasses,
* as the InetAddress abstraction should cover most of the needed
* functionality.</p>
* <h3><b>About IPv6</b></h3>
* <p>Not all systems have support for the IPv6 protocol, and while the Java
* networking stack will attempt to detect it and use it transparently when
* available, it is also possible to disable its use with a system property.
* In the case where IPv6 is not available, or explicitly disabled,
* Inet6Address are not valid arguments for most networking operations any
* more. While methods like {@link java.net.InetAddress#getByName} are
* guaranteed not to return an Inet6Address when looking up host names, it
* is possible, by passing literals, to create such an object. In which
* case, most methods, when called with an Inet6Address will throw an
* Exception.</p>
* <h2>Sockets</h2>
* <p>Sockets are means to establish a communication link between machines over
* the network. The java.net package provides 4 kinds of Sockets:</p>
* <ul>
* <li>{@link java.net.Socket} is a TCP client API, and will typically
* be used to {@linkplain java.net.Socket#connect(SocketAddress)
* connect} to a remote host.</li>
* <li>{@link java.net.ServerSocket} is a TCP server API, and will
* typically {@linkplain java.net.ServerSocket#accept accept}
* connections from client sockets.</li>
* <li>{@link java.net.DatagramSocket} is a UDP endpoint API and is used
* to {@linkplain java.net.DatagramSocket#send send} and
* {@linkplain java.net.DatagramSocket#receive receive}
* {@linkplain java.net.DatagramPacket datagram packets}.</li>
* <li>{@link java.net.MulticastSocket} is a subclass of
* {@code DatagramSocket} used when dealing with multicast
* groups.</li>
* </ul>
* <p>Sending and receiving with TCP sockets is done through InputStreams and
* OutputStreams which can be obtained via the
* {@link java.net.Socket#getInputStream} and
* {@link java.net.Socket#getOutputStream} methods.</p>
* <h2>Interfaces</h2>
* <p>The {@link java.net.NetworkInterface} class provides APIs to browse and
* query all the networking interfaces (e.g. ethernet connection or PPP
* endpoint) of the local machine. It is through that class that you can
* check if any of the local interfaces is configured to support IPv6.</p>
* <p>Note, all conforming implementations must support at least one
* {@code NetworkInterface} object, which must either be connected to a
* network, or be a "loopback" interface that can only communicate with
* entities on the same machine.</p>
*
* <h2>High level API</h2>
* <p>A number of classes in the java.net package do provide for a much higher
* level of abstraction and allow for easy access to resources on the
* network. The classes are:
* <ul>
* <li>{@link java.net.URI} is the class representing a
* Universal Resource Identifier, as specified in RFC 2396.
* As the name indicates, this is just an Identifier and doesn't
* provide directly the means to access the resource.</li>
* <li>{@link java.net.URL} is the class representing a
* Universal Resource Locator, which is both an older concept for
* URIs and a means to access the resources.</li>
* <li>{@link java.net.URLConnection} is created from a URL and is the
* communication link used to access the resource pointed by the
* URL. This abstract class will delegate most of the work to the
* underlying protocol handlers like http or https.</li>
* <li>{@link java.net.HttpURLConnection} is a subclass of URLConnection
* and provides some additional functionalities specific to the
* HTTP protocol. This API has been superceded by the newer
HTTP client API described in the previous section.</li>
* </ul>
* <p>The recommended usage is to use {@link java.net.URI} to identify
* resources, then convert it into a {@link java.net.URL} when it is time to
* access the resource. From that URL, you can either get the
* {@link java.net.URLConnection} for fine control, or get directly the
* InputStream.
* <p>Here is an example:</p>
* <pre>
* URI uri = new URI("http://java.sun.com/");
* URL url = uri.toURL();
* InputStream in = url.openStream();
* </pre>
* <h2>Protocol Handlers</h2>
* As mentioned, URL and URLConnection rely on protocol handlers which must be
* present, otherwise an Exception is thrown. This is the major difference with
* URIs which only identify resources, and therefore don't need to have access
* to the protocol handler. So, while it is possible to create an URI with any
* kind of protocol scheme (e.g. {@code myproto://myhost.mydomain/resource/}),
* a similar URL will try to instantiate the handler for the specified protocol;
* if it doesn't exist an exception will be thrown.
* <p>By default the protocol handlers are loaded dynamically from the default
* location. It is, however, possible to deploy additional protocols handlers
* as {@link java.util.ServiceLoader services}. Service providers of type
* {@linkplain java.net.spi.URLStreamHandlerProvider} are located at
* runtime, as specified in the {@linkplain
* java.net.URL#URL(String,String,int,String) URL constructor}.
* <h2>Additional Specification</h2>
* <ul>
* <li><a href="doc-files/net-properties.html">
* Networking System Properties</a></li>
* </ul>
*
* @since 1.0
*/
package java.net;

View file

@ -0,0 +1,70 @@
/*
* Copyright (c) 2015, 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 java.net.spi;
import java.net.URLStreamHandlerFactory;
/**
* URL stream handler service-provider class.
*
*<p> A URL stream handler provider is a concrete subclass of this class that
* has a zero-argument constructor. URL stream handler providers may be
* installed in an instance of the Java platform by adding them to the
* application class path.
*
* <p> A URL stream handler provider identifies itself with a
* provider-configuration file named java.net.spi.URLStreamHandlerProvider in
* the resource directory META-INF/services. The file should contain a list of
* fully-qualified concrete URL stream handler provider class names, one per
* line.
*
* <p> URL stream handler providers are located at runtime, as specified in the
* {@linkplain java.net.URL#URL(String,String,int,String) URL constructor}.
*
* @since 9
*/
public abstract class URLStreamHandlerProvider
implements URLStreamHandlerFactory
{
private static Void checkPermission() {
SecurityManager sm = System.getSecurityManager();
if (sm != null)
sm.checkPermission(new RuntimePermission("setFactory"));
return null;
}
private URLStreamHandlerProvider(Void ignore) { }
/**
* Initializes a new URL stream handler provider.
*
* @throws SecurityException
* If a security manager has been installed and it denies
* {@link RuntimePermission}{@code ("setFactory")}.
*/
protected URLStreamHandlerProvider() {
this(checkPermission());
}
}

View file

@ -0,0 +1,35 @@
/*
* Copyright (c) 2015, 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.
*/
/**
* Service-provider classes for the {@link java.net} package.
*
* <p> Only developers who are defining new URL stream handler providers
* should need to make direct use of this package.
*
* @since 9
*/
package java.net.spi;