bes Updated for version 3.21.1
The Backend Server (BES) is the lower two tiers of the Hyrax data server
NCMLContainer.cc
1// NCMLContainer.cc
2
3// -*- mode: c++; c-basic-offset:4 -*-
4
5// This file is part of ncml_module, A C++ module that can be loaded in to
6// the OPeNDAP Back-End Server (BES) and is able to handle ncml requests.
7
8// Copyright (c) 2002,2003 OPeNDAP, Inc.
9// Author: Patrick West <pwest@ucar.edu>
10//
11// This library is free software; you can redistribute it and/or
12// modify it under the terms of the GNU Lesser General Public
13// License as published by the Free Software Foundation; either
14// version 2.1 of the License, or (at your option) any later version.
15//
16// This library is distributed in the hope that it will be useful,
17// but 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// You should have received a copy of the GNU Lesser General Public
22// License along with this library; if not, write to the Free Software
23// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24//
25// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
26
27// (c) COPYRIGHT URI/MIT 1994-1999
28// Please read the full copyright statement in the file COPYRIGHT_URI.
29//
30// Authors:
31// pcw Patrick West <pwest@ucar.edu>
32
33#include "config.h"
34
35#ifdef HAVE_UNISTD_H
36#include <unistd.h>
37#endif
38
39#include <fstream>
40#include <cerrno>
41#include <cstdlib>
42#include <cstring>
43
44#if 0
45using std::ofstream;
46using std::endl;
47using std::ios_base;
48#endif
49
50#include "NCMLContainer.h"
51#include "NCMLContainerStorage.h"
52
53#include <BESSyntaxUserError.h>
54#include <BESInternalError.h>
55#include <BESDebug.h>
56
57#include <libdap/util.h> // libdap; for open_temp_fstream()
58
59using namespace std;
60
74NCMLContainer::NCMLContainer(const string &sym_name, const string &xml_doc) :
75 BESContainer(sym_name, "", "ncml"), _xml_doc(xml_doc), _accessed(false)
76{
77}
78
79NCMLContainer::NCMLContainer(const NCMLContainer &copy_from) :
80 BESContainer(copy_from), _xml_doc(copy_from._xml_doc), _accessed(copy_from._accessed)
81{
82 // we can not make a copy of this container once the NCML document has
83 // been written to the temporary file
84 if (_accessed) {
85 string err = (string) "The Container has already been accessed, " + "can not create a copy of this container.";
86 throw BESInternalError(err, __FILE__, __LINE__);
87 }
88}
89
90void NCMLContainer::_duplicate(NCMLContainer &copy_to)
91{
92 if (copy_to._accessed) {
93 string err = (string) "The Container has already been accessed, " + "can not duplicate this resource.";
94 throw BESInternalError(err, __FILE__, __LINE__);
95 }
96 copy_to._xml_doc = _xml_doc;
97 copy_to._accessed = false;
99}
100
103{
104 NCMLContainer *container = new NCMLContainer;
105 _duplicate(*container);
106 return container;
107}
108
109NCMLContainer::~NCMLContainer()
110{
111 if (_accessed) {
112 release();
113 }
114}
115
122{
123 BESDEBUG("ncml", "accessing " << _xml_doc << endl);
124 if (!_accessed) {
125 // save the xml document to a temporary file, open it, unlink
126 // it. In release, close the file. This will remove the file if
127 // it is no longer open.
128#if 0
129 // Replaced with code that uses mkstemp() which lacks the security
130 // problems of mktemp(). jhrg 5/13/15
131 string tempfile_template = NCMLContainerStorage::NCML_TempDir + "/ncml_module_XXXXXX";
132 char *tempfile_c = mktemp((char *) tempfile_template.c_str());
133
134 string tempfile;
135 if (tempfile_c) {
136 tempfile = tempfile_c;
137 }
138 else {
139 string err = (string) "Unable to create temporary ncml document " + _tmp_file_name;
140 throw BESInternalError(err, __FILE__, __LINE__);
141 }
142
143 _tmp_file_name = NCMLContainerStorage::NCML_TempDir + "/" + tempfile + ".ncml";
144#endif
145 // FIXME Don't close the stream 'ostrm' and instead store it in a field of the
146 // object. see the class comment. jhrg 8/12/15
147
148 // FIXME! If we use this code, switch to the BESHandlerUtil.h/cc code that
149 // supports temp files. Or use the code in libdap that supports mkstemps() and
150 // does so in a way the avoids portability problems. THe libdap code (mkstemps)
151 // code supports temp files with extensions (not that big a deal, but it does).
152 // jhrg 8/25/17
153
154 ofstream ostrm;
155 string _tmp_file_name = libdap::open_temp_fstream(ostrm,
156 NCMLContainerStorage::NCML_TempDir + "/ncml_module_XXXXXX", ".ncml");
157
158 if (!ostrm) {
159 string err = (string) "Unable to write out the ncml document " + _tmp_file_name;
160 if (errno) {
161 char *str = strerror(errno);
162 if (str) err += (string) " " + str;
163 }
164 throw BESInternalError(err, __FILE__, __LINE__);
165 }
166
167 // write out <?xml version="1.0" encoding="UTF-8"?>
168 ostrm << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << endl;
169
170 // then write out the r_name as the ncml document (no validation)
171 ostrm << _xml_doc << endl;
172
173 ostrm.close();
174
175 _accessed = true;
176 }
177
178 return _tmp_file_name;
179}
180
188{
189 if (_accessed && !_tmp_file_name.empty()) {
190 unlink(_tmp_file_name.c_str());
191 _tmp_file_name = "";
192 }
193 _accessed = false;
194 return true;
195}
196
204void NCMLContainer::dump(ostream &strm) const
205{
206 strm << BESIndent::LMarg << "NCMLContainer::dump - (" << (void *) this << ")" << endl;
207 BESIndent::Indent();
208 if (_accessed) {
209 strm << BESIndent::LMarg << "temporary file: " << _tmp_file_name << endl;
210 }
211 else {
212 strm << BESIndent::LMarg << "temporary file: not open" << endl;
213 }
214 BESContainer::dump(strm);
215 BESIndent::UnIndent();
216}
217
A container is something that holds data. E.G., a netcdf file or a database entry.
void dump(std::ostream &strm) const override
dumps information about this object
void _duplicate(BESContainer &copy_to)
duplicate this instance into the passed container
exception thrown if internal error encountered
Container representing a NCML request.
virtual bool release()
release the NCML cached resources
virtual void dump(ostream &strm) const
dumps information about this object
virtual BESContainer * ptr_duplicate()
pure abstract method to duplicate this instances of BESContainer
virtual string access()
access the NCML target response by making the NCML request