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