libdap  Updated for version 3.17.0
XMLWriter.cc
00001 
00002 // This file is part of libdap, A C++ implementation of the OPeNDAP Data
00003 // Access Protocol.
00004 
00005 // Copyright (c) 2010 OPeNDAP, Inc.
00006 // Author: James Gallagher <jgallagher@opendap.org>
00007 //
00008 // This library is free software; you can redistribute it and/or
00009 // modify it under the terms of the GNU Lesser General Public
00010 // License as published by the Free Software Foundation; either
00011 // version 2.1 of the License, or (at your option) any later version.
00012 //
00013 // This library is distributed in the hope that it will be useful,
00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016 // Lesser General Public License for more details.
00017 //
00018 // You should have received a copy of the GNU Lesser General Public
00019 // License along with this library; if not, write to the Free Software
00020 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00021 //
00022 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
00023 
00024 /*
00025  * XMLWriter.cpp
00026  *
00027  *  Created on: Jul 28, 2010
00028  *      Author: jimg
00029  */
00030 
00031 #include "config.h"
00032 
00033 #include <libxml/encoding.h>
00034 #include <libxml/xmlwriter.h>
00035 
00036 #include "XMLWriter.h"
00037 #include "InternalErr.h"
00038 
00039 const char *ENCODING = "ISO-8859-1";
00040 const int XML_BUF_SIZE = 2000000;
00041 
00042 using namespace libdap;
00043 
00044 XMLWriter::XMLWriter(const string &pad) {
00045     LIBXML_TEST_VERSION;
00046 
00047     /* Create a new XML buffer, to which the XML document will be
00048      * written */
00049     try {
00050         if (!(d_doc_buf = xmlBufferCreateSize(XML_BUF_SIZE)))
00051             throw InternalErr(__FILE__, __LINE__, "Error allocating the xml buffer");
00052 
00053         xmlBufferSetAllocationScheme(d_doc_buf, XML_BUFFER_ALLOC_DOUBLEIT);
00054 
00055         /* Create a new XmlWriter for memory, with no compression.
00056          * Remark: there is no compression for this kind of xmlTextWriter */
00057         if (!(d_writer = xmlNewTextWriterMemory(d_doc_buf, 0)))
00058             throw InternalErr(__FILE__, __LINE__, "Error allocating memory for xml writer");
00059 
00060         if (xmlTextWriterSetIndent(d_writer, pad.length()) < 0)
00061             throw InternalErr(__FILE__, __LINE__, "Error starting indentation for response document ");
00062 
00063         if (xmlTextWriterSetIndentString(d_writer, (const xmlChar*)pad.c_str()) < 0)
00064             throw InternalErr(__FILE__, __LINE__, "Error setting indentation for response document ");
00065 
00066         d_started = true;
00067         d_ended = false;
00068 
00069         /* Start the document with the xml default for the version,
00070          * encoding ISO 8859-1 and the default for the standalone
00071          * declaration. MY_ENCODING defined at top of this file*/
00072         if (xmlTextWriterStartDocument(d_writer, NULL, ENCODING, NULL) < 0)
00073             throw InternalErr(__FILE__, __LINE__, "Error starting xml response document");
00074     }
00075     catch (InternalErr &e) {
00076         m_cleanup();
00077         throw;
00078     }
00079 
00080 }
00081 
00082 XMLWriter::~XMLWriter() {
00083     m_cleanup();
00084 }
00085 
00086 void XMLWriter::m_cleanup() {
00087     // make sure the buffer and writer are all cleaned up
00088     if (d_writer) {
00089         xmlFreeTextWriter(d_writer); // This frees both d_writer and d_doc_buf
00090         d_writer = 0;
00091         // d_doc_buf = 0;
00092     }
00093 
00094     // We could be here because of an exception and d_writer might be zero
00095     if (d_doc_buf) {
00096         xmlBufferFree(d_doc_buf);
00097         d_doc_buf = 0;
00098     }
00099 
00100     d_started = false;
00101     d_ended = false;
00102 }
00103 
00104 const char *XMLWriter::get_doc() {
00105     if (d_writer && d_started) {
00106         if (xmlTextWriterEndDocument(d_writer) < 0)
00107             throw InternalErr(__FILE__, __LINE__, "Error ending the document");
00108 
00109         d_ended = true;
00110 
00111         // must call this before getting the buffer content. Odd, but appears to be true.
00112         // jhrg
00113         xmlFreeTextWriter(d_writer);
00114         d_writer = 0;
00115     }
00116 
00117     if (!d_doc_buf->content)
00118         throw InternalErr(__FILE__, __LINE__, "Error retrieving response document as string");
00119 
00120     return (const char *)d_doc_buf->content;
00121 }
00122 
00123 unsigned int XMLWriter::get_doc_size() {
00124     if (d_writer && d_started) {
00125         if (xmlTextWriterEndDocument(d_writer) < 0)
00126             throw InternalErr(__FILE__, __LINE__, "Error ending the document");
00127 
00128         d_ended = true;
00129 
00130         // must call this before getting the buffer content. Odd, but appears to be true.
00131         // jhrg
00132         xmlFreeTextWriter(d_writer);
00133         d_writer = 0;
00134     }
00135 
00136     if (!d_doc_buf->content)
00137         throw InternalErr(__FILE__, __LINE__, "Error retrieving response document as string");
00138 
00139     // how much of the buffer is in use?
00140     return d_doc_buf->use;
00141 }