/*
 * Copyright (c) OSGi Alliance (2005, 2013). All Rights Reserved.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.osgi.service.condpermadmin;

import java.security.AccessControlContext;
import java.util.Enumeration;
import org.osgi.annotation.versioning.ProviderType;
import org.osgi.service.permissionadmin.PermissionInfo;

/**
 * Framework service to administer Conditional Permissions. Conditional
 * Permissions can be added to, retrieved from, and removed from the framework.
 * Conditional Permissions are conceptually managed in an ordered table called
 * the Conditional Permission Table.
 * 
 * @ThreadSafe
 * @author $Id: ac911fc403db63464ab69b1a5d532d1162603356 $
 */
@ProviderType
public interface ConditionalPermissionAdmin {
	/**
	 * Create a new Conditional Permission Info in the Conditional Permission
	 * Table.
	 * <p>
	 * The Conditional Permission Info will be given a unique, never reused
	 * name. This entry will be added at the beginning of the Conditional
	 * Permission Table with an access decision of
	 * {@link ConditionalPermissionInfo#ALLOW ALLOW}.
	 * <p>
	 * Since this method changes the Conditional Permission Table any
	 * {@link ConditionalPermissionUpdate}s that were created prior to calling
	 * this method can no longer be committed.
	 * 
	 * @param conditions The conditions that need to be satisfied to enable the
	 *        specified permissions. This argument can be {@code null} or an
	 *        empty array indicating the specified permissions are not guarded
	 *        by any conditions.
	 * @param permissions The permissions that are enabled when the specified
	 *        conditions, if any, are satisfied. This argument must not be
	 *        {@code null} and must specify at least one permission.
	 * @return The ConditionalPermissionInfo for the specified Conditions and
	 *         Permissions.
	 * @throws IllegalArgumentException If no permissions are specified.
	 * @throws SecurityException If the caller does not have
	 *         {@code AllPermission}.
	 * @deprecated Since 1.1. Use {@link #newConditionalPermissionUpdate()}
	 *             instead.
	 */
	ConditionalPermissionInfo addConditionalPermissionInfo(ConditionInfo[] conditions, PermissionInfo[] permissions);

	/**
	 * Set or create a Conditional Permission Info with a specified name in the
	 * Conditional Permission Table.
	 * <p>
	 * If the specified name is {@code null}, a new Conditional Permission Info
	 * must be created and will be given a unique, never reused name. If there
	 * is currently no Conditional Permission Info with the specified name, a
	 * new Conditional Permission Info must be created with the specified name.
	 * Otherwise, the Conditional Permission Info with the specified name must
	 * be updated with the specified Conditions and Permissions. If a new entry
	 * was created in the Conditional Permission Table it will be added at the
	 * beginning of the table with an access decision of
	 * {@link ConditionalPermissionInfo#ALLOW ALLOW}.
	 * <p>
	 * Since this method changes the underlying permission table any
	 * {@link ConditionalPermissionUpdate}s that were created prior to calling
	 * this method can no longer be committed.
	 * 
	 * @param name The name of the Conditional Permission Info, or {@code null}.
	 * @param conditions The conditions that need to be satisfied to enable the
	 *        specified permissions. This argument can be {@code null} or an
	 *        empty array indicating the specified permissions are not guarded
	 *        by any conditions.
	 * @param permissions The permissions that are enabled when the specified
	 *        conditions, if any, are satisfied. This argument must not be
	 *        {@code null} and must specify at least one permission.
	 * @return The ConditionalPermissionInfo for the specified name, Conditions
	 *         and Permissions.
	 * @throws IllegalArgumentException If no permissions are specified.
	 * @throws SecurityException If the caller does not have
	 *         {@code AllPermission}.
	 * @deprecated Since 1.1. Use {@link #newConditionalPermissionUpdate()}
	 *             instead.
	 */
	ConditionalPermissionInfo setConditionalPermissionInfo(String name, ConditionInfo[] conditions, PermissionInfo[] permissions);

	/**
	 * Returns the Conditional Permission Infos from the Conditional Permission
	 * Table.
	 * <p>
	 * The returned Enumeration will return elements in the order they are kept
	 * in the Conditional Permission Table.
	 * <p>
	 * The Enumeration returned is based on a copy of the Conditional Permission
	 * Table and therefore will not throw exceptions if the Conditional
	 * Permission Table is changed during the course of reading elements from
	 * the Enumeration.
	 * 
	 * @return An enumeration of the Conditional Permission Infos that are
	 *         currently in the Conditional Permission Table.
	 * @deprecated Since 1.1. Use {@link #newConditionalPermissionUpdate()}
	 *             instead.
	 */
	Enumeration<ConditionalPermissionInfo> getConditionalPermissionInfos();

	/**
	 * Return the Conditional Permission Info with the specified name.
	 * 
	 * @param name The name of the Conditional Permission Info to be returned.
	 * @return The Conditional Permission Info with the specified name or
	 *         {@code null} if no Conditional Permission Info with the specified
	 *         name exists in the Conditional Permission Table.
	 * @deprecated Since 1.1. Use {@link #newConditionalPermissionUpdate()}
	 *             instead.
	 */
	ConditionalPermissionInfo getConditionalPermissionInfo(String name);

	/**
	 * Returns the Access Control Context that corresponds to the specified
	 * signers.
	 * 
	 * The returned Access Control Context must act as if its protection domain
	 * came from a bundle that has the following characteristics:
	 * <ul>
	 * <li>It is signed by all of the given signers</li>
	 * <li>It has a bundle id of -1</li>
	 * <li>Its location is the empty string</li>
	 * <li>Its state is UNINSTALLED</li>
	 * <li>It has no headers</li>
	 * <li>It has the empty version (0.0.0)</li>
	 * <li>Its last modified time=0</li>
	 * <li>Many methods will throw {@code IllegalStateException} because the
	 * state is UNINSTALLED</li>
	 * <li>All other methods return a {@code null}</li>
	 * </ul>
	 * 
	 * @param signers The signers for which to return an Access Control Context.
	 * @return An {@code AccessControlContext} that has the Permissions
	 *         associated with the signer.
	 */
	AccessControlContext getAccessControlContext(String[] signers);

	/**
	 * Creates a new update for the Conditional Permission Table. The update is
	 * a working copy of the current Conditional Permission Table. If the
	 * running Conditional Permission Table is modified before commit is called
	 * on the returned update, then the call to commit on the returned update
	 * will fail. That is, the commit method will return false and no change
	 * will be made to the running Conditional Permission Table. There is no
	 * requirement that commit is eventually called on the returned update.
	 * 
	 * @return A new update for the Conditional Permission Table.
	 * @since 1.1
	 */
	ConditionalPermissionUpdate newConditionalPermissionUpdate();

	/**
	 * Creates a new ConditionalPermissionInfo with the specified fields
	 * suitable for insertion into a {@link ConditionalPermissionUpdate}. The
	 * {@code delete} method on {@code ConditionalPermissionInfo} objects
	 * created with this method must throw UnsupportedOperationException.
	 * 
	 * @param name The name of the created {@code ConditionalPermissionInfo} or
	 *        {@code null} to have a unique name generated when the returned
	 *        {@code ConditionalPermissionInfo} is committed in an update to the
	 *        Conditional Permission Table.
	 * @param conditions The conditions that need to be satisfied to enable the
	 *        specified permissions. This argument can be {@code null} or an
	 *        empty array indicating the specified permissions are not guarded
	 *        by any conditions.
	 * @param permissions The permissions that are enabled when the specified
	 *        conditions, if any, are satisfied. This argument must not be
	 *        {@code null} and must specify at least one permission.
	 * @param access Access decision. Must be one of the following values:
	 *        <ul>
	 *        <li>{@link ConditionalPermissionInfo#ALLOW allow}</li>
	 *        <li>{@link ConditionalPermissionInfo#DENY deny}</li>
	 *        </ul>
	 *        The specified access decision value must be evaluated case
	 *        insensitively.
	 * @return A {@code ConditionalPermissionInfo} object suitable for insertion
	 *         into a {@link ConditionalPermissionUpdate}.
	 * @throws IllegalArgumentException If no permissions are specified or if
	 *         the specified access decision is not a valid value.
	 * @since 1.1
	 */
	ConditionalPermissionInfo newConditionalPermissionInfo(String name, ConditionInfo[] conditions, PermissionInfo[] permissions, String access);

	/**
	 * Creates a new {@code ConditionalPermissionInfo} from the specified
	 * encoded {@code ConditionalPermissionInfo} string suitable for insertion
	 * into a {@link ConditionalPermissionUpdate}. The {@code delete} method on
	 * {@code ConditionalPermissionInfo} objects created with this method must
	 * throw UnsupportedOperationException.
	 * 
	 * @param encodedConditionalPermissionInfo The encoded
	 *        {@code ConditionalPermissionInfo}. White space in the encoded
	 *        {@code ConditionalPermissionInfo} is ignored. The access decision
	 *        value in the encoded {@code ConditionalPermissionInfo} must be
	 *        evaluated case insensitively. If the encoded
	 *        {@code ConditionalPermissionInfo} does not contain the optional
	 *        name, {@code null} must be used for the name and a unique name
	 *        will be generated when the returned
	 *        {@code ConditionalPermissionInfo} is committed in an update to the
	 *        Conditional Permission Table.
	 * @return A {@code ConditionalPermissionInfo} object suitable for insertion
	 *         into a {@link ConditionalPermissionUpdate}.
	 * @throws IllegalArgumentException If the specified
	 *         {@code encodedConditionalPermissionInfo} is not properly
	 *         formatted.
	 * @see ConditionalPermissionInfo#getEncoded()
	 * @since 1.1
	 */
	ConditionalPermissionInfo newConditionalPermissionInfo(String encodedConditionalPermissionInfo);
}
