38#include <libdap/DataDDS.h>
39#include <libdap/BaseType.h>
40#include <libdap/escaping.h>
42#include <dispatch/BESUtil.h>
43#include <dispatch/BESInternalError.h>
44#include <dispatch/BESContextManager.h>
45#include <dispatch/BESDataNames.h>
46#include <dispatch/BESDebug.h>
47#include <dispatch/RequestServiceTimer.h>
48#include <dispatch/TheBESKeys.h>
50#include <dap/BESDapError.h>
51#include <dap/BESDataDDSResponse.h>
52#include <dap/BESDapNames.h>
53#include <dap/DapFunctionUtils.h>
54#include <dap/TempFile.h>
56#include "GeoTiffTransmitter.h"
57#include "FONgTransform.h"
59#define FONG_TEMP_DIR "/tmp"
60#define FONG_GCS "WGS84"
62#define prolog string("GeoTiffTransmitter::").append(__func__).append("() - ")
67string GeoTiffTransmitter::temp_dir;
68string GeoTiffTransmitter::default_gcs;
91 if (GeoTiffTransmitter::temp_dir.empty()) {
94 string key =
"FONg.Tempdir";
96 if (!found || GeoTiffTransmitter::temp_dir.empty()) {
97 GeoTiffTransmitter::temp_dir = FONG_TEMP_DIR;
99 string::size_type len = GeoTiffTransmitter::temp_dir.size();
100 if (GeoTiffTransmitter::temp_dir[len - 1] ==
'/') {
101 GeoTiffTransmitter::temp_dir = GeoTiffTransmitter::temp_dir.substr(0, len - 1);
105 if (GeoTiffTransmitter::default_gcs.empty()) {
108 string key =
"FONg.Default_GCS";
110 if (!found || GeoTiffTransmitter::default_gcs.empty()) {
111 GeoTiffTransmitter::default_gcs = FONG_GCS;
137 DDS *dds = bdds->get_dds();
139 throw BESInternalError(
"No DataDDS has been created for transmit", __FILE__, __LINE__);
141 ostream &strm = dhi.get_output_stream();
143 throw BESInternalError(
"Output stream is not set, cannot return as", __FILE__, __LINE__);
145 BESDEBUG(MODULE,
"GeoTiffTransmitter::send_data - parsing the constraint" << endl);
148 string ce = www2id(dhi.
data[POST_CONSTRAINT],
"%",
"%20%26");
150 bdds->get_ce().parse_constraint(ce, *dds);
152 catch (
const Error &e) {
153 throw BESDapError(
"Failed to parse the constraint expression: " + e.get_error_message(),
false, e.get_error_code(), __FILE__, __LINE__);
156 throw BESInternalError(
"Failed to parse the constraint expression: Unknown exception caught", __FILE__, __LINE__);
160 BESDEBUG(MODULE,
"GeoTiffTransmitter::send_data - reading data into DataDDS" << endl);
164 if (bdds->get_ce().function_clauses()) {
165 BESDEBUG(MODULE,
"processing a functional constraint clause(s)." << endl);
166 DDS *tmp_dds = bdds->get_ce().eval_function_clauses(*dds);
180 promote_function_output_structures(dds);
186 for (DDS::Vars_iter i = dds->var_begin(); i != dds->var_end(); i++) {
187 if ((*i)->send_p()) {
188 (*i)->intern_data(bdds->get_ce(), *dds);
193 catch (
const Error &e) {
194 throw BESDapError(
"Failed to read data: " + e.get_error_message(),
false, e.get_error_code(), __FILE__, __LINE__);
200 throw BESInternalError(
"Failed to read data: Unknown exception caught", __FILE__, __LINE__);
205 string temp_file_name = temp_file.
create(GeoTiffTransmitter::temp_dir,
"geotiff_");
208 BESDEBUG(MODULE,
"GeoTiffTransmitter::send_data - transforming into temporary file " << temp_file_name << endl);
220 BESDEBUG(MODULE,
"GeoTiffTransmitter::send_data - transmitting temp file " << temp_file_name << endl );
222 GeoTiffTransmitter::return_temp_stream(temp_file_name, strm);
224 catch (
const Error &e) {
225 throw BESDapError(
"Failed to transform data to GeoTiff: " + e.get_error_message(),
false, e.get_error_code(), __FILE__, __LINE__);
231 throw BESInternalError(
"Fileout GeoTiff, was not able to transform to geotiff, unknown error", __FILE__, __LINE__);
234 BESDEBUG(MODULE,
"GeoTiffTransmitter::send_data - done transmitting to geotiff" << endl);
246void GeoTiffTransmitter::return_temp_stream(
const string &filename, ostream &strm)
249 os.open(filename.c_str(), ios::binary | ios::in);
251 throw BESInternalError(
"Cannot connect to data source", __FILE__, __LINE__);
254 os.read(block,
sizeof block);
255 int nbytes = os.gcount();
258 throw BESInternalError(
"Internal server error, got zero count on stream buffer.", __FILE__, __LINE__);
264 string protocol = BESContextManager::TheManager()->
get_context(
"transmit_protocol", found);
265 if (protocol ==
"HTTP") {
266 strm <<
"HTTP/1.0 200 OK\n";
267 strm <<
"Content-type: application/octet-stream\n";
268 strm <<
"Content-Description: " <<
"BES dataset" <<
"\n";
269 strm <<
"Content-Disposition: filename=" << filename <<
".tif;\n\n";
273 strm.write(block, nbytes);
276 os.read(block,
sizeof block);
277 nbytes = os.gcount();
278 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.
Base 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.
static RequestServiceTimer * TheTimer()
Return a pointer to a singleton timer instance. If an instance does not exist it will create and init...
void throw_if_timeout_expired(const std::string &message, const std::string &file, const int line)
Checks the RequestServiceTimer to determine if the time spent servicing the request at this point has...
void get_value(const std::string &s, std::string &val, bool &found)
Retrieve the value of a given key, if set.
static TheBESKeys * TheKeys()
Access to the singleton.
Get a new temporary file.
std::string create(const std::string &dir_name="/tmp/hyrax_tmp", const std::string &path_template="opendap")
Create a new temporary file.