001 /** 002 * 003 * Copyright 2004 Protique Ltd 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 * 017 **/ 018 package org.codehaus.activesoap.util; 019 020 import org.xml.sax.ContentHandler; 021 import org.xml.sax.Attributes; 022 import org.xml.sax.SAXException; 023 import org.xml.sax.helpers.AttributesImpl; 024 025 import javax.xml.namespace.NamespaceContext; 026 import javax.xml.namespace.QName; 027 import javax.xml.stream.XMLStreamConstants; 028 import javax.xml.stream.XMLStreamException; 029 import javax.xml.stream.XMLStreamReader; 030 import javax.xml.stream.XMLStreamWriter; 031 032 import javanet.staxutils.XMLStreamUtils; 033 import javanet.staxutils.XMLStreamReaderToContentHandler; 034 035 /** 036 * Utility methods for working with an XMLStreamWriter. 037 * Maybe push this back into stax-utils project. 038 * 039 * @version $Revision: 1.14 $ 040 */ 041 public class XMLStreamHelper implements XMLStreamConstants { 042 private static Attributes emptyAttributes = new AttributesImpl(); 043 044 045 /** 046 * Returns true if currently at the start of an element, otherwise move forwards to the next 047 * element start and return true, otherwise false is returned if the end of the stream is reached. 048 */ 049 public static boolean skipToStartOfElement(XMLStreamReader in) throws XMLStreamException { 050 for (int code = in.getEventType(); code != END_DOCUMENT; code = in.next()) { 051 if (code == START_ELEMENT) { 052 return true; 053 } 054 } 055 return false; 056 } 057 058 public static void writeStartElement(QName qname, ContentHandler handler) throws SAXException { 059 handler.startElement(qname.getNamespaceURI(), qname.getLocalPart(), QNameHelper.getQualifiedName(qname), emptyAttributes); 060 } 061 062 public static void writeEndElement(QName qname, ContentHandler handler) throws SAXException { 063 handler.endElement(qname.getNamespaceURI(), qname.getLocalPart(), QNameHelper.getQualifiedName(qname)); 064 } 065 066 067 /** 068 * Copies the current element and its conetnt to the output 069 */ 070 public static void copy(XMLStreamReader in, XMLStreamWriter out, boolean repairing) throws XMLStreamException { 071 int elementCount = 0; 072 for (int code = in.getEventType(); in.hasNext(); code = in.next()) { 073 switch (code) { 074 case START_ELEMENT: 075 elementCount++; 076 writeStartElementAndAttributes(out, in, repairing); 077 break; 078 079 case END_ELEMENT: 080 if (--elementCount < 0) { 081 return; 082 } 083 out.writeEndElement(); 084 break; 085 086 case CDATA: 087 out.writeCData(in.getText()); 088 break; 089 090 case CHARACTERS: 091 out.writeCharacters(in.getText()); 092 break; 093 } 094 } 095 while (elementCount-- > 0) { 096 out.writeEndElement(); 097 } 098 } 099 100 public static void writeStartElement(XMLStreamWriter out, String prefix, String uri, String localName, boolean repairing) throws XMLStreamException { 101 boolean map = isPrefixNotMappedToUri(out, prefix, uri); 102 if (prefix != null && prefix.length() > 0) { 103 if (map) { 104 out.setPrefix(prefix, uri); 105 } 106 out.writeStartElement(prefix, localName, uri); 107 if (map && !repairing) { 108 out.writeNamespace(prefix, uri); 109 } 110 } 111 else { 112 boolean hasURI = uri != null && uri.length() > 0; 113 if (map && hasURI) { 114 out.setDefaultNamespace(uri); 115 } 116 out.writeStartElement(uri, localName); 117 if (map && !repairing && hasURI) { 118 out.writeDefaultNamespace(uri); 119 } 120 } 121 } 122 123 public static void writeStartElement(XMLStreamWriter out, QName envelopeName, boolean repairing) throws XMLStreamException { 124 writeStartElement(out, envelopeName.getPrefix(), envelopeName.getNamespaceURI(), envelopeName.getLocalPart(), repairing); 125 } 126 127 public static void writeStartElement(XMLStreamWriter out, XMLStreamReader in, boolean repairing) throws XMLStreamException { 128 String prefix = in.getPrefix(); 129 130 // we can avoid this step if in repairing mode 131 int count = in.getNamespaceCount(); 132 for (int i = 0; i < count; i++) { 133 String aPrefix = in.getNamespacePrefix(i); 134 if (prefix == aPrefix || (prefix != null && prefix.equals(aPrefix))) { 135 continue; 136 } 137 String uri = in.getNamespaceURI(i); 138 if (isPrefixNotMappedToUri(out, aPrefix, uri)) { 139 if (aPrefix != null && aPrefix.length() > 0) { 140 out.setPrefix(aPrefix, uri); 141 } 142 else { 143 out.setDefaultNamespace(uri); 144 } 145 } 146 } 147 String localName = in.getLocalName(); 148 String uri = in.getNamespaceURI(); 149 writeStartElement(out, prefix, uri, localName, repairing); 150 } 151 152 153 public static void writeStartElementAndAttributes(XMLStreamWriter out, XMLStreamReader in, boolean repairing) throws XMLStreamException { 154 writeStartElement(out, in, repairing); 155 if (!repairing) { 156 writeNamespaces(out, in, in.getPrefix()); 157 } 158 writeAttributes(out, in); 159 } 160 161 public static void writeAttributes(XMLStreamWriter out, XMLStreamReader in) throws XMLStreamException { 162 int count = in.getAttributeCount(); 163 for (int i = 0; i < count; i++) { 164 out.writeAttribute(in.getAttributePrefix(i), 165 in.getAttributeNamespace(i), 166 in.getAttributeLocalName(i), 167 in.getAttributeValue(i)); 168 } 169 } 170 171 public static void writeNamespaces(XMLStreamWriter out, XMLStreamReader in, String prefixOfCurrentElement) throws XMLStreamException { 172 int count = in.getNamespaceCount(); 173 for (int i = 0; i < count; i++) { 174 String prefix = in.getNamespacePrefix(i); 175 String uri = in.getNamespaceURI(i); 176 if (prefixOfCurrentElement != null && prefixOfCurrentElement.equals(prefix)) { 177 continue; 178 } 179 if (isPrefixNotMappedToUri(out, prefix, uri)) { 180 out.writeNamespace(prefix, uri); 181 } 182 } 183 } 184 185 186 public static void writeNamespacesExcludingPrefixAndNamespace(XMLStreamWriter out, XMLStreamReader in, String ignorePrefix, String ignoreNamespace) throws XMLStreamException { 187 int count = in.getNamespaceCount(); 188 for (int i = 0; i < count; i++) { 189 String prefix = in.getNamespacePrefix(i); 190 if (!ignorePrefix.equals(prefix)) { 191 String uri = in.getNamespaceURI(i); 192 if (!ignoreNamespace.equals(uri)) { 193 out.writeNamespace(prefix, uri); 194 } 195 } 196 } 197 } 198 199 public static void writeAttribute(XMLStreamWriter out, QName name, String attributeValue) throws XMLStreamException { 200 writeAttribute(out, name.getPrefix(), name.getNamespaceURI(), name.getLocalPart(), attributeValue); 201 } 202 203 public static void writeAttribute(XMLStreamWriter out, String prefix, String namespaceURI, String localPart, String attributeValue) throws XMLStreamException { 204 out.writeAttribute(prefix, namespaceURI, localPart, attributeValue); 205 } 206 207 protected static boolean isPrefixNotMappedToUri(XMLStreamWriter out, String prefix, String uri) { 208 if (prefix == null) { 209 prefix = ""; 210 } 211 NamespaceContext context = out.getNamespaceContext(); 212 if (context == null) { 213 return false; 214 } 215 String mappedUri = context.getPrefix(prefix); 216 boolean map = (mappedUri == null || !mappedUri.equals(uri)); 217 return map; 218 } 219 220 /** 221 * Copies the content to the SAX stream 222 */ 223 public static void copy(XMLStreamReader in, ContentHandler contentHandler) throws XMLStreamException { 224 XMLStreamReaderToContentHandler converter = new XMLStreamReaderToContentHandler(in, contentHandler); 225 converter.bridge(); 226 } 227 228 /** 229 * Copies the element and its content to the SAX stream 230 */ 231 public static void copyElement(XMLStreamReader in, ContentHandler contentHandler) throws XMLStreamException { 232 copy(new DocumentFilterXMLStreamReader(in.getName(), in), contentHandler); 233 } 234 235 }