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