summaryrefslogtreecommitdiffstats
path: root/dbaccess/source/core/recovery
diff options
context:
space:
mode:
Diffstat (limited to 'dbaccess/source/core/recovery')
-rw-r--r--dbaccess/source/core/recovery/dbdocrecovery.cxx347
-rw-r--r--dbaccess/source/core/recovery/settingsimport.cxx216
-rw-r--r--dbaccess/source/core/recovery/settingsimport.hxx163
-rw-r--r--dbaccess/source/core/recovery/storagestream.cxx55
-rw-r--r--dbaccess/source/core/recovery/storagestream.hxx51
-rw-r--r--dbaccess/source/core/recovery/storagetextstream.cxx71
-rw-r--r--dbaccess/source/core/recovery/storagetextstream.hxx52
-rw-r--r--dbaccess/source/core/recovery/storagexmlstream.cxx151
-rw-r--r--dbaccess/source/core/recovery/storagexmlstream.hxx88
-rw-r--r--dbaccess/source/core/recovery/subcomponentloader.cxx124
-rw-r--r--dbaccess/source/core/recovery/subcomponentloader.hxx71
-rw-r--r--dbaccess/source/core/recovery/subcomponentrecovery.cxx628
-rw-r--r--dbaccess/source/core/recovery/subcomponentrecovery.hxx114
-rw-r--r--dbaccess/source/core/recovery/subcomponents.hxx61
14 files changed, 2192 insertions, 0 deletions
diff --git a/dbaccess/source/core/recovery/dbdocrecovery.cxx b/dbaccess/source/core/recovery/dbdocrecovery.cxx
new file mode 100644
index 000000000..db7bb53bd
--- /dev/null
+++ b/dbaccess/source/core/recovery/dbdocrecovery.cxx
@@ -0,0 +1,347 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <recovery/dbdocrecovery.hxx>
+#include <sdbcoretools.hxx>
+#include "storagetextstream.hxx"
+#include "subcomponentrecovery.hxx"
+#include "subcomponents.hxx"
+
+#include <com/sun/star/sdb/application/XDatabaseDocumentUI.hpp>
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/io/TextInputStream.hpp>
+#include <com/sun/star/util/XModifiable.hpp>
+
+#include <rtl/ustrbuf.hxx>
+#include <sal/log.hxx>
+#include <tools/diagnose_ex.h>
+
+namespace dbaccess
+{
+
+ using css::uno::Reference;
+ using css::uno::UNO_QUERY;
+ using css::uno::UNO_QUERY_THROW;
+ using css::uno::UNO_SET_THROW;
+ using css::uno::Exception;
+ using css::uno::Sequence;
+ using css::uno::XComponentContext;
+ using css::embed::XStorage;
+ using css::frame::XController;
+ using css::sdb::application::XDatabaseDocumentUI;
+ using css::lang::XComponent;
+ using css::io::XStream;
+ using css::io::TextInputStream;
+ using css::io::XTextInputStream2;
+ using css::util::XModifiable;
+
+ namespace ElementModes = css::embed::ElementModes;
+
+ // helpers
+ namespace
+ {
+ void lcl_getPersistentRepresentation( const MapStringToCompDesc::value_type& i_rComponentDesc, OUStringBuffer& o_rBuffer )
+ {
+ o_rBuffer.append( i_rComponentDesc.first );
+ o_rBuffer.append( '=' );
+ o_rBuffer.append( i_rComponentDesc.second.sName );
+ o_rBuffer.append( ',' );
+ o_rBuffer.append( sal_Unicode( i_rComponentDesc.second.bForEditing ? '1' : '0' ) );
+ }
+
+ bool lcl_extractCompDesc( const OUString& i_rIniLine, OUString& o_rStorName, SubComponentDescriptor& o_rCompDesc )
+ {
+ const sal_Int32 nEqualSignPos = i_rIniLine.indexOf( '=' );
+ if ( nEqualSignPos < 1 )
+ {
+ OSL_FAIL( "lcl_extractCompDesc: invalid map file entry - unexpected pos of '='" );
+ return false;
+ }
+ o_rStorName = i_rIniLine.copy( 0, nEqualSignPos );
+
+ const sal_Int32 nCommaPos = i_rIniLine.lastIndexOf( ',' );
+ if ( nCommaPos != i_rIniLine.getLength() - 2 )
+ {
+ OSL_FAIL( "lcl_extractCompDesc: invalid map file entry - unexpected pos of ','" );
+ return false;
+ }
+ o_rCompDesc.sName = i_rIniLine.copy( nEqualSignPos + 1, nCommaPos - nEqualSignPos - 1 );
+ o_rCompDesc.bForEditing = ( i_rIniLine[ nCommaPos + 1 ] == '1' );
+ return true;
+ }
+
+ constexpr OUStringLiteral sRecoveryDataSubStorageName = u"recovery";
+
+ constexpr OUStringLiteral sObjectMapStreamName = u"storage-component-map.ini";
+
+ void lcl_writeObjectMap_throw( const Reference<XComponentContext> & i_rContext, const Reference< XStorage >& i_rStorage,
+ const MapStringToCompDesc& i_mapStorageToCompDesc )
+ {
+ if ( i_mapStorageToCompDesc.empty() )
+ // nothing to do
+ return;
+
+ StorageTextOutputStream aTextOutput( i_rContext, i_rStorage, sObjectMapStreamName );
+
+ aTextOutput.writeLine( "[storages]" );
+
+ for (auto const& elem : i_mapStorageToCompDesc)
+ {
+ OUStringBuffer aLine;
+ lcl_getPersistentRepresentation(elem, aLine);
+
+ aTextOutput.writeLine( aLine.makeStringAndClear() );
+ }
+
+ aTextOutput.writeLine();
+ }
+
+ bool lcl_isSectionStart( const OUString& i_rIniLine, OUString& o_rSectionName )
+ {
+ const sal_Int32 nLen = i_rIniLine.getLength();
+ if ( i_rIniLine.startsWith("[") && i_rIniLine.endsWith("]") )
+ {
+ o_rSectionName = i_rIniLine.copy( 1, nLen -2 );
+ return true;
+ }
+ return false;
+ }
+
+ void lcl_stripTrailingLineFeed( OUString& io_rLine )
+ {
+ const sal_Int32 nLen = io_rLine.getLength();
+ if ( io_rLine.endsWith("\n") )
+ io_rLine = io_rLine.copy( 0, nLen - 1 );
+ }
+
+ void lcl_readObjectMap_throw( const Reference<XComponentContext> & i_rxContext, const Reference< XStorage >& i_rStorage,
+ MapStringToCompDesc& o_mapStorageToObjectName )
+ {
+ ENSURE_OR_THROW( i_rStorage.is(), "invalid storage" );
+ if ( !i_rStorage->hasByName( sObjectMapStreamName ) )
+ { // nothing to do, though suspicious
+ OSL_FAIL( "lcl_readObjectMap_throw: if there's no map file, then there's expected to be no storage, too!" );
+ return;
+ }
+
+ Reference< XStream > xIniStream( i_rStorage->openStreamElement(
+ sObjectMapStreamName, ElementModes::READ ), UNO_SET_THROW );
+
+ Reference< XTextInputStream2 > xTextInput = TextInputStream::create( i_rxContext );
+ xTextInput->setEncoding( "UTF-8" );
+ xTextInput->setInputStream( xIniStream->getInputStream() );
+
+ OUString sCurrentSection;
+ bool bCurrentSectionIsKnownToBeUnsupported = true;
+ while ( !xTextInput->isEOF() )
+ {
+ OUString sLine = xTextInput->readLine();
+ lcl_stripTrailingLineFeed( sLine );
+
+ if ( sLine.isEmpty() )
+ continue;
+
+ if ( lcl_isSectionStart( sLine, sCurrentSection ) )
+ {
+ bCurrentSectionIsKnownToBeUnsupported = false;
+ continue;
+ }
+
+ if ( bCurrentSectionIsKnownToBeUnsupported )
+ continue;
+
+ // the only section we support so far is "storages"
+ if ( sCurrentSection != "storages" )
+ {
+ bCurrentSectionIsKnownToBeUnsupported = true;
+ continue;
+ }
+
+ OUString sStorageName;
+ SubComponentDescriptor aCompDesc;
+ if ( !lcl_extractCompDesc( sLine, sStorageName, aCompDesc ) )
+ continue;
+ o_mapStorageToObjectName[ sStorageName ] = aCompDesc;
+ }
+ }
+
+ void lcl_markModified( const Reference< XComponent >& i_rSubComponent )
+ {
+ const Reference< XModifiable > xModify( i_rSubComponent, UNO_QUERY );
+ if ( !xModify.is() )
+ {
+ OSL_FAIL( "lcl_markModified: unhandled case!" );
+ return;
+ }
+
+ xModify->setModified( true );
+ }
+ }
+
+ // DatabaseDocumentRecovery_Data
+ struct DatabaseDocumentRecovery_Data
+ {
+ const Reference<XComponentContext> aContext;
+
+ explicit DatabaseDocumentRecovery_Data( const Reference<XComponentContext> & i_rContext )
+ :aContext( i_rContext )
+ {
+ }
+ };
+
+ // DatabaseDocumentRecovery
+ DatabaseDocumentRecovery::DatabaseDocumentRecovery( const Reference<XComponentContext> & i_rContext )
+ :m_pData( new DatabaseDocumentRecovery_Data( i_rContext ) )
+ {
+ }
+
+ DatabaseDocumentRecovery::~DatabaseDocumentRecovery()
+ {
+ }
+
+ void DatabaseDocumentRecovery::saveModifiedSubComponents( const Reference< XStorage >& i_rTargetStorage,
+ const std::vector< Reference< XController > >& i_rControllers )
+ {
+ ENSURE_OR_THROW( i_rTargetStorage.is(), "invalid document storage" );
+
+ // create a sub storage for recovery data
+ if ( i_rTargetStorage->hasByName( sRecoveryDataSubStorageName ) )
+ i_rTargetStorage->removeElement( sRecoveryDataSubStorageName );
+ Reference< XStorage > xRecoveryStorage = i_rTargetStorage->openStorageElement( sRecoveryDataSubStorageName, ElementModes::READWRITE );
+
+ // store recovery data for open sub components of the given controller(s)
+ if ( !i_rControllers.empty() )
+ {
+ ENSURE_OR_THROW( i_rControllers.size() == 1, "can't handle more than one controller" );
+ // At the moment, there can be only one view to a database document. If we ever allow for more than this,
+ // then we need a concept for sub documents opened from different controllers (i.e. two document views,
+ // and the user opens the very same form in both views). And depending on this, we need a concept for
+ // how those are saved to the recovery file.
+
+ MapCompTypeToCompDescs aMapCompDescs;
+
+ for (auto const& controller : i_rControllers)
+ {
+ Reference< XDatabaseDocumentUI > xDatabaseUI(controller, UNO_QUERY_THROW);
+ const Sequence< Reference< XComponent > > aComponents( xDatabaseUI->getSubComponents() );
+
+ for ( auto const & component : aComponents )
+ {
+ SubComponentRecovery aComponentRecovery( m_pData->aContext, xDatabaseUI, component );
+ aComponentRecovery.saveToRecoveryStorage( xRecoveryStorage, aMapCompDescs );
+ }
+ }
+
+ for (auto const& elem : aMapCompDescs)
+ {
+ Reference< XStorage > xComponentsStor( xRecoveryStorage->openStorageElement(
+ SubComponentRecovery::getComponentsStorageName( elem.first ), ElementModes::WRITE | ElementModes::NOCREATE ) );
+ lcl_writeObjectMap_throw( m_pData->aContext, xComponentsStor, elem.second );
+ tools::stor::commitStorageIfWriteable( xComponentsStor );
+ }
+ }
+
+ // commit the recovery storage
+ tools::stor::commitStorageIfWriteable( xRecoveryStorage );
+ }
+
+ void DatabaseDocumentRecovery::recoverSubDocuments( const Reference< XStorage >& i_rDocumentStorage,
+ const Reference< XController >& i_rTargetController )
+ {
+ ENSURE_OR_THROW( i_rDocumentStorage.is(), "illegal document storage" );
+ Reference< XDatabaseDocumentUI > xDocumentUI( i_rTargetController, UNO_QUERY_THROW );
+
+ if ( !i_rDocumentStorage->hasByName( sRecoveryDataSubStorageName ) )
+ // that's allowed
+ return;
+
+ // the "recovery" sub storage
+ Reference< XStorage > xRecoveryStorage = i_rDocumentStorage->openStorageElement( sRecoveryDataSubStorageName, ElementModes::READ );
+
+ // read the map from sub storages to object names
+ MapCompTypeToCompDescs aMapCompDescs;
+ const SubComponentType aKnownTypes[] = { TABLE, QUERY, FORM, REPORT, RELATION_DESIGN };
+ for (SubComponentType aKnownType : aKnownTypes)
+ {
+ if ( !xRecoveryStorage->hasByName( SubComponentRecovery::getComponentsStorageName( aKnownType ) ) )
+ continue;
+
+ Reference< XStorage > xComponentsStor( xRecoveryStorage->openStorageElement(
+ SubComponentRecovery::getComponentsStorageName( aKnownType ), ElementModes::READ ) );
+ lcl_readObjectMap_throw( m_pData->aContext, xComponentsStor, aMapCompDescs[ aKnownType ] );
+ xComponentsStor->dispose();
+ }
+
+ // recover all sub components as indicated by the map
+ for (auto const& elemMapCompDescs : aMapCompDescs)
+ {
+ const SubComponentType eComponentType = elemMapCompDescs.first;
+
+ // the storage for all components of the current type
+ Reference< XStorage > xComponentsStor( xRecoveryStorage->openStorageElement(
+ SubComponentRecovery::getComponentsStorageName( eComponentType ), ElementModes::READ ), UNO_SET_THROW );
+
+ // loop through all components of this type
+ for (auto const& elem : elemMapCompDescs.second)
+ {
+ const OUString sComponentName(elem.second.sName);
+ if ( !xComponentsStor->hasByName(elem.first) )
+ {
+ SAL_WARN( "dbaccess",
+ "DatabaseDocumentRecovery::recoverSubDocuments: inconsistent recovery storage: storage '" <<
+ elem.first <<
+ "' not found in '" <<
+ SubComponentRecovery::getComponentsStorageName( eComponentType ) <<
+ "', but required per map file!" );
+ continue;
+ }
+
+ // the controller needs to have a connection to be able to open sub components
+ if ( !xDocumentUI->isConnected() )
+ xDocumentUI->connect();
+
+ // recover the single component
+ Reference< XStorage > xCompStor( xComponentsStor->openStorageElement( elem.first, ElementModes::READ ) );
+ SubComponentRecovery aComponentRecovery( m_pData->aContext, xDocumentUI, eComponentType );
+ Reference< XComponent > xSubComponent( aComponentRecovery.recoverFromStorage( xCompStor, sComponentName, elem.second.bForEditing ) );
+
+ // at the moment, we only store, during session save, sub components which are modified. So, set this
+ // recovered sub component to "modified", too.
+ lcl_markModified( xSubComponent );
+ }
+
+ xComponentsStor->dispose();
+ }
+
+ xRecoveryStorage->dispose();
+
+ // now that we successfully recovered, removed the "recovery" sub storage
+ try
+ {
+ i_rDocumentStorage->removeElement( sRecoveryDataSubStorageName );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ }
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/recovery/settingsimport.cxx b/dbaccess/source/core/recovery/settingsimport.cxx
new file mode 100644
index 000000000..821dea045
--- /dev/null
+++ b/dbaccess/source/core/recovery/settingsimport.cxx
@@ -0,0 +1,216 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "settingsimport.hxx"
+
+#include <tools/diagnose_ex.h>
+#include <sal/log.hxx>
+#include <sax/tools/converter.hxx>
+#include <xmloff/xmltoken.hxx>
+
+namespace dbaccess
+{
+
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::Any;
+ using ::com::sun::star::xml::sax::XAttributeList;
+
+ // SettingsImport
+ SettingsImport::SettingsImport()
+ {
+ }
+
+ SettingsImport::~SettingsImport()
+ {
+ }
+
+ void SettingsImport::startElement( const Reference< XAttributeList >& i_rAttributes )
+ {
+ // find the name of the setting
+ if ( i_rAttributes.is() )
+ {
+ m_sItemName = i_rAttributes->getValueByName( "config:name" );
+ m_sItemType = i_rAttributes->getValueByName( "config:type" );
+ }
+ }
+
+ void SettingsImport::endElement()
+ {
+ }
+
+ void SettingsImport::characters( std::u16string_view i_rCharacters )
+ {
+ m_aCharacters.append( i_rCharacters );
+ }
+
+ void SettingsImport::split( const OUString& i_rElementName, OUString& o_rNamespace, OUString& o_rLocalName )
+ {
+ o_rNamespace.clear();
+ o_rLocalName = i_rElementName;
+ const sal_Int32 nSeparatorPos = i_rElementName.indexOf( ':' );
+ if ( nSeparatorPos > -1 )
+ {
+ o_rNamespace = i_rElementName.copy( 0, nSeparatorPos );
+ o_rLocalName = i_rElementName.copy( nSeparatorPos + 1 );
+ }
+
+ OSL_ENSURE( o_rNamespace == "config", "SettingsImport::split: unexpected namespace!" );
+ // our recovery file is kind of hand-made, so there shouldn't be anything else than "config".
+ // If there is, then just ignore it ...
+ }
+
+ // IgnoringSettingsImport
+ ::rtl::Reference< SettingsImport > IgnoringSettingsImport::nextState( const OUString& )
+ {
+ return this;
+ }
+
+ // OfficeSettingsImport
+ OfficeSettingsImport::OfficeSettingsImport( ::comphelper::NamedValueCollection& o_rSettings )
+ :m_rSettings( o_rSettings )
+ {
+ }
+
+ OfficeSettingsImport::~OfficeSettingsImport()
+ {
+ }
+
+ ::rtl::Reference< SettingsImport > OfficeSettingsImport::nextState( const OUString& i_rElementName )
+ {
+ // separate the namespace part from the element name
+ OUString sNamespace;
+ OUString sLocalName;
+ split( i_rElementName, sNamespace, sLocalName );
+
+ if ( sLocalName == "config-item-set" )
+ return new ConfigItemSetImport( m_rSettings );
+
+ SAL_WARN( "dbaccess", "unknown (or unsupported at this place) element name '"
+ << i_rElementName
+ << "', ignoring");
+ return new IgnoringSettingsImport;
+ }
+
+ // ConfigItemImport
+ ConfigItemImport::ConfigItemImport( ::comphelper::NamedValueCollection& o_rSettings )
+ :m_rSettings( o_rSettings )
+ {
+ }
+
+ ConfigItemImport::~ConfigItemImport()
+ {
+ }
+
+ ::rtl::Reference< SettingsImport > ConfigItemImport::nextState( const OUString& )
+ {
+ OSL_FAIL( "ConfigItemImport::nextState: unexpected: this class is responsible for child-less items only!" );
+ return new IgnoringSettingsImport;
+ }
+
+ void ConfigItemImport::endElement()
+ {
+ SettingsImport::endElement();
+
+ const OUString sItemName( getItemName() );
+ ENSURE_OR_RETURN_VOID( !sItemName.isEmpty(), "no item name -> no item value" );
+ Any aValue;
+ getItemValue( aValue );
+ m_rSettings.put( sItemName, aValue );
+ }
+
+ void ConfigItemImport::getItemValue( css::uno::Any& o_rValue ) const
+ {
+ o_rValue.clear();
+
+ // the characters building up th evalue
+ std::u16string_view sValue = getAccumulatedCharacters();
+
+ const OUString& rItemType( getItemType() );
+ ENSURE_OR_RETURN_VOID( !rItemType.isEmpty(), "no item type -> no item value" );
+
+ if ( ::xmloff::token::IsXMLToken( rItemType, ::xmloff::token::XML_INT ) )
+ {
+ sal_Int32 nValue(0);
+ if (::sax::Converter::convertNumber( nValue, sValue ))
+ {
+ o_rValue <<= nValue;
+ }
+ else
+ {
+ OSL_FAIL( "ConfigItemImport::getItemValue: could not convert an int value!" );
+ }
+ }
+ else if ( ::xmloff::token::IsXMLToken( rItemType, ::xmloff::token::XML_BOOLEAN ) )
+ {
+ bool bValue(false);
+ if (::sax::Converter::convertBool( bValue, sValue ))
+ {
+ o_rValue <<= bValue;
+ }
+ else
+ {
+ OSL_FAIL( "ConfigItemImport::getItemValue: could not convert a boolean value!" );
+ }
+ }
+ else if ( ::xmloff::token::IsXMLToken( rItemType, ::xmloff::token::XML_STRING ) )
+ {
+ o_rValue <<= OUString(sValue);
+ }
+ else
+ {
+ SAL_WARN( "dbaccess", "ConfigItemImport::getItemValue: unsupported item type '"
+ << rItemType << "', ignoring");
+ }
+ }
+
+ // ConfigItemSetImport
+ ConfigItemSetImport::ConfigItemSetImport( ::comphelper::NamedValueCollection& o_rSettings )
+ :ConfigItemImport( o_rSettings )
+ {
+ }
+
+ ConfigItemSetImport::~ConfigItemSetImport()
+ {
+ }
+
+ ::rtl::Reference< SettingsImport > ConfigItemSetImport::nextState( const OUString& i_rElementName )
+ {
+ // separate the namespace part from the element name
+ OUString sNamespace;
+ OUString sLocalName;
+ split( i_rElementName, sNamespace, sLocalName );
+
+ if ( sLocalName == "config-item-set" )
+ return new ConfigItemSetImport( m_aChildSettings );
+ if ( sLocalName == "config-item" )
+ return new ConfigItemImport( m_aChildSettings );
+
+ SAL_WARN( "dbaccess", "unknown element name '"
+ << i_rElementName << "', ignoring");
+ return new IgnoringSettingsImport;
+ }
+
+ void ConfigItemSetImport::getItemValue( Any& o_rValue ) const
+ {
+ o_rValue <<= m_aChildSettings.getPropertyValues();
+ }
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/recovery/settingsimport.hxx b/dbaccess/source/core/recovery/settingsimport.hxx
new file mode 100644
index 000000000..bc29bd727
--- /dev/null
+++ b/dbaccess/source/core/recovery/settingsimport.hxx
@@ -0,0 +1,163 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/xml/sax/XAttributeList.hpp>
+
+#include <comphelper/namedvaluecollection.hxx>
+#include <rtl/ref.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <salhelper/simplereferenceobject.hxx>
+
+namespace dbaccess
+{
+
+ // SettingsImport
+ /** a simplified version of xmloff/DocumentSettingsContext
+
+ It would be nice if the DocumentSettingsContext would not be that tightly interwoven with the SvXMLImport
+ class, so we could re-use it here ...
+ */
+ class SettingsImport : public salhelper::SimpleReferenceObject
+ {
+ public:
+ SettingsImport();
+
+ // own overridables
+ virtual ::rtl::Reference< SettingsImport > nextState(
+ const OUString& i_rElementName
+ ) = 0;
+ void startElement(
+ const css::uno::Reference< css::xml::sax::XAttributeList >& i_rAttributes
+ );
+ virtual void endElement();
+ void characters( std::u16string_view i_rCharacters );
+
+ protected:
+ virtual ~SettingsImport() override;
+
+ protected:
+ static void split( const OUString& i_rElementName, OUString& o_rNamespace, OUString& o_rLocalName );
+
+ protected:
+ const OUString& getItemName() const { return m_sItemName; }
+ const OUString& getItemType() const { return m_sItemType; }
+ const OUStringBuffer& getAccumulatedCharacters() const { return m_aCharacters; }
+
+ private:
+ // value of the config:name attribute, if any
+ OUString m_sItemName;
+ // value of the config:type attribute, if any
+ OUString m_sItemType;
+ // accumulated characters, if any
+ OUStringBuffer m_aCharacters;
+ };
+
+ // IgnoringSettingsImport
+ class IgnoringSettingsImport : public SettingsImport
+ {
+ public:
+ IgnoringSettingsImport()
+ {
+ }
+
+ // SettingsImport overridables
+ virtual ::rtl::Reference< SettingsImport > nextState(
+ const OUString& i_rElementName
+ ) override;
+
+ private:
+ virtual ~IgnoringSettingsImport() override
+ {
+ }
+ };
+
+ // OfficeSettingsImport
+ class OfficeSettingsImport : public SettingsImport
+ {
+ public:
+ explicit OfficeSettingsImport( ::comphelper::NamedValueCollection& o_rSettings );
+
+ // SettingsImport overridables
+ virtual ::rtl::Reference< SettingsImport > nextState(
+ const OUString& i_rElementName
+ ) override;
+
+ protected:
+ virtual ~OfficeSettingsImport() override;
+
+ private:
+ // the settings collection to which |this| will contribute a single setting
+ ::comphelper::NamedValueCollection& m_rSettings;
+ };
+
+ // ConfigItemSetImport
+ class ConfigItemImport : public SettingsImport
+ {
+ public:
+ explicit ConfigItemImport( ::comphelper::NamedValueCollection& o_rSettings );
+
+ protected:
+ virtual ~ConfigItemImport() override;
+
+ public:
+ // SettingsImport overridables
+ virtual ::rtl::Reference< SettingsImport > nextState(
+ const OUString& i_rElementName
+ ) override;
+ virtual void endElement() override;
+
+ protected:
+ // own overridables
+ /// retrieves the value represented by the element
+ virtual void getItemValue( css::uno::Any& o_rValue ) const;
+
+ private:
+ // the settings collection to which |this| will contribute a single setting
+ ::comphelper::NamedValueCollection& m_rSettings;
+ };
+
+ // ConfigItemSetImport
+ class ConfigItemSetImport : public ConfigItemImport
+ {
+ public:
+ explicit ConfigItemSetImport( ::comphelper::NamedValueCollection& o_rSettings );
+
+ protected:
+ virtual ~ConfigItemSetImport() override;
+
+ public:
+ // SettingsImport overridables
+ virtual ::rtl::Reference< SettingsImport > nextState(
+ const OUString& i_rElementName
+ ) override;
+
+ protected:
+ // ConfigItemImport overridables
+ virtual void getItemValue( css::uno::Any& o_rValue ) const override;
+
+ private:
+ /// the settings represented by our child elements
+ ::comphelper::NamedValueCollection m_aChildSettings;
+ };
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/recovery/storagestream.cxx b/dbaccess/source/core/recovery/storagestream.cxx
new file mode 100644
index 000000000..2831f406b
--- /dev/null
+++ b/dbaccess/source/core/recovery/storagestream.cxx
@@ -0,0 +1,55 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "storagestream.hxx"
+
+#include <com/sun/star/embed/ElementModes.hpp>
+
+#include <tools/diagnose_ex.h>
+
+namespace dbaccess
+{
+
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::UNO_QUERY_THROW;
+ using ::com::sun::star::uno::UNO_SET_THROW;
+ using ::com::sun::star::embed::XStorage;
+ using ::com::sun::star::io::XStream;
+
+ namespace ElementModes = ::com::sun::star::embed::ElementModes;
+
+ // StorageOutputStream
+ StorageOutputStream::StorageOutputStream( const Reference< XStorage >& i_rParentStorage,
+ const OUString& i_rStreamName
+ )
+ {
+ ENSURE_OR_THROW( i_rParentStorage.is(), "illegal stream" );
+
+ const Reference< XStream > xStream(
+ i_rParentStorage->openStreamElement( i_rStreamName, ElementModes::READWRITE ), UNO_SET_THROW );
+ m_xOutputStream.set( xStream->getOutputStream(), UNO_SET_THROW );
+ }
+
+ StorageOutputStream::~StorageOutputStream()
+ {
+ }
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/recovery/storagestream.hxx b/dbaccess/source/core/recovery/storagestream.hxx
new file mode 100644
index 000000000..64c7e369d
--- /dev/null
+++ b/dbaccess/source/core/recovery/storagestream.hxx
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/embed/XStorage.hpp>
+
+namespace dbaccess
+{
+
+ // StorageOutputStream
+ /** convenience wrapper around a stream living in a storage
+ */
+ class StorageOutputStream
+ {
+ public:
+ StorageOutputStream(
+ const css::uno::Reference< css::embed::XStorage >& i_rParentStorage,
+ const OUString& i_rStreamName
+ );
+ virtual ~StorageOutputStream();
+
+ protected:
+ const css::uno::Reference< css::io::XOutputStream >&
+ getOutputStream() const { return m_xOutputStream; }
+
+ private:
+ css::uno::Reference< css::io::XOutputStream >
+ m_xOutputStream;
+ };
+
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/recovery/storagetextstream.cxx b/dbaccess/source/core/recovery/storagetextstream.cxx
new file mode 100644
index 000000000..32f68da9a
--- /dev/null
+++ b/dbaccess/source/core/recovery/storagetextstream.cxx
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "storagetextstream.hxx"
+
+#include <com/sun/star/io/TextOutputStream.hpp>
+
+namespace dbaccess
+{
+
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::XComponentContext;
+ using ::com::sun::star::embed::XStorage;
+ using ::com::sun::star::io::TextOutputStream;
+ using ::com::sun::star::io::XTextOutputStream2;
+
+ // StorageTextOutputStream_Data
+ struct StorageTextOutputStream_Data
+ {
+ Reference< XTextOutputStream2 > xTextOutput;
+ };
+
+ constexpr OUStringLiteral sLineFeed = u"\n";
+
+ // StorageTextOutputStream
+ StorageTextOutputStream::StorageTextOutputStream( const Reference<XComponentContext>& i_rContext,
+ const Reference< XStorage >& i_rParentStorage,
+ const OUString& i_rStreamName
+ )
+ :StorageOutputStream( i_rParentStorage, i_rStreamName )
+ ,m_pData( new StorageTextOutputStream_Data )
+ {
+ m_pData->xTextOutput = TextOutputStream::create( i_rContext );
+ m_pData->xTextOutput->setEncoding( "UTF-8" );
+ m_pData->xTextOutput->setOutputStream( getOutputStream() );
+ }
+
+ StorageTextOutputStream::~StorageTextOutputStream()
+ {
+ }
+
+ void StorageTextOutputStream::writeLine( const OUString& i_rLine )
+ {
+ m_pData->xTextOutput->writeString( i_rLine );
+ m_pData->xTextOutput->writeString( sLineFeed );
+ }
+
+ void StorageTextOutputStream::writeLine()
+ {
+ m_pData->xTextOutput->writeString( sLineFeed );
+ }
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/recovery/storagetextstream.hxx b/dbaccess/source/core/recovery/storagetextstream.hxx
new file mode 100644
index 000000000..46c3e5b2e
--- /dev/null
+++ b/dbaccess/source/core/recovery/storagetextstream.hxx
@@ -0,0 +1,52 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "storagestream.hxx"
+
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+#include <memory>
+
+namespace dbaccess
+{
+
+ // StorageTextStream
+ struct StorageTextOutputStream_Data;
+ class StorageTextOutputStream : public StorageOutputStream
+ {
+ public:
+ StorageTextOutputStream(
+ const css::uno::Reference< css::uno::XComponentContext >& i_rContext,
+ const css::uno::Reference< css::embed::XStorage >& i_rParentStorage,
+ const OUString& i_rStreamName
+ );
+ virtual ~StorageTextOutputStream() override;
+
+ void writeLine( const OUString& i_rLine );
+ void writeLine();
+
+ private:
+ std::unique_ptr< StorageTextOutputStream_Data > m_pData;
+ };
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/recovery/storagexmlstream.cxx b/dbaccess/source/core/recovery/storagexmlstream.cxx
new file mode 100644
index 000000000..e76dabefe
--- /dev/null
+++ b/dbaccess/source/core/recovery/storagexmlstream.cxx
@@ -0,0 +1,151 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "storagexmlstream.hxx"
+
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
+#include <com/sun/star/xml/sax/Parser.hpp>
+#include <com/sun/star/xml/sax/Writer.hpp>
+
+#include <rtl/ref.hxx>
+#include <tools/diagnose_ex.h>
+#include <xmloff/attrlist.hxx>
+
+#include <stack>
+
+namespace dbaccess
+{
+
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::UNO_QUERY_THROW;
+ using ::com::sun::star::uno::XComponentContext;
+ using ::com::sun::star::embed::XStorage;
+ using ::com::sun::star::xml::sax::XDocumentHandler;
+ using ::com::sun::star::xml::sax::XWriter;
+ using ::com::sun::star::xml::sax::Writer;
+ using ::com::sun::star::xml::sax::Parser;
+ using ::com::sun::star::xml::sax::InputSource;
+
+ // StorageXMLOutputStream_Data
+ struct StorageXMLOutputStream_Data
+ {
+ Reference< XDocumentHandler > xHandler;
+ std::stack< OUString > aElements;
+ ::rtl::Reference< SvXMLAttributeList > xAttributes;
+ };
+
+ // StorageXMLOutputStream
+ StorageXMLOutputStream::StorageXMLOutputStream( const Reference<XComponentContext>& i_rContext,
+ const Reference< XStorage >& i_rParentStorage,
+ const OUString& i_rStreamName )
+ :StorageOutputStream( i_rParentStorage, i_rStreamName )
+ ,m_pData( new StorageXMLOutputStream_Data )
+ {
+ const Reference< XWriter > xSaxWriter = Writer::create( i_rContext );
+ xSaxWriter->setOutputStream( getOutputStream() );
+
+ m_pData->xHandler.set( xSaxWriter, UNO_QUERY_THROW );
+ m_pData->xHandler->startDocument();
+
+ m_pData->xAttributes = new SvXMLAttributeList;
+ }
+
+ StorageXMLOutputStream::~StorageXMLOutputStream()
+ {
+ }
+
+ void StorageXMLOutputStream::close()
+ {
+ ENSURE_OR_RETURN_VOID( m_pData->xHandler.is(), "illegal document handler" );
+ m_pData->xHandler->endDocument();
+ // do not call the base class, it would call closeOutput on the output stream, which is already done by
+ // endDocument
+ }
+
+ void StorageXMLOutputStream::addAttribute( const OUString& i_rName, const OUString& i_rValue ) const
+ {
+ m_pData->xAttributes->AddAttribute( i_rName, i_rValue );
+ }
+
+ void StorageXMLOutputStream::startElement( const OUString& i_rElementName ) const
+ {
+ ENSURE_OR_RETURN_VOID( m_pData->xHandler.is(), "no document handler" );
+
+ m_pData->xHandler->startElement( i_rElementName, m_pData->xAttributes );
+ m_pData->xAttributes = new SvXMLAttributeList;
+ m_pData->aElements.push( i_rElementName );
+ }
+
+ void StorageXMLOutputStream::endElement() const
+ {
+ ENSURE_OR_RETURN_VOID( m_pData->xHandler.is(), "no document handler" );
+ ENSURE_OR_RETURN_VOID( !m_pData->aElements.empty(), "no element on the stack" );
+
+ const OUString sElementName( m_pData->aElements.top() );
+ m_pData->xHandler->endElement( sElementName );
+ m_pData->aElements.pop();
+ }
+
+ void StorageXMLOutputStream::ignorableWhitespace( const OUString& i_rWhitespace ) const
+ {
+ ENSURE_OR_RETURN_VOID( m_pData->xHandler.is(), "no document handler" );
+
+ m_pData->xHandler->ignorableWhitespace( i_rWhitespace );
+ }
+
+ void StorageXMLOutputStream::characters( const OUString& i_rCharacters ) const
+ {
+ ENSURE_OR_RETURN_VOID( m_pData->xHandler.is(), "no document handler" );
+
+ m_pData->xHandler->characters( i_rCharacters );
+ }
+
+ // StorageXMLInputStream
+ StorageXMLInputStream::StorageXMLInputStream( const Reference<XComponentContext>& i_rContext,
+ const Reference< XStorage >& i_rParentStorage,
+ const OUString& i_rStreamName )
+ {
+ ENSURE_OR_THROW( i_rParentStorage.is(), "illegal stream" );
+
+ const Reference< css::io::XStream > xStream(
+ i_rParentStorage->openStreamElement( i_rStreamName, css::embed::ElementModes::READ ), css::uno::UNO_SET_THROW );
+ m_xInputStream.set( xStream->getInputStream(), css::uno::UNO_SET_THROW );
+
+ m_xParser.set( Parser::create(i_rContext) );
+ }
+
+ void StorageXMLInputStream::import( const Reference< XDocumentHandler >& i_rHandler )
+ {
+ ENSURE_OR_THROW( i_rHandler.is(), "illegal document handler (NULL)" );
+
+ InputSource aInputSource;
+ aInputSource.aInputStream = m_xInputStream;
+
+ m_xParser->setDocumentHandler( i_rHandler );
+ m_xParser->parseStream( aInputSource );
+ }
+
+ StorageXMLInputStream::~StorageXMLInputStream()
+ {
+ }
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/recovery/storagexmlstream.hxx b/dbaccess/source/core/recovery/storagexmlstream.hxx
new file mode 100644
index 000000000..fd762ae05
--- /dev/null
+++ b/dbaccess/source/core/recovery/storagexmlstream.hxx
@@ -0,0 +1,88 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "storagestream.hxx"
+
+#include <com/sun/star/xml/sax/XParser.hpp>
+#include <com/sun/star/embed/XStorage.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
+
+#include <memory>
+
+namespace dbaccess
+{
+
+ // StorageXMLOutputStream
+ struct StorageXMLOutputStream_Data;
+ class StorageXMLOutputStream : public StorageOutputStream
+ {
+ public:
+ StorageXMLOutputStream(
+ const css::uno::Reference< css::uno::XComponentContext >& i_rContext,
+ const css::uno::Reference< css::embed::XStorage >& i_rParentStorage,
+ const OUString& i_rStreamName
+ );
+ virtual ~StorageXMLOutputStream() override;
+
+ void close();
+
+ void addAttribute( const OUString& i_rName, const OUString& i_rValue ) const;
+
+ void startElement( const OUString& i_rElementName ) const;
+ void endElement() const;
+
+ void ignorableWhitespace( const OUString& i_rWhitespace ) const;
+ void characters( const OUString& i_rCharacters ) const;
+
+ private:
+ StorageXMLOutputStream( const StorageXMLOutputStream& ) = delete;
+ StorageXMLOutputStream& operator=( const StorageXMLOutputStream& ) = delete;
+
+ private:
+ std::unique_ptr< StorageXMLOutputStream_Data > m_pData;
+ };
+
+ class StorageXMLInputStream
+ {
+ public:
+ StorageXMLInputStream(
+ const css::uno::Reference< css::uno::XComponentContext >& i_rContext,
+ const css::uno::Reference< css::embed::XStorage >& i_rParentStorage,
+ const OUString& i_rStreamName
+ );
+ ~StorageXMLInputStream();
+
+ void import(
+ const css::uno::Reference< css::xml::sax::XDocumentHandler >& i_rHandler
+ );
+
+ StorageXMLInputStream( const StorageXMLInputStream& ) = delete;
+ StorageXMLInputStream& operator=( const StorageXMLInputStream& ) = delete;
+
+ private:
+ css::uno::Reference< css::xml::sax::XParser > m_xParser;
+ css::uno::Reference< css::io::XInputStream > m_xInputStream;
+ };
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/recovery/subcomponentloader.cxx b/dbaccess/source/core/recovery/subcomponentloader.cxx
new file mode 100644
index 000000000..3393c3d13
--- /dev/null
+++ b/dbaccess/source/core/recovery/subcomponentloader.cxx
@@ -0,0 +1,124 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "subcomponentloader.hxx"
+
+#include <com/sun/star/ucb/Command.hpp>
+#include <com/sun/star/frame/XController2.hpp>
+
+#include <tools/diagnose_ex.h>
+
+namespace dbaccess
+{
+
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::UNO_QUERY_THROW;
+ using ::com::sun::star::uno::UNO_SET_THROW;
+ using ::com::sun::star::uno::Exception;
+ using ::com::sun::star::frame::XController;
+ using ::com::sun::star::frame::XFrame;
+ using ::com::sun::star::awt::XWindow;
+ using ::com::sun::star::awt::WindowEvent;
+ using ::com::sun::star::lang::EventObject;
+ using ::com::sun::star::ucb::Command;
+ using ::com::sun::star::ucb::XCommandProcessor;
+ using ::com::sun::star::frame::XController2;
+ using ::com::sun::star::lang::XComponent;
+
+ // SubComponentLoader
+ SubComponentLoader::SubComponentLoader( const Reference< XController >& i_rApplicationController,
+ const Reference< XCommandProcessor >& i_rSubDocumentDefinition )
+ :mxDocDefCommands( i_rSubDocumentDefinition )
+ {
+ // add as window listener to the controller's container window, so we get notified when it is shown
+ Reference< XController2 > xController( i_rApplicationController, UNO_QUERY_THROW );
+ mxAppComponentWindow.set( xController->getComponentWindow(), UNO_SET_THROW );
+
+ osl_atomic_increment( &m_refCount );
+ {
+ mxAppComponentWindow->addWindowListener( this );
+ }
+ osl_atomic_decrement( &m_refCount );
+ }
+
+ SubComponentLoader::SubComponentLoader( const Reference< XController >& i_rApplicationController,
+ const Reference< XComponent >& i_rNonDocumentComponent )
+ :mxNonDocComponent( i_rNonDocumentComponent )
+ {
+ // add as window listener to the controller's container window, so we get notified when it is shown
+ Reference< XController2 > xController( i_rApplicationController, UNO_QUERY_THROW );
+ mxAppComponentWindow.set( xController->getComponentWindow(), UNO_SET_THROW );
+
+ osl_atomic_increment( &m_refCount );
+ {
+ mxAppComponentWindow->addWindowListener( this );
+ }
+ osl_atomic_decrement( &m_refCount );
+ }
+
+ SubComponentLoader::~SubComponentLoader()
+ {
+ }
+
+ void SAL_CALL SubComponentLoader::windowResized( const WindowEvent& )
+ {
+ }
+
+ void SAL_CALL SubComponentLoader::windowMoved( const WindowEvent& )
+ {
+ }
+
+ void SAL_CALL SubComponentLoader::windowShown( const EventObject& )
+ {
+ try
+ {
+ if ( mxDocDefCommands.is() )
+ {
+ Command aCommandOpen;
+ aCommandOpen.Name = "show";
+
+ const sal_Int32 nCommandIdentifier = mxDocDefCommands->createCommandIdentifier();
+ mxDocDefCommands->execute( aCommandOpen, nCommandIdentifier, nullptr );
+ }
+ else
+ {
+ const Reference< XController > xController( mxNonDocComponent, UNO_QUERY_THROW );
+ const Reference< XFrame > xFrame( xController->getFrame(), UNO_SET_THROW );
+ const Reference< XWindow > xWindow( xFrame->getContainerWindow(), UNO_SET_THROW );
+ xWindow->setVisible( true );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ mxAppComponentWindow->removeWindowListener( this );
+ }
+
+ void SAL_CALL SubComponentLoader::windowHidden( const EventObject& )
+ {
+ }
+
+ void SAL_CALL SubComponentLoader::disposing( const EventObject& )
+ {
+ }
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/recovery/subcomponentloader.hxx b/dbaccess/source/core/recovery/subcomponentloader.hxx
new file mode 100644
index 000000000..4ab867880
--- /dev/null
+++ b/dbaccess/source/core/recovery/subcomponentloader.hxx
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/awt/XWindowListener.hpp>
+#include <com/sun/star/frame/XController.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/ucb/XCommandProcessor.hpp>
+
+#include <cppuhelper/implbase.hxx>
+
+namespace dbaccess
+{
+
+ // SubComponentLoader
+ typedef ::cppu::WeakImplHelper< css::awt::XWindowListener
+ > SubComponentLoader_Base;
+ /** is a helper class which loads/opens a given sub component as soon as the main application
+ window becomes visible.
+ */
+ class SubComponentLoader : public SubComponentLoader_Base
+ {
+ public:
+ SubComponentLoader(
+ const css::uno::Reference< css::frame::XController >& i_rApplicationController,
+ const css::uno::Reference< css::ucb::XCommandProcessor >& i_rSubDocumentDefinition
+ );
+
+ SubComponentLoader(
+ const css::uno::Reference< css::frame::XController >& i_rApplicationController,
+ const css::uno::Reference< css::lang::XComponent >& i_rNonDocumentComponent
+ );
+
+ // XWindowListener
+ virtual void SAL_CALL windowResized( const css::awt::WindowEvent& e ) override;
+ virtual void SAL_CALL windowMoved( const css::awt::WindowEvent& e ) override;
+ virtual void SAL_CALL windowShown( const css::lang::EventObject& e ) override;
+ virtual void SAL_CALL windowHidden( const css::lang::EventObject& e ) override;
+
+ // XEventListener
+ virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
+
+ protected:
+ virtual ~SubComponentLoader() override;
+
+ private:
+ const css::uno::Reference< css::ucb::XCommandProcessor > mxDocDefCommands;
+ const css::uno::Reference< css::lang::XComponent > mxNonDocComponent;
+ css::uno::Reference< css::awt::XWindow > mxAppComponentWindow;
+ };
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/recovery/subcomponentrecovery.cxx b/dbaccess/source/core/recovery/subcomponentrecovery.cxx
new file mode 100644
index 000000000..e7ffffd61
--- /dev/null
+++ b/dbaccess/source/core/recovery/subcomponentrecovery.cxx
@@ -0,0 +1,628 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "subcomponentrecovery.hxx"
+
+#include <sdbcoretools.hxx>
+#include "storagexmlstream.hxx"
+#include "subcomponentloader.hxx"
+#include "settingsimport.hxx"
+
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/frame/ModuleManager.hpp>
+#include <com/sun/star/document/XStorageBasedDocument.hpp>
+#include <com/sun/star/ucb/XCommandProcessor.hpp>
+#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
+#include <com/sun/star/sdb/XFormDocumentsSupplier.hpp>
+#include <com/sun/star/sdb/XReportDocumentsSupplier.hpp>
+#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
+
+#include <comphelper/namedvaluecollection.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <connectivity/dbtools.hxx>
+#include <tools/diagnose_ex.h>
+#include <sal/log.hxx>
+#include <xmloff/XMLSettingsExportContext.hxx>
+#include <xmloff/SettingsExportHelper.hxx>
+
+#include <stack>
+
+namespace dbaccess
+{
+
+ using css::uno::Reference;
+ using css::uno::XInterface;
+ using css::uno::UNO_QUERY;
+ using css::uno::UNO_QUERY_THROW;
+ using css::uno::UNO_SET_THROW;
+ using css::uno::Exception;
+ using css::uno::RuntimeException;
+ using css::uno::Any;
+ using css::uno::Sequence;
+ using css::uno::XComponentContext;
+ using css::embed::XStorage;
+ using css::sdb::application::XDatabaseDocumentUI;
+ using css::beans::Pair;
+ using css::frame::ModuleManager;
+ using css::frame::XModuleManager2;
+ using css::lang::XComponent;
+ using css::frame::XModel;
+ using css::frame::XController;
+ using css::beans::XPropertySet;
+ using css::beans::PropertyValue;
+ using css::document::XStorageBasedDocument;
+ using css::ucb::XCommandProcessor;
+ using css::container::XHierarchicalNameAccess;
+ using css::sdb::XFormDocumentsSupplier;
+ using css::sdb::XReportDocumentsSupplier;
+ using css::xml::sax::XLocator;
+ using css::xml::sax::XDocumentHandler;
+ using css::xml::sax::XAttributeList;
+
+ namespace ElementModes = css::embed::ElementModes;
+ namespace DatabaseObject = css::sdb::application::DatabaseObject;
+
+ // helper
+ namespace
+ {
+ OUString lcl_getComponentStorageBaseName( const SubComponentType i_eType )
+ {
+ switch ( i_eType )
+ {
+ case FORM:
+ return "form";
+ case REPORT:
+ return "report";
+ case TABLE:
+ return "table";
+ case QUERY:
+ return "query";
+ default:
+ break;
+ }
+
+ OSL_FAIL( "lcl_getComponentStorageBaseName: unimplemented case!" );
+ return OUString();
+ }
+
+ SubComponentType lcl_databaseObjectToSubComponentType( const sal_Int32 i_nObjectType )
+ {
+ switch ( i_nObjectType )
+ {
+ case DatabaseObject::TABLE: return TABLE;
+ case DatabaseObject::QUERY: return QUERY;
+ case DatabaseObject::FORM: return FORM;
+ case DatabaseObject::REPORT:return REPORT;
+ default:
+ break;
+ }
+ return UNKNOWN;
+ }
+
+ bool lcl_determineReadOnly( const Reference< XComponent >& i_rComponent )
+ {
+ Reference< XModel > xDocument( i_rComponent, UNO_QUERY );
+ if ( !xDocument.is() )
+ {
+ Reference< XController > xController( i_rComponent, UNO_QUERY_THROW );
+ xDocument = xController->getModel();
+ }
+
+ if ( !xDocument.is() )
+ return false;
+
+ ::comphelper::NamedValueCollection aDocArgs( xDocument->getArgs() );
+ return aDocArgs.getOrDefault( "ReadOnly", false );
+ }
+
+ Reference< XCommandProcessor > lcl_getSubComponentDef_nothrow( const Reference< XDatabaseDocumentUI >& i_rAppUI,
+ const SubComponentType i_eType, const OUString& i_rName )
+ {
+ Reference< XController > xController( i_rAppUI, UNO_QUERY_THROW );
+ ENSURE_OR_RETURN( ( i_eType == FORM ) || ( i_eType == REPORT ), "lcl_getSubComponentDef_nothrow: illegal controller", nullptr );
+
+ Reference< XCommandProcessor > xCommandProcessor;
+ try
+ {
+ Reference< XHierarchicalNameAccess > xDefinitionContainer;
+ if ( i_eType == FORM )
+ {
+ Reference< XFormDocumentsSupplier > xSuppForms( xController->getModel(), UNO_QUERY_THROW );
+ xDefinitionContainer.set( xSuppForms->getFormDocuments(), UNO_QUERY_THROW );
+ }
+ else
+ {
+ Reference< XReportDocumentsSupplier > xSuppReports( xController->getModel(), UNO_QUERY_THROW );
+ xDefinitionContainer.set( xSuppReports->getReportDocuments(), UNO_QUERY_THROW );
+ }
+ xCommandProcessor.set( xDefinitionContainer->getByHierarchicalName( i_rName ), UNO_QUERY_THROW );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("dbaccess");
+ }
+ return xCommandProcessor;
+ }
+
+ constexpr OUStringLiteral sSettingsStreamName = u"settings.xml";
+ constexpr OUStringLiteral sCurrentQueryDesignName = u"ooo:current-query-design";
+ }
+
+ namespace {
+
+ // SettingsExportContext
+ class SettingsExportContext : public ::xmloff::XMLSettingsExportContext
+ {
+ public:
+ SettingsExportContext( const Reference<XComponentContext>& i_rContext, const StorageXMLOutputStream& i_rDelegator )
+ :m_rContext( i_rContext )
+ ,m_rDelegator( i_rDelegator )
+ ,m_aNamespace( ::xmloff::token::GetXMLToken( ::xmloff::token::XML_NP_CONFIG ) )
+ {
+ }
+
+ virtual ~SettingsExportContext()
+ {
+ }
+
+ public:
+ virtual void AddAttribute( enum ::xmloff::token::XMLTokenEnum i_eName, const OUString& i_rValue ) override;
+ virtual void AddAttribute( enum ::xmloff::token::XMLTokenEnum i_eName, enum ::xmloff::token::XMLTokenEnum i_eValue ) override;
+ virtual void StartElement( enum ::xmloff::token::XMLTokenEnum i_eName ) override;
+ virtual void EndElement ( const bool i_bIgnoreWhitespace ) override;
+ virtual void Characters( const OUString& i_rCharacters ) override;
+
+ virtual css::uno::Reference< css::uno::XComponentContext >
+ GetComponentContext() const override;
+
+ private:
+ OUString impl_prefix( const ::xmloff::token::XMLTokenEnum i_eToken )
+ {
+ return m_aNamespace + ":" + ::xmloff::token::GetXMLToken( i_eToken );
+ }
+
+ private:
+ const Reference<XComponentContext>& m_rContext;
+ const StorageXMLOutputStream& m_rDelegator;
+ const OUString m_aNamespace;
+ };
+
+ }
+
+ void SettingsExportContext::AddAttribute( enum ::xmloff::token::XMLTokenEnum i_eName, const OUString& i_rValue )
+ {
+ m_rDelegator.addAttribute( impl_prefix( i_eName ), i_rValue );
+ }
+
+ void SettingsExportContext::AddAttribute( enum ::xmloff::token::XMLTokenEnum i_eName, enum ::xmloff::token::XMLTokenEnum i_eValue )
+ {
+ m_rDelegator.addAttribute( impl_prefix( i_eName ), ::xmloff::token::GetXMLToken( i_eValue ) );
+ }
+
+ void SettingsExportContext::StartElement( enum ::xmloff::token::XMLTokenEnum i_eName )
+ {
+ m_rDelegator.ignorableWhitespace( " " );
+
+ m_rDelegator.startElement( impl_prefix( i_eName ) );
+ }
+
+ void SettingsExportContext::EndElement( const bool i_bIgnoreWhitespace )
+ {
+ if ( i_bIgnoreWhitespace )
+ m_rDelegator.ignorableWhitespace( " " );
+ m_rDelegator.endElement();
+ }
+
+ void SettingsExportContext::Characters( const OUString& i_rCharacters )
+ {
+ m_rDelegator.characters( i_rCharacters );
+ }
+
+ Reference< css::uno::XComponentContext > SettingsExportContext::GetComponentContext() const
+ {
+ return m_rContext;
+ }
+
+ // SettingsDocumentHandler
+ typedef ::cppu::WeakImplHelper< XDocumentHandler
+ > SettingsDocumentHandler_Base;
+
+ namespace {
+
+ class SettingsDocumentHandler : public SettingsDocumentHandler_Base
+ {
+ public:
+ SettingsDocumentHandler()
+ {
+ }
+
+ protected:
+ virtual ~SettingsDocumentHandler() override
+ {
+ }
+
+ public:
+ // XDocumentHandler
+ virtual void SAL_CALL startDocument( ) override;
+ virtual void SAL_CALL endDocument( ) override;
+ virtual void SAL_CALL startElement( const OUString& aName, const Reference< XAttributeList >& xAttribs ) override;
+ virtual void SAL_CALL endElement( const OUString& aName ) override;
+ virtual void SAL_CALL characters( const OUString& aChars ) override;
+ virtual void SAL_CALL ignorableWhitespace( const OUString& aWhitespaces ) override;
+ virtual void SAL_CALL processingInstruction( const OUString& aTarget, const OUString& aData ) override;
+ virtual void SAL_CALL setDocumentLocator( const Reference< XLocator >& xLocator ) override;
+
+ const ::comphelper::NamedValueCollection& getSettings() const { return m_aSettings; }
+
+ private:
+ std::stack< ::rtl::Reference< SettingsImport > > m_aStates;
+ ::comphelper::NamedValueCollection m_aSettings;
+ };
+
+ }
+
+ void SAL_CALL SettingsDocumentHandler::startDocument( )
+ {
+ }
+
+ void SAL_CALL SettingsDocumentHandler::endDocument( )
+ {
+ }
+
+ void SAL_CALL SettingsDocumentHandler::startElement( const OUString& i_Name, const Reference< XAttributeList >& i_Attribs )
+ {
+ ::rtl::Reference< SettingsImport > pNewState;
+
+ if ( m_aStates.empty() )
+ {
+ if ( i_Name == "office:settings" )
+ {
+ pNewState = new OfficeSettingsImport( m_aSettings );
+ }
+ else
+ {
+ OSL_FAIL( "SettingsDocumentHandler::startElement: invalid settings file!" );
+ // Yes, that's not correct. Somebody could, in theory, give us a document which starts with "foo:settings",
+ // where "foo" is mapped to the proper namespace URL.
+ // However, there's no need to bother with this. The "recovery" sub storage we're recovering from is
+ // not part of ODF, so we can impose any format restrictions on it ...
+ }
+ }
+ else
+ {
+ ::rtl::Reference< SettingsImport > pCurrentState( m_aStates.top() );
+ pNewState = pCurrentState->nextState( i_Name );
+ }
+
+ ENSURE_OR_THROW( pNewState.is(), "no new state - aborting import" );
+ pNewState->startElement( i_Attribs );
+
+ m_aStates.push( pNewState );
+ }
+
+ void SAL_CALL SettingsDocumentHandler::endElement( const OUString& )
+ {
+ ENSURE_OR_THROW( !m_aStates.empty(), "no active element" );
+
+ ::rtl::Reference< SettingsImport > pCurrentState( m_aStates.top() );
+ pCurrentState->endElement();
+ m_aStates.pop();
+ }
+
+ void SAL_CALL SettingsDocumentHandler::characters( const OUString& i_Chars )
+ {
+ ENSURE_OR_THROW( !m_aStates.empty(), "no active element" );
+
+ ::rtl::Reference< SettingsImport > pCurrentState( m_aStates.top() );
+ pCurrentState->characters( i_Chars );
+ }
+
+ void SAL_CALL SettingsDocumentHandler::ignorableWhitespace( const OUString& )
+ {
+ // ignore them - that's why they're called "ignorable"
+ }
+
+ void SAL_CALL SettingsDocumentHandler::processingInstruction( const OUString&, const OUString& )
+ {
+ OSL_FAIL( "SettingsDocumentHandler::processingInstruction: unexpected ..." );
+ }
+
+ void SAL_CALL SettingsDocumentHandler::setDocumentLocator( const Reference< XLocator >& ) {}
+
+ // SubComponentRecovery
+ OUString SubComponentRecovery::getComponentsStorageName( const SubComponentType i_eType )
+ {
+ switch ( i_eType )
+ {
+ case FORM:
+ return "forms";
+ case REPORT:
+ return "reports";
+ case TABLE:
+ return "tables";
+ case QUERY:
+ return "queries";
+ case RELATION_DESIGN:
+ return "relations";
+ default:
+ break;
+ }
+
+ OSL_FAIL( "SubComponentRecovery::getComponentsStorageName: unimplemented case!" );
+ return OUString();
+ }
+
+ void SubComponentRecovery::saveToRecoveryStorage( const Reference< XStorage >& i_rRecoveryStorage,
+ MapCompTypeToCompDescs& io_mapCompDescs )
+ {
+ if ( m_eType == UNKNOWN )
+ // quite fatal, but has already been reported (as assertion) before
+ return;
+
+ // open the sub storage for the given kind of components
+ const OUString& rStorageName( getComponentsStorageName( m_eType ) );
+ const Reference< XStorage > xComponentsStorage( i_rRecoveryStorage->openStorageElement(
+ rStorageName, ElementModes::READWRITE ), UNO_SET_THROW );
+
+ // find a free sub storage name, and create Yet Another Sub Storage
+ const OUString& rBaseName( lcl_getComponentStorageBaseName( m_eType ) );
+ const OUString sStorName = ::dbtools::createUniqueName( xComponentsStorage, rBaseName );
+ const Reference< XStorage > xObjectStor( xComponentsStorage->openStorageElement(
+ sStorName, ElementModes::READWRITE ), UNO_SET_THROW );
+
+ switch ( m_eType )
+ {
+ case FORM:
+ case REPORT:
+ impl_saveSubDocument_throw( xObjectStor );
+ break;
+
+ case QUERY:
+ impl_saveQueryDesign_throw( xObjectStor );
+ break;
+
+ default:
+ // TODO
+ OSL_FAIL( "SubComponentRecoverys::saveToRecoveryStorage: unimplemented case!" );
+ break;
+ }
+
+ // commit the storage(s)
+ tools::stor::commitStorageIfWriteable( xObjectStor );
+ tools::stor::commitStorageIfWriteable( xComponentsStorage );
+
+ // remember the relationship from the component name to the storage name
+ MapStringToCompDesc& rMapCompDescs = io_mapCompDescs[ m_eType ];
+ OSL_ENSURE( rMapCompDescs.find( sStorName ) == rMapCompDescs.end(),
+ "SubComponentRecoverys::saveToRecoveryStorage: object name already used!" );
+ rMapCompDescs[ sStorName ] = m_aCompDesc;
+ }
+
+ void SubComponentRecovery::impl_identifyComponent_throw()
+ {
+ // ask the controller
+ Pair< sal_Int32, OUString > aComponentIdentity = m_xDocumentUI->identifySubComponent( m_xComponent );
+ m_eType = lcl_databaseObjectToSubComponentType( aComponentIdentity.First );
+ m_aCompDesc.sName = aComponentIdentity.Second;
+
+ // what the controller didn't give us is the information whether this is in edit mode or not ...
+ Reference< XModuleManager2 > xModuleManager( ModuleManager::create(m_rContext) );
+ const OUString sModuleIdentifier = xModuleManager->identify( m_xComponent );
+
+ switch ( m_eType )
+ {
+ case TABLE:
+ m_aCompDesc.bForEditing = sModuleIdentifier == "com.sun.star.sdb.TableDesign";
+ break;
+
+ case QUERY:
+ m_aCompDesc.bForEditing = sModuleIdentifier == "com.sun.star.sdb.QueryDesign";
+ break;
+
+ case REPORT:
+ if ( sModuleIdentifier == "com.sun.star.report.ReportDefinition" )
+ {
+ // it's an SRB report designer
+ m_aCompDesc.bForEditing = true;
+ break;
+ }
+ [[fallthrough]];
+
+ case FORM:
+ m_aCompDesc.bForEditing = !lcl_determineReadOnly( m_xComponent );
+ break;
+
+ default:
+ if ( sModuleIdentifier == "com.sun.star.sdb.RelationDesign" )
+ {
+ m_eType = RELATION_DESIGN;
+ m_aCompDesc.bForEditing = true;
+ }
+ else
+ {
+ OSL_FAIL( "SubComponentRecovery::impl_identifyComponent_throw: couldn't classify the given sub component!" );
+ }
+ break;
+ }
+
+ SAL_WARN_IF( m_eType == UNKNOWN, "dbaccess",
+ "SubComponentRecovery::impl_identifyComponent_throw: couldn't classify the component!" );
+ }
+
+ void SubComponentRecovery::impl_saveQueryDesign_throw( const Reference< XStorage >& i_rObjectStorage )
+ {
+ ENSURE_OR_THROW( m_eType == QUERY, "illegal sub component type" );
+ ENSURE_OR_THROW( i_rObjectStorage.is(), "illegal storage" );
+
+ // retrieve the current query design (which might differ from what we can retrieve as ActiveCommand property, since
+ // the latter is updated only upon successful save of the design)
+ Reference< XPropertySet > xDesignerProps( m_xComponent, UNO_QUERY_THROW );
+ Sequence< PropertyValue > aCurrentQueryDesign;
+ OSL_VERIFY( xDesignerProps->getPropertyValue( "CurrentQueryDesign" ) >>= aCurrentQueryDesign );
+
+ // write the query design
+ StorageXMLOutputStream aDesignOutput( m_rContext, i_rObjectStorage, sSettingsStreamName );
+ SettingsExportContext aSettingsExportContext( m_rContext, aDesignOutput );
+
+ static const OUStringLiteral sWhitespace( u" " );
+
+ aDesignOutput.startElement( "office:settings" );
+ aDesignOutput.ignorableWhitespace( sWhitespace );
+
+ XMLSettingsExportHelper aSettingsExporter( aSettingsExportContext );
+ aSettingsExporter.exportAllSettings( aCurrentQueryDesign, sCurrentQueryDesignName );
+
+ aDesignOutput.ignorableWhitespace( sWhitespace );
+ aDesignOutput.endElement();
+ aDesignOutput.close();
+ }
+
+ void SubComponentRecovery::impl_saveSubDocument_throw( const Reference< XStorage >& i_rObjectStorage )
+ {
+ ENSURE_OR_THROW( ( m_eType == FORM ) || ( m_eType == REPORT ), "illegal sub component type" );
+ ENSURE_OR_THROW( i_rObjectStorage.is(), "illegal storage" );
+
+ // store the document into the storage
+ Reference< XStorageBasedDocument > xStorageDocument( m_xComponent, UNO_QUERY_THROW );
+ xStorageDocument->storeToStorage( i_rObjectStorage, Sequence< PropertyValue >() );
+ }
+
+ Reference< XComponent > SubComponentRecovery::impl_recoverSubDocument_throw( const Reference< XStorage >& i_rRecoveryStorage,
+ const OUString& i_rComponentName, const bool i_bForEditing )
+ {
+ Reference< XComponent > xSubComponent;
+ Reference< XCommandProcessor > xDocDefinition;
+
+ ::comphelper::NamedValueCollection aLoadArgs;
+ aLoadArgs.put( "RecoveryStorage", i_rRecoveryStorage );
+
+ // load/create the sub component hidden. We'll show it when the main app window is shown.
+ aLoadArgs.put( "Hidden", true );
+
+ if ( !i_rComponentName.isEmpty() )
+ {
+ xDocDefinition = lcl_getSubComponentDef_nothrow( m_xDocumentUI, m_eType, i_rComponentName );
+ xSubComponent.set( m_xDocumentUI->loadComponentWithArguments(
+ m_eType,
+ i_rComponentName,
+ i_bForEditing,
+ aLoadArgs.getPropertyValues()
+ ),
+ UNO_SET_THROW
+ );
+ }
+ else
+ {
+ Reference< XComponent > xDocDefComponent;
+ xSubComponent.set( m_xDocumentUI->createComponentWithArguments(
+ m_eType,
+ aLoadArgs.getPropertyValues(),
+ xDocDefComponent
+ ),
+ UNO_SET_THROW
+ );
+
+ xDocDefinition.set( xDocDefComponent, UNO_QUERY );
+ OSL_ENSURE( xDocDefinition.is(), "DatabaseDocumentRecovery::recoverSubDocuments: loaded a form/report, but don't have a document definition?!" );
+ }
+
+ if ( xDocDefinition.is() )
+ {
+ Reference< XController > xController( m_xDocumentUI, UNO_QUERY_THROW );
+ rtl::Reference( new SubComponentLoader( xController, xDocDefinition ) );
+ }
+
+ return xSubComponent;
+ }
+
+ Reference< XComponent > SubComponentRecovery::impl_recoverQueryDesign_throw( const Reference< XStorage >& i_rRecoveryStorage,
+ const OUString& i_rComponentName, const bool i_bForEditing )
+ {
+ Reference< XComponent > xSubComponent;
+
+ // first read the settings query design settings from the storage
+ StorageXMLInputStream aDesignInput( m_rContext, i_rRecoveryStorage, sSettingsStreamName );
+
+ ::rtl::Reference< SettingsDocumentHandler > pDocHandler( new SettingsDocumentHandler );
+ aDesignInput.import( pDocHandler );
+
+ const ::comphelper::NamedValueCollection& rSettings( pDocHandler->getSettings() );
+ const Any& aCurrentQueryDesign = rSettings.get( sCurrentQueryDesignName );
+#if OSL_DEBUG_LEVEL > 0
+ Sequence< PropertyValue > aQueryDesignLayout;
+ OSL_VERIFY( aCurrentQueryDesign >>= aQueryDesignLayout );
+#endif
+
+ // then load the query designer
+ ::comphelper::NamedValueCollection aLoadArgs;
+ aLoadArgs.put( "CurrentQueryDesign", aCurrentQueryDesign );
+ aLoadArgs.put( "Hidden", true );
+
+ if ( !i_rComponentName.isEmpty() )
+ {
+ xSubComponent.set( m_xDocumentUI->loadComponentWithArguments(
+ m_eType,
+ i_rComponentName,
+ i_bForEditing,
+ aLoadArgs.getPropertyValues()
+ ),
+ UNO_SET_THROW
+ );
+ }
+ else
+ {
+ Reference< XComponent > xDummy;
+ xSubComponent.set( m_xDocumentUI->createComponentWithArguments(
+ m_eType,
+ aLoadArgs.getPropertyValues(),
+ xDummy
+ ),
+ UNO_SET_THROW
+ );
+ }
+
+ Reference< XController > xController( m_xDocumentUI, UNO_QUERY_THROW );
+ rtl::Reference( new SubComponentLoader( xController, xSubComponent ) );
+
+ return xSubComponent;
+ }
+
+ Reference< XComponent > SubComponentRecovery::recoverFromStorage( const Reference< XStorage >& i_rRecoveryStorage,
+ const OUString& i_rComponentName, const bool i_bForEditing )
+ {
+ Reference< XComponent > xSubComponent;
+ switch ( m_eType )
+ {
+ case FORM:
+ case REPORT:
+ xSubComponent = impl_recoverSubDocument_throw( i_rRecoveryStorage, i_rComponentName, i_bForEditing );
+ break;
+ case QUERY:
+ xSubComponent = impl_recoverQueryDesign_throw( i_rRecoveryStorage, i_rComponentName, i_bForEditing );
+ break;
+ default:
+ OSL_FAIL( "SubComponentRecovery::recoverFromStorage: unimplemented case!" );
+ break;
+ }
+ return xSubComponent;
+ }
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/recovery/subcomponentrecovery.hxx b/dbaccess/source/core/recovery/subcomponentrecovery.hxx
new file mode 100644
index 000000000..26b81c63f
--- /dev/null
+++ b/dbaccess/source/core/recovery/subcomponentrecovery.hxx
@@ -0,0 +1,114 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "subcomponents.hxx"
+
+#include <com/sun/star/sdb/application/XDatabaseDocumentUI.hpp>
+#include <com/sun/star/embed/XStorage.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+namespace dbaccess
+{
+
+ // SubComponentRecovery
+ class SubComponentRecovery
+ {
+ public:
+ SubComponentRecovery(
+ const css::uno::Reference< css::uno::XComponentContext >& i_rContext,
+ const css::uno::Reference< css::sdb::application::XDatabaseDocumentUI >& i_rController,
+ const css::uno::Reference< css::lang::XComponent >& i_rComponent )
+ :m_rContext( i_rContext )
+ ,m_xDocumentUI( i_rController, css::uno::UNO_SET_THROW )
+ ,m_xComponent( i_rComponent )
+ ,m_eType( UNKNOWN )
+ ,m_aCompDesc()
+ {
+ impl_identifyComponent_throw();
+ }
+
+ SubComponentRecovery(
+ const css::uno::Reference< css::uno::XComponentContext >& i_rContext,
+ const css::uno::Reference< css::sdb::application::XDatabaseDocumentUI >& i_rController,
+ const SubComponentType i_eType )
+ :m_rContext( i_rContext )
+ ,m_xDocumentUI( i_rController, css::uno::UNO_SET_THROW )
+ ,m_xComponent()
+ ,m_eType( i_eType )
+ ,m_aCompDesc()
+ {
+ }
+
+ // only to be used after being constructed with a component
+ void saveToRecoveryStorage(
+ const css::uno::Reference< css::embed::XStorage >& i_rRecoveryStorage,
+ MapCompTypeToCompDescs& io_mapCompDescs
+ );
+
+ // only to be used after being constructed with a type
+ css::uno::Reference< css::lang::XComponent >
+ recoverFromStorage(
+ const css::uno::Reference< css::embed::XStorage >& i_rRecoveryStorage,
+ const OUString& i_rComponentName,
+ const bool i_bForEditing
+ );
+
+ static OUString getComponentsStorageName( const SubComponentType i_eType );
+
+ private:
+ void impl_saveSubDocument_throw(
+ const css::uno::Reference< css::embed::XStorage >& i_rObjectStorage
+ );
+
+ void impl_saveQueryDesign_throw(
+ const css::uno::Reference< css::embed::XStorage >& i_rObjectStorage
+ );
+
+ css::uno::Reference< css::lang::XComponent >
+ impl_recoverSubDocument_throw(
+ const css::uno::Reference< css::embed::XStorage >& i_rRecoveryStorage,
+ const OUString& i_rComponentName,
+ const bool i_bForEditing
+ );
+
+ css::uno::Reference< css::lang::XComponent >
+ impl_recoverQueryDesign_throw(
+ const css::uno::Reference< css::embed::XStorage >& i_rRecoveryStorage,
+ const OUString& i_rComponentName,
+ const bool i_bForEditing
+ );
+
+ void impl_identifyComponent_throw();
+
+ private:
+ const css::uno::Reference< css::uno::XComponentContext >&
+ m_rContext;
+ css::uno::Reference< css::sdb::application::XDatabaseDocumentUI >
+ m_xDocumentUI;
+ const css::uno::Reference< css::lang::XComponent >
+ m_xComponent;
+ SubComponentType m_eType;
+ SubComponentDescriptor m_aCompDesc;
+ };
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/core/recovery/subcomponents.hxx b/dbaccess/source/core/recovery/subcomponents.hxx
new file mode 100644
index 000000000..5e4173605
--- /dev/null
+++ b/dbaccess/source/core/recovery/subcomponents.hxx
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/sdb/application/DatabaseObject.hpp>
+
+#include <rtl/ustring.hxx>
+
+#include <map>
+#include <unordered_map>
+
+namespace dbaccess
+{
+
+ enum SubComponentType
+ {
+ TABLE = css::sdb::application::DatabaseObject::TABLE,
+ QUERY = css::sdb::application::DatabaseObject::QUERY,
+ FORM = css::sdb::application::DatabaseObject::FORM,
+ REPORT = css::sdb::application::DatabaseObject::REPORT,
+
+ RELATION_DESIGN = 1000,
+
+ UNKNOWN = 10001
+ };
+
+ struct SubComponentDescriptor
+ {
+ OUString sName;
+ bool bForEditing;
+
+ SubComponentDescriptor()
+ :sName()
+ ,bForEditing( false )
+ {
+ }
+ };
+
+ typedef std::unordered_map< OUString, SubComponentDescriptor > MapStringToCompDesc;
+ typedef std::map< SubComponentType, MapStringToCompDesc > MapCompTypeToCompDescs;
+
+} // namespace dbaccess
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */