38#include <libdap/DataDDS.h>
39#include <libdap/BaseType.h>
40#include <libdap/escaping.h>
44#include "JPEG2000Transmitter.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 JPEG2000_TEMP_DIR "/tmp"
61#define JPEG2000_GCS "WGS84"
63string JPEG2000Transmitter::temp_dir;
64string JPEG2000Transmitter::default_gcs;
87 if (JPEG2000Transmitter::temp_dir.empty()) {
90 string key =
"JPEG2000.Tempdir";
92 if (!found || JPEG2000Transmitter::temp_dir.empty()) {
93 JPEG2000Transmitter::temp_dir = JPEG2000_TEMP_DIR;
95 string::size_type len = JPEG2000Transmitter::temp_dir.size();
96 if (JPEG2000Transmitter::temp_dir[len - 1] ==
'/') {
97 JPEG2000Transmitter::temp_dir = JPEG2000Transmitter::temp_dir.substr(0, len - 1);
101 if (JPEG2000Transmitter::default_gcs.empty()) {
104 string key =
"JPEG2000.Default_GCS";
106 if (!found || JPEG2000Transmitter::default_gcs.empty()) {
107 JPEG2000Transmitter::default_gcs = JPEG2000_GCS;
134 DDS *dds = bdds->get_dds();
136 throw BESInternalError(
"No DataDDS has been created for transmit", __FILE__, __LINE__);
138 ostream &strm = dhi.get_output_stream();
140 throw BESInternalError(
"Output stream is not set, cannot return as", __FILE__, __LINE__);
142 BESDEBUG(
"JPEG20002",
"JPEG2000Transmitter::send_data - parsing the constraint" << endl);
145 string ce = www2id(dhi.
data[POST_CONSTRAINT],
"%",
"%20%26");
147 bdds->get_ce().parse_constraint(ce, *dds);
150 throw BESDapError(
"Failed to parse the constraint expression: " + e.get_error_message(),
false, e.get_error_code(), __FILE__, __LINE__);
153 throw BESInternalError(
"Failed to parse the constraint expression: Unknown exception caught", __FILE__, __LINE__);
157 BESDEBUG(
"JPEG20002",
"JPEG2000Transmitter::send_data - reading data into DataDDS" << endl);
160 string temp_file_name = temp_file.
create(JPEG2000Transmitter::temp_dir,
"jp2000_");
164 string temp_file_name = JPEG2000Transmitter::temp_dir +
'/' +
"jp2XXXXXX";
166 string::size_type len = temp_file_name.copy(temp_file.data(), temp_file_name.size());
167 temp_file[len] =
'\0';
171 mode_t original_mode = umask(077);
174 int fd = mkstemp(temp_file.data());
175 umask(original_mode);
178 throw BESInternalError(
"Failed to open the temporary file: " + temp_file_name, __FILE__, __LINE__);
181 BESDEBUG(
"JPEG20002",
"JPEG2000Transmitter::send_data - transforming into temporary file " << temp_file_name << endl);
186 if (bdds->get_ce().function_clauses()) {
187 BESDEBUG(
"fong2",
"processing a functional constraint clause(s)." << endl);
188 DDS *tmp_dds = bdds->get_ce().eval_function_clauses(*dds);
202 promote_function_output_structures(dds);
208 for (DDS::Vars_iter i = dds->var_begin(); i != dds->var_end(); i++) {
209 if ((*i)->send_p()) {
210 (*i)->intern_data(bdds->get_ce(), *dds);
217 throw BESDapError(
"Failed to read data: " + e.get_error_message(),
false, e.get_error_code(), __FILE__, __LINE__);
223 throw BESInternalError(
"Failed to read data: Unknown exception caught", __FILE__, __LINE__);
236 BESDEBUG(
"JPEG20002",
"JPEG2000Transmitter::send_data - transmitting temp file " << temp_file_name << endl );
238 JPEG2000Transmitter::return_temp_stream(temp_file_name, strm);
243 (void) unlink(temp_file.data());
245 throw BESDapError(
"Failed to transform data to JPEG2000: " + e.get_error_message(),
false, e.get_error_code(), __FILE__, __LINE__);
250 (void) unlink(temp_file.data());
257 (void) unlink(temp_file.data());
259 throw BESInternalError(
"Fileout GeoTiff, was not able to transform to JPEG2000, unknown error", __FILE__, __LINE__);
264 (void) unlink(temp_file.data());
267 BESDEBUG(
"JPEG20002",
"JPEG2000Transmitter::send_data - done transmitting to jp2" << endl);
279void JPEG2000Transmitter::return_temp_stream(
const string &filename,
ostream &strm)
282 os.open(filename.c_str(), ios::binary | ios::in);
284 throw BESInternalError(
"Cannot connect to data source", __FILE__, __LINE__);
287 os.read(block,
sizeof block);
288 int nbytes = os.gcount();
291 throw BESInternalError(
"Internal server error, got zero count on stream buffer.", __FILE__, __LINE__);
295 string context =
"transmit_protocol";
296 string protocol = BESContextManager::TheManager()->
get_context(context, found);
297 if (protocol ==
"HTTP") {
298 strm <<
"HTTP/1.0 200 OK\n";
299 strm <<
"Content-type: application/octet-stream\n";
300 strm <<
"Content-Description: " <<
"BES dataset" <<
"\n";
301 strm <<
"Content-Disposition: filename=" << filename <<
".jp2;\n\n";
304 strm.write(block, nbytes);
307 os.read(block,
sizeof block);
308 nbytes = os.gcount();
309 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....
JPEG2000Transmitter()
Construct the JPEG2000Transmitter, adding it with name geotiff to be able to transmit a data response...
static void send_data_as_jp2(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()
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.