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 "basprov.hxx" 27 #include "basscript.hxx" 28 #include "baslibnode.hxx" 29 #include <com/sun/star/frame/XModel.hpp> 30 #include <com/sun/star/script/browse/BrowseNodeTypes.hpp> 31 #include <com/sun/star/script/provider/ScriptFrameworkErrorType.hpp> 32 #include <com/sun/star/document/XEmbeddedScripts.hpp> 33 34 #ifndef _CPPUHELPER_IMPLEMENTATIONENTRY_HXX_ 35 #include <cppuhelper/implementationentry.hxx> 36 #endif 37 #include <rtl/uri.hxx> 38 #include <osl/process.h> 39 #include <osl/file.hxx> 40 #include <vos/mutex.hxx> 41 #include <vcl/svapp.hxx> 42 #include <basic/sbx.hxx> 43 #include <basic/basmgr.hxx> 44 #include <basic/basicmanagerrepository.hxx> 45 #include <basic/sbstar.hxx> 46 #include <basic/sbmod.hxx> 47 #include <basic/sbmeth.hxx> 48 #include <sfx2/app.hxx> 49 #include <sfx2/objsh.hxx> 50 51 #include <com/sun/star/util/XMacroExpander.hpp> 52 #include <com/sun/star/script/XLibraryContainer2.hpp> 53 #include <com/sun/star/uri/XUriReference.hpp> 54 #include <com/sun/star/uri/XUriReferenceFactory.hpp> 55 #include <com/sun/star/uri/XVndSunStarScriptUrl.hpp> 56 57 #include <util/util.hxx> 58 #include <util/MiscUtils.hxx> 59 60 61 using namespace ::com::sun::star; 62 using namespace ::com::sun::star::lang; 63 using namespace ::com::sun::star::uno; 64 using namespace ::com::sun::star::script; 65 using namespace ::com::sun::star::document; 66 using namespace ::sf_misc; 67 68 //......................................................................... 69 namespace basprov 70 { 71 //......................................................................... 72 73 // ============================================================================= 74 // component operations 75 // ============================================================================= 76 77 static ::rtl::OUString getImplementationName_BasicProviderImpl() 78 { 79 static ::rtl::OUString* pImplName = 0; 80 if ( !pImplName ) 81 { 82 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); 83 if ( !pImplName ) 84 { 85 static ::rtl::OUString aImplName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.scripting.ScriptProviderForBasic" ) ); 86 pImplName = &aImplName; 87 } 88 } 89 return *pImplName; 90 } 91 92 // ----------------------------------------------------------------------------- 93 94 static Sequence< ::rtl::OUString > getSupportedServiceNames_BasicProviderImpl() 95 { 96 static Sequence< ::rtl::OUString >* pNames = 0; 97 if ( !pNames ) 98 { 99 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); 100 if ( !pNames ) 101 { 102 static Sequence< ::rtl::OUString > aNames(4); 103 aNames.getArray()[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.script.provider.ScriptProviderForBasic" ) ); 104 aNames.getArray()[1] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.script.provider.LanguageScriptProvider" ) ); 105 aNames.getArray()[2] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.script.provider.ScriptProvider" ) ); 106 aNames.getArray()[3] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.script.browse.BrowseNode" ) ); 107 pNames = &aNames; 108 } 109 } 110 return *pNames; 111 } 112 113 // ============================================================================= 114 // BasicProviderImpl 115 // ============================================================================= 116 117 BasicProviderImpl::BasicProviderImpl( const Reference< XComponentContext >& xContext ) 118 :m_pAppBasicManager( 0 ) 119 ,m_pDocBasicManager( 0 ) 120 ,m_xLibContainerApp( 0 ) 121 ,m_xLibContainerDoc( 0 ) 122 ,m_xContext( xContext ) 123 ,m_bIsAppScriptCtx( true ) 124 ,m_bIsUserCtx(true) 125 { 126 } 127 128 // ----------------------------------------------------------------------------- 129 130 BasicProviderImpl::~BasicProviderImpl() 131 { 132 } 133 134 // ----------------------------------------------------------------------------- 135 136 bool BasicProviderImpl::isLibraryShared( const Reference< script::XLibraryContainer >& rxLibContainer, const ::rtl::OUString& rLibName ) 137 { 138 bool bIsShared = false; 139 140 Reference< script::XLibraryContainer2 > xLibContainer( rxLibContainer, UNO_QUERY ); 141 if ( xLibContainer.is() && xLibContainer->hasByName( rLibName ) && xLibContainer->isLibraryLink( rLibName ) ) 142 { 143 ::rtl::OUString aFileURL; 144 if ( m_xContext.is() ) 145 { 146 Reference< uri::XUriReferenceFactory > xUriFac; 147 Reference< lang::XMultiComponentFactory > xSMgr( m_xContext->getServiceManager() ); 148 if ( xSMgr.is() ) 149 { 150 xUriFac.set( xSMgr->createInstanceWithContext( ::rtl::OUString::createFromAscii( 151 "com.sun.star.uri.UriReferenceFactory" ), m_xContext ), UNO_QUERY ); 152 } 153 154 if ( xUriFac.is() ) 155 { 156 ::rtl::OUString aLinkURL( xLibContainer->getLibraryLinkURL( rLibName ) ); 157 Reference< uri::XUriReference > xUriRef( xUriFac->parse( aLinkURL ), UNO_QUERY ); 158 159 if ( xUriRef.is() ) 160 { 161 ::rtl::OUString aScheme = xUriRef->getScheme(); 162 if ( aScheme.equalsIgnoreAsciiCaseAscii( "file" ) ) 163 { 164 aFileURL = aLinkURL; 165 } 166 else if ( aScheme.equalsIgnoreAsciiCaseAscii( "vnd.sun.star.pkg" ) ) 167 { 168 ::rtl::OUString aAuthority = xUriRef->getAuthority(); 169 if ( aAuthority.matchIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM( "vnd.sun.star.expand:" ) ) ) 170 { 171 ::rtl::OUString aDecodedURL( aAuthority.copy( sizeof ( "vnd.sun.star.expand:" ) - 1 ) ); 172 aDecodedURL = ::rtl::Uri::decode( aDecodedURL, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 ); 173 Reference<util::XMacroExpander> xMacroExpander( 174 m_xContext->getValueByName( 175 ::rtl::OUString::createFromAscii( "/singletons/com.sun.star.util.theMacroExpander" ) ), 176 UNO_QUERY ); 177 if ( xMacroExpander.is() ) 178 aFileURL = xMacroExpander->expandMacros( aDecodedURL ); 179 } 180 } 181 } 182 } 183 } 184 185 if ( aFileURL.getLength() ) 186 { 187 osl::DirectoryItem aFileItem; 188 osl::FileStatus aFileStatus( FileStatusMask_FileURL ); 189 OSL_VERIFY( osl::DirectoryItem::get( aFileURL, aFileItem ) == osl::FileBase::E_None ); 190 OSL_VERIFY( aFileItem.getFileStatus( aFileStatus ) == osl::FileBase::E_None ); 191 ::rtl::OUString aCanonicalFileURL( aFileStatus.getFileURL() ); 192 193 ::rtl::OUString aSearchURL1( RTL_CONSTASCII_USTRINGPARAM( "share/basic" ) ); 194 ::rtl::OUString aSearchURL2( RTL_CONSTASCII_USTRINGPARAM( "share/uno_packages" ) ); 195 if( aCanonicalFileURL.indexOf( aSearchURL1 ) != -1 || aCanonicalFileURL.indexOf( aSearchURL2 ) != -1 ) 196 bIsShared = true; 197 } 198 } 199 200 return bIsShared; 201 } 202 203 // ----------------------------------------------------------------------------- 204 // XServiceInfo 205 // ----------------------------------------------------------------------------- 206 207 ::rtl::OUString BasicProviderImpl::getImplementationName( ) 208 { 209 return getImplementationName_BasicProviderImpl(); 210 } 211 212 // ----------------------------------------------------------------------------- 213 214 sal_Bool BasicProviderImpl::supportsService( const ::rtl::OUString& rServiceName ) 215 { 216 Sequence< ::rtl::OUString > aNames( getSupportedServiceNames() ); 217 const ::rtl::OUString* pNames = aNames.getConstArray(); 218 const ::rtl::OUString* pEnd = pNames + aNames.getLength(); 219 for ( ; pNames != pEnd && !pNames->equals( rServiceName ); ++pNames ) 220 ; 221 222 return pNames != pEnd; 223 } 224 225 // ----------------------------------------------------------------------------- 226 227 Sequence< ::rtl::OUString > BasicProviderImpl::getSupportedServiceNames( ) 228 { 229 return getSupportedServiceNames_BasicProviderImpl(); 230 } 231 232 // ----------------------------------------------------------------------------- 233 // XInitialization 234 // ----------------------------------------------------------------------------- 235 236 void BasicProviderImpl::initialize( const Sequence< Any >& aArguments ) 237 { 238 // TODO 239 240 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 241 242 if ( aArguments.getLength() != 1 ) 243 { 244 throw IllegalArgumentException( 245 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "BasicProviderImpl::initialize: incorrect argument count." ) ), 246 *this, 247 1 248 ); 249 } 250 251 Reference< frame::XModel > xModel; 252 253 m_xInvocationContext.set( aArguments[0], UNO_QUERY ); 254 if ( m_xInvocationContext.is() ) 255 { 256 xModel.set( m_xInvocationContext->getScriptContainer(), UNO_QUERY ); 257 if ( !xModel.is() ) 258 { 259 throw IllegalArgumentException( 260 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "BasicProviderImpl::initialize: unable to determine the document model from the script invocation context." ) ), 261 *this, 262 1 263 ); 264 } 265 } 266 else 267 { 268 if ( !( aArguments[0] >>= m_sScriptingContext ) ) 269 { 270 throw IllegalArgumentException( 271 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "BasicProviderImpl::initialize: incorrect argument type " ) ).concat( aArguments[0].getValueTypeName() ), 272 *this, 273 1 274 ); 275 } 276 277 ::rtl::OUString sDoc = OUSTR("vnd.sun.star.tdoc"); 278 if ( m_sScriptingContext.indexOf( sDoc ) == 0 ) 279 { 280 xModel = MiscUtils::tDocUrlToModel( m_sScriptingContext ); 281 // TODO: use ScriptingContantsPool for SCRIPTING_DOC_REF 282 } 283 } 284 285 if ( xModel.is() ) 286 { 287 Reference< XEmbeddedScripts > xDocumentScripts( xModel, UNO_QUERY ); 288 if ( xDocumentScripts.is() ) 289 { 290 m_pDocBasicManager = ::basic::BasicManagerRepository::getDocumentBasicManager( xModel ); 291 m_xLibContainerDoc.set( xDocumentScripts->getBasicLibraries(), UNO_QUERY ); 292 OSL_ENSURE( m_pDocBasicManager && m_xLibContainerDoc.is(), 293 "BasicProviderImpl::initialize: invalid BasicManager, or invalid script container!" ); 294 } 295 m_bIsAppScriptCtx = false; 296 } 297 else 298 { 299 // Provider has been created with application context for user 300 // or share 301 if ( !m_sScriptingContext.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "user" ) ) ) 302 { 303 m_bIsUserCtx = false; 304 } 305 else 306 { 307 /* 308 throw RuntimeException( 309 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "BasicProviderImpl::initialize: no scripting context!" ) ), 310 Reference< XInterface >() ); 311 */ 312 } 313 } 314 315 // TODO 316 if ( !m_pAppBasicManager ) 317 m_pAppBasicManager = SFX_APP()->GetBasicManager(); 318 319 if ( !m_xLibContainerApp.is() ) 320 m_xLibContainerApp = Reference< script::XLibraryContainer >( SFX_APP()->GetBasicContainer(), UNO_QUERY ); 321 } 322 323 // ----------------------------------------------------------------------------- 324 325 // XScriptProvider 326 // ----------------------------------------------------------------------------- 327 328 Reference < provider::XScript > BasicProviderImpl::getScript( const ::rtl::OUString& scriptURI ) 329 { 330 // TODO 331 332 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 333 334 Reference< provider::XScript > xScript; 335 Reference< lang::XMultiComponentFactory > xMcFac ( m_xContext->getServiceManager() ); 336 Reference< uri::XUriReferenceFactory > xFac ( 337 xMcFac->createInstanceWithContext( rtl::OUString::createFromAscii( 338 "com.sun.star.uri.UriReferenceFactory"), m_xContext ) , UNO_QUERY ); 339 340 if ( !xFac.is() ) 341 { 342 throw provider::ScriptFrameworkErrorException( 343 OUSTR( "Failed to instantiate UriReferenceFactory" ), Reference< XInterface >(), 344 scriptURI, OUSTR("Basic"), 345 provider::ScriptFrameworkErrorType::UNKNOWN ); 346 } 347 348 Reference< uri::XUriReference > uriRef( 349 xFac->parse( scriptURI ), UNO_QUERY ); 350 351 Reference < uri::XVndSunStarScriptUrl > sfUri( uriRef, UNO_QUERY ); 352 353 if ( !uriRef.is() || !sfUri.is() ) 354 { 355 ::rtl::OUString errorMsg = ::rtl::OUString::createFromAscii( "BasicProviderImpl::getScript: failed to parse URI: " ); 356 errorMsg = errorMsg.concat( scriptURI ); 357 throw provider::ScriptFrameworkErrorException( 358 errorMsg, Reference< XInterface >(), 359 scriptURI, OUSTR("Basic"), 360 provider::ScriptFrameworkErrorType::MALFORMED_URL ); 361 } 362 363 364 ::rtl::OUString aDescription = sfUri->getName(); 365 ::rtl::OUString aLocation = sfUri->getParameter( 366 ::rtl::OUString::createFromAscii( "location" ) ); 367 368 sal_Int32 nIndex = 0; 369 ::rtl::OUString aLibrary = aDescription.getToken( 0, (sal_Unicode)'.', nIndex ); 370 ::rtl::OUString aModule; 371 if ( nIndex != -1 ) 372 aModule = aDescription.getToken( 0, (sal_Unicode)'.', nIndex ); 373 ::rtl::OUString aMethod; 374 if ( nIndex != -1 ) 375 aMethod = aDescription.getToken( 0, (sal_Unicode)'.', nIndex ); 376 377 if ( aLibrary.getLength() != 0 && aModule.getLength() != 0 && aMethod.getLength() != 0 && aLocation.getLength() != 0 ) 378 { 379 BasicManager* pBasicMgr = NULL; 380 if ( aLocation.equals( ::rtl::OUString::createFromAscii("document") ) ) 381 { 382 pBasicMgr = m_pDocBasicManager; 383 } 384 else if ( aLocation.equals( ::rtl::OUString::createFromAscii("application") ) ) 385 { 386 pBasicMgr = m_pAppBasicManager; 387 } 388 389 if ( pBasicMgr ) 390 { 391 StarBASIC* pBasic = pBasicMgr->GetLib( aLibrary ); 392 if ( !pBasic ) 393 { 394 sal_uInt16 nId = pBasicMgr->GetLibId( aLibrary ); 395 if ( nId != LIB_NOTFOUND ) 396 { 397 pBasicMgr->LoadLib( nId ); 398 pBasic = pBasicMgr->GetLib( aLibrary ); 399 } 400 } 401 if ( pBasic ) 402 { 403 SbModule* pModule = pBasic->FindModule( aModule ); 404 if ( pModule ) 405 { 406 SbxArray* pMethods = pModule->GetMethods(); 407 if ( pMethods ) 408 { 409 SbMethod* pMethod = static_cast< SbMethod* >( pMethods->Find( aMethod, SbxCLASS_METHOD ) ); 410 if ( pMethod && !pMethod->IsHidden() ) 411 { 412 if ( m_pDocBasicManager == pBasicMgr ) 413 xScript = new BasicScriptImpl( aDescription, pMethod, *m_pDocBasicManager, m_xInvocationContext ); 414 else 415 xScript = new BasicScriptImpl( aDescription, pMethod ); 416 } 417 } 418 } 419 } 420 } 421 } 422 423 if ( !xScript.is() ) 424 { 425 ::rtl::OUStringBuffer aMessage; 426 aMessage.appendAscii( "The following Basic script could not be found:\n" ); 427 aMessage.appendAscii( "library: '" ).append( aLibrary ).appendAscii( "'\n" ); 428 aMessage.appendAscii( "module: '" ).append( aModule ).appendAscii( "'\n" ); 429 aMessage.appendAscii( "method: '" ).append( aMethod ).appendAscii( "'\n" ); 430 aMessage.appendAscii( "location: '" ).append( aLocation ).appendAscii( "'\n" ); 431 throw provider::ScriptFrameworkErrorException( 432 aMessage.makeStringAndClear(), 433 Reference< XInterface >(), 434 scriptURI, OUSTR("Basic"), 435 provider::ScriptFrameworkErrorType::NO_SUCH_SCRIPT ); 436 } 437 438 return xScript; 439 } 440 441 // ----------------------------------------------------------------------------- 442 // XBrowseNode 443 // ----------------------------------------------------------------------------- 444 445 ::rtl::OUString BasicProviderImpl::getName( ) 446 { 447 // TODO 448 449 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 450 451 return ::rtl::OUString::createFromAscii( "Basic" ); 452 } 453 454 // ----------------------------------------------------------------------------- 455 456 Sequence< Reference< browse::XBrowseNode > > BasicProviderImpl::getChildNodes( ) 457 { 458 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 459 460 Reference< script::XLibraryContainer > xLibContainer; 461 BasicManager* pBasicManager = NULL; 462 463 if ( m_bIsAppScriptCtx ) 464 { 465 xLibContainer = m_xLibContainerApp; 466 pBasicManager = m_pAppBasicManager; 467 } 468 else 469 { 470 xLibContainer = m_xLibContainerDoc; 471 pBasicManager = m_pDocBasicManager; 472 } 473 474 Sequence< Reference< browse::XBrowseNode > > aChildNodes; 475 476 if ( pBasicManager && xLibContainer.is() ) 477 { 478 Sequence< ::rtl::OUString > aLibNames = xLibContainer->getElementNames(); 479 sal_Int32 nLibCount = aLibNames.getLength(); 480 const ::rtl::OUString* pLibNames = aLibNames.getConstArray(); 481 aChildNodes.realloc( nLibCount ); 482 Reference< browse::XBrowseNode >* pChildNodes = aChildNodes.getArray(); 483 sal_Int32 childsFound = 0; 484 485 for ( sal_Int32 i = 0 ; i < nLibCount ; ++i ) 486 { 487 bool bCreate = false; 488 if ( m_bIsAppScriptCtx ) 489 { 490 bool bShared = isLibraryShared( xLibContainer, pLibNames[i] ); 491 if ( ( m_bIsUserCtx && !bShared ) || ( !m_bIsUserCtx && bShared ) ) 492 bCreate = true; 493 } 494 else 495 { 496 bCreate = true; 497 } 498 if ( bCreate ) 499 { 500 pChildNodes[childsFound++] = static_cast< browse::XBrowseNode* >( new BasicLibraryNodeImpl( 501 m_xContext, m_sScriptingContext, pBasicManager, xLibContainer, pLibNames[i], m_bIsAppScriptCtx ) ); 502 } 503 } 504 505 if ( childsFound != nLibCount ) 506 aChildNodes.realloc( childsFound ); 507 } 508 509 return aChildNodes; 510 } 511 512 // ----------------------------------------------------------------------------- 513 514 sal_Bool BasicProviderImpl::hasChildNodes( ) 515 { 516 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 517 518 sal_Bool bReturn = sal_False; 519 Reference< script::XLibraryContainer > xLibContainer; 520 if ( m_bIsAppScriptCtx ) 521 { 522 xLibContainer = m_xLibContainerApp; 523 } 524 else 525 { 526 xLibContainer = m_xLibContainerDoc; 527 } 528 if ( xLibContainer.is() ) 529 bReturn = xLibContainer->hasElements(); 530 531 return bReturn; 532 } 533 534 // ----------------------------------------------------------------------------- 535 536 sal_Int16 BasicProviderImpl::getType( ) 537 { 538 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 539 540 return browse::BrowseNodeTypes::CONTAINER; 541 } 542 543 // ============================================================================= 544 // component operations 545 // ============================================================================= 546 547 static Reference< XInterface > SAL_CALL create_BasicProviderImpl( 548 Reference< XComponentContext > const & xContext ) 549 SAL_THROW( () ) 550 { 551 return static_cast< lang::XTypeProvider * >( new BasicProviderImpl( xContext ) ); 552 } 553 554 // ----------------------------------------------------------------------------- 555 556 static struct ::cppu::ImplementationEntry s_component_entries [] = 557 { 558 { 559 create_BasicProviderImpl, getImplementationName_BasicProviderImpl, 560 getSupportedServiceNames_BasicProviderImpl, ::cppu::createSingleComponentFactory, 561 0, 0 562 }, 563 { 0, 0, 0, 0, 0, 0 } 564 }; 565 566 // ----------------------------------------------------------------------------- 567 568 //......................................................................... 569 } // namespace basprov 570 //......................................................................... 571 572 573 // ============================================================================= 574 // component exports 575 // ============================================================================= 576 577 extern "C" 578 { 579 SAL_DLLPUBLIC_EXPORT void SAL_CALL component_getImplementationEnvironment( 580 const sal_Char ** ppEnvTypeName, uno_Environment ** ppEnv ) 581 { 582 (void)ppEnv; 583 584 *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; 585 } 586 587 SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory( 588 const sal_Char * pImplName, lang::XMultiServiceFactory * pServiceManager, 589 registry::XRegistryKey * pRegistryKey ) 590 { 591 return ::cppu::component_getFactoryHelper( 592 pImplName, pServiceManager, pRegistryKey, ::basprov::s_component_entries ); 593 } 594 } 595