1 /*************************************************************************
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3 *
4 * Copyright 2009 by Sun Microsystems, Inc.
5 *
6 * OpenOffice.org - a multi-platform office productivity suite
7 *
8 * This file is part of OpenOffice.org.
9 *
10 * OpenOffice.org is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU Lesser General Public License version 3
12 * only, as published by the Free Software Foundation.
13 *
14 * OpenOffice.org is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU Lesser General Public License version 3 for more details
18 * (a copy is included in the LICENSE file that accompanied this code).
19 *
20 * You should have received a copy of the GNU Lesser General Public License
21 * version 3 along with OpenOffice.org.  If not, see
22 * <http://www.openoffice.org/license.html>
23 * for a copy of the LGPLv3 License.
24 ************************************************************************/
25 
26 #include "precompiled_dbaccess.hxx"
27 
28 #include "subcomponentrecovery.hxx"
29 
30 #include "sdbcoretools.hxx"
31 #include "storagexmlstream.hxx"
32 #include "subcomponentloader.hxx"
33 #include "settingsimport.hxx"
34 
35 /** === begin UNO includes === **/
36 #include <com/sun/star/embed/ElementModes.hpp>
37 #include <com/sun/star/frame/XModuleManager.hpp>
38 #include <com/sun/star/document/XStorageBasedDocument.hpp>
39 #include <com/sun/star/ucb/XCommandProcessor.hpp>
40 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
41 #include <com/sun/star/sdb/XFormDocumentsSupplier.hpp>
42 #include <com/sun/star/sdb/XReportDocumentsSupplier.hpp>
43 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
44 /** === end UNO includes === **/
45 
46 #include <comphelper/namedvaluecollection.hxx>
47 #include <connectivity/dbtools.hxx>
48 #include <tools/diagnose_ex.h>
49 #include <xmloff/XMLSettingsExportContext.hxx>
50 #include <xmloff/SettingsExportHelper.hxx>
51 
52 //........................................................................
53 namespace dbaccess
54 {
55 //........................................................................
56 
57 	/** === begin UNO using === **/
58 	using ::com::sun::star::uno::Reference;
59 	using ::com::sun::star::uno::XInterface;
60 	using ::com::sun::star::uno::UNO_QUERY;
61 	using ::com::sun::star::uno::UNO_QUERY_THROW;
62 	using ::com::sun::star::uno::UNO_SET_THROW;
63 	using ::com::sun::star::uno::Exception;
64 	using ::com::sun::star::uno::RuntimeException;
65 	using ::com::sun::star::uno::Any;
66 	using ::com::sun::star::uno::makeAny;
67 	using ::com::sun::star::uno::Sequence;
68 	using ::com::sun::star::uno::Type;
69     using ::com::sun::star::lang::XMultiServiceFactory;
70     using ::com::sun::star::embed::XStorage;
71     using ::com::sun::star::sdb::application::XDatabaseDocumentUI;
72     using ::com::sun::star::beans::Pair;
73     using ::com::sun::star::frame::XModuleManager;
74     using ::com::sun::star::lang::XComponent;
75     using ::com::sun::star::frame::XModel;
76     using ::com::sun::star::frame::XController;
77     using ::com::sun::star::beans::XPropertySet;
78     using ::com::sun::star::beans::PropertyValue;
79     using ::com::sun::star::document::XStorageBasedDocument;
80     using ::com::sun::star::ucb::XCommandProcessor;
81     using ::com::sun::star::container::XHierarchicalNameAccess;
82     using ::com::sun::star::sdb::XFormDocumentsSupplier;
83     using ::com::sun::star::sdb::XReportDocumentsSupplier;
84     using ::com::sun::star::xml::sax::SAXException;
85     using ::com::sun::star::xml::sax::XLocator;
86     using ::com::sun::star::xml::sax::XDocumentHandler;
87     using ::com::sun::star::xml::sax::XAttributeList;
88 	/** === end UNO using === **/
89 
90     namespace ElementModes = ::com::sun::star::embed::ElementModes;
91 
92 
93 	//====================================================================
94 	//= helper
95 	//====================================================================
96     namespace
97     {
98         // .........................................................................
99         static const ::rtl::OUString& lcl_getComponentStorageBaseName( const SubComponentType i_eType )
100         {
101             static const ::rtl::OUString s_sFormBaseName( RTL_CONSTASCII_USTRINGPARAM( "form" ) );
102             static const ::rtl::OUString s_sReportBaseName( RTL_CONSTASCII_USTRINGPARAM( "report" ) );
103             static const ::rtl::OUString s_sTableBaseName( RTL_CONSTASCII_USTRINGPARAM( "table" ) );
104             static const ::rtl::OUString s_sQueryBaseName( RTL_CONSTASCII_USTRINGPARAM( "query" ) );
105 
106             switch ( i_eType )
107             {
108             case FORM:
109                 return s_sFormBaseName;
110             case REPORT:
111                 return s_sReportBaseName;
112             case TABLE:
113                 return s_sTableBaseName;
114             case QUERY:
115                 return s_sQueryBaseName;
116             default:
117                 break;
118             }
119 
120             OSL_ENSURE( false, "lcl_getComponentStorageBaseName: unimplemented case!" );
121             static const ::rtl::OUString s_sFallback;
122             return s_sFallback;
123         }
124 
125         // .........................................................................
126         static SubComponentType lcl_databaseObjectToSubComponentType( const sal_Int32 i_nObjectType )
127         {
128             switch ( i_nObjectType )
129             {
130             case DatabaseObject::TABLE: return TABLE;
131             case DatabaseObject::QUERY: return QUERY;
132             case DatabaseObject::FORM:  return FORM;
133             case DatabaseObject::REPORT:return REPORT;
134             default:
135                 break;
136             }
137             return UNKNOWN;
138         }
139 
140         // .........................................................................
141         static bool lcl_determineReadOnly( const Reference< XComponent >& i_rComponent )
142         {
143             Reference< XModel > xDocument( i_rComponent, UNO_QUERY );
144             if ( !xDocument.is() )
145             {
146                 Reference< XController > xController( i_rComponent, UNO_QUERY_THROW );
147                 xDocument = xController->getModel();
148             }
149 
150             if ( !xDocument.is() )
151                 return false;
152 
153             ::comphelper::NamedValueCollection aDocArgs( xDocument->getArgs() );
154             return aDocArgs.getOrDefault( "ReadOnly", false );
155         }
156 
157         // .........................................................................
158         static Reference< XCommandProcessor > lcl_getSubComponentDef_nothrow( const Reference< XDatabaseDocumentUI >& i_rAppUI,
159             const SubComponentType i_eType, const ::rtl::OUString& i_rName )
160         {
161             Reference< XController > xController( i_rAppUI, UNO_QUERY_THROW );
162             ENSURE_OR_RETURN( ( i_eType == FORM ) || ( i_eType == REPORT ), "lcl_getSubComponentDef_nothrow: illegal controller", NULL );
163 
164             Reference< XCommandProcessor > xCommandProcessor;
165             try
166             {
167                 Reference< XHierarchicalNameAccess > xDefinitionContainer;
168                 if ( i_eType == FORM )
169                 {
170                     Reference< XFormDocumentsSupplier > xSuppForms( xController->getModel(), UNO_QUERY_THROW );
171                     xDefinitionContainer.set( xSuppForms->getFormDocuments(), UNO_QUERY_THROW );
172                 }
173                 else
174                 {
175                     Reference< XReportDocumentsSupplier > xSuppReports( xController->getModel(), UNO_QUERY_THROW );
176                     xDefinitionContainer.set( xSuppReports->getReportDocuments(), UNO_QUERY_THROW );
177                 }
178                 xCommandProcessor.set( xDefinitionContainer->getByHierarchicalName( i_rName ), UNO_QUERY_THROW );
179             }
180             catch( const Exception& )
181             {
182             	DBG_UNHANDLED_EXCEPTION();
183             }
184             return xCommandProcessor;
185         }
186 
187         // .........................................................................
188         static const ::rtl::OUString& lcl_getSettingsStreamName()
189         {
190             static const ::rtl::OUString s_sStatementStreamName( RTL_CONSTASCII_USTRINGPARAM( "settings.xml" ) );
191             return s_sStatementStreamName;
192         }
193 
194         // .........................................................................
195         static const ::rtl::OUString& lcl_getCurrentQueryDesignName()
196         {
197             static const ::rtl::OUString s_sQuerySettingsName( RTL_CONSTASCII_USTRINGPARAM( "ooo:current-query-design" ) );
198             return s_sQuerySettingsName;
199         }
200     }
201 
202 	//====================================================================
203 	//= SettingsExportContext
204 	//====================================================================
205     class DBACCESS_DLLPRIVATE SettingsExportContext : public ::xmloff::XMLSettingsExportContext
206     {
207     public:
208         SettingsExportContext( const ::comphelper::ComponentContext& i_rContext, const StorageXMLOutputStream& i_rDelegator )
209             :m_rContext( i_rContext )
210             ,m_rDelegator( i_rDelegator )
211             ,m_aNamespace( ::xmloff::token::GetXMLToken( ::xmloff::token::XML_NP_CONFIG ) )
212         {
213         }
214 
215         virtual ~SettingsExportContext()
216         {
217         }
218 
219     public:
220 	    virtual void    AddAttribute( enum ::xmloff::token::XMLTokenEnum i_eName, const ::rtl::OUString& i_rValue );
221         virtual void    AddAttribute( enum ::xmloff::token::XMLTokenEnum i_eName, enum ::xmloff::token::XMLTokenEnum i_eValue );
222         virtual void    StartElement( enum ::xmloff::token::XMLTokenEnum i_eName, const sal_Bool i_bIgnoreWhitespace );
223         virtual void    EndElement  ( const sal_Bool i_bIgnoreWhitespace );
224         virtual void    Characters( const ::rtl::OUString& i_rCharacters );
225 
226         virtual ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >
227                         GetServiceFactory() const;
228 
229     private:
230         ::rtl::OUString impl_prefix( const ::xmloff::token::XMLTokenEnum i_eToken )
231         {
232             ::rtl::OUStringBuffer aQualifiedName( m_aNamespace );
233             aQualifiedName.append( sal_Unicode( ':' ) );
234             aQualifiedName.append( ::xmloff::token::GetXMLToken( i_eToken ) );
235             return aQualifiedName.makeStringAndClear();
236         }
237 
238     private:
239         const ::comphelper::ComponentContext&   m_rContext;
240         const StorageXMLOutputStream&           m_rDelegator;
241         const ::rtl::OUStringBuffer             m_aNamespace;
242     };
243 
244 	//--------------------------------------------------------------------
245     void SettingsExportContext::AddAttribute( enum ::xmloff::token::XMLTokenEnum i_eName, const ::rtl::OUString& i_rValue )
246     {
247         m_rDelegator.addAttribute( impl_prefix( i_eName ), i_rValue );
248     }
249 
250 	//--------------------------------------------------------------------
251     void SettingsExportContext::AddAttribute( enum ::xmloff::token::XMLTokenEnum i_eName, enum ::xmloff::token::XMLTokenEnum i_eValue )
252     {
253         m_rDelegator.addAttribute( impl_prefix( i_eName ), ::xmloff::token::GetXMLToken( i_eValue ) );
254     }
255 
256 	//--------------------------------------------------------------------
257     void SettingsExportContext::StartElement( enum ::xmloff::token::XMLTokenEnum i_eName, const sal_Bool i_bIgnoreWhitespace )
258     {
259         if ( i_bIgnoreWhitespace )
260             m_rDelegator.ignorableWhitespace( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " " ) ) );
261 
262         m_rDelegator.startElement( impl_prefix( i_eName ) );
263     }
264 
265 	//--------------------------------------------------------------------
266     void SettingsExportContext::EndElement( const sal_Bool i_bIgnoreWhitespace )
267     {
268         if ( i_bIgnoreWhitespace )
269             m_rDelegator.ignorableWhitespace( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " " ) ) );
270         m_rDelegator.endElement();
271     }
272 
273 	//--------------------------------------------------------------------
274     void SettingsExportContext::Characters( const ::rtl::OUString& i_rCharacters )
275     {
276         m_rDelegator.characters( i_rCharacters );
277     }
278 
279 	//--------------------------------------------------------------------
280     Reference< XMultiServiceFactory > SettingsExportContext::GetServiceFactory() const
281     {
282         return m_rContext.getLegacyServiceFactory();
283     }
284 
285 	//==================================================================================================================
286 	//= SettingsDocumentHandler
287 	//==================================================================================================================
288     typedef ::cppu::WeakImplHelper1 <   XDocumentHandler
289                                     >   SettingsDocumentHandler_Base;
290     class DBACCESS_DLLPRIVATE SettingsDocumentHandler : public SettingsDocumentHandler_Base
291     {
292     public:
293         SettingsDocumentHandler()
294         {
295         }
296 
297     protected:
298         virtual ~SettingsDocumentHandler()
299         {
300         }
301 
302     public:
303         // XDocumentHandler
304         virtual void SAL_CALL startDocument(  ) throw (SAXException, RuntimeException);
305         virtual void SAL_CALL endDocument(  ) throw (SAXException, RuntimeException);
306         virtual void SAL_CALL startElement( const ::rtl::OUString& aName, const Reference< XAttributeList >& xAttribs ) throw (SAXException, RuntimeException);
307         virtual void SAL_CALL endElement( const ::rtl::OUString& aName ) throw (SAXException, RuntimeException);
308         virtual void SAL_CALL characters( const ::rtl::OUString& aChars ) throw (SAXException, RuntimeException);
309         virtual void SAL_CALL ignorableWhitespace( const ::rtl::OUString& aWhitespaces ) throw (SAXException, RuntimeException);
310         virtual void SAL_CALL processingInstruction( const ::rtl::OUString& aTarget, const ::rtl::OUString& aData ) throw (SAXException, RuntimeException);
311         virtual void SAL_CALL setDocumentLocator( const Reference< XLocator >& xLocator ) throw (SAXException, RuntimeException);
312 
313         const ::comphelper::NamedValueCollection&   getSettings() const { return m_aSettings; }
314 
315     private:
316         ::std::stack< ::rtl::Reference< SettingsImport > >  m_aStates;
317         ::comphelper::NamedValueCollection                  m_aSettings;
318     };
319 
320     //--------------------------------------------------------------------
321     void SAL_CALL SettingsDocumentHandler::startDocument(  ) throw (SAXException, RuntimeException)
322     {
323     }
324 
325     //--------------------------------------------------------------------
326     void SAL_CALL SettingsDocumentHandler::endDocument(  ) throw (SAXException, RuntimeException)
327     {
328     }
329 
330     //--------------------------------------------------------------------
331     void SAL_CALL SettingsDocumentHandler::startElement( const ::rtl::OUString& i_Name, const Reference< XAttributeList >& i_Attribs ) throw (SAXException, RuntimeException)
332     {
333         ::rtl::Reference< SettingsImport >  pNewState;
334 
335         if ( m_aStates.empty() )
336         {
337             if ( i_Name.equalsAscii( "office:settings" ) )
338             {
339                 pNewState = new OfficeSettingsImport( m_aSettings );
340             }
341             else
342             {
343                 OSL_ENSURE( false, "SettingsDocumentHandler::startElement: invalid settings file!" );
344                 // Yes, that's not correct. Somebody could, in theory, give us a document which starts with "foo:settings",
345                 // where "foo" is mapped to the proper namespace URL.
346                 // However, there's no need to bother with this. The "recovery" sub storage we're recovering from is
347                 // not part of ODF, so we can impose any format restrictions on it ...
348             }
349         }
350         else
351         {
352             ::rtl::Reference< SettingsImport > pCurrentState( m_aStates.top() );
353             pNewState = pCurrentState->nextState( i_Name );
354         }
355 
356         ENSURE_OR_THROW( pNewState.is(), "no new state - aborting import" );
357         pNewState->startElement( i_Attribs );
358 
359         m_aStates.push( pNewState );
360     }
361 
362     //--------------------------------------------------------------------
363     void SAL_CALL SettingsDocumentHandler::endElement( const ::rtl::OUString& i_Name ) throw (SAXException, RuntimeException)
364     {
365         ENSURE_OR_THROW( !m_aStates.empty(), "no active element" );
366         (void)i_Name;
367 
368         ::rtl::Reference< SettingsImport > pCurrentState( m_aStates.top() );
369         pCurrentState->endElement();
370         m_aStates.pop();
371     }
372 
373     //--------------------------------------------------------------------
374     void SAL_CALL SettingsDocumentHandler::characters( const ::rtl::OUString& i_Chars ) throw (SAXException, RuntimeException)
375     {
376         ENSURE_OR_THROW( !m_aStates.empty(), "no active element" );
377 
378         ::rtl::Reference< SettingsImport > pCurrentState( m_aStates.top() );
379         pCurrentState->characters( i_Chars );
380     }
381 
382     //--------------------------------------------------------------------
383     void SAL_CALL SettingsDocumentHandler::ignorableWhitespace( const ::rtl::OUString& aWhitespaces ) throw (SAXException, RuntimeException)
384     {
385         // ignore them - that's why they're called "ignorable"
386         (void)aWhitespaces;
387     }
388 
389     //--------------------------------------------------------------------
390     void SAL_CALL SettingsDocumentHandler::processingInstruction( const ::rtl::OUString& i_Target, const ::rtl::OUString& i_Data ) throw (SAXException, RuntimeException)
391     {
392         OSL_ENSURE( false, "SettingsDocumentHandler::processingInstruction: unexpected ..." );
393         (void)i_Target;
394         (void)i_Data;
395     }
396 
397     //--------------------------------------------------------------------
398     void SAL_CALL SettingsDocumentHandler::setDocumentLocator( const Reference< XLocator >& i_Locator ) throw (SAXException, RuntimeException)
399     {
400         (void)i_Locator;
401     }
402 
403 	//====================================================================
404     //= SubComponentRecovery
405 	//====================================================================
406 	//--------------------------------------------------------------------
407     const ::rtl::OUString SubComponentRecovery::getComponentsStorageName( const SubComponentType i_eType )
408     {
409         static const ::rtl::OUString s_sFormsStorageName( RTL_CONSTASCII_USTRINGPARAM( "forms" ) );
410         static const ::rtl::OUString s_sReportsStorageName( RTL_CONSTASCII_USTRINGPARAM( "reports" ) );
411         static const ::rtl::OUString s_sTablesStorageName( RTL_CONSTASCII_USTRINGPARAM( "tables" ) );
412         static const ::rtl::OUString s_sQueriesStorageName( RTL_CONSTASCII_USTRINGPARAM( "queries" ) );
413         static const ::rtl::OUString s_sRelationsStorageName( RTL_CONSTASCII_USTRINGPARAM( "relations" ) );
414 
415         switch ( i_eType )
416         {
417         case FORM:
418             return s_sFormsStorageName;
419         case REPORT:
420             return s_sReportsStorageName;
421         case TABLE:
422             return s_sTablesStorageName;
423         case QUERY:
424             return s_sQueriesStorageName;
425         case RELATION_DESIGN:
426             return s_sRelationsStorageName;
427         default:
428             break;
429         }
430 
431         OSL_ENSURE( false, "SubComponentRecovery::getComponentsStorageName: unimplemented case!" );
432         static const ::rtl::OUString s_sFallback;
433         return s_sFallback;
434     }
435 
436 	//--------------------------------------------------------------------
437     void SubComponentRecovery::saveToRecoveryStorage( const Reference< XStorage >& i_rRecoveryStorage,
438         MapCompTypeToCompDescs& io_mapCompDescs )
439     {
440         if ( m_eType == UNKNOWN )
441             // quite fatal, but has already been reported (as assertion) before
442             return;
443 
444         // open the sub storage for the given kind of components
445         const ::rtl::OUString& rStorageName( getComponentsStorageName( m_eType ) );
446         const Reference< XStorage > xComponentsStorage( i_rRecoveryStorage->openStorageElement(
447             rStorageName, ElementModes::READWRITE ), UNO_QUERY_THROW );
448 
449         // find a free sub storage name, and create Yet Another Sub Storage
450         const ::rtl::OUString& rBaseName( lcl_getComponentStorageBaseName( m_eType ) );
451         const ::rtl::OUString sStorName = ::dbtools::createUniqueName( xComponentsStorage.get(), rBaseName, true );
452         const Reference< XStorage > xObjectStor( xComponentsStorage->openStorageElement(
453             sStorName, ElementModes::READWRITE ), UNO_QUERY_THROW );
454 
455         switch ( m_eType )
456         {
457         case FORM:
458         case REPORT:
459             impl_saveSubDocument_throw( xObjectStor );
460             break;
461 
462         case QUERY:
463             impl_saveQueryDesign_throw( xObjectStor );
464             break;
465 
466         default:
467             // TODO
468             OSL_ENSURE( false, "SubComponentRecoverys::saveToRecoveryStorage: unimplemented case!" );
469             break;
470         }
471 
472         // commit the storage(s)
473         tools::stor::commitStorageIfWriteable( xObjectStor );
474         tools::stor::commitStorageIfWriteable( xComponentsStorage );
475 
476         // remember the relationship from the component name to the storage name
477         MapStringToCompDesc& rMapCompDescs = io_mapCompDescs[ m_eType ];
478         OSL_ENSURE( rMapCompDescs.find( sStorName ) == rMapCompDescs.end(),
479             "SubComponentRecoverys::saveToRecoveryStorage: object name already used!" );
480         rMapCompDescs[ sStorName ] = m_aCompDesc;
481     }
482 
483 	//--------------------------------------------------------------------
484     void SubComponentRecovery::impl_identifyComponent_throw()
485     {
486         // ask the controller
487         Pair< sal_Int32, ::rtl::OUString > aComponentIdentity = m_xDocumentUI->identifySubComponent( m_xComponent );
488         m_eType = lcl_databaseObjectToSubComponentType( aComponentIdentity.First );
489         m_aCompDesc.sName = aComponentIdentity.Second;
490 
491         // what the controller didn't give us is the information whether this is in edit mode or not ...
492         Reference< XModuleManager > xModuleManager( m_rContext.createComponent( "com.sun.star.frame.ModuleManager" ), UNO_QUERY_THROW );
493         const ::rtl::OUString sModuleIdentifier = xModuleManager->identify( m_xComponent );
494 
495         switch ( m_eType )
496         {
497         case TABLE:
498             m_aCompDesc.bForEditing = sModuleIdentifier.equalsAscii( "com.sun.star.sdb.TableDesign" );
499             break;
500 
501         case QUERY:
502             m_aCompDesc.bForEditing = sModuleIdentifier.equalsAscii( "com.sun.star.sdb.QueryDesign" );
503             break;
504 
505         case REPORT:
506             if ( sModuleIdentifier.equalsAscii( "com.sun.star.report.ReportDefinition" ) )
507             {
508                 // it's an SRB report desginer
509                 m_aCompDesc.bForEditing = true;
510                 break;
511             }
512             // fall through
513 
514         case FORM:
515             m_aCompDesc.bForEditing = !lcl_determineReadOnly( m_xComponent );
516             break;
517 
518         default:
519             if ( sModuleIdentifier.equalsAscii( "com.sun.star.sdb.RelationDesign" ) )
520             {
521                 m_eType = RELATION_DESIGN;
522                 m_aCompDesc.bForEditing = true;
523             }
524             else
525             {
526                 OSL_ENSURE( false, "SubComponentRecovery::impl_identifyComponent_throw: couldn't classify the given sub component!" );
527             }
528             break;
529         }
530 
531         OSL_POSTCOND( m_eType != UNKNOWN,
532             "SubComponentRecovery::impl_identifyComponent_throw: couldn't classify the component!" );
533     }
534 
535 	//--------------------------------------------------------------------
536     void SubComponentRecovery::impl_saveQueryDesign_throw( const Reference< XStorage >& i_rObjectStorage )
537     {
538         ENSURE_OR_THROW( m_eType == QUERY, "illegal sub component type" );
539         ENSURE_OR_THROW( i_rObjectStorage.is(), "illegal storage" );
540 
541         // retrieve the current query design (which might differ from what we can retrieve as ActiveCommand property, since
542         // the latter is updated only upon successful save of the design)
543         Reference< XPropertySet > xDesignerProps( m_xComponent, UNO_QUERY_THROW );
544         Sequence< PropertyValue > aCurrentQueryDesign;
545         OSL_VERIFY( xDesignerProps->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CurrentQueryDesign" ) ) ) >>= aCurrentQueryDesign );
546 
547         // write the query design
548         StorageXMLOutputStream aDesignOutput( m_rContext, i_rObjectStorage, lcl_getSettingsStreamName() );
549         SettingsExportContext aSettingsExportContext( m_rContext, aDesignOutput );
550 
551         const ::rtl::OUString sWhitespace( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " " ) ) );
552 
553         aDesignOutput.startElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "office:settings" ) ) );
554         aDesignOutput.ignorableWhitespace( sWhitespace );
555 
556         XMLSettingsExportHelper aSettingsExporter( aSettingsExportContext );
557         aSettingsExporter.exportAllSettings( aCurrentQueryDesign, lcl_getCurrentQueryDesignName() );
558 
559         aDesignOutput.ignorableWhitespace( sWhitespace );
560         aDesignOutput.endElement();
561         aDesignOutput.close();
562     }
563 
564 	//--------------------------------------------------------------------
565     void SubComponentRecovery::impl_saveSubDocument_throw( const Reference< XStorage >& i_rObjectStorage )
566     {
567         ENSURE_OR_THROW( ( m_eType == FORM ) || ( m_eType == REPORT ), "illegal sub component type" );
568         ENSURE_OR_THROW( i_rObjectStorage.is(), "illegal storage" );
569 
570         // store the document into the storage
571         Reference< XStorageBasedDocument > xStorageDocument( m_xComponent, UNO_QUERY_THROW );
572         xStorageDocument->storeToStorage( i_rObjectStorage, Sequence< PropertyValue >() );
573     }
574 
575 	//--------------------------------------------------------------------
576     Reference< XComponent > SubComponentRecovery::impl_recoverSubDocument_throw( const Reference< XStorage >& i_rRecoveryStorage,
577             const ::rtl::OUString& i_rComponentName, const bool i_bForEditing )
578     {
579         Reference< XComponent > xSubComponent;
580         Reference< XCommandProcessor > xDocDefinition;
581 
582         ::comphelper::NamedValueCollection aLoadArgs;
583         aLoadArgs.put( "RecoveryStorage", i_rRecoveryStorage );
584 
585         // load/create the sub component hidden. We'll show it when the main app window is shown.
586         aLoadArgs.put( "Hidden", true );
587 
588         if ( i_rComponentName.getLength() )
589         {
590             xDocDefinition = lcl_getSubComponentDef_nothrow( m_xDocumentUI, m_eType, i_rComponentName );
591             xSubComponent.set( m_xDocumentUI->loadComponentWithArguments(
592                     m_eType,
593                     i_rComponentName,
594                     i_bForEditing,
595                     aLoadArgs.getPropertyValues()
596                 ),
597                 UNO_SET_THROW
598             );
599         }
600         else
601         {
602             Reference< XComponent > xDocDefComponent;
603             xSubComponent.set( m_xDocumentUI->createComponentWithArguments(
604                     m_eType,
605                     aLoadArgs.getPropertyValues(),
606                     xDocDefComponent
607                 ),
608                 UNO_SET_THROW
609             );
610 
611             xDocDefinition.set( xDocDefComponent, UNO_QUERY );
612             OSL_ENSURE( xDocDefinition.is(), "DatabaseDocumentRecovery::recoverSubDocuments: loaded a form/report, but don't have a document definition?!" );
613         }
614 
615         if ( xDocDefinition.is() )
616         {
617             Reference< XController > xController( m_xDocumentUI, UNO_QUERY_THROW );
618             Reference< XInterface > xLoader( *new SubComponentLoader( xController, xDocDefinition ) );
619             (void)xLoader;
620         }
621 
622         return xSubComponent;
623     }
624 
625 	//--------------------------------------------------------------------
626     Reference< XComponent > SubComponentRecovery::impl_recoverQueryDesign_throw( const Reference< XStorage >& i_rRecoveryStorage,
627         const ::rtl::OUString& i_rComponentName,  const bool i_bForEditing )
628     {
629         Reference< XComponent > xSubComponent;
630 
631         // first read the settings query design settings from the storage
632         StorageXMLInputStream aDesignInput( m_rContext, i_rRecoveryStorage, lcl_getSettingsStreamName() );
633 
634         ::rtl::Reference< SettingsDocumentHandler > pDocHandler( new SettingsDocumentHandler );
635         aDesignInput.import( pDocHandler.get() );
636 
637         const ::comphelper::NamedValueCollection& rSettings( pDocHandler->getSettings() );
638         const Any aCurrentQueryDesign = rSettings.get( lcl_getCurrentQueryDesignName() );
639 #if OSL_DEBUG_LEVEL > 0
640         Sequence< PropertyValue > aQueryDesignLayout;
641         OSL_VERIFY( aCurrentQueryDesign >>= aQueryDesignLayout );
642 #endif
643 
644         // then load the query designer
645         ::comphelper::NamedValueCollection aLoadArgs;
646         aLoadArgs.put( "CurrentQueryDesign", aCurrentQueryDesign );
647         aLoadArgs.put( "Hidden", true );
648 
649         if ( i_rComponentName.getLength() )
650         {
651             xSubComponent.set( m_xDocumentUI->loadComponentWithArguments(
652                     m_eType,
653                     i_rComponentName,
654                     i_bForEditing,
655                     aLoadArgs.getPropertyValues()
656                 ),
657                 UNO_SET_THROW
658             );
659         }
660         else
661         {
662             Reference< XComponent > xDummy;
663             xSubComponent.set( m_xDocumentUI->createComponentWithArguments(
664                     m_eType,
665                     aLoadArgs.getPropertyValues(),
666                     xDummy
667                 ),
668                 UNO_SET_THROW
669             );
670         }
671 
672         Reference< XController > xController( m_xDocumentUI, UNO_QUERY_THROW );
673         Reference< XInterface > xLoader( *new SubComponentLoader( xController, xSubComponent ) );
674         (void)xLoader;
675 
676         return xSubComponent;
677     }
678 
679 	//--------------------------------------------------------------------
680     Reference< XComponent > SubComponentRecovery::recoverFromStorage( const Reference< XStorage >& i_rRecoveryStorage,
681             const ::rtl::OUString& i_rComponentName, const bool i_bForEditing )
682     {
683         Reference< XComponent > xSubComponent;
684         switch ( m_eType )
685         {
686         case FORM:
687         case REPORT:
688             xSubComponent = impl_recoverSubDocument_throw( i_rRecoveryStorage, i_rComponentName, i_bForEditing );
689             break;
690         case QUERY:
691             xSubComponent = impl_recoverQueryDesign_throw( i_rRecoveryStorage, i_rComponentName, i_bForEditing );
692             break;
693         default:
694             OSL_ENSURE( false, "SubComponentRecovery::recoverFromStorage: unimplemented case!" );
695             break;
696         }
697         return xSubComponent;
698     }
699 
700 //........................................................................
701 } // namespace dbaccess
702 //........................................................................
703