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/SystemShellExecute.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_2(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 this class with needed informations for work.
107 
108     @param      xContext
109                     reference to uno component context
110 
111     @modified   30.04.2002 14:10, as96863
112 */
113 MailToDispatcher::MailToDispatcher( const css::uno::Reference< css::uno::XComponentContext >& xContext )
114 		//	Init baseclasses first
115         : ThreadHelpBase( &Application::GetSolarMutex() )
116         , OWeakObject   (                               )
117         // Init member
118         , m_xContext    ( xContext                      )
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_xContext = 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 which 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 really - 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 immediately.
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 immediately 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                 believe that call was successfully.
260                 <FALSE/> if necessary 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::uno::XComponentContext > xContext;
270     /* SAFE */{
271         ReadGuard aReadLock( m_aLock );
272         xContext = m_xContext;
273     /* SAFE */}
274 
275     css::uno::Reference< css::system::XSystemShellExecute > xSystemShellExecute(
276         css::system::SystemShellExecute::create( xContext ) );
277     if (xSystemShellExecute.is())
278     {
279         try
280         {
281             // start mail client
282             // Because there is no notofocation about success - we use case of
283             // no detected exception as SUCCESS - FAILED otherwhise.
284             xSystemShellExecute->execute( aURL.Complete, ::rtl::OUString(), css::system::SystemShellExecuteFlags::DEFAULTS );
285             bSuccess = sal_True;
286         }
287         catch (css::lang::IllegalArgumentException&)
288         {
289         }
290         catch (css::system::SystemShellExecuteException&)
291         {
292         }
293     }
294 
295     return bSuccess;
296 }
297 
298 //_________________________________________________________________________________________________________________
299 
300 /**
301     @short      add/remove listener for state events
302     @descr      Because we use an external process to forward such mail URLs, and this process doesn't
303                 return any notifications about success or failed state - we doesn't support such status
304                 listener. We have no status to send.
305 
306     @param      xListener
307                     reference to a valid listener for state events
308     @param      aURL
309                     URL about listener will be informed, if something occurred
310 
311     @modified   30.04.2002 14:49, as96863
312 */
313 void SAL_CALL MailToDispatcher::addStatusListener( const css::uno::Reference< css::frame::XStatusListener >& /*xListener*/ ,
314                                                    const css::util::URL&                                     /*aURL*/      ) throw( css::uno::RuntimeException )
315 {
316     // not suported yet
317 }
318 
319 //_________________________________________________________________________________________________________________
320 
321 void SAL_CALL MailToDispatcher::removeStatusListener( const css::uno::Reference< css::frame::XStatusListener >& /*xListener*/ ,
322                                                       const css::util::URL&                                     /*aURL*/      ) throw( css::uno::RuntimeException )
323 {
324     // not suported yet
325 }
326 
327 } //  namespace framework
328