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

aoqi@0 1 /*
aoqi@0 2 * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
aoqi@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
aoqi@0 4 *
aoqi@0 5 * This code is free software; you can redistribute it and/or modify it
aoqi@0 6 * under the terms of the GNU General Public License version 2 only, as
aoqi@0 7 * published by the Free Software Foundation. Oracle designates this
aoqi@0 8 * particular file as subject to the "Classpath" exception as provided
aoqi@0 9 * by Oracle in the LICENSE file that accompanied this code.
aoqi@0 10 *
aoqi@0 11 * This code is distributed in the hope that it will be useful, but WITHOUT
aoqi@0 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
aoqi@0 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
aoqi@0 14 * version 2 for more details (a copy is included in the LICENSE file that
aoqi@0 15 * accompanied this code).
aoqi@0 16 *
aoqi@0 17 * You should have received a copy of the GNU General Public License version
aoqi@0 18 * 2 along with this work; if not, write to the Free Software Foundation,
aoqi@0 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
aoqi@0 20 *
aoqi@0 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
aoqi@0 22 * or visit www.oracle.com if you need additional information or have any
aoqi@0 23 * questions.
aoqi@0 24 */
aoqi@0 25
aoqi@0 26 package com.sun.xml.internal.ws.policy.sourcemodel;
aoqi@0 27
aoqi@0 28 import com.sun.xml.internal.ws.policy.PolicyConstants;
aoqi@0 29 import com.sun.xml.internal.ws.policy.PolicyException;
aoqi@0 30 import com.sun.xml.internal.ws.policy.privateutil.LocalizationMessages;
aoqi@0 31 import com.sun.xml.internal.ws.policy.privateutil.PolicyLogger;
aoqi@0 32 import com.sun.xml.internal.ws.policy.sourcemodel.wspolicy.NamespaceVersion;
aoqi@0 33 import com.sun.xml.internal.ws.policy.sourcemodel.wspolicy.XmlToken;
aoqi@0 34
aoqi@0 35 import java.io.Reader;
aoqi@0 36 import java.net.URI;
aoqi@0 37 import java.net.URISyntaxException;
aoqi@0 38 import java.util.HashMap;
aoqi@0 39 import java.util.Iterator;
aoqi@0 40 import java.util.Map;
aoqi@0 41 import javax.xml.namespace.QName;
aoqi@0 42 import javax.xml.stream.XMLEventReader;
aoqi@0 43 import javax.xml.stream.XMLInputFactory;
aoqi@0 44 import javax.xml.stream.XMLStreamConstants;
aoqi@0 45 import javax.xml.stream.XMLStreamException;
aoqi@0 46 import javax.xml.stream.events.Attribute;
aoqi@0 47 import javax.xml.stream.events.Characters;
aoqi@0 48 import javax.xml.stream.events.EndElement;
aoqi@0 49 import javax.xml.stream.events.StartElement;
aoqi@0 50 import javax.xml.stream.events.XMLEvent;
aoqi@0 51
aoqi@0 52 /**
aoqi@0 53 * Unmarshal XML policy expressions.
aoqi@0 54 *
aoqi@0 55 * @author Marek Potociar
aoqi@0 56 * @author Fabian Ritzmann
aoqi@0 57 */
aoqi@0 58 public class XmlPolicyModelUnmarshaller extends PolicyModelUnmarshaller {
aoqi@0 59
aoqi@0 60 private static final PolicyLogger LOGGER = PolicyLogger.getLogger(XmlPolicyModelUnmarshaller.class);
aoqi@0 61
aoqi@0 62 /**
aoqi@0 63 * Creates a new instance of XmlPolicyModelUnmarshaller
aoqi@0 64 */
aoqi@0 65 protected XmlPolicyModelUnmarshaller() {
aoqi@0 66 // nothing to initialize
aoqi@0 67 }
aoqi@0 68
aoqi@0 69 /**
aoqi@0 70 * See {@link PolicyModelUnmarshaller#unmarshalModel(Object) base method documentation}.
aoqi@0 71 */
aoqi@0 72 public PolicySourceModel unmarshalModel(final Object storage) throws PolicyException {
aoqi@0 73 final XMLEventReader reader = createXMLEventReader(storage);
aoqi@0 74 PolicySourceModel model = null;
aoqi@0 75
aoqi@0 76 loop:
aoqi@0 77 while (reader.hasNext()) {
aoqi@0 78 try {
aoqi@0 79 final XMLEvent event = reader.peek();
aoqi@0 80 switch (event.getEventType()) {
aoqi@0 81 case XMLStreamConstants.START_DOCUMENT:
aoqi@0 82 case XMLStreamConstants.COMMENT:
aoqi@0 83 reader.nextEvent();
aoqi@0 84 break; // skipping the comments and start document events
aoqi@0 85 case XMLStreamConstants.CHARACTERS:
aoqi@0 86 processCharacters(ModelNode.Type.POLICY, event.asCharacters(), null);
aoqi@0 87 // we advance the reader only if there is no exception thrown from
aoqi@0 88 // the processCharacters(...) call. Otherwise we don't modify the stream
aoqi@0 89 reader.nextEvent();
aoqi@0 90 break;
aoqi@0 91 case XMLStreamConstants.START_ELEMENT:
aoqi@0 92 if (NamespaceVersion.resolveAsToken(event.asStartElement().getName()) == XmlToken.Policy) {
aoqi@0 93 StartElement rootElement = reader.nextEvent().asStartElement();
aoqi@0 94
aoqi@0 95 model = initializeNewModel(rootElement);
aoqi@0 96 unmarshalNodeContent(model.getNamespaceVersion(), model.getRootNode(), rootElement.getName(), reader);
aoqi@0 97
aoqi@0 98 break loop;
aoqi@0 99 } else {
aoqi@0 100 throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0048_POLICY_ELEMENT_EXPECTED_FIRST()));
aoqi@0 101 }
aoqi@0 102 default:
aoqi@0 103 throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0048_POLICY_ELEMENT_EXPECTED_FIRST()));
aoqi@0 104 }
aoqi@0 105 } catch (XMLStreamException e) {
aoqi@0 106 throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0068_FAILED_TO_UNMARSHALL_POLICY_EXPRESSION(), e));
aoqi@0 107 }
aoqi@0 108 }
aoqi@0 109 return model;
aoqi@0 110 }
aoqi@0 111
aoqi@0 112 /**
aoqi@0 113 * Allow derived classes to pass in a custom instance of PolicySourceModel.
aoqi@0 114 *
aoqi@0 115 * @param nsVersion
aoqi@0 116 * @param id
aoqi@0 117 * @param name
aoqi@0 118 * @return
aoqi@0 119 */
aoqi@0 120 protected PolicySourceModel createSourceModel(NamespaceVersion nsVersion, String id, String name) {
aoqi@0 121 return PolicySourceModel.createPolicySourceModel(nsVersion, id, name);
aoqi@0 122 }
aoqi@0 123
aoqi@0 124 private PolicySourceModel initializeNewModel(final StartElement element) throws PolicyException, XMLStreamException {
aoqi@0 125 PolicySourceModel model;
aoqi@0 126
aoqi@0 127 final NamespaceVersion nsVersion = NamespaceVersion.resolveVersion(element.getName().getNamespaceURI());
aoqi@0 128
aoqi@0 129 final Attribute policyName = getAttributeByName(element, nsVersion.asQName(XmlToken.Name));
aoqi@0 130 final Attribute xmlId = getAttributeByName(element, PolicyConstants.XML_ID);
aoqi@0 131 Attribute policyId = getAttributeByName(element, PolicyConstants.WSU_ID);
aoqi@0 132
aoqi@0 133 if (policyId == null) {
aoqi@0 134 policyId = xmlId;
aoqi@0 135 } else if (xmlId != null) {
aoqi@0 136 throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0058_MULTIPLE_POLICY_IDS_NOT_ALLOWED()));
aoqi@0 137 }
aoqi@0 138
aoqi@0 139 model = createSourceModel(nsVersion,
aoqi@0 140 (policyId == null) ? null : policyId.getValue(),
aoqi@0 141 (policyName == null) ? null : policyName.getValue());
aoqi@0 142
aoqi@0 143 return model;
aoqi@0 144 }
aoqi@0 145
aoqi@0 146 private ModelNode addNewChildNode(final NamespaceVersion nsVersion, final ModelNode parentNode, final StartElement childElement) throws PolicyException {
aoqi@0 147 ModelNode childNode;
aoqi@0 148 final QName childElementName = childElement.getName();
aoqi@0 149 if (parentNode.getType() == ModelNode.Type.ASSERTION_PARAMETER_NODE) {
aoqi@0 150 childNode = parentNode.createChildAssertionParameterNode();
aoqi@0 151 } else {
aoqi@0 152 XmlToken token = NamespaceVersion.resolveAsToken(childElementName);
aoqi@0 153
aoqi@0 154 switch (token) {
aoqi@0 155 case Policy:
aoqi@0 156 childNode = parentNode.createChildPolicyNode();
aoqi@0 157 break;
aoqi@0 158 case All:
aoqi@0 159 childNode = parentNode.createChildAllNode();
aoqi@0 160 break;
aoqi@0 161 case ExactlyOne:
aoqi@0 162 childNode = parentNode.createChildExactlyOneNode();
aoqi@0 163 break;
aoqi@0 164 case PolicyReference:
aoqi@0 165 final Attribute uri = getAttributeByName(childElement, nsVersion.asQName(XmlToken.Uri));
aoqi@0 166 if (uri == null) {
aoqi@0 167 throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0040_POLICY_REFERENCE_URI_ATTR_NOT_FOUND()));
aoqi@0 168 } else {
aoqi@0 169 try {
aoqi@0 170 final URI reference = new URI(uri.getValue());
aoqi@0 171 final Attribute digest = getAttributeByName(childElement, nsVersion.asQName(XmlToken.Digest));
aoqi@0 172 PolicyReferenceData refData;
aoqi@0 173 if (digest == null) {
aoqi@0 174 refData = new PolicyReferenceData(reference);
aoqi@0 175 } else {
aoqi@0 176 final Attribute digestAlgorithm = getAttributeByName(childElement, nsVersion.asQName(XmlToken.DigestAlgorithm));
aoqi@0 177 URI algorithmRef = null;
aoqi@0 178 if (digestAlgorithm != null) {
aoqi@0 179 algorithmRef = new URI(digestAlgorithm.getValue());
aoqi@0 180 }
aoqi@0 181 refData = new PolicyReferenceData(reference, digest.getValue(), algorithmRef);
aoqi@0 182 }
aoqi@0 183 childNode = parentNode.createChildPolicyReferenceNode(refData);
aoqi@0 184 } catch (URISyntaxException e) {
aoqi@0 185 throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0012_UNABLE_TO_UNMARSHALL_POLICY_MALFORMED_URI(), e));
aoqi@0 186 }
aoqi@0 187 }
aoqi@0 188 break;
aoqi@0 189 default:
aoqi@0 190 if (parentNode.isDomainSpecific()) {
aoqi@0 191 childNode = parentNode.createChildAssertionParameterNode();
aoqi@0 192 } else {
aoqi@0 193 childNode = parentNode.createChildAssertionNode();
aoqi@0 194 }
aoqi@0 195 }
aoqi@0 196 }
aoqi@0 197
aoqi@0 198 return childNode;
aoqi@0 199 }
aoqi@0 200
aoqi@0 201 private void parseAssertionData(NamespaceVersion nsVersion, String value, ModelNode childNode, final StartElement childElement) throws IllegalArgumentException, PolicyException {
aoqi@0 202 // finish assertion node processing: create and set assertion data...
aoqi@0 203 final Map<QName, String> attributeMap = new HashMap<QName, String>();
aoqi@0 204 boolean optional = false;
aoqi@0 205 boolean ignorable = false;
aoqi@0 206
aoqi@0 207 final Iterator iterator = childElement.getAttributes();
aoqi@0 208 while (iterator.hasNext()) {
aoqi@0 209 final Attribute nextAttribute = (Attribute) iterator.next();
aoqi@0 210 final QName name = nextAttribute.getName();
aoqi@0 211 if (attributeMap.containsKey(name)) {
aoqi@0 212 throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0059_MULTIPLE_ATTRS_WITH_SAME_NAME_DETECTED_FOR_ASSERTION(nextAttribute.getName(), childElement.getName())));
aoqi@0 213 } else {
aoqi@0 214 if (nsVersion.asQName(XmlToken.Optional).equals(name)) {
aoqi@0 215 optional = parseBooleanValue(nextAttribute.getValue());
aoqi@0 216 } else if (nsVersion.asQName(XmlToken.Ignorable).equals(name)) {
aoqi@0 217 ignorable = parseBooleanValue(nextAttribute.getValue());
aoqi@0 218 } else {
aoqi@0 219 attributeMap.put(name, nextAttribute.getValue());
aoqi@0 220 }
aoqi@0 221 }
aoqi@0 222 }
aoqi@0 223 final AssertionData nodeData = new AssertionData(childElement.getName(), value, attributeMap, childNode.getType(), optional, ignorable);
aoqi@0 224
aoqi@0 225 // check visibility value syntax if present...
aoqi@0 226 if (nodeData.containsAttribute(PolicyConstants.VISIBILITY_ATTRIBUTE)) {
aoqi@0 227 final String visibilityValue = nodeData.getAttributeValue(PolicyConstants.VISIBILITY_ATTRIBUTE);
aoqi@0 228 if (!PolicyConstants.VISIBILITY_VALUE_PRIVATE.equals(visibilityValue)) {
aoqi@0 229 throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0004_UNEXPECTED_VISIBILITY_ATTR_VALUE(visibilityValue)));
aoqi@0 230 }
aoqi@0 231 }
aoqi@0 232
aoqi@0 233 childNode.setOrReplaceNodeData(nodeData);
aoqi@0 234 }
aoqi@0 235
aoqi@0 236 private Attribute getAttributeByName(final StartElement element,
aoqi@0 237 final QName attributeName) {
aoqi@0 238 // call standard API method to retrieve the attribute by name
aoqi@0 239 Attribute attribute = element.getAttributeByName(attributeName);
aoqi@0 240
aoqi@0 241 // try to find the attribute without a prefix.
aoqi@0 242 if (attribute == null) {
aoqi@0 243 final String localAttributeName = attributeName.getLocalPart();
aoqi@0 244 final Iterator iterator = element.getAttributes();
aoqi@0 245 while (iterator.hasNext()) {
aoqi@0 246 final Attribute nextAttribute = (Attribute) iterator.next();
aoqi@0 247 final QName aName = nextAttribute.getName();
aoqi@0 248 final boolean attributeFoundByWorkaround = aName.equals(attributeName) || (aName.getLocalPart().equals(localAttributeName) && (aName.getPrefix() == null || "".equals(aName.getPrefix())));
aoqi@0 249 if (attributeFoundByWorkaround) {
aoqi@0 250 attribute = nextAttribute;
aoqi@0 251 break;
aoqi@0 252 }
aoqi@0 253
aoqi@0 254 }
aoqi@0 255 }
aoqi@0 256
aoqi@0 257 return attribute;
aoqi@0 258 }
aoqi@0 259
aoqi@0 260 private String unmarshalNodeContent(final NamespaceVersion nsVersion, final ModelNode node, final QName nodeElementName, final XMLEventReader reader) throws PolicyException {
aoqi@0 261 StringBuilder valueBuffer = null;
aoqi@0 262
aoqi@0 263 loop:
aoqi@0 264 while (reader.hasNext()) {
aoqi@0 265 try {
aoqi@0 266 final XMLEvent xmlParserEvent = reader.nextEvent();
aoqi@0 267 switch (xmlParserEvent.getEventType()) {
aoqi@0 268 case XMLStreamConstants.COMMENT:
aoqi@0 269 break; // skipping the comments
aoqi@0 270 case XMLStreamConstants.CHARACTERS:
aoqi@0 271 valueBuffer = processCharacters(node.getType(), xmlParserEvent.asCharacters(), valueBuffer);
aoqi@0 272 break;
aoqi@0 273 case XMLStreamConstants.END_ELEMENT:
aoqi@0 274 checkEndTagName(nodeElementName, xmlParserEvent.asEndElement());
aoqi@0 275 break loop; // data exctraction for currently processed policy node is done
aoqi@0 276 case XMLStreamConstants.START_ELEMENT:
aoqi@0 277 final StartElement childElement = xmlParserEvent.asStartElement();
aoqi@0 278
aoqi@0 279 ModelNode childNode = addNewChildNode(nsVersion, node, childElement);
aoqi@0 280 String value = unmarshalNodeContent(nsVersion, childNode, childElement.getName(), reader);
aoqi@0 281
aoqi@0 282 if (childNode.isDomainSpecific()) {
aoqi@0 283 parseAssertionData(nsVersion, value, childNode, childElement);
aoqi@0 284 }
aoqi@0 285 break;
aoqi@0 286 default:
aoqi@0 287 throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0011_UNABLE_TO_UNMARSHALL_POLICY_XML_ELEM_EXPECTED()));
aoqi@0 288 }
aoqi@0 289 } catch (XMLStreamException e) {
aoqi@0 290 throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0068_FAILED_TO_UNMARSHALL_POLICY_EXPRESSION(), e));
aoqi@0 291 }
aoqi@0 292 }
aoqi@0 293
aoqi@0 294 return (valueBuffer == null) ? null : valueBuffer.toString().trim();
aoqi@0 295 }
aoqi@0 296
aoqi@0 297 /**
aoqi@0 298 * Method checks if the storage type is supported and transforms it to XMLEventReader instance which is then returned.
aoqi@0 299 * Throws PolicyException if the transformation is not succesfull or if the storage type is not supported.
aoqi@0 300 *
aoqi@0 301 * @param storage An XMLEventReader instance.
aoqi@0 302 * @return The storage cast to an XMLEventReader.
aoqi@0 303 * @throws PolicyException If the XMLEventReader cast failed.
aoqi@0 304 */
aoqi@0 305 private XMLEventReader createXMLEventReader(final Object storage)
aoqi@0 306 throws PolicyException {
aoqi@0 307 if (storage instanceof XMLEventReader) {
aoqi@0 308 return (XMLEventReader) storage;
aoqi@0 309 }
aoqi@0 310 else if (!(storage instanceof Reader)) {
aoqi@0 311 throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0022_STORAGE_TYPE_NOT_SUPPORTED(storage.getClass().getName())));
aoqi@0 312 }
aoqi@0 313
aoqi@0 314 try {
aoqi@0 315 return XMLInputFactory.newInstance().createXMLEventReader((Reader) storage);
aoqi@0 316 } catch (XMLStreamException e) {
aoqi@0 317 throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0014_UNABLE_TO_INSTANTIATE_READER_FOR_STORAGE(), e));
aoqi@0 318 }
aoqi@0 319
aoqi@0 320 }
aoqi@0 321
aoqi@0 322 /**
aoqi@0 323 * Method checks whether the actual name of the end tag is equal to the expected name - the name of currently unmarshalled
aoqi@0 324 * XML policy model element. Throws exception, if the two FQNs are not equal as expected.
aoqi@0 325 *
aoqi@0 326 * @param expected The expected element name.
aoqi@0 327 * @param element The actual element.
aoqi@0 328 * @throws PolicyException If the actual element name did not match the expected element.
aoqi@0 329 */
aoqi@0 330 private void checkEndTagName(final QName expected, final EndElement element) throws PolicyException {
aoqi@0 331 final QName actual = element.getName();
aoqi@0 332 if (!expected.equals(actual)) {
aoqi@0 333 throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0003_UNMARSHALLING_FAILED_END_TAG_DOES_NOT_MATCH(expected, actual)));
aoqi@0 334 }
aoqi@0 335
aoqi@0 336 }
aoqi@0 337
aoqi@0 338 private StringBuilder processCharacters(final ModelNode.Type currentNodeType, final Characters characters,
aoqi@0 339 final StringBuilder currentValueBuffer)
aoqi@0 340 throws PolicyException {
aoqi@0 341 if (characters.isWhiteSpace()) {
aoqi@0 342 return currentValueBuffer;
aoqi@0 343 } else {
aoqi@0 344 final StringBuilder buffer = (currentValueBuffer == null) ? new StringBuilder() : currentValueBuffer;
aoqi@0 345 final String data = characters.getData();
aoqi@0 346 if (currentNodeType == ModelNode.Type.ASSERTION || currentNodeType == ModelNode.Type.ASSERTION_PARAMETER_NODE) {
aoqi@0 347 return buffer.append(data);
aoqi@0 348 } else {
aoqi@0 349 throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0009_UNEXPECTED_CDATA_ON_SOURCE_MODEL_NODE(currentNodeType, data)));
aoqi@0 350 }
aoqi@0 351
aoqi@0 352 }
aoqi@0 353 }
aoqi@0 354
aoqi@0 355 /**
aoqi@0 356 * Return true if the value is "true" or "1". Return false if the value is
aoqi@0 357 * "false" or "0". Throw an exception otherwise. The test is case sensitive.
aoqi@0 358 *
aoqi@0 359 * @param value The String representation of the value. Must not be null.
aoqi@0 360 * @return True if the value is "true" or "1". False if the value is
aoqi@0 361 * "false" or "0".
aoqi@0 362 * @throws PolicyException If the value is not "true", "false", "0" or "1".
aoqi@0 363 */
aoqi@0 364 private boolean parseBooleanValue(String value) throws PolicyException {
aoqi@0 365 if ("true".equals(value) || "1".equals(value)) {
aoqi@0 366 return true;
aoqi@0 367 }
aoqi@0 368 else if ("false".equals(value) || "0".equals(value)) {
aoqi@0 369 return false;
aoqi@0 370 }
aoqi@0 371 throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0095_INVALID_BOOLEAN_VALUE(value)));
aoqi@0 372 }
aoqi@0 373
aoqi@0 374 }

mercurial