/******************************************************************************* * Copyright (c) 1998, 2015 Oracle and/or its affiliates. All rights reserved. * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 * which accompanies this distribution. * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html * and the Eclipse Distribution License is available at * http://www.eclipse.org/org/documents/edl-v10.php. * * Contributors: * bdoughan - June 24/2009 - 2.0 - Initial implementation ******************************************************************************/ package org.eclipse.persistence.internal.oxm.record; import javax.xml.stream.XMLStreamReader; import org.eclipse.persistence.internal.oxm.Constants; import org.eclipse.persistence.internal.oxm.Unmarshaller; import org.eclipse.persistence.internal.oxm.record.namespaces.UnmarshalNamespaceContext; import org.xml.sax.ContentHandler; import org.xml.sax.InputSource; import org.xml.sax.Locator; import org.xml.sax.SAXException; import org.xml.sax.ext.Locator2; /** * Convert an XMLStreamReader into SAX events. */ public class XMLStreamReaderReader extends XMLReaderAdapter { private int depth = 0; private UnmarshalNamespaceContext unmarshalNamespaceContext; private XMLStreamReaderAttributes indexedAttributeList; private boolean qNameAware; private XMLStreamReader xmlStreamReader; public XMLStreamReaderReader() { unmarshalNamespaceContext = new UnmarshalNamespaceContext(); indexedAttributeList = new XMLStreamReaderAttributes(); } public XMLStreamReaderReader(Unmarshaller xmlUnmarshaller) { super(xmlUnmarshaller); unmarshalNamespaceContext = new UnmarshalNamespaceContext(); indexedAttributeList = new XMLStreamReaderAttributes(); } @Override public Locator getLocator(){ if(locator == null){ locator = new StreamReaderLocator(xmlStreamReader); } return locator; } @Override public void setContentHandler (ContentHandler handler) { if(handler instanceof UnmarshalRecord){ ((UnmarshalRecord)handler).setUnmarshalNamespaceResolver(unmarshalNamespaceContext); qNameAware = false; if(null == validatingContentHandler) { this.contentHandler = (UnmarshalRecord) handler; }else{ validatingContentHandler.setContentHandler(handler); } }else if(handler instanceof SAXUnmarshallerHandler){ ((SAXUnmarshallerHandler)handler).setUnmarshalNamespaceResolver(unmarshalNamespaceContext); qNameAware = true; if(null == validatingContentHandler) { this.contentHandler = (SAXUnmarshallerHandler) handler; }else{ validatingContentHandler.setContentHandler(handler); } } else { super.setContentHandler(handler); qNameAware = true; } } @Override public void parse(InputSource input) throws SAXException { if(null == contentHandler) { return; } if(input instanceof XMLStreamReaderInputSource) { XMLStreamReader xmlStreamReader = ((XMLStreamReaderInputSource) input).getXmlStreamReader(); parse(xmlStreamReader); } } public void parse(XMLStreamReader xmlStreamReader) throws SAXException { this.xmlStreamReader = xmlStreamReader; unmarshalNamespaceContext.setXmlStreamReader(xmlStreamReader); indexedAttributeList.setXmlStreamReader(xmlStreamReader); try { contentHandler.startDocument(); parseEvent(xmlStreamReader, xmlStreamReader.getEventType()); while(depth > 0) { int eventType = xmlStreamReader.next(); parseEvent(xmlStreamReader, eventType); } if(xmlStreamReader.hasNext()) { xmlStreamReader.next(); } contentHandler.endDocument(); } catch(SAXException e ) { throw e; } catch(Exception e) { throw new SAXException(e); } } private void parseEvent(XMLStreamReader xmlStreamReader, int eventType) throws SAXException { switch (eventType) { case XMLStreamReader.START_ELEMENT: { depth++; int namespaceCount = xmlStreamReader.getNamespaceCount(); if(namespaceCount > 0) { for(int x=0; x<namespaceCount; x++) { contentHandler.startPrefixMapping(xmlStreamReader.getNamespacePrefix(x), xmlStreamReader.getNamespaceURI(x)); } } String localName = xmlStreamReader.getLocalName(); String namespaceURI = xmlStreamReader.getNamespaceURI(); if(Constants.EMPTY_STRING.equals(namespaceURI)) { namespaceURI = null; } if(qNameAware) { String prefix = xmlStreamReader.getPrefix(); if(null == prefix || prefix.length() == 0) { contentHandler.startElement(namespaceURI, localName, localName, indexedAttributeList.reset()); } else { contentHandler.startElement(namespaceURI, localName, prefix + Constants.COLON + localName, indexedAttributeList.reset()); } } else { contentHandler.startElement(namespaceURI, localName, null, indexedAttributeList.reset()); } break; } case XMLStreamReader.END_ELEMENT: { depth--; String localName = xmlStreamReader.getLocalName(); String namespaceURI = xmlStreamReader.getNamespaceURI(); if(Constants.EMPTY_STRING.equals(namespaceURI)) { namespaceURI = null; } if(qNameAware) { String prefix = xmlStreamReader.getPrefix(); if(null == prefix || prefix.length() == 0) { contentHandler.endElement(namespaceURI, localName, localName); } else { contentHandler.endElement(namespaceURI, localName, prefix + Constants.COLON + localName); } } else { contentHandler.endElement(namespaceURI, localName, null); } int namespaceCount = xmlStreamReader.getNamespaceCount(); if(namespaceCount > 0) { for(int x=0; x<namespaceCount; x++) { contentHandler.endPrefixMapping(xmlStreamReader.getNamespacePrefix(x)); } } break; } case XMLStreamReader.PROCESSING_INSTRUCTION: { contentHandler.processingInstruction(xmlStreamReader.getPITarget(), xmlStreamReader.getPIData()); break; } case XMLStreamReader.CHARACTERS: { parseCharactersEvent(xmlStreamReader); break; } case XMLStreamReader.COMMENT: { if(null != lexicalHandler) { lexicalHandler.comment(xmlStreamReader.getTextCharacters(), xmlStreamReader.getTextStart(), xmlStreamReader.getTextLength()); } break; } case XMLStreamReader.SPACE: { contentHandler.characters(xmlStreamReader.getTextCharacters(), xmlStreamReader.getTextStart(), xmlStreamReader.getTextLength()); break; } case XMLStreamReader.START_DOCUMENT: { depth++; break; } case XMLStreamReader.END_DOCUMENT: { depth--; return; } case XMLStreamReader.ENTITY_REFERENCE: { break; } case XMLStreamReader.ATTRIBUTE: { break; } case XMLStreamReader.DTD: { break; } case XMLStreamReader.CDATA: { if(null == lexicalHandler) { parseCharactersEvent(xmlStreamReader); } else { lexicalHandler.startCDATA(); parseCharactersEvent(xmlStreamReader); lexicalHandler.endCDATA(); } break; } } } /** * Subclasses of this class can override this method to provide alternate * mechanisms for processing the characters event. One possibility is * obtaining a CharSequence and calling the corresponding characters method * on the extended content handler. */ protected void parseCharactersEvent(XMLStreamReader xmlStreamReader) throws SAXException { contentHandler.characters(xmlStreamReader.getTextCharacters(), xmlStreamReader.getTextStart(), xmlStreamReader.getTextLength()); } private static class XMLStreamReaderAttributes extends IndexedAttributeList { private XMLStreamReader xmlStreamReader; public void setXmlStreamReader(XMLStreamReader xmlStreamReader) { this.xmlStreamReader = xmlStreamReader; } @Override protected Attribute[] attributes() { if(null == attributes) { int namespaceCount = xmlStreamReader.getNamespaceCount(); int attributeCount = xmlStreamReader.getAttributeCount(); if(namespaceCount + attributeCount == 0) { attributes = NO_ATTRIBUTES; } else { attributes = new Attribute[attributeCount + namespaceCount]; for(int x=0; x<attributeCount; x++) { String uri = xmlStreamReader.getAttributeNamespace(x); String localName = xmlStreamReader.getAttributeLocalName(x); String prefix = xmlStreamReader.getAttributePrefix(x); String qName; if(null == prefix || prefix.length() == 0) { qName = localName; } else { qName = prefix + Constants.COLON + localName; } String value = xmlStreamReader.getAttributeValue(x); attributes[x] = new Attribute(uri, localName, qName, value); } for(int x=0; x<namespaceCount; x++) { String uri = javax.xml.XMLConstants.XMLNS_ATTRIBUTE_NS_URI; String localName = xmlStreamReader.getNamespacePrefix(x); String qName; if(null == localName || localName.length() == 0) { localName = javax.xml.XMLConstants.XMLNS_ATTRIBUTE; qName = javax.xml.XMLConstants.XMLNS_ATTRIBUTE; } else { qName = javax.xml.XMLConstants.XMLNS_ATTRIBUTE + Constants.COLON + localName; } String value = xmlStreamReader.getNamespaceURI(x); attributes[x + attributeCount] = new Attribute(uri, localName, qName, value); } } } return attributes; } @Override public String getValue(String uri, String localName) { if (Constants.EMPTY_STRING.equals(uri)) { uri = null; } return xmlStreamReader.getAttributeValue(uri, localName); } } // Made static for performance reasons. /** * <p>An implementation of Locator, created from an existing XMLStreamReader.</p> * * @see org.xml.sax.Locator * @see javax.xml.stream.XMLStreamReader */ private static class StreamReaderLocator implements Locator2 { private XMLStreamReader reader; /** * Instantiates a new StreamReaderLocator. * * @param r the XMLStreamReader object from which to copy location information. */ public StreamReaderLocator(XMLStreamReader r) { this.reader = r; } /** * Returns the public ID of this Locator. */ @Override public String getPublicId() { return this.reader.getLocation().getPublicId(); } /** * Returns the system ID of this Locator. */ @Override public String getSystemId() { return this.reader.getLocation().getSystemId(); } /** * Returns the line number of this Locator. */ @Override public int getLineNumber() { return this.reader.getLocation().getLineNumber(); } /** * Returns the column number of this Locator. */ @Override public int getColumnNumber() { return this.reader.getLocation().getColumnNumber(); } @Override public String getXMLVersion() { return null; } @Override public String getEncoding() { return null; } } }