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.sourcemodel; aoqi@0: aoqi@0: import java.util.ArrayList; aoqi@0: import java.util.Collection; aoqi@0: import java.util.Collections; aoqi@0: import java.util.HashMap; aoqi@0: import java.util.LinkedList; aoqi@0: import java.util.List; aoqi@0: import java.util.Map; aoqi@0: import java.util.Queue; aoqi@0: aoqi@0: import com.sun.xml.internal.ws.policy.AssertionSet; aoqi@0: import com.sun.xml.internal.ws.policy.Policy; aoqi@0: import com.sun.xml.internal.ws.policy.PolicyAssertion; aoqi@0: import com.sun.xml.internal.ws.policy.PolicyException; aoqi@0: import com.sun.xml.internal.ws.policy.privateutil.LocalizationMessages; aoqi@0: import com.sun.xml.internal.ws.policy.privateutil.PolicyLogger; aoqi@0: import com.sun.xml.internal.ws.policy.privateutil.PolicyUtils; aoqi@0: import com.sun.xml.internal.ws.policy.spi.AssertionCreationException; aoqi@0: import com.sun.xml.internal.ws.policy.spi.PolicyAssertionCreator; aoqi@0: aoqi@0: /** aoqi@0: * This class provides a method for translating a {@link PolicySourceModel} structure to a normalized {@link Policy} expression. aoqi@0: * The resulting Policy is disconnected from its model, thus any additional changes in the model will have no effect on the Policy aoqi@0: * expression. aoqi@0: * aoqi@0: * @author Marek Potociar aoqi@0: * @author Fabian Ritzmann aoqi@0: */ aoqi@0: public class PolicyModelTranslator { aoqi@0: aoqi@0: private static final class ContentDecomposition { aoqi@0: final List> exactlyOneContents = new LinkedList>(); aoqi@0: final List assertions = new LinkedList(); aoqi@0: aoqi@0: void reset() { aoqi@0: exactlyOneContents.clear(); aoqi@0: assertions.clear(); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: private static final class RawAssertion { aoqi@0: ModelNode originalNode; // used to initialize nestedPolicy and nestedAssertions in the constructor of RawAlternative aoqi@0: Collection nestedAlternatives = null; aoqi@0: final Collection parameters; aoqi@0: aoqi@0: RawAssertion(ModelNode originalNode, Collection parameters) { aoqi@0: this.parameters = parameters; aoqi@0: this.originalNode = originalNode; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: private static final class RawAlternative { aoqi@0: private static final PolicyLogger LOGGER = PolicyLogger.getLogger(PolicyModelTranslator.RawAlternative.class); aoqi@0: aoqi@0: final List allNestedPolicies = new LinkedList(); // used to track the nested policies which need to be normalized aoqi@0: final Collection nestedAssertions; aoqi@0: aoqi@0: RawAlternative(Collection assertionNodes) throws PolicyException { aoqi@0: this.nestedAssertions = new LinkedList(); aoqi@0: for (ModelNode node : assertionNodes) { aoqi@0: RawAssertion assertion = new RawAssertion(node, new LinkedList()); aoqi@0: nestedAssertions.add(assertion); aoqi@0: aoqi@0: for (ModelNode assertionNodeChild : assertion.originalNode.getChildren()) { aoqi@0: switch (assertionNodeChild.getType()) { aoqi@0: case ASSERTION_PARAMETER_NODE: aoqi@0: assertion.parameters.add(assertionNodeChild); aoqi@0: break; aoqi@0: case POLICY: aoqi@0: case POLICY_REFERENCE: aoqi@0: if (assertion.nestedAlternatives == null) { aoqi@0: assertion.nestedAlternatives = new LinkedList(); aoqi@0: RawPolicy nestedPolicy; aoqi@0: if (assertionNodeChild.getType() == ModelNode.Type.POLICY) { aoqi@0: nestedPolicy = new RawPolicy(assertionNodeChild, assertion.nestedAlternatives); aoqi@0: } else { aoqi@0: nestedPolicy = new RawPolicy(getReferencedModelRootNode(assertionNodeChild), assertion.nestedAlternatives); aoqi@0: } aoqi@0: this.allNestedPolicies.add(nestedPolicy); aoqi@0: } else { aoqi@0: throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0006_UNEXPECTED_MULTIPLE_POLICY_NODES())); aoqi@0: } aoqi@0: break; aoqi@0: default: aoqi@0: throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0008_UNEXPECTED_CHILD_MODEL_TYPE(assertionNodeChild.getType()))); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: } aoqi@0: aoqi@0: private static final class RawPolicy { aoqi@0: final Collection originalContent; aoqi@0: final Collection alternatives; aoqi@0: aoqi@0: RawPolicy(ModelNode policyNode, Collection alternatives) { aoqi@0: originalContent = policyNode.getChildren(); aoqi@0: this.alternatives = alternatives; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: private static final PolicyLogger LOGGER = PolicyLogger.getLogger(PolicyModelTranslator.class); aoqi@0: aoqi@0: private static final PolicyAssertionCreator defaultCreator = new DefaultPolicyAssertionCreator(); aoqi@0: aoqi@0: private final Map assertionCreators; aoqi@0: aoqi@0: aoqi@0: private PolicyModelTranslator() throws PolicyException { aoqi@0: this(null); aoqi@0: } aoqi@0: aoqi@0: protected PolicyModelTranslator(final Collection creators) throws PolicyException { aoqi@0: LOGGER.entering(creators); aoqi@0: aoqi@0: final Collection allCreators = new LinkedList(); aoqi@0: final PolicyAssertionCreator[] discoveredCreators = PolicyUtils.ServiceProvider.load(PolicyAssertionCreator.class); aoqi@0: for (PolicyAssertionCreator creator : discoveredCreators) { aoqi@0: allCreators.add(creator); aoqi@0: } aoqi@0: if (creators != null) { aoqi@0: for (PolicyAssertionCreator creator : creators) { aoqi@0: allCreators.add(creator); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: final Map pacMap = new HashMap(); aoqi@0: for (PolicyAssertionCreator creator : allCreators) { aoqi@0: final String[] supportedURIs = creator.getSupportedDomainNamespaceURIs(); aoqi@0: final String creatorClassName = creator.getClass().getName(); aoqi@0: aoqi@0: if (supportedURIs == null || supportedURIs.length == 0) { aoqi@0: LOGGER.warning(LocalizationMessages.WSP_0077_ASSERTION_CREATOR_DOES_NOT_SUPPORT_ANY_URI(creatorClassName)); aoqi@0: continue; aoqi@0: } aoqi@0: aoqi@0: for (String supportedURI : supportedURIs) { aoqi@0: LOGGER.config(LocalizationMessages.WSP_0078_ASSERTION_CREATOR_DISCOVERED(creatorClassName, supportedURI)); aoqi@0: if (supportedURI == null || supportedURI.length() == 0) { aoqi@0: throw LOGGER.logSevereException(new PolicyException( aoqi@0: LocalizationMessages.WSP_0070_ERROR_REGISTERING_ASSERTION_CREATOR(creatorClassName))); aoqi@0: } aoqi@0: aoqi@0: final PolicyAssertionCreator oldCreator = pacMap.put(supportedURI, creator); aoqi@0: if (oldCreator != null) { aoqi@0: throw LOGGER.logSevereException(new PolicyException( aoqi@0: LocalizationMessages.WSP_0071_ERROR_MULTIPLE_ASSERTION_CREATORS_FOR_NAMESPACE( aoqi@0: supportedURI, oldCreator.getClass().getName(), creator.getClass().getName()))); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: this.assertionCreators = Collections.unmodifiableMap(pacMap); aoqi@0: LOGGER.exiting(); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Method returns thread-safe policy model translator instance. aoqi@0: * aoqi@0: * This method is only intended to be used by code that has no dependencies on aoqi@0: * JAX-WS. Otherwise use com.sun.xml.internal.ws.policy.api.ModelTranslator. aoqi@0: * aoqi@0: * @return A policy model translator instance. aoqi@0: * @throws PolicyException If instantiating a PolicyAssertionCreator failed. aoqi@0: */ aoqi@0: public static PolicyModelTranslator getTranslator() throws PolicyException { aoqi@0: return new PolicyModelTranslator(); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * The method translates {@link PolicySourceModel} structure into normalized {@link Policy} expression. The resulting Policy aoqi@0: * is disconnected from its model, thus any additional changes in model will have no effect on the Policy expression. aoqi@0: * aoqi@0: * @param model the model to be translated into normalized policy expression. Must not be {@code null}. aoqi@0: * @return translated policy expression in it's normalized form. aoqi@0: * @throws PolicyException in case of translation failure aoqi@0: */ aoqi@0: public Policy translate(final PolicySourceModel model) throws PolicyException { aoqi@0: LOGGER.entering(model); aoqi@0: aoqi@0: if (model == null) { aoqi@0: throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0043_POLICY_MODEL_TRANSLATION_ERROR_INPUT_PARAM_NULL())); aoqi@0: } aoqi@0: aoqi@0: PolicySourceModel localPolicyModelCopy; aoqi@0: try { aoqi@0: localPolicyModelCopy = model.clone(); aoqi@0: } catch (CloneNotSupportedException e) { aoqi@0: throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0016_UNABLE_TO_CLONE_POLICY_SOURCE_MODEL(), e)); aoqi@0: } aoqi@0: aoqi@0: final String policyId = localPolicyModelCopy.getPolicyId(); aoqi@0: final String policyName = localPolicyModelCopy.getPolicyName(); aoqi@0: aoqi@0: final Collection alternatives = createPolicyAlternatives(localPolicyModelCopy); aoqi@0: LOGGER.finest(LocalizationMessages.WSP_0052_NUMBER_OF_ALTERNATIVE_COMBINATIONS_CREATED(alternatives.size())); aoqi@0: aoqi@0: Policy policy = null; aoqi@0: if (alternatives.size() == 0) { aoqi@0: policy = Policy.createNullPolicy(model.getNamespaceVersion(), policyName, policyId); aoqi@0: LOGGER.finest(LocalizationMessages.WSP_0055_NO_ALTERNATIVE_COMBINATIONS_CREATED()); aoqi@0: } else if (alternatives.size() == 1 && alternatives.iterator().next().isEmpty()) { aoqi@0: policy = Policy.createEmptyPolicy(model.getNamespaceVersion(), policyName, policyId); aoqi@0: LOGGER.finest(LocalizationMessages.WSP_0026_SINGLE_EMPTY_ALTERNATIVE_COMBINATION_CREATED()); aoqi@0: } else { aoqi@0: policy = Policy.createPolicy(model.getNamespaceVersion(), policyName, policyId, alternatives); aoqi@0: LOGGER.finest(LocalizationMessages.WSP_0057_N_ALTERNATIVE_COMBINATIONS_M_POLICY_ALTERNATIVES_CREATED(alternatives.size(), policy.getNumberOfAssertionSets())); aoqi@0: } aoqi@0: aoqi@0: LOGGER.exiting(policy); aoqi@0: return policy; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Method creates policy alternatives according to provided model. The model structure is modified in the process. aoqi@0: * aoqi@0: * @return created policy alternatives resulting from policy source model. aoqi@0: */ aoqi@0: private Collection createPolicyAlternatives(final PolicySourceModel model) throws PolicyException { aoqi@0: // creating global method variables aoqi@0: final ContentDecomposition decomposition = new ContentDecomposition(); aoqi@0: aoqi@0: // creating processing queue and starting the processing iterations aoqi@0: final Queue policyQueue = new LinkedList(); aoqi@0: final Queue> contentQueue = new LinkedList>(); aoqi@0: aoqi@0: final RawPolicy rootPolicy = new RawPolicy(model.getRootNode(), new LinkedList()); aoqi@0: RawPolicy processedPolicy = rootPolicy; aoqi@0: do { aoqi@0: Collection processedContent = processedPolicy.originalContent; aoqi@0: do { aoqi@0: decompose(processedContent, decomposition); aoqi@0: if (decomposition.exactlyOneContents.isEmpty()) { aoqi@0: final RawAlternative alternative = new RawAlternative(decomposition.assertions); aoqi@0: processedPolicy.alternatives.add(alternative); aoqi@0: if (!alternative.allNestedPolicies.isEmpty()) { aoqi@0: policyQueue.addAll(alternative.allNestedPolicies); aoqi@0: } aoqi@0: } else { // we have a non-empty collection of exactly ones aoqi@0: final Collection> combinations = PolicyUtils.Collections.combine(decomposition.assertions, decomposition.exactlyOneContents, false); aoqi@0: if (combinations != null && !combinations.isEmpty()) { aoqi@0: // processed alternative was split into some new alternatives, which we need to process aoqi@0: contentQueue.addAll(combinations); aoqi@0: } aoqi@0: } aoqi@0: } while ((processedContent = contentQueue.poll()) != null); aoqi@0: } while ((processedPolicy = policyQueue.poll()) != null); aoqi@0: aoqi@0: // normalize nested policies to contain single alternative only aoqi@0: final Collection assertionSets = new LinkedList(); aoqi@0: for (RawAlternative rootAlternative : rootPolicy.alternatives) { aoqi@0: final Collection normalizedAlternatives = normalizeRawAlternative(rootAlternative); aoqi@0: assertionSets.addAll(normalizedAlternatives); aoqi@0: } aoqi@0: aoqi@0: return assertionSets; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Decomposes the unprocessed alternative content into two different collections: aoqi@0: *

aoqi@0: * Content of 'EXACTLY_ONE' child nodes is expanded and placed in one list and aoqi@0: * 'ASSERTION' nodes are placed into other list. Direct 'ALL' and 'POLICY' child nodes are 'dissolved' in the process. aoqi@0: * aoqi@0: * Method reuses precreated ContentDecomposition object, which is reset before reuse. aoqi@0: */ aoqi@0: private void decompose(final Collection content, final ContentDecomposition decomposition) throws PolicyException { aoqi@0: decomposition.reset(); aoqi@0: aoqi@0: final Queue allContentQueue = new LinkedList(content); aoqi@0: ModelNode node; aoqi@0: while ((node = allContentQueue.poll()) != null) { aoqi@0: // dissolving direct 'POLICY', 'POLICY_REFERENCE' and 'ALL' child nodes aoqi@0: switch (node.getType()) { aoqi@0: case POLICY : aoqi@0: case ALL : aoqi@0: allContentQueue.addAll(node.getChildren()); aoqi@0: break; aoqi@0: case POLICY_REFERENCE : aoqi@0: allContentQueue.addAll(getReferencedModelRootNode(node).getChildren()); aoqi@0: break; aoqi@0: case EXACTLY_ONE : aoqi@0: decomposition.exactlyOneContents.add(expandsExactlyOneContent(node.getChildren())); aoqi@0: break; aoqi@0: case ASSERTION : aoqi@0: decomposition.assertions.add(node); aoqi@0: break; aoqi@0: default : aoqi@0: throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0007_UNEXPECTED_MODEL_NODE_TYPE_FOUND(node.getType()))); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: private static ModelNode getReferencedModelRootNode(final ModelNode policyReferenceNode) throws PolicyException { aoqi@0: final PolicySourceModel referencedModel = policyReferenceNode.getReferencedModel(); aoqi@0: if (referencedModel == null) { aoqi@0: final PolicyReferenceData refData = policyReferenceNode.getPolicyReferenceData(); aoqi@0: if (refData == null) { aoqi@0: throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0041_POLICY_REFERENCE_NODE_FOUND_WITH_NO_POLICY_REFERENCE_IN_IT())); aoqi@0: } else { aoqi@0: throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0010_UNEXPANDED_POLICY_REFERENCE_NODE_FOUND_REFERENCING(refData.getReferencedModelUri()))); aoqi@0: } aoqi@0: } else { aoqi@0: return referencedModel.getRootNode(); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Expands content of 'EXACTLY_ONE' node. Direct 'EXACTLY_ONE' child nodes are dissolved in the process. aoqi@0: */ aoqi@0: private Collection expandsExactlyOneContent(final Collection content) throws PolicyException { aoqi@0: final Collection result = new LinkedList(); aoqi@0: aoqi@0: final Queue eoContentQueue = new LinkedList(content); aoqi@0: ModelNode node; aoqi@0: while ((node = eoContentQueue.poll()) != null) { aoqi@0: // dissolving direct 'EXACTLY_ONE' child nodes aoqi@0: switch (node.getType()) { aoqi@0: case POLICY : aoqi@0: case ALL : aoqi@0: case ASSERTION : aoqi@0: result.add(node); aoqi@0: break; aoqi@0: case POLICY_REFERENCE : aoqi@0: result.add(getReferencedModelRootNode(node)); aoqi@0: break; aoqi@0: case EXACTLY_ONE : aoqi@0: eoContentQueue.addAll(node.getChildren()); aoqi@0: break; aoqi@0: default : aoqi@0: throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0001_UNSUPPORTED_MODEL_NODE_TYPE(node.getType()))); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: return result; aoqi@0: } aoqi@0: aoqi@0: private List normalizeRawAlternative(final RawAlternative alternative) throws AssertionCreationException, PolicyException { aoqi@0: final List normalizedContentBase = new LinkedList(); aoqi@0: final Collection> normalizedContentOptions = new LinkedList>(); aoqi@0: if (!alternative.nestedAssertions.isEmpty()) { aoqi@0: final Queue nestedAssertionsQueue = new LinkedList(alternative.nestedAssertions); aoqi@0: RawAssertion rawAssertion; aoqi@0: while((rawAssertion = nestedAssertionsQueue.poll()) != null) { aoqi@0: final List normalized = normalizeRawAssertion(rawAssertion); aoqi@0: // if there is only a single result, we can add it direclty to the content base collection aoqi@0: // more elements in the result indicate that we will have to create combinations aoqi@0: if (normalized.size() == 1) { aoqi@0: normalizedContentBase.addAll(normalized); aoqi@0: } else { aoqi@0: normalizedContentOptions.add(normalized); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: final List options = new LinkedList(); aoqi@0: if (normalizedContentOptions.isEmpty()) { aoqi@0: // we do not have any options to combine => returning this assertion aoqi@0: options.add(AssertionSet.createAssertionSet(normalizedContentBase)); aoqi@0: } else { aoqi@0: // we have some options to combine => creating assertion options based on content combinations aoqi@0: final Collection> contentCombinations = PolicyUtils.Collections.combine(normalizedContentBase, normalizedContentOptions, true); aoqi@0: for (Collection contentOption : contentCombinations) { aoqi@0: options.add(AssertionSet.createAssertionSet(contentOption)); aoqi@0: } aoqi@0: } aoqi@0: return options; aoqi@0: } aoqi@0: aoqi@0: private List normalizeRawAssertion(final RawAssertion assertion) throws AssertionCreationException, PolicyException { aoqi@0: List parameters; aoqi@0: if (assertion.parameters.isEmpty()) { aoqi@0: parameters = null; aoqi@0: } else { aoqi@0: parameters = new ArrayList(assertion.parameters.size()); aoqi@0: for (ModelNode parameterNode : assertion.parameters) { aoqi@0: parameters.add(createPolicyAssertionParameter(parameterNode)); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: final List nestedAlternatives = new LinkedList(); aoqi@0: if (assertion.nestedAlternatives != null && !assertion.nestedAlternatives.isEmpty()) { aoqi@0: final Queue nestedAlternativeQueue = new LinkedList(assertion.nestedAlternatives); aoqi@0: RawAlternative rawAlternative; aoqi@0: while((rawAlternative = nestedAlternativeQueue.poll()) != null) { aoqi@0: nestedAlternatives.addAll(normalizeRawAlternative(rawAlternative)); aoqi@0: } aoqi@0: // if there is only a single result, we can add it direclty to the content base collection aoqi@0: // more elements in the result indicate that we will have to create combinations aoqi@0: } aoqi@0: aoqi@0: final List assertionOptions = new LinkedList(); aoqi@0: final boolean nestedAlternativesAvailable = !nestedAlternatives.isEmpty(); aoqi@0: if (nestedAlternativesAvailable) { aoqi@0: for (AssertionSet nestedAlternative : nestedAlternatives) { aoqi@0: assertionOptions.add(createPolicyAssertion(assertion.originalNode.getNodeData(), parameters, nestedAlternative)); aoqi@0: } aoqi@0: } else { aoqi@0: assertionOptions.add(createPolicyAssertion(assertion.originalNode.getNodeData(), parameters, null)); aoqi@0: } aoqi@0: return assertionOptions; aoqi@0: } aoqi@0: aoqi@0: private PolicyAssertion createPolicyAssertionParameter(final ModelNode parameterNode) throws AssertionCreationException, PolicyException { aoqi@0: if (parameterNode.getType() != ModelNode.Type.ASSERTION_PARAMETER_NODE) { aoqi@0: throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0065_INCONSISTENCY_IN_POLICY_SOURCE_MODEL(parameterNode.getType()))); aoqi@0: } aoqi@0: aoqi@0: List childParameters = null; aoqi@0: if (parameterNode.hasChildren()) { aoqi@0: childParameters = new ArrayList(parameterNode.childrenSize()); aoqi@0: for (ModelNode childParameterNode : parameterNode) { aoqi@0: childParameters.add(createPolicyAssertionParameter(childParameterNode)); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: return createPolicyAssertion(parameterNode.getNodeData(), childParameters, null /* parameters do not have any nested alternatives */); aoqi@0: } aoqi@0: aoqi@0: private PolicyAssertion createPolicyAssertion(final AssertionData data, final Collection assertionParameters, final AssertionSet nestedAlternative) throws AssertionCreationException { aoqi@0: final String assertionNamespace = data.getName().getNamespaceURI(); aoqi@0: final PolicyAssertionCreator domainSpecificPAC = assertionCreators.get(assertionNamespace); aoqi@0: aoqi@0: aoqi@0: if (domainSpecificPAC == null) { aoqi@0: return defaultCreator.createAssertion(data, assertionParameters, nestedAlternative, null); aoqi@0: } else { aoqi@0: return domainSpecificPAC.createAssertion(data, assertionParameters, nestedAlternative, defaultCreator); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: }