src/share/jaxws_classes/com/sun/xml/internal/ws/policy/AssertionSet.java

Thu, 12 Oct 2017 19:44:07 +0800

author
aoqi
date
Thu, 12 Oct 2017 19:44:07 +0800
changeset 760
e530533619ec
parent 0
373ffda63c9a
permissions
-rw-r--r--

merge

aoqi@0 1 /*
aoqi@0 2 * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
aoqi@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
aoqi@0 4 *
aoqi@0 5 * This code is free software; you can redistribute it and/or modify it
aoqi@0 6 * under the terms of the GNU General Public License version 2 only, as
aoqi@0 7 * published by the Free Software Foundation. Oracle designates this
aoqi@0 8 * particular file as subject to the "Classpath" exception as provided
aoqi@0 9 * by Oracle in the LICENSE file that accompanied this code.
aoqi@0 10 *
aoqi@0 11 * This code is distributed in the hope that it will be useful, but WITHOUT
aoqi@0 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
aoqi@0 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
aoqi@0 14 * version 2 for more details (a copy is included in the LICENSE file that
aoqi@0 15 * accompanied this code).
aoqi@0 16 *
aoqi@0 17 * You should have received a copy of the GNU General Public License version
aoqi@0 18 * 2 along with this work; if not, write to the Free Software Foundation,
aoqi@0 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
aoqi@0 20 *
aoqi@0 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
aoqi@0 22 * or visit www.oracle.com if you need additional information or have any
aoqi@0 23 * questions.
aoqi@0 24 */
aoqi@0 25
aoqi@0 26 package com.sun.xml.internal.ws.policy;
aoqi@0 27
aoqi@0 28 import java.util.Collection;
aoqi@0 29 import java.util.Collections;
aoqi@0 30 import java.util.Comparator;
aoqi@0 31 import java.util.Iterator;
aoqi@0 32 import java.util.Set;
aoqi@0 33 import java.util.TreeSet;
aoqi@0 34
aoqi@0 35 import javax.xml.namespace.QName;
aoqi@0 36
aoqi@0 37 import com.sun.xml.internal.ws.policy.privateutil.LocalizationMessages;
aoqi@0 38 import com.sun.xml.internal.ws.policy.privateutil.PolicyUtils;
aoqi@0 39 import java.util.LinkedList;
aoqi@0 40 import java.util.List;
aoqi@0 41
aoqi@0 42 /**
aoqi@0 43 * The AssertionSet is a set of assertions. It represents a single policy alternative.
aoqi@0 44 *
aoqi@0 45 * @author Fabian Ritzmann, Marek Potociar
aoqi@0 46 */
aoqi@0 47 public final class AssertionSet implements Iterable<PolicyAssertion>, Comparable<AssertionSet> {
aoqi@0 48 private static final AssertionSet EMPTY_ASSERTION_SET = new AssertionSet(Collections.unmodifiableList(new LinkedList<PolicyAssertion>()));
aoqi@0 49 /**
aoqi@0 50 * The comparator comapres policy assertions according to their publicly accessible attributes, in the following
aoqi@0 51 * order of attributes:
aoqi@0 52 *
aoqi@0 53 * 1. namespace (not null String)
aoqi@0 54 * 2. local name (not null String)
aoqi@0 55 * 3. value (String): null < "" < "not empty"
aoqi@0 56 * 4. has nested assertions (boolean): false < true
aoqi@0 57 * 5. has nested policy (boolean): false < true
aoqi@0 58 * 6. hashCode comparison
aoqi@0 59 */
aoqi@0 60 private static final Comparator<PolicyAssertion> ASSERTION_COMPARATOR = new Comparator<PolicyAssertion>() {
aoqi@0 61 public int compare(final PolicyAssertion pa1, final PolicyAssertion pa2) {
aoqi@0 62 if (pa1.equals(pa2)) {
aoqi@0 63 return 0;
aoqi@0 64 }
aoqi@0 65
aoqi@0 66 int result;
aoqi@0 67
aoqi@0 68 result = PolicyUtils.Comparison.QNAME_COMPARATOR.compare(pa1.getName(), pa2.getName());
aoqi@0 69 if (result != 0) {
aoqi@0 70 return result;
aoqi@0 71 }
aoqi@0 72
aoqi@0 73 result = PolicyUtils.Comparison.compareNullableStrings(pa1.getValue(), pa2.getValue());
aoqi@0 74 if (result != 0) {
aoqi@0 75 return result;
aoqi@0 76 }
aoqi@0 77
aoqi@0 78 result = PolicyUtils.Comparison.compareBoolean(pa1.hasNestedAssertions(), pa2.hasNestedAssertions());
aoqi@0 79 if (result != 0) {
aoqi@0 80 return result;
aoqi@0 81 }
aoqi@0 82
aoqi@0 83 result = PolicyUtils.Comparison.compareBoolean(pa1.hasNestedPolicy(), pa2.hasNestedPolicy());
aoqi@0 84 if (result != 0) {
aoqi@0 85 return result;
aoqi@0 86 }
aoqi@0 87
aoqi@0 88 return Math.round(Math.signum(pa1.hashCode() - pa2.hashCode()));
aoqi@0 89 }
aoqi@0 90 };
aoqi@0 91
aoqi@0 92 private final List<PolicyAssertion> assertions;
aoqi@0 93 private final Set<QName> vocabulary = new TreeSet<QName>(PolicyUtils.Comparison.QNAME_COMPARATOR);
aoqi@0 94 private final Collection<QName> immutableVocabulary = Collections.unmodifiableCollection(vocabulary);
aoqi@0 95
aoqi@0 96 private AssertionSet(List<PolicyAssertion> list) {
aoqi@0 97 assert (list != null) : LocalizationMessages.WSP_0037_PRIVATE_CONSTRUCTOR_DOES_NOT_TAKE_NULL();
aoqi@0 98 this.assertions = list;
aoqi@0 99 }
aoqi@0 100
aoqi@0 101 private AssertionSet(final Collection<AssertionSet> alternatives) {
aoqi@0 102 this.assertions = new LinkedList<PolicyAssertion>();
aoqi@0 103 for (AssertionSet alternative : alternatives) {
aoqi@0 104 addAll(alternative.assertions);
aoqi@0 105 }
aoqi@0 106 }
aoqi@0 107
aoqi@0 108 private boolean add(final PolicyAssertion assertion) {
aoqi@0 109 if (assertion == null) {
aoqi@0 110 return false;
aoqi@0 111 }
aoqi@0 112
aoqi@0 113 if (this.assertions.contains(assertion)) {
aoqi@0 114 return false;
aoqi@0 115 } else {
aoqi@0 116 this.assertions.add(assertion);
aoqi@0 117 this.vocabulary.add(assertion.getName());
aoqi@0 118 return true;
aoqi@0 119 }
aoqi@0 120 }
aoqi@0 121
aoqi@0 122 private boolean addAll(final Collection<? extends PolicyAssertion> assertions) {
aoqi@0 123 boolean result = true;
aoqi@0 124
aoqi@0 125 if (assertions != null) {
aoqi@0 126 for (PolicyAssertion assertion : assertions) {
aoqi@0 127 result &= add(assertion); // this is here to ensure that vocabulary is built correctly as well
aoqi@0 128 }
aoqi@0 129 }
aoqi@0 130
aoqi@0 131 return result;
aoqi@0 132 }
aoqi@0 133
aoqi@0 134 /**
aoqi@0 135 * Return all assertions contained in this assertion set.
aoqi@0 136 *
aoqi@0 137 * @return All assertions contained in this assertion set
aoqi@0 138 */
aoqi@0 139 Collection<PolicyAssertion> getAssertions() {
aoqi@0 140 return assertions;
aoqi@0 141 }
aoqi@0 142
aoqi@0 143 /**
aoqi@0 144 * Retrieves the vocabulary of this policy expression. The vocabulary is represented by an immutable collection of
aoqi@0 145 * unique QName objects. Each of those objects represents single assertion type contained in the assertion set.
aoqi@0 146 *
aoqi@0 147 * @return immutable collection of assertion types contained in the assertion set (a policy vocabulary).
aoqi@0 148 */
aoqi@0 149 Collection<QName> getVocabulary() {
aoqi@0 150 return immutableVocabulary;
aoqi@0 151 }
aoqi@0 152
aoqi@0 153 /**
aoqi@0 154 * Checks whether this policy alternative is compatible with the provided policy alternative.
aoqi@0 155 *
aoqi@0 156 * @param alternative policy alternative used for compatibility test
aoqi@0 157 * @param mode compatibility mode to be used
aoqi@0 158 * @return {@code true} if the two policy alternatives are compatible, {@code false} otherwise
aoqi@0 159 */
aoqi@0 160 boolean isCompatibleWith(final AssertionSet alternative, PolicyIntersector.CompatibilityMode mode) {
aoqi@0 161 boolean result = (mode == PolicyIntersector.CompatibilityMode.LAX) || this.vocabulary.equals(alternative.vocabulary);
aoqi@0 162
aoqi@0 163 result = result && this.areAssertionsCompatible(alternative, mode);
aoqi@0 164 result = result && alternative.areAssertionsCompatible(this, mode);
aoqi@0 165
aoqi@0 166 return result;
aoqi@0 167 }
aoqi@0 168
aoqi@0 169 private boolean areAssertionsCompatible(final AssertionSet alternative, PolicyIntersector.CompatibilityMode mode) {
aoqi@0 170 nextAssertion: for (PolicyAssertion thisAssertion : this.assertions) {
aoqi@0 171 if ((mode == PolicyIntersector.CompatibilityMode.STRICT) || !thisAssertion.isIgnorable()) {
aoqi@0 172 for (PolicyAssertion thatAssertion : alternative.assertions) {
aoqi@0 173 if (thisAssertion.isCompatibleWith(thatAssertion, mode)) {
aoqi@0 174 continue nextAssertion;
aoqi@0 175 }
aoqi@0 176 }
aoqi@0 177 return false;
aoqi@0 178 }
aoqi@0 179 }
aoqi@0 180 return true;
aoqi@0 181 }
aoqi@0 182
aoqi@0 183 /**
aoqi@0 184 * Creates and returns new assertion set holding content of all provided policy assertion sets.
aoqi@0 185 * <p/>
aoqi@0 186 * This method should not be used to perform a merge of general Policy instances. A client should be aware of the
aoqi@0 187 * method's result meaning and the difference between merge of Policy instances and merge of AssertionSet instances.
aoqi@0 188 *
aoqi@0 189 *
aoqi@0 190 * @param alternatives collection of provided policy assertion sets which content is to be stored in the assertion set.
aoqi@0 191 * May be {@code null} - empty assertion set is returned in such case.
aoqi@0 192 * @return new instance of assertion set holding the content of all provided policy assertion sets.
aoqi@0 193 */
aoqi@0 194 public static AssertionSet createMergedAssertionSet(final Collection<AssertionSet> alternatives) {
aoqi@0 195 if (alternatives == null || alternatives.isEmpty()) {
aoqi@0 196 return EMPTY_ASSERTION_SET;
aoqi@0 197 }
aoqi@0 198
aoqi@0 199 final AssertionSet result = new AssertionSet(alternatives);
aoqi@0 200 Collections.sort(result.assertions, ASSERTION_COMPARATOR);
aoqi@0 201
aoqi@0 202 return result;
aoqi@0 203 }
aoqi@0 204
aoqi@0 205 /**
aoqi@0 206 * Creates and returns new assertion set holding a set of provided policy assertions.
aoqi@0 207 *
aoqi@0 208 * @param assertions collection of provided policy assertions to be stored in the assertion set. May be {@code null}.
aoqi@0 209 * @return new instance of assertion set holding the provided policy assertions
aoqi@0 210 */
aoqi@0 211 public static AssertionSet createAssertionSet(final Collection<? extends PolicyAssertion> assertions) {
aoqi@0 212 if (assertions == null || assertions.isEmpty()) {
aoqi@0 213 return EMPTY_ASSERTION_SET;
aoqi@0 214 }
aoqi@0 215
aoqi@0 216 final AssertionSet result = new AssertionSet(new LinkedList<PolicyAssertion>());
aoqi@0 217 result.addAll(assertions);
aoqi@0 218 Collections.sort(result.assertions, ASSERTION_COMPARATOR);
aoqi@0 219
aoqi@0 220 return result;
aoqi@0 221 }
aoqi@0 222
aoqi@0 223 public static AssertionSet emptyAssertionSet() {
aoqi@0 224 return EMPTY_ASSERTION_SET;
aoqi@0 225 }
aoqi@0 226 /**
aoqi@0 227 * Returns an iterator over a set of child policy assertion objects.
aoqi@0 228 *
aoqi@0 229 * @return policy assertion Iterator.
aoqi@0 230 */
aoqi@0 231 public Iterator<PolicyAssertion> iterator() {
aoqi@0 232 return this.assertions.iterator();
aoqi@0 233 }
aoqi@0 234
aoqi@0 235 /**
aoqi@0 236 * Searches for assertions with given name. Only assertions that are contained as immediate children of the assertion set are
aoqi@0 237 * searched, i.e. nested policies are not searched.
aoqi@0 238 *
aoqi@0 239 * @param name The fully qualified name of searched assertion
aoqi@0 240 * @return List of all assertions matching the requested name. If no assertions are found, the returned list is empty
aoqi@0 241 * (i.e. {@code null} value is never returned).
aoqi@0 242 */
aoqi@0 243 public Collection<PolicyAssertion> get(final QName name) {
aoqi@0 244 final List<PolicyAssertion> matched = new LinkedList<PolicyAssertion>();
aoqi@0 245
aoqi@0 246 if (vocabulary.contains(name)) {
aoqi@0 247 // we iterate the assertion set only if we are sure we contain such assertion name in our vocabulary
aoqi@0 248 for (PolicyAssertion assertion : assertions) {
aoqi@0 249 if (assertion.getName().equals(name)) {
aoqi@0 250 matched.add(assertion);
aoqi@0 251 }
aoqi@0 252 }
aoqi@0 253 }
aoqi@0 254
aoqi@0 255 return matched;
aoqi@0 256 }
aoqi@0 257
aoqi@0 258 /**
aoqi@0 259 * Returns {@code true} if this assertion set contains no assertions.
aoqi@0 260 *
aoqi@0 261 * @return {@code true} if this assertion set contains no assertions.
aoqi@0 262 */
aoqi@0 263 public boolean isEmpty() {
aoqi@0 264 return assertions.isEmpty();
aoqi@0 265 }
aoqi@0 266
aoqi@0 267 /**
aoqi@0 268 * Returns true if the assertion set contains the assertion name specified in its vocabulary
aoqi@0 269 *
aoqi@0 270 * @param assertionName the fully qualified name of the assertion
aoqi@0 271 * @return {@code true}, if an assertion with the given name could be found in the assertion set vocabulary {@code false} otherwise.
aoqi@0 272 */
aoqi@0 273 public boolean contains(final QName assertionName) {
aoqi@0 274 return vocabulary.contains(assertionName);
aoqi@0 275 }
aoqi@0 276
aoqi@0 277 /**
aoqi@0 278 * An {@code Comparable<T>.compareTo(T o)} interface method implementation.
aoqi@0 279 * @param that other alternative to compare with
aoqi@0 280 */
aoqi@0 281 public int compareTo(final AssertionSet that) {
aoqi@0 282 if (this.equals(that)) {
aoqi@0 283 return 0;
aoqi@0 284 }
aoqi@0 285
aoqi@0 286 // comparing vocabularies
aoqi@0 287 final Iterator<QName> vIterator1 = this.getVocabulary().iterator();
aoqi@0 288 final Iterator<QName> vIterator2 = that.getVocabulary().iterator();
aoqi@0 289 while (vIterator1.hasNext()) {
aoqi@0 290 final QName entry1 = vIterator1.next();
aoqi@0 291 if (vIterator2.hasNext()) {
aoqi@0 292 final QName entry2 = vIterator2.next();
aoqi@0 293 final int result = PolicyUtils.Comparison.QNAME_COMPARATOR.compare(entry1, entry2);
aoqi@0 294 if (result != 0) {
aoqi@0 295 return result;
aoqi@0 296 }
aoqi@0 297 } else {
aoqi@0 298 return 1; // we have more entries in this vocabulary
aoqi@0 299 }
aoqi@0 300 }
aoqi@0 301
aoqi@0 302 if (vIterator2.hasNext()) {
aoqi@0 303 return -1; // we have more entries in that vocabulary
aoqi@0 304 }
aoqi@0 305
aoqi@0 306 // vocabularies are equal => comparing assertions
aoqi@0 307 final Iterator<PolicyAssertion> pIterator1 = this.getAssertions().iterator();
aoqi@0 308 final Iterator<PolicyAssertion> pIterator2 = that.getAssertions().iterator();
aoqi@0 309 while (pIterator1.hasNext()) {
aoqi@0 310 final PolicyAssertion pa1 = pIterator1.next();
aoqi@0 311 if (pIterator2.hasNext()) {
aoqi@0 312 final PolicyAssertion pa2 = pIterator2.next();
aoqi@0 313 final int result = ASSERTION_COMPARATOR.compare(pa1, pa2);
aoqi@0 314 if (result != 0) {
aoqi@0 315 return result;
aoqi@0 316 }
aoqi@0 317 } else {
aoqi@0 318 return 1; // we have more entries in this assertion set
aoqi@0 319 }
aoqi@0 320 }
aoqi@0 321
aoqi@0 322 if (pIterator2.hasNext()) {
aoqi@0 323 return -1; // we have more entries in that assertion set
aoqi@0 324 }
aoqi@0 325
aoqi@0 326 // seems like objects are very simmilar although not equal => we must not return 0 otherwise the TreeSet
aoqi@0 327 // holding this element would discard the newly added element. Thus we return that the first argument is
aoqi@0 328 // greater than second (just because it is first...)
aoqi@0 329 return 1;
aoqi@0 330 }
aoqi@0 331
aoqi@0 332 /**
aoqi@0 333 * An {@code Object.equals(Object obj)} method override.
aoqi@0 334 */
aoqi@0 335 public boolean equals(final Object obj) {
aoqi@0 336 if (this == obj) {
aoqi@0 337 return true;
aoqi@0 338 }
aoqi@0 339
aoqi@0 340 if (!(obj instanceof AssertionSet)) {
aoqi@0 341 return false;
aoqi@0 342 }
aoqi@0 343
aoqi@0 344 final AssertionSet that = (AssertionSet) obj;
aoqi@0 345 boolean result = true;
aoqi@0 346
aoqi@0 347 result = result && this.vocabulary.equals(that.vocabulary);
aoqi@0 348 result = result && this.assertions.size() == that.assertions.size() && this.assertions.containsAll(that.assertions);
aoqi@0 349
aoqi@0 350 return result;
aoqi@0 351 }
aoqi@0 352
aoqi@0 353 /**
aoqi@0 354 * An {@code Object.hashCode()} method override.
aoqi@0 355 */
aoqi@0 356 public int hashCode() {
aoqi@0 357 int result = 17;
aoqi@0 358
aoqi@0 359 result = 37 * result + vocabulary.hashCode();
aoqi@0 360 result = 37 * result + assertions.hashCode();
aoqi@0 361
aoqi@0 362 return result;
aoqi@0 363 }
aoqi@0 364
aoqi@0 365 /**
aoqi@0 366 * An {@code Object.toString()} method override.
aoqi@0 367 */
aoqi@0 368 public String toString() {
aoqi@0 369 return toString(0, new StringBuffer()).toString();
aoqi@0 370 }
aoqi@0 371
aoqi@0 372 /**
aoqi@0 373 * A helper method that appends indented string representation of this instance to the input string buffer.
aoqi@0 374 *
aoqi@0 375 * @param indentLevel indentation level to be used.
aoqi@0 376 * @param buffer buffer to be used for appending string representation of this instance
aoqi@0 377 * @return modified buffer containing new string representation of the instance
aoqi@0 378 */
aoqi@0 379 StringBuffer toString(final int indentLevel, final StringBuffer buffer) {
aoqi@0 380 final String indent = PolicyUtils.Text.createIndent(indentLevel);
aoqi@0 381 final String innerIndent = PolicyUtils.Text.createIndent(indentLevel + 1);
aoqi@0 382
aoqi@0 383 buffer.append(indent).append("assertion set {").append(PolicyUtils.Text.NEW_LINE);
aoqi@0 384
aoqi@0 385 if (assertions.isEmpty()) {
aoqi@0 386 buffer.append(innerIndent).append("no assertions").append(PolicyUtils.Text.NEW_LINE);
aoqi@0 387 } else {
aoqi@0 388 for (PolicyAssertion assertion : assertions) {
aoqi@0 389 assertion.toString(indentLevel + 1, buffer).append(PolicyUtils.Text.NEW_LINE);
aoqi@0 390 }
aoqi@0 391 }
aoqi@0 392
aoqi@0 393 buffer.append(indent).append('}');
aoqi@0 394
aoqi@0 395 return buffer;
aoqi@0 396 }
aoqi@0 397 }

mercurial