merge the formfield patch from ooo-build
[ooovba.git] / scripting / source / basprov / basprov.cxx
blob562e60514c5c1951ca9fb5dbcb57d29e836d039c
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: basprov.cxx,v $
10 * $Revision: 1.21.6.3 $
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 "basprov.hxx"
34 #include "basscript.hxx"
35 #include "baslibnode.hxx"
36 #include <com/sun/star/frame/XModel.hpp>
37 #include <com/sun/star/script/browse/BrowseNodeTypes.hpp>
38 #include <com/sun/star/script/provider/ScriptFrameworkErrorType.hpp>
39 #include <com/sun/star/document/XEmbeddedScripts.hpp>
41 #ifndef _CPPUHELPER_IMPLEMENTATIONENTRY_HXX_
42 #include <cppuhelper/implementationentry.hxx>
43 #endif
44 #include <rtl/uri.hxx>
45 #include <osl/process.h>
46 #include <osl/file.hxx>
47 #include <vos/mutex.hxx>
48 #include <vcl/svapp.hxx>
49 #include <basic/sbx.hxx>
50 #include <basic/basmgr.hxx>
51 #include <basic/basicmanagerrepository.hxx>
52 #include <basic/sbstar.hxx>
53 #include <basic/sbmod.hxx>
54 #include <basic/sbmeth.hxx>
55 #include <sfx2/app.hxx>
56 #include <sfx2/objsh.hxx>
58 #include <com/sun/star/util/XMacroExpander.hpp>
59 #include <com/sun/star/script/XLibraryContainer2.hpp>
60 #include <com/sun/star/uri/XUriReference.hpp>
61 #include <com/sun/star/uri/XUriReferenceFactory.hpp>
62 #include <com/sun/star/uri/XVndSunStarScriptUrl.hpp>
64 #include <util/util.hxx>
65 #include <util/MiscUtils.hxx>
68 using namespace ::com::sun::star;
69 using namespace ::com::sun::star::lang;
70 using namespace ::com::sun::star::uno;
71 using namespace ::com::sun::star::script;
72 using namespace ::com::sun::star::document;
73 using namespace ::sf_misc;
75 //.........................................................................
76 namespace basprov
78 //.........................................................................
80 // =============================================================================
81 // component operations
82 // =============================================================================
84 static ::rtl::OUString getImplementationName_BasicProviderImpl()
86 static ::rtl::OUString* pImplName = 0;
87 if ( !pImplName )
89 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
90 if ( !pImplName )
92 static ::rtl::OUString aImplName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.scripting.ScriptProviderForBasic" ) );
93 pImplName = &aImplName;
96 return *pImplName;
99 // -----------------------------------------------------------------------------
101 static Sequence< ::rtl::OUString > getSupportedServiceNames_BasicProviderImpl()
103 static Sequence< ::rtl::OUString >* pNames = 0;
104 if ( !pNames )
106 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
107 if ( !pNames )
109 static Sequence< ::rtl::OUString > aNames(4);
110 aNames.getArray()[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.script.provider.ScriptProviderForBasic" ) );
111 aNames.getArray()[1] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.script.provider.LanguageScriptProvider" ) );
112 aNames.getArray()[2] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.script.provider.ScriptProvider" ) );
113 aNames.getArray()[3] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.script.browse.BrowseNode" ) );
114 pNames = &aNames;
117 return *pNames;
120 // =============================================================================
121 // BasicProviderImpl
122 // =============================================================================
124 BasicProviderImpl::BasicProviderImpl( const Reference< XComponentContext >& xContext )
125 :m_pAppBasicManager( 0 )
126 ,m_pDocBasicManager( 0 )
127 ,m_xLibContainerApp( 0 )
128 ,m_xLibContainerDoc( 0 )
129 ,m_xContext( xContext )
130 ,m_bIsAppScriptCtx( true )
131 ,m_bIsUserCtx(true)
135 // -----------------------------------------------------------------------------
137 BasicProviderImpl::~BasicProviderImpl()
141 // -----------------------------------------------------------------------------
143 bool BasicProviderImpl::isLibraryShared( const Reference< script::XLibraryContainer >& rxLibContainer, const ::rtl::OUString& rLibName )
145 bool bIsShared = false;
147 Reference< script::XLibraryContainer2 > xLibContainer( rxLibContainer, UNO_QUERY );
148 if ( xLibContainer.is() && xLibContainer->hasByName( rLibName ) && xLibContainer->isLibraryLink( rLibName ) )
150 ::rtl::OUString aFileURL;
151 if ( m_xContext.is() )
153 Reference< uri::XUriReferenceFactory > xUriFac;
154 Reference< lang::XMultiComponentFactory > xSMgr( m_xContext->getServiceManager() );
155 if ( xSMgr.is() )
157 xUriFac.set( xSMgr->createInstanceWithContext( ::rtl::OUString::createFromAscii(
158 "com.sun.star.uri.UriReferenceFactory" ), m_xContext ), UNO_QUERY );
161 if ( xUriFac.is() )
163 ::rtl::OUString aLinkURL( xLibContainer->getLibraryLinkURL( rLibName ) );
164 Reference< uri::XUriReference > xUriRef( xUriFac->parse( aLinkURL ), UNO_QUERY );
166 if ( xUriRef.is() )
168 ::rtl::OUString aScheme = xUriRef->getScheme();
169 if ( aScheme.equalsIgnoreAsciiCaseAscii( "file" ) )
171 aFileURL = aLinkURL;
173 else if ( aScheme.equalsIgnoreAsciiCaseAscii( "vnd.sun.star.pkg" ) )
175 ::rtl::OUString aAuthority = xUriRef->getAuthority();
176 if ( aAuthority.matchIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM( "vnd.sun.star.expand:" ) ) )
178 ::rtl::OUString aDecodedURL( aAuthority.copy( sizeof ( "vnd.sun.star.expand:" ) - 1 ) );
179 aDecodedURL = ::rtl::Uri::decode( aDecodedURL, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 );
180 Reference<util::XMacroExpander> xMacroExpander(
181 m_xContext->getValueByName(
182 ::rtl::OUString::createFromAscii( "/singletons/com.sun.star.util.theMacroExpander" ) ),
183 UNO_QUERY );
184 if ( xMacroExpander.is() )
185 aFileURL = xMacroExpander->expandMacros( aDecodedURL );
192 if ( aFileURL.getLength() )
194 osl::DirectoryItem aFileItem;
195 osl::FileStatus aFileStatus( FileStatusMask_FileURL );
196 OSL_VERIFY( osl::DirectoryItem::get( aFileURL, aFileItem ) == osl::FileBase::E_None );
197 OSL_VERIFY( aFileItem.getFileStatus( aFileStatus ) == osl::FileBase::E_None );
198 ::rtl::OUString aCanonicalFileURL( aFileStatus.getFileURL() );
200 ::rtl::OUString aSearchURL1( RTL_CONSTASCII_USTRINGPARAM( "share/basic" ) );
201 ::rtl::OUString aSearchURL2( RTL_CONSTASCII_USTRINGPARAM( "share/uno_packages" ) );
202 if( aCanonicalFileURL.indexOf( aSearchURL1 ) != -1 || aCanonicalFileURL.indexOf( aSearchURL2 ) != -1 )
203 bIsShared = true;
207 return bIsShared;
210 // -----------------------------------------------------------------------------
211 // XServiceInfo
212 // -----------------------------------------------------------------------------
214 ::rtl::OUString BasicProviderImpl::getImplementationName( ) throw (RuntimeException)
216 return getImplementationName_BasicProviderImpl();
219 // -----------------------------------------------------------------------------
221 sal_Bool BasicProviderImpl::supportsService( const ::rtl::OUString& rServiceName ) throw (RuntimeException)
223 Sequence< ::rtl::OUString > aNames( getSupportedServiceNames() );
224 const ::rtl::OUString* pNames = aNames.getConstArray();
225 const ::rtl::OUString* pEnd = pNames + aNames.getLength();
226 for ( ; pNames != pEnd && !pNames->equals( rServiceName ); ++pNames )
229 return pNames != pEnd;
232 // -----------------------------------------------------------------------------
234 Sequence< ::rtl::OUString > BasicProviderImpl::getSupportedServiceNames( ) throw (RuntimeException)
236 return getSupportedServiceNames_BasicProviderImpl();
239 // -----------------------------------------------------------------------------
240 // XInitialization
241 // -----------------------------------------------------------------------------
243 void BasicProviderImpl::initialize( const Sequence< Any >& aArguments ) throw (Exception, RuntimeException)
245 // TODO
247 ::vos::OGuard aGuard( Application::GetSolarMutex() );
249 if ( aArguments.getLength() != 1 )
251 throw IllegalArgumentException(
252 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "BasicProviderImpl::initialize: incorrect argument count." ) ),
253 *this,
258 Reference< frame::XModel > xModel;
260 m_xInvocationContext.set( aArguments[0], UNO_QUERY );;
261 if ( m_xInvocationContext.is() )
263 xModel.set( m_xInvocationContext->getScriptContainer(), UNO_QUERY );
264 if ( !xModel.is() )
266 throw IllegalArgumentException(
267 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "BasicProviderImpl::initialize: unable to determine the document model from the script invocation context." ) ),
268 *this,
273 else
275 if ( !( aArguments[0] >>= m_sScriptingContext ) )
277 throw IllegalArgumentException(
278 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "BasicProviderImpl::initialize: incorrect argument type " ) ).concat( aArguments[0].getValueTypeName() ),
279 *this,
284 ::rtl::OUString sDoc = OUSTR("vnd.sun.star.tdoc");
285 if ( m_sScriptingContext.indexOf( sDoc ) == 0 )
287 xModel = MiscUtils::tDocUrlToModel( m_sScriptingContext );
288 // TODO: use ScriptingContantsPool for SCRIPTING_DOC_REF
292 if ( xModel.is() )
294 Reference< XEmbeddedScripts > xDocumentScripts( xModel, UNO_QUERY );
295 if ( xDocumentScripts.is() )
297 m_pDocBasicManager = ::basic::BasicManagerRepository::getDocumentBasicManager( xModel );
298 m_xLibContainerDoc.set( xDocumentScripts->getBasicLibraries(), UNO_QUERY );
299 OSL_ENSURE( m_pDocBasicManager && m_xLibContainerDoc.is(),
300 "BasicProviderImpl::initialize: invalid BasicManager, or invalid script container!" );
302 m_bIsAppScriptCtx = false;
304 else
306 // Provider has been created with application context for user
307 // or share
308 if ( !m_sScriptingContext.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "user" ) ) )
310 m_bIsUserCtx = false;
312 else
315 throw RuntimeException(
316 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "BasicProviderImpl::initialize: no scripting context!" ) ),
317 Reference< XInterface >() );
322 // TODO
323 if ( !m_pAppBasicManager )
324 m_pAppBasicManager = SFX_APP()->GetBasicManager();
326 if ( !m_xLibContainerApp.is() )
327 m_xLibContainerApp = Reference< script::XLibraryContainer >( SFX_APP()->GetBasicContainer(), UNO_QUERY );
330 // -----------------------------------------------------------------------------
332 // XScriptProvider
333 // -----------------------------------------------------------------------------
335 Reference < provider::XScript > BasicProviderImpl::getScript( const ::rtl::OUString& scriptURI )
336 throw ( provider::ScriptFrameworkErrorException, RuntimeException)
338 // TODO
340 ::vos::OGuard aGuard( Application::GetSolarMutex() );
342 Reference< provider::XScript > xScript;
343 Reference< lang::XMultiComponentFactory > xMcFac ( m_xContext->getServiceManager() );
344 Reference< uri::XUriReferenceFactory > xFac (
345 xMcFac->createInstanceWithContext( rtl::OUString::createFromAscii(
346 "com.sun.star.uri.UriReferenceFactory"), m_xContext ) , UNO_QUERY );
348 if ( !xFac.is() )
350 throw provider::ScriptFrameworkErrorException(
351 OUSTR( "Failed to instantiate UriReferenceFactory" ), Reference< XInterface >(),
352 scriptURI, OUSTR("Basic"),
353 provider::ScriptFrameworkErrorType::UNKNOWN );
356 Reference< uri::XUriReference > uriRef(
357 xFac->parse( scriptURI ), UNO_QUERY );
359 Reference < uri::XVndSunStarScriptUrl > sfUri( uriRef, UNO_QUERY );
361 if ( !uriRef.is() || !sfUri.is() )
363 ::rtl::OUString errorMsg = ::rtl::OUString::createFromAscii( "BasicProviderImpl::getScript: failed to parse URI: " );
364 errorMsg = errorMsg.concat( scriptURI );
365 throw provider::ScriptFrameworkErrorException(
366 errorMsg, Reference< XInterface >(),
367 scriptURI, OUSTR("Basic"),
368 provider::ScriptFrameworkErrorType::MALFORMED_URL );
372 ::rtl::OUString aDescription = sfUri->getName();
373 ::rtl::OUString aLocation = sfUri->getParameter(
374 ::rtl::OUString::createFromAscii( "location" ) );
376 sal_Int32 nIndex = 0;
377 ::rtl::OUString aLibrary = aDescription.getToken( 0, (sal_Unicode)'.', nIndex );
378 ::rtl::OUString aModule;
379 if ( nIndex != -1 )
380 aModule = aDescription.getToken( 0, (sal_Unicode)'.', nIndex );
381 ::rtl::OUString aMethod;
382 if ( nIndex != -1 )
383 aMethod = aDescription.getToken( 0, (sal_Unicode)'.', nIndex );
385 if ( aLibrary.getLength() != 0 && aModule.getLength() != 0 && aMethod.getLength() != 0 && aLocation.getLength() != 0 )
387 BasicManager* pBasicMgr = NULL;
388 if ( aLocation.equals( ::rtl::OUString::createFromAscii("document") ) )
390 pBasicMgr = m_pDocBasicManager;
392 else if ( aLocation.equals( ::rtl::OUString::createFromAscii("application") ) )
394 pBasicMgr = m_pAppBasicManager;
397 if ( pBasicMgr )
399 StarBASIC* pBasic = pBasicMgr->GetLib( aLibrary );
400 if ( !pBasic )
402 USHORT nId = pBasicMgr->GetLibId( aLibrary );
403 if ( nId != LIB_NOTFOUND )
405 pBasicMgr->LoadLib( nId );
406 pBasic = pBasicMgr->GetLib( aLibrary );
409 if ( pBasic )
411 SbModule* pModule = pBasic->FindModule( aModule );
412 if ( pModule )
414 SbxArray* pMethods = pModule->GetMethods();
415 if ( pMethods )
417 SbMethod* pMethod = static_cast< SbMethod* >( pMethods->Find( aMethod, SbxCLASS_METHOD ) );
418 if ( pMethod )
420 if ( m_pDocBasicManager == pBasicMgr )
421 xScript = new BasicScriptImpl( aDescription, pMethod, *m_pDocBasicManager, m_xInvocationContext );
422 else
423 xScript = new BasicScriptImpl( aDescription, pMethod );
431 if ( !xScript.is() )
433 ::rtl::OUStringBuffer aMessage;
434 aMessage.appendAscii( "The following Basic script could not be found:\n" );
435 aMessage.appendAscii( "library: '" ).append( aLibrary ).appendAscii( "'\n" );
436 aMessage.appendAscii( "module: '" ).append( aModule ).appendAscii( "'\n" );
437 aMessage.appendAscii( "method: '" ).append( aMethod ).appendAscii( "'\n" );
438 aMessage.appendAscii( "location: '" ).append( aLocation ).appendAscii( "'\n" );
439 throw provider::ScriptFrameworkErrorException(
440 aMessage.makeStringAndClear(),
441 Reference< XInterface >(),
442 scriptURI, OUSTR("Basic"),
443 provider::ScriptFrameworkErrorType::NO_SUCH_SCRIPT );
446 return xScript;
449 // -----------------------------------------------------------------------------
450 // XBrowseNode
451 // -----------------------------------------------------------------------------
453 ::rtl::OUString BasicProviderImpl::getName( ) throw (RuntimeException)
455 // TODO
457 ::vos::OGuard aGuard( Application::GetSolarMutex() );
459 return ::rtl::OUString::createFromAscii( "Basic" );
462 // -----------------------------------------------------------------------------
464 Sequence< Reference< browse::XBrowseNode > > BasicProviderImpl::getChildNodes( ) throw (RuntimeException)
466 ::vos::OGuard aGuard( Application::GetSolarMutex() );
468 Reference< script::XLibraryContainer > xLibContainer;
469 BasicManager* pBasicManager = NULL;
471 if ( m_bIsAppScriptCtx )
473 xLibContainer = m_xLibContainerApp;
474 pBasicManager = m_pAppBasicManager;
476 else
478 xLibContainer = m_xLibContainerDoc;
479 pBasicManager = m_pDocBasicManager;
482 Sequence< Reference< browse::XBrowseNode > > aChildNodes;
484 if ( pBasicManager && xLibContainer.is() )
486 Sequence< ::rtl::OUString > aLibNames = xLibContainer->getElementNames();
487 sal_Int32 nLibCount = aLibNames.getLength();
488 const ::rtl::OUString* pLibNames = aLibNames.getConstArray();
489 aChildNodes.realloc( nLibCount );
490 Reference< browse::XBrowseNode >* pChildNodes = aChildNodes.getArray();
491 sal_Int32 childsFound = 0;
493 for ( sal_Int32 i = 0 ; i < nLibCount ; ++i )
495 bool bCreate = false;
496 if ( m_bIsAppScriptCtx )
498 bool bShared = isLibraryShared( xLibContainer, pLibNames[i] );
499 if ( ( m_bIsUserCtx && !bShared ) || ( !m_bIsUserCtx && bShared ) )
500 bCreate = true;
502 else
504 bCreate = true;
506 if ( bCreate )
508 pChildNodes[childsFound++] = static_cast< browse::XBrowseNode* >( new BasicLibraryNodeImpl(
509 m_xContext, m_sScriptingContext, pBasicManager, xLibContainer, pLibNames[i], m_bIsAppScriptCtx ) );
513 if ( childsFound != nLibCount )
514 aChildNodes.realloc( childsFound );
517 return aChildNodes;
520 // -----------------------------------------------------------------------------
522 sal_Bool BasicProviderImpl::hasChildNodes( ) throw (RuntimeException)
524 ::vos::OGuard aGuard( Application::GetSolarMutex() );
526 sal_Bool bReturn = sal_False;
527 Reference< script::XLibraryContainer > xLibContainer;
528 if ( m_bIsAppScriptCtx )
530 xLibContainer = m_xLibContainerApp;
532 else
534 xLibContainer = m_xLibContainerDoc;
536 if ( xLibContainer.is() )
537 bReturn = xLibContainer->hasElements();
539 return bReturn;
542 // -----------------------------------------------------------------------------
544 sal_Int16 BasicProviderImpl::getType( ) throw (RuntimeException)
546 ::vos::OGuard aGuard( Application::GetSolarMutex() );
548 return browse::BrowseNodeTypes::CONTAINER;
551 // =============================================================================
552 // component operations
553 // =============================================================================
555 static Reference< XInterface > SAL_CALL create_BasicProviderImpl(
556 Reference< XComponentContext > const & xContext )
557 SAL_THROW( () )
559 return static_cast< lang::XTypeProvider * >( new BasicProviderImpl( xContext ) );
562 // -----------------------------------------------------------------------------
564 static struct ::cppu::ImplementationEntry s_component_entries [] =
567 create_BasicProviderImpl, getImplementationName_BasicProviderImpl,
568 getSupportedServiceNames_BasicProviderImpl, ::cppu::createSingleComponentFactory,
569 0, 0
571 { 0, 0, 0, 0, 0, 0 }
574 // -----------------------------------------------------------------------------
576 //.........................................................................
577 } // namespace basprov
578 //.........................................................................
581 // =============================================================================
582 // component exports
583 // =============================================================================
585 extern "C"
587 SAL_DLLPUBLIC_EXPORT void SAL_CALL component_getImplementationEnvironment(
588 const sal_Char ** ppEnvTypeName, uno_Environment ** ppEnv )
590 (void)ppEnv;
592 *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
595 SAL_DLLPUBLIC_EXPORT sal_Bool SAL_CALL component_writeInfo(
596 lang::XMultiServiceFactory * pServiceManager, registry::XRegistryKey * pRegistryKey )
598 return ::cppu::component_writeInfoHelper(
599 pServiceManager, pRegistryKey, ::basprov::s_component_entries );
602 SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory(
603 const sal_Char * pImplName, lang::XMultiServiceFactory * pServiceManager,
604 registry::XRegistryKey * pRegistryKey )
606 return ::cppu::component_getFactoryHelper(
607 pImplName, pServiceManager, pRegistryKey, ::basprov::s_component_entries );