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/exc_hlp.hxx>
21 #include <util/MiscUtils.hxx>
23 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
25 #include "ActiveMSPList.hxx"
27 #include <tools/diagnose_ex.h>
29 using namespace com::sun::star
;
30 using namespace com::sun::star::uno
;
31 using namespace com::sun::star::script
;
32 using namespace ::sf_misc
;
34 namespace func_provider
37 ActiveMSPList::ActiveMSPList( const Reference
< XComponentContext
> & xContext
) : m_xContext( xContext
)
39 userDirString
= "user";
40 shareDirString
= "share";
41 bundledDirString
= "bundled";
44 ActiveMSPList::~ActiveMSPList()
48 Reference
< provider::XScriptProvider
>
49 ActiveMSPList::createNewMSP( const uno::Any
& context
)
51 Sequence
< Any
> args( &context
, 1 );
53 Reference
< provider::XScriptProvider
> msp(
54 m_xContext
->getServiceManager()->createInstanceWithArgumentsAndContext(
55 "com.sun.star.script.provider.MasterScriptProvider", args
, m_xContext
), UNO_QUERY
);
59 class NonDocMSPCreator
62 explicit NonDocMSPCreator(ActiveMSPList
*pList
)
64 pList
->createNonDocMSPs();
70 //thread-safe double-locked class to ensure createNonDocMSPs is called once
71 class theNonDocMSPCreator
: public rtl::StaticWithArg
<NonDocMSPCreator
, ActiveMSPList
*, theNonDocMSPCreator
> {};
73 void ensureNonDocMSPs(ActiveMSPList
*pList
)
75 theNonDocMSPCreator::get(pList
);
79 Reference
< provider::XScriptProvider
>
80 ActiveMSPList::getMSPFromAnyContext( const Any
& aContext
)
82 Reference
< provider::XScriptProvider
> msp
;
84 if ( aContext
>>= sContext
)
86 msp
= getMSPFromStringContext( sContext
);
90 Reference
< frame::XModel
> xModel( aContext
, UNO_QUERY
);
92 Reference
< document::XScriptInvocationContext
> xScriptContext( aContext
, UNO_QUERY
);
93 if ( xScriptContext
.is() )
97 // the component supports executing scripts embedded in a - possibly foreign document.
98 // Check whether this other document it's the component itself.
99 if ( !xModel
.is() || ( xModel
!= xScriptContext
->getScriptContainer() ) )
101 msp
= getMSPFromInvocationContext( xScriptContext
);
105 catch( const lang::IllegalArgumentException
& )
107 xModel
.set( Reference
< frame::XModel
>() );
113 sContext
= MiscUtils::xModelToTdocUrl( xModel
, m_xContext
);
114 msp
= getMSPFromStringContext( sContext
);
118 ensureNonDocMSPs(this);
119 return m_hMsps
[ shareDirString
];
122 Reference
< provider::XScriptProvider
>
123 ActiveMSPList::getMSPFromInvocationContext( const Reference
< document::XScriptInvocationContext
>& xContext
)
125 Reference
< provider::XScriptProvider
> msp
;
127 Reference
< document::XEmbeddedScripts
> xScripts
;
129 xScripts
.set( xContext
->getScriptContainer() );
130 if ( !xScripts
.is() )
132 throw lang::IllegalArgumentException(
133 "Failed to create MasterScriptProvider for ScriptInvocationContext: "
134 "Component supporting XEmbeddScripts interface not found.",
138 ::osl::MutexGuard
guard( m_mutex
);
140 Reference
< XInterface
> xNormalized( xContext
, UNO_QUERY
);
141 ScriptComponent_map::const_iterator pos
= m_mScriptComponents
.find( xNormalized
);
142 if ( pos
== m_mScriptComponents
.end() )
145 msp
= createNewMSP( uno::makeAny( xContext
) );
146 addActiveMSP( xNormalized
, msp
);
156 Reference
< provider::XScriptProvider
>
157 ActiveMSPList::getMSPFromStringContext( const OUString
& context
)
159 Reference
< provider::XScriptProvider
> msp
;
162 if ( context
.startsWith( "vnd.sun.star.tdoc" ) )
164 Reference
< frame::XModel
> xModel( MiscUtils::tDocUrlToModel( context
) );
166 Reference
< document::XEmbeddedScripts
> xScripts( xModel
, UNO_QUERY
);
167 Reference
< document::XScriptInvocationContext
> xScriptsContext( xModel
, UNO_QUERY
);
168 if ( !xScripts
.is() && !xScriptsContext
.is() )
170 throw lang::IllegalArgumentException(
171 "Failed to create MasterScriptProvider for '"
173 "': Either XEmbeddScripts or XScriptInvocationContext need to be supported by the document.",
177 ::osl::MutexGuard
guard( m_mutex
);
178 Reference
< XInterface
> xNormalized( xModel
, UNO_QUERY
);
179 ScriptComponent_map::const_iterator pos
= m_mScriptComponents
.find( xNormalized
);
180 if ( pos
== m_mScriptComponents
.end() )
182 msp
= createNewMSP( context
);
183 addActiveMSP( xNormalized
, msp
);
192 ::osl::MutexGuard
guard( m_mutex
);
193 Msp_hash::iterator h_itEnd
= m_hMsps
.end();
194 Msp_hash::const_iterator itr
= m_hMsps
.find( context
);
195 if ( itr
== h_itEnd
)
197 msp
= createNewMSP( context
);
198 m_hMsps
[ context
] = msp
;
202 msp
= m_hMsps
[ context
];
206 catch( const lang::IllegalArgumentException
& )
210 catch( const RuntimeException
& )
214 catch( const Exception
& )
216 css::uno::Any anyEx
= cppu::getCaughtException();
217 throw lang::WrappedTargetRuntimeException(
218 "Failed to create MasterScriptProvider for context '"
226 ActiveMSPList::addActiveMSP( const Reference
< uno::XInterface
>& xComponent
,
227 const Reference
< provider::XScriptProvider
>& msp
)
229 ::osl::MutexGuard
guard( m_mutex
);
230 Reference
< XInterface
> xNormalized( xComponent
, UNO_QUERY
);
231 ScriptComponent_map::const_iterator pos
= m_mScriptComponents
.find( xNormalized
);
232 if ( pos
!= m_mScriptComponents
.end() )
235 m_mScriptComponents
[ xNormalized
] = msp
;
237 // add self as listener for component disposal
238 // should probably throw from this method!!, reexamine
241 Reference
< lang::XComponent
> xBroadcaster( xComponent
, UNO_QUERY_THROW
);
242 xBroadcaster
->addEventListener( this );
244 catch ( const Exception
& )
246 DBG_UNHANDLED_EXCEPTION("scripting");
251 void SAL_CALL
ActiveMSPList::disposing( const css::lang::EventObject
& Source
)
256 Reference
< XInterface
> xNormalized( Source
.Source
, UNO_QUERY
);
257 if ( xNormalized
.is() )
259 ::osl::MutexGuard
guard( m_mutex
);
260 ScriptComponent_map::iterator pos
= m_mScriptComponents
.find( xNormalized
);
261 if ( pos
!= m_mScriptComponents
.end() )
262 m_mScriptComponents
.erase( pos
);
265 catch ( const Exception
& )
267 // if we get an exception here, there is not much we can do about
268 // it can't throw as it will screw up the model that is calling dispose
269 DBG_UNHANDLED_EXCEPTION("scripting");
274 ActiveMSPList::createNonDocMSPs()
276 // do creation of user and share MSPs here
277 OUString
serviceName("com.sun.star.script.provider.MasterScriptProvider");
278 Sequence
< Any
> args(1);
280 args
[ 0 ] <<= userDirString
;
281 Reference
< provider::XScriptProvider
> userMsp( m_xContext
->getServiceManager()->createInstanceWithArgumentsAndContext( serviceName
, args
, m_xContext
), UNO_QUERY
);
282 // should check if provider reference is valid
283 m_hMsps
[ userDirString
] = userMsp
;
285 args
[ 0 ] <<= shareDirString
;
286 Reference
< provider::XScriptProvider
> shareMsp( m_xContext
->getServiceManager()->createInstanceWithArgumentsAndContext( serviceName
, args
, m_xContext
), UNO_QUERY
);
287 // should check if provider reference is valid
288 m_hMsps
[ shareDirString
] = shareMsp
;
290 args
[ 0 ] <<= bundledDirString
;
291 Reference
< provider::XScriptProvider
> bundledMsp( m_xContext
->getServiceManager()->createInstanceWithArgumentsAndContext( serviceName
, args
, m_xContext
), UNO_QUERY
);
292 // should check if provider reference is valid
293 m_hMsps
[ bundledDirString
] = bundledMsp
;
296 } // namespace func_provider
298 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */