src/share/jaxws_classes/com/sun/xml/internal/ws/policy/sourcemodel/PolicySourceModel.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

     1 /*
     2  * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    26 package com.sun.xml.internal.ws.policy.sourcemodel;
    28 import com.sun.xml.internal.ws.policy.sourcemodel.wspolicy.NamespaceVersion;
    29 import com.sun.xml.internal.ws.policy.PolicyConstants;
    30 import com.sun.xml.internal.ws.policy.PolicyException;
    31 import com.sun.xml.internal.ws.policy.privateutil.LocalizationMessages;
    32 import com.sun.xml.internal.ws.policy.privateutil.PolicyLogger;
    33 import com.sun.xml.internal.ws.policy.privateutil.PolicyUtils;
    34 import com.sun.xml.internal.ws.policy.spi.PrefixMapper;
    36 import java.util.Collection;
    37 import java.util.HashMap;
    38 import java.util.HashSet;
    39 import java.util.LinkedList;
    40 import java.util.List;
    41 import java.util.Map;
    42 import java.util.Map.Entry;
    43 import java.util.Queue;
    44 import java.util.Set;
    45 import javax.xml.namespace.QName;
    47 /**
    48  * This class is a root of unmarshaled policy source structure. Each instance of the class contains factory method
    49  * to create new {@link com.sun.xml.internal.ws.policy.sourcemodel.ModelNode} instances associated with the actual model instance.
    50  *
    51  * @author Marek Potociar
    52  * @author Fabian Ritzmann
    53  */
    54 public class PolicySourceModel implements Cloneable {
    56     private static final PolicyLogger LOGGER = PolicyLogger.getLogger(PolicySourceModel.class);
    58     private static final Map<String, String> DEFAULT_NAMESPACE_TO_PREFIX = new HashMap<String, String>();
    59     static {
    60         PrefixMapper[] prefixMappers = PolicyUtils.ServiceProvider.load(PrefixMapper.class);
    61         if (prefixMappers != null) {
    62             for (PrefixMapper mapper: prefixMappers) {
    63                 DEFAULT_NAMESPACE_TO_PREFIX.putAll(mapper.getPrefixMap());
    64             }
    65         }
    67         for (NamespaceVersion version : NamespaceVersion.values()) {
    68             DEFAULT_NAMESPACE_TO_PREFIX.put(version.toString(), version.getDefaultNamespacePrefix());
    69         }
    70         DEFAULT_NAMESPACE_TO_PREFIX.put(PolicyConstants.WSU_NAMESPACE_URI,
    71                 PolicyConstants.WSU_NAMESPACE_PREFIX);
    72         DEFAULT_NAMESPACE_TO_PREFIX.put(PolicyConstants.SUN_POLICY_NAMESPACE_URI,
    73                 PolicyConstants.SUN_POLICY_NAMESPACE_PREFIX);
    74     }
    76     // Map namespaces to prefixes
    77     private final Map<String, String> namespaceToPrefix =
    78             new HashMap<String, String>(DEFAULT_NAMESPACE_TO_PREFIX);
    80     private ModelNode rootNode;
    81     private final String policyId;
    82     private final String policyName;
    83     private final NamespaceVersion nsVersion;
    84     private final List<ModelNode> references = new LinkedList<ModelNode>(); // links to policy reference nodes
    85     private boolean expanded = false;
    88     /**
    89      * Factory method that creates new policy source model instance.
    90      *
    91      * This method is only intended to be used by code that has no dependencies on
    92      * JAX-WS. Otherwise use com.sun.xml.internal.ws.policy.api.SourceModel.
    93      *
    94      * @param nsVersion The policy version
    95      * @return Newly created policy source model instance.
    96      */
    97     public static PolicySourceModel createPolicySourceModel(final NamespaceVersion nsVersion) {
    98         return new PolicySourceModel(nsVersion);
    99     }
   101     /**
   102      * Factory method that creates new policy source model instance and initializes it according to parameters provided.
   103      *
   104      * This method is only intended to be used by code that has no dependencies on
   105      * JAX-WS. Otherwise use com.sun.xml.internal.ws.policy.api.SourceModel.
   106      *
   107      * @param nsVersion The policy version
   108      * @param policyId local policy identifier - relative URI. May be {@code null}.
   109      * @param policyName global policy identifier - absolute policy expression URI. May be {@code null}.
   110      * @return Newly created policy source model instance with its name and id properly set.
   111      */
   112     public static PolicySourceModel createPolicySourceModel(final NamespaceVersion nsVersion, final String policyId, final String policyName) {
   113         return new PolicySourceModel(nsVersion, policyId, policyName);
   114     }
   116     /**
   117      * Constructor that creates a new policy source model instance without any
   118      * id or name identifier. The namespace-to-prefix map is initialized with mapping
   119      * of policy namespace to the default value set by
   120      * {@link PolicyConstants#POLICY_NAMESPACE_PREFIX POLICY_NAMESPACE_PREFIX constant}.
   121      *
   122      * @param nsVersion The WS-Policy version.
   123      */
   124     private PolicySourceModel(NamespaceVersion nsVersion) {
   125         this(nsVersion, null, null);
   126     }
   128     /**
   129      * Constructor that creates a new policy source model instance with given
   130      * id or name identifier.
   131      *
   132      * @param nsVersion The WS-Policy version.
   133      * @param policyId Relative policy reference within an XML document. May be {@code null}.
   134      * @param policyName Absolute IRI of policy expression. May be {@code null}.
   135      */
   136     private PolicySourceModel(NamespaceVersion nsVersion, String policyId, String policyName) {
   137         this(nsVersion, policyId, policyName, null);
   138     }
   140     /**
   141      * Constructor that creates a new policy source model instance with given
   142      * id or name identifier and a set of PrefixMappers.
   143      *
   144      * This constructor is intended to be used by the JAX-WS com.sun.xml.internal.ws.policy.api.SourceModel.
   145      *
   146      * @param nsVersion The WS-Policy version.
   147      * @param policyId Relative policy reference within an XML document. May be {@code null}.
   148      * @param policyName Absolute IRI of policy expression. May be {@code null}.
   149      * @param prefixMappers A collection of PrefixMappers to be used with this instance. May be {@code null}.
   150      */
   151     protected PolicySourceModel(NamespaceVersion nsVersion, String policyId,
   152             String policyName, Collection<PrefixMapper> prefixMappers) {
   153         this.rootNode = ModelNode.createRootPolicyNode(this);
   154         this.nsVersion = nsVersion;
   155         this.policyId = policyId;
   156         this.policyName = policyName;
   157         if (prefixMappers != null) {
   158             for (PrefixMapper prefixMapper : prefixMappers) {
   159                 this.namespaceToPrefix.putAll(prefixMapper.getPrefixMap());
   160             }
   161         }
   162     }
   164     /**
   165      * Returns a root node of this policy source model. It is allways of POLICY type.
   166      *
   167      * @return root policy source model node - allways of POLICY type.
   168      */
   169     public ModelNode getRootNode() {
   170         return rootNode;
   171     }
   173     /**
   174      * Returns a policy name of this policy source model.
   175      *
   176      * @return policy name.
   177      */
   178     public String getPolicyName() {
   179         return policyName;
   180     }
   182     /**
   183      * Returns a policy ID of this policy source model.
   184      *
   185      * @return policy ID.
   186      */
   187     public String getPolicyId() {
   188         return policyId;
   189     }
   191     /**
   192      * Returns an original namespace version of this policy source model.
   193      *
   194      * @return namespace version.
   195      */
   196     public NamespaceVersion getNamespaceVersion() {
   197         return nsVersion;
   198     }
   200     /**
   201      * Provides information about how namespaces used in this {@link PolicySourceModel}
   202      * instance should be mapped to their default prefixes when marshalled.
   203      *
   204      * @return immutable map that holds information about namespaces used in the
   205      *         model and their mapping to prefixes that should be used when marshalling
   206      *         this model.
   207      * @throws PolicyException Thrown if one of the prefix mappers threw an exception.
   208      */
   209     Map<String, String> getNamespaceToPrefixMapping() throws PolicyException {
   210         final Map<String, String> nsToPrefixMap = new HashMap<String, String>();
   212         final Collection<String> namespaces = getUsedNamespaces();
   213         for (String namespace : namespaces) {
   214             final String prefix = getDefaultPrefix(namespace);
   215             if (prefix != null) {
   216                 nsToPrefixMap.put(namespace, prefix);
   217             }
   218         }
   220         return nsToPrefixMap;
   221     }
   223     /**
   224      * An {@code Object.equals(Object obj)} method override.
   225      * <p/>
   226      * When child nodes are tested for equality, the parent policy source model is not considered. Thus two different
   227      * policy source models instances may be equal based on their node content.
   228      */
   229     @Override
   230     public boolean equals(final Object obj) {
   231         if (this == obj) {
   232             return true;
   233         }
   235         if (!(obj instanceof PolicySourceModel)) {
   236             return false;
   237         }
   239         boolean result = true;
   240         final PolicySourceModel that = (PolicySourceModel) obj;
   242         result = result && ((this.policyId == null) ? that.policyId == null : this.policyId.equals(that.policyId));
   243         result = result && ((this.policyName == null) ? that.policyName == null : this.policyName.equals(that.policyName));
   244         result = result && this.rootNode.equals(that.rootNode);
   246         return result;
   247     }
   249     /**
   250      * An {@code Object.hashCode()} method override.
   251      */
   252     @Override
   253     public int hashCode() {
   254         int result = 17;
   256         result = 37 * result + ((this.policyId == null) ? 0 : this.policyId.hashCode());
   257         result = 37 * result + ((this.policyName == null) ? 0 : this.policyName.hashCode());
   258         result = 37 * result + this.rootNode.hashCode();
   260         return result;
   261     }
   263     /**
   264      * Returns a string representation of the object. In general, the <code>toString</code> method
   265      * returns a string that "textually represents" this object.
   266      *
   267      * @return  a string representation of the object.
   268      */
   269     @Override
   270     public String toString() {
   271         final String innerIndent = PolicyUtils.Text.createIndent(1);
   272         final StringBuffer buffer = new StringBuffer(60);
   274         buffer.append("Policy source model {").append(PolicyUtils.Text.NEW_LINE);
   275         buffer.append(innerIndent).append("policy id = '").append(policyId).append('\'').append(PolicyUtils.Text.NEW_LINE);
   276         buffer.append(innerIndent).append("policy name = '").append(policyName).append('\'').append(PolicyUtils.Text.NEW_LINE);
   277         rootNode.toString(1, buffer).append(PolicyUtils.Text.NEW_LINE).append('}');
   279         return buffer.toString();
   280     }
   282     @Override
   283     protected PolicySourceModel clone() throws CloneNotSupportedException {
   284         final PolicySourceModel clone = (PolicySourceModel) super.clone();
   286         clone.rootNode = this.rootNode.clone();
   287         try {
   288             clone.rootNode.setParentModel(clone);
   289         } catch (IllegalAccessException e) {
   290             throw LOGGER.logSevereException(new CloneNotSupportedException(LocalizationMessages.WSP_0013_UNABLE_TO_SET_PARENT_MODEL_ON_ROOT()), e);
   291         }
   293         return clone;
   294     }
   296     /**
   297      * Returns a boolean value indicating whether this policy source model contains references to another policy source models.
   298      * <p/>
   299      * Every source model that references other policies must be expanded before it can be translated into a Policy objects. See
   300      * {@link #expand(PolicySourceModelContext)} and {@link #isExpanded()} for more details.
   301      *
   302      * @return {@code true} or {code false} depending on whether this policy source model contains references to another policy source models.
   303      */
   304     public boolean containsPolicyReferences() {
   305         return !references.isEmpty();
   306     }
   308     /**
   309      * Returns a boolean value indicating whether this policy source model contains is already expanded (i.e. contains no unexpanded
   310      * policy references) or not. This means that if model does not originally contain any policy references, it is considered as expanded,
   311      * thus this method returns {@code true} in such case. Also this method does not check whether the references policy source models are expanded
   312      * 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
   313      * can be considered to be fully expanded only if all policy source models stored in PolicySourceModelContext instance are expanded, provided the
   314      * PolicySourceModelContext instance contains full set of policy source models.
   315      * <p/>
   316      * Every source model that references other policies must be expanded before it can be translated into a Policy object. See
   317      * {@link #expand(PolicySourceModelContext)} and {@link #containsPolicyReferences()} for more details.
   318      *
   319      * @return {@code true} or {@code false} depending on whether this policy source model contains is expanded or not.
   320      */
   321     private boolean isExpanded() {
   322         return references.isEmpty() || expanded;
   323     }
   325     /**
   326      * Expands current policy model. This means, that if this model contains any (unexpanded) policy references, then the method expands those
   327      * references by placing the content of the referenced policy source models under the policy reference nodes. This operation merely creates
   328      * a link between this and referenced policy source models. Thus any change in the referenced models will be visible wihtin this model as well.
   329      * <p/>
   330      * Please, notice that the method does not check if the referenced models are already expanded nor does the method try to expand unexpanded
   331      * referenced models. This must be preformed manually within client's code. Consecutive calls of this method will have no effect.
   332      * <p/>
   333      * Every source model that references other policies must be expanded before it can be translated into a Policy object. See
   334      * {@link #isExpanded()} and {@link #containsPolicyReferences()} for more details.
   335      *
   336      * @param context a policy source model context holding the set of unmarshalled policy source models within the same context.
   337      * @throws PolicyException Thrown if a referenced policy could not be resolved
   338      */
   339     public synchronized void expand(final PolicySourceModelContext context) throws PolicyException {
   340         if (!isExpanded()) {
   341             for (ModelNode reference : references) {
   342                 final PolicyReferenceData refData = reference.getPolicyReferenceData();
   343                 final String digest = refData.getDigest();
   344                 PolicySourceModel referencedModel;
   345                 if (digest == null) {
   346                     referencedModel = context.retrieveModel(refData.getReferencedModelUri());
   347                 } else {
   348                     referencedModel = context.retrieveModel(refData.getReferencedModelUri(), refData.getDigestAlgorithmUri(), digest);
   349                 }
   351                 reference.setReferencedModel(referencedModel);
   352             }
   353             expanded = true;
   354         }
   355     }
   357     /**
   358      * Adds new policy reference to the policy source model. The method is used by
   359      * the ModelNode instances of type POLICY_REFERENCE that need to register themselves
   360      * as policy references in the model.
   361      *
   362      * @param node policy reference model node to be registered as a policy reference
   363      *        in this model.
   364      */
   365     void addNewPolicyReference(final ModelNode node) {
   366         if (node.getType() != ModelNode.Type.POLICY_REFERENCE) {
   367             throw new IllegalArgumentException(LocalizationMessages.WSP_0042_POLICY_REFERENCE_NODE_EXPECTED_INSTEAD_OF(node.getType()));
   368         }
   370         references.add(node);
   371     }
   373     /**
   374      * Iterates through policy vocabulary and extracts set of namespaces used in
   375      * the policy expression.
   376      *
   377      * @return collection of used namespaces within given policy instance
   378      * @throws PolicyException Thrown if internal processing failed.
   379      */
   380     private Collection<String> getUsedNamespaces() throws PolicyException {
   381         final Set<String> namespaces = new HashSet<String>();
   382         namespaces.add(getNamespaceVersion().toString());
   384         if (this.policyId != null) {
   385             namespaces.add(PolicyConstants.WSU_NAMESPACE_URI);
   386         }
   388         final Queue<ModelNode> nodesToBeProcessed = new LinkedList<ModelNode>();
   389         nodesToBeProcessed.add(rootNode);
   391         ModelNode processedNode;
   392         while ((processedNode = nodesToBeProcessed.poll()) != null) {
   393             for (ModelNode child : processedNode.getChildren()) {
   394                 if (child.hasChildren()) {
   395                     if (!nodesToBeProcessed.offer(child)) {
   396                         throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0081_UNABLE_TO_INSERT_CHILD(nodesToBeProcessed, child)));
   397                     }
   398                 }
   400                 if (child.isDomainSpecific()) {
   401                     final AssertionData nodeData = child.getNodeData();
   402                     namespaces.add(nodeData.getName().getNamespaceURI());
   403                     if (nodeData.isPrivateAttributeSet()) {
   404                         namespaces.add(PolicyConstants.SUN_POLICY_NAMESPACE_URI);
   405                     }
   407                     for (Entry<QName, String> attribute : nodeData.getAttributesSet()) {
   408                         namespaces.add(attribute.getKey().getNamespaceURI());
   409                     }
   410                 }
   411             }
   412         }
   414         return namespaces;
   415     }
   417     /**
   418      * Method retrieves default prefix for given namespace. Method returns null if
   419      * no default prefix is defined..
   420      *
   421      * @param namespace to get default prefix for.
   422      * @return default prefix for given namespace. May return {@code null} if the
   423      *         default prefix for given namespace is not defined.
   424      */
   425     private String getDefaultPrefix(final String namespace) {
   426         return namespaceToPrefix.get(namespace);
   427     }
   428 }

mercurial