2010-01-13 15:46:51 +01:00
|
|
|
/*************************************************************************
|
|
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
|
|
*
|
|
|
|
* Copyright 2009 by Sun Microsystems, Inc.
|
|
|
|
*
|
|
|
|
* OpenOffice.org - a multi-platform office productivity suite
|
|
|
|
*
|
|
|
|
* This file is part of OpenOffice.org.
|
|
|
|
*
|
|
|
|
* OpenOffice.org is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU Lesser General Public License version 3
|
|
|
|
* only, as published by the Free Software Foundation.
|
|
|
|
*
|
|
|
|
* OpenOffice.org is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU Lesser General Public License version 3 for more details
|
|
|
|
* (a copy is included in the LICENSE file that accompanied this code).
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
|
|
* version 3 along with OpenOffice.org. If not, see
|
|
|
|
* <http://www.openoffice.org/license.html>
|
|
|
|
* for a copy of the LGPLv3 License.
|
|
|
|
************************************************************************/
|
|
|
|
|
|
|
|
#include "precompiled_dbaccess.hxx"
|
|
|
|
|
2010-01-28 22:34:45 +01:00
|
|
|
#include "recovery/dbdocrecovery.hxx"
|
2010-01-13 15:46:51 +01:00
|
|
|
#include "sdbcoretools.hxx"
|
2010-01-29 13:04:04 +01:00
|
|
|
#include "subcomponentloader.hxx"
|
2010-01-26 13:19:11 +01:00
|
|
|
#include "dbastrings.hrc"
|
2010-01-13 15:46:51 +01:00
|
|
|
|
|
|
|
/** === begin UNO includes === **/
|
|
|
|
#include <com/sun/star/sdb/application/XDatabaseDocumentUI.hpp>
|
|
|
|
#include <com/sun/star/frame/XModuleManager.hpp>
|
|
|
|
#include <com/sun/star/embed/ElementModes.hpp>
|
|
|
|
#include <com/sun/star/document/XStorageBasedDocument.hpp>
|
|
|
|
#include <com/sun/star/io/XTextOutputStream.hpp>
|
2010-01-14 15:10:17 +01:00
|
|
|
#include <com/sun/star/io/XTextInputStream.hpp>
|
2010-01-13 15:46:51 +01:00
|
|
|
#include <com/sun/star/io/XActiveDataSource.hpp>
|
2010-01-14 15:10:17 +01:00
|
|
|
#include <com/sun/star/io/XActiveDataSink.hpp>
|
|
|
|
#include <com/sun/star/sdb/application/DatabaseObject.hpp>
|
autorecovery: save/recover forms and reports
Still some lose ends. Most notably, the current code contains cases for other sub component types,
but has no real implementation - attempting to save/recover those other types will yield multiple
assertions only. Also, recovery of SRB-reports has not been tested, yet, chances are good there's
some work ahead here.
Other known open issues:
- recovering sub components immediately shows them, instead of initially hiding them, and showing
only when the main document window is shown
- the implementation currently is no real session save, which would require saving information about
*unmodified* open sub components (though not their actual content), and restoring them upon
recovery.
- doing an implicit "connect" at the controller of the to-be-recovered database document is a requirement
to actually load the sub components, but might yield problems in case this requires interaction
(e.g. a login). Need to investigate
- the "recovery" storage is not removed from the database document storage after un/successful recovery
- cancelling the recovery of a "modified" database document always suggests to store this doc somewhere
2010-01-15 15:21:15 +01:00
|
|
|
#include <com/sun/star/util/XModifiable.hpp>
|
2010-01-29 13:04:04 +01:00
|
|
|
#include <com/sun/star/sdb/XFormDocumentsSupplier.hpp>
|
|
|
|
#include <com/sun/star/sdb/XReportDocumentsSupplier.hpp>
|
|
|
|
#include <com/sun/star/ucb/XCommandProcessor.hpp>
|
|
|
|
#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
|
2010-01-13 15:46:51 +01:00
|
|
|
/** === end UNO includes === **/
|
|
|
|
|
|
|
|
#include <comphelper/componentcontext.hxx>
|
autorecovery: save/recover forms and reports
Still some lose ends. Most notably, the current code contains cases for other sub component types,
but has no real implementation - attempting to save/recover those other types will yield multiple
assertions only. Also, recovery of SRB-reports has not been tested, yet, chances are good there's
some work ahead here.
Other known open issues:
- recovering sub components immediately shows them, instead of initially hiding them, and showing
only when the main document window is shown
- the implementation currently is no real session save, which would require saving information about
*unmodified* open sub components (though not their actual content), and restoring them upon
recovery.
- doing an implicit "connect" at the controller of the to-be-recovered database document is a requirement
to actually load the sub components, but might yield problems in case this requires interaction
(e.g. a login). Need to investigate
- the "recovery" storage is not removed from the database document storage after un/successful recovery
- cancelling the recovery of a "modified" database document always suggests to store this doc somewhere
2010-01-15 15:21:15 +01:00
|
|
|
#include <comphelper/namedvaluecollection.hxx>
|
2010-01-13 15:46:51 +01:00
|
|
|
#include <connectivity/dbtools.hxx>
|
|
|
|
#include <rtl/strbuf.hxx>
|
|
|
|
#include <tools/diagnose_ex.h>
|
|
|
|
|
|
|
|
#include <hash_map>
|
2010-01-26 13:19:11 +01:00
|
|
|
#include <algorithm>
|
2010-01-13 15:46:51 +01:00
|
|
|
|
|
|
|
//........................................................................
|
|
|
|
namespace dbaccess
|
|
|
|
{
|
|
|
|
//........................................................................
|
|
|
|
|
|
|
|
/** === begin UNO using === **/
|
|
|
|
using ::com::sun::star::uno::Reference;
|
|
|
|
using ::com::sun::star::uno::XInterface;
|
|
|
|
using ::com::sun::star::uno::UNO_QUERY;
|
|
|
|
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::uno::RuntimeException;
|
|
|
|
using ::com::sun::star::uno::Any;
|
|
|
|
using ::com::sun::star::uno::makeAny;
|
|
|
|
using ::com::sun::star::uno::Sequence;
|
|
|
|
using ::com::sun::star::uno::Type;
|
|
|
|
using ::com::sun::star::embed::XStorage;
|
|
|
|
using ::com::sun::star::frame::XController;
|
|
|
|
using ::com::sun::star::sdb::application::XDatabaseDocumentUI;
|
|
|
|
using ::com::sun::star::frame::XModuleManager;
|
|
|
|
using ::com::sun::star::lang::XComponent;
|
|
|
|
using ::com::sun::star::document::XStorageBasedDocument;
|
|
|
|
using ::com::sun::star::beans::PropertyValue;
|
|
|
|
using ::com::sun::star::beans::Pair;
|
|
|
|
using ::com::sun::star::io::XStream;
|
|
|
|
using ::com::sun::star::io::XOutputStream;
|
|
|
|
using ::com::sun::star::io::XTextOutputStream;
|
|
|
|
using ::com::sun::star::io::XActiveDataSource;
|
2010-01-14 15:10:17 +01:00
|
|
|
using ::com::sun::star::io::XTextInputStream;
|
|
|
|
using ::com::sun::star::io::XActiveDataSink;
|
autorecovery: save/recover forms and reports
Still some lose ends. Most notably, the current code contains cases for other sub component types,
but has no real implementation - attempting to save/recover those other types will yield multiple
assertions only. Also, recovery of SRB-reports has not been tested, yet, chances are good there's
some work ahead here.
Other known open issues:
- recovering sub components immediately shows them, instead of initially hiding them, and showing
only when the main document window is shown
- the implementation currently is no real session save, which would require saving information about
*unmodified* open sub components (though not their actual content), and restoring them upon
recovery.
- doing an implicit "connect" at the controller of the to-be-recovered database document is a requirement
to actually load the sub components, but might yield problems in case this requires interaction
(e.g. a login). Need to investigate
- the "recovery" storage is not removed from the database document storage after un/successful recovery
- cancelling the recovery of a "modified" database document always suggests to store this doc somewhere
2010-01-15 15:21:15 +01:00
|
|
|
using ::com::sun::star::frame::XModel;
|
|
|
|
using ::com::sun::star::util::XModifiable;
|
2010-01-29 13:04:04 +01:00
|
|
|
using ::com::sun::star::sdb::XFormDocumentsSupplier;
|
|
|
|
using ::com::sun::star::sdb::XReportDocumentsSupplier;
|
|
|
|
using ::com::sun::star::ucb::XCommandProcessor;
|
|
|
|
using ::com::sun::star::container::XHierarchicalNameAccess;
|
2010-01-13 15:46:51 +01:00
|
|
|
/** === end UNO using === **/
|
|
|
|
|
|
|
|
namespace ElementModes = ::com::sun::star::embed::ElementModes;
|
2010-01-14 15:10:17 +01:00
|
|
|
namespace DatabaseObject = ::com::sun::star::sdb::application::DatabaseObject;
|
2010-01-13 15:46:51 +01:00
|
|
|
|
|
|
|
//====================================================================
|
|
|
|
//= helpers
|
|
|
|
//====================================================================
|
|
|
|
namespace
|
|
|
|
{
|
|
|
|
// .........................................................................
|
2010-01-14 15:10:17 +01:00
|
|
|
enum SubComponentType
|
2010-01-13 15:46:51 +01:00
|
|
|
{
|
2010-01-14 15:10:17 +01:00
|
|
|
TABLE = DatabaseObject::TABLE,
|
|
|
|
QUERY = DatabaseObject::QUERY,
|
|
|
|
FORM = DatabaseObject::FORM,
|
|
|
|
REPORT = DatabaseObject::REPORT,
|
|
|
|
|
|
|
|
RELATION_DESIGN = 1000,
|
|
|
|
|
|
|
|
UNKNOWN = 10001
|
|
|
|
};
|
|
|
|
|
2010-01-29 13:04:04 +01:00
|
|
|
struct DBACCESS_DLLPRIVATE SubComponentDescriptor
|
2010-01-14 15:10:17 +01:00
|
|
|
{
|
|
|
|
::rtl::OUString sName;
|
|
|
|
bool bForEditing;
|
|
|
|
|
|
|
|
SubComponentDescriptor()
|
|
|
|
:sName()
|
|
|
|
,bForEditing( false )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
SubComponentDescriptor( const ::rtl::OUString& i_rName, const bool i_bForEditing )
|
|
|
|
:sName( i_rName )
|
|
|
|
,bForEditing( i_bForEditing )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// .........................................................................
|
|
|
|
typedef ::std::hash_map< ::rtl::OUString, SubComponentDescriptor, ::rtl::OUStringHash > MapStringToCompDesc;
|
|
|
|
typedef ::std::map< SubComponentType, MapStringToCompDesc > MapCompTypeToCompDescs;
|
2010-01-13 15:46:51 +01:00
|
|
|
|
|
|
|
// .........................................................................
|
2010-01-29 13:04:04 +01:00
|
|
|
static void lcl_getPersistentRepresentation( const MapStringToCompDesc::value_type& i_rComponentDesc, ::rtl::OUStringBuffer& o_rBuffer )
|
2010-01-13 15:46:51 +01:00
|
|
|
{
|
2010-01-14 15:10:17 +01:00
|
|
|
o_rBuffer.append( i_rComponentDesc.first );
|
|
|
|
o_rBuffer.append( sal_Unicode( '=' ) );
|
|
|
|
o_rBuffer.append( i_rComponentDesc.second.sName );
|
|
|
|
o_rBuffer.append( sal_Unicode( ',' ) );
|
|
|
|
o_rBuffer.append( sal_Unicode( i_rComponentDesc.second.bForEditing ? '1' : '0' ) );
|
2010-01-13 15:46:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// .........................................................................
|
2010-01-29 13:04:04 +01:00
|
|
|
static bool lcl_extractCompDesc( const ::rtl::OUString& i_rIniLine, ::rtl::OUString& o_rStorName, SubComponentDescriptor& o_rCompDesc )
|
2010-01-13 15:46:51 +01:00
|
|
|
{
|
2010-01-14 15:10:17 +01:00
|
|
|
const sal_Int32 nEqualSignPos = i_rIniLine.indexOf( sal_Unicode( '=' ) );
|
|
|
|
if ( nEqualSignPos < 1 )
|
|
|
|
{
|
|
|
|
OSL_ENSURE( false, "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( sal_Unicode( ',' ) );
|
|
|
|
if ( nCommaPos != i_rIniLine.getLength() - 2 )
|
|
|
|
{
|
|
|
|
OSL_ENSURE( false, "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.getStr()[ nCommaPos + 1 ] == '1' );
|
|
|
|
return true;
|
2010-01-13 15:46:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// .........................................................................
|
2010-01-29 13:04:04 +01:00
|
|
|
static SubComponentType lcl_databaseObjectToSubComponentType( const sal_Int32 i_nObjectType )
|
2010-01-13 15:46:51 +01:00
|
|
|
{
|
2010-01-14 15:10:17 +01:00
|
|
|
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;
|
2010-01-13 15:46:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// .........................................................................
|
2010-01-29 13:04:04 +01:00
|
|
|
static const ::rtl::OUString& lcl_getRecoveryDataSubStorageName()
|
2010-01-13 15:46:51 +01:00
|
|
|
{
|
2010-01-14 15:10:17 +01:00
|
|
|
static const ::rtl::OUString s_sRecDataStorName( RTL_CONSTASCII_USTRINGPARAM( "recovery" ) );
|
|
|
|
return s_sRecDataStorName;
|
|
|
|
}
|
2010-01-13 15:46:51 +01:00
|
|
|
|
|
|
|
// .........................................................................
|
2010-01-29 13:04:04 +01:00
|
|
|
static const ::rtl::OUString& lcl_getComponentsStorageName( const SubComponentType i_eType )
|
2010-01-13 15:46:51 +01:00
|
|
|
{
|
2010-01-14 15:10:17 +01:00
|
|
|
static const ::rtl::OUString s_sFormsStorageName( RTL_CONSTASCII_USTRINGPARAM( "forms" ) );
|
|
|
|
static const ::rtl::OUString s_sReportsStorageName( RTL_CONSTASCII_USTRINGPARAM( "reports" ) );
|
|
|
|
static const ::rtl::OUString s_sTablesStorageName( RTL_CONSTASCII_USTRINGPARAM( "tables" ) );
|
|
|
|
static const ::rtl::OUString s_sQueriesStorageName( RTL_CONSTASCII_USTRINGPARAM( "queries" ) );
|
|
|
|
static const ::rtl::OUString s_sRelationsStorageName( RTL_CONSTASCII_USTRINGPARAM( "relations" ) );
|
2010-01-13 15:46:51 +01:00
|
|
|
|
2010-01-14 15:10:17 +01:00
|
|
|
switch ( i_eType )
|
2010-01-13 15:46:51 +01:00
|
|
|
{
|
2010-01-14 15:10:17 +01:00
|
|
|
case FORM:
|
|
|
|
return s_sFormsStorageName;
|
|
|
|
case REPORT:
|
|
|
|
return s_sReportsStorageName;
|
|
|
|
case TABLE:
|
|
|
|
return s_sTablesStorageName;
|
|
|
|
case QUERY:
|
|
|
|
return s_sQueriesStorageName;
|
|
|
|
case RELATION_DESIGN:
|
|
|
|
return s_sRelationsStorageName;
|
|
|
|
default:
|
|
|
|
break;
|
2010-01-13 15:46:51 +01:00
|
|
|
}
|
|
|
|
|
2010-01-14 15:10:17 +01:00
|
|
|
OSL_ENSURE( false, "lcl_getComponentsStorageName: unimplemented case!" );
|
|
|
|
static const ::rtl::OUString s_sFallback;
|
|
|
|
return s_sFallback;
|
|
|
|
}
|
|
|
|
|
|
|
|
// .........................................................................
|
2010-01-29 13:04:04 +01:00
|
|
|
static const ::rtl::OUString& lcl_getObjectMapStreamName()
|
2010-01-14 15:10:17 +01:00
|
|
|
{
|
|
|
|
static const ::rtl::OUString s_sObjectMapStreamName( RTL_CONSTASCII_USTRINGPARAM( "storage-component-map.ini" ) );
|
|
|
|
return s_sObjectMapStreamName;
|
|
|
|
}
|
|
|
|
|
|
|
|
// .........................................................................
|
2010-01-29 13:04:04 +01:00
|
|
|
static const ::rtl::OUString& lcl_getMapStreamEncodingName()
|
2010-01-14 15:10:17 +01:00
|
|
|
{
|
|
|
|
static const ::rtl::OUString s_sMapStreamEncodingName( RTL_CONSTASCII_USTRINGPARAM( "UTF-8" ) );
|
|
|
|
return s_sMapStreamEncodingName;
|
2010-01-13 15:46:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// .........................................................................
|
2010-01-29 13:04:04 +01:00
|
|
|
static void lcl_writeObjectMap_throw( const ::comphelper::ComponentContext& i_rContext, const Reference< XStorage >& i_rStorage,
|
2010-01-14 15:10:17 +01:00
|
|
|
const MapStringToCompDesc& i_mapStorageToCompDesc )
|
2010-01-13 15:46:51 +01:00
|
|
|
{
|
2010-01-14 15:10:17 +01:00
|
|
|
if ( i_mapStorageToCompDesc.empty() )
|
2010-01-13 15:46:51 +01:00
|
|
|
// nothing to do
|
|
|
|
return;
|
|
|
|
|
|
|
|
ENSURE_OR_THROW( i_rStorage.is(), "invalid storage" );
|
|
|
|
Reference< XStream > xIniStream( i_rStorage->openStreamElement(
|
|
|
|
lcl_getObjectMapStreamName(), ElementModes::WRITE | ElementModes::TRUNCATE ), UNO_SET_THROW );
|
|
|
|
|
|
|
|
Reference< XTextOutputStream > xTextOutput( i_rContext.createComponent( "com.sun.star.io.TextOutputStream" ), UNO_QUERY_THROW );
|
2010-01-14 15:10:17 +01:00
|
|
|
xTextOutput->setEncoding( lcl_getMapStreamEncodingName() );
|
2010-01-13 15:46:51 +01:00
|
|
|
|
|
|
|
Reference< XActiveDataSource > xDataSource( xTextOutput, UNO_QUERY_THROW );
|
|
|
|
xDataSource->setOutputStream( xIniStream->getOutputStream() );
|
|
|
|
|
|
|
|
const ::rtl::OUString sLineFeed( sal_Unicode( '\n' ) );
|
|
|
|
xTextOutput->writeString( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "[storages]" ) ) );
|
|
|
|
xTextOutput->writeString( sLineFeed );
|
|
|
|
|
2010-01-14 15:10:17 +01:00
|
|
|
for ( MapStringToCompDesc::const_iterator stor = i_mapStorageToCompDesc.begin();
|
|
|
|
stor != i_mapStorageToCompDesc.end();
|
2010-01-13 15:46:51 +01:00
|
|
|
++stor
|
|
|
|
)
|
|
|
|
{
|
|
|
|
::rtl::OUStringBuffer aLine;
|
2010-01-14 15:10:17 +01:00
|
|
|
lcl_getPersistentRepresentation( *stor, aLine );
|
2010-01-13 15:46:51 +01:00
|
|
|
aLine.append( sLineFeed );
|
2010-01-14 15:10:17 +01:00
|
|
|
|
2010-01-13 15:46:51 +01:00
|
|
|
xTextOutput->writeString( aLine.makeStringAndClear() );
|
|
|
|
}
|
|
|
|
|
|
|
|
xTextOutput->writeString( sLineFeed );
|
|
|
|
}
|
2010-01-14 15:10:17 +01:00
|
|
|
|
|
|
|
// .........................................................................
|
2010-01-29 13:04:04 +01:00
|
|
|
static bool lcl_isSectionStart( const ::rtl::OUString& i_rIniLine, ::rtl::OUString& o_rSectionName )
|
2010-01-14 15:10:17 +01:00
|
|
|
{
|
|
|
|
const sal_Int32 nLen = i_rIniLine.getLength();
|
|
|
|
if ( ( nLen > 0 ) && ( i_rIniLine.getStr()[0] == '[' ) && ( i_rIniLine.getStr()[ nLen - 1 ] == ']' ) )
|
|
|
|
{
|
|
|
|
o_rSectionName = i_rIniLine.copy( 1, nLen -2 );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// .........................................................................
|
2010-01-29 13:04:04 +01:00
|
|
|
static void lcl_stripTrailingLineFeed( ::rtl::OUString& io_rLine )
|
2010-01-14 15:10:17 +01:00
|
|
|
{
|
|
|
|
const sal_Int32 nLen = io_rLine.getLength();
|
|
|
|
if ( ( nLen > 0 ) && ( io_rLine.getStr()[ nLen - 1 ] == '\n' ) )
|
|
|
|
io_rLine = io_rLine.copy( 0, nLen - 1 );
|
|
|
|
}
|
|
|
|
|
|
|
|
// .........................................................................
|
2010-01-29 13:04:04 +01:00
|
|
|
static void lcl_readObjectMap_throw( const ::comphelper::ComponentContext& i_rContext, const Reference< XStorage >& i_rStorage,
|
2010-01-14 15:10:17 +01:00
|
|
|
MapStringToCompDesc& o_mapStorageToObjectName )
|
|
|
|
{
|
|
|
|
ENSURE_OR_THROW( i_rStorage.is(), "invalid storage" );
|
|
|
|
if ( !i_rStorage->hasByName( lcl_getObjectMapStreamName() ) )
|
|
|
|
{ // nothing to do, though suspicious
|
|
|
|
OSL_ENSURE( false, "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(
|
|
|
|
lcl_getObjectMapStreamName(), ElementModes::READ ), UNO_SET_THROW );
|
|
|
|
|
|
|
|
Reference< XTextInputStream > xTextInput( i_rContext.createComponent( "com.sun.star.io.TextInputStream" ), UNO_QUERY_THROW );
|
|
|
|
xTextInput->setEncoding( lcl_getMapStreamEncodingName() );
|
|
|
|
|
|
|
|
Reference< XActiveDataSink > xDataSink( xTextInput, UNO_QUERY_THROW );
|
|
|
|
xDataSink->setInputStream( xIniStream->getInputStream() );
|
|
|
|
|
|
|
|
::rtl::OUString sCurrentSection;
|
|
|
|
bool bCurrentSectionIsKnownToBeUnsupported = true;
|
|
|
|
while ( !xTextInput->isEOF() )
|
|
|
|
{
|
|
|
|
::rtl::OUString sLine = xTextInput->readLine();
|
|
|
|
lcl_stripTrailingLineFeed( sLine );
|
|
|
|
|
|
|
|
if ( sLine.getLength() == 0 )
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if ( lcl_isSectionStart( sLine, sCurrentSection ) )
|
|
|
|
{
|
|
|
|
bCurrentSectionIsKnownToBeUnsupported = false;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( bCurrentSectionIsKnownToBeUnsupported )
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// the only section we support so far is "storages"
|
|
|
|
if ( !sCurrentSection.equalsAscii( "storages" ) )
|
|
|
|
{
|
|
|
|
bCurrentSectionIsKnownToBeUnsupported = true;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
::rtl::OUString sStorageName;
|
|
|
|
SubComponentDescriptor aCompDesc;
|
|
|
|
if ( !lcl_extractCompDesc( sLine, sStorageName, aCompDesc ) )
|
|
|
|
continue;
|
|
|
|
o_mapStorageToObjectName[ sStorageName ] = aCompDesc;
|
|
|
|
}
|
|
|
|
}
|
autorecovery: save/recover forms and reports
Still some lose ends. Most notably, the current code contains cases for other sub component types,
but has no real implementation - attempting to save/recover those other types will yield multiple
assertions only. Also, recovery of SRB-reports has not been tested, yet, chances are good there's
some work ahead here.
Other known open issues:
- recovering sub components immediately shows them, instead of initially hiding them, and showing
only when the main document window is shown
- the implementation currently is no real session save, which would require saving information about
*unmodified* open sub components (though not their actual content), and restoring them upon
recovery.
- doing an implicit "connect" at the controller of the to-be-recovered database document is a requirement
to actually load the sub components, but might yield problems in case this requires interaction
(e.g. a login). Need to investigate
- the "recovery" storage is not removed from the database document storage after un/successful recovery
- cancelling the recovery of a "modified" database document always suggests to store this doc somewhere
2010-01-15 15:21:15 +01:00
|
|
|
|
|
|
|
// .........................................................................
|
2010-01-29 13:04:04 +01:00
|
|
|
static bool lcl_determineReadOnly( const Reference< XComponent >& i_rComponent )
|
autorecovery: save/recover forms and reports
Still some lose ends. Most notably, the current code contains cases for other sub component types,
but has no real implementation - attempting to save/recover those other types will yield multiple
assertions only. Also, recovery of SRB-reports has not been tested, yet, chances are good there's
some work ahead here.
Other known open issues:
- recovering sub components immediately shows them, instead of initially hiding them, and showing
only when the main document window is shown
- the implementation currently is no real session save, which would require saving information about
*unmodified* open sub components (though not their actual content), and restoring them upon
recovery.
- doing an implicit "connect" at the controller of the to-be-recovered database document is a requirement
to actually load the sub components, but might yield problems in case this requires interaction
(e.g. a login). Need to investigate
- the "recovery" storage is not removed from the database document storage after un/successful recovery
- cancelling the recovery of a "modified" database document always suggests to store this doc somewhere
2010-01-15 15:21:15 +01:00
|
|
|
{
|
|
|
|
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 );
|
|
|
|
}
|
|
|
|
|
|
|
|
// .........................................................................
|
2010-01-29 13:04:04 +01:00
|
|
|
static void lcl_markModified( const Reference< XComponent >& i_rSubComponent )
|
autorecovery: save/recover forms and reports
Still some lose ends. Most notably, the current code contains cases for other sub component types,
but has no real implementation - attempting to save/recover those other types will yield multiple
assertions only. Also, recovery of SRB-reports has not been tested, yet, chances are good there's
some work ahead here.
Other known open issues:
- recovering sub components immediately shows them, instead of initially hiding them, and showing
only when the main document window is shown
- the implementation currently is no real session save, which would require saving information about
*unmodified* open sub components (though not their actual content), and restoring them upon
recovery.
- doing an implicit "connect" at the controller of the to-be-recovered database document is a requirement
to actually load the sub components, but might yield problems in case this requires interaction
(e.g. a login). Need to investigate
- the "recovery" storage is not removed from the database document storage after un/successful recovery
- cancelling the recovery of a "modified" database document always suggests to store this doc somewhere
2010-01-15 15:21:15 +01:00
|
|
|
{
|
|
|
|
const Reference< XModifiable > xModify( i_rSubComponent, UNO_QUERY );
|
|
|
|
if ( !xModify.is() )
|
|
|
|
{
|
|
|
|
OSL_ENSURE( false, "lcl_markModified: unhandled case!" );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
xModify->setModified( sal_True );
|
|
|
|
}
|
2010-01-29 13:04:04 +01:00
|
|
|
|
|
|
|
// .........................................................................
|
|
|
|
static Reference< XCommandProcessor > lcl_getSubComponentDef_nothrow( const Reference< XController >& i_rAppUI,
|
|
|
|
SubComponentType i_eType, const ::rtl::OUString& i_rName )
|
|
|
|
{
|
|
|
|
ENSURE_OR_RETURN( i_rAppUI.is(), "lcl_getSubComponentDef_nothrow: illegal controller", NULL );
|
|
|
|
ENSURE_OR_RETURN( ( i_eType == FORM ) || ( i_eType == REPORT ), "lcl_getSubComponentDef_nothrow: illegal controller", NULL );
|
|
|
|
|
|
|
|
Reference< XCommandProcessor > xCommandProcessor;
|
|
|
|
try
|
|
|
|
{
|
|
|
|
Reference< XHierarchicalNameAccess > xDefinitionContainer;
|
|
|
|
if ( i_eType == FORM )
|
|
|
|
{
|
|
|
|
Reference< XFormDocumentsSupplier > xSuppForms( i_rAppUI->getModel(), UNO_QUERY_THROW );
|
|
|
|
xDefinitionContainer.set( xSuppForms->getFormDocuments(), UNO_QUERY_THROW );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Reference< XReportDocumentsSupplier > xSuppReports( i_rAppUI->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();
|
|
|
|
}
|
|
|
|
return xCommandProcessor;
|
|
|
|
}
|
2010-01-13 15:46:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//====================================================================
|
|
|
|
//= DatabaseDocumentRecovery_Data
|
|
|
|
//====================================================================
|
|
|
|
struct DatabaseDocumentRecovery_Data
|
|
|
|
{
|
2010-01-14 15:10:17 +01:00
|
|
|
const ::comphelper::ComponentContext aContext;
|
2010-01-13 15:46:51 +01:00
|
|
|
|
2010-01-14 15:10:17 +01:00
|
|
|
DatabaseDocumentRecovery_Data( const ::comphelper::ComponentContext& i_rContext )
|
2010-01-13 15:46:51 +01:00
|
|
|
:aContext( i_rContext )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
//====================================================================
|
|
|
|
//= SubComponentRecovery
|
|
|
|
//====================================================================
|
|
|
|
class SubComponentRecovery
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
SubComponentRecovery( const ::comphelper::ComponentContext& i_rContext, const Reference< XDatabaseDocumentUI >& i_rController,
|
|
|
|
const Reference< XComponent >& i_rComponent )
|
|
|
|
:m_rContext( i_rContext )
|
|
|
|
,m_xComponent( i_rComponent )
|
2010-01-14 15:10:17 +01:00
|
|
|
,m_eType( UNKNOWN )
|
|
|
|
,m_aCompDesc()
|
2010-01-13 15:46:51 +01:00
|
|
|
{
|
2010-01-14 15:10:17 +01:00
|
|
|
impl_identifyComponent_throw( i_rController );
|
2010-01-13 15:46:51 +01:00
|
|
|
}
|
|
|
|
|
2010-01-14 15:10:17 +01:00
|
|
|
void saveToRecoveryStorage( const Reference< XStorage >& i_rRecoveryStorage, MapCompTypeToCompDescs& io_mapCompDescs );
|
2010-01-13 15:46:51 +01:00
|
|
|
|
|
|
|
private:
|
2010-01-14 15:10:17 +01:00
|
|
|
void impl_saveSubDocument_throw(
|
|
|
|
const Reference< XStorage >& i_rRecoveryStorage,
|
|
|
|
MapStringToCompDesc& io_mapStorageToCompDesc
|
|
|
|
);
|
|
|
|
|
|
|
|
void impl_identifyComponent_throw(
|
|
|
|
const Reference< XDatabaseDocumentUI >& i_rController
|
|
|
|
);
|
2010-01-13 15:46:51 +01:00
|
|
|
|
|
|
|
private:
|
|
|
|
const ::comphelper::ComponentContext& m_rContext;
|
|
|
|
const Reference< XComponent > m_xComponent;
|
2010-01-14 15:10:17 +01:00
|
|
|
SubComponentType m_eType;
|
|
|
|
SubComponentDescriptor m_aCompDesc;
|
2010-01-13 15:46:51 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------
|
2010-01-14 15:10:17 +01:00
|
|
|
void SubComponentRecovery::saveToRecoveryStorage( const Reference< XStorage >& i_rRecoveryStorage,
|
|
|
|
MapCompTypeToCompDescs& io_mapCompDescs )
|
2010-01-13 15:46:51 +01:00
|
|
|
{
|
2010-01-14 15:10:17 +01:00
|
|
|
|
|
|
|
if ( m_eType == UNKNOWN )
|
|
|
|
// quite fatal, but has already been reported (as assertion) before
|
2010-01-13 15:46:51 +01:00
|
|
|
return;
|
|
|
|
|
2010-01-14 15:10:17 +01:00
|
|
|
switch ( m_eType )
|
2010-01-13 15:46:51 +01:00
|
|
|
{
|
2010-01-14 15:10:17 +01:00
|
|
|
case FORM:
|
|
|
|
case REPORT:
|
|
|
|
impl_saveSubDocument_throw( i_rRecoveryStorage, io_mapCompDescs[ m_eType ] );
|
2010-01-13 15:46:51 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
// TODO
|
|
|
|
OSL_ENSURE( false, "SubComponentRecoverys::saveToRecoveryStorage: unimplemented case!" );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
autorecovery: save/recover forms and reports
Still some lose ends. Most notably, the current code contains cases for other sub component types,
but has no real implementation - attempting to save/recover those other types will yield multiple
assertions only. Also, recovery of SRB-reports has not been tested, yet, chances are good there's
some work ahead here.
Other known open issues:
- recovering sub components immediately shows them, instead of initially hiding them, and showing
only when the main document window is shown
- the implementation currently is no real session save, which would require saving information about
*unmodified* open sub components (though not their actual content), and restoring them upon
recovery.
- doing an implicit "connect" at the controller of the to-be-recovered database document is a requirement
to actually load the sub components, but might yield problems in case this requires interaction
(e.g. a login). Need to investigate
- the "recovery" storage is not removed from the database document storage after un/successful recovery
- cancelling the recovery of a "modified" database document always suggests to store this doc somewhere
2010-01-15 15:21:15 +01:00
|
|
|
//--------------------------------------------------------------------
|
2010-01-14 15:10:17 +01:00
|
|
|
void SubComponentRecovery::impl_identifyComponent_throw( const Reference< XDatabaseDocumentUI >& i_rController )
|
|
|
|
{
|
|
|
|
ENSURE_OR_THROW( i_rController.is(), "illegal controller" );
|
|
|
|
|
|
|
|
// ask the controller
|
|
|
|
Pair< sal_Int32, ::rtl::OUString > aComponentIdentity = i_rController->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< XModuleManager > xModuleManager( m_rContext.createComponent( "com.sun.star.frame.ModuleManager" ), UNO_QUERY_THROW );
|
|
|
|
const ::rtl::OUString sModuleIdentifier = xModuleManager->identify( m_xComponent );
|
|
|
|
|
|
|
|
switch ( m_eType )
|
|
|
|
{
|
|
|
|
case TABLE:
|
|
|
|
m_aCompDesc.bForEditing = sModuleIdentifier.equalsAscii( "com.sun.star.sdb.TableDesign" );
|
|
|
|
break;
|
|
|
|
|
|
|
|
case QUERY:
|
|
|
|
m_aCompDesc.bForEditing = sModuleIdentifier.equalsAscii( "com.sun.star.sdb.QueryDesign" );
|
|
|
|
break;
|
|
|
|
|
|
|
|
case REPORT:
|
|
|
|
if ( sModuleIdentifier.equalsAscii( "com.sun.star.report.ReportDefinition" ) )
|
|
|
|
{
|
|
|
|
// it's an SRB report desginer
|
|
|
|
m_aCompDesc.bForEditing = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// fall through
|
|
|
|
|
|
|
|
case FORM:
|
autorecovery: save/recover forms and reports
Still some lose ends. Most notably, the current code contains cases for other sub component types,
but has no real implementation - attempting to save/recover those other types will yield multiple
assertions only. Also, recovery of SRB-reports has not been tested, yet, chances are good there's
some work ahead here.
Other known open issues:
- recovering sub components immediately shows them, instead of initially hiding them, and showing
only when the main document window is shown
- the implementation currently is no real session save, which would require saving information about
*unmodified* open sub components (though not their actual content), and restoring them upon
recovery.
- doing an implicit "connect" at the controller of the to-be-recovered database document is a requirement
to actually load the sub components, but might yield problems in case this requires interaction
(e.g. a login). Need to investigate
- the "recovery" storage is not removed from the database document storage after un/successful recovery
- cancelling the recovery of a "modified" database document always suggests to store this doc somewhere
2010-01-15 15:21:15 +01:00
|
|
|
m_aCompDesc.bForEditing = !lcl_determineReadOnly( m_xComponent );
|
2010-01-14 15:10:17 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
if ( sModuleIdentifier.equalsAscii( "com.sun.star.sdb.RelationDesign" ) )
|
|
|
|
{
|
|
|
|
m_eType = RELATION_DESIGN;
|
|
|
|
m_aCompDesc.bForEditing = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
OSL_ENSURE( false, "SubComponentRecovery::impl_identifyComponent_throw: couldn't classify the given sub component!" );
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
OSL_POSTCOND( m_eType != UNKNOWN,
|
|
|
|
"SubComponentRecovery::impl_identifyComponent_throw: couldn't classify the component!" );
|
|
|
|
}
|
|
|
|
|
2010-01-13 15:46:51 +01:00
|
|
|
//--------------------------------------------------------------------
|
2010-01-14 15:10:17 +01:00
|
|
|
void SubComponentRecovery::impl_saveSubDocument_throw( const Reference< XStorage >& i_rRecoveryStorage,
|
|
|
|
MapStringToCompDesc& io_mapStorageToCompDesc )
|
2010-01-13 15:46:51 +01:00
|
|
|
{
|
2010-01-14 15:10:17 +01:00
|
|
|
ENSURE_OR_THROW( ( m_eType == FORM ) || ( m_eType == REPORT ), "illegal sub component type" );
|
2010-01-13 15:46:51 +01:00
|
|
|
ENSURE_OR_THROW( i_rRecoveryStorage.is(), "illegal storage" );
|
|
|
|
|
|
|
|
// open the sub storage for the given kind of documents
|
2010-01-14 15:10:17 +01:00
|
|
|
const ::rtl::OUString& rStorageName( lcl_getComponentsStorageName( m_eType ) );
|
|
|
|
const Reference< XStorage > xDocsStor( i_rRecoveryStorage->openStorageElement(
|
|
|
|
rStorageName, ElementModes::READWRITE ), UNO_QUERY_THROW );
|
2010-01-13 15:46:51 +01:00
|
|
|
|
|
|
|
// find a free sub storage name, and create Yet Another Sub Storage
|
2010-01-14 15:10:17 +01:00
|
|
|
const ::rtl::OUString sBaseName( ::rtl::OUString::createFromAscii( m_eType == FORM ? "form" : "report" ) );
|
2010-01-13 15:46:51 +01:00
|
|
|
const ::rtl::OUString sCompStorName = ::dbtools::createUniqueName( xDocsStor.get(), sBaseName, true );
|
2010-01-14 15:10:17 +01:00
|
|
|
const Reference< XStorage > xCompStor( xDocsStor->openStorageElement(
|
|
|
|
sCompStorName, ElementModes::READWRITE ), UNO_QUERY_THROW );
|
2010-01-13 15:46:51 +01:00
|
|
|
|
|
|
|
// store the document into the storage
|
|
|
|
Reference< XStorageBasedDocument > xStorageDocument( m_xComponent, UNO_QUERY_THROW );
|
|
|
|
xStorageDocument->storeToStorage( xCompStor, Sequence< PropertyValue >() );
|
|
|
|
|
2010-01-14 15:10:17 +01:00
|
|
|
// remember the relationship between the component name to the storage name
|
|
|
|
OSL_ENSURE( io_mapStorageToCompDesc.find( sCompStorName ) == io_mapStorageToCompDesc.end(),
|
|
|
|
"SubComponentRecoverys::impl_saveSubDocument_throw: object name already used!" );
|
|
|
|
io_mapStorageToCompDesc[ sCompStorName ] = m_aCompDesc;
|
2010-01-13 15:46:51 +01:00
|
|
|
|
|
|
|
// commit the storage for the documents collection
|
|
|
|
tools::stor::commitStorageIfWriteable( xDocsStor );
|
|
|
|
}
|
|
|
|
|
|
|
|
//====================================================================
|
|
|
|
//= DatabaseDocumentRecovery
|
|
|
|
//====================================================================
|
|
|
|
//--------------------------------------------------------------------
|
2010-01-14 15:10:17 +01:00
|
|
|
DatabaseDocumentRecovery::DatabaseDocumentRecovery( const ::comphelper::ComponentContext& i_rContext )
|
|
|
|
:m_pData( new DatabaseDocumentRecovery_Data( i_rContext ) )
|
2010-01-13 15:46:51 +01:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
|
|
DatabaseDocumentRecovery::~DatabaseDocumentRecovery()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------
|
2010-01-14 15:10:17 +01:00
|
|
|
void DatabaseDocumentRecovery::saveModifiedSubComponents( const Reference< XStorage >& i_rTargetStorage,
|
|
|
|
const ::std::vector< Reference< XController > >& i_rControllers )
|
2010-01-13 15:46:51 +01:00
|
|
|
{
|
2010-01-14 15:10:17 +01:00
|
|
|
ENSURE_OR_THROW( i_rTargetStorage.is(), "invalid document storage" );
|
|
|
|
|
2010-01-13 15:46:51 +01:00
|
|
|
// create a sub storage for recovery data
|
2010-01-14 15:10:17 +01:00
|
|
|
if ( i_rTargetStorage->hasByName( lcl_getRecoveryDataSubStorageName() ) )
|
|
|
|
i_rTargetStorage->removeElement( lcl_getRecoveryDataSubStorageName() );
|
|
|
|
Reference< XStorage > xRecoveryStorage = i_rTargetStorage->openStorageElement( lcl_getRecoveryDataSubStorageName(), ElementModes::READWRITE );
|
2010-01-13 15:46:51 +01:00
|
|
|
|
|
|
|
// 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.
|
|
|
|
|
2010-01-14 15:10:17 +01:00
|
|
|
MapCompTypeToCompDescs aMapCompDescs;
|
2010-01-13 15:46:51 +01:00
|
|
|
|
|
|
|
for ( ::std::vector< Reference< XController > >::const_iterator ctrl = i_rControllers.begin();
|
|
|
|
ctrl != i_rControllers.end();
|
|
|
|
++ctrl
|
|
|
|
)
|
|
|
|
{
|
|
|
|
Reference< XDatabaseDocumentUI > xDatabaseUI( *ctrl, UNO_QUERY_THROW );
|
|
|
|
Sequence< Reference< XComponent > > aComponents( xDatabaseUI->getSubComponents() );
|
|
|
|
|
|
|
|
const Reference< XComponent >* component = aComponents.getConstArray();
|
|
|
|
const Reference< XComponent >* componentEnd = aComponents.getConstArray() + aComponents.getLength();
|
|
|
|
for ( ; component != componentEnd; ++component )
|
|
|
|
{
|
|
|
|
SubComponentRecovery aComponentRecovery( m_pData->aContext, xDatabaseUI, *component );
|
2010-01-14 15:10:17 +01:00
|
|
|
aComponentRecovery.saveToRecoveryStorage( xRecoveryStorage, aMapCompDescs );
|
2010-01-13 15:46:51 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-01-14 15:10:17 +01:00
|
|
|
for ( MapCompTypeToCompDescs::const_iterator map = aMapCompDescs.begin();
|
|
|
|
map != aMapCompDescs.end();
|
|
|
|
++map
|
|
|
|
)
|
|
|
|
{
|
|
|
|
Reference< XStorage > xComponentsStor( xRecoveryStorage->openStorageElement(
|
|
|
|
lcl_getComponentsStorageName( map->first ), ElementModes::WRITE | ElementModes::NOCREATE ) );
|
|
|
|
lcl_writeObjectMap_throw( m_pData->aContext, xComponentsStor, map->second );
|
|
|
|
tools::stor::commitStorageIfWriteable( xComponentsStor );
|
|
|
|
}
|
2010-01-13 15:46:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// commit the recovery storage
|
|
|
|
tools::stor::commitStorageIfWriteable( xRecoveryStorage );
|
|
|
|
}
|
|
|
|
|
2010-01-14 15:10:17 +01:00
|
|
|
//--------------------------------------------------------------------
|
|
|
|
void DatabaseDocumentRecovery::recoverSubDocuments( const Reference< XStorage >& i_rDocumentStorage,
|
|
|
|
const Reference< XController >& i_rTargetController )
|
|
|
|
{
|
|
|
|
ENSURE_OR_THROW( i_rDocumentStorage.is(), "illegal document storage" );
|
autorecovery: save/recover forms and reports
Still some lose ends. Most notably, the current code contains cases for other sub component types,
but has no real implementation - attempting to save/recover those other types will yield multiple
assertions only. Also, recovery of SRB-reports has not been tested, yet, chances are good there's
some work ahead here.
Other known open issues:
- recovering sub components immediately shows them, instead of initially hiding them, and showing
only when the main document window is shown
- the implementation currently is no real session save, which would require saving information about
*unmodified* open sub components (though not their actual content), and restoring them upon
recovery.
- doing an implicit "connect" at the controller of the to-be-recovered database document is a requirement
to actually load the sub components, but might yield problems in case this requires interaction
(e.g. a login). Need to investigate
- the "recovery" storage is not removed from the database document storage after un/successful recovery
- cancelling the recovery of a "modified" database document always suggests to store this doc somewhere
2010-01-15 15:21:15 +01:00
|
|
|
Reference< XDatabaseDocumentUI > xDocumentUI( i_rTargetController, UNO_QUERY_THROW );
|
2010-01-14 15:10:17 +01:00
|
|
|
|
|
|
|
if ( !i_rDocumentStorage->hasByName( lcl_getRecoveryDataSubStorageName() ) )
|
|
|
|
// that's allowed
|
|
|
|
return;
|
|
|
|
|
|
|
|
// the "recovery" sub storage
|
|
|
|
Reference< XStorage > xRecoveryStorage = i_rDocumentStorage->openStorageElement( lcl_getRecoveryDataSubStorageName(), ElementModes::READ );
|
|
|
|
|
|
|
|
// read the map from sub storages to object names
|
|
|
|
MapCompTypeToCompDescs aMapCompDescs;
|
|
|
|
SubComponentType aKnownTypes[] = { TABLE, QUERY, FORM, REPORT, RELATION_DESIGN };
|
|
|
|
for ( size_t i = 0; i < sizeof( aKnownTypes ) / sizeof( aKnownTypes[0] ); ++i )
|
|
|
|
{
|
|
|
|
if ( !xRecoveryStorage->hasByName( lcl_getComponentsStorageName( aKnownTypes[i] ) ) )
|
|
|
|
continue;
|
|
|
|
|
|
|
|
Reference< XStorage > xComponentsStor( xRecoveryStorage->openStorageElement(
|
|
|
|
lcl_getComponentsStorageName( aKnownTypes[i] ), ElementModes::READ ) );
|
|
|
|
lcl_readObjectMap_throw( m_pData->aContext, xComponentsStor, aMapCompDescs[ aKnownTypes[i] ] );
|
|
|
|
xComponentsStor->dispose();
|
|
|
|
}
|
|
|
|
|
|
|
|
// recover all sub components as indicated by the map
|
|
|
|
for ( MapCompTypeToCompDescs::const_iterator map = aMapCompDescs.begin();
|
|
|
|
map != aMapCompDescs.end();
|
|
|
|
++map
|
|
|
|
)
|
|
|
|
{
|
2010-01-26 13:19:11 +01:00
|
|
|
const SubComponentType eComponentType = map->first;
|
|
|
|
if ( ( eComponentType != FORM ) && ( eComponentType != REPORT ) )
|
|
|
|
{
|
|
|
|
// nobody saves tables/queries/relations at the moment, so encountering those is worth an assertion
|
|
|
|
OSL_ENSURE( false, "DatabaseDocumentRecovery::recoverSubDocuments: only embedded objects can be recovered currently!" );
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2010-01-14 15:10:17 +01:00
|
|
|
// the storage for all components of the current type
|
|
|
|
Reference< XStorage > xComponentsStor( xRecoveryStorage->openStorageElement(
|
2010-01-26 13:19:11 +01:00
|
|
|
lcl_getComponentsStorageName( eComponentType ), ElementModes::READ ), UNO_QUERY_THROW );
|
2010-01-14 15:10:17 +01:00
|
|
|
|
|
|
|
// loop thru all components of this type
|
|
|
|
for ( MapStringToCompDesc::const_iterator stor = map->second.begin();
|
|
|
|
stor != map->second.end();
|
|
|
|
++stor
|
|
|
|
)
|
|
|
|
{
|
2010-01-26 13:19:11 +01:00
|
|
|
const ::rtl::OUString sComponentName( stor->second.sName );
|
2010-01-14 15:10:17 +01:00
|
|
|
if ( !xComponentsStor->hasByName( stor->first ) )
|
|
|
|
{
|
|
|
|
#if OSL_DEBUG_LEVEL > 0
|
|
|
|
::rtl::OStringBuffer message;
|
|
|
|
message.append( "DatabaseDocumentRecovery::recoverSubDocuments: inconsistent recovery storage: storage '" );
|
|
|
|
message.append( ::rtl::OUStringToOString( stor->first, RTL_TEXTENCODING_ASCII_US ) );
|
|
|
|
message.append( "' not found in '" );
|
2010-01-26 13:19:11 +01:00
|
|
|
message.append( ::rtl::OUStringToOString( lcl_getComponentsStorageName( eComponentType ), RTL_TEXTENCODING_ASCII_US ) );
|
2010-01-14 15:10:17 +01:00
|
|
|
message.append( "', but required per map file!" );
|
|
|
|
OSL_ENSURE( false, message.makeStringAndClear() );
|
|
|
|
#endif
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
autorecovery: save/recover forms and reports
Still some lose ends. Most notably, the current code contains cases for other sub component types,
but has no real implementation - attempting to save/recover those other types will yield multiple
assertions only. Also, recovery of SRB-reports has not been tested, yet, chances are good there's
some work ahead here.
Other known open issues:
- recovering sub components immediately shows them, instead of initially hiding them, and showing
only when the main document window is shown
- the implementation currently is no real session save, which would require saving information about
*unmodified* open sub components (though not their actual content), and restoring them upon
recovery.
- doing an implicit "connect" at the controller of the to-be-recovered database document is a requirement
to actually load the sub components, but might yield problems in case this requires interaction
(e.g. a login). Need to investigate
- the "recovery" storage is not removed from the database document storage after un/successful recovery
- cancelling the recovery of a "modified" database document always suggests to store this doc somewhere
2010-01-15 15:21:15 +01:00
|
|
|
// the controller needs to have a connection to be able to open sub components
|
|
|
|
if ( !xDocumentUI->isConnected() )
|
|
|
|
xDocumentUI->connect();
|
|
|
|
|
2010-01-14 15:10:17 +01:00
|
|
|
// recover the single component
|
|
|
|
Reference< XStorage > xCompStor( xComponentsStor->openStorageElement( stor->first, ElementModes::READ ) );
|
autorecovery: save/recover forms and reports
Still some lose ends. Most notably, the current code contains cases for other sub component types,
but has no real implementation - attempting to save/recover those other types will yield multiple
assertions only. Also, recovery of SRB-reports has not been tested, yet, chances are good there's
some work ahead here.
Other known open issues:
- recovering sub components immediately shows them, instead of initially hiding them, and showing
only when the main document window is shown
- the implementation currently is no real session save, which would require saving information about
*unmodified* open sub components (though not their actual content), and restoring them upon
recovery.
- doing an implicit "connect" at the controller of the to-be-recovered database document is a requirement
to actually load the sub components, but might yield problems in case this requires interaction
(e.g. a login). Need to investigate
- the "recovery" storage is not removed from the database document storage after un/successful recovery
- cancelling the recovery of a "modified" database document always suggests to store this doc somewhere
2010-01-15 15:21:15 +01:00
|
|
|
::comphelper::NamedValueCollection aLoadArgs;
|
2010-01-26 13:19:11 +01:00
|
|
|
aLoadArgs.put( "RecoveryStorage", xCompStor );
|
|
|
|
|
2010-01-29 13:04:04 +01:00
|
|
|
// load/create the sub component hidden. We'll show it when the main app window is shown.
|
|
|
|
aLoadArgs.put( "Hidden", true );
|
|
|
|
|
2010-02-01 11:43:40 +01:00
|
|
|
Reference< XComponent > xSubComponent;
|
|
|
|
Reference< XCommandProcessor > xDocDefinition;
|
|
|
|
|
|
|
|
if ( sComponentName.getLength() )
|
|
|
|
{
|
|
|
|
xDocDefinition = lcl_getSubComponentDef_nothrow( i_rTargetController, eComponentType, sComponentName );
|
|
|
|
xSubComponent.set( xDocumentUI->loadComponentWithArguments(
|
|
|
|
eComponentType,
|
|
|
|
sComponentName,
|
|
|
|
stor->second.bForEditing,
|
|
|
|
aLoadArgs.getPropertyValues()
|
|
|
|
),
|
|
|
|
UNO_SET_THROW
|
|
|
|
);
|
|
|
|
}
|
|
|
|
else
|
autorecovery: save/recover forms and reports
Still some lose ends. Most notably, the current code contains cases for other sub component types,
but has no real implementation - attempting to save/recover those other types will yield multiple
assertions only. Also, recovery of SRB-reports has not been tested, yet, chances are good there's
some work ahead here.
Other known open issues:
- recovering sub components immediately shows them, instead of initially hiding them, and showing
only when the main document window is shown
- the implementation currently is no real session save, which would require saving information about
*unmodified* open sub components (though not their actual content), and restoring them upon
recovery.
- doing an implicit "connect" at the controller of the to-be-recovered database document is a requirement
to actually load the sub components, but might yield problems in case this requires interaction
(e.g. a login). Need to investigate
- the "recovery" storage is not removed from the database document storage after un/successful recovery
- cancelling the recovery of a "modified" database document always suggests to store this doc somewhere
2010-01-15 15:21:15 +01:00
|
|
|
{
|
2010-02-01 11:43:40 +01:00
|
|
|
Reference< XComponent > xDocDefComponent;
|
|
|
|
xSubComponent.set( xDocumentUI->createComponentWithArguments(
|
|
|
|
eComponentType,
|
|
|
|
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?!" );
|
autorecovery: save/recover forms and reports
Still some lose ends. Most notably, the current code contains cases for other sub component types,
but has no real implementation - attempting to save/recover those other types will yield multiple
assertions only. Also, recovery of SRB-reports has not been tested, yet, chances are good there's
some work ahead here.
Other known open issues:
- recovering sub components immediately shows them, instead of initially hiding them, and showing
only when the main document window is shown
- the implementation currently is no real session save, which would require saving information about
*unmodified* open sub components (though not their actual content), and restoring them upon
recovery.
- doing an implicit "connect" at the controller of the to-be-recovered database document is a requirement
to actually load the sub components, but might yield problems in case this requires interaction
(e.g. a login). Need to investigate
- the "recovery" storage is not removed from the database document storage after un/successful recovery
- cancelling the recovery of a "modified" database document always suggests to store this doc somewhere
2010-01-15 15:21:15 +01:00
|
|
|
}
|
2010-02-01 11:43:40 +01:00
|
|
|
|
|
|
|
if ( xDocDefinition.is() )
|
autorecovery: save/recover forms and reports
Still some lose ends. Most notably, the current code contains cases for other sub component types,
but has no real implementation - attempting to save/recover those other types will yield multiple
assertions only. Also, recovery of SRB-reports has not been tested, yet, chances are good there's
some work ahead here.
Other known open issues:
- recovering sub components immediately shows them, instead of initially hiding them, and showing
only when the main document window is shown
- the implementation currently is no real session save, which would require saving information about
*unmodified* open sub components (though not their actual content), and restoring them upon
recovery.
- doing an implicit "connect" at the controller of the to-be-recovered database document is a requirement
to actually load the sub components, but might yield problems in case this requires interaction
(e.g. a login). Need to investigate
- the "recovery" storage is not removed from the database document storage after un/successful recovery
- cancelling the recovery of a "modified" database document always suggests to store this doc somewhere
2010-01-15 15:21:15 +01:00
|
|
|
{
|
2010-02-01 11:43:40 +01:00
|
|
|
Reference< XInterface > xLoader( *new SubComponentLoader( i_rTargetController, xDocDefinition ) );
|
|
|
|
(void)xLoader;
|
autorecovery: save/recover forms and reports
Still some lose ends. Most notably, the current code contains cases for other sub component types,
but has no real implementation - attempting to save/recover those other types will yield multiple
assertions only. Also, recovery of SRB-reports has not been tested, yet, chances are good there's
some work ahead here.
Other known open issues:
- recovering sub components immediately shows them, instead of initially hiding them, and showing
only when the main document window is shown
- the implementation currently is no real session save, which would require saving information about
*unmodified* open sub components (though not their actual content), and restoring them upon
recovery.
- doing an implicit "connect" at the controller of the to-be-recovered database document is a requirement
to actually load the sub components, but might yield problems in case this requires interaction
(e.g. a login). Need to investigate
- the "recovery" storage is not removed from the database document storage after un/successful recovery
- cancelling the recovery of a "modified" database document always suggests to store this doc somewhere
2010-01-15 15:21:15 +01:00
|
|
|
}
|
2010-02-01 11:43:40 +01:00
|
|
|
|
|
|
|
// 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 );
|
2010-01-14 15:10:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
xComponentsStor->dispose();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-01-13 15:46:51 +01:00
|
|
|
//........................................................................
|
|
|
|
} // namespace dbaccess
|
|
|
|
//........................................................................
|