forked from Silverfish/proton-bridge
feat(GODT-2364): added optional details to C++ exceptions.
This commit is contained in:
@ -23,11 +23,13 @@ namespace bridgepp {
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] what A description of the exception
|
||||
/// \param[in] what A description of the exception.
|
||||
/// \param[in] details The optional details for the exception.
|
||||
//****************************************************************************************************************************************************
|
||||
Exception::Exception(QString what) noexcept
|
||||
Exception::Exception(QString what, QString details) noexcept
|
||||
: std::exception()
|
||||
, what_(std::move(what)) {
|
||||
, what_(std::move(what))
|
||||
, details_(std::move(details)) {
|
||||
}
|
||||
|
||||
|
||||
@ -36,7 +38,8 @@ Exception::Exception(QString what) noexcept
|
||||
//****************************************************************************************************************************************************
|
||||
Exception::Exception(Exception const &ref) noexcept
|
||||
: std::exception(ref)
|
||||
, what_(ref.what_) {
|
||||
, what_(ref.what_)
|
||||
, details_(ref.details_) {
|
||||
}
|
||||
|
||||
|
||||
@ -45,14 +48,15 @@ Exception::Exception(Exception const &ref) noexcept
|
||||
//****************************************************************************************************************************************************
|
||||
Exception::Exception(Exception &&ref) noexcept
|
||||
: std::exception(ref)
|
||||
, what_(ref.what_) {
|
||||
, what_(ref.what_)
|
||||
, details_(ref.details_) {
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return a string describing the exception
|
||||
//****************************************************************************************************************************************************
|
||||
QString const &Exception::qwhat() const noexcept {
|
||||
QString Exception::qwhat() const noexcept {
|
||||
return what_;
|
||||
}
|
||||
|
||||
@ -65,4 +69,12 @@ const char *Exception::what() const noexcept {
|
||||
}
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \return The details for the exception.
|
||||
//****************************************************************************************************************************************************
|
||||
QString Exception::details() const noexcept {
|
||||
return details_;
|
||||
}
|
||||
|
||||
|
||||
} // namespace bridgepp
|
||||
|
||||
@ -31,17 +31,19 @@ namespace bridgepp {
|
||||
//****************************************************************************************************************************************************
|
||||
class Exception : public std::exception {
|
||||
public: // member functions
|
||||
explicit Exception(QString what = QString()) noexcept; ///< Constructor
|
||||
explicit Exception(QString what = QString(), QString details = QString()) noexcept; ///< Constructor
|
||||
Exception(Exception const &ref) noexcept; ///< copy constructor
|
||||
Exception(Exception &&ref) noexcept; ///< copy constructor
|
||||
Exception &operator=(Exception const &) = delete; ///< Disabled assignment operator
|
||||
Exception &operator=(Exception &&) = delete; ///< Disabled assignment operator
|
||||
~Exception() noexcept override = default; ///< Destructor
|
||||
QString const &qwhat() const noexcept; ///< Return the description of the exception as a QString
|
||||
QString qwhat() const noexcept; ///< Return the description of the exception as a QString
|
||||
const char *what() const noexcept override; ///< Return the description of the exception as C style string
|
||||
QString details() const noexcept; ///< Return the details for the exception
|
||||
|
||||
private: // data members
|
||||
QString const what_; ///< The description of the exception
|
||||
QString const what_; ///< The description of the exception.
|
||||
QString const details_; ///< The optional details for the exception.
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -88,8 +88,9 @@ GRPCConfig GRPCClient::waitAndRetrieveServiceConfig(qint64 timeoutMs, ProcessMon
|
||||
}
|
||||
|
||||
GRPCConfig sc;
|
||||
if (!sc.load(path)) {
|
||||
throw Exception("The gRPC service configuration file is invalid.");
|
||||
QString err;
|
||||
if (!sc.load(path, &err)) {
|
||||
throw Exception("The gRPC service configuration file is invalid.", err);
|
||||
}
|
||||
|
||||
return sc;
|
||||
@ -105,11 +106,10 @@ void GRPCClient::setLog(Log *log) {
|
||||
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[out] outError If the function returns false, this variable contains a description of the error.
|
||||
/// \param[in] serverProcess An optional server process to monitor. If the process it, no need and retry, as connexion cannot be established. Ignored if null.
|
||||
/// \return true iff the connection was successful.
|
||||
//****************************************************************************************************************************************************
|
||||
bool GRPCClient::connectToServer(GRPCConfig const &config, ProcessMonitor *serverProcess, QString &outError) {
|
||||
void GRPCClient::connectToServer(GRPCConfig const &config, ProcessMonitor *serverProcess) {
|
||||
try {
|
||||
serverToken_ = config.token.toStdString();
|
||||
QString address;
|
||||
@ -158,9 +158,10 @@ bool GRPCClient::connectToServer(GRPCConfig const &config, ProcessMonitor *serve
|
||||
this->logInfo("Successfully connected to gRPC server.");
|
||||
|
||||
QString const clientToken = QUuid::createUuid().toString();
|
||||
QString clientConfigPath = createClientConfigFile(clientToken);
|
||||
QString error;
|
||||
QString clientConfigPath = createClientConfigFile(clientToken, &error);
|
||||
if (clientConfigPath.isEmpty()) {
|
||||
throw Exception("gRPC client config could not be saved.");
|
||||
throw Exception("gRPC client config could not be saved.", error);
|
||||
}
|
||||
this->logInfo(QString("Client config file was saved to '%1'").arg(QDir::toNativeSeparators(clientConfigPath)));
|
||||
|
||||
@ -176,12 +177,9 @@ bool GRPCClient::connectToServer(GRPCConfig const &config, ProcessMonitor *serve
|
||||
}
|
||||
|
||||
log_->info("gRPC token was validated");
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception const &e) {
|
||||
outError = e.qwhat();
|
||||
return false;
|
||||
throw Exception("Cannot connect to Go backend via gRPC: " + e.qwhat(), e.details());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -59,7 +59,7 @@ public: // member functions.
|
||||
GRPCClient &operator=(GRPCClient const &) = delete; ///< Disabled assignment operator.
|
||||
GRPCClient &operator=(GRPCClient &&) = delete; ///< Disabled move assignment operator.
|
||||
void setLog(Log *log); ///< Set the log for the client.
|
||||
bool connectToServer(GRPCConfig const &config, class ProcessMonitor *serverProcess, QString &outError); ///< Establish connection to the gRPC server.
|
||||
void connectToServer(GRPCConfig const &config, class ProcessMonitor *serverProcess); ///< Establish connection to the gRPC server.
|
||||
|
||||
grpc::Status checkTokens(QString const &clientConfigPath, QString &outReturnedClientToken); ///< Performs a token check.
|
||||
grpc::Status addLogEntry(Log::Level level, QString const &package, QString const &message); ///< Performs the "AddLogEntry" gRPC call.
|
||||
|
||||
@ -25,8 +25,7 @@ using namespace bridgepp;
|
||||
|
||||
namespace {
|
||||
|
||||
Exception const invalidFileException("The service configuration file is invalid"); // Exception for invalid config.
|
||||
Exception const couldNotSaveException("The service configuration file could not be saved"); ///< Exception for write errors.
|
||||
Exception const invalidFileException("The content of the service configuration file is invalid"); // Exception for invalid config.
|
||||
QString const keyPort = "port"; ///< The JSON key for the port.
|
||||
QString const keyCert = "cert"; ///< The JSON key for the TLS certificate.
|
||||
QString const keyToken = "token"; ///< The JSON key for the identification token.
|
||||
@ -78,8 +77,11 @@ qint32 jsonIntValue(QJsonObject const &object, QString const &key) {
|
||||
bool GRPCConfig::load(QString const &path, QString *outError) {
|
||||
try {
|
||||
QFile file(path);
|
||||
if (!file.exists())
|
||||
throw Exception("The file service configuration file does not exist.");
|
||||
|
||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
throw Exception("Could not open gRPC service config file.");
|
||||
throw Exception("The file exists but cannot be opened.");
|
||||
}
|
||||
|
||||
QJsonDocument const doc = QJsonDocument::fromJson(file.readAll());
|
||||
@ -93,7 +95,7 @@ bool GRPCConfig::load(QString const &path, QString *outError) {
|
||||
}
|
||||
catch (Exception const &e) {
|
||||
if (outError) {
|
||||
*outError = e.qwhat();
|
||||
*outError = QString("Error loading gRPC service configuration file '%1'.\n%2").arg(QFileInfo(path).absoluteFilePath(), e.qwhat());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -115,19 +117,19 @@ bool GRPCConfig::save(QString const &path, QString *outError) {
|
||||
|
||||
QFile file(path);
|
||||
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||
throw couldNotSaveException;
|
||||
throw Exception("The file could not be opened for writing.");
|
||||
}
|
||||
|
||||
QByteArray const array = QJsonDocument(object).toJson();
|
||||
if (array.size() != file.write(array)) {
|
||||
throw couldNotSaveException;
|
||||
throw Exception("An error occurred while writing to the file.");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception const &e) {
|
||||
if (outError) {
|
||||
*outError = e.qwhat();
|
||||
*outError = QString("Error saving gRPC service configuration file '%1'.\n%2").arg(QFileInfo(path).absoluteFilePath(), e.qwhat());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -76,10 +76,12 @@ QString grpcClientConfigBasePath() {
|
||||
|
||||
//****************************************************************************************************************************************************
|
||||
/// \param[in] token The token to put in the file.
|
||||
/// \param[out] outError if the function returns an empty string and this pointer is not null, the pointer variable holds a description of the error
|
||||
/// on exit.
|
||||
/// \return The path of the created file.
|
||||
/// \return A null string if the file could not be saved..
|
||||
/// \return A null string if the file could not be saved.
|
||||
//****************************************************************************************************************************************************
|
||||
QString createClientConfigFile(QString const &token) {
|
||||
QString createClientConfigFile(QString const &token, QString *outError) {
|
||||
QString const basePath = grpcClientConfigBasePath();
|
||||
QString path, error;
|
||||
for (qint32 i = 0; i < 1000; ++i) // we try a decent amount of times
|
||||
@ -88,13 +90,16 @@ QString createClientConfigFile(QString const &token) {
|
||||
if (!QFileInfo(path).exists()) {
|
||||
GRPCConfig config;
|
||||
config.token = token;
|
||||
if (!config.save(path)) {
|
||||
|
||||
if (!config.save(path, outError)) {
|
||||
return QString();
|
||||
}
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
if (outError)
|
||||
*outError = "no usable client configuration file name could be found.";
|
||||
return QString();
|
||||
}
|
||||
|
||||
|
||||
@ -36,7 +36,7 @@ typedef std::shared_ptr<grpc::StreamEvent> SPStreamEvent; ///< Type definition f
|
||||
|
||||
QString grpcServerConfigPath(); ///< Return the path of the gRPC server config file.
|
||||
QString grpcClientConfigBasePath(); ///< Return the path of the gRPC client config file.
|
||||
QString createClientConfigFile(QString const &token); ///< Create the client config file the server will retrieve and return its path.
|
||||
QString createClientConfigFile(QString const &token, QString *outError); ///< Create the client config file the server will retrieve and return its path.
|
||||
grpc::LogLevel logLevelToGRPC(Log::Level level); ///< Convert a Log::Level to gRPC enum value.
|
||||
Log::Level logLevelFromGRPC(grpc::LogLevel level); ///< Convert a grpc::LogLevel to a Log::Level.
|
||||
grpc::UserState userStateToGRPC(UserState state); ///< Convert a bridgepp::UserState to a grpc::UserState.
|
||||
|
||||
Reference in New Issue
Block a user