SSPCPP-616 - clean up concatenated string literals
[shibboleth/cpp-sp.git] / shibsp / handler / impl / DiscoveryFeed.cpp
index fbad37a..f0f3514 100644 (file)
@@ -1,17 +1,21 @@
-/*
- *  Copyright 2010 Internet2
+/**
+ * Licensed to the University Corporation for Advanced Internet
+ * Development, Inc. (UCAID) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
  *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * UCAID licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the
+ * License at
  *
- *     http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
  *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific
+ * language governing permissions and limitations under the License.
  */
 
 /**
@@ -45,6 +49,7 @@ using namespace shibsp;
 #ifndef SHIBSP_LITE
 using namespace opensaml::saml2md;
 using namespace opensaml;
+using namespace boost;
 #endif
 using namespace xmltooling;
 using namespace std;
@@ -90,7 +95,7 @@ namespace shibsp {
         // A queue of feed files, linked to the last time of "access".
         // Each filename is also a cache tag.
         mutable queue< pair<string,time_t> > m_feedQueue;
-        Mutex* m_feedLock;
+        scoped_ptr<Mutex> m_feedLock;
 #endif
     };
 
@@ -106,10 +111,7 @@ namespace shibsp {
 };
 
 DiscoveryFeed::DiscoveryFeed(const DOMElement* e, const char* appId)
-    : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT".DiscoveryFeed"), &g_Blocker), m_cacheToClient(false)
-#ifndef SHIBSP_LITE
-    , m_feedLock(nullptr)
-#endif
+    : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT ".DiscoveryFeed"), &g_Blocker), m_cacheToClient(false)
 {
     pair<bool,const char*> prop = getString("Location");
     if (!prop.first)
@@ -125,10 +127,10 @@ DiscoveryFeed::DiscoveryFeed(const DOMElement* e, const char* appId)
         prop = getString("dir");
         if (prop.first)
             m_dir = prop.second;
-        XMLToolingConfig::getConfig().getPathResolver()->resolve(m_dir, PathResolver::XMLTOOLING_RUN_FILE);
+        XMLToolingConfig::getConfig().getPathResolver()->resolve(m_dir, PathResolver::XMLTOOLING_CACHE_FILE);
         m_log.info("feed files will be cached in %s", m_dir.c_str());
 #ifndef SHIBSP_LITE
-        m_feedLock = Mutex::create();
+        m_feedLock.reset(Mutex::create());
 #endif
     }
 }
@@ -141,11 +143,10 @@ DiscoveryFeed::~DiscoveryFeed()
         // Anything left will be orphaned, but that shouldn't happen too often.
         time_t now = time(nullptr);
         while (!m_feedQueue.empty() && now - m_feedQueue.front().second > 120) {
-            string fname = m_dir + '/' + m_feedQueue.front().first;
+            string fname = m_dir + '/' + m_feedQueue.front().first + ".json";
             remove(fname.c_str());
             m_feedQueue.pop();
         }
-        delete m_feedLock;
     }
 #endif
 }
@@ -170,7 +171,7 @@ pair<bool,long> DiscoveryFeed::run(SPRequest& request, bool isHandler) const
                         string etag = '"' + s + '"';
                         request.setResponseHeader("ETag", etag.c_str());
                     }
-                    request.setContentType("application/json");
+                    request.setContentType("application/json; charset=UTF-8");
                     return make_pair(true, request.sendResponse(buf));
                 }
             }
@@ -196,7 +197,7 @@ pair<bool,long> DiscoveryFeed::run(SPRequest& request, bool isHandler) const
                 }
                 if (out["feed"].string()) {
                     istringstream buf(out["feed"].string());
-                    request.setContentType("application/json");
+                    request.setContentType("application/json; charset=UTF-8");
                     return make_pair(true, request.sendResponse(buf));
                 }
                 throw ConfigurationException("Discovery feed was empty.");
@@ -222,10 +223,10 @@ pair<bool,long> DiscoveryFeed::run(SPRequest& request, bool isHandler) const
             string etag = '"' + s + '"';
             request.setResponseHeader("ETag", etag.c_str());
         }
-        request.setContentType("application/json");
+        request.setContentType("application/json; charset=UTF-8");
         return make_pair(true, request.sendResponse(feed));
     }
-    catch (exception& ex) {
+    catch (std::exception& ex) {
         request.log(SPRequest::SPError, string("error while processing request:") + ex.what());
         istringstream msg("Discovery Request Failed");
         return make_pair(true, request.sendResponse(msg, HTTPResponse::XMLTOOLING_HTTP_STATUS_ERROR));
@@ -274,47 +275,48 @@ void DiscoveryFeed::feedToFile(const Application& application, string& cacheTag)
 #ifndef SHIBSP_LITE
     m_log.debug("processing discovery feed request");
 
-    DiscoverableMetadataProvider* m=dynamic_cast<DiscoverableMetadataProvider*>(application.getMetadataProvider());
-    if (m) {
-        Locker locker(m);
-        string feedTag = m->getCacheTag();
-        if (cacheTag == ('"' + feedTag + '"')) {
-            // The client already has the same feed we do.
-            m_log.debug("client's cache tag matches our feed (%s)", feedTag.c_str());
-            cacheTag.erase();   // clear the tag to signal no change
-            return;
-        }
+    DiscoverableMetadataProvider* m = dynamic_cast<DiscoverableMetadataProvider*>(application.getMetadataProvider(false));
+    if (!m)
+        m_log.warn("MetadataProvider missing or does not support discovery feed");
+    Locker locker(m);
+    string feedTag = m ? m->getCacheTag() : "empty";
+    if (cacheTag == ('"' + feedTag + '"')) {
+        // The client already has the same feed we do.
+        m_log.debug("client's cache tag matches our feed (%s)", feedTag.c_str());
+        cacheTag.erase();   // clear the tag to signal no change
+        return;
+    }
 
-        cacheTag = feedTag;
+    cacheTag = feedTag;
 
-        // The client is out of date or not caching, so we need to see if our copy is good.
-        Lock lock(m_feedLock);
-        time_t now = time(nullptr);
+    // The client is out of date or not caching, so we need to see if our copy is good.
+    Lock lock(m_feedLock);
+    time_t now = time(nullptr);
 
-        // Clean up any old files.
-        while (m_feedQueue.size() > 1 && (now - m_feedQueue.front().second > 120)) {
-            string fname = m_dir + '/' + m_feedQueue.front().first;
-            remove(fname.c_str());
-            m_feedQueue.pop();
-        }
+    // Clean up any old files.
+    while (m_feedQueue.size() > 1 && (now - m_feedQueue.front().second > 120)) {
+        string fname = m_dir + '/' + m_feedQueue.front().first + ".json";
+        remove(fname.c_str());
+        m_feedQueue.pop();
+    }
 
-        if (m_feedQueue.empty() || m_feedQueue.back().first != feedTag) {
-            // We're out of date.
-            string fname = m_dir + '/' + feedTag + ".json";
-            ofstream ofile(fname.c_str());
-            if (!ofile)
-                throw ConfigurationException("Unable to create feed in ($1).", params(1,fname.c_str()));
-            m->outputFeed(ofile);
-            ofile.close();
-            m_feedQueue.push(make_pair(feedTag, now));
-        }
-        else {
-            // Update the back of the queue.
-            m_feedQueue.back().second = now;
-        }
+    if (m_feedQueue.empty() || m_feedQueue.back().first != feedTag) {
+        // We're out of date.
+        string fname = m_dir + '/' + feedTag + ".json";
+        ofstream ofile(fname.c_str());
+        if (!ofile)
+            throw ConfigurationException("Unable to create feed in ($1).", params(1,fname.c_str()));
+        bool first = true;
+        if (m)
+            m->outputFeed(ofile, first);
+        else
+            ofile << "[\n]";
+        ofile.close();
+        m_feedQueue.push(make_pair(feedTag, now));
     }
     else {
-        throw MetadataException("MetadataProvider does not support discovery feed.");
+        // Update the back of the queue.
+        m_feedQueue.back().second = now;
     }
 #else
     throw ConfigurationException("Build does not support discovery feed.");
@@ -326,23 +328,24 @@ void DiscoveryFeed::feedToStream(const Application& application, string& cacheTa
 #ifndef SHIBSP_LITE
     m_log.debug("processing discovery feed request");
 
-    DiscoverableMetadataProvider* m=dynamic_cast<DiscoverableMetadataProvider*>(application.getMetadataProvider());
-    if (m) {
-        Locker locker(m);
-        string feedTag = m->getCacheTag();
-        if (cacheTag == ('"' + feedTag + '"')) {
-            // The client already has the same feed we do.
-            m_log.debug("client's cache tag matches our feed (%s)", feedTag.c_str());
-            cacheTag.erase();   // clear the tag to signal no change
-            return;
-        }
-
-        cacheTag = feedTag;
-        m->outputFeed(os);
-    }
-    else {
-        throw MetadataException("MetadataProvider does not support discovery feed.");
+    DiscoverableMetadataProvider* m = dynamic_cast<DiscoverableMetadataProvider*>(application.getMetadataProvider(false));
+    if (!m)
+        m_log.warn("MetadataProvider missing or does not support discovery feed");
+    Locker locker(m);
+    string feedTag = m ? m->getCacheTag() : "empty";
+    if (cacheTag == ('"' + feedTag + '"')) {
+        // The client already has the same feed we do.
+        m_log.debug("client's cache tag matches our feed (%s)", feedTag.c_str());
+        cacheTag.erase();   // clear the tag to signal no change
+        return;
     }
+
+    cacheTag = feedTag;
+    bool first = true;
+    if (m)
+        m->outputFeed(os, first);
+    else
+        os << "[\n]";
 #else
     throw ConfigurationException("Build does not support discovery feed.");
 #endif