bes Updated for version 3.21.1
The Backend Server (BES) is the lower two tiers of the Hyrax data server
BESXMLWriter.cc
1/*
2 * BESXMLWriter.cpp
3 *
4 * Created on: Jul 28, 2010
5 * Author: jimg
6 */
7
8// Copyright (c) 2013 OPeNDAP, Inc. Author: James Gallagher
9// <jgallagher@opendap.org>, Patrick West <pwest@opendap.org>
10// Nathan Potter <npotter@opendap.org>
11//
12// modify it under the terms of the GNU Lesser General Public License
13// as published by the Free Software Foundation; either version 2.1 of
14// the License, or (at your option) any later version.
15//
16// This library is distributed in the hope that it will be useful, but
17// WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19// Lesser General Public License for more details.
20//
21// License along with this library; if not, write to the Free Software
22// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23// 02110-1301 U\ SA
24//
25// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI.
26// 02874-0112.
27
28#include "BESXMLWriter.h"
29
30#include <libxml/encoding.h>
31#include <libxml/xmlwriter.h>
32
33#include <BESInternalFatalError.h>
34
35static const char *ENCODING = "ISO-8859-1";
36// Hack
37static const char *HAI_NS = "https://xml.opendap.org/ns/bes/admin/1.0#";
38constexpr int XML_BUF_SIZE = 2000000;
39
40BESXMLWriter::BESXMLWriter() // : d_ns_uri(HAI_NS)
41{
42 LIBXML_TEST_VERSION;
43
44 /* Create a new XML buffer, to which the XML document will be
45 * written */
46 try {
47 if (!(d_doc_buf = xmlBufferCreateSize(XML_BUF_SIZE)))
48 throw BESInternalFatalError("Error allocating the xml buffer", __FILE__, __LINE__);
49
50 xmlBufferSetAllocationScheme(d_doc_buf, XML_BUFFER_ALLOC_DOUBLEIT);
51
52 /* Create a new XmlWriter for memory, with no compression.
53 * Remark: there is no compression for this kind of xmlTextWriter */
54 if (!(d_writer = xmlNewTextWriterMemory(d_doc_buf, 0)))
55 throw BESInternalFatalError("Error allocating memory for xml writer", __FILE__, __LINE__);
56
57 if (xmlTextWriterSetIndent(d_writer, 4) < 0)
58 throw BESInternalFatalError("Error starting indentation for response document ", __FILE__, __LINE__);
59
60 if (xmlTextWriterSetIndentString(d_writer, (const xmlChar*) " ") < 0)
61 throw BESInternalFatalError("Error setting indentation for response document ", __FILE__, __LINE__);
62
63 d_started = true;
64 d_ended = false;
65
66 /* Start the document with the xml default for the version,
67 * encoding ISO 8859-1 and the default for the standalone
68 * declaration. MY_ENCODING defined at top of this file*/
69 if (xmlTextWriterStartDocument(d_writer, NULL, ENCODING, NULL) < 0)
70 throw BESInternalFatalError("Error starting xml response document", __FILE__, __LINE__);
71
72 /* Start an element named "Dataset". Since this is the first element,
73 * this will be the root element of the document */
74 if (xmlTextWriterStartElementNS(d_writer, (const xmlChar*) "hai", (const xmlChar*) "BesAdminCmd", (const xmlChar*) HAI_NS) < 0)
75 throw BESInternalFatalError("Error starting the response element for response ", __FILE__, __LINE__);
76 }
77 catch (BESInternalFatalError &e) {
78 m_cleanup();
79 throw;
80 }
81}
82
83BESXMLWriter::~BESXMLWriter()
84{
85 m_cleanup();
86}
87
88void BESXMLWriter::m_cleanup()
89{
90 // make sure the buffer and writer are all cleaned up
91 if (d_writer) {
92 xmlFreeTextWriter(d_writer);
93 d_writer = nullptr;
94 }
95 if (d_doc_buf) {
96 xmlBufferFree(d_doc_buf);
97 d_doc_buf = nullptr;
98 }
99
100 d_started = false;
101 d_ended = false;
102}
103
104const char *BESXMLWriter::get_doc()
105{
106 if (d_writer && d_started) {
107 // this should end the response element
108 if (xmlTextWriterEndElement(d_writer) < 0)
109 throw BESInternalFatalError("Error ending Dataset element.", __FILE__, __LINE__);
110
111 if (xmlTextWriterEndDocument(d_writer) < 0)
112 throw BESInternalFatalError("Error ending the document", __FILE__, __LINE__);
113
114 d_ended = true;
115
116 // must call this before getting the buffer content. Odd, but appears to be true.
117 // jhrg
118 xmlFreeTextWriter(d_writer);
119 d_writer = nullptr;
120 }
121
122 // get the xml document as a string and return
123 if (!d_doc_buf->content)
124 throw BESInternalFatalError("Error retrieving response document as string", __FILE__, __LINE__);
125
126 return (const char *) d_doc_buf->content;
127}