xref: /trunk/main/scripting/source/provider/ActiveMSPList.cxx (revision 137931e43899a1545869cb6af6ea936d8cee4956)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_scripting.hxx"
26 #include <cppuhelper/implementationentry.hxx>
27 #include <cppuhelper/factory.hxx>
28 #include <cppuhelper/implbase1.hxx>
29 #include <cppuhelper/exc_hlp.hxx>
30 #include <util/scriptingconstants.hxx>
31 #include <util/util.hxx>
32 #include <util/MiscUtils.hxx>
33 
34 #include <com/sun/star/beans/XPropertySet.hpp>
35 #include <com/sun/star/util/XMacroExpander.hpp>
36 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
37 
38 #include <com/sun/star/script/browse/BrowseNodeTypes.hpp>
39 
40 #include "MasterScriptProvider.hxx"
41 #include "ActiveMSPList.hxx"
42 
43 #include <tools/diagnose_ex.h>
44 
45 using namespace com::sun::star;
46 using namespace com::sun::star::uno;
47 using namespace com::sun::star::script;
48 using namespace ::sf_misc;
49 
50 namespace func_provider
51 {
52 
53 ActiveMSPList::ActiveMSPList(  const Reference< XComponentContext > & xContext ) : m_xContext( xContext )
54 {
55     userDirString = ::rtl::OUString::createFromAscii("user");
56     shareDirString =  ::rtl::OUString::createFromAscii("share");
57     bundledDirString = ::rtl::OUString::createFromAscii("bundled");
58 }
59 
60 ActiveMSPList::~ActiveMSPList()
61 {
62 }
63 
64 Reference< provider::XScriptProvider >
65 ActiveMSPList::createNewMSP( const uno::Any& context )
66 {
67     ::rtl::OUString serviceName = ::rtl::OUString::createFromAscii("com.sun.star.script.provider.MasterScriptProvider");
68     Sequence< Any > args( &context, 1 );
69 
70     Reference< provider::XScriptProvider > msp(
71         m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
72             serviceName, args, m_xContext ), UNO_QUERY );
73     return msp;
74 }
75 
76 Reference< provider::XScriptProvider >
77 ActiveMSPList::getMSPFromAnyContext( const Any& aContext )
78 {
79     Reference< provider::XScriptProvider > msp;
80     ::rtl::OUString sContext;
81     if ( aContext >>= sContext )
82     {
83         msp = getMSPFromStringContext( sContext );
84         return msp;
85     }
86 
87     Reference< frame::XModel > xModel( aContext, UNO_QUERY );
88 
89     Reference< document::XScriptInvocationContext > xScriptContext( aContext, UNO_QUERY );
90     if ( xScriptContext.is() )
91     {
92         try
93         {
94             // the component supports executing scripts embedded in a - possibly foreign document.
95             // Check whether this other document its the component itself.
96             if ( !xModel.is() || ( xModel != xScriptContext->getScriptContainer() ) )
97             {
98                 msp = getMSPFromInvocationContext( xScriptContext );
99                 return msp;
100             }
101         }
102         catch( const lang::IllegalArgumentException& )
103         {
104             xModel.set( Reference< frame::XModel >() );
105         }
106     }
107 
108     if ( xModel.is() )
109     {
110         sContext = MiscUtils::xModelToTdocUrl( xModel, m_xContext );
111         msp = getMSPFromStringContext( sContext );
112         return msp;
113     }
114 
115     createNonDocMSPs();
116     return m_hMsps[ shareDirString ];
117 }
118 
119 Reference< provider::XScriptProvider >
120     ActiveMSPList::getMSPFromInvocationContext( const Reference< document::XScriptInvocationContext >& xContext )
121 {
122     Reference< provider::XScriptProvider > msp;
123 
124     Reference< document::XEmbeddedScripts > xScripts;
125     if ( xContext.is() )
126         xScripts.set( xContext->getScriptContainer() );
127     if ( !xScripts.is() )
128     {
129         ::rtl::OUStringBuffer buf;
130         buf.appendAscii( "Failed to create MasterScriptProvider for ScriptInvocationContext: " );
131         buf.appendAscii( "Component supporting XEmbeddScripts interface not found." );
132         throw lang::IllegalArgumentException( buf.makeStringAndClear(), NULL, 1 );
133     }
134 
135     ::osl::MutexGuard guard( m_mutex );
136 
137     Reference< XInterface > xNormalized( xContext, UNO_QUERY );
138     ScriptComponent_map::const_iterator pos = m_mScriptComponents.find( xNormalized );
139     if ( pos == m_mScriptComponents.end() )
140     {
141         // TODO
142         msp = createNewMSP( uno::makeAny( xContext ) );
143         addActiveMSP( xNormalized, msp );
144     }
145     else
146     {
147         msp = pos->second;
148     }
149 
150     return msp;
151 }
152 
153 Reference< provider::XScriptProvider >
154     ActiveMSPList::getMSPFromStringContext( const ::rtl::OUString& context )
155 {
156     Reference< provider::XScriptProvider > msp;
157     try
158     {
159         if ( context.indexOf( OUSTR( "vnd.sun.star.tdoc" ) ) == 0 )
160         {
161             Reference< frame::XModel > xModel( MiscUtils::tDocUrlToModel( context ) );
162 
163             Reference< document::XEmbeddedScripts > xScripts( xModel, UNO_QUERY );
164             Reference< document::XScriptInvocationContext > xScriptsContext( xModel, UNO_QUERY );
165             if ( !xScripts.is() && !xScriptsContext.is() )
166             {
167                 ::rtl::OUStringBuffer buf;
168                 buf.appendAscii( "Failed to create MasterScriptProvider for '" );
169                 buf.append     ( context );
170                 buf.appendAscii( "': Either XEmbeddScripts or XScriptInvocationContext need to be supported by the document." );
171                 throw lang::IllegalArgumentException( buf.makeStringAndClear(), NULL, 1 );
172             }
173 
174             ::osl::MutexGuard guard( m_mutex );
175             Reference< XInterface > xNormalized( xModel, UNO_QUERY );
176             ScriptComponent_map::const_iterator pos = m_mScriptComponents.find( xNormalized );
177             if ( pos == m_mScriptComponents.end() )
178             {
179                 msp = createNewMSP( context );
180                 addActiveMSP( xNormalized, msp );
181             }
182             else
183             {
184                 msp = pos->second;
185             }
186         }
187         else
188         {
189             ::osl::MutexGuard guard( m_mutex );
190             Msp_hash::iterator h_itEnd =  m_hMsps.end();
191             Msp_hash::const_iterator itr = m_hMsps.find( context );
192             if ( itr ==  h_itEnd )
193             {
194                 msp = createNewMSP( context );
195                 m_hMsps[ context ] = msp;
196             }
197             else
198             {
199                 msp = m_hMsps[ context ];
200             }
201         }
202     }
203     catch( const lang::IllegalArgumentException& )
204     {
205         // allowed to leave
206     }
207     catch( const RuntimeException& )
208     {
209         // allowed to leave
210     }
211     catch( const Exception& )
212     {
213         ::rtl::OUStringBuffer aMessage;
214         aMessage.appendAscii( "Failed to create MasterScriptProvider for context '" );
215         aMessage.append     ( context );
216         aMessage.appendAscii( "'." );
217         throw lang::WrappedTargetRuntimeException(
218             aMessage.makeStringAndClear(), *this, ::cppu::getCaughtException() );
219     }
220     return msp;
221 }
222 
223 void
224 ActiveMSPList::addActiveMSP( const Reference< uno::XInterface >& xComponent,
225             const Reference< provider::XScriptProvider >& msp )
226 {
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() )
231     {
232         m_mScriptComponents[ xNormalized ] = msp;
233 
234         // add self as listener for component disposal
235         // should probably throw from this method!!, reexamine
236         try
237         {
238             Reference< lang::XComponent > xBroadcaster =
239                 Reference< lang::XComponent >( xComponent, UNO_QUERY_THROW );
240             xBroadcaster->addEventListener( this );
241         }
242         catch ( const Exception& )
243         {
244             DBG_UNHANDLED_EXCEPTION();
245         }
246     }
247 }
248 
249 //*************************************************************************
250 void SAL_CALL
251 ActiveMSPList::disposing( const ::com::sun::star::lang::EventObject& Source )
252 
253 {
254     try
255     {
256         Reference< XInterface > xNormalized( Source.Source, UNO_QUERY );
257         if ( xNormalized.is() )
258         {
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 );
263         }
264     }
265     catch ( const Exception& )
266     {
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();
270     }
271 }
272 
273 
274 void
275 ActiveMSPList::createNonDocMSPs()
276 {
277     static bool created = false;
278     if ( created )
279     {
280         return;
281     }
282     else
283     {
284         ::osl::MutexGuard guard( m_mutex );
285         if ( created )
286         {
287             return;
288         }
289         // do creation of user and share MSPs here
290         ::rtl::OUString serviceName = ::rtl::OUString::createFromAscii("com.sun.star.script.provider.MasterScriptProvider");
291         Sequence< Any > args(1);
292 
293         args[ 0 ] <<= userDirString;
294         Reference< provider::XScriptProvider > userMsp( m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext( serviceName, args, m_xContext ), UNO_QUERY );
295         // should check if provider reference is valid
296         m_hMsps[ userDirString ] = userMsp;
297 
298         args[ 0 ] <<= shareDirString;
299         Reference< provider::XScriptProvider > shareMsp( m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext( serviceName, args, m_xContext ), UNO_QUERY );
300         // should check if provider reference is valid
301         m_hMsps[ shareDirString ] = shareMsp;
302 
303         args[ 0 ] <<= bundledDirString;
304         Reference< provider::XScriptProvider > bundledMsp( m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext( serviceName, args, m_xContext ), UNO_QUERY );
305         // should check if provider reference is valid
306         m_hMsps[ bundledDirString ] = bundledMsp;
307 
308         created = true;
309     }
310 
311 }
312 
313 
314 } // namespace func_provider
315