diff --git a/src/common/common.cmake b/src/common/common.cmake index 5c7cd52c90..82437cd04e 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 7e705d94e7..0000000000 --- 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 3d28f7dd3f..0000000000 --- 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 8c5c53d7b8..b1bdb5324f 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; + qCCritical(lcPlugin) << "Could not load plugin: not existant" << name; return nullptr; } - QPluginLoader loader(pluginPath); - auto plugin = loader.instance(); - if (!plugin) { - qCCritical(lcPlugin) << "Could not load plugin" << pluginPath << loader.errorString(); - 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 c11f59bb28..66fae7e4b2 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 72d2b26bf9..35a4a9300b 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 fec473b575..0000000000 --- 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 3765e02855..0000000000 --- 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 be64b62a6b..357d5c88ea 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 ce70c2ebbb..3feca6ea06 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