Somehow these two files were missed when I updated to the ASL licensed files.
git-svn-id: https://svn.apache.org/repos/asf/incubator/felix/trunk@386660 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/org.osgi/src/main/java/org/osgi/service/permissionadmin/PermissionAdmin.java b/org.osgi/src/main/java/org/osgi/service/permissionadmin/PermissionAdmin.java
index 904b318..4f8b25f 100644
--- a/org.osgi/src/main/java/org/osgi/service/permissionadmin/PermissionAdmin.java
+++ b/org.osgi/src/main/java/org/osgi/service/permissionadmin/PermissionAdmin.java
@@ -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);
}
\ No newline at end of file
diff --git a/org.osgi/src/main/java/org/osgi/service/permissionadmin/PermissionInfo.java b/org.osgi/src/main/java/org/osgi/service/permissionadmin/PermissionInfo.java
index 3502e89..fff10b5 100644
--- a/org.osgi/src/main/java/org/osgi/service/permissionadmin/PermissionInfo.java
+++ b/org.osgi/src/main/java/org/osgi/service/permissionadmin/PermissionInfo.java
@@ -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 "name")
- * </pre>
- *
- * or
- *
- * <pre>
- * (type "name" "actions")
- * </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
- * "<i>name</i>" and between "<i>name</i>" and "<i>actions</i>".
- *
- * @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 "name")
+ * </pre>
+ *
+ * or
+ *
+ * <pre>
+ * (type "name" "actions")
+ * </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
+ * "<i>name</i>" and between "<i>name</i>" and "<i>actions</i>".
+ *
+ * @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();
+ }
}
\ No newline at end of file