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