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 <comphelper/diagnose_ex.hxx>
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 u
"com.sun.star.script.provider.MasterScriptProvider"_ustr
, args
, m_xContext
), UNO_QUERY
);
59 class NonDocMSPCreator
62 explicit NonDocMSPCreator(ActiveMSPList
*pList
)
64 pList
->createNonDocMSPs();
70 //thread-safe method to ensure createNonDocMSPs is called once
71 void ensureNonDocMSPs(ActiveMSPList
*pList
)
73 static NonDocMSPCreator
theCreator(pList
);
77 Reference
< provider::XScriptProvider
>
78 ActiveMSPList::getMSPFromAnyContext( const Any
& aContext
)
80 Reference
< provider::XScriptProvider
> msp
;
82 if ( aContext
>>= sContext
)
84 msp
= getMSPFromStringContext( sContext
);
88 Reference
< frame::XModel
> xModel( aContext
, UNO_QUERY
);
90 Reference
< document::XScriptInvocationContext
> xScriptContext( aContext
, UNO_QUERY
);
91 if ( xScriptContext
.is() )
95 // the component supports executing scripts embedded in a - possibly foreign document.
96 // Check whether this other document it's the component itself.
97 if ( !xModel
.is() || ( xModel
!= xScriptContext
->getScriptContainer() ) )
99 msp
= getMSPFromInvocationContext( xScriptContext
);
103 catch( const lang::IllegalArgumentException
& )
105 xModel
.set( Reference
< frame::XModel
>() );
111 sContext
= MiscUtils::xModelToTdocUrl( xModel
, m_xContext
);
112 msp
= getMSPFromStringContext( sContext
);
116 ensureNonDocMSPs(this);
117 return m_hMsps
[ shareDirString
];
120 Reference
< provider::XScriptProvider
>
121 ActiveMSPList::getMSPFromInvocationContext( const Reference
< document::XScriptInvocationContext
>& xContext
)
123 Reference
< provider::XScriptProvider
> msp
;
125 Reference
< document::XEmbeddedScripts
> xScripts
;
127 xScripts
.set( xContext
->getScriptContainer() );
128 if ( !xScripts
.is() )
130 throw lang::IllegalArgumentException(
131 u
"Failed to create MasterScriptProvider for ScriptInvocationContext: "
132 "Component supporting XEmbeddScripts interface not found."_ustr
,
136 ::osl::MutexGuard
guard( m_mutex
);
138 Reference
< XInterface
> xNormalized( xContext
, UNO_QUERY
);
139 ScriptComponent_map::const_iterator pos
= m_mScriptComponents
.find( xNormalized
);
140 if ( pos
== m_mScriptComponents
.end() )
143 msp
= createNewMSP( uno::Any( xContext
) );
144 addActiveMSP( xNormalized
, msp
);
154 Reference
< provider::XScriptProvider
>
155 ActiveMSPList::getMSPFromStringContext( const OUString
& context
)
157 Reference
< provider::XScriptProvider
> msp
;
160 if ( context
.startsWith( "vnd.sun.star.tdoc" ) )
162 Reference
< frame::XModel
> xModel( MiscUtils::tDocUrlToModel( context
) );
164 Reference
< document::XEmbeddedScripts
> xScripts( xModel
, UNO_QUERY
);
165 Reference
< document::XScriptInvocationContext
> xScriptsContext( xModel
, UNO_QUERY
);
166 if ( !xScripts
.is() && !xScriptsContext
.is() )
168 throw lang::IllegalArgumentException(
169 "Failed to create MasterScriptProvider for '"
171 "': Either XEmbeddScripts or XScriptInvocationContext need to be supported by the document.",
175 ::osl::MutexGuard
guard( m_mutex
);
176 Reference
< XInterface
> xNormalized( xModel
, UNO_QUERY
);
177 ScriptComponent_map::const_iterator pos
= m_mScriptComponents
.find( xNormalized
);
178 if ( pos
== m_mScriptComponents
.end() )
180 msp
= createNewMSP( context
);
181 addActiveMSP( xNormalized
, msp
);
190 ::osl::MutexGuard
guard( m_mutex
);
191 Msp_hash::iterator h_itEnd
= m_hMsps
.end();
192 Msp_hash::const_iterator itr
= m_hMsps
.find( context
);
193 if ( itr
== h_itEnd
)
195 msp
= createNewMSP( context
);
196 m_hMsps
[ context
] = msp
;
200 msp
= m_hMsps
[ context
];
204 catch( const lang::IllegalArgumentException
& )
208 catch( const RuntimeException
& )
212 catch( const Exception
& )
214 css::uno::Any anyEx
= cppu::getCaughtException();
215 throw lang::WrappedTargetRuntimeException(
216 "Failed to create MasterScriptProvider for context '"
224 ActiveMSPList::addActiveMSP( const Reference
< uno::XInterface
>& xComponent
,
225 const Reference
< provider::XScriptProvider
>& msp
)
227 ::osl::MutexGuard
guard( m_mutex
);
228 Reference
< XInterface
> xNormalized( xComponent
, UNO_QUERY
);
229 ScriptComponent_map::const_iterator pos
= m_mScriptComponents
.find( xNormalized
);
230 if ( pos
!= m_mScriptComponents
.end() )
233 m_mScriptComponents
[ xNormalized
] = msp
;
235 // add self as listener for component disposal
236 // should probably throw from this method!!, reexamine
239 Reference
< lang::XComponent
> xBroadcaster( xComponent
, UNO_QUERY_THROW
);
240 xBroadcaster
->addEventListener( this );
242 catch ( const Exception
& )
244 DBG_UNHANDLED_EXCEPTION("scripting");
249 void SAL_CALL
ActiveMSPList::disposing( const css::lang::EventObject
& Source
)
254 Reference
< XInterface
> xNormalized( Source
.Source
, UNO_QUERY
);
255 if ( xNormalized
.is() )
257 ::osl::MutexGuard
guard( m_mutex
);
258 ScriptComponent_map::iterator pos
= m_mScriptComponents
.find( xNormalized
);
259 if ( pos
!= m_mScriptComponents
.end() )
260 m_mScriptComponents
.erase( pos
);
263 catch ( const Exception
& )
265 // if we get an exception here, there is not much we can do about
266 // it can't throw as it will screw up the model that is calling dispose
267 DBG_UNHANDLED_EXCEPTION("scripting");
272 ActiveMSPList::createNonDocMSPs()
274 // do creation of user and share MSPs here
275 OUString
serviceName(u
"com.sun.star.script.provider.MasterScriptProvider"_ustr
);
277 Sequence
< Any
> args
{ Any(userDirString
) };
278 // should check if provider reference is valid
279 m_hMsps
[ userDirString
].set( m_xContext
->getServiceManager()->createInstanceWithArgumentsAndContext( serviceName
, args
, m_xContext
), UNO_QUERY
);
281 args
= { Any(shareDirString
) };
282 // should check if provider reference is valid
283 m_hMsps
[ shareDirString
].set( m_xContext
->getServiceManager()->createInstanceWithArgumentsAndContext( serviceName
, args
, m_xContext
), UNO_QUERY
);
285 args
= { Any(bundledDirString
) };
286 // should check if provider reference is valid
287 m_hMsps
[ bundledDirString
].set( m_xContext
->getServiceManager()->createInstanceWithArgumentsAndContext( serviceName
, args
, m_xContext
), UNO_QUERY
);
290 } // namespace func_provider
292 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */