Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * Effective License of whole file:
5 : : *
6 : : * This library is free software; you can redistribute it and/or
7 : : * modify it under the terms of the GNU Lesser General Public
8 : : * License version 2.1, as published by the Free Software Foundation.
9 : : *
10 : : * This library is distributed in the hope that it will be useful,
11 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 : : * Lesser General Public License for more details.
14 : : *
15 : : * You should have received a copy of the GNU Lesser General Public
16 : : * License along with this library; if not, write to the Free Software
17 : : * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
18 : : * MA 02111-1307 USA
19 : : *
20 : : * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
21 : : *
22 : : * The Contents of this file are made available subject to the terms of
23 : : * the GNU Lesser General Public License Version 2.1
24 : : *
25 : : * Copyright: 2000 by Sun Microsystems, Inc.
26 : : *
27 : : * Contributor(s): Joerg Budischewski
28 : : *
29 : : * All parts contributed on or after August 2011:
30 : : *
31 : : * Version: MPL 1.1 / GPLv3+ / LGPLv2.1+
32 : : *
33 : : * The contents of this file are subject to the Mozilla Public License Version
34 : : * 1.1 (the "License"); you may not use this file except in compliance with
35 : : * the License or as specified alternatively below. You may obtain a copy of
36 : : * the License at http://www.mozilla.org/MPL/
37 : : *
38 : : * Software distributed under the License is distributed on an "AS IS" basis,
39 : : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
40 : : * for the specific language governing rights and limitations under the
41 : : * License.
42 : : *
43 : : * Major Contributor(s):
44 : : * [ Copyright (C) 2011 Lionel Elie Mamane <lionel@mamane.lu> ]
45 : : *
46 : : * All Rights Reserved.
47 : : *
48 : : * For minor contributions see the git repository.
49 : : *
50 : : * Alternatively, the contents of this file may be used under the terms of
51 : : * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
52 : : * the GNU Lesser General Public License Version 2.1 or later (the "LGPLv2.1+"),
53 : : * in which case the provisions of the GPLv3+ or the LGPLv2.1+ are applicable
54 : : * instead of those above.
55 : : *
56 : : ************************************************************************/
57 : :
58 : : #include <rtl/ustrbuf.hxx>
59 : :
60 : : #include <com/sun/star/sdbc/XRow.hpp>
61 : : #include <com/sun/star/sdbc/XParameters.hpp>
62 : :
63 : :
64 : : #include <cppuhelper/implbase1.hxx>
65 : :
66 : : #include "pq_xcontainer.hxx"
67 : : #include "pq_statics.hxx"
68 : : #include "pq_tools.hxx"
69 : :
70 : : using osl::MutexGuard;
71 : :
72 : : using rtl::OUString;
73 : : using rtl::OUStringBuffer;
74 : : using rtl::OUStringToOString;
75 : :
76 : : using com::sun::star::beans::XPropertySet;
77 : :
78 : : using com::sun::star::uno::Any;
79 : : using com::sun::star::uno::makeAny;
80 : : using com::sun::star::uno::UNO_QUERY;
81 : : using com::sun::star::uno::Type;
82 : : using com::sun::star::uno::XInterface;
83 : : using com::sun::star::uno::Reference;
84 : : using com::sun::star::uno::Sequence;
85 : : using com::sun::star::uno::RuntimeException;
86 : :
87 : : using com::sun::star::container::NoSuchElementException;
88 : : using com::sun::star::container::XEnumeration;
89 : : using com::sun::star::container::XContainerListener;
90 : : using com::sun::star::container::ContainerEvent;
91 : : using com::sun::star::lang::IndexOutOfBoundsException;
92 : : using com::sun::star::lang::XEventListener;
93 : :
94 : : using com::sun::star::lang::WrappedTargetException;
95 : :
96 : : using com::sun::star::sdbc::XRow;
97 : : using com::sun::star::sdbc::XCloseable;
98 : : using com::sun::star::sdbc::XStatement;
99 : : using com::sun::star::sdbc::XResultSet;
100 : : using com::sun::star::sdbc::XParameters;
101 : : using com::sun::star::sdbc::XPreparedStatement;
102 : : using com::sun::star::sdbcx::XDataDescriptorFactory;
103 : :
104 : : namespace pq_sdbc_driver
105 : : {
106 : : #define ASCII_STR(x) OUString( RTL_CONSTASCII_USTRINGPARAM( x ) )
107 : :
108 : :
109 : 0 : class ReplacedBroadcaster : public EventBroadcastHelper
110 : : {
111 : : ContainerEvent m_event;
112 : : public:
113 : 0 : ReplacedBroadcaster(
114 : : const Reference< XInterface > & source,
115 : : const rtl::OUString & name,
116 : : const Any & newElement,
117 : : const rtl::OUString & oldElement ) :
118 : 0 : m_event( source, makeAny( name ), newElement, makeAny(oldElement) )
119 : 0 : {}
120 : :
121 : 0 : virtual void fire( XEventListener * listener ) const
122 : : {
123 : 0 : ((XContainerListener*)listener)->elementReplaced( m_event );
124 : 0 : }
125 : 0 : virtual Type getType() const
126 : : {
127 : 0 : return getCppuType( (Reference< XContainerListener > *)0 );
128 : : }
129 : : };
130 : :
131 : 0 : class InsertedBroadcaster : public EventBroadcastHelper
132 : : {
133 : : public:
134 : : ContainerEvent m_event;
135 : 0 : InsertedBroadcaster(
136 : : const Reference< XInterface > & source,
137 : : const rtl::OUString & name,
138 : : const Any & newElement ) :
139 : 0 : m_event( source, makeAny( name ), newElement, Any() )
140 : 0 : {}
141 : :
142 : 0 : virtual void fire( XEventListener * listener ) const
143 : : {
144 : 0 : ((XContainerListener*)listener)->elementInserted( m_event );
145 : 0 : }
146 : :
147 : 0 : virtual Type getType() const
148 : : {
149 : 0 : return getCppuType( (Reference< XContainerListener > *)0 );
150 : : }
151 : : };
152 : :
153 : 0 : class RemovedBroadcaster : public EventBroadcastHelper
154 : : {
155 : : public:
156 : : ContainerEvent m_event;
157 : 0 : RemovedBroadcaster(
158 : : const Reference< XInterface > & source,
159 : : const rtl::OUString & name) :
160 : 0 : m_event( source, makeAny( name ), Any(), Any() )
161 : 0 : {}
162 : :
163 : 0 : virtual void fire( XEventListener * listener ) const
164 : : {
165 : 0 : ((XContainerListener*)listener)->elementRemoved( m_event );
166 : 0 : }
167 : :
168 : 0 : virtual Type getType() const
169 : : {
170 : 0 : return getCppuType( (Reference< XContainerListener > *)0 );
171 : : }
172 : : };
173 : :
174 : 0 : Container::Container(
175 : : const ::rtl::Reference< RefCountedMutex > & refMutex,
176 : : const ::com::sun::star::uno::Reference< com::sun::star::sdbc::XConnection > & origin,
177 : : ConnectionSettings *pSettings,
178 : : const ::rtl::OUString &type)
179 : 0 : : ContainerBase( refMutex->mutex ),
180 : : m_refMutex( refMutex ),
181 : : m_pSettings( pSettings ),
182 : : m_origin( origin ),
183 : 0 : m_type( type )
184 : : {
185 : 0 : }
186 : :
187 : 0 : Any Container::getByName( const ::rtl::OUString& aName )
188 : : throw (NoSuchElementException,WrappedTargetException,RuntimeException)
189 : : {
190 : 0 : String2IntMap::const_iterator ii = m_name2index.find( aName );
191 : 0 : if( ii == m_name2index.end() )
192 : : {
193 : 0 : OUStringBuffer buf(128);
194 : 0 : buf.appendAscii( "Element " );
195 : 0 : buf.append( aName );
196 : 0 : buf.appendAscii( " unknown in " );
197 : 0 : buf.append( m_type );
198 : 0 : buf.appendAscii( "-Container" );
199 : 0 : throw NoSuchElementException( buf.makeStringAndClear() , *this );
200 : : }
201 : : OSL_ASSERT( ii->second >= 0 && ii->second < m_values.getLength() );
202 : 0 : return m_values[ ii->second ];
203 : : }
204 : :
205 : 0 : Sequence< OUString > Container::getElementNames( )
206 : : throw (::com::sun::star::uno::RuntimeException)
207 : : {
208 : 0 : Sequence< OUString > ret( m_values.getLength() );
209 : 0 : for( String2IntMap::const_iterator ii = m_name2index.begin();
210 : 0 : ii != m_name2index.end() ;
211 : : ++ ii )
212 : : {
213 : : // give element names in index order !
214 : 0 : ret[ii->second] = ii->first;
215 : : // ret[i] = ii->first;
216 : : }
217 : 0 : return ret;
218 : : }
219 : :
220 : 0 : sal_Bool Container::hasByName( const ::rtl::OUString& aName )
221 : : throw (::com::sun::star::uno::RuntimeException)
222 : : {
223 : 0 : return m_name2index.find( aName ) != m_name2index.end();
224 : : }
225 : : // Methods
226 : 0 : Type Container::getElementType( )
227 : : throw (::com::sun::star::uno::RuntimeException)
228 : : {
229 : 0 : return Type();
230 : : }
231 : :
232 : 0 : sal_Bool Container::hasElements( )
233 : : throw (::com::sun::star::uno::RuntimeException)
234 : : {
235 : 0 : return ! m_name2index.empty();
236 : : }
237 : :
238 : 0 : Any Container::getByIndex( sal_Int32 Index )
239 : : throw (::com::sun::star::lang::IndexOutOfBoundsException,
240 : : ::com::sun::star::lang::WrappedTargetException,
241 : : ::com::sun::star::uno::RuntimeException)
242 : : {
243 : 0 : if( Index < 0 || Index >= m_values.getLength() )
244 : : {
245 : 0 : OUStringBuffer buf(128);
246 : 0 : buf.appendAscii( "Index " );
247 : 0 : buf.append( Index );
248 : 0 : buf.appendAscii(" out of range for " );
249 : 0 : buf.append( m_type );
250 : 0 : buf.appendAscii("-Container, expected 0 <= x <= " );
251 : 0 : buf.append( (sal_Int32 ) (m_values.getLength() -1));
252 : 0 : throw IndexOutOfBoundsException( buf.makeStringAndClear(), *this );
253 : : }
254 : 0 : return m_values[Index];
255 : : }
256 : :
257 : 0 : sal_Int32 Container::getCount()
258 : : throw (::com::sun::star::uno::RuntimeException)
259 : : {
260 : 0 : return m_values.getLength();
261 : : }
262 : :
263 : :
264 : 0 : class ContainerEnumeration : public ::cppu::WeakImplHelper1< XEnumeration >
265 : : {
266 : : com::sun::star::uno::Sequence< com::sun::star::uno::Any > m_vec;
267 : : sal_Int32 m_index;
268 : : public:
269 : 0 : ContainerEnumeration( const com::sun::star::uno::Sequence< com::sun::star::uno::Any > &vec )
270 : : : m_vec( vec ),
271 : 0 : m_index( -1 )
272 : 0 : {}
273 : :
274 : : public:
275 : : // XEnumeration
276 : : virtual sal_Bool SAL_CALL hasMoreElements( )
277 : : throw (::com::sun::star::uno::RuntimeException);
278 : : virtual ::com::sun::star::uno::Any SAL_CALL nextElement( )
279 : : throw (::com::sun::star::container::NoSuchElementException,
280 : : ::com::sun::star::lang::WrappedTargetException,
281 : : ::com::sun::star::uno::RuntimeException);
282 : :
283 : : };
284 : :
285 : 0 : sal_Bool ContainerEnumeration::hasMoreElements()
286 : : throw (::com::sun::star::uno::RuntimeException)
287 : : {
288 : 0 : return m_vec.getLength() > m_index +1;
289 : : }
290 : :
291 : 0 : com::sun::star::uno::Any ContainerEnumeration::nextElement()
292 : : throw (::com::sun::star::container::NoSuchElementException,
293 : : ::com::sun::star::lang::WrappedTargetException,
294 : : ::com::sun::star::uno::RuntimeException)
295 : : {
296 : 0 : if( ! hasMoreElements() )
297 : : {
298 : : throw NoSuchElementException(
299 : 0 : ASCII_STR( "NoSuchElementException during enumeration" ), *this );
300 : : }
301 : 0 : m_index ++;
302 : 0 : return m_vec[m_index];
303 : : }
304 : :
305 : 0 : Reference< XEnumeration > Container::createEnumeration( )
306 : : throw (::com::sun::star::uno::RuntimeException)
307 : : {
308 : 0 : return new ContainerEnumeration( m_values );
309 : : }
310 : :
311 : 0 : void Container::addRefreshListener(
312 : : const ::com::sun::star::uno::Reference< ::com::sun::star::util::XRefreshListener >& l )
313 : : throw (::com::sun::star::uno::RuntimeException)
314 : : {
315 : 0 : rBHelper.addListener( getCppuType(&l) , l );
316 : 0 : }
317 : :
318 : 0 : void Container::removeRefreshListener(
319 : : const ::com::sun::star::uno::Reference< ::com::sun::star::util::XRefreshListener >& l )
320 : : throw (::com::sun::star::uno::RuntimeException)
321 : : {
322 : 0 : rBHelper.removeListener( getCppuType(&l) , l );
323 : 0 : }
324 : :
325 : 0 : void Container::disposing()
326 : : {
327 : 0 : m_origin.clear();
328 : 0 : }
329 : :
330 : 0 : void Container::rename( const rtl::OUString &oldName, const rtl::OUString &newName )
331 : : {
332 : 0 : Any newValue;
333 : : {
334 : 0 : osl::MutexGuard guard ( m_refMutex->mutex );
335 : 0 : String2IntMap::iterator ii = m_name2index.find( oldName );
336 : 0 : if( ii != m_name2index.end() )
337 : : {
338 : 0 : sal_Int32 nIndex = ii->second;
339 : 0 : newValue = m_values[nIndex];
340 : 0 : m_name2index.erase( ii );
341 : 0 : m_name2index[ newName ] = nIndex;
342 : 0 : newValue = m_values[nIndex];
343 : 0 : }
344 : : }
345 : 0 : fire( ReplacedBroadcaster( *this, newName, newValue, oldName ) );
346 : 0 : fire( RefreshedBroadcaster( *this ) );
347 : 0 : }
348 : :
349 : 0 : void Container::dropByName( const ::rtl::OUString& elementName )
350 : : throw (::com::sun::star::sdbc::SQLException,
351 : : ::com::sun::star::container::NoSuchElementException,
352 : : ::com::sun::star::uno::RuntimeException)
353 : : {
354 : 0 : osl::MutexGuard guard( m_refMutex->mutex );
355 : 0 : String2IntMap::const_iterator ii = m_name2index.find( elementName );
356 : 0 : if( ii == m_name2index.end() )
357 : : {
358 : 0 : OUStringBuffer buf( 128 );
359 : 0 : buf.appendAscii( "Column " );
360 : 0 : buf.append( elementName );
361 : 0 : buf.appendAscii( " is unknown in " );
362 : 0 : buf.append( m_type );
363 : : // buf.appendAscii( " " );
364 : : // buf.append( m_schemaName );
365 : : // buf.appendAscii( "." );
366 : : // buf.append( m_tableName );
367 : 0 : buf.appendAscii( " container, so it can't be dropped" );
368 : : throw com::sun::star::container::NoSuchElementException(
369 : 0 : buf.makeStringAndClear(), *this );
370 : : }
371 : 0 : dropByIndex( ii->second );
372 : 0 : }
373 : :
374 : 0 : void Container::dropByIndex( sal_Int32 index )
375 : : throw (::com::sun::star::sdbc::SQLException,
376 : : ::com::sun::star::lang::IndexOutOfBoundsException,
377 : : ::com::sun::star::uno::RuntimeException)
378 : : {
379 : 0 : osl::MutexGuard guard( m_refMutex->mutex );
380 : 0 : if( index < 0 || index >= m_values.getLength() )
381 : : {
382 : 0 : OUStringBuffer buf( 128 );
383 : 0 : buf.appendAscii( "Index out of range (allowed 0 to " );
384 : 0 : buf.append((sal_Int32)(m_values.getLength() -1) );
385 : 0 : buf.appendAscii( ", got " );
386 : 0 : buf.append( index );
387 : 0 : buf.appendAscii( ") in " );
388 : 0 : buf.append( m_type );
389 : : throw com::sun::star::lang::IndexOutOfBoundsException(
390 : 0 : buf.makeStringAndClear(), *this );
391 : : }
392 : :
393 : 0 : OUString name;
394 : 0 : for( String2IntMap::iterator ii = m_name2index.begin() ;
395 : 0 : ii != m_name2index.end() ;
396 : : ++ ii )
397 : : {
398 : 0 : if( ii->second == index )
399 : : {
400 : 0 : name = ii->first;
401 : 0 : m_name2index.erase( ii );
402 : 0 : break;
403 : : }
404 : : }
405 : :
406 : 0 : Any oldElement = m_values[index];
407 : 0 : for( int i = index +1 ; i < m_values.getLength() ; i ++ )
408 : : {
409 : 0 : m_values[i-1] = m_values[i];
410 : :
411 : : // I know, this is expensive, but don't want to maintain another map ...
412 : 0 : for( String2IntMap::iterator ii = m_name2index.begin() ;
413 : 0 : ii != m_name2index.end() ;
414 : : ++ ii )
415 : : {
416 : 0 : if( ii->second == i )
417 : : {
418 : 0 : ii->second = i-1;
419 : 0 : break;
420 : : }
421 : : }
422 : : }
423 : 0 : m_values.realloc( m_values.getLength() - 1 );
424 : :
425 : 0 : fire( RemovedBroadcaster( *this, name ) );
426 : 0 : }
427 : :
428 : 0 : void Container::append(
429 : : const rtl::OUString & name,
430 : : const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& descriptor )
431 : : throw ( ::com::sun::star::container::ElementExistException )
432 : :
433 : : {
434 : 0 : osl::MutexGuard guard( m_refMutex->mutex );
435 : :
436 : 0 : if( hasByName( name ) )
437 : : {
438 : 0 : OUStringBuffer buf( 128 );
439 : 0 : buf.appendAscii( "a ");
440 : 0 : buf.append( m_type );
441 : 0 : buf.appendAscii( " with name " );
442 : 0 : buf.append( name );
443 : 0 : buf.appendAscii( " already exists in this container" );
444 : : throw com::sun::star::container::ElementExistException(
445 : 0 : buf.makeStringAndClear() , *this );
446 : : }
447 : :
448 : 0 : int index = m_values.getLength();
449 : 0 : m_values.realloc( m_values.getLength() + 1 );
450 : 0 : m_values[index] = makeAny( descriptor );
451 : 0 : m_name2index[name] = index;
452 : :
453 : 0 : fire( InsertedBroadcaster( *this, name, makeAny( descriptor ) ) );
454 : 0 : }
455 : :
456 : 0 : void Container::appendByDescriptor(
457 : : const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& descriptor)
458 : : throw (::com::sun::star::sdbc::SQLException,
459 : : ::com::sun::star::container::ElementExistException,
460 : : ::com::sun::star::uno::RuntimeException)
461 : : {
462 : 0 : append( extractStringProperty( descriptor, getStatics().NAME ), descriptor );
463 : 0 : }
464 : :
465 : :
466 : 0 : void Container::addContainerListener(
467 : : const ::com::sun::star::uno::Reference< ::com::sun::star::container::XContainerListener >& l )
468 : : throw (::com::sun::star::uno::RuntimeException)
469 : : {
470 : 0 : rBHelper.addListener( getCppuType(&l) , l );
471 : 0 : }
472 : :
473 : 0 : void Container::removeContainerListener(
474 : : const ::com::sun::star::uno::Reference< ::com::sun::star::container::XContainerListener >& l )
475 : : throw (::com::sun::star::uno::RuntimeException)
476 : : {
477 : 0 : rBHelper.removeListener( getCppuType(&l) , l );
478 : 0 : }
479 : :
480 : :
481 : 0 : void Container::fire( const EventBroadcastHelper &helper )
482 : : {
483 : 0 : Reference< ::com::sun::star::util::XRefreshListener > l;
484 : 0 : cppu::OInterfaceContainerHelper *container = rBHelper.getContainer( helper.getType() );
485 : 0 : if( container )
486 : : {
487 : 0 : cppu::OInterfaceIteratorHelper iterator( * container );
488 : 0 : while( iterator.hasMoreElements() )
489 : : {
490 : : try
491 : : {
492 : 0 : helper.fire( (XEventListener * ) iterator.next() );
493 : : }
494 : 0 : catch ( com::sun::star::uno::RuntimeException & )
495 : : {
496 : : OSL_ENSURE( 0, "exception catched" );
497 : : // loose coupling, a runtime exception shall not break anything
498 : : // TODO: log away as warning !
499 : : }
500 : 0 : catch( com::sun::star::uno::Exception & )
501 : : {
502 : : OSL_ENSURE( 0, "exception from listener flying through" );
503 : 0 : throw;
504 : : }
505 : 0 : }
506 : 0 : }
507 : :
508 : 0 : }
509 : :
510 : : }
|