/*
 * Copyright (c) OSGi Alliance (2000, 2017). 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.io.NotSerializableException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamField;
import java.security.AccessController;
import java.security.BasicPermission;
import java.security.Permission;
import java.security.PermissionCollection;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

/**
 * 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
 *                    BundleStartLevel.setStartLevel
 * 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            FrameworkWiring.refreshBundles
 *                    FrameworkWiring.resolveBundles
 * resource           Bundle.getResource
 *                    Bundle.getResources
 *                    Bundle.getEntry
 *                    Bundle.getEntryPaths
 *                    Bundle.findEntries
 *                    Bundle resource/entry URL creation
 * startlevel         FrameworkStartLevel.setStartLevel
 *                    FrameworkStartLevel.setInitialBundleStartLevel
 * context            Bundle.getBundleContext
 * weave              WovenClass.getBytes
 *                    WovenClass.setBytes
 *                    WovenClass.getDynamicImports for modification
 * </pre>
 * 
 * <p>
 * The special action &quot;*&quot; will represent all actions. The
 * {@code resolve} action is implied by the {@code class}, {@code execute} and
 * {@code resource} actions.
 * <p>
 * The name of this permission is a filter expression. The filter gives access
 * to the following attributes:
 * <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>
 * Filter attribute names are processed in a case sensitive manner.
 * 
 * @ThreadSafe
 * @author $Id: 7906054ba14028f4c0dc21610dfd8b86ae3ffa00 $
 */

public final class AdminPermission extends BasicPermission {
	static final long								serialVersionUID			= 307051004521261705L;

	/**
	 * The action string {@code class}. The {@code class} action implies the
	 * {@code resolve} action.
	 * 
	 * @since 1.3
	 */
	public final static String						CLASS						= "class";
	/**
	 * The action string {@code execute}. The {@code execute} action implies the
	 * {@code resolve} action.
	 * 
	 * @since 1.3
	 */
	public final static String						EXECUTE						= "execute";
	/**
	 * The action string {@code extensionLifecycle}.
	 * 
	 * @since 1.3
	 */
	public final static String						EXTENSIONLIFECYCLE			= "extensionLifecycle";
	/**
	 * The action string {@code lifecycle}.
	 * 
	 * @since 1.3
	 */
	public final static String						LIFECYCLE					= "lifecycle";
	/**
	 * The action string {@code listener}.
	 * 
	 * @since 1.3
	 */
	public final static String						LISTENER					= "listener";
	/**
	 * The action string {@code metadata}.
	 * 
	 * @since 1.3
	 */
	public final static String						METADATA					= "metadata";
	/**
	 * The action string {@code resolve}. The {@code resolve} action is implied
	 * by the {@code class}, {@code execute} and {@code resource} actions.
	 * 
	 * @since 1.3
	 */
	public final static String						RESOLVE						= "resolve";
	/**
	 * The action string {@code resource}. The {@code resource} action implies
	 * the {@code resolve} action.
	 * 
	 * @since 1.3
	 */
	public final static String						RESOURCE					= "resource";
	/**
	 * The action string {@code startlevel}.
	 * 
	 * @since 1.3
	 */
	public final static String						STARTLEVEL					= "startlevel";

	/**
	 * The action string {@code context}.
	 * 
	 * @since 1.4
	 */
	public final static String						CONTEXT						= "context";

	/**
	 * The action string {@code weave}.
	 * 
	 * @since 1.6
	 */
	public final static String						WEAVE						= "weave";

	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_WEAVE				= 0x00000800;
	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 | ACTION_WEAVE;
	final static int								ACTION_NONE					= 0;

	/**
	 * The actions in canonical form.
	 * 
	 * @serial
	 */
	private volatile String							actions						= null;

	/**
	 * The actions mask.
	 */
	transient int									action_mask;

	/**
	 * If this AdminPermission was constructed with a filter, this holds a
	 * Filter matching object used to evaluate the filter in implies.
	 */
	transient Filter								filter;

	/**
	 * The bundle governed by this AdminPermission - only used if filter == null
	 */
	transient final Bundle							bundle;

	/**
	 * This map holds the properties of the permission, used to match a filter
	 * in implies. This is not initialized until necessary, and then cached in
	 * this object.
	 */
	private transient volatile Map<String, Object>	properties;

	/**
	 * ThreadLocal used to determine if we have recursively called
	 * getProperties.
	 */
	private static final ThreadLocal<Bundle>		recurse						= new ThreadLocal<Bundle>();

	/**
	 * Creates a new {@code AdminPermission} object that matches all bundles and
	 * has all actions. Equivalent to AdminPermission("*","*");
	 */
	public AdminPermission() {
		this(null, ACTION_ALL);
	}

	/**
	 * 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} matches all
	 *        bundle. Filter attribute names are processed in a case sensitive
	 *        manner.
	 * @param actions {@code class}, {@code execute}, {@code extensionLifecycle}
	 *        , {@code lifecycle}, {@code listener}, {@code metadata},
	 *        {@code resolve} , {@code resource}, {@code startlevel},
	 *        {@code context} or {@code weave}. A value of "*" or {@code null}
	 *        indicates all actions.
	 * @throws IllegalArgumentException If the filter has an invalid syntax.
	 */
	public AdminPermission(String filter, String actions) {
		// arguments will be null if called from a PermissionInfo defined with
		// no args
		this(parseFilter(filter), parseActions(actions));
	}

	/**
	 * Creates a new requested {@code AdminPermission} object to be used by the
	 * code that must perform {@code checkPermission}. {@code AdminPermission}
	 * objects created with this constructor cannot be added to an
	 * {@code AdminPermission} permission collection.
	 * 
	 * @param bundle A bundle.
	 * @param actions {@code class}, {@code execute}, {@code extensionLifecycle}
	 *        , {@code lifecycle}, {@code listener}, {@code metadata},
	 *        {@code resolve} , {@code resource}, {@code startlevel},
	 *        {@code context}, {@code weave}. A value of "*" or {@code null}
	 *        indicates all actions.
	 * @since 1.3
	 */
	public AdminPermission(Bundle bundle, String actions) {
		super(createName(bundle));
		setTransients(null, parseActions(actions));
		this.bundle = bundle;
	}

	/**
	 * 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) {
		if (bundle == null) {
			throw new IllegalArgumentException("bundle must not be null");
		}
		StringBuilder sb = new StringBuilder("(id=");
		sb.append(bundle.getBundleId());
		sb.append(")");
		return sb.toString();
	}

	/**
	 * Package private constructor used by AdminPermissionCollection.
	 * 
	 * @param filter name filter or {@code null} for wildcard.
	 * @param mask action mask
	 */
	AdminPermission(Filter filter, int mask) {
		super((filter == null) ? "*" : filter.toString());
		setTransients(filter, mask);
		this.bundle = null;
	}

	/**
	 * Called by constructors and when deserialized.
	 * 
	 * @param filter Permission's filter or {@code null} for wildcard.
	 * @param mask action mask
	 */
	private void setTransients(Filter filter, int mask) {
		this.filter = filter;
		if ((mask == ACTION_NONE) || ((mask & ACTION_ALL) != mask)) {
			throw new IllegalArgumentException("invalid action string");
		}
		this.action_mask = mask;
	}

	/**
	 * Parse action string into action mask.
	 * 
	 * @param actions Action string.
	 * @return action mask.
	 */
	private static int parseActions(String actions) {
		if ((actions == null) || actions.equals("*")) {
			return ACTION_ALL;
		}

		boolean seencomma = false;

		int mask = ACTION_NONE;

		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 | ACTION_RESOLVE;

			} 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 | ACTION_RESOLVE;

				} 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
													| ACTION_RESOLVE;

										} 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 >= 4
															&& (a[i - 4] == 'w' || a[i - 4] == 'W')
															&& (a[i - 3] == 'e' || a[i - 3] == 'E')
															&& (a[i - 2] == 'a' || a[i - 2] == 'A')
															&& (a[i - 1] == 'v' || a[i - 1] == 'V')
															&& (a[i] == 'e' || a[i] == 'E')) {
														matchlen = 5;
														mask |= ACTION_WEAVE;

													} else
														if (i >= 0 && (a[i] == '*')) {
															matchlen = 1;
															mask |= ACTION_ALL;

														} else {
															// parse error
															throw new IllegalArgumentException("invalid permission: " + actions);
														}

			// 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);
				}
				i--;
			}

			// point i at the location of the comma minus one (or -1).
			i -= matchlen;
		}

		if (seencomma) {
			throw new IllegalArgumentException("invalid permission: " + actions);
		}

		return mask;
	}

	/**
	 * Parse filter string into a Filter object.
	 * 
	 * @param filterString The filter string to parse.
	 * @return a Filter for this bundle. If the specified filterString is
	 *         {@code null} or equals "*", then {@code null} is returned to
	 *         indicate a wildcard.
	 * @throws IllegalArgumentException If the filter syntax is invalid.
	 */
	private static Filter parseFilter(String filterString) {
		if (filterString == null) {
			return null;
		}
		filterString = filterString.trim();
		if (filterString.equals("*")) {
			return null;
		}

		try {
			return FrameworkUtil.createFilter(filterString);
		} catch (InvalidSyntaxException e) {
			throw new IllegalArgumentException("invalid filter", e);
		}
	}

	/**
	 * 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} 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} if this object's filter is
	 * "*" and this object's actions include all of the specified permission's
	 * actions
	 * 
	 * @param p The requested permission.
	 * @return {@code true} if the specified permission is implied by this
	 *         object; {@code false} otherwise.
	 */
	@Override
	public boolean implies(Permission p) {
		if (!(p instanceof AdminPermission)) {
			return false;
		}
		AdminPermission requested = (AdminPermission) p;
		if (bundle != null) {
			return false;
		}
		// if requested permission has a filter, then it is an invalid argument
		if (requested.filter != null) {
			return false;
		}
		return implies0(requested, ACTION_NONE);
	}

	/**
	 * Internal implies method. Used by the implies and the permission
	 * collection implies methods.
	 * 
	 * @param requested The requested AdminPermision which has already be
	 *        validated as a proper argument. The requested AdminPermission must
	 *        not have a filter expression.
	 * @param effective The effective actions with which to start.
	 * @return {@code true} if the specified permission is implied by this
	 *         object; {@code false} otherwise.
	 */
	boolean implies0(AdminPermission requested, int effective) {
		/* check actions first - much faster */
		effective |= action_mask;
		final int desired = requested.action_mask;
		if ((effective & desired) != desired) {
			return false;
		}

		/* Get our filter */
		Filter f = filter;
		if (f == null) {
			// it's "*"
			return true;
		}
		/* is requested a wildcard filter? */
		if (requested.bundle == null) {
			return false;
		}
		Map<String, Object> requestedProperties = requested.getProperties();
		if (requestedProperties == null) {
			/*
			 * If the requested properties are null, then we have detected a
			 * recursion getting the bundle location. So we return true to
			 * permit the bundle location request in the AdminPermission check
			 * up the stack to succeed.
			 */
			return true;
		}
		return f.matches(requestedProperties);
	}

	/**
	 * Returns the canonical string representation of the
	 * {@code AdminPermission} actions.
	 * 
	 * <p>
	 * Always returns present {@code AdminPermission} actions in the following
	 * order: {@code class}, {@code execute}, {@code extensionLifecycle},
	 * {@code lifecycle}, {@code listener}, {@code metadata}, {@code resolve},
	 * {@code resource}, {@code startlevel}, {@code context}, {@code weave}.
	 * 
	 * @return Canonical string representation of the {@code AdminPermission}
	 *         actions.
	 */
	@Override
	public String getActions() {
		String result = actions;
		if (result == null) {
			StringBuilder sb = new StringBuilder();

			int mask = action_mask;
			if ((mask & ACTION_CLASS) == ACTION_CLASS) {
				sb.append(CLASS);
				sb.append(',');
			}

			if ((mask & ACTION_EXECUTE) == ACTION_EXECUTE) {
				sb.append(EXECUTE);
				sb.append(',');
			}

			if ((mask & ACTION_EXTENSIONLIFECYCLE) == ACTION_EXTENSIONLIFECYCLE) {
				sb.append(EXTENSIONLIFECYCLE);
				sb.append(',');
			}

			if ((mask & ACTION_LIFECYCLE) == ACTION_LIFECYCLE) {
				sb.append(LIFECYCLE);
				sb.append(',');
			}

			if ((mask & ACTION_LISTENER) == ACTION_LISTENER) {
				sb.append(LISTENER);
				sb.append(',');
			}

			if ((mask & ACTION_METADATA) == ACTION_METADATA) {
				sb.append(METADATA);
				sb.append(',');
			}

			if ((mask & ACTION_RESOLVE) == ACTION_RESOLVE) {
				sb.append(RESOLVE);
				sb.append(',');
			}

			if ((mask & ACTION_RESOURCE) == ACTION_RESOURCE) {
				sb.append(RESOURCE);
				sb.append(',');
			}

			if ((mask & ACTION_STARTLEVEL) == ACTION_STARTLEVEL) {
				sb.append(STARTLEVEL);
				sb.append(',');
			}

			if ((mask & ACTION_CONTEXT) == ACTION_CONTEXT) {
				sb.append(CONTEXT);
				sb.append(',');
			}

			if ((mask & ACTION_WEAVE) == ACTION_WEAVE) {
				sb.append(WEAVE);
				sb.append(',');
			}

			// remove trailing comma
			if (sb.length() > 0) {
				sb.setLength(sb.length() - 1);
			}

			actions = result = sb.toString();
		}
		return result;
	}

	/**
	 * Returns a new {@code PermissionCollection} object suitable for storing
	 * {@code AdminPermission}s.
	 * 
	 * @return A new {@code PermissionCollection} object.
	 */
	@Override
	public PermissionCollection newPermissionCollection() {
		return new AdminPermissionCollection();
	}

	/**
	 * Determines the equality of two {@code AdminPermission} objects.
	 * 
	 * @param obj The object being compared for equality with this object.
	 * @return {@code true} if {@code obj} is equivalent to this
	 *         {@code AdminPermission}; {@code false} otherwise.
	 */
	@Override
	public boolean equals(Object obj) {
		if (obj == this) {
			return true;
		}

		if (!(obj instanceof AdminPermission)) {
			return false;
		}

		AdminPermission ap = (AdminPermission) obj;

		return (action_mask == ap.action_mask) && ((bundle == ap.bundle) || ((bundle != null) && bundle.equals(ap.bundle))) && (filter == null ? ap.filter == null : filter.equals(ap.filter));
	}

	/**
	 * Returns the hash code value for this object.
	 * 
	 * @return Hash code value for this object.
	 */
	@Override
	public int hashCode() {
		int h = 31 * 17 + getName().hashCode();
		h = 31 * h + getActions().hashCode();
		if (bundle != null) {
			h = 31 * h + bundle.hashCode();
		}
		return h;
	}

	/**
	 * WriteObject is called to save the state of this permission object to a
	 * stream. The actions are serialized, and the superclass takes care of the
	 * name.
	 */
	private synchronized void writeObject(java.io.ObjectOutputStream s) throws IOException {
		if (bundle != null) {
			throw new NotSerializableException("cannot serialize");
		}
		// Write out the actions. The superclass takes care of the name
		// call getActions to make sure actions field is initialized
		if (actions == null)
			getActions();
		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 data, then initialize the transients
		s.defaultReadObject();
		setTransients(parseFilter(getName()), parseActions(actions));
	}

	/**
	 * Called by {@code implies0} on an AdminPermission which was constructed
	 * with a Bundle. This method loads a map with the filter-matchable
	 * properties of this bundle. The map 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 map of properties for this bundle
	 */
	private Map<String, Object> getProperties() {
		Map<String, Object> result = properties;
		if (result != null) {
			return result;
		}
		/*
		 * We may have recursed here due to the Bundle.getLocation call in the
		 * doPrivileged below. If this is the case, return null to allow implies
		 * to return true.
		 */
		final Object mark = recurse.get();
		if (mark == bundle) {
			return null;
		}
		recurse.set(bundle);
		try {
			final Map<String, Object> map = new HashMap<String, Object>(4);
			AccessController.doPrivileged(new PrivilegedAction<Void>() {
				@Override
				public Void run() {
					map.put("id", Long.valueOf(bundle.getBundleId()));
					map.put("location", bundle.getLocation());
					String name = bundle.getSymbolicName();
					if (name != null) {
						map.put("name", name);
					}
					SignerProperty signer = new SignerProperty(bundle);
					if (signer.isBundleSigned()) {
						map.put("signer", signer);
					}
					return null;
				}
			});
			return properties = map;
		} finally {
			recurse.set(null);
		}
	}
}

/**
 * Stores a collection of {@code AdminPermission}s.
 */
final class AdminPermissionCollection extends PermissionCollection {
	private static final long						serialVersionUID	= 3906372644575328048L;
	/**
	 * Collection of permissions.
	 * 
	 * @GuardedBy this
	 */
	private transient Map<String, AdminPermission>	permissions;

	/**
	 * Boolean saying if "*" is in the collection.
	 * 
	 * @serial
	 * @GuardedBy this
	 */
	private boolean									all_allowed;

	/**
	 * Create an empty AdminPermissions object.
	 * 
	 */
	public AdminPermissionCollection() {
		permissions = new HashMap<String, AdminPermission>();
	}

	/**
	 * Adds a permission to this permission collection.
	 * 
	 * @param permission The {@code AdminPermission} object to add.
	 * @throws IllegalArgumentException If the specified permission is not an
	 *         {@code AdminPermission} instance or was constructed with a Bundle
	 *         object.
	 * @throws SecurityException If this {@code AdminPermissionCollection}
	 *         object has been marked read-only.
	 */
	@Override
	public void add(Permission permission) {
		if (!(permission instanceof AdminPermission)) {
			throw new IllegalArgumentException("invalid permission: " + permission);
		}
		if (isReadOnly()) {
			throw new SecurityException("attempt to add a Permission to a " + "readonly PermissionCollection");
		}
		final AdminPermission ap = (AdminPermission) permission;
		if (ap.bundle != null) {
			throw new IllegalArgumentException("cannot add to collection: " + ap);
		}
		final String name = ap.getName();
		synchronized (this) {
			Map<String, AdminPermission> pc = permissions;
			AdminPermission existing = pc.get(name);
			if (existing != null) {
				int oldMask = existing.action_mask;
				int newMask = ap.action_mask;

				if (oldMask != newMask) {
					pc.put(name, new AdminPermission(existing.filter, oldMask | newMask));
				}
			} else {
				pc.put(name, ap);
			}
			if (!all_allowed) {
				if (name.equals("*")) {
					all_allowed = true;
				}
			}
		}
	}

	/**
	 * Determines if the specified permissions implies the permissions expressed
	 * in {@code permission}.
	 * 
	 * @param permission The Permission object to compare with the
	 *        {@code AdminPermission} objects in this collection.
	 * @return {@code true} if {@code permission} is implied by an
	 *         {@code AdminPermission} in this collection, {@code false}
	 *         otherwise.
	 */
	@Override
	public boolean implies(Permission permission) {
		if (!(permission instanceof AdminPermission)) {
			return false;
		}

		AdminPermission requested = (AdminPermission) permission;
		// if requested permission has a filter, then it is an invalid argument
		if (requested.filter != null) {
			return false;
		}
		int effective = AdminPermission.ACTION_NONE;
		Collection<AdminPermission> perms;
		synchronized (this) {
			Map<String, AdminPermission> pc = permissions;
			// short circuit if the "*" Permission was added
			if (all_allowed) {
				AdminPermission ap = pc.get("*");
				if (ap != null) {
					effective |= ap.action_mask;
					final int desired = requested.action_mask;
					if ((effective & desired) == desired) {
						return true;
					}
				}
			}
			perms = pc.values();
		}

		// just iterate one by one
		for (AdminPermission perm : perms) {
			if (perm.implies0(requested, effective)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * Returns an enumeration of all {@code AdminPermission} objects in the
	 * container.
	 * 
	 * @return Enumeration of all {@code AdminPermission} objects.
	 */
	@Override
	public synchronized Enumeration<Permission> elements() {
		List<Permission> all = new ArrayList<Permission>(permissions.values());
		return Collections.enumeration(all);
	}

	/* serialization logic */
	private static final ObjectStreamField[]	serialPersistentFields	= {new ObjectStreamField("permissions", Hashtable.class), new ObjectStreamField("all_allowed", Boolean.TYPE)};

	private synchronized void writeObject(ObjectOutputStream out) throws IOException {
		Hashtable<String, AdminPermission> hashtable = new Hashtable<String, AdminPermission>(permissions);
		ObjectOutputStream.PutField pfields = out.putFields();
		pfields.put("permissions", hashtable);
		pfields.put("all_allowed", all_allowed);
		out.writeFields();
	}

	private synchronized void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
		ObjectInputStream.GetField gfields = in.readFields();
		@SuppressWarnings("unchecked")
		Hashtable<String, AdminPermission> hashtable = (Hashtable<String, AdminPermission>) gfields.get("permissions", null);
		permissions = new HashMap<String, AdminPermission>(hashtable);
		all_allowed = gfields.get("all_allowed", false);
	}
}
