1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/AssertionSet.java Wed Apr 27 01:27:09 2016 +0800 1.3 @@ -0,0 +1,397 @@ 1.4 +/* 1.5 + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. Oracle designates this 1.11 + * particular file as subject to the "Classpath" exception as provided 1.12 + * by Oracle in the LICENSE file that accompanied this code. 1.13 + * 1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.17 + * version 2 for more details (a copy is included in the LICENSE file that 1.18 + * accompanied this code). 1.19 + * 1.20 + * You should have received a copy of the GNU General Public License version 1.21 + * 2 along with this work; if not, write to the Free Software Foundation, 1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.23 + * 1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.25 + * or visit www.oracle.com if you need additional information or have any 1.26 + * questions. 1.27 + */ 1.28 + 1.29 +package com.sun.xml.internal.ws.policy; 1.30 + 1.31 +import java.util.Collection; 1.32 +import java.util.Collections; 1.33 +import java.util.Comparator; 1.34 +import java.util.Iterator; 1.35 +import java.util.Set; 1.36 +import java.util.TreeSet; 1.37 + 1.38 +import javax.xml.namespace.QName; 1.39 + 1.40 +import com.sun.xml.internal.ws.policy.privateutil.LocalizationMessages; 1.41 +import com.sun.xml.internal.ws.policy.privateutil.PolicyUtils; 1.42 +import java.util.LinkedList; 1.43 +import java.util.List; 1.44 + 1.45 +/** 1.46 + * The AssertionSet is a set of assertions. It represents a single policy alternative. 1.47 + * 1.48 + * @author Fabian Ritzmann, Marek Potociar 1.49 + */ 1.50 +public final class AssertionSet implements Iterable<PolicyAssertion>, Comparable<AssertionSet> { 1.51 + private static final AssertionSet EMPTY_ASSERTION_SET = new AssertionSet(Collections.unmodifiableList(new LinkedList<PolicyAssertion>())); 1.52 + /** 1.53 + * The comparator comapres policy assertions according to their publicly accessible attributes, in the following 1.54 + * order of attributes: 1.55 + * 1.56 + * 1. namespace (not null String) 1.57 + * 2. local name (not null String) 1.58 + * 3. value (String): null < "" < "not empty" 1.59 + * 4. has nested assertions (boolean): false < true 1.60 + * 5. has nested policy (boolean): false < true 1.61 + * 6. hashCode comparison 1.62 + */ 1.63 + private static final Comparator<PolicyAssertion> ASSERTION_COMPARATOR = new Comparator<PolicyAssertion>() { 1.64 + public int compare(final PolicyAssertion pa1, final PolicyAssertion pa2) { 1.65 + if (pa1.equals(pa2)) { 1.66 + return 0; 1.67 + } 1.68 + 1.69 + int result; 1.70 + 1.71 + result = PolicyUtils.Comparison.QNAME_COMPARATOR.compare(pa1.getName(), pa2.getName()); 1.72 + if (result != 0) { 1.73 + return result; 1.74 + } 1.75 + 1.76 + result = PolicyUtils.Comparison.compareNullableStrings(pa1.getValue(), pa2.getValue()); 1.77 + if (result != 0) { 1.78 + return result; 1.79 + } 1.80 + 1.81 + result = PolicyUtils.Comparison.compareBoolean(pa1.hasNestedAssertions(), pa2.hasNestedAssertions()); 1.82 + if (result != 0) { 1.83 + return result; 1.84 + } 1.85 + 1.86 + result = PolicyUtils.Comparison.compareBoolean(pa1.hasNestedPolicy(), pa2.hasNestedPolicy()); 1.87 + if (result != 0) { 1.88 + return result; 1.89 + } 1.90 + 1.91 + return Math.round(Math.signum(pa1.hashCode() - pa2.hashCode())); 1.92 + } 1.93 + }; 1.94 + 1.95 + private final List<PolicyAssertion> assertions; 1.96 + private final Set<QName> vocabulary = new TreeSet<QName>(PolicyUtils.Comparison.QNAME_COMPARATOR); 1.97 + private final Collection<QName> immutableVocabulary = Collections.unmodifiableCollection(vocabulary); 1.98 + 1.99 + private AssertionSet(List<PolicyAssertion> list) { 1.100 + assert (list != null) : LocalizationMessages.WSP_0037_PRIVATE_CONSTRUCTOR_DOES_NOT_TAKE_NULL(); 1.101 + this.assertions = list; 1.102 + } 1.103 + 1.104 + private AssertionSet(final Collection<AssertionSet> alternatives) { 1.105 + this.assertions = new LinkedList<PolicyAssertion>(); 1.106 + for (AssertionSet alternative : alternatives) { 1.107 + addAll(alternative.assertions); 1.108 + } 1.109 + } 1.110 + 1.111 + private boolean add(final PolicyAssertion assertion) { 1.112 + if (assertion == null) { 1.113 + return false; 1.114 + } 1.115 + 1.116 + if (this.assertions.contains(assertion)) { 1.117 + return false; 1.118 + } else { 1.119 + this.assertions.add(assertion); 1.120 + this.vocabulary.add(assertion.getName()); 1.121 + return true; 1.122 + } 1.123 + } 1.124 + 1.125 + private boolean addAll(final Collection<? extends PolicyAssertion> assertions) { 1.126 + boolean result = true; 1.127 + 1.128 + if (assertions != null) { 1.129 + for (PolicyAssertion assertion : assertions) { 1.130 + result &= add(assertion); // this is here to ensure that vocabulary is built correctly as well 1.131 + } 1.132 + } 1.133 + 1.134 + return result; 1.135 + } 1.136 + 1.137 + /** 1.138 + * Return all assertions contained in this assertion set. 1.139 + * 1.140 + * @return All assertions contained in this assertion set 1.141 + */ 1.142 + Collection<PolicyAssertion> getAssertions() { 1.143 + return assertions; 1.144 + } 1.145 + 1.146 + /** 1.147 + * Retrieves the vocabulary of this policy expression. The vocabulary is represented by an immutable collection of 1.148 + * unique QName objects. Each of those objects represents single assertion type contained in the assertion set. 1.149 + * 1.150 + * @return immutable collection of assertion types contained in the assertion set (a policy vocabulary). 1.151 + */ 1.152 + Collection<QName> getVocabulary() { 1.153 + return immutableVocabulary; 1.154 + } 1.155 + 1.156 + /** 1.157 + * Checks whether this policy alternative is compatible with the provided policy alternative. 1.158 + * 1.159 + * @param alternative policy alternative used for compatibility test 1.160 + * @param mode compatibility mode to be used 1.161 + * @return {@code true} if the two policy alternatives are compatible, {@code false} otherwise 1.162 + */ 1.163 + boolean isCompatibleWith(final AssertionSet alternative, PolicyIntersector.CompatibilityMode mode) { 1.164 + boolean result = (mode == PolicyIntersector.CompatibilityMode.LAX) || this.vocabulary.equals(alternative.vocabulary); 1.165 + 1.166 + result = result && this.areAssertionsCompatible(alternative, mode); 1.167 + result = result && alternative.areAssertionsCompatible(this, mode); 1.168 + 1.169 + return result; 1.170 + } 1.171 + 1.172 + private boolean areAssertionsCompatible(final AssertionSet alternative, PolicyIntersector.CompatibilityMode mode) { 1.173 + nextAssertion: for (PolicyAssertion thisAssertion : this.assertions) { 1.174 + if ((mode == PolicyIntersector.CompatibilityMode.STRICT) || !thisAssertion.isIgnorable()) { 1.175 + for (PolicyAssertion thatAssertion : alternative.assertions) { 1.176 + if (thisAssertion.isCompatibleWith(thatAssertion, mode)) { 1.177 + continue nextAssertion; 1.178 + } 1.179 + } 1.180 + return false; 1.181 + } 1.182 + } 1.183 + return true; 1.184 + } 1.185 + 1.186 + /** 1.187 + * Creates and returns new assertion set holding content of all provided policy assertion sets. 1.188 + * <p/> 1.189 + * This method should not be used to perform a merge of general Policy instances. A client should be aware of the 1.190 + * method's result meaning and the difference between merge of Policy instances and merge of AssertionSet instances. 1.191 + * 1.192 + * 1.193 + * @param alternatives collection of provided policy assertion sets which content is to be stored in the assertion set. 1.194 + * May be {@code null} - empty assertion set is returned in such case. 1.195 + * @return new instance of assertion set holding the content of all provided policy assertion sets. 1.196 + */ 1.197 + public static AssertionSet createMergedAssertionSet(final Collection<AssertionSet> alternatives) { 1.198 + if (alternatives == null || alternatives.isEmpty()) { 1.199 + return EMPTY_ASSERTION_SET; 1.200 + } 1.201 + 1.202 + final AssertionSet result = new AssertionSet(alternatives); 1.203 + Collections.sort(result.assertions, ASSERTION_COMPARATOR); 1.204 + 1.205 + return result; 1.206 + } 1.207 + 1.208 + /** 1.209 + * Creates and returns new assertion set holding a set of provided policy assertions. 1.210 + * 1.211 + * @param assertions collection of provided policy assertions to be stored in the assertion set. May be {@code null}. 1.212 + * @return new instance of assertion set holding the provided policy assertions 1.213 + */ 1.214 + public static AssertionSet createAssertionSet(final Collection<? extends PolicyAssertion> assertions) { 1.215 + if (assertions == null || assertions.isEmpty()) { 1.216 + return EMPTY_ASSERTION_SET; 1.217 + } 1.218 + 1.219 + final AssertionSet result = new AssertionSet(new LinkedList<PolicyAssertion>()); 1.220 + result.addAll(assertions); 1.221 + Collections.sort(result.assertions, ASSERTION_COMPARATOR); 1.222 + 1.223 + return result; 1.224 + } 1.225 + 1.226 + public static AssertionSet emptyAssertionSet() { 1.227 + return EMPTY_ASSERTION_SET; 1.228 + } 1.229 + /** 1.230 + * Returns an iterator over a set of child policy assertion objects. 1.231 + * 1.232 + * @return policy assertion Iterator. 1.233 + */ 1.234 + public Iterator<PolicyAssertion> iterator() { 1.235 + return this.assertions.iterator(); 1.236 + } 1.237 + 1.238 + /** 1.239 + * Searches for assertions with given name. Only assertions that are contained as immediate children of the assertion set are 1.240 + * searched, i.e. nested policies are not searched. 1.241 + * 1.242 + * @param name The fully qualified name of searched assertion 1.243 + * @return List of all assertions matching the requested name. If no assertions are found, the returned list is empty 1.244 + * (i.e. {@code null} value is never returned). 1.245 + */ 1.246 + public Collection<PolicyAssertion> get(final QName name) { 1.247 + final List<PolicyAssertion> matched = new LinkedList<PolicyAssertion>(); 1.248 + 1.249 + if (vocabulary.contains(name)) { 1.250 + // we iterate the assertion set only if we are sure we contain such assertion name in our vocabulary 1.251 + for (PolicyAssertion assertion : assertions) { 1.252 + if (assertion.getName().equals(name)) { 1.253 + matched.add(assertion); 1.254 + } 1.255 + } 1.256 + } 1.257 + 1.258 + return matched; 1.259 + } 1.260 + 1.261 + /** 1.262 + * Returns {@code true} if this assertion set contains no assertions. 1.263 + * 1.264 + * @return {@code true} if this assertion set contains no assertions. 1.265 + */ 1.266 + public boolean isEmpty() { 1.267 + return assertions.isEmpty(); 1.268 + } 1.269 + 1.270 + /** 1.271 + * Returns true if the assertion set contains the assertion name specified in its vocabulary 1.272 + * 1.273 + * @param assertionName the fully qualified name of the assertion 1.274 + * @return {@code true}, if an assertion with the given name could be found in the assertion set vocabulary {@code false} otherwise. 1.275 + */ 1.276 + public boolean contains(final QName assertionName) { 1.277 + return vocabulary.contains(assertionName); 1.278 + } 1.279 + 1.280 + /** 1.281 + * An {@code Comparable<T>.compareTo(T o)} interface method implementation. 1.282 + * @param that other alternative to compare with 1.283 + */ 1.284 + public int compareTo(final AssertionSet that) { 1.285 + if (this.equals(that)) { 1.286 + return 0; 1.287 + } 1.288 + 1.289 + // comparing vocabularies 1.290 + final Iterator<QName> vIterator1 = this.getVocabulary().iterator(); 1.291 + final Iterator<QName> vIterator2 = that.getVocabulary().iterator(); 1.292 + while (vIterator1.hasNext()) { 1.293 + final QName entry1 = vIterator1.next(); 1.294 + if (vIterator2.hasNext()) { 1.295 + final QName entry2 = vIterator2.next(); 1.296 + final int result = PolicyUtils.Comparison.QNAME_COMPARATOR.compare(entry1, entry2); 1.297 + if (result != 0) { 1.298 + return result; 1.299 + } 1.300 + } else { 1.301 + return 1; // we have more entries in this vocabulary 1.302 + } 1.303 + } 1.304 + 1.305 + if (vIterator2.hasNext()) { 1.306 + return -1; // we have more entries in that vocabulary 1.307 + } 1.308 + 1.309 + // vocabularies are equal => comparing assertions 1.310 + final Iterator<PolicyAssertion> pIterator1 = this.getAssertions().iterator(); 1.311 + final Iterator<PolicyAssertion> pIterator2 = that.getAssertions().iterator(); 1.312 + while (pIterator1.hasNext()) { 1.313 + final PolicyAssertion pa1 = pIterator1.next(); 1.314 + if (pIterator2.hasNext()) { 1.315 + final PolicyAssertion pa2 = pIterator2.next(); 1.316 + final int result = ASSERTION_COMPARATOR.compare(pa1, pa2); 1.317 + if (result != 0) { 1.318 + return result; 1.319 + } 1.320 + } else { 1.321 + return 1; // we have more entries in this assertion set 1.322 + } 1.323 + } 1.324 + 1.325 + if (pIterator2.hasNext()) { 1.326 + return -1; // we have more entries in that assertion set 1.327 + } 1.328 + 1.329 + // seems like objects are very simmilar although not equal => we must not return 0 otherwise the TreeSet 1.330 + // holding this element would discard the newly added element. Thus we return that the first argument is 1.331 + // greater than second (just because it is first...) 1.332 + return 1; 1.333 + } 1.334 + 1.335 + /** 1.336 + * An {@code Object.equals(Object obj)} method override. 1.337 + */ 1.338 + public boolean equals(final Object obj) { 1.339 + if (this == obj) { 1.340 + return true; 1.341 + } 1.342 + 1.343 + if (!(obj instanceof AssertionSet)) { 1.344 + return false; 1.345 + } 1.346 + 1.347 + final AssertionSet that = (AssertionSet) obj; 1.348 + boolean result = true; 1.349 + 1.350 + result = result && this.vocabulary.equals(that.vocabulary); 1.351 + result = result && this.assertions.size() == that.assertions.size() && this.assertions.containsAll(that.assertions); 1.352 + 1.353 + return result; 1.354 + } 1.355 + 1.356 + /** 1.357 + * An {@code Object.hashCode()} method override. 1.358 + */ 1.359 + public int hashCode() { 1.360 + int result = 17; 1.361 + 1.362 + result = 37 * result + vocabulary.hashCode(); 1.363 + result = 37 * result + assertions.hashCode(); 1.364 + 1.365 + return result; 1.366 + } 1.367 + 1.368 + /** 1.369 + * An {@code Object.toString()} method override. 1.370 + */ 1.371 + public String toString() { 1.372 + return toString(0, new StringBuffer()).toString(); 1.373 + } 1.374 + 1.375 + /** 1.376 + * A helper method that appends indented string representation of this instance to the input string buffer. 1.377 + * 1.378 + * @param indentLevel indentation level to be used. 1.379 + * @param buffer buffer to be used for appending string representation of this instance 1.380 + * @return modified buffer containing new string representation of the instance 1.381 + */ 1.382 + StringBuffer toString(final int indentLevel, final StringBuffer buffer) { 1.383 + final String indent = PolicyUtils.Text.createIndent(indentLevel); 1.384 + final String innerIndent = PolicyUtils.Text.createIndent(indentLevel + 1); 1.385 + 1.386 + buffer.append(indent).append("assertion set {").append(PolicyUtils.Text.NEW_LINE); 1.387 + 1.388 + if (assertions.isEmpty()) { 1.389 + buffer.append(innerIndent).append("no assertions").append(PolicyUtils.Text.NEW_LINE); 1.390 + } else { 1.391 + for (PolicyAssertion assertion : assertions) { 1.392 + assertion.toString(indentLevel + 1, buffer).append(PolicyUtils.Text.NEW_LINE); 1.393 + } 1.394 + } 1.395 + 1.396 + buffer.append(indent).append('}'); 1.397 + 1.398 + return buffer; 1.399 + } 1.400 +}