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