aoqi@0: /* aoqi@0: * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. Oracle designates this aoqi@0: * particular file as subject to the "Classpath" exception as provided aoqi@0: * by Oracle in the LICENSE file that accompanied this code. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: */ aoqi@0: aoqi@0: package com.sun.xml.internal.ws.policy; aoqi@0: aoqi@0: import com.sun.xml.internal.ws.policy.privateutil.PolicyLogger; aoqi@0: import java.util.Collection; aoqi@0: import java.util.LinkedList; aoqi@0: import java.util.List; aoqi@0: import java.util.Queue; aoqi@0: import com.sun.xml.internal.ws.policy.privateutil.LocalizationMessages; aoqi@0: import com.sun.xml.internal.ws.policy.sourcemodel.wspolicy.NamespaceVersion; aoqi@0: import java.util.ArrayList; aoqi@0: aoqi@0: /** aoqi@0: * The instance of this class is intended to provide policy intersection mechanism. aoqi@0: * aoqi@0: * @author Marek Potociar (marek.potociar@sun.com) aoqi@0: */ aoqi@0: public final class PolicyIntersector { aoqi@0: static enum CompatibilityMode { aoqi@0: STRICT, aoqi@0: LAX aoqi@0: } aoqi@0: aoqi@0: private static final PolicyIntersector STRICT_INTERSECTOR = new PolicyIntersector(CompatibilityMode.STRICT); aoqi@0: private static final PolicyIntersector LAX_INTERSECTOR = new PolicyIntersector(CompatibilityMode.LAX); aoqi@0: private static final PolicyLogger LOGGER = PolicyLogger.getLogger(PolicyIntersector.class); aoqi@0: aoqi@0: private CompatibilityMode mode; aoqi@0: aoqi@0: /** aoqi@0: * Prevents direct instantiation of this class from outside aoqi@0: * @param intersectionMode intersection mode aoqi@0: */ aoqi@0: private PolicyIntersector(CompatibilityMode intersectionMode) { aoqi@0: this.mode = intersectionMode; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Returns a strict policy intersector that can be used to intersect group of policies. aoqi@0: * aoqi@0: * @return policy intersector instance. aoqi@0: */ aoqi@0: public static PolicyIntersector createStrictPolicyIntersector() { aoqi@0: return PolicyIntersector.STRICT_INTERSECTOR; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Returns a strict policy intersector that can be used to intersect group of policies. aoqi@0: * aoqi@0: * @return policy intersector instance. aoqi@0: */ aoqi@0: public static PolicyIntersector createLaxPolicyIntersector() { aoqi@0: return PolicyIntersector.LAX_INTERSECTOR; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Performs intersection on the input collection of policies and returns the resulting (intersected) policy. If input policy aoqi@0: * collection contains only a single policy instance, no intersection is performed and the instance is directly returned aoqi@0: * as a method call result. aoqi@0: * aoqi@0: * @param policies collection of policies to be intersected. Must not be {@code null} nor empty, otherwise exception is thrown. aoqi@0: * @return intersected policy as a result of perfromed policy intersection. A {@code null} value is never returned. aoqi@0: * aoqi@0: * @throws IllegalArgumentException in case {@code policies} argument is either {@code null} or empty collection. aoqi@0: */ aoqi@0: public Policy intersect(final Policy... policies) { aoqi@0: if (policies == null || policies.length == 0) { aoqi@0: throw LOGGER.logSevereException(new IllegalArgumentException(LocalizationMessages.WSP_0056_NEITHER_NULL_NOR_EMPTY_POLICY_COLLECTION_EXPECTED())); aoqi@0: } else if (policies.length == 1) { aoqi@0: return policies[0]; aoqi@0: } aoqi@0: aoqi@0: // check for "null" and "empty" policy: if such policy is found return "null" policy, aoqi@0: // or if all policies are "empty", return "empty" policy aoqi@0: boolean found = false; aoqi@0: boolean allPoliciesEmpty = true; aoqi@0: NamespaceVersion latestVersion = null; aoqi@0: for (Policy tested : policies) { aoqi@0: if (tested.isEmpty()) { aoqi@0: found = true; aoqi@0: } else { aoqi@0: if (tested.isNull()) { aoqi@0: found = true; aoqi@0: } aoqi@0: allPoliciesEmpty = false; aoqi@0: } aoqi@0: if (latestVersion == null) { aoqi@0: latestVersion = tested.getNamespaceVersion(); aoqi@0: } else if (latestVersion.compareTo(tested.getNamespaceVersion()) < 0) { aoqi@0: latestVersion = tested.getNamespaceVersion(); aoqi@0: } aoqi@0: aoqi@0: if (found && !allPoliciesEmpty) { aoqi@0: return Policy.createNullPolicy(latestVersion, null, null); aoqi@0: } aoqi@0: } aoqi@0: latestVersion = (latestVersion != null) ? latestVersion : NamespaceVersion.getLatestVersion(); aoqi@0: if (allPoliciesEmpty) { aoqi@0: return Policy.createEmptyPolicy(latestVersion, null, null); aoqi@0: } aoqi@0: aoqi@0: // simple tests didn't lead to final answer => let's performe some intersecting ;) aoqi@0: final List finalAlternatives = new LinkedList(policies[0].getContent()); aoqi@0: final Queue testedAlternatives = new LinkedList(); aoqi@0: final List alternativesToMerge = new ArrayList(2); aoqi@0: for (int i = 1; i < policies.length; i++) { aoqi@0: final Collection currentAlternatives = policies[i].getContent(); aoqi@0: aoqi@0: testedAlternatives.clear(); aoqi@0: testedAlternatives.addAll(finalAlternatives); aoqi@0: finalAlternatives.clear(); aoqi@0: aoqi@0: AssertionSet testedAlternative; aoqi@0: while ((testedAlternative = testedAlternatives.poll()) != null) { aoqi@0: for (AssertionSet currentAlternative : currentAlternatives) { aoqi@0: if (testedAlternative.isCompatibleWith(currentAlternative, this.mode)) { aoqi@0: alternativesToMerge.add(testedAlternative); aoqi@0: alternativesToMerge.add(currentAlternative); aoqi@0: finalAlternatives.add(AssertionSet.createMergedAssertionSet(alternativesToMerge)); aoqi@0: alternativesToMerge.clear(); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: return Policy.createPolicy(latestVersion, null, null, finalAlternatives); aoqi@0: } aoqi@0: }