196de5490SAndrew Rist /**************************************************************
296de5490SAndrew Rist  *
396de5490SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
496de5490SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
596de5490SAndrew Rist  * distributed with this work for additional information
696de5490SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
796de5490SAndrew Rist  * to you under the Apache License, Version 2.0 (the
896de5490SAndrew Rist  * "License"); you may not use this file except in compliance
996de5490SAndrew Rist  * with the License.  You may obtain a copy of the License at
1096de5490SAndrew Rist  *
1196de5490SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
1296de5490SAndrew Rist  *
1396de5490SAndrew Rist  * Unless required by applicable law or agreed to in writing,
1496de5490SAndrew Rist  * software distributed under the License is distributed on an
1596de5490SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
1696de5490SAndrew Rist  * KIND, either express or implied.  See the License for the
1796de5490SAndrew Rist  * specific language governing permissions and limitations
1896de5490SAndrew Rist  * under the License.
1996de5490SAndrew Rist  *
2096de5490SAndrew Rist  *************************************************************/
2196de5490SAndrew Rist 
2296de5490SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir #include "precompiled_dbaccess.hxx"
25cdf0e10cSrcweir 
26cdf0e10cSrcweir #include "recovery/dbdocrecovery.hxx"
27cdf0e10cSrcweir #include "sdbcoretools.hxx"
28cdf0e10cSrcweir #include "storagetextstream.hxx"
29cdf0e10cSrcweir #include "subcomponentrecovery.hxx"
30cdf0e10cSrcweir #include "subcomponents.hxx"
31cdf0e10cSrcweir #include "dbastrings.hrc"
32cdf0e10cSrcweir 
33cdf0e10cSrcweir /** === begin UNO includes === **/
34cdf0e10cSrcweir #include <com/sun/star/sdb/application/XDatabaseDocumentUI.hpp>
35cdf0e10cSrcweir #include <com/sun/star/embed/ElementModes.hpp>
36cdf0e10cSrcweir #include <com/sun/star/document/XStorageBasedDocument.hpp>
37cdf0e10cSrcweir #include <com/sun/star/io/XTextOutputStream.hpp>
38cdf0e10cSrcweir #include <com/sun/star/io/XTextInputStream.hpp>
39cdf0e10cSrcweir #include <com/sun/star/io/XActiveDataSource.hpp>
40cdf0e10cSrcweir #include <com/sun/star/io/XActiveDataSink.hpp>
41cdf0e10cSrcweir #include <com/sun/star/util/XModifiable.hpp>
42cdf0e10cSrcweir #include <com/sun/star/beans/XPropertySet.hpp>
43cdf0e10cSrcweir /** === end UNO includes === **/
44cdf0e10cSrcweir 
45cdf0e10cSrcweir #include <comphelper/componentcontext.hxx>
46cdf0e10cSrcweir #include <comphelper/namedvaluecollection.hxx>
47cdf0e10cSrcweir #include <rtl/ustrbuf.hxx>
48cdf0e10cSrcweir #include <tools/diagnose_ex.h>
49cdf0e10cSrcweir 
50cdf0e10cSrcweir #include <algorithm>
51cdf0e10cSrcweir 
52cdf0e10cSrcweir //........................................................................
53cdf0e10cSrcweir namespace dbaccess
54cdf0e10cSrcweir {
55cdf0e10cSrcweir //........................................................................
56cdf0e10cSrcweir 
57cdf0e10cSrcweir 	/** === begin UNO using === **/
58cdf0e10cSrcweir 	using ::com::sun::star::uno::Reference;
59cdf0e10cSrcweir 	using ::com::sun::star::uno::XInterface;
60cdf0e10cSrcweir 	using ::com::sun::star::uno::UNO_QUERY;
61cdf0e10cSrcweir 	using ::com::sun::star::uno::UNO_QUERY_THROW;
62cdf0e10cSrcweir 	using ::com::sun::star::uno::UNO_SET_THROW;
63cdf0e10cSrcweir 	using ::com::sun::star::uno::Exception;
64cdf0e10cSrcweir 	using ::com::sun::star::uno::RuntimeException;
65cdf0e10cSrcweir 	using ::com::sun::star::uno::Any;
66cdf0e10cSrcweir 	using ::com::sun::star::uno::makeAny;
67cdf0e10cSrcweir 	using ::com::sun::star::uno::Sequence;
68cdf0e10cSrcweir 	using ::com::sun::star::uno::Type;
69cdf0e10cSrcweir     using ::com::sun::star::embed::XStorage;
70cdf0e10cSrcweir     using ::com::sun::star::frame::XController;
71cdf0e10cSrcweir     using ::com::sun::star::sdb::application::XDatabaseDocumentUI;
72cdf0e10cSrcweir     using ::com::sun::star::lang::XComponent;
73cdf0e10cSrcweir     using ::com::sun::star::document::XStorageBasedDocument;
74cdf0e10cSrcweir     using ::com::sun::star::beans::PropertyValue;
75cdf0e10cSrcweir     using ::com::sun::star::io::XStream;
76cdf0e10cSrcweir     using ::com::sun::star::io::XTextOutputStream;
77cdf0e10cSrcweir     using ::com::sun::star::io::XActiveDataSource;
78cdf0e10cSrcweir     using ::com::sun::star::io::XTextInputStream;
79cdf0e10cSrcweir     using ::com::sun::star::io::XActiveDataSink;
80cdf0e10cSrcweir     using ::com::sun::star::frame::XModel;
81cdf0e10cSrcweir     using ::com::sun::star::util::XModifiable;
82cdf0e10cSrcweir     using ::com::sun::star::beans::XPropertySet;
83cdf0e10cSrcweir     using ::com::sun::star::lang::XMultiServiceFactory;
84cdf0e10cSrcweir 	/** === end UNO using === **/
85cdf0e10cSrcweir 
86cdf0e10cSrcweir     namespace ElementModes = ::com::sun::star::embed::ElementModes;
87cdf0e10cSrcweir 
88cdf0e10cSrcweir 	//====================================================================
89cdf0e10cSrcweir 	//= helpers
90cdf0e10cSrcweir 	//====================================================================
91cdf0e10cSrcweir     namespace
92cdf0e10cSrcweir     {
93cdf0e10cSrcweir         // .........................................................................
lcl_getPersistentRepresentation(const MapStringToCompDesc::value_type & i_rComponentDesc,::rtl::OUStringBuffer & o_rBuffer)94cdf0e10cSrcweir         static void lcl_getPersistentRepresentation( const MapStringToCompDesc::value_type& i_rComponentDesc, ::rtl::OUStringBuffer& o_rBuffer )
95cdf0e10cSrcweir         {
96cdf0e10cSrcweir             o_rBuffer.append( i_rComponentDesc.first );
97cdf0e10cSrcweir             o_rBuffer.append( sal_Unicode( '=' ) );
98cdf0e10cSrcweir             o_rBuffer.append( i_rComponentDesc.second.sName );
99cdf0e10cSrcweir             o_rBuffer.append( sal_Unicode( ',' ) );
100cdf0e10cSrcweir             o_rBuffer.append( sal_Unicode( i_rComponentDesc.second.bForEditing ? '1' : '0' ) );
101cdf0e10cSrcweir         }
102cdf0e10cSrcweir 
103cdf0e10cSrcweir         // .........................................................................
lcl_extractCompDesc(const::rtl::OUString & i_rIniLine,::rtl::OUString & o_rStorName,SubComponentDescriptor & o_rCompDesc)104cdf0e10cSrcweir         static bool lcl_extractCompDesc( const ::rtl::OUString& i_rIniLine, ::rtl::OUString& o_rStorName, SubComponentDescriptor& o_rCompDesc )
105cdf0e10cSrcweir         {
106cdf0e10cSrcweir             const sal_Int32 nEqualSignPos = i_rIniLine.indexOf( sal_Unicode( '=' ) );
107cdf0e10cSrcweir             if ( nEqualSignPos < 1 )
108cdf0e10cSrcweir             {
109cdf0e10cSrcweir                 OSL_ENSURE( false, "lcl_extractCompDesc: invalid map file entry - unexpected pos of '='" );
110cdf0e10cSrcweir                 return false;
111cdf0e10cSrcweir             }
112cdf0e10cSrcweir             o_rStorName = i_rIniLine.copy( 0, nEqualSignPos );
113cdf0e10cSrcweir 
114cdf0e10cSrcweir             const sal_Int32 nCommaPos = i_rIniLine.lastIndexOf( sal_Unicode( ',' ) );
115cdf0e10cSrcweir             if ( nCommaPos != i_rIniLine.getLength() - 2 )
116cdf0e10cSrcweir             {
117cdf0e10cSrcweir                 OSL_ENSURE( false, "lcl_extractCompDesc: invalid map file entry - unexpected pos of ','" );
118cdf0e10cSrcweir                 return false;
119cdf0e10cSrcweir             }
120cdf0e10cSrcweir             o_rCompDesc.sName = i_rIniLine.copy( nEqualSignPos + 1, nCommaPos - nEqualSignPos - 1 );
121cdf0e10cSrcweir             o_rCompDesc.bForEditing = ( i_rIniLine.getStr()[ nCommaPos + 1 ] == '1' );
122cdf0e10cSrcweir             return true;
123cdf0e10cSrcweir         }
124cdf0e10cSrcweir 
125cdf0e10cSrcweir         // .........................................................................
lcl_getRecoveryDataSubStorageName()126cdf0e10cSrcweir         static const ::rtl::OUString& lcl_getRecoveryDataSubStorageName()
127cdf0e10cSrcweir         {
128cdf0e10cSrcweir             static const ::rtl::OUString s_sRecDataStorName( RTL_CONSTASCII_USTRINGPARAM( "recovery" ) );
129cdf0e10cSrcweir             return s_sRecDataStorName;
130cdf0e10cSrcweir         }
131cdf0e10cSrcweir         // .........................................................................
lcl_getObjectMapStreamName()132cdf0e10cSrcweir         static const ::rtl::OUString& lcl_getObjectMapStreamName()
133cdf0e10cSrcweir         {
134cdf0e10cSrcweir             static const ::rtl::OUString s_sObjectMapStreamName( RTL_CONSTASCII_USTRINGPARAM( "storage-component-map.ini" ) );
135cdf0e10cSrcweir             return s_sObjectMapStreamName;
136cdf0e10cSrcweir         }
137cdf0e10cSrcweir 
138cdf0e10cSrcweir         // .........................................................................
lcl_getMapStreamEncodingName()139cdf0e10cSrcweir         static const ::rtl::OUString& lcl_getMapStreamEncodingName()
140cdf0e10cSrcweir         {
141cdf0e10cSrcweir             static const ::rtl::OUString s_sMapStreamEncodingName( RTL_CONSTASCII_USTRINGPARAM( "UTF-8" ) );
142cdf0e10cSrcweir             return s_sMapStreamEncodingName;
143cdf0e10cSrcweir         }
144cdf0e10cSrcweir 
145cdf0e10cSrcweir         // .........................................................................
lcl_writeObjectMap_throw(const::comphelper::ComponentContext & i_rContext,const Reference<XStorage> & i_rStorage,const MapStringToCompDesc & i_mapStorageToCompDesc)146cdf0e10cSrcweir         static void lcl_writeObjectMap_throw( const ::comphelper::ComponentContext& i_rContext, const Reference< XStorage >& i_rStorage,
147cdf0e10cSrcweir             const MapStringToCompDesc& i_mapStorageToCompDesc )
148cdf0e10cSrcweir         {
149cdf0e10cSrcweir             if ( i_mapStorageToCompDesc.empty() )
150cdf0e10cSrcweir                 // nothing to do
151cdf0e10cSrcweir                 return;
152cdf0e10cSrcweir 
153cdf0e10cSrcweir             StorageTextOutputStream aTextOutput( i_rContext, i_rStorage, lcl_getObjectMapStreamName() );
154cdf0e10cSrcweir 
155cdf0e10cSrcweir             aTextOutput.writeLine( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "[storages]" ) ) );
156cdf0e10cSrcweir 
157cdf0e10cSrcweir             for (   MapStringToCompDesc::const_iterator stor = i_mapStorageToCompDesc.begin();
158cdf0e10cSrcweir                     stor != i_mapStorageToCompDesc.end();
159cdf0e10cSrcweir                     ++stor
160cdf0e10cSrcweir                 )
161cdf0e10cSrcweir             {
162cdf0e10cSrcweir                 ::rtl::OUStringBuffer aLine;
163cdf0e10cSrcweir                 lcl_getPersistentRepresentation( *stor, aLine );
164cdf0e10cSrcweir 
165cdf0e10cSrcweir                 aTextOutput.writeLine( aLine.makeStringAndClear() );
166cdf0e10cSrcweir             }
167cdf0e10cSrcweir 
168cdf0e10cSrcweir             aTextOutput.writeLine();
169cdf0e10cSrcweir         }
170cdf0e10cSrcweir 
171cdf0e10cSrcweir         // .........................................................................
lcl_isSectionStart(const::rtl::OUString & i_rIniLine,::rtl::OUString & o_rSectionName)172cdf0e10cSrcweir         static bool lcl_isSectionStart( const ::rtl::OUString& i_rIniLine, ::rtl::OUString& o_rSectionName )
173cdf0e10cSrcweir         {
174cdf0e10cSrcweir             const sal_Int32 nLen = i_rIniLine.getLength();
175cdf0e10cSrcweir             if ( ( nLen > 0 ) && ( i_rIniLine.getStr()[0] == '[' ) && ( i_rIniLine.getStr()[ nLen - 1 ] == ']' ) )
176cdf0e10cSrcweir             {
177cdf0e10cSrcweir                 o_rSectionName = i_rIniLine.copy( 1, nLen -2 );
178cdf0e10cSrcweir                 return true;
179cdf0e10cSrcweir             }
180cdf0e10cSrcweir             return false;
181cdf0e10cSrcweir         }
182cdf0e10cSrcweir 
183cdf0e10cSrcweir         // .........................................................................
lcl_stripTrailingLineFeed(::rtl::OUString & io_rLine)184cdf0e10cSrcweir         static void lcl_stripTrailingLineFeed( ::rtl::OUString& io_rLine )
185cdf0e10cSrcweir         {
186cdf0e10cSrcweir             const sal_Int32 nLen = io_rLine.getLength();
187cdf0e10cSrcweir             if ( ( nLen > 0 ) && ( io_rLine.getStr()[ nLen - 1 ] == '\n' ) )
188cdf0e10cSrcweir                 io_rLine = io_rLine.copy( 0, nLen - 1 );
189cdf0e10cSrcweir         }
190cdf0e10cSrcweir 
191cdf0e10cSrcweir         // .........................................................................
lcl_readObjectMap_throw(const::comphelper::ComponentContext & i_rContext,const Reference<XStorage> & i_rStorage,MapStringToCompDesc & o_mapStorageToObjectName)192cdf0e10cSrcweir         static void lcl_readObjectMap_throw( const ::comphelper::ComponentContext& i_rContext, const Reference< XStorage >& i_rStorage,
193cdf0e10cSrcweir             MapStringToCompDesc& o_mapStorageToObjectName )
194cdf0e10cSrcweir         {
195cdf0e10cSrcweir             ENSURE_OR_THROW( i_rStorage.is(), "invalid storage" );
196cdf0e10cSrcweir             if ( !i_rStorage->hasByName( lcl_getObjectMapStreamName() ) )
197cdf0e10cSrcweir             {   // nothing to do, though suspicious
198cdf0e10cSrcweir                 OSL_ENSURE( false, "lcl_readObjectMap_throw: if there's no map file, then there's expected to be no storage, too!" );
199cdf0e10cSrcweir                 return;
200cdf0e10cSrcweir             }
201cdf0e10cSrcweir 
202cdf0e10cSrcweir             Reference< XStream > xIniStream( i_rStorage->openStreamElement(
203cdf0e10cSrcweir                 lcl_getObjectMapStreamName(), ElementModes::READ ), UNO_SET_THROW );
204cdf0e10cSrcweir 
205cdf0e10cSrcweir             Reference< XTextInputStream > xTextInput( i_rContext.createComponent( "com.sun.star.io.TextInputStream" ), UNO_QUERY_THROW );
206cdf0e10cSrcweir             xTextInput->setEncoding( lcl_getMapStreamEncodingName() );
207cdf0e10cSrcweir 
208cdf0e10cSrcweir             Reference< XActiveDataSink > xDataSink( xTextInput, UNO_QUERY_THROW );
209cdf0e10cSrcweir             xDataSink->setInputStream( xIniStream->getInputStream() );
210cdf0e10cSrcweir 
211cdf0e10cSrcweir             ::rtl::OUString sCurrentSection;
212cdf0e10cSrcweir             bool bCurrentSectionIsKnownToBeUnsupported = true;
213cdf0e10cSrcweir             while ( !xTextInput->isEOF() )
214cdf0e10cSrcweir             {
215cdf0e10cSrcweir                 ::rtl::OUString sLine = xTextInput->readLine();
216cdf0e10cSrcweir                 lcl_stripTrailingLineFeed( sLine );
217cdf0e10cSrcweir 
218cdf0e10cSrcweir                 if ( sLine.getLength() == 0 )
219cdf0e10cSrcweir                     continue;
220cdf0e10cSrcweir 
221cdf0e10cSrcweir                 if ( lcl_isSectionStart( sLine, sCurrentSection ) )
222cdf0e10cSrcweir                 {
223cdf0e10cSrcweir                     bCurrentSectionIsKnownToBeUnsupported = false;
224cdf0e10cSrcweir                     continue;
225cdf0e10cSrcweir                 }
226cdf0e10cSrcweir 
227cdf0e10cSrcweir                 if ( bCurrentSectionIsKnownToBeUnsupported )
228cdf0e10cSrcweir                     continue;
229cdf0e10cSrcweir 
230cdf0e10cSrcweir                 // the only section we support so far is "storages"
231cdf0e10cSrcweir                 if ( !sCurrentSection.equalsAscii( "storages" ) )
232cdf0e10cSrcweir                 {
233cdf0e10cSrcweir                     bCurrentSectionIsKnownToBeUnsupported = true;
234cdf0e10cSrcweir                     continue;
235cdf0e10cSrcweir                 }
236cdf0e10cSrcweir 
237cdf0e10cSrcweir                 ::rtl::OUString sStorageName;
238cdf0e10cSrcweir                 SubComponentDescriptor aCompDesc;
239cdf0e10cSrcweir                 if ( !lcl_extractCompDesc( sLine, sStorageName, aCompDesc ) )
240cdf0e10cSrcweir                     continue;
241cdf0e10cSrcweir                 o_mapStorageToObjectName[ sStorageName ] = aCompDesc;
242cdf0e10cSrcweir             }
243cdf0e10cSrcweir         }
244cdf0e10cSrcweir 
245cdf0e10cSrcweir         // .........................................................................
lcl_markModified(const Reference<XComponent> & i_rSubComponent)246cdf0e10cSrcweir         static void lcl_markModified( const Reference< XComponent >& i_rSubComponent )
247cdf0e10cSrcweir         {
248cdf0e10cSrcweir             const Reference< XModifiable > xModify( i_rSubComponent, UNO_QUERY );
249cdf0e10cSrcweir             if ( !xModify.is() )
250cdf0e10cSrcweir             {
251cdf0e10cSrcweir                 OSL_ENSURE( false, "lcl_markModified: unhandled case!" );
252cdf0e10cSrcweir                 return;
253cdf0e10cSrcweir             }
254cdf0e10cSrcweir 
255cdf0e10cSrcweir             xModify->setModified( sal_True );
256cdf0e10cSrcweir         }
257cdf0e10cSrcweir     }
258cdf0e10cSrcweir 
259cdf0e10cSrcweir 	//====================================================================
260cdf0e10cSrcweir 	//= DatabaseDocumentRecovery_Data
261cdf0e10cSrcweir 	//====================================================================
262cdf0e10cSrcweir     struct DBACCESS_DLLPRIVATE DatabaseDocumentRecovery_Data
263cdf0e10cSrcweir     {
264cdf0e10cSrcweir         const ::comphelper::ComponentContext aContext;
265cdf0e10cSrcweir 
DatabaseDocumentRecovery_Datadbaccess::DatabaseDocumentRecovery_Data266cdf0e10cSrcweir         DatabaseDocumentRecovery_Data( const ::comphelper::ComponentContext& i_rContext )
267cdf0e10cSrcweir             :aContext( i_rContext )
268cdf0e10cSrcweir         {
269cdf0e10cSrcweir         }
270cdf0e10cSrcweir     };
271cdf0e10cSrcweir 
272cdf0e10cSrcweir 	//====================================================================
273cdf0e10cSrcweir 	//= DatabaseDocumentRecovery
274cdf0e10cSrcweir 	//====================================================================
275cdf0e10cSrcweir 	//--------------------------------------------------------------------
DatabaseDocumentRecovery(const::comphelper::ComponentContext & i_rContext)276cdf0e10cSrcweir     DatabaseDocumentRecovery::DatabaseDocumentRecovery( const ::comphelper::ComponentContext& i_rContext )
277cdf0e10cSrcweir         :m_pData( new DatabaseDocumentRecovery_Data( i_rContext ) )
278cdf0e10cSrcweir     {
279cdf0e10cSrcweir     }
280cdf0e10cSrcweir 
281cdf0e10cSrcweir 	//--------------------------------------------------------------------
~DatabaseDocumentRecovery()282cdf0e10cSrcweir     DatabaseDocumentRecovery::~DatabaseDocumentRecovery()
283cdf0e10cSrcweir     {
284cdf0e10cSrcweir     }
285cdf0e10cSrcweir 
286cdf0e10cSrcweir 	//--------------------------------------------------------------------
saveModifiedSubComponents(const Reference<XStorage> & i_rTargetStorage,const::std::vector<Reference<XController>> & i_rControllers)287cdf0e10cSrcweir     void DatabaseDocumentRecovery::saveModifiedSubComponents( const Reference< XStorage >& i_rTargetStorage,
288cdf0e10cSrcweir         const ::std::vector< Reference< XController > >& i_rControllers )
289cdf0e10cSrcweir     {
290cdf0e10cSrcweir         ENSURE_OR_THROW( i_rTargetStorage.is(), "invalid document storage" );
291cdf0e10cSrcweir 
292cdf0e10cSrcweir         // create a sub storage for recovery data
293cdf0e10cSrcweir         if ( i_rTargetStorage->hasByName( lcl_getRecoveryDataSubStorageName() ) )
294cdf0e10cSrcweir             i_rTargetStorage->removeElement( lcl_getRecoveryDataSubStorageName() );
295cdf0e10cSrcweir         Reference< XStorage > xRecoveryStorage = i_rTargetStorage->openStorageElement( lcl_getRecoveryDataSubStorageName(), ElementModes::READWRITE );
296cdf0e10cSrcweir 
297cdf0e10cSrcweir         // store recovery data for open sub components of the given controller(s)
298cdf0e10cSrcweir         if ( !i_rControllers.empty() )
299cdf0e10cSrcweir         {
300cdf0e10cSrcweir             ENSURE_OR_THROW( i_rControllers.size() == 1, "can't handle more than one controller" );
301cdf0e10cSrcweir             // At the moment, there can be only one view to a database document. If we ever allow for more than this,
302cdf0e10cSrcweir             // then we need a concept for sub documents opened from different controllers (i.e. two document views,
303cdf0e10cSrcweir             // and the user opens the very same form in both views). And depending on this, we need a concept for
304cdf0e10cSrcweir             // how those are saved to the recovery file.
305cdf0e10cSrcweir 
306cdf0e10cSrcweir             MapCompTypeToCompDescs aMapCompDescs;
307cdf0e10cSrcweir 
308cdf0e10cSrcweir             for (   ::std::vector< Reference< XController > >::const_iterator ctrl = i_rControllers.begin();
309cdf0e10cSrcweir                     ctrl != i_rControllers.end();
310cdf0e10cSrcweir                     ++ctrl
311cdf0e10cSrcweir                 )
312cdf0e10cSrcweir             {
313cdf0e10cSrcweir                 Reference< XDatabaseDocumentUI > xDatabaseUI( *ctrl, UNO_QUERY_THROW );
314cdf0e10cSrcweir                 Sequence< Reference< XComponent > > aComponents( xDatabaseUI->getSubComponents() );
315cdf0e10cSrcweir 
316cdf0e10cSrcweir                 const Reference< XComponent >* component = aComponents.getConstArray();
317cdf0e10cSrcweir                 const Reference< XComponent >* componentEnd = aComponents.getConstArray() + aComponents.getLength();
318cdf0e10cSrcweir                 for ( ; component != componentEnd; ++component )
319cdf0e10cSrcweir                 {
320cdf0e10cSrcweir                     SubComponentRecovery aComponentRecovery( m_pData->aContext, xDatabaseUI, *component );
321cdf0e10cSrcweir                     aComponentRecovery.saveToRecoveryStorage( xRecoveryStorage, aMapCompDescs );
322cdf0e10cSrcweir                 }
323cdf0e10cSrcweir             }
324cdf0e10cSrcweir 
325cdf0e10cSrcweir             for (   MapCompTypeToCompDescs::const_iterator map = aMapCompDescs.begin();
326cdf0e10cSrcweir                     map != aMapCompDescs.end();
327cdf0e10cSrcweir                     ++map
328cdf0e10cSrcweir                 )
329cdf0e10cSrcweir             {
330cdf0e10cSrcweir                 Reference< XStorage > xComponentsStor( xRecoveryStorage->openStorageElement(
331cdf0e10cSrcweir                     SubComponentRecovery::getComponentsStorageName( map->first ), ElementModes::WRITE | ElementModes::NOCREATE ) );
332cdf0e10cSrcweir                 lcl_writeObjectMap_throw( m_pData->aContext, xComponentsStor, map->second );
333cdf0e10cSrcweir                 tools::stor::commitStorageIfWriteable( xComponentsStor );
334cdf0e10cSrcweir             }
335cdf0e10cSrcweir         }
336cdf0e10cSrcweir 
337cdf0e10cSrcweir         // commit the recovery storage
338cdf0e10cSrcweir         tools::stor::commitStorageIfWriteable( xRecoveryStorage );
339cdf0e10cSrcweir     }
340cdf0e10cSrcweir 
341cdf0e10cSrcweir     //--------------------------------------------------------------------
recoverSubDocuments(const Reference<XStorage> & i_rDocumentStorage,const Reference<XController> & i_rTargetController)342cdf0e10cSrcweir     void DatabaseDocumentRecovery::recoverSubDocuments( const Reference< XStorage >& i_rDocumentStorage,
343cdf0e10cSrcweir         const Reference< XController >& i_rTargetController )
344cdf0e10cSrcweir     {
345cdf0e10cSrcweir         ENSURE_OR_THROW( i_rDocumentStorage.is(), "illegal document storage" );
346cdf0e10cSrcweir         Reference< XDatabaseDocumentUI > xDocumentUI( i_rTargetController, UNO_QUERY_THROW );
347cdf0e10cSrcweir 
348cdf0e10cSrcweir         if ( !i_rDocumentStorage->hasByName( lcl_getRecoveryDataSubStorageName() ) )
349cdf0e10cSrcweir             // that's allowed
350cdf0e10cSrcweir             return;
351cdf0e10cSrcweir 
352cdf0e10cSrcweir         // the "recovery" sub storage
353cdf0e10cSrcweir         Reference< XStorage > xRecoveryStorage = i_rDocumentStorage->openStorageElement( lcl_getRecoveryDataSubStorageName(), ElementModes::READ );
354cdf0e10cSrcweir 
355cdf0e10cSrcweir         // read the map from sub storages to object names
356cdf0e10cSrcweir         MapCompTypeToCompDescs aMapCompDescs;
357cdf0e10cSrcweir         SubComponentType aKnownTypes[] = { TABLE, QUERY, FORM, REPORT, RELATION_DESIGN };
358cdf0e10cSrcweir         for ( size_t i = 0; i < sizeof( aKnownTypes ) / sizeof( aKnownTypes[0] ); ++i )
359cdf0e10cSrcweir         {
360cdf0e10cSrcweir             if ( !xRecoveryStorage->hasByName( SubComponentRecovery::getComponentsStorageName( aKnownTypes[i] ) ) )
361cdf0e10cSrcweir                 continue;
362cdf0e10cSrcweir 
363cdf0e10cSrcweir             Reference< XStorage > xComponentsStor( xRecoveryStorage->openStorageElement(
364cdf0e10cSrcweir                 SubComponentRecovery::getComponentsStorageName( aKnownTypes[i] ), ElementModes::READ ) );
365cdf0e10cSrcweir             lcl_readObjectMap_throw( m_pData->aContext, xComponentsStor, aMapCompDescs[ aKnownTypes[i] ] );
366cdf0e10cSrcweir             xComponentsStor->dispose();
367cdf0e10cSrcweir         }
368cdf0e10cSrcweir 
369cdf0e10cSrcweir         // recover all sub components as indicated by the map
370cdf0e10cSrcweir         for (   MapCompTypeToCompDescs::const_iterator map = aMapCompDescs.begin();
371cdf0e10cSrcweir                 map != aMapCompDescs.end();
372cdf0e10cSrcweir                 ++map
373cdf0e10cSrcweir             )
374cdf0e10cSrcweir         {
375cdf0e10cSrcweir             const SubComponentType eComponentType = map->first;
376cdf0e10cSrcweir 
377cdf0e10cSrcweir             // the storage for all components of the current type
378cdf0e10cSrcweir             Reference< XStorage > xComponentsStor( xRecoveryStorage->openStorageElement(
379cdf0e10cSrcweir                 SubComponentRecovery::getComponentsStorageName( eComponentType ), ElementModes::READ ), UNO_QUERY_THROW );
380cdf0e10cSrcweir 
381*30acf5e8Spfg             // loop through all components of this type
382cdf0e10cSrcweir             for (   MapStringToCompDesc::const_iterator stor = map->second.begin();
383cdf0e10cSrcweir                     stor != map->second.end();
384cdf0e10cSrcweir                     ++stor
385cdf0e10cSrcweir                 )
386cdf0e10cSrcweir             {
387cdf0e10cSrcweir                 const ::rtl::OUString sComponentName( stor->second.sName );
388cdf0e10cSrcweir                 if ( !xComponentsStor->hasByName( stor->first ) )
389cdf0e10cSrcweir                 {
390cdf0e10cSrcweir                 #if OSL_DEBUG_LEVEL > 0
391cdf0e10cSrcweir                     ::rtl::OStringBuffer message;
392cdf0e10cSrcweir                     message.append( "DatabaseDocumentRecovery::recoverSubDocuments: inconsistent recovery storage: storage '" );
393cdf0e10cSrcweir                     message.append( ::rtl::OUStringToOString( stor->first, RTL_TEXTENCODING_ASCII_US ) );
394cdf0e10cSrcweir                     message.append( "' not found in '" );
395cdf0e10cSrcweir                     message.append( ::rtl::OUStringToOString( SubComponentRecovery::getComponentsStorageName( eComponentType ), RTL_TEXTENCODING_ASCII_US ) );
396cdf0e10cSrcweir                     message.append( "', but required per map file!" );
39724c56ab9SHerbert Dürr                     OSL_ENSURE( false, message.getStr() );
398cdf0e10cSrcweir                 #endif
399cdf0e10cSrcweir                     continue;
400cdf0e10cSrcweir                 }
401cdf0e10cSrcweir 
402cdf0e10cSrcweir                 // the controller needs to have a connection to be able to open sub components
403cdf0e10cSrcweir                 if ( !xDocumentUI->isConnected() )
404cdf0e10cSrcweir                     xDocumentUI->connect();
405cdf0e10cSrcweir 
406cdf0e10cSrcweir                 // recover the single component
407cdf0e10cSrcweir                 Reference< XStorage > xCompStor( xComponentsStor->openStorageElement( stor->first, ElementModes::READ ) );
408cdf0e10cSrcweir                 SubComponentRecovery aComponentRecovery( m_pData->aContext, xDocumentUI, eComponentType );
409cdf0e10cSrcweir                 Reference< XComponent > xSubComponent( aComponentRecovery.recoverFromStorage( xCompStor, sComponentName, stor->second.bForEditing ) );
410cdf0e10cSrcweir 
411cdf0e10cSrcweir                 // at the moment, we only store, during session save, sub components which are modified. So, set this
412cdf0e10cSrcweir                 // recovered sub component to "modified", too.
413cdf0e10cSrcweir                 lcl_markModified( xSubComponent );
414cdf0e10cSrcweir             }
415cdf0e10cSrcweir 
416cdf0e10cSrcweir             xComponentsStor->dispose();
417cdf0e10cSrcweir         }
418cdf0e10cSrcweir 
419cdf0e10cSrcweir         xRecoveryStorage->dispose();
420cdf0e10cSrcweir 
421cdf0e10cSrcweir         // now that we successfully recovered, removed the "recovery" sub storage
422cdf0e10cSrcweir         try
423cdf0e10cSrcweir         {
424cdf0e10cSrcweir             i_rDocumentStorage->removeElement( lcl_getRecoveryDataSubStorageName() );
425cdf0e10cSrcweir         }
426cdf0e10cSrcweir         catch( const Exception& )
427cdf0e10cSrcweir         {
428cdf0e10cSrcweir         	DBG_UNHANDLED_EXCEPTION();
429cdf0e10cSrcweir         }
430cdf0e10cSrcweir     }
431cdf0e10cSrcweir 
432cdf0e10cSrcweir //........................................................................
433cdf0e10cSrcweir } // namespace dbaccess
434cdf0e10cSrcweir //........................................................................
435