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 #ifndef __FRAMEWORK_DISPATCH_BASEDISPATCHER_HXX_
25 #define __FRAMEWORK_DISPATCH_BASEDISPATCHER_HXX_
26 
27 //_________________________________________________________________________________________________________________
28 //	my own includes
29 //_________________________________________________________________________________________________________________
30 
31 #include <classes/taskcreator.hxx>
32 #include <threadhelp/resetableguard.hxx>
33 #include <threadhelp/threadhelpbase.hxx>
34 
35 #ifndef __FRAMEWORK_THREADHELP_TRANSACTIONBASE_HXX_
36 #include <threadhelp/transactionbase.hxx>
37 #endif
38 #include <macros/xinterface.hxx>
39 #include <macros/xtypeprovider.hxx>
40 #include <macros/debug.hxx>
41 #include <macros/generic.hxx>
42 #include <stdtypes.h>
43 
44 //_________________________________________________________________________________________________________________
45 //	interface includes
46 //_________________________________________________________________________________________________________________
47 #include <com/sun/star/lang/XTypeProvider.hpp>
48 #include <com/sun/star/frame/XNotifyingDispatch.hpp>
49 #include <com/sun/star/util/URL.hpp>
50 #include <com/sun/star/frame/DispatchDescriptor.hpp>
51 #include <com/sun/star/beans/PropertyValue.hpp>
52 #include <com/sun/star/frame/XDispatchResultListener.hpp>
53 #include <com/sun/star/frame/XFrameLoader.hpp>
54 #include <com/sun/star/frame/XLoadEventListener.hpp>
55 #include <com/sun/star/frame/XDesktop.hpp>
56 #include <com/sun/star/frame/FeatureStateEvent.hpp>
57 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
58 
59 //_________________________________________________________________________________________________________________
60 //	other includes
61 //_________________________________________________________________________________________________________________
62 #include <cppuhelper/weak.hxx>
63 #include <cppuhelper/weakref.hxx>
64 #include <cppuhelper/interfacecontainer.h>
65 /*DRAFT
66 #include <unotools/historyoptions.hxx>
67 */
68 
69 //_________________________________________________________________________________________________________________
70 //	namespace
71 //_________________________________________________________________________________________________________________
72 
73 namespace framework{
74 
75 //_________________________________________________________________________________________________________________
76 //	exported const
77 //_________________________________________________________________________________________________________________
78 
79 //_________________________________________________________________________________________________________________
80 //	exported definitions
81 //_________________________________________________________________________________________________________________
82 
83 /*-************************************************************************************************************//**
84     @descr      We must support loading of different URLs with different handler or loader into different tasks simultaniously.
85                 They call us back to return state of operation. We need some informations to distinguish
86                 between these different "loading threads".
87                 This is the reason to implement this dynamicly list.
88 
89     @attention  I marked class LoaderThreads threadsafe! Using will be easier in a multithreaded environment.
90                 struct DispatchBinding doesn't need that!
91 *//*-*************************************************************************************************************/
92 struct LoadBinding
93 {
94     //-------------------------------------------------------------------------------------------------------------
95     public:
96 
97         //---------------------------------------------------------------------------------------------------------
LoadBindingframework::LoadBinding98         inline LoadBinding()
99         {
100             free();
101         }
102 
103         //---------------------------------------------------------------------------------------------------------
104         // use to initialize struct for asynchronous dispatching by using handler
LoadBindingframework::LoadBinding105         inline LoadBinding( const css::util::URL&                                   aNewURL         ,
106                             const css::uno::Sequence< css::beans::PropertyValue >   lNewDescriptor  ,
107                             const css::uno::Reference< css::frame::XDispatch >&     xNewHandler     ,
108                             const css::uno::Any&                                    aNewAsyncInfo   )
109         {
110             free();
111             xHandler    = xNewHandler   ;
112             aURL        = aNewURL       ;
113             lDescriptor = lNewDescriptor;
114             aAsyncInfo  = aNewAsyncInfo ;
115         }
116 
117         //---------------------------------------------------------------------------------------------------------
118         // use to initialize struct for asynchronous loading by using frame loader
LoadBindingframework::LoadBinding119         inline LoadBinding( const css::util::URL&                                   aNewURL         ,
120                             const css::uno::Sequence< css::beans::PropertyValue >   lNewDescriptor  ,
121                             const css::uno::Reference< css::frame::XFrame >&        xNewFrame       ,
122                             const css::uno::Reference< css::frame::XFrameLoader >&  xNewLoader      ,
123                             const css::uno::Any&                                    aNewAsyncInfo   )
124         {
125             free();
126             xLoader     = xNewLoader    ;
127             xFrame      = xNewFrame     ;
128             aURL        = aNewURL       ;
129             lDescriptor = lNewDescriptor;
130             aAsyncInfo  = aNewAsyncInfo ;
131         }
132 
133         //---------------------------------------------------------------------------------------------------------
134         // dont forget toe release used references
~LoadBindingframework::LoadBinding135         inline ~LoadBinding()
136         {
137             free();
138         }
139 
140         //---------------------------------------------------------------------------------------------------------
freeframework::LoadBinding141         inline void free()
142         {
143             xHandler    = css::uno::Reference< css::frame::XDispatch >()   ;
144             xLoader     = css::uno::Reference< css::frame::XFrameLoader >();
145             xFrame      = css::uno::Reference< css::frame::XFrame >()      ;
146             aURL        = css::util::URL()                                 ;
147             lDescriptor = css::uno::Sequence< css::beans::PropertyValue >();
148             aAsyncInfo  = css::uno::Any()                                  ;
149         }
150 
151     //-------------------------------------------------------------------------------------------------------------
152     public:
153         css::uno::Reference< css::frame::XDispatch >        xHandler    ;   // if handler was used, this reference will be valid
154         css::uno::Reference< css::frame::XFrameLoader >     xLoader     ;   // if loader was used, this reference will be valid
155         css::uno::Reference< css::frame::XFrame >           xFrame      ;   // Target of loading
156         css::util::URL                                      aURL        ;   // dispatched URL - necessary to find listener for status event!
157         css::uno::Sequence< css::beans::PropertyValue >     lDescriptor ;   // dispatched arguments - necessary for "reactForLoadingState()"!
158         css::uno::Any                                       aAsyncInfo  ;   // superclasses could use them to save her own user specific data for these asynchron call-info
159         css::uno::Reference< css::frame::XDispatchResultListener > xListener;
160 };
161 
162 //*****************************************************************************************************************
163 class LoaderThreads : private ::std::vector< LoadBinding >
164                     , private ThreadHelpBase
165 {
166     //-------------------------------------------------------------------------------------------------------------
167     public:
168 
169         //---------------------------------------------------------------------------------------------------------
LoaderThreads()170         inline LoaderThreads()
171                 : ThreadHelpBase()
172         {
173         }
174 
175         //---------------------------------------------------------------------------------------------------------
append(const LoadBinding & aBinding)176         inline void append( const LoadBinding& aBinding )
177         {
178             ResetableGuard aGuard( m_aLock );
179             push_back( aBinding );
180         }
181 
182         //---------------------------------------------------------------------------------------------------------
183         /// search for handler thread in list which match given parameter and delete it
searchAndForget(const css::uno::Reference<css::frame::XDispatchResultListener> & rListener,LoadBinding & aBinding)184         inline sal_Bool searchAndForget( const css::uno::Reference < css::frame::XDispatchResultListener >& rListener, LoadBinding& aBinding )
185         {
186             ResetableGuard aGuard( m_aLock );
187             sal_Bool bFound = sal_False;
188             for( iterator pItem=begin(); pItem!=end(); ++pItem )
189             {
190                 if( pItem->xListener == rListener )
191                 {
192                     aBinding = *pItem;
193                     erase( pItem );
194                     bFound = sal_True;
195                     break;
196                 }
197             }
198             return bFound;
199         }
200 
201         //---------------------------------------------------------------------------------------------------------
202         /// search for loader thread in list which match given parameter and delete it
searchAndForget(const css::uno::Reference<css::frame::XFrameLoader> xLoader,LoadBinding & aBinding)203         inline sal_Bool searchAndForget( const css::uno::Reference< css::frame::XFrameLoader > xLoader, LoadBinding& aBinding )
204         {
205             ResetableGuard aGuard( m_aLock );
206             sal_Bool bFound = sal_False;
207             for( iterator pItem=begin(); pItem!=end(); ++pItem )
208             {
209                 if( pItem->xLoader == xLoader )
210                 {
211                     aBinding = *pItem;
212                     erase( pItem );
213                     bFound = sal_True;
214                     break;
215                 }
216             }
217             return bFound;
218         }
219 
220         //---------------------------------------------------------------------------------------------------------
221         // free ALL memory ... I hope it
free()222         inline void free()
223         {
224             ResetableGuard aGuard( m_aLock );
225             LoaderThreads().swap( *this );
226         }
227 };
228 
229 /*-************************************************************************************************************//**
230     @short          base class for dispatcher implementations
231     @descr          Most of our dispatch implementations do every time the same. They try to handle or load
232                     something into a target ... normally a frame/task/pluginframe!
233                     They must do it synchron or sometimes asynchron. They must wait for callbacks and
234                     notify registered listener with right status events.
235                     All these things are implemented by this baseclass. You should override some methods
236                     to change something.
237 
238                     "dispatch()"                =>  should be you dispatch algorithm
239                     "reactForLoadingState()"    =>  do something depending from loading state ...
240 
241 	@implements		XInterface
242 					XDispatch
243                     XLoadEventListener
244 					XEventListener
245 
246 	@base			ThreadHelpBase
247                     TransactionBase
248 					OWeakObject
249 
250 	@devstatus		ready to use
251     @threadsafe     yes
252 *//*-*************************************************************************************************************/
253 class BaseDispatcher    :   // interfaces
254                             public    css::lang::XTypeProvider                 ,
255                             public    css::frame::XNotifyingDispatch           ,
256                             public    css::frame::XLoadEventListener           ,   // => XEventListener too!
257                             // baseclasses
258                             // Order is necessary for right initialization!
259                             protected ThreadHelpBase                           ,
260                             protected TransactionBase                          ,
261                             public    ::cppu::OWeakObject
262 {
263 	//-------------------------------------------------------------------------------------------------------------
264 	//	public methods
265 	//-------------------------------------------------------------------------------------------------------------
266 	public:
267 
268 		//	constructor / destructor
269         BaseDispatcher( const css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory    ,
270                         const css::uno::Reference< css::frame::XFrame >&              xOwnerFrame );
271 
272         void dispatchFinished ( const css::frame::DispatchResultEvent& aEvent, const css::uno::Reference < css::frame::XDispatchResultListener >& rListener );
273 
274 		//	XInterface
275 		DECLARE_XINTERFACE
276 		DECLARE_XTYPEPROVIDER
277 
278         //  XNotifyingDispatch
279         virtual void SAL_CALL dispatchWithNotification ( const css::util::URL& aURL,
280                                                       const css::uno::Sequence< css::beans::PropertyValue >& aArgs,
281                                                       const css::uno::Reference< css::frame::XDispatchResultListener >& Listener ) throw ( css::uno::RuntimeException);
282 
283         //  XDispatch
284         virtual void SAL_CALL dispatch              ( const css::util::URL&                                     aURL       ,
285                                                       const css::uno::Sequence< css::beans::PropertyValue >&    lArguments ) throw( css::uno::RuntimeException ) = 0;
286         virtual void SAL_CALL addStatusListener     ( const css::uno::Reference< css::frame::XStatusListener >& xListener  ,
287                                                       const css::util::URL&                                     aURL       ) throw( css::uno::RuntimeException );
288         virtual void SAL_CALL removeStatusListener  ( const css::uno::Reference< css::frame::XStatusListener >& xListener  ,
289                                                       const css::util::URL&                                     aURL       ) throw( css::uno::RuntimeException );
290 
291         //   XLoadEventListener
292         virtual void SAL_CALL loadFinished          ( const css::uno::Reference< css::frame::XFrameLoader >&    xLoader    ) throw( css::uno::RuntimeException );
293         virtual void SAL_CALL loadCancelled         ( const css::uno::Reference< css::frame::XFrameLoader >&    xLoader    ) throw( css::uno::RuntimeException );
294 
295 		//	 XEventListener
296         virtual void SAL_CALL disposing             ( const css::lang::EventObject&                             aEvent     ) throw( css::uno::RuntimeException );
297 
298 	//-------------------------------------------------------------------------------------------------------------
299 	//	protected methods
300 	//-------------------------------------------------------------------------------------------------------------
301 	protected:
302         virtual ~BaseDispatcher();
303 
304         /*-****************************************************************************************************//**
305             @short      you should react for successfully or failed load/handle operations.
306             @descr      These baseclass implement handling of dispatched URLs and synchronous/asynchronous loading
307                         of it into a target frame. It implement the complete listener mechanism to get events from
308                         used loader or handler and sending of status events to registered listener too!
309                         But we couldn't react for this events in all cases.
310                         May be - you wish to reactivate suspended controllers or wish to delete a new created
311                         task if operation failed ...!?
312                         By overwriting these pure virtual methods it's possible to do such things.
313                         We call you with all available informations ... you should react for it.
314                         BUT - don't send any status events to your listener! We will do it every time.
315                         (other listener could be informed as well!)
316 
317                         You will called back in: a) "reactForLoadingState()" , if URL was loaded into a frame
318                                                  b) "reactForHandlingState()", if URL was handled by a registered content handler
319                                                                                (without using a target frame!)
320 
321             @seealso    method statusChanged()
322             @seealso    method loadFinished()
323             @seealso    method loadCancelled()
324 
325             @param      "aURL"         , original dispatched URL
326             @param      "lDescriptor"  , original dispatched arguments
327             @param      "xTarget"      , target of operation (could be NULL if URL was handled not loaded!)
328             @param      "bState"       , state of operation
329             @return     -
330 
331             @onerror    -
332             @threadsafe -
333         *//*-*****************************************************************************************************/
334         virtual void SAL_CALL reactForLoadingState ( const css::util::URL&                                  aURL          ,
335                                                      const css::uno::Sequence< css::beans::PropertyValue >& lDescriptor   ,
336                                                      const css::uno::Reference< css::frame::XFrame >&       xTarget       ,
337                                                            sal_Bool                                         bState        ,
338                                                      const css::uno::Any&                                   aAsyncInfo    ) = 0;
339 
340         virtual void SAL_CALL reactForHandlingState( const css::util::URL&                                  aURL          ,
341                                                      const css::uno::Sequence< css::beans::PropertyValue >& lDescriptor   ,
342                                                            sal_Bool                                         bState        ,
343                                                      const css::uno::Any&                                   aAsyncInfo    ) = 0;
344 
345 	//-------------------------------------------------------------------------------------------------------------
346     //  protected methods
347 	//-------------------------------------------------------------------------------------------------------------
348     protected:
349         ::rtl::OUString implts_detectType           ( const css::util::URL&                                   aURL            ,
350                                                             css::uno::Sequence< css::beans::PropertyValue >&  lDescriptor     ,
351                                                             sal_Bool                                          bDeep           );
352         sal_Bool        implts_handleIt             ( const css::util::URL&                                   aURL            ,
353                                                             css::uno::Sequence< css::beans::PropertyValue >&  lDescriptor     ,
354                                                       const ::rtl::OUString&                                  sTypeName       ,
355                                                       const css::uno::Any&                                    aAsyncInfo      = css::uno::Any() );
356         sal_Bool        implts_loadIt               ( const css::util::URL&                                   aURL            ,
357                                                             css::uno::Sequence< css::beans::PropertyValue >&  lDescriptor     ,
358                                                       const ::rtl::OUString&                                  sTypeName       ,
359                                                       const css::uno::Reference< css::frame::XFrame >&        xTarget         ,
360                                                       const css::uno::Any&                                    aAsyncInfo      = css::uno::Any() );
361         void            implts_enableFrame          ( const css::uno::Reference< css::frame::XFrame >&        xFrame          ,
362                                                       const css::uno::Sequence< css::beans::PropertyValue >&  lDescriptor     );
363         void            implts_disableFrame         ( const css::uno::Reference< css::frame::XFrame >&        xFrame          );
364         sal_Bool        implts_deactivateController ( const css::uno::Reference< css::frame::XController >&   xController     );
365         sal_Bool        implts_reactivateController ( const css::uno::Reference< css::frame::XController >&   xController     );
366         void            implts_sendResultEvent      ( const css::uno::Reference< css::frame::XFrame >&        xEventSource    ,
367                                                       const ::rtl::OUString&                                  sURL            ,
368                                                             sal_Bool                                          bLoadState      );
369 
370 	//-------------------------------------------------------------------------------------------------------------
371 	//	variables
372     //  - should be private normally ...
373     //  - but some super classes need access to some of them => protected!
374 	//-------------------------------------------------------------------------------------------------------------
375     protected:
376         css::uno::Reference< css::lang::XMultiServiceFactory >      m_xFactory            ;   /// global uno service manager to create new services
377         css::uno::WeakReference< css::frame::XFrame >               m_xOwner              ;   /// weakreference to owner (Don't use a hard reference. Owner can't delete us then!)
378 
379     private:
380         LoaderThreads                                               m_aLoaderThreads      ;   /// list of bindings between handler/loader, tasks and loaded URLs
381         ListenerHash                                                m_aListenerContainer  ;   /// hash table for listener at specified URLs
382 
383 };      //  class BaseDispatcher
384 
385 }		//	namespace framework
386 
387 #endif  //  #ifndef __FRAMEWORK_DISPATCH_BASEDISPATCHER_HXX_
388