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