You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by ri...@apache.org on 2006/03/17 16:43:13 UTC

svn commit: r386660 - in /incubator/felix/trunk/org.osgi/src/main/java/org/osgi/service/permissionadmin: PermissionAdmin.java PermissionInfo.java

Author: rickhall
Date: Fri Mar 17 07:43:12 2006
New Revision: 386660

URL: http://svn.apache.org/viewcvs?rev=386660&view=rev
Log:
Somehow these two files were missed when I updated to the ASL licensed files.

Modified:
    incubator/felix/trunk/org.osgi/src/main/java/org/osgi/service/permissionadmin/PermissionAdmin.java
    incubator/felix/trunk/org.osgi/src/main/java/org/osgi/service/permissionadmin/PermissionInfo.java

Modified: incubator/felix/trunk/org.osgi/src/main/java/org/osgi/service/permissionadmin/PermissionAdmin.java
URL: http://svn.apache.org/viewcvs/incubator/felix/trunk/org.osgi/src/main/java/org/osgi/service/permissionadmin/PermissionAdmin.java?rev=386660&r1=386659&r2=386660&view=diff
==============================================================================
--- incubator/felix/trunk/org.osgi/src/main/java/org/osgi/service/permissionadmin/PermissionAdmin.java (original)
+++ incubator/felix/trunk/org.osgi/src/main/java/org/osgi/service/permissionadmin/PermissionAdmin.java Fri Mar 17 07:43:12 2006
@@ -1,113 +1,121 @@
-/*
- * $Header: /cvshome/build/org.osgi.service.permissionadmin/src/org/osgi/service/permissionadmin/PermissionAdmin.java,v 1.7 2005/05/13 20:33:46 hargrave Exp $
- * 
- * Copyright (c) OSGi Alliance (2001, 2005). All Rights Reserved.
- * 
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this 
- * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html.
- */
-
-package org.osgi.service.permissionadmin;
-
-/**
- * The Permission Admin service allows management agents to manage the
- * permissions of bundles. There is at most one Permission Admin service present
- * in the OSGi environment.
- * <p>
- * Access to the Permission Admin service is protected by corresponding
- * <code>ServicePermission</code>. In addition <code>AdminPermission</code> is
- * required to actually set permissions.
- * 
- * <p>
- * Bundle permissions are managed using a permission table. A bundle's location
- * serves as the key into this permission table. The value of a table entry is
- * the set of permissions (of type <code>PermissionInfo</code>) granted to the
- * bundle named by the given location. A bundle may have an entry in the
- * permission table prior to being installed in the Framework.
- * 
- * <p>
- * The permissions specified in <code>setDefaultPermissions</code> are used as the
- * default permissions which are granted to all bundles that do not have an
- * entry in the permission table.
- * 
- * <p>
- * Any changes to a bundle's permissions in the permission table will take
- * effect no later than when bundle's <code>java.security.ProtectionDomain</code>
- * is next involved in a permission check, and will be made persistent.
- * 
- * <p>
- * Only permission classes on the system classpath or from an exported package
- * are considered during a permission check. Additionally, only permission
- * classes that are subclasses of <code>java.security.Permission</code> and define
- * a 2-argument constructor that takes a <i>name </i> string and an <i>actions
- * </i> string can be used.
- * <p>
- * Permissions implicitly granted by the Framework (for example, a bundle's
- * permission to access its persistent storage area) cannot be changed, and are
- * not reflected in the permissions returned by <code>getPermissions</code> and
- * <code>getDefaultPermissions</code>.
- * 
- * @version $Revision: 1.7 $
- */
-public interface PermissionAdmin {
-	/**
-	 * Gets the permissions assigned to the bundle with the specified location.
-	 * 
-	 * @param location The location of the bundle whose permissions are to be
-	 *        returned.
-	 * 
-	 * @return The permissions assigned to the bundle with the specified
-	 *         location, or <code>null</code> if that bundle has not been assigned
-	 *         any permissions.
-	 */
-	PermissionInfo[] getPermissions(String location);
-
-	/**
-	 * Assigns the specified permissions to the bundle with the specified
-	 * location.
-	 * 
-	 * @param location The location of the bundle that will be assigned the
-	 *        permissions.
-	 * @param permissions The permissions to be assigned, or <code>null</code> if
-	 *        the specified location is to be removed from the permission table.
-	 * @exception SecurityException if the caller does not have the
-	 *            <code>AdminPermission</code>.
-	 */
-	void setPermissions(String location, PermissionInfo[] permissions);
-
-	/**
-	 * Returns the bundle locations that have permissions assigned to them, that
-	 * is, bundle locations for which an entry exists in the permission table.
-	 * 
-	 * @return The locations of bundles that have been assigned any permissions,
-	 *         or <code>null</code> if the permission table is empty.
-	 */
-	String[] getLocations();
-
-	/**
-	 * Gets the default permissions.
-	 * 
-	 * <p>
-	 * These are the permissions granted to any bundle that does not have
-	 * permissions assigned to its location.
-	 * 
-	 * @return The default permissions, or <code>null</code> if no default
-	 *         permissions are set.
-	 */
-	PermissionInfo[] getDefaultPermissions();
-
-	/**
-	 * Sets the default permissions.
-	 * 
-	 * <p>
-	 * These are the permissions granted to any bundle that does not have
-	 * permissions assigned to its location.
-	 * 
-	 * @param permissions The default permissions, or <code>null</code> if the
-	 *        default permissions are to be removed from the permission table.
-	 * @exception SecurityException if the caller does not have the
-	 *            <code>AdminPermission</code>.
-	 */
-	void setDefaultPermissions(PermissionInfo[] permissions);
+/*
+ * $Header: /cvshome/build/org.osgi.service.permissionadmin/src/org/osgi/service/permissionadmin/PermissionAdmin.java,v 1.11 2006/03/14 01:21:28 hargrave Exp $
+ * 
+ * Copyright (c) OSGi Alliance (2001, 2005). All Rights Reserved.
+ * 
+ * Licensed 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.osgi.service.permissionadmin;
+
+/**
+ * The Permission Admin service allows management agents to manage the
+ * permissions of bundles. There is at most one Permission Admin service present
+ * in the OSGi environment.
+ * <p>
+ * Access to the Permission Admin service is protected by corresponding
+ * <code>ServicePermission</code>. In addition <code>AdminPermission</code> is
+ * required to actually set permissions.
+ * 
+ * <p>
+ * Bundle permissions are managed using a permission table. A bundle's location
+ * serves as the key into this permission table. The value of a table entry is
+ * the set of permissions (of type <code>PermissionInfo</code>) granted to the
+ * bundle named by the given location. A bundle may have an entry in the
+ * permission table prior to being installed in the Framework.
+ * 
+ * <p>
+ * The permissions specified in <code>setDefaultPermissions</code> are used as the
+ * default permissions which are granted to all bundles that do not have an
+ * entry in the permission table.
+ * 
+ * <p>
+ * Any changes to a bundle's permissions in the permission table will take
+ * effect no later than when bundle's <code>java.security.ProtectionDomain</code>
+ * is next involved in a permission check, and will be made persistent.
+ * 
+ * <p>
+ * Only permission classes on the system classpath or from an exported package
+ * are considered during a permission check. Additionally, only permission
+ * classes that are subclasses of <code>java.security.Permission</code> and define
+ * a 2-argument constructor that takes a <i>name </i> string and an <i>actions
+ * </i> string can be used.
+ * <p>
+ * Permissions implicitly granted by the Framework (for example, a bundle's
+ * permission to access its persistent storage area) cannot be changed, and are
+ * not reflected in the permissions returned by <code>getPermissions</code> and
+ * <code>getDefaultPermissions</code>.
+ * 
+ * @version $Revision: 1.11 $
+ */
+public interface PermissionAdmin {
+	/**
+	 * Gets the permissions assigned to the bundle with the specified location.
+	 * 
+	 * @param location The location of the bundle whose permissions are to be
+	 *        returned.
+	 * 
+	 * @return The permissions assigned to the bundle with the specified
+	 *         location, or <code>null</code> if that bundle has not been assigned
+	 *         any permissions.
+	 */
+	PermissionInfo[] getPermissions(String location);
+
+	/**
+	 * Assigns the specified permissions to the bundle with the specified
+	 * location.
+	 * 
+	 * @param location The location of the bundle that will be assigned the
+	 *        permissions.
+	 * @param permissions The permissions to be assigned, or <code>null</code> if
+	 *        the specified location is to be removed from the permission table.
+	 * @throws SecurityException If the caller does not have
+	 *            <code>AllPermission</code>.
+	 */
+	void setPermissions(String location, PermissionInfo[] permissions);
+
+	/**
+	 * Returns the bundle locations that have permissions assigned to them, that
+	 * is, bundle locations for which an entry exists in the permission table.
+	 * 
+	 * @return The locations of bundles that have been assigned any permissions,
+	 *         or <code>null</code> if the permission table is empty.
+	 */
+	String[] getLocations();
+
+	/**
+	 * Gets the default permissions.
+	 * 
+	 * <p>
+	 * These are the permissions granted to any bundle that does not have
+	 * permissions assigned to its location.
+	 * 
+	 * @return The default permissions, or <code>null</code> if no default
+	 *         permissions are set.
+	 */
+	PermissionInfo[] getDefaultPermissions();
+
+	/**
+	 * Sets the default permissions.
+	 * 
+	 * <p>
+	 * These are the permissions granted to any bundle that does not have
+	 * permissions assigned to its location.
+	 * 
+	 * @param permissions The default permissions, or <code>null</code> if the
+	 *        default permissions are to be removed from the permission table.
+	 * @throws SecurityException If the caller does not have
+	 *            <code>AllPermission</code>.
+	 */
+	void setDefaultPermissions(PermissionInfo[] permissions);
 }

Modified: incubator/felix/trunk/org.osgi/src/main/java/org/osgi/service/permissionadmin/PermissionInfo.java
URL: http://svn.apache.org/viewcvs/incubator/felix/trunk/org.osgi/src/main/java/org/osgi/service/permissionadmin/PermissionInfo.java?rev=386660&r1=386659&r2=386660&view=diff
==============================================================================
--- incubator/felix/trunk/org.osgi/src/main/java/org/osgi/service/permissionadmin/PermissionInfo.java (original)
+++ incubator/felix/trunk/org.osgi/src/main/java/org/osgi/service/permissionadmin/PermissionInfo.java Fri Mar 17 07:43:12 2006
@@ -1,360 +1,406 @@
-/*
- * $Header: /cvshome/build/org.osgi.service.permissionadmin/src/org/osgi/service/permissionadmin/PermissionInfo.java,v 1.8 2005/06/21 15:41:57 hargrave Exp $
- * 
- * Copyright (c) OSGi Alliance (2001, 2005). All Rights Reserved.
- * 
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this 
- * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html.
- */
-
-package org.osgi.service.permissionadmin;
-
-/**
- * Permission representation used by the Permission Admin service.
- * 
- * <p>
- * This class encapsulates three pieces of information: a Permission <i>type
- * </i> (class name), which must be a subclass of
- * <code>java.security.Permission</code>, and the <i>name </i> and <i>actions
- * </i> arguments passed to its constructor.
- * 
- * <p>
- * In order for a permission represented by a <code>PermissionInfo</code> to be
- * instantiated and considered during a permission check, its Permission class
- * must be available from the system classpath or an exported package. This
- * means that the instantiation of a permission represented by a
- * <code>PermissionInfo</code> may be delayed until the package containing its
- * Permission class has been exported by a bundle.
- * 
- * @version $Revision: 1.8 $
- */
-public class PermissionInfo {
-	private String	type;
-	private String	name;
-	private String	actions;
-
-	/**
-	 * Constructs a <code>PermissionInfo</code> from the given type, name, and
-	 * actions.
-	 * 
-	 * @param type The fully qualified class name of the permission represented
-	 *        by this <code>PermissionInfo</code>. The class must be a subclass
-	 *        of <code>java.security.Permission</code> and must define a
-	 *        2-argument constructor that takes a <i>name </i> string and an
-	 *        <i>actions </i> string.
-	 * 
-	 * @param name The permission name that will be passed as the first argument
-	 *        to the constructor of the <code>Permission</code> class identified
-	 *        by <code>type</code>.
-	 * 
-	 * @param actions The permission actions that will be passed as the second
-	 *        argument to the constructor of the <code>Permission</code> class
-	 *        identified by <code>type</code>.
-	 * 
-	 * @exception java.lang.NullPointerException if <code>type</code> is
-	 *            <code>null</code>.
-	 * @exception java.lang.IllegalArgumentException if <code>action</code> is not
-	 *            <code>null</code> and <code>name</code> is <code>null</code>.
-	 */
-	public PermissionInfo(String type, String name, String actions) {
-		this.type = type;
-		this.name = name;
-		this.actions = actions;
-		if (type == null) {
-			throw new NullPointerException("type is null");
-		}
-		if ((name == null) && (actions != null)) {
-			throw new IllegalArgumentException("name missing");
-		}
-	}
-
-	/**
-	 * Constructs a <code>PermissionInfo</code> object from the given encoded
-	 * <code>PermissionInfo</code> string.
-	 * 
-	 * @param encodedPermission The encoded <code>PermissionInfo</code>.
-	 * @see #getEncoded
-	 * @exception java.lang.IllegalArgumentException if
-	 *            <code>encodedPermission</code> is not properly formatted.
-	 */
-	public PermissionInfo(String encodedPermission) {
-		if (encodedPermission == null) {
-			throw new NullPointerException("missing encoded permission");
-		}
-		if (encodedPermission.length() == 0) {
-			throw new IllegalArgumentException("empty encoded permission");
-		}
-		try {
-			char[] encoded = encodedPermission.toCharArray();
-			/* the first character must be '(' */
-			if (encoded[0] != '(') {
-				throw new IllegalArgumentException(
-						"first character not open parenthesis");
-			}
-			/* type is not quoted or encoded */
-			int end = 1;
-			int begin = end;
-			while ((encoded[end] != ' ') && (encoded[end] != ')')) {
-				end++;
-			}
-			if (end == begin) {
-				throw new IllegalArgumentException("expecting type");
-			}
-			this.type = new String(encoded, begin, end - begin);
-			/* type may be followed by name which is quoted and encoded */
-			// TODO Need to support multiple spaces
-			if (encoded[end] == ' ') {
-				end++;
-				if (encoded[end] != '"') {
-					throw new IllegalArgumentException("expecting quoted name");
-				}
-				end++;
-				begin = end;
-				while (encoded[end] != '"') {
-					if (encoded[end] == '\\') {
-						end++;
-					}
-					end++;
-				}
-				this.name = decodeString(encoded, begin, end);
-				end++;
-				/* name may be followed by actions which is quoted and encoded */
-				// TODO Need to support multiple spaces
-				if (encoded[end] == ' ') {
-					end++;
-					if (encoded[end] != '"') {
-						throw new IllegalArgumentException(
-								"expecting quoted actions");
-					}
-					end++;
-					begin = end;
-					while (encoded[end] != '"') {
-						if (encoded[end] == '\\') {
-							end++;
-						}
-						end++;
-					}
-					this.actions = decodeString(encoded, begin, end);
-					end++;
-				}
-			}
-			/* the final character must be ')' */
-			if ((encoded[end] != ')') || (end + 1 != encoded.length)) {
-				throw new IllegalArgumentException("last character not "
-						+ "close parenthesis");
-			}
-		}
-		catch (ArrayIndexOutOfBoundsException e) {
-			throw new IllegalArgumentException("parsing terminated abruptly");
-		}
-	}
-
-	/**
-	 * Returns the string encoding of this <code>PermissionInfo</code> in a form
-	 * suitable for restoring this <code>PermissionInfo</code>.
-	 * 
-	 * <p>
-	 * The encoded format is:
-	 * 
-	 * <pre>
-	 * (type)
-	 * </pre>
-	 * 
-	 * or
-	 * 
-	 * <pre>
-	 * (type &quot;name&quot;)
-	 * </pre>
-	 * 
-	 * or
-	 * 
-	 * <pre>
-	 * (type &quot;name&quot; &quot;actions&quot;)
-	 * </pre>
-	 * 
-	 * where <i>name</i> and <i>actions</i> are strings that are encoded for
-	 * proper parsing. Specifically, the <code>"</code>,<code>\</code>, carriage
-	 * return, and linefeed characters are escaped using <code>\"</code>,
-	 * <code>\\</code>,<code>\r</code>, and <code>\n</code>, respectively.
-	 * 
-	 * <p>
-	 * The encoded string must contain no leading or trailing whitespace
-	 * characters. A single space character must be used between <i>type</i> and 
-	 * &quot;<i>name</i>&quot; and between &quot;<i>name</i>&quot; and &quot;<i>actions</i>&quot;.
-	 * 
-	 * @return The string encoding of this <code>PermissionInfo</code>.
-	 */
-	public final String getEncoded() {
-		StringBuffer output = new StringBuffer(
-				8
-						+ type.length()
-						+ ((((name == null) ? 0 : name.length()) + ((actions == null) ? 0
-								: actions.length())) << 1));
-		output.append('(');
-		output.append(type);
-		if (name != null) {
-			output.append(" \"");
-			encodeString(name, output);
-			if (actions != null) {
-				output.append("\" \"");
-				encodeString(actions, output);
-			}
-			output.append('\"');
-		}
-		output.append(')');
-		return (output.toString());
-	}
-
-	/**
-	 * Returns the string representation of this <code>PermissionInfo</code>. The
-	 * string is created by calling the <code>getEncoded</code> method on this
-	 * <code>PermissionInfo</code>.
-	 * 
-	 * @return The string representation of this <code>PermissionInfo</code>.
-	 */
-	public String toString() {
-		return (getEncoded());
-	}
-
-	/**
-	 * Returns the fully qualified class name of the permission represented by
-	 * this <code>PermissionInfo</code>.
-	 * 
-	 * @return The fully qualified class name of the permission represented by
-	 *         this <code>PermissionInfo</code>.
-	 */
-	public final String getType() {
-		return (type);
-	}
-
-	/**
-	 * Returns the name of the permission represented by this
-	 * <code>PermissionInfo</code>.
-	 * 
-	 * @return The name of the permission represented by this
-	 *         <code>PermissionInfo</code>, or <code>null</code> if the permission
-	 *         does not have a name.
-	 */
-	public final String getName() {
-		return (name);
-	}
-
-	/**
-	 * Returns the actions of the permission represented by this
-	 * <code>PermissionInfo</code>.
-	 * 
-	 * @return The actions of the permission represented by this
-	 *         <code>PermissionInfo</code>, or <code>null</code> if the permission
-	 *         does not have any actions associated with it.
-	 */
-	public final String getActions() {
-		return (actions);
-	}
-
-	/**
-	 * Determines the equality of two <code>PermissionInfo</code> objects.
-	 * 
-	 * This method checks that specified object has the same type, name and
-	 * actions as this <code>PermissionInfo</code> object.
-	 * 
-	 * @param obj The object to test for equality with this
-	 *        <code>PermissionInfo</code> object.
-	 * @return <code>true</code> if <code>obj</code> is a <code>PermissionInfo</code>,
-	 *         and has the same type, name and actions as this
-	 *         <code>PermissionInfo</code> object; <code>false</code> otherwise.
-	 */
-	public boolean equals(Object obj) {
-		if (obj == this) {
-			return (true);
-		}
-		if (!(obj instanceof PermissionInfo)) {
-			return (false);
-		}
-		PermissionInfo other = (PermissionInfo) obj;
-		if (!type.equals(other.type) || ((name == null) ^ (other.name == null))
-				|| ((actions == null) ^ (other.actions == null))) {
-			return (false);
-		}
-		if (name != null) {
-			if (actions != null) {
-				return (name.equals(other.name) && actions
-						.equals(other.actions));
-			}
-			else {
-				return (name.equals(other.name));
-			}
-		}
-		else {
-			return (true);
-		}
-	}
-
-	/**
-	 * Returns the hash code value for this object.
-	 * 
-	 * @return A hash code value for this object.
-	 */
-	public int hashCode() {
-		int hash = type.hashCode();
-		if (name != null) {
-			hash ^= name.hashCode();
-			if (actions != null) {
-				hash ^= actions.hashCode();
-			}
-		}
-		return (hash);
-	}
-
-	/**
-	 * This escapes the quotes, backslashes, \n, and \r in the string using a
-	 * backslash and appends the newly escaped string to a StringBuffer.
-	 */
-	private static void encodeString(String str, StringBuffer output) {
-		int len = str.length();
-		for (int i = 0; i < len; i++) {
-			char c = str.charAt(i);
-			switch (c) {
-				case '"' :
-				case '\\' :
-					output.append('\\');
-					output.append(c);
-					break;
-				case '\r' :
-					output.append("\\r");
-					break;
-				case '\n' :
-					output.append("\\n");
-					break;
-				default :
-					output.append(c);
-					break;
-			}
-		}
-	}
-
-	/**
-	 * Takes an encoded character array and decodes it into a new String.
-	 */
-	private static String decodeString(char[] str, int begin, int end) {
-		StringBuffer output = new StringBuffer(end - begin);
-		for (int i = begin; i < end; i++) {
-			char c = str[i];
-			if (c == '\\') {
-				i++;
-				if (i < end) {
-					c = str[i];
-					if (c == 'n') {
-						c = '\n';
-					}
-					else
-						if (c == 'r') {
-							c = '\r';
-						}
-				}
-			}
-			output.append(c);
-		}
-		return (output.toString());
-	}
+/*
+ * $Header: /cvshome/build/org.osgi.service.permissionadmin/src/org/osgi/service/permissionadmin/PermissionInfo.java,v 1.15 2006/03/14 01:21:28 hargrave Exp $
+ * 
+ * Copyright (c) OSGi Alliance (2001, 2005). All Rights Reserved.
+ * 
+ * Licensed 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.osgi.service.permissionadmin;
+
+/**
+ * Permission representation used by the Permission Admin service.
+ * 
+ * <p>
+ * This class encapsulates three pieces of information: a Permission <i>type
+ * </i> (class name), which must be a subclass of
+ * <code>java.security.Permission</code>, and the <i>name </i> and <i>actions
+ * </i> arguments passed to its constructor.
+ * 
+ * <p>
+ * In order for a permission represented by a <code>PermissionInfo</code> to be
+ * instantiated and considered during a permission check, its Permission class
+ * must be available from the system classpath or an exported package. This
+ * means that the instantiation of a permission represented by a
+ * <code>PermissionInfo</code> may be delayed until the package containing its
+ * Permission class has been exported by a bundle.
+ * 
+ * @version $Revision: 1.15 $
+ */
+public class PermissionInfo {
+	private String	type;
+	private String	name;
+	private String	actions;
+
+	/**
+	 * Constructs a <code>PermissionInfo</code> from the specified type, name, and
+	 * actions.
+	 * 
+	 * @param type The fully qualified class name of the permission represented
+	 *        by this <code>PermissionInfo</code>. The class must be a subclass
+	 *        of <code>java.security.Permission</code> and must define a
+	 *        2-argument constructor that takes a <i>name </i> string and an
+	 *        <i>actions </i> string.
+	 * 
+	 * @param name The permission name that will be passed as the first argument
+	 *        to the constructor of the <code>Permission</code> class identified
+	 *        by <code>type</code>.
+	 * 
+	 * @param actions The permission actions that will be passed as the second
+	 *        argument to the constructor of the <code>Permission</code> class
+	 *        identified by <code>type</code>.
+	 * 
+	 * @throws java.lang.NullPointerException if <code>type</code> is
+	 *            <code>null</code>.
+	 * @throws java.lang.IllegalArgumentException if <code>action</code> is not
+	 *            <code>null</code> and <code>name</code> is <code>null</code>.
+	 */
+	public PermissionInfo(String type, String name, String actions) {
+		this.type = type;
+		this.name = name;
+		this.actions = actions;
+		if (type == null) {
+			throw new NullPointerException("type is null");
+		}
+		if ((name == null) && (actions != null)) {
+			throw new IllegalArgumentException("name missing");
+		}
+	}
+
+	/**
+	 * Constructs a <code>PermissionInfo</code> object from the specified encoded
+	 * <code>PermissionInfo</code> string. White space in the encoded
+	 * <code>PermissionInfo</code> string is ignored.
+	 * 
+	 * 
+	 * @param encodedPermission The encoded <code>PermissionInfo</code>.
+	 * @see #getEncoded
+	 * @throws java.lang.IllegalArgumentException If the 
+	 *            <code>encodedPermission</code> is not properly formatted.
+	 */
+	public PermissionInfo(String encodedPermission) {
+		if (encodedPermission == null) {
+			throw new NullPointerException("missing encoded permission");
+		}
+		if (encodedPermission.length() == 0) {
+			throw new IllegalArgumentException("empty encoded permission");
+		}
+		try {
+			char[] encoded = encodedPermission.toCharArray();
+			int length = encoded.length;
+			int pos = 0;
+			
+			/* skip whitespace */
+			while (Character.isWhitespace(encoded[pos])) {
+				pos++;
+			}
+			
+			/* the first character must be '(' */
+			if (encoded[pos] != '(') {
+				throw new IllegalArgumentException(
+						"expecting open parenthesis");
+			}
+			pos++;
+
+			/* skip whitespace */
+			while (Character.isWhitespace(encoded[pos])) {
+				pos++;
+			}
+			
+			/* type is not quoted or encoded */
+			int begin = pos;
+			while (!Character.isWhitespace(encoded[pos]) && (encoded[pos] != ')')) {
+				pos++;
+			}
+			if (pos == begin || encoded[begin] == '"') {
+				throw new IllegalArgumentException("expecting type");
+			}
+			this.type = new String(encoded, begin, pos - begin);
+			
+			/* skip whitespace */
+			while (Character.isWhitespace(encoded[pos])) {
+				pos++;
+			}
+			
+			/* type may be followed by name which is quoted and encoded */
+			if (encoded[pos] == '"') {
+				pos++;
+				begin = pos;
+				while (encoded[pos] != '"') {
+					if (encoded[pos] == '\\') {
+						pos++;
+					}
+					pos++;
+				}
+				this.name = unescapeString(encoded, begin, pos);
+				pos++;
+
+				if (Character.isWhitespace(encoded[pos])) {
+					/* skip whitespace */
+					while (Character.isWhitespace(encoded[pos])) {
+						pos++;
+					}
+					
+					/* name may be followed by actions which is quoted and encoded */
+					if (encoded[pos] == '"') {
+						pos++;
+						begin = pos;
+						while (encoded[pos] != '"') {
+							if (encoded[pos] == '\\') {
+								pos++;
+							}
+							pos++;
+						}
+						this.actions = unescapeString(encoded, begin, pos);
+						pos++;
+
+						/* skip whitespace */
+						while (Character.isWhitespace(encoded[pos])) {
+							pos++;
+						}
+					}
+				}
+			}
+			
+			/* the final character must be ')' */
+			char c = encoded[pos];
+			pos++;
+			while ((pos < length) && Character.isWhitespace(encoded[pos])) {
+				pos++;
+			}
+			if ((c != ')') || (pos != length)) {
+				throw new IllegalArgumentException("expecting close parenthesis");
+			}
+		}
+		catch (ArrayIndexOutOfBoundsException e) {
+			throw new IllegalArgumentException("parsing terminated abruptly");
+		}
+	}
+
+	/**
+	 * Returns the string encoding of this <code>PermissionInfo</code> in a form
+	 * suitable for restoring this <code>PermissionInfo</code>.
+	 * 
+	 * <p>
+	 * The encoded format is:
+	 * 
+	 * <pre>
+	 * (type)
+	 * </pre>
+	 * 
+	 * or
+	 * 
+	 * <pre>
+	 * (type &quot;name&quot;)
+	 * </pre>
+	 * 
+	 * or
+	 * 
+	 * <pre>
+	 * (type &quot;name&quot; &quot;actions&quot;)
+	 * </pre>
+	 * 
+	 * where <i>name</i> and <i>actions</i> are strings that are encoded for
+	 * proper parsing. Specifically, the <code>"</code>,<code>\</code>, carriage
+	 * return, and linefeed characters are escaped using <code>\"</code>,
+	 * <code>\\</code>,<code>\r</code>, and <code>\n</code>, respectively.
+	 * 
+	 * <p>
+	 * The encoded string contains no leading or trailing whitespace
+	 * characters. A single space character is used between <i>type</i> and 
+	 * &quot;<i>name</i>&quot; and between &quot;<i>name</i>&quot; and &quot;<i>actions</i>&quot;.
+	 * 
+	 * @return The string encoding of this <code>PermissionInfo</code>.
+	 */
+	public final String getEncoded() {
+		StringBuffer output = new StringBuffer(
+				8
+						+ type.length()
+						+ ((((name == null) ? 0 : name.length()) + ((actions == null) ? 0
+								: actions.length())) << 1));
+		output.append('(');
+		output.append(type);
+		if (name != null) {
+			output.append(" \"");
+			escapeString(name, output);
+			if (actions != null) {
+				output.append("\" \"");
+				escapeString(actions, output);
+			}
+			output.append('\"');
+		}
+		output.append(')');
+		return output.toString();
+	}
+
+	/**
+	 * Returns the string representation of this <code>PermissionInfo</code>. The
+	 * string is created by calling the <code>getEncoded</code> method on this
+	 * <code>PermissionInfo</code>.
+	 * 
+	 * @return The string representation of this <code>PermissionInfo</code>.
+	 */
+	public String toString() {
+		return getEncoded();
+	}
+
+	/**
+	 * Returns the fully qualified class name of the permission represented by
+	 * this <code>PermissionInfo</code>.
+	 * 
+	 * @return The fully qualified class name of the permission represented by
+	 *         this <code>PermissionInfo</code>.
+	 */
+	public final String getType() {
+		return type;
+	}
+
+	/**
+	 * Returns the name of the permission represented by this
+	 * <code>PermissionInfo</code>.
+	 * 
+	 * @return The name of the permission represented by this
+	 *         <code>PermissionInfo</code>, or <code>null</code> if the permission
+	 *         does not have a name.
+	 */
+	public final String getName() {
+		return name;
+	}
+
+	/**
+	 * Returns the actions of the permission represented by this
+	 * <code>PermissionInfo</code>.
+	 * 
+	 * @return The actions of the permission represented by this
+	 *         <code>PermissionInfo</code>, or <code>null</code> if the permission
+	 *         does not have any actions associated with it.
+	 */
+	public final String getActions() {
+		return actions;
+	}
+
+	/**
+	 * Determines the equality of two <code>PermissionInfo</code> objects.
+	 * 
+	 * This method checks that specified object has the same type, name and
+	 * actions as this <code>PermissionInfo</code> object.
+	 * 
+	 * @param obj The object to test for equality with this
+	 *        <code>PermissionInfo</code> object.
+	 * @return <code>true</code> if <code>obj</code> is a <code>PermissionInfo</code>,
+	 *         and has the same type, name and actions as this
+	 *         <code>PermissionInfo</code> object; <code>false</code> otherwise.
+	 */
+	public boolean equals(Object obj) {
+		if (obj == this) {
+			return true;
+		}
+		if (!(obj instanceof PermissionInfo)) {
+			return false;
+		}
+		PermissionInfo other = (PermissionInfo) obj;
+		if (!type.equals(other.type) || ((name == null) ^ (other.name == null))
+				|| ((actions == null) ^ (other.actions == null))) {
+			return false;
+		}
+		if (name != null) {
+			if (actions != null) {
+				return name.equals(other.name) && actions
+						.equals(other.actions);
+			}
+			else {
+				return name.equals(other.name);
+			}
+		}
+		else {
+			return true;
+		}
+	}
+
+	/**
+	 * Returns the hash code value for this object.
+	 * 
+	 * @return A hash code value for this object.
+	 */
+	public int hashCode() {
+		int hash = type.hashCode();
+		if (name != null) {
+			hash ^= name.hashCode();
+			if (actions != null) {
+				hash ^= actions.hashCode();
+			}
+		}
+		return hash;
+	}
+
+	/**
+	 * This escapes the quotes, backslashes, \n, and \r in the string using a
+	 * backslash and appends the newly escaped string to a StringBuffer.
+	 */
+	private static void escapeString(String str, StringBuffer output) {
+		int len = str.length();
+		for (int i = 0; i < len; i++) {
+			char c = str.charAt(i);
+			switch (c) {
+				case '"' :
+				case '\\' :
+					output.append('\\');
+					output.append(c);
+					break;
+				case '\r' :
+					output.append("\\r");
+					break;
+				case '\n' :
+					output.append("\\n");
+					break;
+				default :
+					output.append(c);
+					break;
+			}
+		}
+	}
+
+	/**
+	 * Takes an encoded character array and decodes it into a new String.
+	 */
+	private static String unescapeString(char[] str, int begin, int end) {
+		StringBuffer output = new StringBuffer(end - begin);
+		for (int i = begin; i < end; i++) {
+			char c = str[i];
+			if (c == '\\') {
+				i++;
+				if (i < end) {
+					c = str[i];
+					switch (c) {
+						case '"' :
+						case '\\' :
+							break;
+						case 'r' :
+							c = '\r';
+							break;
+						case 'n' :
+							c = '\n';
+							break;
+						default :
+							c = '\\';
+							i--;
+							break;
+					}
+				}
+			}
+			output.append(c);
+		}
+		
+		return output.toString();
+	}
 }