Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / scripting / source / provider / ActiveMSPList.cxx
blob3cf34551d52c28e41eab12b5bffc545883b2e6a1
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <cppuhelper/implementationentry.hxx>
21 #include <cppuhelper/factory.hxx>
22 #include <cppuhelper/exc_hlp.hxx>
23 #include <util/MiscUtils.hxx>
25 #include <com/sun/star/beans/XPropertySet.hpp>
26 #include <com/sun/star/util/XMacroExpander.hpp>
27 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
29 #include "MasterScriptProvider.hxx"
30 #include "ActiveMSPList.hxx"
32 #include <tools/diagnose_ex.h>
34 using namespace com::sun::star;
35 using namespace com::sun::star::uno;
36 using namespace com::sun::star::script;
37 using namespace ::sf_misc;
39 namespace func_provider
42 ActiveMSPList::ActiveMSPList( const Reference< XComponentContext > & xContext ) : m_xContext( xContext )
44 userDirString = "user";
45 shareDirString = "share";
46 bundledDirString = "bundled";
49 ActiveMSPList::~ActiveMSPList()
53 Reference< provider::XScriptProvider >
54 ActiveMSPList::createNewMSP( const uno::Any& context )
56 Sequence< Any > args( &context, 1 );
58 Reference< provider::XScriptProvider > msp(
59 m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
60 "com.sun.star.script.provider.MasterScriptProvider", args, m_xContext ), UNO_QUERY );
61 return msp;
64 class NonDocMSPCreator
66 public:
67 explicit NonDocMSPCreator(ActiveMSPList *pList)
69 pList->createNonDocMSPs();
73 namespace
75 //thread-safe double-locked class to ensure createNonDocMSPs is called once
76 class theNonDocMSPCreator : public rtl::StaticWithArg<NonDocMSPCreator, ActiveMSPList*, theNonDocMSPCreator> {};
78 void ensureNonDocMSPs(ActiveMSPList *pList)
80 theNonDocMSPCreator::get(pList);
84 Reference< provider::XScriptProvider >
85 ActiveMSPList::getMSPFromAnyContext( const Any& aContext )
87 Reference< provider::XScriptProvider > msp;
88 OUString sContext;
89 if ( aContext >>= sContext )
91 msp = getMSPFromStringContext( sContext );
92 return msp;
95 Reference< frame::XModel > xModel( aContext, UNO_QUERY );
97 Reference< document::XScriptInvocationContext > xScriptContext( aContext, UNO_QUERY );
98 if ( xScriptContext.is() )
102 // the component supports executing scripts embedded in a - possibly foreign document.
103 // Check whether this other document it's the component itself.
104 if ( !xModel.is() || ( xModel != xScriptContext->getScriptContainer() ) )
106 msp = getMSPFromInvocationContext( xScriptContext );
107 return msp;
110 catch( const lang::IllegalArgumentException& )
112 xModel.set( Reference< frame::XModel >() );
116 if ( xModel.is() )
118 sContext = MiscUtils::xModelToTdocUrl( xModel, m_xContext );
119 msp = getMSPFromStringContext( sContext );
120 return msp;
123 ensureNonDocMSPs(this);
124 return m_hMsps[ shareDirString ];
127 Reference< provider::XScriptProvider >
128 ActiveMSPList::getMSPFromInvocationContext( const Reference< document::XScriptInvocationContext >& xContext )
130 Reference< provider::XScriptProvider > msp;
132 Reference< document::XEmbeddedScripts > xScripts;
133 if ( xContext.is() )
134 xScripts.set( xContext->getScriptContainer() );
135 if ( !xScripts.is() )
137 throw lang::IllegalArgumentException(
138 "Failed to create MasterScriptProvider for ScriptInvocationContext: "
139 "Component supporting XEmbeddScripts interface not found.",
140 nullptr, 1 );
143 ::osl::MutexGuard guard( m_mutex );
145 Reference< XInterface > xNormalized( xContext, UNO_QUERY );
146 ScriptComponent_map::const_iterator pos = m_mScriptComponents.find( xNormalized );
147 if ( pos == m_mScriptComponents.end() )
149 // TODO
150 msp = createNewMSP( uno::makeAny( xContext ) );
151 addActiveMSP( xNormalized, msp );
153 else
155 msp = pos->second;
158 return msp;
161 Reference< provider::XScriptProvider >
162 ActiveMSPList::getMSPFromStringContext( const OUString& context )
164 Reference< provider::XScriptProvider > msp;
167 if ( context.startsWith( "vnd.sun.star.tdoc" ) )
169 Reference< frame::XModel > xModel( MiscUtils::tDocUrlToModel( context ) );
171 Reference< document::XEmbeddedScripts > xScripts( xModel, UNO_QUERY );
172 Reference< document::XScriptInvocationContext > xScriptsContext( xModel, UNO_QUERY );
173 if ( !xScripts.is() && !xScriptsContext.is() )
175 throw lang::IllegalArgumentException(
176 "Failed to create MasterScriptProvider for '"
177 + context +
178 "': Either XEmbeddScripts or XScriptInvocationContext need to be supported by the document.",
179 nullptr, 1 );
182 ::osl::MutexGuard guard( m_mutex );
183 Reference< XInterface > xNormalized( xModel, UNO_QUERY );
184 ScriptComponent_map::const_iterator pos = m_mScriptComponents.find( xNormalized );
185 if ( pos == m_mScriptComponents.end() )
187 msp = createNewMSP( context );
188 addActiveMSP( xNormalized, msp );
190 else
192 msp = pos->second;
195 else
197 ::osl::MutexGuard guard( m_mutex );
198 Msp_hash::iterator h_itEnd = m_hMsps.end();
199 Msp_hash::const_iterator itr = m_hMsps.find( context );
200 if ( itr == h_itEnd )
202 msp = createNewMSP( context );
203 m_hMsps[ context ] = msp;
205 else
207 msp = m_hMsps[ context ];
211 catch( const lang::IllegalArgumentException& )
213 // allowed to leave
215 catch( const RuntimeException& )
217 // allowed to leave
219 catch( const Exception& )
221 css::uno::Any anyEx = cppu::getCaughtException();
222 throw lang::WrappedTargetRuntimeException(
223 "Failed to create MasterScriptProvider for context '"
224 + context + "'.",
225 *this, anyEx );
227 return msp;
230 void
231 ActiveMSPList::addActiveMSP( const Reference< uno::XInterface >& xComponent,
232 const Reference< provider::XScriptProvider >& msp )
234 ::osl::MutexGuard guard( m_mutex );
235 Reference< XInterface > xNormalized( xComponent, UNO_QUERY );
236 ScriptComponent_map::const_iterator pos = m_mScriptComponents.find( xNormalized );
237 if ( pos == m_mScriptComponents.end() )
239 m_mScriptComponents[ xNormalized ] = msp;
241 // add self as listener for component disposal
242 // should probably throw from this method!!, reexamine
245 Reference< lang::XComponent > xBroadcaster( xComponent, UNO_QUERY_THROW );
246 xBroadcaster->addEventListener( this );
248 catch ( const Exception& )
250 DBG_UNHANDLED_EXCEPTION("scripting");
256 void SAL_CALL ActiveMSPList::disposing( const css::lang::EventObject& Source )
261 Reference< XInterface > xNormalized( Source.Source, UNO_QUERY );
262 if ( xNormalized.is() )
264 ::osl::MutexGuard guard( m_mutex );
265 ScriptComponent_map::iterator pos = m_mScriptComponents.find( xNormalized );
266 if ( pos != m_mScriptComponents.end() )
267 m_mScriptComponents.erase( pos );
270 catch ( const Exception& )
272 // if we get an exception here, there is not much we can do about
273 // it can't throw as it will screw up the model that is calling dispose
274 DBG_UNHANDLED_EXCEPTION("scripting");
278 void
279 ActiveMSPList::createNonDocMSPs()
281 // do creation of user and share MSPs here
282 OUString serviceName("com.sun.star.script.provider.MasterScriptProvider");
283 Sequence< Any > args(1);
285 args[ 0 ] <<= userDirString;
286 Reference< provider::XScriptProvider > userMsp( m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext( serviceName, args, m_xContext ), UNO_QUERY );
287 // should check if provider reference is valid
288 m_hMsps[ userDirString ] = userMsp;
290 args[ 0 ] <<= shareDirString;
291 Reference< provider::XScriptProvider > shareMsp( m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext( serviceName, args, m_xContext ), UNO_QUERY );
292 // should check if provider reference is valid
293 m_hMsps[ shareDirString ] = shareMsp;
295 args[ 0 ] <<= bundledDirString;
296 Reference< provider::XScriptProvider > bundledMsp( m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext( serviceName, args, m_xContext ), UNO_QUERY );
297 // should check if provider reference is valid
298 m_hMsps[ bundledDirString ] = bundledMsp;
301 } // namespace func_provider
303 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */