Update ooo320-m1
[ooovba.git] / scripting / source / protocolhandler / scripthandler.cxx
blob8a009c342b9bfd3fd1cec0f12c36df4db9535e04
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: scripthandler.cxx,v $
10 * $Revision: 1.29.6.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_scripting.hxx"
33 #include "scripthandler.hxx"
35 #include <osl/mutex.hxx>
37 #include <com/sun/star/frame/DispatchResultEvent.hpp>
38 #include <com/sun/star/frame/DispatchResultState.hpp>
39 #include <com/sun/star/frame/XController.hpp>
40 #include <com/sun/star/frame/XModel.hpp>
42 #include <com/sun/star/document/XEmbeddedScripts.hpp>
43 #include <com/sun/star/document/XScriptInvocationContext.hpp>
45 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
47 #include <com/sun/star/script/provider/XScriptProviderSupplier.hpp>
48 #include <com/sun/star/script/provider/XScriptProviderFactory.hpp>
49 #include <com/sun/star/script/provider/ScriptFrameworkErrorType.hpp>
51 #include <sfx2/objsh.hxx>
52 #include <sfx2/frame.hxx>
53 #include <sfx2/sfxdlg.hxx>
54 #include <vcl/abstdlg.hxx>
56 #include <cppuhelper/factory.hxx>
57 #include <cppuhelper/exc_hlp.hxx>
58 #include <util/util.hxx>
60 #include "com/sun/star/uno/XComponentContext.hpp"
61 #include "com/sun/star/uri/XUriReference.hpp"
62 #include "com/sun/star/uri/XUriReferenceFactory.hpp"
63 #include "com/sun/star/uri/XVndSunStarScriptUrl.hpp"
64 #include "com/sun/star/beans/XPropertySet.hpp"
66 using namespace ::com::sun::star;
67 using namespace ::com::sun::star::uno;
68 using namespace ::com::sun::star::frame;
69 using namespace ::com::sun::star::util;
70 using namespace ::com::sun::star::beans;
71 using namespace ::com::sun::star::lang;
72 using namespace ::com::sun::star::script;
73 using namespace ::com::sun::star::script::provider;
74 using namespace ::com::sun::star::document;
75 using namespace ::scripting_util;
77 namespace scripting_protocolhandler
80 const sal_Char * const MYSERVICENAME = "com.sun.star.frame.ProtocolHandler";
81 const sal_Char * const MYIMPLNAME = "com.sun.star.comp.ScriptProtocolHandler";
82 const sal_Char * MYSCHEME = "vnd.sun.star.script";
83 const sal_Int32 MYSCHEME_LEN = 20;
85 void SAL_CALL ScriptProtocolHandler::initialize(
86 const css::uno::Sequence < css::uno::Any >& aArguments )
87 throw ( css::uno::Exception )
89 if ( m_bInitialised )
91 return ;
94 // first argument contains a reference to the frame (may be empty or the desktop,
95 // but usually it's a "real" frame)
96 if ( aArguments.getLength() &&
97 sal_False == ( aArguments[ 0 ] >>= m_xFrame ) )
99 ::rtl::OUString temp = OUSTR( "ScriptProtocolHandler::initialize: could not extract reference to the frame" );
100 throw RuntimeException( temp, Reference< XInterface >() );
103 validateXRef( m_xFactory,
104 "ScriptProtocolHandler::initialize: No Service Manager available" );
105 m_bInitialised = true;
108 Reference< XDispatch > SAL_CALL ScriptProtocolHandler::queryDispatch(
109 const URL& aURL, const ::rtl::OUString& sTargetFrameName, sal_Int32 nSearchFlags )
110 throw( ::com::sun::star::uno::RuntimeException )
112 (void)sTargetFrameName;
113 (void)nSearchFlags;
115 Reference< XDispatch > xDispatcher;
116 // get scheme of url
118 Reference< uri::XUriReferenceFactory > xFac (
119 m_xFactory->createInstance( rtl::OUString::createFromAscii(
120 "com.sun.star.uri.UriReferenceFactory") ) , UNO_QUERY );
121 if ( xFac.is() )
123 Reference< uri::XUriReference > uriRef(
124 xFac->parse( aURL.Complete ), UNO_QUERY );
125 if ( uriRef.is() )
127 if ( uriRef->getScheme().equals( ::rtl::OUString::createFromAscii( ::scripting_protocolhandler::MYSCHEME ) ) )
129 xDispatcher = this;
134 return xDispatcher;
137 Sequence< Reference< XDispatch > > SAL_CALL
138 ScriptProtocolHandler::queryDispatches(
139 const Sequence < DispatchDescriptor >& seqDescriptor )
140 throw( RuntimeException )
142 sal_Int32 nCount = seqDescriptor.getLength();
143 Sequence< Reference< XDispatch > > lDispatcher( nCount );
144 for ( sal_Int32 i = 0; i < nCount; ++i )
146 lDispatcher[ i ] = this->queryDispatch( seqDescriptor[ i ].FeatureURL,
147 seqDescriptor[ i ].FrameName,
148 seqDescriptor[ i ].SearchFlags );
150 return lDispatcher;
153 void SAL_CALL ScriptProtocolHandler::dispatchWithNotification(
154 const URL& aURL, const Sequence < PropertyValue >& lArgs,
155 const Reference< XDispatchResultListener >& xListener )
156 throw ( RuntimeException )
159 sal_Bool bSuccess = sal_False;
160 Any invokeResult;
161 bool bCaughtException = FALSE;
162 Any aException;
164 if ( m_bInitialised )
168 bool bIsDocumentScript = ( aURL.Complete.indexOf( ::rtl::OUString::createFromAscii( "document" ) ) !=-1 );
169 // TODO: isn't this somewhat strange? This should be a test for a location=document parameter, shouldn't it?
171 if ( bIsDocumentScript )
173 // obtain the component for our security check
174 Reference< XEmbeddedScripts > xDocumentScripts;
175 if ( getScriptInvocation() )
176 xDocumentScripts.set( m_xScriptInvocation->getScriptContainer(), UNO_SET_THROW );
178 OSL_ENSURE( xDocumentScripts.is(), "ScriptProtocolHandler::dispatchWithNotification: can't do the security check!" );
179 if ( !xDocumentScripts.is() || !xDocumentScripts->getAllowMacroExecution() )
180 return;
183 // Creates a ScriptProvider ( if one is not created allready )
184 createScriptProvider();
186 Reference< provider::XScript > xFunc =
187 m_xScriptProvider->getScript( aURL.Complete );
188 validateXRef( xFunc,
189 "ScriptProtocolHandler::dispatchWithNotification: validate xFunc - unable to obtain XScript interface" );
192 Sequence< Any > inArgs( 0 );
193 Sequence< Any > outArgs( 0 );
194 Sequence< sal_Int16 > outIndex;
196 if ( lArgs.getLength() > 0 )
198 int argCount = 0;
199 for ( int index = 0; index < lArgs.getLength(); index++ )
201 // Sometimes we get a propertyval with name = "Referer"
202 // this is not an argument to be passed to script, so
203 // ignore.
204 if ( lArgs[ index ].Name.compareToAscii("Referer") != 0 ||
205 lArgs[ index ].Name.getLength() == 0 )
207 inArgs.realloc( ++argCount );
208 inArgs[ argCount - 1 ] = lArgs[ index ].Value;
213 bSuccess = sal_False;
214 while ( !bSuccess )
216 Any aFirstCaughtException;
219 invokeResult = xFunc->invoke( inArgs, outIndex, outArgs );
220 bSuccess = sal_True;
222 catch( const provider::ScriptFrameworkErrorException& se )
224 if ( !aFirstCaughtException.hasValue() )
225 aFirstCaughtException = ::cppu::getCaughtException();
227 if ( se.errorType != provider::ScriptFrameworkErrorType::NO_SUCH_SCRIPT )
228 // the only condition which allows us to retry is if there is no method with the
229 // given name/signature
230 ::cppu::throwException( aFirstCaughtException );
232 if ( inArgs.getLength() == 0 )
233 // no chance to retry if we can't strip more in-args
234 ::cppu::throwException( aFirstCaughtException );
236 // strip one argument, then retry
237 inArgs.realloc( inArgs.getLength() - 1 );
241 // Office doesn't handle exceptions rethrown here very well, it cores,
242 // all we can is log them and then set fail for the dispatch event!
243 // (if there is a listener of course)
244 catch ( const Exception & e )
246 aException = ::cppu::getCaughtException();
248 ::rtl::OUString reason = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ScriptProtocolHandler::dispatch: caught " ) );
250 invokeResult <<= reason.concat( aException.getValueTypeName() ).concat( e.Message );
252 bCaughtException = TRUE;
254 #ifdef _DEBUG
255 catch ( ... )
257 ::rtl::OUString reason = ::rtl::OUString::createFromAscii(
258 "ScriptProtocolHandler::dispatch: caught unknown exception" );
260 invokeResult <<= reason;
262 #endif
265 else
267 ::rtl::OUString reason = ::rtl::OUString::createFromAscii(
268 "ScriptProtocolHandler::dispatchWithNotification failed, ScriptProtocolHandler not initialised"
270 invokeResult <<= reason;
273 if ( bCaughtException )
275 SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create();
277 if ( pFact != NULL )
279 VclAbstractDialog* pDlg =
280 pFact->CreateScriptErrorDialog( NULL, aException );
282 if ( pDlg != NULL )
284 pDlg->Execute();
285 delete pDlg;
290 if ( xListener.is() )
292 // always call dispatchFinished(), because we didn't load a document but
293 // executed a macro instead!
294 ::com::sun::star::frame::DispatchResultEvent aEvent;
296 aEvent.Source = static_cast< ::cppu::OWeakObject* >( this );
297 aEvent.Result = invokeResult;
298 if ( bSuccess )
300 aEvent.State = ::com::sun::star::frame::DispatchResultState::SUCCESS;
302 else
304 aEvent.State = ::com::sun::star::frame::DispatchResultState::FAILURE;
309 xListener->dispatchFinished( aEvent ) ;
311 catch(RuntimeException & e)
313 OSL_TRACE(
314 "ScriptProtocolHandler::dispatchWithNotification: caught RuntimeException"
315 "while dispatchFinished %s",
316 ::rtl::OUStringToOString( e.Message,
317 RTL_TEXTENCODING_ASCII_US ).pData->buffer );
322 void SAL_CALL ScriptProtocolHandler::dispatch(
323 const URL& aURL, const Sequence< PropertyValue >& lArgs )
324 throw ( RuntimeException )
326 dispatchWithNotification( aURL, lArgs, Reference< XDispatchResultListener >() );
329 void SAL_CALL ScriptProtocolHandler::addStatusListener(
330 const Reference< XStatusListener >& xControl, const URL& aURL )
331 throw ( RuntimeException )
333 (void)xControl;
334 (void)aURL;
336 // implement if status is supported
339 void SAL_CALL ScriptProtocolHandler::removeStatusListener(
340 const Reference< XStatusListener >& xControl, const URL& aURL )
341 throw ( RuntimeException )
343 (void)xControl;
344 (void)aURL;
347 bool
348 ScriptProtocolHandler::getScriptInvocation()
350 if ( !m_xScriptInvocation.is() && m_xFrame.is() )
352 Reference< XController > xController = m_xFrame->getController();
353 if ( xController .is() )
355 // try to obtain an XScriptInvocationContext interface, preferred from the
356 // mode, then from the controller
357 if ( !m_xScriptInvocation.set( xController->getModel(), UNO_QUERY ) )
358 m_xScriptInvocation.set( xController, UNO_QUERY );
361 return m_xScriptInvocation.is();
364 void
365 ScriptProtocolHandler::createScriptProvider()
367 if ( m_xScriptProvider.is() )
369 return;
373 // first, ask the component supporting the XScriptInvocationContext interface
374 // (if there is one) for a script provider
375 if ( getScriptInvocation() )
377 Reference< XScriptProviderSupplier > xSPS( m_xScriptInvocation, UNO_QUERY );
378 if ( xSPS.is() )
379 m_xScriptProvider = xSPS->getScriptProvider();
382 // second, ask the model in our frame
383 if ( !m_xScriptProvider.is() && m_xFrame.is() )
385 Reference< XController > xController = m_xFrame->getController();
386 if ( xController .is() )
388 Reference< XScriptProviderSupplier > xSPS( xController->getModel(), UNO_QUERY );
389 if ( xSPS.is() )
390 m_xScriptProvider = xSPS->getScriptProvider();
395 // as a fallback, ask the controller
396 if ( !m_xScriptProvider.is() && m_xFrame.is() )
398 Reference< XScriptProviderSupplier > xSPS( m_xFrame->getController(), UNO_QUERY );
399 if ( xSPS.is() )
400 m_xScriptProvider = xSPS->getScriptProvider();
403 if ( !m_xScriptProvider.is() )
405 Reference< XPropertySet > xProps( m_xFactory, UNO_QUERY_THROW );
407 ::rtl::OUString dc(
408 RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ) );
410 Reference< XComponentContext > xCtx(
411 xProps->getPropertyValue( dc ), UNO_QUERY_THROW );
413 ::rtl::OUString tmspf = ::rtl::OUString::createFromAscii(
414 "/singletons/com.sun.star.script.provider.theMasterScriptProviderFactory");
416 Reference< provider::XScriptProviderFactory > xFac(
417 xCtx->getValueByName( tmspf ), UNO_QUERY_THROW );
419 Any aContext;
420 if ( getScriptInvocation() )
421 aContext = makeAny( m_xScriptInvocation );
422 m_xScriptProvider = Reference< provider::XScriptProvider > (
423 xFac->createScriptProvider( aContext ), UNO_QUERY_THROW );
426 catch ( RuntimeException & e )
428 ::rtl::OUString temp = OUSTR( "ScriptProtocolHandler::createScriptProvider(), " );
429 throw RuntimeException( temp.concat( e.Message ), Reference< XInterface >() );
431 catch ( Exception & e )
433 ::rtl::OUString temp = OUSTR( "ScriptProtocolHandler::createScriptProvider: " );
434 throw RuntimeException( temp.concat( e.Message ), Reference< XInterface >() );
436 #ifdef _DEBUG
437 catch ( ... )
439 throw RuntimeException(
440 OUSTR( "ScriptProtocolHandler::createScriptProvider: UnknownException: " ),
441 Reference< XInterface > () );
443 #endif
447 ScriptProtocolHandler::ScriptProtocolHandler(
448 Reference< css::lang::XMultiServiceFactory > const& rFact ) :
449 m_bInitialised( false ), m_xFactory( rFact )
453 ScriptProtocolHandler::~ScriptProtocolHandler()
457 /* XServiceInfo */
458 ::rtl::OUString SAL_CALL ScriptProtocolHandler::getImplementationName( )
459 throw( RuntimeException )
461 return impl_getStaticImplementationName();
464 /* XServiceInfo */
465 sal_Bool SAL_CALL ScriptProtocolHandler::supportsService(
466 const ::rtl::OUString& sServiceName )
467 throw( RuntimeException )
469 Sequence< ::rtl::OUString > seqServiceNames = getSupportedServiceNames();
470 const ::rtl::OUString* pArray = seqServiceNames.getConstArray();
471 for ( sal_Int32 nCounter = 0; nCounter < seqServiceNames.getLength(); nCounter++ )
473 if ( pArray[ nCounter ] == sServiceName )
475 return sal_True ;
479 return sal_False ;
482 /* XServiceInfo */
483 Sequence< ::rtl::OUString > SAL_CALL ScriptProtocolHandler::getSupportedServiceNames()
484 throw( RuntimeException )
486 return impl_getStaticSupportedServiceNames();
489 /* Helper for XServiceInfo */
490 Sequence< ::rtl::OUString > ScriptProtocolHandler::impl_getStaticSupportedServiceNames()
492 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
493 Sequence< ::rtl::OUString > seqServiceNames( 1 );
494 seqServiceNames.getArray() [ 0 ] =
495 ::rtl::OUString::createFromAscii( ::scripting_protocolhandler::MYSERVICENAME );
496 return seqServiceNames ;
499 /* Helper for XServiceInfo */
500 ::rtl::OUString ScriptProtocolHandler::impl_getStaticImplementationName()
502 return ::rtl::OUString::createFromAscii( ::scripting_protocolhandler::MYIMPLNAME );
505 /* Helper for registry */
506 Reference< XInterface > SAL_CALL ScriptProtocolHandler::impl_createInstance(
507 const Reference< css::lang::XMultiServiceFactory >& xServiceManager )
508 throw( RuntimeException )
510 return Reference< XInterface > ( *new ScriptProtocolHandler( xServiceManager ) );
513 /* Factory for registration */
514 Reference< XSingleServiceFactory > ScriptProtocolHandler::impl_createFactory(
515 const Reference< XMultiServiceFactory >& xServiceManager )
517 Reference< XSingleServiceFactory > xReturn (
518 cppu::createSingleFactory( xServiceManager,
519 ScriptProtocolHandler::impl_getStaticImplementationName(),
520 ScriptProtocolHandler::impl_createInstance,
521 ScriptProtocolHandler::impl_getStaticSupportedServiceNames() )
523 return xReturn;
526 } // namespace scripting_protocolhandler
528 /* exported functions for registration */
529 extern "C"
532 #undef css
533 #define css ::com::sun::star
535 void SAL_CALL component_getImplementationEnvironment(
536 const sal_Char** ppEnvironmentTypeName, uno_Environment** ppEnvironment )
538 (void)ppEnvironment;
540 *ppEnvironmentTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME ;
543 sal_Bool SAL_CALL component_writeInfo( void * pServiceManager ,
544 void * pRegistryKey )
546 (void)pServiceManager;
548 Reference< css::registry::XRegistryKey > xKey(
549 reinterpret_cast< css::registry::XRegistryKey* >( pRegistryKey ) ) ;
551 ::rtl::OUString aStr = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/" ) );
552 aStr +=
553 ::scripting_protocolhandler::ScriptProtocolHandler::impl_getStaticImplementationName();
555 aStr += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/UNO/SERVICES" ) );
556 Reference< css::registry::XRegistryKey > xNewKey = xKey->createKey( aStr );
557 xNewKey->createKey(
558 ::rtl::OUString::createFromAscii( ::scripting_protocolhandler::MYSERVICENAME )
561 return sal_True;
564 void* SAL_CALL component_getFactory( const sal_Char * pImplementationName ,
565 void * pServiceManager ,
566 void * pRegistryKey )
568 (void)pRegistryKey;
570 // Set default return value for this operation - if it failed.
571 void * pReturn = NULL ;
573 if (
574 ( pImplementationName != NULL ) &&
575 ( pServiceManager != NULL )
578 // Define variables which are used in following macros.
579 ::com::sun::star::uno::Reference<
580 ::com::sun::star::lang::XSingleServiceFactory > xFactory ;
581 ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >
582 xServiceManager( reinterpret_cast<
583 ::com::sun::star::lang::XMultiServiceFactory* >( pServiceManager ) ) ;
585 if ( ::scripting_protocolhandler::ScriptProtocolHandler::impl_getStaticImplementationName().equals(
586 ::rtl::OUString::createFromAscii( pImplementationName ) ) )
588 xFactory = ::scripting_protocolhandler::ScriptProtocolHandler::impl_createFactory( xServiceManager );
591 // Factory is valid - service was found.
592 if ( xFactory.is() )
594 xFactory->acquire();
595 pReturn = xFactory.get();
599 // Return with result of this operation.
600 return pReturn ;
602 } // extern "C"