173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root/* 273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. 373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * 573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * This code is free software; you can redistribute it and/or modify it 673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * under the terms of the GNU General Public License version 2 only, as 773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * published by the Free Software Foundation. Oracle designates this 873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * particular file as subject to the "Classpath" exception as provided 973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * by Oracle in the LICENSE file that accompanied this code. 1073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * 1173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * This code is distributed in the hope that it will be useful, but WITHOUT 1273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * version 2 for more details (a copy is included in the LICENSE file that 1573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * accompanied this code). 1673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * 1773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * You should have received a copy of the GNU General Public License version 1873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * 2 along with this work; if not, write to the Free Software Foundation, 1973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * 2173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * or visit www.oracle.com if you need additional information or have any 2373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * questions. 2473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root */ 2573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 2673405ff8729cca39da90b2e2f604062e323f6f7aKenny Rootpackage sun.security.provider.certpath; 2773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 2873405ff8729cca39da90b2e2f604062e323f6f7aKenny Rootimport java.util.Collections; 2973405ff8729cca39da90b2e2f604062e323f6f7aKenny Rootimport java.util.HashSet; 3073405ff8729cca39da90b2e2f604062e323f6f7aKenny Rootimport java.util.Iterator; 3173405ff8729cca39da90b2e2f604062e323f6f7aKenny Rootimport java.util.Set; 3273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 3373405ff8729cca39da90b2e2f604062e323f6f7aKenny Rootimport java.security.cert.*; 3473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 3573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root/** 3673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * Implements the <code>PolicyNode</code> interface. 3773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * <p> 3873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * This class provides an implementation of the <code>PolicyNode</code> 3973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * interface, and is used internally to build and search Policy Trees. 4073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * While the implementation is mutable during construction, it is immutable 4173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * before returning to a client and no mutable public or protected methods 4273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * are exposed by this implementation, as per the contract of PolicyNode. 4373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * 4473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @since 1.4 4573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @author Seth Proctor 4673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @author Sean Mullan 4773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root */ 4873405ff8729cca39da90b2e2f604062e323f6f7aKenny Rootfinal class PolicyNodeImpl implements PolicyNode { 4973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 5073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root /** 5173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * Use to specify the special policy "Any Policy" 5273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root */ 5373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root private static final String ANY_POLICY = "2.5.29.32.0"; 5473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 5573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root // every node has one parent, and zero or more children 5673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root private PolicyNodeImpl mParent; 5773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root private HashSet<PolicyNodeImpl> mChildren; 5873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 5973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root // the 4 fields specified by RFC 3280 6073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root private String mValidPolicy; 6173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root private HashSet<PolicyQualifierInfo> mQualifierSet; 6273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root private boolean mCriticalityIndicator; 6373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root private HashSet<String> mExpectedPolicySet; 6473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root private boolean mOriginalExpectedPolicySet; 6573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 6673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root // the tree depth 6773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root private int mDepth; 6873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root // immutability flag 6973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root private boolean isImmutable = false; 7073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 7173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root /** 7273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * Constructor which takes a <code>PolicyNodeImpl</code> representing the 7373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * parent in the Policy Tree to this node. If null, this is the 7473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * root of the tree. The constructor also takes the associated data 7573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * for this node, as found in the certificate. It also takes a boolean 7673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * argument specifying whether this node is being created as a result 7773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * of policy mapping. 7873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * 7973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @param parent the PolicyNode above this in the tree, or null if this 8073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * node is the tree's root node 8173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @param validPolicy a String representing this node's valid policy OID 8273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @param qualifierSet the Set of qualifiers for this policy 8373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @param criticalityIndicator a boolean representing whether or not the 8473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * extension is critical 8573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @param expectedPolicySet a Set of expected policies 8673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @param generatedByPolicyMapping a boolean indicating whether this 8773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * node was generated by a policy mapping 8873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root */ 8973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root PolicyNodeImpl(PolicyNodeImpl parent, String validPolicy, 9073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root Set<PolicyQualifierInfo> qualifierSet, 9173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root boolean criticalityIndicator, Set<String> expectedPolicySet, 9273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root boolean generatedByPolicyMapping) { 9373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root mParent = parent; 9473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root mChildren = new HashSet<PolicyNodeImpl>(); 9573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 9673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (validPolicy != null) 9773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root mValidPolicy = validPolicy; 9873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root else 9973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root mValidPolicy = ""; 10073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 10173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (qualifierSet != null) 10273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root mQualifierSet = new HashSet<PolicyQualifierInfo>(qualifierSet); 10373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root else 10473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root mQualifierSet = new HashSet<PolicyQualifierInfo>(); 10573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 10673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root mCriticalityIndicator = criticalityIndicator; 10773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 10873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (expectedPolicySet != null) 10973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root mExpectedPolicySet = new HashSet<String>(expectedPolicySet); 11073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root else 11173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root mExpectedPolicySet = new HashSet<String>(); 11273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 11373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root mOriginalExpectedPolicySet = !generatedByPolicyMapping; 11473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 11573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root // see if we're the root, and act appropriately 11673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (mParent != null) { 11773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root mDepth = mParent.getDepth() + 1; 11873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root mParent.addChild(this); 11973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } else { 12073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root mDepth = 0; 12173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 12273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 12373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 12473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root /** 12573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * Alternate constructor which makes a new node with the policy data 12673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * in an existing <code>PolicyNodeImpl</code>. 12773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * 12873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @param parent a PolicyNode that's the new parent of the node, or 12973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * null if this is the root node 13073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @param node a PolicyNode containing the policy data to copy 13173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root */ 13273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root PolicyNodeImpl(PolicyNodeImpl parent, PolicyNodeImpl node) { 13373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root this(parent, node.mValidPolicy, node.mQualifierSet, 13473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root node.mCriticalityIndicator, node.mExpectedPolicySet, false); 13573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 13673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 13773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root @Override 13873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root public PolicyNode getParent() { 13973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root return mParent; 14073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 14173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 14273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root @Override 14373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root public Iterator<PolicyNodeImpl> getChildren() { 14473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root return Collections.unmodifiableSet(mChildren).iterator(); 14573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 14673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 14773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root @Override 14873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root public int getDepth() { 14973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root return mDepth; 15073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 15173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 15273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root @Override 15373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root public String getValidPolicy() { 15473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root return mValidPolicy; 15573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 15673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 15773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root @Override 15873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root public Set<PolicyQualifierInfo> getPolicyQualifiers() { 15973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root return Collections.unmodifiableSet(mQualifierSet); 16073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 16173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 16273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root @Override 16373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root public Set<String> getExpectedPolicies() { 16473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root return Collections.unmodifiableSet(mExpectedPolicySet); 16573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 16673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 16773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root @Override 16873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root public boolean isCritical() { 16973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root return mCriticalityIndicator; 17073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 17173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 17273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root /** 17373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * Return a printable representation of the PolicyNode. 17473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * Starting at the node on which this method is called, 17573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * it recurses through the tree and prints out each node. 17673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * 17773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @return a String describing the contents of the Policy Node 17873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root */ 17973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root @Override 18073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root public String toString() { 18173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root StringBuilder buffer = new StringBuilder(this.asString()); 18273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 18373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root for (PolicyNodeImpl node : mChildren) { 18473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root buffer.append(node); 18573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 18673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root return buffer.toString(); 18773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 18873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 18973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root // private methods and package private operations 19073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 19173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root boolean isImmutable() { 19273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root return isImmutable; 19373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 19473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 19573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root /** 19673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * Sets the immutability flag of this node and all of its children 19773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * to true. 19873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root */ 19973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root void setImmutable() { 20073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (isImmutable) 20173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root return; 20273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root for (PolicyNodeImpl node : mChildren) { 20373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root node.setImmutable(); 20473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 20573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root isImmutable = true; 20673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 20773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 20873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root /** 20973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * Private method sets a child node. This is called from the child's 21073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * constructor. 21173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * 21273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @param child new <code>PolicyNodeImpl</code> child node 21373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root */ 21473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root private void addChild(PolicyNodeImpl child) { 21573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (isImmutable) { 21673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root throw new IllegalStateException("PolicyNode is immutable"); 21773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 21873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root mChildren.add(child); 21973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 22073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 22173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root /** 22273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * Adds an expectedPolicy to the expected policy set. 22373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * If this is the original expected policy set initialized 22473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * by the constructor, then the expected policy set is cleared 22573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * before the expected policy is added. 22673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * 22773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @param expectedPolicy a String representing an expected policy. 22873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root */ 22973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root void addExpectedPolicy(String expectedPolicy) { 23073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (isImmutable) { 23173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root throw new IllegalStateException("PolicyNode is immutable"); 23273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 23373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (mOriginalExpectedPolicySet) { 23473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root mExpectedPolicySet.clear(); 23573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root mOriginalExpectedPolicySet = false; 23673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 23773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root mExpectedPolicySet.add(expectedPolicy); 23873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 23973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 24073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root /** 24173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * Removes all paths which don't reach the specified depth. 24273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * 24373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @param depth an int representing the desired minimum depth of all paths 24473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root */ 24573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root void prune(int depth) { 24673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (isImmutable) 24773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root throw new IllegalStateException("PolicyNode is immutable"); 24873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 24973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root // if we have no children, we can't prune below us... 25073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (mChildren.size() == 0) 25173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root return; 25273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 25373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root Iterator<PolicyNodeImpl> it = mChildren.iterator(); 25473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root while (it.hasNext()) { 25573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root PolicyNodeImpl node = it.next(); 25673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root node.prune(depth); 25773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root // now that we've called prune on the child, see if we should 25873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root // remove it from the tree 25973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if ((node.mChildren.size() == 0) && (depth > mDepth + 1)) 26073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root it.remove(); 26173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 26273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 26373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 26473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root /** 26573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * Deletes the specified child node of this node, if it exists. 26673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * 26773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @param childNode the child node to be deleted 26873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root */ 26973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root void deleteChild(PolicyNode childNode) { 27073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (isImmutable) { 27173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root throw new IllegalStateException("PolicyNode is immutable"); 27273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 27373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root mChildren.remove(childNode); 27473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 27573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 27673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root /** 27773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * Returns a copy of the tree, without copying the policy-related data, 27873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * rooted at the node on which this was called. 27973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * 28073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @return a copy of the tree 28173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root */ 28273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root PolicyNodeImpl copyTree() { 28373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root return copyTree(null); 28473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 28573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 28673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root private PolicyNodeImpl copyTree(PolicyNodeImpl parent) { 28773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root PolicyNodeImpl newNode = new PolicyNodeImpl(parent, this); 28873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 28973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root for (PolicyNodeImpl node : mChildren) { 29073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root node.copyTree(newNode); 29173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 29273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 29373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root return newNode; 29473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 29573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 29673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root /** 29773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * Returns all nodes at the specified depth in the tree. 29873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * 29973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @param depth an int representing the depth of the desired nodes 30073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @return a <code>Set</code> of all nodes at the specified depth 30173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root */ 30273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root Set<PolicyNodeImpl> getPolicyNodes(int depth) { 30373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root Set<PolicyNodeImpl> set = new HashSet<>(); 30473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root getPolicyNodes(depth, set); 30573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root return set; 30673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 30773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 30873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root /** 30973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * Add all nodes at depth depth to set and return the Set. 31073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * Internal recursion helper. 31173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root */ 31273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root private void getPolicyNodes(int depth, Set<PolicyNodeImpl> set) { 31373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root // if we've reached the desired depth, then return ourself 31473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (mDepth == depth) { 31573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root set.add(this); 31673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } else { 31773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root for (PolicyNodeImpl node : mChildren) { 31873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root node.getPolicyNodes(depth, set); 31973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 32073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 32173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 32273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 32373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root /** 32473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * Finds all nodes at the specified depth whose expected_policy_set 32573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * contains the specified expected OID (if matchAny is false) 32673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * or the special OID "any value" (if matchAny is true). 32773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * 32873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @param depth an int representing the desired depth 32973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @param expectedOID a String encoding the valid OID to match 33073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @param matchAny a boolean indicating whether an expected_policy_set 33173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * containing ANY_POLICY should be considered a match 33273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @return a Set of matched <code>PolicyNode</code>s 33373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root */ 33473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root Set<PolicyNodeImpl> getPolicyNodesExpected(int depth, 33573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root String expectedOID, boolean matchAny) { 33673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 33773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (expectedOID.equals(ANY_POLICY)) { 33873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root return getPolicyNodes(depth); 33973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } else { 34073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root return getPolicyNodesExpectedHelper(depth, expectedOID, matchAny); 34173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 34273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 34373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 34473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root private Set<PolicyNodeImpl> getPolicyNodesExpectedHelper(int depth, 34573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root String expectedOID, boolean matchAny) { 34673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 34773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root HashSet<PolicyNodeImpl> set = new HashSet<>(); 34873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 34973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (mDepth < depth) { 35073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root for (PolicyNodeImpl node : mChildren) { 35173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root set.addAll(node.getPolicyNodesExpectedHelper(depth, 35273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root expectedOID, 35373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root matchAny)); 35473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 35573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } else { 35673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (matchAny) { 35773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (mExpectedPolicySet.contains(ANY_POLICY)) 35873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root set.add(this); 35973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } else { 36073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (mExpectedPolicySet.contains(expectedOID)) 36173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root set.add(this); 36273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 36373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 36473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 36573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root return set; 36673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 36773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 36873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root /** 36973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * Finds all nodes at the specified depth that contains the 37073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * specified valid OID 37173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * 37273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @param depth an int representing the desired depth 37373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @param validOID a String encoding the valid OID to match 37473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @return a Set of matched <code>PolicyNode</code>s 37573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root */ 37673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root Set<PolicyNodeImpl> getPolicyNodesValid(int depth, String validOID) { 37773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root HashSet<PolicyNodeImpl> set = new HashSet<>(); 37873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 37973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (mDepth < depth) { 38073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root for (PolicyNodeImpl node : mChildren) { 38173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root set.addAll(node.getPolicyNodesValid(depth, validOID)); 38273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 38373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } else { 38473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (mValidPolicy.equals(validOID)) 38573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root set.add(this); 38673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 38773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 38873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root return set; 38973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 39073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 39173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root private static String policyToString(String oid) { 39273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (oid.equals(ANY_POLICY)) { 39373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root return "anyPolicy"; 39473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } else { 39573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root return oid; 39673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 39773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 39873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root 39973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root /** 40073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * Prints out some data on this node. 40173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root */ 40273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root String asString() { 40373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root if (mParent == null) { 40473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root return "anyPolicy ROOT\n"; 40573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } else { 40673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root StringBuilder sb = new StringBuilder(); 40773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root for (int i = 0, n = getDepth(); i < n; i++) { 40873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root sb.append(" "); 40973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 41073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root sb.append(policyToString(getValidPolicy())); 41173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root sb.append(" CRIT: "); 41273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root sb.append(isCritical()); 41373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root sb.append(" EP: "); 41473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root for (String policy : getExpectedPolicies()) { 41573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root sb.append(policyToString(policy)); 41673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root sb.append(" "); 41773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 41873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root sb.append(" ("); 41973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root sb.append(getDepth()); 42073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root sb.append(")\n"); 42173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root return sb.toString(); 42273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 42373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root } 42473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root} 425