src/share/jaxws_classes/com/sun/xml/internal/ws/policy/sourcemodel/XmlPolicyModelUnmarshaller.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.PolicyConstants;
    29 import com.sun.xml.internal.ws.policy.PolicyException;
    30 import com.sun.xml.internal.ws.policy.privateutil.LocalizationMessages;
    31 import com.sun.xml.internal.ws.policy.privateutil.PolicyLogger;
    32 import com.sun.xml.internal.ws.policy.sourcemodel.wspolicy.NamespaceVersion;
    33 import com.sun.xml.internal.ws.policy.sourcemodel.wspolicy.XmlToken;
    35 import java.io.Reader;
    36 import java.net.URI;
    37 import java.net.URISyntaxException;
    38 import java.util.HashMap;
    39 import java.util.Iterator;
    40 import java.util.Map;
    41 import javax.xml.namespace.QName;
    42 import javax.xml.stream.XMLEventReader;
    43 import javax.xml.stream.XMLInputFactory;
    44 import javax.xml.stream.XMLStreamConstants;
    45 import javax.xml.stream.XMLStreamException;
    46 import javax.xml.stream.events.Attribute;
    47 import javax.xml.stream.events.Characters;
    48 import javax.xml.stream.events.EndElement;
    49 import javax.xml.stream.events.StartElement;
    50 import javax.xml.stream.events.XMLEvent;
    52 /**
    53  * Unmarshal XML policy expressions.
    54  *
    55  * @author Marek Potociar
    56  * @author Fabian Ritzmann
    57  */
    58 public class XmlPolicyModelUnmarshaller extends PolicyModelUnmarshaller {
    60     private static final PolicyLogger LOGGER = PolicyLogger.getLogger(XmlPolicyModelUnmarshaller.class);
    62     /**
    63      * Creates a new instance of XmlPolicyModelUnmarshaller
    64      */
    65     protected XmlPolicyModelUnmarshaller() {
    66         // nothing to initialize
    67     }
    69     /**
    70      * See {@link PolicyModelUnmarshaller#unmarshalModel(Object) base method documentation}.
    71      */
    72     public PolicySourceModel unmarshalModel(final Object storage) throws PolicyException {
    73         final XMLEventReader reader = createXMLEventReader(storage);
    74         PolicySourceModel model = null;
    76         loop:
    77         while (reader.hasNext()) {
    78             try {
    79                 final XMLEvent event = reader.peek();
    80                 switch (event.getEventType()) {
    81                     case XMLStreamConstants.START_DOCUMENT:
    82                     case XMLStreamConstants.COMMENT:
    83                         reader.nextEvent();
    84                         break; // skipping the comments and start document events
    85                     case XMLStreamConstants.CHARACTERS:
    86                         processCharacters(ModelNode.Type.POLICY, event.asCharacters(), null);
    87                         // we advance the reader only if there is no exception thrown from
    88                         // the processCharacters(...) call. Otherwise we don't modify the stream
    89                         reader.nextEvent();
    90                         break;
    91                     case XMLStreamConstants.START_ELEMENT:
    92                         if (NamespaceVersion.resolveAsToken(event.asStartElement().getName()) == XmlToken.Policy) {
    93                             StartElement rootElement = reader.nextEvent().asStartElement();
    95                             model = initializeNewModel(rootElement);
    96                             unmarshalNodeContent(model.getNamespaceVersion(), model.getRootNode(), rootElement.getName(), reader);
    98                             break loop;
    99                         } else {
   100                             throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0048_POLICY_ELEMENT_EXPECTED_FIRST()));
   101                         }
   102                     default:
   103                         throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0048_POLICY_ELEMENT_EXPECTED_FIRST()));
   104                 }
   105             } catch (XMLStreamException e) {
   106                 throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0068_FAILED_TO_UNMARSHALL_POLICY_EXPRESSION(), e));
   107             }
   108         }
   109         return model;
   110     }
   112     /**
   113      * Allow derived classes to pass in a custom instance of PolicySourceModel.
   114      *
   115      * @param nsVersion
   116      * @param id
   117      * @param name
   118      * @return
   119      */
   120     protected PolicySourceModel createSourceModel(NamespaceVersion nsVersion, String id, String name) {
   121         return PolicySourceModel.createPolicySourceModel(nsVersion, id, name);
   122     }
   124     private PolicySourceModel initializeNewModel(final StartElement element) throws PolicyException, XMLStreamException {
   125         PolicySourceModel model;
   127         final NamespaceVersion nsVersion = NamespaceVersion.resolveVersion(element.getName().getNamespaceURI());
   129         final Attribute policyName = getAttributeByName(element, nsVersion.asQName(XmlToken.Name));
   130         final Attribute xmlId = getAttributeByName(element, PolicyConstants.XML_ID);
   131         Attribute policyId = getAttributeByName(element, PolicyConstants.WSU_ID);
   133         if (policyId == null) {
   134             policyId = xmlId;
   135         } else if (xmlId != null) {
   136             throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0058_MULTIPLE_POLICY_IDS_NOT_ALLOWED()));
   137         }
   139         model = createSourceModel(nsVersion,
   140                 (policyId == null) ? null : policyId.getValue(),
   141                 (policyName == null) ? null : policyName.getValue());
   143         return model;
   144     }
   146     private ModelNode addNewChildNode(final NamespaceVersion nsVersion, final ModelNode parentNode, final StartElement childElement) throws PolicyException {
   147         ModelNode childNode;
   148         final QName childElementName = childElement.getName();
   149         if (parentNode.getType() == ModelNode.Type.ASSERTION_PARAMETER_NODE) {
   150             childNode = parentNode.createChildAssertionParameterNode();
   151         } else {
   152             XmlToken token = NamespaceVersion.resolveAsToken(childElementName);
   154             switch (token) {
   155                 case Policy:
   156                     childNode = parentNode.createChildPolicyNode();
   157                     break;
   158                 case All:
   159                     childNode = parentNode.createChildAllNode();
   160                     break;
   161                 case ExactlyOne:
   162                     childNode = parentNode.createChildExactlyOneNode();
   163                     break;
   164                 case PolicyReference:
   165                     final Attribute uri = getAttributeByName(childElement, nsVersion.asQName(XmlToken.Uri));
   166                     if (uri == null) {
   167                         throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0040_POLICY_REFERENCE_URI_ATTR_NOT_FOUND()));
   168                     } else {
   169                         try {
   170                             final URI reference = new URI(uri.getValue());
   171                             final Attribute digest = getAttributeByName(childElement, nsVersion.asQName(XmlToken.Digest));
   172                             PolicyReferenceData refData;
   173                             if (digest == null) {
   174                                 refData = new PolicyReferenceData(reference);
   175                             } else {
   176                                 final Attribute digestAlgorithm = getAttributeByName(childElement, nsVersion.asQName(XmlToken.DigestAlgorithm));
   177                                 URI algorithmRef = null;
   178                                 if (digestAlgorithm != null) {
   179                                     algorithmRef = new URI(digestAlgorithm.getValue());
   180                                 }
   181                                 refData = new PolicyReferenceData(reference, digest.getValue(), algorithmRef);
   182                             }
   183                             childNode = parentNode.createChildPolicyReferenceNode(refData);
   184                         } catch (URISyntaxException e) {
   185                             throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0012_UNABLE_TO_UNMARSHALL_POLICY_MALFORMED_URI(), e));
   186                         }
   187                     }
   188                     break;
   189                 default:
   190                     if (parentNode.isDomainSpecific()) {
   191                         childNode = parentNode.createChildAssertionParameterNode();
   192                     } else {
   193                         childNode = parentNode.createChildAssertionNode();
   194                     }
   195             }
   196         }
   198         return childNode;
   199     }
   201     private void parseAssertionData(NamespaceVersion nsVersion, String value, ModelNode childNode, final StartElement childElement) throws IllegalArgumentException, PolicyException {
   202         // finish assertion node processing: create and set assertion data...
   203         final Map<QName, String> attributeMap = new HashMap<QName, String>();
   204         boolean optional = false;
   205         boolean ignorable = false;
   207         final Iterator iterator = childElement.getAttributes();
   208         while (iterator.hasNext()) {
   209             final Attribute nextAttribute = (Attribute) iterator.next();
   210             final QName name = nextAttribute.getName();
   211             if (attributeMap.containsKey(name)) {
   212                 throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0059_MULTIPLE_ATTRS_WITH_SAME_NAME_DETECTED_FOR_ASSERTION(nextAttribute.getName(), childElement.getName())));
   213             } else {
   214                 if (nsVersion.asQName(XmlToken.Optional).equals(name)) {
   215                     optional = parseBooleanValue(nextAttribute.getValue());
   216                 } else if (nsVersion.asQName(XmlToken.Ignorable).equals(name)) {
   217                     ignorable = parseBooleanValue(nextAttribute.getValue());
   218                 } else {
   219                     attributeMap.put(name, nextAttribute.getValue());
   220                 }
   221             }
   222         }
   223         final AssertionData nodeData = new AssertionData(childElement.getName(), value, attributeMap, childNode.getType(), optional, ignorable);
   225         // check visibility value syntax if present...
   226         if (nodeData.containsAttribute(PolicyConstants.VISIBILITY_ATTRIBUTE)) {
   227             final String visibilityValue = nodeData.getAttributeValue(PolicyConstants.VISIBILITY_ATTRIBUTE);
   228             if (!PolicyConstants.VISIBILITY_VALUE_PRIVATE.equals(visibilityValue)) {
   229                 throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0004_UNEXPECTED_VISIBILITY_ATTR_VALUE(visibilityValue)));
   230             }
   231         }
   233         childNode.setOrReplaceNodeData(nodeData);
   234     }
   236     private Attribute getAttributeByName(final StartElement element,
   237             final QName attributeName) {
   238         // call standard API method to retrieve the attribute by name
   239         Attribute attribute = element.getAttributeByName(attributeName);
   241         // try to find the attribute without a prefix.
   242         if (attribute == null) {
   243             final String localAttributeName = attributeName.getLocalPart();
   244             final Iterator iterator = element.getAttributes();
   245             while (iterator.hasNext()) {
   246                 final Attribute nextAttribute = (Attribute) iterator.next();
   247                 final QName aName = nextAttribute.getName();
   248                 final boolean attributeFoundByWorkaround = aName.equals(attributeName) || (aName.getLocalPart().equals(localAttributeName) && (aName.getPrefix() == null || "".equals(aName.getPrefix())));
   249                 if (attributeFoundByWorkaround) {
   250                     attribute = nextAttribute;
   251                     break;
   252                 }
   254             }
   255         }
   257         return attribute;
   258     }
   260     private String unmarshalNodeContent(final NamespaceVersion nsVersion, final ModelNode node, final QName nodeElementName, final XMLEventReader reader) throws PolicyException {
   261         StringBuilder valueBuffer = null;
   263         loop:
   264         while (reader.hasNext()) {
   265             try {
   266                 final XMLEvent xmlParserEvent = reader.nextEvent();
   267                 switch (xmlParserEvent.getEventType()) {
   268                     case XMLStreamConstants.COMMENT:
   269                         break; // skipping the comments
   270                     case XMLStreamConstants.CHARACTERS:
   271                         valueBuffer = processCharacters(node.getType(), xmlParserEvent.asCharacters(), valueBuffer);
   272                         break;
   273                     case XMLStreamConstants.END_ELEMENT:
   274                         checkEndTagName(nodeElementName, xmlParserEvent.asEndElement());
   275                         break loop; // data exctraction for currently processed policy node is done
   276                     case XMLStreamConstants.START_ELEMENT:
   277                         final StartElement childElement = xmlParserEvent.asStartElement();
   279                         ModelNode childNode = addNewChildNode(nsVersion, node, childElement);
   280                         String value = unmarshalNodeContent(nsVersion, childNode, childElement.getName(), reader);
   282                         if (childNode.isDomainSpecific()) {
   283                             parseAssertionData(nsVersion, value, childNode, childElement);
   284                         }
   285                         break;
   286                     default:
   287                         throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0011_UNABLE_TO_UNMARSHALL_POLICY_XML_ELEM_EXPECTED()));
   288                 }
   289             } catch (XMLStreamException e) {
   290                 throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0068_FAILED_TO_UNMARSHALL_POLICY_EXPRESSION(), e));
   291             }
   292         }
   294         return (valueBuffer == null) ? null : valueBuffer.toString().trim();
   295     }
   297     /**
   298      * Method checks if the storage type is supported and transforms it to XMLEventReader instance which is then returned.
   299      * Throws PolicyException if the transformation is not succesfull or if the storage type is not supported.
   300      *
   301      * @param storage An XMLEventReader instance.
   302      * @return The storage cast to an XMLEventReader.
   303      * @throws PolicyException If the XMLEventReader cast failed.
   304      */
   305     private XMLEventReader createXMLEventReader(final Object storage)
   306             throws PolicyException {
   307         if (storage instanceof XMLEventReader) {
   308             return (XMLEventReader) storage;
   309         }
   310         else if (!(storage instanceof Reader)) {
   311             throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0022_STORAGE_TYPE_NOT_SUPPORTED(storage.getClass().getName())));
   312         }
   314         try {
   315             return XMLInputFactory.newInstance().createXMLEventReader((Reader) storage);
   316         } catch (XMLStreamException e) {
   317             throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0014_UNABLE_TO_INSTANTIATE_READER_FOR_STORAGE(), e));
   318         }
   320     }
   322     /**
   323      * Method checks whether the actual name of the end tag is equal to the expected name - the name of currently unmarshalled
   324      * XML policy model element. Throws exception, if the two FQNs are not equal as expected.
   325      *
   326      * @param expected The expected element name.
   327      * @param element The actual element.
   328      * @throws PolicyException If the actual element name did not match the expected element.
   329      */
   330     private void checkEndTagName(final QName expected, final EndElement element) throws PolicyException {
   331         final QName actual = element.getName();
   332         if (!expected.equals(actual)) {
   333             throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0003_UNMARSHALLING_FAILED_END_TAG_DOES_NOT_MATCH(expected, actual)));
   334         }
   336     }
   338     private StringBuilder processCharacters(final ModelNode.Type currentNodeType, final Characters characters,
   339             final StringBuilder currentValueBuffer)
   340             throws PolicyException {
   341         if (characters.isWhiteSpace()) {
   342             return currentValueBuffer;
   343         } else {
   344             final StringBuilder buffer = (currentValueBuffer == null) ? new StringBuilder() : currentValueBuffer;
   345             final String data = characters.getData();
   346             if (currentNodeType == ModelNode.Type.ASSERTION || currentNodeType == ModelNode.Type.ASSERTION_PARAMETER_NODE) {
   347                 return buffer.append(data);
   348             } else {
   349                 throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0009_UNEXPECTED_CDATA_ON_SOURCE_MODEL_NODE(currentNodeType, data)));
   350             }
   352         }
   353     }
   355     /**
   356      * Return true if the value is "true" or "1". Return false if the value is
   357      * "false" or "0". Throw an exception otherwise. The test is case sensitive.
   358      *
   359      * @param value The String representation of the value. Must not be null.
   360      * @return True if the value is "true" or "1". False if the value is
   361      *   "false" or "0".
   362      * @throws PolicyException If the value is not "true", "false", "0" or "1".
   363      */
   364     private boolean parseBooleanValue(String value) throws PolicyException {
   365         if ("true".equals(value) || "1".equals(value)) {
   366             return true;
   367         }
   368         else if ("false".equals(value) || "0".equals(value)) {
   369             return false;
   370         }
   371         throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0095_INVALID_BOOLEAN_VALUE(value)));
   372     }
   374 }

mercurial