1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_framework.hxx"
30 
31 //_______________________________________________
32 // my own includes
33 #include <services/dispatchhelper.hxx>
34 #include <threadhelp/readguard.hxx>
35 #include <threadhelp/writeguard.hxx>
36 #include <services.h>
37 
38 //_______________________________________________
39 // interface includes
40 #include <com/sun/star/util/XURLTransformer.hpp>
41 #include <com/sun/star/frame/XNotifyingDispatch.hpp>
42 
43 //_______________________________________________
44 // includes of other projects
45 
46 //_______________________________________________
47 // namespace
48 
49 namespace framework{
50 
51 //_______________________________________________
52 // non exported const
53 
54 //_______________________________________________
55 // non exported definitions
56 
57 //_______________________________________________
58 // declarations
59 
60 //_______________________________________________
61 // XInterface, XTypeProvider, XServiceInfo
62 
63 DEFINE_XSERVICEINFO_MULTISERVICE(DispatchHelper                   ,
64                                  ::cppu::OWeakObject              ,
65                                  SERVICENAME_DISPATCHHELPER       ,
66                                  IMPLEMENTATIONNAME_DISPATCHHELPER)
67 
68 DEFINE_INIT_SERVICE( DispatchHelper, {} )
69 
70 //_______________________________________________
71 
72 /** ctor.
73 
74     @param xSMGR    the global uno service manager, which can be used to create own needed services.
75 */
76 DispatchHelper::DispatchHelper( const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR )
77         :   ThreadHelpBase(     )
78 		// Init member
79         ,   m_xSMGR       (xSMGR)
80 {
81 }
82 
83 //_______________________________________________
84 
85 /** dtor.
86 */
87 DispatchHelper::~DispatchHelper()
88 {
89 }
90 
91 //_______________________________________________
92 
93 /** capsulate all steps of a dispatch request and provide so an easy way for dispatches.
94 
95     @param xDispatchProvider
96                 identifies the object, which provides may be valid dispatch objects for this execute.
97 
98     @param sURL
99                 describes the requested feature.
100 
101     @param sTargetFrameName
102                 points to the frame, which must be used (or may be created) for this dispatch.
103 
104     @param nSearchFlags
105                 in case the <var>sTargetFrameName</var> isn't unique, these flags regulate further searches.
106 
107     @param lArguments
108                 optional arguments for this request.
109 
110     @return An Any which capsulate a possible result of the internal wrapped dispatch.
111  */
112 css::uno::Any SAL_CALL DispatchHelper::executeDispatch(
113                                 const css::uno::Reference< css::frame::XDispatchProvider >& xDispatchProvider ,
114                                 const ::rtl::OUString&                                      sURL              ,
115                                 const ::rtl::OUString&                                      sTargetFrameName  ,
116                                       sal_Int32                                             nSearchFlags      ,
117                                 const css::uno::Sequence< css::beans::PropertyValue >&      lArguments        )
118     throw(css::uno::RuntimeException)
119 {
120     css::uno::Reference< css::uno::XInterface > xTHIS(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);
121 
122     // check for valid parameters
123     if (
124         (!xDispatchProvider.is()) ||
125         (sURL.getLength()<1     )
126        )
127     {
128 		return css::uno::Any();
129     }
130 
131     // parse given URL
132     /* SAFE { */
133     ReadGuard aReadLock(m_aLock);
134     css::uno::Reference< css::util::XURLTransformer > xParser(m_xSMGR->createInstance(SERVICENAME_URLTRANSFORMER), css::uno::UNO_QUERY);
135     aReadLock.unlock();
136     /* } SAFE */
137 
138     css::util::URL aURL;
139     aURL.Complete = sURL;
140     xParser->parseStrict(aURL);
141 
142     // search dispatcher
143     css::uno::Reference< css::frame::XDispatch >          xDispatch       = xDispatchProvider->queryDispatch(aURL, sTargetFrameName, nSearchFlags);
144     css::uno::Reference< css::frame::XNotifyingDispatch > xNotifyDispatch (xDispatch, css::uno::UNO_QUERY);
145 
146     // make sure that synchronous execution is used (if possible)
147     css::uno::Sequence< css::beans::PropertyValue > aArguments( lArguments );
148     sal_Int32 nLength = lArguments.getLength();
149     aArguments.realloc( nLength + 1 );
150     aArguments[ nLength ].Name = ::rtl::OUString::createFromAscii("SynchronMode");
151     aArguments[ nLength ].Value <<= (sal_Bool) sal_True;
152 
153     css::uno::Any aResult;
154     if (xNotifyDispatch.is())
155     {
156         // dispatch it with guaranteed notification
157         // Here we can hope for a result ... instead of the normal dispatch.
158         css::uno::Reference< css::frame::XDispatchResultListener > xListener(xTHIS, css::uno::UNO_QUERY);
159         /* SAFE { */
160         WriteGuard aWriteLock(m_aLock);
161         m_xBroadcaster = css::uno::Reference< css::uno::XInterface >(xNotifyDispatch, css::uno::UNO_QUERY);
162         m_aResult      = css::uno::Any();
163         m_aBlock.reset();
164         aWriteLock.unlock();
165         /* } SAFE */
166 
167         // dispatch it and wait for a notification
168         // TODO/MBA: waiting in main thread?!
169         xNotifyDispatch->dispatchWithNotification(aURL, aArguments, xListener);
170         //m_aBlock.wait();
171         aResult = m_aResult;
172     }
173     else
174     if (xDispatch.is())
175     {
176         // dispatch it without any chance to get a result
177         xDispatch->dispatch( aURL, aArguments );
178     }
179 
180     return aResult;
181 }
182 
183 //_______________________________________________
184 
185 /** callback for started dispatch with guaranteed notifications.
186 
187     We must save the result, so the method executeDispatch() can return it.
188     Further we must release the broadcaster (otherwhise it can't die)
189     and unblock the waiting executeDispatch() request.
190 
191     @param  aResult
192                 describes the result of the dispatch operation
193  */
194 void SAL_CALL DispatchHelper::dispatchFinished( const css::frame::DispatchResultEvent& aResult )
195     throw(css::uno::RuntimeException)
196 {
197     /* SAFE { */
198     WriteGuard aWriteLock(m_aLock);
199 
200     m_aResult <<= aResult;
201     m_aBlock.set();
202     m_xBroadcaster.clear();
203 
204     /* } SAFE */
205 }
206 
207 //_______________________________________________
208 
209 /** we has to realease our broadcaster reference.
210 
211     @param aEvent
212                 describe the source of this event and MUST be our save broadcaster!
213  */
214 void SAL_CALL DispatchHelper::disposing( const css::lang::EventObject& )
215     throw(css::uno::RuntimeException)
216 {
217     /* SAFE { */
218     WriteGuard aWriteLock(m_aLock);
219 
220     m_aResult.clear();
221 	m_aBlock.set();
222     m_xBroadcaster.clear();
223 
224     /* } SAFE */
225 }
226 
227 }
228