зеркало из https://github.com/mono/ikvm-fork.git
*** empty log message ***
This commit is contained in:
Родитель
e25574ce81
Коммит
4074223516
|
@ -20,10 +20,6 @@ java/lang/ref/Reference.java
|
|||
java/lang/reflect/Constructor.java
|
||||
java/lang/reflect/Method.java
|
||||
java/lang/reflect/Field.java
|
||||
java/net/PlainSocketImpl.java
|
||||
java/net/PlainDatagramSocketImpl.java
|
||||
java/net/SocketInputStream.java
|
||||
java/net/SocketOutputStream.java
|
||||
java/security/VMAccessController.java
|
||||
java/util/VMTimeZone.java
|
||||
sun/misc/Ref.java
|
||||
|
|
|
@ -100,4 +100,6 @@ public interface Configuration
|
|||
* Name of default AWT peer library.
|
||||
*/
|
||||
String default_awt_peer_toolkit = "gnu.java.awt.peer.gtk.GTKToolkit";
|
||||
|
||||
boolean JAVA_LANG_SYSTEM_EXPLICIT_INITIALIZATION = false;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,438 @@
|
|||
/* PlainDatagramSocketImpl.java -- Default DatagramSocket implementation
|
||||
Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath 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 for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.java.net;
|
||||
|
||||
public class PlainDatagramSocketImpl extends java.net.PlainDatagramSocketImpl
|
||||
import java.io.IOException;
|
||||
import java.net.*;
|
||||
import cli.System.Net.IPEndPoint;
|
||||
import cli.System.Net.Sockets.SocketOptionName;
|
||||
import cli.System.Net.Sockets.SocketOptionLevel;
|
||||
import cli.System.Net.Sockets.MulticastOption;
|
||||
import cli.System.Net.Sockets.SocketFlags;
|
||||
import cli.System.Net.Sockets.SocketType;
|
||||
import cli.System.Net.Sockets.ProtocolType;
|
||||
import cli.System.Net.Sockets.AddressFamily;
|
||||
import ikvm.lang.CIL;
|
||||
import ikvm.lang.ByteArrayHack;
|
||||
|
||||
/**
|
||||
* This is the default socket implementation for datagram sockets.
|
||||
* It makes native calls to C routines that implement BSD style
|
||||
* SOCK_DGRAM sockets in the AF_INET family.
|
||||
*
|
||||
* @version 0.1
|
||||
*
|
||||
* @author Aaron M. Renn (arenn@urbanophile.com)
|
||||
*/
|
||||
public class PlainDatagramSocketImpl extends DatagramSocketImpl
|
||||
{
|
||||
public int getNativeFD() { throw new NoSuchMethodError("Not supported"); }
|
||||
}
|
||||
/*
|
||||
* Static Variables
|
||||
*/
|
||||
|
||||
/**
|
||||
* This is the actual underlying socket
|
||||
*/
|
||||
private cli.System.Net.Sockets.Socket socket = new cli.System.Net.Sockets.Socket(
|
||||
AddressFamily.wrap(AddressFamily.InterNetwork),
|
||||
SocketType.wrap(SocketType.Dgram),
|
||||
ProtocolType.wrap(ProtocolType.Udp));
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/*
|
||||
* Constructors
|
||||
*/
|
||||
|
||||
/**
|
||||
* Default do nothing constructor
|
||||
*/
|
||||
public PlainDatagramSocketImpl()
|
||||
{
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/*
|
||||
* Instance Methods
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates a new datagram socket
|
||||
*
|
||||
* @exception SocketException If an error occurs
|
||||
*/
|
||||
protected void create() throws SocketException
|
||||
{
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* Closes the socket
|
||||
*/
|
||||
protected void close()
|
||||
{
|
||||
if(socket != null)
|
||||
{
|
||||
socket.Close();
|
||||
socket = null;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* Binds this socket to a particular port and interface
|
||||
*
|
||||
* @param port The port to bind to
|
||||
* @param addr The address to bind to
|
||||
*
|
||||
* @exception SocketException If an error occurs
|
||||
*/
|
||||
protected void bind(int port, InetAddress addr) throws SocketException
|
||||
{
|
||||
try
|
||||
{
|
||||
if(false) throw new cli.System.Net.Sockets.SocketException();
|
||||
socket.Bind(new IPEndPoint(PlainSocketImpl.getAddressFromInetAddress(addr), port));
|
||||
localPort = ((IPEndPoint)socket.get_LocalEndPoint()).get_Port();
|
||||
}
|
||||
catch(cli.System.Net.Sockets.SocketException x)
|
||||
{
|
||||
throw new BindException(x.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* Sends a packet of data to a remote host
|
||||
*
|
||||
* @param packet The packet to send
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected void send(DatagramPacket packet) throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
if(false) throw new cli.System.Net.Sockets.SocketException();
|
||||
int len = packet.getLength();
|
||||
if(socket.SendTo(ByteArrayHack.cast(packet.getData()), len, SocketFlags.wrap(SocketFlags.None), new IPEndPoint(PlainSocketImpl.getAddressFromInetAddress(packet.getAddress()), packet.getPort())) != len)
|
||||
{
|
||||
throw new SocketException("Not all data was sent");
|
||||
}
|
||||
}
|
||||
catch(cli.System.Net.Sockets.SocketException x)
|
||||
{
|
||||
throw PlainSocketImpl.convertSocketExceptionToIOException(x);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* What does this method really do?
|
||||
*/
|
||||
protected int peek(InetAddress addr) throws IOException
|
||||
{
|
||||
throw new IOException("Not Implemented Yet");
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* Receives a UDP packet from the network
|
||||
*
|
||||
* @param packet The packet to fill in with the data received
|
||||
*
|
||||
* @exception IOException IOException If an error occurs
|
||||
*/
|
||||
protected void receive(DatagramPacket packet) throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
if(false) throw new cli.System.Net.Sockets.SocketException();
|
||||
byte[] data = packet.getData();
|
||||
cli.System.Net.EndPoint[] remoteEP = new cli.System.Net.EndPoint[]
|
||||
{
|
||||
new cli.System.Net.IPEndPoint(0, 0)
|
||||
};
|
||||
int length = socket.ReceiveFrom(ByteArrayHack.cast(data), remoteEP);
|
||||
packet.setLength(length);
|
||||
int remoteIP = (int)((cli.System.Net.IPEndPoint)remoteEP[0]).get_Address().get_Address();
|
||||
byte[] ipv4 = new byte[] { (byte)remoteIP, (byte)(remoteIP >> 8), (byte)(remoteIP >> 16), (byte)(remoteIP >> 24) };
|
||||
InetAddress remoteAddress = InetAddress.getByAddress(ipv4);
|
||||
packet.setAddress(remoteAddress);
|
||||
packet.setPort(((cli.System.Net.IPEndPoint)remoteEP[0]).get_Port());
|
||||
}
|
||||
catch(cli.System.Net.Sockets.SocketException x)
|
||||
{
|
||||
throw PlainSocketImpl.convertSocketExceptionToIOException(x);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* Joins a multicast group
|
||||
*
|
||||
* @param addr The group to join
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected void join(InetAddress addr) throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
if(false) throw new cli.System.Net.Sockets.SocketException();
|
||||
if(false) throw new cli.System.ArgumentException();
|
||||
socket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.IP), SocketOptionName.wrap(SocketOptionName.AddMembership), new MulticastOption(new cli.System.Net.IPAddress(PlainSocketImpl.getAddressFromInetAddress(addr))));
|
||||
}
|
||||
catch(cli.System.Net.Sockets.SocketException x)
|
||||
{
|
||||
throw PlainSocketImpl.convertSocketExceptionToIOException(x);
|
||||
}
|
||||
catch(cli.System.ArgumentException x1)
|
||||
{
|
||||
throw new IOException(x1.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* Leaves a multicast group
|
||||
*
|
||||
* @param addr The group to leave
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected void leave(InetAddress addr) throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
if(false) throw new cli.System.Net.Sockets.SocketException();
|
||||
if(false) throw new cli.System.ArgumentException();
|
||||
socket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.IP), SocketOptionName.wrap(SocketOptionName.DropMembership), new MulticastOption(new cli.System.Net.IPAddress(PlainSocketImpl.getAddressFromInetAddress(addr))));
|
||||
}
|
||||
catch(cli.System.Net.Sockets.SocketException x)
|
||||
{
|
||||
throw PlainSocketImpl.convertSocketExceptionToIOException(x);
|
||||
}
|
||||
catch(cli.System.ArgumentException x1)
|
||||
{
|
||||
throw new IOException(x1.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* Gets the Time to Live value for the socket
|
||||
*
|
||||
* @return The TTL value
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected byte getTTL() throws IOException
|
||||
{
|
||||
return (byte)CIL.unbox_int(socket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.IP), SocketOptionName.wrap(SocketOptionName.IpTimeToLive)));
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* Sets the Time to Live value for the socket
|
||||
*
|
||||
* @param ttl The new TTL value
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected void setTTL(byte ttl) throws IOException
|
||||
{
|
||||
socket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.IP), SocketOptionName.wrap(SocketOptionName.IpTimeToLive), ttl & 0xff);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* Gets the Time to Live value for the socket
|
||||
*
|
||||
* @return The TTL value
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected int getTimeToLive() throws IOException
|
||||
{
|
||||
return CIL.unbox_int(socket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.IP), SocketOptionName.wrap(SocketOptionName.IpTimeToLive)));
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* Sets the Time to Live value for the socket
|
||||
*
|
||||
* @param ttl The new TTL value
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected void setTimeToLive(int ttl) throws IOException
|
||||
{
|
||||
socket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.IP), SocketOptionName.wrap(SocketOptionName.IpTimeToLive), ttl);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* Retrieves the value of an option on the socket
|
||||
*
|
||||
* @param option_id The identifier of the option to retrieve
|
||||
*
|
||||
* @return The value of the option
|
||||
*
|
||||
* @exception SocketException If an error occurs
|
||||
*/
|
||||
public Object getOption(int option_id) throws SocketException
|
||||
{
|
||||
try
|
||||
{
|
||||
if(false) throw new cli.System.Net.Sockets.SocketException();
|
||||
switch(option_id)
|
||||
{
|
||||
case SocketOptions.SO_REUSEADDR:
|
||||
return new Boolean(CIL.unbox_int(socket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.ReuseAddress))) != 0);
|
||||
case SocketOptions.SO_BROADCAST:
|
||||
return new Boolean(CIL.unbox_int(socket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.Broadcast))) != 0);
|
||||
case SocketOptions.IP_MULTICAST_IF:
|
||||
return getInetAddressFromInt(CIL.unbox_int(socket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.IP), SocketOptionName.wrap(SocketOptionName.MulticastInterface))));
|
||||
case SocketOptions.IP_MULTICAST_IF2:
|
||||
throw new SocketException("SocketOptions.IP_MULTICAST_IF2 not implemented");
|
||||
case SocketOptions.IP_MULTICAST_LOOP:
|
||||
return new Boolean(CIL.unbox_int(socket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.IP), SocketOptionName.wrap(SocketOptionName.MulticastLoopback))) != 0);
|
||||
default:
|
||||
return PlainSocketImpl.getCommonSocketOption(socket, option_id);
|
||||
}
|
||||
}
|
||||
catch(cli.System.Net.Sockets.SocketException x)
|
||||
{
|
||||
throw new SocketException(x.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private static InetAddress getInetAddressFromInt(int i) throws SocketException
|
||||
{
|
||||
byte[] b = new byte[4];
|
||||
b[0] = (byte)(i >> 0);
|
||||
b[1] = (byte)(i >> 8);
|
||||
b[2] = (byte)(i >> 16);
|
||||
b[3] = (byte)(i >> 24);
|
||||
try
|
||||
{
|
||||
return InetAddress.getByAddress(b);
|
||||
}
|
||||
catch(UnknownHostException x)
|
||||
{
|
||||
throw new SocketException(x.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* Sets the value of an option on the socket
|
||||
*
|
||||
* @param option_id The identifier of the option to set
|
||||
* @param val The value of the option to set
|
||||
*
|
||||
* @exception SocketException If an error occurs
|
||||
*/
|
||||
public void setOption(int option_id, Object val) throws SocketException
|
||||
{
|
||||
try
|
||||
{
|
||||
if(false) throw new cli.System.Net.Sockets.SocketException();
|
||||
switch(option_id)
|
||||
{
|
||||
case SocketOptions.SO_REUSEADDR:
|
||||
socket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.ReuseAddress), ((Boolean)val).booleanValue() ? 1 : 0);
|
||||
break;
|
||||
case SocketOptions.SO_BROADCAST:
|
||||
socket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.Broadcast), ((Boolean)val).booleanValue() ? 1 : 0);
|
||||
break;
|
||||
case SocketOptions.IP_MULTICAST_IF:
|
||||
socket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.IP), SocketOptionName.wrap(SocketOptionName.MulticastInterface), (int)PlainSocketImpl.getAddressFromInetAddress((InetAddress)val));
|
||||
break;
|
||||
case SocketOptions.IP_MULTICAST_IF2:
|
||||
throw new SocketException("SocketOptions.IP_MULTICAST_IF2 not implemented");
|
||||
case SocketOptions.IP_MULTICAST_LOOP:
|
||||
socket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.IP), SocketOptionName.wrap(SocketOptionName.MulticastLoopback), ((Boolean)val).booleanValue() ? 1 : 0);
|
||||
break;
|
||||
default:
|
||||
PlainSocketImpl.setCommonSocketOption(socket, option_id, val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch(cli.System.Net.Sockets.SocketException x)
|
||||
{
|
||||
throw new SocketException(x.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public int peekData(DatagramPacket packet)
|
||||
{
|
||||
// TODO
|
||||
throw new InternalError ("PlainDatagramSocketImpl::peekData is not implemented");
|
||||
}
|
||||
|
||||
public void joinGroup(SocketAddress address, NetworkInterface netIf)
|
||||
{
|
||||
// TODO
|
||||
throw new InternalError ("PlainDatagramSocketImpl::joinGroup is not implemented");
|
||||
}
|
||||
|
||||
public void leaveGroup(SocketAddress address, NetworkInterface netIf)
|
||||
{
|
||||
// TODO
|
||||
throw new InternalError ("PlainDatagramSocketImpl::leaveGroup is not implemented");
|
||||
}
|
||||
|
||||
public int getNativeFD() { throw new NoSuchMethodError("Not supported"); }
|
||||
} // class PlainDatagramSocketImpl
|
||||
|
|
|
@ -1,7 +1,613 @@
|
|||
/* PlainSocketImpl.java -- Default socket implementation
|
||||
Copyright (C) 1998, 1999 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath 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 for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package gnu.java.net;
|
||||
|
||||
public class PlainSocketImpl extends java.net.PlainSocketImpl
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.*;
|
||||
import cli.System.Net.IPEndPoint;
|
||||
import cli.System.Net.Sockets.SocketOptionName;
|
||||
import cli.System.Net.Sockets.SocketOptionLevel;
|
||||
import cli.System.Net.Sockets.SocketFlags;
|
||||
import cli.System.Net.Sockets.SocketType;
|
||||
import cli.System.Net.Sockets.ProtocolType;
|
||||
import cli.System.Net.Sockets.AddressFamily;
|
||||
import cli.System.Net.Sockets.SocketShutdown;
|
||||
import ikvm.lang.CIL;
|
||||
import ikvm.lang.ByteArrayHack;
|
||||
|
||||
/**
|
||||
* Unless the application installs its own SocketImplFactory, this is the
|
||||
* default socket implemetation that will be used. It simply uses a
|
||||
* combination of Java and native routines to implement standard BSD
|
||||
* style sockets of family AF_INET and types SOCK_STREAM and SOCK_DGRAM
|
||||
*
|
||||
* @version 0.1
|
||||
*
|
||||
* @author Aaron M. Renn (arenn@urbanophile.com)
|
||||
*/
|
||||
public class PlainSocketImpl extends SocketImpl
|
||||
{
|
||||
static IOException convertSocketExceptionToIOException(cli.System.Net.Sockets.SocketException x) throws IOException
|
||||
{
|
||||
switch(x.get_ErrorCode())
|
||||
{
|
||||
case 10048: //WSAEADDRINUSE
|
||||
return new BindException(x.getMessage());
|
||||
case 10051: //WSAENETUNREACH
|
||||
case 10065: //WSAEHOSTUNREACH
|
||||
return new NoRouteToHostException(x.getMessage());
|
||||
case 10060: //WSAETIMEDOUT
|
||||
return new java.io.InterruptedIOException(x.getMessage());
|
||||
case 10061: //WSAECONNREFUSED
|
||||
return new PortUnreachableException(x.getMessage());
|
||||
case 11001: //WSAHOST_NOT_FOUND
|
||||
return new UnknownHostException(x.getMessage());
|
||||
default:
|
||||
return new SocketException(x.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the native file descriptor for this socket
|
||||
*/
|
||||
private cli.System.Net.Sockets.Socket socket;
|
||||
|
||||
|
||||
/**
|
||||
* Default do nothing constructor
|
||||
*/
|
||||
public PlainSocketImpl()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepts a new connection on this socket and returns in in the
|
||||
* passed in SocketImpl.
|
||||
*
|
||||
* @param impl The SocketImpl object to accept this connection.
|
||||
*/
|
||||
protected void accept(SocketImpl _impl) throws IOException
|
||||
{
|
||||
PlainSocketImpl impl = (PlainSocketImpl)_impl;
|
||||
try
|
||||
{
|
||||
if(false) throw new cli.System.Net.Sockets.SocketException();
|
||||
int timeout = ((Integer)getOption(SO_TIMEOUT)).intValue();
|
||||
if(timeout != 0 && !socket.Poll(Math.min(timeout, Integer.MAX_VALUE / 1000) * 1000,
|
||||
cli.System.Net.Sockets.SelectMode.wrap(cli.System.Net.Sockets.SelectMode.SelectRead)))
|
||||
{
|
||||
throw new SocketTimeoutException("Accept timed out");
|
||||
}
|
||||
cli.System.Net.Sockets.Socket accept = socket.Accept();
|
||||
((PlainSocketImpl)impl).socket = accept;
|
||||
IPEndPoint remoteEndPoint = ((IPEndPoint)accept.get_RemoteEndPoint());
|
||||
long remoteIP = remoteEndPoint.get_Address().get_Address();
|
||||
String remote = (remoteIP & 0xff) + "." + ((remoteIP >> 8) & 0xff) + "." + ((remoteIP >> 16) & 0xff) + "." + ((remoteIP >> 24) & 0xff);
|
||||
impl.address = InetAddress.getByName(remote);
|
||||
impl.port = remoteEndPoint.get_Port();
|
||||
impl.localport = ((IPEndPoint)accept.get_LocalEndPoint()).get_Port();
|
||||
}
|
||||
catch(cli.System.Net.Sockets.SocketException x)
|
||||
{
|
||||
throw convertSocketExceptionToIOException(x);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of bytes that the caller can read from this socket
|
||||
* without blocking.
|
||||
*
|
||||
* @return The number of readable bytes before blocking
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected int available() throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
if(false) throw new cli.System.Net.Sockets.SocketException();
|
||||
return socket.get_Available();
|
||||
}
|
||||
catch(cli.System.Net.Sockets.SocketException x)
|
||||
{
|
||||
throw convertSocketExceptionToIOException(x);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds to the specified port on the specified addr. Note that this addr
|
||||
* must represent a local IP address. **** How bind to INADDR_ANY? ****
|
||||
*
|
||||
* @param addr The address to bind to
|
||||
* @param port The port number to bind to
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected void bind(InetAddress addr, int port) throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
if(false) throw new cli.System.Net.Sockets.SocketException();
|
||||
socket.Bind(new IPEndPoint(getAddressFromInetAddress(addr), port));
|
||||
this.address = addr;
|
||||
}
|
||||
catch(cli.System.Net.Sockets.SocketException x)
|
||||
{
|
||||
throw new BindException(x.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
static long getAddressFromInetAddress(InetAddress addr)
|
||||
{
|
||||
byte[] b = addr.getAddress();
|
||||
return (((b[3] & 0xff) << 24) + ((b[2] & 0xff) << 16) + ((b[1] & 0xff) << 8) + (b[0] & 0xff)) & 0xffffffffL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the socket. This will cause any InputStream or OutputStream
|
||||
* objects for this Socket to be closed as well.
|
||||
* <p>
|
||||
* Note that if the SO_LINGER option is set on this socket, then the
|
||||
* operation could block.
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected void close() throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
if(false) throw new cli.System.Net.Sockets.SocketException();
|
||||
socket.Close();
|
||||
}
|
||||
catch(cli.System.Net.Sockets.SocketException x)
|
||||
{
|
||||
throw convertSocketExceptionToIOException(x);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Connects to the remote address and port specified as arguments.
|
||||
*
|
||||
* @param addr The remote address to connect to
|
||||
* @param port The remote port to connect to
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected void connect(InetAddress addr, int port) throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
if(false) throw new cli.System.Net.Sockets.SocketException();
|
||||
socket.Connect(new IPEndPoint(getAddressFromInetAddress(addr), port));
|
||||
this.address = addr;
|
||||
this.port = port;
|
||||
this.localport = ((IPEndPoint)socket.get_LocalEndPoint()).get_Port();
|
||||
}
|
||||
catch(cli.System.Net.Sockets.SocketException x)
|
||||
{
|
||||
throw new ConnectException(x.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Connects to the remote hostname and port specified as arguments.
|
||||
*
|
||||
* @param hostname The remote hostname to connect to
|
||||
* @param port The remote port to connect to
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected void connect(String hostname, int port) throws IOException
|
||||
{
|
||||
connect(InetAddress.getByName(hostname), port);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new socket that is not bound to any local address/port and
|
||||
* is not connected to any remote address/port. This will be created as
|
||||
* a stream socket if the stream parameter is true, or a datagram socket
|
||||
* if the stream parameter is false.
|
||||
*
|
||||
* @param stream true for a stream socket, false for a datagram socket
|
||||
*/
|
||||
protected void create(boolean stream) throws IOException
|
||||
{
|
||||
if(!stream)
|
||||
{
|
||||
// TODO
|
||||
System.out.println("NOTE: PlainSocketImpl.create(false) not implemented");
|
||||
throw new IOException("PlainSocketImpl.create(false) not implemented");
|
||||
}
|
||||
try
|
||||
{
|
||||
if(false) throw new cli.System.Net.Sockets.SocketException();
|
||||
socket = new cli.System.Net.Sockets.Socket(AddressFamily.wrap(AddressFamily.InterNetwork), SocketType.wrap(SocketType.Stream), ProtocolType.wrap(ProtocolType.Tcp));
|
||||
}
|
||||
catch(cli.System.Net.Sockets.SocketException x)
|
||||
{
|
||||
throw convertSocketExceptionToIOException(x);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts listening for connections on a socket. The queuelen parameter
|
||||
* is how many pending connections will queue up waiting to be serviced
|
||||
* before being accept'ed. If the queue of pending requests exceeds this
|
||||
* number, additional connections will be refused.
|
||||
*
|
||||
* @param queuelen The length of the pending connection queue
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected void listen(int queuelen) throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
if(false) throw new cli.System.Net.Sockets.SocketException();
|
||||
socket.Listen(queuelen);
|
||||
localport = ((IPEndPoint)socket.get_LocalEndPoint()).get_Port();
|
||||
}
|
||||
catch(cli.System.Net.Sockets.SocketException x)
|
||||
{
|
||||
throw convertSocketExceptionToIOException(x);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal method used by SocketInputStream for reading data from
|
||||
* the connection. Reads up to len bytes of data into the buffer
|
||||
* buf starting at offset bytes into the buffer.
|
||||
*
|
||||
* @return The actual number of bytes read or -1 if end of stream.
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected int read(byte[] buf, int offset, int len) throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
if(false) throw new cli.System.Net.Sockets.SocketException();
|
||||
return socket.Receive(ByteArrayHack.cast(buf), offset, len, SocketFlags.wrap(SocketFlags.None));
|
||||
}
|
||||
catch(cli.System.Net.Sockets.SocketException x)
|
||||
{
|
||||
throw convertSocketExceptionToIOException(x);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal method used by SocketOuputStream for writing data to
|
||||
* the connection. Writes up to len bytes of data from the buffer
|
||||
* buf starting at offset bytes into the buffer.
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected void write(byte[] buf, int offset, int len) throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
if(false) throw new cli.System.Net.Sockets.SocketException();
|
||||
socket.Send(ByteArrayHack.cast(buf), offset, len, SocketFlags.wrap(SocketFlags.None));
|
||||
}
|
||||
catch(cli.System.Net.Sockets.SocketException x)
|
||||
{
|
||||
throw convertSocketExceptionToIOException(x);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the specified option on a socket to the passed in object. For
|
||||
* options that take an integer argument, the passed in object is an
|
||||
* Integer. The option_id parameter is one of the defined constants in
|
||||
* this interface.
|
||||
*
|
||||
* @param option_id The identifier of the option
|
||||
* @param val The value to set the option to
|
||||
*
|
||||
* @exception SocketException If an error occurs
|
||||
*/
|
||||
public void setOption(int option_id, Object val) throws SocketException
|
||||
{
|
||||
try
|
||||
{
|
||||
if(false) throw new cli.System.Net.Sockets.SocketException();
|
||||
switch(option_id)
|
||||
{
|
||||
case SocketOptions.TCP_NODELAY:
|
||||
socket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Tcp), SocketOptionName.wrap(SocketOptionName.NoDelay), ((Boolean)val).booleanValue() ? 1 : 0);
|
||||
break;
|
||||
case SocketOptions.SO_KEEPALIVE:
|
||||
socket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.KeepAlive), ((Boolean)val).booleanValue() ? 1 : 0);
|
||||
break;
|
||||
case SocketOptions.SO_LINGER:
|
||||
{
|
||||
cli.System.Net.Sockets.LingerOption linger;
|
||||
if(val instanceof Boolean)
|
||||
{
|
||||
linger = new cli.System.Net.Sockets.LingerOption(false, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
linger = new cli.System.Net.Sockets.LingerOption(true, ((Integer)val).intValue());
|
||||
}
|
||||
socket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.Linger), linger);
|
||||
break;
|
||||
}
|
||||
case SocketOptions.SO_OOBINLINE:
|
||||
socket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.OutOfBandInline), ((Boolean)val).booleanValue() ? 1 : 0);
|
||||
break;
|
||||
default:
|
||||
setCommonSocketOption(socket, option_id, val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch(cli.System.Net.Sockets.SocketException x)
|
||||
{
|
||||
throw new SocketException(x.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
static void setCommonSocketOption(cli.System.Net.Sockets.Socket socket, int option_id, Object val) throws SocketException
|
||||
{
|
||||
try
|
||||
{
|
||||
if(false) throw new cli.System.Net.Sockets.SocketException();
|
||||
switch(option_id)
|
||||
{
|
||||
case SocketOptions.SO_TIMEOUT:
|
||||
socket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.ReceiveTimeout), ((Integer)val).intValue());
|
||||
socket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.SendTimeout), ((Integer)val).intValue());
|
||||
break;
|
||||
case SocketOptions.SO_SNDBUF:
|
||||
socket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.SendBuffer), ((Integer)val).intValue());
|
||||
break;
|
||||
case SocketOptions.SO_RCVBUF:
|
||||
socket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.ReceiveBuffer), ((Integer)val).intValue());
|
||||
break;
|
||||
case SocketOptions.IP_TOS:
|
||||
socket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.IP), SocketOptionName.wrap(SocketOptionName.TypeOfService), ((Integer)val).intValue());
|
||||
break;
|
||||
case SocketOptions.SO_BINDADDR: // read-only
|
||||
default:
|
||||
throw new SocketException("Invalid socket option: " + option_id);
|
||||
}
|
||||
}
|
||||
catch(cli.System.Net.Sockets.SocketException x)
|
||||
{
|
||||
throw new SocketException(x.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current setting of the specified option. The Object returned
|
||||
* will be an Integer for options that have integer values. The option_id
|
||||
* is one of the defined constants in this interface.
|
||||
*
|
||||
* @param option_id The option identifier
|
||||
*
|
||||
* @return The current value of the option
|
||||
*
|
||||
* @exception SocketException If an error occurs
|
||||
*/
|
||||
public Object getOption(int option_id) throws SocketException
|
||||
{
|
||||
try
|
||||
{
|
||||
if(false) throw new cli.System.Net.Sockets.SocketException();
|
||||
switch(option_id)
|
||||
{
|
||||
case SocketOptions.TCP_NODELAY:
|
||||
return new Boolean(CIL.unbox_int(socket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Tcp), SocketOptionName.wrap(SocketOptionName.NoDelay))) != 0);
|
||||
case SocketOptions.SO_KEEPALIVE:
|
||||
return new Boolean(CIL.unbox_int(socket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.KeepAlive))) != 0);
|
||||
case SocketOptions.SO_LINGER:
|
||||
{
|
||||
cli.System.Net.Sockets.LingerOption linger = (cli.System.Net.Sockets.LingerOption)socket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.Linger));
|
||||
if(linger.get_Enabled())
|
||||
{
|
||||
return new Integer(linger.get_LingerTime());
|
||||
}
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
case SocketOptions.SO_OOBINLINE:
|
||||
return new Integer(CIL.unbox_int(socket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.OutOfBandInline))));
|
||||
default:
|
||||
return getCommonSocketOption(socket, option_id);
|
||||
}
|
||||
}
|
||||
catch(cli.System.Net.Sockets.SocketException x)
|
||||
{
|
||||
throw new SocketException(x.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
static Object getCommonSocketOption(cli.System.Net.Sockets.Socket socket, int option_id) throws SocketException
|
||||
{
|
||||
try
|
||||
{
|
||||
if(false) throw new cli.System.Net.Sockets.SocketException();
|
||||
switch(option_id)
|
||||
{
|
||||
case SocketOptions.SO_TIMEOUT:
|
||||
return new Integer(CIL.unbox_int(socket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.ReceiveTimeout))));
|
||||
case SocketOptions.SO_SNDBUF:
|
||||
return new Integer(CIL.unbox_int(socket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.SendBuffer))));
|
||||
case SocketOptions.SO_RCVBUF:
|
||||
return new Integer(CIL.unbox_int(socket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.ReceiveBuffer))));
|
||||
case SocketOptions.IP_TOS:
|
||||
return new Integer(CIL.unbox_int(socket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.IP), SocketOptionName.wrap(SocketOptionName.TypeOfService))));
|
||||
case SocketOptions.SO_BINDADDR:
|
||||
try
|
||||
{
|
||||
return InetAddress.getByAddress(getLocalAddress(socket));
|
||||
}
|
||||
catch(UnknownHostException x)
|
||||
{
|
||||
throw new SocketException(x.getMessage());
|
||||
}
|
||||
default:
|
||||
throw new SocketException("Invalid socket option: " + option_id);
|
||||
}
|
||||
}
|
||||
catch(cli.System.Net.Sockets.SocketException x)
|
||||
{
|
||||
throw new SocketException(x.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
static byte[] getLocalAddress(cli.System.Net.Sockets.Socket socket)
|
||||
{
|
||||
int address = (int)((cli.System.Net.IPEndPoint)socket.get_LocalEndPoint()).get_Address().get_Address();
|
||||
return new byte[] { (byte)address, (byte)(address >> 8), (byte)(address >> 16), (byte)(address >> 24) };
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an InputStream object for reading from this socket. This will
|
||||
* be an instance of SocketInputStream.
|
||||
*
|
||||
* @return An InputStream
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected InputStream getInputStream() throws IOException
|
||||
{
|
||||
return new InputStream()
|
||||
{
|
||||
public int available() throws IOException
|
||||
{
|
||||
return PlainSocketImpl.this.available();
|
||||
}
|
||||
public void close() throws IOException
|
||||
{
|
||||
PlainSocketImpl.this.close();
|
||||
}
|
||||
public int read() throws IOException
|
||||
{
|
||||
byte buf[] = new byte[1];
|
||||
int bytes_read = read(buf, 0, buf.length);
|
||||
if (bytes_read == 1)
|
||||
return buf[0] & 0xFF;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
public int read(byte[] buf) throws IOException
|
||||
{
|
||||
return read(buf, 0, buf.length);
|
||||
}
|
||||
public int read(byte[] buf, int offset, int len) throws IOException
|
||||
{
|
||||
int bytes_read = PlainSocketImpl.this.read(buf, offset, len);
|
||||
if (bytes_read == 0)
|
||||
return -1;
|
||||
return bytes_read;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an OutputStream object for writing to this socket. This will
|
||||
* be an instance of SocketOutputStream.
|
||||
*
|
||||
* @return An OutputStream
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected OutputStream getOutputStream() throws IOException
|
||||
{
|
||||
return new OutputStream()
|
||||
{
|
||||
public void close() throws IOException
|
||||
{
|
||||
PlainSocketImpl.this.close();
|
||||
}
|
||||
public void write(int b) throws IOException
|
||||
{
|
||||
byte buf[] = { (byte)b };
|
||||
write(buf, 0, buf.length);
|
||||
}
|
||||
public void write(byte[] buf) throws IOException
|
||||
{
|
||||
write(buf, 0, buf.length);
|
||||
}
|
||||
public void write(byte[] buf, int offset, int len) throws IOException
|
||||
{
|
||||
PlainSocketImpl.this.write(buf, offset, len);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public void connect(SocketAddress address, int timeout) throws IOException
|
||||
{
|
||||
// NOTE for now we ignore the timeout and we only support InetSocketAddress
|
||||
InetSocketAddress inetAddress = (InetSocketAddress)address;
|
||||
connect(inetAddress.getAddress(), inetAddress.getPort());
|
||||
}
|
||||
|
||||
protected boolean supportsUrgentData()
|
||||
{
|
||||
// This method has to be overwritten by socket classes that support
|
||||
// sending urgent data.
|
||||
return true;
|
||||
}
|
||||
|
||||
public void sendUrgentData(int data)
|
||||
{
|
||||
// Send one byte of urgent data on the socket. The byte to be sent is
|
||||
// the lowest eight bits of the data parameter.
|
||||
// The urgent byte is sent after any preceding writes to the socket
|
||||
// OutputStream and before any future writes to the OutputStream.
|
||||
byte[] oob = { (byte)data };
|
||||
socket.Send(ByteArrayHack.cast(oob), SocketFlags.wrap(SocketFlags.OutOfBand));
|
||||
}
|
||||
|
||||
public void shutdownInput()
|
||||
{
|
||||
socket.Shutdown(SocketShutdown.wrap(SocketShutdown.Receive));
|
||||
}
|
||||
|
||||
public void shutdownOutput()
|
||||
{
|
||||
socket.Shutdown(SocketShutdown.wrap(SocketShutdown.Send));
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether a channel initiated whatever operation
|
||||
* is being invoked on this socket.
|
||||
|
|
|
@ -1,425 +0,0 @@
|
|||
/* PlainDatagramSocketImpl.java -- Default DatagramSocket implementation
|
||||
Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath 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 for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package java.net;
|
||||
|
||||
import java.io.IOException;
|
||||
import cli.System.Net.*;
|
||||
import cli.System.Net.Sockets.*;
|
||||
import ikvm.lang.CIL;
|
||||
import ikvm.lang.ByteArrayHack;
|
||||
|
||||
/**
|
||||
* This is the default socket implementation for datagram sockets.
|
||||
* It makes native calls to C routines that implement BSD style
|
||||
* SOCK_DGRAM sockets in the AF_INET family.
|
||||
*
|
||||
* @version 0.1
|
||||
*
|
||||
* @author Aaron M. Renn (arenn@urbanophile.com)
|
||||
*/
|
||||
public class PlainDatagramSocketImpl extends DatagramSocketImpl
|
||||
{
|
||||
/*
|
||||
* Static Variables
|
||||
*/
|
||||
|
||||
/**
|
||||
* This is the actual underlying socket
|
||||
*/
|
||||
private cli.System.Net.Sockets.Socket socket = new cli.System.Net.Sockets.Socket(
|
||||
AddressFamily.wrap(AddressFamily.InterNetwork),
|
||||
SocketType.wrap(SocketType.Dgram),
|
||||
ProtocolType.wrap(ProtocolType.Udp));
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/*
|
||||
* Constructors
|
||||
*/
|
||||
|
||||
/**
|
||||
* Default do nothing constructor
|
||||
*/
|
||||
public PlainDatagramSocketImpl()
|
||||
{
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/*
|
||||
* Instance Methods
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates a new datagram socket
|
||||
*
|
||||
* @exception SocketException If an error occurs
|
||||
*/
|
||||
protected void create() throws SocketException
|
||||
{
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* Closes the socket
|
||||
*/
|
||||
protected void close()
|
||||
{
|
||||
if(socket != null)
|
||||
{
|
||||
socket.Close();
|
||||
socket = null;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* Binds this socket to a particular port and interface
|
||||
*
|
||||
* @param port The port to bind to
|
||||
* @param addr The address to bind to
|
||||
*
|
||||
* @exception SocketException If an error occurs
|
||||
*/
|
||||
protected void bind(int port, InetAddress addr) throws SocketException
|
||||
{
|
||||
try
|
||||
{
|
||||
if(false) throw new cli.System.Net.Sockets.SocketException();
|
||||
socket.Bind(new IPEndPoint(PlainSocketImpl.getAddressFromInetAddress(addr), port));
|
||||
localPort = ((IPEndPoint)socket.get_LocalEndPoint()).get_Port();
|
||||
}
|
||||
catch(cli.System.Net.Sockets.SocketException x)
|
||||
{
|
||||
throw new BindException(x.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* Sends a packet of data to a remote host
|
||||
*
|
||||
* @param packet The packet to send
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected void send(DatagramPacket packet) throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
if(false) throw new cli.System.Net.Sockets.SocketException();
|
||||
int len = packet.getLength();
|
||||
if(socket.SendTo(ByteArrayHack.cast(packet.getData()), len, SocketFlags.wrap(SocketFlags.None), new IPEndPoint(PlainSocketImpl.getAddressFromInetAddress(packet.getAddress()), packet.getPort())) != len)
|
||||
{
|
||||
throw new SocketException("Not all data was sent");
|
||||
}
|
||||
}
|
||||
catch(cli.System.Net.Sockets.SocketException x)
|
||||
{
|
||||
throw PlainSocketImpl.convertSocketExceptionToIOException(x);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* What does this method really do?
|
||||
*/
|
||||
protected int peek(InetAddress addr) throws IOException
|
||||
{
|
||||
throw new IOException("Not Implemented Yet");
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* Receives a UDP packet from the network
|
||||
*
|
||||
* @param packet The packet to fill in with the data received
|
||||
*
|
||||
* @exception IOException IOException If an error occurs
|
||||
*/
|
||||
protected void receive(DatagramPacket packet) throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
if(false) throw new cli.System.Net.Sockets.SocketException();
|
||||
byte[] data = packet.getData();
|
||||
cli.System.Net.EndPoint[] remoteEP = new cli.System.Net.EndPoint[] {
|
||||
new cli.System.Net.IPEndPoint(0, 0)
|
||||
};
|
||||
int length = socket.ReceiveFrom(ByteArrayHack.cast(data), remoteEP);
|
||||
packet.setLength(length);
|
||||
int remoteIP = (int)((cli.System.Net.IPEndPoint)remoteEP[0]).get_Address().get_Address();
|
||||
byte[] ipv4 = new byte[] { (byte)remoteIP, (byte)(remoteIP >> 8), (byte)(remoteIP >> 16), (byte)(remoteIP >> 24) };
|
||||
InetAddress remoteAddress = InetAddress.getByAddress(ipv4);
|
||||
packet.setAddress(remoteAddress);
|
||||
packet.setPort(((cli.System.Net.IPEndPoint)remoteEP[0]).get_Port());
|
||||
}
|
||||
catch(cli.System.Net.Sockets.SocketException x)
|
||||
{
|
||||
throw PlainSocketImpl.convertSocketExceptionToIOException(x);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* Joins a multicast group
|
||||
*
|
||||
* @param addr The group to join
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected void join(InetAddress addr) throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
if(false) throw new cli.System.Net.Sockets.SocketException();
|
||||
if(false) throw new cli.System.ArgumentException();
|
||||
socket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.IP), SocketOptionName.wrap(SocketOptionName.AddMembership), new MulticastOption(new cli.System.Net.IPAddress(PlainSocketImpl.getAddressFromInetAddress(addr))));
|
||||
}
|
||||
catch(cli.System.Net.Sockets.SocketException x)
|
||||
{
|
||||
throw PlainSocketImpl.convertSocketExceptionToIOException(x);
|
||||
}
|
||||
catch(cli.System.ArgumentException x1)
|
||||
{
|
||||
throw new IOException(x1.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* Leaves a multicast group
|
||||
*
|
||||
* @param addr The group to leave
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected void leave(InetAddress addr) throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
if(false) throw new cli.System.Net.Sockets.SocketException();
|
||||
if(false) throw new cli.System.ArgumentException();
|
||||
socket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.IP), SocketOptionName.wrap(SocketOptionName.DropMembership), new MulticastOption(new cli.System.Net.IPAddress(PlainSocketImpl.getAddressFromInetAddress(addr))));
|
||||
}
|
||||
catch(cli.System.Net.Sockets.SocketException x)
|
||||
{
|
||||
throw PlainSocketImpl.convertSocketExceptionToIOException(x);
|
||||
}
|
||||
catch(cli.System.ArgumentException x1)
|
||||
{
|
||||
throw new IOException(x1.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* Gets the Time to Live value for the socket
|
||||
*
|
||||
* @return The TTL value
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected byte getTTL() throws IOException
|
||||
{
|
||||
return (byte)CIL.unbox_int(socket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.IP), SocketOptionName.wrap(SocketOptionName.IpTimeToLive)));
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* Sets the Time to Live value for the socket
|
||||
*
|
||||
* @param ttl The new TTL value
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected void setTTL(byte ttl) throws IOException
|
||||
{
|
||||
socket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.IP), SocketOptionName.wrap(SocketOptionName.IpTimeToLive), ttl & 0xff);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* Gets the Time to Live value for the socket
|
||||
*
|
||||
* @return The TTL value
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected int getTimeToLive() throws IOException
|
||||
{
|
||||
return CIL.unbox_int(socket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.IP), SocketOptionName.wrap(SocketOptionName.IpTimeToLive)));
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* Sets the Time to Live value for the socket
|
||||
*
|
||||
* @param ttl The new TTL value
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected void setTimeToLive(int ttl) throws IOException
|
||||
{
|
||||
socket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.IP), SocketOptionName.wrap(SocketOptionName.IpTimeToLive), ttl);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* Retrieves the value of an option on the socket
|
||||
*
|
||||
* @param option_id The identifier of the option to retrieve
|
||||
*
|
||||
* @return The value of the option
|
||||
*
|
||||
* @exception SocketException If an error occurs
|
||||
*/
|
||||
public Object getOption(int option_id) throws SocketException
|
||||
{
|
||||
try
|
||||
{
|
||||
if(false) throw new cli.System.Net.Sockets.SocketException();
|
||||
switch(option_id)
|
||||
{
|
||||
case SocketOptions.SO_REUSEADDR:
|
||||
return new Boolean(CIL.unbox_int(socket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.ReuseAddress))) != 0);
|
||||
case SocketOptions.SO_BROADCAST:
|
||||
return new Boolean(CIL.unbox_int(socket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.Broadcast))) != 0);
|
||||
case SocketOptions.IP_MULTICAST_IF:
|
||||
return getInetAddressFromInt(CIL.unbox_int(socket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.IP), SocketOptionName.wrap(SocketOptionName.MulticastInterface))));
|
||||
case SocketOptions.IP_MULTICAST_IF2:
|
||||
throw new SocketException("SocketOptions.IP_MULTICAST_IF2 not implemented");
|
||||
case SocketOptions.IP_MULTICAST_LOOP:
|
||||
return new Boolean(CIL.unbox_int(socket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.IP), SocketOptionName.wrap(SocketOptionName.MulticastLoopback))) != 0);
|
||||
default:
|
||||
return PlainSocketImpl.getCommonSocketOption(socket, option_id);
|
||||
}
|
||||
}
|
||||
catch(cli.System.Net.Sockets.SocketException x)
|
||||
{
|
||||
throw new SocketException(x.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private static InetAddress getInetAddressFromInt(int i) throws SocketException
|
||||
{
|
||||
byte[] b = new byte[4];
|
||||
b[0] = (byte)(i >> 0);
|
||||
b[1] = (byte)(i >> 8);
|
||||
b[2] = (byte)(i >> 16);
|
||||
b[3] = (byte)(i >> 24);
|
||||
try
|
||||
{
|
||||
return InetAddress.getByAddress(b);
|
||||
}
|
||||
catch(UnknownHostException x)
|
||||
{
|
||||
throw new SocketException(x.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* Sets the value of an option on the socket
|
||||
*
|
||||
* @param option_id The identifier of the option to set
|
||||
* @param val The value of the option to set
|
||||
*
|
||||
* @exception SocketException If an error occurs
|
||||
*/
|
||||
public void setOption(int option_id, Object val) throws SocketException
|
||||
{
|
||||
try
|
||||
{
|
||||
if(false) throw new cli.System.Net.Sockets.SocketException();
|
||||
switch(option_id)
|
||||
{
|
||||
case SocketOptions.SO_REUSEADDR:
|
||||
socket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.ReuseAddress), ((Boolean)val).booleanValue() ? 1 : 0);
|
||||
break;
|
||||
case SocketOptions.SO_BROADCAST:
|
||||
socket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.Broadcast), ((Boolean)val).booleanValue() ? 1 : 0);
|
||||
break;
|
||||
case SocketOptions.IP_MULTICAST_IF:
|
||||
socket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.IP), SocketOptionName.wrap(SocketOptionName.MulticastInterface), (int)PlainSocketImpl.getAddressFromInetAddress((InetAddress)val));
|
||||
break;
|
||||
case SocketOptions.IP_MULTICAST_IF2:
|
||||
throw new SocketException("SocketOptions.IP_MULTICAST_IF2 not implemented");
|
||||
case SocketOptions.IP_MULTICAST_LOOP:
|
||||
socket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.IP), SocketOptionName.wrap(SocketOptionName.MulticastLoopback), ((Boolean)val).booleanValue() ? 1 : 0);
|
||||
break;
|
||||
default:
|
||||
PlainSocketImpl.setCommonSocketOption(socket, option_id, val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch(cli.System.Net.Sockets.SocketException x)
|
||||
{
|
||||
throw new SocketException(x.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public int peekData(DatagramPacket packet)
|
||||
{
|
||||
throw new InternalError ("PlainDatagramSocketImpl::peekData is not implemented");
|
||||
}
|
||||
|
||||
public void joinGroup(SocketAddress address, NetworkInterface netIf)
|
||||
{
|
||||
throw new InternalError ("PlainDatagramSocketImpl::joinGroup is not implemented");
|
||||
}
|
||||
|
||||
public void leaveGroup(SocketAddress address, NetworkInterface netIf)
|
||||
{
|
||||
throw new InternalError ("PlainDatagramSocketImpl::leaveGroup is not implemented");
|
||||
}
|
||||
} // class PlainDatagramSocketImpl
|
|
@ -1,554 +0,0 @@
|
|||
/* PlainSocketImpl.java -- Default socket implementation
|
||||
Copyright (C) 1998, 1999 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath 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 for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package java.net;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.IOException;
|
||||
import cli.System.Net.*;
|
||||
import cli.System.Net.Sockets.*;
|
||||
import ikvm.lang.CIL;
|
||||
import ikvm.lang.ByteArrayHack;
|
||||
|
||||
/**
|
||||
* Unless the application installs its own SocketImplFactory, this is the
|
||||
* default socket implemetation that will be used. It simply uses a
|
||||
* combination of Java and native routines to implement standard BSD
|
||||
* style sockets of family AF_INET and types SOCK_STREAM and SOCK_DGRAM
|
||||
*
|
||||
* @version 0.1
|
||||
*
|
||||
* @author Aaron M. Renn (arenn@urbanophile.com)
|
||||
*/
|
||||
public class PlainSocketImpl extends SocketImpl
|
||||
{
|
||||
static IOException convertSocketExceptionToIOException(cli.System.Net.Sockets.SocketException x) throws IOException
|
||||
{
|
||||
switch(x.get_ErrorCode())
|
||||
{
|
||||
case 10048: //WSAEADDRINUSE
|
||||
return new BindException(x.getMessage());
|
||||
case 10051: //WSAENETUNREACH
|
||||
case 10065: //WSAEHOSTUNREACH
|
||||
return new NoRouteToHostException(x.getMessage());
|
||||
case 10060: //WSAETIMEDOUT
|
||||
return new java.io.InterruptedIOException(x.getMessage());
|
||||
case 10061: //WSAECONNREFUSED
|
||||
return new PortUnreachableException(x.getMessage());
|
||||
case 11001: //WSAHOST_NOT_FOUND
|
||||
return new UnknownHostException(x.getMessage());
|
||||
default:
|
||||
return new SocketException(x.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the native file descriptor for this socket
|
||||
*/
|
||||
private cli.System.Net.Sockets.Socket socket;
|
||||
|
||||
|
||||
/**
|
||||
* Default do nothing constructor
|
||||
*/
|
||||
public PlainSocketImpl()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepts a new connection on this socket and returns in in the
|
||||
* passed in SocketImpl.
|
||||
*
|
||||
* @param impl The SocketImpl object to accept this connection.
|
||||
*/
|
||||
protected void accept(SocketImpl impl) throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
if(false) throw new cli.System.Net.Sockets.SocketException();
|
||||
int timeout = ((Integer)getOption(SO_TIMEOUT)).intValue();
|
||||
if(timeout != 0 && !socket.Poll(Math.min(timeout, Integer.MAX_VALUE / 1000) * 1000,
|
||||
cli.System.Net.Sockets.SelectMode.wrap(cli.System.Net.Sockets.SelectMode.SelectRead)))
|
||||
{
|
||||
throw new SocketTimeoutException("Accept timed out");
|
||||
}
|
||||
cli.System.Net.Sockets.Socket accept = socket.Accept();
|
||||
((PlainSocketImpl)impl).socket = accept;
|
||||
IPEndPoint remoteEndPoint = ((IPEndPoint)accept.get_RemoteEndPoint());
|
||||
long remoteIP = remoteEndPoint.get_Address().get_Address();
|
||||
String remote = (remoteIP & 0xff) + "." + ((remoteIP >> 8) & 0xff) + "." + ((remoteIP >> 16) & 0xff) + "." + ((remoteIP >> 24) & 0xff);
|
||||
impl.address = InetAddress.getByName(remote);
|
||||
impl.port = remoteEndPoint.get_Port();
|
||||
impl.localport = ((IPEndPoint)accept.get_LocalEndPoint()).get_Port();
|
||||
}
|
||||
catch(cli.System.Net.Sockets.SocketException x)
|
||||
{
|
||||
throw convertSocketExceptionToIOException(x);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of bytes that the caller can read from this socket
|
||||
* without blocking.
|
||||
*
|
||||
* @return The number of readable bytes before blocking
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected int available() throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
if(false) throw new cli.System.Net.Sockets.SocketException();
|
||||
return socket.get_Available();
|
||||
}
|
||||
catch(cli.System.Net.Sockets.SocketException x)
|
||||
{
|
||||
throw convertSocketExceptionToIOException(x);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds to the specified port on the specified addr. Note that this addr
|
||||
* must represent a local IP address. **** How bind to INADDR_ANY? ****
|
||||
*
|
||||
* @param addr The address to bind to
|
||||
* @param port The port number to bind to
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected void bind(InetAddress addr, int port) throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
if(false) throw new cli.System.Net.Sockets.SocketException();
|
||||
socket.Bind(new IPEndPoint(getAddressFromInetAddress(addr), port));
|
||||
this.address = addr;
|
||||
}
|
||||
catch(cli.System.Net.Sockets.SocketException x)
|
||||
{
|
||||
throw new BindException(x.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
static long getAddressFromInetAddress(InetAddress addr)
|
||||
{
|
||||
byte[] b = addr.getAddress();
|
||||
return (((b[3] & 0xff) << 24) + ((b[2] & 0xff) << 16) + ((b[1] & 0xff) << 8) + (b[0] & 0xff)) & 0xffffffffL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the socket. This will cause any InputStream or OutputStream
|
||||
* objects for this Socket to be closed as well.
|
||||
* <p>
|
||||
* Note that if the SO_LINGER option is set on this socket, then the
|
||||
* operation could block.
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected void close() throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
if(false) throw new cli.System.Net.Sockets.SocketException();
|
||||
socket.Close();
|
||||
}
|
||||
catch(cli.System.Net.Sockets.SocketException x)
|
||||
{
|
||||
throw convertSocketExceptionToIOException(x);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Connects to the remote address and port specified as arguments.
|
||||
*
|
||||
* @param addr The remote address to connect to
|
||||
* @param port The remote port to connect to
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected void connect(InetAddress addr, int port) throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
if(false) throw new cli.System.Net.Sockets.SocketException();
|
||||
socket.Connect(new IPEndPoint(getAddressFromInetAddress(addr), port));
|
||||
this.address = addr;
|
||||
this.port = port;
|
||||
this.localport = ((IPEndPoint)socket.get_LocalEndPoint()).get_Port();
|
||||
}
|
||||
catch(cli.System.Net.Sockets.SocketException x)
|
||||
{
|
||||
throw new ConnectException(x.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Connects to the remote hostname and port specified as arguments.
|
||||
*
|
||||
* @param hostname The remote hostname to connect to
|
||||
* @param port The remote port to connect to
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected void connect(String hostname, int port) throws IOException
|
||||
{
|
||||
connect(InetAddress.getByName(hostname), port);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new socket that is not bound to any local address/port and
|
||||
* is not connected to any remote address/port. This will be created as
|
||||
* a stream socket if the stream parameter is true, or a datagram socket
|
||||
* if the stream parameter is false.
|
||||
*
|
||||
* @param stream true for a stream socket, false for a datagram socket
|
||||
*/
|
||||
protected void create(boolean stream) throws IOException
|
||||
{
|
||||
if(!stream)
|
||||
{
|
||||
// TODO
|
||||
System.out.println("NOTE: PlainSocketImpl.create(false) not implemented");
|
||||
throw new IOException("PlainSocketImpl.create(false) not implemented");
|
||||
}
|
||||
try
|
||||
{
|
||||
if(false) throw new cli.System.Net.Sockets.SocketException();
|
||||
socket = new cli.System.Net.Sockets.Socket(AddressFamily.wrap(AddressFamily.InterNetwork), SocketType.wrap(SocketType.Stream), ProtocolType.wrap(ProtocolType.Tcp));
|
||||
}
|
||||
catch(cli.System.Net.Sockets.SocketException x)
|
||||
{
|
||||
throw convertSocketExceptionToIOException(x);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts listening for connections on a socket. The queuelen parameter
|
||||
* is how many pending connections will queue up waiting to be serviced
|
||||
* before being accept'ed. If the queue of pending requests exceeds this
|
||||
* number, additional connections will be refused.
|
||||
*
|
||||
* @param queuelen The length of the pending connection queue
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected void listen(int queuelen) throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
if(false) throw new cli.System.Net.Sockets.SocketException();
|
||||
socket.Listen(queuelen);
|
||||
localport = ((IPEndPoint)socket.get_LocalEndPoint()).get_Port();
|
||||
}
|
||||
catch(cli.System.Net.Sockets.SocketException x)
|
||||
{
|
||||
throw convertSocketExceptionToIOException(x);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal method used by SocketInputStream for reading data from
|
||||
* the connection. Reads up to len bytes of data into the buffer
|
||||
* buf starting at offset bytes into the buffer.
|
||||
*
|
||||
* @return The actual number of bytes read or -1 if end of stream.
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected int read(byte[] buf, int offset, int len) throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
if(false) throw new cli.System.Net.Sockets.SocketException();
|
||||
return socket.Receive(ByteArrayHack.cast(buf), offset, len, SocketFlags.wrap(SocketFlags.None));
|
||||
}
|
||||
catch(cli.System.Net.Sockets.SocketException x)
|
||||
{
|
||||
throw convertSocketExceptionToIOException(x);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal method used by SocketOuputStream for writing data to
|
||||
* the connection. Writes up to len bytes of data from the buffer
|
||||
* buf starting at offset bytes into the buffer.
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected void write(byte[] buf, int offset, int len) throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
if(false) throw new cli.System.Net.Sockets.SocketException();
|
||||
socket.Send(ByteArrayHack.cast(buf), offset, len, SocketFlags.wrap(SocketFlags.None));
|
||||
}
|
||||
catch(cli.System.Net.Sockets.SocketException x)
|
||||
{
|
||||
throw convertSocketExceptionToIOException(x);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the specified option on a socket to the passed in object. For
|
||||
* options that take an integer argument, the passed in object is an
|
||||
* Integer. The option_id parameter is one of the defined constants in
|
||||
* this interface.
|
||||
*
|
||||
* @param option_id The identifier of the option
|
||||
* @param val The value to set the option to
|
||||
*
|
||||
* @exception SocketException If an error occurs
|
||||
*/
|
||||
public void setOption(int option_id, Object val) throws SocketException
|
||||
{
|
||||
try
|
||||
{
|
||||
if(false) throw new cli.System.Net.Sockets.SocketException();
|
||||
switch(option_id)
|
||||
{
|
||||
case SocketOptions.TCP_NODELAY:
|
||||
socket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Tcp), SocketOptionName.wrap(SocketOptionName.NoDelay), ((Boolean)val).booleanValue() ? 1 : 0);
|
||||
break;
|
||||
case SocketOptions.SO_KEEPALIVE:
|
||||
socket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.KeepAlive), ((Boolean)val).booleanValue() ? 1 : 0);
|
||||
break;
|
||||
case SocketOptions.SO_LINGER:
|
||||
{
|
||||
cli.System.Net.Sockets.LingerOption linger;
|
||||
if(val instanceof Boolean)
|
||||
{
|
||||
linger = new cli.System.Net.Sockets.LingerOption(false, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
linger = new cli.System.Net.Sockets.LingerOption(true, ((Integer)val).intValue());
|
||||
}
|
||||
socket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.Linger), linger);
|
||||
break;
|
||||
}
|
||||
case SocketOptions.SO_OOBINLINE:
|
||||
socket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.OutOfBandInline), ((Boolean)val).booleanValue() ? 1 : 0);
|
||||
break;
|
||||
default:
|
||||
setCommonSocketOption(socket, option_id, val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch(cli.System.Net.Sockets.SocketException x)
|
||||
{
|
||||
throw new SocketException(x.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
static void setCommonSocketOption(cli.System.Net.Sockets.Socket socket, int option_id, Object val) throws SocketException
|
||||
{
|
||||
try
|
||||
{
|
||||
if(false) throw new cli.System.Net.Sockets.SocketException();
|
||||
switch(option_id)
|
||||
{
|
||||
case SocketOptions.SO_TIMEOUT:
|
||||
socket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.ReceiveTimeout), ((Integer)val).intValue());
|
||||
socket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.SendTimeout), ((Integer)val).intValue());
|
||||
break;
|
||||
case SocketOptions.SO_SNDBUF:
|
||||
socket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.SendBuffer), ((Integer)val).intValue());
|
||||
break;
|
||||
case SocketOptions.SO_RCVBUF:
|
||||
socket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.ReceiveBuffer), ((Integer)val).intValue());
|
||||
break;
|
||||
case SocketOptions.IP_TOS:
|
||||
socket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.IP), SocketOptionName.wrap(SocketOptionName.TypeOfService), ((Integer)val).intValue());
|
||||
break;
|
||||
case SocketOptions.SO_BINDADDR: // read-only
|
||||
default:
|
||||
throw new SocketException("Invalid socket option: " + option_id);
|
||||
}
|
||||
}
|
||||
catch(cli.System.Net.Sockets.SocketException x)
|
||||
{
|
||||
throw new SocketException(x.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current setting of the specified option. The Object returned
|
||||
* will be an Integer for options that have integer values. The option_id
|
||||
* is one of the defined constants in this interface.
|
||||
*
|
||||
* @param option_id The option identifier
|
||||
*
|
||||
* @return The current value of the option
|
||||
*
|
||||
* @exception SocketException If an error occurs
|
||||
*/
|
||||
public Object getOption(int option_id) throws SocketException
|
||||
{
|
||||
try
|
||||
{
|
||||
if(false) throw new cli.System.Net.Sockets.SocketException();
|
||||
switch(option_id)
|
||||
{
|
||||
case SocketOptions.TCP_NODELAY:
|
||||
return new Boolean(CIL.unbox_int(socket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Tcp), SocketOptionName.wrap(SocketOptionName.NoDelay))) != 0);
|
||||
case SocketOptions.SO_KEEPALIVE:
|
||||
return new Boolean(CIL.unbox_int(socket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.KeepAlive))) != 0);
|
||||
case SocketOptions.SO_LINGER:
|
||||
{
|
||||
cli.System.Net.Sockets.LingerOption linger = (cli.System.Net.Sockets.LingerOption)socket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.Linger));
|
||||
if(linger.get_Enabled())
|
||||
{
|
||||
return new Integer(linger.get_LingerTime());
|
||||
}
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
case SocketOptions.SO_OOBINLINE:
|
||||
return new Integer(CIL.unbox_int(socket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.OutOfBandInline))));
|
||||
default:
|
||||
return getCommonSocketOption(socket, option_id);
|
||||
}
|
||||
}
|
||||
catch(cli.System.Net.Sockets.SocketException x)
|
||||
{
|
||||
throw new SocketException(x.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
static Object getCommonSocketOption(cli.System.Net.Sockets.Socket socket, int option_id) throws SocketException
|
||||
{
|
||||
try
|
||||
{
|
||||
if(false) throw new cli.System.Net.Sockets.SocketException();
|
||||
switch(option_id)
|
||||
{
|
||||
case SocketOptions.SO_TIMEOUT:
|
||||
return new Integer(CIL.unbox_int(socket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.ReceiveTimeout))));
|
||||
case SocketOptions.SO_SNDBUF:
|
||||
return new Integer(CIL.unbox_int(socket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.SendBuffer))));
|
||||
case SocketOptions.SO_RCVBUF:
|
||||
return new Integer(CIL.unbox_int(socket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.ReceiveBuffer))));
|
||||
case SocketOptions.IP_TOS:
|
||||
return new Integer(CIL.unbox_int(socket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.IP), SocketOptionName.wrap(SocketOptionName.TypeOfService))));
|
||||
case SocketOptions.SO_BINDADDR:
|
||||
try
|
||||
{
|
||||
return InetAddress.getByAddress(getLocalAddress(socket));
|
||||
}
|
||||
catch(UnknownHostException x)
|
||||
{
|
||||
throw new SocketException(x.getMessage());
|
||||
}
|
||||
default:
|
||||
throw new SocketException("Invalid socket option: " + option_id);
|
||||
}
|
||||
}
|
||||
catch(cli.System.Net.Sockets.SocketException x)
|
||||
{
|
||||
throw new SocketException(x.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
static byte[] getLocalAddress(cli.System.Net.Sockets.Socket socket)
|
||||
{
|
||||
int address = (int)((cli.System.Net.IPEndPoint)socket.get_LocalEndPoint()).get_Address().get_Address();
|
||||
return new byte[] { (byte)address, (byte)(address >> 8), (byte)(address >> 16), (byte)(address >> 24) };
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an InputStream object for reading from this socket. This will
|
||||
* be an instance of SocketInputStream.
|
||||
*
|
||||
* @return An InputStream
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected InputStream getInputStream() throws IOException
|
||||
{
|
||||
return new SocketInputStream(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an OutputStream object for writing to this socket. This will
|
||||
* be an instance of SocketOutputStream.
|
||||
*
|
||||
* @return An OutputStream
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
protected OutputStream getOutputStream() throws IOException
|
||||
{
|
||||
return new SocketOutputStream(this);
|
||||
}
|
||||
|
||||
public void connect(SocketAddress address, int timeout) throws IOException
|
||||
{
|
||||
// NOTE for now we ignore the timeout and we only support InetSocketAddress
|
||||
InetSocketAddress inetAddress = (InetSocketAddress)address;
|
||||
connect(inetAddress.getAddress(), inetAddress.getPort());
|
||||
}
|
||||
|
||||
protected boolean supportsUrgentData()
|
||||
{
|
||||
// This method has to be overwritten by socket classes that support
|
||||
// sending urgent data.
|
||||
return true;
|
||||
}
|
||||
|
||||
public void sendUrgentData(int data)
|
||||
{
|
||||
// Send one byte of urgent data on the socket. The byte to be sent is
|
||||
// the lowest eight bits of the data parameter.
|
||||
// The urgent byte is sent after any preceding writes to the socket
|
||||
// OutputStream and before any future writes to the OutputStream.
|
||||
byte[] oob = {(byte)data};
|
||||
socket.Send(ByteArrayHack.cast(oob),
|
||||
SocketFlags.wrap(SocketFlags.OutOfBand));
|
||||
}
|
||||
|
||||
public void shutdownInput()
|
||||
{
|
||||
socket.Shutdown(SocketShutdown.wrap(SocketShutdown.Receive));
|
||||
}
|
||||
|
||||
public void shutdownOutput()
|
||||
{
|
||||
socket.Shutdown(SocketShutdown.wrap(SocketShutdown.Send));
|
||||
}
|
||||
} // class PlainSocketImpl
|
|
@ -1,204 +0,0 @@
|
|||
/* SocketInputStream.java -- An InputStream for Sockets
|
||||
Copyright (C) 1998, 2000, 2002 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath 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 for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
|
||||
package java.net;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* This class contains an implementation of <code>InputStream</code> for
|
||||
* sockets. It in an internal only class used by <code>PlainSocketImpl</code>.
|
||||
*
|
||||
* @author Aaron M. Renn (arenn@urbanophile.com)
|
||||
*/
|
||||
class SocketInputStream extends InputStream
|
||||
{
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/*
|
||||
* Instance Variables
|
||||
*/
|
||||
|
||||
/**
|
||||
* The PlainSocketImpl object this stream is associated with
|
||||
*/
|
||||
private PlainSocketImpl impl;
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/*
|
||||
* Constructors
|
||||
*/
|
||||
|
||||
/**
|
||||
* Builds an instance of this class from a PlainSocketImpl object
|
||||
*/
|
||||
protected
|
||||
SocketInputStream(PlainSocketImpl impl)
|
||||
{
|
||||
this.impl = impl;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/*
|
||||
* Instance Methods
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns the number of bytes available to be read before blocking
|
||||
*/
|
||||
public int
|
||||
available() throws IOException
|
||||
{
|
||||
return(impl.available());
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* Determines if "mark" functionality is supported on this stream. For
|
||||
* sockets, this is always false. Note that the superclass default is
|
||||
* false, but it is overridden out of safety concerns and/or paranoia.
|
||||
*/
|
||||
public boolean
|
||||
markSupported()
|
||||
{
|
||||
return(false);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* Do nothing mark method since we don't support this functionality. Again,
|
||||
* overriding out of paranoia.
|
||||
*
|
||||
* @param readlimit In theory, the number of bytes we can read before the mark becomes invalid
|
||||
*/
|
||||
public void
|
||||
mark(int readlimit)
|
||||
{
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* Since we don't support mark, this method always throws an exception
|
||||
*
|
||||
* @exception IOException Everytime since we don't support this functionality
|
||||
*/
|
||||
public void
|
||||
reset() throws IOException
|
||||
{
|
||||
throw new IOException("Socket InputStreams do not support mark/reset");
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* This method not only closes the stream, it closes the underlying socket
|
||||
* (and thus any connection) and invalidates any other Input/Output streams
|
||||
* for the underlying impl object
|
||||
*/
|
||||
public void
|
||||
close() throws IOException
|
||||
{
|
||||
impl.close();
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* Reads the next byte of data and returns it as an int.
|
||||
*
|
||||
* @return The byte read (as an int) or -1 if end of stream);
|
||||
*
|
||||
* @exception IOException If an error occurs.
|
||||
*/
|
||||
public int
|
||||
read() throws IOException
|
||||
{
|
||||
byte buf[] = new byte[1];
|
||||
|
||||
int bytes_read = read(buf, 0, buf.length);
|
||||
|
||||
if (bytes_read != -1)
|
||||
return(buf[0] & 0xFF);
|
||||
else
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* Reads up to buf.length bytes of data into the caller supplied buffer.
|
||||
*
|
||||
* @return The actual number of bytes read or -1 if end of stream
|
||||
*
|
||||
* @exception IOException If an error occurs.
|
||||
*/
|
||||
public int
|
||||
read(byte[] buf) throws IOException
|
||||
{
|
||||
return(read(buf, 0, buf.length));
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* Reads up to len bytes of data into the caller supplied buffer starting
|
||||
* at offset bytes from the start of the buffer
|
||||
*
|
||||
* @return The number of bytes actually read or -1 if end of stream
|
||||
*
|
||||
* @exception IOException If an error occurs.
|
||||
*/
|
||||
public int
|
||||
read(byte[] buf, int offset, int len) throws IOException
|
||||
{
|
||||
int bytes_read = impl.read(buf, offset, len);
|
||||
if (bytes_read == 0)
|
||||
return(-1);
|
||||
|
||||
return(bytes_read);
|
||||
}
|
||||
|
||||
} // class SocketInputStream
|
||||
|
|
@ -1,165 +0,0 @@
|
|||
/* SocketOutputStream.java -- OutputStream for PlainSocketImpl
|
||||
Copyright (C) 1998,2000 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath 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 for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version. */
|
||||
|
||||
package java.net;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* This class is used internally by <code>PlainSocketImpl</code> to be the
|
||||
* <code>OutputStream</code> subclass returned by its
|
||||
* <code>getOutputStream method</code>. It expects only to be used in that
|
||||
* context.
|
||||
*
|
||||
* @author Aaron M. Renn (arenn@urbanophile.com)
|
||||
*/
|
||||
class SocketOutputStream extends OutputStream
|
||||
{
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/*
|
||||
* Instance Variables
|
||||
*/
|
||||
|
||||
/**
|
||||
* The PlainSocketImpl object this stream is associated with
|
||||
*/
|
||||
private PlainSocketImpl impl;
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/*
|
||||
* Constructors
|
||||
*/
|
||||
|
||||
/**
|
||||
* Build an instance of this class from a PlainSocketImpl object
|
||||
*/
|
||||
protected
|
||||
SocketOutputStream(PlainSocketImpl impl)
|
||||
{
|
||||
this.impl = impl;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/*
|
||||
* Instance Methods
|
||||
*/
|
||||
|
||||
/**
|
||||
* This method closes the stream and the underlying socket connection. This
|
||||
* action also effectively closes any other InputStream or OutputStream
|
||||
* object associated with the connection.
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
public void
|
||||
close() throws IOException
|
||||
{
|
||||
impl.close();
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* Hmmm, we don't seem to have a flush() method in Socket impl, so just
|
||||
* return for now, but this might need to be looked at later.
|
||||
*
|
||||
* @exception IOException Can't happen
|
||||
*/
|
||||
public void
|
||||
flush() throws IOException
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* Writes a byte (passed in as an int) to the given output stream
|
||||
*
|
||||
* @param b The byte to write
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
public void
|
||||
write(int b) throws IOException
|
||||
{
|
||||
byte buf[] = new byte[1];
|
||||
|
||||
Integer i = new Integer(b);
|
||||
buf[0] = i.byteValue();
|
||||
|
||||
write(buf, 0, buf.length);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* Write an array of bytes to the output stream
|
||||
*
|
||||
* @param buf The array of bytes to write
|
||||
*
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
public void
|
||||
write(byte[] buf) throws IOException
|
||||
{
|
||||
write(buf, 0, buf.length);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/**
|
||||
* Writes len number of bytes from the array buf to the stream starting
|
||||
* at offset bytes into the buffer.
|
||||
*
|
||||
* @param buf The buffer
|
||||
* @param offset Offset into the buffer to start writing from
|
||||
* @param len The number of bytes to write
|
||||
*/
|
||||
public void
|
||||
write(byte[] buf, int offset, int len) throws IOException
|
||||
{
|
||||
impl.write(buf, offset, len);
|
||||
}
|
||||
|
||||
} // class SocketOutputStream
|
||||
|
|
@ -194,13 +194,13 @@
|
|||
<constructor sig="([B)V" modifiers="public">
|
||||
<redirect class="java.lang.StringHelper" name="NewString" type="static" sig="([B)Ljava.lang.String;" />
|
||||
</constructor>
|
||||
<constructor sig="([BI)V" modifiers="public">
|
||||
<constructor sig="([BI)V" modifiers="public" deprecated="true">
|
||||
<redirect class="java.lang.StringHelper" name="NewString" type="static" sig="([BI)Ljava.lang.String;" />
|
||||
</constructor>
|
||||
<constructor sig="([BII)V" modifiers="public">
|
||||
<redirect class="java.lang.StringHelper" name="NewString" type="static" sig="([BII)Ljava.lang.String;" />
|
||||
</constructor>
|
||||
<constructor sig="([BIII)V" modifiers="public">
|
||||
<constructor sig="([BIII)V" modifiers="public" deprecated="true">
|
||||
<redirect class="java.lang.StringHelper" name="NewString" type="static" sig="([BIII)Ljava.lang.String;" />
|
||||
</constructor>
|
||||
<constructor sig="([BLjava.lang.String;)V" modifiers="public">
|
||||
|
@ -389,7 +389,7 @@
|
|||
<method name="regionMatches" sig="(ILjava.lang.String;II)Z" modifiers="public">
|
||||
<redirect class="java.lang.StringHelper" type="static" sig="(Ljava.lang.String;ILjava.lang.String;II)Z" />
|
||||
</method>
|
||||
<method name="getBytes" sig="(II[BI)V" modifiers="public">
|
||||
<method name="getBytes" sig="(II[BI)V" modifiers="public" deprecated="true">
|
||||
<redirect class="java.lang.StringHelper" type="static" sig="(Ljava.lang.String;II[BI)V" />
|
||||
</method>
|
||||
<method name="concat" sig="(Ljava.lang.String;)Ljava.lang.String;" modifiers="public">
|
||||
|
|
|
@ -419,6 +419,20 @@ class ClassFileAttribute
|
|||
}
|
||||
}
|
||||
|
||||
class DeprecatedAttribute : ClassFileAttribute
|
||||
{
|
||||
internal DeprecatedAttribute(ClassFileWriter classFile)
|
||||
: base(classFile.AddUtf8("Deprecated"))
|
||||
{
|
||||
}
|
||||
|
||||
public override void Write(BigEndianStream bes)
|
||||
{
|
||||
base.Write(bes);
|
||||
bes.WriteUInt32(0);
|
||||
}
|
||||
}
|
||||
|
||||
class ConstantValueAttribute : ClassFileAttribute
|
||||
{
|
||||
private ushort constant_index;
|
||||
|
|
|
@ -173,6 +173,10 @@ public class NetExp
|
|||
}
|
||||
ClassFileWriter f = new ClassFileWriter(classmods, name, super);
|
||||
f.AddStringAttribute("IKVM.NET.Assembly", assemblyName);
|
||||
if(IKVM.Runtime.Util.IsClassDeprecated(c))
|
||||
{
|
||||
f.AddAttribute(new DeprecatedAttribute(f));
|
||||
}
|
||||
InnerClassesAttribute innerClassesAttribute = null;
|
||||
if(outer != null)
|
||||
{
|
||||
|
@ -233,6 +237,10 @@ public class NetExp
|
|||
};
|
||||
m.AddAttribute(code);
|
||||
AddExceptions(f, m, constructors[i].getExceptionTypes());
|
||||
if(IKVM.Runtime.Util.IsConstructorDeprecated(constructors[i]))
|
||||
{
|
||||
m.AddAttribute(new DeprecatedAttribute(f));
|
||||
}
|
||||
}
|
||||
}
|
||||
Method[] methods = c.getDeclaredMethods();
|
||||
|
@ -248,69 +256,74 @@ public class NetExp
|
|||
// TODO what happens if one of the argument types (or the return type) is non-public?
|
||||
FieldOrMethod m = f.AddMethod(mods, methods[i].getName(), MakeSig(methods[i].getParameterTypes(), methods[i].getReturnType()));
|
||||
AddExceptions(f, m, methods[i].getExceptionTypes());
|
||||
if(IKVM.Runtime.Util.IsMethodDeprecated(methods[i]))
|
||||
{
|
||||
m.AddAttribute(new DeprecatedAttribute(f));
|
||||
}
|
||||
}
|
||||
}
|
||||
Field[] fields = c.getDeclaredFields();
|
||||
for(int i = 0; i < fields.Length; i++)
|
||||
{
|
||||
Modifiers mods = (Modifiers)fields[i].getModifiers();
|
||||
if((mods & (Modifiers.Public | Modifiers.Protected)) != 0)
|
||||
if((mods & (Modifiers.Public | Modifiers.Protected)) != 0 ||
|
||||
// Include serialVersionUID field, to make Japitools comparison more acurate
|
||||
((mods & (Modifiers.Static | Modifiers.Final)) == (Modifiers.Static | Modifiers.Final) &&
|
||||
fields[i].getName() == "serialVersionUID" && fields[i].getType() == java.lang.Long.TYPE))
|
||||
{
|
||||
object constantValue = null;
|
||||
// HACK we only look for constants on potential constant fields, to trigger less static initializers
|
||||
if((mods & (Modifiers.Final | Modifiers.Static)) == (Modifiers.Final | Modifiers.Static) &&
|
||||
(fields[i].getType().isPrimitive() || fields[i].getType() == Class.forName("java.lang.String")))
|
||||
// HACK we use the IKVM runtime API to get constant value
|
||||
// NOTE we can't use Field.get() because that will run the static initializer and
|
||||
// also won't allow us to see the difference between constants and blank final fields.
|
||||
object constantValue = IKVM.Runtime.Util.GetFieldConstantValue(fields[i]);
|
||||
if(constantValue != null)
|
||||
{
|
||||
// HACK we use a non-standard API to get constant value
|
||||
// NOTE we can't use Field.get() because that will run the static initializer and
|
||||
// also won't allow us to see the difference between constants and blank final fields.
|
||||
constantValue = IKVM.NativeCode.java.lang.reflect.Field.getConstant(fields[i]);
|
||||
if(constantValue != null)
|
||||
if(constantValue is java.lang.Boolean)
|
||||
{
|
||||
if(constantValue is java.lang.Boolean)
|
||||
{
|
||||
constantValue = ((java.lang.Boolean)constantValue).booleanValue();
|
||||
}
|
||||
else if(constantValue is java.lang.Byte)
|
||||
{
|
||||
constantValue = ((java.lang.Byte)constantValue).byteValue();
|
||||
}
|
||||
else if(constantValue is java.lang.Short)
|
||||
{
|
||||
constantValue = ((java.lang.Short)constantValue).shortValue();
|
||||
}
|
||||
else if(constantValue is java.lang.Character)
|
||||
{
|
||||
constantValue = ((java.lang.Character)constantValue).charValue();
|
||||
}
|
||||
else if(constantValue is java.lang.Integer)
|
||||
{
|
||||
constantValue = ((java.lang.Integer)constantValue).intValue();
|
||||
}
|
||||
else if(constantValue is java.lang.Long)
|
||||
{
|
||||
constantValue = ((java.lang.Long)constantValue).longValue();
|
||||
}
|
||||
else if(constantValue is java.lang.Float)
|
||||
{
|
||||
constantValue = ((java.lang.Float)constantValue).floatValue();
|
||||
}
|
||||
else if(constantValue is java.lang.Double)
|
||||
{
|
||||
constantValue = ((java.lang.Double)constantValue).doubleValue();
|
||||
}
|
||||
else if(constantValue is string)
|
||||
{
|
||||
// no conversion needed
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
constantValue = ((java.lang.Boolean)constantValue).booleanValue();
|
||||
}
|
||||
else if(constantValue is java.lang.Byte)
|
||||
{
|
||||
constantValue = ((java.lang.Byte)constantValue).byteValue();
|
||||
}
|
||||
else if(constantValue is java.lang.Short)
|
||||
{
|
||||
constantValue = ((java.lang.Short)constantValue).shortValue();
|
||||
}
|
||||
else if(constantValue is java.lang.Character)
|
||||
{
|
||||
constantValue = ((java.lang.Character)constantValue).charValue();
|
||||
}
|
||||
else if(constantValue is java.lang.Integer)
|
||||
{
|
||||
constantValue = ((java.lang.Integer)constantValue).intValue();
|
||||
}
|
||||
else if(constantValue is java.lang.Long)
|
||||
{
|
||||
constantValue = ((java.lang.Long)constantValue).longValue();
|
||||
}
|
||||
else if(constantValue is java.lang.Float)
|
||||
{
|
||||
constantValue = ((java.lang.Float)constantValue).floatValue();
|
||||
}
|
||||
else if(constantValue is java.lang.Double)
|
||||
{
|
||||
constantValue = ((java.lang.Double)constantValue).doubleValue();
|
||||
}
|
||||
else if(constantValue is string)
|
||||
{
|
||||
// no conversion needed
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
}
|
||||
// TODO what happens if the field type is non-public?
|
||||
f.AddField(mods, fields[i].getName(), ClassToSig(fields[i].getType()), constantValue);
|
||||
FieldOrMethod fld = f.AddField(mods, fields[i].getName(), ClassToSig(fields[i].getType()), constantValue);
|
||||
if(IKVM.Runtime.Util.IsFieldDeprecated(fields[i]))
|
||||
{
|
||||
fld.AddAttribute(new DeprecatedAttribute(f));
|
||||
}
|
||||
}
|
||||
}
|
||||
if(innerClassesAttribute != null)
|
||||
|
|
|
@ -1,18 +1,28 @@
|
|||
<?xml version="1.0"?>
|
||||
<project name="japi-status" default="ikvm-japi-status.html">
|
||||
<project name="japi-status" default="default">
|
||||
|
||||
<property name="REFERENCE_API_JARS" value="c:\j2re1.4.1\lib\rt.jar c:\j2re1.4.1\lib\jce.jar c:\j2re1.4.1\lib\jsse.jar" />
|
||||
<property name="REFERENCE_API_NAME" value="JDK-1.4.1" />
|
||||
<property name="REFERENCE_API_JARS" value="c:\j2sdk1.4.0\jre\lib\rt.jar c:\j2sdk1.4.0\jre\lib\jce.jar c:\j2sdk1.4.0\jre\lib\jsse.jar" />
|
||||
<property name="REFERENCE_API_NAME" value="JDK-1.4" />
|
||||
<!--
|
||||
<property name="REFERENCE_API_JARS" value="c:\jdk1.5\jre\lib\rt.jar c:\jdk1.5\jre\lib\jce.jar c:\jdk1.5\jre\lib\jsse.jar" />
|
||||
<property name="REFERENCE_API_NAME" value="JDK-1.5" />
|
||||
-->
|
||||
<property name="JAPI_HOME" value="c:\japi\japitools" />
|
||||
<property name="IKVM_VERSION" value="0.9" />
|
||||
|
||||
<target name="ikvm-japi-status.html" depends="japi.diff">
|
||||
<exec program="perl" commandline="${JAPI_HOME}/bin/japiohtml japi.diff" output="ikvm-japi-status.html" />
|
||||
<target name="default">
|
||||
<call target="status" />
|
||||
<call target="clean" />
|
||||
</target>
|
||||
|
||||
<target name="status" depends="japi.diff">
|
||||
<exec program="perl" commandline="${JAPI_HOME}/bin/japiohtml japi1.diff" output="IKVM-${IKVM_VERSION}-vs-${REFERENCE_API_NAME}.html" />
|
||||
<exec program="perl" commandline="${JAPI_HOME}/bin/japiohtml japi2.diff" output="${REFERENCE_API_NAME}-vs-IKVM-${IKVM_VERSION}.html" />
|
||||
</target>
|
||||
|
||||
<target name="japi.diff" depends="jdk.japi,ikvm.japi">
|
||||
<exec program="perl" commandline="${JAPI_HOME}/bin/japicompat -j -o japi.diff ${REFERENCE_API_NAME}.japi IKVM-${IKVM_VERSION}.japi" />
|
||||
<exec program="perl" commandline="${JAPI_HOME}/bin/japicompat -v -j -o japi1.diff IKVM-${IKVM_VERSION}.japi ${REFERENCE_API_NAME}.japi" />
|
||||
<exec program="perl" commandline="${JAPI_HOME}/bin/japicompat -v -j -o japi2.diff ${REFERENCE_API_NAME}.japi IKVM-${IKVM_VERSION}.japi" />
|
||||
</target>
|
||||
|
||||
<target name="jdk.japi" depends="japize">
|
||||
|
@ -35,7 +45,8 @@
|
|||
<delete failonerror="false">
|
||||
<fileset>
|
||||
<includes name="IKVM.GNU.Classpath.jar" />
|
||||
<includes name="japi.diff" />
|
||||
<includes name="japi1.diff" />
|
||||
<includes name="japi2.diff" />
|
||||
<includes name="${REFERENCE_API_NAME}.japi" />
|
||||
<includes name="IKVM-${IKVM_VERSION}.japi" />
|
||||
<includes name="../bin/japize.exe" />
|
||||
|
|
|
@ -1372,13 +1372,6 @@ class ClassFile
|
|||
break;
|
||||
}
|
||||
}
|
||||
// spec (4.7.2) says we should silently ignore ConstantValue attribute on non-static fields
|
||||
// NOTE a field doesn't have to be final to have a constant value!
|
||||
if(!IsStatic)
|
||||
{
|
||||
// TODO is this needed?
|
||||
constantValue = null;
|
||||
}
|
||||
}
|
||||
|
||||
internal object ConstantValue
|
||||
|
|
|
@ -453,14 +453,8 @@ class ClassLoaderWrapper
|
|||
{
|
||||
if(!(a is AssemblyBuilder))
|
||||
{
|
||||
Type t = a.GetType(name);
|
||||
if(t != null && t.Module.IsDefined(typeof(JavaModuleAttribute), false))
|
||||
{
|
||||
return t;
|
||||
}
|
||||
// HACK we might be looking for an inner classes
|
||||
t = a.GetType(name.Replace('$', '+'));
|
||||
if(t != null && t.Module.IsDefined(typeof(JavaModuleAttribute), false))
|
||||
Type t = GetJavaTypeFromAssembly(a, name);
|
||||
if(t != null)
|
||||
{
|
||||
return t;
|
||||
}
|
||||
|
@ -469,6 +463,22 @@ class ClassLoaderWrapper
|
|||
return null;
|
||||
}
|
||||
|
||||
private static Type GetJavaTypeFromAssembly(Assembly a, string name)
|
||||
{
|
||||
Type t = a.GetType(name);
|
||||
if(t != null && t.Module.IsDefined(typeof(JavaModuleAttribute), false))
|
||||
{
|
||||
return t;
|
||||
}
|
||||
// HACK we might be looking for an inner classes
|
||||
t = a.GetType(name.Replace('$', '+'));
|
||||
if(t != null && t.Module.IsDefined(typeof(JavaModuleAttribute), false))
|
||||
{
|
||||
return t;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
internal virtual TypeWrapper GetTypeWrapperCompilerHook(string name)
|
||||
{
|
||||
return null;
|
||||
|
@ -577,7 +587,7 @@ class ClassLoaderWrapper
|
|||
}
|
||||
}
|
||||
|
||||
private TypeWrapper DefineNetExpType(string name, string assembly)
|
||||
private TypeWrapper DefineNetExpType(string name, string assemblyName)
|
||||
{
|
||||
Debug.Assert(this == GetBootstrapClassLoader());
|
||||
lock(types.SyncRoot)
|
||||
|
@ -592,18 +602,27 @@ class ClassLoaderWrapper
|
|||
}
|
||||
// The sole purpose of the netexp class is to let us load the assembly that the class lives in,
|
||||
// once we've done that, all types in it become visible.
|
||||
Assembly asm;
|
||||
try
|
||||
{
|
||||
Assembly.Load(assembly);
|
||||
asm = Assembly.Load(assemblyName);
|
||||
}
|
||||
catch(Exception x)
|
||||
{
|
||||
throw new NoClassDefFoundError(name + " (" + x.Message + ")");
|
||||
}
|
||||
// pre-compiled Java types can also live in a netexp referenced assembly,
|
||||
// so we have to explicitly check for those
|
||||
// (DotNetTypeWrapper.CreateDotNetTypeWrapper will refuse to return Java types).
|
||||
Type t = GetJavaTypeFromAssembly(asm, name);
|
||||
if(t != null)
|
||||
{
|
||||
return GetWrapperFromBootstrapType(t);
|
||||
}
|
||||
type = DotNetTypeWrapper.CreateDotNetTypeWrapper(name);
|
||||
if(type == null)
|
||||
{
|
||||
throw new NoClassDefFoundError(name + " not found in " + assembly);
|
||||
throw new NoClassDefFoundError(name + " not found in " + assemblyName);
|
||||
}
|
||||
types.Add(name, type);
|
||||
return type;
|
||||
|
@ -707,7 +726,7 @@ class ClassLoaderWrapper
|
|||
name.Name = "ikvm_dynamic_assembly__" + (this == GetBootstrapClassLoader() ? "bootstrap" : javaClassLoader);
|
||||
}
|
||||
AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(name, saveDebugImage ? AssemblyBuilderAccess.RunAndSave : AssemblyBuilderAccess.Run, null, null, null, null, null, true);
|
||||
ModuleBuilder moduleBuilder = saveDebugImage ? assemblyBuilder.DefineDynamicModule(name.Name, "ikvmdump.exe", JVM.Debug) : assemblyBuilder.DefineDynamicModule(name.Name, JVM.Debug);
|
||||
ModuleBuilder moduleBuilder = saveDebugImage ? assemblyBuilder.DefineDynamicModule("ikvmdump.exe", "ikvmdump.exe", JVM.Debug) : assemblyBuilder.DefineDynamicModule(name.Name, JVM.Debug);
|
||||
CustomAttributeBuilder debugAttr = new CustomAttributeBuilder(typeof(DebuggableAttribute).GetConstructor(new Type[] { typeof(bool), typeof(bool) }), new object[] { true, JVM.Debug });
|
||||
assemblyBuilder.SetCustomAttribute(debugAttr);
|
||||
return moduleBuilder;
|
||||
|
|
|
@ -1068,17 +1068,31 @@ abstract class FieldWrapper : MemberWrapper
|
|||
Debug.Assert(fieldType != null, this.DeclaringType.Name + "::" + this.name + " (" + this.sig+ ")");
|
||||
}
|
||||
|
||||
// HACK used (indirectly thru IKVM.NativeCode.java.lang.Field.getConstant) by netexp to find out if the
|
||||
// HACK used (thru IKVM.Runtime.Util.GetFieldConstantValue) by ikvmstub to find out if the
|
||||
// field is a constant (and if it is, to get its value)
|
||||
internal object GetConstant()
|
||||
{
|
||||
AssertLinked();
|
||||
// NOTE only pritimives and string can be literals in Java (because the other "primitives" (like uint),
|
||||
// are treated as NonPrimitiveValueTypes)
|
||||
if(field != null && (fieldType.IsPrimitive || fieldType == CoreClasses.java.lang.String.Wrapper) && field.IsLiteral)
|
||||
if(field != null && (fieldType.IsPrimitive || fieldType == CoreClasses.java.lang.String.Wrapper))
|
||||
{
|
||||
ReflectionOnConstant.IssueWarning(field);
|
||||
object val = field.GetValue(null);
|
||||
object val = null;
|
||||
if(field.IsLiteral)
|
||||
{
|
||||
ReflectionOnConstant.IssueWarning(field);
|
||||
val = field.GetValue(null);
|
||||
}
|
||||
else
|
||||
{
|
||||
// In Java, instance fields can also have a ConstantValue attribute so we emulate that
|
||||
// with ConstantValueAttribute (for consumption by ikvmstub only)
|
||||
object[] attrib = field.GetCustomAttributes(typeof(ConstantValueAttribute), false);
|
||||
if(attrib.Length == 1)
|
||||
{
|
||||
val = ((ConstantValueAttribute)attrib[0]).GetConstantValue();
|
||||
}
|
||||
}
|
||||
if(val != null && !(val is string))
|
||||
{
|
||||
return IKVM.NativeCode.java.lang.reflect.JavaWrapper.Box(val);
|
||||
|
|
|
@ -3058,7 +3058,7 @@ sealed class DynamicTypeWrapper : TypeWrapper
|
|||
|
||||
static JniProxyBuilder()
|
||||
{
|
||||
mod = ((AssemblyBuilder)ClassLoaderWrapper.GetBootstrapClassLoader().ModuleBuilder.Assembly).DefineDynamicModule("jniproxy", "jniproxy.dll");
|
||||
mod = ((AssemblyBuilder)ClassLoaderWrapper.GetBootstrapClassLoader().ModuleBuilder.Assembly).DefineDynamicModule("jniproxy.dll", "jniproxy.dll");
|
||||
}
|
||||
|
||||
private static string Cleanup(string n)
|
||||
|
@ -3151,11 +3151,7 @@ sealed class DynamicTypeWrapper : TypeWrapper
|
|||
ilGenerator.Emit(OpCodes.Call, monitorEnter);
|
||||
ilGenerator.BeginExceptionBlock();
|
||||
}
|
||||
FieldBuilder methodPtr = wrapper.TypeAsBuilder.DefineField("jniptr/" + m.Name + m.Signature, typeof(IntPtr), FieldAttributes.Static | (thruProxy ? FieldAttributes.Assembly : FieldAttributes.PrivateScope));
|
||||
if(thruProxy)
|
||||
{
|
||||
AttributeHelper.HideFromJava(methodPtr);
|
||||
}
|
||||
FieldBuilder methodPtr = typeBuilder.DefineField("__<jniptr/" + m.Name + m.Signature + ">", typeof(IntPtr), FieldAttributes.Static | FieldAttributes.PrivateScope);
|
||||
LocalBuilder localRefStruct = ilGenerator.DeclareLocal(localRefStructType);
|
||||
ilGenerator.Emit(OpCodes.Ldloca, localRefStruct);
|
||||
ilGenerator.Emit(OpCodes.Initobj, localRefStructType);
|
||||
|
@ -3471,6 +3467,13 @@ sealed class DynamicTypeWrapper : TypeWrapper
|
|||
// TODO the field should be marked as modreq(IsVolatile), but Reflection.Emit doesn't have a way of doing this
|
||||
setModifiers = true;
|
||||
}
|
||||
// Instance fields can also have a ConstantValue attribute (and are inlined by the compiler),
|
||||
// and ikvmstub has to export them, so we have to add a custom attribute.
|
||||
if(constantValue != null)
|
||||
{
|
||||
CustomAttributeBuilder constantValueAttrib = new CustomAttributeBuilder(typeof(ConstantValueAttribute).GetConstructor(new Type[] { constantValue.GetType() }), new object[] { constantValue });
|
||||
field.SetCustomAttribute(constantValueAttrib);
|
||||
}
|
||||
if(isWrappedFinal)
|
||||
{
|
||||
methodAttribs |= MethodAttributes.SpecialName;
|
||||
|
|
|
@ -359,4 +359,40 @@ namespace IKVM.Attributes
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Field)]
|
||||
public sealed class ConstantValueAttribute : Attribute
|
||||
{
|
||||
private object val;
|
||||
|
||||
public ConstantValueAttribute(int val)
|
||||
{
|
||||
this.val = val;
|
||||
}
|
||||
|
||||
public ConstantValueAttribute(long val)
|
||||
{
|
||||
this.val = val;
|
||||
}
|
||||
|
||||
public ConstantValueAttribute(float val)
|
||||
{
|
||||
this.val = val;
|
||||
}
|
||||
|
||||
public ConstantValueAttribute(double val)
|
||||
{
|
||||
this.val = val;
|
||||
}
|
||||
|
||||
public ConstantValueAttribute(string val)
|
||||
{
|
||||
this.val = val;
|
||||
}
|
||||
|
||||
public object GetConstantValue()
|
||||
{
|
||||
return val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -312,14 +312,6 @@ namespace IKVM.NativeCode.java
|
|||
|
||||
public class Field
|
||||
{
|
||||
// HACK this is used by netexp to query the constant value of a field
|
||||
public static object getConstant(object field)
|
||||
{
|
||||
// HACK we use reflection to extract the fieldCookie from the java.lang.reflect.Field object
|
||||
FieldWrapper wrapper = (FieldWrapper)field.GetType().GetField("fieldCookie", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(field);
|
||||
return wrapper.GetConstant();
|
||||
}
|
||||
|
||||
public static string GetName(object fieldCookie)
|
||||
{
|
||||
FieldWrapper wrapper = (FieldWrapper)fieldCookie;
|
||||
|
|
|
@ -827,6 +827,8 @@ namespace IKVM.Internal.MapXml
|
|||
public string Sig;
|
||||
[XmlAttribute("modifiers")]
|
||||
public MapModifiers Modifiers;
|
||||
[XmlAttribute("deprecated")]
|
||||
public bool Deprecated;
|
||||
public InstructionList body;
|
||||
public InstructionList alternateBody;
|
||||
public Redirect redirect;
|
||||
|
@ -872,6 +874,8 @@ namespace IKVM.Internal.MapXml
|
|||
public MapModifiers Modifiers;
|
||||
[XmlAttribute("type")]
|
||||
public string Type;
|
||||
[XmlAttribute("deprecated")]
|
||||
public bool Deprecated;
|
||||
public InstructionList body;
|
||||
public InstructionList alternateBody;
|
||||
public InstructionList nonvirtualAlternateBody;
|
||||
|
@ -891,6 +895,8 @@ namespace IKVM.Internal.MapXml
|
|||
public MapModifiers Modifiers;
|
||||
[XmlAttribute("constant")]
|
||||
public string Constant;
|
||||
[XmlAttribute("deprecated")]
|
||||
public bool Deprecated;
|
||||
public Redirect redirect;
|
||||
}
|
||||
|
||||
|
@ -938,6 +944,8 @@ namespace IKVM.Internal.MapXml
|
|||
public MapModifiers Modifiers;
|
||||
[XmlAttribute("scope")]
|
||||
public Scope scope;
|
||||
[XmlAttribute("deprecated")]
|
||||
public bool Deprecated;
|
||||
[XmlElement("constructor")]
|
||||
public Constructor[] Constructors;
|
||||
[XmlElement("method")]
|
||||
|
|
|
@ -208,6 +208,77 @@ namespace IKVM.Runtime
|
|||
}
|
||||
return IKVM.NativeCode.java.lang.VMClass.getClassFromWrapper(ClassLoaderWrapper.GetWrapperFromType(t));
|
||||
}
|
||||
|
||||
private static FieldWrapper GetFieldWrapperFromField(object field)
|
||||
{
|
||||
if(field == null)
|
||||
{
|
||||
throw new ArgumentNullException("field");
|
||||
}
|
||||
if(field.GetType().FullName != "java.lang.reflect.Field")
|
||||
{
|
||||
throw new ArgumentException("field");
|
||||
}
|
||||
// HACK we use reflection to extract the fieldCookie from the java.lang.reflect.Field object
|
||||
return (FieldWrapper)field.GetType().GetField("fieldCookie", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(field);
|
||||
}
|
||||
|
||||
public static object GetFieldConstantValue(object field)
|
||||
{
|
||||
return GetFieldWrapperFromField(field).GetConstant();
|
||||
}
|
||||
|
||||
public static bool IsFieldDeprecated(object field)
|
||||
{
|
||||
FieldInfo fi = GetFieldWrapperFromField(field).GetField();
|
||||
return fi != null && fi.IsDefined(typeof(ObsoleteAttribute), false);
|
||||
}
|
||||
|
||||
public static bool IsMethodDeprecated(object method)
|
||||
{
|
||||
if(method == null)
|
||||
{
|
||||
throw new ArgumentNullException("method");
|
||||
}
|
||||
if(method.GetType().FullName != "java.lang.reflect.Method")
|
||||
{
|
||||
throw new ArgumentException("method");
|
||||
}
|
||||
// HACK we use reflection to extract the methodCookie from the java.lang.reflect.Method object
|
||||
MethodWrapper mw = (MethodWrapper)method.GetType().GetField("methodCookie", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(method);
|
||||
MethodBase mb = mw.GetMethod();
|
||||
return mb != null && mb.IsDefined(typeof(ObsoleteAttribute), false);
|
||||
}
|
||||
|
||||
public static bool IsConstructorDeprecated(object constructor)
|
||||
{
|
||||
if(constructor == null)
|
||||
{
|
||||
throw new ArgumentNullException("constructor");
|
||||
}
|
||||
if(constructor.GetType().FullName != "java.lang.reflect.Constructor")
|
||||
{
|
||||
throw new ArgumentException("constructor");
|
||||
}
|
||||
// HACK we use reflection to extract the methodCookie from the java.lang.reflect.Constructor object
|
||||
MethodWrapper mw = (MethodWrapper)constructor.GetType().GetField("methodCookie", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(constructor);
|
||||
MethodBase mb = mw.GetMethod();
|
||||
return mb != null && mb.IsDefined(typeof(ObsoleteAttribute), false);
|
||||
}
|
||||
|
||||
public static bool IsClassDeprecated(object clazz)
|
||||
{
|
||||
if(clazz == null)
|
||||
{
|
||||
throw new ArgumentNullException("clazz");
|
||||
}
|
||||
if(clazz.GetType().FullName != "java.lang.Class")
|
||||
{
|
||||
throw new ArgumentException("clazz");
|
||||
}
|
||||
TypeWrapper wrapper = IKVM.NativeCode.java.lang.VMClass.getWrapperFromClass(clazz);
|
||||
return wrapper.TypeAsTBD.IsDefined(typeof(ObsoleteAttribute), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -626,6 +697,11 @@ namespace IKVM.Internal
|
|||
AttributeHelper.SetSourceFile(typeBuilder, IKVM.Internal.MapXml.Root.filename);
|
||||
}
|
||||
|
||||
if(c.Deprecated)
|
||||
{
|
||||
AttributeHelper.SetDeprecatedAttribute(typeBuilder);
|
||||
}
|
||||
|
||||
if(baseIsSealed)
|
||||
{
|
||||
AttributeHelper.SetModifiers(typeBuilder, (Modifiers)c.Modifiers);
|
||||
|
@ -742,11 +818,19 @@ namespace IKVM.Internal
|
|||
AttributeHelper.SetModifiers(mbHelper, (Modifiers)m.Modifiers);
|
||||
AttributeHelper.SetNameSig(mbHelper, "<init>", m.Sig);
|
||||
AddDeclaredExceptions(mbHelper, m.throws);
|
||||
if(m.Deprecated)
|
||||
{
|
||||
AttributeHelper.SetDeprecatedAttribute(mbHelper);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cbCore = typeWrapper.typeBuilder.DefineConstructor(attr, CallingConventions.Standard, paramTypes);
|
||||
AddDeclaredExceptions(cbCore, m.throws);
|
||||
if(m.Deprecated)
|
||||
{
|
||||
AttributeHelper.SetDeprecatedAttribute(cbCore);
|
||||
}
|
||||
}
|
||||
return cbCore;
|
||||
}
|
||||
|
@ -1040,6 +1124,10 @@ namespace IKVM.Internal
|
|||
typeWrapper.typeBuilder.DefineMethodOverride(mbCore, overrideMethod);
|
||||
}
|
||||
AddDeclaredExceptions(mbCore, m.throws);
|
||||
if(m.Deprecated)
|
||||
{
|
||||
AttributeHelper.SetDeprecatedAttribute(mbCore);
|
||||
}
|
||||
}
|
||||
|
||||
if((m.Modifiers & IKVM.Internal.MapXml.MapModifiers.Static) == 0)
|
||||
|
@ -1062,6 +1150,10 @@ namespace IKVM.Internal
|
|||
AttributeHelper.SetModifiers(mbHelper, (Modifiers)m.Modifiers);
|
||||
AttributeHelper.SetNameSig(mbHelper, m.Name, m.Sig);
|
||||
AddDeclaredExceptions(mbHelper, m.throws);
|
||||
if(m.Deprecated)
|
||||
{
|
||||
AttributeHelper.SetDeprecatedAttribute(mbHelper);
|
||||
}
|
||||
}
|
||||
return mbCore;
|
||||
}
|
||||
|
@ -1412,6 +1504,10 @@ namespace IKVM.Internal
|
|||
{
|
||||
AddField(FieldWrapper.Create(this, GetClassLoader().FieldTypeWrapperFromSig(f.Sig), fb, f.Name, f.Sig, (Modifiers)f.Modifiers));
|
||||
}
|
||||
if(f.Deprecated)
|
||||
{
|
||||
AttributeHelper.SetDeprecatedAttribute(fb);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче