PageRenderTime 54ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/resin/src/main/java/com/caucho/xml/stream/StaxUtil.java

http://github.com/CleverCloud/Quercus
Java | 450 lines | 306 code | 79 blank | 65 comment | 67 complexity | d1ef14b534a42e0beb508ddaceeccf60 MD5 | raw file
Possible License(s): GPL-2.0
  1. /*
  2. * Copyright (c) 1998-2010 Caucho Technology -- all rights reserved
  3. *
  4. * This file is part of Resin(R) Open Source
  5. *
  6. * Each copy or derived work must preserve the copyright notice and this
  7. * notice unmodified.
  8. *
  9. * Resin Open Source is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * Resin Open Source is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
  17. * of NON-INFRINGEMENT. See the GNU General Public License for more
  18. * details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with Resin Open Source; if not, write to the
  22. *
  23. * Free Software Foundation, Inc.
  24. * 59 Temple Place, Suite 330
  25. * Boston, MA 02111-1307 USA
  26. *
  27. * @author Emil Ong
  28. */
  29. package com.caucho.xml.stream;
  30. import static javax.xml.XMLConstants.*;
  31. import javax.xml.namespace.NamespaceContext;
  32. import javax.xml.namespace.QName;
  33. import javax.xml.stream.XMLOutputFactory;
  34. import static javax.xml.stream.XMLStreamConstants.*;
  35. import javax.xml.stream.XMLStreamException;
  36. import javax.xml.stream.XMLStreamReader;
  37. import javax.xml.stream.XMLStreamWriter;
  38. import java.io.IOException;
  39. import java.util.Iterator;
  40. import com.caucho.util.L10N;
  41. /**
  42. * Utility class to do namespace repairs on XMLStreamWriters that don't have
  43. * repair enabled. Used by JAXB.
  44. **/
  45. public class StaxUtil {
  46. public static final L10N L = new L10N(StaxUtil.class);
  47. public static QName resolveStringToQName(String string, XMLStreamReader in)
  48. throws XMLStreamException
  49. {
  50. return resolveStringToQName(string, in.getNamespaceContext());
  51. }
  52. public static QName resolveStringToQName(String string,
  53. NamespaceContext context)
  54. throws XMLStreamException
  55. {
  56. int colon = string.indexOf(':');
  57. if (colon < 0)
  58. return new QName(string);
  59. if (colon + 1 >= string.length())
  60. throw new XMLStreamException(L.l("Invalid qualified name: {0}", string));
  61. String prefix = string.substring(0, colon);
  62. String localName = string.substring(colon + 1);
  63. String namespace = context.getNamespaceURI(prefix);
  64. if (NULL_NS_URI.equals(namespace))
  65. throw new XMLStreamException(L.l("No namespace for qualifed name: {0}", string));
  66. return new QName(namespace, localName, prefix);
  67. }
  68. /**
  69. * Ensures that a given namespace exists within the namespace context
  70. * given.
  71. **/
  72. public static void repairNamespace(XMLStreamWriter out, String namespace)
  73. throws XMLStreamException
  74. {
  75. try {
  76. Object repairing =
  77. out.getProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES);
  78. if (Boolean.TRUE.equals(repairing))
  79. return;
  80. }
  81. catch (IllegalArgumentException e) {
  82. }
  83. catch (NullPointerException e) {
  84. }
  85. getNamespacePrefix(out, namespace);
  86. }
  87. /**
  88. * Ensures that a given namespace exists within the namespace context
  89. * given and returns the prefix.
  90. **/
  91. public static String getNamespacePrefix(XMLStreamWriter out, String namespace)
  92. throws XMLStreamException
  93. {
  94. NamespaceContext context = out.getNamespaceContext();
  95. String prefix = context.getPrefix(namespace);
  96. if (prefix != null)
  97. return prefix;
  98. if (context instanceof NamespaceWriterContext) {
  99. NamespaceWriterContext writerContext = (NamespaceWriterContext) context;
  100. boolean repair = writerContext.getRepair();
  101. writerContext.setRepair(true);
  102. prefix = writerContext.declare(namespace);
  103. writerContext.setRepair(repair);
  104. return prefix;
  105. }
  106. else {
  107. // not one of ours...
  108. // we have to search for a unique prefix...
  109. int i = 0;
  110. String unique = "ns" + i;
  111. while (true) {
  112. boolean found = false;
  113. Iterator iterator = context.getPrefixes(namespace);
  114. while (iterator.hasNext()) {
  115. prefix = iterator.next().toString();
  116. if (prefix.equals(unique)) {
  117. i++;
  118. unique = "ns" + i;
  119. found = true;
  120. break;
  121. }
  122. }
  123. if (! found)
  124. break;
  125. }
  126. out.writeNamespace(unique, namespace);
  127. return unique;
  128. }
  129. }
  130. /**
  131. * Ensures that a given prefix->namespace mapping exists within the
  132. * namespace context given.
  133. **/
  134. public static void repairNamespace(XMLStreamWriter out,
  135. String prefix, String namespace)
  136. throws XMLStreamException
  137. {
  138. try {
  139. Object repairing =
  140. out.getProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES);
  141. if (Boolean.TRUE.equals(repairing))
  142. return;
  143. }
  144. catch (IllegalArgumentException e) {
  145. }
  146. catch (NullPointerException e) {
  147. }
  148. NamespaceContext context = out.getNamespaceContext();
  149. String oldPrefix = context.getPrefix(namespace);
  150. if (! prefix.equals(oldPrefix))
  151. out.writeNamespace(prefix, namespace);
  152. }
  153. public static XMLStreamWriter toRepairingXMLStreamWriter(XMLStreamWriter out)
  154. {
  155. try {
  156. Object repairing =
  157. out.getProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES);
  158. if (Boolean.TRUE.equals(repairing))
  159. return out;
  160. }
  161. catch (IllegalArgumentException e) {
  162. }
  163. catch (NullPointerException e) {
  164. }
  165. if (out instanceof XMLStreamWriterImpl) {
  166. ((XMLStreamWriterImpl) out).setRepair(true);
  167. return out;
  168. }
  169. else {
  170. return new XMLStreamWriterRepairingWrapper(out);
  171. }
  172. }
  173. /**
  174. * Copys all the events from the input to the output, without going past
  175. * an unmatch end element.
  176. *
  177. * E.g.: if the input is at the start of <y>, it will only read just past </y>
  178. *
  179. * <x>
  180. * <y>
  181. * <z/>
  182. * </y>
  183. * </x>
  184. *
  185. **/
  186. public static void copyReaderToWriter(XMLStreamReader in, XMLStreamWriter out)
  187. throws XMLStreamException
  188. {
  189. int depth = 0;
  190. do {
  191. switch (in.getEventType()) {
  192. case ATTRIBUTE:
  193. break;
  194. case CDATA:
  195. out.writeCData(in.getText());
  196. break;
  197. case CHARACTERS:
  198. out.writeCharacters(in.getText());
  199. break;
  200. case COMMENT:
  201. out.writeComment(in.getText());
  202. break;
  203. case DTD:
  204. out.writeDTD(in.getText());
  205. break;
  206. case END_DOCUMENT:
  207. out.writeEndDocument();
  208. break;
  209. case END_ELEMENT:
  210. depth--;
  211. if (depth < 0) {
  212. out.flush();
  213. return;
  214. }
  215. out.writeEndElement();
  216. break;
  217. case ENTITY_REFERENCE:
  218. out.writeEntityRef(in.getText());
  219. break;
  220. case NAMESPACE:
  221. break;
  222. case PROCESSING_INSTRUCTION:
  223. out.writeProcessingInstruction(in.getPITarget(), in.getPIData());
  224. break;
  225. case SPACE:
  226. out.writeCharacters(in.getText());
  227. break;
  228. case START_DOCUMENT:
  229. out.writeStartDocument(in.getEncoding(), in.getVersion());
  230. break;
  231. case START_ELEMENT:
  232. QName qname = in.getName();
  233. if (qname.getNamespaceURI() == null ||
  234. "".equals(qname.getNamespaceURI()))
  235. out.writeStartElement(qname.getLocalPart());
  236. else if (qname.getPrefix() == null || "".equals(qname.getPrefix()))
  237. out.writeStartElement(qname.getNamespaceURI(),
  238. qname.getLocalPart());
  239. else
  240. out.writeStartElement(qname.getPrefix(),
  241. qname.getLocalPart(),
  242. qname.getNamespaceURI());
  243. for (int i = 0; i < in.getAttributeCount(); i++) {
  244. qname = in.getAttributeName(i);
  245. String value = in.getAttributeValue(i);
  246. if (qname.getNamespaceURI() == null ||
  247. "".equals(qname.getNamespaceURI()))
  248. out.writeAttribute(qname.getLocalPart(), value);
  249. else if (qname.getPrefix() == null || "".equals(qname.getPrefix()))
  250. out.writeAttribute(qname.getNamespaceURI(),
  251. qname.getLocalPart(),
  252. value);
  253. else
  254. out.writeAttribute(qname.getPrefix(),
  255. qname.getNamespaceURI(),
  256. qname.getLocalPart(),
  257. value);
  258. }
  259. for (int i = 0; i < in.getNamespaceCount(); i++)
  260. out.writeNamespace(in.getNamespacePrefix(i), in.getNamespaceURI(i));
  261. depth++;
  262. break;
  263. }
  264. if (in.hasNext())
  265. in.next();
  266. else
  267. break;
  268. }
  269. while (depth >= 0);
  270. out.flush();
  271. }
  272. public static String constantToString(int constant)
  273. throws XMLStreamException
  274. {
  275. switch(constant) {
  276. case ATTRIBUTE: return "ATTRIBUTE";
  277. case CDATA: return "CDATA";
  278. case CHARACTERS: return "CHARACTERS";
  279. case COMMENT: return "COMMENT";
  280. case DTD: return "DTD";
  281. case END_DOCUMENT: return "END_DOCUMENT";
  282. case END_ELEMENT: return "END_ELEMENT";
  283. case ENTITY_DECLARATION: return "ENTITY_DECLARATION";
  284. case ENTITY_REFERENCE: return "ENTITY_REFERENCE";
  285. case NAMESPACE: return "NAMESPACE";
  286. case NOTATION_DECLARATION: return "NOTATION_DECLARATION";
  287. case PROCESSING_INSTRUCTION: return "PROCESSING_INSTRUCTION";
  288. case SPACE: return "SPACE";
  289. case START_DOCUMENT: return "START_DOCUMENT";
  290. case START_ELEMENT: return "START_ELEMENT";
  291. case -1:
  292. throw new XMLStreamException(L.l("Unexpected end of stream"));
  293. default:
  294. throw new RuntimeException(L.l("constantToString({0}) unknown", constant));
  295. }
  296. }
  297. public static String printStreamState(XMLStreamReader in)
  298. throws XMLStreamException
  299. {
  300. StringBuilder sb = new StringBuilder(constantToString(in.getEventType()));
  301. if (in.getEventType() == in.START_ELEMENT ||
  302. in.getEventType() == in.END_ELEMENT) {
  303. sb.append(": ");
  304. sb.append(in.getName());
  305. }
  306. else if (in.getEventType() == in.CHARACTERS) {
  307. sb.append(": ");
  308. sb.append(in.getText());
  309. }
  310. return sb.toString();
  311. }
  312. /**
  313. * Converts a QName to a String using the context of a XMLStreamWriter.
  314. * Intended for writing QNames as attributes or text in a XMLStreamWriter
  315. * that's passed in.
  316. **/
  317. public static String qnameToString(XMLStreamWriter out, QName qname)
  318. throws XMLStreamException
  319. {
  320. if (qname.getNamespaceURI() == null || "".equals(qname.getNamespaceURI()))
  321. return qname.getLocalPart();
  322. NamespaceContext context = out.getNamespaceContext();
  323. String prefix = context.getPrefix(qname.getNamespaceURI());
  324. if (prefix == null) {
  325. if (qname.getPrefix() != null && ! "".equals(qname.getPrefix())) {
  326. out.writeNamespace(qname.getPrefix(), qname.getNamespaceURI());
  327. return qname.getPrefix() + ':' + qname.getLocalPart();
  328. }
  329. prefix = getNamespacePrefix(out, qname.getNamespaceURI());
  330. // XXX this shouldn't be necessary
  331. out.writeNamespace(prefix, qname.getNamespaceURI());
  332. }
  333. return prefix + ':' + qname.getLocalPart();
  334. }
  335. public static void writeStartElement(XMLStreamWriter out, QName name)
  336. throws XMLStreamException
  337. {
  338. if (name == null)
  339. return;
  340. if (name.getPrefix() != null && ! "".equals(name.getPrefix()))
  341. out.writeStartElement(name.getPrefix(),
  342. name.getLocalPart(),
  343. name.getNamespaceURI());
  344. else if (name.getNamespaceURI() != null &&
  345. ! "".equals(name.getNamespaceURI()))
  346. out.writeStartElement(name.getNamespaceURI(), name.getLocalPart());
  347. else
  348. out.writeStartElement(name.getLocalPart());
  349. }
  350. public static void writeEndElement(XMLStreamWriter out, QName name)
  351. throws XMLStreamException
  352. {
  353. if (name == null)
  354. return;
  355. out.writeEndElement();
  356. }
  357. public static void writeAttribute(XMLStreamWriter out,
  358. QName name, String value)
  359. throws XMLStreamException
  360. {
  361. if (name.getNamespaceURI() == null || "".equals(name.getNamespaceURI()))
  362. out.writeAttribute(name.getLocalPart(), value);
  363. else if (name.getPrefix() == null || "".equals(name.getPrefix()))
  364. out.writeAttribute(name.getNamespaceURI(), name.getLocalPart(), value);
  365. else
  366. out.writeAttribute(name.getPrefix(),
  367. name.getNamespaceURI(),
  368. name.getLocalPart(),
  369. value);
  370. }
  371. }