325N/A/*
325N/A * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
325N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
325N/A *
325N/A * This code is free software; you can redistribute it and/or modify it
325N/A * under the terms of the GNU General Public License version 2 only, as
325N/A * published by the Free Software Foundation. Oracle designates this
325N/A * particular file as subject to the "Classpath" exception as provided
325N/A * by Oracle in the LICENSE file that accompanied this code.
325N/A *
325N/A * This code is distributed in the hope that it will be useful, but WITHOUT
325N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
325N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
325N/A * version 2 for more details (a copy is included in the LICENSE file that
325N/A * accompanied this code).
325N/A *
325N/A * You should have received a copy of the GNU General Public License version
325N/A * 2 along with this work; if not, write to the Free Software Foundation,
325N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
325N/A *
325N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
325N/A * or visit www.oracle.com if you need additional information or have any
325N/A * questions.
325N/A */
325N/A
325N/Apackage com.sun.xml.internal.ws.policy.sourcemodel;
325N/A
325N/Aimport com.sun.xml.internal.ws.policy.sourcemodel.wspolicy.NamespaceVersion;
325N/Aimport com.sun.xml.internal.ws.policy.PolicyConstants;
325N/Aimport com.sun.xml.internal.ws.policy.PolicyException;
325N/Aimport com.sun.xml.internal.ws.policy.privateutil.LocalizationMessages;
325N/Aimport com.sun.xml.internal.ws.policy.privateutil.PolicyLogger;
325N/Aimport com.sun.xml.internal.ws.policy.privateutil.PolicyUtils;
325N/Aimport com.sun.xml.internal.ws.policy.spi.PrefixMapper;
325N/A
325N/Aimport java.util.Collection;
325N/Aimport java.util.HashMap;
325N/Aimport java.util.HashSet;
325N/Aimport java.util.LinkedList;
325N/Aimport java.util.List;
325N/Aimport java.util.Map;
325N/Aimport java.util.Map.Entry;
325N/Aimport java.util.Queue;
325N/Aimport java.util.Set;
325N/Aimport javax.xml.namespace.QName;
325N/A
325N/A/**
325N/A * This class is a root of unmarshaled policy source structure. Each instance of the class contains factory method
325N/A * to create new {@link com.sun.xml.internal.ws.policy.sourcemodel.ModelNode} instances associated with the actual model instance.
325N/A *
325N/A * @author Marek Potociar
325N/A * @author Fabian Ritzmann
325N/A */
325N/Apublic class PolicySourceModel implements Cloneable {
325N/A
325N/A private static final PolicyLogger LOGGER = PolicyLogger.getLogger(PolicySourceModel.class);
325N/A
325N/A private static final Map<String, String> DEFAULT_NAMESPACE_TO_PREFIX = new HashMap<String, String>();
325N/A static {
325N/A PrefixMapper[] prefixMappers = PolicyUtils.ServiceProvider.load(PrefixMapper.class);
325N/A if (prefixMappers != null) {
325N/A for (PrefixMapper mapper: prefixMappers) {
325N/A DEFAULT_NAMESPACE_TO_PREFIX.putAll(mapper.getPrefixMap());
325N/A }
325N/A }
325N/A
325N/A for (NamespaceVersion version : NamespaceVersion.values()) {
325N/A DEFAULT_NAMESPACE_TO_PREFIX.put(version.toString(), version.getDefaultNamespacePrefix());
325N/A }
325N/A DEFAULT_NAMESPACE_TO_PREFIX.put(PolicyConstants.WSU_NAMESPACE_URI,
325N/A PolicyConstants.WSU_NAMESPACE_PREFIX);
325N/A DEFAULT_NAMESPACE_TO_PREFIX.put(PolicyConstants.SUN_POLICY_NAMESPACE_URI,
325N/A PolicyConstants.SUN_POLICY_NAMESPACE_PREFIX);
325N/A }
325N/A
325N/A // Map namespaces to prefixes
325N/A private final Map<String, String> namespaceToPrefix =
325N/A new HashMap<String, String>(DEFAULT_NAMESPACE_TO_PREFIX);
325N/A
325N/A private ModelNode rootNode;
325N/A private final String policyId;
325N/A private final String policyName;
325N/A private final NamespaceVersion nsVersion;
325N/A private final List<ModelNode> references = new LinkedList<ModelNode>(); // links to policy reference nodes
325N/A private boolean expanded = false;
325N/A
325N/A
325N/A /**
325N/A * Factory method that creates new policy source model instance.
325N/A *
325N/A * This method is only intended to be used by code that has no dependencies on
325N/A * JAX-WS. Otherwise use com.sun.xml.internal.ws.policy.api.SourceModel.
325N/A *
325N/A * @param nsVersion The policy version
325N/A * @return Newly created policy source model instance.
325N/A */
325N/A public static PolicySourceModel createPolicySourceModel(final NamespaceVersion nsVersion) {
325N/A return new PolicySourceModel(nsVersion);
325N/A }
325N/A
325N/A /**
325N/A * Factory method that creates new policy source model instance and initializes it according to parameters provided.
325N/A *
325N/A * This method is only intended to be used by code that has no dependencies on
325N/A * JAX-WS. Otherwise use com.sun.xml.internal.ws.policy.api.SourceModel.
325N/A *
325N/A * @param nsVersion The policy version
325N/A * @param policyId local policy identifier - relative URI. May be {@code null}.
325N/A * @param policyName global policy identifier - absolute policy expression URI. May be {@code null}.
325N/A * @return Newly created policy source model instance with its name and id properly set.
325N/A */
325N/A public static PolicySourceModel createPolicySourceModel(final NamespaceVersion nsVersion, final String policyId, final String policyName) {
325N/A return new PolicySourceModel(nsVersion, policyId, policyName);
325N/A }
325N/A
325N/A /**
325N/A * Constructor that creates a new policy source model instance without any
325N/A * id or name identifier. The namespace-to-prefix map is initialized with mapping
325N/A * of policy namespace to the default value set by
325N/A * {@link PolicyConstants#POLICY_NAMESPACE_PREFIX POLICY_NAMESPACE_PREFIX constant}.
325N/A *
325N/A * @param nsVersion The WS-Policy version.
325N/A */
325N/A private PolicySourceModel(NamespaceVersion nsVersion) {
325N/A this(nsVersion, null, null);
325N/A }
325N/A
325N/A /**
325N/A * Constructor that creates a new policy source model instance with given
325N/A * id or name identifier.
325N/A *
325N/A * @param nsVersion The WS-Policy version.
325N/A * @param policyId Relative policy reference within an XML document. May be {@code null}.
325N/A * @param policyName Absolute IRI of policy expression. May be {@code null}.
325N/A */
325N/A private PolicySourceModel(NamespaceVersion nsVersion, String policyId, String policyName) {
325N/A this(nsVersion, policyId, policyName, null);
325N/A }
325N/A
325N/A /**
325N/A * Constructor that creates a new policy source model instance with given
325N/A * id or name identifier and a set of PrefixMappers.
325N/A *
325N/A * This constructor is intended to be used by the JAX-WS com.sun.xml.internal.ws.policy.api.SourceModel.
325N/A *
325N/A * @param nsVersion The WS-Policy version.
325N/A * @param policyId Relative policy reference within an XML document. May be {@code null}.
325N/A * @param policyName Absolute IRI of policy expression. May be {@code null}.
325N/A * @param prefixMappers A collection of PrefixMappers to be used with this instance. May be {@code null}.
325N/A */
325N/A protected PolicySourceModel(NamespaceVersion nsVersion, String policyId,
325N/A String policyName, Collection<PrefixMapper> prefixMappers) {
325N/A this.rootNode = ModelNode.createRootPolicyNode(this);
325N/A this.nsVersion = nsVersion;
325N/A this.policyId = policyId;
325N/A this.policyName = policyName;
325N/A if (prefixMappers != null) {
325N/A for (PrefixMapper prefixMapper : prefixMappers) {
325N/A this.namespaceToPrefix.putAll(prefixMapper.getPrefixMap());
325N/A }
325N/A }
325N/A }
325N/A
325N/A /**
325N/A * Returns a root node of this policy source model. It is allways of POLICY type.
325N/A *
325N/A * @return root policy source model node - allways of POLICY type.
325N/A */
325N/A public ModelNode getRootNode() {
325N/A return rootNode;
325N/A }
325N/A
325N/A /**
325N/A * Returns a policy name of this policy source model.
325N/A *
325N/A * @return policy name.
325N/A */
325N/A public String getPolicyName() {
325N/A return policyName;
325N/A }
325N/A
325N/A /**
325N/A * Returns a policy ID of this policy source model.
325N/A *
325N/A * @return policy ID.
325N/A */
325N/A public String getPolicyId() {
325N/A return policyId;
325N/A }
325N/A
325N/A /**
325N/A * Returns an original namespace version of this policy source model.
325N/A *
325N/A * @return namespace version.
325N/A */
325N/A public NamespaceVersion getNamespaceVersion() {
325N/A return nsVersion;
325N/A }
325N/A
325N/A /**
325N/A * Provides information about how namespaces used in this {@link PolicySourceModel}
325N/A * instance should be mapped to their default prefixes when marshalled.
325N/A *
325N/A * @return immutable map that holds information about namespaces used in the
325N/A * model and their mapping to prefixes that should be used when marshalling
325N/A * this model.
325N/A * @throws PolicyException Thrown if one of the prefix mappers threw an exception.
325N/A */
325N/A Map<String, String> getNamespaceToPrefixMapping() throws PolicyException {
325N/A final Map<String, String> nsToPrefixMap = new HashMap<String, String>();
325N/A
325N/A final Collection<String> namespaces = getUsedNamespaces();
325N/A for (String namespace : namespaces) {
325N/A final String prefix = getDefaultPrefix(namespace);
325N/A if (prefix != null) {
325N/A nsToPrefixMap.put(namespace, prefix);
325N/A }
325N/A }
325N/A
325N/A return nsToPrefixMap;
325N/A }
325N/A
325N/A /**
325N/A * An {@code Object.equals(Object obj)} method override.
325N/A * <p/>
325N/A * When child nodes are tested for equality, the parent policy source model is not considered. Thus two different
325N/A * policy source models instances may be equal based on their node content.
325N/A */
325N/A @Override
325N/A public boolean equals(final Object obj) {
325N/A if (this == obj) {
325N/A return true;
325N/A }
325N/A
325N/A if (!(obj instanceof PolicySourceModel)) {
325N/A return false;
325N/A }
325N/A
325N/A boolean result = true;
325N/A final PolicySourceModel that = (PolicySourceModel) obj;
325N/A
325N/A result = result && ((this.policyId == null) ? that.policyId == null : this.policyId.equals(that.policyId));
325N/A result = result && ((this.policyName == null) ? that.policyName == null : this.policyName.equals(that.policyName));
325N/A result = result && this.rootNode.equals(that.rootNode);
325N/A
325N/A return result;
325N/A }
325N/A
325N/A /**
325N/A * An {@code Object.hashCode()} method override.
325N/A */
325N/A @Override
325N/A public int hashCode() {
325N/A int result = 17;
325N/A
325N/A result = 37 * result + ((this.policyId == null) ? 0 : this.policyId.hashCode());
325N/A result = 37 * result + ((this.policyName == null) ? 0 : this.policyName.hashCode());
325N/A result = 37 * result + this.rootNode.hashCode();
325N/A
325N/A return result;
325N/A }
325N/A
325N/A /**
325N/A * Returns a string representation of the object. In general, the <code>toString</code> method
325N/A * returns a string that "textually represents" this object.
325N/A *
325N/A * @return a string representation of the object.
325N/A */
325N/A @Override
325N/A public String toString() {
325N/A final String innerIndent = PolicyUtils.Text.createIndent(1);
325N/A final StringBuffer buffer = new StringBuffer(60);
325N/A
325N/A buffer.append("Policy source model {").append(PolicyUtils.Text.NEW_LINE);
325N/A buffer.append(innerIndent).append("policy id = '").append(policyId).append('\'').append(PolicyUtils.Text.NEW_LINE);
325N/A buffer.append(innerIndent).append("policy name = '").append(policyName).append('\'').append(PolicyUtils.Text.NEW_LINE);
325N/A rootNode.toString(1, buffer).append(PolicyUtils.Text.NEW_LINE).append('}');
325N/A
325N/A return buffer.toString();
325N/A }
325N/A
325N/A @Override
325N/A protected PolicySourceModel clone() throws CloneNotSupportedException {
325N/A final PolicySourceModel clone = (PolicySourceModel) super.clone();
325N/A
325N/A clone.rootNode = this.rootNode.clone();
325N/A try {
325N/A clone.rootNode.setParentModel(clone);
325N/A } catch (IllegalAccessException e) {
325N/A throw LOGGER.logSevereException(new CloneNotSupportedException(LocalizationMessages.WSP_0013_UNABLE_TO_SET_PARENT_MODEL_ON_ROOT()), e);
325N/A }
325N/A
325N/A return clone;
325N/A }
325N/A
325N/A /**
325N/A * Returns a boolean value indicating whether this policy source model contains references to another policy source models.
325N/A * <p/>
325N/A * Every source model that references other policies must be expanded before it can be translated into a Policy objects. See
325N/A * {@link #expand(PolicySourceModelContext)} and {@link #isExpanded()} for more details.
325N/A *
325N/A * @return {@code true} or {code false} depending on whether this policy source model contains references to another policy source models.
325N/A */
325N/A public boolean containsPolicyReferences() {
325N/A return !references.isEmpty();
325N/A }
325N/A
325N/A /**
325N/A * Returns a boolean value indicating whether this policy source model contains is already expanded (i.e. contains no unexpanded
325N/A * policy references) or not. This means that if model does not originally contain any policy references, it is considered as expanded,
325N/A * thus this method returns {@code true} in such case. Also this method does not check whether the references policy source models are expanded
325N/A * as well, so after expanding this model a value of {@code true} is returned even if referenced models are not expanded yet. Thus each model
325N/A * can be considered to be fully expanded only if all policy source models stored in PolicySourceModelContext instance are expanded, provided the
325N/A * PolicySourceModelContext instance contains full set of policy source models.
325N/A * <p/>
325N/A * Every source model that references other policies must be expanded before it can be translated into a Policy object. See
325N/A * {@link #expand(PolicySourceModelContext)} and {@link #containsPolicyReferences()} for more details.
325N/A *
325N/A * @return {@code true} or {@code false} depending on whether this policy source model contains is expanded or not.
325N/A */
325N/A private boolean isExpanded() {
325N/A return references.isEmpty() || expanded;
325N/A }
325N/A
325N/A /**
325N/A * Expands current policy model. This means, that if this model contains any (unexpanded) policy references, then the method expands those
325N/A * references by placing the content of the referenced policy source models under the policy reference nodes. This operation merely creates
325N/A * a link between this and referenced policy source models. Thus any change in the referenced models will be visible wihtin this model as well.
325N/A * <p/>
325N/A * Please, notice that the method does not check if the referenced models are already expanded nor does the method try to expand unexpanded
325N/A * referenced models. This must be preformed manually within client's code. Consecutive calls of this method will have no effect.
325N/A * <p/>
325N/A * Every source model that references other policies must be expanded before it can be translated into a Policy object. See
325N/A * {@link #isExpanded()} and {@link #containsPolicyReferences()} for more details.
325N/A *
325N/A * @param context a policy source model context holding the set of unmarshalled policy source models within the same context.
325N/A * @throws PolicyException Thrown if a referenced policy could not be resolved
325N/A */
325N/A public synchronized void expand(final PolicySourceModelContext context) throws PolicyException {
325N/A if (!isExpanded()) {
325N/A for (ModelNode reference : references) {
325N/A final PolicyReferenceData refData = reference.getPolicyReferenceData();
325N/A final String digest = refData.getDigest();
325N/A PolicySourceModel referencedModel;
325N/A if (digest == null) {
325N/A referencedModel = context.retrieveModel(refData.getReferencedModelUri());
325N/A } else {
325N/A referencedModel = context.retrieveModel(refData.getReferencedModelUri(), refData.getDigestAlgorithmUri(), digest);
325N/A }
325N/A
325N/A reference.setReferencedModel(referencedModel);
325N/A }
325N/A expanded = true;
325N/A }
325N/A }
325N/A
325N/A /**
325N/A * Adds new policy reference to the policy source model. The method is used by
325N/A * the ModelNode instances of type POLICY_REFERENCE that need to register themselves
325N/A * as policy references in the model.
325N/A *
325N/A * @param node policy reference model node to be registered as a policy reference
325N/A * in this model.
325N/A */
325N/A void addNewPolicyReference(final ModelNode node) {
325N/A if (node.getType() != ModelNode.Type.POLICY_REFERENCE) {
325N/A throw new IllegalArgumentException(LocalizationMessages.WSP_0042_POLICY_REFERENCE_NODE_EXPECTED_INSTEAD_OF(node.getType()));
325N/A }
325N/A
325N/A references.add(node);
325N/A }
325N/A
325N/A /**
325N/A * Iterates through policy vocabulary and extracts set of namespaces used in
325N/A * the policy expression.
325N/A *
325N/A * @return collection of used namespaces within given policy instance
325N/A * @throws PolicyException Thrown if internal processing failed.
325N/A */
325N/A private Collection<String> getUsedNamespaces() throws PolicyException {
325N/A final Set<String> namespaces = new HashSet<String>();
325N/A namespaces.add(getNamespaceVersion().toString());
325N/A
325N/A if (this.policyId != null) {
325N/A namespaces.add(PolicyConstants.WSU_NAMESPACE_URI);
325N/A }
325N/A
325N/A final Queue<ModelNode> nodesToBeProcessed = new LinkedList<ModelNode>();
325N/A nodesToBeProcessed.add(rootNode);
325N/A
325N/A ModelNode processedNode;
325N/A while ((processedNode = nodesToBeProcessed.poll()) != null) {
325N/A for (ModelNode child : processedNode.getChildren()) {
325N/A if (child.hasChildren()) {
325N/A if (!nodesToBeProcessed.offer(child)) {
325N/A throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0081_UNABLE_TO_INSERT_CHILD(nodesToBeProcessed, child)));
325N/A }
325N/A }
325N/A
325N/A if (child.isDomainSpecific()) {
325N/A final AssertionData nodeData = child.getNodeData();
325N/A namespaces.add(nodeData.getName().getNamespaceURI());
325N/A if (nodeData.isPrivateAttributeSet()) {
325N/A namespaces.add(PolicyConstants.SUN_POLICY_NAMESPACE_URI);
325N/A }
325N/A
325N/A for (Entry<QName, String> attribute : nodeData.getAttributesSet()) {
325N/A namespaces.add(attribute.getKey().getNamespaceURI());
325N/A }
325N/A }
325N/A }
325N/A }
325N/A
325N/A return namespaces;
325N/A }
325N/A
325N/A /**
325N/A * Method retrieves default prefix for given namespace. Method returns null if
325N/A * no default prefix is defined..
325N/A *
325N/A * @param namespace to get default prefix for.
325N/A * @return default prefix for given namespace. May return {@code null} if the
325N/A * default prefix for given namespace is not defined.
325N/A */
325N/A private String getDefaultPrefix(final String namespace) {
325N/A return namespaceToPrefix.get(namespace);
325N/A }
325N/A}