001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common Development
008: * and Distribution License("CDDL") (collectively, the "License"). You
009: * may not use this file except in compliance with the License. You can obtain
010: * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
011: * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
012: * language governing permissions and limitations under the License.
013: *
014: * When distributing the software, include this License Header Notice in each
015: * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
016: * Sun designates this particular file as subject to the "Classpath" exception
017: * as provided by Sun in the GPL Version 2 section of the License file that
018: * accompanied this code. If applicable, add the following below the License
019: * Header, with the fields enclosed by brackets [] replaced by your own
020: * identifying information: "Portions Copyrighted [year]
021: * [name of copyright owner]"
022: *
023: * Contributor(s):
024: *
025: * If you wish your version of this file to be governed by only the CDDL or
026: * only the GPL Version 2, indicate your decision by adding "[Contributor]
027: * elects to include this software in this distribution under the [CDDL or GPL
028: * Version 2] license." If you don't indicate a single choice of license, a
029: * recipient has the option to distribute your version of this file under
030: * either the CDDL, the GPL Version 2 or to extend the choice of license to
031: * its licensees as provided above. However, if you add GPL Version 2 code
032: * and therefore, elected the GPL Version 2 license, then the option applies
033: * only if the new code is made subject to such option by the copyright
034: * holder.
035: */
036:
037: package com.sun.xml.ws.policy.sourcemodel;
038:
039: import java.io.Reader;
040: import java.net.URI;
041: import java.net.URISyntaxException;
042: import java.util.HashMap;
043: import java.util.Iterator;
044: import java.util.Map;
045: import javax.xml.namespace.QName;
046: import javax.xml.stream.XMLEventReader;
047: import javax.xml.stream.XMLInputFactory;
048: import javax.xml.stream.XMLStreamConstants;
049: import javax.xml.stream.XMLStreamException;
050: import javax.xml.stream.events.Attribute;
051: import javax.xml.stream.events.Characters;
052: import javax.xml.stream.events.EndElement;
053: import javax.xml.stream.events.StartElement;
054: import javax.xml.stream.events.XMLEvent;
055:
056: import com.sun.xml.ws.policy.PolicyConstants;
057: import com.sun.xml.ws.policy.PolicyException;
058: import com.sun.xml.ws.policy.privateutil.LocalizationMessages;
059: import com.sun.xml.ws.policy.privateutil.PolicyLogger;
060:
061: /**
062: *
063: * @author Marek Potociar
064: */
065: final class XmlPolicyModelUnmarshaller extends PolicyModelUnmarshaller {
066: private static final PolicyLogger LOGGER = PolicyLogger
067: .getLogger(XmlPolicyModelUnmarshaller.class);
068:
069: /**
070: * Creates a new instance of XmlPolicyModelUnmarshaller
071: */
072: XmlPolicyModelUnmarshaller() {
073: // nothing to initialize
074: }
075:
076: /**
077: * See {@link PolicyModelUnmarshaller#unmarshalModel(Object) base method documentation}.
078: */
079: public PolicySourceModel unmarshalModel(final Object storage)
080: throws PolicyException {
081: final XMLEventReader reader = createXMLEventReader(storage);
082: PolicySourceModel model = null;
083:
084: loop: while (reader.hasNext()) {
085: try {
086: final XMLEvent event = reader.peek();
087: switch (event.getEventType()) {
088: case XMLStreamConstants.START_DOCUMENT:
089: case XMLStreamConstants.COMMENT:
090: reader.nextEvent();
091: break; // skipping the comments and start document events
092: case XMLStreamConstants.CHARACTERS:
093: processCharacters(ModelNode.Type.POLICY, event
094: .asCharacters(), null);
095: // we advance the reader only if there is no exception thrown from
096: // the processCharacters() call. Otherwise we don't modify the stream
097: reader.nextEvent();
098: break;
099: case XMLStreamConstants.START_ELEMENT:
100: if (ModelNode.Type.POLICY.asQName().equals(
101: event.asStartElement().getName())) {
102: final StartElement element = reader.nextEvent()
103: .asStartElement();
104:
105: Attribute policyId = getAttributeByName(
106: element, PolicyConstants.WSU_ID);
107: final Attribute xmlId = getAttributeByName(
108: element, PolicyConstants.XML_ID);
109:
110: if (policyId == null) {
111: policyId = xmlId;
112: } else if (xmlId != null) {
113: throw LOGGER
114: .logSevereException(new PolicyException(
115: LocalizationMessages
116: .WSP_0058_MULTIPLE_POLICY_IDS_NOT_ALLOWED()));
117: }
118:
119: final Attribute policyName = getAttributeByName(
120: element, PolicyConstants.POLICY_NAME);
121:
122: model = PolicySourceModel
123: .createPolicySourceModel(
124: (policyId == null) ? null
125: : policyId.getValue(),
126: (policyName == null) ? null
127: : policyName.getValue());
128:
129: unmarshalNodeContent(model.getRootNode(), event
130: .asStartElement(), reader);
131: break loop;
132: }
133: // else (this is not a policy tag) -> go to default => throw exception
134: default:
135: throw LOGGER
136: .logSevereException(new PolicyException(
137: LocalizationMessages
138: .WSP_0048_POLICY_ELEMENT_EXPECTED_FIRST()));
139: }
140: } catch (XMLStreamException e) {
141: throw LOGGER
142: .logSevereException(new PolicyException(
143: LocalizationMessages
144: .WSP_0068_FAILED_TO_UNMARSHALL_POLICY_EXPRESSION(),
145: e));
146: }
147: }
148: return model;
149: }
150:
151: private void unmarshalNodeContent(final ModelNode lastNode,
152: final StartElement lastStartElement,
153: final XMLEventReader reader) throws PolicyException {
154: final QName lastElementName = lastStartElement.getName();
155: StringBuffer valueBuffer = null;
156:
157: loop: while (reader.hasNext()) {
158: try {
159: final XMLEvent xmlParserEvent = reader.nextEvent();
160: switch (xmlParserEvent.getEventType()) {
161: case XMLStreamConstants.COMMENT:
162: break; // skipping the comments
163:
164: case XMLStreamConstants.CHARACTERS:
165: valueBuffer = processCharacters(lastNode.getType(),
166: xmlParserEvent.asCharacters(), valueBuffer);
167: break;
168:
169: case XMLStreamConstants.END_ELEMENT:
170: checkEndTagName(lastElementName, xmlParserEvent
171: .asEndElement());
172: break loop; // data exctraction for currently processed policy node is done
173:
174: case XMLStreamConstants.START_ELEMENT:
175: final StartElement childElement = xmlParserEvent
176: .asStartElement();
177: final QName childElementName = childElement
178: .getName();
179:
180: ModelNode childNode;
181: if (lastNode.getType() == ModelNode.Type.ASSERTION_PARAMETER_NODE) {
182: childNode = lastNode
183: .createChildAssertionParameterNode();
184: } else {
185: if (ModelNode.Type.POLICY.asQName().equals(
186: childElementName)) {
187: childNode = lastNode
188: .createChildPolicyNode();
189: } else if (ModelNode.Type.ALL.asQName().equals(
190: childElementName)) {
191: childNode = lastNode.createChildAllNode();
192: } else if (ModelNode.Type.EXACTLY_ONE.asQName()
193: .equals(childElementName)) {
194: childNode = lastNode
195: .createChildExactlyOneNode();
196: } else if (ModelNode.Type.POLICY_REFERENCE
197: .asQName().equals(childElementName)) {
198: final Attribute uri = getAttributeByName(
199: childElement,
200: PolicyReferenceData.ATTRIBUTE_URI);
201: if (uri == null) {
202: throw LOGGER
203: .logSevereException(new PolicyException(
204: LocalizationMessages
205: .WSP_0040_POLICY_REFERENCE_URI_ATTR_NOT_FOUND()));
206: } else {
207: try {
208: final URI reference = new URI(uri
209: .getValue());
210: final Attribute digest = getAttributeByName(
211: childElement,
212: PolicyReferenceData.ATTRIBUTE_DIGEST);
213: PolicyReferenceData refData;
214: if (digest == null) {
215: refData = new PolicyReferenceData(
216: reference);
217: } else {
218: final Attribute digestAlgorithm = getAttributeByName(
219: childElement,
220: PolicyReferenceData.ATTRIBUTE_DIGEST_ALGORITHM);
221: URI algorithmRef = null;
222: if (digestAlgorithm != null) {
223: algorithmRef = new URI(
224: digestAlgorithm
225: .getValue());
226: }
227: refData = new PolicyReferenceData(
228: reference, digest
229: .getValue(),
230: algorithmRef);
231: }
232: childNode = lastNode
233: .createChildPolicyReferenceNode(refData);
234: } catch (URISyntaxException e) {
235: throw LOGGER
236: .logSevereException(new PolicyException(
237: LocalizationMessages
238: .WSP_0012_UNABLE_TO_UNMARSHALL_POLICY_MALFORMED_URI(),
239: e));
240: }
241: }
242: } else {
243: if (lastNode.isAssertionRelatedNode()) {
244: childNode = lastNode
245: .createChildAssertionParameterNode();
246: } else {
247: childNode = lastNode
248: .createChildAssertionNode();
249: }
250: }
251: }
252:
253: unmarshalNodeContent(childNode, childElement,
254: reader);
255: break;
256: default:
257: throw LOGGER
258: .logSevereException(new PolicyException(
259: LocalizationMessages
260: .WSP_0011_UNABLE_TO_UNMARSHALL_POLICY_XML_ELEM_EXPECTED()));
261: }
262: } catch (XMLStreamException e) {
263: throw LOGGER
264: .logSevereException(new PolicyException(
265: LocalizationMessages
266: .WSP_0068_FAILED_TO_UNMARSHALL_POLICY_EXPRESSION(),
267: e));
268: }
269: }
270:
271: if (lastNode.isAssertionRelatedNode()) {
272: // finish assertion node processing: create and set assertion data...
273: final Map<QName, String> attributeMap = new HashMap<QName, String>();
274: final Iterator iterator = lastStartElement.getAttributes();
275: while (iterator.hasNext()) {
276: final Attribute nextAttribute = (Attribute) iterator
277: .next();
278: final QName name = nextAttribute.getName();
279: if (attributeMap.containsKey(name)) {
280: throw LOGGER
281: .logSevereException(new PolicyException(
282: LocalizationMessages
283: .WSP_0059_MULTIPLE_ATTRS_WITH_SAME_NAME_DETECTED_FOR_ASSERTION(
284: nextAttribute
285: .getName(),
286: lastElementName)));
287: } else {
288: attributeMap.put(name, nextAttribute.getValue());
289: }
290: }
291: final AssertionData nodeData = new AssertionData(
292: lastElementName, (valueBuffer == null) ? null
293: : valueBuffer.toString(), attributeMap,
294: lastNode.getType());
295:
296: // check visibility value syntax if present...
297: if (nodeData
298: .containsAttribute(PolicyConstants.VISIBILITY_ATTRIBUTE)) {
299: final String visibilityValue = nodeData
300: .getAttributeValue(PolicyConstants.VISIBILITY_ATTRIBUTE);
301: if (!PolicyConstants.VISIBILITY_VALUE_PRIVATE
302: .equals(visibilityValue)) {
303: throw LOGGER
304: .logSevereException(new PolicyException(
305: LocalizationMessages
306: .WSP_0004_UNEXPECTED_VISIBILITY_ATTR_VALUE(visibilityValue)));
307: }
308: }
309:
310: lastNode.setOrReplaceNodeData(nodeData);
311: }
312: }
313:
314: /**
315: * Method checks if the storage type is supported and transforms it to XMLEventReader instance which is then returned.
316: * Throws PolicyException if the transformation is not succesfull or if the storage type is not supported.
317: */
318: private XMLEventReader createXMLEventReader(final Object storage)
319: throws PolicyException {
320: if (!(storage instanceof Reader)) {
321: throw LOGGER
322: .logSevereException(new PolicyException(
323: LocalizationMessages
324: .WSP_0022_STORAGE_TYPE_NOT_SUPPORTED(storage
325: .getClass().getName())));
326: }
327:
328: try {
329: return XMLInputFactory.newInstance().createXMLEventReader(
330: (Reader) storage);
331: } catch (XMLStreamException e) {
332: throw LOGGER
333: .logSevereException(new PolicyException(
334: LocalizationMessages
335: .WSP_0014_UNABLE_TO_INSTANTIATE_READER_FOR_STORAGE(),
336: e));
337: }
338: }
339:
340: /**
341: * Method checks whether the actual name of the end tag is equal to the expected name - the name of currently unmarshalled
342: * XML policy model element. Throws exception, if the two FQNs are not equal as expected.
343: */
344: private void checkEndTagName(final QName expected,
345: final EndElement element) throws PolicyException {
346: final QName actual = element.getName();
347: if (!expected.equals(actual)) {
348: throw LOGGER
349: .logSevereException(new PolicyException(
350: LocalizationMessages
351: .WSP_0003_UNMARSHALLING_FAILED_END_TAG_DOES_NOT_MATCH(
352: expected, actual)));
353: }
354: }
355:
356: private StringBuffer processCharacters(
357: final ModelNode.Type currentNodeType,
358: final Characters characters,
359: final StringBuffer currentValueBuffer)
360: throws PolicyException {
361: if (characters.isWhiteSpace()) {
362: return currentValueBuffer;
363: } else {
364: final StringBuffer buffer = (currentValueBuffer == null) ? new StringBuffer()
365: : currentValueBuffer;
366: final String data = characters.getData();
367: if (currentNodeType == ModelNode.Type.ASSERTION
368: || currentNodeType == ModelNode.Type.ASSERTION_PARAMETER_NODE) {
369: return buffer.append(data);
370: } else {
371: throw LOGGER
372: .logSevereException(new PolicyException(
373: LocalizationMessages
374: .WSP_0009_UNEXPECTED_CDATA_ON_SOURCE_MODEL_NODE(
375: currentNodeType, data)));
376: }
377: }
378: }
379:
380: private Attribute getAttributeByName(final StartElement element,
381: final QName attributeName) {
382: // call standard API method to retrieve the attribute by name
383: Attribute attribute = element.getAttributeByName(attributeName);
384:
385: // try to find the attribute without a prefix.
386: if (attribute == null) {
387: final String localAttributeName = attributeName
388: .getLocalPart();
389: final Iterator iterator = element.getAttributes();
390: while (iterator.hasNext()) {
391: final Attribute nextAttribute = (Attribute) iterator
392: .next();
393: final QName aName = nextAttribute.getName();
394: final boolean attributeFoundByWorkaround = aName
395: .equals(attributeName)
396: || (aName.getLocalPart().equals(
397: localAttributeName) && (aName
398: .getPrefix() == null || "".equals(aName
399: .getPrefix())));
400: if (attributeFoundByWorkaround) {
401: attribute = nextAttribute;
402: break;
403: }
404: }
405: }
406:
407: return attribute;
408: }
409: }
|