1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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
);
64 class NonDocMSPCreator
67 explicit NonDocMSPCreator(ActiveMSPList
*pList
)
69 pList
->createNonDocMSPs();
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
;
89 if ( aContext
>>= sContext
)
91 msp
= getMSPFromStringContext( sContext
);
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
);
110 catch( const lang::IllegalArgumentException
& )
112 xModel
.set( Reference
< frame::XModel
>() );
118 sContext
= MiscUtils::xModelToTdocUrl( xModel
, m_xContext
);
119 msp
= getMSPFromStringContext( sContext
);
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
;
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.",
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() )
150 msp
= createNewMSP( uno::makeAny( xContext
) );
151 addActiveMSP( xNormalized
, 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 '"
178 "': Either XEmbeddScripts or XScriptInvocationContext need to be supported by the document.",
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
);
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
;
207 msp
= m_hMsps
[ context
];
211 catch( const lang::IllegalArgumentException
& )
215 catch( const RuntimeException
& )
219 catch( const Exception
& )
221 css::uno::Any anyEx
= cppu::getCaughtException();
222 throw lang::WrappedTargetRuntimeException(
223 "Failed to create MasterScriptProvider for context '"
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");
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: */