1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/sourcemodel/XmlPolicyModelUnmarshaller.java Wed Apr 27 01:27:09 2016 +0800 1.3 @@ -0,0 +1,374 @@ 1.4 +/* 1.5 + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. Oracle designates this 1.11 + * particular file as subject to the "Classpath" exception as provided 1.12 + * by Oracle in the LICENSE file that accompanied this code. 1.13 + * 1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.17 + * version 2 for more details (a copy is included in the LICENSE file that 1.18 + * accompanied this code). 1.19 + * 1.20 + * You should have received a copy of the GNU General Public License version 1.21 + * 2 along with this work; if not, write to the Free Software Foundation, 1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.23 + * 1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.25 + * or visit www.oracle.com if you need additional information or have any 1.26 + * questions. 1.27 + */ 1.28 + 1.29 +package com.sun.xml.internal.ws.policy.sourcemodel; 1.30 + 1.31 +import com.sun.xml.internal.ws.policy.PolicyConstants; 1.32 +import com.sun.xml.internal.ws.policy.PolicyException; 1.33 +import com.sun.xml.internal.ws.policy.privateutil.LocalizationMessages; 1.34 +import com.sun.xml.internal.ws.policy.privateutil.PolicyLogger; 1.35 +import com.sun.xml.internal.ws.policy.sourcemodel.wspolicy.NamespaceVersion; 1.36 +import com.sun.xml.internal.ws.policy.sourcemodel.wspolicy.XmlToken; 1.37 + 1.38 +import java.io.Reader; 1.39 +import java.net.URI; 1.40 +import java.net.URISyntaxException; 1.41 +import java.util.HashMap; 1.42 +import java.util.Iterator; 1.43 +import java.util.Map; 1.44 +import javax.xml.namespace.QName; 1.45 +import javax.xml.stream.XMLEventReader; 1.46 +import javax.xml.stream.XMLInputFactory; 1.47 +import javax.xml.stream.XMLStreamConstants; 1.48 +import javax.xml.stream.XMLStreamException; 1.49 +import javax.xml.stream.events.Attribute; 1.50 +import javax.xml.stream.events.Characters; 1.51 +import javax.xml.stream.events.EndElement; 1.52 +import javax.xml.stream.events.StartElement; 1.53 +import javax.xml.stream.events.XMLEvent; 1.54 + 1.55 +/** 1.56 + * Unmarshal XML policy expressions. 1.57 + * 1.58 + * @author Marek Potociar 1.59 + * @author Fabian Ritzmann 1.60 + */ 1.61 +public class XmlPolicyModelUnmarshaller extends PolicyModelUnmarshaller { 1.62 + 1.63 + private static final PolicyLogger LOGGER = PolicyLogger.getLogger(XmlPolicyModelUnmarshaller.class); 1.64 + 1.65 + /** 1.66 + * Creates a new instance of XmlPolicyModelUnmarshaller 1.67 + */ 1.68 + protected XmlPolicyModelUnmarshaller() { 1.69 + // nothing to initialize 1.70 + } 1.71 + 1.72 + /** 1.73 + * See {@link PolicyModelUnmarshaller#unmarshalModel(Object) base method documentation}. 1.74 + */ 1.75 + public PolicySourceModel unmarshalModel(final Object storage) throws PolicyException { 1.76 + final XMLEventReader reader = createXMLEventReader(storage); 1.77 + PolicySourceModel model = null; 1.78 + 1.79 + loop: 1.80 + while (reader.hasNext()) { 1.81 + try { 1.82 + final XMLEvent event = reader.peek(); 1.83 + switch (event.getEventType()) { 1.84 + case XMLStreamConstants.START_DOCUMENT: 1.85 + case XMLStreamConstants.COMMENT: 1.86 + reader.nextEvent(); 1.87 + break; // skipping the comments and start document events 1.88 + case XMLStreamConstants.CHARACTERS: 1.89 + processCharacters(ModelNode.Type.POLICY, event.asCharacters(), null); 1.90 + // we advance the reader only if there is no exception thrown from 1.91 + // the processCharacters(...) call. Otherwise we don't modify the stream 1.92 + reader.nextEvent(); 1.93 + break; 1.94 + case XMLStreamConstants.START_ELEMENT: 1.95 + if (NamespaceVersion.resolveAsToken(event.asStartElement().getName()) == XmlToken.Policy) { 1.96 + StartElement rootElement = reader.nextEvent().asStartElement(); 1.97 + 1.98 + model = initializeNewModel(rootElement); 1.99 + unmarshalNodeContent(model.getNamespaceVersion(), model.getRootNode(), rootElement.getName(), reader); 1.100 + 1.101 + break loop; 1.102 + } else { 1.103 + throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0048_POLICY_ELEMENT_EXPECTED_FIRST())); 1.104 + } 1.105 + default: 1.106 + throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0048_POLICY_ELEMENT_EXPECTED_FIRST())); 1.107 + } 1.108 + } catch (XMLStreamException e) { 1.109 + throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0068_FAILED_TO_UNMARSHALL_POLICY_EXPRESSION(), e)); 1.110 + } 1.111 + } 1.112 + return model; 1.113 + } 1.114 + 1.115 + /** 1.116 + * Allow derived classes to pass in a custom instance of PolicySourceModel. 1.117 + * 1.118 + * @param nsVersion 1.119 + * @param id 1.120 + * @param name 1.121 + * @return 1.122 + */ 1.123 + protected PolicySourceModel createSourceModel(NamespaceVersion nsVersion, String id, String name) { 1.124 + return PolicySourceModel.createPolicySourceModel(nsVersion, id, name); 1.125 + } 1.126 + 1.127 + private PolicySourceModel initializeNewModel(final StartElement element) throws PolicyException, XMLStreamException { 1.128 + PolicySourceModel model; 1.129 + 1.130 + final NamespaceVersion nsVersion = NamespaceVersion.resolveVersion(element.getName().getNamespaceURI()); 1.131 + 1.132 + final Attribute policyName = getAttributeByName(element, nsVersion.asQName(XmlToken.Name)); 1.133 + final Attribute xmlId = getAttributeByName(element, PolicyConstants.XML_ID); 1.134 + Attribute policyId = getAttributeByName(element, PolicyConstants.WSU_ID); 1.135 + 1.136 + if (policyId == null) { 1.137 + policyId = xmlId; 1.138 + } else if (xmlId != null) { 1.139 + throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0058_MULTIPLE_POLICY_IDS_NOT_ALLOWED())); 1.140 + } 1.141 + 1.142 + model = createSourceModel(nsVersion, 1.143 + (policyId == null) ? null : policyId.getValue(), 1.144 + (policyName == null) ? null : policyName.getValue()); 1.145 + 1.146 + return model; 1.147 + } 1.148 + 1.149 + private ModelNode addNewChildNode(final NamespaceVersion nsVersion, final ModelNode parentNode, final StartElement childElement) throws PolicyException { 1.150 + ModelNode childNode; 1.151 + final QName childElementName = childElement.getName(); 1.152 + if (parentNode.getType() == ModelNode.Type.ASSERTION_PARAMETER_NODE) { 1.153 + childNode = parentNode.createChildAssertionParameterNode(); 1.154 + } else { 1.155 + XmlToken token = NamespaceVersion.resolveAsToken(childElementName); 1.156 + 1.157 + switch (token) { 1.158 + case Policy: 1.159 + childNode = parentNode.createChildPolicyNode(); 1.160 + break; 1.161 + case All: 1.162 + childNode = parentNode.createChildAllNode(); 1.163 + break; 1.164 + case ExactlyOne: 1.165 + childNode = parentNode.createChildExactlyOneNode(); 1.166 + break; 1.167 + case PolicyReference: 1.168 + final Attribute uri = getAttributeByName(childElement, nsVersion.asQName(XmlToken.Uri)); 1.169 + if (uri == null) { 1.170 + throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0040_POLICY_REFERENCE_URI_ATTR_NOT_FOUND())); 1.171 + } else { 1.172 + try { 1.173 + final URI reference = new URI(uri.getValue()); 1.174 + final Attribute digest = getAttributeByName(childElement, nsVersion.asQName(XmlToken.Digest)); 1.175 + PolicyReferenceData refData; 1.176 + if (digest == null) { 1.177 + refData = new PolicyReferenceData(reference); 1.178 + } else { 1.179 + final Attribute digestAlgorithm = getAttributeByName(childElement, nsVersion.asQName(XmlToken.DigestAlgorithm)); 1.180 + URI algorithmRef = null; 1.181 + if (digestAlgorithm != null) { 1.182 + algorithmRef = new URI(digestAlgorithm.getValue()); 1.183 + } 1.184 + refData = new PolicyReferenceData(reference, digest.getValue(), algorithmRef); 1.185 + } 1.186 + childNode = parentNode.createChildPolicyReferenceNode(refData); 1.187 + } catch (URISyntaxException e) { 1.188 + throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0012_UNABLE_TO_UNMARSHALL_POLICY_MALFORMED_URI(), e)); 1.189 + } 1.190 + } 1.191 + break; 1.192 + default: 1.193 + if (parentNode.isDomainSpecific()) { 1.194 + childNode = parentNode.createChildAssertionParameterNode(); 1.195 + } else { 1.196 + childNode = parentNode.createChildAssertionNode(); 1.197 + } 1.198 + } 1.199 + } 1.200 + 1.201 + return childNode; 1.202 + } 1.203 + 1.204 + private void parseAssertionData(NamespaceVersion nsVersion, String value, ModelNode childNode, final StartElement childElement) throws IllegalArgumentException, PolicyException { 1.205 + // finish assertion node processing: create and set assertion data... 1.206 + final Map<QName, String> attributeMap = new HashMap<QName, String>(); 1.207 + boolean optional = false; 1.208 + boolean ignorable = false; 1.209 + 1.210 + final Iterator iterator = childElement.getAttributes(); 1.211 + while (iterator.hasNext()) { 1.212 + final Attribute nextAttribute = (Attribute) iterator.next(); 1.213 + final QName name = nextAttribute.getName(); 1.214 + if (attributeMap.containsKey(name)) { 1.215 + throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0059_MULTIPLE_ATTRS_WITH_SAME_NAME_DETECTED_FOR_ASSERTION(nextAttribute.getName(), childElement.getName()))); 1.216 + } else { 1.217 + if (nsVersion.asQName(XmlToken.Optional).equals(name)) { 1.218 + optional = parseBooleanValue(nextAttribute.getValue()); 1.219 + } else if (nsVersion.asQName(XmlToken.Ignorable).equals(name)) { 1.220 + ignorable = parseBooleanValue(nextAttribute.getValue()); 1.221 + } else { 1.222 + attributeMap.put(name, nextAttribute.getValue()); 1.223 + } 1.224 + } 1.225 + } 1.226 + final AssertionData nodeData = new AssertionData(childElement.getName(), value, attributeMap, childNode.getType(), optional, ignorable); 1.227 + 1.228 + // check visibility value syntax if present... 1.229 + if (nodeData.containsAttribute(PolicyConstants.VISIBILITY_ATTRIBUTE)) { 1.230 + final String visibilityValue = nodeData.getAttributeValue(PolicyConstants.VISIBILITY_ATTRIBUTE); 1.231 + if (!PolicyConstants.VISIBILITY_VALUE_PRIVATE.equals(visibilityValue)) { 1.232 + throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0004_UNEXPECTED_VISIBILITY_ATTR_VALUE(visibilityValue))); 1.233 + } 1.234 + } 1.235 + 1.236 + childNode.setOrReplaceNodeData(nodeData); 1.237 + } 1.238 + 1.239 + private Attribute getAttributeByName(final StartElement element, 1.240 + final QName attributeName) { 1.241 + // call standard API method to retrieve the attribute by name 1.242 + Attribute attribute = element.getAttributeByName(attributeName); 1.243 + 1.244 + // try to find the attribute without a prefix. 1.245 + if (attribute == null) { 1.246 + final String localAttributeName = attributeName.getLocalPart(); 1.247 + final Iterator iterator = element.getAttributes(); 1.248 + while (iterator.hasNext()) { 1.249 + final Attribute nextAttribute = (Attribute) iterator.next(); 1.250 + final QName aName = nextAttribute.getName(); 1.251 + final boolean attributeFoundByWorkaround = aName.equals(attributeName) || (aName.getLocalPart().equals(localAttributeName) && (aName.getPrefix() == null || "".equals(aName.getPrefix()))); 1.252 + if (attributeFoundByWorkaround) { 1.253 + attribute = nextAttribute; 1.254 + break; 1.255 + } 1.256 + 1.257 + } 1.258 + } 1.259 + 1.260 + return attribute; 1.261 + } 1.262 + 1.263 + private String unmarshalNodeContent(final NamespaceVersion nsVersion, final ModelNode node, final QName nodeElementName, final XMLEventReader reader) throws PolicyException { 1.264 + StringBuilder valueBuffer = null; 1.265 + 1.266 + loop: 1.267 + while (reader.hasNext()) { 1.268 + try { 1.269 + final XMLEvent xmlParserEvent = reader.nextEvent(); 1.270 + switch (xmlParserEvent.getEventType()) { 1.271 + case XMLStreamConstants.COMMENT: 1.272 + break; // skipping the comments 1.273 + case XMLStreamConstants.CHARACTERS: 1.274 + valueBuffer = processCharacters(node.getType(), xmlParserEvent.asCharacters(), valueBuffer); 1.275 + break; 1.276 + case XMLStreamConstants.END_ELEMENT: 1.277 + checkEndTagName(nodeElementName, xmlParserEvent.asEndElement()); 1.278 + break loop; // data exctraction for currently processed policy node is done 1.279 + case XMLStreamConstants.START_ELEMENT: 1.280 + final StartElement childElement = xmlParserEvent.asStartElement(); 1.281 + 1.282 + ModelNode childNode = addNewChildNode(nsVersion, node, childElement); 1.283 + String value = unmarshalNodeContent(nsVersion, childNode, childElement.getName(), reader); 1.284 + 1.285 + if (childNode.isDomainSpecific()) { 1.286 + parseAssertionData(nsVersion, value, childNode, childElement); 1.287 + } 1.288 + break; 1.289 + default: 1.290 + throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0011_UNABLE_TO_UNMARSHALL_POLICY_XML_ELEM_EXPECTED())); 1.291 + } 1.292 + } catch (XMLStreamException e) { 1.293 + throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0068_FAILED_TO_UNMARSHALL_POLICY_EXPRESSION(), e)); 1.294 + } 1.295 + } 1.296 + 1.297 + return (valueBuffer == null) ? null : valueBuffer.toString().trim(); 1.298 + } 1.299 + 1.300 + /** 1.301 + * Method checks if the storage type is supported and transforms it to XMLEventReader instance which is then returned. 1.302 + * Throws PolicyException if the transformation is not succesfull or if the storage type is not supported. 1.303 + * 1.304 + * @param storage An XMLEventReader instance. 1.305 + * @return The storage cast to an XMLEventReader. 1.306 + * @throws PolicyException If the XMLEventReader cast failed. 1.307 + */ 1.308 + private XMLEventReader createXMLEventReader(final Object storage) 1.309 + throws PolicyException { 1.310 + if (storage instanceof XMLEventReader) { 1.311 + return (XMLEventReader) storage; 1.312 + } 1.313 + else if (!(storage instanceof Reader)) { 1.314 + throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0022_STORAGE_TYPE_NOT_SUPPORTED(storage.getClass().getName()))); 1.315 + } 1.316 + 1.317 + try { 1.318 + return XMLInputFactory.newInstance().createXMLEventReader((Reader) storage); 1.319 + } catch (XMLStreamException e) { 1.320 + throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0014_UNABLE_TO_INSTANTIATE_READER_FOR_STORAGE(), e)); 1.321 + } 1.322 + 1.323 + } 1.324 + 1.325 + /** 1.326 + * Method checks whether the actual name of the end tag is equal to the expected name - the name of currently unmarshalled 1.327 + * XML policy model element. Throws exception, if the two FQNs are not equal as expected. 1.328 + * 1.329 + * @param expected The expected element name. 1.330 + * @param element The actual element. 1.331 + * @throws PolicyException If the actual element name did not match the expected element. 1.332 + */ 1.333 + private void checkEndTagName(final QName expected, final EndElement element) throws PolicyException { 1.334 + final QName actual = element.getName(); 1.335 + if (!expected.equals(actual)) { 1.336 + throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0003_UNMARSHALLING_FAILED_END_TAG_DOES_NOT_MATCH(expected, actual))); 1.337 + } 1.338 + 1.339 + } 1.340 + 1.341 + private StringBuilder processCharacters(final ModelNode.Type currentNodeType, final Characters characters, 1.342 + final StringBuilder currentValueBuffer) 1.343 + throws PolicyException { 1.344 + if (characters.isWhiteSpace()) { 1.345 + return currentValueBuffer; 1.346 + } else { 1.347 + final StringBuilder buffer = (currentValueBuffer == null) ? new StringBuilder() : currentValueBuffer; 1.348 + final String data = characters.getData(); 1.349 + if (currentNodeType == ModelNode.Type.ASSERTION || currentNodeType == ModelNode.Type.ASSERTION_PARAMETER_NODE) { 1.350 + return buffer.append(data); 1.351 + } else { 1.352 + throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0009_UNEXPECTED_CDATA_ON_SOURCE_MODEL_NODE(currentNodeType, data))); 1.353 + } 1.354 + 1.355 + } 1.356 + } 1.357 + 1.358 + /** 1.359 + * Return true if the value is "true" or "1". Return false if the value is 1.360 + * "false" or "0". Throw an exception otherwise. The test is case sensitive. 1.361 + * 1.362 + * @param value The String representation of the value. Must not be null. 1.363 + * @return True if the value is "true" or "1". False if the value is 1.364 + * "false" or "0". 1.365 + * @throws PolicyException If the value is not "true", "false", "0" or "1". 1.366 + */ 1.367 + private boolean parseBooleanValue(String value) throws PolicyException { 1.368 + if ("true".equals(value) || "1".equals(value)) { 1.369 + return true; 1.370 + } 1.371 + else if ("false".equals(value) || "0".equals(value)) { 1.372 + return false; 1.373 + } 1.374 + throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0095_INVALID_BOOLEAN_VALUE(value))); 1.375 + } 1.376 + 1.377 +}