Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/security/provider/certpath/PolicyNodeImpl.java
38923 views
/*1* Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.security.provider.certpath;2627import java.util.Collections;28import java.util.HashSet;29import java.util.Iterator;30import java.util.Set;3132import java.security.cert.*;3334/**35* Implements the <code>PolicyNode</code> interface.36* <p>37* This class provides an implementation of the <code>PolicyNode</code>38* interface, and is used internally to build and search Policy Trees.39* While the implementation is mutable during construction, it is immutable40* before returning to a client and no mutable public or protected methods41* are exposed by this implementation, as per the contract of PolicyNode.42*43* @since 1.444* @author Seth Proctor45* @author Sean Mullan46*/47final class PolicyNodeImpl implements PolicyNode {4849/**50* Use to specify the special policy "Any Policy"51*/52private static final String ANY_POLICY = "2.5.29.32.0";5354// every node has one parent, and zero or more children55private PolicyNodeImpl mParent;56private HashSet<PolicyNodeImpl> mChildren;5758// the 4 fields specified by RFC 528059private String mValidPolicy;60private HashSet<PolicyQualifierInfo> mQualifierSet;61private boolean mCriticalityIndicator;62private HashSet<String> mExpectedPolicySet;63private boolean mOriginalExpectedPolicySet;6465// the tree depth66private int mDepth;67// immutability flag68private boolean isImmutable = false;6970/**71* Constructor which takes a <code>PolicyNodeImpl</code> representing the72* parent in the Policy Tree to this node. If null, this is the73* root of the tree. The constructor also takes the associated data74* for this node, as found in the certificate. It also takes a boolean75* argument specifying whether this node is being created as a result76* of policy mapping.77*78* @param parent the PolicyNode above this in the tree, or null if this79* node is the tree's root node80* @param validPolicy a String representing this node's valid policy OID81* @param qualifierSet the Set of qualifiers for this policy82* @param criticalityIndicator a boolean representing whether or not the83* extension is critical84* @param expectedPolicySet a Set of expected policies85* @param generatedByPolicyMapping a boolean indicating whether this86* node was generated by a policy mapping87*/88PolicyNodeImpl(PolicyNodeImpl parent, String validPolicy,89Set<PolicyQualifierInfo> qualifierSet,90boolean criticalityIndicator, Set<String> expectedPolicySet,91boolean generatedByPolicyMapping) {92mParent = parent;93mChildren = new HashSet<PolicyNodeImpl>();9495if (validPolicy != null)96mValidPolicy = validPolicy;97else98mValidPolicy = "";99100if (qualifierSet != null)101mQualifierSet = new HashSet<PolicyQualifierInfo>(qualifierSet);102else103mQualifierSet = new HashSet<PolicyQualifierInfo>();104105mCriticalityIndicator = criticalityIndicator;106107if (expectedPolicySet != null)108mExpectedPolicySet = new HashSet<String>(expectedPolicySet);109else110mExpectedPolicySet = new HashSet<String>();111112mOriginalExpectedPolicySet = !generatedByPolicyMapping;113114// see if we're the root, and act appropriately115if (mParent != null) {116mDepth = mParent.getDepth() + 1;117mParent.addChild(this);118} else {119mDepth = 0;120}121}122123/**124* Alternate constructor which makes a new node with the policy data125* in an existing <code>PolicyNodeImpl</code>.126*127* @param parent a PolicyNode that's the new parent of the node, or128* null if this is the root node129* @param node a PolicyNode containing the policy data to copy130*/131PolicyNodeImpl(PolicyNodeImpl parent, PolicyNodeImpl node) {132this(parent, node.mValidPolicy, node.mQualifierSet,133node.mCriticalityIndicator, node.mExpectedPolicySet, false);134}135136@Override137public PolicyNode getParent() {138return mParent;139}140141@Override142public Iterator<PolicyNodeImpl> getChildren() {143return Collections.unmodifiableSet(mChildren).iterator();144}145146@Override147public int getDepth() {148return mDepth;149}150151@Override152public String getValidPolicy() {153return mValidPolicy;154}155156@Override157public Set<PolicyQualifierInfo> getPolicyQualifiers() {158return Collections.unmodifiableSet(mQualifierSet);159}160161@Override162public Set<String> getExpectedPolicies() {163return Collections.unmodifiableSet(mExpectedPolicySet);164}165166@Override167public boolean isCritical() {168return mCriticalityIndicator;169}170171/**172* Return a printable representation of the PolicyNode.173* Starting at the node on which this method is called,174* it recurses through the tree and prints out each node.175*176* @return a String describing the contents of the Policy Node177*/178@Override179public String toString() {180StringBuilder buffer = new StringBuilder(this.asString());181182for (PolicyNodeImpl node : mChildren) {183buffer.append(node);184}185return buffer.toString();186}187188// private methods and package private operations189190boolean isImmutable() {191return isImmutable;192}193194/**195* Sets the immutability flag of this node and all of its children196* to true.197*/198void setImmutable() {199if (isImmutable)200return;201for (PolicyNodeImpl node : mChildren) {202node.setImmutable();203}204isImmutable = true;205}206207/**208* Private method sets a child node. This is called from the child's209* constructor.210*211* @param child new <code>PolicyNodeImpl</code> child node212*/213private void addChild(PolicyNodeImpl child) {214if (isImmutable) {215throw new IllegalStateException("PolicyNode is immutable");216}217mChildren.add(child);218}219220/**221* Adds an expectedPolicy to the expected policy set.222* If this is the original expected policy set initialized223* by the constructor, then the expected policy set is cleared224* before the expected policy is added.225*226* @param expectedPolicy a String representing an expected policy.227*/228void addExpectedPolicy(String expectedPolicy) {229if (isImmutable) {230throw new IllegalStateException("PolicyNode is immutable");231}232if (mOriginalExpectedPolicySet) {233mExpectedPolicySet.clear();234mOriginalExpectedPolicySet = false;235}236mExpectedPolicySet.add(expectedPolicy);237}238239/**240* Removes all paths which don't reach the specified depth.241*242* @param depth an int representing the desired minimum depth of all paths243*/244void prune(int depth) {245if (isImmutable)246throw new IllegalStateException("PolicyNode is immutable");247248// if we have no children, we can't prune below us...249if (mChildren.size() == 0)250return;251252Iterator<PolicyNodeImpl> it = mChildren.iterator();253while (it.hasNext()) {254PolicyNodeImpl node = it.next();255node.prune(depth);256// now that we've called prune on the child, see if we should257// remove it from the tree258if ((node.mChildren.size() == 0) && (depth > mDepth + 1))259it.remove();260}261}262263/**264* Deletes the specified child node of this node, if it exists.265*266* @param childNode the child node to be deleted267*/268void deleteChild(PolicyNode childNode) {269if (isImmutable) {270throw new IllegalStateException("PolicyNode is immutable");271}272mChildren.remove(childNode);273}274275/**276* Returns a copy of the tree, without copying the policy-related data,277* rooted at the node on which this was called.278*279* @return a copy of the tree280*/281PolicyNodeImpl copyTree() {282return copyTree(null);283}284285private PolicyNodeImpl copyTree(PolicyNodeImpl parent) {286PolicyNodeImpl newNode = new PolicyNodeImpl(parent, this);287288for (PolicyNodeImpl node : mChildren) {289node.copyTree(newNode);290}291292return newNode;293}294295/**296* Returns all nodes at the specified depth in the tree.297*298* @param depth an int representing the depth of the desired nodes299* @return a <code>Set</code> of all nodes at the specified depth300*/301Set<PolicyNodeImpl> getPolicyNodes(int depth) {302Set<PolicyNodeImpl> set = new HashSet<>();303getPolicyNodes(depth, set);304return set;305}306307/**308* Add all nodes at depth depth to set and return the Set.309* Internal recursion helper.310*/311private void getPolicyNodes(int depth, Set<PolicyNodeImpl> set) {312// if we've reached the desired depth, then return ourself313if (mDepth == depth) {314set.add(this);315} else {316for (PolicyNodeImpl node : mChildren) {317node.getPolicyNodes(depth, set);318}319}320}321322/**323* Finds all nodes at the specified depth whose expected_policy_set324* contains the specified expected OID (if matchAny is false)325* or the special OID "any value" (if matchAny is true).326*327* @param depth an int representing the desired depth328* @param expectedOID a String encoding the valid OID to match329* @param matchAny a boolean indicating whether an expected_policy_set330* containing ANY_POLICY should be considered a match331* @return a Set of matched <code>PolicyNode</code>s332*/333Set<PolicyNodeImpl> getPolicyNodesExpected(int depth,334String expectedOID, boolean matchAny) {335336if (expectedOID.equals(ANY_POLICY)) {337return getPolicyNodes(depth);338} else {339return getPolicyNodesExpectedHelper(depth, expectedOID, matchAny);340}341}342343private Set<PolicyNodeImpl> getPolicyNodesExpectedHelper(int depth,344String expectedOID, boolean matchAny) {345346HashSet<PolicyNodeImpl> set = new HashSet<>();347348if (mDepth < depth) {349for (PolicyNodeImpl node : mChildren) {350set.addAll(node.getPolicyNodesExpectedHelper(depth,351expectedOID,352matchAny));353}354} else {355if (matchAny) {356if (mExpectedPolicySet.contains(ANY_POLICY))357set.add(this);358} else {359if (mExpectedPolicySet.contains(expectedOID))360set.add(this);361}362}363364return set;365}366367/**368* Finds all nodes at the specified depth that contains the369* specified valid OID370*371* @param depth an int representing the desired depth372* @param validOID a String encoding the valid OID to match373* @return a Set of matched <code>PolicyNode</code>s374*/375Set<PolicyNodeImpl> getPolicyNodesValid(int depth, String validOID) {376HashSet<PolicyNodeImpl> set = new HashSet<>();377378if (mDepth < depth) {379for (PolicyNodeImpl node : mChildren) {380set.addAll(node.getPolicyNodesValid(depth, validOID));381}382} else {383if (mValidPolicy.equals(validOID))384set.add(this);385}386387return set;388}389390private static String policyToString(String oid) {391if (oid.equals(ANY_POLICY)) {392return "anyPolicy";393} else {394return oid;395}396}397398/**399* Prints out some data on this node.400*/401String asString() {402if (mParent == null) {403return "anyPolicy ROOT\n";404} else {405StringBuilder sb = new StringBuilder();406for (int i = 0, n = getDepth(); i < n; i++) {407sb.append(" ");408}409sb.append(policyToString(getValidPolicy()));410sb.append(" CRIT: ");411sb.append(isCritical());412sb.append(" EP: ");413for (String policy : getExpectedPolicies()) {414sb.append(policyToString(policy));415sb.append(" ");416}417sb.append(" (");418sb.append(getDepth());419sb.append(")\n");420return sb.toString();421}422}423}424425426