FileDocCategorySizeDatePackage
SocketPermission.javaAPI DocAndroid 1.5 API17862Wed May 06 22:41:04 BST 2009java.net

SocketPermission

public final class SocketPermission extends Permission implements Serializable
Regulates the access to network operations available through sockets through permissions. A permission consists of a target (a host), and an associated action list. The target should identify the host by either indicating the (possibly wildcarded (eg. {@code .company.com})) DNS style name of the host or its IP address in standard {@code nn.nn.nn.nn} ("dot") notation. The action list can be made up of one or more of the following actions separated by a comma:
connect
requests permission to connect to the host
listen
requests permission to listen for connections from the host
accept
requests permission to accept connections from the host
resolve
requests permission to resolve the hostname
Note that {@code resolve} is implied when any (or none) of the others are present.

Access to a particular port can be requested by appending a colon and a single digit to the name (eg. {@code .company.com:7000}). A range of port numbers can also be specified, by appending a pattern of the form LOW-HIGH where LOW and HIGH are valid port numbers. If either LOW or HIGH is omitted it is equivalent to entering the lowest or highest possible value respectively. For example:

{@code SocketPermission("www.company.com:7000-", "connect,accept")}
represents the permission to connect to and accept connections from {@code www.company.com} on ports in the range {@code 7000} to {@code 65535}.

since
Android 1.0

Fields Summary
private static final long
serialVersionUID
static final int
SP_CONNECT
static final int
SP_LISTEN
static final int
SP_ACCEPT
static final int
SP_RESOLVE
private static final String[]
actionNames
private transient boolean
isPartialWild
private transient boolean
isWild
private static final int
HIGHEST_PORT
private static final int
LOWEST_PORT
transient String
hostName
transient String
ipString
transient boolean
resolved
transient int
portMin
transient int
portMax
private String
actions
transient int
actionsMask
Constructors Summary
public SocketPermission(String host, String action)
Constructs a new {@code SocketPermission} instance. The hostname can be a DNS name, an individual hostname, an IP address or the empty string which implies {@code localhost}. The port or port range is optional.

The action list is a comma-separated list which can consists of the possible operations {@code "connect"}, {@code "listen"}, {@code "accept"} , and {@code "resolve"}. They are case-insensitive and can be put together in any order. {@code "resolve"} is implied per default.

param
host the hostname this permission is valid for.
param
action the action string of this permission.
since
Android 1.0


                                                                                                                                 
         
        super(host.equals("") ? "localhost" : host); //$NON-NLS-1$ //$NON-NLS-2$
        hostName = getHostString(host);
        if (action == null) {
            throw new NullPointerException();
        }
        if (action.equals("")) { //$NON-NLS-1$
            throw new IllegalArgumentException();
        }

        setActions(action);
        actions = toCanonicalActionString(action);
        // Use host since we are only checking for port presence
        parsePort(host, hostName);
    
Methods Summary
booleancheckHost(java.net.SocketPermission sp)
Determines whether or not this permission could refer to the same host as sp.

        if (isPartialWild) {
            if (isWild) {
                return true; // Match on any host
            }
            int length = hostName.length() - 1;
            return sp.hostName.regionMatches(sp.hostName.length() - length,
                    hostName, 1, length);
        }
        // The ipString may not be the same, some hosts resolve to
        // multiple ips
        return (getIPString() != null && ipString.equals(sp.getIPString()))
                || hostName.equals(sp.hostName);
    
public booleanequals(java.lang.Object o)
Compares the argument {@code o} to this instance and returns {@code true} if they represent the same permission using a class specific comparison.

param
o the object to compare with this {@code SocketPermission} instance.
return
{@code true} if they represent the same permission, {@code false} otherwise.
see
#hashCode
since
Android 1.0

        if (this == o) {
            return true;
        }
        if (o == null || this.getClass() != o.getClass()) {
            return false;
        }
        SocketPermission sp = (SocketPermission) o;
        if (!hostName.equals(sp.hostName)) {
            if (getIPString() == null || !ipString.equals(sp.getIPString())) {
                return false;
            }
        }
        if (this.actionsMask != SP_RESOLVE) {
            if (this.portMin != sp.portMin) {
                return false;
            }
            if (this.portMax != sp.portMax) {
                return false;
            }
        }
        return this.actionsMask == sp.actionsMask;
    
public java.lang.StringgetActions()
Gets a comma-separated list of all actions allowed by this permission. If more than one action is returned they follow this order: {@code connect}, {@code listen}, {@code accept}, {@code resolve}.

return
the comma-separated action list.
since
Android 1.0

        return actions;
    
private java.lang.StringgetHostString(java.lang.String host)
Get the host part from the host[:port] one. The host should be host = (hostname | IPv4address | IPv6reference | IPv6 in full uncompressed form) The wildcard "*" may be included once in a DNS name host specification. If it is included, it must be in the leftmost position

param
host
return
throws
IllegalArgumentException if the host is invalid.

        host = host.trim();
        int idx = -1;
        idx = host.indexOf(':");
        isPartialWild = (host.length() > 0 && host.charAt(0) == '*");
        if (isPartialWild) {
            resolved = true;
            isWild = (host.length() == 1);
            if (isWild) {
                return host;
            }
            if (idx > -1) {
                host = host.substring(0, idx);
            }
            return host.toLowerCase();
        }

        int lastIdx = host.lastIndexOf(':");
        
        if (idx == lastIdx) {
            if (-1 != idx) {
                // only one colon, should be port
                host = host.substring(0, idx);
            }
            return host.toLowerCase();
        }
            // maybe ipv6
        boolean isFirstBracket = (host.charAt(0) == '[");
        if (!isFirstBracket) {
            // No bracket, should be in full form
            int colonNum = 0;
            for (int i = 0; i < host.length(); ++i) {
                if (host.charAt(i) == ':") {
                    colonNum++;
                }
            }
            // Get rid of the colon before port
            if (8 == colonNum) {
                host = host.substring(0, lastIdx);
            }
            if (Inet6Util.isIP6AddressInFullForm(host)) {
                return host.toLowerCase();
            }
            throw new IllegalArgumentException(Msg.getString("K004a") + " "
                    + host);
        }
        // forward bracket found
        int bbracketIdx = host.indexOf(']");
        if (-1 == bbracketIdx) {
            // no back bracket found, wrong
            throw new IllegalArgumentException(Msg.getString("K004a") + " "
                    + host);
        }
        host = host.substring(0, bbracketIdx + 1);
        if (Inet6Util.isValidIP6Address(host)) {
            return host.toLowerCase();
        }
        throw new IllegalArgumentException(Msg.getString("K004a") + " " + host);
    
private java.lang.StringgetIPString()

        if (!resolved) {
            try {
                ipString = InetAddress.getHostNameInternal(hostName);
            } catch (UnknownHostException e) {
                // ignore
            }
            resolved = true;
        }
        return ipString;
    
public inthashCode()
Returns the hash value for this {@code SocketPermission} instance. Any two objects which returns {@code true} when passed to {@code equals()} must return the same value as a result of this method.

return
the hashcode value for this instance.
see
#equals
since
Android 1.0

        return hostName.hashCode() ^ actionsMask ^ portMin ^ portMax;
    
public booleanimplies(java.security.Permission p)
Checks whether this {@code SocketPermission} instance allows all actions which are allowed by the given permission object {@code p}. All argument permission actions, hosts and ports must be implied by this permission instance in order to return {@code true}. This permission may imply additional actions not present in the argument permission.

param
p the socket permission which has to be implied by this instance.
return
{@code true} if this permission instance implies all permissions represented by {@code p}, {@code false} otherwise.
since
Android 1.0

        SocketPermission sp;
        try {
            sp = (SocketPermission) p;
        } catch (ClassCastException e) {
            return false;
        }

        // tests if the action list of p is the subset of the one of the
        // receiver
        if (sp == null || (actionsMask & sp.actionsMask) != sp.actionsMask) {
            return false;
        }

        // only check the port range if the action string of the current object
        // is not "resolve"
        if (!p.getActions().equals("resolve")) { //$NON-NLS-1$
            if ((sp.portMin < this.portMin) || (sp.portMax > this.portMax)) {
                return false;
            }
        }

        // Verify the host is valid
        return checkHost(sp);
    
public java.security.PermissionCollectionnewPermissionCollection()
Creates a new {@code PermissionCollection} to store {@code SocketPermission} objects.

return
the new permission collection.
since
Android 1.0

        return new SocketPermissionCollection();
    
private voidparsePort(java.lang.String hostPort, java.lang.String host)
Parse the port, including the minPort, maxPort

param
hostPort the host[:port] one
param
host the host name we just get
throws
IllegalArgumentException If the port is not a positive number or minPort is not less than or equal maxPort

       String port = hostPort.substring(host.length());
       String emptyString = ""; //$NON-NLS-1$

       if (emptyString.equals(port)) {
           // Not specified
           portMin = 80;
           portMax = 80;
           return;
       }
       
       if (":*".equals(port)) {
           // The port range should be 0-65535
           portMin = 0;
           portMax = 65535;
           return;
       }
       
       // Omit ':'
       port = port.substring(1);
       int negIdx = port.indexOf('-");
       String strPortMin = emptyString;
       String strPortMax = emptyString;
       if (-1 == negIdx) {
           // No neg mark, only one number
           strPortMin = port;
           strPortMax = port;
       } else {
           strPortMin = port.substring(0, negIdx);
           strPortMax = port.substring(negIdx + 1);
           if (emptyString.equals(strPortMin)) {
               strPortMin = "0";
           }
           if (emptyString.equals(strPortMax)) {
               strPortMax = "65535";
           }
       }
       try {
           portMin = Integer.valueOf(strPortMin).intValue();
           portMax = Integer.valueOf(strPortMax).intValue();
           
           if (portMin > portMax) {
               throw new IllegalArgumentException(Msg.getString("K0049") + " " + port); //$NON-NLS-1$
           }
       } catch (NumberFormatException e) {
           throw new IllegalArgumentException(Msg.getString("K004a") + " " + port); //$NON-NLS-1$
       }
    
private voidreadObject(java.io.ObjectInputStream stream)

        stream.defaultReadObject();
        // Initialize locals
        isPartialWild = false;
        isWild = false;
        portMin = LOWEST_PORT;
        portMax = HIGHEST_PORT;
        actionsMask = SP_RESOLVE;
        hostName = getHostString(getName());
        parsePort(getName(), hostName);
        setActions(actions);
    
private voidsetActions(java.lang.String actions)
Stores the actions for this permission as a bit field.

param
actions java.lang.String the action list

        if (actions.equals("")) { //$NON-NLS-1$
            return;
        }
        boolean parsing = true;
        String action;
        StringBuffer sb = new StringBuffer();
        int pos = 0, length = actions.length();
        while (parsing) {
            char c;
            sb.setLength(0);
            while (pos < length && (c = actions.charAt(pos++)) != ',") {
                sb.append(c);
            }
            if (pos == length) {
                parsing = false;
            }
            action = sb.toString().trim().toLowerCase();
            if (action.equals(actionNames[SP_CONNECT])) {
                actionsMask |= SP_CONNECT;
            } else if (action.equals(actionNames[SP_LISTEN])) {
                actionsMask |= SP_LISTEN;
            } else if (action.equals(actionNames[SP_ACCEPT])) {
                actionsMask |= SP_ACCEPT;
            } else if (action.equals(actionNames[SP_RESOLVE])) {
                // do nothing
            } else {
                throw new IllegalArgumentException(Msg.getString("K0048", //$NON-NLS-1$
                        action));
            }
        }
    
private java.lang.StringtoCanonicalActionString(java.lang.String action)
Creates a canonical action list.

param
action java.lang.String
return
java.lang.String

        if (action == null || action.equals("") || actionsMask == SP_RESOLVE) { //$NON-NLS-1$
            return actionNames[SP_RESOLVE]; // If none specified return the
        }
        // implied action resolve
        StringBuffer sb = new StringBuffer();
        if ((actionsMask & SP_CONNECT) == SP_CONNECT) {
            sb.append(',");
            sb.append(actionNames[SP_CONNECT]);
        }
        if ((actionsMask & SP_LISTEN) == SP_LISTEN) {
            sb.append(',");
            sb.append(actionNames[SP_LISTEN]);
        }
        if ((actionsMask & SP_ACCEPT) == SP_ACCEPT) {
            sb.append(',");
            sb.append(actionNames[SP_ACCEPT]);
        }
        sb.append(',");
        sb.append(actionNames[SP_RESOLVE]);// Resolve is always implied
        // Don't copy the first ','.
        return actions = sb.substring(1, sb.length());
    
private voidwriteObject(java.io.ObjectOutputStream stream)

        stream.defaultWriteObject();