/*
 * Copyright (c) OSGi Alliance (2004, 2016). 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.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamField;
import java.security.BasicPermission;
import java.security.Permission;
import java.security.PermissionCollection;
import java.util.ArrayList;
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 require or provide a bundle or to receive or attach
 * fragments.
 * 
 * <p>
 * A bundle symbolic name defines a unique fully qualified name. Wildcards may
 * be used.
 * 
 * <pre>
 * name ::= &lt;symbolic name&gt; | &lt;symbolic name ending in &quot;.*&quot;&gt; | *
 * </pre>
 * 
 * Examples:
 * 
 * <pre>
 * org.osgi.example.bundle
 * org.osgi.example.*
 * *
 * </pre>
 * 
 * <p>
 * {@code BundlePermission} has four actions: {@code provide}, {@code require},
 * {@code host}, and {@code fragment}. The {@code provide} action implies the
 * {@code require} action.
 * 
 * @since 1.3
 * @ThreadSafe
 * @author $Id: 7b0816059dc9b3e37f0375039bebbe5f0b18d998 $
 */

public final class BundlePermission extends BasicPermission {

	private static final long	serialVersionUID	= 3257846601685873716L;

	/**
	 * The action string {@code provide}. The {@code provide} action implies the
	 * {@code require} action.
	 */
	public final static String	PROVIDE				= "provide";

	/**
	 * The action string {@code require}. The {@code require} action is implied
	 * by the {@code provide} action.
	 */
	public final static String	REQUIRE				= "require";

	/**
	 * The action string {@code host}.
	 */
	public final static String	HOST				= "host";

	/**
	 * The action string {@code fragment}.
	 */
	public final static String	FRAGMENT			= "fragment";

	private final static int	ACTION_PROVIDE		= 0x00000001;
	private final static int	ACTION_REQUIRE		= 0x00000002;
	private final static int	ACTION_HOST			= 0x00000004;
	private final static int	ACTION_FRAGMENT		= 0x00000008;
	private final static int	ACTION_ALL			= ACTION_PROVIDE | ACTION_REQUIRE | ACTION_HOST | ACTION_FRAGMENT;
	final static int			ACTION_NONE			= 0;
	/**
	 * The actions mask.
	 */
	private transient int		action_mask;

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

	/**
	 * Defines the authority to provide and/or require and or specify a host
	 * fragment symbolic name within the OSGi environment.
	 * <p>
	 * Bundle Permissions are granted over all possible versions of a bundle.
	 * 
	 * A bundle that needs to provide a bundle must have the appropriate
	 * {@code BundlePermission} for the symbolic name; a bundle that requires a
	 * bundle must have the appropriate {@code BundlePermssion} for that
	 * symbolic name; a bundle that specifies a fragment host must have the
	 * appropriate {@code BundlePermission} for that symbolic name.
	 * 
	 * @param symbolicName The bundle symbolic name.
	 * @param actions {@code provide},{@code require}, {@code host},
	 *        {@code fragment} (canonical order).
	 */
	public BundlePermission(String symbolicName, String actions) {
		this(symbolicName, parseActions(actions));
	}

	/**
	 * Package private constructor used by BundlePermissionCollection.
	 * 
	 * @param symbolicName the bundle symbolic name
	 * @param mask the action mask
	 */
	BundlePermission(String symbolicName, int mask) {
		super(symbolicName);
		setTransients(mask);
	}

	/**
	 * Called by constructors and when deserialized.
	 * 
	 * @param mask
	 */
	private synchronized void setTransients(int mask) {
		if ((mask == ACTION_NONE) || ((mask & ACTION_ALL) != mask)) {
			throw new IllegalArgumentException("invalid action string");
		}

		action_mask = mask;
	}

	/**
	 * Returns the current action mask.
	 * <p>
	 * Used by the BundlePermissionCollection class.
	 * 
	 * @return Current action mask.
	 */
	synchronized int getActionsMask() {
		return action_mask;
	}

	/**
	 * Parse action string into action mask.
	 * 
	 * @param actions Action string.
	 * @return action mask.
	 */
	private static int parseActions(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 >= 6 && (a[i - 6] == 'p' || a[i - 6] == 'P')
					&& (a[i - 5] == 'r' || a[i - 5] == 'R')
					&& (a[i - 4] == 'o' || a[i - 4] == 'O')
					&& (a[i - 3] == 'v' || a[i - 3] == 'V')
					&& (a[i - 2] == 'i' || a[i - 2] == 'I')
					&& (a[i - 1] == 'd' || a[i - 1] == 'D')
					&& (a[i] == 'e' || a[i] == 'E')) {
				matchlen = 7;
				mask |= ACTION_PROVIDE | ACTION_REQUIRE;
			} else
				if (i >= 6 && (a[i - 6] == 'r' || a[i - 6] == 'R')
						&& (a[i - 5] == 'e' || a[i - 5] == 'E')
						&& (a[i - 4] == 'q' || a[i - 4] == 'Q')
						&& (a[i - 3] == 'u' || a[i - 3] == 'U')
						&& (a[i - 2] == 'i' || a[i - 2] == 'I')
						&& (a[i - 1] == 'r' || a[i - 1] == 'R')
						&& (a[i] == 'e' || a[i] == 'E')) {
					matchlen = 7;
					mask |= ACTION_REQUIRE;
				} else
					if (i >= 3 && (a[i - 3] == 'h' || a[i - 3] == 'H')
							&& (a[i - 2] == 'o' || a[i - 2] == 'O')
							&& (a[i - 1] == 's' || a[i - 1] == 'S')
							&& (a[i] == 't' || a[i] == 'T')) {
						matchlen = 4;
						mask |= ACTION_HOST;
					} else
						if (i >= 7 && (a[i - 7] == 'f' || a[i - 7] == 'F')
								&& (a[i - 6] == 'r' || a[i - 6] == 'R')
								&& (a[i - 5] == 'a' || a[i - 5] == 'A')
								&& (a[i - 4] == 'g' || a[i - 4] == 'G')
								&& (a[i - 3] == 'm' || a[i - 3] == 'M')
								&& (a[i - 2] == 'e' || a[i - 2] == 'E')
								&& (a[i - 1] == 'n' || a[i - 1] == 'N')
								&& (a[i] == 't' || a[i] == 'T')) {
							matchlen = 8;
							mask |= ACTION_FRAGMENT;
						} else {
							// parse error
							throw new IllegalArgumentException("invalid permission: " + actions);
						}

			// make sure we didn't just match the tail of a word
			// like "ackbarfrequire". 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;
	}

	/**
	 * Determines if the specified permission is implied by this object.
	 * 
	 * <p>
	 * This method checks that the symbolic name of the target is implied by the
	 * symbolic name of this object. The list of {@code BundlePermission}
	 * actions must either match or allow for the list of the target object to
	 * imply the target {@code BundlePermission} action.
	 * <p>
	 * The permission to provide a bundle implies the permission to require the
	 * named symbolic name.
	 * 
	 * <pre>
	 *       x.y.*,&quot;provide&quot; -&gt; x.y.z,&quot;provide&quot; is true
	 *       *,&quot;require&quot; -&gt; x.y, &quot;require&quot;      is true
	 *       *,&quot;provide&quot; -&gt; x.y, &quot;require&quot;      is true
	 *       x.y,&quot;provide&quot; -&gt; x.y.z, &quot;provide&quot;  is false
	 * </pre>
	 * 
	 * @param p The requested permission.
	 * @return {@code true} if the specified {@code BundlePermission} action is
	 *         implied by this object; {@code false} otherwise.
	 */
	@Override
	public boolean implies(Permission p) {
		if (!(p instanceof BundlePermission)) {
			return false;
		}
		BundlePermission requested = (BundlePermission) p;

		final int effective = getActionsMask();
		final int desired = requested.getActionsMask();
		return ((effective & desired) == desired) && super.implies(requested);
	}

	/**
	 * Returns the canonical string representation of the
	 * {@code BundlePermission} actions.
	 * 
	 * <p>
	 * Always returns present {@code BundlePermission} actions in the following
	 * order: {@code provide}, {@code require}, {@code host}, {@code fragment}.
	 * 
	 * @return Canonical string representation of the {@code BundlePermission
	 *         } actions.
	 */
	@Override
	public String getActions() {
		String result = actions;
		if (result == null) {
			StringBuilder sb = new StringBuilder();
			boolean comma = false;

			if ((action_mask & ACTION_PROVIDE) == ACTION_PROVIDE) {
				sb.append(PROVIDE);
				comma = true;
			}

			if ((action_mask & ACTION_REQUIRE) == ACTION_REQUIRE) {
				if (comma)
					sb.append(',');
				sb.append(REQUIRE);
				comma = true;
			}

			if ((action_mask & ACTION_HOST) == ACTION_HOST) {
				if (comma)
					sb.append(',');
				sb.append(HOST);
				comma = true;
			}

			if ((action_mask & ACTION_FRAGMENT) == ACTION_FRAGMENT) {
				if (comma)
					sb.append(',');
				sb.append(FRAGMENT);
			}

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

	/**
	 * Returns a new {@code PermissionCollection} object suitable for storing
	 * {@code BundlePermission} objects.
	 * 
	 * @return A new {@code PermissionCollection} object.
	 */
	@Override
	public PermissionCollection newPermissionCollection() {
		return new BundlePermissionCollection();
	}

	/**
	 * Determines the equality of two {@code BundlePermission} objects.
	 * 
	 * This method checks that specified bundle has the same bundle symbolic
	 * name and {@code BundlePermission} actions as this
	 * {@code BundlePermission} object.
	 * 
	 * @param obj The object to test for equality with this
	 *        {@code BundlePermission} object.
	 * @return {@code true} if {@code obj} is a {@code BundlePermission}, and
	 *         has the same bundle symbolic name and actions as this
	 *         {@code BundlePermission} object; {@code false} otherwise.
	 */
	@Override
	public boolean equals(Object obj) {
		if (obj == this) {
			return true;
		}

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

		BundlePermission bp = (BundlePermission) obj;

		return (getActionsMask() == bp.getActionsMask()) && getName().equals(bp.getName());
	}

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

	/**
	 * WriteObject is called to save the state of the {@code BundlePermission}
	 * 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 {
		// 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 the BundlePermission from a
	 * stream.
	 */
	private synchronized void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException {
		// Read in the action, then initialize the rest
		s.defaultReadObject();
		setTransients(parseActions(actions));
	}
}

/**
 * Stores a set of {@code BundlePermission} permissions.
 * 
 * @see java.security.Permission
 * @see java.security.Permissions
 * @see java.security.PermissionCollection
 */

final class BundlePermissionCollection extends PermissionCollection {
	private static final long						serialVersionUID	= 3258407326846433079L;

	/**
	 * Table of permissions.
	 * 
	 * @GuardedBy this
	 */
	private transient Map<String, BundlePermission>	permissions;

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

	/**
	 * Create an empty BundlePermissions object.
	 * 
	 */
	public BundlePermissionCollection() {
		permissions = new HashMap<String, BundlePermission>();
		all_allowed = false;
	}

	/**
	 * Add a permission to this permission collection.
	 * 
	 * @param permission The {@code BundlePermission} object to add.
	 * @throws IllegalArgumentException If the permission is not a
	 *         {@code BundlePermission} instance.
	 * @throws SecurityException If this {@code BundlePermissionCollection}
	 *         object has been marked read-only.
	 */
	@Override
	public void add(final Permission permission) {
		if (!(permission instanceof BundlePermission)) {
			throw new IllegalArgumentException("invalid permission: " + permission);
		}
		if (isReadOnly()) {
			throw new SecurityException("attempt to add a Permission to a " + "readonly PermissionCollection");
		}
		final BundlePermission bp = (BundlePermission) permission;
		final String name = bp.getName();
		synchronized (this) {
			Map<String, BundlePermission> pc = permissions;
			BundlePermission existing = pc.get(name);
			if (existing != null) {
				final int oldMask = existing.getActionsMask();
				final int newMask = bp.getActionsMask();
				if (oldMask != newMask) {
					pc.put(name, new BundlePermission(name, oldMask | newMask));

				}
			} else {
				pc.put(name, bp);
			}

			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 this
	 *        {@code BundlePermission} object.
	 * @return {@code true} if {@code permission} is a proper subset of a
	 *         permission in the set; {@code false} otherwise.
	 */
	@Override
	public boolean implies(final Permission permission) {
		if (!(permission instanceof BundlePermission)) {
			return false;
		}
		BundlePermission requested = (BundlePermission) permission;
		String requestedName = requested.getName();
		final int desired = requested.getActionsMask();
		int effective = BundlePermission.ACTION_NONE;
		BundlePermission bp;

		synchronized (this) {
			Map<String, BundlePermission> pc = permissions;
			/* short circuit if the "*" Permission was added */
			if (all_allowed) {
				bp = pc.get("*");
				if (bp != null) {
					effective |= bp.getActionsMask();
					if ((effective & desired) == desired) {
						return true;
					}
				}
			}
			bp = pc.get(requestedName);
			// strategy:
			// Check for full match first. Then work our way up the
			// name looking for matches on a.b.*
			if (bp != null) {
				// we have a direct hit!
				effective |= bp.getActionsMask();
				if ((effective & desired) == desired) {
					return true;
				}
			}
			// work our way up the tree...
			int last;
			int offset = requestedName.length() - 1;
			while ((last = requestedName.lastIndexOf(".", offset)) != -1) {
				requestedName = requestedName.substring(0, last + 1) + "*";
				bp = pc.get(requestedName);
				if (bp != null) {
					effective |= bp.getActionsMask();
					if ((effective & desired) == desired) {
						return true;
					}
				}
				offset = last - 1;
			}
			// we don't have to check for "*" as it was already checked
			// at the top (all_allowed), so we just return false
			return false;
		}
	}

	/**
	 * Returns an enumeration of all {@code BundlePermission} objects in the
	 * container.
	 * 
	 * @return Enumeration of all {@code BundlePermission} 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, BundlePermission> hashtable = new Hashtable<String, BundlePermission>(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, BundlePermission> hashtable = (Hashtable<String, BundlePermission>) gfields.get("permissions", null);
		permissions = new HashMap<String, BundlePermission>(hashtable);
		all_allowed = gfields.get("all_allowed", false);
	}
}
