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