mirror of
https://github.com/nextcloud/desktop.git
synced 2024-11-23 13:35:58 +03:00
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 <kevin.ottens@nextcloud.com>
This commit is contained in:
parent
7e5f81ea81
commit
201dbd54db
10 changed files with 34 additions and 194 deletions
|
@ -11,8 +11,6 @@ set(common_SOURCES
|
||||||
${CMAKE_CURRENT_LIST_DIR}/remotepermissions.cpp
|
${CMAKE_CURRENT_LIST_DIR}/remotepermissions.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/vfs.cpp
|
${CMAKE_CURRENT_LIST_DIR}/vfs.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/pinstate.cpp
|
${CMAKE_CURRENT_LIST_DIR}/pinstate.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/plugin.cpp
|
|
||||||
${CMAKE_CURRENT_LIST_DIR}/syncfilestatus.cpp
|
${CMAKE_CURRENT_LIST_DIR}/syncfilestatus.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
configure_file(${CMAKE_CURRENT_LIST_DIR}/vfspluginmetadata.json.in ${CMAKE_CURRENT_BINARY_DIR}/vfspluginmetadata.json)
|
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) by Dominik Schmidt <dschmidt@owncloud.com>
|
|
||||||
*
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,48 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) by Dominik Schmidt <dschmidt@owncloud.com>
|
|
||||||
*
|
|
||||||
* 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 <QObject>
|
|
||||||
|
|
||||||
namespace OCC {
|
|
||||||
|
|
||||||
class OCSYNC_EXPORT PluginFactory
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual ~PluginFactory();
|
|
||||||
virtual QObject* create(QObject* parent) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class PluginClass>
|
|
||||||
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")
|
|
|
@ -17,7 +17,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "vfs.h"
|
#include "vfs.h"
|
||||||
#include "plugin.h"
|
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "syncjournaldb.h"
|
#include "syncjournaldb.h"
|
||||||
|
|
||||||
|
@ -28,6 +27,15 @@
|
||||||
|
|
||||||
using namespace OCC;
|
using namespace OCC;
|
||||||
|
|
||||||
|
using MetaObjectHash = QHash<QString, Vfs::Factory>;
|
||||||
|
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)
|
Vfs::Vfs(QObject* parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
{
|
{
|
||||||
|
@ -150,33 +158,9 @@ bool OCC::isVfsPluginAvailable(Vfs::Mode mode)
|
||||||
auto name = modeToPluginName(mode);
|
auto name = modeToPluginName(mode);
|
||||||
if (name.isEmpty())
|
if (name.isEmpty())
|
||||||
return false;
|
return false;
|
||||||
auto pluginPath = pluginFileName(QStringLiteral("vfs"), name);
|
|
||||||
QPluginLoader loader(pluginPath);
|
|
||||||
|
|
||||||
auto basemeta = loader.metaData();
|
if (!vfsFactoryHash()->contains(name)) {
|
||||||
if (basemeta.isEmpty() || !basemeta.contains(QStringLiteral("IID"))) {
|
qCDebug(lcPlugin) << "Plugin isn't registered:" << name;
|
||||||
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();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,32 +185,24 @@ std::unique_ptr<Vfs> OCC::createVfsFromPlugin(Vfs::Mode mode)
|
||||||
auto name = modeToPluginName(mode);
|
auto name = modeToPluginName(mode);
|
||||||
if (name.isEmpty())
|
if (name.isEmpty())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
auto pluginPath = pluginFileName(QStringLiteral("vfs"), name);
|
|
||||||
|
|
||||||
if (!isVfsPluginAvailable(mode)) {
|
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;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
QPluginLoader loader(pluginPath);
|
const auto factory = vfsFactoryHash()->value(name);
|
||||||
auto plugin = loader.instance();
|
|
||||||
if (!plugin) {
|
|
||||||
qCCritical(lcPlugin) << "Could not load plugin" << pluginPath << loader.errorString();
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto factory = qobject_cast<PluginFactory *>(plugin);
|
|
||||||
if (!factory) {
|
if (!factory) {
|
||||||
qCCritical(lcPlugin) << "Plugin" << loader.fileName() << "does not implement PluginFactory";
|
qCCritical(lcPlugin) << "Could not load plugin" << name;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto vfs = std::unique_ptr<Vfs>(qobject_cast<Vfs *>(factory->create(nullptr)));
|
auto vfs = std::unique_ptr<Vfs>(qobject_cast<Vfs *>(factory()));
|
||||||
if (!vfs) {
|
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;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
qCInfo(lcPlugin) << "Created VFS instance from plugin" << pluginPath;
|
qCInfo(lcPlugin) << "Created VFS instance for:" << name;
|
||||||
return vfs;
|
return vfs;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QCoreApplication>
|
||||||
#include <QScopedPointer>
|
#include <QScopedPointer>
|
||||||
#include <QSharedPointer>
|
#include <QSharedPointer>
|
||||||
|
|
||||||
|
@ -111,6 +112,9 @@ public:
|
||||||
using AvailabilityResult = Result<VfsItemAvailability, AvailabilityError>;
|
using AvailabilityResult = Result<VfsItemAvailability, AvailabilityError>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
using Factory = Vfs* (*)();
|
||||||
|
static void registerPlugin(const QString &name, Factory factory);
|
||||||
|
|
||||||
explicit Vfs(QObject* parent = nullptr);
|
explicit Vfs(QObject* parent = nullptr);
|
||||||
virtual ~Vfs();
|
virtual ~Vfs();
|
||||||
|
|
||||||
|
@ -319,3 +323,13 @@ OCSYNC_EXPORT Vfs::Mode bestAvailableVfsMode();
|
||||||
OCSYNC_EXPORT std::unique_ptr<Vfs> createVfsFromPlugin(Vfs::Mode mode);
|
OCSYNC_EXPORT std::unique_ptr<Vfs> createVfsFromPlugin(Vfs::Mode mode);
|
||||||
|
|
||||||
} // namespace OCC
|
} // namespace OCC
|
||||||
|
|
||||||
|
#define OCC_DEFINE_VFS_FACTORY(name, Type) \
|
||||||
|
static_assert (std::is_base_of<OCC::Vfs, Type>::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) \
|
||||||
|
}
|
||||||
|
|
|
@ -58,6 +58,7 @@ set(libsync_SRCS
|
||||||
creds/abstractcredentials.cpp
|
creds/abstractcredentials.cpp
|
||||||
creds/credentialscommon.cpp
|
creds/credentialscommon.cpp
|
||||||
creds/keychainchunk.cpp
|
creds/keychainchunk.cpp
|
||||||
|
vfs/suffix/vfs_suffix.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
if(TOKEN_AUTH_ONLY)
|
if(TOKEN_AUTH_ONLY)
|
||||||
|
@ -138,6 +139,3 @@ if(NOT BUILD_OWNCLOUD_OSX_BUNDLE)
|
||||||
else()
|
else()
|
||||||
install(TARGETS ${synclib_NAME} DESTINATION ${OWNCLOUD_OSX_BUNDLE}/Contents/MacOS)
|
install(TARGETS ${synclib_NAME} DESTINATION ${OWNCLOUD_OSX_BUNDLE}/Contents/MacOS)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
add_subdirectory(vfs)
|
|
||||||
|
|
|
@ -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()
|
|
|
@ -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}"
|
|
||||||
)
|
|
||||||
|
|
|
@ -152,3 +152,5 @@ Vfs::AvailabilityResult VfsSuffix::availability(const QString &folderPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace OCC
|
} // namespace OCC
|
||||||
|
|
||||||
|
OCC_DEFINE_VFS_FACTORY("suffix", OCC::VfsSuffix)
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
#include <QScopedPointer>
|
#include <QScopedPointer>
|
||||||
|
|
||||||
#include "common/vfs.h"
|
#include "common/vfs.h"
|
||||||
#include "common/plugin.h"
|
|
||||||
|
|
||||||
namespace OCC {
|
namespace OCC {
|
||||||
|
|
||||||
|
@ -61,11 +60,4 @@ protected:
|
||||||
void startImpl(const VfsSetupParams ¶ms) override;
|
void startImpl(const VfsSetupParams ¶ms) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SuffixVfsPluginFactory : public QObject, public DefaultPluginFactory<VfsSuffix>
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
Q_PLUGIN_METADATA(IID "org.owncloud.PluginFactory" FILE "vfspluginmetadata.json")
|
|
||||||
Q_INTERFACES(OCC::PluginFactory)
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace OCC
|
} // namespace OCC
|
||||||
|
|
Loading…
Reference in a new issue