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_dbaccess.hxx"
26 
27 #ifndef _DBAUI_INTERACTION_HXX_
28 #include "dbinteraction.hxx"
29 #endif
30 #ifndef _DBU_REGHELPER_HXX_
31 #include "dbu_reghelper.hxx"
32 #endif
33 #ifndef _TOOLS_DEBUG_HXX
34 #include <tools/debug.hxx>
35 #endif
36 #ifndef TOOLS_DIAGNOSE_EX_H
37 #include <tools/diagnose_ex.h>
38 #endif
39 #ifndef _SV_MSGBOX_HXX
40 #include <vcl/msgbox.hxx>
41 #endif
42 #ifndef _DBHELPER_DBEXCEPTION_HXX_
43 #include <connectivity/dbexception.hxx>
44 #endif
45 #ifndef _DBAUI_SQLMESSAGE_HXX_
46 #include "sqlmessage.hxx"
47 #endif
48 #ifndef _COM_SUN_STAR_TASK_XINTERACTIONAPPROVE_HPP_
49 #include <com/sun/star/task/XInteractionApprove.hpp>
50 #endif
51 #ifndef _COM_SUN_STAR_TASK_XINTERACTIONDISAPPROVE_HPP_
52 #include <com/sun/star/task/XInteractionDisapprove.hpp>
53 #endif
54 #ifndef _COM_SUN_STAR_TASK_XINTERACTIONRETRY_HPP_
55 #include <com/sun/star/task/XInteractionRetry.hpp>
56 #endif
57 #ifndef _COM_SUN_STAR_TASK_XINTERACTIONABORT_HPP_
58 #include <com/sun/star/task/XInteractionAbort.hpp>
59 #endif
60 #ifndef _COM_SUN_STAR_SDB_XINTERACTIONSUPPLYPARAMETERS_HPP_
61 #include <com/sun/star/sdb/XInteractionSupplyParameters.hpp>
62 #endif
63 #ifndef _COM_SUN_STAR_SDB_XINTERACTIONDOCUMENTSAVE_HPP_
64 #include <com/sun/star/sdb/XInteractionDocumentSave.hpp>
65 #endif
66 #ifndef SFX_QUERYSAVEDOCUMENT_HXX
67 #include <sfx2/QuerySaveDocument.hxx>
68 #endif
69 #ifndef _DBU_UNO_HRC_
70 #include "dbu_uno.hrc"
71 #endif
72 #ifndef _DBAUI_PARAMDIALOG_HXX_
73 #include "paramdialog.hxx"
74 #endif
75 #ifndef _SV_SVAPP_HXX
76 #include <vcl/svapp.hxx>
77 #endif
78 #ifndef _VOS_MUTEX_HXX_
79 #include <vos/mutex.hxx>
80 #endif
81 #ifndef DBAUI_COLLECTIONVIEW_HXX
82 #include "CollectionView.hxx"
83 #endif
84 #ifndef DBAUI_TOOLS_HXX
85 #include "UITools.hxx"
86 #endif
87 
88 
89 //==========================================================================
90 
createRegistryInfo_OInteractionHandler()91 extern "C" void SAL_CALL createRegistryInfo_OInteractionHandler()
92 {
93 	static ::dbaui::OMultiInstanceAutoRegistration< ::dbaui::SQLExceptionInteractionHandler > aSQLExceptionInteractionHandler_AutoRegistration;
94 	static ::dbaui::OMultiInstanceAutoRegistration< ::dbaui::LegacyInteractionHandler > aLegacyInteractionHandler_AutoRegistration;
95 }
96 
97 //.........................................................................
98 namespace dbaui
99 {
100 //.........................................................................
101 	using namespace ::com::sun::star::uno;
102 	using namespace ::com::sun::star::ucb;
103 	using namespace ::com::sun::star::sdb;
104 	using namespace ::com::sun::star::lang;
105 	using namespace ::com::sun::star::task;
106 	using namespace ::com::sun::star::beans;
107 	using namespace ::dbtools;
108 
109 	//=========================================================================
110 	//= BasicInteractionHandler
111 	//=========================================================================
112 	//-------------------------------------------------------------------------
BasicInteractionHandler(const Reference<XMultiServiceFactory> & _rxORB,const bool i_bFallbackToGeneric)113 	BasicInteractionHandler::BasicInteractionHandler( const Reference< XMultiServiceFactory >& _rxORB, const bool i_bFallbackToGeneric )
114 		:m_xORB( _rxORB )
115         ,m_bFallbackToGeneric( i_bFallbackToGeneric )
116 	{
117         OSL_ENSURE( !m_bFallbackToGeneric,
118             "BasicInteractionHandler::BasicInteractionHandler: enabling legacy behavior, there should be no clients of this anymore!" );
119 	}
120 
121 	//-------------------------------------------------------------------------
handleInteractionRequest(const Reference<XInteractionRequest> & i_rRequest)122     ::sal_Bool SAL_CALL BasicInteractionHandler::handleInteractionRequest( const Reference< XInteractionRequest >& i_rRequest ) throw (RuntimeException)
123     {
124         return impl_handle_throw( i_rRequest );
125     }
126 
127 	//-------------------------------------------------------------------------
handle(const Reference<XInteractionRequest> & i_rRequest)128 	void SAL_CALL BasicInteractionHandler::handle( const Reference< XInteractionRequest >& i_rRequest ) throw(RuntimeException)
129     {
130         impl_handle_throw( i_rRequest );
131     }
132 
133 	//-------------------------------------------------------------------------
impl_handle_throw(const Reference<XInteractionRequest> & i_Request)134     sal_Bool BasicInteractionHandler::impl_handle_throw( const Reference< XInteractionRequest >& i_Request )
135 	{
136 		Any aRequest( i_Request->getRequest() );
137 		DBG_ASSERT(aRequest.hasValue(), "BasicInteractionHandler::handle: invalid request!");
138 		if ( !aRequest.hasValue() )
139 			// no request -> no handling
140 			return sal_False;
141 
142 		Sequence< Reference< XInteractionContinuation > > aContinuations( i_Request->getContinuations() );
143 
144 		// try to extract an SQLException (or one of it's derived members
145 		SQLExceptionInfo aInfo( aRequest );
146 		if ( aInfo.isValid() )
147 		{
148 			implHandle( aInfo, aContinuations );
149 			return sal_True;
150 		}
151 
152 		ParametersRequest aParamRequest;
153 		if ( aRequest >>= aParamRequest )
154 		{
155 			implHandle( aParamRequest, aContinuations );
156 			return sal_True;
157 		}
158 
159 		DocumentSaveRequest aDocuRequest;
160 		if ( aRequest >>= aDocuRequest )
161 		{
162 			implHandle( aDocuRequest, aContinuations );
163 			return sal_True;
164 		}
165 
166         if ( m_bFallbackToGeneric )
167             return implHandleUnknown( i_Request );
168 
169         return sal_False;
170 	}
171 
172 	//-------------------------------------------------------------------------
implHandle(const ParametersRequest & _rParamRequest,const Sequence<Reference<XInteractionContinuation>> & _rContinuations)173 	void BasicInteractionHandler::implHandle(const ParametersRequest& _rParamRequest, const Sequence< Reference< XInteractionContinuation > >& _rContinuations)
174 	{
175 		::vos::OGuard aGuard(Application::GetSolarMutex());
176 			// want to open a dialog ....
177 
178 		sal_Int32 nAbortPos = getContinuation(ABORT, _rContinuations);
179 		sal_Int32 nParamPos = getContinuation(SUPPLY_PARAMETERS, _rContinuations);
180 
181 		Reference< XInteractionSupplyParameters > xParamCallback;
182 		if (-1 != nParamPos)
183 			xParamCallback = Reference< XInteractionSupplyParameters >(_rContinuations[nParamPos], UNO_QUERY);
184 		DBG_ASSERT(xParamCallback.is(), "BasicInteractionHandler::implHandle(ParametersRequest): can't set the parameters without an appropriate interaction handler!s");
185 
186 		// determine the style of the dialog, dependent on the present continuation types
187 		WinBits nDialogStyle = WB_OK | WB_DEF_OK;
188 		if (-1 != nAbortPos)
189 			nDialogStyle = WB_OK_CANCEL;
190 
191 		OParameterDialog aDlg(NULL, _rParamRequest.Parameters, _rParamRequest.Connection, m_xORB);
192 		sal_Int16 nResult = aDlg.Execute();
193 		try
194 		{
195 			switch (nResult)
196 			{
197 				case RET_OK:
198 					if (xParamCallback.is())
199 					{
200 						xParamCallback->setParameters(aDlg.getValues());
201 						xParamCallback->select();
202 					}
203 					break;
204 				default:
205 					if (-1 != nAbortPos)
206 						_rContinuations[nAbortPos]->select();
207 					break;
208 			}
209 		}
210         catch( const Exception& )
211         {
212             DBG_UNHANDLED_EXCEPTION();
213         }
214 	}
215 
216 	//-------------------------------------------------------------------------
implHandle(const SQLExceptionInfo & _rSqlInfo,const Sequence<Reference<XInteractionContinuation>> & _rContinuations)217 	void BasicInteractionHandler::implHandle(const SQLExceptionInfo& _rSqlInfo, const Sequence< Reference< XInteractionContinuation > >& _rContinuations)
218 	{
219 		::vos::OGuard aGuard(Application::GetSolarMutex());
220 			// want to open a dialog ....
221 
222 		sal_Int32 nApprovePos = getContinuation(APPROVE, _rContinuations);
223 		sal_Int32 nDisapprovePos = getContinuation(DISAPPROVE, _rContinuations);
224 		sal_Int32 nAbortPos = getContinuation(ABORT, _rContinuations);
225 		sal_Int32 nRetryPos = getContinuation(RETRY, _rContinuations);
226 
227         // determine the style of the dialog, dependent on the present continuation types
228 		WinBits nDialogStyle = 0;
229         bool bHaveCancel = nAbortPos != -1;
230         // "approve" means "Yes", "disapprove" means "No"
231         // VCL only supports having both (which makes sense ...)
232         if ( ( nApprovePos != -1 ) || ( nDisapprovePos != -1 ) )
233             nDialogStyle = ( bHaveCancel ? WB_YES_NO_CANCEL : WB_YES_NO ) | WB_DEF_YES;
234         else
235         {
236             // if there's no yes/no, then use a default OK button
237             nDialogStyle = ( bHaveCancel ? WB_OK_CANCEL : WB_OK ) | WB_DEF_OK;
238         }
239 
240         // If there's a "Retry" continuation, have a "Retry" button
241 		if ( nRetryPos != -1 )
242         {
243 			nDialogStyle = WB_RETRY_CANCEL | WB_DEF_RETRY;
244         }
245 
246 		// excute the dialog
247 		OSQLMessageBox aDialog(NULL, _rSqlInfo, nDialogStyle);
248 			// TODO: need a way to specify the parent window
249 		sal_Int16 nResult = aDialog.Execute();
250 		try
251 		{
252 			switch (nResult)
253 			{
254                 case RET_YES:
255                 case RET_OK:
256                     if ( nApprovePos != -1 )
257                         _rContinuations[ nApprovePos ]->select();
258                     else
259                         OSL_ENSURE( nResult != RET_YES, "BasicInteractionHandler::implHandle: no handler for YES!" );
260                     break;
261 
262                 case RET_NO:
263                     if ( nDisapprovePos != -1 )
264                         _rContinuations[ nDisapprovePos ]->select();
265                     else
266                         OSL_ENSURE( false, "BasicInteractionHandler::implHandle: no handler for NO!" );
267                     break;
268 
269 				case RET_CANCEL:
270 					if ( nAbortPos != -1 )
271 						_rContinuations[ nAbortPos ]->select();
272                     else if ( nDisapprovePos != -1 )
273 						_rContinuations[ nDisapprovePos ]->select();
274                     else
275                         OSL_ENSURE( false, "BasicInteractionHandler::implHandle: no handler for CANCEL!" );
276 					break;
277 				case RET_RETRY:
278 					if ( nRetryPos != -1 )
279 						_rContinuations[ nRetryPos ]->select();
280                     else
281                         OSL_ENSURE( false, "BasicInteractionHandler::implHandle: where does the RETRY come from?" );
282 					break;
283 			}
284 		}
285 		catch( const Exception& )
286 		{
287             DBG_UNHANDLED_EXCEPTION();
288 		}
289 	}
290 	//-------------------------------------------------------------------------
implHandle(const DocumentSaveRequest & _rDocuRequest,const Sequence<Reference<XInteractionContinuation>> & _rContinuations)291 	void BasicInteractionHandler::implHandle(const DocumentSaveRequest& _rDocuRequest, const Sequence< Reference< XInteractionContinuation > >& _rContinuations)
292 	{
293 		::vos::OGuard aGuard(Application::GetSolarMutex());
294 			// want to open a dialog ....
295 
296 		sal_Int32 nApprovePos = getContinuation(APPROVE, _rContinuations);
297 		sal_Int32 nDisApprovePos = getContinuation(DISAPPROVE, _rContinuations);
298 		sal_Int32 nAbortPos = getContinuation(ABORT, _rContinuations);
299 
300 		short nRet = RET_YES;
301 		if ( -1 != nApprovePos )
302 		{
303 			// fragen, ob gespeichert werden soll
304 			nRet = ExecuteQuerySaveDocument(NULL,_rDocuRequest.Name);
305 		}
306 
307 		if ( RET_CANCEL == nRet )
308 		{
309 			if (-1 != nAbortPos)
310 				_rContinuations[nAbortPos]->select();
311 			return;
312 		}
313 		else if ( RET_YES == nRet )
314 		{
315 			sal_Int32 nDocuPos = getContinuation(SUPPLY_DOCUMENTSAVE, _rContinuations);
316 
317 			if (-1 != nDocuPos)
318 			{
319 				Reference< XInteractionDocumentSave > xCallback(_rContinuations[nDocuPos], UNO_QUERY);
320 				DBG_ASSERT(xCallback.is(), "BasicInteractionHandler::implHandle(DocumentSaveRequest): can't save document without an appropriate interaction handler!s");
321 
322 				// determine the style of the dialog, dependent on the present continuation types
323 				WinBits nDialogStyle = WB_OK | WB_DEF_OK;
324 				if (-1 != nAbortPos)
325 					nDialogStyle = WB_OK_CANCEL;
326 
327 				OCollectionView aDlg(NULL,_rDocuRequest.Content,_rDocuRequest.Name,m_xORB);
328 				sal_Int16 nResult = aDlg.Execute();
329 				try
330 				{
331 					switch (nResult)
332 					{
333 						case RET_OK:
334 							if (xCallback.is())
335 							{
336 								xCallback->setName(aDlg.getName(),aDlg.getSelectedFolder());
337 								xCallback->select();
338 							}
339 							break;
340 						default:
341 							if (-1 != nAbortPos)
342 								_rContinuations[nAbortPos]->select();
343 							break;
344 					}
345 				}
346                 catch( const Exception& )
347                 {
348                     DBG_UNHANDLED_EXCEPTION();
349                 }
350 			}
351 			else if ( -1 != nApprovePos )
352 				_rContinuations[nApprovePos]->select();
353 		}
354 		else if ( -1 != nDisApprovePos )
355 				_rContinuations[nDisApprovePos]->select();
356 	}
357 
358 	//-------------------------------------------------------------------------
implHandleUnknown(const Reference<XInteractionRequest> & _rxRequest)359     bool BasicInteractionHandler::implHandleUnknown( const Reference< XInteractionRequest >& _rxRequest )
360     {
361         Reference< XInteractionHandler > xFallbackHandler;
362         if ( m_xORB.is() )
363             xFallbackHandler = xFallbackHandler.query( m_xORB->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.task.InteractionHandler" ) ) ) );
364         if ( xFallbackHandler.is() )
365         {
366             xFallbackHandler->handle( _rxRequest );
367             return true;
368         }
369         return false;
370     }
371 
372 	//-------------------------------------------------------------------------
getContinuation(Continuation _eCont,const Sequence<Reference<XInteractionContinuation>> & _rContinuations)373 	sal_Int32 BasicInteractionHandler::getContinuation(Continuation _eCont, const Sequence< Reference< XInteractionContinuation > >& _rContinuations)
374 	{
375 		const Reference< XInteractionContinuation >* pContinuations = _rContinuations.getConstArray();
376 		for (sal_Int32 i=0; i<_rContinuations.getLength(); ++i, ++pContinuations)
377 		{
378 			switch (_eCont)
379 			{
380 				case APPROVE:
381 					if (Reference< XInteractionApprove >(*pContinuations, UNO_QUERY).is())
382 						return i;
383 					break;
384 				case DISAPPROVE:
385 					if (Reference< XInteractionDisapprove >(*pContinuations, UNO_QUERY).is())
386 						return i;
387 					break;
388 				case RETRY:
389 					if (Reference< XInteractionRetry >(*pContinuations, UNO_QUERY).is())
390 						return i;
391 					break;
392 				case ABORT:
393 					if (Reference< XInteractionAbort >(*pContinuations, UNO_QUERY).is())
394 						return i;
395 					break;
396 				case SUPPLY_PARAMETERS:
397 					if (Reference< XInteractionSupplyParameters >(*pContinuations, UNO_QUERY).is())
398 						return i;
399 					break;
400 				case SUPPLY_DOCUMENTSAVE:
401 					if (Reference< XInteractionDocumentSave >(*pContinuations, UNO_QUERY).is())
402 						return i;
403 					break;
404 			}
405 		}
406 
407 		return -1;
408 	}
409 
410     //==========================================================================
411     //= SQLExceptionInteractionHandler
412     //==========================================================================
413 	IMPLEMENT_SERVICE_INFO1_STATIC( SQLExceptionInteractionHandler, "com.sun.star.comp.dbaccess.DatabaseInteractionHandler", "com.sun.star.sdb.DatabaseInteractionHandler" );
414 
415     //==========================================================================
416     //= LegacyInteractionHandler
417     //==========================================================================
418 	IMPLEMENT_SERVICE_INFO1_STATIC( LegacyInteractionHandler, "com.sun.star.comp.dbaccess.LegacyInteractionHandler", "com.sun.star.sdb.InteractionHandler" );
419 
420 //.........................................................................
421 }	// namespace dbaui
422 //.........................................................................
423 
424