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