| /* | |
| * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. | |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| * | |
| * This code is free software; you can redistribute it and/or modify it | |
| * under the terms of the GNU General Public License version 2 only, as | |
| * published by the Free Software Foundation. Oracle designates this | |
| * particular file as subject to the "Classpath" exception as provided | |
| * by Oracle in the LICENSE file that accompanied this code. | |
| * | |
| * This code is distributed in the hope that it will be useful, but WITHOUT | |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| * version 2 for more details (a copy is included in the LICENSE file that | |
| * accompanied this code). | |
| * | |
| * You should have received a copy of the GNU General Public License version | |
| * 2 along with this work; if not, write to the Free Software Foundation, | |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| * | |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| * or visit www.oracle.com if you need additional information or have any | |
| * questions. | |
| */ | |
| package java.security; | |
| import java.util.ArrayList; | |
| import java.util.List; | |
| /** | |
| * {@code AccessControlContext} was used with the Security Manager for access | |
| * control decisions based on context that it encapsulated. This feature no | |
| * longer exists. | |
| * | |
| * @author Roland Schemers | |
| * @since 1.2 | |
| * @deprecated This class was only useful in conjunction with the {@linkplain | |
| * SecurityManager the Security Manager}, which is no longer supported. | |
| * There is no replacement for the Security Manager or this class. | |
| */ | |
| @Deprecated(since="17", forRemoval=true) | |
| public final class AccessControlContext { | |
| private ProtectionDomain[] context; | |
| @SuppressWarnings("removal") | |
| private DomainCombiner combiner = null; | |
| /** | |
| * Create an {@code AccessControlContext} with the given array of | |
| * {@code ProtectionDomain} objects. | |
| * Context must not be {@code null}. Duplicate domains will be removed | |
| * from the context. | |
| * | |
| * @param context the {@code ProtectionDomain} objects associated with this | |
| * context. The non-duplicate domains are copied from the array. Subsequent | |
| * changes to the array will not affect this {@code AccessControlContext}. | |
| * @throws NullPointerException if {@code context} is {@code null} | |
| */ | |
| public AccessControlContext(ProtectionDomain[] context) | |
| { | |
| if (context.length == 0) { | |
| this.context = null; | |
| } else if (context.length == 1) { | |
| if (context[0] != null) { | |
| this.context = context.clone(); | |
| } else { | |
| this.context = null; | |
| } | |
| } else { | |
| List<ProtectionDomain> v = new ArrayList<>(context.length); | |
| for (int i =0; i< context.length; i++) { | |
| if ((context[i] != null) && (!v.contains(context[i]))) | |
| v.add(context[i]); | |
| } | |
| if (!v.isEmpty()) { | |
| this.context = new ProtectionDomain[v.size()]; | |
| this.context = v.toArray(this.context); | |
| } | |
| } | |
| } | |
| /** | |
| * Create a new {@code AccessControlContext} with the given | |
| * {@code AccessControlContext} and {@code DomainCombiner}. | |
| * This constructor associates the provided | |
| * {@code DomainCombiner} with the provided | |
| * {@code AccessControlContext}. | |
| * | |
| * @param acc the {@code AccessControlContext} associated | |
| * with the provided {@code DomainCombiner}. | |
| * | |
| * @param combiner the {@code DomainCombiner} to be associated | |
| * with the provided {@code AccessControlContext}. | |
| * | |
| * @throws NullPointerException if the provided | |
| * {@code context} is {@code null}. | |
| * | |
| * @since 1.3 | |
| */ | |
| public AccessControlContext(AccessControlContext acc, | |
| @SuppressWarnings("removal") DomainCombiner combiner) { | |
| this.context = acc.context; | |
| this.combiner = combiner; | |
| } | |
| /** | |
| * Get the {@code DomainCombiner} associated with this | |
| * {@code AccessControlContext}. | |
| * | |
| * @return the {@code DomainCombiner} associated with this | |
| * {@code AccessControlContext}, or {@code null} | |
| * if there is none. | |
| * | |
| * @since 1.3 | |
| */ | |
| @SuppressWarnings("removal") | |
| public DomainCombiner getDomainCombiner() { | |
| return combiner; | |
| } | |
| /** | |
| * Throws {@code AccessControlException}. | |
| * | |
| * @param perm ignored | |
| * @throws AccessControlException always | |
| */ | |
| @SuppressWarnings("removal") | |
| public void checkPermission(Permission perm) | |
| throws AccessControlException | |
| { | |
| throw new AccessControlException("checking permissions is not supported"); | |
| } | |
| /** | |
| * Checks two {@code AccessControlContext} objects for equality. | |
| * Checks that {@code obj} is | |
| * an {@code AccessControlContext} and has the same set of | |
| * {@code ProtectionDomain} objects as this context. | |
| * | |
| * @param obj the object we are testing for equality with this object. | |
| * @return {@code true} if {@code obj} is an {@code AccessControlContext}, | |
| * and has the same set of {@code ProtectionDomain} objects as this context, | |
| * {@code false} otherwise. | |
| */ | |
| @Override | |
| public boolean equals(Object obj) { | |
| if (obj == this) | |
| return true; | |
| return obj instanceof AccessControlContext that | |
| && equalContext(that); | |
| } | |
| /* | |
| * Compare for equality based on state that is free of limited | |
| * privilege complications. | |
| */ | |
| private boolean equalContext(AccessControlContext that) { | |
| if (!equalPDs(this.context, that.context)) | |
| return false; | |
| if (this.combiner == null && that.combiner != null) | |
| return false; | |
| if (this.combiner != null && !this.combiner.equals(that.combiner)) | |
| return false; | |
| return true; | |
| } | |
| private boolean equalPDs(ProtectionDomain[] a, ProtectionDomain[] b) { | |
| if (a == null) { | |
| return (b == null); | |
| } | |
| if (b == null) | |
| return false; | |
| if (!(containsAllPDs(a, b) && containsAllPDs(b, a))) | |
| return false; | |
| return true; | |
| } | |
| private static boolean containsAllPDs(ProtectionDomain[] thisContext, | |
| ProtectionDomain[] thatContext) { | |
| boolean match = false; | |
| // | |
| // ProtectionDomains within an ACC currently cannot be null | |
| // and this is enforced by the constructor and the various | |
| // optimize methods. However, historically this logic made attempts | |
| // to support the notion of a null PD and therefore this logic continues | |
| // to support that notion. | |
| ProtectionDomain thisPd; | |
| for (int i = 0; i < thisContext.length; i++) { | |
| match = false; | |
| if ((thisPd = thisContext[i]) == null) { | |
| for (int j = 0; (j < thatContext.length) && !match; j++) { | |
| match = (thatContext[j] == null); | |
| } | |
| } else { | |
| Class<?> thisPdClass = thisPd.getClass(); | |
| ProtectionDomain thatPd; | |
| for (int j = 0; (j < thatContext.length) && !match; j++) { | |
| thatPd = thatContext[j]; | |
| // Class check required to avoid PD exposure (4285406) | |
| match = (thatPd != null && | |
| thisPdClass == thatPd.getClass() && thisPd.equals(thatPd)); | |
| } | |
| } | |
| if (!match) return false; | |
| } | |
| return match; | |
| } | |
| /** | |
| * {@return the hash code value for this context} | |
| * The hash code is computed by exclusive or-ing the hash code of all the | |
| * protection domains in the context together. | |
| */ | |
| @Override | |
| public int hashCode() { | |
| int hashCode = 0; | |
| if (context == null) | |
| return hashCode; | |
| for (ProtectionDomain protectionDomain : context) { | |
| if (protectionDomain != null) | |
| hashCode ^= protectionDomain.hashCode(); | |
| } | |
| return hashCode; | |
| } | |
| } |