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