/*
 * Copyright (c) OSGi Alliance (2000, 2021). 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$
 */

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<>();

	/**
	 * 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<>(4);
			AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
				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<>();
	}

	/**
	 * 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<>(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<>(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<>(hashtable);
		all_allowed = gfields.get("all_allowed", false);
	}
}
