/*
 * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.xml.internal.ws.policy.sourcemodel;

import com.sun.xml.internal.ws.policy.PolicyConstants;
import com.sun.xml.internal.ws.policy.PolicyException;
import com.sun.xml.internal.ws.policy.privateutil.LocalizationMessages;
import com.sun.xml.internal.ws.policy.privateutil.PolicyLogger;
import com.sun.xml.internal.ws.policy.sourcemodel.wspolicy.NamespaceVersion;
import com.sun.xml.internal.ws.policy.sourcemodel.wspolicy.XmlToken;

import java.io.Reader;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.Characters;
import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;

Unmarshal XML policy expressions.
Author:Marek Potociar, Fabian Ritzmann
/** * Unmarshal XML policy expressions. * * @author Marek Potociar * @author Fabian Ritzmann */
public class XmlPolicyModelUnmarshaller extends PolicyModelUnmarshaller { private static final PolicyLogger LOGGER = PolicyLogger.getLogger(XmlPolicyModelUnmarshaller.class);
Creates a new instance of XmlPolicyModelUnmarshaller
/** * Creates a new instance of XmlPolicyModelUnmarshaller */
protected XmlPolicyModelUnmarshaller() { // nothing to initialize } /** * See {@link PolicyModelUnmarshaller#unmarshalModel(Object) base method documentation}. */ public PolicySourceModel unmarshalModel(final Object storage) throws PolicyException { final XMLEventReader reader = createXMLEventReader(storage); PolicySourceModel model = null; loop: while (reader.hasNext()) { try { final XMLEvent event = reader.peek(); switch (event.getEventType()) { case XMLStreamConstants.START_DOCUMENT: case XMLStreamConstants.COMMENT: reader.nextEvent(); break; // skipping the comments and start document events case XMLStreamConstants.CHARACTERS: processCharacters(ModelNode.Type.POLICY, event.asCharacters(), null); // we advance the reader only if there is no exception thrown from // the processCharacters(...) call. Otherwise we don't modify the stream reader.nextEvent(); break; case XMLStreamConstants.START_ELEMENT: if (NamespaceVersion.resolveAsToken(event.asStartElement().getName()) == XmlToken.Policy) { StartElement rootElement = reader.nextEvent().asStartElement(); model = initializeNewModel(rootElement); unmarshalNodeContent(model.getNamespaceVersion(), model.getRootNode(), rootElement.getName(), reader); break loop; } else { throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0048_POLICY_ELEMENT_EXPECTED_FIRST())); } default: throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0048_POLICY_ELEMENT_EXPECTED_FIRST())); } } catch (XMLStreamException e) { throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0068_FAILED_TO_UNMARSHALL_POLICY_EXPRESSION(), e)); } } return model; }
Allow derived classes to pass in a custom instance of PolicySourceModel.
Params:
  • nsVersion –
  • id –
  • name –
Returns:
/** * Allow derived classes to pass in a custom instance of PolicySourceModel. * * @param nsVersion * @param id * @param name * @return */
protected PolicySourceModel createSourceModel(NamespaceVersion nsVersion, String id, String name) { return PolicySourceModel.createPolicySourceModel(nsVersion, id, name); } private PolicySourceModel initializeNewModel(final StartElement element) throws PolicyException, XMLStreamException { PolicySourceModel model; final NamespaceVersion nsVersion = NamespaceVersion.resolveVersion(element.getName().getNamespaceURI()); final Attribute policyName = getAttributeByName(element, nsVersion.asQName(XmlToken.Name)); final Attribute xmlId = getAttributeByName(element, PolicyConstants.XML_ID); Attribute policyId = getAttributeByName(element, PolicyConstants.WSU_ID); if (policyId == null) { policyId = xmlId; } else if (xmlId != null) { throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0058_MULTIPLE_POLICY_IDS_NOT_ALLOWED())); } model = createSourceModel(nsVersion, (policyId == null) ? null : policyId.getValue(), (policyName == null) ? null : policyName.getValue()); return model; } private ModelNode addNewChildNode(final NamespaceVersion nsVersion, final ModelNode parentNode, final StartElement childElement) throws PolicyException { ModelNode childNode; final QName childElementName = childElement.getName(); if (parentNode.getType() == ModelNode.Type.ASSERTION_PARAMETER_NODE) { childNode = parentNode.createChildAssertionParameterNode(); } else { XmlToken token = NamespaceVersion.resolveAsToken(childElementName); switch (token) { case Policy: childNode = parentNode.createChildPolicyNode(); break; case All: childNode = parentNode.createChildAllNode(); break; case ExactlyOne: childNode = parentNode.createChildExactlyOneNode(); break; case PolicyReference: final Attribute uri = getAttributeByName(childElement, nsVersion.asQName(XmlToken.Uri)); if (uri == null) { throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0040_POLICY_REFERENCE_URI_ATTR_NOT_FOUND())); } else { try { final URI reference = new URI(uri.getValue()); final Attribute digest = getAttributeByName(childElement, nsVersion.asQName(XmlToken.Digest)); PolicyReferenceData refData; if (digest == null) { refData = new PolicyReferenceData(reference); } else { final Attribute digestAlgorithm = getAttributeByName(childElement, nsVersion.asQName(XmlToken.DigestAlgorithm)); URI algorithmRef = null; if (digestAlgorithm != null) { algorithmRef = new URI(digestAlgorithm.getValue()); } refData = new PolicyReferenceData(reference, digest.getValue(), algorithmRef); } childNode = parentNode.createChildPolicyReferenceNode(refData); } catch (URISyntaxException e) { throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0012_UNABLE_TO_UNMARSHALL_POLICY_MALFORMED_URI(), e)); } } break; default: if (parentNode.isDomainSpecific()) { childNode = parentNode.createChildAssertionParameterNode(); } else { childNode = parentNode.createChildAssertionNode(); } } } return childNode; } private void parseAssertionData(NamespaceVersion nsVersion, String value, ModelNode childNode, final StartElement childElement) throws IllegalArgumentException, PolicyException { // finish assertion node processing: create and set assertion data... final Map<QName, String> attributeMap = new HashMap<QName, String>(); boolean optional = false; boolean ignorable = false; final Iterator iterator = childElement.getAttributes(); while (iterator.hasNext()) { final Attribute nextAttribute = (Attribute) iterator.next(); final QName name = nextAttribute.getName(); if (attributeMap.containsKey(name)) { throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0059_MULTIPLE_ATTRS_WITH_SAME_NAME_DETECTED_FOR_ASSERTION(nextAttribute.getName(), childElement.getName()))); } else { if (nsVersion.asQName(XmlToken.Optional).equals(name)) { optional = parseBooleanValue(nextAttribute.getValue()); } else if (nsVersion.asQName(XmlToken.Ignorable).equals(name)) { ignorable = parseBooleanValue(nextAttribute.getValue()); } else { attributeMap.put(name, nextAttribute.getValue()); } } } final AssertionData nodeData = new AssertionData(childElement.getName(), value, attributeMap, childNode.getType(), optional, ignorable); // check visibility value syntax if present... if (nodeData.containsAttribute(PolicyConstants.VISIBILITY_ATTRIBUTE)) { final String visibilityValue = nodeData.getAttributeValue(PolicyConstants.VISIBILITY_ATTRIBUTE); if (!PolicyConstants.VISIBILITY_VALUE_PRIVATE.equals(visibilityValue)) { throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0004_UNEXPECTED_VISIBILITY_ATTR_VALUE(visibilityValue))); } } childNode.setOrReplaceNodeData(nodeData); } private Attribute getAttributeByName(final StartElement element, final QName attributeName) { // call standard API method to retrieve the attribute by name Attribute attribute = element.getAttributeByName(attributeName); // try to find the attribute without a prefix. if (attribute == null) { final String localAttributeName = attributeName.getLocalPart(); final Iterator iterator = element.getAttributes(); while (iterator.hasNext()) { final Attribute nextAttribute = (Attribute) iterator.next(); final QName aName = nextAttribute.getName(); final boolean attributeFoundByWorkaround = aName.equals(attributeName) || (aName.getLocalPart().equals(localAttributeName) && (aName.getPrefix() == null || "".equals(aName.getPrefix()))); if (attributeFoundByWorkaround) { attribute = nextAttribute; break; } } } return attribute; } private String unmarshalNodeContent(final NamespaceVersion nsVersion, final ModelNode node, final QName nodeElementName, final XMLEventReader reader) throws PolicyException { StringBuilder valueBuffer = null; loop: while (reader.hasNext()) { try { final XMLEvent xmlParserEvent = reader.nextEvent(); switch (xmlParserEvent.getEventType()) { case XMLStreamConstants.COMMENT: break; // skipping the comments case XMLStreamConstants.CHARACTERS: valueBuffer = processCharacters(node.getType(), xmlParserEvent.asCharacters(), valueBuffer); break; case XMLStreamConstants.END_ELEMENT: checkEndTagName(nodeElementName, xmlParserEvent.asEndElement()); break loop; // data exctraction for currently processed policy node is done case XMLStreamConstants.START_ELEMENT: final StartElement childElement = xmlParserEvent.asStartElement(); ModelNode childNode = addNewChildNode(nsVersion, node, childElement); String value = unmarshalNodeContent(nsVersion, childNode, childElement.getName(), reader); if (childNode.isDomainSpecific()) { parseAssertionData(nsVersion, value, childNode, childElement); } break; default: throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0011_UNABLE_TO_UNMARSHALL_POLICY_XML_ELEM_EXPECTED())); } } catch (XMLStreamException e) { throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0068_FAILED_TO_UNMARSHALL_POLICY_EXPRESSION(), e)); } } return (valueBuffer == null) ? null : valueBuffer.toString().trim(); }
Method checks if the storage type is supported and transforms it to XMLEventReader instance which is then returned. Throws PolicyException if the transformation is not succesfull or if the storage type is not supported.
Params:
  • storage – An XMLEventReader instance.
Throws:
Returns:The storage cast to an XMLEventReader.
/** * Method checks if the storage type is supported and transforms it to XMLEventReader instance which is then returned. * Throws PolicyException if the transformation is not succesfull or if the storage type is not supported. * * @param storage An XMLEventReader instance. * @return The storage cast to an XMLEventReader. * @throws PolicyException If the XMLEventReader cast failed. */
private XMLEventReader createXMLEventReader(final Object storage) throws PolicyException { if (storage instanceof XMLEventReader) { return (XMLEventReader) storage; } else if (!(storage instanceof Reader)) { throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0022_STORAGE_TYPE_NOT_SUPPORTED(storage.getClass().getName()))); } try { return XMLInputFactory.newInstance().createXMLEventReader((Reader) storage); } catch (XMLStreamException e) { throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0014_UNABLE_TO_INSTANTIATE_READER_FOR_STORAGE(), e)); } }
Method checks whether the actual name of the end tag is equal to the expected name - the name of currently unmarshalled XML policy model element. Throws exception, if the two FQNs are not equal as expected.
Params:
  • expected – The expected element name.
  • element – The actual element.
Throws:
  • PolicyException – If the actual element name did not match the expected element.
/** * Method checks whether the actual name of the end tag is equal to the expected name - the name of currently unmarshalled * XML policy model element. Throws exception, if the two FQNs are not equal as expected. * * @param expected The expected element name. * @param element The actual element. * @throws PolicyException If the actual element name did not match the expected element. */
private void checkEndTagName(final QName expected, final EndElement element) throws PolicyException { final QName actual = element.getName(); if (!expected.equals(actual)) { throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0003_UNMARSHALLING_FAILED_END_TAG_DOES_NOT_MATCH(expected, actual))); } } private StringBuilder processCharacters(final ModelNode.Type currentNodeType, final Characters characters, final StringBuilder currentValueBuffer) throws PolicyException { if (characters.isWhiteSpace()) { return currentValueBuffer; } else { final StringBuilder buffer = (currentValueBuffer == null) ? new StringBuilder() : currentValueBuffer; final String data = characters.getData(); if (currentNodeType == ModelNode.Type.ASSERTION || currentNodeType == ModelNode.Type.ASSERTION_PARAMETER_NODE) { return buffer.append(data); } else { throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0009_UNEXPECTED_CDATA_ON_SOURCE_MODEL_NODE(currentNodeType, data))); } } }
Return true if the value is "true" or "1". Return false if the value is "false" or "0". Throw an exception otherwise. The test is case sensitive.
Params:
  • value – The String representation of the value. Must not be null.
Throws:
Returns:True if the value is "true" or "1". False if the value is "false" or "0".
/** * Return true if the value is "true" or "1". Return false if the value is * "false" or "0". Throw an exception otherwise. The test is case sensitive. * * @param value The String representation of the value. Must not be null. * @return True if the value is "true" or "1". False if the value is * "false" or "0". * @throws PolicyException If the value is not "true", "false", "0" or "1". */
private boolean parseBooleanValue(String value) throws PolicyException { if ("true".equals(value) || "1".equals(value)) { return true; } else if ("false".equals(value) || "0".equals(value)) { return false; } throw LOGGER.logSevereException(new PolicyException(LocalizationMessages.WSP_0095_INVALID_BOOLEAN_VALUE(value))); } }