From 201dbd54dba6fcde02266b53d489aed28aba4d92 Mon Sep 17 00:00:00 2001 From: Kevin Ottens Date: Thu, 10 Dec 2020 14:40:25 +0100 Subject: [PATCH] Remove the plugin loader mechanism for VFS backends We will have all the code in public anyway so it can just be compiled in. Thus no need to go through the plugin loading dance. Replaced the loading with factory functions. Kept mostly the same structure otherwise. Signed-off-by: Kevin Ottens --- src/common/common.cmake | 2 - src/common/plugin.cpp | 33 --------------- src/common/plugin.h | 48 ---------------------- src/common/vfs.cpp | 58 ++++++++------------------- src/common/vfs.h | 14 +++++++ src/libsync/CMakeLists.txt | 4 +- src/libsync/vfs/CMakeLists.txt | 25 ------------ src/libsync/vfs/suffix/CMakeLists.txt | 34 ---------------- src/libsync/vfs/suffix/vfs_suffix.cpp | 2 + src/libsync/vfs/suffix/vfs_suffix.h | 8 ---- 10 files changed, 34 insertions(+), 194 deletions(-) delete mode 100644 src/common/plugin.cpp delete mode 100644 src/common/plugin.h delete mode 100644 src/libsync/vfs/CMakeLists.txt delete mode 100644 src/libsync/vfs/suffix/CMakeLists.txt diff --git a/src/common/common.cmake b/src/common/common.cmake index 5c7cd52c9..82437cd04 100644 --- a/src/common/common.cmake +++ b/src/common/common.cmake @@ -11,8 +11,6 @@ set(common_SOURCES ${CMAKE_CURRENT_LIST_DIR}/remotepermissions.cpp ${CMAKE_CURRENT_LIST_DIR}/vfs.cpp ${CMAKE_CURRENT_LIST_DIR}/pinstate.cpp - ${CMAKE_CURRENT_LIST_DIR}/plugin.cpp ${CMAKE_CURRENT_LIST_DIR}/syncfilestatus.cpp ) -configure_file(${CMAKE_CURRENT_LIST_DIR}/vfspluginmetadata.json.in ${CMAKE_CURRENT_BINARY_DIR}/vfspluginmetadata.json) diff --git a/src/common/plugin.cpp b/src/common/plugin.cpp deleted file mode 100644 index 7e705d94e..000000000 --- a/src/common/plugin.cpp +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) by Dominik Schmidt - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "plugin.h" - -#include "config.h" - -namespace OCC { - -PluginFactory::~PluginFactory() = default; - -QString pluginFileName(const QString &type, const QString &name) -{ - return QStringLiteral("%1sync_%2_%3") - .arg(QStringLiteral(APPLICATION_EXECUTABLE), type, name); -} - -} diff --git a/src/common/plugin.h b/src/common/plugin.h deleted file mode 100644 index 3d28f7dd3..000000000 --- a/src/common/plugin.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) by Dominik Schmidt - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#pragma once - -#include "ocsynclib.h" -#include - -namespace OCC { - -class OCSYNC_EXPORT PluginFactory -{ -public: - virtual ~PluginFactory(); - virtual QObject* create(QObject* parent) = 0; -}; - -template -class DefaultPluginFactory : public PluginFactory -{ -public: - QObject* create(QObject *parent) override - { - return new PluginClass(parent); - } -}; - -/// Return the expected name of a plugin, for use with QPluginLoader -QString pluginFileName(const QString &type, const QString &name); - -} - -Q_DECLARE_INTERFACE(OCC::PluginFactory, "org.owncloud.PluginFactory") diff --git a/src/common/vfs.cpp b/src/common/vfs.cpp index 8c5c53d7b..b1bdb5324 100644 --- a/src/common/vfs.cpp +++ b/src/common/vfs.cpp @@ -17,7 +17,6 @@ */ #include "vfs.h" -#include "plugin.h" #include "version.h" #include "syncjournaldb.h" @@ -28,6 +27,15 @@ using namespace OCC; +using MetaObjectHash = QHash; +Q_GLOBAL_STATIC(MetaObjectHash, vfsFactoryHash); + +void Vfs::registerPlugin(const QString &name, Factory factory) +{ + Q_ASSERT(!vfsFactoryHash()->contains(name)); + vfsFactoryHash()->insert(name, factory); +} + Vfs::Vfs(QObject* parent) : QObject(parent) { @@ -150,33 +158,9 @@ bool OCC::isVfsPluginAvailable(Vfs::Mode mode) auto name = modeToPluginName(mode); if (name.isEmpty()) return false; - auto pluginPath = pluginFileName(QStringLiteral("vfs"), name); - QPluginLoader loader(pluginPath); - auto basemeta = loader.metaData(); - if (basemeta.isEmpty() || !basemeta.contains(QStringLiteral("IID"))) { - qCDebug(lcPlugin) << "Plugin doesn't exist" << loader.fileName(); - return false; - } - if (basemeta[QStringLiteral("IID")].toString() != QLatin1String("org.owncloud.PluginFactory")) { - qCWarning(lcPlugin) << "Plugin has wrong IID" << loader.fileName() << basemeta[QStringLiteral("IID")]; - return false; - } - - auto metadata = basemeta[QStringLiteral("MetaData")].toObject(); - if (metadata[QStringLiteral("type")].toString() != QLatin1String("vfs")) { - qCWarning(lcPlugin) << "Plugin has wrong type" << loader.fileName() << metadata[QStringLiteral("type")]; - return false; - } - if (metadata[QStringLiteral("version")].toString() != QStringLiteral(MIRALL_VERSION_STRING)) { - qCWarning(lcPlugin) << "Plugin has wrong version" << loader.fileName() << metadata[QStringLiteral("version")]; - return false; - } - - // Attempting to load the plugin is essential as it could have dependencies that - // can't be resolved and thus not be available after all. - if (!loader.load()) { - qCWarning(lcPlugin) << "Plugin failed to load:" << loader.errorString(); + if (!vfsFactoryHash()->contains(name)) { + qCDebug(lcPlugin) << "Plugin isn't registered:" << name; return false; } @@ -201,32 +185,24 @@ std::unique_ptr OCC::createVfsFromPlugin(Vfs::Mode mode) auto name = modeToPluginName(mode); if (name.isEmpty()) return nullptr; - auto pluginPath = pluginFileName(QStringLiteral("vfs"), name); if (!isVfsPluginAvailable(mode)) { - qCCritical(lcPlugin) << "Could not load plugin: not existant or bad metadata" << pluginPath; - return nullptr; - } - - QPluginLoader loader(pluginPath); - auto plugin = loader.instance(); - if (!plugin) { - qCCritical(lcPlugin) << "Could not load plugin" << pluginPath << loader.errorString(); + qCCritical(lcPlugin) << "Could not load plugin: not existant" << name; return nullptr; } - auto factory = qobject_cast(plugin); + const auto factory = vfsFactoryHash()->value(name); if (!factory) { - qCCritical(lcPlugin) << "Plugin" << loader.fileName() << "does not implement PluginFactory"; + qCCritical(lcPlugin) << "Could not load plugin" << name; return nullptr; } - auto vfs = std::unique_ptr(qobject_cast(factory->create(nullptr))); + auto vfs = std::unique_ptr(qobject_cast(factory())); if (!vfs) { - qCCritical(lcPlugin) << "Plugin" << loader.fileName() << "does not create a Vfs instance"; + qCCritical(lcPlugin) << "Plugin" << name << "does not create a Vfs instance"; return nullptr; } - qCInfo(lcPlugin) << "Created VFS instance from plugin" << pluginPath; + qCInfo(lcPlugin) << "Created VFS instance for:" << name; return vfs; } diff --git a/src/common/vfs.h b/src/common/vfs.h index c11f59bb2..66fae7e4b 100644 --- a/src/common/vfs.h +++ b/src/common/vfs.h @@ -14,6 +14,7 @@ #pragma once #include +#include #include #include @@ -111,6 +112,9 @@ public: using AvailabilityResult = Result; public: + using Factory = Vfs* (*)(); + static void registerPlugin(const QString &name, Factory factory); + explicit Vfs(QObject* parent = nullptr); virtual ~Vfs(); @@ -319,3 +323,13 @@ OCSYNC_EXPORT Vfs::Mode bestAvailableVfsMode(); OCSYNC_EXPORT std::unique_ptr createVfsFromPlugin(Vfs::Mode mode); } // namespace OCC + +#define OCC_DEFINE_VFS_FACTORY(name, Type) \ + static_assert (std::is_base_of::value, "Please define VFS factories only for OCC::Vfs subclasses"); \ + namespace { \ + void initPlugin() \ + { \ + OCC::Vfs::registerPlugin(QStringLiteral(name), []() -> OCC::Vfs * { return new Type; }); \ + } \ + Q_COREAPP_STARTUP_FUNCTION(initPlugin) \ + } diff --git a/src/libsync/CMakeLists.txt b/src/libsync/CMakeLists.txt index 72d2b26bf..35a4a9300 100644 --- a/src/libsync/CMakeLists.txt +++ b/src/libsync/CMakeLists.txt @@ -58,6 +58,7 @@ set(libsync_SRCS creds/abstractcredentials.cpp creds/credentialscommon.cpp creds/keychainchunk.cpp + vfs/suffix/vfs_suffix.cpp ) if(TOKEN_AUTH_ONLY) @@ -138,6 +139,3 @@ if(NOT BUILD_OWNCLOUD_OSX_BUNDLE) else() install(TARGETS ${synclib_NAME} DESTINATION ${OWNCLOUD_OSX_BUNDLE}/Contents/MacOS) endif() - - -add_subdirectory(vfs) diff --git a/src/libsync/vfs/CMakeLists.txt b/src/libsync/vfs/CMakeLists.txt deleted file mode 100644 index fec473b57..000000000 --- a/src/libsync/vfs/CMakeLists.txt +++ /dev/null @@ -1,25 +0,0 @@ -# Globbing for plugins has a problem with in-source builds -# that create directories for the build. -#file(GLOB VIRTUAL_FILE_SYSTEM_PLUGINS RELATIVE ${CMAKE_CURRENT_LIST_DIR} "*") - -list(APPEND VIRTUAL_FILE_SYSTEM_PLUGINS "suffix" "win") - -foreach(vfsPlugin ${VIRTUAL_FILE_SYSTEM_PLUGINS}) - set(vfsPluginPath ${vfsPlugin}) - get_filename_component(vfsPluginName ${vfsPlugin} NAME) - if (NOT IS_ABSOLUTE ${vfsPlugin}) - set(vfsPluginPath "${CMAKE_CURRENT_LIST_DIR}/${vfsPlugin}") - endif() - if(NOT IS_DIRECTORY ${vfsPluginPath}) - continue() - endif() - - add_subdirectory(${vfsPluginPath} ${vfsPluginName}) - - if(UNIT_TESTING AND IS_DIRECTORY "${vfsPluginPath}/test") - add_subdirectory("${vfsPluginPath}/test" "${vfsPluginName}_test") - message(STATUS "Added vfsPlugin with tests: ${vfsPluginName}") - else() - message(STATUS "Added vfsPlugin without tests: ${vfsPluginName}") - endif() -endforeach() diff --git a/src/libsync/vfs/suffix/CMakeLists.txt b/src/libsync/vfs/suffix/CMakeLists.txt deleted file mode 100644 index 3765e0285..000000000 --- a/src/libsync/vfs/suffix/CMakeLists.txt +++ /dev/null @@ -1,34 +0,0 @@ -add_library("${synclib_NAME}_vfs_suffix" SHARED - vfs_suffix.cpp -) - -target_link_libraries("${synclib_NAME}_vfs_suffix" - "${synclib_NAME}" -) - -set_target_properties("${synclib_NAME}_vfs_suffix" PROPERTIES - LIBRARY_OUTPUT_DIRECTORY ${BIN_OUTPUT_DIRECTORY} - RUNTIME_OUTPUT_DIRECTORY ${BIN_OUTPUT_DIRECTORY} - PREFIX "" - AUTOMOC TRUE -) - -if(APPLE) - # for being loadable when client run from build dir - set(vfs_buildoutputdir "${BIN_OUTPUT_DIRECTORY}/${OWNCLOUD_OSX_BUNDLE}/Contents/PlugIns/") - set_target_properties("${synclib_NAME}_vfs_suffix" - PROPERTIES - LIBRARY_OUTPUT_DIRECTORY ${vfs_buildoutputdir} - RUNTIME_OUTPUT_DIRECTORY ${vfs_buildoutputdir} - ) - # For being lodable when client run from install dir (after make macdeployqt) - set(vfs_installdir "${LIB_INSTALL_DIR}/../PlugIns") -else() - set(vfs_installdir "${PLUGINDIR}") -endif() - -INSTALL(TARGETS "${synclib_NAME}_vfs_suffix" - LIBRARY DESTINATION "${vfs_installdir}" - RUNTIME DESTINATION "${vfs_installdir}" -) - diff --git a/src/libsync/vfs/suffix/vfs_suffix.cpp b/src/libsync/vfs/suffix/vfs_suffix.cpp index be64b62a6..357d5c88e 100644 --- a/src/libsync/vfs/suffix/vfs_suffix.cpp +++ b/src/libsync/vfs/suffix/vfs_suffix.cpp @@ -152,3 +152,5 @@ Vfs::AvailabilityResult VfsSuffix::availability(const QString &folderPath) } } // namespace OCC + +OCC_DEFINE_VFS_FACTORY("suffix", OCC::VfsSuffix) diff --git a/src/libsync/vfs/suffix/vfs_suffix.h b/src/libsync/vfs/suffix/vfs_suffix.h index ce70c2ebb..3feca6ea0 100644 --- a/src/libsync/vfs/suffix/vfs_suffix.h +++ b/src/libsync/vfs/suffix/vfs_suffix.h @@ -17,7 +17,6 @@ #include #include "common/vfs.h" -#include "common/plugin.h" namespace OCC { @@ -61,11 +60,4 @@ protected: void startImpl(const VfsSetupParams ¶ms) override; }; -class SuffixVfsPluginFactory : public QObject, public DefaultPluginFactory -{ - Q_OBJECT - Q_PLUGIN_METADATA(IID "org.owncloud.PluginFactory" FILE "vfspluginmetadata.json") - Q_INTERFACES(OCC::PluginFactory) -}; - } // namespace OCC -- 2.30.2