001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */package org.apache.cxf.ws.policy;
019:
020: import java.util.ArrayList;
021: import java.util.Collection;
022: import java.util.Iterator;
023: import java.util.List;
024:
025: import org.apache.cxf.helpers.CastUtils;
026: import org.apache.neethi.All;
027: import org.apache.neethi.Assertion;
028: import org.apache.neethi.ExactlyOne;
029: import org.apache.neethi.Policy;
030:
031: /**
032: * This class contains methods dealing with policy intersection.
033: * Intersection of two assertions, i.e. computation if a compatible assertion,
034: * is domain specific and relies on AssertionBuilder.buildCompatible.
035: * See Section 4.5 in http://www.w3.org/TR/2006/WD-ws-policy-20061117.
036: */
037: public class Intersector {
038:
039: private AssertionBuilderRegistry assertionBuilderRegistry;
040: private boolean strict;
041:
042: public Intersector(AssertionBuilderRegistry abr) {
043: assertionBuilderRegistry = abr;
044: strict = true;
045: }
046:
047: public boolean isStrict() {
048: return strict;
049: }
050:
051: public void setStrict(boolean s) {
052: strict = s;
053: }
054:
055: boolean compatibleAssertions(Assertion a1, Assertion a2) {
056: AssertionBuilder ab = assertionBuilderRegistry
057: .get(a1.getName());
058: if (null == ab) {
059: return false;
060: }
061: return null != ab.buildCompatible(a1, a2);
062: }
063:
064: boolean compatibleAlternatives(Collection<Assertion> alt1,
065: Collection<Assertion> alt2) {
066: if (alt1.isEmpty() || alt2.isEmpty()) {
067: return true;
068: }
069: if (strict) {
070: for (Assertion a1 : alt1) {
071: if (null == findCompatibleAssertion(a1, alt2)) {
072: return false;
073: }
074: }
075: for (Assertion a2 : alt2) {
076: if (null == findCompatibleAssertion(a2, alt1)) {
077: return false;
078: }
079: }
080: return true;
081: }
082: // Lax intersection not supported as neethi does not support Ignorable yet.
083: throw new UnsupportedOperationException(
084: "Lax intersection of assertions is not supported "
085: + "because the Ignorable attribute is not supported.");
086: }
087:
088: boolean compatiblePolicies(Policy p1, Policy p2) {
089: Iterator i1 = p1.getAlternatives();
090: while (i1.hasNext()) {
091: Collection<Assertion> alt1 = CastUtils.cast((Collection) i1
092: .next(), Assertion.class);
093: Iterator i2 = p2.getAlternatives();
094: while (i2.hasNext()) {
095: Collection<Assertion> alt2 = CastUtils.cast(
096: (Collection) i2.next(), Assertion.class);
097: if (compatibleAlternatives(alt1, alt2)) {
098: return true;
099: }
100: }
101: return false;
102: }
103: return true;
104: }
105:
106: public Assertion intersect(Assertion a1, Assertion a2) {
107: AssertionBuilder ab = assertionBuilderRegistry
108: .get(a1.getName());
109: if (null == ab) {
110: return null;
111: }
112: return ab.buildCompatible(a1, a2);
113: }
114:
115: public Collection<Assertion> intersect(Collection<Assertion> alt1,
116: Collection<Assertion> alt2) {
117: if (!compatibleAlternatives(alt1, alt2)) {
118: return null;
119: }
120: Collection<Assertion> intersection = new ArrayList<Assertion>();
121: intersection.addAll(alt1);
122: intersection.addAll(alt2);
123: return intersection;
124: }
125:
126: public Policy intersect(Policy p1, Policy p2) {
127: if (!compatiblePolicies(p1, p2)) {
128: return null;
129: }
130:
131: Policy compatible = new Policy();
132: ExactlyOne eo = new ExactlyOne();
133:
134: Iterator i1 = p1.getAlternatives();
135: while (i1.hasNext()) {
136: List<Assertion> alt1 = CastUtils.cast((List) i1.next(),
137: Assertion.class);
138: Iterator i2 = p2.getAlternatives();
139: while (i2.hasNext()) {
140: List<Assertion> alt2 = CastUtils.cast((List) i2.next(),
141: Assertion.class);
142: if (compatibleAlternatives(alt1, alt2)) {
143: All all = new All();
144: all.addPolicyComponents(alt1);
145: all.addPolicyComponents(alt2);
146: eo.addPolicyComponent(all);
147: }
148: }
149: }
150:
151: if (!eo.isEmpty()) {
152: compatible.addPolicyComponent(eo);
153: }
154:
155: return compatible;
156: }
157:
158: private Assertion findCompatibleAssertion(Assertion assertion,
159: Collection<Assertion> alt) {
160: for (Assertion a : alt) {
161: Assertion compatible = intersect(assertion, a);
162: if (null != compatible) {
163: return compatible;
164: }
165: }
166: return null;
167: }
168: }
|