1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_ucb.hxx"
26
27 #include <vector>
28 #include <sortdynres.hxx>
29 #include <cppuhelper/interfacecontainer.hxx>
30 #include <com/sun/star/ucb/ContentResultSetCapability.hpp>
31 #include <com/sun/star/ucb/ListActionType.hpp>
32 #include <com/sun/star/ucb/WelcomeDynamicResultSetStruct.hpp>
33 #include <com/sun/star/ucb/XCachedDynamicResultSetStubFactory.hpp>
34 #include <com/sun/star/ucb/XSourceInitialization.hpp>
35
36 //-----------------------------------------------------------------------------
37 using namespace com::sun::star::beans;
38 using namespace com::sun::star::lang;
39 using namespace com::sun::star::sdbc;
40 using namespace com::sun::star::ucb;
41 using namespace com::sun::star::uno;
42 using namespace cppu;
43 using namespace rtl;
44
45 //=========================================================================
46
47 // The mutex to synchronize access to containers.
getContainerMutex()48 static osl::Mutex& getContainerMutex()
49 {
50 static osl::Mutex* pMutex = NULL;
51 if( !pMutex )
52 {
53 osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
54 if( !pMutex )
55 {
56 static osl::Mutex aMutex;
57 pMutex = &aMutex;
58 }
59 }
60
61 return *pMutex;
62 }
63
64 //=========================================================================
65 //
66 // SortedDynamicResultSet
67 //
68 //=========================================================================
69
SortedDynamicResultSet(const Reference<XDynamicResultSet> & xOriginal,const Sequence<NumberedSortingInfo> & aOptions,const Reference<XAnyCompareFactory> & xCompFac,const Reference<XMultiServiceFactory> & xSMgr)70 SortedDynamicResultSet::SortedDynamicResultSet(
71 const Reference < XDynamicResultSet > &xOriginal,
72 const Sequence < NumberedSortingInfo > &aOptions,
73 const Reference < XAnyCompareFactory > &xCompFac,
74 const Reference < XMultiServiceFactory > &xSMgr )
75 {
76 mpDisposeEventListeners = NULL;
77 mpOwnListener = new SortedDynamicResultSetListener( this );
78
79 mxOwnListener = Reference< XDynamicResultSetListener >( mpOwnListener );
80
81 mxOriginal = xOriginal;
82 maOptions = aOptions;
83 mxCompFac = xCompFac;
84 mxSMgr = xSMgr;
85
86 mpOne = NULL;
87 mpTwo = NULL;
88
89 mbGotWelcome = sal_False;
90 mbUseOne = sal_True;
91 mbStatic = sal_False;
92 }
93
94 //--------------------------------------------------------------------------
~SortedDynamicResultSet()95 SortedDynamicResultSet::~SortedDynamicResultSet()
96 {
97 mpOwnListener->impl_OwnerDies();
98 mxOwnListener.clear();
99
100 delete mpDisposeEventListeners;
101
102 mxOne.clear();
103 mxTwo.clear();
104 mxOriginal.clear();
105
106 mpOne = NULL;
107 mpTwo = NULL;
108 }
109
110 //--------------------------------------------------------------------------
111 // XInterface methods.
112 //--------------------------------------------------------------------------
113
114 XINTERFACE_IMPL_4( SortedDynamicResultSet,
115 XTypeProvider,
116 XServiceInfo,
117 XComponent, /* base class of XDynamicResultSet */
118 XDynamicResultSet );
119
120 //--------------------------------------------------------------------------
121 // XTypeProvider methods.
122 //--------------------------------------------------------------------------
123
124 XTYPEPROVIDER_IMPL_3( SortedDynamicResultSet,
125 XTypeProvider,
126 XServiceInfo,
127 XDynamicResultSet );
128
129 //--------------------------------------------------------------------------
130 // XServiceInfo methods.
131 //--------------------------------------------------------------------------
132
133 XSERVICEINFO_NOFACTORY_IMPL_1( SortedDynamicResultSet,
134 OUString::createFromAscii(
135 "com.sun.star.comp.ucb.SortedDynamicResultSet" ),
136 OUString::createFromAscii(
137 DYNAMIC_RESULTSET_SERVICE_NAME ) );
138
139 //--------------------------------------------------------------------------
140 // XComponent methods.
141 //--------------------------------------------------------------------------
dispose()142 void SAL_CALL SortedDynamicResultSet::dispose()
143 throw( RuntimeException )
144 {
145 osl::Guard< osl::Mutex > aGuard( maMutex );
146
147 if ( mpDisposeEventListeners && mpDisposeEventListeners->getLength() )
148 {
149 EventObject aEvt;
150 aEvt.Source = static_cast< XComponent * >( this );
151 mpDisposeEventListeners->disposeAndClear( aEvt );
152 }
153
154 mxOne.clear();
155 mxTwo.clear();
156 mxOriginal.clear();
157
158 mpOne = NULL;
159 mpTwo = NULL;
160 mbUseOne = sal_True;
161 }
162
163 //--------------------------------------------------------------------------
addEventListener(const Reference<XEventListener> & Listener)164 void SAL_CALL SortedDynamicResultSet::addEventListener(
165 const Reference< XEventListener >& Listener )
166 throw( RuntimeException )
167 {
168 osl::Guard< osl::Mutex > aGuard( maMutex );
169
170 if ( !mpDisposeEventListeners )
171 mpDisposeEventListeners =
172 new OInterfaceContainerHelper( getContainerMutex() );
173
174 mpDisposeEventListeners->addInterface( Listener );
175 }
176
177 //--------------------------------------------------------------------------
removeEventListener(const Reference<XEventListener> & Listener)178 void SAL_CALL SortedDynamicResultSet::removeEventListener(
179 const Reference< XEventListener >& Listener )
180 throw( RuntimeException )
181 {
182 osl::Guard< osl::Mutex > aGuard( maMutex );
183
184 if ( mpDisposeEventListeners )
185 mpDisposeEventListeners->removeInterface( Listener );
186 }
187
188 //--------------------------------------------------------------------------
189 // XDynamicResultSet methods.
190 // ------------------------------------------------------------------------------
191 Reference< XResultSet > SAL_CALL
getStaticResultSet()192 SortedDynamicResultSet::getStaticResultSet()
193 throw( ListenerAlreadySetException, RuntimeException )
194 {
195 osl::Guard< osl::Mutex > aGuard( maMutex );
196
197 if ( mxListener.is() )
198 throw ListenerAlreadySetException();
199
200 mbStatic = sal_True;
201
202 if ( mxOriginal.is() )
203 {
204 mpOne = new SortedResultSet( mxOriginal->getStaticResultSet() );
205 mxOne = mpOne;
206 mpOne->Initialize( maOptions, mxCompFac );
207 }
208
209 return mxOne;
210 }
211
212 // ------------------------------------------------------------------------------
213 void SAL_CALL
setListener(const Reference<XDynamicResultSetListener> & Listener)214 SortedDynamicResultSet::setListener( const Reference< XDynamicResultSetListener >& Listener )
215 throw( ListenerAlreadySetException, RuntimeException )
216 {
217 osl::Guard< osl::Mutex > aGuard( maMutex );
218
219 if ( mxListener.is() )
220 throw ListenerAlreadySetException();
221
222 addEventListener( Reference< XEventListener >::query( Listener ) );
223
224 mxListener = Listener;
225
226 if ( mxOriginal.is() )
227 mxOriginal->setListener( mxOwnListener );
228 }
229
230 // ------------------------------------------------------------------------------
231 void SAL_CALL
connectToCache(const Reference<XDynamicResultSet> & xCache)232 SortedDynamicResultSet::connectToCache(
233 const Reference< XDynamicResultSet > & xCache )
234 throw( ListenerAlreadySetException,
235 AlreadyInitializedException,
236 ServiceNotFoundException,
237 RuntimeException )
238 {
239 if( mxListener.is() )
240 throw ListenerAlreadySetException();
241
242 if( mbStatic )
243 throw ListenerAlreadySetException();
244
245 Reference< XSourceInitialization > xTarget( xCache, UNO_QUERY );
246 if( xTarget.is() && mxSMgr.is() )
247 {
248 Reference< XCachedDynamicResultSetStubFactory > xStubFactory;
249 try
250 {
251 xStubFactory = Reference< XCachedDynamicResultSetStubFactory >(
252 mxSMgr->createInstance(
253 OUString::createFromAscii(
254 "com.sun.star.ucb.CachedDynamicResultSetStubFactory" ) ),
255 UNO_QUERY );
256 }
257 catch ( Exception const & )
258 {
259 }
260
261 if( xStubFactory.is() )
262 {
263 xStubFactory->connectToCache(
264 this, xCache, Sequence< NumberedSortingInfo > (), NULL );
265 return;
266 }
267 }
268 throw ServiceNotFoundException();
269 }
270
271 // ------------------------------------------------------------------------------
272 sal_Int16 SAL_CALL
getCapabilities()273 SortedDynamicResultSet::getCapabilities()
274 throw( RuntimeException )
275 {
276 osl::Guard< osl::Mutex > aGuard( maMutex );
277
278 sal_Int16 nCaps = 0;
279
280 if ( mxOriginal.is() )
281 nCaps = mxOriginal->getCapabilities();
282
283 nCaps |= ContentResultSetCapability::SORTED;
284
285 return nCaps;
286 }
287
288 //--------------------------------------------------------------------------
289 // XDynamicResultSetListener methods.
290 // ------------------------------------------------------------------------------
291
292 /** In the first notify-call the listener gets the two
293 <type>XResultSet</type>s and has to hold them. The <type>XResultSet</type>s
294 are implementations of the service <type>ContentResultSet</type>.
295
296 <p>The notified new <type>XResultSet</type> will stay valid after returning
297 notification. The old one will become invalid after returning notification.
298
299 <p>While in notify-call the listener is allowed to read old and new version,
300 except in the first call, where only the new Resultset is valid.
301
302 <p>The Listener is allowed to blockade this call, until he really want to go
303 to the new version. The only situation, where the listener has to return the
304 update call at once is, while he disposes his broadcaster or while he is
305 removing himsef as listener (otherwise you deadlock)!!!
306 */
307 void SAL_CALL
impl_notify(const ListEvent & Changes)308 SortedDynamicResultSet::impl_notify( const ListEvent& Changes )
309 throw( RuntimeException )
310 {
311 osl::Guard< osl::Mutex > aGuard( maMutex );
312
313 sal_Bool bHasNew = sal_False;
314 sal_Bool bHasModified = sal_False;
315
316 SortedResultSet *pCurSet = NULL;
317
318 // mxNew und mxOld vertauschen und anschliessend die Tabellen von Old
319 // nach New kopieren
320 if ( mbGotWelcome )
321 {
322 if ( mbUseOne )
323 {
324 mbUseOne = sal_False;
325 mpTwo->CopyData( mpOne );
326 pCurSet = mpTwo;
327 }
328 else
329 {
330 mbUseOne = sal_True;
331 mpOne->CopyData( mpTwo );
332 pCurSet = mpOne;
333 }
334 }
335
336 Any aRet;
337
338 try {
339 aRet = pCurSet->getPropertyValue( OUString::createFromAscii( "IsRowCountFinal" ) );
340 }
341 catch ( UnknownPropertyException ) {}
342 catch ( WrappedTargetException ) {}
343
344 long nOldCount = pCurSet->GetCount();
345 sal_Bool bWasFinal = false;
346
347 aRet >>= bWasFinal;
348
349 // handle the actions in the list
350 for ( long i=0; i<Changes.Changes.getLength(); i++ )
351 {
352 const ListAction aAction = Changes.Changes[i];
353 switch ( aAction.ListActionType )
354 {
355 case ListActionType::WELCOME:
356 {
357 WelcomeDynamicResultSetStruct aWelcome;
358 if ( aAction.ActionInfo >>= aWelcome )
359 {
360 mpTwo = new SortedResultSet( aWelcome.Old );
361 mxTwo = mpTwo;
362 mpOne = new SortedResultSet( aWelcome.New );
363 mxOne = mpOne;
364 mpOne->Initialize( maOptions, mxCompFac );
365 mbGotWelcome = sal_True;
366 mbUseOne = sal_True;
367 pCurSet = mpOne;
368
369 aWelcome.Old = mxTwo;
370 aWelcome.New = mxOne;
371
372 ListAction *pWelcomeAction = new ListAction;
373 pWelcomeAction->ActionInfo <<= aWelcome;
374 pWelcomeAction->Position = 0;
375 pWelcomeAction->Count = 0;
376 pWelcomeAction->ListActionType = ListActionType::WELCOME;
377
378 maActions.Insert( pWelcomeAction );
379 }
380 else
381 {
382 // throw RuntimeException();
383 }
384 break;
385 }
386 case ListActionType::INSERTED:
387 {
388 pCurSet->InsertNew( aAction.Position, aAction.Count );
389 bHasNew = sal_True;
390 break;
391 }
392 case ListActionType::REMOVED:
393 {
394 pCurSet->Remove( aAction.Position,
395 aAction.Count,
396 &maActions );
397 break;
398 }
399 case ListActionType::MOVED:
400 {
401 long nOffset = 0;
402 if ( aAction.ActionInfo >>= nOffset )
403 {
404 pCurSet->Move( aAction.Position,
405 aAction.Count,
406 nOffset );
407 }
408 break;
409 }
410 case ListActionType::PROPERTIES_CHANGED:
411 {
412 pCurSet->SetChanged( aAction.Position, aAction.Count );
413 bHasModified = sal_True;
414 break;
415 }
416 default: break;
417 }
418 }
419
420 if ( bHasModified )
421 pCurSet->ResortModified( &maActions );
422
423 if ( bHasNew )
424 pCurSet->ResortNew( &maActions );
425
426 // send the new actions with a notify to the listeners
427 SendNotify();
428
429 // check for propertyChangeEvents
430 pCurSet->CheckProperties( nOldCount, bWasFinal );
431 }
432
433 //-----------------------------------------------------------------
434 // XEventListener
435 //-----------------------------------------------------------------
436 void SAL_CALL
impl_disposing(const EventObject &)437 SortedDynamicResultSet::impl_disposing( const EventObject& )
438 throw( RuntimeException )
439 {
440 mxListener.clear();
441 mxOriginal.clear();
442 }
443
444 // ------------------------------------------------------------------------------
445 // private methods
446 // ------------------------------------------------------------------------------
SendNotify()447 void SortedDynamicResultSet::SendNotify()
448 {
449 long nCount = maActions.Count();
450
451 if ( nCount && mxListener.is() )
452 {
453 Sequence< ListAction > aActionList( maActions.Count() );
454 ListAction *pActionList = aActionList.getArray();
455
456 for ( long i=0; i<nCount; i++ )
457 {
458 pActionList[ i ] = *(maActions.GetAction( i ));
459 }
460
461 ListEvent aNewEvent;
462 aNewEvent.Changes = aActionList;
463
464 mxListener->notify( aNewEvent );
465 }
466
467 // clean up
468 maActions.Clear();
469 }
470
471 //=========================================================================
472 //
473 // SortedDynamicResultSetFactory
474 //
475 //=========================================================================
SortedDynamicResultSetFactory(const Reference<XMultiServiceFactory> & rSMgr)476 SortedDynamicResultSetFactory::SortedDynamicResultSetFactory(
477 const Reference< XMultiServiceFactory > & rSMgr )
478 {
479 mxSMgr = rSMgr;
480 }
481
482 //--------------------------------------------------------------------------
~SortedDynamicResultSetFactory()483 SortedDynamicResultSetFactory::~SortedDynamicResultSetFactory()
484 {
485 }
486
487 //--------------------------------------------------------------------------
488 // XInterface methods.
489 //--------------------------------------------------------------------------
490
491 XINTERFACE_IMPL_3( SortedDynamicResultSetFactory,
492 XTypeProvider,
493 XServiceInfo,
494 XSortedDynamicResultSetFactory );
495
496 //--------------------------------------------------------------------------
497 // XTypeProvider methods.
498 //--------------------------------------------------------------------------
499
500 XTYPEPROVIDER_IMPL_3( SortedDynamicResultSetFactory,
501 XTypeProvider,
502 XServiceInfo,
503 XSortedDynamicResultSetFactory );
504
505 //--------------------------------------------------------------------------
506 // XServiceInfo methods.
507 //--------------------------------------------------------------------------
508
509 XSERVICEINFO_IMPL_1( SortedDynamicResultSetFactory,
510 OUString::createFromAscii(
511 "com.sun.star.comp.ucb.SortedDynamicResultSetFactory" ),
512 OUString::createFromAscii(
513 DYNAMIC_RESULTSET_FACTORY_NAME ) );
514
515 //--------------------------------------------------------------------------
516 // Service factory implementation.
517 //--------------------------------------------------------------------------
518
519 ONE_INSTANCE_SERVICE_FACTORY_IMPL( SortedDynamicResultSetFactory );
520
521 //--------------------------------------------------------------------------
522 // SortedDynamicResultSetFactory methods.
523 //--------------------------------------------------------------------------
524 Reference< XDynamicResultSet > SAL_CALL
createSortedDynamicResultSet(const Reference<XDynamicResultSet> & Source,const Sequence<NumberedSortingInfo> & Info,const Reference<XAnyCompareFactory> & CompareFactory)525 SortedDynamicResultSetFactory::createSortedDynamicResultSet(
526 const Reference< XDynamicResultSet > & Source,
527 const Sequence< NumberedSortingInfo > & Info,
528 const Reference< XAnyCompareFactory > & CompareFactory )
529 throw( RuntimeException )
530 {
531 Reference< XDynamicResultSet > xRet;
532 xRet = new SortedDynamicResultSet( Source, Info, CompareFactory, mxSMgr );
533 return xRet;
534 }
535
536 //=========================================================================
537 //
538 // EventList
539 //
540 //=========================================================================
541
Clear()542 void EventList::Clear()
543 {
544 for ( std::deque< LISTACTION* >::size_type i = 0;
545 i < maData.size(); ++i )
546 {
547 delete maData[i];
548 }
549
550 maData.clear();
551 }
552
553 //--------------------------------------------------------------------------
AddEvent(long nType,long nPos,long nCount)554 void EventList::AddEvent( long nType, long nPos, long nCount )
555 {
556 ListAction *pAction = new ListAction;
557 pAction->Position = nPos;
558 pAction->Count = nCount;
559 pAction->ListActionType = nType;
560
561 Insert( pAction );
562 }
563
564 //=================================================================
565 //
566 // SortedDynamicResultSetListener
567 //
568 //=================================================================
569
SortedDynamicResultSetListener(SortedDynamicResultSet * mOwner)570 SortedDynamicResultSetListener::SortedDynamicResultSetListener(
571 SortedDynamicResultSet *mOwner )
572 {
573 mpOwner = mOwner;
574 }
575
576 //-----------------------------------------------------------------
~SortedDynamicResultSetListener()577 SortedDynamicResultSetListener::~SortedDynamicResultSetListener()
578 {
579 }
580
581 //-----------------------------------------------------------------
582 // XInterface methods.
583 //-----------------------------------------------------------------
584
585 XINTERFACE_IMPL_2( SortedDynamicResultSetListener,
586 XEventListener, /* base class of XDynamicResultSetListener */
587 XDynamicResultSetListener );
588
589 //-----------------------------------------------------------------
590 // XEventListener ( base of XDynamicResultSetListener )
591 //-----------------------------------------------------------------
592 void SAL_CALL
disposing(const EventObject & Source)593 SortedDynamicResultSetListener::disposing( const EventObject& Source )
594 throw( RuntimeException )
595 {
596 osl::Guard< osl::Mutex > aGuard( maMutex );
597
598 if ( mpOwner )
599 mpOwner->impl_disposing( Source );
600 }
601
602 //-----------------------------------------------------------------
603 // XDynamicResultSetListener
604 //-----------------------------------------------------------------
605 void SAL_CALL
notify(const ListEvent & Changes)606 SortedDynamicResultSetListener::notify( const ListEvent& Changes )
607 throw( RuntimeException )
608 {
609 osl::Guard< osl::Mutex > aGuard( maMutex );
610
611 if ( mpOwner )
612 mpOwner->impl_notify( Changes );
613 }
614
615 //-----------------------------------------------------------------
616 // own methods:
617 //-----------------------------------------------------------------
618 void SAL_CALL
impl_OwnerDies()619 SortedDynamicResultSetListener::impl_OwnerDies()
620 {
621 osl::Guard< osl::Mutex > aGuard( maMutex );
622 mpOwner = NULL;
623 }
624
625