LCOV - code coverage report
Current view: top level - dbaccess/source/core/dataaccess - databasecontext.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 287 328 87.5 %
Date: 2015-06-13 12:38:46 Functions: 51 54 94.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <config_features.h>
      21             : 
      22             : #include "apitools.hxx"
      23             : #include "core_resource.hrc"
      24             : #include "core_resource.hxx"
      25             : #include "databasecontext.hxx"
      26             : #include "databasedocument.hxx"
      27             : #include "databaseregistrations.hxx"
      28             : #include "datasource.hxx"
      29             : #include "dbastrings.hrc"
      30             : #include "module_dba.hxx"
      31             : 
      32             : #include <com/sun/star/beans/NamedValue.hpp>
      33             : #include <com/sun/star/beans/PropertyAttribute.hpp>
      34             : #include <com/sun/star/beans/XPropertySet.hpp>
      35             : #include <com/sun/star/document/MacroExecMode.hpp>
      36             : #include <com/sun/star/document/XFilter.hpp>
      37             : #include <com/sun/star/document/XImporter.hpp>
      38             : #include <com/sun/star/frame/Desktop.hpp>
      39             : #include <com/sun/star/frame/XModel.hpp>
      40             : #include <com/sun/star/frame/XModel2.hpp>
      41             : #include <com/sun/star/frame/XTerminateListener.hpp>
      42             : #include <com/sun/star/lang/DisposedException.hpp>
      43             : #include <com/sun/star/registry/InvalidRegistryException.hpp>
      44             : #include <com/sun/star/sdbc/XDataSource.hpp>
      45             : #include <com/sun/star/task/InteractionClassification.hpp>
      46             : #include <com/sun/star/ucb/InteractiveIOException.hpp>
      47             : #include <com/sun/star/ucb/IOErrorCode.hpp>
      48             : #include <com/sun/star/task/InteractionHandler.hpp>
      49             : #include <com/sun/star/util/XCloseable.hpp>
      50             : 
      51             : #include <basic/basmgr.hxx>
      52             : #include <comphelper/enumhelper.hxx>
      53             : #include <comphelper/evtlistenerhlp.hxx>
      54             : #include <comphelper/namedvaluecollection.hxx>
      55             : #include <comphelper/processfactory.hxx>
      56             : #include <comphelper/sequence.hxx>
      57             : #include <cppuhelper/implbase1.hxx>
      58             : #include <cppuhelper/supportsservice.hxx>
      59             : #include <cppuhelper/typeprovider.hxx>
      60             : #include <cppuhelper/exc_hlp.hxx>
      61             : #include <svl/filenotation.hxx>
      62             : #include <tools/debug.hxx>
      63             : #include <tools/diagnose_ex.h>
      64             : #include <tools/urlobj.hxx>
      65             : #include <ucbhelper/content.hxx>
      66             : #include <unotools/confignode.hxx>
      67             : #include <unotools/pathoptions.hxx>
      68             : #include <unotools/sharedunocomponent.hxx>
      69             : #include <list>
      70             : 
      71             : using namespace ::com::sun::star::sdbc;
      72             : using namespace ::com::sun::star::sdb;
      73             : using namespace ::com::sun::star::beans;
      74             : using namespace ::com::sun::star::uno;
      75             : using namespace ::com::sun::star::document;
      76             : using namespace ::com::sun::star::frame;
      77             : using namespace ::com::sun::star::lang;
      78             : using namespace ::com::sun::star::container;
      79             : using namespace ::com::sun::star::util;
      80             : using namespace ::com::sun::star::registry;
      81             : using namespace ::com::sun::star;
      82             : using namespace ::cppu;
      83             : using namespace ::osl;
      84             : using namespace ::utl;
      85             : 
      86             : using ::com::sun::star::task::InteractionClassification_ERROR;
      87             : using ::com::sun::star::ucb::IOErrorCode_NO_FILE;
      88             : using ::com::sun::star::ucb::InteractiveIOException;
      89             : using ::com::sun::star::ucb::IOErrorCode_NOT_EXISTING;
      90             : using ::com::sun::star::ucb::IOErrorCode_NOT_EXISTING_PATH;
      91             : 
      92             : namespace dbaccess
      93             : {
      94             : 
      95             :         typedef ::cppu::WeakImplHelper1 <   XTerminateListener
      96             :                                         >   DatabaseDocumentLoader_Base;
      97          32 :         class DatabaseDocumentLoader : public DatabaseDocumentLoader_Base
      98             :         {
      99             :         private:
     100             :             Reference< XDesktop2 >               m_xDesktop;
     101             :             ::std::list< const ODatabaseModelImpl* >  m_aDatabaseDocuments;
     102             : 
     103             :         public:
     104             :             DatabaseDocumentLoader( const Reference<XComponentContext> & rxContext);
     105             : 
     106         111 :             inline void append(const ODatabaseModelImpl& _rModelImpl )
     107             :             {
     108         111 :                 m_aDatabaseDocuments.push_back(&_rModelImpl);
     109         111 :             }
     110         110 :             inline void remove(const ODatabaseModelImpl& _rModelImpl) { m_aDatabaseDocuments.remove(&_rModelImpl); }
     111             : 
     112             :         private:
     113             :             // XTerminateListener
     114             :             virtual void SAL_CALL queryTermination( const lang::EventObject& Event ) throw (TerminationVetoException, RuntimeException, std::exception) SAL_OVERRIDE;
     115             :             virtual void SAL_CALL notifyTermination( const lang::EventObject& Event ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
     116             :             // XEventListener
     117             :             virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
     118             :         };
     119             : 
     120          20 :         DatabaseDocumentLoader::DatabaseDocumentLoader( const Reference<XComponentContext> & rxContext )
     121             :         {
     122          20 :             acquire();
     123             :             try
     124             :             {
     125          20 :                 m_xDesktop.set( Desktop::create(rxContext) );
     126          20 :                 m_xDesktop->addTerminateListener( this );
     127             :             }
     128           0 :             catch( const Exception& )
     129             :             {
     130             :                 DBG_UNHANDLED_EXCEPTION();
     131             :             }
     132          20 :         }
     133             : 
     134             :         struct TerminateFunctor : ::std::unary_function<ODatabaseModelImpl* , void>
     135             :         {
     136           8 :             void operator()( const ODatabaseModelImpl* _pModelImpl ) const
     137             :             {
     138             :                 try
     139             :                 {
     140           9 :                     const Reference< XModel2> xModel( _pModelImpl ->getModel_noCreate(),UNO_QUERY_THROW );
     141           7 :                     if ( !xModel->getControllers()->hasMoreElements() )
     142             :                     {
     143           7 :                         Reference<util::XCloseable> xCloseable(xModel,UNO_QUERY_THROW);
     144           7 :                         xCloseable->close(sal_False);
     145           7 :                     }
     146             :                 }
     147           0 :                 catch(const CloseVetoException&)
     148             :                 {
     149           0 :                     throw TerminationVetoException();
     150             :                 }
     151           7 :             }
     152             :         };
     153             : 
     154          10 :         void SAL_CALL DatabaseDocumentLoader::queryTermination( const lang::EventObject& /*Event*/ ) throw (TerminationVetoException, RuntimeException, std::exception)
     155             :         {
     156          10 :             ::std::list< const ODatabaseModelImpl* > aCopy(m_aDatabaseDocuments);
     157          11 :             ::std::for_each(aCopy.begin(),aCopy.end(),TerminateFunctor());
     158           9 :         }
     159             : 
     160           9 :         void SAL_CALL DatabaseDocumentLoader::notifyTermination( const lang::EventObject& /*Event*/ ) throw (RuntimeException, std::exception)
     161             :         {
     162           9 :         }
     163             : 
     164          18 :         void SAL_CALL DatabaseDocumentLoader::disposing( const lang::EventObject& /*Source*/ ) throw (RuntimeException, std::exception)
     165             :         {
     166          18 :         }
     167             : 
     168             : // ODatabaseContext
     169             : 
     170          20 : ODatabaseContext::ODatabaseContext( const Reference< XComponentContext >& _rxContext )
     171             :     :DatabaseAccessContext_Base(m_aMutex)
     172             :     ,m_aContext( _rxContext )
     173          20 :     ,m_aContainerListeners(m_aMutex)
     174             : {
     175          20 :     m_pDatabaseDocumentLoader = new DatabaseDocumentLoader( _rxContext );
     176             : 
     177             : #if HAVE_FEATURE_SCRIPTING
     178          20 :     ::basic::BasicManagerRepository::registerCreationListener( *this );
     179             : #endif
     180             : 
     181          20 :     osl_atomic_increment( &m_refCount );
     182             :     {
     183          20 :         m_xDBRegistrationAggregate.set( createDataSourceRegistrations( m_aContext ), UNO_SET_THROW );
     184          20 :         m_xDatabaseRegistrations.set( m_xDBRegistrationAggregate, UNO_QUERY_THROW );
     185             : 
     186          20 :         m_xDBRegistrationAggregate->setDelegator( *this );
     187             :     }
     188          20 :     osl_atomic_decrement( &m_refCount );
     189          20 : }
     190             : 
     191          48 : ODatabaseContext::~ODatabaseContext()
     192             : {
     193             : #if HAVE_FEATURE_SCRIPTING
     194          16 :     ::basic::BasicManagerRepository::revokeCreationListener( *this );
     195             : #endif
     196             : 
     197          16 :     if ( m_pDatabaseDocumentLoader )
     198          16 :         m_pDatabaseDocumentLoader->release();
     199             : 
     200          16 :     m_xDBRegistrationAggregate->setDelegator( NULL );
     201          16 :     m_xDBRegistrationAggregate.clear();
     202          16 :     m_xDatabaseRegistrations.clear();
     203          32 : }
     204             : 
     205             : // Helper
     206          21 : OUString ODatabaseContext::getImplementationName_static() throw( RuntimeException )
     207             : {
     208          21 :     return OUString("com.sun.star.comp.dba.ODatabaseContext");
     209             : }
     210             : 
     211          20 : Reference< XInterface > ODatabaseContext::Create(const Reference< XComponentContext >& _rxContext)
     212             : {
     213          20 :     return *( new ODatabaseContext( _rxContext ) );
     214             : }
     215             : 
     216          21 : Sequence< OUString > ODatabaseContext::getSupportedServiceNames_static() throw( RuntimeException )
     217             : {
     218          21 :     Sequence< OUString > aSNS( 1 );
     219          21 :     aSNS[0] = "com.sun.star.sdb.DatabaseContext";
     220          21 :     return aSNS;
     221             : }
     222             : 
     223             : // XServiceInfo
     224           1 : OUString ODatabaseContext::getImplementationName(  ) throw(RuntimeException, std::exception)
     225             : {
     226           1 :     return getImplementationName_static();
     227             : }
     228             : 
     229           0 : sal_Bool ODatabaseContext::supportsService( const OUString& _rServiceName ) throw (RuntimeException, std::exception)
     230             : {
     231           0 :     return cppu::supportsService(this, _rServiceName);
     232             : }
     233             : 
     234           1 : Sequence< OUString > ODatabaseContext::getSupportedServiceNames(  ) throw (RuntimeException, std::exception)
     235             : {
     236           1 :     return getSupportedServiceNames_static();
     237             : }
     238             : 
     239          94 : Reference< XInterface > ODatabaseContext::impl_createNewDataSource()
     240             : {
     241          94 :     ::rtl::Reference<ODatabaseModelImpl> pImpl( new ODatabaseModelImpl( m_aContext, *this ) );
     242         188 :     Reference< XDataSource > xDataSource( pImpl->getOrCreateDataSource() );
     243             : 
     244         188 :     return xDataSource.get();
     245             : }
     246             : 
     247          86 : Reference< XInterface > SAL_CALL ODatabaseContext::createInstance(  ) throw (Exception, RuntimeException, std::exception)
     248             : {
     249             :     // for convenience of the API user, we ensure the document is fully initialized (effectively: XLoadable::initNew
     250             :     // has been called at the DatabaseDocument).
     251          86 :     return impl_createNewDataSource();
     252             : }
     253             : 
     254           8 : Reference< XInterface > SAL_CALL ODatabaseContext::createInstanceWithArguments( const Sequence< Any >& _rArguments ) throw (Exception, RuntimeException, std::exception)
     255             : {
     256           8 :     ::comphelper::NamedValueCollection aArgs( _rArguments );
     257          16 :     OUString sURL = aArgs.getOrDefault( OUString(INFO_POOLURL), OUString() );
     258             : 
     259           8 :     Reference< XInterface > xDataSource;
     260           8 :     if ( !sURL.isEmpty() )
     261           7 :         xDataSource = getObject( sURL );
     262             : 
     263           8 :     if ( !xDataSource.is() )
     264           8 :         xDataSource = impl_createNewDataSource();
     265             : 
     266          16 :     return xDataSource;
     267             : }
     268             : 
     269             : // DatabaseAccessContext_Base
     270          19 : void ODatabaseContext::disposing()
     271             : {
     272             :     // notify our listener
     273          19 :     com::sun::star::lang::EventObject aDisposeEvent(static_cast< XContainer* >(this));
     274          19 :     m_aContainerListeners.disposeAndClear(aDisposeEvent);
     275             : 
     276             :     // dispose the data sources
     277             :     // disposing seems to remove elements, so work on copy for valid iterators
     278          38 :     ObjectCache objCopy(m_aDatabaseObjects);
     279          19 :     ObjectCache::iterator const aEnd = objCopy.end();
     280          33 :     for (   ObjectCache::iterator aIter = objCopy.begin();
     281             :             aIter != aEnd;
     282             :             ++aIter
     283             :         )
     284             :     {
     285          14 :         rtl::Reference< ODatabaseModelImpl > obj(aIter->second);
     286             :             // make sure obj is acquired and does not delete itself from within
     287             :             // dispose()
     288          14 :         obj->dispose();
     289          14 :     }
     290          38 :     m_aDatabaseObjects.clear();
     291          19 : }
     292             : 
     293             : // XNamingService
     294           6 : Reference< XInterface >  ODatabaseContext::getRegisteredObject(const OUString& _rName) throw( Exception, RuntimeException, std::exception )
     295             : {
     296           6 :     MutexGuard aGuard(m_aMutex);
     297           6 :     ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed);
     298             : 
     299           8 :     OUString sURL( getDatabaseLocation( _rName ) );
     300             : 
     301           2 :     if ( sURL.isEmpty() )
     302             :         // there is a registration for this name, but no URL
     303           0 :         throw IllegalArgumentException();
     304             : 
     305             :     // check if URL is already loaded
     306           4 :     Reference< XInterface > xExistent = getObject( sURL );
     307           2 :     if ( xExistent.is() )
     308           1 :         return xExistent;
     309             : 
     310           7 :     return loadObjectFromURL( _rName, sURL );
     311             : }
     312             : 
     313          10 : Reference< XInterface > ODatabaseContext::loadObjectFromURL(const OUString& _rName,const OUString& _sURL)
     314             : {
     315          10 :     INetURLObject aURL( _sURL );
     316             : 
     317          10 :     if ( aURL.GetProtocol() == INetProtocol::NotValid )
     318           1 :         throw NoSuchElementException( _rName, *this );
     319             : 
     320           9 :     bool bEmbeddedDataSource = _sURL.startsWithIgnoreAsciiCase("vnd.sun.star.pkg:");
     321             :     try
     322             :     {
     323           9 :         if (!bEmbeddedDataSource)
     324             :         {
     325           8 :             ::ucbhelper::Content aContent( _sURL, NULL, comphelper::getProcessComponentContext() );
     326           8 :             if ( !aContent.isDocument() )
     327             :                 throw InteractiveIOException(
     328             :                     _sURL, *this, InteractionClassification_ERROR, IOErrorCode_NO_FILE
     329           0 :                 );
     330             :         }
     331             :     }
     332           0 :     catch ( const InteractiveIOException& e )
     333             :     {
     334           0 :         if  (   ( e.Code == IOErrorCode_NO_FILE )
     335           0 :             ||  ( e.Code == IOErrorCode_NOT_EXISTING )
     336           0 :             ||  ( e.Code == IOErrorCode_NOT_EXISTING_PATH )
     337             :             )
     338             :         {
     339             :             // #i40463# #i39187#
     340           0 :             OUString sErrorMessage( DBACORE_RESSTRING( RID_STR_FILE_DOES_NOT_EXIST ) );
     341           0 :             ::svt::OFileNotation aTransformer( _sURL );
     342             : 
     343           0 :             SQLException aError;
     344           0 :             aError.Message = sErrorMessage.replaceAll( "$file$", aTransformer.get( ::svt::OFileNotation::N_SYSTEM ) );
     345             : 
     346           0 :             throw WrappedTargetException( _sURL, *this, makeAny( aError ) );
     347             :         }
     348           0 :         throw WrappedTargetException( _sURL, *this, ::cppu::getCaughtException() );
     349             :     }
     350           0 :     catch( const Exception& )
     351             :     {
     352           0 :         throw WrappedTargetException( _sURL, *this, ::cppu::getCaughtException() );
     353             :     }
     354             : 
     355             :     OSL_ENSURE( m_aDatabaseObjects.find( _sURL ) == m_aDatabaseObjects.end(),
     356             :         "ODatabaseContext::loadObjectFromURL: not intended for already-cached objects!" );
     357             : 
     358          18 :     ::rtl::Reference< ODatabaseModelImpl > pModelImpl;
     359             :     {
     360           9 :         pModelImpl.set( new ODatabaseModelImpl( _rName, m_aContext, *this ) );
     361             : 
     362           9 :         Reference< XModel > xModel( pModelImpl->createNewModel_deliverOwnership( false ), UNO_SET_THROW );
     363          18 :         Reference< XLoadable > xLoad( xModel, UNO_QUERY_THROW );
     364             : 
     365          18 :         ::comphelper::NamedValueCollection aArgs;
     366           9 :         aArgs.put( "URL", _sURL );
     367           9 :         aArgs.put( "MacroExecutionMode", MacroExecMode::USE_CONFIG );
     368           9 :         aArgs.put( "InteractionHandler", task::InteractionHandler::createWithParent(m_aContext, 0) );
     369           9 :         if (bEmbeddedDataSource)
     370             :         {
     371             :             // In this case the host contains the real path, and the path is the embedded stream name.
     372           1 :             OUString sBaseURI = aURL.GetHost(INetURLObject::DECODE_WITH_CHARSET) + aURL.GetURLPath(INetURLObject::DECODE_WITH_CHARSET);
     373           1 :             aArgs.put("BaseURI", sBaseURI);
     374             :         }
     375             : 
     376          18 :         Sequence< PropertyValue > aResource( aArgs.getPropertyValues() );
     377           9 :         xLoad->load( aResource );
     378           9 :         xModel->attachResource( _sURL, aResource );
     379             : 
     380          18 :         ::utl::CloseableComponent aEnsureClose( xModel );
     381             :     }
     382             : 
     383           9 :     setTransientProperties( _sURL, *pModelImpl );
     384             : 
     385          19 :     return pModelImpl->getOrCreateDataSource().get();
     386             : }
     387             : 
     388         111 : void ODatabaseContext::appendAtTerminateListener(const ODatabaseModelImpl& _rDataSourceModel)
     389             : {
     390         111 :     m_pDatabaseDocumentLoader->append(_rDataSourceModel);
     391         111 : }
     392             : 
     393         110 : void ODatabaseContext::removeFromTerminateListener(const ODatabaseModelImpl& _rDataSourceModel)
     394             : {
     395         110 :     m_pDatabaseDocumentLoader->remove(_rDataSourceModel);
     396         110 : }
     397             : 
     398         116 : void ODatabaseContext::setTransientProperties(const OUString& _sURL, ODatabaseModelImpl& _rDataSourceModel )
     399             : {
     400         116 :     if ( m_aDatasourceProperties.end() == m_aDatasourceProperties.find(_sURL) )
     401         160 :         return;
     402             :     try
     403             :     {
     404          72 :         OUString sAuthFailedPassword;
     405         144 :         Reference< XPropertySet > xDSProps( _rDataSourceModel.getOrCreateDataSource(), UNO_QUERY_THROW );
     406          72 :         const Sequence< PropertyValue >& rSessionPersistentProps = m_aDatasourceProperties[_sURL];
     407          72 :         const PropertyValue* pProp = rSessionPersistentProps.getConstArray();
     408          72 :         const PropertyValue* pPropsEnd = rSessionPersistentProps.getConstArray() + rSessionPersistentProps.getLength();
     409         216 :         for ( ; pProp != pPropsEnd; ++pProp )
     410             :         {
     411         144 :             if ( pProp->Name == "AuthFailedPassword" )
     412             :             {
     413          72 :                 OSL_VERIFY( pProp->Value >>= sAuthFailedPassword );
     414             :             }
     415             :             else
     416             :             {
     417          72 :                 xDSProps->setPropertyValue( pProp->Name, pProp->Value );
     418             :             }
     419             :         }
     420             : 
     421         144 :         _rDataSourceModel.m_sFailedPassword = sAuthFailedPassword;
     422             :     }
     423           0 :     catch( const Exception& )
     424             :     {
     425             :         DBG_UNHANDLED_EXCEPTION();
     426             :     }
     427             : }
     428             : 
     429          88 : void ODatabaseContext::registerObject(const OUString& _rName, const Reference< XInterface > & _rxObject) throw( Exception, RuntimeException, std::exception )
     430             : {
     431          88 :     MutexGuard aGuard(m_aMutex);
     432          88 :     ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed);
     433             : 
     434          88 :     if ( _rName.isEmpty() )
     435           0 :         throw IllegalArgumentException( OUString(), *this, 1 );
     436             : 
     437         176 :     Reference< XDocumentDataSource > xDocDataSource( _rxObject, UNO_QUERY );
     438         176 :     Reference< XModel > xModel( xDocDataSource.is() ? xDocDataSource->getDatabaseDocument() : Reference< XOfficeDatabaseDocument >(), UNO_QUERY );
     439          88 :     if ( !xModel.is() )
     440           0 :         throw IllegalArgumentException( OUString(), *this, 2 );
     441             : 
     442         176 :     OUString sURL = xModel->getURL();
     443          88 :     if ( sURL.isEmpty() )
     444           0 :         throw IllegalArgumentException( DBACORE_RESSTRING( RID_STR_DATASOURCE_NOT_STORED ), *this, 2 );
     445             : 
     446          88 :     registerDatabaseLocation( _rName, sURL );
     447             : 
     448          88 :     ODatabaseSource::setName( xDocDataSource, _rName, ODatabaseSource::DBContextAccess() );
     449             : 
     450             :     // notify our container listeners
     451         176 :     ContainerEvent aEvent(static_cast<XContainer*>(this), makeAny(_rName), makeAny(_rxObject), Any());
     452         176 :     m_aContainerListeners.notifyEach( &XContainerListener::elementInserted, aEvent );
     453          88 : }
     454             : 
     455         110 : void ODatabaseContext::storeTransientProperties( ODatabaseModelImpl& _rModelImpl)
     456             : {
     457         110 :     Reference< XPropertySet > xSource( _rModelImpl.getOrCreateDataSource(), UNO_QUERY );
     458         220 :     ::comphelper::NamedValueCollection aRememberProps;
     459             : 
     460             :     try
     461             :     {
     462             :         // get the info about the properties, check which ones are transient and not readonly
     463         110 :         Reference< XPropertySetInfo > xSetInfo;
     464         110 :         if (xSource.is())
     465         110 :             xSetInfo = xSource->getPropertySetInfo();
     466         220 :         Sequence< Property > aProperties;
     467         110 :         if (xSetInfo.is())
     468         110 :             aProperties = xSetInfo->getProperties();
     469             : 
     470         110 :         if (aProperties.getLength())
     471             :         {
     472         110 :             const Property* pProperties = aProperties.getConstArray();
     473        1540 :             for ( sal_Int32 i=0; i<aProperties.getLength(); ++i, ++pProperties )
     474             :             {
     475        1430 :                 if  (   ( ( pProperties->Attributes & PropertyAttribute::TRANSIENT) != 0 )
     476         220 :                     &&  ( ( pProperties->Attributes & PropertyAttribute::READONLY) == 0 )
     477             :                     )
     478             :                 {
     479             :                     // found such a property
     480         110 :                     aRememberProps.put( pProperties->Name, xSource->getPropertyValue( pProperties->Name ) );
     481             :                 }
     482             :             }
     483         110 :         }
     484             :     }
     485           0 :     catch ( const Exception& )
     486             :     {
     487             :         DBG_UNHANDLED_EXCEPTION();
     488             :     }
     489             : 
     490             :     // additionally, remember the "failed password", which is not available as property
     491             :     // #i86178#
     492         110 :     aRememberProps.put( "AuthFailedPassword", _rModelImpl.m_sFailedPassword );
     493             : 
     494         220 :     OUString sDocumentURL( _rModelImpl.getURL() );
     495         110 :     if ( m_aDatabaseObjects.find( sDocumentURL ) != m_aDatabaseObjects.end() )
     496             :     {
     497          96 :         m_aDatasourceProperties[ sDocumentURL ] = aRememberProps.getPropertyValues();
     498             :     }
     499          14 :     else if ( m_aDatabaseObjects.find( _rModelImpl.m_sName ) != m_aDatabaseObjects.end() )
     500             :     {
     501             :         OSL_FAIL( "ODatabaseContext::storeTransientProperties: a database document register by name? This shouldn't happen anymore!" );
     502             :             // all the code should have been changed so that registration is by URL only
     503           0 :         m_aDatasourceProperties[ _rModelImpl.m_sName ] = aRememberProps.getPropertyValues();
     504             :     }
     505             :     else
     506             :     {
     507             :         OSL_ENSURE(  sDocumentURL.isEmpty()  &&  _rModelImpl.m_sName.isEmpty() ,
     508             :             "ODatabaseContext::storeTransientProperties: a non-empty data source which I do not know?!" );
     509         110 :     }
     510         110 : }
     511             : 
     512           1 : void SAL_CALL ODatabaseContext::addContainerListener( const Reference< XContainerListener >& _rxListener ) throw(RuntimeException, std::exception)
     513             : {
     514           1 :     m_aContainerListeners.addInterface(_rxListener);
     515           1 : }
     516             : 
     517           1 : void SAL_CALL ODatabaseContext::removeContainerListener( const Reference< XContainerListener >& _rxListener ) throw(RuntimeException, std::exception)
     518             : {
     519           1 :     m_aContainerListeners.removeInterface(_rxListener);
     520           1 : }
     521             : 
     522         166 : void ODatabaseContext::revokeObject(const OUString& _rName) throw( Exception, RuntimeException, std::exception )
     523             : {
     524         166 :     ClearableMutexGuard aGuard(m_aMutex);
     525         166 :     ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed);
     526             : 
     527         250 :     OUString sURL = getDatabaseLocation( _rName );
     528             : 
     529          84 :     revokeDatabaseLocation( _rName );
     530             :         // will throw if something goes wrong
     531             : 
     532          84 :     if ( m_aDatabaseObjects.find( _rName ) != m_aDatabaseObjects.end() )
     533             :     {
     534           0 :         m_aDatasourceProperties[ sURL ] = m_aDatasourceProperties[ _rName ];
     535             :     }
     536             : 
     537             :     // check if URL is already loaded
     538          84 :     ObjectCache::iterator aExistent = m_aDatabaseObjects.find( sURL );
     539          84 :     if ( aExistent != m_aDatabaseObjects.end() )
     540          11 :         m_aDatabaseObjects.erase( aExistent );
     541             : 
     542             :     // notify our container listeners
     543         168 :     ContainerEvent aEvent( *this, makeAny( _rName ), Any(), Any() );
     544          84 :     aGuard.clear();
     545         250 :     m_aContainerListeners.notifyEach( &XContainerListener::elementRemoved, aEvent );
     546          84 : }
     547             : 
     548          80 : sal_Bool SAL_CALL ODatabaseContext::hasRegisteredDatabase( const OUString& _Name ) throw (IllegalArgumentException, RuntimeException, std::exception)
     549             : {
     550          80 :     return m_xDatabaseRegistrations->hasRegisteredDatabase( _Name );
     551             : }
     552             : 
     553           4 : Sequence< OUString > SAL_CALL ODatabaseContext::getRegistrationNames() throw (RuntimeException, std::exception)
     554             : {
     555           4 :     return m_xDatabaseRegistrations->getRegistrationNames();
     556             : }
     557             : 
     558         237 : OUString SAL_CALL ODatabaseContext::getDatabaseLocation( const OUString& _Name ) throw (IllegalArgumentException, NoSuchElementException, RuntimeException, std::exception)
     559             : {
     560         237 :     return m_xDatabaseRegistrations->getDatabaseLocation( _Name );
     561             : }
     562             : 
     563          88 : void SAL_CALL ODatabaseContext::registerDatabaseLocation( const OUString& _Name, const OUString& _Location ) throw (IllegalArgumentException, ElementExistException, RuntimeException, std::exception)
     564             : {
     565          88 :     m_xDatabaseRegistrations->registerDatabaseLocation( _Name, _Location );
     566          88 : }
     567             : 
     568          84 : void SAL_CALL ODatabaseContext::revokeDatabaseLocation( const OUString& _Name ) throw (IllegalArgumentException, NoSuchElementException, IllegalAccessException, RuntimeException, std::exception)
     569             : {
     570          84 :     m_xDatabaseRegistrations->revokeDatabaseLocation( _Name );
     571          84 : }
     572             : 
     573           0 : void SAL_CALL ODatabaseContext::changeDatabaseLocation( const OUString& _Name, const OUString& _NewLocation ) throw (IllegalArgumentException, NoSuchElementException, IllegalAccessException, RuntimeException, std::exception)
     574             : {
     575           0 :     m_xDatabaseRegistrations->changeDatabaseLocation( _Name, _NewLocation );
     576           0 : }
     577             : 
     578           0 : sal_Bool SAL_CALL ODatabaseContext::isDatabaseRegistrationReadOnly( const OUString& _Name ) throw (IllegalArgumentException, NoSuchElementException, RuntimeException, std::exception)
     579             : {
     580           0 :     return m_xDatabaseRegistrations->isDatabaseRegistrationReadOnly( _Name );
     581             : }
     582             : 
     583           3 : void SAL_CALL ODatabaseContext::addDatabaseRegistrationsListener( const Reference< XDatabaseRegistrationsListener >& _Listener ) throw (RuntimeException, std::exception)
     584             : {
     585           3 :     m_xDatabaseRegistrations->addDatabaseRegistrationsListener( _Listener );
     586           3 : }
     587             : 
     588           1 : void SAL_CALL ODatabaseContext::removeDatabaseRegistrationsListener( const Reference< XDatabaseRegistrationsListener >& _Listener ) throw (RuntimeException, std::exception)
     589             : {
     590           1 :     m_xDatabaseRegistrations->removeDatabaseRegistrationsListener( _Listener );
     591           1 : }
     592             : 
     593             : // ::com::sun::star::container::XElementAccess
     594           1 : Type ODatabaseContext::getElementType(  ) throw(RuntimeException, std::exception)
     595             : {
     596           1 :     return cppu::UnoType<XDataSource>::get();
     597             : }
     598             : 
     599           1 : sal_Bool ODatabaseContext::hasElements() throw( RuntimeException, std::exception )
     600             : {
     601           1 :     MutexGuard aGuard(m_aMutex);
     602           1 :     ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed);
     603             : 
     604           1 :     return 0 != getElementNames().getLength();
     605             : }
     606             : 
     607             : // ::com::sun::star::container::XEnumerationAccess
     608           1 : Reference< ::com::sun::star::container::XEnumeration >  ODatabaseContext::createEnumeration() throw( RuntimeException, std::exception )
     609             : {
     610           1 :     MutexGuard aGuard(m_aMutex);
     611           1 :     return new ::comphelper::OEnumerationByName(static_cast<XNameAccess*>(this));
     612             : }
     613             : 
     614             : // ::com::sun::star::container::XNameAccess
     615          69 : Any ODatabaseContext::getByName(const OUString& _rName) throw( NoSuchElementException,
     616             :                                                           WrappedTargetException, RuntimeException, std::exception )
     617             : {
     618          69 :     MutexGuard aGuard(m_aMutex);
     619          69 :     ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed);
     620          69 :     if ( _rName.isEmpty() )
     621           0 :         throw NoSuchElementException(_rName, *this);
     622             : 
     623             :     try
     624             :     {
     625          69 :         Reference< XInterface > xExistent = getObject( _rName );
     626          69 :         if ( xExistent.is() )
     627           2 :             return makeAny( xExistent );
     628             : 
     629             :         // see whether this is an registered name
     630         134 :         OUString sURL;
     631          67 :         if ( hasRegisteredDatabase( _rName ) )
     632             :         {
     633          65 :             sURL = getDatabaseLocation( _rName );
     634             :             // is the object cached under its URL?
     635          65 :             xExistent = getObject( sURL );
     636             :         }
     637             :         else
     638             :             // interpret the name as URL
     639           2 :             sURL = _rName;
     640             : 
     641          67 :         if ( !xExistent.is() )
     642             :             // try to load this as URL
     643           9 :             xExistent = loadObjectFromURL( _rName, sURL );
     644         135 :         return makeAny( xExistent );
     645             :     }
     646           2 :     catch (const NoSuchElementException&)
     647             :     {   // let these exceptions through
     648           1 :         throw;
     649             :     }
     650           0 :     catch (const WrappedTargetException&)
     651             :     {   // let these exceptions through
     652           0 :         throw;
     653             :     }
     654           0 :     catch (const RuntimeException&)
     655             :     {   // let these exceptions through
     656           0 :         throw;
     657             :     }
     658           0 :     catch (const Exception&)
     659             :     {   // exceptions other than the speciafied ones -> wrap
     660           0 :         Any aError = ::cppu::getCaughtException();
     661           0 :         throw WrappedTargetException(_rName, *this, aError );
     662          69 :     }
     663             : }
     664             : 
     665           4 : Sequence< OUString > ODatabaseContext::getElementNames() throw( RuntimeException, std::exception )
     666             : {
     667           4 :     MutexGuard aGuard(m_aMutex);
     668           4 :     ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed);
     669             : 
     670           4 :     return getRegistrationNames();
     671             : }
     672             : 
     673          13 : sal_Bool ODatabaseContext::hasByName(const OUString& _rName) throw( RuntimeException, std::exception )
     674             : {
     675          13 :     MutexGuard aGuard(m_aMutex);
     676          13 :     ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed);
     677             : 
     678          13 :     return hasRegisteredDatabase( _rName );
     679             : }
     680             : 
     681         143 : Reference< XInterface > ODatabaseContext::getObject( const OUString& _rURL )
     682             : {
     683         143 :     ObjectCache::iterator aFind = m_aDatabaseObjects.find( _rURL );
     684         143 :     Reference< XInterface > xExistent;
     685         143 :     if ( aFind != m_aDatabaseObjects.end() )
     686          61 :         xExistent = aFind->second->getOrCreateDataSource();
     687         143 :     return xExistent;
     688             : }
     689             : 
     690         107 : void ODatabaseContext::registerDatabaseDocument( ODatabaseModelImpl& _rModelImpl )
     691             : {
     692         107 :     OUString sURL( _rModelImpl.getURL() );
     693             : #if OSL_DEBUG_LEVEL > 1
     694             :     OSL_TRACE( "DatabaseContext: registering %s", OUStringToOString( sURL, RTL_TEXTENCODING_UTF8 ).getStr() );
     695             : #endif
     696         107 :     if ( m_aDatabaseObjects.find( sURL ) == m_aDatabaseObjects.end() )
     697             :     {
     698         107 :         m_aDatabaseObjects[ sURL ] = &_rModelImpl;
     699         107 :         setTransientProperties( sURL, _rModelImpl );
     700             :     }
     701             :     else
     702         107 :         OSL_FAIL( "ODatabaseContext::registerDatabaseDocument: already have an object registered for this URL!" );
     703         107 : }
     704             : 
     705         106 : void ODatabaseContext::revokeDatabaseDocument( const ODatabaseModelImpl& _rModelImpl )
     706             : {
     707         106 :     OUString sURL( _rModelImpl.getURL() );
     708             : #if OSL_DEBUG_LEVEL > 1
     709             :     OSL_TRACE( "DatabaseContext: deregistering %s", OUStringToOString( sURL, RTL_TEXTENCODING_UTF8 ).getStr() );
     710             : #endif
     711         106 :     m_aDatabaseObjects.erase( sURL );
     712         106 : }
     713             : 
     714           1 : void ODatabaseContext::databaseDocumentURLChange( const OUString& _rOldURL, const OUString& _rNewURL )
     715             : {
     716             : #if OSL_DEBUG_LEVEL > 1
     717             :     OSL_TRACE( "DatabaseContext: changing registration from %s to %s",
     718             :         OUStringToOString( _rOldURL, RTL_TEXTENCODING_UTF8 ).getStr(),
     719             :         OUStringToOString( _rNewURL, RTL_TEXTENCODING_UTF8 ).getStr() );
     720             : #endif
     721           1 :     ObjectCache::iterator oldPos = m_aDatabaseObjects.find( _rOldURL );
     722           1 :     ENSURE_OR_THROW( oldPos != m_aDatabaseObjects.end(), "illegal old database document URL" );
     723           1 :     ObjectCache::iterator newPos = m_aDatabaseObjects.find( _rNewURL );
     724           1 :     ENSURE_OR_THROW( newPos == m_aDatabaseObjects.end(), "illegal new database document URL" );
     725             : 
     726           1 :     m_aDatabaseObjects[ _rNewURL ] = oldPos->second;
     727           1 :     m_aDatabaseObjects.erase( oldPos );
     728           1 : }
     729             : 
     730           8 : sal_Int64 SAL_CALL ODatabaseContext::getSomething( const Sequence< sal_Int8 >& rId ) throw(RuntimeException, std::exception)
     731             : {
     732           8 :     if (rId.getLength() == 16 && 0 == memcmp(getUnoTunnelImplementationId().getConstArray(),  rId.getConstArray(), 16 ) )
     733           8 :         return reinterpret_cast<sal_Int64>(this);
     734             : 
     735           0 :     return 0;
     736             : }
     737             : 
     738          16 : Sequence< sal_Int8 > ODatabaseContext::getUnoTunnelImplementationId()
     739             : {
     740             :     static ::cppu::OImplementationId * pId = 0;
     741          16 :     if (! pId)
     742             :     {
     743           3 :         ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
     744           3 :         if (! pId)
     745             :         {
     746           3 :             static ::cppu::OImplementationId aId;
     747           3 :             pId = &aId;
     748           3 :         }
     749             :     }
     750          16 :     return pId->getImplementationId();
     751             : }
     752             : 
     753          18 : void ODatabaseContext::onBasicManagerCreated( const Reference< XModel >& _rxForDocument, BasicManager& _rBasicManager )
     754             : {
     755             : #if !HAVE_FEATURE_SCRIPTING
     756             :     (void) _rxForDocument;
     757             :     (void) _rBasicManager;
     758             : #else
     759             :     // if it's a database document ...
     760          18 :     Reference< XOfficeDatabaseDocument > xDatabaseDocument( _rxForDocument, UNO_QUERY );
     761             :     // ... or a sub document of a database document ...
     762          18 :     if ( !xDatabaseDocument.is() )
     763             :     {
     764          18 :         Reference< XChild > xDocAsChild( _rxForDocument, UNO_QUERY );
     765          18 :         if ( xDocAsChild.is() )
     766          12 :             xDatabaseDocument.set( xDocAsChild->getParent(), UNO_QUERY );
     767             :     }
     768             : 
     769             :     // ... whose BasicManager has just been created, then add the global DatabaseDocument variable to its scope.
     770          18 :     if ( xDatabaseDocument.is() )
     771           0 :         _rBasicManager.SetGlobalUNOConstant( "ThisDatabaseDocument", makeAny( xDatabaseDocument ) );
     772             : #endif
     773          18 : }
     774             : 
     775             : }   // namespace dbaccess
     776             : 
     777             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11