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