#include "list_elements.h" #include "print_table.h" #include #include #include #include "../../global/cmdlnparser/cmdlnparser.h" #include "../../global/exec_dir_helper.h" #include "../../global/flags.h" #include "../error_msg.h" void ListHelp(const SContext& rsContext) { // First argument should be "LIST" if (rsContext.seqCmdLine.size() < 1) { if (!rsContext.bSilent) std::cerr << "ERROR: missing listing command..." << std::endl; return; } if (!iequals(rsContext.seqCmdLine[0], "LIST")) { if (!rsContext.bSilent) std::cerr << "ERROR: invalid command: " << rsContext.seqCmdLine[0] << std::endl; return; } // Which list command help is requested enum class EListCommand { unknown, modules, classes, components, installations, connections } eListCommand = EListCommand::unknown; if (rsContext.seqCmdLine.size() >= 2) { if (iequals(rsContext.seqCmdLine[1], "MODULES")) eListCommand = EListCommand::modules; else if (iequals(rsContext.seqCmdLine[1], "CLASSES")) eListCommand = EListCommand::classes; else if (iequals(rsContext.seqCmdLine[1], "COMPONENTS")) eListCommand = EListCommand::components; else if (iequals(rsContext.seqCmdLine[1], "INSTALLATIONS")) eListCommand = EListCommand::installations; else if (iequals(rsContext.seqCmdLine[1], "CONNECTIONS")) eListCommand = EListCommand::connections; } // Print help if requested if (!rsContext.bSilent) { switch (eListCommand) { case EListCommand::modules: CCommandLine::PrintHelpText(std::cout, "Usage: sdv_control LIST MODULES [options...]\n\nShow a list of all loaded modules.\n"); break; case EListCommand::classes: CCommandLine::PrintHelpText(std::cout, "Usage: sdv_control LIST CLASSES [options...]\n\nShow a list of available component classes.\n"); break; case EListCommand::components: CCommandLine::PrintHelpText(std::cout, "Usage: sdv_control LIST COMPONENTS [options...]\n\nShow a list of all loaded components.\n"); break; case EListCommand::installations: CCommandLine::PrintHelpText(std::cout, "Usage: sdv_control LIST INSTALLATIONS [options...]\n\nShow a list of all installations.\n"); break; case EListCommand::connections: CCommandLine::PrintHelpText(std::cout, "Usage: sdv_control LIST CONNECTIONS [options...]\n\nShow a list of all connected applications.\n"); break; default: CCommandLine::PrintHelpText(std::cout, R"code(Usage: sdv_control LIST [options...] Supported listing commands: LIST MODULES Show a list of loaded server modules. LIST CLASSES Show a list of available component classes. LIST COMPONENTS Show a list of instantiated server components LIST INSTALLATIONS Show a list of installations. LIST CONNECTIONS Show a list of current connections. )code"); break; } std::cout << "Options:\n"; std::cout << " --no_header Do not print a header for the listing table.\n"; std::cout << " --short Print only the most essential information as one column.\n\n"; } } int ListElements(const SContext& rsContext, std::ostream& rstream /*= std::cout*/) { // First argument should be "LIST" if (rsContext.seqCmdLine.size() < 1) { if (!rsContext.bSilent) std::cerr << "ERROR: " << CMDLN_ARG_ERR_MSG << " Missing listing command." << std::endl; return CMDLN_ARG_ERR; } if (!iequals(rsContext.seqCmdLine[0], "LIST")) { if (!rsContext.bSilent) std::cerr << "ERROR: " << CMDLN_ARG_ERR_MSG << " Invalid command: " << rsContext.seqCmdLine[0] << std::endl; return CMDLN_ARG_ERR; } // Which list command help is requested enum class EListCommand { unknown, modules, classes, components, installations, connections } eListCommand = EListCommand::unknown; if (rsContext.seqCmdLine.size() >= 2) { if (iequals(rsContext.seqCmdLine[1], "MODULES")) eListCommand = EListCommand::modules; else if (iequals(rsContext.seqCmdLine[1], "CLASSES")) eListCommand = EListCommand::classes; else if (iequals(rsContext.seqCmdLine[1], "COMPONENTS")) eListCommand = EListCommand::components; else if (iequals(rsContext.seqCmdLine[1], "INSTALLATIONS")) eListCommand = EListCommand::installations; else if (iequals(rsContext.seqCmdLine[1], "CONNECTIONS")) eListCommand = EListCommand::connections; } else { if (!rsContext.bSilent) { std::cerr << "ERROR: " << CMDLN_ARG_ERR_MSG << " Missing listing command.." << std::endl << std::endl; ListHelp(rsContext); } return CMDLN_ARG_ERR; } // Try to connect sdv::TObjectPtr ptrRepository = sdv::com::ConnectToLocalServerRepository(rsContext.uiInstanceID); if (!ptrRepository) { if (!rsContext.bSilent) std::cerr << "ERROR: " << CONNECT_SDV_SERVER_ERROR_MSG << " Instance #" << rsContext.uiInstanceID << "." << std::endl; return CONNECT_SDV_SERVER_ERROR; } int iRet = -100; switch (eListCommand) { case EListCommand::modules: iRet = ListModules(rsContext, ptrRepository, rstream); break; case EListCommand::classes: iRet = ListClasses(rsContext, ptrRepository, rstream); break; case EListCommand::components: iRet = ListComponents(rsContext, ptrRepository, rstream); break; case EListCommand::installations: iRet = ListInstallations(rsContext, ptrRepository, rstream); break; case EListCommand::connections: iRet = ListConnections(rsContext, ptrRepository, rstream); break; default: break; } return iRet; } int ListModules(const SContext& rsContext, const sdv::TObjectPtr& rptrRepository, std::ostream& rstream) { // Get access to the module control service sdv::core::IObjectAccess* pObjectAccess = rptrRepository.GetInterface(); const sdv::core::IModuleInfo* pModuleInfo = nullptr; if (pObjectAccess) pModuleInfo = sdv::TInterfaceAccessPtr(pObjectAccess->GetObject("ModuleControlService")). GetInterface(); if (!pModuleInfo) { if (!rsContext.bSilent) std::cerr << "ERROR: " << MODULE_CONTROL_SERVICE_ACCESS_ERROR_MSG << std::endl; return MODULE_CONTROL_SERVICE_ACCESS_ERROR; } // Relative path from exe auto fnPrintRelPath = [](const sdv::u8string& rssPath) { std::filesystem::path path = rssPath.c_str(); if (path.is_relative()) return path.generic_u8string(); return path.lexically_relative(GetExecDirectory()).generic_u8string(); }; // Create the module list sdv::sequence seqModules = pModuleInfo->GetModuleList(); if (rsContext.bListShort) { std::vector> vecShortModuleList; vecShortModuleList.push_back({ "Path" }); for (const sdv::core::SModuleInfo& rsModuleInfo : seqModules) vecShortModuleList.push_back({ fnPrintRelPath(rsModuleInfo.ssPath) }); // Print the module list PrintTable(vecShortModuleList, rstream, rsContext.bListNoHdr); } else { std::vector> vecModuleList; vecModuleList.push_back({ "Module ID", "Filename", "Version", "Active", "Path" }); for (const sdv::core::SModuleInfo& rsModuleInfo : seqModules) vecModuleList.push_back({ std::to_string(static_cast(rsModuleInfo.tModuleID)), rsModuleInfo.ssFilename, std::to_string(rsModuleInfo.uiVersion / 100) + "." + std::to_string(rsModuleInfo.uiVersion % 100), (rsModuleInfo.bActive ? " +" : " -"), fnPrintRelPath(rsModuleInfo.ssPath) }); // Print the module list PrintTable(vecModuleList, rstream, rsContext.bListNoHdr); } return NO_ERROR; } int ListClasses(const SContext& rsContext, const sdv::TObjectPtr& rptrRepository, std::ostream& rstream) { // Get access to the module control service sdv::core::IObjectAccess* pObjectAccess = rptrRepository.GetInterface(); const sdv::core::IModuleInfo* pModuleInfo = nullptr; if (pObjectAccess) pModuleInfo = sdv::TInterfaceAccessPtr(pObjectAccess->GetObject("ModuleControlService")). GetInterface(); if (!pModuleInfo) { if (!rsContext.bSilent) std::cerr << "ERROR: " << MODULE_CONTROL_SERVICE_ACCESS_ERROR_MSG << std::endl; return MODULE_CONTROL_SERVICE_ACCESS_ERROR; } // Class type auto fnPrintClassType = [](sdv::EObjectType eType) { switch (eType) { case sdv::EObjectType::SystemObject: return "SystemObject"; case sdv::EObjectType::Device: return "Device"; case sdv::EObjectType::BasicService: return "BasicService"; case sdv::EObjectType::ComplexService: return "ComplexService"; case sdv::EObjectType::Application: return "Application"; case sdv::EObjectType::Proxy: return "Proxy"; case sdv::EObjectType::Stub: return "Stub"; case sdv::EObjectType::Utility: return "Utility"; default: return "Unknown"; } }; // Class flags auto fnPrintClassFlags = [](uint32_t uiFlags) { hlpr::flags flags(uiFlags); std::stringstream sstream; if (flags.check(sdv::EObjectFlags::singleton)) { if (!sstream.str().empty()) sstream << ", "; sstream << "Singleton"; } return std::string("{") + sstream.str() + std::string("}"); }; // Dependencies auto fnPrintList = [](const sdv::sequence& rseqList) { std::stringstream sstream; for (const sdv::u8string& rss : rseqList) { if (!sstream.str().empty()) sstream << ", "; sstream << rss; } return std::string("{") + sstream.str() + std::string("}"); }; // Create the module list if (rsContext.bListShort) { std::vector> vecShortClassList; vecShortClassList.push_back({ "Class name", "Aliases"}); sdv::sequence seqModules = pModuleInfo->GetModuleList(); for (const sdv::core::SModuleInfo& rsModuleInfo : seqModules) { sdv::sequence seqClasses = pModuleInfo->GetClassList(rsModuleInfo.tModuleID); for (const sdv::SClassInfo& rsClassInfo : seqClasses) vecShortClassList.push_back({ rsClassInfo.ssClassName, fnPrintList(rsClassInfo.seqClassAliases) }); } // Print the module list PrintTable(vecShortClassList, rstream, rsContext.bListNoHdr); } else { std::vector> vecClassList; vecClassList.push_back({ "Class name", "Aliases", "Default name", "Type", "Flags", "Module ID", "Dependencies" }); sdv::sequence seqModules = pModuleInfo->GetModuleList(); for (const sdv::core::SModuleInfo& rsModuleInfo : seqModules) { sdv::sequence seqClasses = pModuleInfo->GetClassList(rsModuleInfo.tModuleID); for (const sdv::SClassInfo& rsClassInfo : seqClasses) vecClassList.push_back({ rsClassInfo.ssClassName, fnPrintList(rsClassInfo.seqClassAliases), rsClassInfo.ssDefaultObjectName, fnPrintClassType(rsClassInfo.eType), fnPrintClassFlags(rsClassInfo.uiFlags), std::to_string(static_cast(rsModuleInfo.tModuleID)), fnPrintList(rsClassInfo.seqDependencies) }); } // Print the module list PrintTable(vecClassList, rstream, rsContext.bListNoHdr); } return NO_ERROR; } int ListComponents(const SContext& rsContext, const sdv::TObjectPtr& rptrRepository, std::ostream& rstream) { // Get access to the module control service sdv::core::IObjectAccess* pObjectAccess = rptrRepository.GetInterface(); const sdv::core::IRepositoryInfo* pRepoInfo = nullptr; if (pObjectAccess) pRepoInfo = sdv::TInterfaceAccessPtr(pObjectAccess->GetObject("RepositoryService")). GetInterface(); if (!pRepoInfo) { if (!rsContext.bSilent) std::cerr << "ERROR: " << REPOSITORY_SERVICE_ACCESS_ERROR_MSG << std::endl; return REPOSITORY_SERVICE_ACCESS_ERROR; } // Class type auto fnPrintClassType = [](sdv::EObjectType eType) { switch (eType) { case sdv::EObjectType::SystemObject: return "SystemObject"; case sdv::EObjectType::Device: return "Device"; case sdv::EObjectType::BasicService: return "BasicService"; case sdv::EObjectType::ComplexService: return "ComplexService"; case sdv::EObjectType::Application: return "Application"; case sdv::EObjectType::Proxy: return "Proxy"; case sdv::EObjectType::Stub: return "Stub"; case sdv::EObjectType::Utility: return "Utility"; default: return "Unknown"; } }; // Object flags auto fnPrintObjectFlags = [](uint32_t uiFlags) { hlpr::flags flags(uiFlags); std::stringstream sstream; if (flags.check(sdv::core::EObjectInfoFlags::object_controlled)) { if (!sstream.str().empty()) sstream << ", "; sstream << "Controlled"; } if (flags.check(sdv::core::EObjectInfoFlags::object_foreign)) { if (!sstream.str().empty()) sstream << ", "; sstream << "Foreign"; } if (flags.check(sdv::core::EObjectInfoFlags::object_isolated)) { if (!sstream.str().empty()) sstream << ", "; sstream << "Isolated"; } return std::string("{") + sstream.str() + std::string("}"); }; // Create the object list if (rsContext.bListShort) { std::vector> vecShortObjectList; vecShortObjectList.push_back({ "Object name" }); sdv::sequence seqObjects = pRepoInfo->GetObjectList(); for (const sdv::core::SObjectInfo& rsObjectInfo : seqObjects) vecShortObjectList.push_back({ rsObjectInfo.ssObjectName }); // Print the module list PrintTable(vecShortObjectList, rstream, rsContext.bListNoHdr); } else { std::vector> vecObjectList; vecObjectList.push_back({ "Object ID", "Class name", "Object name", "Type", "Flags", "Module ID" }); sdv::sequence seqObjects = pRepoInfo->GetObjectList(); for (const sdv::core::SObjectInfo& rsObjectInfo : seqObjects) vecObjectList.push_back({ std::to_string(static_cast(rsObjectInfo.tModuleID)), rsObjectInfo.sClassInfo.ssClassName, rsObjectInfo.ssObjectName, fnPrintClassType(rsObjectInfo.sClassInfo.eType), fnPrintObjectFlags(rsObjectInfo.uiFlags), std::to_string(static_cast(rsObjectInfo.tModuleID)) }); // Print the module list PrintTable(vecObjectList, rstream, rsContext.bListNoHdr); } return NO_ERROR; } int ListInstallations(const SContext& rsContext, const sdv::TObjectPtr& rptrRepository, std::ostream& rstream) { // Get access to the module control service sdv::core::IObjectAccess* pObjectAccess = rptrRepository.GetInterface(); const sdv::installation::IAppInstall* pAppInstall = nullptr; if (pObjectAccess) pAppInstall = sdv::TInterfaceAccessPtr(pObjectAccess->GetObject("ConfigService")). GetInterface(); if (!pAppInstall) { if (!rsContext.bSilent) std::cerr << "ERROR: " << CONFIG_SERVICE_ACCESS_ERROR_MSG << std::endl; return CONFIG_SERVICE_ACCESS_ERROR; } // Create the object list std::vector> vecInstallList; vecInstallList.push_back({"Installation"}); sdv::sequence seqInstallations = pAppInstall->GetInstallations(); for (const sdv::u8string& rssInstallation : seqInstallations) vecInstallList.push_back({ rssInstallation}); // Print the module list PrintTable(vecInstallList, rstream, rsContext.bListNoHdr); return NO_ERROR; } int ListConnections(const SContext& /*rsContext*/, const sdv::TObjectPtr& /*rptrRepository*/, std::ostream& /*rstream = std::cout */ ) { std::cout << "ERROR: " << NOT_IMPLEMENTED_MSG << " :-(" << std::endl; return NOT_IMPLEMENTED; }