bes  Updated for version 3.20.6
HttpdCatalogContainer.cc
1 // -*- mode: c++; c-basic-offset:4 -*-
2 //
3 // This file is part of cnr_module, A C++ module that can be loaded in to
4 // the OPeNDAP Back-End Server (BES) and is able to handle remote requests.
5 //
6 // Copyright (c) 2018 OPeNDAP, Inc.
7 // Author: Nathan Potter <ndp@opendap.org>
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2.1 of the License, or (at your option) any later version.
13 //
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 //
23 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
24 
25 #include <BESSyntaxUserError.h>
26 #include <BESInternalError.h>
27 #include <BESNotFoundError.h>
28 #include <BESDebug.h>
29 #include <BESUtil.h>
30 #include <TheBESKeys.h>
31 #include <WhiteList.h>
32 
33 #include "HttpdCatalogContainer.h"
34 #include "HttpdCatalogUtils.h"
35 #include "HttpdCatalogNames.h"
36 #include "HttpdCatalog.h"
37 #include "RemoteHttpResource.h"
38 
39 using namespace std;
40 using namespace bes;
41 
42 #define prolog std::string("HttpdCatalogContainer::").append(__func__).append("() - ")
43 
44 namespace httpd_catalog {
45 
56 HttpdCatalogContainer::HttpdCatalogContainer(const string &sym_name, const string &real_name, const string &type) :
57  BESContainer(sym_name, real_name, type), d_remoteResource(0)
58 {
59 
60  BESDEBUG(MODULE, prolog << "BEGIN sym_name: " << sym_name << " real_name: " << real_name << " type: " << type << endl);
61 
62  string path = real_name;
63  if (path.empty() || path[0] != '/') {
64  path = "/" + path;
65  }
66 
67 #if 0
68  // unused
69  vector<string> path_elements = BESUtil::split(path);
70  BESDEBUG(MODULE, prolog << "path: '" << path << "' path_elements.size(): " << path_elements.size() << endl);
71 #endif
72 
73 
74  set_relative_name(path);
75 
76  // The container type is set in the access() method when the remote resource is accessed using the
77  // MIME type information using mappings between handlers (e.g., 'h5') and MIME types like application/x-hdf5.
78  // However, bes/dispatchBESContainerStorageVolatile::add_container(BESContainer *) expects the field
79  // to be not empty, so I'll add a place holder value. jhrg 1/25/19
80  if (type == "")
81  this->set_container_type("place_holder");
82 
83  BESDEBUG(MODULE, prolog << "END" << endl);
84 }
85 
86 HttpdCatalogContainer::HttpdCatalogContainer(const HttpdCatalogContainer &copy_from) :
87  BESContainer(copy_from), d_remoteResource(0)
88 {
89  // we can not make a copy of this container once the request has
90  // been made
91  if (copy_from.d_remoteResource) {
92  throw BESInternalError("The Container has already been accessed, cannot create a copy of this container.", __FILE__, __LINE__);
93  }
94 }
95 
96 void HttpdCatalogContainer::_duplicate(HttpdCatalogContainer &copy_to)
97 {
98  if (copy_to.d_remoteResource) {
99  throw BESInternalError("The Container has already been accessed, cannot duplicate this resource.", __FILE__, __LINE__);
100  }
101  copy_to.d_remoteResource = d_remoteResource;
102  BESContainer::_duplicate(copy_to);
103 }
104 
105 BESContainer *
107 {
109  _duplicate(*container);
110  return container;
111 }
112 
113 HttpdCatalogContainer::~HttpdCatalogContainer()
114 {
115  if (d_remoteResource) {
116  release();
117  }
118 }
119 
126 {
127  BESDEBUG(MODULE, prolog << "BEGIN" << endl);
128 
129  string path = get_real_name();
130  BESDEBUG(MODULE, prolog << "path: " << path << endl);
131 
132  HttpdCatalog hc;
133  string access_url = hc.path_to_access_url(path);
134 
135  if (!d_remoteResource) {
136  BESDEBUG(MODULE, prolog << "Building new RemoteResource." << endl);
137  d_remoteResource = new RemoteHttpResource(access_url);
138  d_remoteResource->retrieveResource();
139  }
140 
141  BESDEBUG(MODULE, prolog << "Located remote resource." << endl);
142 
143  string cachedResource = d_remoteResource->getCacheFileName();
144  BESDEBUG(MODULE, prolog << "Using local cache file: " << cachedResource << endl);
145 
146  string type = d_remoteResource->getType();
147  set_container_type(type);
148 
149  BESDEBUG(MODULE, prolog << "Type: " << type << endl);
150 
151  BESDEBUG(MODULE, prolog << "Done accessing " << get_real_name() << " returning cached file " << cachedResource << endl);
152  BESDEBUG(MODULE, prolog << "Done accessing " << *this << endl);
153  BESDEBUG(MODULE, prolog << "END" << endl);
154 
155  return cachedResource; // this should return the file name from the CmrCache
156 }
157 
165 {
166  BESDEBUG(MODULE, prolog << "BEGIN" << endl);
167  if (d_remoteResource) {
168  BESDEBUG(MODULE, prolog << "Releasing RemoteResource" << endl);
169  delete d_remoteResource;
170  d_remoteResource = 0;
171  }
172  BESDEBUG(MODULE, prolog << "END" << endl);
173  return true;
174 }
175 
183 void HttpdCatalogContainer::dump(ostream &strm) const
184 {
185  strm << BESIndent::LMarg << prolog<<"(" << (void *) this
186  << ")" << endl;
187  BESIndent::Indent();
188  BESContainer::dump(strm);
189  if (d_remoteResource) {
190  strm << BESIndent::LMarg << "RemoteResource.getCacheFileName(): " <<d_remoteResource->getCacheFileName()
191  << endl;
192  strm << BESIndent::LMarg << "response headers: ";
193 
194  vector<string> hdrs;
195  d_remoteResource->getResponseHeaders(hdrs);
196  if (!hdrs.empty()) {
197  strm << endl;
198  BESIndent::Indent();
199  vector<string>::const_iterator i = hdrs.begin();
200  vector<string>::const_iterator e = hdrs.end();
201  for (; i != e; i++) {
202  string hdr_line = (*i);
203  strm << BESIndent::LMarg << hdr_line << endl;
204  }
205  BESIndent::UnIndent();
206  }
207  else {
208  strm << "none" << endl;
209  }
210  }
211  else {
212  strm << BESIndent::LMarg << "response not yet obtained" << endl;
213  }
214 
215  BESIndent::UnIndent();
216 }
217 
218 } // namespace http_catalog
httpd_catalog::HttpdCatalogContainer::release
virtual bool release()
release the resources
Definition: HttpdCatalogContainer.cc:164
httpd_catalog::RemoteHttpResource::getType
std::string getType()
Definition: httpd_catalog_module/RemoteHttpResource.h:105
httpd_catalog::RemoteHttpResource::getCacheFileName
std::string getCacheFileName()
Definition: httpd_catalog_module/RemoteHttpResource.h:114
httpd_catalog::HttpdCatalog::path_to_access_url
virtual std::string path_to_access_url(const std::string &path) const
Takes a path which begins with the name of an HttpdCatalog collection and returns the associated acce...
Definition: HttpdCatalog.cc:201
httpd_catalog::RemoteHttpResource::retrieveResource
void retrieveResource()
Definition: httpd_catalog_module/RemoteHttpResource.cc:139
httpd_catalog::RemoteHttpResource
Definition: httpd_catalog_module/RemoteHttpResource.h:44
httpd_catalog::HttpdCatalogContainer::ptr_duplicate
virtual BESContainer * ptr_duplicate()
pure abstract method to duplicate this instances of BESContainer
Definition: HttpdCatalogContainer.cc:106
httpd_catalog::HttpdCatalog
builds catalogs from a directory structure exposed by Apache httpd
Definition: HttpdCatalog.h:50
httpd_catalog::HttpdCatalogContainer::dump
virtual void dump(std::ostream &strm) const
dumps information about this object
Definition: HttpdCatalogContainer.cc:183
httpd_catalog::RemoteHttpResource::getResponseHeaders
void getResponseHeaders(std::vector< std::string > &hdrs)
Definition: httpd_catalog_module/RemoteHttpResource.h:127
BESInternalError
exception thrown if internal error encountered
Definition: BESInternalError.h:43
httpd_catalog::HttpdCatalogContainer
Container representing a remote request.
Definition: HttpdCatalogContainer.h:48
BESContainer
A container is something that holds data. E.G., a netcdf file or a database entry.
Definition: BESContainer.h:65
BESContainer::get_real_name
std::string get_real_name() const
retrieve the real name for this container, such as a file name.
Definition: BESContainer.h:180
BESUtil::split
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:1125
BESContainer::set_container_type
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
BESContainer::set_relative_name
void set_relative_name(const std::string &relative)
Set the relative name of the object in this container.
Definition: BESContainer.h:152
BESContainer::_duplicate
void _duplicate(BESContainer &copy_to)
duplicate this instance into the passed container
Definition: BESContainer.cc:54
httpd_catalog::HttpdCatalogContainer::access
virtual std::string access()
access the remote target response by making the remote request
Definition: HttpdCatalogContainer.cc:125
BESContainer::dump
virtual void dump(std::ostream &strm) const
dumps information about this object
Definition: BESContainer.cc:73