You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by mt...@apache.org on 2011/05/05 10:35:50 UTC

svn commit: r1099718 - in /commons/sandbox/runtime/trunk/src/main: java/org/apache/commons/runtime/ java/org/apache/commons/runtime/net/ native/shared/

Author: mturk
Date: Thu May  5 08:35:50 2011
New Revision: 1099718

URL: http://svn.apache.org/viewvc?rev=1099718&view=rev
Log:
Refactor address api. More work to follow

Added:
    commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/LingerOption.java   (with props)
    commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/ProtocolType.java   (with props)
Modified:
    commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/Properties.java
    commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/EndpointAddress.java
    commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/LocalSocketAddress.java
    commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/SocketAddress.java
    commons/sandbox/runtime/trunk/src/main/native/shared/netaddr.c

Modified: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/Properties.java
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/Properties.java?rev=1099718&r1=1099717&r2=1099718&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/Properties.java (original)
+++ commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/Properties.java Thu May  5 08:35:50 2011
@@ -52,7 +52,8 @@ public final class Properties
         instance = new Properties();
     }
 
-    /** Get resource property value.
+    /**
+     * Get resource property value.
      * @param key Resource name to get.
      * @param def Default value in case {@code key} was not found.
      */
@@ -81,18 +82,39 @@ public final class Properties
                 }
             }
         }
+        if (rv == null) {
+            // Try with System properties
+            try {
+                rv = System.getProperty(key);
+            } catch (Exception ex) {
+                // Ignore
+            }
+
+        }
         return rv;
     }
 
     /** Get resource property value.
-     * @param key Resource name to get. In case the propery is not present
-     * this method returns {@code null}.
+     * In case the propery is not present this method returns {@code null}.
+     * 
+     * @param key Resource name to get.
      */
     public static String get(String key)
     {
         return get(key, null);
     }
 
+    /** Get resource property value.
+     * In case the propery is not present or not equat, ignoring case to
+     * the string {@code "true"}, this method returns {@code false}.
+     * 
+     * @param key Resource name to get.
+     */
+    public static boolean getBoolean(String key)
+    {
+        return Boolean.parseBoolean(get(key));
+    }
+
     private static int getI(String key, int def)
     {
         String val = get(key);
@@ -152,6 +174,14 @@ public final class Properties
             return null;
     }
 
+    /** Get resource property values.
+     * <p>
+     * Returns string array with keys that are prefixed
+     * using {@code key.0 ... key.N}
+     * </p>
+     * @param key Resource name to get. In case the propery is not present
+     * this method returns {@code null}.
+     */
     public static String[] getArray(String key, String def)
     {
         String [] rv = getA(key);
@@ -179,7 +209,7 @@ public final class Properties
     public static final String   VERSION_PNAME = getS("runtime.version.pname");
     /** Build Time stamp.
      */
-    public static final String   VERSION_BUILT  = getS("runtime.version.built");
+    public static final String   VERSION_BUILT = getS("runtime.version.built");
     /** Build UUID.
      * <p>
      * Generated at build time ensurig no two builds have the same signature.

Modified: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/EndpointAddress.java
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/EndpointAddress.java?rev=1099718&r1=1099717&r2=1099718&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/EndpointAddress.java (original)
+++ commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/EndpointAddress.java Thu May  5 08:35:50 2011
@@ -18,61 +18,70 @@
 
 package org.apache.commons.runtime.net;
 
-import java.io.File;
-import java.net.SocketException;
 import java.net.SocketAddress;
-import java.net.UnknownHostException;
-import org.apache.commons.runtime.Status;
 
 /**
- * This class represents a socket endpoint described by a IP address and a port
- * number. It is a concrete implementation of {@code SocketAddress} for IP.
+ * This class represents a network address.
  */
 public abstract class EndpointAddress extends SocketAddress
 {
+    private int  family;
+    /**
+     * Native representation of @{code this} address.
+     * This is pointer to acr_sockaddr_t and is directly
+     * used by socket functions.
+     */
+    private long sa;
 
-    private AddressFamily family;
-    protected EndpointAddress()
-    {
-        // No instance
-    }
+    private static native void init0();
+    private static native int  family0(long sa);
+    private static native void free0(long sa);
 
-    protected EndpointAddress(AddressFamily family)
-    {
-        this.family = family;
+    static {
+        init0();
     }
-
     /**
-     * Gets the hostname of this socket.
-     *
-     * @return the socket endpoint hostname.
+     * Creates a new EndpointAddress object.
      */
-    public abstract String getHostName();
-
+    protected EndpointAddress()
+    {
+        this.family = -1;
+    }
+    
     /**
-     * Gets the service name of this socket.
-     *
-     * @return the socket endpoint service name.
+     * Creates a new EndpointAddress object.
+     * @param family The address family to which the endpoint belongs.
      */
-    public abstract String getServiceName();
+    protected EndpointAddress(AddressFamily family)
+    {
+        this.family = family.valueOf();
+    }
 
     /**
-     * Gets the port number of this socket.
-     *
-     * @return the socket endpoint port number.
+     * Get the address family to which the endpoint belongs.
      */
-    public int getPort()
+    public final AddressFamily getFamily()
     {
-        return 0;
+        if (family == -1 && sa != 0L)
+            family = family0(sa);
+        return AddressFamily.valueOf(family);
     }
 
     /**
-     * Gets the {@code AddressFamily} of this socket.
-     *
-     * @return the socket AddressFamily.
+     * Called by the garbage collector when the object is destroyed.
+     * The class will free internal resources allocated by the Operating system.
+     * @see Object#finalize()
+     * @throws Throwable the {@code Exception} raised by this method.
      */
-    public AddressFamily getFamily()
+    @Override
+    protected final void finalize()
+        throws Throwable
     {
-        return family;
+        try {
+            free0(sa);
+        } finally {
+            sa = 0L;
+        }
     }
+    
 }

Added: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/LingerOption.java
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/LingerOption.java?rev=1099718&view=auto
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/LingerOption.java (added)
+++ commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/LingerOption.java Thu May  5 08:35:50 2011
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.runtime.net;
+
+import java.net.SocketAddress;
+
+/**
+ * This class represents a network address.
+ */
+public final class LingerOption
+{
+    private boolean enabled;
+    private int     seconds;
+    private LingerOption()
+    {
+        // No intance
+    }
+
+    /**
+     * Creates a new LingerOption object.
+     * @param enabled Sets a value that indicated whether to linger
+     *          after the {@code Socket} is closed.
+     * @param seconds Sets the amount of time to remain connected after
+     *          closing the {@code Socket} if data remains to be send.
+     */
+    public LingerOption(boolean enabled, int seconds)
+    {
+        this.enabled = enabled;
+        this.seconds = seconds;
+    }
+
+    /**
+     * Sets a value that indicated whether to linger after the {@code Socket}
+     * is closed.
+     */
+    public final void setEnabled(boolean enabled)
+    {
+        this.enabled = enabled;        
+    }
+
+    /**
+     * Gets a value that indicated whether to linger after the {@code Socket}
+     * is closed.
+     */
+    public final boolean getEnabled()
+    {
+        return enabled;
+    }
+
+    /**
+     * Sets the amount of time to remain connected after closing the
+     * {@code Socket} if data remains to be send.
+     */
+    public final void setLingerTime(int seconds)
+    {
+        this.seconds = seconds;
+    }
+
+    /**
+     * Gets the amount of time to remain connected after closing the
+     * {@code Socket} if data remains to be send.
+     */
+    public final int getLingerTime()
+    {
+        return seconds;
+    }
+
+    
+}

Propchange: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/LingerOption.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/LocalSocketAddress.java
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/LocalSocketAddress.java?rev=1099718&r1=1099717&r2=1099718&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/LocalSocketAddress.java (original)
+++ commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/LocalSocketAddress.java Thu May  5 08:35:50 2011
@@ -42,18 +42,25 @@ public final class LocalSocketAddress ex
      * Create a new local socket adrress.
      */
     public LocalSocketAddress(String name)
-        throws SystemException
+        throws SystemException, IllegalArgumentException
     {
-        super(name, AddressFamily.LOCAL);
+        super(AddressFamily.LOCAL);
+        if (name == null)
+            throw new IllegalArgumentException("name can't be null");
+        init(name, AddressFamily.LOCAL);
     }
 
     /**
      * Create a new local socket adrress.
      */
     public LocalSocketAddress(File path)
-        throws SystemException
+        throws SystemException, IllegalArgumentException
     {
-        super(path.getPath(), AddressFamily.LOCAL);
+        super(AddressFamily.LOCAL);
+        String host = path.getPath();
+        if (host == null)
+            throw new IllegalArgumentException("path can't be null");
+        init(host, AddressFamily.LOCAL);
     }
 
 }

Added: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/ProtocolType.java
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/ProtocolType.java?rev=1099718&view=auto
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/ProtocolType.java (added)
+++ commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/ProtocolType.java Thu May  5 08:35:50 2011
@@ -0,0 +1,53 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.runtime.net;
+
+/** Represents the protocol family which will be used for communication.
+ */
+public enum ProtocolType
+{
+    /** Unspecified protocol type */
+    UNSPEC(     0),
+    /** Transmission Control Protocol (TCP). */
+    TCP(        1),
+    /** User Datagrap Protocol */
+    UDP(        2),
+    /** Raw Internet Protocol */
+    IP(         3);
+
+
+    private int value;
+    private ProtocolType(int v)
+    {
+        value = v;
+    }
+
+    public int valueOf()
+    {
+        return value;
+    }
+
+    public static ProtocolType valueOf(int value)
+    {
+        for (ProtocolType e : values()) {
+            if (e.value == value)
+                return e;
+        }
+        return UNSPEC;
+    }
+
+}

Propchange: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/ProtocolType.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/SocketAddress.java
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/SocketAddress.java?rev=1099718&r1=1099717&r2=1099718&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/SocketAddress.java (original)
+++ commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/SocketAddress.java Thu May  5 08:35:50 2011
@@ -45,76 +45,44 @@ public abstract class SocketAddress exte
      */
     private static final int IPV6_ADDR_OK  = 2;
 
-    private static native void    init0();
-    private static native void    free0(long addr);
     /* Structure members */
-    private static native String  hostname0(long addr);
-    private static native String  servname0(long addr);
-    private static native int     port0(long addr);
-    private static native int     family0(long addr);
-
-    private static native String  ipaddr0(long addr);
-    private static native long    geti0(String hostname, int family, int port, int flags)
-        throws SystemException;
-    private static native boolean equals0(long addr1, long addr2);
-
-    /**
-     * Native representation of @{code this} address.
-     * This is pointer to acr_sockaddr_t and is directly
-     * used by socket functions.
-     * 
-     */
-    private long      addr;
-    /**
-     * True if this address has been resolved.
-     */
-    private boolean   resolved;
-
-    static {
-        init0();
-    }
+    private native String  hostname0();
+    private native String  servname0();
+    private native int     port0();
+
+    private native String  ipaddr0();
+    private native int     geti0(String hostname, int family, int port, int flags);
+    private native boolean equals0(SocketAddress other);
 
     /**
      * Creates an new object
      */
     protected SocketAddress()
     {
-        super(AddressFamily.UNSPEC);
     }
 
     /**
      * Creates an new object
      */
-    protected SocketAddress(String host, AddressFamily family, int port, int flags)
-        throws SystemException
+    protected SocketAddress(AddressFamily family)
     {
         super(family);
-        if (host == null && family == AddressFamily.LOCAL)
-            throw new IllegalArgumentException("host can't be null");
-        addr = geti0(host, family.valueOf(), port, flags);
     }
 
-    protected SocketAddress(String host, AddressFamily family)
+    protected void init(String host, AddressFamily family, int port, int flags)
         throws SystemException
     {
-        super(family);
-        if (host == null && family == AddressFamily.LOCAL)
-            throw new IllegalArgumentException("host can't be null");
-        addr = geti0(host, family.valueOf(), 0, 0);
+        int rc = geti0(host, family.valueOf(), port, flags);
+        if (rc != 0)
+            throw new SystemException(Status.describe(rc));
     }
 
-    protected SocketAddress(String host, int port)
+    protected void init(String host, AddressFamily family)
         throws SystemException
     {
-        super(AddressFamily.UNSPEC);
-        addr = geti0(host, 0, port, 0);
-    }
-
-    protected SocketAddress(int port)
-        throws SystemException
-    {
-        super(AddressFamily.UNSPEC);
-        addr = geti0(null, 0, port, 0);
+        int rc = geti0(host, family.valueOf(), 0, 0);
+        if (rc != 0)
+            throw new SystemException(Status.describe(rc));
     }
 
     /**
@@ -122,10 +90,9 @@ public abstract class SocketAddress exte
      *
      * @return the socket endpoint hostname.
      */
-    @Override
     public final String getHostName()
     {
-        return hostname0(addr);
+        return hostname0();
     }
 
     /**
@@ -133,10 +100,9 @@ public abstract class SocketAddress exte
      *
      * @return the socket endpoint service name.
      */
-    @Override
     public final String getServiceName()
     {
-        return servname0(addr);
+        return servname0();
     }
 
     /**
@@ -144,24 +110,9 @@ public abstract class SocketAddress exte
      *
      * @return the socket endpoint port number.
      */
-    @Override
-    public int getPort()
+    public final int getPort()
     {
-        return port0(addr);
-    }
-
-    /**
-     * Gets the {@code AddressFamily} of this socket.
-     *
-     * @return the socket AddressFamily.
-     */
-    @Override
-    public final AddressFamily getFamily()
-    {
-        if (super.getFamily() == AddressFamily.LOCAL)
-            return AddressFamily.LOCAL;
-        else
-            return AddressFamily.valueOf(family0(addr));
+        return port0();
     }
 
     /**
@@ -179,26 +130,10 @@ public abstract class SocketAddress exte
         if (other == this)
             return true;
         if (other instanceof SocketAddress)
-            return equals0(addr, ((SocketAddress)other).addr);
+            return equals0((SocketAddress)other);
         else
            return false;
     }
 
-    /**
-     * Called by the garbage collector when the object is destroyed.
-     * The class will free internal resources allocated by the Operating system.
-     * @see Object#finalize()
-     * @throws Throwable the {@code Exception} raised by this method.
-     */
-    @Override
-    protected void finalize()
-        throws Throwable
-    {
-        try {
-            free0(addr);
-        } finally {
-            addr = 0L;
-        }
-    }
 
 }

Modified: commons/sandbox/runtime/trunk/src/main/native/shared/netaddr.c
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/shared/netaddr.c?rev=1099718&r1=1099717&r2=1099718&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/shared/netaddr.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/shared/netaddr.c Thu May  5 08:35:50 2011
@@ -50,14 +50,14 @@ J_DECLARE_CLAZZ = {
     0,
     0,
     0,
-    ACR_NET_CP "SocketAddress"
+    ACR_NET_CP "EndpointAddress"
 };
 
 J_DECLARE_F_ID(0000) = {
     INVALID_FIELD_OFFSET,
     INVALID_FIELD_OFFSET,
     0,
-    "addr",
+    "sa",
     "J"
 };
 
@@ -752,7 +752,7 @@ AcrGetNameInfo(char **hostname, acr_sock
     return 0;
 }
 
-ACR_NET_EXPORT(void, SocketAddress, init0)(JNI_STDARGS)
+ACR_NET_EXPORT(void, EndpointAddress, init0)(JNI_STDARGS)
 {
     _clazzn.i = (jclass)(*env)->NewGlobalRef(env, obj);
     if (_clazzn.i == 0)
@@ -762,35 +762,92 @@ ACR_NET_EXPORT(void, SocketAddress, init
     _clazzn.u = 1;
 }
 
-ACR_NET_EXPORT(void, SocketAddress, free0)(JNI_STDARGS, jlong sa)
+ACR_NET_EXPORT(void, EndpointAddress, free0)(JNI_STDARGS, jlong sa)
 {
     AcrFreeSockaddr(J2P(sa, acr_sockaddr_t *));
 }
 
-ACR_NET_EXPORT(jstring, SocketAddress, hostname0)(JNI_STDARGS, jlong sa)
+ACR_NET_EXPORT(jint, EndpointAddress, family0)(JNI_STDARGS, jlong sa)
 {
-    acr_sockaddr_t *a = J2P(sa, acr_sockaddr_t *);  
-    if (a->hostname != '\0')
-        return AcrNewJavaStringA(env, a->hostname);
+    acr_sockaddr_t *a = J2P(sa, acr_sockaddr_t *);
+    switch (a->family) {
+        case AF_INET:
+            return 1;
+        case AF_INET6:
+            return 2;
+        case AF_LOCAL:
+            return 3;
+        default:
+        break;
+    }
+    return 0;
+}
+
+static acr_sockaddr_t *ea_sockaddr(JNI_STDARGS)
+{
+    jlong sa = 0;
+
+    if (J4FLD_OFF(0000) != INVALID_FIELD_OFFSET) {
+        char *oa = *(char **)obj;
+        if (oa != 0) {
+            char *fa = (oa + J4FLD_PTR(0000));
+            sa = *((jlong *)fa);
+        }
+    }
+    else if (CLAZZ_LOADED) {
+        sa = GET_IFIELD_J(0000, obj);
+    }
+    return J2P(sa, acr_sockaddr_t *);
+}
+
+static int set_sockaddr(JNI_STDARGS, acr_sockaddr_t *sa)
+{
+    int rc = ACR_EBADF;
+
+    if (J4FLD_OFF(0000) != INVALID_FIELD_OFFSET) {
+        char *oa = *(char **)obj;
+        if (oa != 0) {
+            char *fa = (oa + J4FLD_PTR(0000));
+            *((jlong *)fa) = P2J(sa);
+            rc = 0;
+        }
+    }
+    else if (CLAZZ_LOADED) {
+        SET_IFIELD_P(0000, obj, sa);
+        rc = 0;
+    }
+    return rc;
+}
+
+
+ACR_NET_EXPORT(jstring, SocketAddress, hostname0)(JNI_STDARGS)
+{
+    acr_sockaddr_t *sa = ea_sockaddr(env, obj);  
+    if (sa != 0 && sa->hostname != '\0')
+        return AcrNewJavaStringA(env, sa->hostname);
     else
         return 0;
 }
 
-ACR_NET_EXPORT(jstring, SocketAddress, servname0)(JNI_STDARGS, jlong sa)
+ACR_NET_EXPORT(jstring, SocketAddress, servname0)(JNI_STDARGS)
 {
-    acr_sockaddr_t *a = J2P(sa, acr_sockaddr_t *);
-    if (a->servname != '\0')
-        return AcrNewJavaStringA(env, a->servname);
+    acr_sockaddr_t *sa = ea_sockaddr(env, obj);
+    if (sa != 0 && sa->servname != '\0')
+        return AcrNewJavaStringA(env, sa->servname);
     else
         return 0;
 }
 
-ACR_NET_EXPORT(jstring, SocketAddress, ipaddr0)(JNI_STDARGS, jlong sa)
+ACR_NET_EXPORT(jstring, SocketAddress, ipaddr0)(JNI_STDARGS)
 {
     char buf[256];
-    acr_sockaddr_t *a = J2P(sa, acr_sockaddr_t *);
+    acr_sockaddr_t *sa = ea_sockaddr(env, obj);
 
-    if (AcrGetSockaddrIp(buf, 256, a) == 0)
+    if (sa == 0) {
+        ACR_THROW(ACR_EX_EINVAL, 0);
+        return 0;
+    }
+    if (AcrGetSockaddrIp(buf, 256, sa) == 0)
         return AcrNewJavaStringA(env, buf);
     else {
         ACR_THROW(ACR_EX_ENOMEM, ACR_ENOSPC);
@@ -798,30 +855,18 @@ ACR_NET_EXPORT(jstring, SocketAddress, i
     }
 }
 
-ACR_NET_EXPORT(jint, SocketAddress, port0)(JNI_STDARGS, jlong sa)
+ACR_NET_EXPORT(jint, SocketAddress, port0)(JNI_STDARGS)
 {
-    acr_sockaddr_t *a = J2P(sa, acr_sockaddr_t *);
-    return a->port;
+    acr_sockaddr_t *sa = ea_sockaddr(env, obj);
+    if (sa != 0)
+        return sa->port;
+    else
+        return 0;
 }
 
-ACR_NET_EXPORT(jint, SocketAddress, family0)(JNI_STDARGS, jlong sa)
-{
-    acr_sockaddr_t *a = J2P(sa, acr_sockaddr_t *);
-    switch (a->family) {
-        case AF_INET:
-            return 1;
-        case AF_INET6:
-            return 2;
-        case AF_LOCAL:
-            return 3;
-        default:
-        break;
-    }
-    return 0;
-}
 
-ACR_NET_EXPORT(jlong, SocketAddress, geti0)(JNI_STDARGS, jstring hostname,
-                                                    jint family, jint port, jint flags)
+ACR_NET_EXPORT(jint, SocketAddress, geti0)(JNI_STDARGS, jstring hostname,
+                                           jint family, jint port, jint flags)
 {
     acr_sockaddr_t *sa = 0;
     int ffamily = AF_UNSPEC;
@@ -842,18 +887,18 @@ ACR_NET_EXPORT(jlong, SocketAddress, get
         rc = AcrGetSockaddrInfo(&sa, J2S(hostname), ffamily, port, flags);
     } DONE_WITH_STR(hostname);
 
-    if (rc != 0) {
-        /* XXX: Throw UnknownHostException?
-         */
-        ACR_THROW_BY_ERROR(rc);
-    }
-    return P2J(sa);
+    if (rc == 0)
+        rc = set_sockaddr(env, obj, sa);
+    return rc;
 }
 
-ACR_NET_EXPORT(jboolean, SocketAddress, equals0)(jlong sa1, jlong sa2)
+ACR_NET_EXPORT(jboolean, SocketAddress, equals0)(JNI_STDARGS, jobject sa2)
 {
-    acr_sockaddr_t *addr1 = J2P(sa1, acr_sockaddr_t *);
-    acr_sockaddr_t *addr2 = J2P(sa2, acr_sockaddr_t *);
+    acr_sockaddr_t *addr1 = ea_sockaddr(env, obj);
+    acr_sockaddr_t *addr2 = ea_sockaddr(env, sa2);
+
+    if (addr1 == 0 || addr2 == 0)
+        return JNI_FALSE;
     if (addr1->iplen == addr2->iplen &&
         memcmp(addr1->ipaddr, addr2->ipaddr, addr1->iplen) == 0) {
         return JNI_TRUE;