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 <basic/basicmanagerrepository.hxx>
21 #include <basic/basmgr.hxx>
22 #include <scriptcont.hxx>
23 #include <dlgcont.hxx>
24 #include <basic/sbuno.hxx>
25 #include <sbintern.hxx>
26 
27 #include <com/sun/star/document/XStorageBasedDocument.hpp>
28 #include <com/sun/star/document/XEmbeddedScripts.hpp>
29 #include <com/sun/star/frame/Desktop.hpp>
30 #include <svtools/ehdl.hxx>
31 #include <svtools/sfxecode.hxx>
32 #include <unotools/pathoptions.hxx>
33 #include <svl/hint.hxx>
34 #include <vcl/svapp.hxx>
35 #include <tools/debug.hxx>
36 #include <tools/diagnose_ex.h>
37 #include <tools/urlobj.hxx>
38 #include <comphelper/stl_types.hxx>
39 #include <comphelper/processfactory.hxx>
40 #include <comphelper/documentinfo.hxx>
41 #include <unotools/eventlisteneradapter.hxx>
42 
43 #include <osl/getglobalmutex.hxx>
44 #include <rtl/instance.hxx>
45 #include <rtl/strbuf.hxx>
46 
47 #include <map>
48 
49 
50 namespace basic
51 {
52     using ::com::sun::star::uno::Reference;
53     using ::com::sun::star::uno::XComponentContext;
54     using ::com::sun::star::frame::XModel;
55     using ::com::sun::star::frame::Desktop;
56     using ::com::sun::star::uno::XInterface;
57     using ::com::sun::star::uno::UNO_QUERY;
58     using ::com::sun::star::embed::XStorage;
59     using ::com::sun::star::script::XPersistentLibraryContainer;
60     using ::com::sun::star::uno::UNO_QUERY_THROW;
61     using ::com::sun::star::uno::Exception;
62     using ::com::sun::star::document::XStorageBasedDocument;
63     using ::com::sun::star::lang::XComponent;
64     using ::com::sun::star::document::XEmbeddedScripts;
65 
66     typedef std::map< Reference< XInterface >, std::unique_ptr<BasicManager>, ::comphelper::OInterfaceCompare< XInterface > > BasicManagerStore;
67 
68     typedef std::vector< BasicManagerCreationListener* >  CreationListeners;
69 
70     class ImplRepository : public ::utl::OEventListenerAdapter, public SfxListener
71     {
72     private:
73         friend struct CreateImplRepository;
74         ImplRepository();
75 
76     private:
77         BasicManagerStore   m_aStore;
78         CreationListeners   m_aCreationListeners;
79 
80     public:
81         static ImplRepository& Instance();
82 
83         BasicManager*   getDocumentBasicManager( const Reference< XModel >& _rxDocumentModel );
84         BasicManager*   getOrCreateApplicationBasicManager();
85         static BasicManager* getApplicationBasicManager();
86         static void          setApplicationBasicManager( std::unique_ptr<BasicManager> _pBasicManager );
87         void    registerCreationListener( BasicManagerCreationListener& _rListener );
88         void    revokeCreationListener( BasicManagerCreationListener& _rListener );
89 
90     private:
91         /** retrieves the location at which the BasicManager for the given model
92             is stored.
93 
94             If previously, the BasicManager for this model has never been requested,
95             then the model is added to the map, with an initial NULL BasicManager.
96 
97             @param _rxDocumentModel
98                 the model whose BasicManager's location is to be retrieved. Must not be <NULL/>.
99 
100             @precond
101                 our mutex is locked
102         */
103         std::unique_ptr<BasicManager>&
104                 impl_getLocationForModel( const Reference< XModel >& _rxDocumentModel );
105 
106         /** tests if there is a location set at which the BasicManager for the given model
107             is stored.
108 
109             @param _rxDocumentModel
110                 the model whose BasicManager's location is to be retrieved. Must not be <NULL/>.
111 
112             @precond
113                 our mutex is locked
114         */
115         bool impl_hasLocationForModel( const Reference< XModel >& _rxDocumentModel ) const;
116 
117         /** creates a new BasicManager instance for the given model
118 
119             @param _out_rpBasicManager
120                 reference to the pointer variable that will hold the new
121                 BasicManager.
122 
123             @param _rxDocumentModel
124                 the model whose BasicManager will be created. Must not be <NULL/>.
125         */
126         bool impl_createManagerForModel(
127                     std::unique_ptr<BasicManager>& _out_rpBasicManager,
128                     const Reference< XModel >& _rxDocumentModel );
129 
130         /** creates the application-wide BasicManager
131         */
132         BasicManager* impl_createApplicationBasicManager();
133 
134         /** notifies all listeners which expressed interest in the creation of BasicManager instances.
135         */
136         void    impl_notifyCreationListeners(
137                     const Reference< XModel >& _rxDocumentModel,
138                     BasicManager& _rManager
139                  );
140 
141         /** retrieves the current storage of a given document
142 
143             @param  _rxDocument
144                 the document whose storage is to be retrieved.
145 
146             @param  _out_rStorage
147                 takes the storage upon successful return. Note that this might be <NULL/> even
148                 if <TRUE/> is returned. In this case, the document has not yet been saved.
149 
150             @return
151                 <TRUE/> if the storage could be successfully retrieved (in which case
152                 <arg>_out_rStorage</arg> might or might not be <NULL/>), <FALSE/> otherwise.
153                 In the latter case, processing this document should stop.
154         */
155         static bool impl_getDocumentStorage_nothrow( const Reference< XModel >& _rxDocument, Reference< XStorage >& _out_rStorage );
156 
157         /** retrieves the containers for Basic and Dialog libraries for a given document
158 
159             @param  _rxDocument
160                 the document whose containers are to be retrieved.
161 
162             @param _out_rxBasicLibraries
163                 takes the basic library container upon successful return
164 
165             @param _out_rxDialogLibraries
166                 takes the dialog library container upon successful return
167 
168             @return
169                 <TRUE/> if and only if both containers exist, and could successfully be retrieved
170         */
171         static bool impl_getDocumentLibraryContainers_nothrow(
172                     const Reference< XModel >& _rxDocument,
173                     Reference< XPersistentLibraryContainer >& _out_rxBasicLibraries,
174                     Reference< XPersistentLibraryContainer >& _out_rxDialogLibraries
175                 );
176 
177         /** initializes the given library containers, which belong to a document
178         */
179         static void impl_initDocLibraryContainers_nothrow(
180                     const Reference< XPersistentLibraryContainer >& _rxBasicLibraries,
181                     const Reference< XPersistentLibraryContainer >& _rxDialogLibraries
182                 );
183 
184         // OEventListenerAdapter overridables
185         virtual void _disposing( const css::lang::EventObject& _rSource ) override;
186 
187         // SfxListener overridables
188         virtual void Notify( SfxBroadcaster& _rBC, const SfxHint& _rHint ) override;
189 
190         /** removes the Model/BasicManager pair given by iterator from our store
191         */
192         void impl_removeFromRepository( const BasicManagerStore::iterator& _pos );
193 
194     private:
195         StarBASIC* impl_getDefaultAppBasicLibrary();
196     };
197 
198 
199     struct CreateImplRepository
200     {
201         ImplRepository* operator()()
202         {
203             static ImplRepository* pRepository = new ImplRepository;
204             return pRepository;
205         }
206     };
207 
208 
209     ImplRepository::ImplRepository()
210     {
211     }
212 
213 
214     ImplRepository& ImplRepository::Instance()
215     {
216         return *rtl_Instance< ImplRepository, CreateImplRepository, ::osl::MutexGuard, ::osl::GetGlobalMutex >::
217             create( CreateImplRepository(), ::osl::GetGlobalMutex() );
218     }
219 
220     BasicManager* ImplRepository::getDocumentBasicManager( const Reference< XModel >& _rxDocumentModel )
221     {
222         SolarMutexGuard g;
223 
224         /*  #163556# (DR) - This function may be called recursively while
225             constructing the Basic manager and loading the Basic storage. By
226             passing the map entry received from impl_getLocationForModel() to
227             the function impl_createManagerForModel(), the new Basic manager
228             will be put immediately into the map of existing Basic managers,
229             thus a recursive call of this function will find and return it
230             without creating another instance.
231          */
232         std::unique_ptr<BasicManager>& pBasicManager = impl_getLocationForModel( _rxDocumentModel );
233         if (pBasicManager != nullptr)
234             return pBasicManager.get();
235         if (impl_createManagerForModel(pBasicManager, _rxDocumentModel))
236             return pBasicManager.get();
237         return nullptr;
238     }
239 
240     BasicManager* ImplRepository::getOrCreateApplicationBasicManager()
241     {
242         SolarMutexGuard g;
243 
244         BasicManager* pAppManager = GetSbData()->pAppBasMgr.get();
245         if (pAppManager == nullptr)
246             pAppManager = impl_createApplicationBasicManager();
247         return pAppManager;
248     }
249 
250     BasicManager* ImplRepository::getApplicationBasicManager()
251     {
252         SolarMutexGuard g;
253 
254         return GetSbData()->pAppBasMgr.get();
255     }
256 
257     void ImplRepository::setApplicationBasicManager( std::unique_ptr<BasicManager> _pBasicManager )
258     {
259         SolarMutexGuard g;
260 
261         GetSbData()->pAppBasMgr = std::move(_pBasicManager);
262     }
263 
264 
265     BasicManager* ImplRepository::impl_createApplicationBasicManager()
266     {
267         SolarMutexGuard g;
268 
269         OSL_PRECOND(getApplicationBasicManager() == nullptr, "ImplRepository::impl_createApplicationBasicManager: there already is one!");
270 
271         // Determine Directory
272         SvtPathOptions aPathCFG;
273         OUString aAppBasicDir( aPathCFG.GetBasicPath() );
274         if ( aAppBasicDir.isEmpty() )
275         {
276             aPathCFG.SetBasicPath("$(prog)");
277         }
278 
279         // Create basic and load it
280         // AppBasicDir is now a PATH
281         INetURLObject aAppBasic( SvtPathOptions().SubstituteVariable("$(progurl)") );
282         aAppBasic.insertName( Application::GetAppName() );
283 
284         BasicManager* pBasicManager = new BasicManager( new StarBASIC, &aAppBasicDir );
285         setApplicationBasicManager( std::unique_ptr<BasicManager>(pBasicManager) );
286 
287         // The first dir in the path as destination:
288         OUString aFileName( aAppBasic.getName() );
289         aAppBasic = INetURLObject( aAppBasicDir.getToken(1, ';') );
290         DBG_ASSERT(aAppBasic.GetProtocol() != INetProtocol::NotValid,
291             OString("Invalid URL: \"" +
292                     OUStringToOString(aAppBasicDir, osl_getThreadTextEncoding()) +
293                     "\"").getStr());
294         aAppBasic.insertName( aFileName );
295         pBasicManager->SetStorageName( aAppBasic.PathToFileName() );
296 
297         // Basic container
298         SfxScriptLibraryContainer* pBasicCont = new SfxScriptLibraryContainer( Reference< XStorage >() );
299         Reference< XPersistentLibraryContainer > xBasicCont( pBasicCont );
300         pBasicCont->setBasicManager( pBasicManager );
301 
302         // Dialog container
303         SfxDialogLibraryContainer* pDialogCont = new SfxDialogLibraryContainer( Reference< XStorage >() );
304         Reference< XPersistentLibraryContainer > xDialogCont( pDialogCont );
305 
306         LibraryContainerInfo aInfo( xBasicCont, xDialogCont, static_cast< OldBasicPassword* >( pBasicCont ) );
307         pBasicManager->SetLibraryContainerInfo( aInfo );
308 
309         // global constants
310 
311         // StarDesktop
312         Reference< XComponentContext > xContext = ::comphelper::getProcessComponentContext();
313         pBasicManager->SetGlobalUNOConstant( "StarDesktop", css::uno::Any( Desktop::create(xContext)));
314 
315         // (BasicLibraries and DialogLibraries have automatically been added in SetLibraryContainerInfo)
316 
317         // notify
318         impl_notifyCreationListeners( nullptr, *pBasicManager );
319 
320         // outta here
321         return pBasicManager;
322     }
323 
324 
325     void ImplRepository::registerCreationListener( BasicManagerCreationListener& _rListener )
326     {
327         SolarMutexGuard g;
328 
329         m_aCreationListeners.push_back( &_rListener );
330     }
331 
332 
333     void ImplRepository::revokeCreationListener( BasicManagerCreationListener& _rListener )
334     {
335         SolarMutexGuard g;
336 
337         CreationListeners::iterator pos = std::find( m_aCreationListeners.begin(), m_aCreationListeners.end(), &_rListener );
338         if ( pos != m_aCreationListeners.end() )
339             m_aCreationListeners.erase( pos );
340         else {
341             OSL_FAIL( "ImplRepository::revokeCreationListener: listener is not registered!" );
342         }
343     }
344 
345 
346     void ImplRepository::impl_notifyCreationListeners( const Reference< XModel >& _rxDocumentModel, BasicManager& _rManager )
347     {
348         for (auto const& creationListener : m_aCreationListeners)
349         {
350             creationListener->onBasicManagerCreated( _rxDocumentModel, _rManager );
351         }
352     }
353 
354 
355     StarBASIC* ImplRepository::impl_getDefaultAppBasicLibrary()
356     {
357         BasicManager* pAppManager = getOrCreateApplicationBasicManager();
358 
359         StarBASIC* pAppBasic = pAppManager ? pAppManager->GetLib(0) : nullptr;
360         DBG_ASSERT( pAppBasic != nullptr, "impl_getApplicationBasic: unable to determine the default application's Basic library!" );
361         return pAppBasic;
362     }
363 
364     std::unique_ptr<BasicManager>& ImplRepository::impl_getLocationForModel( const Reference< XModel >& _rxDocumentModel )
365     {
366         Reference< XInterface > xNormalized( _rxDocumentModel, UNO_QUERY );
367         DBG_ASSERT( _rxDocumentModel.is(), "ImplRepository::impl_getLocationForModel: invalid model!" );
368 
369         std::unique_ptr<BasicManager>& location = m_aStore[ xNormalized ];
370         return location;
371     }
372 
373     bool ImplRepository::impl_hasLocationForModel( const Reference< XModel >& _rxDocumentModel ) const
374     {
375         Reference< XInterface > xNormalized( _rxDocumentModel, UNO_QUERY );
376         DBG_ASSERT( _rxDocumentModel.is(), "ImplRepository::impl_getLocationForModel: invalid model!" );
377 
378         return m_aStore.find(xNormalized) != m_aStore.end();
379     }
380 
381     void ImplRepository::impl_initDocLibraryContainers_nothrow( const Reference< XPersistentLibraryContainer >& _rxBasicLibraries, const Reference< XPersistentLibraryContainer >& _rxDialogLibraries )
382     {
383         OSL_PRECOND( _rxBasicLibraries.is() && _rxDialogLibraries.is(),
384             "ImplRepository::impl_initDocLibraryContainers_nothrow: illegal library containers, this will crash!" );
385 
386         try
387         {
388             // ensure there's a standard library in the basic container
389             OUString aStdLibName( "Standard" );
390             if ( !_rxBasicLibraries->hasByName( aStdLibName ) )
391             {
392                 _rxBasicLibraries->createLibrary( aStdLibName );
393             }
394             // as well as in the dialog container
395             if ( !_rxDialogLibraries->hasByName( aStdLibName ) )
396             {
397                 _rxDialogLibraries->createLibrary( aStdLibName );
398             }
399         }
400         catch( const Exception& )
401         {
402             DBG_UNHANDLED_EXCEPTION("basic");
403         }
404     }
405 
406     bool ImplRepository::impl_createManagerForModel( std::unique_ptr<BasicManager>& _out_rpBasicManager, const Reference< XModel >& _rxDocumentModel )
407     {
408         StarBASIC* pAppBasic = impl_getDefaultAppBasicLibrary();
409 
410         _out_rpBasicManager = nullptr;
411         Reference< XStorage > xStorage;
412         if ( !impl_getDocumentStorage_nothrow( _rxDocumentModel, xStorage ) )
413         {
414             // the document is not able to provide the storage it is based on.
415             return false;
416         }
417         Reference< XPersistentLibraryContainer > xBasicLibs;
418         Reference< XPersistentLibraryContainer > xDialogLibs;
419         if ( !impl_getDocumentLibraryContainers_nothrow( _rxDocumentModel, xBasicLibs, xDialogLibs ) )
420             // the document does not have BasicLibraries and DialogLibraries
421             return false;
422 
423         if ( xStorage.is() )
424         {
425             // load BASIC-manager
426             SfxErrorContext aErrContext( ERRCTX_SFX_LOADBASIC,
427                 ::comphelper::DocumentInfo::getDocumentTitle( _rxDocumentModel ) );
428             OUString aAppBasicDir = SvtPathOptions().GetBasicPath();
429 
430             // Storage and BaseURL are only needed by binary documents!
431             tools::SvRef<SotStorage> xDummyStor = new SotStorage( OUString() );
432             _out_rpBasicManager.reset(new BasicManager( *xDummyStor, OUString() /* TODO/LATER: xStorage */,
433                                                                 pAppBasic,
434                                                                 &aAppBasicDir, true ));
435             if ( !_out_rpBasicManager->GetErrors().empty() )
436             {
437                 // handle errors
438                 std::vector<BasicError>& aErrors = _out_rpBasicManager->GetErrors();
439                 for(const auto& rError : aErrors)
440                 {
441                     // show message to user
442                     if ( ErrorHandler::HandleError( rError.GetErrorId() ) == DialogMask::ButtonsCancel )
443                     {
444                         // user wants to break loading of BASIC-manager
445                         _out_rpBasicManager.reset();
446                         xStorage.clear();
447                         break;
448                     }
449                 }
450             }
451         }
452 
453         // not loaded?
454         if ( !xStorage.is() )
455         {
456             // create new BASIC-manager
457             StarBASIC* pBasic = new StarBASIC( pAppBasic );
458             pBasic->SetFlag( SbxFlagBits::ExtSearch );
459             _out_rpBasicManager.reset(new BasicManager( pBasic, nullptr, true ));
460         }
461 
462         // knit the containers with the BasicManager
463         LibraryContainerInfo aInfo( xBasicLibs, xDialogLibs, dynamic_cast< OldBasicPassword* >( xBasicLibs.get() ) );
464         OSL_ENSURE( aInfo.mpOldBasicPassword, "ImplRepository::impl_createManagerForModel: wrong BasicLibraries implementation!" );
465         _out_rpBasicManager->SetLibraryContainerInfo( aInfo );
466 
467         // initialize the containers
468         impl_initDocLibraryContainers_nothrow( xBasicLibs, xDialogLibs );
469 
470         // so that also dialogs etc. could be 'qualified' addressed
471         _out_rpBasicManager->GetLib(0)->SetParent( pAppBasic );
472 
473         // global properties in the document's Basic
474         _out_rpBasicManager->SetGlobalUNOConstant( "ThisComponent", css::uno::Any( _rxDocumentModel ) );
475 
476         // notify
477         impl_notifyCreationListeners( _rxDocumentModel, *_out_rpBasicManager );
478 
479         // register as listener for this model being disposed/closed
480         OSL_ENSURE( _rxDocumentModel.is(), "ImplRepository::impl_createManagerForModel: the document must be an XComponent!" );
481         assert(impl_hasLocationForModel(_rxDocumentModel));
482         startComponentListening( _rxDocumentModel );
483 
484         bool bOk = false;
485         // startComponentListening may fail in a disposed _rxDocumentModel, in which case _out_rpBasicManager will be removed
486         // from the map and destroyed
487         if (impl_hasLocationForModel(_rxDocumentModel))
488         {
489             bOk = true;
490             // register as listener for the BasicManager being destroyed
491             StartListening( *_out_rpBasicManager );
492         }
493 
494         // #i104876: Library container must not be modified just after
495         // creation. This happens as side effect when creating default
496         // "Standard" libraries and needs to be corrected here
497         xBasicLibs->setModified( false );
498         xDialogLibs->setModified( false );
499         return bOk;
500     }
501 
502     bool ImplRepository::impl_getDocumentStorage_nothrow( const Reference< XModel >& _rxDocument, Reference< XStorage >& _out_rStorage )
503     {
504         _out_rStorage.clear();
505         try
506         {
507             Reference< XStorageBasedDocument > xStorDoc( _rxDocument, UNO_QUERY_THROW );
508             _out_rStorage.set( xStorDoc->getDocumentStorage() );
509         }
510         catch( const Exception& )
511         {
512             DBG_UNHANDLED_EXCEPTION("basic");
513             return false;
514         }
515         return true;
516     }
517 
518 
519     bool ImplRepository::impl_getDocumentLibraryContainers_nothrow( const Reference< XModel >& _rxDocument,
520         Reference< XPersistentLibraryContainer >& _out_rxBasicLibraries, Reference< XPersistentLibraryContainer >& _out_rxDialogLibraries )
521     {
522         _out_rxBasicLibraries.clear();
523         _out_rxDialogLibraries.clear();
524         try
525         {
526             Reference< XEmbeddedScripts > xScripts( _rxDocument, UNO_QUERY_THROW );
527             _out_rxBasicLibraries.set( xScripts->getBasicLibraries(), UNO_QUERY_THROW );
528             _out_rxDialogLibraries.set( xScripts->getDialogLibraries(), UNO_QUERY_THROW );
529         }
530         catch( const Exception& )
531         {
532             DBG_UNHANDLED_EXCEPTION("basic");
533         }
534         return _out_rxBasicLibraries.is() && _out_rxDialogLibraries.is();
535     }
536 
537 
538     void ImplRepository::impl_removeFromRepository( const BasicManagerStore::iterator& _pos )
539     {
540         OSL_PRECOND( _pos != m_aStore.end(), "ImplRepository::impl_removeFromRepository: invalid position!" );
541 
542         std::unique_ptr<BasicManager> pManager = std::move(_pos->second);
543 
544         // *first* remove from map (else Notify won't work properly)
545         m_aStore.erase( _pos );
546 
547         // *then* delete the BasicManager
548         EndListening( *pManager );
549     }
550 
551 
552     void ImplRepository::_disposing( const css::lang::EventObject& _rSource )
553     {
554         SolarMutexGuard g;
555 
556         Reference< XInterface > xNormalizedSource( _rSource.Source, UNO_QUERY );
557 
558         for (   BasicManagerStore::iterator loop = m_aStore.begin();
559                 loop != m_aStore.end();
560                 ++loop
561             )
562         {
563             if ( loop->first.get() == xNormalizedSource.get() )
564             {
565                 impl_removeFromRepository( loop );
566                 return;
567             }
568         }
569 
570         OSL_FAIL( "ImplRepository::_disposing: where does this come from?" );
571     }
572 
573 
574     void ImplRepository::Notify( SfxBroadcaster& _rBC, const SfxHint& _rHint )
575     {
576         if ( _rHint.GetId() != SfxHintId::Dying )
577             // not interested in
578             return;
579 
580         BasicManager* pManager = dynamic_cast< BasicManager* >( &_rBC );
581         OSL_ENSURE( pManager, "ImplRepository::Notify: where does this come from?" );
582 
583         for (   BasicManagerStore::iterator loop = m_aStore.begin();
584                 loop != m_aStore.end();
585                 ++loop
586             )
587         {
588             if ( loop->second.get() == pManager )
589             {
590                 // a BasicManager which is still in our repository is being deleted.
591                 // That's bad, since by definition, we *own* all instances in our
592                 // repository.
593                 OSL_FAIL( "ImplRepository::Notify: nobody should tamper with the managers, except ourself!" );
594                 m_aStore.erase( loop );
595                 break;
596             }
597         }
598     }
599 
600     BasicManager* BasicManagerRepository::getDocumentBasicManager( const Reference< XModel >& _rxDocumentModel )
601     {
602         return ImplRepository::Instance().getDocumentBasicManager( _rxDocumentModel );
603     }
604 
605     BasicManager* BasicManagerRepository::getApplicationBasicManager()
606     {
607         return ImplRepository::Instance().getOrCreateApplicationBasicManager();
608     }
609 
610     void BasicManagerRepository::resetApplicationBasicManager()
611     {
612         ImplRepository::setApplicationBasicManager( nullptr );
613     }
614 
615     void BasicManagerRepository::registerCreationListener( BasicManagerCreationListener& _rListener )
616     {
617         ImplRepository::Instance().registerCreationListener( _rListener );
618     }
619 
620     void BasicManagerRepository::revokeCreationListener( BasicManagerCreationListener& _rListener )
621     {
622         ImplRepository::Instance().revokeCreationListener( _rListener );
623     }
624 
625 } // namespace basic
626 
627 
628 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
629