diff options
Diffstat (limited to 'scripting/source/basprov')
-rw-r--r-- | scripting/source/basprov/baslibnode.cxx | 130 | ||||
-rw-r--r-- | scripting/source/basprov/baslibnode.hxx | 70 | ||||
-rw-r--r-- | scripting/source/basprov/basmethnode.cxx | 291 | ||||
-rw-r--r-- | scripting/source/basprov/basmethnode.hxx | 108 | ||||
-rw-r--r-- | scripting/source/basprov/basmodnode.cxx | 134 | ||||
-rw-r--r-- | scripting/source/basprov/basmodnode.hxx | 64 | ||||
-rw-r--r-- | scripting/source/basprov/basprov.component | 29 | ||||
-rw-r--r-- | scripting/source/basprov/basprov.cxx | 477 | ||||
-rw-r--r-- | scripting/source/basprov/basprov.hxx | 97 | ||||
-rw-r--r-- | scripting/source/basprov/basscript.cxx | 314 | ||||
-rw-r--r-- | scripting/source/basprov/basscript.hxx | 103 |
11 files changed, 1817 insertions, 0 deletions
diff --git a/scripting/source/basprov/baslibnode.cxx b/scripting/source/basprov/baslibnode.cxx new file mode 100644 index 000000000..33942c6b2 --- /dev/null +++ b/scripting/source/basprov/baslibnode.cxx @@ -0,0 +1,130 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "baslibnode.hxx" +#include "basmodnode.hxx" +#include <com/sun/star/script/browse/BrowseNodeTypes.hpp> +#include <comphelper/sequence.hxx> +#include <vcl/svapp.hxx> +#include <basic/basmgr.hxx> +#include <basic/sbstar.hxx> + + +using namespace ::com::sun::star; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::script; + + +namespace basprov +{ + + + // BasicLibraryNodeImpl + + + BasicLibraryNodeImpl::BasicLibraryNodeImpl( const Reference< XComponentContext >& rxContext, + const OUString& sScriptingContext, BasicManager* pBasicManager, + const Reference< script::XLibraryContainer >& xLibContainer, const OUString& sLibName, bool isAppScript ) + :m_xContext( rxContext ) + ,m_sScriptingContext( sScriptingContext ) + ,m_pBasicManager( pBasicManager ) + ,m_xLibContainer( xLibContainer ) + ,m_sLibName( sLibName ) + ,m_bIsAppScript( isAppScript ) + { + if ( m_xLibContainer.is() ) + { + Any aElement = m_xLibContainer->getByName( m_sLibName ); + aElement >>= m_xLibrary; + } + } + + + BasicLibraryNodeImpl::~BasicLibraryNodeImpl() + { + } + + + // XBrowseNode + + + OUString BasicLibraryNodeImpl::getName( ) + { + SolarMutexGuard aGuard; + + return m_sLibName; + } + + + Sequence< Reference< browse::XBrowseNode > > BasicLibraryNodeImpl::getChildNodes( ) + { + SolarMutexGuard aGuard; + + std::vector< Reference< browse::XBrowseNode > > aChildNodes; + + if ( m_xLibContainer.is() && m_xLibContainer->hasByName( m_sLibName ) && !m_xLibContainer->isLibraryLoaded( m_sLibName ) ) + m_xLibContainer->loadLibrary( m_sLibName ); + + if ( m_pBasicManager ) + { + StarBASIC* pBasic = m_pBasicManager->GetLib( m_sLibName ); + if ( pBasic && m_xLibrary.is() ) + { + Sequence< OUString > aNames = m_xLibrary->getElementNames(); + sal_Int32 nCount = aNames.getLength(); + const OUString* pNames = aNames.getConstArray(); + aChildNodes.resize( nCount ); + + for ( sal_Int32 i = 0 ; i < nCount ; ++i ) + { + SbModule* pModule = pBasic->FindModule( pNames[i] ); + if ( pModule ) + aChildNodes[i] = new BasicModuleNodeImpl(m_xContext, m_sScriptingContext, + pModule, m_bIsAppScript); + } + } + } + + return comphelper::containerToSequence(aChildNodes); + } + + + sal_Bool BasicLibraryNodeImpl::hasChildNodes( ) + { + SolarMutexGuard aGuard; + + bool bReturn = false; + if ( m_xLibrary.is() ) + bReturn = m_xLibrary->hasElements(); + + return bReturn; + } + + + sal_Int16 BasicLibraryNodeImpl::getType( ) + { + return browse::BrowseNodeTypes::CONTAINER; + } + + +} // namespace basprov + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/scripting/source/basprov/baslibnode.hxx b/scripting/source/basprov/baslibnode.hxx new file mode 100644 index 000000000..46d31aae5 --- /dev/null +++ b/scripting/source/basprov/baslibnode.hxx @@ -0,0 +1,70 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <com/sun/star/script/XLibraryContainer.hpp> +#include <com/sun/star/script/browse/XBrowseNode.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <cppuhelper/implbase.hxx> + +class BasicManager; + + +namespace basprov +{ + + + + + typedef ::cppu::WeakImplHelper< + css::script::browse::XBrowseNode > BasicLibraryNodeImpl_BASE; + + + class BasicLibraryNodeImpl : public BasicLibraryNodeImpl_BASE + { + private: + css::uno::Reference< css::uno::XComponentContext > m_xContext; + OUString m_sScriptingContext; + BasicManager* m_pBasicManager; + css::uno::Reference< css::script::XLibraryContainer > m_xLibContainer; + css::uno::Reference< css::container::XNameContainer > m_xLibrary; + OUString m_sLibName; + bool m_bIsAppScript; + + public: + BasicLibraryNodeImpl( const css::uno::Reference< css::uno::XComponentContext >& rxContext, + const OUString& sScriptingContext, + BasicManager* pBasicManager, + const css::uno::Reference< css::script::XLibraryContainer >& xLibContainer, + const OUString& sLibName, bool isAppScript ); + virtual ~BasicLibraryNodeImpl() override; + + // XBrowseNode + virtual OUString SAL_CALL getName( ) override; + virtual css::uno::Sequence< css::uno::Reference< css::script::browse::XBrowseNode > > SAL_CALL getChildNodes( ) override; + virtual sal_Bool SAL_CALL hasChildNodes( ) override; + virtual sal_Int16 SAL_CALL getType( ) override; + }; + + +} // namespace basprov + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/scripting/source/basprov/basmethnode.cxx b/scripting/source/basprov/basmethnode.cxx new file mode 100644 index 000000000..fca2cafe8 --- /dev/null +++ b/scripting/source/basprov/basmethnode.cxx @@ -0,0 +1,291 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "basmethnode.hxx" +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/frame/DispatchHelper.hpp> +#include <com/sun/star/frame/Desktop.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/script/browse/BrowseNodeTypes.hpp> + +#include <comphelper/propertyvalue.hxx> +#include <vcl/svapp.hxx> +#include <basic/sbstar.hxx> +#include <basic/sbmeth.hxx> +#include <basic/sbmod.hxx> + +#include <util/MiscUtils.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::comphelper; +using namespace ::com::sun::star::script; +using namespace ::sf_misc; + +#define BASPROV_PROPERTY_ID_URI 1 +#define BASPROV_PROPERTY_ID_EDITABLE 2 + +constexpr OUStringLiteral BASPROV_PROPERTY_URI = u"URI"; +constexpr OUStringLiteral BASPROV_PROPERTY_EDITABLE = u"Editable"; + +#define BASPROV_DEFAULT_ATTRIBS() PropertyAttribute::BOUND | PropertyAttribute::TRANSIENT | PropertyAttribute::READONLY + + +namespace basprov +{ + + + // BasicMethodNodeImpl + + + BasicMethodNodeImpl::BasicMethodNodeImpl( const Reference< XComponentContext >& rxContext, + const OUString& sScriptingContext, SbMethod* pMethod, bool isAppScript ) + : ::scripting_helper::OBroadcastHelperHolder( m_aMutex ) + ,OPropertyContainer( GetBroadcastHelper() ) + ,m_xContext( rxContext ) + ,m_sScriptingContext( sScriptingContext ) + ,m_pMethod( pMethod ) + ,m_bIsAppScript( isAppScript ) + ,m_bEditable( true ) + { + if ( m_pMethod ) + { + SbModule* pModule = m_pMethod->GetModule(); + if ( pModule ) + { + StarBASIC* pBasic = static_cast< StarBASIC* >( pModule->GetParent() ); + if ( pBasic ) + { + m_sURI = "vnd.sun.star.script:"; + m_sURI += pBasic->GetName(); + m_sURI += "."; + m_sURI += pModule->GetName(); + m_sURI += "."; + m_sURI += m_pMethod->GetName(); + m_sURI += "?language=Basic&location="; + if ( m_bIsAppScript ) + m_sURI += "application"; + else + m_sURI += "document"; + } + } + } + + registerProperty( BASPROV_PROPERTY_URI, BASPROV_PROPERTY_ID_URI, BASPROV_DEFAULT_ATTRIBS(), &m_sURI, cppu::UnoType<decltype(m_sURI)>::get() ); + registerProperty( BASPROV_PROPERTY_EDITABLE, BASPROV_PROPERTY_ID_EDITABLE, BASPROV_DEFAULT_ATTRIBS(), &m_bEditable, cppu::UnoType<decltype(m_bEditable)>::get() ); + } + + + BasicMethodNodeImpl::~BasicMethodNodeImpl() + { + } + + + // XInterface + + + IMPLEMENT_FORWARD_XINTERFACE2( BasicMethodNodeImpl, BasicMethodNodeImpl_BASE, OPropertyContainer ) + + + // XTypeProvider + + + IMPLEMENT_FORWARD_XTYPEPROVIDER2( BasicMethodNodeImpl, BasicMethodNodeImpl_BASE, OPropertyContainer ) + + + // XBrowseNode + + + OUString BasicMethodNodeImpl::getName( ) + { + SolarMutexGuard aGuard; + + OUString sMethodName; + if ( m_pMethod ) + sMethodName = m_pMethod->GetName(); + + return sMethodName; + } + + + Sequence< Reference< browse::XBrowseNode > > BasicMethodNodeImpl::getChildNodes( ) + { + return Sequence< Reference< browse::XBrowseNode > >(); + } + + + sal_Bool BasicMethodNodeImpl::hasChildNodes( ) + { + return false; + } + + + sal_Int16 BasicMethodNodeImpl::getType( ) + { + return browse::BrowseNodeTypes::SCRIPT; + } + + + // OPropertySetHelper + + + ::cppu::IPropertyArrayHelper& BasicMethodNodeImpl::getInfoHelper( ) + { + return *getArrayHelper(); + } + + + // OPropertyArrayUsageHelper + + + ::cppu::IPropertyArrayHelper* BasicMethodNodeImpl::createArrayHelper( ) const + { + Sequence< Property > aProps; + describeProperties( aProps ); + return new ::cppu::OPropertyArrayHelper( aProps ); + } + + + // XPropertySet + + + Reference< XPropertySetInfo > BasicMethodNodeImpl::getPropertySetInfo( ) + { + Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) ); + return xInfo; + } + + + // XInvocation + + + Reference< XIntrospectionAccess > BasicMethodNodeImpl::getIntrospection( ) + { + return Reference< XIntrospectionAccess >(); + } + + + Any BasicMethodNodeImpl::invoke( const OUString& aFunctionName, const Sequence< Any >&, + Sequence< sal_Int16 >&, Sequence< Any >& ) + { + if ( aFunctionName != BASPROV_PROPERTY_EDITABLE ) + { + throw IllegalArgumentException( + "BasicMethodNodeImpl::invoke: function name not supported!", + Reference< XInterface >(), 1 ); + } + + OUString sDocURL, sLibName, sModName; + sal_uInt16 nLine1 = 0; + + if ( !m_bIsAppScript ) + { + Reference< frame::XModel > xModel = MiscUtils::tDocUrlToModel( m_sScriptingContext ); + + if ( xModel.is() ) + { + sDocURL = xModel->getURL(); + if ( sDocURL.isEmpty() ) + { + const Sequence < PropertyValue > aProps = xModel->getArgs(); + // TODO: according to MBA the property 'Title' may change in future + const PropertyValue* pProp = std::find_if(aProps.begin(), aProps.end(), + [](const PropertyValue& rProp) { return rProp.Name == "Title"; }); + if (pProp != aProps.end()) + pProp->Value >>= sDocURL; + } + } + } + + if ( m_pMethod ) + { + sal_uInt16 nLine2; + m_pMethod->GetLineRange( nLine1, nLine2 ); + SbModule* pModule = m_pMethod->GetModule(); + if ( pModule ) + { + sModName = pModule->GetName(); + StarBASIC* pBasic = static_cast< StarBASIC* >( pModule->GetParent() ); + if ( pBasic ) + sLibName = pBasic->GetName(); + } + } + + if ( m_xContext.is() ) + { + Reference< frame::XDesktop2 > xDesktop = frame::Desktop::create( m_xContext ); + + Reference < frame::XDispatchProvider > xProv( xDesktop->getCurrentFrame(), UNO_QUERY ); + + if ( xProv.is() ) + { + Reference< frame::XDispatchHelper > xHelper( frame::DispatchHelper::create( m_xContext ) ); + + Sequence < PropertyValue > aArgs{ + comphelper::makePropertyValue("Document", sDocURL), + comphelper::makePropertyValue("LibName", sLibName), + comphelper::makePropertyValue("Name", sModName), + comphelper::makePropertyValue("Type", OUString("Module")), + comphelper::makePropertyValue("Line", static_cast< sal_uInt32 >( nLine1 )) + }; + xHelper->executeDispatch( xProv, ".uno:BasicIDEAppear", OUString(), 0, aArgs ); + } + } + + + return Any(); + } + + + void BasicMethodNodeImpl::setValue( const OUString&, const Any& ) + { + throw UnknownPropertyException( + "BasicMethodNodeImpl::setValue: property name is unknown!" ); + } + + + Any BasicMethodNodeImpl::getValue( const OUString& ) + { + throw UnknownPropertyException( + "BasicMethodNodeImpl::getValue: property name is unknown!" ); + } + + + sal_Bool BasicMethodNodeImpl::hasMethod( const OUString& aName ) + { + bool bReturn = false; + if ( aName == BASPROV_PROPERTY_EDITABLE ) + bReturn = true; + + return bReturn; + } + + + sal_Bool BasicMethodNodeImpl::hasProperty( const OUString& ) + { + return false; + } + + +} // namespace basprov + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/scripting/source/basprov/basmethnode.hxx b/scripting/source/basprov/basmethnode.hxx new file mode 100644 index 000000000..d1eddada0 --- /dev/null +++ b/scripting/source/basprov/basmethnode.hxx @@ -0,0 +1,108 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <bcholder.hxx> +#include <com/sun/star/beans/XPropertySetInfo.hpp> +#include <com/sun/star/script/XInvocation.hpp> +#include <com/sun/star/script/browse/XBrowseNode.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <comphelper/proparrhlp.hxx> +#include <comphelper/propertycontainer.hxx> +#include <comphelper/uno3.hxx> +#include <cppuhelper/basemutex.hxx> +#include <cppuhelper/implbase.hxx> + + +class SbMethod; + + +namespace basprov +{ + + + + + typedef ::cppu::WeakImplHelper< + css::script::browse::XBrowseNode, + css::script::XInvocation > BasicMethodNodeImpl_BASE; + + class BasicMethodNodeImpl : public BasicMethodNodeImpl_BASE, + public cppu::BaseMutex, + public ::scripting_helper::OBroadcastHelperHolder, + public ::comphelper::OPropertyContainer, + public ::comphelper::OPropertyArrayUsageHelper< BasicMethodNodeImpl > + { + private: + css::uno::Reference< css::uno::XComponentContext > m_xContext; + OUString m_sScriptingContext; + SbMethod* m_pMethod; + bool m_bIsAppScript; + + // properties + OUString m_sURI; + bool m_bEditable; + + protected: + // OPropertySetHelper + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper( ) override; + + // OPropertyArrayUsageHelper + virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const override; + + public: + BasicMethodNodeImpl( const css::uno::Reference< css::uno::XComponentContext >& rxContext, + const OUString& sScriptingContext, + SbMethod* pMethod, bool isAppScript ); + virtual ~BasicMethodNodeImpl() override; + + // XInterface + DECLARE_XINTERFACE() + + // XTypeProvider + DECLARE_XTYPEPROVIDER() + + // XBrowseNode + virtual OUString SAL_CALL getName( ) override; + virtual css::uno::Sequence< css::uno::Reference< css::script::browse::XBrowseNode > > SAL_CALL getChildNodes( ) override; + virtual sal_Bool SAL_CALL hasChildNodes( ) override; + virtual sal_Int16 SAL_CALL getType( ) override; + + // XPropertySet + virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override; + + // XInvocation + virtual css::uno::Reference< css::beans::XIntrospectionAccess > SAL_CALL getIntrospection( ) override; + virtual css::uno::Any SAL_CALL invoke( + const OUString& aFunctionName, + const css::uno::Sequence< css::uno::Any >& aParams, + css::uno::Sequence< sal_Int16 >& aOutParamIndex, + css::uno::Sequence< css::uno::Any >& aOutParam ) override; + virtual void SAL_CALL setValue( const OUString& aPropertyName, const css::uno::Any& aValue ) override; + virtual css::uno::Any SAL_CALL getValue( const OUString& aPropertyName ) override; + virtual sal_Bool SAL_CALL hasMethod( const OUString& aName ) override; + virtual sal_Bool SAL_CALL hasProperty( const OUString& aName ) override; + }; + + +} // namespace basprov + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/scripting/source/basprov/basmodnode.cxx b/scripting/source/basprov/basmodnode.cxx new file mode 100644 index 000000000..986e3062d --- /dev/null +++ b/scripting/source/basprov/basmodnode.cxx @@ -0,0 +1,134 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "basmodnode.hxx" +#include "basmethnode.hxx" +#include <com/sun/star/script/browse/BrowseNodeTypes.hpp> +#include <vcl/svapp.hxx> +#include <basic/sbx.hxx> +#include <basic/sbmod.hxx> +#include <basic/sbmeth.hxx> + + +using namespace ::com::sun::star; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::script; + + +namespace basprov +{ + + + // BasicModuleNodeImpl + + + BasicModuleNodeImpl::BasicModuleNodeImpl( const Reference< XComponentContext >& rxContext, + const OUString& sScriptingContext, SbModule* pModule, bool isAppScript ) + :m_xContext( rxContext ) + ,m_sScriptingContext( sScriptingContext ) + ,m_pModule( pModule ) + ,m_bIsAppScript( isAppScript ) + { + } + + + BasicModuleNodeImpl::~BasicModuleNodeImpl() + { + } + + + // XBrowseNode + + + OUString BasicModuleNodeImpl::getName( ) + { + SolarMutexGuard aGuard; + + OUString sModuleName; + if ( m_pModule ) + sModuleName = m_pModule->GetName(); + + return sModuleName; + } + + + Sequence< Reference< browse::XBrowseNode > > BasicModuleNodeImpl::getChildNodes( ) + { + SolarMutexGuard aGuard; + + Sequence< Reference< browse::XBrowseNode > > aChildNodes; + + if ( m_pModule ) + { + SbxArray* pMethods = m_pModule->GetMethods().get(); + if ( pMethods ) + { + sal_uInt32 nCount = pMethods->Count(); + sal_Int32 nRealCount = 0; + for ( sal_uInt32 i = 0; i < nCount; ++i ) + { + SbMethod* pMethod = static_cast<SbMethod*>(pMethods->Get(i)); + if ( pMethod && !pMethod->IsHidden() ) + ++nRealCount; + } + aChildNodes.realloc( nRealCount ); + Reference< browse::XBrowseNode >* pChildNodes = aChildNodes.getArray(); + + sal_Int32 iTarget = 0; + for ( sal_uInt32 i = 0; i < nCount; ++i ) + { + SbMethod* pMethod = static_cast<SbMethod*>(pMethods->Get(i)); + if ( pMethod && !pMethod->IsHidden() ) + pChildNodes[iTarget++] = new BasicMethodNodeImpl( + m_xContext, m_sScriptingContext, pMethod, m_bIsAppScript); + } + } + } + + return aChildNodes; + } + + + sal_Bool BasicModuleNodeImpl::hasChildNodes( ) + { + SolarMutexGuard aGuard; + + bool bReturn = false; + if ( m_pModule ) + { + SbxArray* pMethods = m_pModule->GetMethods().get(); + if (pMethods && pMethods->Count() > 0) + bReturn = true; + } + + return bReturn; + } + + + sal_Int16 BasicModuleNodeImpl::getType( ) + { + return browse::BrowseNodeTypes::CONTAINER; + } + + +} // namespace basprov + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/scripting/source/basprov/basmodnode.hxx b/scripting/source/basprov/basmodnode.hxx new file mode 100644 index 000000000..ebf0957ef --- /dev/null +++ b/scripting/source/basprov/basmodnode.hxx @@ -0,0 +1,64 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <com/sun/star/script/browse/XBrowseNode.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <cppuhelper/implbase.hxx> + +class SbModule; + + +namespace basprov +{ + + + + + typedef ::cppu::WeakImplHelper< + css::script::browse::XBrowseNode > BasicModuleNodeImpl_BASE; + + + class BasicModuleNodeImpl : public BasicModuleNodeImpl_BASE + { + private: + css::uno::Reference< css::uno::XComponentContext > m_xContext; + OUString m_sScriptingContext; + SbModule* m_pModule; + bool m_bIsAppScript; + + public: + BasicModuleNodeImpl( const css::uno::Reference< css::uno::XComponentContext >& rxContext, + const OUString& sScriptingContext, + SbModule* pModule, bool isAppScript ); + virtual ~BasicModuleNodeImpl() override; + + // XBrowseNode + virtual OUString SAL_CALL getName( ) override; + virtual css::uno::Sequence< css::uno::Reference< css::script::browse::XBrowseNode > > SAL_CALL getChildNodes( ) override; + virtual sal_Bool SAL_CALL hasChildNodes( ) override; + virtual sal_Int16 SAL_CALL getType( ) override; + }; + + +} // namespace basprov + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/scripting/source/basprov/basprov.component b/scripting/source/basprov/basprov.component new file mode 100644 index 000000000..d0d6bf974 --- /dev/null +++ b/scripting/source/basprov/basprov.component @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + --> + +<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.scripting.ScriptProviderForBasic" + constructor="scripting_BasicProviderImpl_get_implementation"> + <service name="com.sun.star.script.browse.BrowseNode"/> + <service name="com.sun.star.script.provider.LanguageScriptProvider"/> + <service name="com.sun.star.script.provider.ScriptProvider"/> + <service name="com.sun.star.script.provider.ScriptProviderForBasic"/> + </implementation> +</component> diff --git a/scripting/source/basprov/basprov.cxx b/scripting/source/basprov/basprov.cxx new file mode 100644 index 000000000..d4afb41ea --- /dev/null +++ b/scripting/source/basprov/basprov.cxx @@ -0,0 +1,477 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "basprov.hxx" +#include "basscript.hxx" +#include "baslibnode.hxx" +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/script/browse/BrowseNodeTypes.hpp> +#include <com/sun/star/script/provider/ScriptFrameworkErrorException.hpp> +#include <com/sun/star/script/provider/ScriptFrameworkErrorType.hpp> +#include <com/sun/star/document/XEmbeddedScripts.hpp> +#include <com/sun/star/uri/UriReferenceFactory.hpp> + +#include <cppuhelper/supportsservice.hxx> +#include <rtl/uri.hxx> +#include <sal/log.hxx> +#include <osl/file.hxx> +#include <vcl/svapp.hxx> +#include <basic/basmgr.hxx> +#include <basic/basicmanagerrepository.hxx> +#include <basic/sbstar.hxx> +#include <basic/sbmod.hxx> +#include <basic/sbmeth.hxx> +#include <sfx2/app.hxx> + +#include <com/sun/star/util/theMacroExpander.hpp> +#include <com/sun/star/script/XLibraryContainer2.hpp> +#include <com/sun/star/uri/XUriReference.hpp> +#include <com/sun/star/uri/XUriReferenceFactory.hpp> +#include <com/sun/star/uri/XVndSunStarScriptUrl.hpp> + +#include <util/MiscUtils.hxx> + + +using namespace ::com::sun::star; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::script; +using namespace ::com::sun::star::document; +using namespace ::sf_misc; + + +namespace basprov +{ + + // BasicProviderImpl + + + BasicProviderImpl::BasicProviderImpl( const Reference< XComponentContext >& xContext ) + :m_pAppBasicManager( nullptr ) + ,m_pDocBasicManager( nullptr ) + ,m_xContext( xContext ) + ,m_bIsAppScriptCtx( true ) + ,m_bIsUserCtx(true) + { + } + + + BasicProviderImpl::~BasicProviderImpl() + { + SolarMutexGuard aGuard; + EndListeningAll(); + } + + + bool BasicProviderImpl::isLibraryShared( const Reference< script::XLibraryContainer >& rxLibContainer, const OUString& rLibName ) + { + bool bIsShared = false; + + Reference< script::XLibraryContainer2 > xLibContainer( rxLibContainer, UNO_QUERY ); + if ( xLibContainer.is() && xLibContainer->hasByName( rLibName ) && xLibContainer->isLibraryLink( rLibName ) ) + { + OUString aFileURL; + if ( m_xContext.is() ) + { + Reference< uri::XUriReferenceFactory > xUriFac( uri::UriReferenceFactory::create( m_xContext ) ); + + OUString aLinkURL( xLibContainer->getLibraryLinkURL( rLibName ) ); + Reference< uri::XUriReference > xUriRef = xUriFac->parse( aLinkURL ); + + if ( xUriRef.is() ) + { + OUString aScheme = xUriRef->getScheme(); + if ( aScheme.equalsIgnoreAsciiCase("file") ) + { + aFileURL = aLinkURL; + } + else if ( aScheme.equalsIgnoreAsciiCase("vnd.sun.star.pkg") ) + { + OUString aAuthority = xUriRef->getAuthority(); + if ( aAuthority.matchIgnoreAsciiCase( "vnd.sun.star.expand:" ) ) + { + OUString aDecodedURL( aAuthority.copy( sizeof ( "vnd.sun.star.expand:" ) - 1 ) ); + aDecodedURL = ::rtl::Uri::decode( aDecodedURL, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 ); + Reference<util::XMacroExpander> xMacroExpander = + util::theMacroExpander::get(m_xContext); + aFileURL = xMacroExpander->expandMacros( aDecodedURL ); + } + } + } + } + + if ( !aFileURL.isEmpty() ) + { + osl::DirectoryItem aFileItem; + osl::FileStatus aFileStatus( osl_FileStatus_Mask_FileURL ); + OSL_VERIFY( osl::DirectoryItem::get( aFileURL, aFileItem ) == osl::FileBase::E_None ); + OSL_VERIFY( aFileItem.getFileStatus( aFileStatus ) == osl::FileBase::E_None ); + OUString aCanonicalFileURL( aFileStatus.getFileURL() ); + + if( aCanonicalFileURL.indexOf( "share/basic" ) != -1 + || aCanonicalFileURL.indexOf( "share/uno_packages" ) != -1 ) + bIsShared = true; + } + } + + return bIsShared; + } + + // SfxListener + void BasicProviderImpl::Notify(SfxBroadcaster& rBC, const SfxHint& rHint) + { + if (auto pManager = dynamic_cast<const BasicManager*>(&rBC)) + if (pManager == m_pAppBasicManager && rHint.GetId() == SfxHintId::Dying) + { + EndListening(*m_pAppBasicManager); + m_pAppBasicManager = nullptr; + } + } + + // XServiceInfo + OUString BasicProviderImpl::getImplementationName( ) + { + return "com.sun.star.comp.scripting.ScriptProviderForBasic"; + } + + sal_Bool BasicProviderImpl::supportsService( const OUString& rServiceName ) + { + return cppu::supportsService(this, rServiceName); + } + + Sequence< OUString > BasicProviderImpl::getSupportedServiceNames( ) + { + return { + "com.sun.star.script.provider.ScriptProviderForBasic", + "com.sun.star.script.provider.LanguageScriptProvider", + "com.sun.star.script.provider.ScriptProvider", + "com.sun.star.script.browse.BrowseNode"}; + } + + + // XInitialization + + + void BasicProviderImpl::initialize( const Sequence< Any >& aArguments ) + { + // TODO + + SolarMutexGuard aGuard; + + if ( aArguments.getLength() != 1 ) + { + throw IllegalArgumentException( + "BasicProviderImpl::initialize: incorrect argument count.", + *this, + 1 + ); + } + + Reference< frame::XModel > xModel; + + m_xInvocationContext.set( aArguments[0], UNO_QUERY ); + if ( m_xInvocationContext.is() ) + { + xModel.set( m_xInvocationContext->getScriptContainer(), UNO_QUERY ); + if ( !xModel.is() ) + { + throw IllegalArgumentException( + "BasicProviderImpl::initialize: unable to determine the document model from the script invocation context.", + *this, + 1 + ); + } + } + else + { + if ( !( aArguments[0] >>= m_sScriptingContext ) ) + { + throw IllegalArgumentException( + "BasicProviderImpl::initialize: incorrect argument type " + aArguments[0].getValueTypeName(), + *this, + 1 + ); + } + + if ( m_sScriptingContext.startsWith( "vnd.sun.star.tdoc" ) ) + { + xModel = MiscUtils::tDocUrlToModel( m_sScriptingContext ); + } + } + + if ( xModel.is() ) + { + Reference< XEmbeddedScripts > xDocumentScripts( xModel, UNO_QUERY ); + if ( xDocumentScripts.is() ) + { + m_pDocBasicManager = ::basic::BasicManagerRepository::getDocumentBasicManager( xModel ); + m_xLibContainerDoc = xDocumentScripts->getBasicLibraries(); + OSL_ENSURE( m_pDocBasicManager && m_xLibContainerDoc.is(), + "BasicProviderImpl::initialize: invalid BasicManager, or invalid script container!" ); + } + m_bIsAppScriptCtx = false; + } + else + { + // Provider has been created with application context for user + // or share + if ( m_sScriptingContext != "user" ) + { + m_bIsUserCtx = false; + } + else + { + /* + throw RuntimeException( + "BasicProviderImpl::initialize: no scripting context!" ); + */ + } + } + + // TODO + if ( !m_pAppBasicManager ) + { + m_pAppBasicManager = SfxApplication::GetBasicManager(); + if (m_pAppBasicManager) + StartListening(*m_pAppBasicManager); + } + + if ( !m_xLibContainerApp.is() ) + m_xLibContainerApp = SfxGetpApp()->GetBasicContainer(); + } + + + // XScriptProvider + + + Reference < provider::XScript > BasicProviderImpl::getScript( const OUString& scriptURI ) + { + // TODO + + SolarMutexGuard aGuard; + + Reference< provider::XScript > xScript; + Reference< uri::XUriReferenceFactory > xFac ( uri::UriReferenceFactory::create( m_xContext ) ); + + Reference< uri::XUriReference > uriRef = xFac->parse( scriptURI ); + + Reference < uri::XVndSunStarScriptUrl > sfUri( uriRef, UNO_QUERY ); + + if ( !uriRef.is() || !sfUri.is() ) + { + throw provider::ScriptFrameworkErrorException( + "BasicProviderImpl::getScript: failed to parse URI: " + scriptURI, + Reference< XInterface >(), + scriptURI, "Basic", + provider::ScriptFrameworkErrorType::MALFORMED_URL ); + } + + + OUString aDescription = sfUri->getName(); + OUString aLocation = sfUri->getParameter( "location" ); + + sal_Int32 nIndex = 0; + // In some strange circumstances the Library name can have an + // apparently illegal '.' in it ( in imported VBA ) + + BasicManager* pBasicMgr = nullptr; + if ( aLocation == "document" ) + { + pBasicMgr = m_pDocBasicManager; + } + else if ( aLocation == "application" ) + { + pBasicMgr = m_pAppBasicManager; + } + OUString sProjectName; + if ( pBasicMgr ) + sProjectName = pBasicMgr->GetName(); + + OUString aLibrary; + if ( !sProjectName.isEmpty() && aDescription.match( sProjectName ) ) + { + SAL_WARN("scripting", "LibraryName " << sProjectName << " is part of the url " << aDescription ); + aLibrary = sProjectName; + nIndex = sProjectName.getLength() + 1; + } + else + aLibrary = aDescription.getToken( 0, '.', nIndex ); + OUString aModule; + if ( nIndex != -1 ) + aModule = aDescription.getToken( 0, '.', nIndex ); + OUString aMethod; + if ( nIndex != -1 ) + aMethod = aDescription.getToken( 0, '.', nIndex ); + + if ( !aLibrary.isEmpty() && !aModule.isEmpty() && !aMethod.isEmpty() && !aLocation.isEmpty() ) + { + + if ( pBasicMgr ) + { + StarBASIC* pBasic = pBasicMgr->GetLib( aLibrary ); + if ( !pBasic ) + { + sal_uInt16 nId = pBasicMgr->GetLibId( aLibrary ); + if ( nId != LIB_NOTFOUND ) + { + pBasicMgr->LoadLib( nId ); + pBasic = pBasicMgr->GetLib( aLibrary ); + } + } + if ( pBasic ) + { + SbModule* pModule = pBasic->FindModule( aModule ); + if ( pModule ) + { + SbMethod* pMethod = pModule->FindMethod( aMethod, SbxClassType::Method ); + if ( pMethod && !pMethod->IsHidden() ) + { + if ( m_pDocBasicManager == pBasicMgr ) + xScript = new BasicScriptImpl( aDescription, pMethod, *m_pDocBasicManager, m_xInvocationContext ); + else + xScript = new BasicScriptImpl( aDescription, pMethod ); + } + } + } + } + } + + if ( !xScript.is() ) + { + throw provider::ScriptFrameworkErrorException( + "The following Basic script could not be found:\n" + "library: '" + aLibrary + "'\n" + "module: '" + aModule + "'\n" + "method: '" + aMethod + "'\n" + "location: '" + aLocation + "'\n", + Reference< XInterface >(), + scriptURI, "Basic", + provider::ScriptFrameworkErrorType::NO_SUCH_SCRIPT ); + } + + return xScript; + } + + + // XBrowseNode + + + OUString BasicProviderImpl::getName( ) + { + return "Basic"; + } + + + Sequence< Reference< browse::XBrowseNode > > BasicProviderImpl::getChildNodes( ) + { + SolarMutexGuard aGuard; + + Reference< script::XLibraryContainer > xLibContainer; + BasicManager* pBasicManager = nullptr; + + if ( m_bIsAppScriptCtx ) + { + xLibContainer = m_xLibContainerApp; + pBasicManager = m_pAppBasicManager; + } + else + { + xLibContainer = m_xLibContainerDoc; + pBasicManager = m_pDocBasicManager; + } + + Sequence< Reference< browse::XBrowseNode > > aChildNodes; + + if ( pBasicManager && xLibContainer.is() ) + { + const Sequence< OUString > aLibNames = xLibContainer->getElementNames(); + sal_Int32 nLibCount = aLibNames.getLength(); + aChildNodes.realloc( nLibCount ); + Reference< browse::XBrowseNode >* pChildNodes = aChildNodes.getArray(); + sal_Int32 childrenFound = 0; + + for ( const OUString& rLibName : aLibNames ) + { + bool bCreate = false; + if ( m_bIsAppScriptCtx ) + { + const bool bShared = isLibraryShared( xLibContainer, rLibName ); + if (m_bIsUserCtx != bShared) + bCreate = true; + } + else + { + bCreate = true; + } + if ( bCreate ) + { + pChildNodes[childrenFound++] + = new BasicLibraryNodeImpl(m_xContext, m_sScriptingContext, pBasicManager, + xLibContainer, rLibName, m_bIsAppScriptCtx); + } + } + + if ( childrenFound != nLibCount ) + aChildNodes.realloc( childrenFound ); + } + + return aChildNodes; + } + + + sal_Bool BasicProviderImpl::hasChildNodes( ) + { + SolarMutexGuard aGuard; + + bool bReturn = false; + Reference< script::XLibraryContainer > xLibContainer; + if ( m_bIsAppScriptCtx ) + { + xLibContainer = m_xLibContainerApp; + } + else + { + xLibContainer = m_xLibContainerDoc; + } + if ( xLibContainer.is() ) + bReturn = xLibContainer->hasElements(); + + return bReturn; + } + + + sal_Int16 BasicProviderImpl::getType( ) + { + return browse::BrowseNodeTypes::CONTAINER; + } + + + // component operations + + extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* + scripting_BasicProviderImpl_get_implementation( + css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&) + { + return cppu::acquire(new BasicProviderImpl(context)); + } + + +} // namespace basprov + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/scripting/source/basprov/basprov.hxx b/scripting/source/basprov/basprov.hxx new file mode 100644 index 000000000..994113b62 --- /dev/null +++ b/scripting/source/basprov/basprov.hxx @@ -0,0 +1,97 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/script/XLibraryContainer.hpp> +#include <com/sun/star/script/browse/XBrowseNode.hpp> +#include <com/sun/star/script/provider/XScriptProvider.hpp> +#include <com/sun/star/document/XScriptInvocationContext.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <cppuhelper/implbase.hxx> +#include <svl/lstner.hxx> + +class BasicManager; + + +namespace basprov +{ + + + + + typedef ::cppu::WeakImplHelper< + css::lang::XServiceInfo, + css::lang::XInitialization, + css::script::provider::XScriptProvider, + css::script::browse::XBrowseNode > BasicProviderImpl_BASE; + + + class BasicProviderImpl : public BasicProviderImpl_BASE, public SfxListener + { + private: + BasicManager* m_pAppBasicManager; + BasicManager* m_pDocBasicManager; + css::uno::Reference< css::script::XLibraryContainer > m_xLibContainerApp; + css::uno::Reference< css::script::XLibraryContainer > m_xLibContainerDoc; + css::uno::Reference< css::uno::XComponentContext > m_xContext; + css::uno::Reference< css::document::XScriptInvocationContext > m_xInvocationContext; + OUString m_sScriptingContext; + bool m_bIsAppScriptCtx; + bool m_bIsUserCtx; + + bool isLibraryShared( + const css::uno::Reference< css::script::XLibraryContainer >& rxLibContainer, + const OUString& rLibName ); + + public: + explicit BasicProviderImpl( + const css::uno::Reference< css::uno::XComponentContext >& xContext ); + virtual ~BasicProviderImpl() override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName( ) override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; + + // XInitialization + virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override; + + // XScriptProvider + virtual css::uno::Reference < css::script::provider::XScript > SAL_CALL getScript( + const OUString& scriptURI ) override; + + // XBrowseNode + virtual OUString SAL_CALL getName( ) override; + virtual css::uno::Sequence< css::uno::Reference< css::script::browse::XBrowseNode > > SAL_CALL getChildNodes( ) override; + virtual sal_Bool SAL_CALL hasChildNodes( ) override; + virtual sal_Int16 SAL_CALL getType( ) override; + + protected: + // SfxListener + virtual void Notify(SfxBroadcaster& rBC, const SfxHint& rHint) override; + }; + + +} // namespace basprov + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/scripting/source/basprov/basscript.cxx b/scripting/source/basprov/basscript.cxx new file mode 100644 index 000000000..b5a3f6136 --- /dev/null +++ b/scripting/source/basprov/basscript.cxx @@ -0,0 +1,314 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "basscript.hxx" +#include <vcl/svapp.hxx> +#include <basic/sbx.hxx> +#include <basic/sbmod.hxx> +#include <basic/sbmeth.hxx> +#include <basic/sbuno.hxx> +#include <basic/basmgr.hxx> +#include <com/sun/star/script/provider/ScriptFrameworkErrorException.hpp> +#include <com/sun/star/script/provider/ScriptFrameworkErrorType.hpp> +#include <bcholder.hxx> +#include <comphelper/propertycontainer.hxx> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <map> + + +using namespace ::com::sun::star; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::script; +using namespace ::com::sun::star::document; +using namespace ::com::sun::star::beans; + + +namespace basprov +{ + +#define BASSCRIPT_PROPERTY_ID_CALLER 1 +constexpr OUStringLiteral BASSCRIPT_PROPERTY_CALLER = u"Caller"; + +#define BASSCRIPT_DEFAULT_ATTRIBS() PropertyAttribute::BOUND | PropertyAttribute::TRANSIENT + + typedef ::std::map< sal_Int16, Any > OutParamMap; + + + // BasicScriptImpl + + + BasicScriptImpl::BasicScriptImpl( const OUString& funcName, SbMethodRef const & xMethod ) + : ::scripting_helper::OBroadcastHelperHolder( m_aMutex ) + ,OPropertyContainer( GetBroadcastHelper() ) + ,m_xMethod( xMethod ) + ,m_funcName( funcName ) + ,m_documentBasicManager( nullptr ) + ,m_xDocumentScriptContext() + { + registerProperty( BASSCRIPT_PROPERTY_CALLER, BASSCRIPT_PROPERTY_ID_CALLER, BASSCRIPT_DEFAULT_ATTRIBS(), &m_caller, cppu::UnoType<decltype(m_caller)>::get() ); + } + + + BasicScriptImpl::BasicScriptImpl( const OUString& funcName, SbMethodRef const & xMethod, + BasicManager& documentBasicManager, const Reference< XScriptInvocationContext >& documentScriptContext ) : ::scripting_helper::OBroadcastHelperHolder( m_aMutex ) + ,OPropertyContainer( GetBroadcastHelper() ) + ,m_xMethod( xMethod ) + ,m_funcName( funcName ) + ,m_documentBasicManager( &documentBasicManager ) + ,m_xDocumentScriptContext( documentScriptContext ) + { + StartListening( *m_documentBasicManager ); + registerProperty( BASSCRIPT_PROPERTY_CALLER, BASSCRIPT_PROPERTY_ID_CALLER, BASSCRIPT_DEFAULT_ATTRIBS(), &m_caller, cppu::UnoType<decltype(m_caller)>::get() ); + } + + + BasicScriptImpl::~BasicScriptImpl() + { + SolarMutexGuard g; + + if ( m_documentBasicManager ) + EndListening( *m_documentBasicManager ); + } + + + // SfxListener + + void BasicScriptImpl::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) + { + if ( &rBC != m_documentBasicManager ) + { + OSL_ENSURE( false, "BasicScriptImpl::Notify: where does this come from?" ); + // not interested in + return; + } + if ( rHint.GetId() == SfxHintId::Dying ) + { + m_documentBasicManager = nullptr; + EndListening( rBC ); // prevent multiple notifications + } + } + + + // XInterface + + + IMPLEMENT_FORWARD_XINTERFACE2( BasicScriptImpl, BasicScriptImpl_BASE, OPropertyContainer ) + + + // XTypeProvider + + + IMPLEMENT_FORWARD_XTYPEPROVIDER2( BasicScriptImpl, BasicScriptImpl_BASE, OPropertyContainer ) + + + // OPropertySetHelper + + + ::cppu::IPropertyArrayHelper& BasicScriptImpl::getInfoHelper( ) + { + return *getArrayHelper(); + } + + + // OPropertyArrayUsageHelper + + + ::cppu::IPropertyArrayHelper* BasicScriptImpl::createArrayHelper( ) const + { + Sequence< Property > aProps; + describeProperties( aProps ); + return new ::cppu::OPropertyArrayHelper( aProps ); + } + + + // XPropertySet + + + Reference< XPropertySetInfo > BasicScriptImpl::getPropertySetInfo( ) + { + Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) ); + return xInfo; + } + + + // XScript + + + Any BasicScriptImpl::invoke( const Sequence< Any >& aParams, Sequence< sal_Int16 >& aOutParamIndex, Sequence< Any >& aOutParam ) + { + // TODO: throw CannotConvertException + // TODO: check length of aOutParamIndex, aOutParam + + SolarMutexGuard aGuard; + + Any aReturn; + + if ( m_xMethod.is() ) + { + // check if compiled + SbModule* pModule = static_cast< SbModule* >( m_xMethod->GetParent() ); + if ( pModule && !pModule->IsCompiled() ) + pModule->Compile(); + + // check number of parameters + sal_Int32 nParamsCount = aParams.getLength(); + SbxInfo* pInfo = m_xMethod->GetInfo(); + if ( pInfo ) + { + sal_Int32 nSbxOptional = 0; + sal_uInt16 n = 1; + for ( const SbxParamInfo* pParamInfo = pInfo->GetParam( n ); pParamInfo; pParamInfo = pInfo->GetParam( ++n ) ) + { + if ( pParamInfo->nFlags & SbxFlagBits::Optional ) + ++nSbxOptional; + else + nSbxOptional = 0; + } + sal_Int32 nSbxCount = n - 1; + if ( nParamsCount < nSbxCount - nSbxOptional ) + { + throw provider::ScriptFrameworkErrorException( + "wrong number of parameters!", + Reference< XInterface >(), + m_funcName, + "Basic", + provider::ScriptFrameworkErrorType::NO_SUCH_SCRIPT ); + } + } + + // set parameters + SbxArrayRef xSbxParams; + if ( nParamsCount > 0 ) + { + xSbxParams = new SbxArray; + const Any* pParams = aParams.getConstArray(); + for ( sal_Int32 i = 0; i < nParamsCount; ++i ) + { + SbxVariableRef xSbxVar = new SbxVariable( SbxVARIANT ); + unoToSbxValue( xSbxVar.get(), pParams[i] ); + xSbxParams->Put(xSbxVar.get(), static_cast<sal_uInt32>(i) + 1); + + if (pInfo) + { + if (auto* p = pInfo->GetParam(static_cast<sal_uInt16>(i) + 1)) + { + SbxDataType t = static_cast<SbxDataType>(p->eType & 0x0FFF); + // tdf#133889 Revert the downcasting performed in sbxToUnoValueImpl + // to allow passing by reference. + SbxDataType a = xSbxVar->GetType(); + if (t == SbxSINGLE && (a == SbxINTEGER || a == SbxLONG)) + { + sal_Int32 val = xSbxVar->GetLong(); + if (val >= -16777216 && val <= 16777215) + xSbxVar->SetType(t); + } + else if (t == SbxDOUBLE && (a == SbxINTEGER || a == SbxLONG)) + xSbxVar->SetType(t); + else if (t == SbxLONG && a == SbxINTEGER) + xSbxVar->SetType(t); + else if (t == SbxULONG && a == SbxUSHORT) + xSbxVar->SetType(t); + // Enable passing by ref + if (t != SbxVARIANT) + xSbxVar->SetFlag(SbxFlagBits::Fixed); + } + } + } + } + if ( xSbxParams.is() ) + m_xMethod->SetParameters( xSbxParams.get() ); + + // call method + SbxVariableRef xReturn = new SbxVariable; + ErrCode nErr = ERRCODE_NONE; + + // if it's a document-based script, temporarily reset ThisComponent to the script invocation context + Any aOldThisComponent; + if ( m_documentBasicManager && m_xDocumentScriptContext.is() ) + m_documentBasicManager->SetGlobalUNOConstant( "ThisComponent", Any( m_xDocumentScriptContext ), &aOldThisComponent ); + + if ( m_caller.hasElements() && m_caller[ 0 ].hasValue() ) + { + SbxVariableRef xCallerVar = new SbxVariable( SbxVARIANT ); + unoToSbxValue( xCallerVar.get(), m_caller[ 0 ] ); + nErr = m_xMethod->Call( xReturn.get(), xCallerVar.get() ); + } + else + nErr = m_xMethod->Call( xReturn.get() ); + + if ( m_documentBasicManager && m_xDocumentScriptContext.is() ) + m_documentBasicManager->SetGlobalUNOConstant( "ThisComponent", aOldThisComponent ); + + if ( nErr != ERRCODE_NONE ) + { + // TODO: throw InvocationTargetException ? + } + + // get output parameters + if ( xSbxParams.is() ) + { + SbxInfo* pInfo_ = m_xMethod->GetInfo(); + if ( pInfo_ ) + { + OutParamMap aOutParamMap; + for (sal_uInt32 n = 1, nCount = xSbxParams->Count(); n < nCount; ++n) + { + assert(nCount <= std::numeric_limits<sal_uInt16>::max()); + const SbxParamInfo* pParamInfo = pInfo_->GetParam( sal::static_int_cast<sal_uInt16>(n) ); + if ( pParamInfo && ( pParamInfo->eType & SbxBYREF ) != 0 ) + { + SbxVariable* pVar = xSbxParams->Get(n); + if ( pVar ) + { + SbxVariableRef xVar = pVar; + aOutParamMap.emplace( n - 1, sbxToUnoValue( xVar.get() ) ); + } + } + } + sal_Int32 nOutParamCount = aOutParamMap.size(); + aOutParamIndex.realloc( nOutParamCount ); + aOutParam.realloc( nOutParamCount ); + sal_Int16* pOutParamIndex = aOutParamIndex.getArray(); + Any* pOutParam = aOutParam.getArray(); + for ( const auto& rEntry : aOutParamMap ) + { + *pOutParamIndex = rEntry.first; + ++pOutParamIndex; + *pOutParam = rEntry.second; + ++pOutParam; + } + } + } + + // get return value + aReturn = sbxToUnoValue( xReturn.get() ); + + // reset parameters + m_xMethod->SetParameters( nullptr ); + } + + return aReturn; + } + + +} // namespace basprov + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/scripting/source/basprov/basscript.hxx b/scripting/source/basprov/basscript.hxx new file mode 100644 index 000000000..d0f9e6e7a --- /dev/null +++ b/scripting/source/basprov/basscript.hxx @@ -0,0 +1,103 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <bcholder.hxx> +#include <com/sun/star/script/provider/XScript.hpp> +#include <com/sun/star/document/XScriptInvocationContext.hpp> +#include <cppuhelper/basemutex.hxx> +#include <cppuhelper/implbase.hxx> +#include <comphelper/proparrhlp.hxx> +#include <comphelper/propertycontainer.hxx> +#include <basic/sbmeth.hxx> +#include <svl/lstner.hxx> + +class BasicManager; + + +namespace basprov +{ + + + + + typedef ::cppu::WeakImplHelper< + css::script::provider::XScript > BasicScriptImpl_BASE; + + + class BasicScriptImpl : public BasicScriptImpl_BASE, public SfxListener, + public cppu::BaseMutex, + public ::scripting_helper::OBroadcastHelperHolder, + public ::comphelper::OPropertyContainer, + public ::comphelper::OPropertyArrayUsageHelper< BasicScriptImpl > + { + private: + SbMethodRef m_xMethod; + OUString m_funcName; + BasicManager* m_documentBasicManager; + css::uno::Reference< css::document::XScriptInvocationContext > + m_xDocumentScriptContext; + // hack, OPropertyContainer doesn't allow you to define a property of unknown + // type ( I guess because an Any can't contain an Any... I've always wondered why? + // as it's not unusual to do that in corba ) + css::uno::Sequence< css::uno::Any > m_caller; + protected: + // OPropertySetHelper + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper( ) override; + + // OPropertyArrayUsageHelper + virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const override; + + public: + BasicScriptImpl( + const OUString& funcName, + SbMethodRef const & xMethod + ); + BasicScriptImpl( + const OUString& funcName, + SbMethodRef const & xMethod, + BasicManager& documentBasicManager, + const css::uno::Reference< css::document::XScriptInvocationContext >& documentScriptContext + ); + virtual ~BasicScriptImpl() override; + + // XInterface + DECLARE_XINTERFACE() + + // XTypeProvider + DECLARE_XTYPEPROVIDER() + + // XScript + virtual css::uno::Any SAL_CALL invoke( + const css::uno::Sequence< css::uno::Any >& aParams, + css::uno::Sequence< sal_Int16 >& aOutParamIndex, + css::uno::Sequence< css::uno::Any >& aOutParam ) override; + // XPropertySet + virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override; + + // SfxListener + virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) override; + }; + + +} // namespace basprov + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |