xref: /trunk/main/dbaccess/source/ui/misc/linkeddocuments.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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_LINKEDDOCUMENTS_HXX_
32 #include "linkeddocuments.hxx"
33 #endif
34 #ifndef _OSL_DIAGNOSE_H_
35 #include <osl/diagnose.h>
36 #endif
37 #include <tools/diagnose_ex.h>
38 #include <unotools/confignode.hxx>
39 #ifndef DBACCESS_SHARED_DBUSTRINGS_HRC
40 #include "dbustrings.hrc"
41 #endif
42 #include <comphelper/classids.hxx>
43 #ifndef COMPHELPER_NAMEDVALUECOLLECTION_HXX
44 #include <comphelper/namedvaluecollection.hxx>
45 #endif
46 #ifndef _COM_SUN_STAR_LANG_XSINGLESERVICEFACTORY_HPP_
47 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
48 #endif
49 #ifndef _COM_SUN_STAR_FRAME_XDISPATCHPROVIDER_HPP_
50 #include <com/sun/star/frame/XDispatchProvider.hpp>
51 #endif
52 #ifndef _COM_SUN_STAR_FRAME_XCOMPONENTLOADER_HPP_
53 #include <com/sun/star/frame/XComponentLoader.hpp>
54 #endif
55 #ifndef _COM_SUN_STAR_UTIL_URL_HPP_
56 #include <com/sun/star/util/URL.hpp>
57 #endif
58 #ifndef _COM_SUN_STAR_FRAME_FRAMESEARCHFLAG_HPP_
59 #include <com/sun/star/frame/FrameSearchFlag.hpp>
60 #endif
61 #ifndef _COM_SUN_STAR_CONTAINER_XNAMECONTAINER_HPP_
62 #include <com/sun/star/container/XNameContainer.hpp>
63 #endif
64 #ifndef _COM_SUN_STAR_UCB_XCOMMANDPROCESSOR_HPP_
65 #include <com/sun/star/ucb/XCommandProcessor.hpp>
66 #endif
67 #ifndef _COM_SUN_STAR_UCB_OPENCOMMANDARGUMENT_HPP_
68 #include <com/sun/star/ucb/OpenCommandArgument.hpp>
69 #endif
70 #ifndef _COM_SUN_STAR_UCB_OPENMODE_HPP_
71 #include <com/sun/star/ucb/OpenMode.hpp>
72 #endif
73 #ifndef _COM_SUN_STAR_TASK_XJOBEXECUTOR_HPP_
74 #include <com/sun/star/task/XJobExecutor.hpp>
75 #endif
76 #ifndef _COMPHELPER_EXTRACT_HXX_
77 #include <comphelper/extract.hxx>
78 #endif
79 #ifndef _COMPHELPER_TYPES_HXX_
80 #include <comphelper/types.hxx>
81 #endif
82 #ifndef _SV_MSGBOX_HXX
83 #include <vcl/msgbox.hxx>
84 #endif
85 #ifndef _UCBHELPER_CONTENT_HXX
86 #include <ucbhelper/content.hxx>
87 #endif
88 #ifndef _DBU_MISC_HRC_
89 #include "dbu_misc.hrc"
90 #endif
91 #ifndef SVTOOLS_FILENOTATION_HXX_
92 #include <svl/filenotation.hxx>
93 #endif
94 #ifndef DBACCESS_UI_BROWSER_ID_HXX
95 #include "browserids.hxx"
96 #endif
97 #ifndef _SFXNEW_HXX
98 #include <sfx2/new.hxx>
99 #endif
100 #ifndef _SVTOOLS_TEMPLDLG_HXX
101 #include <svtools/templdlg.hxx>
102 #endif
103 #ifndef _DBAUI_MODULE_DBU_HXX_
104 #include "moduledbu.hxx"
105 #endif
106 // -----------------
107 // for calling basic
108 #ifndef _SFXAPP_HXX
109 #include <sfx2/app.hxx>
110 #endif
111 #ifndef _SBXCLASS_HXX
112 #include <basic/sbx.hxx>
113 #endif
114 #ifndef _SB_SBUNO_HXX
115 #include <basic/sbuno.hxx>
116 #endif
117 #ifndef _EHDL_HXX
118 #include <svtools/ehdl.hxx>
119 #endif
120 #ifndef _SVX_DATACCESSDESCRIPTOR_HXX_
121 #include <svx/dataaccessdescriptor.hxx>
122 #endif
123 #ifndef _COM_SUN_STAR_CONTAINER_XHIERARCHICALNAMECONTAINER_HPP_
124 #include <com/sun/star/container/XHierarchicalNameContainer.hpp>
125 #endif
126 #ifndef _SV_WAITOBJ_HXX
127 #include <vcl/waitobj.hxx>
128 #endif
129 #ifndef _COMPHELPER_MIMECONFIGHELPER_HXX_
130 #include <comphelper/mimeconfighelper.hxx>
131 #endif
132 
133 #include <cppuhelper/exc_hlp.hxx>
134 #include <connectivity/dbtools.hxx>
135 #include <toolkit/helper/vclunohelper.hxx>
136 #include <com/sun/star/io/WrongFormatException.hpp>
137 #include "com/sun/star/sdb/RowSetVetoException.hpp"
138 
139 //......................................................................
140 namespace dbaui
141 {
142 //......................................................................
143 
144     using namespace ::com::sun::star::uno;
145     using namespace ::com::sun::star::container;
146     using namespace ::com::sun::star::lang;
147     using namespace ::com::sun::star::frame;
148     using namespace ::com::sun::star::beans;
149     using namespace ::com::sun::star::util;
150     using namespace ::com::sun::star::ucb;
151     using namespace ::com::sun::star::sdbc;
152     using namespace ::com::sun::star::sdb::application;
153     using namespace ::com::sun::star::task;
154     using namespace ::svt;
155 
156     namespace
157     {
158         Sequence< sal_Int8 > lcl_GetSequenceClassID( sal_uInt32 n1, sal_uInt16 n2, sal_uInt16 n3,
159                                                     sal_uInt8 b8, sal_uInt8 b9, sal_uInt8 b10, sal_uInt8 b11,
160                                                     sal_uInt8 b12, sal_uInt8 b13, sal_uInt8 b14, sal_uInt8 b15 )
161         {
162             Sequence< sal_Int8 > aResult( 16 );
163             aResult[0] = static_cast<sal_Int8>(n1 >> 24);
164             aResult[1] = static_cast<sal_Int8>(( n1 << 8 ) >> 24);
165             aResult[2] = static_cast<sal_Int8>(( n1 << 16 ) >> 24);
166             aResult[3] = static_cast<sal_Int8>(( n1 << 24 ) >> 24);
167             aResult[4] = static_cast<sal_Int8>(n2 >> 8);
168             aResult[5] = static_cast<sal_Int8>(( n2 << 8 ) >> 8);
169             aResult[6] = static_cast<sal_Int8>(n3 >> 8);
170             aResult[7] = static_cast<sal_Int8>(( n3 << 8 ) >> 8);
171             aResult[8] = b8;
172             aResult[9] = b9;
173             aResult[10] = b10;
174             aResult[11] = b11;
175             aResult[12] = b12;
176             aResult[13] = b13;
177             aResult[14] = b14;
178             aResult[15] = b15;
179 
180             return aResult;
181         }
182     }
183 
184 
185     //==================================================================
186     //= OLinkedDocumentsAccess
187     //==================================================================
188     DBG_NAME(OLinkedDocumentsAccess)
189     //------------------------------------------------------------------
190     OLinkedDocumentsAccess::OLinkedDocumentsAccess( Window* _pDialogParent, const Reference< XDatabaseDocumentUI >& i_rDocumentUI,
191         const Reference< XMultiServiceFactory >& _rxORB, const Reference< XNameAccess >& _rxContainer,
192         const Reference< XConnection>& _xConnection, const ::rtl::OUString& _sDataSourceName )
193         :m_xORB(_rxORB)
194         ,m_xDocumentContainer(_rxContainer)
195         ,m_xConnection(_xConnection)
196         ,m_xDocumentUI( i_rDocumentUI )
197         ,m_pDialogParent(_pDialogParent)
198         ,m_sDataSourceName(_sDataSourceName)
199     {
200         DBG_CTOR(OLinkedDocumentsAccess,NULL);
201         OSL_ENSURE(m_xORB.is(), "OLinkedDocumentsAccess::OLinkedDocumentsAccess: invalid service factory!");
202         OSL_ENSURE(m_pDialogParent, "OLinkedDocumentsAccess::OLinkedDocumentsAccess: really need a dialog parent!");
203     }
204     //------------------------------------------------------------------
205     OLinkedDocumentsAccess::~OLinkedDocumentsAccess()
206     {
207         DBG_DTOR(OLinkedDocumentsAccess,NULL);
208     }
209     //------------------------------------------------------------------
210     Reference< XComponent> OLinkedDocumentsAccess::impl_open( const ::rtl::OUString& _rLinkName, Reference< XComponent >& _xDefinition,
211         ElementOpenMode _eOpenMode, const ::comphelper::NamedValueCollection& _rAdditionalArgs )
212     {
213         Reference< XComponent> xRet;
214         OSL_ENSURE(m_xDocumentContainer.is(), "OLinkedDocumentsAccess::OLinkedDocumentsAccess: invalid document container!");
215         Reference< XComponentLoader > xComponentLoader(m_xDocumentContainer,UNO_QUERY);
216         if ( !xComponentLoader.is() )
217             return xRet;
218 
219         WaitObject aWaitCursor( m_pDialogParent );
220 
221         ::comphelper::NamedValueCollection aArguments;
222         ::rtl::OUString sOpenMode;
223         switch ( _eOpenMode )
224         {
225             case E_OPEN_NORMAL:
226                 sOpenMode = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "open" ) );
227                 break;
228 
229             case E_OPEN_FOR_MAIL:
230                 aArguments.put( "Hidden", true );
231                 // fall through
232 
233             case E_OPEN_DESIGN:
234                 sOpenMode = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "openDesign" ) );
235                 break;
236 
237             default:
238                 OSL_ENSURE( false, "OLinkedDocumentsAccess::implOpen: invalid open mode!" );
239                 break;
240         }
241         aArguments.put( "OpenMode", sOpenMode );
242 
243         aArguments.put( (::rtl::OUString)PROPERTY_ACTIVE_CONNECTION, m_xConnection );
244         try
245         {
246             Reference<XHierarchicalNameContainer> xHier(m_xDocumentContainer,UNO_QUERY);
247             if ( xHier.is() && xHier->hasByHierarchicalName(_rLinkName) )
248             {
249                 _xDefinition.set(xHier->getByHierarchicalName(_rLinkName),UNO_QUERY);
250             }
251 
252             aArguments.merge( _rAdditionalArgs, true );
253 
254             xRet = xComponentLoader->loadComponentFromURL( _rLinkName, ::rtl::OUString(), 0, aArguments.getPropertyValues() );
255         }
256         catch(Exception& e)
257         {
258             (void)e;
259             throw;
260         }
261 
262         return xRet;
263     }
264     //------------------------------------------------------------------
265     void OLinkedDocumentsAccess::impl_newWithPilot( const char* _pWizardService,
266         const sal_Int32 _nCommandType, const ::rtl::OUString& _rObjectName )
267     {
268         try
269         {
270             ::comphelper::NamedValueCollection aArgs;
271             aArgs.put( "DataSourceName", m_sDataSourceName );
272 
273             if ( m_xConnection.is() )
274                 aArgs.put( "ActiveConnection", m_xConnection );
275 
276             if ( _rObjectName.getLength() && ( _nCommandType != -1 ) )
277             {
278                 aArgs.put( "CommandType", _nCommandType );
279                 aArgs.put( "Command", _rObjectName );
280             }
281 
282             aArgs.put( "DocumentUI", m_xDocumentUI );
283 
284             Reference< XJobExecutor > xWizard;
285             {
286                 WaitObject aWaitCursor( m_pDialogParent );
287                 xWizard.set( m_xORB->createInstanceWithArguments(
288                     ::rtl::OUString::createFromAscii( _pWizardService ),
289                     aArgs.getWrappedPropertyValues()
290                     ), UNO_QUERY_THROW );
291             }
292 
293             xWizard->trigger( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "start" ) ) );
294             ::comphelper::disposeComponent( xWizard );
295         }
296         catch(const Exception& e)
297         {
298             DBG_UNHANDLED_EXCEPTION();
299         }
300     }
301     //------------------------------------------------------------------
302     void OLinkedDocumentsAccess::newFormWithPilot( const sal_Int32 _nCommandType,const ::rtl::OUString& _rObjectName )
303     {
304         impl_newWithPilot( "com.sun.star.wizards.form.CallFormWizard", _nCommandType, _rObjectName );
305     }
306 
307     //------------------------------------------------------------------
308     void OLinkedDocumentsAccess::newReportWithPilot( const sal_Int32 _nCommandType, const ::rtl::OUString& _rObjectName )
309     {
310         impl_newWithPilot( "com.sun.star.wizards.report.CallReportWizard", _nCommandType, _rObjectName );
311     }
312     //------------------------------------------------------------------
313     void OLinkedDocumentsAccess::newTableWithPilot()
314     {
315         impl_newWithPilot( "com.sun.star.wizards.table.CallTableWizard", -1, ::rtl::OUString() );
316     }
317     //------------------------------------------------------------------
318     void OLinkedDocumentsAccess::newQueryWithPilot()
319     {
320         impl_newWithPilot( "com.sun.star.wizards.query.CallQueryWizard", -1, ::rtl::OUString() );
321     }
322     //------------------------------------------------------------------
323     Reference< XComponent > OLinkedDocumentsAccess::newDocument( sal_Int32 i_nActionID,
324         const ::comphelper::NamedValueCollection& i_rCreationArgs, Reference< XComponent >& o_rDefinition )
325     {
326         OSL_ENSURE(m_xDocumentContainer.is(), "OLinkedDocumentsAccess::newDocument: invalid document container!");
327         // determine the class ID to use for the new document
328         Sequence<sal_Int8> aClassId;
329         if  (   !i_rCreationArgs.has( "ClassID" )
330             &&  !i_rCreationArgs.has( "MediaType" )
331             &&  !i_rCreationArgs.has( "DocumentServiceName" )
332             )
333         {
334             switch ( i_nActionID )
335             {
336                 case ID_FORM_NEW_TEXT:
337                     aClassId = lcl_GetSequenceClassID(SO3_SW_CLASSID);
338                     OSL_ENSURE(aClassId == comphelper::MimeConfigurationHelper::GetSequenceClassID(SO3_SW_CLASSID),"Not equal");
339                     break;
340 
341                 case ID_FORM_NEW_CALC:
342                     aClassId = lcl_GetSequenceClassID(SO3_SC_CLASSID);
343                     break;
344 
345                 case ID_FORM_NEW_IMPRESS:
346                     aClassId = lcl_GetSequenceClassID(SO3_SIMPRESS_CLASSID);
347                     break;
348 
349                 case ID_REPORT_NEW_TEXT:
350                     aClassId = comphelper::MimeConfigurationHelper::GetSequenceClassID(SO3_RPT_CLASSID_90);
351                     break;
352 
353                 default:
354                     OSL_ENSURE( sal_False, "OLinkedDocumentsAccess::newDocument: please use newFormWithPilot!" );
355                     return Reference< XComponent >();
356 
357             }
358         }
359 
360         // load the document as template
361         Reference< XComponent > xNewDocument;
362         try
363         {   // get the desktop object
364 
365             Reference<XMultiServiceFactory> xORB(m_xDocumentContainer,UNO_QUERY);
366             if ( xORB.is() )
367             {
368                 ::comphelper::NamedValueCollection aCreationArgs( i_rCreationArgs );
369                 if ( aClassId.getLength() )
370                     aCreationArgs.put( "ClassID", aClassId );
371                 aCreationArgs.put( (::rtl::OUString)PROPERTY_ACTIVE_CONNECTION, m_xConnection );
372 
373                 // separate values which are real creation args from args relevant for opening the doc
374                 ::comphelper::NamedValueCollection aCommandArgs;
375                 if ( aCreationArgs.has( "Hidden" ) )
376                 {
377                     aCommandArgs.put( "Hidden", aCreationArgs.get( "Hidden" ) );
378                     aCreationArgs.remove( "Hidden" );
379                 }
380 
381                 Reference< XCommandProcessor > xContent( xORB->createInstanceWithArguments(
382                         SERVICE_SDB_DOCUMENTDEFINITION,
383                         aCreationArgs.getWrappedPropertyValues()
384                     ),
385                     UNO_QUERY_THROW
386                 );
387                 o_rDefinition.set( xContent, UNO_QUERY );
388 
389                 // put the OpenMode into the OpenArgs
390                 OpenCommandArgument aOpenModeArg;
391                 aOpenModeArg.Mode = OpenMode::DOCUMENT;
392                 aCommandArgs.put( "OpenMode", aOpenModeArg );
393 
394                 Command aCommand;
395                 aCommand.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "openDesign" ) );
396                 aCommand.Argument <<= aCommandArgs.getPropertyValues();
397                 WaitObject aWaitCursor( m_pDialogParent );
398                 xNewDocument.set( xContent->execute( aCommand, xContent->createCommandIdentifier(), NULL ), UNO_QUERY );
399             }
400         }
401         catch(const Exception& )
402         {
403             DBG_UNHANDLED_EXCEPTION();
404         }
405 
406         return xNewDocument;
407     }
408 
409     //------------------------------------------------------------------
410     Reference< XComponent > OLinkedDocumentsAccess::open( const ::rtl::OUString& _rLinkName, Reference< XComponent >& _xDefinition,
411         ElementOpenMode _eOpenMode, const ::comphelper::NamedValueCollection& _rAdditionalArgs )
412     {
413         dbtools::SQLExceptionInfo aInfo;
414         Reference< XComponent > xRet;
415         try
416         {
417             xRet = impl_open( _rLinkName, _xDefinition, _eOpenMode, _rAdditionalArgs );
418             if ( !xRet.is() )
419             {
420                 String sMessage = String(ModuleRes(STR_COULDNOTOPEN_LINKEDDOC));
421                 sMessage.SearchAndReplaceAscii("$file$",_rLinkName);
422 
423                 com::sun::star::sdbc::SQLException aSQLException;
424                 aSQLException.Message = sMessage;
425                 // aSQLException.Context = e.Context;
426                 aInfo = dbtools::SQLExceptionInfo(aSQLException);
427             }
428             return xRet;
429         }
430         catch (com::sun::star::io::WrongFormatException e)
431         {
432             com::sun::star::sdbc::SQLException aSQLException;
433             aSQLException.Message = e.Message;
434             aSQLException.Context = e.Context;
435             aInfo = dbtools::SQLExceptionInfo(aSQLException);
436 
437             // more like a hack, insert an empty message
438             String sText( ModuleRes( RID_STR_EXTENSION_NOT_PRESENT ) );
439             sText.SearchAndReplaceAscii("$file$",_rLinkName);
440             aInfo.prepend(sText);
441 
442             String sMessage = String(ModuleRes(STR_COULDNOTOPEN_LINKEDDOC));
443             sMessage.SearchAndReplaceAscii("$file$",_rLinkName);
444             aInfo.prepend(sMessage);
445         }
446         catch(Exception& e)
447         {
448             Any aAny = ::cppu::getCaughtException();
449             com::sun::star::sdbc::SQLException a;
450             if ( !(aAny >>= a) || (a.ErrorCode != dbtools::ParameterInteractionCancelled) )
451             {
452                 com::sun::star::sdbc::SQLException aSQLException;
453                 aSQLException.Message = e.Message;
454                 aSQLException.Context = e.Context;
455                 aInfo = dbtools::SQLExceptionInfo(aSQLException);
456 
457                 // more like a hack, insert an empty message
458                 aInfo.prepend(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" \n")));
459 
460                 String sMessage = String(ModuleRes(STR_COULDNOTOPEN_LINKEDDOC));
461                 sMessage.SearchAndReplaceAscii("$file$",_rLinkName);
462                 aInfo.prepend(sMessage);
463             }
464         }
465         if (aInfo.isValid())
466         {
467             showError(aInfo, VCLUnoHelper::GetInterface(m_pDialogParent), m_xORB );
468         }
469         return xRet;
470     }
471 
472 
473 //......................................................................
474 }   // namespace dbaui
475 //......................................................................
476 
477