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