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