38#include <libdap/DataDDS.h>
39#include <libdap/BaseType.h>
40#include <libdap/escaping.h>
44#include "GeoTiffTransmitter.h"
45#include "FONgTransform.h"
48#include <BESInternalError.h>
49#include <BESDapError.h>
50#include <BESContextManager.h>
51#include <BESDataDDSResponse.h>
52#include <BESDapNames.h>
53#include <BESDataNames.h>
56#include <DapFunctionUtils.h>
58#include <TheBESKeys.h>
60#define FONG_TEMP_DIR "/tmp"
61#define FONG_GCS "WGS84"
63string GeoTiffTransmitter::temp_dir;
64string GeoTiffTransmitter::default_gcs;
87 if (GeoTiffTransmitter::temp_dir.empty()) {
90 string key =
"FONg.Tempdir";
92 if (!found || GeoTiffTransmitter::temp_dir.empty()) {
93 GeoTiffTransmitter::temp_dir = FONG_TEMP_DIR;
95 string::size_type len = GeoTiffTransmitter::temp_dir.length();
96 if (GeoTiffTransmitter::temp_dir[len - 1] ==
'/') {
97 GeoTiffTransmitter::temp_dir = GeoTiffTransmitter::temp_dir.substr(0, len - 1);
101 if (GeoTiffTransmitter::default_gcs.empty()) {
104 string key =
"FONg.Default_GCS";
106 if (!found || GeoTiffTransmitter::default_gcs.empty()) {
107 GeoTiffTransmitter::default_gcs = FONG_GCS;
133 DDS *dds = bdds->get_dds();
135 throw BESInternalError(
"No DataDDS has been created for transmit", __FILE__, __LINE__);
137 ostream &strm = dhi.get_output_stream();
139 throw BESInternalError(
"Output stream is not set, cannot return as", __FILE__, __LINE__);
141 BESDEBUG(
"fong2",
"GeoTiffTransmitter::send_data - parsing the constraint" << endl);
144 string ce = www2id(dhi.
data[POST_CONSTRAINT],
"%",
"%20%26");
146 bdds->get_ce().parse_constraint(ce, *dds);
149 throw BESDapError(
"Failed to parse the constraint expression: " + e.get_error_message(),
false, e.get_error_code(), __FILE__, __LINE__);
152 throw BESInternalError(
"Failed to parse the constraint expression: Unknown exception caught", __FILE__, __LINE__);
156 BESDEBUG(
"fong2",
"GeoTiffTransmitter::send_data - reading data into DataDDS" << endl);
160 if (bdds->get_ce().function_clauses()) {
161 BESDEBUG(
"fong2",
"processing a functional constraint clause(s)." << endl);
162 DDS *tmp_dds = bdds->get_ce().eval_function_clauses(*dds);
176 promote_function_output_structures(dds);
182 for (DDS::Vars_iter i = dds->var_begin(); i != dds->var_end(); i++) {
183 if ((*i)->send_p()) {
184 (*i)->intern_data(bdds->get_ce(), *dds);
190 throw BESDapError(
"Failed to read data: " + e.get_error_message(),
false, e.get_error_code(), __FILE__, __LINE__);
196 throw BESInternalError(
"Failed to read data: Unknown exception caught", __FILE__, __LINE__);
200 bes::TempFile temp_file(GeoTiffTransmitter::temp_dir +
'/' +
"geotiffXXXXXX");
204 string temp_file_name = GeoTiffTransmitter::temp_dir +
'/' +
"geotiffXXXXXX";
205 vector<char> temp_file(temp_file_name.length() + 1);
206 string::size_type len = temp_file_name.copy(&temp_file[0], temp_file_name.length());
207 temp_file[len] =
'\0';
211 mode_t original_mode = umask(077);
214 int fd = mkstemp(&temp_file[0]);
215 umask(original_mode);
218 throw BESInternalError(
"Failed to open the temporary file: " + temp_file_name, __FILE__, __LINE__);
221 BESDEBUG(
"fong2",
"GeoTiffTransmitter::send_data - transforming into temporary file " << temp_file.
get_name() << endl);
233 BESDEBUG(
"fong2",
"GeoTiffTransmitter::send_data - transmitting temp file " << temp_file.
get_name() << endl );
235 GeoTiffTransmitter::return_temp_stream(temp_file.
get_name(), strm);
240 (void) unlink(&temp_file[0]);
242 throw BESDapError(
"Failed to transform data to GeoTiff: " + e.get_error_message(),
false, e.get_error_code(), __FILE__, __LINE__);
247 (void) unlink(&temp_file[0]);
254 (void) unlink(&temp_file[0]);
256 throw BESInternalError(
"Fileout GeoTiff, was not able to transform to geotiff, unknown error", __FILE__, __LINE__);
261 (void) unlink(&temp_file[0]);
264 BESDEBUG(
"fong2",
"GeoTiffTransmitter::send_data - done transmitting to geotiff" << endl);
276void GeoTiffTransmitter::return_temp_stream(
const string &filename, ostream &strm)
279 os.open(filename.c_str(), ios::binary | ios::in);
281 throw BESInternalError(
"Cannot connect to data source", __FILE__, __LINE__);
284 os.read(block,
sizeof block);
285 int nbytes = os.gcount();
288 throw BESInternalError(
"Internal server error, got zero count on stream buffer.", __FILE__, __LINE__);
294 string protocol = BESContextManager::TheManager()->
get_context(
"transmit_protocol", found);
295 if (protocol ==
"HTTP") {
296 strm <<
"HTTP/1.0 200 OK\n";
297 strm <<
"Content-type: application/octet-stream\n";
298 strm <<
"Content-Description: " <<
"BES dataset" <<
"\n";
299 strm <<
"Content-Disposition: filename=" << filename <<
".tif;\n\n";
303 strm.write(block, nbytes);
306 os.read(block,
sizeof block);
307 nbytes = os.gcount();
308 strm.write(block, nbytes);
virtual std::string get_context(const std::string &name, bool &found)
retrieve the value of the specified context from the BES
error object created from libdap error objects and can handle those errors
Represents an OPeNDAP DataDDS DAP2 data object within the BES.
void set_dds(libdap::DDS *ddsIn)
Structure storing information used by the BES to handle the request.
std::map< std::string, std::string > data
the map of string data that will be required for the current request.
Abstract exception class for the BES with basic string message.
exception thrown if internal error encountered
Abstract base class representing a specific set of information in response to a request to the BES.
static void conditional_timeout_cancel()
Checks if the timeout alarm should be canceled based on the value of the BES key BES....
GeoTiffTransmitter()
Construct the GeoTiffTransmitter, adding it with name geotiff to be able to transmit a data response.
static void send_data_as_geotiff(BESResponseObject *obj, BESDataHandlerInterface &dhi)
The static method registered to transmit OPeNDAP data objects as a netcdf file.
void get_value(const std::string &s, std::string &val, bool &found)
Retrieve the value of a given key, if set.
static TheBESKeys * TheKeys()
Get a new temporary file.
std::string get_name() const