1 /*
   2  * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package com.sun.xml.internal.stream.events;
  26 
  27 import com.sun.org.apache.xerces.internal.impl.PropertyManager;
  28 import java.util.List;
  29 import javax.xml.stream.util.XMLEventAllocator;
  30 import javax.xml.stream.*;
  31 import javax.xml.stream.events.*;
  32 import javax.xml.XMLConstants;
  33 import javax.xml.namespace.QName;
  34 import com.sun.org.apache.xerces.internal.util.NamespaceContextWrapper;
  35 import com.sun.org.apache.xerces.internal.util.NamespaceSupport;
  36 import javax.xml.stream.util.XMLEventConsumer;
  37 
  38 /**
  39  * Implementation of XMLEvent Allocator.
  40  *
  41  * @author Neeraj.bajaj@sun.com, k.venugopal@sun.com
  42  */
  43 public class XMLEventAllocatorImpl implements XMLEventAllocator {
  44 
  45     /**
  46      * Creates a new instance of XMLEventAllocator
  47      */
  48     public XMLEventAllocatorImpl() {
  49     }
  50 
  51     public XMLEvent allocate(XMLStreamReader xMLStreamReader) throws XMLStreamException {
  52         if (xMLStreamReader == null) {
  53             throw new XMLStreamException("Reader cannot be null");
  54         }
  55         //        allocate is not supposed to change the state of the reader so we shouldn't be calling next.
  56         //        return getNextEvent(xMLStreamReader);
  57         return getXMLEvent(xMLStreamReader);
  58     }
  59 
  60     public void allocate(XMLStreamReader xMLStreamReader, XMLEventConsumer xMLEventConsumer)
  61             throws XMLStreamException {
  62         XMLEvent currentEvent = getXMLEvent(xMLStreamReader);
  63         if (currentEvent != null) {
  64             xMLEventConsumer.add(currentEvent);
  65         }
  66 
  67         return;
  68     }
  69 
  70     public javax.xml.stream.util.XMLEventAllocator newInstance() {
  71         return new XMLEventAllocatorImpl();
  72     }
  73 
  74     //REVISIT: shouldn't we be using XMLEventFactory to create events.
  75     XMLEvent getXMLEvent(XMLStreamReader streamReader) {
  76         XMLEvent event = null;
  77         //returns the current event
  78         int eventType = streamReader.getEventType();
  79         switch (eventType) {
  80 
  81             case XMLEvent.START_ELEMENT: {
  82                 StartElementEvent startElementEvent = new StartElementEvent(getQName(streamReader));
  83                 fillAttributes(startElementEvent, streamReader);
  84                 //we might have different XMLStreamReader so check every time for
  85                 //the namespace aware property. we should be setting namespace
  86                 //related values only when isNamespaceAware is 'true'
  87                 if (((Boolean) streamReader.getProperty(XMLInputFactory.IS_NAMESPACE_AWARE))) {
  88                     fillNamespaceAttributes(startElementEvent, streamReader);
  89                     setNamespaceContext(startElementEvent, streamReader);
  90                 }
  91 
  92                 startElementEvent.setLocation(streamReader.getLocation());
  93                 event = startElementEvent;
  94                 break;
  95             }
  96             case XMLEvent.END_ELEMENT: {
  97                 EndElementEvent endElementEvent = new EndElementEvent(getQName(streamReader));
  98                 endElementEvent.setLocation(streamReader.getLocation());
  99 
 100                 if (((Boolean) streamReader.getProperty(XMLInputFactory.IS_NAMESPACE_AWARE))) {
 101                     fillNamespaceAttributes(endElementEvent, streamReader);
 102                 }
 103                 event = endElementEvent;
 104                 break;
 105             }
 106             case XMLEvent.PROCESSING_INSTRUCTION: {
 107                 ProcessingInstructionEvent piEvent = new ProcessingInstructionEvent(
 108                         streamReader.getPITarget(), streamReader.getPIData());
 109                 piEvent.setLocation(streamReader.getLocation());
 110                 event = piEvent;
 111                 break;
 112             }
 113             case XMLEvent.CHARACTERS: {
 114                 CharacterEvent cDataEvent = new CharacterEvent(streamReader.getText());
 115                 cDataEvent.setLocation(streamReader.getLocation());
 116                 event = cDataEvent;
 117                 break;
 118             }
 119             case XMLEvent.COMMENT: {
 120                 CommentEvent commentEvent = new CommentEvent(streamReader.getText());
 121                 commentEvent.setLocation(streamReader.getLocation());
 122                 event = commentEvent;
 123                 break;
 124             }
 125             case XMLEvent.START_DOCUMENT: {
 126                 StartDocumentEvent sdEvent = new StartDocumentEvent();
 127                 sdEvent.setVersion(streamReader.getVersion());
 128                 sdEvent.setEncoding(streamReader.getEncoding());
 129                 if (streamReader.getCharacterEncodingScheme() != null) {
 130                     sdEvent.setDeclaredEncoding(true);
 131                 } else {
 132                     sdEvent.setDeclaredEncoding(false);
 133                 }
 134                 sdEvent.setStandalone(streamReader.isStandalone());
 135                 sdEvent.setLocation(streamReader.getLocation());
 136                 event = sdEvent;
 137                 break;
 138             }
 139             case XMLEvent.END_DOCUMENT: {
 140                 EndDocumentEvent endDocumentEvent = new EndDocumentEvent();
 141                 endDocumentEvent.setLocation(streamReader.getLocation());
 142                 event = endDocumentEvent;
 143                 break;
 144             }
 145             case XMLEvent.ENTITY_REFERENCE: {
 146                 EntityReferenceEvent entityEvent = new EntityReferenceEvent(streamReader.getLocalName(),
 147                         new EntityDeclarationImpl(streamReader.getLocalName(), streamReader.getText()));
 148                 entityEvent.setLocation(streamReader.getLocation());
 149                 event = entityEvent;
 150                 break;
 151 
 152             }
 153             case XMLEvent.ATTRIBUTE: {
 154                 event = null;
 155                 break;
 156             }
 157             case XMLEvent.DTD: {
 158                 DTDEvent dtdEvent = new DTDEvent(streamReader.getText());
 159                 dtdEvent.setLocation(streamReader.getLocation());
 160                 @SuppressWarnings("unchecked")
 161                 List<EntityDeclaration> entities = (List<EntityDeclaration>)
 162                         streamReader.getProperty(PropertyManager.STAX_ENTITIES);
 163                 if (entities != null && entities.size() != 0) {
 164                     dtdEvent.setEntities(entities);
 165                 }
 166                 @SuppressWarnings("unchecked")
 167                 List<NotationDeclaration> notations = (List<NotationDeclaration>)
 168                         streamReader.getProperty(PropertyManager.STAX_NOTATIONS);
 169                 if (notations != null && !notations.isEmpty()) {
 170                     dtdEvent.setNotations(notations);
 171                 }
 172                 event = dtdEvent;
 173                 break;
 174             }
 175             case XMLEvent.CDATA: {
 176                 CharacterEvent cDataEvent = new CharacterEvent(streamReader.getText(), true);
 177                 cDataEvent.setLocation(streamReader.getLocation());
 178                 event = cDataEvent;
 179                 break;
 180             }
 181             case XMLEvent.SPACE: {
 182                 CharacterEvent spaceEvent = new CharacterEvent(streamReader.getText(), false, true);
 183                 spaceEvent.setLocation(streamReader.getLocation());
 184                 event = spaceEvent;
 185                 break;
 186             }
 187         }
 188         return event;
 189     }
 190 
 191     //this function is not used..
 192     protected XMLEvent getNextEvent(XMLStreamReader streamReader) throws XMLStreamException {
 193         //advance the reader to next event.
 194         streamReader.next();
 195         return getXMLEvent(streamReader);
 196     }
 197 
 198     protected void fillAttributes(StartElementEvent event, XMLStreamReader xmlr) {
 199 
 200         int len = xmlr.getAttributeCount();
 201         QName qname = null;
 202         AttributeImpl attr = null;
 203         NamespaceImpl nattr = null;
 204         for (int i = 0; i < len; i++) {
 205             qname = xmlr.getAttributeName(i);
 206             //this method doesn't include namespace declarations
 207             //so we can be sure that there wont be any namespace declaration as part of this function call
 208             //we can avoid this check - nb.
 209             /**
 210              * prefix = qname.getPrefix(); localpart = qname.getLocalPart(); if
 211              * (prefix.equals(XMLConstants.XMLNS_ATTRIBUTE) ) { attr = new
 212              * NamespaceImpl(localpart,xmlr.getAttributeValue(i)); }else if
 213              * (prefix.equals(XMLConstants.DEFAULT_NS_PREFIX)){ attr = new
 214              * NamespaceImpl(xmlr.getAttributeValue(i)); }else{ attr = new
 215              * AttributeImpl(); attr.setName(qname); }
 216              *
 217              */
 218             attr = new AttributeImpl();
 219             attr.setName(qname);
 220             attr.setAttributeType(xmlr.getAttributeType(i));
 221             attr.setSpecified(xmlr.isAttributeSpecified(i));
 222             attr.setValue(xmlr.getAttributeValue(i));
 223             event.addAttribute(attr);
 224         }
 225     }
 226 
 227     protected void fillNamespaceAttributes(StartElementEvent event, XMLStreamReader xmlr) {
 228         int count = xmlr.getNamespaceCount();
 229         String uri = null;
 230         String prefix = null;
 231         NamespaceImpl attr = null;
 232         for (int i = 0; i < count; i++) {
 233             uri = xmlr.getNamespaceURI(i);
 234             prefix = xmlr.getNamespacePrefix(i);
 235             if (prefix == null) {
 236                 prefix = XMLConstants.DEFAULT_NS_PREFIX;
 237             }
 238             attr = new NamespaceImpl(prefix, uri);
 239             event.addNamespaceAttribute(attr);
 240         }
 241     }
 242 
 243     protected void fillNamespaceAttributes(EndElementEvent event, XMLStreamReader xmlr) {
 244         int count = xmlr.getNamespaceCount();
 245         String uri = null;
 246         String prefix = null;
 247         NamespaceImpl attr = null;
 248         for (int i = 0; i < count; i++) {
 249             uri = xmlr.getNamespaceURI(i);
 250             prefix = xmlr.getNamespacePrefix(i);
 251             if (prefix == null) {
 252                 prefix = XMLConstants.DEFAULT_NS_PREFIX;
 253             }
 254             attr = new NamespaceImpl(prefix, uri);
 255             event.addNamespace(attr);
 256         }
 257     }
 258 
 259     //Revisit : Creating a new Namespacecontext for now.
 260     //see if we can do better job.
 261     private void setNamespaceContext(StartElementEvent event, XMLStreamReader xmlr) {
 262         NamespaceContextWrapper contextWrapper = (NamespaceContextWrapper) xmlr.getNamespaceContext();
 263         NamespaceSupport ns = new NamespaceSupport(contextWrapper.getNamespaceContext());
 264         event.setNamespaceContext(new NamespaceContextWrapper(ns));
 265     }
 266 
 267     private QName getQName(XMLStreamReader xmlr) {
 268         return new QName(xmlr.getNamespaceURI(), xmlr.getLocalName(),
 269                 xmlr.getPrefix());
 270     }
 271 }