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_framework.hxx"
26 
27 //_________________________________________________________________________________________________________________
28 //	my own includes
29 //_________________________________________________________________________________________________________________
30 #include <dispatch/mailtodispatcher.hxx>
31 #include <threadhelp/readguard.hxx>
32 #include <general.h>
33 #include <services.h>
34 
35 //_________________________________________________________________________________________________________________
36 //	interface includes
37 //_________________________________________________________________________________________________________________
38 #include <com/sun/star/system/XSystemShellExecute.hpp>
39 #include <com/sun/star/system/SystemShellExecuteFlags.hpp>
40 #include <com/sun/star/frame/DispatchResultState.hpp>
41 
42 //_________________________________________________________________________________________________________________
43 //	includes of other projects
44 //_________________________________________________________________________________________________________________
45 
46 #include <vcl/svapp.hxx>
47 
48 //_________________________________________________________________________________________________________________
49 //	namespace
50 //_________________________________________________________________________________________________________________
51 
52 namespace framework{
53 
54 //_________________________________________________________________________________________________________________
55 //	non exported const
56 //_________________________________________________________________________________________________________________
57 
58 #define PROTOCOL_VALUE      "mailto:"
59 #define PROTOCOL_LENGTH     7
60 
61 //_________________________________________________________________________________________________________________
62 //	non exported definitions
63 //_________________________________________________________________________________________________________________
64 
65 //_________________________________________________________________________________________________________________
66 //	declarations
67 //_________________________________________________________________________________________________________________
68 
69 //_________________________________________________________________________________________________________________
70 // XInterface, XTypeProvider, XServiceInfo
71 
72 DEFINE_XINTERFACE_5(MailToDispatcher                                ,
73                     OWeakObject                                     ,
74                     DIRECT_INTERFACE(css::lang::XTypeProvider      ),
75                     DIRECT_INTERFACE(css::lang::XServiceInfo       ),
76                     DIRECT_INTERFACE(css::frame::XDispatchProvider ),
77                     DIRECT_INTERFACE(css::frame::XNotifyingDispatch),
78                     DIRECT_INTERFACE(css::frame::XDispatch         ))
79 
80 DEFINE_XTYPEPROVIDER_5(MailToDispatcher              ,
81                        css::lang::XTypeProvider      ,
82                        css::lang::XServiceInfo       ,
83                        css::frame::XDispatchProvider ,
84                        css::frame::XNotifyingDispatch,
85                        css::frame::XDispatch         )
86 
87 DEFINE_XSERVICEINFO_MULTISERVICE(MailToDispatcher                   ,
88                                  ::cppu::OWeakObject                ,
89                                  SERVICENAME_PROTOCOLHANDLER        ,
90                                  IMPLEMENTATIONNAME_MAILTODISPATCHER)
91 
92 DEFINE_INIT_SERVICE(MailToDispatcher,
93                     {
94                         /*Attention
95                             I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance()
96                             to create a new instance of this class by our own supported service factory.
97                             see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further informations!
98                         */
99                     }
100                    )
101 
102 //_________________________________________________________________________________________________________________
103 
104 /**
105     @short      standard ctor
106     @descr      These initialize a new instance of ths class with needed informations for work.
107 
108     @param      xFactory
109                     reference to uno servicemanager for creation of new services
110 
111     @modified   30.04.2002 14:10, as96863
112 */
113 MailToDispatcher::MailToDispatcher( const css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory )
114 		//	Init baseclasses first
115         : ThreadHelpBase( &Application::GetSolarMutex() )
116         , OWeakObject   (                               )
117         // Init member
118         , m_xFactory    ( xFactory                      )
119 {
120 }
121 
122 //_________________________________________________________________________________________________________________
123 
124 /**
125     @short      standard dtor
126     @descr      -
127 
128     @modified   30.04.2002 14:10, as96863
129 */
130 MailToDispatcher::~MailToDispatcher()
131 {
132     m_xFactory = NULL;
133 }
134 
135 //_________________________________________________________________________________________________________________
136 
137 /**
138     @short      decide if this dispatch implementation can be used for requested URL or not
139     @descr      A protocol handler is registerd for an URL pattern inside configuration and will
140                 be asked by the generic dispatch mechanism inside framework, if he can handle this
141                 special URL wich match his registration. He can agree by returning of a valid dispatch
142                 instance or disagree by returning <NULL/>.
143                 We don't create new dispatch instances here realy - we return THIS as result to handle it
144                 at the same implementation.
145 
146     @modified   02.05.2002 15:25, as96863
147 */
148 css::uno::Reference< css::frame::XDispatch > SAL_CALL MailToDispatcher::queryDispatch( const css::util::URL&  aURL    ,
149                                                                                        const ::rtl::OUString& /*sTarget*/ ,
150                                                                                              sal_Int32        /*nFlags*/  ) throw( css::uno::RuntimeException )
151 {
152     css::uno::Reference< css::frame::XDispatch > xDispatcher;
153     if (aURL.Complete.compareToAscii(PROTOCOL_VALUE,PROTOCOL_LENGTH)==0)
154         xDispatcher = this;
155     return xDispatcher;
156 }
157 
158 //_________________________________________________________________________________________________________________
159 
160 /**
161     @short      do the same like dispatch() but for multiple requests at the same time
162     @descr      -
163 
164     @modified   02.05.2002 15:27, as96863
165 */
166 css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL MailToDispatcher::queryDispatches( const css::uno::Sequence< css::frame::DispatchDescriptor >& lDescriptor ) throw( css::uno::RuntimeException )
167 {
168     sal_Int32 nCount = lDescriptor.getLength();
169     css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > lDispatcher( nCount );
170     for( sal_Int32 i=0; i<nCount; ++i )
171     {
172         lDispatcher[i] = this->queryDispatch(
173                             lDescriptor[i].FeatureURL,
174                             lDescriptor[i].FrameName,
175                             lDescriptor[i].SearchFlags);
176     }
177     return lDispatcher;
178 }
179 
180 //_________________________________________________________________________________________________________________
181 
182 /**
183     @short      dispatch URL with arguments
184     @descr      We use threadsafe internal method to do so. It returns a state value - but we ignore it.
185                 Because we doesn't support status listener notifications here. Status events are not guaranteed -
186                 and we call another service internaly which doesn't return any notifications too.
187 
188     @param      aURL
189                     mail URL which should be executed
190     @param      lArguments
191                     list of optional arguments for this mail request
192 
193     @modified   30.04.2002 14:15, as96863
194 */
195 void SAL_CALL MailToDispatcher::dispatch( const css::util::URL&                                  aURL       ,
196                                           const css::uno::Sequence< css::beans::PropertyValue >& lArguments ) throw( css::uno::RuntimeException )
197 {
198     // dispatch() is an [oneway] call ... and may our user release his reference to us immediatly.
199     // So we should hold us self alive till this call ends.
200     css::uno::Reference< css::frame::XNotifyingDispatch > xSelfHold(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);
201     implts_dispatch(aURL,lArguments);
202     // No notification for status listener!
203 }
204 
205 //_________________________________________________________________________________________________________________
206 
207 /**
208     @short      dispatch with guaranteed notifications about success
209     @descr      We use threadsafe internal method to do so. Return state of this function will be used
210                 for notification if an optional listener is given.
211 
212     @param      aURL
213                     mail URL which should be executed
214     @param      lArguments
215                     list of optional arguments for this mail request
216     @param      xListener
217                     reference to a valid listener for state events
218 
219     @modified   30.04.2002 14:49, as96863
220 */
221 void SAL_CALL MailToDispatcher::dispatchWithNotification( const css::util::URL&                                             aURL      ,
222                                                           const css::uno::Sequence< css::beans::PropertyValue >&            lArguments,
223                                                           const css::uno::Reference< css::frame::XDispatchResultListener >& xListener ) throw( css::uno::RuntimeException )
224 {
225     // This class was designed to die by reference. And if user release his reference to us immediatly after calling this method
226     // we can run into some problems. So we hold us self alive till this method ends.
227     // Another reason: We can use this reference as source of sending event at the end too.
228     css::uno::Reference< css::frame::XNotifyingDispatch > xThis(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);
229 
230     sal_Bool bState = implts_dispatch(aURL,lArguments);
231     if (xListener.is())
232     {
233         css::frame::DispatchResultEvent aEvent;
234         if (bState)
235             aEvent.State = css::frame::DispatchResultState::SUCCESS;
236         else
237             aEvent.State = css::frame::DispatchResultState::FAILURE;
238         aEvent.Source = xThis;
239 
240         xListener->dispatchFinished( aEvent );
241     }
242 }
243 
244 //_________________________________________________________________________________________________________________
245 
246 /**
247     @short      threadsafe helper for dispatch calls
248     @descr      We support two interfaces for the same process - dispatch URLs. That the reason for this internal
249                 function. It implements the real dispatch operation and returns a state value which inform caller
250                 about success. He can notify listener then by using this return value.
251 
252     @param      aURL
253                     mail URL which should be executed
254     @param      lArguments
255                     list of optional arguments for this mail request
256 
257     @return     <TRUE/> if dispatch could be started successfully
258                 Note: Our internal used shell executor doesn't return any state value - so we must
259                 belive that call was successfully.
260                 <FALSE/> if neccessary ressource couldn't be created or an exception was thrown.
261 
262     @modified   30.04.2002 14:49, as96863
263 */
264 sal_Bool MailToDispatcher::implts_dispatch( const css::util::URL&                                  aURL       ,
265                                             const css::uno::Sequence< css::beans::PropertyValue >& /*lArguments*/ ) throw( css::uno::RuntimeException )
266 {
267     sal_Bool bSuccess = sal_False;
268 
269     css::uno::Reference< css::lang::XMultiServiceFactory > xFactory;
270     /* SAFE */{
271         ReadGuard aReadLock( m_aLock );
272         xFactory = m_xFactory;
273     /* SAFE */}
274 
275     css::uno::Reference< css::system::XSystemShellExecute > xSystemShellExecute( xFactory->createInstance(SERVICENAME_SYSTEMSHELLEXECUTE), css::uno::UNO_QUERY );
276     if (xSystemShellExecute.is())
277     {
278         try
279         {
280             // start mail client
281             // Because there is no notofocation about success - we use case of
282             // no detected exception as SUCCESS - FAILED otherwhise.
283             xSystemShellExecute->execute( aURL.Complete, ::rtl::OUString(), css::system::SystemShellExecuteFlags::DEFAULTS );
284             bSuccess = sal_True;
285         }
286         catch (css::lang::IllegalArgumentException&)
287         {
288         }
289         catch (css::system::SystemShellExecuteException&)
290         {
291         }
292     }
293 
294     return bSuccess;
295 }
296 
297 //_________________________________________________________________________________________________________________
298 
299 /**
300     @short      add/remove listener for state events
301     @descr      Because we use an external process to forward such mail URLs, and this process doesn't
302                 return any notifications about success or failed state - we doesn't support such status
303                 listener. We have no status to send.
304 
305     @param      xListener
306                     reference to a valid listener for state events
307     @param      aURL
308                     URL about listener will be informed, if something occured
309 
310     @modified   30.04.2002 14:49, as96863
311 */
312 void SAL_CALL MailToDispatcher::addStatusListener( const css::uno::Reference< css::frame::XStatusListener >& /*xListener*/ ,
313                                                    const css::util::URL&                                     /*aURL*/      ) throw( css::uno::RuntimeException )
314 {
315     // not suported yet
316 }
317 
318 //_________________________________________________________________________________________________________________
319 
320 void SAL_CALL MailToDispatcher::removeStatusListener( const css::uno::Reference< css::frame::XStatusListener >& /*xListener*/ ,
321                                                       const css::util::URL&                                     /*aURL*/      ) throw( css::uno::RuntimeException )
322 {
323     // not suported yet
324 }
325 
326 } //  namespace framework
327