|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// This file is part of libdap, A C++ implementation of the OPeNDAP Data
|
|
Packit |
a4aae4 |
// Access Protocol.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Copyright (c) 2010 OPeNDAP, Inc.
|
|
Packit |
a4aae4 |
// Author: James Gallagher <jgallagher@opendap.org>
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// This library is free software; you can redistribute it and/or
|
|
Packit |
a4aae4 |
// modify it under the terms of the GNU Lesser General Public
|
|
Packit |
a4aae4 |
// License as published by the Free Software Foundation; either
|
|
Packit |
a4aae4 |
// version 2.1 of the License, or (at your option) any later version.
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// This library is distributed in the hope that it will be useful,
|
|
Packit |
a4aae4 |
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
a4aae4 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
a4aae4 |
// Lesser General Public License for more details.
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// You should have received a copy of the GNU Lesser General Public
|
|
Packit |
a4aae4 |
// License along with this library; if not, write to the Free Software
|
|
Packit |
a4aae4 |
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/*
|
|
Packit |
a4aae4 |
* XMLWriter.cpp
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* Created on: Jul 28, 2010
|
|
Packit |
a4aae4 |
* Author: jimg
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "config.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include <libxml/encoding.h>
|
|
Packit |
a4aae4 |
#include <libxml/xmlwriter.h>
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "XMLWriter.h"
|
|
Packit |
a4aae4 |
#include "InternalErr.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// TODO - Bite the bullet and make the encoding UTF-8 as required by dap4. This will break a lot of tests but the baselines could be amended using a bash script and sed.
|
|
Packit |
a4aae4 |
const char *ENCODING = "ISO-8859-1";
|
|
Packit |
a4aae4 |
const int XML_BUF_SIZE = 2000000;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
using namespace libdap;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
XMLWriter::XMLWriter(const string &pad) {
|
|
Packit |
a4aae4 |
LIBXML_TEST_VERSION;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/* Create a new XML buffer, to which the XML document will be
|
|
Packit |
a4aae4 |
* written */
|
|
Packit |
a4aae4 |
try {
|
|
Packit |
a4aae4 |
if (!(d_doc_buf = xmlBufferCreateSize(XML_BUF_SIZE)))
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Error allocating the xml buffer");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
xmlBufferSetAllocationScheme(d_doc_buf, XML_BUFFER_ALLOC_DOUBLEIT);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/* Create a new XmlWriter for memory, with no compression.
|
|
Packit |
a4aae4 |
* Remark: there is no compression for this kind of xmlTextWriter */
|
|
Packit |
a4aae4 |
if (!(d_writer = xmlNewTextWriterMemory(d_doc_buf, 0)))
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Error allocating memory for xml writer");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (xmlTextWriterSetIndent(d_writer, pad.length()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Error starting indentation for response document ");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (xmlTextWriterSetIndentString(d_writer, (const xmlChar*)pad.c_str()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Error setting indentation for response document ");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_started = true;
|
|
Packit |
a4aae4 |
d_ended = false;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/* Start the document with the xml default for the version,
|
|
Packit |
a4aae4 |
* encoding ISO 8859-1 and the default for the standalone
|
|
Packit |
a4aae4 |
* declaration. MY_ENCODING defined at top of this file*/
|
|
Packit |
a4aae4 |
if (xmlTextWriterStartDocument(d_writer, NULL, ENCODING, NULL) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Error starting xml response document");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
catch (InternalErr &e) {
|
|
Packit |
a4aae4 |
m_cleanup();
|
|
Packit |
a4aae4 |
throw;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
XMLWriter::~XMLWriter() {
|
|
Packit |
a4aae4 |
m_cleanup();
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void XMLWriter::m_cleanup() {
|
|
Packit |
a4aae4 |
// make sure the buffer and writer are all cleaned up
|
|
Packit |
a4aae4 |
if (d_writer) {
|
|
Packit |
a4aae4 |
xmlFreeTextWriter(d_writer); // This frees both d_writer and d_doc_buf
|
|
Packit |
a4aae4 |
d_writer = 0;
|
|
Packit |
a4aae4 |
// d_doc_buf = 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// We could be here because of an exception and d_writer might be zero
|
|
Packit |
a4aae4 |
if (d_doc_buf) {
|
|
Packit |
a4aae4 |
xmlBufferFree(d_doc_buf);
|
|
Packit |
a4aae4 |
d_doc_buf = 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_started = false;
|
|
Packit |
a4aae4 |
d_ended = false;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
const char *XMLWriter::get_doc() {
|
|
Packit |
a4aae4 |
if (d_writer && d_started) {
|
|
Packit |
a4aae4 |
if (xmlTextWriterEndDocument(d_writer) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Error ending the document");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_ended = true;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// must call this before getting the buffer content. Odd, but appears to be true.
|
|
Packit |
a4aae4 |
// jhrg
|
|
Packit |
a4aae4 |
xmlFreeTextWriter(d_writer);
|
|
Packit |
a4aae4 |
d_writer = 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (!d_doc_buf->content)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Error retrieving response document as string");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return (const char *)d_doc_buf->content;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
unsigned int XMLWriter::get_doc_size() {
|
|
Packit |
a4aae4 |
if (d_writer && d_started) {
|
|
Packit |
a4aae4 |
if (xmlTextWriterEndDocument(d_writer) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Error ending the document");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_ended = true;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// must call this before getting the buffer content. Odd, but appears to be true.
|
|
Packit |
a4aae4 |
// jhrg
|
|
Packit |
a4aae4 |
xmlFreeTextWriter(d_writer);
|
|
Packit |
a4aae4 |
d_writer = 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (!d_doc_buf->content)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Error retrieving response document as string");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// how much of the buffer is in use?
|
|
Packit |
a4aae4 |
return d_doc_buf->use;
|
|
Packit |
a4aae4 |
}
|