From e5900bee28cc0a0a06cecbf50364ba2c65e6fd4b Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Fri, 3 Apr 2026 16:31:09 +0200 Subject: [PATCH] scripting: Add script provider helpers for files with single macros Adds a set of helpers to implement a script provider where the script files are the entire macro. The provider only needs to make a subclass of the abstract SingleScriptFactory class to provide the filename extension, language name and a method to convert the contents of a file to an XScript. The parts about handling file browsing and reading the file contents are in the shared helper code. This is based on the script provider from Luno. Change-Id: Id39f3a07e887898650b0d77ec493011fb5acc858 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/203216 Tested-by: Jenkins Reviewed-by: Neil Roberts --- Repository.mk | 1 + scripting/Library_singleprov.mk | 35 +++ scripting/Module_scripting.mk | 1 + scripting/README.md | 5 + .../source/inc/singleprov/scriptprovider.hxx | 101 +++++++ .../inc/singleprov/singlescriptfactory.hxx | 43 +++ scripting/source/singleprov/provcontext.cxx | 25 ++ scripting/source/singleprov/provcontext.hxx | 47 ++++ scripting/source/singleprov/scriptbrowser.cxx | 100 +++++++ scripting/source/singleprov/scriptbrowser.hxx | 76 ++++++ scripting/source/singleprov/scriptdir.cxx | 109 ++++++++ scripting/source/singleprov/scriptdir.hxx | 34 +++ scripting/source/singleprov/scriptfile.cxx | 44 ++++ scripting/source/singleprov/scriptfile.hxx | 30 +++ scripting/source/singleprov/scriptmacro.cxx | 85 ++++++ scripting/source/singleprov/scriptmacro.hxx | 43 +++ .../source/singleprov/scriptprovider.cxx | 248 ++++++++++++++++++ 17 files changed, 1027 insertions(+) create mode 100644 scripting/Library_singleprov.mk create mode 100644 scripting/source/inc/singleprov/scriptprovider.hxx create mode 100644 scripting/source/inc/singleprov/singlescriptfactory.hxx create mode 100644 scripting/source/singleprov/provcontext.cxx create mode 100644 scripting/source/singleprov/provcontext.hxx create mode 100644 scripting/source/singleprov/scriptbrowser.cxx create mode 100644 scripting/source/singleprov/scriptbrowser.hxx create mode 100644 scripting/source/singleprov/scriptdir.cxx create mode 100644 scripting/source/singleprov/scriptdir.hxx create mode 100644 scripting/source/singleprov/scriptfile.cxx create mode 100644 scripting/source/singleprov/scriptfile.hxx create mode 100644 scripting/source/singleprov/scriptmacro.cxx create mode 100644 scripting/source/singleprov/scriptmacro.hxx create mode 100644 scripting/source/singleprov/scriptprovider.cxx diff --git a/Repository.mk b/Repository.mk index 295e24404a4a..19853c205686 100644 --- a/Repository.mk +++ b/Repository.mk @@ -470,6 +470,7 @@ $(eval $(call gb_Helper_register_libraries_for_install,OOOLIBS,ooo, \ sd \ sdd \ sfx \ + singleprov \ slideshow \ sot \ $(if $(or $(DISABLE_GUI),$(ENABLE_WASM_STRIP_SPLASH)),,spl) \ diff --git a/scripting/Library_singleprov.mk b/scripting/Library_singleprov.mk new file mode 100644 index 000000000000..c1e7c88d913d --- /dev/null +++ b/scripting/Library_singleprov.mk @@ -0,0 +1,35 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t; fill-column: 100 -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_Library_Library,singleprov)) + +$(eval $(call gb_Library_use_sdk_api,singleprov)) + +$(eval $(call gb_Library_set_include,singleprov,\ + $$(INCLUDE) \ + -I$(SRCDIR)/scripting/source/inc \ +)) + +$(eval $(call gb_Library_use_libraries,singleprov,\ + comphelper \ + cppu \ + cppuhelper \ + sal \ +)) + +$(eval $(call gb_Library_add_exception_objects,singleprov,\ + scripting/source/singleprov/provcontext \ + scripting/source/singleprov/scriptbrowser \ + scripting/source/singleprov/scriptdir \ + scripting/source/singleprov/scriptfile \ + scripting/source/singleprov/scriptmacro \ + scripting/source/singleprov/scriptprovider \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/scripting/Module_scripting.mk b/scripting/Module_scripting.mk index 1d974e8e7c26..2c52f6656b03 100644 --- a/scripting/Module_scripting.mk +++ b/scripting/Module_scripting.mk @@ -40,6 +40,7 @@ $(eval $(call gb_Module_add_targets,scripting,\ Library_basprov \ Library_dlgprov \ Library_protocolhandler \ + Library_singleprov \ Library_scriptframe \ Library_stringresource \ Library_vbaevents \ diff --git a/scripting/README.md b/scripting/README.md index 0560a73b9786..0bfe4d184572 100644 --- a/scripting/README.md +++ b/scripting/README.md @@ -27,6 +27,11 @@ browsing and executing scripts. C++ for a `ProtocolHandler` implementation that handles `vnd.sun.star.script` URIs and dispatches them for execution to the Scripting Framework. +- `source/singleprov` + +A base helper class for C++ implementations of LanguageScriptProviders +that store a single macro in a source file. + - `source/basprov` C++ implementation of the `LanguageScriptProvider` UNO service for Basic diff --git a/scripting/source/inc/singleprov/scriptprovider.hxx b/scripting/source/inc/singleprov/scriptprovider.hxx new file mode 100644 index 000000000000..b6f0110ef704 --- /dev/null +++ b/scripting/source/inc/singleprov/scriptprovider.hxx @@ -0,0 +1,101 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace singleprovider +{ +class ProviderContext; +class ScriptBrowser; +class SingleScriptFactory; + +class ScriptProvider + : public cppu::WeakImplHelper +{ +public: + // XInitialization + void SAL_CALL initialize(const css::uno::Sequence& aArguments) override; + + // XServiceInfo + OUString SAL_CALL getImplementationName() override; + sal_Bool SAL_CALL supportsService(OUString const& serviceName) override; + css::uno::Sequence SAL_CALL getSupportedServiceNames() override; + + // XBrowseNode + OUString SAL_CALL getName() override; + css::uno::Sequence> + SAL_CALL getChildNodes() override; + sal_Bool SAL_CALL hasChildNodes() override; + sal_Int16 SAL_CALL getType() override; + + // XScriptProvider + css::uno::Reference + SAL_CALL getScript(const OUString& sScriptUri) override; + + // XPropertySet + css::uno::Reference SAL_CALL getPropertySetInfo() override; + void SAL_CALL setPropertyValue(const OUString& aPropertyName, + const css::uno::Any& aValue) override; + css::uno::Any SAL_CALL getPropertyValue(const OUString& sPropertyName) override; + void SAL_CALL addPropertyChangeListener( + const OUString& aPropertyName, + const css::uno::Reference& xListener) override; + void SAL_CALL removePropertyChangeListener( + const OUString& aPropertyName, + const css::uno::Reference& aListener) override; + void SAL_CALL addVetoableChangeListener( + const OUString& PropertyName, + const css::uno::Reference& aListener) override; + void SAL_CALL removeVetoableChangeListener( + const OUString& PropertyName, + const css::uno::Reference& aListener) override; + + // XInvocation + css::uno::Reference SAL_CALL getIntrospection() override; + css::uno::Any SAL_CALL invoke(const OUString& sFunctionName, + const css::uno::Sequence& aParams, + css::uno::Sequence& aOutParamIndex, + css::uno::Sequence& aOutParam) override; + void SAL_CALL setValue(const OUString& sPropertyName, const css::uno::Any& aValue) override; + css::uno::Any SAL_CALL getValue(const OUString& sPropertyName) override; + sal_Bool SAL_CALL hasMethod(const OUString& sName) override; + sal_Bool SAL_CALL hasProperty(const OUString& sName) override; + + static SAL_DLLPUBLIC_EXPORT OUString + getImplementationNameStatic(std::u16string_view sLanguageName); + static SAL_DLLPUBLIC_EXPORT css::uno::Sequence + getSupportedServiceNamesStatic(std::u16string_view sLanguageName); + static SAL_DLLPUBLIC_EXPORT css::uno::Reference + create(const css::uno::Reference& xContext, + const std::shared_ptr& pSingleScriptFactory); + +private: + ScriptProvider(const css::uno::Reference& xContext, + const std::shared_ptr& pSingleScriptFactory); + + void setLocation(const OUString& sLocation); + + std::shared_ptr m_pProviderContext; + css::uno::Reference m_xRootBrowser; +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/scripting/source/inc/singleprov/singlescriptfactory.hxx b/scripting/source/inc/singleprov/singlescriptfactory.hxx new file mode 100644 index 000000000000..c8332f4edb71 --- /dev/null +++ b/scripting/source/inc/singleprov/singlescriptfactory.hxx @@ -0,0 +1,43 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include +#include + +namespace com::sun::star::script::provider +{ +class XScript; +} + +namespace com::sun::star::uno +{ +class XComponentContext; +} + +namespace singleprovider +{ +// Abstract class to provide callbacks into the real script provider. The provider should be able to +// just provide an implementation of the class and pass it to singleprov::ScriptBrowser. +class SingleScriptFactory +{ +public: + virtual OUString getLanguageName() const = 0; + // Gets the extensions (including the ‘.’) for files that this factory is interested in + virtual OUString getExtension() const = 0; + // Given the source code, returns the XScript for the macro contained within + virtual css::uno::Reference + getScript(css::uno::Reference xContext, const OUString& sName, + std::string_view sSource) const = 0; + + virtual ~SingleScriptFactory() = default; +}; +} diff --git a/scripting/source/singleprov/provcontext.cxx b/scripting/source/singleprov/provcontext.cxx new file mode 100644 index 000000000000..ac750804c3d0 --- /dev/null +++ b/scripting/source/singleprov/provcontext.cxx @@ -0,0 +1,25 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "provcontext.hxx" + +#include + +namespace singleprovider +{ +ProviderContext::ProviderContext(const css::uno::Reference& xContext, + const std::shared_ptr& pSingleScriptFactory) + : m_xContext(xContext) + , m_pSingleScriptFactory(pSingleScriptFactory) + , m_xFileAccess(css::ucb::SimpleFileAccess::create(xContext)) +{ +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/scripting/source/singleprov/provcontext.hxx b/scripting/source/singleprov/provcontext.hxx new file mode 100644 index 000000000000..14d7c7e19e01 --- /dev/null +++ b/scripting/source/singleprov/provcontext.hxx @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include + +namespace com::sun::star::script::provider +{ +class XScriptURIHelper; +} + +namespace com::sun::star::uno +{ +class XComponentContext; +} + +namespace com::sun::star::ucb +{ +class XSimpleFileAccess3; +} + +namespace singleprovider +{ +class SingleScriptFactory; + +class ProviderContext +{ +public: + ProviderContext(const css::uno::Reference& xContext, + const std::shared_ptr& pSingleScriptFactory); + + css::uno::Reference m_xContext; + std::shared_ptr m_pSingleScriptFactory; + css::uno::Reference m_xUriHelper; + css::uno::Reference m_xFileAccess; +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/scripting/source/singleprov/scriptbrowser.cxx b/scripting/source/singleprov/scriptbrowser.cxx new file mode 100644 index 000000000000..c9676016e80d --- /dev/null +++ b/scripting/source/singleprov/scriptbrowser.cxx @@ -0,0 +1,100 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "scriptbrowser.hxx" + +#include + +#include + +#include "provcontext.hxx" + +namespace singleprovider +{ +ScriptBrowser::ScriptBrowser(const std::shared_ptr& pProviderContext, + const OUString& sName, const OUString& sBaseUri) + : m_pProviderContext(pProviderContext) + , m_sName(sName) + , m_sBaseUri(sBaseUri) +{ +} + +OUString SAL_CALL ScriptBrowser::getName() { return m_sName; } + +css::uno::Reference SAL_CALL ScriptBrowser::getPropertySetInfo() +{ + return this; +} + +void SAL_CALL ScriptBrowser::setPropertyValue(const OUString&, const css::uno::Any&) {} + +css::uno::Any SAL_CALL ScriptBrowser::getPropertyValue(const OUString& sPropertyName) +{ + throw css::beans::UnknownPropertyException("Tried to get unknown property " + sPropertyName); +} + +void SAL_CALL ScriptBrowser::addPropertyChangeListener( + const OUString&, const css::uno::Reference&) +{ +} + +void SAL_CALL ScriptBrowser::removePropertyChangeListener( + const OUString&, const css::uno::Reference&) +{ +} + +void SAL_CALL ScriptBrowser::addVetoableChangeListener( + const OUString&, const css::uno::Reference&) +{ +} + +void SAL_CALL ScriptBrowser::removeVetoableChangeListener( + const OUString&, const css::uno::Reference&) +{ +} + +css::uno::Sequence SAL_CALL ScriptBrowser::getProperties() +{ + return css::uno::Sequence(); +} + +css::beans::Property SAL_CALL ScriptBrowser::getPropertyByName(const OUString& sName) +{ + throw css::beans::UnknownPropertyException("Tried to retrieve unknown property " + sName); +} + +sal_Bool SAL_CALL ScriptBrowser::hasPropertyByName(const OUString&) { return false; } + +css::uno::Reference SAL_CALL ScriptBrowser::getIntrospection() +{ + return css::uno::Reference(); +} + +css::uno::Any SAL_CALL ScriptBrowser::invoke(const OUString& sMethodName, + const css::uno::Sequence&, + css::uno::Sequence&, + css::uno::Sequence&) +{ + throw css::lang::IllegalArgumentException("Tried to invoke unknown method " + sMethodName, + getXWeak(), 0); +} + +void SAL_CALL ScriptBrowser::setValue(const OUString&, const css::uno::Any&) {} + +css::uno::Any SAL_CALL ScriptBrowser::getValue(const OUString& sName) +{ + throw css::beans::UnknownPropertyException("Tried to get unknown property " + sName); +} + +sal_Bool SAL_CALL ScriptBrowser::hasMethod(const OUString&) { return false; } + +sal_Bool SAL_CALL ScriptBrowser::hasProperty(const OUString&) { return false; } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/scripting/source/singleprov/scriptbrowser.hxx b/scripting/source/singleprov/scriptbrowser.hxx new file mode 100644 index 000000000000..981220d0bb6c --- /dev/null +++ b/scripting/source/singleprov/scriptbrowser.hxx @@ -0,0 +1,76 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace singleprovider +{ +class ProviderContext; + +class ScriptBrowser + : public cppu::WeakImplHelper +{ +public: + // XBrowseNode + OUString SAL_CALL getName() override; + + // XPropertySet + css::uno::Reference SAL_CALL getPropertySetInfo() override; + void SAL_CALL setPropertyValue(const OUString& aPropertyName, + const css::uno::Any& aValue) override; + css::uno::Any SAL_CALL getPropertyValue(const OUString& sPropertyName) override; + void SAL_CALL addPropertyChangeListener( + const OUString& aPropertyName, + const css::uno::Reference& xListener) override; + void SAL_CALL removePropertyChangeListener( + const OUString& aPropertyName, + const css::uno::Reference& aListener) override; + void SAL_CALL addVetoableChangeListener( + const OUString& PropertyName, + const css::uno::Reference& aListener) override; + void SAL_CALL removeVetoableChangeListener( + const OUString& PropertyName, + const css::uno::Reference& aListener) override; + + // XPropertySetInfo + css::uno::Sequence SAL_CALL getProperties() override; + css::beans::Property SAL_CALL getPropertyByName(const OUString& sName) override; + sal_Bool SAL_CALL hasPropertyByName(const OUString& sName) override; + + // XInvocation + css::uno::Reference SAL_CALL getIntrospection() override; + css::uno::Any SAL_CALL invoke(const OUString& sFunctionName, + const css::uno::Sequence& aParams, + css::uno::Sequence& aOutParamIndex, + css::uno::Sequence& aOutParam) override; + void SAL_CALL setValue(const OUString& sPropertyName, const css::uno::Any& aValue) override; + css::uno::Any SAL_CALL getValue(const OUString& sPropertyName) override; + sal_Bool SAL_CALL hasMethod(const OUString& sName) override; + sal_Bool SAL_CALL hasProperty(const OUString& sName) override; + +protected: + ScriptBrowser(const std::shared_ptr& pProviderContext, const OUString& sName, + const OUString& sBaseUri); + + std::shared_ptr m_pProviderContext; + + OUString m_sName; + OUString m_sBaseUri; +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/scripting/source/singleprov/scriptdir.cxx b/scripting/source/singleprov/scriptdir.cxx new file mode 100644 index 000000000000..f6a5bd1f9dce --- /dev/null +++ b/scripting/source/singleprov/scriptdir.cxx @@ -0,0 +1,109 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "scriptdir.hxx" + +#include +#include +#include +#include +#include + +#include + +#include "provcontext.hxx" +#include "scriptfile.hxx" + +namespace singleprovider +{ +ScriptDir::ScriptDir(const std::shared_ptr& pProviderContext) + : ScriptDir(pProviderContext, pProviderContext->m_pSingleScriptFactory->getLanguageName(), + pProviderContext->m_xUriHelper->getRootStorageURI()) +{ +} + +ScriptDir::ScriptDir(const std::shared_ptr& pProviderContext, + const OUString& sName, const OUString& sBaseUri) + : ScriptBrowser(pProviderContext, sName, sBaseUri) +{ +} + +css::uno::Sequence> + SAL_CALL ScriptDir::getChildNodes() +{ + const css::uno::Reference& xFileAccess + = m_pProviderContext->m_xFileAccess; + + try + { + css::uno::Sequence aChildren = xFileAccess->getFolderContents(m_sBaseUri, true); + + std::vector> aNodes; + aNodes.reserve(aChildren.getLength()); + + OUString sExtension = m_pProviderContext->m_pSingleScriptFactory->getExtension(); + + for (int i = 0, nCount = aChildren.getLength(); i < nCount; ++i) + { + if (xFileAccess->isFolder(aChildren[i])) + { + OUString sName = nameFromUrl(aChildren[i]); + + aNodes.emplace_back(new ScriptDir(m_pProviderContext, sName, aChildren[i])); + } + else if (aChildren[i].endsWith(sExtension)) + { + OUString sName = nameFromUrl(aChildren[i]); + + aNodes.emplace_back(new ScriptFile(m_pProviderContext, sName, aChildren[i])); + } + } + + css::uno::Sequence> aNodesSequence( + aNodes.size()); + css::uno::Reference* pNodesSequence + = aNodesSequence.getArray(); + + for (int i = 0, nCount = aNodes.size(); i < nCount; ++i) + pNodesSequence[i] = std::move(aNodes[i]); + + return aNodesSequence; + } + catch (const css::uno::RuntimeException&) + { + throw; + } + catch (const css::uno::Exception&) + { + return css::uno::Sequence>(); + } +} + +sal_Bool SAL_CALL ScriptDir::hasChildNodes() { return true; } + +sal_Int16 SAL_CALL ScriptDir::getType() { return css::script::browse::BrowseNodeTypes::CONTAINER; } + +OUString ScriptDir::nameFromUrl(const OUString& sUrl) +{ + sal_Int32 nSlashPos = sUrl.lastIndexOf('/'); + sal_Int32 nStart = nSlashPos == -1 ? 0 : nSlashPos + 1; + + sal_Int32 nCount = sUrl.getLength() - nStart; + + OUString sExtension = m_pProviderContext->m_pSingleScriptFactory->getExtension(); + + if (sUrl.endsWith(sExtension)) + nCount -= sExtension.getLength(); + + return rtl::Uri::decode(sUrl.copy(nStart, nCount), rtl_UriDecodeWithCharset, + RTL_TEXTENCODING_UTF8); +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/scripting/source/singleprov/scriptdir.hxx b/scripting/source/singleprov/scriptdir.hxx new file mode 100644 index 000000000000..4100e4accdbc --- /dev/null +++ b/scripting/source/singleprov/scriptdir.hxx @@ -0,0 +1,34 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include "scriptbrowser.hxx" + +namespace singleprovider +{ +class ScriptDir : public ScriptBrowser +{ +public: + ScriptDir(const std::shared_ptr& pProviderContext); + ScriptDir(const std::shared_ptr& pProviderContext, const OUString& sName, + const OUString& sBaseUri); + + // XBrowseNode + css::uno::Sequence> + SAL_CALL getChildNodes() override; + sal_Bool SAL_CALL hasChildNodes() override; + sal_Int16 SAL_CALL getType() override; + +private: + OUString nameFromUrl(const OUString& sUrl); +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/scripting/source/singleprov/scriptfile.cxx b/scripting/source/singleprov/scriptfile.cxx new file mode 100644 index 000000000000..d085d870bb95 --- /dev/null +++ b/scripting/source/singleprov/scriptfile.cxx @@ -0,0 +1,44 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "scriptfile.hxx" + +#include +#include + +#include + +#include "provcontext.hxx" +#include "scriptmacro.hxx" + +namespace singleprovider +{ +ScriptFile::ScriptFile(const std::shared_ptr& pProviderContext, + const OUString& sName, const OUString& sBaseUri) + : ScriptBrowser(pProviderContext, sName, sBaseUri) +{ +} + +css::uno::Sequence> + SAL_CALL ScriptFile::getChildNodes() +{ + // Each file is treated as a container with a single macro inside it + css::uno::Sequence> aChild(1); + + aChild.getArray()[0].set(new ScriptMacro(m_pProviderContext, m_sName, m_sBaseUri)); + + return aChild; +} + +sal_Bool SAL_CALL ScriptFile::hasChildNodes() { return true; } + +sal_Int16 SAL_CALL ScriptFile::getType() { return css::script::browse::BrowseNodeTypes::CONTAINER; } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/scripting/source/singleprov/scriptfile.hxx b/scripting/source/singleprov/scriptfile.hxx new file mode 100644 index 000000000000..ebf5b75c4a82 --- /dev/null +++ b/scripting/source/singleprov/scriptfile.hxx @@ -0,0 +1,30 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include "scriptbrowser.hxx" + +namespace singleprovider +{ +class ScriptFile : public ScriptBrowser +{ +public: + ScriptFile(const std::shared_ptr& pProviderContext, const OUString& sName, + const OUString& sBaseUri); + + // XBrowseNode + css::uno::Sequence> + SAL_CALL getChildNodes() override; + sal_Bool SAL_CALL hasChildNodes() override; + sal_Int16 SAL_CALL getType() override; +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/scripting/source/singleprov/scriptmacro.cxx b/scripting/source/singleprov/scriptmacro.cxx new file mode 100644 index 000000000000..fcf6575fd8c8 --- /dev/null +++ b/scripting/source/singleprov/scriptmacro.cxx @@ -0,0 +1,85 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "scriptmacro.hxx" + +#include +#include +#include + +#include "provcontext.hxx" + +namespace singleprovider +{ +ScriptMacro::ScriptMacro(const std::shared_ptr& pProviderContext, + const OUString& sName, const OUString& sUri) + : ScriptBrowser(pProviderContext, sName, sUri) +{ +} + +css::uno::Sequence> + SAL_CALL ScriptMacro::getChildNodes() +{ + return css::uno::Sequence>(); +} + +sal_Bool SAL_CALL ScriptMacro::hasChildNodes() { return false; } + +sal_Int16 SAL_CALL ScriptMacro::getType() { return css::script::browse::BrowseNodeTypes::SCRIPT; } + +css::uno::Any SAL_CALL ScriptMacro::getPropertyValue(const OUString& sPropertyName) +{ + if (sPropertyName == "URI") + { + css::uno::Any xRet; + + xRet <<= m_pProviderContext->m_xUriHelper->getScriptURI(m_sBaseUri); + + return xRet; + } + else + return ScriptBrowser::getPropertyValue(sPropertyName); +} + +css::uno::Sequence SAL_CALL ScriptMacro::getProperties() +{ + const css::uno::Sequence aParentProperties + = ScriptBrowser::getProperties(); + + css::uno::Sequence aProperties(aParentProperties.getLength() + 1); + aProperties.getArray()[0] = getUriProperty(); + + std::copy(aParentProperties.begin(), aParentProperties.end(), aProperties.getArray() + 1); + + return aProperties; +} + +css::beans::Property SAL_CALL ScriptMacro::getPropertyByName(const OUString& sName) +{ + if (sName == "URI") + return getUriProperty(); + else + return ScriptBrowser::getPropertyByName(sName); +} + +sal_Bool SAL_CALL ScriptMacro::hasPropertyByName(const OUString& sName) +{ + if (sName == "URI") + return true; + else + return ScriptBrowser::hasPropertyByName(sName); +} + +css::beans::Property ScriptMacro::getUriProperty() +{ + return css::beans::Property("URI", 0, cppu::UnoType::get(), 0); +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/scripting/source/singleprov/scriptmacro.hxx b/scripting/source/singleprov/scriptmacro.hxx new file mode 100644 index 000000000000..dd12b7185926 --- /dev/null +++ b/scripting/source/singleprov/scriptmacro.hxx @@ -0,0 +1,43 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include "scriptbrowser.hxx" + +namespace singleprovider +{ +class ProviderContext; + +class ScriptMacro : public ScriptBrowser +{ +public: + ScriptMacro(const std::shared_ptr& pProviderContext, const OUString& sName, + const OUString& sUri); + + // XBrowseNode + css::uno::Sequence> + SAL_CALL getChildNodes() override; + sal_Bool SAL_CALL hasChildNodes() override; + sal_Int16 SAL_CALL getType() override; + + // XPropertySet + css::uno::Any SAL_CALL getPropertyValue(const OUString& sPropertyName) override; + + // XPropertySetInfo + css::uno::Sequence SAL_CALL getProperties() override; + css::beans::Property SAL_CALL getPropertyByName(const OUString& sName) override; + sal_Bool SAL_CALL hasPropertyByName(const OUString& sName) override; + +private: + static css::beans::Property getUriProperty(); +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/scripting/source/singleprov/scriptprovider.cxx b/scripting/source/singleprov/scriptprovider.cxx new file mode 100644 index 000000000000..eda1edd9032a --- /dev/null +++ b/scripting/source/singleprov/scriptprovider.cxx @@ -0,0 +1,248 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include +#include +#include +#include +#include + +#include + +#include "provcontext.hxx" +#include "scriptdir.hxx" + +namespace singleprovider +{ +ScriptProvider::ScriptProvider(const css::uno::Reference& xContext, + const std::shared_ptr& pSingleScriptFactory) + : m_pProviderContext(std::make_shared(xContext, pSingleScriptFactory)) +{ +} + +void SAL_CALL ScriptProvider::initialize(const css::uno::Sequence& aArguments) +{ + if (aArguments.getLength() > 0) + { + OUString sLocation; + if (aArguments[0] >>= sLocation) + setLocation(sLocation); + } +} + +void ScriptProvider::setLocation(const OUString& sLocation) +{ + OUString sLanguageName = m_pProviderContext->m_pSingleScriptFactory->getLanguageName(); + + m_pProviderContext->m_xUriHelper = css::script::provider::ScriptURIHelper::create( + m_pProviderContext->m_xContext, sLanguageName, sLocation); + m_xRootBrowser + = css::uno::Reference(new ScriptDir(m_pProviderContext)); +} + +OUString SAL_CALL ScriptProvider::getName() +{ + return m_pProviderContext->m_pSingleScriptFactory->getLanguageName(); +} + +css::uno::Sequence> + SAL_CALL ScriptProvider::getChildNodes() +{ + if (m_xRootBrowser.is()) + return m_xRootBrowser->getChildNodes(); + else + return css::uno::Sequence>(); +} + +sal_Bool SAL_CALL ScriptProvider::hasChildNodes() +{ + return m_xRootBrowser.is() && m_xRootBrowser->hasChildNodes(); +} + +sal_Int16 SAL_CALL ScriptProvider::getType() +{ + return m_xRootBrowser.is() ? m_xRootBrowser->getType() : 0; +} + +css::uno::Reference + SAL_CALL ScriptProvider::getScript(const OUString& sScriptUri) +{ + OUString sStorageUri = m_pProviderContext->m_xUriHelper->getStorageURI(sScriptUri); + + sal_Int32 nSlashPos = sStorageUri.lastIndexOf('/'); + OUString sName = sStorageUri.copy(nSlashPos == -1 ? 0 : nSlashPos + 1); + + try + { + std::vector aSource; + constexpr sal_Int32 nBufSize = 1024; + css::uno::Sequence aBuf(nBufSize); + + css::uno::Reference xIn + = m_pProviderContext->m_xFileAccess->openFileRead(sStorageUri); + + while (true) + { + sal_Int32 nBytesRead = xIn->readBytes(aBuf, aBuf.getLength()); + const char* pBuf = reinterpret_cast(aBuf.getConstArray()); + aSource.insert(aSource.end(), pBuf, pBuf + nBytesRead); + + if (nBytesRead < nBufSize) + break; + } + + return m_pProviderContext->m_pSingleScriptFactory->getScript( + m_pProviderContext->m_xContext, sName, + std::string_view(aSource.begin(), aSource.end())); + } + catch (const css::uno::Exception& e) + { + throw css::script::provider::ScriptFrameworkErrorException( + e.Message, static_cast(this), sName, + m_pProviderContext->m_pSingleScriptFactory->getLanguageName(), + css::script::provider::ScriptFrameworkErrorType::UNKNOWN); + } +} + +css::uno::Reference SAL_CALL ScriptProvider::getPropertySetInfo() +{ + css::uno::Reference xPropertySetInfo; + + css::uno::Reference xPropertySet(m_xRootBrowser, css::uno::UNO_QUERY); + + if (xPropertySet.is()) + xPropertySetInfo = xPropertySet->getPropertySetInfo(); + + return xPropertySetInfo; +} + +void SAL_CALL ScriptProvider::setPropertyValue(const OUString&, const css::uno::Any&) {} + +css::uno::Any SAL_CALL ScriptProvider::getPropertyValue(const OUString& sPropertyName) +{ + css::uno::Any xRet; + + css::uno::Reference xPropertySet(m_xRootBrowser, css::uno::UNO_QUERY); + + if (xPropertySet.is()) + xRet = xPropertySet->getPropertyValue(sPropertyName); + + return xRet; +} + +void SAL_CALL ScriptProvider::addPropertyChangeListener( + const OUString&, const css::uno::Reference&) +{ +} + +void SAL_CALL ScriptProvider::removePropertyChangeListener( + const OUString&, const css::uno::Reference&) +{ +} + +void SAL_CALL ScriptProvider::addVetoableChangeListener( + const OUString&, const css::uno::Reference&) +{ +} + +void SAL_CALL ScriptProvider::removeVetoableChangeListener( + const OUString&, const css::uno::Reference&) +{ +} + +css::uno::Reference SAL_CALL ScriptProvider::getIntrospection() +{ + return css::uno::Reference(); +} + +css::uno::Any SAL_CALL ScriptProvider::invoke(const OUString& sFunctionName, + const css::uno::Sequence& aParams, + css::uno::Sequence& aOutParamIndex, + css::uno::Sequence& aOutParam) +{ + css::uno::Any xRet; + + css::uno::Reference xInvocation(m_xRootBrowser, css::uno::UNO_QUERY); + + if (xInvocation.is()) + xRet = xInvocation->invoke(sFunctionName, aParams, aOutParamIndex, aOutParam); + + return xRet; +} + +void SAL_CALL ScriptProvider::setValue(const OUString&, const css::uno::Any&) {} + +css::uno::Any SAL_CALL ScriptProvider::getValue(const OUString&) { return css::uno::Any(); } + +sal_Bool SAL_CALL ScriptProvider::hasMethod(const OUString& sName) +{ + css::uno::Reference xInvocation(m_xRootBrowser, css::uno::UNO_QUERY); + + if (xInvocation.is()) + return xInvocation->hasMethod(sName); + else + return false; +} + +sal_Bool SAL_CALL ScriptProvider::hasProperty(const OUString&) { return false; } + +OUString SAL_CALL ScriptProvider::getImplementationName() +{ + return getImplementationNameStatic( + m_pProviderContext->m_pSingleScriptFactory->getLanguageName()); +} + +sal_Bool SAL_CALL ScriptProvider::supportsService(OUString const& serviceName) +{ + const css::uno::Sequence names = getSupportedServiceNames(); + const OUString* pNames = names.getConstArray(); + + for (sal_Int32 i = 0, count = names.getLength(); i < count; i++) + { + if (pNames[i] == serviceName) + return true; + } + + return false; +} + +css::uno::Sequence SAL_CALL ScriptProvider::getSupportedServiceNames() +{ + return getSupportedServiceNamesStatic( + m_pProviderContext->m_pSingleScriptFactory->getLanguageName()); +} + +SAL_DLLPUBLIC_EXPORT OUString +ScriptProvider::getImplementationNameStatic(std::u16string_view sLanguageName) +{ + return u"com.sun.star.singleprov.ScriptProviderFor"_ustr + sLanguageName; +} + +SAL_DLLPUBLIC_EXPORT css::uno::Sequence +ScriptProvider::getSupportedServiceNamesStatic(std::u16string_view sLanguageName) +{ + css::uno::Sequence names(2); + OUString* pNames = names.getArray(); + pNames[0] = u"com.sun.star.script.provider.ScriptProviderFor"_ustr + sLanguageName; + pNames[1] = "com.sun.star.script.provider.LanguageScriptProvider"; + return names; +} + +SAL_DLLPUBLIC_EXPORT css::uno::Reference +ScriptProvider::create(const css::uno::Reference& xContext, + const std::shared_ptr& pSingleScriptFactory) +{ + return static_cast( + new ScriptProvider(xContext, pSingleScriptFactory)); +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */