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