bes Updated for version 3.20.13
CmrContainer.cc
1// CmrContainer.cc
2
3// -*- mode: c++; c-basic-offset:4 -*-
4
5// This file is part of cnr_module, A C++ module that can be loaded in to
6// the OPeNDAP Back-End Server (BES) and is able to handle remote requests.
7
8// Copyright (c) 2018 OPeNDAP, Inc.
9// Author: Nathan Potter <ndp@opendap.org>
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// Authors:
28// ndp Nathan Potter <ndp@opendap.org>
29
30#include <BESSyntaxUserError.h>
31#include <BESInternalError.h>
32#include <BESNotFoundError.h>
33#include <BESDebug.h>
34#include <BESUtil.h>
35#include <TheBESKeys.h>
36#include <AllowedHosts.h>
37#include "RemoteResource.h"
38
39#include "CmrContainer.h"
40#include "CmrNames.h"
41#include "CmrApi.h"
42
43using namespace std;
44using namespace bes;
45
46#define prolog std::string("CmrContainer::").append(__func__).append("() - ")
47
48namespace cmr {
49
60CmrContainer::CmrContainer(const string &sym_name,
61 const string &real_name, const string &type) :
62 BESContainer(sym_name, real_name, type), d_remoteResource(0) {
63
64 BESDEBUG(MODULE, prolog << "BEGIN sym_name: " << sym_name
65 << " real_name: " << real_name << " type: " << type << endl);
66
67
68 string path = BESUtil::normalize_path(real_name, true, false);
69 vector<string> path_elements = BESUtil::split(path);
70 BESDEBUG(MODULE, prolog << "path: '" << path << "' path_elements.size(): " << path_elements.size() << endl);
71
72
74
75 if (type == "") {
76 // @TODO FIX Dynamically determine the type from the Granule information (type-match to name, mime-type, etc)
77 this->set_container_type("nc");
78 }
79
80
81
82 /*
83
84 if (type.empty())
85 set_container_type("cmr");
86
87 BESUtil::url url_parts;
88 BESUtil::url_explode(real_name, url_parts);
89 url_parts.uname = "";
90 url_parts.psswd = "";
91 string use_real_name = BESUtil::url_create(url_parts);
92
93 if (!AllowedHosts::theHosts()->is_allowed(use_real_name)) {
94 string err = (string) "The specified URL " + real_name
95 + " does not match any of the accessible services in"
96 + " the allowed hosts list.";
97 throw BESSyntaxUserError(err, __FILE__, __LINE__);
98 }
99
100 // Because we know the name is really a URL, then we know the "relative_name" is meaningless
101 // So we set it to be the same as "name"
102 set_relative_name(real_name);
103 */
104
105 BESDEBUG( MODULE, prolog << "END" << endl);
106
107}
108
112CmrContainer::CmrContainer(const CmrContainer &copy_from) :
113 BESContainer(copy_from), d_remoteResource(copy_from.d_remoteResource) {
114 // we can not make a copy of this container once the request has
115 // been made
116 if (d_remoteResource) {
117 string err = (string) "The Container has already been accessed, "
118 + "can not create a copy of this container.";
119 throw BESInternalError(err, __FILE__, __LINE__);
120 }
121}
122
123void CmrContainer::_duplicate(CmrContainer &copy_to) {
124 if (copy_to.d_remoteResource) {
125 string err = (string) "The Container has already been accessed, "
126 + "can not duplicate this resource.";
127 throw BESInternalError(err, __FILE__, __LINE__);
128 }
129 copy_to.d_remoteResource = d_remoteResource;
131}
132
135 CmrContainer *container = new CmrContainer;
136 _duplicate(*container);
137 return container;
138}
139
140CmrContainer::~CmrContainer() {
141 if (d_remoteResource) {
142 release();
143 }
144}
145
152
153 BESDEBUG( MODULE, prolog << "BEGIN" << endl);
154
155 // Since this the CMR thang we know that the real_name is a path of facets and such.
156 string path = get_real_name();
157 BESDEBUG( MODULE, prolog << "path: " << path << endl);
158
159 Granule *granule = getTemporalFacetGranule(path);
160 if (!granule) {
161 throw BESNotFoundError("Failed locate a granule associated with the path " + path, __FILE__, __LINE__);
162 }
163 string url = granule->getDataAccessUrl();
164 delete granule;
165 granule = 0;
166
167 string type = get_container_type();
168 if (type == MODULE)
169 type = "";
170
171 if(!d_remoteResource) {
172 BESDEBUG( MODULE, prolog << "Building new RemoteResource." << endl );
173 shared_ptr<http::url> target_url(new http::url(url));
174 d_remoteResource = new http::RemoteResource(target_url);
175 d_remoteResource->retrieveResource();
176 }
177 BESDEBUG( MODULE, prolog << "Located remote resource." << endl );
178
179
180 string cachedResource = d_remoteResource->getCacheFileName();
181 BESDEBUG( MODULE, prolog << "Using local cache file: " << cachedResource << endl );
182
183 type = d_remoteResource->getType();
184 set_container_type(type);
185 BESDEBUG( MODULE, prolog << "Type: " << type << endl );
186
187
188 BESDEBUG( MODULE, prolog << "Done accessing " << get_real_name() << " returning cached file " << cachedResource << endl);
189 BESDEBUG( MODULE, prolog << "Done accessing " << *this << endl);
190 BESDEBUG( MODULE, prolog << "END" << endl);
191
192 return cachedResource; // this should return the file name from the CmrCache
193}
194
195
196
204 BESDEBUG( MODULE, prolog << "BEGIN" << endl);
205 if (d_remoteResource) {
206 BESDEBUG( MODULE, prolog << "Releasing RemoteResource" << endl);
207 delete d_remoteResource;
208 d_remoteResource = 0;
209 }
210 BESDEBUG( MODULE, prolog << "END" << endl);
211 return true;
212}
213
221void CmrContainer::dump(ostream &strm) const {
222 strm << BESIndent::LMarg << prolog << "(" << (void *) this
223 << ")" << endl;
224 BESIndent::Indent();
225 BESContainer::dump(strm);
226 if (d_remoteResource) {
227 strm << BESIndent::LMarg << "RemoteResource.getCacheFileName(): " << d_remoteResource->getCacheFileName()
228 << endl;
229 strm << BESIndent::LMarg << "response headers: ";
230
231 vector<string> *hdrs = d_remoteResource->getResponseHeaders();
232 if (hdrs) {
233 strm << endl;
234 BESIndent::Indent();
235 vector<string>::const_iterator i = hdrs->begin();
236 vector<string>::const_iterator e = hdrs->end();
237 for (; i != e; i++) {
238 string hdr_line = (*i);
239 strm << BESIndent::LMarg << hdr_line << endl;
240 }
241 BESIndent::UnIndent();
242 } else {
243 strm << "none" << endl;
244 }
245 } else {
246 strm << BESIndent::LMarg << "response not yet obtained" << endl;
247 }
248 BESIndent::UnIndent();
249}
250
251 Granule * CmrContainer::getTemporalFacetGranule(const std::string granule_path)
252 {
253
254 BESDEBUG(MODULE, prolog << "BEGIN (granule_path: '" << granule_path << ")" << endl);
255
256 string collection;
257 string facet = "temporal";
258 string year = "-";
259 string month = "-";
260 string day = "-";
261 string granule_id = "-";
262
263 string path = BESUtil::normalize_path(granule_path,false, false);
264 vector<string> path_elements = BESUtil::split(path);
265 BESDEBUG(MODULE, prolog << "path: '" << path << "' path_elements.size(): " << path_elements.size() << endl);
266
267 switch(path_elements.size()){
268 case 6:
269 {
270 collection = path_elements[0];
271 BESDEBUG(MODULE, prolog << "collection: '" << collection << endl);
272 facet = path_elements[1];
273 BESDEBUG(MODULE, prolog << "facet: '" << facet << endl);
274 year = path_elements[2];
275 BESDEBUG(MODULE, prolog << "year: '" << year << endl);
276 month = path_elements[3];
277 BESDEBUG(MODULE, prolog << "month: '" << month << endl);
278 day = path_elements[4];
279 BESDEBUG(MODULE, prolog << "day: '" << day << endl);
280 granule_id = path_elements[5];
281 BESDEBUG(MODULE, prolog << "granule_id: '" << granule_id << endl);
282 }
283 break;
284 default:
285 {
286 throw BESNotFoundError("Can't find it man...",__FILE__,__LINE__);
287 }
288 break;
289 }
290 CmrApi cmrApi;
291
292 return cmrApi.get_granule( collection, year, month, day, granule_id);
293 }
294
295} // namespace cmr
A container is something that holds data. E.G., a netcdf file or a database entry.
Definition: BESContainer.h:65
void set_container_type(const std::string &type)
set the type of data that this container represents, such as cedar or netcdf.
Definition: BESContainer.h:161
virtual void dump(std::ostream &strm) const
dumps information about this object
Definition: BESContainer.cc:73
std::string get_container_type() const
retrieve the type of data this container holds, such as cedar or netcdf.
Definition: BESContainer.h:232
void set_relative_name(const std::string &relative)
Set the relative name of the object in this container.
Definition: BESContainer.h:152
void _duplicate(BESContainer &copy_to)
duplicate this instance into the passed container
Definition: BESContainer.cc:54
std::string get_real_name() const
retrieve the real name for this container, such as a file name.
Definition: BESContainer.h:180
exception thrown if internal error encountered
error thrown if the resource requested cannot be found
static std::vector< std::string > split(const std::string &s, char delim='/', bool skip_empty=true)
Splits the string s into the return vector of tokens using the delimiter delim and skipping empty val...
Definition: BESUtil.cc:1065
static std::string normalize_path(const std::string &path, bool leading_separator, bool trailing_separator, std::string separator="/")
Removes duplicate separators and provides leading and trailing separators as directed.
Definition: BESUtil.cc:946
Container representing a remote request.
Definition: CmrContainer.h:53
virtual bool release()
release the resources
virtual void dump(std::ostream &strm) const
dumps information about this object
virtual BESContainer * ptr_duplicate()
pure abstract method to duplicate this instances of BESContainer
virtual std::string access()
access the remote target response by making the remote request
std::string getCacheFileName()
std::vector< std::string > * getResponseHeaders()
std::string getType()