blob: 0475c4b05b731a44ca0c43697b755d90a6d53bf5 [file] [log] [blame]
/*
* $Date: 2008/07/31 22:25:18 $
*
* Copyright (c) OSGi Alliance (2000, 2007). 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.framework;
import java.io.IOException;
import java.security.*;
import java.util.*;
import org.eclipse.osgi.framework.internal.core.AbstractBundle;
import org.eclipse.osgi.framework.internal.core.FilterImpl;
/**
* A bundle's authority to perform specific privileged administrative operations
* on or to get sensitive information about a bundle. The actions for this
* permission are:
*
* <pre>
* Action Methods
* class Bundle.loadClass
* execute Bundle.start
* Bundle.stop
* StartLevel.setBundleStartLevel
* extensionLifecycle BundleContext.installBundle for extension bundles
* Bundle.update for extension bundles
* Bundle.uninstall for extension bundles
* lifecycle BundleContext.installBundle
* Bundle.update
* Bundle.uninstall
* listener BundleContext.addBundleListener for SynchronousBundleListener
* BundleContext.removeBundleListener for SynchronousBundleListener
* metadata Bundle.getHeaders
* Bundle.getLocation
* resolve PackageAdmin.refreshPackages
* PackageAdmin.resolveBundles
* resource Bundle.getResource
* Bundle.getResources
* Bundle.getEntry
* Bundle.getEntryPaths
* Bundle.findEntries
* Bundle resource/entry URL creation
* startlevel StartLevel.setStartLevel
* StartLevel.setInitialBundleStartLevel
* context Bundle.getBundleContext
*
* </pre>
*
* <p>
* The special action &quot;*&quot; will represent all actions.
* <p>
* The name of this permission is a filter expression. The filter gives access
* to the following parameters:
* <ul>
* <li>signer - A Distinguished Name chain used to sign a bundle. Wildcards in
* a DN are not matched according to the filter string rules, but according to
* the rules defined for a DN chain.</li>
* <li>location - The location of a bundle.</li>
* <li>id - The bundle ID of the designated bundle.</li>
* <li>name - The symbolic name of a bundle.</li>
* </ul>
*
* @ThreadSafe
* @version $Revision: 1.25 $
*/
public final class AdminPermission extends BasicPermission {
static final long serialVersionUID = 307051004521261705L;
/**
* The action string <code>class</code> (Value is "class").
*
* @since 1.3
*/
public final static String CLASS = "class";
/**
* The action string <code>execute</code> (Value is "execute").
*
* @since 1.3
*/
public final static String EXECUTE = "execute";
/**
* The action string <code>extensionLifecycle</code> (Value is
* "extensionLifecycle").
*
* @since 1.3
*/
public final static String EXTENSIONLIFECYCLE = "extensionLifecycle";
/**
* The action string <code>lifecycle</code> (Value is "lifecycle").
*
* @since 1.3
*/
public final static String LIFECYCLE = "lifecycle";
/**
* The action string <code>listener</code> (Value is "listener").
*
* @since 1.3
*/
public final static String LISTENER = "listener";
/**
* The action string <code>metadata</code> (Value is "metadata").
*
* @since 1.3
*/
public final static String METADATA = "metadata";
/**
* The action string <code>resolve</code> (Value is "resolve").
*
* @since 1.3
*/
public final static String RESOLVE = "resolve";
/**
* The action string <code>resource</code> (Value is "resource").
*
* @since 1.3
*/
public final static String RESOURCE = "resource";
/**
* The action string <code>startlevel</code> (Value is "startlevel").
*
* @since 1.3
*/
public final static String STARTLEVEL = "startlevel";
/**
* The action string <code>context</code> (Value is "context").
*
* @since 1.4
*/
public final static String CONTEXT = "context";
private final static int ACTION_CLASS = 0x00000001;
private final static int ACTION_EXECUTE = 0x00000002;
private final static int ACTION_LIFECYCLE = 0x00000004;
private final static int ACTION_LISTENER = 0x00000008;
private final static int ACTION_METADATA = 0x00000010;
private final static int ACTION_RESOLVE = 0x00000040;
private final static int ACTION_RESOURCE = 0x00000080;
private final static int ACTION_STARTLEVEL = 0x00000100;
private final static int ACTION_EXTENSIONLIFECYCLE = 0x00000200;
private final static int ACTION_CONTEXT = 0x00000400;
private final static int ACTION_ALL =
ACTION_CLASS |
ACTION_EXECUTE |
ACTION_LIFECYCLE |
ACTION_LISTENER |
ACTION_METADATA |
ACTION_RESOLVE |
ACTION_RESOURCE |
ACTION_STARTLEVEL |
ACTION_EXTENSIONLIFECYCLE |
ACTION_CONTEXT;
private final static int ACTION_NONE = 0;
/**
* Indicates that this AdminPermission refers to all bundles
* @serial
*/
private boolean wildcard;
/**
* An x.500 distinguished name used to match a bundle's signature - only used if
* wildcard is false and bundle = null
* @serial
*/
private String filter;
/**
* The actions in canonical form.
*
* @serial
*/
private String actions = null;
/**
* The actions mask.
*/
private transient int action_mask = ACTION_NONE;
/**
* The bundle governed by this AdminPermission - only used if
* wildcard is false and filter == null
*/
private transient Bundle bundle;
/**
* If this AdminPermission was constructed with a bundle, this dictionary holds
* the properties of that bundle, used to match a filter in implies.
* This is not initialized until necessary, and then cached in this object.
*/
private transient Dictionary bundleProperties;
/**
* If this AdminPermission was constructed with a filter, this dictionary holds
* a Filter matching object used to evaluate the filter in implies.
* This is not initialized until necessary, and then cached in this object
*/
private transient Filter filterImpl;
/**
* Creates a new <code>AdminPermission</code> object that matches all
* bundles and has all actions. Equivalent to AdminPermission("*","*");
*/
public AdminPermission() {
this("*",AdminPermission.ACTION_ALL); //$NON-NLS-1$
}
/**
* Create a new AdminPermission.
*
* This constructor must only be used to create a permission that is going
* to be checked.
* <p>
* Examples:
*
* <pre>
* (signer=\*,o=ACME,c=US)
* (&amp;(signer=\*,o=ACME,c=US)(name=com.acme.*)(location=http://www.acme.com/bundles/*))
* (id&gt;=1)
* </pre>
*
* <p>
* When a signer key is used within the filter expression the signer value
* must escape the special filter chars ('*', '(', ')').
* <p>
* Null arguments are equivalent to "*".
*
* @param filter A filter expression that can use signer, location, id, and
* name keys. A value of &quot;*&quot; or <code>null</code> matches
* all bundle.
* @param actions <code>class</code>, <code>execute</code>,
* <code>extensionLifecycle</code>, <code>lifecycle</code>,
* <code>listener</code>, <code>metadata</code>,
* <code>resolve</code>, <code>resource</code>,
* <code>startlevel</code> or <code>context</code>. A value of
* "*" or <code>null</code> indicates all actions
*/
public AdminPermission(String filter, String actions) {
//arguments will be null if called from a PermissionInfo defined with
//no args
this(
(filter == null ? "*" : filter), //$NON-NLS-1$
getMask((actions == null ? "*" : actions)) //$NON-NLS-1$
);
}
/**
* Creates a new <code>AdminPermission</code> object to be used by the
* code that must check a <code>Permission</code> object.
*
* @param bundle A bundle
* @param actions <code>class</code>, <code>execute</code>,
* <code>extensionLifecycle</code>, <code>lifecycle</code>,
* <code>listener</code>, <code>metadata</code>,
* <code>resolve</code>, <code>resource</code>,
* <code>startlevel</code>, <code>context</code>.
* @since 1.3
*/
public AdminPermission(Bundle bundle, String actions) {
super(createName(bundle));
this.bundle = bundle;
this.wildcard = false;
this.filter = null;
this.action_mask = getMask(actions);
}
/**
* Create a permission name from a Bundle
*
* @param bundle Bundle to use to create permission name.
* @return permission name.
*/
private static String createName(Bundle bundle) {
StringBuffer sb = new StringBuffer();
sb.append("(id=");
sb.append(bundle.getBundleId());
sb.append(")");
return sb.toString();
}
/**
* Determines the equality of two <code>AdminPermission</code> objects.
*
* @param obj The object being compared for equality with this object.
* @return <code>true</code> if <code>obj</code> is equivalent to this
* <code>AdminPermission</code>; <code>false</code> otherwise.
*/
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof AdminPermission)) {
return false;
}
AdminPermission a = (AdminPermission) obj;
return (action_mask == a.action_mask) &&
(wildcard == a.wildcard) &&
(bundle == null ? a.bundle == null : (a.bundle == null ? false : bundle.getBundleId() == a.bundle.getBundleId())) &&
(filter == null ? a.filter == null : filter.equals(a.filter));
}
/**
* Returns the hash code value for this object.
*
* @return Hash code value for this object.
*/
public int hashCode() {
return getName().hashCode() ^ getActions().hashCode();
}
/**
* Returns the canonical string representation of the
* <code>AdminPermission</code> actions.
*
* <p>
* Always returns present <code>AdminPermission</code> actions in the
* following order: <code>class</code>, <code>execute</code>,
* <code>extensionLifecycle</code>, <code>lifecycle</code>,
* <code>listener</code>, <code>metadata</code>, <code>resolve</code>,
* <code>resource</code>, <code>startlevel</code>,
* <code>context</code>.
*
* @return Canonical string representation of the
* <code>AdminPermission</code> actions.
*/
public String getActions() {
if (actions == null) {
StringBuffer sb = new StringBuffer();
if ((action_mask & ACTION_CLASS) == ACTION_CLASS) {
sb.append(CLASS);
sb.append(',');
}
if ((action_mask & ACTION_EXECUTE) == ACTION_EXECUTE) {
sb.append(EXECUTE);
sb.append(',');
}
if ((action_mask & ACTION_EXTENSIONLIFECYCLE) == ACTION_EXTENSIONLIFECYCLE) {
sb.append(EXTENSIONLIFECYCLE);
sb.append(',');
}
if ((action_mask & ACTION_LIFECYCLE) == ACTION_LIFECYCLE) {
sb.append(LIFECYCLE);
sb.append(',');
}
if ((action_mask & ACTION_LISTENER) == ACTION_LISTENER) {
sb.append(LISTENER);
sb.append(',');
}
if ((action_mask & ACTION_METADATA) == ACTION_METADATA) {
sb.append(METADATA);
sb.append(',');
}
if ((action_mask & ACTION_RESOLVE) == ACTION_RESOLVE) {
sb.append(RESOLVE);
sb.append(',');
}
if ((action_mask & ACTION_RESOURCE) == ACTION_RESOURCE) {
sb.append(RESOURCE);
sb.append(',');
}
if ((action_mask & ACTION_STARTLEVEL) == ACTION_STARTLEVEL) {
sb.append(STARTLEVEL);
sb.append(',');
}
if ((action_mask & ACTION_CONTEXT) == ACTION_CONTEXT) {
sb.append(CONTEXT);
sb.append(',');
}
//remove trailing comma
if (sb.length() > 0) {
sb.setLength(sb.length()-1);
}
actions = sb.toString();
}
return actions;
}
/**
* Determines if the specified permission is implied by this object. This
* method throws an exception if the specified permission was not
* constructed with a bundle.
*
* <p>
* This method returns <code>true</code> if the specified permission is an
* AdminPermission AND
* <ul>
* <li>this object's filter matches the specified permission's bundle ID,
* bundle symbolic name, bundle location and bundle signer distinguished
* name chain OR</li>
* <li>this object's filter is "*"</li>
* </ul>
* AND this object's actions include all of the specified permission's
* actions.
* <p>
* Special case: if the specified permission was constructed with "*"
* filter, then this method returns <code>true</code> if this object's
* filter is "*" and this object's actions include all of the specified
* permission's actions
*
* @param p The permission to interrogate.
*
* @return <code>true</code> if the specified permission is implied by
* this object; <code>false</code> otherwise.
* @throws RuntimeException if specified permission was not constructed with
* a bundle or "*"
*/
public boolean implies(Permission p) {
if (!(p instanceof AdminPermission))
return false;
AdminPermission target = (AdminPermission)p;
//check actions first - much faster
if ((action_mask & target.action_mask)!=target.action_mask)
return false;
//if passed in a filter, puke
if (target.filter != null)
throw new RuntimeException("Cannot imply a filter"); //$NON-NLS-1$
//special case - only wildcard implies wildcard
if (target.wildcard)
return wildcard;
//check our name
if (filter != null) {
//it's a filter
Filter filterImpl = getFilterImpl();
return filterImpl != null && filterImpl.match(target.getProperties());
} else if (wildcard) {
//it's "*"
return true;
} else {
//it's a bundle id
return bundle.equals(target.bundle);
}
}
/**
* Returns a new <code>PermissionCollection</code> object suitable for
* storing <code>AdminPermission</code>s.
*
* @return A new <code>PermissionCollection</code> object.
*/
public PermissionCollection newPermissionCollection() {
return(new AdminPermissionCollection());
}
/**
* Package private constructor used by AdminPermissionCollection.
*
* @param filter name filter
* @param action_mask mask
*/
AdminPermission(String filter, int action_mask) {
super(filter);
//name must be either * or a filter
if (filter.equals("*")) { //$NON-NLS-1$
this.wildcard = true;
this.filter = null;
} else {
this.wildcard = false;
this.filter = filter;
}
this.bundle = null;
this.action_mask = action_mask;
}
/**
* Parse action string into action mask.
*
* @param actions Action string.
* @return action mask.
*/
private static int getMask(String actions) {
boolean seencomma = false;
int mask = ACTION_NONE;
if (actions == null) {
return mask;
}
char[] a = actions.toCharArray();
int i = a.length - 1;
if (i < 0)
return mask;
while (i != -1) {
char c;
// skip whitespace
while ((i!=-1) && ((c = a[i]) == ' ' ||
c == '\r' ||
c == '\n' ||
c == '\f' ||
c == '\t'))
i--;
// check for the known strings
int matchlen;
if (i >= 4 &&
(a[i-4] == 'c' || a[i-4] == 'C') &&
(a[i-3] == 'l' || a[i-3] == 'L') &&
(a[i-2] == 'a' || a[i-2] == 'A') &&
(a[i-1] == 's' || a[i-1] == 'S') &&
(a[i] == 's' || a[i] == 'S'))
{
matchlen = 5;
mask |= ACTION_CLASS;
} else if (i >= 6 &&
(a[i-6] == 'e' || a[i-6] == 'E') &&
(a[i-5] == 'x' || a[i-5] == 'X') &&
(a[i-4] == 'e' || a[i-4] == 'E') &&
(a[i-3] == 'c' || a[i-3] == 'C') &&
(a[i-2] == 'u' || a[i-2] == 'U') &&
(a[i-1] == 't' || a[i-1] == 'T') &&
(a[i] == 'e' || a[i] == 'E'))
{
matchlen = 7;
mask |= ACTION_EXECUTE;
} else if (i >= 17 &&
(a[i-17] == 'e' || a[i-17] == 'E') &&
(a[i-16] == 'x' || a[i-16] == 'X') &&
(a[i-15] == 't' || a[i-15] == 'T') &&
(a[i-14] == 'e' || a[i-14] == 'E') &&
(a[i-13] == 'n' || a[i-13] == 'N') &&
(a[i-12] == 's' || a[i-12] == 'S') &&
(a[i-11] == 'i' || a[i-11] == 'I') &&
(a[i-10] == 'o' || a[i-10] == 'O') &&
(a[i-9] == 'n' || a[i-9] == 'N') &&
(a[i-8] == 'l' || a[i-8] == 'L') &&
(a[i-7] == 'i' || a[i-7] == 'I') &&
(a[i-6] == 'f' || a[i-6] == 'F') &&
(a[i-5] == 'e' || a[i-5] == 'E') &&
(a[i-4] == 'c' || a[i-4] == 'C') &&
(a[i-3] == 'y' || a[i-3] == 'Y') &&
(a[i-2] == 'c' || a[i-2] == 'C') &&
(a[i-1] == 'l' || a[i-1] == 'L') &&
(a[i] == 'e' || a[i] == 'E'))
{
matchlen = 18;
mask |= ACTION_EXTENSIONLIFECYCLE;
} else if (i >= 8 &&
(a[i-8] == 'l' || a[i-8] == 'L') &&
(a[i-7] == 'i' || a[i-7] == 'I') &&
(a[i-6] == 'f' || a[i-6] == 'F') &&
(a[i-5] == 'e' || a[i-5] == 'E') &&
(a[i-4] == 'c' || a[i-4] == 'C') &&
(a[i-3] == 'y' || a[i-3] == 'Y') &&
(a[i-2] == 'c' || a[i-2] == 'C') &&
(a[i-1] == 'l' || a[i-1] == 'L') &&
(a[i] == 'e' || a[i] == 'E'))
{
matchlen = 9;
mask |= ACTION_LIFECYCLE;
} else if (i >= 7 &&
(a[i-7] == 'l' || a[i-7] == 'L') &&
(a[i-6] == 'i' || a[i-6] == 'I') &&
(a[i-5] == 's' || a[i-5] == 'S') &&
(a[i-4] == 't' || a[i-4] == 'T') &&
(a[i-3] == 'e' || a[i-3] == 'E') &&
(a[i-2] == 'n' || a[i-2] == 'N') &&
(a[i-1] == 'e' || a[i-1] == 'E') &&
(a[i] == 'r' || a[i] == 'R'))
{
matchlen = 8;
mask |= ACTION_LISTENER;
} else if (i >= 7 &&
(a[i-7] == 'm' || a[i-7] == 'M') &&
(a[i-6] == 'e' || a[i-6] == 'E') &&
(a[i-5] == 't' || a[i-5] == 'T') &&
(a[i-4] == 'a' || a[i-4] == 'A') &&
(a[i-3] == 'd' || a[i-3] == 'D') &&
(a[i-2] == 'a' || a[i-2] == 'A') &&
(a[i-1] == 't' || a[i-1] == 'T') &&
(a[i] == 'a' || a[i] == 'A'))
{
matchlen = 8;
mask |= ACTION_METADATA;
} else if (i >= 6 &&
(a[i-6] == 'r' || a[i-6] == 'R') &&
(a[i-5] == 'e' || a[i-5] == 'E') &&
(a[i-4] == 's' || a[i-4] == 'S') &&
(a[i-3] == 'o' || a[i-3] == 'O') &&
(a[i-2] == 'l' || a[i-2] == 'L') &&
(a[i-1] == 'v' || a[i-1] == 'V') &&
(a[i] == 'e' || a[i] == 'E'))
{
matchlen = 7;
mask |= ACTION_RESOLVE;
} else if (i >= 7 &&
(a[i-7] == 'r' || a[i-7] == 'R') &&
(a[i-6] == 'e' || a[i-6] == 'E') &&
(a[i-5] == 's' || a[i-5] == 'S') &&
(a[i-4] == 'o' || a[i-4] == 'O') &&
(a[i-3] == 'u' || a[i-3] == 'U') &&
(a[i-2] == 'r' || a[i-2] == 'R') &&
(a[i-1] == 'c' || a[i-1] == 'C') &&
(a[i] == 'e' || a[i] == 'E'))
{
matchlen = 8;
mask |= ACTION_RESOURCE;
} else if (i >= 9 &&
(a[i-9] == 's' || a[i-9] == 'S') &&
(a[i-8] == 't' || a[i-8] == 'T') &&
(a[i-7] == 'a' || a[i-7] == 'A') &&
(a[i-6] == 'r' || a[i-6] == 'R') &&
(a[i-5] == 't' || a[i-5] == 'T') &&
(a[i-4] == 'l' || a[i-4] == 'L') &&
(a[i-3] == 'e' || a[i-3] == 'E') &&
(a[i-2] == 'v' || a[i-2] == 'V') &&
(a[i-1] == 'e' || a[i-1] == 'E') &&
(a[i] == 'l' || a[i] == 'L'))
{
matchlen = 10;
mask |= ACTION_STARTLEVEL;
} else if (i >= 6 &&
(a[i-6] == 'c' || a[i-6] == 'C') &&
(a[i-5] == 'o' || a[i-5] == 'O') &&
(a[i-4] == 'n' || a[i-4] == 'N') &&
(a[i-3] == 't' || a[i-3] == 'T') &&
(a[i-2] == 'e' || a[i-2] == 'E') &&
(a[i-1] == 'x' || a[i-1] == 'X') &&
(a[i] == 't' || a[i] == 'T'))
{
matchlen = 7;
mask |= ACTION_CONTEXT;
} else if (i >= 0 &&
(a[i] == '*'))
{
matchlen = 1;
mask |= ACTION_ALL;
} else {
// parse error
throw new IllegalArgumentException(
"invalid permission: " + actions); //$NON-NLS-1$
}
// make sure we didn't just match the tail of a word
// like "ackbarfstartlevel". Also, skip to the comma.
seencomma = false;
while (i >= matchlen && !seencomma) {
switch(a[i-matchlen]) {
case ',':
seencomma = true;
/*FALLTHROUGH*/
case ' ': case '\r': case '\n':
case '\f': case '\t':
break;
default:
throw new IllegalArgumentException(
"invalid permission: " + actions); //$NON-NLS-1$
}
i--;
}
// point i at the location of the comma minus one (or -1).
i -= matchlen;
}
if (seencomma) {
throw new IllegalArgumentException("invalid permission: " + //$NON-NLS-1$
actions);
}
return mask;
}
/**
* Called by <code><@link AdminPermission#implies(Permission)></code> on an AdminPermission
* which was constructed with a Bundle. This method loads a dictionary with the
* filter-matchable properties of this bundle. The dictionary is cached so this lookup
* only happens once.
*
* This method should only be called on an AdminPermission which was constructed with a
* bundle
*
* @return a dictionary of properties for this bundle
*/
private Dictionary getProperties() {
if (bundleProperties == null) {
bundleProperties = new Hashtable();
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
//set Id
bundleProperties.put("id",new Long(bundle.getBundleId())); //$NON-NLS-1$
//set location
bundleProperties.put("location",bundle.getLocation()); //$NON-NLS-1$
//set name
if (bundle.getSymbolicName() != null)
bundleProperties.put("name",bundle.getSymbolicName()); //$NON-NLS-1$
//set signers
bundleProperties.put("signer",new SignerWrapper(bundle)); //$NON-NLS-1$
return null;
}
});
}
return bundleProperties;
}
private static class SignerWrapper extends Object {
private Bundle bundle;
private String pattern;
public SignerWrapper(String pattern) {
this.pattern = pattern;
}
SignerWrapper(Bundle bundle) {
this.bundle = bundle;
}
public boolean equals(Object o) {
if (!(o instanceof SignerWrapper))
return false;
SignerWrapper other = (SignerWrapper) o;
AbstractBundle matchBundle = (AbstractBundle) (bundle != null ? bundle : other.bundle);
String matchPattern = bundle != null ? other.pattern : pattern;
return matchBundle.getBundleData().matchDNChain(matchPattern);
}
}
/**
* Called by <tt><@link AdminPermission#implies(Permission)></tt> on an AdminPermission
* which was constructed with a filter. This method loads a FilterImpl with the
* filter specification of this AdminPermission. The filter is cached so this work
* only happens once.
*
* This method should only be called on an AdminPermission which was constructed with a
* filter
*
* @return a filterImpl for this bundle
*/
private Filter getFilterImpl() {
if (filterImpl == null) {
try {
int pos = filter.indexOf("signer"); //$NON-NLS-1$
if (pos != -1){
//there may be a signer attribute
StringBuffer filterBuf = new StringBuffer(filter);
int numAsteriskFound = 0; //use as offset to replace in buffer
int walkbackPos; //temp pos
//find occurences of (signer= and escape out *'s
while (pos != -1) {
//walk back and look for '(' to see if this is an attr
walkbackPos = pos-1;
//consume whitespace
while(walkbackPos >= 0 && Character.isWhitespace(filter.charAt(walkbackPos))) {
walkbackPos--;
}
if (walkbackPos <0) {
//filter is invalid - FilterImpl will throw error
break;
}
//check to see if we have unescaped '('
if (filter.charAt(walkbackPos) != '(' || (walkbackPos > 0 && filter.charAt(walkbackPos-1) == '\\')) {
//'(' was escaped or not there
pos = filter.indexOf("signer",pos+6); //$NON-NLS-1$
continue;
}
pos+=6; //skip over 'signer'
//found signer - consume whitespace before '='
while (Character.isWhitespace(filter.charAt(pos))) {
pos++;
}
//look for '='
if (filter.charAt(pos) != '=') {
//attr was signerx - keep looking
pos = filter.indexOf("signer",pos); //$NON-NLS-1$
continue;
}
pos++; //skip over '='
//found signer value - escape '*'s
while (!(filter.charAt(pos) == ')' && filter.charAt(pos-1) != '\\')) {
// only add an escape if it is not already escaped
if (filter.charAt(pos) == '*' && filter.charAt(pos-1) != '\\') {
filterBuf.insert(pos+numAsteriskFound,'\\');
numAsteriskFound++;
}
pos++;
}
//end of signer value - look for more?
pos = filter.indexOf("signer",pos); //$NON-NLS-1$
} //end while (pos != -1)
filter = filterBuf.toString();
} //end if (pos != -1)
filterImpl = new FilterImpl(filter);
} catch (InvalidSyntaxException e) {
//we will return null
}
}
return filterImpl;
}
/**
* Returns the current action mask.
* <p>
* Used by the AdminPermissionCollection class.
*
* @return Current action mask.
*/
int getMask() {
return action_mask;
}
private synchronized void writeObject(java.io.ObjectOutputStream s) throws IOException {
// Write out the actions. The superclass takes care of the name
// call getActions to make sure actions field is initialized
if (actions == null)
getActions();
if (filter == null && !wildcard)
throw new UnsupportedOperationException("cannot serialize"); //$NON-NLS-1$
s.defaultWriteObject();
}
/**
* readObject is called to restore the state of this permission from a
* stream.
*/
private synchronized void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException {
// Read in the action, then initialize the rest
s.defaultReadObject();
action_mask = getMask(actions);
}
}
/**
* Stores a collection of <code>AdminPermission</code>s.
*/
final class AdminPermissionCollection extends PermissionCollection
{
private static final long serialVersionUID = 3906372644575328048L;
/**
* Collection of permissions.
*
* @serial
*/
private Hashtable permissions;
/**
* Create an empty AdminPermissions object.
*
*/
public AdminPermissionCollection()
{
permissions = new Hashtable();
}
/**
* Adds a permission to the <code>AdminPermission</code> objects. The key for
* the hashtable is the name
*
* @param permission The <code>AdminPermission</code> object to add.
*
* @exception IllegalArgumentException If the permission is not an
* <code>AdminPermission</code> instance.
*
* @exception SecurityException If this <code>AdminPermissionCollection</code>
* object has been marked read-only.
*/
public void add(Permission permission)
{
if (! (permission instanceof AdminPermission))
throw new IllegalArgumentException("invalid permission: "+ //$NON-NLS-1$
permission);
if (isReadOnly())
throw new SecurityException("attempt to add a Permission to a " + //$NON-NLS-1$
"readonly AdminCollection"); //$NON-NLS-1$
AdminPermission ap = (AdminPermission) permission;
AdminPermission existing = (AdminPermission) permissions.get(ap.getName());
if (existing != null){
int oldMask = existing.getMask();
int newMask = ap.getMask();
if (oldMask != newMask) {
permissions.put(existing.getName(),
new AdminPermission(existing.getName(), oldMask | newMask));
}
} else {
permissions.put(ap.getName(), ap);
}
}
/**
* Determines if the specified permissions implies the permissions
* expressed in <code>permission</code>.
*
* @param permission The Permission object to compare with the <code>AdminPermission</code>
* objects in this collection.
*
* @return <code>true</code> if <code>permission</code> is implied by an
* <code>AdminPermission</code> in this collection, <code>false</code> otherwise.
*/
public boolean implies(Permission permission)
{
if (!(permission instanceof AdminPermission))
return(false);
AdminPermission target = (AdminPermission) permission;
//just iterate one by one
Iterator permItr = permissions.values().iterator();
while(permItr.hasNext())
if (((AdminPermission)permItr.next()).implies(target))
return true;
return false;
}
/**
* Returns an enumeration of all <code>AdminPermission</code> objects in the
* container.
*
* @return Enumeration of all <code>AdminPermission</code> objects.
*/
public Enumeration elements()
{
return(Collections.enumeration(permissions.values()));
}
}