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 "querycontainer.hxx"
22 : : #include "dbastrings.hrc"
23 : : #include "query.hxx"
24 : : #include "objectnameapproval.hxx"
25 : : #include "ContainerListener.hxx"
26 : : #include "veto.hxx"
27 : :
28 : : #include <com/sun/star/beans/XPropertySet.hpp>
29 : : #include <com/sun/star/container/XContainer.hpp>
30 : : #include <com/sun/star/sdbc/XConnection.hpp>
31 : : #include <com/sun/star/container/XContainerApproveBroadcaster.hpp>
32 : :
33 : : #include <connectivity/dbexception.hxx>
34 : :
35 : : #include <tools/debug.hxx>
36 : : #include <osl/diagnose.h>
37 : : #include <comphelper/enumhelper.hxx>
38 : : #include <comphelper/uno3.hxx>
39 : : #include <comphelper/property.hxx>
40 : : #include <comphelper/sequence.hxx>
41 : : #include <comphelper/extract.hxx>
42 : : #include <cppuhelper/exc_hlp.hxx>
43 : :
44 : : using namespace dbtools;
45 : : using namespace ::com::sun::star::uno;
46 : : using namespace ::com::sun::star::ucb;
47 : : using namespace ::com::sun::star::lang;
48 : : using namespace ::com::sun::star::beans;
49 : : using namespace ::com::sun::star::sdb;
50 : : using namespace ::com::sun::star::sdbc;
51 : : using namespace ::com::sun::star::sdbcx;
52 : : using namespace ::com::sun::star::container;
53 : : using namespace ::com::sun::star::util;
54 : : using namespace ::osl;
55 : : using namespace ::comphelper;
56 : : using namespace ::cppu;
57 : :
58 : : namespace dbaccess
59 : : {
60 : :
61 : : //==========================================================================
62 : : //= OQueryContainer
63 : : //==========================================================================
64 : : DBG_NAME(OQueryContainer)
65 : :
66 : 56 : OQueryContainer::OQueryContainer(
67 : : const Reference< XNameContainer >& _rxCommandDefinitions
68 : : , const Reference< XConnection >& _rxConn
69 : : , const Reference< XMultiServiceFactory >& _rxORB,
70 : : ::dbtools::IWarningsContainer* _pWarnings)
71 [ + - ]: 56 : :ODefinitionContainer(_rxORB,NULL,TContentPtr(new ODefinitionContainer_Impl))
72 : : ,m_pWarnings( _pWarnings )
73 : : ,m_xCommandDefinitions(_rxCommandDefinitions)
74 [ + - ][ + - ]: 112 : ,m_xConnection(_rxConn)
75 : : {
76 : : DBG_CTOR(OQueryContainer, NULL);
77 : :
78 [ + - ]: 56 : increment(m_refCount);
79 : : {
80 [ + - ]: 56 : m_pCommandsListener = new OContainerListener( *this, m_aMutex );
81 : 56 : m_pCommandsListener->acquire();
82 : :
83 [ + - ]: 56 : Reference< XContainer > xContainer( m_xCommandDefinitions, UNO_QUERY_THROW );
84 [ + - ][ + - ]: 56 : xContainer->addContainerListener( m_pCommandsListener );
[ + - ][ + - ]
85 : :
86 [ + - ]: 56 : Reference< XContainerApproveBroadcaster > xContainerApprove( m_xCommandDefinitions, UNO_QUERY_THROW );
87 [ + - ][ + - ]: 56 : xContainerApprove->addContainerApproveListener( m_pCommandsListener );
[ + - ][ + - ]
88 : :
89 : : // fill my structures
90 [ + - ]: 56 : ODefinitionContainer_Impl& rDefinitions( getDefinitions() );
91 [ + - ][ + - ]: 56 : Sequence< ::rtl::OUString > sDefinitionNames = m_xCommandDefinitions->getElementNames();
92 : 56 : const ::rtl::OUString* pDefinitionName = sDefinitionNames.getConstArray();
93 : 56 : const ::rtl::OUString* pEnd = pDefinitionName + sDefinitionNames.getLength();
94 [ - + ]: 56 : for ( ; pDefinitionName != pEnd; ++pDefinitionName )
95 : : {
96 [ # # ][ # # ]: 0 : rDefinitions.insert( *pDefinitionName, TContentPtr() );
[ # # ]
97 [ # # ][ # # ]: 0 : m_aDocuments.push_back(m_aDocumentMap.insert(Documents::value_type(*pDefinitionName,Documents::mapped_type())).first);
[ # # ][ # # ]
[ # # ][ # # ]
98 [ + - ]: 56 : }
99 : : }
100 [ + - ]: 56 : decrement(m_refCount);
101 : :
102 [ + - ][ + - ]: 56 : setElementApproval( PContainerApprove( new ObjectNameApproval( _rxConn, ObjectNameApproval::TypeQuery ) ) );
[ + - ][ + - ]
[ + - ]
103 : 56 : }
104 : :
105 : 56 : OQueryContainer::~OQueryContainer()
106 : : {
107 : : DBG_DTOR(OQueryContainer, NULL);
108 : : // dispose();
109 : : // maybe we're already disposed, but this should be uncritical
110 [ - + ]: 112 : }
111 : :
112 [ - + ][ # # ]: 1256 : IMPLEMENT_FORWARD_XINTERFACE2( OQueryContainer,ODefinitionContainer,OQueryContainer_Base)
113 : :
114 [ # # ][ # # ]: 0 : IMPLEMENT_FORWARD_XTYPEPROVIDER2( OQueryContainer,ODefinitionContainer,OQueryContainer_Base)
[ # # ]
115 : :
116 : 56 : void OQueryContainer::disposing()
117 : : {
118 [ + - ]: 56 : ODefinitionContainer::disposing();
119 [ + - ]: 56 : MutexGuard aGuard(m_aMutex);
120 [ - + ]: 56 : if ( !m_xCommandDefinitions.is() )
121 : : // already disposed
122 : 56 : return;
123 : :
124 [ + - ]: 56 : if ( m_pCommandsListener )
125 : : {
126 [ + - ]: 56 : Reference< XContainer > xContainer( m_xCommandDefinitions, UNO_QUERY );
127 [ + - ][ + - ]: 56 : xContainer->removeContainerListener( m_pCommandsListener );
[ + - ][ + - ]
128 [ + - ]: 56 : Reference< XContainerApproveBroadcaster > xContainerApprove( m_xCommandDefinitions, UNO_QUERY );
129 [ + - ][ + - ]: 56 : xContainerApprove->removeContainerApproveListener( m_pCommandsListener );
[ + - ][ + - ]
130 : :
131 : 56 : m_pCommandsListener->dispose();
132 : 56 : m_pCommandsListener->release();
133 : 56 : m_pCommandsListener = NULL;
134 : : }
135 : :
136 [ + - ]: 56 : m_xCommandDefinitions = NULL;
137 [ + - ][ + - ]: 56 : m_xConnection = NULL;
[ + - ]
138 : : }
139 : :
140 : : // XServiceInfo
141 [ # # ][ # # ]: 0 : IMPLEMENT_SERVICE_INFO2(OQueryContainer, "com.sun.star.sdb.dbaccess.OQueryContainer", SERVICE_SDBCX_CONTAINER.ascii, SERVICE_SDB_QUERIES.ascii)
[ # # ][ # # ]
[ # # ][ # # ]
142 : :
143 : : // XDataDescriptorFactory
144 : 0 : Reference< XPropertySet > SAL_CALL OQueryContainer::createDataDescriptor( ) throw(RuntimeException)
145 : : {
146 [ # # ][ # # ]: 0 : return new OQueryDescriptor();
147 : : }
148 : :
149 : : // XAppend
150 : 0 : void SAL_CALL OQueryContainer::appendByDescriptor( const Reference< XPropertySet >& _rxDesc ) throw(SQLException, ElementExistException, RuntimeException)
151 : : {
152 [ # # ]: 0 : ResettableMutexGuard aGuard(m_aMutex);
153 [ # # ]: 0 : if ( !m_xCommandDefinitions.is() )
154 [ # # ][ # # ]: 0 : throw DisposedException( ::rtl::OUString(), *this );
155 : :
156 : : // first clone this object's CommandDefinition part
157 [ # # ][ # # ]: 0 : Reference< XPropertySet > xCommandDefinitionPart( m_aContext.createComponent( (::rtl::OUString)SERVICE_SDB_QUERYDEFINITION ), UNO_QUERY_THROW );
[ # # ]
158 [ # # ]: 0 : ::comphelper::copyProperties( _rxDesc, xCommandDefinitionPart );
159 : : // TODO : the columns part of the descriptor has to be copied
160 : :
161 : : // create a wrapper for the object (*before* inserting into our command definition container)
162 [ # # ][ # # ]: 0 : Reference< XContent > xNewObject( implCreateWrapper( Reference< XContent>( xCommandDefinitionPart, UNO_QUERY_THROW ) ) );
163 : :
164 : 0 : ::rtl::OUString sNewObjectName;
165 [ # # ][ # # ]: 0 : _rxDesc->getPropertyValue(PROPERTY_NAME) >>= sNewObjectName;
[ # # ]
166 : :
167 : : try
168 : : {
169 [ # # ][ # # ]: 0 : notifyByName( aGuard, sNewObjectName, xNewObject, NULL, E_INSERTED, ApproveListeners );
170 : : }
171 [ # # ]: 0 : catch( const Exception& )
172 : : {
173 [ # # ]: 0 : disposeComponent( xNewObject );
174 [ # # ]: 0 : disposeComponent( xCommandDefinitionPart );
175 : 0 : throw;
176 : : }
177 : :
178 : : // insert the basic object into the definition container
179 : : {
180 : 0 : m_eDoingCurrently = INSERTING;
181 : 0 : OAutoActionReset aAutoReset(this);
182 [ # # ][ # # ]: 0 : m_xCommandDefinitions->insertByName(sNewObjectName, makeAny(xCommandDefinitionPart));
[ # # ]
183 : : }
184 : :
185 [ # # ]: 0 : implAppend( sNewObjectName, xNewObject );
186 [ # # ][ # # ]: 0 : notifyByName( aGuard, sNewObjectName, xNewObject, NULL, E_INSERTED, ContainerListemers );
[ # # ]
187 : 0 : }
188 : :
189 : : // XDrop
190 : 0 : void SAL_CALL OQueryContainer::dropByName( const ::rtl::OUString& _rName ) throw(SQLException, NoSuchElementException, RuntimeException)
191 : : {
192 [ # # ]: 0 : MutexGuard aGuard(m_aMutex);
193 [ # # ][ # # ]: 0 : if ( !checkExistence(_rName) )
194 [ # # ][ # # ]: 0 : throw NoSuchElementException(_rName,*this);
195 : :
196 [ # # ]: 0 : if ( !m_xCommandDefinitions.is() )
197 [ # # ][ # # ]: 0 : throw DisposedException( ::rtl::OUString(), *this );
198 : :
199 : : // now simply forward the remove request to the CommandDefinition container, we're a listener for the removal
200 : : // and thus we do everything neccessary in ::elementRemoved
201 [ # # ][ # # ]: 0 : m_xCommandDefinitions->removeByName(_rName);
[ # # ]
202 : 0 : }
203 : :
204 : 0 : void SAL_CALL OQueryContainer::dropByIndex( sal_Int32 _nIndex ) throw(SQLException, IndexOutOfBoundsException, RuntimeException)
205 : : {
206 [ # # ]: 0 : MutexGuard aGuard(m_aMutex);
207 [ # # ][ # # ]: 0 : if ((_nIndex<0) || (_nIndex>getCount()))
[ # # ][ # # ]
208 [ # # ]: 0 : throw IndexOutOfBoundsException();
209 : :
210 [ # # ]: 0 : if ( !m_xCommandDefinitions.is() )
211 [ # # ][ # # ]: 0 : throw DisposedException( ::rtl::OUString(), *this );
212 : :
213 : 0 : ::rtl::OUString sName;
214 [ # # ][ # # ]: 0 : Reference<XPropertySet> xProp(Reference<XIndexAccess>(m_xCommandDefinitions,UNO_QUERY)->getByIndex(_nIndex),UNO_QUERY);
[ # # ][ # # ]
215 [ # # ]: 0 : if ( xProp.is() )
216 [ # # ][ # # ]: 0 : xProp->getPropertyValue(PROPERTY_NAME) >>= sName;
[ # # ]
217 : :
218 [ # # ][ # # ]: 0 : dropByName(sName);
219 : 0 : }
220 : :
221 : 0 : void SAL_CALL OQueryContainer::elementInserted( const ::com::sun::star::container::ContainerEvent& _rEvent ) throw(::com::sun::star::uno::RuntimeException)
222 : : {
223 : 0 : Reference< XContent > xNewElement;
224 : 0 : ::rtl::OUString sElementName;
225 : 0 : _rEvent.Accessor >>= sElementName;
226 : : {
227 [ # # ]: 0 : MutexGuard aGuard(m_aMutex);
228 [ # # ]: 0 : if (INSERTING == m_eDoingCurrently)
229 : : // nothing to do, we're inserting via an "appendByDescriptor"
230 : : return;
231 : :
232 : : OSL_ENSURE(!sElementName.isEmpty(), "OQueryContainer::elementInserted : invalid name !");
233 : : OSL_ENSURE(m_aDocumentMap.find(sElementName) == m_aDocumentMap.end(), "OQueryContainer::elementInserted : oops .... we're inconsistent with our master container !");
234 [ # # ][ # # ]: 0 : if (sElementName.isEmpty() || hasByName(sElementName))
[ # # ][ # # ]
235 : : return;
236 : :
237 : : // insert an own new element
238 [ # # ][ # # ]: 0 : xNewElement = implCreateWrapper(sElementName);
[ # # ][ # # ]
239 : : }
240 [ # # ][ # # ]: 0 : insertByName(sElementName,makeAny(xNewElement));
[ # # ][ # # ]
241 : : }
242 : :
243 : 0 : void SAL_CALL OQueryContainer::elementRemoved( const ::com::sun::star::container::ContainerEvent& _rEvent ) throw(::com::sun::star::uno::RuntimeException)
244 : : {
245 : 0 : ::rtl::OUString sAccessor;
246 : 0 : _rEvent.Accessor >>= sAccessor;
247 : : {
248 : : OSL_ENSURE(!sAccessor.isEmpty(), "OQueryContainer::elementRemoved : invalid name !");
249 : : OSL_ENSURE(m_aDocumentMap.find(sAccessor) != m_aDocumentMap.end(), "OQueryContainer::elementRemoved : oops .... we're inconsistent with our master container !");
250 [ # # ][ # # ]: 0 : if ( sAccessor.isEmpty() || !hasByName(sAccessor) )
[ # # ][ # # ]
251 : 0 : return;
252 : : }
253 [ # # ][ # # ]: 0 : removeByName(sAccessor);
254 : : }
255 : :
256 : 0 : void SAL_CALL OQueryContainer::elementReplaced( const ::com::sun::star::container::ContainerEvent& _rEvent ) throw(::com::sun::star::uno::RuntimeException)
257 : : {
258 : 0 : Reference< XPropertySet > xReplacedElement;
259 : 0 : Reference< XContent > xNewElement;
260 : 0 : ::rtl::OUString sAccessor;
261 : 0 : _rEvent.Accessor >>= sAccessor;
262 : :
263 : : {
264 [ # # ]: 0 : MutexGuard aGuard(m_aMutex);
265 : : OSL_ENSURE(!sAccessor.isEmpty(), "OQueryContainer::elementReplaced : invalid name !");
266 : : OSL_ENSURE(m_aDocumentMap.find(sAccessor) != m_aDocumentMap.end(), "OQueryContainer::elementReplaced : oops .... we're inconsistent with our master container !");
267 [ # # ][ # # ]: 0 : if (sAccessor.isEmpty() || !hasByName(sAccessor))
[ # # ][ # # ]
268 : 0 : return;
269 : :
270 [ # # ][ # # ]: 0 : xNewElement = implCreateWrapper(sAccessor);
[ # # ][ # # ]
271 : : }
272 : :
273 [ # # ][ # # ]: 0 : replaceByName(sAccessor,makeAny(xNewElement));
[ # # ][ # # ]
[ # # ]
274 : : }
275 : :
276 : 0 : Reference< XVeto > SAL_CALL OQueryContainer::approveInsertElement( const ContainerEvent& Event ) throw (WrappedTargetException, RuntimeException)
277 : : {
278 : 0 : ::rtl::OUString sName;
279 : 0 : OSL_VERIFY( Event.Accessor >>= sName );
280 [ # # ]: 0 : Reference< XContent > xElement( Event.Element, UNO_QUERY_THROW );
281 : :
282 : 0 : Reference< XVeto > xReturn;
283 : : try
284 : : {
285 [ # # ][ # # ]: 0 : getElementApproval()->approveElement( sName, xElement.get() );
[ # # ][ # # ]
[ # # ]
286 : : }
287 [ # # # # ]: 0 : catch( const Exception& )
288 : : {
289 [ # # # # : 0 : xReturn = new Veto( ::rtl::OUString(), ::cppu::getCaughtException() );
# # # # ]
290 : : }
291 : 0 : return xReturn;
292 : : }
293 : :
294 : 0 : Reference< XVeto > SAL_CALL OQueryContainer::approveReplaceElement( const ContainerEvent& /*Event*/ ) throw (WrappedTargetException, RuntimeException)
295 : : {
296 : 0 : return NULL;
297 : : }
298 : :
299 : 0 : Reference< XVeto > SAL_CALL OQueryContainer::approveRemoveElement( const ContainerEvent& /*Event*/ ) throw (WrappedTargetException, RuntimeException)
300 : : {
301 : 0 : return NULL;
302 : : }
303 : :
304 : 16 : void SAL_CALL OQueryContainer::disposing( const ::com::sun::star::lang::EventObject& _rSource ) throw(::com::sun::star::uno::RuntimeException)
305 : : {
306 [ + - ][ - + ]: 16 : if (_rSource.Source.get() == Reference< XInterface >(m_xCommandDefinitions, UNO_QUERY).get())
307 : : { // our "master container" (with the command definitions) is being disposed
308 : : OSL_FAIL("OQueryContainer::disposing : nobody should dispose the CommandDefinition container before disposing my connection !");
309 : 0 : dispose();
310 : : }
311 : : else
312 : : {
313 [ + - ]: 16 : Reference< XContent > xSource(_rSource.Source, UNO_QUERY);
314 : : // it's one of our documents ....
315 : 16 : Documents::iterator aIter = m_aDocumentMap.begin();
316 : 16 : Documents::iterator aEnd = m_aDocumentMap.end();
317 [ - + ]: 16 : for (;aIter != aEnd;++aIter )
318 : : {
319 [ # # ][ # # ]: 0 : if ( xSource == aIter->second.get() )
[ # # ]
320 : : {
321 [ # # ][ # # ]: 0 : m_xCommandDefinitions->removeByName(aIter->first);
322 : 0 : break;
323 : : }
324 : : }
325 [ + - ]: 16 : ODefinitionContainer::disposing(_rSource);
326 : : }
327 : 16 : }
328 : :
329 : 0 : ::rtl::OUString OQueryContainer::determineContentType() const
330 : : {
331 : 0 : return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "application/vnd.org.openoffice.DatabaseQueryContainer" ) );
332 : : }
333 : :
334 : 0 : Reference< XContent > OQueryContainer::implCreateWrapper(const ::rtl::OUString& _rName)
335 : : {
336 [ # # ][ # # ]: 0 : Reference< XContent > xObject(m_xCommandDefinitions->getByName(_rName),UNO_QUERY);
[ # # ]
337 [ # # ]: 0 : return implCreateWrapper(xObject);
338 : : }
339 : :
340 : 0 : Reference< XContent > OQueryContainer::implCreateWrapper(const Reference< XContent >& _rxCommandDesc)
341 : : {
342 [ # # ]: 0 : Reference<XNameContainer> xContainer(_rxCommandDesc,UNO_QUERY);
343 : 0 : Reference< XContent > xReturn;
344 [ # # ]: 0 : if ( xContainer .is() )
345 : : {
346 [ # # ][ # # ]: 0 : xReturn = new OQueryContainer( xContainer, m_xConnection, m_aContext.getLegacyServiceFactory(), m_pWarnings );
[ # # ][ # # ]
347 : : }
348 : : else
349 : : {
350 [ # # ][ # # ]: 0 : OQuery* pNewObject = new OQuery( Reference< XPropertySet >( _rxCommandDesc, UNO_QUERY ), m_xConnection, m_aContext.getLegacyServiceFactory() );
[ # # ]
351 [ # # ][ # # ]: 0 : xReturn = pNewObject;
352 : :
353 : 0 : pNewObject->setWarningsContainer( m_pWarnings );
354 : : // pNewObject->getColumns();
355 : : // Why? This is expensive. If you comment this in 'cause you really need it, be sure to run the
356 : : // QueryInQuery test in dbaccess/qa/complex/dbaccess ...
357 : : }
358 : :
359 : 0 : return xReturn;
360 : : }
361 : :
362 : 0 : Reference< XContent > OQueryContainer::createObject( const ::rtl::OUString& _rName)
363 : : {
364 : 0 : return implCreateWrapper(_rName);
365 : : }
366 : :
367 : 0 : sal_Bool OQueryContainer::checkExistence(const ::rtl::OUString& _rName)
368 : : {
369 : 0 : sal_Bool bRet = sal_False;
370 [ # # ]: 0 : if ( !m_bInPropertyChange )
371 : : {
372 [ # # ][ # # ]: 0 : bRet = m_xCommandDefinitions->hasByName(_rName);
373 [ # # ]: 0 : Documents::iterator aFind = m_aDocumentMap.find(_rName);
374 [ # # ][ # # ]: 0 : if ( !bRet && aFind != m_aDocumentMap.end() )
[ # # ][ # # ]
375 : : {
376 [ # # ][ # # ]: 0 : m_aDocuments.erase( ::std::find(m_aDocuments.begin(),m_aDocuments.end(),aFind));
377 [ # # ]: 0 : m_aDocumentMap.erase(aFind);
378 : : }
379 [ # # ][ # # ]: 0 : else if ( bRet && aFind == m_aDocumentMap.end() )
[ # # ][ # # ]
380 : : {
381 [ # # ][ # # ]: 0 : implAppend(_rName,NULL);
382 : : }
383 : : }
384 : 0 : return bRet;
385 : : }
386 : :
387 : 0 : sal_Bool SAL_CALL OQueryContainer::hasElements( ) throw (RuntimeException)
388 : : {
389 [ # # ]: 0 : MutexGuard aGuard(m_aMutex);
390 [ # # ][ # # ]: 0 : return m_xCommandDefinitions->hasElements();
[ # # ]
391 : : }
392 : :
393 : 0 : sal_Int32 SAL_CALL OQueryContainer::getCount( ) throw(RuntimeException)
394 : : {
395 [ # # ]: 0 : MutexGuard aGuard(m_aMutex);
396 [ # # ][ # # ]: 0 : return Reference<XIndexAccess>(m_xCommandDefinitions,UNO_QUERY)->getCount();
[ # # ][ # # ]
397 : : }
398 : :
399 : 0 : Sequence< ::rtl::OUString > SAL_CALL OQueryContainer::getElementNames( ) throw(RuntimeException)
400 : : {
401 [ # # ]: 0 : MutexGuard aGuard(m_aMutex);
402 : :
403 [ # # ][ # # ]: 0 : return m_xCommandDefinitions->getElementNames();
[ # # ]
404 : : }
405 : :
406 : : } // namespace dbaccess
407 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|