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_dbaccess.hxx"
30 
31 #include "commandcontainer.hxx"
32 #include "connection.hxx"
33 #include "core_resource.hrc"
34 #include "core_resource.hxx"
35 #include "databasecontext.hxx"
36 #include "databasedocument.hxx"
37 #include "datasource.hxx"
38 #include "dbastrings.hrc"
39 #include "ModelImpl.hxx"
40 #include "userinformation.hxx"
41 #include "sdbcoretools.hxx"
42 
43 /** === begin UNO includes === **/
44 #include <com/sun/star/container/XSet.hpp>
45 #include <com/sun/star/document/MacroExecMode.hpp>
46 #include <com/sun/star/embed/XTransactedObject.hpp>
47 #include <com/sun/star/embed/XTransactionBroadcaster.hpp>
48 #include <com/sun/star/sdb/BooleanComparisonMode.hpp>
49 #include <com/sun/star/script/DocumentScriptLibraryContainer.hpp>
50 #include <com/sun/star/script/DocumentDialogLibraryContainer.hpp>
51 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
52 #include <com/sun/star/form/XLoadable.hpp>
53 /** === end UNO includes === **/
54 
55 #include <comphelper/interaction.hxx>
56 #include <comphelper/mediadescriptor.hxx>
57 #include <comphelper/seqstream.hxx>
58 #include <comphelper/sequence.hxx>
59 #include <connectivity/dbexception.hxx>
60 #include <cppuhelper/exc_hlp.hxx>
61 #include <cppuhelper/typeprovider.hxx>
62 #include <rtl/digest.h>
63 #include <sfx2/signaturestate.hxx>
64 #include <tools/debug.hxx>
65 #include <tools/diagnose_ex.h>
66 #include <tools/errcode.hxx>
67 #include <tools/urlobj.hxx>
68 #include <unotools/sharedunocomponent.hxx>
69 
70 #include <algorithm>
71 
72 using namespace ::com::sun::star::document;
73 using namespace ::com::sun::star::sdbc;
74 using namespace ::com::sun::star::sdbcx;
75 using namespace ::com::sun::star::sdb;
76 using namespace ::com::sun::star::beans;
77 using namespace ::com::sun::star::uno;
78 using namespace ::com::sun::star::lang;
79 using namespace ::com::sun::star::embed;
80 using namespace ::com::sun::star::container;
81 using namespace ::com::sun::star::util;
82 using namespace ::com::sun::star::io;
83 using namespace ::com::sun::star::task;
84 using namespace ::com::sun::star::ucb;
85 using namespace ::com::sun::star::frame;
86 using namespace ::com::sun::star::view;
87 using namespace ::com::sun::star::task;
88 using namespace ::com::sun::star::reflection;
89 using namespace ::com::sun::star::script;
90 using namespace ::cppu;
91 using namespace ::osl;
92 using namespace ::vos;
93 using namespace ::dbtools;
94 using namespace ::comphelper;
95 namespace css = ::com::sun::star;
96 
97 //........................................................................
98 namespace dbaccess
99 {
100 //........................................................................
101 
102 //============================================================
103 //= VosMutexFacade
104 //============================================================
105 //------------------------------------------------------------------------
106 VosMutexFacade::VosMutexFacade( ::osl::Mutex& _rMutex )
107     :m_rMutex( _rMutex )
108 {
109 }
110 
111 //------------------------------------------------------------------------
112 void SAL_CALL VosMutexFacade::acquire()
113 {
114     m_rMutex.acquire();
115 }
116 
117 //------------------------------------------------------------------------
118 sal_Bool SAL_CALL VosMutexFacade::tryToAcquire()
119 {
120     return m_rMutex.tryToAcquire();
121 }
122 
123 //------------------------------------------------------------------------
124 void SAL_CALL VosMutexFacade::release()
125 {
126     m_rMutex.release();
127 }
128 
129 //============================================================
130 //= DocumentStorageAccess
131 //============================================================
132 DBG_NAME( DocumentStorageAccess )
133 class DocumentStorageAccess : public ::cppu::WeakImplHelper2<   XDocumentSubStorageSupplier
134                                                             ,   XTransactionListener >
135 {
136     typedef ::std::map< ::rtl::OUString, Reference< XStorage > >    NamedStorages;
137 
138     ::osl::Mutex        m_aMutex;
139     /// all sub storages which we ever gave to the outer world
140     NamedStorages       m_aExposedStorages;
141     ODatabaseModelImpl* m_pModelImplementation;
142     bool                m_bPropagateCommitToRoot;
143     bool                m_bDisposingSubStorages;
144 
145 public:
146     DocumentStorageAccess( ODatabaseModelImpl& _rModelImplementation )
147         :m_pModelImplementation( &_rModelImplementation )
148         ,m_bPropagateCommitToRoot( true )
149         ,m_bDisposingSubStorages( false )
150     {
151         DBG_CTOR( DocumentStorageAccess, NULL );
152     }
153 
154 protected:
155     ~DocumentStorageAccess()
156     {
157         DBG_DTOR( DocumentStorageAccess, NULL );
158     }
159 
160 public:
161     void dispose();
162 
163     // XDocumentSubStorageSupplier
164     virtual Reference< XStorage > SAL_CALL getDocumentSubStorage( const ::rtl::OUString& aStorageName, ::sal_Int32 _nMode ) throw (RuntimeException);
165     virtual Sequence< ::rtl::OUString > SAL_CALL getDocumentSubStoragesNames(  ) throw (IOException, RuntimeException);
166 
167     // XTransactionListener
168     virtual void SAL_CALL preCommit( const ::com::sun::star::lang::EventObject& aEvent ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);
169     virtual void SAL_CALL commited( const ::com::sun::star::lang::EventObject& aEvent ) throw (::com::sun::star::uno::RuntimeException);
170     virtual void SAL_CALL preRevert( const ::com::sun::star::lang::EventObject& aEvent ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);
171     virtual void SAL_CALL reverted( const ::com::sun::star::lang::EventObject& aEvent ) throw (::com::sun::star::uno::RuntimeException);
172 
173     // XEventListener
174     virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException);
175 
176     /// disposes all storages managed by this instance
177     void disposeStorages();
178 
179     /// disposes all known sub storages
180     void commitStorages() SAL_THROW(( IOException, RuntimeException ));
181 
182     /// commits the dedicated "database" storage
183     bool commitEmbeddedStorage( bool _bPreventRootCommits );
184 
185 private:
186     /** opens the sub storage with the given name, in the given mode
187     */
188     Reference< XStorage > impl_openSubStorage_nothrow( const ::rtl::OUString& _rStorageName, sal_Int32 _nMode );
189 
190     void impl_suspendCommitPropagation()
191     {
192         OSL_ENSURE( m_bPropagateCommitToRoot, "DocumentStorageAccess::impl_suspendCommitPropagation: already suspended" );
193         m_bPropagateCommitToRoot = false;
194     }
195     void impl_resumeCommitPropagation()
196     {
197         OSL_ENSURE( !m_bPropagateCommitToRoot, "DocumentStorageAccess::impl_resumeCommitPropagation: not suspended" );
198         m_bPropagateCommitToRoot = true;
199     }
200 
201 };
202 
203 //--------------------------------------------------------------------------
204 void DocumentStorageAccess::dispose()
205 {
206     ::osl::MutexGuard aGuard( m_aMutex );
207 
208     for (   NamedStorages::iterator loop = m_aExposedStorages.begin();
209             loop != m_aExposedStorages.end();
210             ++loop
211         )
212     {
213         try
214         {
215             Reference< XTransactionBroadcaster > xBroadcaster( loop->second, UNO_QUERY );
216 	        if ( xBroadcaster.is() )
217 		        xBroadcaster->removeTransactionListener( this );
218         }
219         catch( const Exception& )
220         {
221             DBG_UNHANDLED_EXCEPTION();
222         }
223     }
224 
225     m_aExposedStorages.clear();
226 
227     m_pModelImplementation = NULL;
228 }
229 
230 //--------------------------------------------------------------------------
231 Reference< XStorage > DocumentStorageAccess::impl_openSubStorage_nothrow( const ::rtl::OUString& _rStorageName, sal_Int32 _nDesiredMode )
232 {
233 	OSL_ENSURE( _rStorageName.getLength(),"ODatabaseModelImpl::impl_openSubStorage_nothrow: Invalid storage name!" );
234 
235     Reference< XStorage > xStorage;
236     try
237 	{
238 	    Reference< XStorage > xRootStorage( m_pModelImplementation->getOrCreateRootStorage() );
239         if ( xRootStorage.is() )
240 	    {
241             sal_Int32 nRealMode = m_pModelImplementation->m_bDocumentReadOnly ? ElementModes::READ : _nDesiredMode;
242             if ( nRealMode == ElementModes::READ )
243             {
244                 Reference< XNameAccess > xSubStorageNames( xRootStorage, UNO_QUERY );
245                 if ( xSubStorageNames.is() && !xSubStorageNames->hasByName( _rStorageName ) )
246                     return xStorage;
247             }
248 
249 			xStorage = xRootStorage->openStorageElement( _rStorageName, nRealMode );
250 
251             Reference< XTransactionBroadcaster > xBroad( xStorage, UNO_QUERY );
252             if ( xBroad.is() )
253                 xBroad->addTransactionListener( this );
254 		}
255 	}
256 	catch( const Exception& )
257 	{
258         DBG_UNHANDLED_EXCEPTION();
259 	}
260 
261 	return xStorage;
262 }
263 
264 //--------------------------------------------------------------------------
265 void DocumentStorageAccess::disposeStorages()
266 {
267     m_bDisposingSubStorages = true;
268 
269 	NamedStorages::iterator aEnd = m_aExposedStorages.end();
270 	for (   NamedStorages::iterator aIter = m_aExposedStorages.begin();
271             aIter != aEnd ;
272             ++aIter
273         )
274 	{
275         try
276         {
277 		    ::comphelper::disposeComponent( aIter->second );
278         }
279         catch( const Exception& )
280         {
281             DBG_UNHANDLED_EXCEPTION();
282         }
283 	}
284 	m_aExposedStorages.clear();
285 
286     m_bDisposingSubStorages = false;
287 }
288 
289 //--------------------------------------------------------------------------
290 void DocumentStorageAccess::commitStorages() SAL_THROW(( IOException, RuntimeException ))
291 {
292     try
293     {
294         for (   NamedStorages::const_iterator aIter = m_aExposedStorages.begin();
295                 aIter != m_aExposedStorages.end();
296                 ++aIter
297             )
298         {
299             tools::stor::commitStorageIfWriteable( aIter->second );
300         }
301     }
302     catch(const WrappedTargetException&)
303     {
304         // WrappedTargetException not allowed to leave
305         throw IOException();
306     }
307 }
308 
309 //--------------------------------------------------------------------------
310 bool DocumentStorageAccess::commitEmbeddedStorage( bool _bPreventRootCommits )
311 {
312 	if ( _bPreventRootCommits )
313         impl_suspendCommitPropagation();
314 
315     bool bSuccess = false;
316 	try
317 	{
318 		NamedStorages::const_iterator pos = m_aExposedStorages.find( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "database" ) ) );
319 		if ( pos != m_aExposedStorages.end() )
320 			bSuccess = tools::stor::commitStorageIfWriteable( pos->second );
321 	}
322 	catch( Exception& )
323 	{
324         DBG_UNHANDLED_EXCEPTION();
325 	}
326 
327     if ( _bPreventRootCommits )
328         impl_resumeCommitPropagation();
329 
330     return bSuccess;
331 
332 }
333 
334 //--------------------------------------------------------------------------
335 Reference< XStorage > SAL_CALL DocumentStorageAccess::getDocumentSubStorage( const ::rtl::OUString& aStorageName, ::sal_Int32 _nDesiredMode ) throw (RuntimeException)
336 {
337     ::osl::MutexGuard aGuard( m_aMutex );
338     NamedStorages::iterator pos = m_aExposedStorages.find( aStorageName );
339     if ( pos == m_aExposedStorages.end() )
340     {
341 	    Reference< XStorage > xResult = impl_openSubStorage_nothrow( aStorageName, _nDesiredMode );
342         pos = m_aExposedStorages.insert( NamedStorages::value_type( aStorageName, xResult ) ).first;
343     }
344 
345     return pos->second;
346 }
347 
348 //--------------------------------------------------------------------------
349 Sequence< ::rtl::OUString > SAL_CALL DocumentStorageAccess::getDocumentSubStoragesNames(  ) throw (IOException, RuntimeException)
350 {
351     Reference< XStorage > xRootStor( m_pModelImplementation->getRootStorage() );
352     if ( !xRootStor.is() )
353         return Sequence< ::rtl::OUString >();
354 
355     ::std::vector< ::rtl::OUString > aNames;
356 
357     Reference< XNameAccess > xNames( xRootStor, UNO_QUERY_THROW );
358     Sequence< ::rtl::OUString > aElementNames( xNames->getElementNames() );
359     for ( sal_Int32 i=0; i<aElementNames.getLength(); ++i )
360     {
361         if ( xRootStor->isStorageElement( aElementNames[i] ) )
362             aNames.push_back( aElementNames[i] );
363     }
364     return aNames.empty()
365         ?  Sequence< ::rtl::OUString >()
366         :  Sequence< ::rtl::OUString >( &aNames[0], aNames.size() );
367 }
368 
369 //--------------------------------------------------------------------------
370 void SAL_CALL DocumentStorageAccess::preCommit( const css::lang::EventObject& /*aEvent*/ ) throw (Exception, RuntimeException)
371 {
372 	// not interested in
373 }
374 
375 //--------------------------------------------------------------------------
376 void SAL_CALL DocumentStorageAccess::commited( const css::lang::EventObject& aEvent ) throw (RuntimeException)
377 {
378 	::osl::MutexGuard aGuard( m_aMutex );
379 
380     if ( m_pModelImplementation )
381         m_pModelImplementation->setModified( sal_True );
382 
383     if ( m_pModelImplementation && m_bPropagateCommitToRoot )
384     {
385         Reference< XStorage > xStorage( aEvent.Source, UNO_QUERY );
386 
387         // check if this is the dedicated "database" sub storage
388         NamedStorages::const_iterator pos = m_aExposedStorages.find( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "database" ) ) );
389 	    if  (   ( pos != m_aExposedStorages.end() )
390             &&  ( pos->second == xStorage )
391             )
392 	    {
393             // if so, also commit the root storage
394             m_pModelImplementation->commitRootStorage();
395         }
396     }
397 }
398 
399 //--------------------------------------------------------------------------
400 void SAL_CALL DocumentStorageAccess::preRevert( const css::lang::EventObject& /*aEvent*/ ) throw (Exception, RuntimeException)
401 {
402 	// not interested in
403 }
404 
405 //--------------------------------------------------------------------------
406 void SAL_CALL DocumentStorageAccess::reverted( const css::lang::EventObject& /*aEvent*/ ) throw (RuntimeException)
407 {
408 	// not interested in
409 }
410 
411 //--------------------------------------------------------------------------
412 void SAL_CALL DocumentStorageAccess::disposing( const css::lang::EventObject& Source ) throw ( RuntimeException )
413 {
414     OSL_ENSURE( Reference< XStorage >( Source.Source, UNO_QUERY ).is(), "DocumentStorageAccess::disposing: No storage? What's this?" );
415 
416     if ( m_bDisposingSubStorages )
417         return;
418 
419     for (   NamedStorages::iterator find = m_aExposedStorages.begin();
420             find != m_aExposedStorages.end();
421             ++find
422         )
423         if ( find->second == Source.Source )
424         {
425             m_aExposedStorages.erase( find );
426             break;
427         }
428 }
429 
430 //============================================================
431 //= ODatabaseModelImpl
432 //============================================================
433 DBG_NAME(ODatabaseModelImpl)
434 //--------------------------------------------------------------------------
435 ODatabaseModelImpl::ODatabaseModelImpl( const Reference< XMultiServiceFactory >& _rxFactory, ODatabaseContext& _rDBContext )
436             :m_xModel()
437             ,m_xDataSource()
438             ,m_pStorageAccess( NULL )
439             ,m_aMutex()
440             ,m_aMutexFacade( m_aMutex )
441             ,m_aContainer(4)
442             ,m_aMacroMode( *this )
443 			,m_nImposedMacroExecMode( MacroExecMode::NEVER_EXECUTE )
444 			,m_pDBContext( &_rDBContext )
445             ,m_refCount(0)
446             ,m_aEmbeddedMacros()
447             ,m_bModificationLock( false )
448             ,m_bDocumentInitialized( false )
449 			,m_aContext( _rxFactory )
450 			,m_nLoginTimeout(0)
451             ,m_bReadOnly(sal_False)
452 			,m_bPasswordRequired(sal_False)
453 			,m_bSuppressVersionColumns(sal_True)
454 			,m_bModified(sal_False)
455 			,m_bDocumentReadOnly(sal_False)
456 			,m_pSharedConnectionManager(NULL)
457 			,m_nControllerLockCount(0)
458 {
459 	// some kind of default
460 	DBG_CTOR(ODatabaseModelImpl,NULL);
461 	m_sConnectURL = ::rtl::OUString::createFromAscii("jdbc:");
462 	m_aTableFilter.realloc(1);
463 	m_aTableFilter[0] = ::rtl::OUString::createFromAscii("%");
464 	impl_construct_nothrow();
465 }
466 
467 //--------------------------------------------------------------------------
468 ODatabaseModelImpl::ODatabaseModelImpl(
469 					const ::rtl::OUString& _rRegistrationName,
470 					const Reference< XMultiServiceFactory >& _rxFactory,
471 					ODatabaseContext& _rDBContext
472 					)
473             :m_xModel()
474             ,m_xDataSource()
475             ,m_pStorageAccess( NULL )
476             ,m_aMutex()
477             ,m_aMutexFacade( m_aMutex )
478             ,m_aContainer(4)
479             ,m_aMacroMode( *this )
480 			,m_nImposedMacroExecMode( MacroExecMode::NEVER_EXECUTE )
481 			,m_pDBContext( &_rDBContext )
482             ,m_refCount(0)
483             ,m_aEmbeddedMacros()
484             ,m_bModificationLock( false )
485             ,m_bDocumentInitialized( false )
486 			,m_aContext( _rxFactory )
487             ,m_sName(_rRegistrationName)
488 			,m_nLoginTimeout(0)
489 			,m_bReadOnly(sal_False)
490 			,m_bPasswordRequired(sal_False)
491 			,m_bSuppressVersionColumns(sal_True)
492 			,m_bModified(sal_False)
493 			,m_bDocumentReadOnly(sal_False)
494 			,m_pSharedConnectionManager(NULL)
495 			,m_nControllerLockCount(0)
496 {
497 	DBG_CTOR(ODatabaseModelImpl,NULL);
498 	impl_construct_nothrow();
499 }
500 
501 //--------------------------------------------------------------------------
502 ODatabaseModelImpl::~ODatabaseModelImpl()
503 {
504 	DBG_DTOR(ODatabaseModelImpl,NULL);
505 }
506 
507 // -----------------------------------------------------------------------------
508 void ODatabaseModelImpl::impl_construct_nothrow()
509 {
510     // create the property bag to hold the settings (also known as "Info" property)
511     try
512     {
513         // the set of property value types in the bag is limited:
514         Sequence< Type > aAllowedTypes(6);
515         Type* pAllowedType = aAllowedTypes.getArray();
516         *pAllowedType++ = ::getCppuType( static_cast< sal_Bool* >( NULL ) );
517         *pAllowedType++ = ::getCppuType( static_cast< double* >( NULL ) );
518         *pAllowedType++ = ::getCppuType( static_cast< ::rtl::OUString* >( NULL ) );
519         *pAllowedType++ = ::getCppuType( static_cast< sal_Int32* >( NULL ) );
520         *pAllowedType++ = ::getCppuType( static_cast< sal_Int16* >( NULL ) );
521         *pAllowedType++ = ::getCppuType( static_cast< Sequence< Any >* >( NULL ) );
522 
523         Sequence< Any > aInitArgs( 2 );
524         aInitArgs[0] <<= NamedValue(
525             ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "AutomaticAddition" ) ),
526             makeAny( (sal_Bool)sal_True )
527         );
528         aInitArgs[1] <<= NamedValue(
529             ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "AllowedTypes" ) ),
530             makeAny( aAllowedTypes )
531         );
532 
533         m_xSettings.set( m_aContext.createComponentWithArguments( "com.sun.star.beans.PropertyBag", aInitArgs ), UNO_QUERY_THROW );
534 
535         // insert the default settings
536         Reference< XPropertyContainer > xContainer( m_xSettings, UNO_QUERY_THROW );
537         Reference< XSet > xSettingsSet( m_xSettings, UNO_QUERY_THROW );
538         const AsciiPropertyValue* pSettings = getDefaultDataSourceSettings();
539         for ( ; pSettings->AsciiName; ++pSettings )
540         {
541             if ( !pSettings->DefaultValue.hasValue() )
542             {
543                 Property aProperty(
544                     ::rtl::OUString::createFromAscii( pSettings->AsciiName ),
545                     -1,
546                     pSettings->ValueType,
547                     PropertyAttribute::BOUND | PropertyAttribute::MAYBEDEFAULT | PropertyAttribute::MAYBEVOID
548                 );
549                 xSettingsSet->insert( makeAny( aProperty ) );
550             }
551             else
552             {
553                 xContainer->addProperty(
554                     ::rtl::OUString::createFromAscii( pSettings->AsciiName ),
555                     PropertyAttribute::BOUND | PropertyAttribute::MAYBEDEFAULT,
556                     pSettings->DefaultValue
557                 );
558             }
559         }
560     }
561     catch( const Exception& )
562     {
563         DBG_UNHANDLED_EXCEPTION();
564     }
565     m_pDBContext->appendAtTerminateListener(*this);
566 }
567 
568 // -----------------------------------------------------------------------------
569 namespace
570 {
571     // .........................................................................
572     ::rtl::OUString lcl_getContainerStorageName_throw( ODatabaseModelImpl::ObjectType _eType )
573     {
574         const sal_Char* pAsciiName( NULL );
575         switch ( _eType )
576         {
577         case ODatabaseModelImpl::E_FORM:   pAsciiName = "forms"; break;
578         case ODatabaseModelImpl::E_REPORT: pAsciiName = "reports"; break;
579         case ODatabaseModelImpl::E_QUERY:  pAsciiName = "queries"; break;
580         case ODatabaseModelImpl::E_TABLE:  pAsciiName = "tables"; break;
581         default:
582             throw RuntimeException();
583         }
584         return ::rtl::OUString::createFromAscii( pAsciiName );
585     }
586 
587     // .........................................................................
588     bool lcl_hasObjectWithMacros_throw( const ODefinitionContainer_Impl& _rObjectDefinitions, const Reference< XStorage >& _rxContainerStorage )
589     {
590         bool bSomeDocHasMacros = false;
591 
592         for (   ODefinitionContainer_Impl::const_iterator object = _rObjectDefinitions.begin();
593                 ( object != _rObjectDefinitions.end() ) && !bSomeDocHasMacros;
594                 ++object
595             )
596         {
597 #if OSL_DEBUG_LEVEL > 0
598             const ::rtl::OUString& rName( object->first ); (void)rName;
599 #endif
600 
601             const TContentPtr& rDefinition( object->second );
602             const ::rtl::OUString& rPersistentName( rDefinition->m_aProps.sPersistentName );
603 
604             if ( !rPersistentName.getLength() )
605             {   // it's a logical sub folder used to organize the real objects
606                 const ODefinitionContainer_Impl& rSubFoldersObjectDefinitions( dynamic_cast< const ODefinitionContainer_Impl& >( *rDefinition.get() ) );
607                 bSomeDocHasMacros = lcl_hasObjectWithMacros_throw( rSubFoldersObjectDefinitions, _rxContainerStorage );
608                 continue;
609             }
610 
611             bSomeDocHasMacros = ODatabaseModelImpl::objectHasMacros( _rxContainerStorage, rPersistentName );
612         }
613         return bSomeDocHasMacros;
614     }
615 
616     // .........................................................................
617     bool lcl_hasObjectsWithMacros_nothrow( ODatabaseModelImpl& _rModel, const ODatabaseModelImpl::ObjectType _eType )
618     {
619         bool bSomeDocHasMacros = false;
620 
621         const OContentHelper_Impl& rContainerData( *_rModel.getObjectContainer( _eType ).get() );
622         const ODefinitionContainer_Impl& rObjectDefinitions = dynamic_cast< const ODefinitionContainer_Impl& >( rContainerData );
623 
624         try
625         {
626             Reference< XStorage > xContainerStorage( _rModel.getStorage( _eType, ElementModes::READWRITE ) );
627             // note the READWRITE here: If the storage already existed before, then the OpenMode will
628             // be ignored, anyway.
629             // If the storage did not yet exist, then it will be created. If the database document
630             // is read-only, the OpenMode will be automatically downgraded to READ. Otherwise,
631             // the storage will in fact be created as READWRITE. While this is not strictly necessary
632             // for this particular use case here, it is required since the storage is *cached*, and
633             // later use cases will need the READWRITE mode.
634 
635             if ( xContainerStorage.is() )
636                 bSomeDocHasMacros = lcl_hasObjectWithMacros_throw( rObjectDefinitions, xContainerStorage );
637         }
638         catch( const Exception& )
639         {
640         	DBG_UNHANDLED_EXCEPTION();
641             // be on the safe side: If we can't reliably determine whether there are macros,
642             // assume there actually are. Better this way, than the other way round.
643             bSomeDocHasMacros = true;
644         }
645 
646         return bSomeDocHasMacros;
647     }
648 }
649 
650 // -----------------------------------------------------------------------------
651 bool ODatabaseModelImpl::objectHasMacros( const Reference< XStorage >& _rxContainerStorage, const ::rtl::OUString& _rPersistentName )
652 {
653     OSL_PRECOND( _rxContainerStorage.is(), "ODatabaseModelImpl::objectHasMacros: this will crash!" );
654 
655     bool bHasMacros = true;
656     try
657     {
658         if ( !_rxContainerStorage->hasByName( _rPersistentName ) )
659             return false;
660 
661         Reference< XStorage > xObjectStor( _rxContainerStorage->openStorageElement(
662             _rPersistentName, ElementModes::READ ) );
663 
664         bHasMacros = ::sfx2::DocumentMacroMode::storageHasMacros( xObjectStor );
665     }
666     catch( const Exception& )
667     {
668     	DBG_UNHANDLED_EXCEPTION();
669     }
670     return bHasMacros;
671 }
672 
673 // -----------------------------------------------------------------------------
674 void ODatabaseModelImpl::reset()
675 {
676 	m_bReadOnly = sal_False;
677     ::std::vector< TContentPtr > aEmptyContainers( 4 );
678     m_aContainer.swap( aEmptyContainers );
679 
680     if ( m_pStorageAccess )
681     {
682         m_pStorageAccess->dispose();
683         m_pStorageAccess->release();
684         m_pStorageAccess = NULL;
685     }
686 }
687 // -----------------------------------------------------------------------------
688 void SAL_CALL ODatabaseModelImpl::disposing( const ::com::sun::star::lang::EventObject& Source ) throw(RuntimeException)
689 {
690 	Reference<XConnection> xCon(Source.Source,UNO_QUERY);
691 	if ( xCon.is() )
692 	{
693 		bool bStore = false;
694 		OWeakConnectionArray::iterator aEnd = m_aConnections.end();
695 		for (OWeakConnectionArray::iterator i = m_aConnections.begin(); aEnd != i; ++i)
696 		{
697 			if ( xCon == i->get() )
698 			{
699 				*i = OWeakConnection();
700                 bStore = true;
701                 break;
702 			}
703 		}
704 
705 		if ( bStore )
706             commitRootStorage();
707 	}
708 	else
709 	{
710         OSL_ENSURE( false, "ODatabaseModelImpl::disposing: where does this come from?" );
711 	}
712 }
713 //------------------------------------------------------------------------------
714 void ODatabaseModelImpl::clearConnections()
715 {
716     OWeakConnectionArray aConnections;
717     aConnections.swap( m_aConnections );
718 
719 	Reference< XConnection > xConn;
720     OWeakConnectionArray::iterator aEnd = aConnections.end();
721 	for ( OWeakConnectionArray::iterator i = aConnections.begin(); aEnd != i; ++i )
722 	{
723 		xConn = *i;
724 		if ( xConn.is() )
725 		{
726 			try
727 			{
728 				xConn->close();
729 			}
730 			catch(const Exception&)
731 			{
732 				DBG_UNHANDLED_EXCEPTION();
733 			}
734 		}
735 	}
736 
737     m_pSharedConnectionManager = NULL;
738 	m_xSharedConnectionManager = NULL;
739 }
740 //------------------------------------------------------------------------------
741 void ODatabaseModelImpl::dispose()
742 {
743     // dispose the data source and the model
744     try
745     {
746         Reference< XDataSource > xDS( m_xDataSource );
747 		::comphelper::disposeComponent( xDS );
748 
749         Reference< XModel > xModel( m_xModel );
750         ::comphelper::disposeComponent( xModel );
751     }
752     catch( const Exception& )
753     {
754         DBG_UNHANDLED_EXCEPTION();
755     }
756 	m_xDataSource = WeakReference<XDataSource>();
757     m_xModel = WeakReference< XModel >();
758 
759 	::std::vector<TContentPtr>::iterator aIter = m_aContainer.begin();
760 	::std::vector<TContentPtr>::iterator aEnd = m_aContainer.end();
761 	for (;aIter != aEnd ; ++aIter)
762 	{
763 		if ( aIter->get() )
764 			(*aIter)->m_pDataSource = NULL;
765 	}
766 	m_aContainer.clear();
767 
768 	clearConnections();
769 
770 	m_xNumberFormatsSupplier = NULL;
771 
772     try
773 	{
774         sal_Bool bCouldStore = commitEmbeddedStorage( true );
775             // "true" means that committing the embedded storage should not trigger committing the root
776             // storage. This is because we are going to commit the root storage ourself, anyway
777         disposeStorages();
778         if ( bCouldStore )
779             commitRootStorage();
780 
781         impl_switchToStorage_throw( NULL );
782 	}
783 	catch( const Exception& )
784 	{
785         DBG_UNHANDLED_EXCEPTION();
786 	}
787 
788     if ( m_pStorageAccess )
789     {
790         m_pStorageAccess->dispose();
791         m_pStorageAccess->release();
792         m_pStorageAccess = NULL;
793     }
794 }
795 // -----------------------------------------------------------------------------
796 const Reference< XNumberFormatsSupplier > & ODatabaseModelImpl::getNumberFormatsSupplier()
797 {
798 	if (!m_xNumberFormatsSupplier.is())
799 	{
800 		// the arguments : the locale of the current user
801 		UserInformation aUserInfo;
802 		Sequence< Any > aArguments(1);
803 		aArguments.getArray()[0] <<= aUserInfo.getUserLanguage();
804 
805         m_xNumberFormatsSupplier.set(
806             m_aContext.createComponentWithArguments( "com.sun.star.util.NumberFormatsSupplier", aArguments ), UNO_QUERY_THROW );
807 		DBG_ASSERT(m_xNumberFormatsSupplier.is(), "ODatabaseModelImpl::getNumberFormatsSupplier : could not instantiate the formats supplier !");
808 	}
809 	return m_xNumberFormatsSupplier;
810 }
811 
812 // -----------------------------------------------------------------------------
813 void ODatabaseModelImpl::setDocFileLocation( const ::rtl::OUString& i_rLoadedFrom )
814 {
815     ENSURE_OR_THROW( i_rLoadedFrom.getLength(), "invalid URL" );
816     m_sDocFileLocation = i_rLoadedFrom;
817 }
818 
819 // -----------------------------------------------------------------------------
820 void ODatabaseModelImpl::setResource( const ::rtl::OUString& i_rDocumentURL, const Sequence< PropertyValue >& _rArgs )
821 {
822     ENSURE_OR_THROW( i_rDocumentURL.getLength(), "invalid URL" );
823 
824     ::comphelper::NamedValueCollection aMediaDescriptor( _rArgs );
825 #if OSL_DEBUG_LEVEL > 0
826     if ( aMediaDescriptor.has( "SalvagedFile" ) )
827     {
828         ::rtl::OUString sSalvagedFile( aMediaDescriptor.getOrDefault( "SalvagedFile", ::rtl::OUString() ) );
829         // If SalvagedFile is an empty string, this indicates "the document is being recovered, but i_rDocumentURL already
830         // is the real document URL, not the temporary document location"
831         if ( !sSalvagedFile.getLength() )
832             sSalvagedFile = i_rDocumentURL;
833 
834         OSL_ENSURE( sSalvagedFile == i_rDocumentURL, "ODatabaseModelImpl::setResource: inconsistency!" );
835             // nowadays, setResource should only be called with the logical URL of the document
836     }
837 #endif
838 
839     m_aMediaDescriptor = stripLoadArguments( aMediaDescriptor );
840 
841     impl_switchToLogicalURL( i_rDocumentURL );
842 }
843 
844 // -----------------------------------------------------------------------------
845 ::comphelper::NamedValueCollection ODatabaseModelImpl::stripLoadArguments( const ::comphelper::NamedValueCollection& _rArguments )
846 {
847     OSL_ENSURE( !_rArguments.has( "Model" ), "ODatabaseModelImpl::stripLoadArguments: this is suspicious (1)!" );
848     OSL_ENSURE( !_rArguments.has( "ViewName" ), "ODatabaseModelImpl::stripLoadArguments: this is suspicious (2)!" );
849 
850     ::comphelper::NamedValueCollection aMutableArgs( _rArguments );
851     aMutableArgs.remove( "Model" );
852     aMutableArgs.remove( "ViewName" );
853     return aMutableArgs;
854 }
855 
856 // -----------------------------------------------------------------------------
857 void ODatabaseModelImpl::disposeStorages() SAL_THROW(())
858 {
859     getDocumentStorageAccess()->disposeStorages();
860 }
861 
862 // -----------------------------------------------------------------------------
863 Reference< XSingleServiceFactory > ODatabaseModelImpl::createStorageFactory() const
864 {
865     return Reference< XSingleServiceFactory >( m_aContext.createComponent( "com.sun.star.embed.StorageFactory" ), UNO_QUERY_THROW );
866 }
867 // -----------------------------------------------------------------------------
868 void ODatabaseModelImpl::commitRootStorage()
869 {
870     Reference< XStorage > xStorage( getOrCreateRootStorage() );
871 #if OSL_DEBUG_LEVEL > 0
872     bool bSuccess =
873 #endif
874     commitStorageIfWriteable_ignoreErrors( xStorage );
875     OSL_ENSURE( bSuccess || !xStorage.is(),
876         "ODatabaseModelImpl::commitRootStorage: could commit the storage!" );
877 }
878 // -----------------------------------------------------------------------------
879 Reference< XStorage > ODatabaseModelImpl::getOrCreateRootStorage()
880 {
881 	if ( !m_xDocumentStorage.is() )
882 	{
883 		Reference< XSingleServiceFactory> xStorageFactory = createStorageFactory();
884         if ( xStorageFactory.is() )
885 		{
886             Any aSource;
887             aSource = m_aMediaDescriptor.get( "Stream" );
888             if ( !aSource.hasValue() )
889                 aSource = m_aMediaDescriptor.get( "InputStream" );
890             if ( !aSource.hasValue() && m_sDocFileLocation.getLength() )
891                 aSource <<= m_sDocFileLocation;
892             // TODO: shouldn't we also check URL?
893 
894             OSL_ENSURE( aSource.hasValue(), "ODatabaseModelImpl::getOrCreateRootStorage: no source to create the storage from!" );
895 
896             if ( aSource.hasValue() )
897             {
898 			    Sequence< Any > aStorageCreationArgs(2);
899                 aStorageCreationArgs[0] = aSource;
900 			    aStorageCreationArgs[1] <<= ElementModes::READWRITE;
901 
902                 Reference< XStorage > xDocumentStorage;
903 			    try
904 			    {
905 				    xDocumentStorage.set( xStorageFactory->createInstanceWithArguments( aStorageCreationArgs ), UNO_QUERY_THROW );
906 			    }
907 			    catch( const Exception& )
908 			    {
909 				    m_bDocumentReadOnly = sal_True;
910 				    aStorageCreationArgs[1] <<= ElementModes::READ;
911 				    try
912 				    {
913 					    xDocumentStorage.set( xStorageFactory->createInstanceWithArguments( aStorageCreationArgs ), UNO_QUERY_THROW );
914 				    }
915 				    catch( const Exception& )
916 				    {
917                         DBG_UNHANDLED_EXCEPTION();
918 				    }
919 			    }
920 
921                 impl_switchToStorage_throw( xDocumentStorage );
922             }
923 		}
924 	}
925 	return m_xDocumentStorage.getTyped();
926 }
927 // -----------------------------------------------------------------------------
928 DocumentStorageAccess* ODatabaseModelImpl::getDocumentStorageAccess()
929 {
930     if ( !m_pStorageAccess )
931     {
932         m_pStorageAccess = new DocumentStorageAccess( *this );
933         m_pStorageAccess->acquire();
934     }
935     return m_pStorageAccess;
936 }
937 
938 // -----------------------------------------------------------------------------
939 void ODatabaseModelImpl::modelIsDisposing( const bool _wasInitialized, ResetModelAccess )
940 {
941     m_xModel = Reference< XModel >();
942 
943     // Basic libraries and Dialog libraries are a model facet, though held at this impl class.
944     // They automatically dispose themself when the model they belong to is being disposed.
945     // So, to not be tempted to do anything with them, again, we reset them.
946     m_xBasicLibraries.clear();
947     m_xDialogLibraries.clear();
948 
949     m_bDocumentInitialized = _wasInitialized;
950 }
951 
952 // -----------------------------------------------------------------------------
953 Reference< XDocumentSubStorageSupplier > ODatabaseModelImpl::getDocumentSubStorageSupplier()
954 {
955     return getDocumentStorageAccess();
956 }
957 
958 // -----------------------------------------------------------------------------
959 bool ODatabaseModelImpl::commitEmbeddedStorage( bool _bPreventRootCommits )
960 {
961     return getDocumentStorageAccess()->commitEmbeddedStorage( _bPreventRootCommits );
962 }
963 
964 // -----------------------------------------------------------------------------
965 bool ODatabaseModelImpl::commitStorageIfWriteable_ignoreErrors( const Reference< XStorage >& _rxStorage ) SAL_THROW(())
966 {
967     bool bSuccess = false;
968     try
969     {
970         bSuccess = tools::stor::commitStorageIfWriteable( _rxStorage );
971     }
972     catch( const Exception& )
973     {
974         DBG_UNHANDLED_EXCEPTION();
975     }
976     return bSuccess;
977 }
978 // -----------------------------------------------------------------------------
979 void ODatabaseModelImpl::setModified( sal_Bool _bModified )
980 {
981     if ( isModifyLocked() )
982         return;
983 
984     try
985     {
986         Reference< XModifiable > xModi( m_xModel.get(), UNO_QUERY );
987         if ( xModi.is() )
988             xModi->setModified( _bModified );
989         else
990             m_bModified = _bModified;
991     }
992     catch( const Exception& )
993     {
994         DBG_UNHANDLED_EXCEPTION();
995     }
996 }
997 
998 // -----------------------------------------------------------------------------
999 Reference<XDataSource> ODatabaseModelImpl::getOrCreateDataSource()
1000 {
1001 	Reference<XDataSource> xDs = m_xDataSource;
1002 	if ( !xDs.is() )
1003 	{
1004 		xDs = new ODatabaseSource(this);
1005         m_xDataSource = xDs;
1006 	}
1007 	return xDs;
1008 }
1009 // -----------------------------------------------------------------------------
1010 Reference< XModel> ODatabaseModelImpl::getModel_noCreate() const
1011 {
1012     return m_xModel;
1013 }
1014 // -----------------------------------------------------------------------------
1015 Reference< XModel > ODatabaseModelImpl::createNewModel_deliverOwnership( bool _bInitialize )
1016 {
1017     Reference< XModel > xModel( m_xModel );
1018     OSL_PRECOND( !xModel.is(), "ODatabaseModelImpl::createNewModel_deliverOwnership: not to be called if there already is a model!" );
1019 	if ( !xModel.is() )
1020     {
1021         bool bHadModelBefore = m_bDocumentInitialized;
1022 
1023         xModel = ODatabaseDocument::createDatabaseDocument( this, ODatabaseDocument::FactoryAccess() );
1024         m_xModel = xModel;
1025 
1026         try
1027         {
1028             Reference< XSet > xModelCollection;
1029             if ( m_aContext.createComponent( "com.sun.star.frame.GlobalEventBroadcaster", xModelCollection ) )
1030                 xModelCollection->insert( makeAny( xModel ) );
1031         }
1032         catch( const Exception& )
1033         {
1034             DBG_UNHANDLED_EXCEPTION();
1035         }
1036 
1037         if ( bHadModelBefore )
1038         {
1039             // do an attachResources
1040             // In case the document is loaded regularly, this is not necessary, as our loader will do it.
1041             // However, in case that the document is implicitly created by asking the data source for the document,
1042             // then nobody would call the doc's attachResource. So, we do it here, to ensure it's in a proper
1043             // state, fires all events, and so on.
1044             // #i105505# / 2009-10-02 / frank.schoenheit@sun.com
1045             xModel->attachResource( xModel->getURL(), m_aMediaDescriptor.getPropertyValues() );
1046         }
1047 
1048         if ( _bInitialize )
1049         {
1050             try
1051             {
1052                 Reference< XLoadable > xLoad( xModel, UNO_QUERY_THROW );
1053                 xLoad->initNew();
1054             }
1055             catch( RuntimeException& ) { throw; }
1056             catch( const Exception& )
1057             {
1058         	    DBG_UNHANDLED_EXCEPTION();
1059             }
1060         }
1061     }
1062 	return xModel;
1063 }
1064 // -----------------------------------------------------------------------------
1065 oslInterlockedCount SAL_CALL ODatabaseModelImpl::acquire()
1066 {
1067 	return osl_incrementInterlockedCount(&m_refCount);
1068 }
1069 // -----------------------------------------------------------------------------
1070 oslInterlockedCount SAL_CALL ODatabaseModelImpl::release()
1071 {
1072 	if ( osl_decrementInterlockedCount(&m_refCount) == 0 )
1073 	{
1074         acquire();  // prevent multiple releases
1075         m_pDBContext->removeFromTerminateListener(*this);
1076         dispose();
1077         m_pDBContext->storeTransientProperties(*this);
1078         revokeDataSource();
1079 		delete this;
1080 		return 0;
1081 	}
1082 	return m_refCount;
1083 }
1084 // -----------------------------------------------------------------------------
1085 void ODatabaseModelImpl::commitStorages() SAL_THROW(( IOException, RuntimeException ))
1086 {
1087     getDocumentStorageAccess()->commitStorages();
1088 }
1089 
1090 // -----------------------------------------------------------------------------
1091 Reference< XStorage > ODatabaseModelImpl::getStorage( const ObjectType _eType, const sal_Int32 _nDesiredMode )
1092 {
1093     return getDocumentStorageAccess()->getDocumentSubStorage( getObjectContainerStorageName( _eType ), _nDesiredMode );
1094 }
1095 
1096 // -----------------------------------------------------------------------------
1097 const AsciiPropertyValue* ODatabaseModelImpl::getDefaultDataSourceSettings()
1098 {
1099     static const AsciiPropertyValue aKnownSettings[] =
1100     {
1101         // known JDBC settings
1102         AsciiPropertyValue( "JavaDriverClass",            makeAny( ::rtl::OUString() ) ),
1103         AsciiPropertyValue( "JavaDriverClassPath",       makeAny( ::rtl::OUString() ) ),
1104         AsciiPropertyValue( "IgnoreCurrency",             makeAny( (sal_Bool)sal_False ) ),
1105         // known settings for file-based drivers
1106         AsciiPropertyValue( "Extension",                  makeAny( ::rtl::OUString() ) ),
1107         AsciiPropertyValue( "CharSet",                    makeAny( ::rtl::OUString() ) ),
1108         AsciiPropertyValue( "HeaderLine",                 makeAny( (sal_Bool)sal_True ) ),
1109         AsciiPropertyValue( "FieldDelimiter",             makeAny( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "," ) ) ) ),
1110         AsciiPropertyValue( "StringDelimiter",            makeAny( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "\"" ) ) ) ),
1111         AsciiPropertyValue( "DecimalDelimiter",           makeAny( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "." ) ) ) ),
1112         AsciiPropertyValue( "ThousandDelimiter",          makeAny( ::rtl::OUString() ) ),
1113         AsciiPropertyValue( "ShowDeleted",                makeAny( (sal_Bool)sal_False ) ),
1114         // known ODBC settings
1115         AsciiPropertyValue( "SystemDriverSettings",       makeAny( ::rtl::OUString() ) ),
1116         AsciiPropertyValue( "UseCatalog",                 makeAny( (sal_Bool)sal_False ) ),
1117         AsciiPropertyValue( "TypeInfoSettings",           makeAny( Sequence< Any >()) ),
1118         // settings related to auto increment handling
1119         AsciiPropertyValue( "AutoIncrementCreation",      makeAny( ::rtl::OUString() ) ),
1120         AsciiPropertyValue( "AutoRetrievingStatement",    makeAny( ::rtl::OUString() ) ),
1121         AsciiPropertyValue( "IsAutoRetrievingEnabled",    makeAny( (sal_Bool)sal_False ) ),
1122         // known Adabas D driver setting
1123         AsciiPropertyValue( "ShutdownDatabase",           makeAny( (sal_Bool)sal_False ) ),
1124         AsciiPropertyValue( "DataCacheSizeIncrement",     makeAny( (sal_Int32)20 ) ),
1125         AsciiPropertyValue( "DataCacheSize",              makeAny( (sal_Int32)20 ) ),
1126         AsciiPropertyValue( "ControlUser",                makeAny( ::rtl::OUString() ) ),
1127         AsciiPropertyValue( "ControlPassword",            makeAny( ::rtl::OUString() ) ),
1128         // known LDAP driver settings
1129         AsciiPropertyValue( "HostName",                   makeAny( ::rtl::OUString() ) ),
1130         AsciiPropertyValue( "PortNumber",                 makeAny( (sal_Int32)389 ) ),
1131         AsciiPropertyValue( "BaseDN",                     makeAny( ::rtl::OUString() ) ),
1132         AsciiPropertyValue( "MaxRowCount",                makeAny( (sal_Int32)100 ) ),
1133         // known MySQLNative driver settings
1134         AsciiPropertyValue( "LocalSocket",                makeAny( ::rtl::OUString() ) ),
1135         AsciiPropertyValue( "NamedPipe",                  makeAny( ::rtl::OUString() ) ),
1136         // misc known driver settings
1137         AsciiPropertyValue( "ParameterNameSubstitution",  makeAny( (sal_Bool)sal_False ) ),
1138         AsciiPropertyValue( "AddIndexAppendix",           makeAny( (sal_Bool)sal_True ) ),
1139         AsciiPropertyValue( "IgnoreDriverPrivileges",     makeAny( (sal_Bool)sal_True ) ),
1140         AsciiPropertyValue( "ImplicitCatalogRestriction", ::cppu::UnoType< ::rtl::OUString >::get() ),
1141         AsciiPropertyValue( "ImplicitSchemaRestriction",  ::cppu::UnoType< ::rtl::OUString >::get() ),
1142         AsciiPropertyValue( "PrimaryKeySupport",          ::cppu::UnoType< sal_Bool >::get() ),
1143         AsciiPropertyValue( "ShowColumnDescription",      makeAny( (sal_Bool)sal_False ) ),
1144         // known SDB level settings
1145         AsciiPropertyValue( "NoNameLengthLimit",          makeAny( (sal_Bool)sal_False ) ),
1146         AsciiPropertyValue( "AppendTableAliasName",       makeAny( (sal_Bool)sal_False ) ),
1147         AsciiPropertyValue( "GenerateASBeforeCorrelationName",  makeAny( (sal_Bool)sal_True ) ),
1148         AsciiPropertyValue( "ColumnAliasInOrderBy",       makeAny( (sal_Bool)sal_True ) ),
1149         AsciiPropertyValue( "EnableSQL92Check",           makeAny( (sal_Bool)sal_False ) ),
1150         AsciiPropertyValue( "BooleanComparisonMode",      makeAny( BooleanComparisonMode::EQUAL_INTEGER ) ),
1151         AsciiPropertyValue( "TableTypeFilterMode",        makeAny( (sal_Int32)3 ) ),
1152         AsciiPropertyValue( "RespectDriverResultSetType", makeAny( (sal_Bool)sal_False ) ),
1153         AsciiPropertyValue( "UseSchemaInSelect",          makeAny( (sal_Bool)sal_True ) ),
1154         AsciiPropertyValue( "UseCatalogInSelect",         makeAny( (sal_Bool)sal_True ) ),
1155         AsciiPropertyValue( "EnableOuterJoinEscape",      makeAny( (sal_Bool)sal_True ) ),
1156         AsciiPropertyValue( "PreferDosLikeLineEnds",      makeAny( (sal_Bool)sal_False ) ),
1157         AsciiPropertyValue( "FormsCheckRequiredFields",   makeAny( (sal_Bool)sal_True ) ),
1158         AsciiPropertyValue( "EscapeDateTime",             makeAny( (sal_Bool)sal_True ) ),
1159 
1160         // known services to handle database tasks
1161         AsciiPropertyValue( "TableAlterationServiceName", makeAny( ::rtl::OUString() ) ),
1162         AsciiPropertyValue( "TableRenameServiceName",     makeAny( ::rtl::OUString() ) ),
1163         AsciiPropertyValue( "ViewAlterationServiceName",  makeAny( ::rtl::OUString() ) ),
1164         AsciiPropertyValue( "ViewAccessServiceName",      makeAny( ::rtl::OUString() ) ),
1165         AsciiPropertyValue( "CommandDefinitions",         makeAny( ::rtl::OUString() ) ),
1166         AsciiPropertyValue( "Forms",                      makeAny( ::rtl::OUString() ) ),
1167         AsciiPropertyValue( "Reports",                    makeAny( ::rtl::OUString() ) ),
1168         AsciiPropertyValue( "KeyAlterationServiceName",   makeAny( ::rtl::OUString() ) ),
1169         AsciiPropertyValue( "IndexAlterationServiceName", makeAny( ::rtl::OUString() ) ),
1170 
1171         AsciiPropertyValue()
1172     };
1173     return aKnownSettings;
1174 }
1175 
1176 // -----------------------------------------------------------------------------
1177 TContentPtr& ODatabaseModelImpl::getObjectContainer( ObjectType _eType )
1178 {
1179     OSL_PRECOND( _eType >= E_FORM && _eType <= E_TABLE, "ODatabaseModelImpl::getObjectContainer: illegal index!" );
1180     TContentPtr& rContentPtr = m_aContainer[ _eType ];
1181 
1182     if ( !rContentPtr.get() )
1183 	{
1184 		rContentPtr = TContentPtr( new ODefinitionContainer_Impl );
1185 		rContentPtr->m_pDataSource = this;
1186 		rContentPtr->m_aProps.aTitle = lcl_getContainerStorageName_throw( _eType );
1187 	}
1188     return rContentPtr;
1189 }
1190 
1191 // -----------------------------------------------------------------------------
1192 void ODatabaseModelImpl::revokeDataSource() const
1193 {
1194     if ( m_pDBContext && m_sDocumentURL.getLength() )
1195         m_pDBContext->revokeDatabaseDocument( *this );
1196 }
1197 
1198 // -----------------------------------------------------------------------------
1199 bool ODatabaseModelImpl::adjustMacroMode_AutoReject()
1200 {
1201     return m_aMacroMode.adjustMacroMode( NULL );
1202 }
1203 
1204 // -----------------------------------------------------------------------------
1205 bool ODatabaseModelImpl::checkMacrosOnLoading()
1206 {
1207     Reference< XInteractionHandler > xInteraction;
1208     xInteraction = m_aMediaDescriptor.getOrDefault( "InteractionHandler", xInteraction );
1209     return m_aMacroMode.checkMacrosOnLoading( xInteraction );
1210 }
1211 
1212 // -----------------------------------------------------------------------------
1213 void ODatabaseModelImpl::resetMacroExecutionMode()
1214 {
1215     m_aMacroMode = ::sfx2::DocumentMacroMode( *this );
1216 }
1217 
1218 // -----------------------------------------------------------------------------
1219 Reference< XStorageBasedLibraryContainer > ODatabaseModelImpl::getLibraryContainer( bool _bScript )
1220 {
1221     Reference< XStorageBasedLibraryContainer >& rxContainer( _bScript ? m_xBasicLibraries : m_xDialogLibraries );
1222     if ( rxContainer.is() )
1223         return rxContainer;
1224 
1225     Reference< XStorageBasedDocument > xDocument( getModel_noCreate(), UNO_QUERY_THROW );
1226         // this is only to be called if there already exists a document model - in fact, it is
1227         // to be called by the document model only
1228 
1229     try
1230     {
1231         Reference< XStorageBasedLibraryContainer > (*Factory)( const Reference< XComponentContext >&, const Reference< XStorageBasedDocument >&)
1232             = _bScript ? &DocumentScriptLibraryContainer::create : &DocumentDialogLibraryContainer::create;
1233 
1234         rxContainer.set(
1235             (*Factory)( m_aContext.getUNOContext(), xDocument ),
1236             UNO_QUERY_THROW
1237         );
1238     }
1239     catch( const RuntimeException& )
1240     {
1241         throw;
1242     }
1243     catch( const Exception& )
1244     {
1245         throw WrappedTargetRuntimeException(
1246             ::rtl::OUString(),
1247             xDocument,
1248             ::cppu::getCaughtException()
1249         );
1250     }
1251     return rxContainer;
1252 }
1253 
1254 // -----------------------------------------------------------------------------
1255 void ODatabaseModelImpl::storeLibraryContainersTo( const Reference< XStorage >& _rxToRootStorage )
1256 {
1257     if ( m_xBasicLibraries.is() )
1258         m_xBasicLibraries->storeLibrariesToStorage( _rxToRootStorage );
1259 
1260     if ( m_xDialogLibraries.is() )
1261         m_xDialogLibraries->storeLibrariesToStorage( _rxToRootStorage );
1262 }
1263 
1264 // -----------------------------------------------------------------------------
1265 Reference< XStorage > ODatabaseModelImpl::switchToStorage( const Reference< XStorage >& _rxNewRootStorage )
1266 {
1267     if ( !_rxNewRootStorage.is() )
1268         throw IllegalArgumentException();
1269 
1270     return impl_switchToStorage_throw( _rxNewRootStorage );
1271 }
1272 
1273 // -----------------------------------------------------------------------------
1274 namespace
1275 {
1276     void lcl_modifyListening( ::sfx2::IModifiableDocument& _rDocument,
1277         const Reference< XStorage >& _rxStorage, ::rtl::Reference< ::sfx2::DocumentStorageModifyListener >& _inout_rListener,
1278         ::vos::IMutex& _rMutex, bool _bListen )
1279     {
1280         Reference< XModifiable > xModify( _rxStorage, UNO_QUERY );
1281         OSL_ENSURE( xModify.is() || !_rxStorage.is(), "lcl_modifyListening: storage can't notify us!" );
1282 
1283         if ( xModify.is() && !_bListen && _inout_rListener.is() )
1284         {
1285             xModify->removeModifyListener( _inout_rListener.get() );
1286         }
1287 
1288         if ( _inout_rListener.is() )
1289         {
1290             _inout_rListener->dispose();
1291             _inout_rListener = NULL;
1292         }
1293 
1294         if ( xModify.is() && _bListen )
1295         {
1296             _inout_rListener = new ::sfx2::DocumentStorageModifyListener( _rDocument, _rMutex );
1297             xModify->addModifyListener( _inout_rListener.get() );
1298         }
1299     }
1300 }
1301 
1302 // -----------------------------------------------------------------------------
1303 namespace
1304 {
1305     static void lcl_rebaseScriptStorage_throw( const Reference< XStorageBasedLibraryContainer >& _rxContainer,
1306         const Reference< XStorage >& _rxNewRootStorage )
1307     {
1308         if ( _rxContainer.is() )
1309         {
1310             if ( _rxNewRootStorage.is() )
1311                 _rxContainer->setRootStorage( _rxNewRootStorage );
1312 //            else
1313                    // TODO: what to do here? dispose the container?
1314         }
1315     }
1316 }
1317 
1318 // -----------------------------------------------------------------------------
1319 Reference< XStorage > ODatabaseModelImpl::impl_switchToStorage_throw( const Reference< XStorage >& _rxNewRootStorage )
1320 {
1321     // stop listening for modifications at the old storage
1322     lcl_modifyListening( *this, m_xDocumentStorage.getTyped(), m_pStorageModifyListener, m_aMutexFacade, false );
1323 
1324     // set new storage
1325     m_xDocumentStorage.reset( _rxNewRootStorage, SharedStorage::TakeOwnership );
1326 
1327     // start listening for modifications
1328     lcl_modifyListening( *this, m_xDocumentStorage.getTyped(), m_pStorageModifyListener, m_aMutexFacade, true );
1329 
1330     // forward new storage to Basic and Dialog library containers
1331     lcl_rebaseScriptStorage_throw( m_xBasicLibraries, m_xDocumentStorage.getTyped() );
1332     lcl_rebaseScriptStorage_throw( m_xDialogLibraries, m_xDocumentStorage.getTyped() );
1333 
1334     m_bReadOnly = !tools::stor::storageIsWritable_nothrow( m_xDocumentStorage.getTyped() );
1335     // TODO: our data source, if it exists, must broadcast the change of its ReadOnly property
1336 
1337     return m_xDocumentStorage.getTyped();
1338 }
1339 
1340 // -----------------------------------------------------------------------------
1341 void ODatabaseModelImpl::impl_switchToLogicalURL( const ::rtl::OUString& i_rDocumentURL )
1342 {
1343     if ( i_rDocumentURL == m_sDocumentURL )
1344         return;
1345 
1346     const ::rtl::OUString sOldURL( m_sDocumentURL );
1347     // update our name, if necessary
1348     if  (   ( m_sName == m_sDocumentURL )   // our name is our old URL
1349         ||  ( !m_sName.getLength() )        // we do not have a name, yet (i.e. are not registered at the database context)
1350         )
1351     {
1352 	    INetURLObject aURL( i_rDocumentURL );
1353 	    if ( aURL.GetProtocol() != INET_PROT_NOT_VALID )
1354         {
1355 		    m_sName = i_rDocumentURL;
1356             // TODO: our data source must broadcast the change of the Name property
1357         }
1358     }
1359 
1360     // remember URL
1361     m_sDocumentURL = i_rDocumentURL;
1362 
1363     // update our location, if necessary
1364     if  ( m_sDocFileLocation.getLength() == 0 )
1365         m_sDocFileLocation = m_sDocumentURL;
1366 
1367     // register at the database context, or change registration
1368     if ( m_pDBContext )
1369     {
1370 	    if ( sOldURL.getLength() )
1371             m_pDBContext->databaseDocumentURLChange( sOldURL, m_sDocumentURL );
1372         else
1373             m_pDBContext->registerDatabaseDocument( *this );
1374     }
1375 }
1376 
1377 // -----------------------------------------------------------------------------
1378 ::rtl::OUString ODatabaseModelImpl::getObjectContainerStorageName( const ObjectType _eType )
1379 {
1380     return lcl_getContainerStorageName_throw( _eType );
1381 }
1382 
1383 // -----------------------------------------------------------------------------
1384 sal_Int16 ODatabaseModelImpl::getCurrentMacroExecMode() const
1385 {
1386     sal_Int16 nCurrentMode = MacroExecMode::NEVER_EXECUTE;
1387     try
1388     {
1389         nCurrentMode = m_aMediaDescriptor.getOrDefault( "MacroExecutionMode", nCurrentMode );
1390     }
1391     catch( const Exception& )
1392     {
1393     	DBG_UNHANDLED_EXCEPTION();
1394     }
1395     return nCurrentMode;
1396 }
1397 
1398 // -----------------------------------------------------------------------------
1399 sal_Bool ODatabaseModelImpl::setCurrentMacroExecMode( sal_uInt16 nMacroMode )
1400 {
1401     m_aMediaDescriptor.put( "MacroExecutionMode", nMacroMode );
1402     return sal_True;
1403 }
1404 
1405 // -----------------------------------------------------------------------------
1406 ::rtl::OUString ODatabaseModelImpl::getDocumentLocation() const
1407 {
1408     return getURL();
1409     // formerly, we returned getDocFileLocation here, which is the location of the file from which we
1410     // recovered the "real" document.
1411     // However, during CWS autorecovery evolving, we clarified (with MAV/MT) the role of XModel::getURL and
1412     // XStorable::getLocation. In this course, we agreed that for a macro security check, the *document URL*
1413     // (not the recovery file URL) is to be used: The recovery file lies in the backup folder, and by definition,
1414     // this folder is considered to be secure. So, the document URL needs to be used to decide about the security.
1415 }
1416 
1417 // -----------------------------------------------------------------------------
1418 Reference< XStorage > ODatabaseModelImpl::getZipStorageToSign()
1419 {
1420     // we do not support signing the scripting storages, so we're allowed to
1421     // return <NULL/> here.
1422     return Reference< XStorage >();
1423 }
1424 
1425 // -----------------------------------------------------------------------------
1426 ODatabaseModelImpl::EmbeddedMacros ODatabaseModelImpl::determineEmbeddedMacros()
1427 {
1428     if ( !m_aEmbeddedMacros )
1429     {
1430         if ( ::sfx2::DocumentMacroMode::storageHasMacros( const_cast< ODatabaseModelImpl* >( this )->getOrCreateRootStorage() ) )
1431         {
1432             m_aEmbeddedMacros.reset( eDocumentWideMacros );
1433         }
1434         else if (   lcl_hasObjectsWithMacros_nothrow( const_cast< ODatabaseModelImpl& >( *this ), E_FORM )
1435                 ||  lcl_hasObjectsWithMacros_nothrow( const_cast< ODatabaseModelImpl& >( *this ), E_REPORT )
1436                 )
1437         {
1438             m_aEmbeddedMacros.reset( eSubDocumentMacros );
1439         }
1440         else
1441         {
1442             m_aEmbeddedMacros.reset( eNoMacros );
1443         }
1444     }
1445     return *m_aEmbeddedMacros;
1446 }
1447 
1448 // -----------------------------------------------------------------------------
1449 sal_Bool ODatabaseModelImpl::documentStorageHasMacros() const
1450 {
1451     const_cast< ODatabaseModelImpl* >( this )->determineEmbeddedMacros();
1452     return ( *m_aEmbeddedMacros != eNoMacros );
1453 }
1454 
1455 // -----------------------------------------------------------------------------
1456 Reference< XEmbeddedScripts > ODatabaseModelImpl::getEmbeddedDocumentScripts() const
1457 {
1458     return Reference< XEmbeddedScripts >( getModel_noCreate(), UNO_QUERY );
1459 }
1460 
1461 // -----------------------------------------------------------------------------
1462 sal_Int16 ODatabaseModelImpl::getScriptingSignatureState()
1463 {
1464     // no support for signatures at the moment
1465     return SIGNATURESTATE_NOSIGNATURES;
1466 }
1467 
1468 // -----------------------------------------------------------------------------
1469 sal_Bool ODatabaseModelImpl::hasTrustedScriptingSignature( sal_Bool /*bAllowUIToAddAuthor*/ )
1470 {
1471     // no support for signatures at the moment
1472     return sal_False;
1473 }
1474 
1475 // -----------------------------------------------------------------------------
1476 void ODatabaseModelImpl::showBrokenSignatureWarning( const Reference< XInteractionHandler >& /*_rxInteraction*/ ) const
1477 {
1478     OSL_ENSURE( false, "ODatabaseModelImpl::showBrokenSignatureWarning: signatures can't be broken - we do not support them!" );
1479 }
1480 
1481 // -----------------------------------------------------------------------------
1482 void ODatabaseModelImpl::storageIsModified()
1483 {
1484     setModified( sal_True );
1485 }
1486 
1487 // -----------------------------------------------------------------------------
1488 ModelDependentComponent::ModelDependentComponent( const ::rtl::Reference< ODatabaseModelImpl >& _model )
1489     :m_pImpl( _model )
1490     ,m_aMutex( _model->getSharedMutex() )
1491 {
1492 }
1493 
1494 // -----------------------------------------------------------------------------
1495 ModelDependentComponent::~ModelDependentComponent()
1496 {
1497 }
1498 
1499 //........................................................................
1500 }	// namespace dbaccess
1501 //........................................................................
1502 
1503