1. Project Clover database Sat Feb 2 2019 06:45:20 CET
  2. Package com.xpn.xwiki.internal.xml

File DOMXMLWriter.java

 

Coverage histogram

../../../../../img/srcFileCovDistChart4.png
80% of files have more coverage

Code metrics

8
37
17
2
331
136
23
0.62
2.18
8.5
1.35

Classes

Class Line # Actions
DOMXMLWriter 93 36 0% 22 37
0.3833333338.3%
DOMXMLWriter.SAXUnsupportedException 321 1 0% 1 2
0.00%
 

Contributing tests

No tests hitting this source file were found.

Source view

1    /*
2    * See the NOTICE file distributed with this work for additional
3    * information regarding copyright ownership.
4    *
5    * This is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU Lesser General Public License as
7    * published by the Free Software Foundation; either version 2.1 of
8    * the License, or (at your option) any later version.
9    *
10    * This software is distributed in the hope that it will be useful,
11    * but WITHOUT ANY WARRANTY; without even the implied warranty of
12    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13    * Lesser General Public License for more details.
14    *
15    * You should have received a copy of the GNU Lesser General Public
16    * License along with this software; if not, write to the Free
17    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19    */
20    package com.xpn.xwiki.internal.xml;
21   
22    import java.io.ByteArrayOutputStream;
23    import java.io.IOException;
24    import java.io.InputStream;
25    import java.io.Reader;
26    import java.io.UnsupportedEncodingException;
27    import java.util.EmptyStackException;
28   
29    import org.apache.commons.codec.binary.Base64OutputStream;
30    import org.apache.commons.io.IOUtils;
31    import org.apache.commons.io.output.NullOutputStream;
32    import org.dom4j.Document;
33    import org.dom4j.Element;
34    import org.dom4j.io.OutputFormat;
35    import org.xml.sax.Attributes;
36    import org.xml.sax.SAXException;
37   
38    /**
39    * This a minimal implementation to transform an XMLWriter into a <code>{@link org.dom4j.dom.DOMDocument}</code>
40    * builder.
41    * <p>
42    * This implementation allow the use of a same function accepting an XMLWriter, to either produce output into an
43    * <code>{@link java.io.OutputStream}</code> or to create a <code>{@link org.dom4j.dom.DOMDocument}</code>. Here a
44    * sample of the way to do so:
45    * </p>
46    * <code><pre>
47    * public void toXML(XMLWriter wr) throws IOException
48    * {
49    * Element docel = new DOMElement("html");
50    * wr.writeOpen(docel);
51    * Element hbel = new DOMElement("head");
52    * wr.writeOpen(hbel);
53    * Element el = new DOMElement("title");
54    * el.addText("My Title");
55    * wr.write(el);
56    * wr.writeClose(hbel);
57    * hbel = new DOMElement("body");
58    * wr.writeOpen(hbel);
59    * el = new DOMElement("p");
60    * el.addText("My Body");
61    * wr.write(el);
62    * }
63    *
64    * public void toXML(OutputStream out) throws IOException
65    * {
66    * XMLWriter wr = new XMLWriter(out, new OutputFormat(" ", true, "UTF-8"));
67    *
68    * Document doc = new DOMDocument();
69    * wr.writeDocumentStart(doc);
70    * toXML(wr);
71    * wr.writeDocumentEnd(doc);
72    * }
73    *
74    * public Document toXMLDocument()
75    * {
76    * Document doc = new DOMDocument();
77    * DOMXMLWriter wr = new DOMXMLWriter(doc, new OutputFormat(" ", true, "UTF-8"));
78    *
79    * try {
80    * toXML(wr);
81    * return doc;
82    * } catch (IOException e) {
83    * throw new RuntimeException(e);
84    * }
85    * }
86    * </pre></code>
87    * <p>
88    * <b>WARNING</b> - This implementation in INCOMPLETE and a minimal support. It should be improve as needed over time
89    * </p>
90    *
91    * @version $Id: 557e275d4f9debcb4ea8a29c180f02a886cf3048 $
92    */
 
93    public class DOMXMLWriter extends XMLWriter
94    {
95    /**
96    * The <code>{@link Document}</code> currently built by this writer.
97    */
98    private Document doc;
99   
100    /**
101    * The <code>{@link OutputFormat}</code> providing the encoding requested.
102    */
103    private OutputFormat format;
104   
105    /**
106    * Create a new <code>{@link DOMXMLWriter}</code> that will build into the provided document using the default
107    * encoding.
108    *
109    * @param doc <code>{@link Document}</code> that will be build by this writer
110    */
 
111  2 toggle public DOMXMLWriter(Document doc)
112    {
113  2 this(doc, DEFAULT_FORMAT);
114    }
115   
116    /**
117    * Create a new <code>{@link DOMXMLWriter}</code> that will build into the provided document using the encoding
118    * provided in the <code>{@link OutputFormat}</code>.
119    *
120    * @param doc <code>{@link Document}</code> that will be build by this writer
121    * @param format <code>{@link OutputFormat}</code> used to retrieve the proper encoding
122    */
 
123  3 toggle public DOMXMLWriter(Document doc, OutputFormat format)
124    {
125    // Set an output stream in order to not use System.out. If close() is called on this writer, this would
126    // close System.out which wouldn't be a good thing!
127    // Thus we use a dummy output stream since it's not used anyway...
128  3 try {
129  3 setOutputStream(NullOutputStream.NULL_OUTPUT_STREAM);
130    } catch (UnsupportedEncodingException e) {
131  0 throw new RuntimeException("Failed to create DOMXMLWriter instance", e);
132    }
133  3 this.format = format;
134  3 this.doc = doc;
135    }
136   
137    /**
138    * {@inheritDoc}
139    * <p>
140    * Add the element into the <code>{@link Document}</code> as a children of the element at the top of the stack of
141    * opened elements, putting the whole stream content as text in the content of the <code>{@link Element}</code>. The
142    * stream is converted to a String encoded in the current encoding.
143    * </p>
144    *
145    * @see com.xpn.xwiki.internal.xml.XMLWriter#write(org.dom4j.Element, java.io.InputStream)
146    */
 
147  0 toggle @Override
148    public void write(Element element, InputStream is) throws IOException
149    {
150  0 element.addText(IOUtils.toString(is, this.format.getEncoding()));
151  0 write(element);
152    }
153   
154    /**
155    * {@inheritDoc}
156    * <p>
157    * Add the element into the <code>{@link Document}</code> as a children of the element at the top of the stack of of
158    * the <code>{@link Element}</code>.
159    * </p>
160    *
161    * @see com.xpn.xwiki.internal.xml.XMLWriter#write(org.dom4j.Element, java.io.Reader)
162    */
 
163  0 toggle @Override
164    public void write(Element element, Reader rd) throws IOException
165    {
166  0 element.addText(IOUtils.toString(rd));
167  0 write(element);
168    }
169   
170    /**
171    * {@inheritDoc}
172    * <p>
173    * Add the element into the <code>{@link Document}</code> as a children of the element at the top of the stack of
174    * opened elements, putting the whole stream content as Base64 text in the content of the
175    * <code>{@link Element}</code>.
176    * </p>
177    *
178    * @see com.xpn.xwiki.internal.xml.XMLWriter#writeBase64(org.dom4j.Element, java.io.InputStream)
179    */
 
180  0 toggle @Override
181    public void writeBase64(Element element, InputStream is) throws IOException
182    {
183  0 ByteArrayOutputStream baos = new ByteArrayOutputStream();
184  0 Base64OutputStream out = new Base64OutputStream(baos, true, 0, null);
185  0 IOUtils.copy(is, out);
186  0 out.close();
187  0 element.addText(baos.toString(this.format.getEncoding()));
188  0 write(element);
189    }
190   
191    /**
192    * {@inheritDoc}
193    * <p>
194    * Cleanup the stack of opened elements.
195    * </p>
196    *
197    * @see com.xpn.xwiki.internal.xml.XMLWriter#writeDocumentEnd(org.dom4j.Document)
198    */
 
199  0 toggle @Override
200    public void writeDocumentEnd(Document doc) throws IOException
201    {
202  0 if (!this.parent.isEmpty()) {
203  0 writeClose(this.parent.firstElement());
204    }
205    }
206   
207    /**
208    * {@inheritDoc}
209    * <p>
210    * Does nothing, avoid default action.
211    * </p>
212    *
213    * @see com.xpn.xwiki.internal.xml.XMLWriter#writeDocumentStart(org.dom4j.Document)
214    */
 
215  0 toggle @Override
216    public void writeDocumentStart(Document doc) throws IOException
217    {
218    }
219   
220    /**
221    * {@inheritDoc}
222    * <p>
223    * Add the element into the <code>{@link Document}</code> as a children of the element at the top of the stack of
224    * opened elements.
225    * </p>
226    *
227    * @see org.dom4j.io.XMLWriter#write(org.dom4j.Element)
228    */
 
229  4 toggle @Override
230    public void write(Element element) throws IOException
231    {
232  4 if (this.parent.isEmpty()) {
233  3 this.doc.setRootElement((Element) element.clone());
234    } else {
235  1 this.parent.peek().add((Element) element.clone());
236    }
237    }
238   
239    /**
240    * {@inheritDoc}
241    * <p>
242    * Cleanup the stack of opened elements up to the given element.
243    * </p>
244    *
245    * @see com.xpn.xwiki.internal.xml.XMLWriter#writeClose(org.dom4j.Element)
246    */
 
247  1 toggle @Override
248    public void writeClose(Element element) throws IOException
249    {
250  1 try {
251  1 while (this.parent.peek() != element) {
252  0 this.parent.pop();
253    }
254  1 this.parent.pop();
255    } catch (EmptyStackException e) {
256  0 throw new IOException("FATAL: Closing a element that have never been opened");
257    }
258    }
259   
260    /**
261    * {@inheritDoc}
262    * <p>
263    * Add the element into the <code>{@link Document}</code> as a children of the element at the top of the stack of
264    * opened elements. Add this element at the top of the stack of opened elements.
265    * </p>
266    *
267    * @see com.xpn.xwiki.internal.xml.XMLWriter#writeOpen(org.dom4j.Element)
268    */
 
269  1 toggle @Override
270    public void writeOpen(Element element) throws IOException
271    {
272  1 if (this.parent.isEmpty()) {
273  1 this.doc.setRootElement(element);
274    } else {
275  0 this.parent.add(element);
276    }
277   
278  1 this.parent.push(element);
279    }
280   
 
281  0 toggle @Override
282    public void startCDATA() throws SAXException
283    {
284  0 throw new SAXUnsupportedException();
285    }
286   
 
287  0 toggle @Override
288    public void startElement(String namespaceURI, String localName, String qName, Attributes attributes)
289    throws SAXException
290    {
291  0 throw new SAXUnsupportedException();
292    }
293   
 
294  0 toggle @Override
295    public void startEntity(String name) throws SAXException
296    {
297  0 throw new SAXUnsupportedException();
298    }
299   
 
300  0 toggle @Override
301    public void endCDATA() throws SAXException
302    {
303  0 throw new SAXUnsupportedException();
304    }
305   
 
306  0 toggle @Override
307    public void endElement(String namespaceURI, String localName, String qName) throws SAXException
308    {
309  0 throw new SAXUnsupportedException();
310    }
311   
 
312  0 toggle @Override
313    public void endEntity(String name) throws SAXException
314    {
315  0 throw new SAXUnsupportedException();
316    }
317   
318    /**
319    * Thrown for SAX api methods since we don't support them.
320    */
 
321    public class SAXUnsupportedException extends RuntimeException
322    {
323    /**
324    * Constructs a <code>SAXUnsupportedException</code>.
325    */
 
326  0 toggle public SAXUnsupportedException()
327    {
328  0 super("SAX api is not supported");
329    }
330    }
331    }