bes  Updated for version 3.20.8
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 <BESDebug.h>
28 #include <AllowedHosts.h>
29 #include "RemoteResource.h"
30 
31 #include "HttpdCatalogContainer.h"
32 #include "HttpdCatalog.h"
33 
34 using namespace std;
35 using namespace bes;
36 
37 #define prolog std::string("HttpdCatalogContainer::").append(__func__).append("() - ")
38 
39 namespace httpd_catalog {
40 
51 HttpdCatalogContainer::HttpdCatalogContainer(const string &sym_name, const string &real_name, const string &type) :
52  BESContainer(sym_name, real_name, type), d_remoteResource(0)
53 {
54 
55  BESDEBUG(MODULE, prolog << "BEGIN sym_name: " << sym_name << " real_name: " << real_name << " type: " << type << endl);
56 
57  string path = real_name;
58  if (path.empty() || path[0] != '/') {
59  path = "/" + path;
60  }
61 
62 #if 0
63  // unused
64  vector<string> path_elements = BESUtil::split(path);
65  BESDEBUG(MODULE, prolog << "path: '" << path << "' path_elements.size(): " << path_elements.size() << endl);
66 #endif
67 
68 
69  set_relative_name(path);
70 
71  // The container type is set in the access() method when the remote resource is accessed using the
72  // MIME type information using mappings between handlers (e.g., 'h5') and MIME types like application/x-hdf5.
73  // However, bes/dispatchBESContainerStorageVolatile::add_container(BESContainer *) expects the field
74  // to be not empty, so I'll add a place holder value. jhrg 1/25/19
75  if (type == "")
76  this->set_container_type("place_holder");
77 
78  BESDEBUG(MODULE, prolog << "END" << endl);
79 }
80 
81 HttpdCatalogContainer::HttpdCatalogContainer(const HttpdCatalogContainer &copy_from) :
82  BESContainer(copy_from), d_remoteResource(0)
83 {
84  // we can not make a copy of this container once the request has
85  // been made
86  if (copy_from.d_remoteResource) {
87  throw BESInternalError("The Container has already been accessed, cannot create a copy of this container.", __FILE__, __LINE__);
88  }
89 }
90 
91 void HttpdCatalogContainer::_duplicate(HttpdCatalogContainer &copy_to)
92 {
93  if (copy_to.d_remoteResource) {
94  throw BESInternalError("The Container has already been accessed, cannot duplicate this resource.", __FILE__, __LINE__);
95  }
96  copy_to.d_remoteResource = d_remoteResource;
97  BESContainer::_duplicate(copy_to);
98 }
99 
100 BESContainer *
102 {
104  _duplicate(*container);
105  return container;
106 }
107 
108 HttpdCatalogContainer::~HttpdCatalogContainer()
109 {
110  if (d_remoteResource) {
111  release();
112  }
113 }
114 
121 {
122  BESDEBUG(MODULE, prolog << "BEGIN" << endl);
123 
124  string path = get_real_name();
125  BESDEBUG(MODULE, prolog << "path: " << path << endl);
126 
127  HttpdCatalog hc;
128  string access_url = hc.path_to_access_url(path);
129 
130  if (!d_remoteResource) {
131  BESDEBUG(MODULE, prolog << "Building new RemoteResource." << endl);
132  d_remoteResource = new http::RemoteResource(access_url);
133  d_remoteResource->retrieveResource();
134  }
135 
136  BESDEBUG(MODULE, prolog << "Located remote resource." << endl);
137 
138  string cachedResource = d_remoteResource->getCacheFileName();
139  BESDEBUG(MODULE, prolog << "Using local cache file: " << cachedResource << endl);
140 
141  string type = d_remoteResource->getType();
142  set_container_type(type);
143 
144  BESDEBUG(MODULE, prolog << "Type: " << type << endl);
145 
146  BESDEBUG(MODULE, prolog << "Done accessing " << get_real_name() << " returning cached file " << cachedResource << endl);
147  BESDEBUG(MODULE, prolog << "Done accessing " << *this << endl);
148  BESDEBUG(MODULE, prolog << "END" << endl);
149 
150  return cachedResource; // this should return the file name from the CmrCache
151 }
152 
160 {
161  BESDEBUG(MODULE, prolog << "BEGIN" << endl);
162  if (d_remoteResource) {
163  BESDEBUG(MODULE, prolog << "Releasing RemoteResource" << endl);
164  delete d_remoteResource;
165  d_remoteResource = 0;
166  }
167  BESDEBUG(MODULE, prolog << "END" << endl);
168  return true;
169 }
170 
178 void HttpdCatalogContainer::dump(ostream &strm) const
179 {
180  strm << BESIndent::LMarg << prolog<<"(" << (void *) this
181  << ")" << endl;
182  BESIndent::Indent();
183  BESContainer::dump(strm);
184  if (d_remoteResource) {
185  strm << BESIndent::LMarg << "RemoteResource.getCacheFileName(): " << d_remoteResource->getCacheFileName()
186  << endl;
187  strm << BESIndent::LMarg << "response headers: ";
188 
189  vector<string> *hdrs = d_remoteResource->getResponseHeaders();
190  if (hdrs) {
191  strm << endl;
192  BESIndent::Indent();
193  vector<string>::const_iterator i = hdrs->begin();
194  vector<string>::const_iterator e = hdrs->end();
195  for (; i != e; i++) {
196  string hdr_line = (*i);
197  strm << BESIndent::LMarg << hdr_line << endl;
198  }
199  BESIndent::UnIndent();
200  }
201  else {
202  strm << "none" << endl;
203  }
204  }
205  else {
206  strm << BESIndent::LMarg << "response not yet obtained" << endl;
207  }
208 
209  BESIndent::UnIndent();
210 }
211 
212 } // namespace http_catalog
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
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
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
std::string getCacheFileName()
std::vector< std::string > * getResponseHeaders()
std::string getType()
Container representing a remote request.
virtual bool release()
release the resources
virtual std::string access()
access the remote target response by making the remote request
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
builds catalogs from a directory structure exposed by Apache httpd
Definition: HttpdCatalog.h:50
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...