/*
* Copyright 1990-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 only, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License version 2 for more details (a copy is
* included at /legal/license.txt).
*
* You should have received a copy of the GNU General Public License
* version 2 along with this work; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 or visit www.sun.com if you need additional
* information or have any questions.
*/
package javax.microedition.io;
import java.security.PermissionCollection;
import java.security.Permission;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
/**
* This class represents access rights to connections via the "comm" protocol.
* A <code>CommProtocolPermission</code> consists of a URI string but no
* actions list.
* <p>
* The URI string specifies a logical serial port connection and optional
* parameters. It takes the following form:
* <pre>
* comm:{port identifier}[{optional parameters}]
* </pre>
* An asterisk may appear at the end of the URI string to indicate a
* wildcard match in the <em>port identifer</em> field.
* Valid examples include "comm:*" and "comm:port*".
*
* @see Connector#open
* @see "javax.microedition.io.CommConnection" in <a href="http://www.jcp.org/en/jsr/detail?id=271">MIDP 3.0 Specification</a>
*/
public final class CommProtocolPermission extends GCFPermission {
// A way to create a path normalizer, pass it to superclass ctor and then
// store it to an instance field. It works unless the superclass constructor
// somehow triggers construction of one more subclass instance.
private static final Hashtable map = new Hashtable();
private static PathNormalizer createPathNormalizer() {
CommOptParameterParser p = new CommOptParameterParser();
Thread t = Thread.currentThread();
// NOTE: the mapping can be non-empty at this point if the previous
// ctor invocation was terminated abruptly with an exception thrown
// from superclass ctor. We override the existing mapping.
map.put(t, p);
return p;
}
private static CommOptParameterParser getParser() {
Thread t = Thread.currentThread();
Object o = map.remove(t);
return (CommOptParameterParser)o;
}
private final CommOptParameterParser parser;
/**
* Creates a new <code>CommProtocolPermission</code> with the specified
* URI as its name. The URI string must conform to the specification
* given above.
*
* @param uri the URI string.
*
* @throws IllegalArgumentException if <code>uri</code> is malformed.
* @throws NullPointerException if <code>uri</code> is <code>null</code>.
*
* @see #getName
*/
public CommProtocolPermission(String uri) {
super(uri, false /* requireAuthority */,
null /* portRangeNormalizer */,
CommProtocolPermission.createPathNormalizer());
parser = CommProtocolPermission.getParser();
if (!"comm".equals(getProtocol())) {
throw new IllegalArgumentException("Expected comm protocol: " + uri);
}
String info = getSchemeSpecificPart();
if (info == null || "".equals(info)) {
throw new IllegalArgumentException(
"Expected scheme-specific part: " + uri);
}
}
/**
* Checks if this <code>CommProtocolPermission</code> object "implies"
* the specified permission.
* <p>
* More specifically, this method returns <code>true</code> if:
* <p>
* <ul>
* <li> <i>p</i> is an instanceof <code>CommProtocolPermission</code>, and
* <p>
* <li> <i>p</i>'s URI string equals or (in the case of wildcards) is
* implied by this object's URI string.
* For example, "comm:*" implies "comm:port1;baudrate=300".
* </ul>
* @param p the permission to check against
*
* @return true if the specified permission is implied by this object,
* false if not.
*/
public boolean implies(Permission p) {
if (!(p instanceof CommProtocolPermission)) {
return false;
}
CommProtocolPermission that = (CommProtocolPermission)p;
String thisPart = this.getSchemeSpecificPart();
String thatPart = that.getSchemeSpecificPart();
if (thisPart.equals(thatPart)) {
return true;
}
if (thisPart.endsWith("*")) {
String s = thisPart.substring(0, thisPart.length() - 1);
return thatPart.startsWith(s);
}
if (!this.parser.port.equals(that.parser.port)) {
return false;
}
if (this.parser.baud != -1 && this.parser.baud != that.parser.baud) {
return false;
}
int thisParams =
this.parser.bbc | this.parser.stop | this.parser.parity |
this.parser.rts | this.parser.cts | this.parser.blocking;
int thatParams =
that.parser.bbc | that.parser.stop | that.parser.parity |
that.parser.rts | that.parser.cts | that.parser.blocking;
return (thisParams & thatParams) == thatParams;
}
/**
* Checks two <code>CommProtocolPermission</code> objects for equality.
*
* @param obj the object we are testing for equality with this object.
*
* @return <code>true</code> if <code>obj</code> is a
* <code>CommProtocolPermission</code> and has the same URI string as
* this <code>CommProtocolPermission</code> object.
*/
public boolean equals(Object obj) {
if (!(obj instanceof CommProtocolPermission)) {
return false;
}
CommProtocolPermission other = (CommProtocolPermission)obj;
return other.getURI().equals(getURI());
}
/**
* Returns the hash code value for this object.
*
* @return a hash code value for this object.
*/
public int hashCode() {
return getURI().hashCode();
}
/**
* Returns the canonical string representation of the actions, which
* currently is the empty string "", since there are no actions defined
* for <code>CommProtocolPermission</code>.
*
* @return the empty string "".
*/
public String getActions() {
return "";
}
/**
* Returns a new <code>PermissionCollection</code> for storing
* <code>CommProtocolPermission</code> objects.
* <p>
* <code>CommProtocolPermission</code> objects must be stored in a
* manner that allows
* them to be inserted into the collection in any order, but that also
* enables the <code>PermissionCollection</code> implies method to be
* implemented in an efficient (and consistent) manner.
*
* @return a new <code>PermissionCollection</code> suitable for storing
* <code>CommProtocolPermission</code> objects.
*/
public PermissionCollection newPermissionCollection() {
return new CommProtocolPermissionCollection();
}
}
/**
* A GCFPermissionCollection stores a collection
* of GCFPermission permissions. GCFPermission objects
* must be stored in a manner that allows them to be inserted in any
* order, but enable the implies function to evaluate the implies
* method in an efficient (and consistent) manner.
*
* A GCFPermissionCollection handles comparing a permission like "a.b.c.d.e"
* with a Permission such as "a.b.*", or "*".
*
* @see java.security.Permission
* @see java.security.Permissions
* @see java.security.PermissionsImpl
*
*
*
*/
final class CommProtocolPermissionCollection extends PermissionCollection {
private Vector permissions = new Vector(6);;
/**
* Create an empty GCFPermissionCollection object.
*
*/
public CommProtocolPermissionCollection() {}
/**
* Adds a permission to the GCFPermissions. The key for the hash is
* permission.uri.
*
* @param permission the Permission object to add.
*
* @exception IllegalArgumentException - if the permission is not a
* GCFPermission, or if
* the permission is not of the
* same Class as the other
* permissions in this collection.
*
* @exception SecurityException - if this GCFPermissionCollection object
* has been marked readonly
*/
public void add(Permission permission) {
if (!(permission instanceof CommProtocolPermission)) {
throw new IllegalArgumentException("invalid permission: "+
permission);
}
if (isReadOnly()) {
throw new SecurityException(
"Cannot add a Permission to a readonly PermissionCollection");
}
permissions.addElement(permission);
}
/**
* Check and see if this set of permissions implies the permissions
* expressed in "permission".
*
* @param p the Permission object to compare
*
* @return true if "permission" is a proper subset of a permission in
* the set, false if not.
*/
public boolean implies(Permission permission) {
if (!(permission instanceof CommProtocolPermission)) {
return false;
}
Enumeration search = elements();
while (search.hasMoreElements()) {
CommProtocolPermission p = (CommProtocolPermission)search.nextElement();
if (p.implies(permission)) {
return true;
}
}
return false;
}
/**
* Returns an enumeration of all the GCFPermission objects in the
* container.
*
* @return an enumeration of all the GCFPermission objects.
*/
public Enumeration elements() {
return permissions.elements();
}
}