/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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. */ /* * Copyright (C) 2008 The Android Open Source Project * * 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 java.security; import org.apache.harmony.security.fortress.PolicyUtils; import java.util.ArrayList; /** * {@code AccessControlContext} encapsulates the {@code ProtectionDomain}s on * which access control decisions are based. */ public final class AccessControlContext { // List of ProtectionDomains wrapped by the AccessControlContext // It has the following characteristics: // - 'context' can not be null // - never contains null(s) // - all elements are unique (no dups) ProtectionDomain[] context; DomainCombiner combiner; // An AccessControlContext inherited by the current thread from its parent private AccessControlContext inherited; /** * Constructs a new instance of {@code AccessControlContext} with the * specified {@code AccessControlContext} and {@code DomainCombiner}. *
* If a {@code SecurityManager} is installed, code calling this constructor
* need the {@code SecurityPermission} {@code createAccessControlContext} to
* be granted, otherwise a {@code SecurityException} will be thrown.
*
* @param acc
* the {@code AccessControlContext} related to the given {@code
* DomainCombiner}
* @param combiner
* the {@code DomainCombiner} related to the given {@code
* AccessControlContext}
* @throws SecurityException
* if a {@code SecurityManager} is installed and the caller does
* not have permission to invoke this constructor
* @throws NullPointerException
* if {@code acc} is {@code null}
* @since Android 1.0
*/
public AccessControlContext(AccessControlContext acc,
DomainCombiner combiner) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new SecurityPermission(
"createAccessControlContext"));
}
// no need to clone() here as ACC is immutable
this.context = acc.context;
this.combiner = combiner;
}
/**
* Constructs a new instance of {@code AccessControlContext} with the
* specified array of {@code ProtectionDomain}s.
*
* @param context
* the {@code ProtectionDomain}s that are used to perform access
* checks in the context of this {@code AccessControlContext}
* @throws NullPointerException
* if {@code context} is {@code null}
* @since Android 1.0
*/
public AccessControlContext(ProtectionDomain[] context) {
if (context == null) {
throw new NullPointerException("context can not be null");
}
if (context.length != 0) {
// remove dup entries
ArrayList
* A permission is considered granted if every {@link ProtectionDomain} in
* this context has been granted the specified permission.
*
* If privileged operations are on the call stack, only the {@code
* ProtectionDomain}s from the last privileged operation are taken into
* account.
*
* If inherited methods are on the call stack, the protection domains of the
* declaring classes are checked, not the protection domains of the classes
* on which the method is invoked.
*
* @param perm
* the permission to check against the policy
* @throws AccessControlException
* if the specified permission is not granted
* @throws NullPointerException
* if the specified permission is {@code null}
* @see AccessController#checkPermission(Permission)
* @since Android 1.0
*/
public void checkPermission(Permission perm) throws AccessControlException {
if (perm == null) {
throw new NullPointerException("Permission cannot be null");
}
for (int i = 0; i < context.length; i++) {
if (!context[i].implies(perm)) {
throw new AccessControlException("Permission check failed "
+ perm, perm);
}
}
if (inherited != null) {
inherited.checkPermission(perm);
}
}
/**
* Compares the specified object with this {@code AccessControlContext} for
* equality. Returns {@code true} if the specified object is also an
* instance of {@code AccessControlContext}, and the two contexts
* encapsulate the same {@code ProtectionDomain}s. The order of the {@code
* ProtectionDomain}s is ignored by this method.
*
* @param obj
* object to be compared for equality with this {@code
* AccessControlContext}
* @return {@code true} if the specified object is equal to this {@code
* AccessControlContext}, otherwise {@code false}
* @since Android 1.0
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof AccessControlContext) {
AccessControlContext that = (AccessControlContext) obj;
if (!(PolicyUtils.matchSubset(context, that.context) && PolicyUtils
.matchSubset(that.context, context))) {
return false;
}
// BEGIN android-changed
if(combiner != null) {
return combiner.equals(that.combiner);
}
return that.combiner == null;
// END android-changed
}
return false;
}
/**
* Returns the {@code DomainCombiner} associated with this {@code
* AccessControlContext}.
*
* If a {@code SecurityManager} is installed, code calling this method needs
* the {@code SecurityPermission} {@code getDomainCombiner} to be granted,
* otherwise a {@code SecurityException} will be thrown.
*
* @return the {@code DomainCombiner} associated with this {@code
* AccessControlContext}
* @throws SecurityException
* if a {@code SecurityManager} is installed and the caller does
* not have permission to invoke this method
* @since Android 1.0
*/
public DomainCombiner getDomainCombiner() {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new SecurityPermission("getDomainCombiner"));
}
return combiner;
}
/**
* Returns the hash code value for this {@code AccessControlContext}.
* Returns the same hash code for {@code AccessControlContext}s that are
* equal to each other as required by the general contract of
* {@link Object#hashCode}.
*
* @return the hash code value for this {@code AccessControlContext}
* @see Object#equals(Object)
* @see AccessControlContext#equals(Object)
* @since Android 1.0
*/
public int hashCode() {
int hash = 0;
for (int i = 0; i < context.length; i++) {
hash ^= context[i].hashCode();
}
return hash;
}
}
* ProtectionDomains passed as stack
is then passed into
* {@link #AccessControlContext(ProtectionDomain[])}, therefore:
*
* ProtectionDomains passed as stack
is then passed into
* {@link #AccessControlContext(ProtectionDomain[])}, therefore:
*