Exception handling for json_utility APIs

This commit adds code to handle exceptions for some of the json_utility
APIs. Each API will have output returned in case of error based on the
return type of the API instead of throwing an exception.

Also updated the caller of the json_utility APIs to handle the return
value.

Change-Id: Ib43028974b61c18a0edae96608a8764cb440234a
Signed-off-by: RekhaAparna01 <vrekhaaparna@ibm.com>
diff --git a/vpd-manager/include/utility/json_utility.hpp b/vpd-manager/include/utility/json_utility.hpp
index 764fb66..05e3fda 100644
--- a/vpd-manager/include/utility/json_utility.hpp
+++ b/vpd-manager/include/utility/json_utility.hpp
@@ -88,38 +88,42 @@
 /**
  * @brief API to parse respective JSON.
  *
- * Exception is thrown in case of JSON parse error.
- *
  * @param[in] pathToJson - Path to JSON.
- * @return Parsed JSON.
+ * @return on success parsed JSON. On failure empty JSON object.
+ *
+ * Note: Caller has to handle it in case an empty JSON object is received.
  */
-inline nlohmann::json getParsedJson(const std::string& pathToJson)
+inline nlohmann::json getParsedJson(const std::string& pathToJson) noexcept
 {
-    if (pathToJson.empty())
-    {
-        throw std::runtime_error("Path to JSON is missing");
-    }
-
-    if (!std::filesystem::exists(pathToJson) ||
-        std::filesystem::is_empty(pathToJson))
-    {
-        throw std::runtime_error("Incorrect File Path or empty file");
-    }
-
-    std::ifstream jsonFile(pathToJson);
-    if (!jsonFile)
-    {
-        throw std::runtime_error("Failed to access Json path = " + pathToJson);
-    }
-
     try
     {
-        return nlohmann::json::parse(jsonFile);
+        if (pathToJson.empty())
+        {
+            throw std::runtime_error("Path to JSON is missing");
+        }
+
+        if (!std::filesystem::exists(pathToJson) ||
+            std::filesystem::is_empty(pathToJson))
+        {
+            throw std::runtime_error("Incorrect file Path or empty file");
+        }
+
+        std::ifstream l_jsonFile(pathToJson);
+        if (!l_jsonFile)
+        {
+            throw std::runtime_error(
+                "Failed to access Json path = " + pathToJson);
+        }
+
+        return nlohmann::json::parse(l_jsonFile);
     }
-    catch (const nlohmann::json::parse_error& e)
+    catch (const std::exception& l_ex)
     {
-        throw std::runtime_error("Failed to parse JSON file");
+        logging::logMessage(
+            "Failed to parse JSON file, error: " + std::string(l_ex.what()));
     }
+
+    return nlohmann::json{};
 }
 
 /**
@@ -131,48 +135,60 @@
  * @param[in] i_sysCfgJsonObj - System config JSON object
  * @param[in] i_vpdPath - Path to where VPD is stored.
  *
- * @throw std::runtime_error.
- *
  * @return On success a valid path is returned, on failure an empty string is
- * returned or an exception is thrown.
+ * returned.
+ *
+ * Note: Caller has to handle it in case an empty string is received.
  */
 inline std::string getInventoryObjPathFromJson(
-    const nlohmann::json& i_sysCfgJsonObj, const std::string& i_vpdPath)
+    const nlohmann::json& i_sysCfgJsonObj,
+    const std::string& i_vpdPath) noexcept
 {
-    if (i_vpdPath.empty())
+    try
     {
-        throw std::runtime_error("Path parameter is empty.");
-    }
-
-    if (!i_sysCfgJsonObj.contains("frus"))
-    {
-        throw std::runtime_error("Missing frus tag in system config JSON.");
-    }
-
-    // check if given path is FRU path
-    if (i_sysCfgJsonObj["frus"].contains(i_vpdPath))
-    {
-        return i_sysCfgJsonObj["frus"][i_vpdPath].at(0).value(
-            "inventoryPath", "");
-    }
-
-    const nlohmann::json& l_fruList =
-        i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
-
-    for (const auto& l_fru : l_fruList.items())
-    {
-        const auto l_fruPath = l_fru.key();
-        const auto l_invObjPath =
-            i_sysCfgJsonObj["frus"][l_fruPath].at(0).value("inventoryPath", "");
-
-        // check if given path is redundant FRU path or inventory path
-        if (i_vpdPath == i_sysCfgJsonObj["frus"][l_fruPath].at(0).value(
-                             "redundantEeprom", "") ||
-            (i_vpdPath == l_invObjPath))
+        if (i_vpdPath.empty())
         {
-            return l_invObjPath;
+            throw std::runtime_error("Path parameter is empty.");
+        }
+
+        if (!i_sysCfgJsonObj.contains("frus"))
+        {
+            throw std::runtime_error("Missing frus tag in system config JSON.");
+        }
+
+        // check if given path is FRU path
+        if (i_sysCfgJsonObj["frus"].contains(i_vpdPath))
+        {
+            return i_sysCfgJsonObj["frus"][i_vpdPath].at(0).value(
+                "inventoryPath", "");
+        }
+
+        const nlohmann::json& l_fruList =
+            i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
+
+        for (const auto& l_fru : l_fruList.items())
+        {
+            const auto l_fruPath = l_fru.key();
+            const auto l_invObjPath =
+                i_sysCfgJsonObj["frus"][l_fruPath].at(0).value("inventoryPath",
+                                                               "");
+
+            // check if given path is redundant FRU path or inventory path
+            if (i_vpdPath == i_sysCfgJsonObj["frus"][l_fruPath].at(0).value(
+                                 "redundantEeprom", "") ||
+                (i_vpdPath == l_invObjPath))
+            {
+                return l_invObjPath;
+            }
         }
     }
+    catch (const std::exception& l_ex)
+    {
+        logging::logMessage(
+            "Failed to get inventory object path from json, error: " +
+            std::string(l_ex.what()));
+    }
+
     return std::string();
 }
 
diff --git a/vpd-manager/src/backup_restore.cpp b/vpd-manager/src/backup_restore.cpp
index 294efc4..9de43b9 100644
--- a/vpd-manager/src/backup_restore.cpp
+++ b/vpd-manager/src/backup_restore.cpp
@@ -20,17 +20,14 @@
 {
     std::string l_backupAndRestoreCfgFilePath =
         i_sysCfgJsonObj.value("backupRestoreConfigPath", "");
-    try
+
+    m_backupAndRestoreCfgJsonObj =
+        jsonUtility::getParsedJson(l_backupAndRestoreCfgFilePath);
+
+    if (m_backupAndRestoreCfgJsonObj.empty())
     {
-        m_backupAndRestoreCfgJsonObj =
-            jsonUtility::getParsedJson(l_backupAndRestoreCfgFilePath);
-    }
-    catch (const std::exception& ex)
-    {
-        logging::logMessage(
-            "Failed to intialize backup and restore object for file = " +
-            l_backupAndRestoreCfgFilePath);
-        throw(ex);
+        throw JsonException("JSON parsing failed",
+                            l_backupAndRestoreCfgFilePath);
     }
 }
 
diff --git a/vpd-manager/src/worker.cpp b/vpd-manager/src/worker.cpp
index 262e3dc..4199c15 100644
--- a/vpd-manager/src/worker.cpp
+++ b/vpd-manager/src/worker.cpp
@@ -496,11 +496,9 @@
         }
 
         // re-parse the JSON once appropriate JSON has been selected.
-        try
-        {
-            m_parsedJson = jsonUtility::getParsedJson(systemJson);
-        }
-        catch (const nlohmann::json::parse_error& ex)
+        m_parsedJson = jsonUtility::getParsedJson(systemJson);
+
+        if (m_parsedJson.empty())
         {
             throw(JsonException("Json parsing failed", systemJson));
         }
@@ -1459,22 +1457,25 @@
 
         // Set CollectionStatus as InProgress. Since it's an intermediate state
         // D-bus set-property call is good enough to update the status.
-        try
-        {
-            l_inventoryPath = jsonUtility::getInventoryObjPathFromJson(
-                m_parsedJson, i_vpdFilePath);
+        l_inventoryPath = jsonUtility::getInventoryObjPathFromJson(
+            m_parsedJson, i_vpdFilePath);
 
-            dbusUtility::writeDbusProperty(
-                jsonUtility::getServiceName(m_parsedJson, l_inventoryPath),
-                l_inventoryPath, constants::vpdCollectionInterface,
-                "CollectionStatus",
-                types::DbusVariantType{constants::vpdCollectionInProgress});
-        }
-        catch (const std::exception& l_exception)
+        if (!l_inventoryPath.empty())
         {
-            logging::logMessage(
-                "Unable to set CollectionStatus as InProgress for " +
-                i_vpdFilePath + ". Error : " + l_exception.what());
+            try
+            {
+                dbusUtility::writeDbusProperty(
+                    jsonUtility::getServiceName(m_parsedJson, l_inventoryPath),
+                    l_inventoryPath, constants::vpdCollectionInterface,
+                    "CollectionStatus",
+                    types::DbusVariantType{constants::vpdCollectionInProgress});
+            }
+            catch (const std::exception& l_exception)
+            {
+                logging::logMessage(
+                    "Unable to set CollectionStatus as InProgress for " +
+                    i_vpdFilePath + ". Error : " + l_exception.what());
+            }
         }
 
         const types::VPDMapVariant& parsedVpdMap = parseVpdFile(i_vpdFilePath);
@@ -1511,24 +1512,14 @@
             // logging error for these cases.
             if (vpdSpecificUtility::isPass1Planar())
             {
-                // Till exceptions are removed from utility method, this needs
-                // to be handled in place.
-                try
-                {
-                    const std::string& l_invPathLeafValue =
-                        sdbusplus::message::object_path(
-                            jsonUtility::getInventoryObjPathFromJson(
-                                m_parsedJson, i_vpdFilePath))
-                            .filename();
+                const std::string& l_invPathLeafValue =
+                    sdbusplus::message::object_path(
+                        jsonUtility::getInventoryObjPathFromJson(m_parsedJson,
+                                                                 i_vpdFilePath))
+                        .filename();
 
-                    if ((l_invPathLeafValue.find("pcie_card", 0) !=
-                         std::string::npos))
-                    {
-                        // skip logging any PEL for PCIe cards on pass 1 planar.
-                        return std::make_tuple(false, i_vpdFilePath);
-                    }
-                }
-                catch (const std::exception& l_ex)
+                if ((l_invPathLeafValue.find("pcie_card", 0) !=
+                     std::string::npos))
                 {
                     // skip logging any PEL for PCIe cards on pass 1 planar.
                     return std::make_tuple(false, i_vpdFilePath);
@@ -1665,6 +1656,12 @@
         nlohmann::json l_backupAndRestoreCfgJsonObj =
             jsonUtility::getParsedJson(l_backupAndRestoreCfgFilePath);
 
+        if (l_backupAndRestoreCfgJsonObj.empty())
+        {
+            throw JsonException("JSON parsing failed",
+                                l_backupAndRestoreCfgFilePath);
+        }
+
         // check if either of "source" or "destination" has inventory path.
         // this indicates that this sytem has System VPD on hardware
         // and other copy on D-Bus (BMC cache).