1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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>
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 //.........................................................................
78 //.........................................................................
80 // =============================================================================
81 // component operations
82 // =============================================================================
84 static ::rtl::OUString
getImplementationName_BasicProviderImpl()
86 static ::rtl::OUString
* pImplName
= 0;
89 ::osl::MutexGuard
aGuard( ::osl::Mutex::getGlobalMutex() );
92 static ::rtl::OUString
aImplName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.scripting.ScriptProviderForBasic" ) );
93 pImplName
= &aImplName
;
99 // -----------------------------------------------------------------------------
101 static Sequence
< ::rtl::OUString
> getSupportedServiceNames_BasicProviderImpl()
103 static Sequence
< ::rtl::OUString
>* pNames
= 0;
106 ::osl::MutexGuard
aGuard( ::osl::Mutex::getGlobalMutex() );
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" ) );
120 // =============================================================================
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 )
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() );
157 xUriFac
.set( xSMgr
->createInstanceWithContext( ::rtl::OUString::createFromAscii(
158 "com.sun.star.uri.UriReferenceFactory" ), m_xContext
), UNO_QUERY
);
163 ::rtl::OUString
aLinkURL( xLibContainer
->getLibraryLinkURL( rLibName
) );
164 Reference
< uri::XUriReference
> xUriRef( xUriFac
->parse( aLinkURL
), UNO_QUERY
);
168 ::rtl::OUString aScheme
= xUriRef
->getScheme();
169 if ( aScheme
.equalsIgnoreAsciiCaseAscii( "file" ) )
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" ) ),
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 )
210 // -----------------------------------------------------------------------------
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 // -----------------------------------------------------------------------------
241 // -----------------------------------------------------------------------------
243 void BasicProviderImpl::initialize( const Sequence
< Any
>& aArguments
) throw (Exception
, RuntimeException
)
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." ) ),
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
);
266 throw IllegalArgumentException(
267 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "BasicProviderImpl::initialize: unable to determine the document model from the script invocation context." ) ),
275 if ( !( aArguments
[0] >>= m_sScriptingContext
) )
277 throw IllegalArgumentException(
278 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "BasicProviderImpl::initialize: incorrect argument type " ) ).concat( aArguments
[0].getValueTypeName() ),
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
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;
306 // Provider has been created with application context for user
308 if ( !m_sScriptingContext
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "user" ) ) )
310 m_bIsUserCtx
= false;
315 throw RuntimeException(
316 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "BasicProviderImpl::initialize: no scripting context!" ) ),
317 Reference< XInterface >() );
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 // -----------------------------------------------------------------------------
333 // -----------------------------------------------------------------------------
335 Reference
< provider::XScript
> BasicProviderImpl::getScript( const ::rtl::OUString
& scriptURI
)
336 throw ( provider::ScriptFrameworkErrorException
, RuntimeException
)
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
);
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
;
380 aModule
= aDescription
.getToken( 0, (sal_Unicode
)'.', nIndex
);
381 ::rtl::OUString aMethod
;
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
;
399 StarBASIC
* pBasic
= pBasicMgr
->GetLib( aLibrary
);
402 USHORT nId
= pBasicMgr
->GetLibId( aLibrary
);
403 if ( nId
!= LIB_NOTFOUND
)
405 pBasicMgr
->LoadLib( nId
);
406 pBasic
= pBasicMgr
->GetLib( aLibrary
);
411 SbModule
* pModule
= pBasic
->FindModule( aModule
);
414 SbxArray
* pMethods
= pModule
->GetMethods();
417 SbMethod
* pMethod
= static_cast< SbMethod
* >( pMethods
->Find( aMethod
, SbxCLASS_METHOD
) );
420 if ( m_pDocBasicManager
== pBasicMgr
)
421 xScript
= new BasicScriptImpl( aDescription
, pMethod
, *m_pDocBasicManager
, m_xInvocationContext
);
423 xScript
= new BasicScriptImpl( aDescription
, pMethod
);
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
);
449 // -----------------------------------------------------------------------------
451 // -----------------------------------------------------------------------------
453 ::rtl::OUString
BasicProviderImpl::getName( ) throw (RuntimeException
)
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
;
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
) )
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
);
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
;
534 xLibContainer
= m_xLibContainerDoc
;
536 if ( xLibContainer
.is() )
537 bReturn
= xLibContainer
->hasElements();
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
)
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
,
574 // -----------------------------------------------------------------------------
576 //.........................................................................
577 } // namespace basprov
578 //.........................................................................
581 // =============================================================================
583 // =============================================================================
587 SAL_DLLPUBLIC_EXPORT
void SAL_CALL
component_getImplementationEnvironment(
588 const sal_Char
** ppEnvTypeName
, uno_Environment
** 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
);