001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Emil Ong
028: */
029:
030: package com.caucho.xml.stream;
031:
032: import com.caucho.util.L10N;
033: import com.caucho.xml.QDocument;
034:
035: import org.xml.sax.ContentHandler;
036: import org.xml.sax.SAXException;
037: import org.xml.sax.ext.LexicalHandler;
038: import org.xml.sax.helpers.AttributesImpl;
039:
040: import javax.xml.XMLConstants;
041: import javax.xml.namespace.NamespaceContext;
042: import javax.xml.stream.XMLStreamException;
043: import javax.xml.stream.XMLStreamWriter;
044: import javax.xml.transform.sax.SAXResult;
045: import java.util.ArrayList;
046: import java.util.HashMap;
047: import java.util.Iterator;
048: import java.util.List;
049: import java.util.Map;
050: import java.util.logging.Logger;
051:
052: public class SAXResultXMLStreamWriterImpl implements XMLStreamWriter {
053: private static final Logger log = Logger
054: .getLogger(SAXResultXMLStreamWriterImpl.class.getName());
055: private static final L10N L = new L10N(
056: SAXResultXMLStreamWriterImpl.class);
057:
058: private LexicalHandler _lexicalHandler;
059: private ContentHandler _contentHandler;
060:
061: // current element data
062: private String _uri;
063: private String _localName;
064: private String _qName;
065: private AttributesImpl _attributes = new AttributesImpl();
066: private boolean _unwritten = false;
067:
068: private boolean _currentIsEmpty = false;
069: private boolean _ended = false;
070:
071: private SimpleNamespaceContext _context = new SimpleNamespaceContext(
072: null);
073:
074: public SAXResultXMLStreamWriterImpl(SAXResult result)
075: throws XMLStreamException {
076: _lexicalHandler = result.getLexicalHandler();
077: _contentHandler = result.getHandler();
078: }
079:
080: public void close() throws XMLStreamException {
081: try {
082: if (!_ended)
083: _contentHandler.endDocument();
084: } catch (SAXException e) {
085: throw new XMLStreamException(e);
086: }
087: }
088:
089: public void flush() throws XMLStreamException {
090: }
091:
092: public NamespaceContext getNamespaceContext() {
093: return _context;
094: }
095:
096: public String getPrefix(String uri) throws XMLStreamException {
097: return _context.getPrefix(uri);
098: }
099:
100: public Object getProperty(String name)
101: throws IllegalArgumentException {
102: throw new PropertyNotSupportedException(name);
103: }
104:
105: public void setDefaultNamespace(String uri)
106: throws XMLStreamException {
107: _context.declare("", uri);
108: }
109:
110: public void setNamespaceContext(NamespaceContext context)
111: throws XMLStreamException {
112: String message = "please do not set the NamespaceContext";
113: throw new UnsupportedOperationException(message);
114: }
115:
116: public void setPrefix(String prefix, String uri)
117: throws XMLStreamException {
118: try {
119: _context.declare(prefix, uri);
120: _contentHandler.startPrefixMapping(prefix, uri);
121: } catch (SAXException e) {
122: throw new XMLStreamException(e);
123: }
124: }
125:
126: public void writeAttribute(String localName, String value)
127: throws XMLStreamException {
128: if (!_unwritten)
129: throw new IllegalStateException();
130:
131: // XXX other types?
132: _attributes.addAttribute("", localName, localName, "CDATA",
133: value);
134: }
135:
136: public void writeAttribute(String namespaceURI, String localName,
137: String value) throws XMLStreamException {
138: if (!_unwritten)
139: throw new IllegalStateException();
140:
141: _attributes.addAttribute(namespaceURI, localName, localName,
142: "CDATA", value);
143: }
144:
145: public void writeAttribute(String prefix, String namespaceURI,
146: String localName, String value) throws XMLStreamException {
147: if (!_unwritten)
148: throw new IllegalStateException();
149:
150: _attributes.addAttribute(namespaceURI, localName, prefix + ':'
151: + localName, "CDATA", value);
152: }
153:
154: public void writeCData(String data) throws XMLStreamException {
155: // XXX
156: throw new UnsupportedOperationException();
157: }
158:
159: public void writeCharacters(char[] text, int start, int len)
160: throws XMLStreamException {
161: handleUnwrittenStart();
162:
163: try {
164: _contentHandler.characters(text, start, len);
165: } catch (SAXException e) {
166: throw new XMLStreamException(e);
167: }
168: }
169:
170: public void writeCharacters(String text) throws XMLStreamException {
171: handleUnwrittenStart();
172:
173: char[] array = text.toCharArray();
174: writeCharacters(array, 0, array.length);
175: }
176:
177: public void writeComment(String data) throws XMLStreamException {
178: handleUnwrittenStart();
179:
180: try {
181: if (_lexicalHandler != null) {
182: char[] array = data.toCharArray();
183: _lexicalHandler.comment(array, 0, array.length);
184: }
185: } catch (SAXException e) {
186: throw new XMLStreamException(e);
187: }
188: }
189:
190: public void writeDefaultNamespace(String namespaceURI)
191: throws XMLStreamException {
192: if (!_unwritten)
193: throw new IllegalStateException();
194:
195: try {
196: _context.declare("", namespaceURI);
197: _contentHandler.startPrefixMapping("", namespaceURI);
198: } catch (SAXException e) {
199: throw new XMLStreamException(e);
200: }
201: }
202:
203: public void writeDTD(String dtd) throws XMLStreamException {
204: handleUnwrittenStart();
205:
206: // XXX: lexicalHandler
207: throw new UnsupportedOperationException();
208: }
209:
210: public void writeEmptyElement(String localName)
211: throws XMLStreamException {
212: if (_currentIsEmpty)
213: popContext();
214:
215: handleUnwrittenStart();
216:
217: pushContext();
218:
219: _uri = null;
220: _localName = localName;
221: _qName = localName;
222: _attributes = new AttributesImpl();
223:
224: _currentIsEmpty = true;
225: }
226:
227: public void writeEmptyElement(String namespaceURI, String localName)
228: throws XMLStreamException {
229: if (_currentIsEmpty)
230: popContext();
231:
232: handleUnwrittenStart();
233:
234: pushContext();
235:
236: _uri = namespaceURI;
237: _localName = localName;
238: _qName = localName;
239: _attributes = new AttributesImpl();
240:
241: _currentIsEmpty = true;
242: }
243:
244: public void writeEmptyElement(String prefix, String localName,
245: String namespaceURI) throws XMLStreamException {
246: if (_currentIsEmpty)
247: popContext();
248:
249: handleUnwrittenStart();
250:
251: pushContext();
252:
253: _uri = namespaceURI;
254: _localName = localName;
255: _qName = prefix + ':' + localName;
256: _attributes = new AttributesImpl();
257:
258: _currentIsEmpty = true;
259: }
260:
261: public void writeEndDocument() throws XMLStreamException {
262: handleUnwrittenStart();
263:
264: try {
265: _contentHandler.endDocument();
266: _ended = true;
267: } catch (SAXException e) {
268: throw new XMLStreamException(e);
269: }
270: }
271:
272: public void writeEndElement() throws XMLStreamException {
273: popContext();
274: }
275:
276: public void writeEntityRef(String name) throws XMLStreamException {
277: handleUnwrittenStart();
278:
279: // XXX
280: throw new UnsupportedOperationException();
281: }
282:
283: public void writeNamespace(String prefix, String namespaceURI)
284: throws XMLStreamException {
285: if (!_unwritten)
286: throw new IllegalStateException();
287:
288: _context.declare(prefix, namespaceURI);
289: _attributes.addAttribute(XMLConstants.XMLNS_ATTRIBUTE_NS_URI,
290: prefix, XMLConstants.XMLNS_ATTRIBUTE + ':' + prefix,
291: "CDATA", namespaceURI);
292: }
293:
294: public void writeProcessingInstruction(String target)
295: throws XMLStreamException {
296: handleUnwrittenStart();
297:
298: writeProcessingInstruction(target, null);
299: }
300:
301: public void writeProcessingInstruction(String target, String data)
302: throws XMLStreamException {
303: handleUnwrittenStart();
304:
305: try {
306: _contentHandler.processingInstruction(target, data);
307: } catch (SAXException e) {
308: throw new XMLStreamException(e);
309: }
310: }
311:
312: public void writeStartDocument() throws XMLStreamException {
313: try {
314: _contentHandler.startDocument();
315: } catch (SAXException e) {
316: throw new XMLStreamException(e);
317: }
318: }
319:
320: public void writeStartDocument(String version)
321: throws XMLStreamException {
322: try {
323: _contentHandler.startDocument();
324: } catch (SAXException e) {
325: throw new XMLStreamException(e);
326: }
327: }
328:
329: public void writeStartDocument(String version, String encoding)
330: throws XMLStreamException {
331: try {
332: _contentHandler.startDocument();
333: } catch (SAXException e) {
334: throw new XMLStreamException(e);
335: }
336: }
337:
338: public void writeStartElement(String localName)
339: throws XMLStreamException {
340: if (_currentIsEmpty) {
341: popContext();
342: _currentIsEmpty = false;
343: }
344:
345: pushContext();
346:
347: _uri = null;
348: _localName = localName;
349: _qName = localName;
350: _attributes = new AttributesImpl();
351: _unwritten = true;
352: }
353:
354: public void writeStartElement(String namespaceURI, String localName)
355: throws XMLStreamException {
356: if (_currentIsEmpty) {
357: popContext();
358: _currentIsEmpty = false;
359: }
360:
361: pushContext();
362:
363: _uri = namespaceURI;
364: _localName = localName;
365: _qName = localName;
366: _attributes = new AttributesImpl();
367: _unwritten = true;
368: }
369:
370: public void writeStartElement(String prefix, String localName,
371: String namespaceURI) throws XMLStreamException {
372: if (_currentIsEmpty) {
373: popContext();
374: _currentIsEmpty = false;
375: }
376:
377: pushContext();
378:
379: _uri = namespaceURI;
380: _localName = localName;
381: _qName = prefix + ':' + localName;
382: _attributes = new AttributesImpl();
383: _unwritten = true;
384: }
385:
386: //////////////////////////////////////////////////////////////////////////
387:
388: private void handleUnwrittenStart() throws XMLStreamException {
389: try {
390: if (_unwritten)
391: _contentHandler.startElement(_uri, _localName, _qName,
392: _attributes);
393:
394: _unwritten = false;
395: } catch (SAXException e) {
396: throw new XMLStreamException(e);
397: }
398: }
399:
400: private void pushContext() throws XMLStreamException {
401: _context = new SimpleNamespaceContext(_context);
402: }
403:
404: private void popContext() throws XMLStreamException {
405: try {
406: if (_currentIsEmpty)
407: _contentHandler.startElement(_uri, _localName, _qName,
408: _attributes);
409:
410: for (String prefix : _context.getPrefixMap().keySet())
411: _contentHandler.endPrefixMapping(prefix);
412:
413: _contentHandler.endElement(_uri, _localName, _qName);
414:
415: _context = _context.getParent();
416: } catch (SAXException e) {
417: throw new XMLStreamException(e);
418: }
419: }
420:
421: // XXX switch to NamespaceWriterContext
422: private static class SimpleNamespaceContext implements
423: NamespaceContext {
424: private HashMap<String, String> _uris = new HashMap<String, String>();
425: private HashMap<String, List<String>> _prefixes = new HashMap<String, List<String>>();
426: private SimpleNamespaceContext _parent;
427: private int _prefixCounter = 0;
428:
429: public SimpleNamespaceContext(SimpleNamespaceContext parent) {
430: _parent = parent;
431: }
432:
433: public String getNamespaceURI(String prefix) {
434: return _uris.get(prefix);
435: }
436:
437: public String getPrefix(String namespaceURI) {
438: List<String> prefixes = _prefixes.get(namespaceURI);
439:
440: if (prefixes == null || prefixes.size() == 0)
441: return null;
442:
443: return prefixes.get(0);
444: }
445:
446: public Iterator getPrefixes(String namespaceURI) {
447: List<String> prefixes = _prefixes.get(namespaceURI);
448:
449: if (prefixes == null) {
450: prefixes = new ArrayList<String>();
451: _prefixes.put(namespaceURI, prefixes);
452: }
453:
454: return prefixes.iterator();
455: }
456:
457: public HashMap<String, String> getPrefixMap() {
458: return _uris;
459: }
460:
461: public String declare(String namespaceURI) {
462: String prefix = "ns" + _prefixCounter;
463: declare(prefix, namespaceURI);
464: _prefixCounter++;
465:
466: return prefix;
467: }
468:
469: public void declare(String prefix, String namespaceURI) {
470: _uris.put(prefix, namespaceURI);
471:
472: List<String> prefixes = _prefixes.get(namespaceURI);
473:
474: if (prefixes == null) {
475: prefixes = new ArrayList<String>();
476: _prefixes.put(namespaceURI, prefixes);
477: }
478:
479: prefixes.add(prefix);
480: }
481:
482: public SimpleNamespaceContext getParent() {
483: return _parent;
484: }
485: }
486: }
|