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/implbase1.hxx>
23 #include <cppuhelper/exc_hlp.hxx>
24 #include <util/scriptingconstants.hxx>
25 #include <util/MiscUtils.hxx>
27 #include <com/sun/star/beans/XPropertySet.hpp>
28 #include <com/sun/star/util/XMacroExpander.hpp>
29 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
31 #include <com/sun/star/script/browse/BrowseNodeTypes.hpp>
33 #include "MasterScriptProvider.hxx"
34 #include "ActiveMSPList.hxx"
36 #include <tools/diagnose_ex.h>
38 using namespace com::sun::star
;
39 using namespace com::sun::star::uno
;
40 using namespace com::sun::star::script
;
41 using namespace ::sf_misc
;
43 namespace func_provider
46 ActiveMSPList::ActiveMSPList( const Reference
< XComponentContext
> & xContext
) : m_xContext( xContext
)
48 userDirString
= "user";
49 shareDirString
= "share";
50 bundledDirString
= "bundled";
53 ActiveMSPList::~ActiveMSPList()
57 Reference
< provider::XScriptProvider
>
58 ActiveMSPList::createNewMSP( const uno::Any
& context
)
60 OUString
serviceName("com.sun.star.script.provider.MasterScriptProvider");
61 Sequence
< Any
> args( &context
, 1 );
63 Reference
< provider::XScriptProvider
> msp(
64 m_xContext
->getServiceManager()->createInstanceWithArgumentsAndContext(
65 serviceName
, args
, m_xContext
), UNO_QUERY
);
69 class NonDocMSPCreator
72 NonDocMSPCreator(ActiveMSPList
*pList
)
74 pList
->createNonDocMSPs();
80 //thread-safe double-locked class to ensure createNonDocMSPs is called once
81 class theNonDocMSPCreator
: public rtl::StaticWithArg
<NonDocMSPCreator
, ActiveMSPList
*, theNonDocMSPCreator
> {};
83 void ensureNonDocMSPs(ActiveMSPList
*pList
)
85 theNonDocMSPCreator::get(pList
);
89 Reference
< provider::XScriptProvider
>
90 ActiveMSPList::getMSPFromAnyContext( const Any
& aContext
)
92 Reference
< provider::XScriptProvider
> msp
;
94 if ( aContext
>>= sContext
)
96 msp
= getMSPFromStringContext( sContext
);
100 Reference
< frame::XModel
> xModel( aContext
, UNO_QUERY
);
102 Reference
< document::XScriptInvocationContext
> xScriptContext( aContext
, UNO_QUERY
);
103 if ( xScriptContext
.is() )
107 // the component supports executing scripts embedded in a - possibly foreign document.
108 // Check whether this other document its the component itself.
109 if ( !xModel
.is() || ( xModel
!= xScriptContext
->getScriptContainer() ) )
111 msp
= getMSPFromInvocationContext( xScriptContext
);
115 catch( const lang::IllegalArgumentException
& )
117 xModel
.set( Reference
< frame::XModel
>() );
123 sContext
= MiscUtils::xModelToTdocUrl( xModel
, m_xContext
);
124 msp
= getMSPFromStringContext( sContext
);
128 ensureNonDocMSPs(this);
129 return m_hMsps
[ shareDirString
];
132 Reference
< provider::XScriptProvider
>
133 ActiveMSPList::getMSPFromInvocationContext( const Reference
< document::XScriptInvocationContext
>& xContext
)
135 Reference
< provider::XScriptProvider
> msp
;
137 Reference
< document::XEmbeddedScripts
> xScripts
;
139 xScripts
.set( xContext
->getScriptContainer() );
140 if ( !xScripts
.is() )
143 buf
.appendAscii( "Failed to create MasterScriptProvider for ScriptInvocationContext: " );
144 buf
.appendAscii( "Component supporting XEmbeddScripts interface not found." );
145 throw lang::IllegalArgumentException( buf
.makeStringAndClear(), NULL
, 1 );
148 ::osl::MutexGuard
guard( m_mutex
);
150 Reference
< XInterface
> xNormalized( xContext
, UNO_QUERY
);
151 ScriptComponent_map::const_iterator pos
= m_mScriptComponents
.find( xNormalized
);
152 if ( pos
== m_mScriptComponents
.end() )
155 msp
= createNewMSP( uno::makeAny( xContext
) );
156 addActiveMSP( xNormalized
, msp
);
166 Reference
< provider::XScriptProvider
>
167 ActiveMSPList::getMSPFromStringContext( const OUString
& context
)
169 Reference
< provider::XScriptProvider
> msp
;
172 if ( context
.startsWith( "vnd.sun.star.tdoc" ) )
174 Reference
< frame::XModel
> xModel( MiscUtils::tDocUrlToModel( context
) );
176 Reference
< document::XEmbeddedScripts
> xScripts( xModel
, UNO_QUERY
);
177 Reference
< document::XScriptInvocationContext
> xScriptsContext( xModel
, UNO_QUERY
);
178 if ( !xScripts
.is() && !xScriptsContext
.is() )
181 buf
.appendAscii( "Failed to create MasterScriptProvider for '" );
182 buf
.append ( context
);
183 buf
.appendAscii( "': Either XEmbeddScripts or XScriptInvocationContext need to be supported by the document." );
184 throw lang::IllegalArgumentException( buf
.makeStringAndClear(), NULL
, 1 );
187 ::osl::MutexGuard
guard( m_mutex
);
188 Reference
< XInterface
> xNormalized( xModel
, UNO_QUERY
);
189 ScriptComponent_map::const_iterator pos
= m_mScriptComponents
.find( xNormalized
);
190 if ( pos
== m_mScriptComponents
.end() )
192 msp
= createNewMSP( context
);
193 addActiveMSP( xNormalized
, msp
);
202 ::osl::MutexGuard
guard( m_mutex
);
203 Msp_hash::iterator h_itEnd
= m_hMsps
.end();
204 Msp_hash::const_iterator itr
= m_hMsps
.find( context
);
205 if ( itr
== h_itEnd
)
207 msp
= createNewMSP( context
);
208 m_hMsps
[ context
] = msp
;
212 msp
= m_hMsps
[ context
];
216 catch( const lang::IllegalArgumentException
& )
220 catch( const RuntimeException
& )
224 catch( const Exception
& )
226 OUStringBuffer aMessage
;
227 aMessage
.appendAscii( "Failed to create MasterScriptProvider for context '" );
228 aMessage
.append ( context
);
229 aMessage
.appendAscii( "'." );
230 throw lang::WrappedTargetRuntimeException(
231 aMessage
.makeStringAndClear(), *this, ::cppu::getCaughtException() );
237 ActiveMSPList::addActiveMSP( const Reference
< uno::XInterface
>& xComponent
,
238 const Reference
< provider::XScriptProvider
>& msp
)
240 ::osl::MutexGuard
guard( m_mutex
);
241 Reference
< XInterface
> xNormalized( xComponent
, UNO_QUERY
);
242 ScriptComponent_map::const_iterator pos
= m_mScriptComponents
.find( xNormalized
);
243 if ( pos
== m_mScriptComponents
.end() )
245 m_mScriptComponents
[ xNormalized
] = msp
;
247 // add self as listener for component disposal
248 // should probably throw from this method!!, reexamine
251 Reference
< lang::XComponent
> xBroadcaster
=
252 Reference
< lang::XComponent
>( xComponent
, UNO_QUERY_THROW
);
253 xBroadcaster
->addEventListener( this );
255 catch ( const Exception
& )
257 DBG_UNHANDLED_EXCEPTION();
264 ActiveMSPList::disposing( const ::com::sun::star::lang::EventObject
& Source
)
265 throw ( ::com::sun::star::uno::RuntimeException
, std::exception
)
270 Reference
< XInterface
> xNormalized( Source
.Source
, UNO_QUERY
);
271 if ( xNormalized
.is() )
273 ::osl::MutexGuard
guard( m_mutex
);
274 ScriptComponent_map::iterator pos
= m_mScriptComponents
.find( xNormalized
);
275 if ( pos
!= m_mScriptComponents
.end() )
276 m_mScriptComponents
.erase( pos
);
279 catch ( const Exception
& )
281 // if we get an exception here, there is not much we can do about
282 // it can't throw as it will screw up the model that is calling dispose
283 DBG_UNHANDLED_EXCEPTION();
288 ActiveMSPList::createNonDocMSPs()
290 // do creation of user and share MSPs here
291 OUString
serviceName("com.sun.star.script.provider.MasterScriptProvider");
292 Sequence
< Any
> args(1);
294 args
[ 0 ] <<= userDirString
;
295 Reference
< provider::XScriptProvider
> userMsp( m_xContext
->getServiceManager()->createInstanceWithArgumentsAndContext( serviceName
, args
, m_xContext
), UNO_QUERY
);
296 // should check if provider reference is valid
297 m_hMsps
[ userDirString
] = userMsp
;
299 args
[ 0 ] <<= shareDirString
;
300 Reference
< provider::XScriptProvider
> shareMsp( m_xContext
->getServiceManager()->createInstanceWithArgumentsAndContext( serviceName
, args
, m_xContext
), UNO_QUERY
);
301 // should check if provider reference is valid
302 m_hMsps
[ shareDirString
] = shareMsp
;
304 args
[ 0 ] <<= bundledDirString
;
305 Reference
< provider::XScriptProvider
> bundledMsp( m_xContext
->getServiceManager()->createInstanceWithArgumentsAndContext( serviceName
, args
, m_xContext
), UNO_QUERY
);
306 // should check if provider reference is valid
307 m_hMsps
[ bundledDirString
] = bundledMsp
;
310 } // namespace func_provider
312 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */