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 : * This Source Code Form is subject to the terms of the Mozilla Public
32 : * License, v. 2.0. If a copy of the MPL was not distributed with this
33 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
34 : *
35 : ************************************************************************/
36 :
37 : #include <rtl/ustrbuf.hxx>
38 :
39 : #include <com/sun/star/sdbc/XRow.hpp>
40 : #include <com/sun/star/sdbc/XParameters.hpp>
41 :
42 :
43 : #include <cppuhelper/implbase1.hxx>
44 :
45 : #include "pq_xcontainer.hxx"
46 : #include "pq_statics.hxx"
47 : #include "pq_tools.hxx"
48 :
49 : using osl::MutexGuard;
50 :
51 :
52 : using com::sun::star::beans::XPropertySet;
53 :
54 : using com::sun::star::uno::Any;
55 : using com::sun::star::uno::makeAny;
56 : using com::sun::star::uno::UNO_QUERY;
57 : using com::sun::star::uno::Type;
58 : using com::sun::star::uno::XInterface;
59 : using com::sun::star::uno::Reference;
60 : using com::sun::star::uno::Sequence;
61 : using com::sun::star::uno::RuntimeException;
62 :
63 : using com::sun::star::container::NoSuchElementException;
64 : using com::sun::star::container::XEnumeration;
65 : using com::sun::star::container::XContainerListener;
66 : using com::sun::star::container::ContainerEvent;
67 : using com::sun::star::lang::IndexOutOfBoundsException;
68 : using com::sun::star::lang::XEventListener;
69 :
70 : using com::sun::star::lang::WrappedTargetException;
71 :
72 : using com::sun::star::sdbc::XRow;
73 : using com::sun::star::sdbc::XCloseable;
74 : using com::sun::star::sdbc::XStatement;
75 : using com::sun::star::sdbc::XResultSet;
76 : using com::sun::star::sdbc::XParameters;
77 : using com::sun::star::sdbc::XPreparedStatement;
78 : using com::sun::star::sdbcx::XDataDescriptorFactory;
79 :
80 : namespace pq_sdbc_driver
81 : {
82 :
83 0 : class ReplacedBroadcaster : public EventBroadcastHelper
84 : {
85 : ContainerEvent m_event;
86 : public:
87 0 : ReplacedBroadcaster(
88 : const Reference< XInterface > & source,
89 : const OUString & name,
90 : const Any & newElement,
91 : const OUString & oldElement ) :
92 0 : m_event( source, makeAny( name ), newElement, makeAny(oldElement) )
93 0 : {}
94 :
95 0 : virtual void fire( XEventListener * listener ) const SAL_OVERRIDE
96 : {
97 0 : static_cast<XContainerListener*>(listener)->elementReplaced( m_event );
98 0 : }
99 0 : virtual Type getType() const SAL_OVERRIDE
100 : {
101 0 : return cppu::UnoType<XContainerListener>::get();
102 : }
103 : };
104 :
105 0 : class InsertedBroadcaster : public EventBroadcastHelper
106 : {
107 : public:
108 : ContainerEvent m_event;
109 0 : InsertedBroadcaster(
110 : const Reference< XInterface > & source,
111 : const OUString & name,
112 : const Any & newElement ) :
113 0 : m_event( source, makeAny( name ), newElement, Any() )
114 0 : {}
115 :
116 0 : virtual void fire( XEventListener * listener ) const SAL_OVERRIDE
117 : {
118 0 : static_cast<XContainerListener*>(listener)->elementInserted( m_event );
119 0 : }
120 :
121 0 : virtual Type getType() const SAL_OVERRIDE
122 : {
123 0 : return cppu::UnoType<XContainerListener>::get();
124 : }
125 : };
126 :
127 0 : class RemovedBroadcaster : public EventBroadcastHelper
128 : {
129 : public:
130 : ContainerEvent m_event;
131 0 : RemovedBroadcaster(
132 : const Reference< XInterface > & source,
133 : const OUString & name) :
134 0 : m_event( source, makeAny( name ), Any(), Any() )
135 0 : {}
136 :
137 0 : virtual void fire( XEventListener * listener ) const SAL_OVERRIDE
138 : {
139 0 : static_cast<XContainerListener*>(listener)->elementRemoved( m_event );
140 0 : }
141 :
142 0 : virtual Type getType() const SAL_OVERRIDE
143 : {
144 0 : return cppu::UnoType<XContainerListener>::get();
145 : }
146 : };
147 :
148 0 : Container::Container(
149 : const ::rtl::Reference< RefCountedMutex > & refMutex,
150 : const ::com::sun::star::uno::Reference< com::sun::star::sdbc::XConnection > & origin,
151 : ConnectionSettings *pSettings,
152 : const OUString &type)
153 0 : : ContainerBase( refMutex->mutex ),
154 : m_refMutex( refMutex ),
155 : m_pSettings( pSettings ),
156 : m_origin( origin ),
157 0 : m_type( type )
158 : {
159 0 : }
160 :
161 0 : Any Container::getByName( const OUString& aName )
162 : throw (NoSuchElementException,WrappedTargetException,RuntimeException, std::exception)
163 : {
164 0 : String2IntMap::const_iterator ii = m_name2index.find( aName );
165 0 : if( ii == m_name2index.end() )
166 : {
167 0 : OUStringBuffer buf(128);
168 0 : buf.appendAscii( "Element " );
169 0 : buf.append( aName );
170 0 : buf.appendAscii( " unknown in " );
171 0 : buf.append( m_type );
172 0 : buf.appendAscii( "-Container" );
173 0 : throw NoSuchElementException( buf.makeStringAndClear() , *this );
174 : }
175 : OSL_ASSERT( ii->second >= 0 && ii->second < m_values.getLength() );
176 0 : return m_values[ ii->second ];
177 : }
178 :
179 0 : Sequence< OUString > Container::getElementNames( )
180 : throw (::com::sun::star::uno::RuntimeException, std::exception)
181 : {
182 0 : Sequence< OUString > ret( m_values.getLength() );
183 0 : for( String2IntMap::const_iterator ii = m_name2index.begin();
184 0 : ii != m_name2index.end() ;
185 : ++ ii )
186 : {
187 : // give element names in index order !
188 0 : ret[ii->second] = ii->first;
189 : // ret[i] = ii->first;
190 : }
191 0 : return ret;
192 : }
193 :
194 0 : sal_Bool Container::hasByName( const OUString& aName )
195 : throw (::com::sun::star::uno::RuntimeException, std::exception)
196 : {
197 0 : return m_name2index.find( aName ) != m_name2index.end();
198 : }
199 : // Methods
200 0 : Type Container::getElementType( )
201 : throw (::com::sun::star::uno::RuntimeException, std::exception)
202 : {
203 0 : return Type();
204 : }
205 :
206 0 : sal_Bool Container::hasElements( )
207 : throw (::com::sun::star::uno::RuntimeException, std::exception)
208 : {
209 0 : return ! m_name2index.empty();
210 : }
211 :
212 0 : Any Container::getByIndex( sal_Int32 Index )
213 : throw (::com::sun::star::lang::IndexOutOfBoundsException,
214 : ::com::sun::star::lang::WrappedTargetException,
215 : ::com::sun::star::uno::RuntimeException, std::exception)
216 : {
217 0 : if( Index < 0 || Index >= m_values.getLength() )
218 : {
219 0 : OUStringBuffer buf(128);
220 0 : buf.appendAscii( "Index " );
221 0 : buf.append( Index );
222 0 : buf.appendAscii(" out of range for " );
223 0 : buf.append( m_type );
224 0 : buf.appendAscii("-Container, expected 0 <= x <= " );
225 0 : buf.append( (sal_Int32 ) (m_values.getLength() -1));
226 0 : throw IndexOutOfBoundsException( buf.makeStringAndClear(), *this );
227 : }
228 0 : return m_values[Index];
229 : }
230 :
231 0 : sal_Int32 Container::getCount()
232 : throw (::com::sun::star::uno::RuntimeException, std::exception)
233 : {
234 0 : return m_values.getLength();
235 : }
236 :
237 :
238 0 : class ContainerEnumeration : public ::cppu::WeakImplHelper1< XEnumeration >
239 : {
240 : com::sun::star::uno::Sequence< com::sun::star::uno::Any > m_vec;
241 : sal_Int32 m_index;
242 : public:
243 0 : ContainerEnumeration( const com::sun::star::uno::Sequence< com::sun::star::uno::Any > &vec )
244 : : m_vec( vec ),
245 0 : m_index( -1 )
246 0 : {}
247 :
248 : public:
249 : // XEnumeration
250 : virtual sal_Bool SAL_CALL hasMoreElements( )
251 : throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
252 : virtual ::com::sun::star::uno::Any SAL_CALL nextElement( )
253 : throw (::com::sun::star::container::NoSuchElementException,
254 : ::com::sun::star::lang::WrappedTargetException,
255 : ::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
256 :
257 : };
258 :
259 0 : sal_Bool ContainerEnumeration::hasMoreElements()
260 : throw (::com::sun::star::uno::RuntimeException, std::exception)
261 : {
262 0 : return m_vec.getLength() > m_index +1;
263 : }
264 :
265 0 : com::sun::star::uno::Any ContainerEnumeration::nextElement()
266 : throw (::com::sun::star::container::NoSuchElementException,
267 : ::com::sun::star::lang::WrappedTargetException,
268 : ::com::sun::star::uno::RuntimeException, std::exception)
269 : {
270 0 : if( ! hasMoreElements() )
271 : {
272 : throw NoSuchElementException(
273 0 : "NoSuchElementException during enumeration", *this );
274 : }
275 0 : m_index ++;
276 0 : return m_vec[m_index];
277 : }
278 :
279 0 : Reference< XEnumeration > Container::createEnumeration( )
280 : throw (::com::sun::star::uno::RuntimeException, std::exception)
281 : {
282 0 : return new ContainerEnumeration( m_values );
283 : }
284 :
285 0 : void Container::addRefreshListener(
286 : const ::com::sun::star::uno::Reference< ::com::sun::star::util::XRefreshListener >& l )
287 : throw (::com::sun::star::uno::RuntimeException, std::exception)
288 : {
289 0 : rBHelper.addListener( getCppuType(&l) , l );
290 0 : }
291 :
292 0 : void Container::removeRefreshListener(
293 : const ::com::sun::star::uno::Reference< ::com::sun::star::util::XRefreshListener >& l )
294 : throw (::com::sun::star::uno::RuntimeException, std::exception)
295 : {
296 0 : rBHelper.removeListener( getCppuType(&l) , l );
297 0 : }
298 :
299 0 : void Container::disposing()
300 : {
301 0 : m_origin.clear();
302 0 : }
303 :
304 0 : void Container::rename( const OUString &oldName, const OUString &newName )
305 : {
306 0 : Any newValue;
307 : {
308 0 : osl::MutexGuard guard ( m_refMutex->mutex );
309 0 : String2IntMap::iterator ii = m_name2index.find( oldName );
310 0 : if( ii != m_name2index.end() )
311 : {
312 0 : sal_Int32 nIndex = ii->second;
313 0 : newValue = m_values[nIndex];
314 0 : m_name2index.erase( ii );
315 0 : m_name2index[ newName ] = nIndex;
316 0 : }
317 : }
318 0 : fire( ReplacedBroadcaster( *this, newName, newValue, oldName ) );
319 0 : fire( RefreshedBroadcaster( *this ) );
320 0 : }
321 :
322 0 : void Container::dropByName( const OUString& elementName )
323 : throw (::com::sun::star::sdbc::SQLException,
324 : ::com::sun::star::container::NoSuchElementException,
325 : ::com::sun::star::uno::RuntimeException, std::exception)
326 : {
327 0 : osl::MutexGuard guard( m_refMutex->mutex );
328 0 : String2IntMap::const_iterator ii = m_name2index.find( elementName );
329 0 : if( ii == m_name2index.end() )
330 : {
331 0 : OUStringBuffer buf( 128 );
332 0 : buf.appendAscii( "Column " );
333 0 : buf.append( elementName );
334 0 : buf.appendAscii( " is unknown in " );
335 0 : buf.append( m_type );
336 : // buf.appendAscii( " " );
337 : // buf.append( m_schemaName );
338 : // buf.appendAscii( "." );
339 : // buf.append( m_tableName );
340 0 : buf.appendAscii( " container, so it can't be dropped" );
341 : throw com::sun::star::container::NoSuchElementException(
342 0 : buf.makeStringAndClear(), *this );
343 : }
344 0 : dropByIndex( ii->second );
345 0 : }
346 :
347 0 : void Container::dropByIndex( sal_Int32 index )
348 : throw (::com::sun::star::sdbc::SQLException,
349 : ::com::sun::star::lang::IndexOutOfBoundsException,
350 : ::com::sun::star::uno::RuntimeException, std::exception)
351 : {
352 0 : osl::MutexGuard guard( m_refMutex->mutex );
353 0 : if( index < 0 || index >= m_values.getLength() )
354 : {
355 0 : OUStringBuffer buf( 128 );
356 0 : buf.appendAscii( "Index out of range (allowed 0 to " );
357 0 : buf.append((sal_Int32)(m_values.getLength() -1) );
358 0 : buf.appendAscii( ", got " );
359 0 : buf.append( index );
360 0 : buf.appendAscii( ") in " );
361 0 : buf.append( m_type );
362 : throw com::sun::star::lang::IndexOutOfBoundsException(
363 0 : buf.makeStringAndClear(), *this );
364 : }
365 :
366 0 : OUString name;
367 0 : for( String2IntMap::iterator ii = m_name2index.begin() ;
368 0 : ii != m_name2index.end() ;
369 : ++ ii )
370 : {
371 0 : if( ii->second == index )
372 : {
373 0 : name = ii->first;
374 0 : m_name2index.erase( ii );
375 0 : break;
376 : }
377 : }
378 :
379 0 : for( int i = index +1 ; i < m_values.getLength() ; i ++ )
380 : {
381 0 : m_values[i-1] = m_values[i];
382 :
383 : // I know, this is expensive, but don't want to maintain another map ...
384 0 : for( String2IntMap::iterator ii = m_name2index.begin() ;
385 0 : ii != m_name2index.end() ;
386 : ++ ii )
387 : {
388 0 : if( ii->second == i )
389 : {
390 0 : ii->second = i-1;
391 0 : break;
392 : }
393 : }
394 : }
395 0 : m_values.realloc( m_values.getLength() - 1 );
396 :
397 0 : fire( RemovedBroadcaster( *this, name ) );
398 0 : }
399 :
400 0 : void Container::append(
401 : const OUString & name,
402 : const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& descriptor )
403 : throw ( ::com::sun::star::container::ElementExistException )
404 :
405 : {
406 0 : osl::MutexGuard guard( m_refMutex->mutex );
407 :
408 0 : if( hasByName( name ) )
409 : {
410 0 : OUStringBuffer buf( 128 );
411 0 : buf.appendAscii( "a ");
412 0 : buf.append( m_type );
413 0 : buf.appendAscii( " with name " );
414 0 : buf.append( name );
415 0 : buf.appendAscii( " already exists in this container" );
416 : throw com::sun::star::container::ElementExistException(
417 0 : buf.makeStringAndClear() , *this );
418 : }
419 :
420 0 : int index = m_values.getLength();
421 0 : m_values.realloc( m_values.getLength() + 1 );
422 0 : m_values[index] = makeAny( descriptor );
423 0 : m_name2index[name] = index;
424 :
425 0 : fire( InsertedBroadcaster( *this, name, makeAny( descriptor ) ) );
426 0 : }
427 :
428 0 : void Container::appendByDescriptor(
429 : const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& descriptor)
430 : throw (::com::sun::star::sdbc::SQLException,
431 : ::com::sun::star::container::ElementExistException,
432 : ::com::sun::star::uno::RuntimeException, std::exception)
433 : {
434 0 : append( extractStringProperty( descriptor, getStatics().NAME ), descriptor );
435 0 : }
436 :
437 :
438 0 : void Container::addContainerListener(
439 : const ::com::sun::star::uno::Reference< ::com::sun::star::container::XContainerListener >& l )
440 : throw (::com::sun::star::uno::RuntimeException, std::exception)
441 : {
442 0 : rBHelper.addListener( getCppuType(&l) , l );
443 0 : }
444 :
445 0 : void Container::removeContainerListener(
446 : const ::com::sun::star::uno::Reference< ::com::sun::star::container::XContainerListener >& l )
447 : throw (::com::sun::star::uno::RuntimeException, std::exception)
448 : {
449 0 : rBHelper.removeListener( getCppuType(&l) , l );
450 0 : }
451 :
452 :
453 0 : void Container::fire( const EventBroadcastHelper &helper )
454 : {
455 0 : Reference< ::com::sun::star::util::XRefreshListener > l;
456 0 : cppu::OInterfaceContainerHelper *container = rBHelper.getContainer( helper.getType() );
457 0 : if( container )
458 : {
459 0 : cppu::OInterfaceIteratorHelper iterator( * container );
460 0 : while( iterator.hasMoreElements() )
461 : {
462 : try
463 : {
464 0 : helper.fire( static_cast<XEventListener *>(iterator.next()) );
465 : }
466 0 : catch ( com::sun::star::uno::RuntimeException & )
467 : {
468 : OSL_ENSURE( false, "exception catched" );
469 : // loose coupling, a runtime exception shall not break anything
470 : // TODO: log away as warning !
471 : }
472 0 : catch( com::sun::star::uno::Exception & )
473 : {
474 : OSL_ENSURE( false, "exception from listener flying through" );
475 0 : throw;
476 : }
477 0 : }
478 0 : }
479 :
480 0 : }
481 :
482 : }
483 :
484 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|