diff options
Diffstat (limited to 'dbaccess/source/core')
47 files changed, 4507 insertions, 714 deletions
diff --git a/dbaccess/source/core/api/RowSet.cxx b/dbaccess/source/core/api/RowSet.cxx index 5f421f89724d..2d7bda3f29b4 100644 --- a/dbaccess/source/core/api/RowSet.cxx +++ b/dbaccess/source/core/api/RowSet.cxx @@ -1575,7 +1575,11 @@ void ORowSet::setStatementResultSetType( const Reference< XPropertySet >& _rxSta { ResultSetType::SCROLL_INSENSITIVE, ResultSetConcurrency::READ_ONLY }, { ResultSetType::FORWARD_ONLY, ResultSetConcurrency::READ_ONLY } }; - for ( sal_Int32 i=0; i<5; ++i ) + sal_Int32 i=0; + if ( m_xActiveConnection->getMetaData()->isReadOnly() ) + i = 2; // if the database is read-only we only should use read-only concurrency + + for ( ; i<5; ++i ) { nResultSetType = nCharacteristics[i][0]; nResultSetConcurrency = nCharacteristics[i][1]; @@ -1897,6 +1901,8 @@ void ORowSet::execute_NoApprove_NoNewConn(ResettableMutexGuard& _rClearForNotifi if(!xColumn.is()) { // no column found so we could look at the position i + //bReFetchName = sal_True; + //sColumnLabel = ::rtl::OUString(); Reference<XIndexAccess> xIndexAccess(m_xColumns,UNO_QUERY); if(xIndexAccess.is() && i <= xIndexAccess->getCount()) { @@ -1906,7 +1912,9 @@ void ORowSet::execute_NoApprove_NoNewConn(ResettableMutexGuard& _rClearForNotifi { Sequence< ::rtl::OUString> aSeq = m_xColumns->getElementNames(); if( i <= aSeq.getLength()) + { m_xColumns->getByName(aSeq.getConstArray()[i-1]) >>= xColumn; + } } } if(bReFetchName && xColumn.is()) @@ -2314,6 +2322,12 @@ sal_Bool ORowSet::impl_buildActiveCommand_throw() { xQuery->getPropertyValue(PROPERTY_COMMAND) >>= sCommand; xQuery->getPropertyValue(PROPERTY_ESCAPE_PROCESSING) >>= bDoEscapeProcessing; + if ( bDoEscapeProcessing != m_bUseEscapeProcessing ) + { + sal_Bool bOldValue = m_bUseEscapeProcessing; + m_bUseEscapeProcessing = bDoEscapeProcessing; + fireProperty(PROPERTY_ID_ESCAPE_PROCESSING,bOldValue,bDoEscapeProcessing); + } ::rtl::OUString aCatalog,aSchema,aTable; xQuery->getPropertyValue(PROPERTY_UPDATE_CATALOGNAME) >>= aCatalog; diff --git a/dbaccess/source/core/api/SingleSelectQueryComposer.cxx b/dbaccess/source/core/api/SingleSelectQueryComposer.cxx index 82f6f5e293de..b14b4440275a 100644 --- a/dbaccess/source/core/api/SingleSelectQueryComposer.cxx +++ b/dbaccess/source/core/api/SingleSelectQueryComposer.cxx @@ -34,6 +34,7 @@ #include "dbastrings.hrc" #include "HelperCollections.hxx" #include "SingleSelectQueryComposer.hxx" +#include "sdbcoretools.hxx" /** === begin UNO includes === **/ #include <com/sun/star/beans/PropertyAttribute.hpp> @@ -225,24 +226,11 @@ OSingleSelectQueryComposer::OSingleSelectQueryComposer(const Reference< XNameAcc OSL_ENSURE(m_sDecimalSep.getLength() == 1,"OSingleSelectQueryComposer::OSingleSelectQueryComposer decimal separator is not 1 length"); try { - Reference< XChild> xChild(_xConnection, UNO_QUERY); - if(xChild.is()) + Any aValue; + Reference<XInterface> xDs = dbaccess::getDataSource(_xConnection); + if ( dbtools::getDataSourceSetting(xDs,static_cast <rtl::OUString> (PROPERTY_BOOLEANCOMPARISONMODE),aValue) ) { - Reference< XPropertySet> xProp(xChild->getParent(),UNO_QUERY); - if ( xProp.is() ) - { - Sequence< PropertyValue > aInfo; - xProp->getPropertyValue(PROPERTY_INFO) >>= aInfo; - const PropertyValue* pBegin = aInfo.getConstArray(); - const PropertyValue* pEnd = pBegin + aInfo.getLength(); - for (; pBegin != pEnd; ++pBegin) - { - if ( pBegin->Name == static_cast <rtl::OUString> (PROPERTY_BOOLEANCOMPARISONMODE) ) - { - OSL_VERIFY( pBegin->Value >>= m_nBoolCompareMode ); - } - } - } + OSL_VERIFY( aValue >>= m_nBoolCompareMode ); } } catch(Exception&) diff --git a/dbaccess/source/core/api/View.cxx b/dbaccess/source/core/api/View.cxx new file mode 100644 index 000000000000..fa528d203466 --- /dev/null +++ b/dbaccess/source/core/api/View.cxx @@ -0,0 +1,161 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: View.cxx,v $ + * $Revision: 1.3 $ + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#include "View.hxx" +#include "dbastrings.hrc" + +#include "connectivity/dbexception.hxx" +#include "connectivity/dbtools.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/lang/WrappedTargetException.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/sdbc/XRow.hpp> +/** === end UNO includes === **/ + +#include <cppuhelper/exc_hlp.hxx> +#include <tools/diagnose_ex.h> +#include <unotools/sharedunocomponent.hxx> + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + + /** === begin UNO using === **/ + using namespace ::com::sun::star::uno; + using ::com::sun::star::sdbc::XDatabaseMetaData; + using ::com::sun::star::sdbc::SQLException; + using ::com::sun::star::sdbc::XConnection; + using ::com::sun::star::lang::WrappedTargetException; + using ::com::sun::star::lang::XMultiServiceFactory; + using ::com::sun::star::sdbc::XResultSet; + using ::com::sun::star::sdbc::XStatement; + using ::com::sun::star::lang::DisposedException; + using ::com::sun::star::sdbc::XRow; + /** === end UNO using === **/ + + ::rtl::OUString lcl_getServiceNameForSetting(const Reference< ::com::sun::star::sdbc::XConnection >& _xConnection,const ::rtl::OUString& i_sSetting) + { + ::rtl::OUString sSupportService; + Any aValue; + if ( dbtools::getDataSourceSetting(_xConnection,i_sSetting,aValue) ) + { + aValue >>= sSupportService; + } + return sSupportService; + } + //==================================================================== + //= View + //==================================================================== + //-------------------------------------------------------------------- + View::View( const Reference< XConnection >& _rxConnection, sal_Bool _bCaseSensitive, + const ::rtl::OUString& _rCatalogName,const ::rtl::OUString& _rSchemaName, const ::rtl::OUString& _rName ) + :View_Base( _bCaseSensitive, _rName, _rxConnection->getMetaData(), 0, ::rtl::OUString(), _rSchemaName, _rCatalogName ) + { + m_nCommandHandle = getProperty(PROPERTY_COMMAND).Handle; + try + { + Reference<XMultiServiceFactory> xFac(_rxConnection,UNO_QUERY_THROW); + static const ::rtl::OUString s_sViewAccess(RTL_CONSTASCII_USTRINGPARAM("ViewAccessServiceName")); + m_xViewAccess.set(xFac->createInstance(lcl_getServiceNameForSetting(_rxConnection,s_sViewAccess)),UNO_QUERY); + } + catch(const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + //-------------------------------------------------------------------- + View::~View() + { + } + + //-------------------------------------------------------------------- + IMPLEMENT_FORWARD_REFCOUNT( View, View_Base ) + IMPLEMENT_GET_IMPLEMENTATION_ID( View ) + // ------------------------------------------------------------------------- + Any SAL_CALL View::queryInterface( const Type & _rType ) throw(RuntimeException) + { + if(_rType == getCppuType( (Reference<XAlterView>*)0) && !m_xViewAccess.is() ) + return Any(); + Any aReturn = View_Base::queryInterface( _rType ); + if ( !aReturn.hasValue() ) + aReturn = View_IBASE::queryInterface( _rType ); + return aReturn; + } + // ------------------------------------------------------------------------- + Sequence< Type > SAL_CALL View::getTypes( ) throw(RuntimeException) + { + Type aAlterType = getCppuType( (Reference<XAlterView>*)0); + + Sequence< Type > aTypes( ::comphelper::concatSequences(View_Base::getTypes(),View_IBASE::getTypes()) ); + ::std::vector<Type> aOwnTypes; + aOwnTypes.reserve(aTypes.getLength()); + + const Type* pIter = aTypes.getConstArray(); + const Type* pEnd = pIter + aTypes.getLength(); + for(;pIter != pEnd ;++pIter) + { + if( (*pIter != aAlterType || m_xViewAccess.is()) ) + aOwnTypes.push_back(*pIter); + } + + Type* pTypes = aOwnTypes.empty() ? 0 : &aOwnTypes[0]; + return Sequence< Type >(pTypes, aOwnTypes.size()); + } + + //-------------------------------------------------------------------- + void SAL_CALL View::alterCommand( const ::rtl::OUString& _rNewCommand ) throw (SQLException, RuntimeException) + { + OSL_ENSURE(m_xViewAccess.is(),"Illegal call to AlterView!"); + m_xViewAccess->alterCommand(this,_rNewCommand); + } + + //-------------------------------------------------------------------- + void SAL_CALL View::getFastPropertyValue( Any& _rValue, sal_Int32 _nHandle ) const + { + if ( _nHandle == m_nCommandHandle && m_xViewAccess.is() ) + { + // retrieve the very current command, don't rely on the base classes cached value + // (which we initialized empty, anyway) + _rValue <<= m_xViewAccess->getCommand(const_cast<View*>(this)); + return; + } + + View_Base::getFastPropertyValue( _rValue, _nHandle ); + } + // ----------------------------------------------------------------------------- +//........................................................................ +} // namespace dbaccess +//........................................................................ diff --git a/dbaccess/source/core/api/column.cxx b/dbaccess/source/core/api/column.cxx index 9665b3465338..292bf5694793 100644 --- a/dbaccess/source/core/api/column.cxx +++ b/dbaccess/source/core/api/column.cxx @@ -414,7 +414,16 @@ sdbcx::ObjectType OColumns::appendObject( const ::rtl::OUString& _rForName, cons else if ( m_pTable && !m_pTable->isNew() ) { if ( m_bAddColumn ) - xReturn = OColumns_BASE::appendObject( _rForName, descriptor ); + { + Reference< ::com::sun::star::sdb::tools::XTableAlteration> xAlterService = m_pTable->getAlterService(); + if ( xAlterService.is() ) + { + xAlterService->addColumn(m_pTable,descriptor); + xReturn = createObject( _rForName ); + } + else + xReturn = OColumns_BASE::appendObject( _rForName, descriptor ); + } else ::dbtools::throwGenericSQLException( DBA_RES( RID_STR_NO_COLUMN_ADD ), static_cast<XChild*>(static_cast<TXChild*>(this)) ); } @@ -440,7 +449,13 @@ void OColumns::dropObject(sal_Int32 _nPos,const ::rtl::OUString _sElementName) else if ( m_pTable && !m_pTable->isNew() ) { if ( m_bDropColumn ) - OColumns_BASE::dropObject(_nPos,_sElementName); + { + Reference< ::com::sun::star::sdb::tools::XTableAlteration> xAlterService = m_pTable->getAlterService(); + if ( xAlterService.is() ) + xAlterService->dropColumn(m_pTable,_sElementName); + else + OColumns_BASE::dropObject(_nPos,_sElementName); + } else ::dbtools::throwGenericSQLException( DBA_RES( RID_STR_NO_COLUMN_DROP ), static_cast<XChild*>(static_cast<TXChild*>(this)) ); } diff --git a/dbaccess/source/core/api/definitioncolumn.cxx b/dbaccess/source/core/api/definitioncolumn.cxx index 8a9f5649a7bd..63f39e13c6e7 100644 --- a/dbaccess/source/core/api/definitioncolumn.cxx +++ b/dbaccess/source/core/api/definitioncolumn.cxx @@ -189,7 +189,7 @@ rtl::OUString OTableColumn::getImplementationName( ) throw (RuntimeException) DBG_NAME( OQueryColumn ); // ------------------------------------------------------------------------- -OQueryColumn::OQueryColumn( const Reference< XPropertySet >& _rxParserColumn, const Reference< XConnection >& _rxConnection ) +OQueryColumn::OQueryColumn( const Reference< XPropertySet >& _rxParserColumn, const Reference< XConnection >& _rxConnection,const ::rtl::OUString& _sNewName ) :OTableColumnDescriptor( false /* do not act as descriptor */ ) { const sal_Int32 nPropAttr = PropertyAttribute::READONLY; @@ -207,7 +207,14 @@ OQueryColumn::OQueryColumn( const Reference< XPropertySet >& _rxParserColumn, co OSL_VERIFY( _rxParserColumn->getPropertyValue( PROPERTY_TYPE ) >>= m_nType ); OSL_VERIFY( _rxParserColumn->getPropertyValue( PROPERTY_ISAUTOINCREMENT ) >>= m_bAutoIncrement ); OSL_VERIFY( _rxParserColumn->getPropertyValue( PROPERTY_ISCURRENCY ) >>= m_bCurrency ); - OSL_VERIFY( _rxParserColumn->getPropertyValue( PROPERTY_NAME ) >>= m_sName ); + if ( _sNewName.getLength() ) + { + m_sName = _sNewName; + } + else + { + OSL_VERIFY( _rxParserColumn->getPropertyValue( PROPERTY_NAME ) >>= m_sName ); + } m_bRowVersion = sal_False; Reference< XPropertySetInfo > xPSI( _rxParserColumn->getPropertySetInfo(), UNO_SET_THROW ); diff --git a/dbaccess/source/core/api/makefile.mk b/dbaccess/source/core/api/makefile.mk index 308a9e6c7748..afd42c9914b7 100644 --- a/dbaccess/source/core/api/makefile.mk +++ b/dbaccess/source/core/api/makefile.mk @@ -70,6 +70,7 @@ SLOFILES= \ $(SLO)$/SingleSelectQueryComposer.obj \ $(SLO)$/HelperCollections.obj \ $(SLO)$/datasettings.obj \ + $(SLO)$/View.obj \ $(SLO)$/columnsettings.obj # --- Targets ---------------------------------- diff --git a/dbaccess/source/core/api/query.cxx b/dbaccess/source/core/api/query.cxx index 84c7730308c8..82b7b0525992 100644 --- a/dbaccess/source/core/api/query.cxx +++ b/dbaccess/source/core/api/query.cxx @@ -188,9 +188,10 @@ void OQuery::rebuildColumns() m_pColumnMediator = NULL; Reference<XColumnsSupplier> xColSup(m_xCommandDefinition,UNO_QUERY); + Reference< XNameAccess > xColumnDefinitions; if ( xColSup.is() ) { - Reference< XNameAccess > xColumnDefinitions = xColSup->getColumns(); + xColumnDefinitions = xColSup->getColumns(); if ( xColumnDefinitions.is() ) m_pColumnMediator = new OContainerMediator( m_pColumns, xColumnDefinitions, m_xConnection, OContainerMediator::eColumns ); } @@ -233,19 +234,29 @@ void OQuery::rebuildColumns() } Sequence< ::rtl::OUString> aNames = xColumns->getElementNames(); - const ::rtl::OUString* pBegin = aNames.getConstArray(); - const ::rtl::OUString* pEnd = pBegin + aNames.getLength(); - for ( ;pBegin != pEnd; ++pBegin) + Sequence< ::rtl::OUString> aDefintionNames; + bool bApplyDefinitionNames = false; + //if ( xColumnDefinitions.is() ) + //{ + // aDefintionNames = xColumnDefinitions->getElementNames(); + // bApplyDefinitionNames = aDefintionNames.getLength() == aNames.getLength(); + //} + + ::rtl::OUString sEmpty; + const ::rtl::OUString* pIter = aNames.getConstArray(); + const ::rtl::OUString* pEnd = pIter + aNames.getLength(); + for ( sal_Int32 i = 0;pIter != pEnd; ++pIter,++i) { - Reference<XPropertySet> xSource(xColumns->getByName( *pBegin ),UNO_QUERY); - OQueryColumn* pColumn = new OQueryColumn( xSource, m_xConnection ); + Reference<XPropertySet> xSource(xColumns->getByName( *pIter ),UNO_QUERY); + OQueryColumn* pColumn = new OQueryColumn( xSource, m_xConnection, bApplyDefinitionNames ? aDefintionNames[i] : sEmpty); Reference< XChild > xChild( *pColumn, UNO_QUERY_THROW ); xChild->setParent( *this ); - implAppendColumn( *pBegin, pColumn ); + ::rtl::OUString sNewName = bApplyDefinitionNames ? aDefintionNames[i] : *pIter; + implAppendColumn( sNewName, pColumn ); Reference< XPropertySet > xDest( *pColumn, UNO_QUERY_THROW ); if ( m_pColumnMediator.is() ) - m_pColumnMediator->notifyElementCreated( *pBegin, xDest ); + m_pColumnMediator->notifyElementCreated( sNewName, xDest ); } } catch( const SQLContext& e ) diff --git a/dbaccess/source/core/api/resultcolumn.cxx b/dbaccess/source/core/api/resultcolumn.cxx index fb418eba7b9f..02195693bba1 100644 --- a/dbaccess/source/core/api/resultcolumn.cxx +++ b/dbaccess/source/core/api/resultcolumn.cxx @@ -107,20 +107,26 @@ void OResultColumn::impl_determineIsRowVersion_nothrow() getPropertyValue( PROPERTY_TABLENAME ) >>= sTable; getPropertyValue( PROPERTY_NAME ) >>= sColumnName; - Reference< XResultSet > xVersionColumns = m_xDBMetaData->getVersionColumns( - makeAny( sCatalog ), sSchema, sTable ); - if ( xVersionColumns.is() ) // allowed to be NULL + try { - Reference< XRow > xResultRow( xVersionColumns, UNO_QUERY_THROW ); - while ( xVersionColumns->next() ) + Reference< XResultSet > xVersionColumns = m_xDBMetaData->getVersionColumns( + makeAny( sCatalog ), sSchema, sTable ); + if ( xVersionColumns.is() ) // allowed to be NULL { - if ( xResultRow->getString( 2 ) == sColumnName ) + Reference< XRow > xResultRow( xVersionColumns, UNO_QUERY_THROW ); + while ( xVersionColumns->next() ) { - m_aIsRowVersion <<= (sal_Bool)(sal_True); - break; + if ( xResultRow->getString( 2 ) == sColumnName ) + { + m_aIsRowVersion <<= (sal_Bool)(sal_True); + break; + } } } } + catch(const SQLException&) + { + } } catch( const Exception& ) { diff --git a/dbaccess/source/core/api/table.cxx b/dbaccess/source/core/api/table.cxx index d11c035f6f5d..e33098f74f4c 100644 --- a/dbaccess/source/core/api/table.cxx +++ b/dbaccess/source/core/api/table.cxx @@ -28,77 +28,33 @@ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_dbaccess.hxx" -#ifndef _DBA_CORE_TABLE_HXX_ #include "table.hxx" -#endif -#ifndef _DBACORE_DEFINITIONCOLUMN_HXX_ #include <definitioncolumn.hxx> -#endif -#ifndef DBACCESS_SHARED_DBASTRINGS_HRC #include "dbastrings.hrc" -#endif -#ifndef _DBA_CORE_RESOURCE_HXX_ #include "core_resource.hxx" -#endif -#ifndef _DBA_CORE_RESOURCE_HRC_ #include "core_resource.hrc" -#endif -#ifndef _TOOLS_DEBUG_HXX -#include <tools/debug.hxx> -#endif +#include "CIndexes.hxx" -#ifndef _CPPUHELPER_TYPEPROVIDER_HXX_ +#include <tools/debug.hxx> #include <cppuhelper/typeprovider.hxx> -#endif -#ifndef _COMPHELPER_ENUMHELPER_HXX_ #include <comphelper/enumhelper.hxx> -#endif -#ifndef _COMPHELPER_CONTAINER_HXX_ #include <comphelper/container.hxx> -#endif -#ifndef _COMPHELPER_SEQUENCE_HXX_ #include <comphelper/sequence.hxx> -#endif -#ifndef _COMPHELPER_TYPES_HXX_ #include <comphelper/types.hxx> -#endif -#ifndef _COM_SUN_STAR_UTIL_XREFRESHLISTENER_HPP_ +//#include <comphelper/extract.hxx> #include <com/sun/star/util/XRefreshListener.hpp> -#endif -#ifndef _COM_SUN_STAR_SDBC_XCONNECTION_HPP_ #include <com/sun/star/sdbc/XConnection.hpp> -#endif -#ifndef _COM_SUN_STAR_SDBC_XROW_HPP_ #include <com/sun/star/sdbc/XRow.hpp> -#endif -#ifndef _COM_SUN_STAR_SDBCX_PRIVILEGE_HPP_ #include <com/sun/star/sdbcx/Privilege.hpp> -#endif +#include <com/sun/star/sdbc/XResultSetMetaData.hpp> +#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp> + #include <connectivity/TKeys.hxx> -#ifndef DBACCESS_INDEXES_HXX_ -#include "CIndexes.hxx" -#endif -#ifndef _CONNECTIVITY_DBTOOLS_HXX_ #include <connectivity/dbtools.hxx> -#endif -#ifndef _DBHELPER_DBEXCEPTION_HXX_ #include <connectivity/dbexception.hxx> -#endif -#ifndef _COMPHELPER_EXTRACT_HXX_ -#include <comphelper/extract.hxx> -#endif -#ifndef DBACORE_SDBCORETOOLS_HXX + #include "sdbcoretools.hxx" -#endif -#ifndef _COM_SUN_STAR_SDBC_XRESULTSETMETADATA_HPP_ -#include <com/sun/star/sdbc/XResultSetMetaData.hpp> -#endif -#ifndef _COM_SUN_STAR_SDBC_XRESULTSETMETADATASUPPLIER_HPP_ -#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp> -#endif -#ifndef DBA_CONTAINERMEDIATOR_HXX #include "ContainerMediator.hxx" -#endif #include <rtl/logfile.hxx> using namespace dbaccess; @@ -149,6 +105,7 @@ ODBTable::ODBTable(connectivity::sdbcx::OCollection* _pTables :OTable_Base(_pTables,_rxConn, _rxConn->getMetaData().is() && _rxConn->getMetaData()->supportsMixedCaseQuotedIdentifiers()) ,m_nPrivileges(-1) { + DBG_CTOR(ODBTable, NULL); RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTable::ODBTable" ); } // ------------------------------------------------------------------------- @@ -308,18 +265,18 @@ void ODBTable::construct() describeProperties(aProps); if(!_nId) { - Property* pBegin = aProps.getArray(); - Property* pEnd = pBegin + aProps.getLength(); - for(;pBegin != pEnd;++pBegin) + Property* pIter = aProps.getArray(); + Property* pEnd = pIter + aProps.getLength(); + for(;pIter != pEnd;++pIter) { - if (0 == pBegin->Name.compareToAscii(PROPERTY_CATALOGNAME)) - pBegin->Attributes = PropertyAttribute::READONLY; - else if (0 == pBegin->Name.compareToAscii(PROPERTY_SCHEMANAME)) - pBegin->Attributes = PropertyAttribute::READONLY; - else if (0 == pBegin->Name.compareToAscii(PROPERTY_DESCRIPTION)) - pBegin->Attributes = PropertyAttribute::READONLY; - else if (0 == pBegin->Name.compareToAscii(PROPERTY_NAME)) - pBegin->Attributes = PropertyAttribute::READONLY; + if (0 == pIter->Name.compareToAscii(PROPERTY_CATALOGNAME)) + pIter->Attributes = PropertyAttribute::READONLY; + else if (0 == pIter->Name.compareToAscii(PROPERTY_SCHEMANAME)) + pIter->Attributes = PropertyAttribute::READONLY; + else if (0 == pIter->Name.compareToAscii(PROPERTY_DESCRIPTION)) + pIter->Attributes = PropertyAttribute::READONLY; + else if (0 == pIter->Name.compareToAscii(PROPERTY_NAME)) + pIter->Attributes = PropertyAttribute::READONLY; } } @@ -337,14 +294,11 @@ IMPLEMENT_SERVICE_INFO1(ODBTable, "com.sun.star.sdb.dbaccess.ODBTable", SERVICE_ Any SAL_CALL ODBTable::queryInterface( const Type & rType ) throw(RuntimeException) { RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTable::getInfoHelper" ); - Any aRet; - if(rType == getCppuType( (Reference<XRename>*)0)) + if(rType == getCppuType( (Reference<XRename>*)0) && !getRenameService().is() ) return Any(); - if(rType == getCppuType( (Reference<XAlterTable>*)0)) + if(rType == getCppuType( (Reference<XAlterTable>*)0) && !getAlterService().is() ) return Any(); - aRet = OTable_Base::queryInterface( rType); - - return aRet; + return OTable_Base::queryInterface( rType); } // ------------------------------------------------------------------------- Sequence< Type > SAL_CALL ODBTable::getTypes( ) throw(RuntimeException) @@ -357,12 +311,12 @@ Sequence< Type > SAL_CALL ODBTable::getTypes( ) throw(RuntimeException) ::std::vector<Type> aOwnTypes; aOwnTypes.reserve(aTypes.getLength()); - const Type* pBegin = aTypes.getConstArray(); - const Type* pEnd = pBegin + aTypes.getLength(); - for(;pBegin != pEnd ;++pBegin) + const Type* pIter = aTypes.getConstArray(); + const Type* pEnd = pIter + aTypes.getLength(); + for(;pIter != pEnd ;++pIter) { - if(*pBegin != aRenameType && *pBegin != aAlterType) - aOwnTypes.push_back(*pBegin); + if( (*pIter != aRenameType || getRenameService().is()) && (*pIter != aAlterType || getAlterService().is())) + aOwnTypes.push_back(*pIter); } Type* pTypes = aOwnTypes.empty() ? 0 : &aOwnTypes[0]; @@ -370,10 +324,17 @@ Sequence< Type > SAL_CALL ODBTable::getTypes( ) throw(RuntimeException) } // XRename, //------------------------------------------------------------------------------ -void SAL_CALL ODBTable::rename( const ::rtl::OUString& /*_rNewName*/ ) throw(SQLException, ElementExistException, RuntimeException) +void SAL_CALL ODBTable::rename( const ::rtl::OUString& _rNewName ) throw(SQLException, ElementExistException, RuntimeException) { RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTable::rename" ); - throw SQLException(DBACORE_RESSTRING(RID_STR_NO_TABLE_RENAME),*this,SQLSTATE_GENERAL,1000,Any() ); + ::osl::MutexGuard aGuard(m_aMutex); + checkDisposed(connectivity::sdbcx::OTableDescriptor_BASE::rBHelper.bDisposed); + if ( !getRenameService().is() ) + throw SQLException(DBACORE_RESSTRING(RID_STR_NO_TABLE_RENAME),*this,SQLSTATE_GENERAL,1000,Any() ); + + Reference<XPropertySet> xTable(this); + getRenameService()->rename(xTable,_rNewName); + ::connectivity::OTable_TYPEDEF::rename(_rNewName); } // XAlterTable, @@ -382,55 +343,15 @@ void SAL_CALL ODBTable::alterColumnByName( const ::rtl::OUString& _rName, const { RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTable::alterColumnByName" ); ::osl::MutexGuard aGuard(m_aMutex); - checkDisposed( - connectivity::sdbcx::OTableDescriptor_BASE::rBHelper.bDisposed); - if(m_pColumns->hasByName(_rName)) - { - ::rtl::OUString sSql = ::rtl::OUString::createFromAscii("ALTER TABLE "); - ::rtl::OUString aQuote; - Reference<XDatabaseMetaData> xMeta = getMetaData(); - if ( xMeta.is() ) - aQuote = xMeta->getIdentifierQuoteString( ); - ::rtl::OUString sComposedName; - - sComposedName = ::dbtools::composeTableName( xMeta, m_CatalogName, m_SchemaName, m_Name, sal_True, ::dbtools::eInTableDefinitions ); - if(!sComposedName.getLength()) - ::dbtools::throwFunctionSequenceException(*this); - - sSql += sComposedName; - sSql += ::rtl::OUString::createFromAscii(" ALTER "); - sSql += ::dbtools::quoteName(aQuote,_rName); - - ::rtl::OUString sNewDefaultValue,sDefaultValue; - - Reference<XPropertySet> xColumn; - m_pColumns->getByName(_rName) >>= xColumn; - if(_rxDescriptor->getPropertySetInfo()->hasPropertyByName(PROPERTY_DEFAULTVALUE)) - _rxDescriptor->getPropertyValue(PROPERTY_DEFAULTVALUE) >>= sNewDefaultValue; - if(xColumn.is() && xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_DEFAULTVALUE)) - xColumn->getPropertyValue(PROPERTY_DEFAULTVALUE) >>= sDefaultValue; - - if(sNewDefaultValue != sDefaultValue && getMetaData().is() ) - { - if(sNewDefaultValue.getLength()) - { - sSql += ::rtl::OUString::createFromAscii(" SET DEFAULT "); - sSql += sNewDefaultValue; - } - else - sSql += ::rtl::OUString::createFromAscii(" DROP DEFAULT"); - OSL_ENSURE(getMetaData()->getConnection().is(),"Connection is null!"); - Reference< XStatement > xStmt = getMetaData()->getConnection()->createStatement( ); - if(xStmt.is()) - xStmt->execute(sSql); - } - else - // not supported - throw SQLException(DBACORE_RESSTRING(RID_STR_NO_ALTER_COLUMN_DEF),*this,SQLSTATE_GENERAL,1000,Any() ); - } - else - // not supported - throw SQLException(DBACORE_RESSTRING(RID_STR_COLUMN_ALTER_BY_NAME),*this,SQLSTATE_GENERAL,1000,Any() ); + checkDisposed(connectivity::sdbcx::OTableDescriptor_BASE::rBHelper.bDisposed); + if ( !getAlterService().is() ) + throw SQLException(DBACORE_RESSTRING(RID_STR_NO_TABLE_RENAME),*this,SQLSTATE_GENERAL,1000,Any() ); + + if ( !m_pColumns->hasByName(_rName) ) + throw SQLException(DBACORE_RESSTRING(RID_STR_COLUMN_NOT_VALID),*this,SQLSTATE_GENERAL,1000,Any() ); + + Reference<XPropertySet> xTable(this); + getAlterService()->alterColumnByName(xTable,_rName,_rxDescriptor); m_pColumns->refresh(); } // ----------------------------------------------------------------------------- @@ -473,8 +394,8 @@ sdbcx::OCollection* ODBTable::createColumns(const TStringVector& _rNames) RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTable::createColumns" ); Reference<XDatabaseMetaData> xMeta = getMetaData(); OColumns* pCol = new OColumns(*this, m_aMutex, NULL, isCaseSensitive(), _rNames, this,this, - xMeta.is() && xMeta->supportsAlterTableWithAddColumn(), - xMeta.is() && xMeta->supportsAlterTableWithDropColumn()); + getAlterService().is() || (xMeta.is() && xMeta->supportsAlterTableWithAddColumn()), + getAlterService().is() || (xMeta.is() && xMeta->supportsAlterTableWithDropColumn())); static_cast<OColumnsHelper*>(pCol)->setParent(this); pCol->setParent(*this); m_pColumnMediator = new OContainerMediator( pCol, m_xColumnDefinitions, getConnection(), OContainerMediator::eColumns ); @@ -494,7 +415,3 @@ sdbcx::OCollection* ODBTable::createIndexes(const TStringVector& _rNames) return new OIndexes(this,m_aMutex,_rNames,NULL); } // ----------------------------------------------------------------------------- - - - - diff --git a/dbaccess/source/core/api/viewcontainer.cxx b/dbaccess/source/core/api/viewcontainer.cxx index 6c48d02f76e5..0fc2542bfa4a 100644 --- a/dbaccess/source/core/api/viewcontainer.cxx +++ b/dbaccess/source/core/api/viewcontainer.cxx @@ -28,74 +28,30 @@ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_dbaccess.hxx" -#ifndef _DBA_CORE_VIEWCONTAINER_HXX_ #include "viewcontainer.hxx" -#endif -#ifndef DBACCESS_SHARED_DBASTRINGS_HRC #include "dbastrings.hrc" -#endif -#ifndef _TOOLS_DEBUG_HXX +#include "core_resource.hxx" +#include "core_resource.hrc" +#include "View.hxx" + #include <tools/debug.hxx> -#endif -#ifndef _WLDCRD_HXX #include <tools/wldcrd.hxx> -#endif -#ifndef _COMPHELPER_ENUMHELPER_HXX_ #include <comphelper/enumhelper.hxx> -#endif -#ifndef _DBA_CORE_RESOURCE_HXX_ -#include "core_resource.hxx" -#endif -#ifndef _DBA_CORE_RESOURCE_HRC_ -#include "core_resource.hrc" -#endif +#include <comphelper/types.hxx> +#include <connectivity/dbtools.hxx> +#include <comphelper/extract.hxx> +#include <connectivity/dbexception.hxx> +#include <rtl/ustrbuf.hxx> -#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_ #include <com/sun/star/beans/XPropertySet.hpp> -#endif - -#ifndef _COM_SUN_STAR_SDBC_XCONNECTION_HPP_ #include <com/sun/star/sdbc/XConnection.hpp> -#endif -#ifndef _COM_SUN_STAR_SDBC_XDATABASEMETADATA_HPP_ #include <com/sun/star/sdbc/XDatabaseMetaData.hpp> -#endif -#ifndef _COM_SUN_STAR_SDBCX_XCOLUMNSSUPPLIER_HPP_ -#include <com/sun/star/sdbcx/XColumnsSupplier.hpp> -#endif -#ifndef _COM_SUN_STAR_SDBCX_XTABLESSUPPLIER_HPP_ -#include <com/sun/star/sdbcx/XTablesSupplier.hpp> -#endif -#ifndef _COM_SUN_STAR_SDBC_KEYRULE_HPP_ #include <com/sun/star/sdbc/KeyRule.hpp> -#endif -#ifndef _COM_SUN_STAR_SDBCX_KEYTYPE_HPP_ -#include <com/sun/star/sdbcx/KeyType.hpp> -#endif -#ifndef _COM_SUN_STAR_SDBC_COLUMNVALUE_HPP_ #include <com/sun/star/sdbc/ColumnValue.hpp> -#endif -#ifndef _COM_SUN_STAR_SDBC_XROW_HPP_ #include <com/sun/star/sdbc/XRow.hpp> -#endif -#ifndef _COMPHELPER_TYPES_HXX_ -#include <comphelper/types.hxx> -#endif -#ifndef _CONNECTIVITY_DBTOOLS_HXX_ -#include <connectivity/dbtools.hxx> -#endif -#ifndef _COMPHELPER_EXTRACT_HXX_ -#include <comphelper/extract.hxx> -#endif -#ifndef _DBHELPER_DBEXCEPTION_HXX_ -#include <connectivity/dbexception.hxx> -#endif -#ifndef _CONNECTIVITY_SDBCX_VIEW_HXX_ -#include <connectivity/sdbcx/VView.hxx> -#endif -#ifndef _RTL_USTRBUF_HXX_ -#include <rtl/ustrbuf.hxx> -#endif +#include <com/sun/star/sdbcx/XColumnsSupplier.hpp> +#include <com/sun/star/sdbcx/XTablesSupplier.hpp> +#include <com/sun/star/sdbcx/KeyType.hpp> using namespace dbaccess; using namespace dbtools; @@ -156,14 +112,12 @@ ObjectType OViewContainer::createObject(const ::rtl::OUString& _rName) sSchema, sTable, ::dbtools::eInDataManipulation); - return new ::connectivity::sdbcx::OView(isCaseSensitive(), - sTable, - m_xMetaData, - 0, - ::rtl::OUString(), - sSchema, - sCatalog - ); + return new View(m_xConnection, + isCaseSensitive(), + sCatalog, + sSchema, + sTable + ); } return xProp; diff --git a/dbaccess/source/core/dataaccess/ModelImpl.cxx b/dbaccess/source/core/dataaccess/ModelImpl.cxx index b77d53eb7783..516b035eb23e 100644 --- a/dbaccess/source/core/dataaccess/ModelImpl.cxx +++ b/dbaccess/source/core/dataaccess/ModelImpl.cxx @@ -38,6 +38,7 @@ #include "dbastrings.hrc" #include "ModelImpl.hxx" #include "userinformation.hxx" +#include "sdbcoretools.hxx" /** === begin UNO includes === **/ #include <com/sun/star/container/XSet.hpp> @@ -53,7 +54,6 @@ #include <comphelper/interaction.hxx> #include <comphelper/mediadescriptor.hxx> -#include <comphelper/namedvaluecollection.hxx> #include <comphelper/seqstream.hxx> #include <comphelper/sequence.hxx> #include <connectivity/dbexception.hxx> @@ -296,7 +296,7 @@ void DocumentStorageAccess::commitStorages() SAL_THROW(( IOException, RuntimeExc ++aIter ) { - m_pModelImplementation->commitStorageIfWriteable( aIter->second ); + tools::stor::commitStorageIfWriteable( aIter->second ); } } catch(const WrappedTargetException&) @@ -317,7 +317,7 @@ bool DocumentStorageAccess::commitEmbeddedStorage( bool _bPreventRootCommits ) { NamedStorages::const_iterator pos = m_aExposedStorages.find( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "database" ) ) ); if ( pos != m_aExposedStorages.end() ) - bSuccess = m_pModelImplementation->commitStorageIfWriteable( pos->second ); + bSuccess = tools::stor::commitStorageIfWriteable( pos->second ); } catch( Exception& ) { @@ -808,27 +808,41 @@ const Reference< XNumberFormatsSupplier > & ODatabaseModelImpl::getNumberFormats } return m_xNumberFormatsSupplier; } + // ----------------------------------------------------------------------------- -void ODatabaseModelImpl::attachResource( const ::rtl::OUString& _rURL, const Sequence< PropertyValue >& _rArgs ) +void ODatabaseModelImpl::setDocFileLocation( const ::rtl::OUString& i_rLoadedFrom ) { - ::comphelper::NamedValueCollection aMediaDescriptor( _rArgs ); + ENSURE_OR_THROW( i_rLoadedFrom.getLength(), "invalid URL" ); + m_sDocFileLocation = i_rLoadedFrom; +} - ::rtl::OUString sDocumentLocation( aMediaDescriptor.getOrDefault( "SalvagedFile", _rURL ) ); - if ( !sDocumentLocation.getLength() ) - // this indicates "the document is being recovered, but _rURL already is the real document URL, - // not the temporary document location" - sDocumentLocation = _rURL; +// ----------------------------------------------------------------------------- +void ODatabaseModelImpl::setResource( const ::rtl::OUString& i_rDocumentURL, const Sequence< PropertyValue >& _rArgs ) +{ + ENSURE_OR_THROW( i_rDocumentURL.getLength(), "invalid URL" ); + ::comphelper::NamedValueCollection aMediaDescriptor( _rArgs ); +#if OSL_DEBUG_LEVEL > 0 if ( aMediaDescriptor.has( "SalvagedFile" ) ) - aMediaDescriptor.remove( "SalvagedFile" ); + { + ::rtl::OUString sSalvagedFile( aMediaDescriptor.getOrDefault( "SalvagedFile", ::rtl::OUString() ) ); + // If SalvagedFile is an empty string, this indicates "the document is being recovered, but i_rDocumentURL already + // is the real document URL, not the temporary document location" + if ( !sSalvagedFile.getLength() ) + sSalvagedFile = i_rDocumentURL; + + OSL_ENSURE( sSalvagedFile == i_rDocumentURL, "ODatabaseModelImpl::setResource: inconsistency!" ); + // nowadays, setResource should only be called with the logical URL of the document + } +#endif - m_aArgs = stripLoadArguments( aMediaDescriptor ); + m_aMediaDescriptor = stripLoadArguments( aMediaDescriptor ); - switchToURL( sDocumentLocation, _rURL ); + impl_switchToLogicalURL( i_rDocumentURL ); } // ----------------------------------------------------------------------------- -Sequence< PropertyValue > ODatabaseModelImpl::stripLoadArguments( const ::comphelper::NamedValueCollection& _rArguments ) +::comphelper::NamedValueCollection ODatabaseModelImpl::stripLoadArguments( const ::comphelper::NamedValueCollection& _rArguments ) { OSL_ENSURE( !_rArguments.has( "Model" ), "ODatabaseModelImpl::stripLoadArguments: this is suspicious (1)!" ); OSL_ENSURE( !_rArguments.has( "ViewName" ), "ODatabaseModelImpl::stripLoadArguments: this is suspicious (2)!" ); @@ -836,7 +850,7 @@ Sequence< PropertyValue > ODatabaseModelImpl::stripLoadArguments( const ::comphe ::comphelper::NamedValueCollection aMutableArgs( _rArguments ); aMutableArgs.remove( "Model" ); aMutableArgs.remove( "ViewName" ); - return aMutableArgs.getPropertyValues(); + return aMutableArgs; } // ----------------------------------------------------------------------------- @@ -870,11 +884,9 @@ Reference< XStorage > ODatabaseModelImpl::getOrCreateRootStorage() if ( xStorageFactory.is() ) { Any aSource; - ::comphelper::NamedValueCollection aArgs( m_aArgs ); - - aSource = aArgs.get( "Stream" ); + aSource = m_aMediaDescriptor.get( "Stream" ); if ( !aSource.hasValue() ) - aSource = aArgs.get( "InputStream" ); + aSource = m_aMediaDescriptor.get( "InputStream" ); if ( !aSource.hasValue() && m_sDocFileLocation.getLength() ) aSource <<= m_sDocFileLocation; // TODO: shouldn't we also check URL? @@ -950,48 +962,12 @@ bool ODatabaseModelImpl::commitEmbeddedStorage( bool _bPreventRootCommits ) } // ----------------------------------------------------------------------------- -namespace -{ - bool lcl_storageIsWritable_nothrow( const Reference< XStorage >& _rxStorage ) - { - if ( !_rxStorage.is() ) - return false; - - sal_Int32 nMode = ElementModes::READ; - try - { - Reference< XPropertySet > xStorageProps( _rxStorage, UNO_QUERY_THROW ); - xStorageProps->getPropertyValue( - ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OpenMode" ) ) ) >>= nMode; - } - catch( const Exception& ) - { - DBG_UNHANDLED_EXCEPTION(); - } - return ( nMode & ElementModes::WRITE ) != 0; - } -} - -// ----------------------------------------------------------------------------- -bool ODatabaseModelImpl::commitStorageIfWriteable( const Reference< XStorage >& _rxStorage ) SAL_THROW(( IOException, WrappedTargetException, RuntimeException )) -{ - bool bSuccess = false; - Reference<XTransactedObject> xTrans( _rxStorage, UNO_QUERY ); - if ( xTrans.is() ) - { - if ( lcl_storageIsWritable_nothrow( _rxStorage ) ) - xTrans->commit(); - bSuccess = true; - } - return bSuccess; -} -// ----------------------------------------------------------------------------- bool ODatabaseModelImpl::commitStorageIfWriteable_ignoreErrors( const Reference< XStorage >& _rxStorage ) SAL_THROW(()) { bool bSuccess = false; try { - bSuccess = commitStorageIfWriteable( _rxStorage ); + bSuccess = tools::stor::commitStorageIfWriteable( _rxStorage ); } catch( const Exception& ) { @@ -1066,7 +1042,7 @@ Reference< XModel > ODatabaseModelImpl::createNewModel_deliverOwnership( bool _b // then nobody would call the doc's attachResource. So, we do it here, to ensure it's in a proper // state, fires all events, and so on. // #i105505# / 2009-10-02 / frank.schoenheit@sun.com - xModel->attachResource( xModel->getURL(), m_aArgs ); + xModel->attachResource( xModel->getURL(), m_aMediaDescriptor.getPropertyValues() ); } if ( _bInitialize ) @@ -1180,6 +1156,17 @@ const AsciiPropertyValue* ODatabaseModelImpl::getDefaultDataSourceSettings() AsciiPropertyValue( "FormsCheckRequiredFields", makeAny( (sal_Bool)sal_True ) ), AsciiPropertyValue( "EscapeDateTime", makeAny( (sal_Bool)sal_True ) ), + // known services to handle database tasks + AsciiPropertyValue( "TableAlterationServiceName", makeAny( ::rtl::OUString() ) ), + AsciiPropertyValue( "TableRenameServiceName", makeAny( ::rtl::OUString() ) ), + AsciiPropertyValue( "ViewAlterationServiceName", makeAny( ::rtl::OUString() ) ), + AsciiPropertyValue( "ViewAccessServiceName", makeAny( ::rtl::OUString() ) ), + AsciiPropertyValue( "CommandDefinitions", makeAny( ::rtl::OUString() ) ), + AsciiPropertyValue( "Forms", makeAny( ::rtl::OUString() ) ), + AsciiPropertyValue( "Reports", makeAny( ::rtl::OUString() ) ), + AsciiPropertyValue( "KeyAlterationServiceName", makeAny( ::rtl::OUString() ) ), + AsciiPropertyValue( "IndexAlterationServiceName", makeAny( ::rtl::OUString() ) ), + AsciiPropertyValue() }; return aKnownSettings; @@ -1216,9 +1203,8 @@ bool ODatabaseModelImpl::adjustMacroMode_AutoReject() // ----------------------------------------------------------------------------- bool ODatabaseModelImpl::checkMacrosOnLoading() { - ::comphelper::NamedValueCollection aArgs( m_aArgs ); Reference< XInteractionHandler > xInteraction; - xInteraction = aArgs.getOrDefault( "InteractionHandler", xInteraction ); + xInteraction = m_aMediaDescriptor.getOrDefault( "InteractionHandler", xInteraction ); return m_aMacroMode.checkMacrosOnLoading( xInteraction ); } @@ -1344,38 +1330,41 @@ Reference< XStorage > ODatabaseModelImpl::impl_switchToStorage_throw( const Refe lcl_rebaseScriptStorage_throw( m_xBasicLibraries, m_xDocumentStorage.getTyped() ); lcl_rebaseScriptStorage_throw( m_xDialogLibraries, m_xDocumentStorage.getTyped() ); - m_bReadOnly = !lcl_storageIsWritable_nothrow( m_xDocumentStorage.getTyped() ); + m_bReadOnly = !tools::stor::storageIsWritable_nothrow( m_xDocumentStorage.getTyped() ); // TODO: our data source, if it exists, must broadcast the change of its ReadOnly property return m_xDocumentStorage.getTyped(); } // ----------------------------------------------------------------------------- -void ODatabaseModelImpl::switchToURL( const ::rtl::OUString& _rDocumentLocation, const ::rtl::OUString& _rDocumentURL ) +void ODatabaseModelImpl::impl_switchToLogicalURL( const ::rtl::OUString& i_rDocumentURL ) { - // register at the database context, or change registration - const bool bURLChanged = ( _rDocumentURL != m_sDocumentURL ); + if ( i_rDocumentURL == m_sDocumentURL ) + return; + const ::rtl::OUString sOldURL( m_sDocumentURL ); - if ( bURLChanged ) + // update our name, if necessary + if ( ( m_sName == m_sDocumentURL ) // our name is our old URL + || ( !m_sName.getLength() ) // we do not have a name, yet (i.e. are not registered at the database context) + ) { - if ( ( m_sName == m_sDocumentURL ) // our name is our old URL - || ( !m_sName.getLength() ) // we do not have a name, yet (i.e. are not registered at the database context) - ) + INetURLObject aURL( i_rDocumentURL ); + if ( aURL.GetProtocol() != INET_PROT_NOT_VALID ) { - INetURLObject aURL( _rDocumentURL ); - if ( aURL.GetProtocol() != INET_PROT_NOT_VALID ) - { - m_sName = _rDocumentURL; - // TODO: our data source must broadcast the change of the Name property - } + m_sName = i_rDocumentURL; + // TODO: our data source must broadcast the change of the Name property } } - // remember both - m_sDocFileLocation = _rDocumentLocation.getLength() ? _rDocumentLocation : _rDocumentURL; - m_sDocumentURL = _rDocumentURL; + // remember URL + m_sDocumentURL = i_rDocumentURL; - if ( bURLChanged && m_pDBContext ) + // update our location, if necessary + if ( m_sDocFileLocation.getLength() == 0 ) + m_sDocFileLocation = m_sDocumentURL; + + // register at the database context, or change registration + if ( m_pDBContext ) { if ( sOldURL.getLength() ) m_pDBContext->databaseDocumentURLChange( sOldURL, m_sDocumentURL ); @@ -1396,8 +1385,7 @@ sal_Int16 ODatabaseModelImpl::getCurrentMacroExecMode() const sal_Int16 nCurrentMode = MacroExecMode::NEVER_EXECUTE; try { - ::comphelper::NamedValueCollection aArgs( m_aArgs ); - nCurrentMode = aArgs.getOrDefault( "MacroExecutionMode", nCurrentMode ); + nCurrentMode = m_aMediaDescriptor.getOrDefault( "MacroExecutionMode", nCurrentMode ); } catch( const Exception& ) { @@ -1409,28 +1397,20 @@ sal_Int16 ODatabaseModelImpl::getCurrentMacroExecMode() const // ----------------------------------------------------------------------------- sal_Bool ODatabaseModelImpl::setCurrentMacroExecMode( sal_uInt16 nMacroMode ) { - try - { - ::comphelper::NamedValueCollection aArgs( m_aArgs ); - aArgs.put( "MacroExecutionMode", nMacroMode ); - aArgs >>= m_aArgs; - return sal_True; - } - catch( const Exception& ) - { - DBG_UNHANDLED_EXCEPTION(); - } - - return sal_False; + m_aMediaDescriptor.put( "MacroExecutionMode", nMacroMode ); + return sal_True; } // ----------------------------------------------------------------------------- ::rtl::OUString ODatabaseModelImpl::getDocumentLocation() const { - // don't return getURL() (or m_sDocumentURL, which is the same). In case we were recovered - // after a previous crash of OOo, m_sDocFileLocation points to the file which were loaded from, - // and this is the one we need for security checks. - return getDocFileLocation(); + return getURL(); + // formerly, we returned getDocFileLocation here, which is the location of the file from which we + // recovered the "real" document. + // However, during CWS autorecovery evolving, we clarified (with MAV/MT) the role of XModel::getURL and + // XStorable::getLocation. In this course, we agreed that for a macro security check, the *document URL* + // (not the recovery file URL) is to be used: The recovery file lies in the backup folder, and by definition, + // this folder is considered to be secure. So, the document URL needs to be used to decide about the security. } // ----------------------------------------------------------------------------- diff --git a/dbaccess/source/core/dataaccess/ModelImpl.hxx b/dbaccess/source/core/dataaccess/ModelImpl.hxx index 3b51e85d1c1c..f83b2230c2b4 100644 --- a/dbaccess/source/core/dataaccess/ModelImpl.hxx +++ b/dbaccess/source/core/dataaccess/ModelImpl.hxx @@ -70,6 +70,7 @@ /** === end UNO includes === **/ #include <comphelper/broadcasthelper.hxx> +#include <comphelper/namedvaluecollection.hxx> #include <comphelper/proparrhlp.hxx> #include <comphelper/sharedmutex.hxx> #include <connectivity/CommonTools.hxx> @@ -207,7 +208,7 @@ private: ODatabaseContext* m_pDBContext; DocumentEventsData m_aDocumentEvents; - ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > m_aArgs; + ::comphelper::NamedValueCollection m_aMediaDescriptor; /// the URL the document was loaded from ::rtl::OUString m_sDocFileLocation; @@ -318,14 +319,18 @@ public: DocumentEventsData& getDocumentEvents() { return m_aDocumentEvents; } - const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& - getResource() const { return m_aArgs; } + const ::comphelper::NamedValueCollection& + getMediaDescriptor() const { return m_aMediaDescriptor; } - void attachResource( + void setResource( const ::rtl::OUString& _rURL, - const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& _rArgs ); + const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& _rArgs + ); + void setDocFileLocation( + const ::rtl::OUString& i_rLoadedFrom + ); - static ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > + static ::comphelper::NamedValueCollection stripLoadArguments( const ::comphelper::NamedValueCollection& _rArguments ); // other stuff @@ -341,16 +346,6 @@ public: /// commits our storage void commitRootStorage(); - /// commits a given storage if it's not readonly - static bool commitStorageIfWriteable( - const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& _rxStorage - ) - SAL_THROW(( - ::com::sun::star::io::IOException, - ::com::sun::star::lang::WrappedTargetException, - ::com::sun::star::uno::RuntimeException - )); - /// commits a given storage if it's not readonly, ignoring (but asserting) all errors static bool commitStorageIfWriteable_ignoreErrors( const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& _rxStorage @@ -488,19 +483,6 @@ public: const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& _rxNewRootStorage ); - /** switches to the given document location/URL - - The document location is the URL of the file from which the document has been loaded. - The document URL is the "intended location" of the document. It differs from the location - if and only if the document was loaded as part of a document recovery process. In this case, - the location points to some temporary file, but the URL is the URL of the file which has been - just recovered. The next store operation would operate on the URL, not the location. - */ - void switchToURL( - const ::rtl::OUString& _rDocumentLocation, - const ::rtl::OUString& _rDocumentURL - ); - /** returns the macro mode imposed by an external instance, which passed it to attachResource */ sal_Int16 getImposedMacroExecMode() const @@ -536,6 +518,14 @@ private: void impl_construct_nothrow(); ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage > impl_switchToStorage_throw( const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& _rxNewRootStorage ); + + /** switches to the given document URL, which denotes the logical URL of the document, not necessariy the + URL where the doc was loaded/recovered from + */ + void impl_switchToLogicalURL( + const ::rtl::OUString& i_rDocumentURL + ); + }; /** a small base class for UNO components whose functionality depends on a ODatabaseModelImpl diff --git a/dbaccess/source/core/dataaccess/connection.cxx b/dbaccess/source/core/dataaccess/connection.cxx index 257f8fc6477d..f543e2665a7e 100644 --- a/dbaccess/source/core/dataaccess/connection.cxx +++ b/dbaccess/source/core/dataaccess/connection.cxx @@ -39,6 +39,7 @@ #include "ContainerMediator.hxx" #include "SingleSelectQueryComposer.hxx" #include "querycomposer.hxx" +#include "sdbcoretools.hxx" /** === begin UNO includes === **/ #include <com/sun/star/sdb/CommandType.hpp> @@ -74,6 +75,10 @@ using namespace ::comphelper; using namespace ::cppu; using namespace ::dbtools; +using ::com::sun::star::sdb::tools::XTableName; +using ::com::sun::star::sdb::tools::XObjectNames; +using ::com::sun::star::sdb::tools::XDataSourceMetaData; + //........................................................................ namespace dbaccess { @@ -614,7 +619,7 @@ void OConnection::refresh(const Reference< XNameAccess >& _rToBeRefreshed) RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::refresh" ); if ( _rToBeRefreshed == Reference< XNameAccess >(m_pTables) ) { - if (!m_pTables->isInitialized()) + if (m_pTables && !m_pTables->isInitialized()) { impl_fillTableFilter(); // check if our "master connection" can supply tables @@ -632,7 +637,7 @@ void OConnection::refresh(const Reference< XNameAccess >& _rToBeRefreshed) } else if ( _rToBeRefreshed == Reference< XNameAccess >(m_pViews) ) { - if (!m_pViews->isInitialized()) + if (m_pViews && !m_pViews->isInitialized()) { impl_fillTableFilter(); // check if our "master connection" can supply tables @@ -726,6 +731,21 @@ Reference< XInterface > SAL_CALL OConnection::createInstance( const ::rtl::OUStr xRet = new OSingleSelectQueryComposer( getTables(),this, m_aContext ); m_aComposers.push_back(WeakReferenceHelper(xRet)); } + else + { + if ( _sServiceSpecifier.getLength() ) + { + TSupportServices::iterator aFind = m_aSupportServices.find(_sServiceSpecifier); + if ( aFind == m_aSupportServices.end() ) + { + Sequence<Any> aArgs(1); + Reference<XConnection> xMy(this); + aArgs[0] <<= NamedValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ActiveConnection")),makeAny(xMy)); + aFind = m_aSupportServices.insert(TSupportServices::value_type(_sServiceSpecifier,m_aContext.createComponentWithArguments(_sServiceSpecifier,aArgs))).first; + } + return aFind->second; + } + } return Reference< XInterface >(xRet,UNO_QUERY); } // ----------------------------------------------------------------------------- @@ -795,7 +815,7 @@ void OConnection::impl_loadConnectionTools_throw() } // ----------------------------------------------------------------------------- -Reference< tools::XTableName > SAL_CALL OConnection::createTableName( ) throw (RuntimeException) +Reference< XTableName > SAL_CALL OConnection::createTableName( ) throw (RuntimeException) { RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::createTableName" ); MutexGuard aGuard(m_aMutex); @@ -806,7 +826,7 @@ Reference< tools::XTableName > SAL_CALL OConnection::createTableName( ) throw ( } // ----------------------------------------------------------------------------- -Reference< tools::XObjectNames > SAL_CALL OConnection::getObjectNames( ) throw (RuntimeException) +Reference< XObjectNames > SAL_CALL OConnection::getObjectNames( ) throw (RuntimeException) { RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getObjectNames" ); MutexGuard aGuard(m_aMutex); @@ -817,7 +837,7 @@ Reference< tools::XObjectNames > SAL_CALL OConnection::getObjectNames( ) throw } // ----------------------------------------------------------------------------- -Reference< tools::XDataSourceMetaData > SAL_CALL OConnection::getDataSourceMetaData( ) throw (RuntimeException) +Reference< XDataSourceMetaData > SAL_CALL OConnection::getDataSourceMetaData( ) throw (RuntimeException) { RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getDataSourceMetaData" ); MutexGuard aGuard(m_aMutex); diff --git a/dbaccess/source/core/dataaccess/connection.hxx b/dbaccess/source/core/dataaccess/connection.hxx index e4eace3db14c..eb80cc2fc7db 100644 --- a/dbaccess/source/core/dataaccess/connection.hxx +++ b/dbaccess/source/core/dataaccess/connection.hxx @@ -27,62 +27,25 @@ #ifndef _DBA_CORE_CONNECTION_HXX_ #define _DBA_CORE_CONNECTION_HXX_ -#ifndef _DBASHARED_APITOOLS_HXX_ #include "apitools.hxx" -#endif -#ifndef _DBA_CORE_QUERYCONTAINER_HXX_ #include "querycontainer.hxx" -#endif -#ifndef _DBA_CORE_TABLECONTAINER_HXX_ #include "tablecontainer.hxx" -#endif -#ifndef _DBA_CORE_VIEWCONTAINER_HXX_ #include "viewcontainer.hxx" -#endif -#ifndef DBA_CORE_REFRESHLISTENER_HXX #include "RefreshListener.hxx" -#endif -#ifndef DBTOOLS_WARNINGSCONTAINER_HXX -#include <connectivity/warningscontainer.hxx> -#endif /** === begin UNO includes === **/ -#ifndef _COM_SUN_STAR_CONTAINER_XCHILD_HPP_ #include <com/sun/star/container/XChild.hpp> -#endif -#ifndef _COM_SUN_STAR_LANG_DISPOSEDEXCEPTION_HPP_ #include <com/sun/star/lang/DisposedException.hpp> -#endif -#ifndef _COM_SUN_STAR_SDB_XSQLQUERYCOMPOSERFACTORY_HPP_ #include <com/sun/star/sdb/XSQLQueryComposerFactory.hpp> -#endif -#ifndef _COM_SUN_STAR_SDB_XCOMMANDPREPARATION_HPP_ #include <com/sun/star/sdb/XCommandPreparation.hpp> -#endif -#ifndef _COM_SUN_STAR_SDBCX_XTABLESSUPPLIER_HPP_ #include <com/sun/star/sdbcx/XTablesSupplier.hpp> -#endif -#ifndef _COM_SUN_STAR_SDBCX_XVIEWSSUPPLIER_HPP_ #include <com/sun/star/sdbcx/XViewsSupplier.hpp> -#endif -#ifndef _COM_SUN_STAR_SDBCX_XUSERSSUPPLIER_HPP_ #include <com/sun/star/sdbcx/XUsersSupplier.hpp> -#endif -#ifndef _COM_SUN_STAR_SDBCX_XGROUPSSUPPLIER_HPP_ #include <com/sun/star/sdbcx/XGroupsSupplier.hpp> -#endif -#ifndef _COM_SUN_STAR_SDB_XQUERIESSUPPLIER_HPP_ #include <com/sun/star/sdb/XQueriesSupplier.hpp> -#endif -#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_ #include <com/sun/star/lang/XMultiServiceFactory.hpp> -#endif -#ifndef _COM_SUN_STAR_SDB_TOOLS_XCONNECTIONTOOLS_HPP_ #include <com/sun/star/sdb/tools/XConnectionTools.hpp> -#endif -#ifndef _COM_SUN_STAR_SDB_APPLICATION_XTABLEUIPROVIDER_HPP_ #include <com/sun/star/sdb/application/XTableUIProvider.hpp> -#endif /** === end UNO includes === **/ #if ! defined(INCLUDED_COMPHELPER_IMPLBASE_VAR_HXX_14) @@ -90,14 +53,10 @@ #define COMPHELPER_IMPLBASE_INTERFACE_NUMBER 14 #include <comphelper/implbase_var.hxx> #endif - -#ifndef COMPHELPER_COMPONENTCONTEXT_HXX #include <comphelper/componentcontext.hxx> -#endif - -#ifndef _CONNECTIVITY_CONNECTIONWRAPPER_HXX_ +#include <comphelper/stl_types.hxx> #include <connectivity/ConnectionWrapper.hxx> -#endif +#include <connectivity/warningscontainer.hxx> //........................................................................ namespace dbaccess @@ -148,6 +107,11 @@ protected: ::com::sun::star::uno::Reference< ::com::sun::star::sdb::tools::XConnectionTools > m_xConnectionTools; ::com::sun::star::uno::Reference< ::com::sun::star::sdb::application::XTableUIProvider > m_xTableUIProvider; + // defines the helper services for example to query the command of a view + // @ see com.sun.star.sdb.tools.XViewAccess + DECLARE_STL_USTRINGACCESS_MAP( ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface>, TSupportServices); + TSupportServices m_aSupportServices; + OTableContainer* m_pTables; OViewContainer* m_pViews; diff --git a/dbaccess/source/core/dataaccess/databasecontext.cxx b/dbaccess/source/core/dataaccess/databasecontext.cxx index 4d0fbd7ff480..8ee57b538365 100644 --- a/dbaccess/source/core/dataaccess/databasecontext.cxx +++ b/dbaccess/source/core/dataaccess/databasecontext.cxx @@ -385,7 +385,7 @@ Reference< XInterface > ODatabaseContext::loadObjectFromURL(const ::rtl::OUStrin ::comphelper::NamedValueCollection aArgs; aArgs.put( "URL", _sURL ); aArgs.put( "MacroExecutionMode", MacroExecMode::USE_CONFIG ); - aArgs.put( "InteractionHandler", m_aContext.createComponent( "com.sun.star.sdb.InteractionHandler" ) ); + aArgs.put( "InteractionHandler", m_aContext.createComponent( "com.sun.star.task.InteractionHandler" ) ); Sequence< PropertyValue > aResource( aArgs.getPropertyValues() ); xLoad->load( aResource ); diff --git a/dbaccess/source/core/dataaccess/databasedocument.cxx b/dbaccess/source/core/dataaccess/databasedocument.cxx index c04097254886..125c54121628 100644 --- a/dbaccess/source/core/dataaccess/databasedocument.cxx +++ b/dbaccess/source/core/dataaccess/databasedocument.cxx @@ -38,6 +38,7 @@ #include "databasecontext.hxx" #include "documentcontainer.hxx" #include "sdbcoretools.hxx" +#include "recovery/dbdocrecovery.hxx" /** === begin UNO includes === **/ #include <com/sun/star/beans/Optional.hpp> @@ -60,6 +61,8 @@ #include <com/sun/star/ui/XUIConfigurationStorage.hpp> #include <com/sun/star/view/XSelectionSupplier.hpp> #include <com/sun/star/xml/sax/XDocumentHandler.hpp> +#include <com/sun/star/ucb/XContent.hpp> +#include <com/sun/star/sdb/application/XDatabaseDocumentUI.hpp> /** === end UNO includes === **/ #include <comphelper/documentconstants.hxx> @@ -71,6 +74,11 @@ #include <comphelper/numberedcollection.hxx> #include <comphelper/property.hxx> #include <comphelper/storagehelper.hxx> +#include <comphelper/genericpropertyset.hxx> +#include <comphelper/property.hxx> + +#include <connectivity/dbtools.hxx> + #include <cppuhelper/exc_hlp.hxx> #include <framework/titlehelper.hxx> #include <unotools/saveopt.hxx> @@ -110,6 +118,8 @@ using namespace ::cppu; using namespace ::osl; using ::com::sun::star::awt::XWindow; +using ::com::sun::star::ucb::XContent; +using ::com::sun::star::sdb::application::XDatabaseDocumentUI; //........................................................................ namespace dbaccess @@ -132,7 +142,7 @@ bool ViewMonitor::onControllerConnected( const Reference< XController >& _rxCont } //-------------------------------------------------------------------------- -void ViewMonitor::onSetCurrentController( const Reference< XController >& _rxController ) +bool ViewMonitor::onSetCurrentController( const Reference< XController >& _rxController ) { // we interpret this as "loading the document (including UI) is finished", // if and only if this is the controller which was last connected, and it was the @@ -142,6 +152,8 @@ void ViewMonitor::onSetCurrentController( const Reference< XController >& _rxCon // notify the respective events if ( bLoadFinished ) m_rEventNotifier.notifyDocumentEventAsync( m_bIsNewDocument ? "OnNew" : "OnLoad" ); + + return bLoadFinished; } //============================================================ @@ -168,6 +180,7 @@ ODatabaseDocument::ODatabaseDocument(const ::rtl::Reference<ODatabaseModelImpl>& ,m_eInitState( NotInitialized ) ,m_bClosing( false ) ,m_bAllowDocumentScripting( false ) + ,m_bHasBeenRecovered( false ) { DBG_CTOR(ODatabaseDocument,NULL); OSL_TRACE( "DD: ctor: %p: %p", this, m_pImpl.get() ); @@ -372,15 +385,15 @@ namespace } // ----------------------------------------------------------------------------- - static Sequence< PropertyValue > lcl_appendFileNameToDescriptor( const Sequence< PropertyValue >& _rDescriptor, const ::rtl::OUString _rURL ) + static Sequence< PropertyValue > lcl_appendFileNameToDescriptor( const ::comphelper::NamedValueCollection& _rDescriptor, const ::rtl::OUString _rURL ) { - ::comphelper::NamedValueCollection aMediaDescriptor( _rDescriptor ); + ::comphelper::NamedValueCollection aMutableDescriptor( _rDescriptor ); if ( _rURL.getLength() ) { - aMediaDescriptor.put( "FileName", _rURL ); - aMediaDescriptor.put( "URL", _rURL ); + aMutableDescriptor.put( "FileName", _rURL ); + aMutableDescriptor.put( "URL", _rURL ); } - return aMediaDescriptor.getPropertyValues(); + return aMutableDescriptor.getPropertyValues(); } } @@ -422,9 +435,9 @@ void ODatabaseDocument::impl_reset_nothrow() void ODatabaseDocument::impl_import_nolck_throw( const ::comphelper::ComponentContext _rContext, const Reference< XInterface >& _rxTargetComponent, const ::comphelper::NamedValueCollection& _rResource ) { - Sequence< Any > aFilterArgs; + Sequence< Any > aFilterCreationArgs; Reference< XStatusIndicator > xStatusIndicator; - lcl_extractAndStartStatusIndicator( _rResource, xStatusIndicator, aFilterArgs ); + lcl_extractAndStartStatusIndicator( _rResource, xStatusIndicator, aFilterCreationArgs ); /** property map for import info set */ comphelper::PropertyMapEntry aExportInfoMap[] = @@ -437,19 +450,20 @@ void ODatabaseDocument::impl_import_nolck_throw( const ::comphelper::ComponentCo xInfoSet->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("BaseURI")), uno::makeAny(_rResource.getOrDefault("URL",::rtl::OUString()))); xInfoSet->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("StreamName")), uno::makeAny(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("content.xml")))); - const sal_Int32 nCount = aFilterArgs.getLength(); - aFilterArgs.realloc(nCount + 1); - aFilterArgs[nCount] <<= xInfoSet; + const sal_Int32 nCount = aFilterCreationArgs.getLength(); + aFilterCreationArgs.realloc(nCount + 1); + aFilterCreationArgs[nCount] <<= xInfoSet; Reference< XImporter > xImporter( - _rContext.createComponentWithArguments( "com.sun.star.comp.sdb.DBFilter", aFilterArgs ), + _rContext.createComponentWithArguments( "com.sun.star.comp.sdb.DBFilter", aFilterCreationArgs ), UNO_QUERY_THROW ); Reference< XComponent > xComponent( _rxTargetComponent, UNO_QUERY_THROW ); xImporter->setTargetDocument( xComponent ); Reference< XFilter > xFilter( xImporter, UNO_QUERY_THROW ); - xFilter->filter( ODatabaseModelImpl::stripLoadArguments( _rResource ) ); + Sequence< PropertyValue > aFilterArgs( ODatabaseModelImpl::stripLoadArguments( _rResource ).getPropertyValues() ); + xFilter->filter( aFilterArgs ); if ( xStatusIndicator.is() ) xStatusIndicator->end(); @@ -537,14 +551,176 @@ void SAL_CALL ODatabaseDocument::load( const Sequence< PropertyValue >& _Argumen } // ----------------------------------------------------------------------------- +namespace +{ + // ......................................................................... + bool lcl_hasAnyModifiedSubComponent_throw( const Reference< XController >& i_rController ) + { + Reference< XDatabaseDocumentUI > xDatabaseUI( i_rController, UNO_QUERY_THROW ); + + Sequence< Reference< XComponent > > aComponents( xDatabaseUI->getSubComponents() ); + const Reference< XComponent >* component = aComponents.getConstArray(); + const Reference< XComponent >* componentsEnd = aComponents.getConstArray() + aComponents.getLength(); + + bool isAnyModified = false; + for ( ; component != componentsEnd; ++component ) + { + Reference< XModifiable > xModify( *component, UNO_QUERY ); + if ( xModify.is() ) + { + isAnyModified = xModify->isModified(); + continue; + } + + // TODO: clarify: anything else to care for? Both the sub componbents with and without model + // should support the XModifiable interface, so I think nothing more is needed here. + OSL_ENSURE( false, "lcl_hasAnyModifiedSubComponent_throw: anything left to do here?" ); + } + + return isAnyModified; + } +} + +// ----------------------------------------------------------------------------- +::sal_Bool SAL_CALL ODatabaseDocument::wasModifiedSinceLastSave() throw ( RuntimeException ) +{ + DocumentGuard aGuard( *this ); + + // The implementation here is somewhat sloppy, in that it returns whether *any* part of the whole + // database document, including opened sub components, is modified. This is more than what is requested: + // We need to return <TRUE/> if the doc itself, or any of the opened sub components, has been modified + // since the last call to any of the save* methods, or since the document has been loaded/created. + // However, the API definition explicitly allows to be that sloppy ... + + if ( isModified() ) + return sal_True; + + // auto recovery is an "UI feature", it is to restore the UI the user knows. Thus, + // we ask our connected controllers, not simply our existing form/report definitions. + // (There is some information which even cannot be obtained without asking the controller. + // For instance, newly created, but not yet saved, forms/reports are acessible via the + // controller only, but not via the model.) + + try + { + for ( Controllers::const_iterator ctrl = m_aControllers.begin(); + ctrl != m_aControllers.end(); + ++ctrl + ) + { + if ( lcl_hasAnyModifiedSubComponent_throw( *ctrl ) ) + return sal_True; + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + return sal_False; +} + +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseDocument::storeToRecoveryFile( const ::rtl::OUString& i_TargetLocation, const Sequence< PropertyValue >& i_MediaDescriptor ) throw ( RuntimeException, IOException, WrappedTargetException ) +{ + DocumentGuard aGuard( *this ); + ModifyLock aLock( *this ); + + try + { + // create a storage for the target location + Reference< XStorage > xTargetStorage( impl_createStorageFor_throw( i_TargetLocation ) ); + + // first store the document as a whole into this storage + impl_storeToStorage_throw( xTargetStorage, i_MediaDescriptor, aGuard ); + + // save the sub components which need saving + DatabaseDocumentRecovery aDocRecovery( m_pImpl->m_aContext); + aDocRecovery.saveModifiedSubComponents( xTargetStorage, m_aControllers ); + + // commit the root storage + tools::stor::commitStorageIfWriteable( xTargetStorage ); + } + catch( const Exception& ) + { + Any aError = ::cppu::getCaughtException(); + if ( aError.isExtractableTo( ::cppu::UnoType< IOException >::get() ) + || aError.isExtractableTo( ::cppu::UnoType< RuntimeException >::get() ) + || aError.isExtractableTo( ::cppu::UnoType< WrappedTargetException >::get() ) + ) + { + // allowed to leave + throw; + } + + throw WrappedTargetException( ::rtl::OUString(), *this, aError ); + } +} + +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseDocument::recoverFromFile( const ::rtl::OUString& i_SourceLocation, const ::rtl::OUString& i_SalvagedFile, const Sequence< PropertyValue >& i_MediaDescriptor ) throw ( RuntimeException, IOException, WrappedTargetException ) +{ + DocumentGuard aGuard( *this, DocumentGuard::InitMethod ); + + if ( i_SourceLocation.getLength() == 0 ) + throw IllegalArgumentException( ::rtl::OUString(), *this, 1 ); + + try + { + // load the document itself, by simply delegating to our "load" method + + // our load implementation expects the SalvagedFile and URL to be in the media descriptor + ::comphelper::NamedValueCollection aMediaDescriptor( i_MediaDescriptor ); + aMediaDescriptor.put( "SalvagedFile", i_SalvagedFile ); + aMediaDescriptor.put( "URL", i_SourceLocation ); + + aGuard.clear(); // (load has an own guarding scheme) + load( aMediaDescriptor.getPropertyValues() ); + + // Without a controller, we are unable to recover the sub components, as they're always tied to a controller. + // So, everything else is done when the first controller is connected. + m_bHasBeenRecovered = true; + + // tell the impl that we've been loaded from the given location + m_pImpl->setDocFileLocation( i_SourceLocation ); + + // by definition (of XDocumentRecovery), we're responsible for delivering a fully-initialized document, + // which includes an attachResource call. + const ::rtl::OUString sLogicalDocumentURL( i_SalvagedFile.getLength() ? i_SalvagedFile : i_SourceLocation ); + impl_attachResource( sLogicalDocumentURL, aMediaDescriptor.getPropertyValues(), aGuard ); + // <- SYNCHRONIZED + } + catch( const Exception& ) + { + Any aError = ::cppu::getCaughtException(); + if ( aError.isExtractableTo( ::cppu::UnoType< IOException >::get() ) + || aError.isExtractableTo( ::cppu::UnoType< RuntimeException >::get() ) + || aError.isExtractableTo( ::cppu::UnoType< WrappedTargetException >::get() ) + ) + { + // allowed to leave + throw; + } + + throw WrappedTargetException( ::rtl::OUString(), *this, aError ); + } +} + +// ----------------------------------------------------------------------------- // XModel sal_Bool SAL_CALL ODatabaseDocument::attachResource( const ::rtl::OUString& _rURL, const Sequence< PropertyValue >& _rArguments ) throw (RuntimeException) { DocumentGuard aGuard( *this, DocumentGuard::MethodUsedDuringInit ); + return impl_attachResource( _rURL, _rArguments, aGuard ); +} - if ( ( _rURL == getURL() ) - && ( _rArguments.getLength() == 1 ) - && ( _rArguments[0].Name.compareToAscii( "BreakMacroSignature" ) == 0 ) +// ----------------------------------------------------------------------------- +sal_Bool ODatabaseDocument::impl_attachResource( const ::rtl::OUString& i_rLogicalDocumentURL, + const Sequence< PropertyValue >& i_rMediaDescriptor, DocumentGuard& _rDocGuard ) +{ + if ( ( i_rLogicalDocumentURL == getURL() ) + && ( i_rMediaDescriptor.getLength() == 1 ) + && ( i_rMediaDescriptor[0].Name.compareToAscii( "BreakMacroSignature" ) == 0 ) ) { // this is a BAD hack of the Basic importer code ... there should be a dedicated API for this, @@ -553,7 +729,14 @@ sal_Bool SAL_CALL ODatabaseDocument::attachResource( const ::rtl::OUString& _rUR // (we do not support macro signatures, so we can ignore this call) } - m_pImpl->attachResource( _rURL, _rArguments ); + // if no URL has been provided, the caller was lazy enough to not call our getURL - which is not allowed anymore, + // now since getURL and getLocation both return the same, so calling one of those should be simple. + ::rtl::OUString sDocumentURL( i_rLogicalDocumentURL ); + OSL_ENSURE( sDocumentURL.getLength(), "ODatabaseDocument::impl_attachResource: invalid URL!" ); + if ( !sDocumentURL.getLength() ) + sDocumentURL = getURL(); + + m_pImpl->setResource( sDocumentURL, i_rMediaDescriptor ); if ( impl_isInitializing() ) { // this means we've just been loaded, and this is the attachResource call which follows @@ -565,7 +748,7 @@ sal_Bool SAL_CALL ODatabaseDocument::attachResource( const ::rtl::OUString& _rUR // should know this before anybody actually uses the object. m_bAllowDocumentScripting = ( m_pImpl->determineEmbeddedMacros() != ODatabaseModelImpl::eSubDocumentMacros ); - aGuard.clear(); + _rDocGuard.clear(); // <- SYNCHRONIZED m_aEventNotifier.notifyDocumentEvent( "OnLoadFinished" ); } @@ -584,7 +767,7 @@ sal_Bool SAL_CALL ODatabaseDocument::attachResource( const ::rtl::OUString& _rUR Sequence< PropertyValue > SAL_CALL ODatabaseDocument::getArgs( ) throw (RuntimeException) { DocumentGuard aGuard( *this, DocumentGuard::MethodWithoutInit ); - return m_pImpl->getResource(); + return m_pImpl->getMediaDescriptor().getPropertyValues(); } // ----------------------------------------------------------------------------- @@ -592,6 +775,16 @@ void SAL_CALL ODatabaseDocument::connectController( const Reference< XController { DocumentGuard aGuard( *this ); +#if OSL_DEBUG_LEVEL > 0 + for ( Controllers::const_iterator controller = m_aControllers.begin(); + controller != m_aControllers.end(); + ++controller + ) + { + OSL_ENSURE( *controller != _xController, "ODatabaseDocument::connectController: this controller is already connected!" ); + } +#endif + m_aControllers.push_back( _xController ); m_aEventNotifier.notifyDocumentEventAsync( "OnViewCreated", Reference< XController2 >( _xController, UNO_QUERY ) ); @@ -688,8 +881,29 @@ void SAL_CALL ODatabaseDocument::setCurrentController( const Reference< XControl m_xCurrentController = _xController; - m_aViewMonitor.onSetCurrentController( _xController ); + if ( !m_aViewMonitor.onSetCurrentController( _xController ) ) + return; + + // check if there are sub components to recover from our document storage + bool bAttemptRecovery = m_bHasBeenRecovered; + if ( !bAttemptRecovery && m_pImpl->getMediaDescriptor().has( "ForceRecovery" ) ) + // do not use getOrDefault, it will throw for invalid types, which is not desired here + m_pImpl->getMediaDescriptor().get( "ForceRecovery" ) >>= bAttemptRecovery; + + if ( !bAttemptRecovery ) + return; + + try + { + DatabaseDocumentRecovery aDocRecovery( m_pImpl->m_aContext ); + aDocRecovery.recoverSubDocuments( m_pImpl->getRootStorage(), _xController ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } } + // ----------------------------------------------------------------------------- Reference< XInterface > SAL_CALL ODatabaseDocument::getCurrentSelection( ) throw (RuntimeException) { @@ -714,6 +928,8 @@ sal_Bool SAL_CALL ODatabaseDocument::hasLocation( ) throw (RuntimeException) { DocumentGuard aGuard( *this, DocumentGuard::MethodWithoutInit ); return m_pImpl->getURL(); + // both XStorable::getLocation and XModel::getURL have to return the URL of the document, *not* + // the location of the file which the docunment was possibly recovered from (which would be getDocFileLocation) } // ----------------------------------------------------------------------------- sal_Bool SAL_CALL ODatabaseDocument::isReadonly( ) throw (RuntimeException) @@ -726,15 +942,53 @@ void SAL_CALL ODatabaseDocument::store( ) throw (IOException, RuntimeException) { DocumentGuard aGuard( *this ); - if ( m_pImpl->getDocFileLocation() == m_pImpl->getURL() ) - if ( m_pImpl->m_bDocumentReadOnly ) - throw IOException(); + ::rtl::OUString sDocumentURL( m_pImpl->getURL() ); + if ( sDocumentURL.getLength() ) + { + if ( m_pImpl->getDocFileLocation() == m_pImpl->getURL() ) + if ( m_pImpl->m_bDocumentReadOnly ) + throw IOException(); + + impl_storeAs_throw( m_pImpl->getURL(), m_pImpl->getMediaDescriptor(), SAVE, aGuard ); + return; + } + + // if we have no URL, but did survive the DocumentGuard above, then we've been inited via XLoadable::initNew, + // i.e. we're based on a temporary storage + OSL_ENSURE( m_pImpl->getDocFileLocation().getLength() == 0, "ODatabaseDocument::store: unexpected URL inconsistency!" ); - impl_storeAs_throw( m_pImpl->getURL(), m_pImpl->getResource(), SAVE, aGuard ); + try + { + impl_storeToStorage_throw( m_pImpl->getRootStorage(), m_pImpl->getMediaDescriptor().getPropertyValues(), aGuard ); + } + catch( const Exception& ) + { + Any aError = ::cppu::getCaughtException(); + if ( aError.isExtractableTo( ::cppu::UnoType< IOException >::get() ) + || aError.isExtractableTo( ::cppu::UnoType< RuntimeException >::get() ) + ) + { + // allowed to leave + throw; + } + impl_throwIOExceptionCausedBySave_throw( aError, ::rtl::OUString() ); + } } // ----------------------------------------------------------------------------- -void ODatabaseDocument::impl_storeAs_throw( const ::rtl::OUString& _rURL, const Sequence< PropertyValue>& _rArguments, +void ODatabaseDocument::impl_throwIOExceptionCausedBySave_throw( const Any& i_rError, const ::rtl::OUString& i_rTargetURL ) const +{ + ::rtl::OUString sErrorMessage = extractExceptionMessage( m_pImpl->m_aContext, i_rError ); + sErrorMessage = ResourceManager::loadString( + RID_STR_ERROR_WHILE_SAVING, + "$location$", i_rTargetURL, + "$message$", sErrorMessage + ); + throw IOException( sErrorMessage, *const_cast< ODatabaseDocument* >( this ) ); +} + +// ----------------------------------------------------------------------------- +void ODatabaseDocument::impl_storeAs_throw( const ::rtl::OUString& _rURL, const ::comphelper::NamedValueCollection& _rArguments, const StoreType _eType, DocumentGuard& _rGuard ) throw ( IOException, RuntimeException ) { OSL_PRECOND( ( _eType == SAVE ) || ( _eType == SAVE_AS ), @@ -780,6 +1034,12 @@ void ODatabaseDocument::impl_storeAs_throw( const ::rtl::OUString& _rURL, const m_pImpl->disposeStorages(); + // each and every document definition obtained via m_xForms and m_xReports depends + // on the sub storages which we just disposed. So, dispose the forms/reports collections, too. + // This ensures that they're re-created when needed. + clearObjectContainer( m_xForms ); + clearObjectContainer( m_xReports ); + xNewRootStorage = m_pImpl->switchToStorage( xTargetStorage ); m_pImpl->m_bDocumentReadOnly = sal_False; @@ -791,7 +1051,8 @@ void ODatabaseDocument::impl_storeAs_throw( const ::rtl::OUString& _rURL, const impl_storeToStorage_throw( xCurrentStorage, aMediaDescriptor, _rGuard ); // success - tell our impl - m_pImpl->attachResource( _rURL, aMediaDescriptor ); + m_pImpl->setDocFileLocation( _rURL ); + m_pImpl->setResource( _rURL, aMediaDescriptor ); // if we are in an initialization process, then this is finished, now that we stored the document if ( bIsInitializationProcess ) @@ -813,13 +1074,7 @@ void ODatabaseDocument::impl_storeAs_throw( const ::rtl::OUString& _rURL, const throw; } - ::rtl::OUString sErrorMessage = extractExceptionMessage( m_pImpl->m_aContext, aError ); - sErrorMessage = ResourceManager::loadString( - RID_STR_ERROR_WHILE_SAVING, - "$location$", _rURL, - "$message$", sErrorMessage - ); - throw IOException( sErrorMessage, *this ); + impl_throwIOExceptionCausedBySave_throw( aError, _rURL ); } // notify the document event @@ -934,7 +1189,7 @@ void ODatabaseDocument::impl_storeToStorage_throw( const Reference< XStorage >& lcl_triggerStatusIndicator_throw( aWriteArgs, _rDocGuard, false ); // commit target storage - OSL_VERIFY( ODatabaseModelImpl::commitStorageIfWriteable( _rxTargetStorage ) ); + OSL_VERIFY( tools::stor::commitStorageIfWriteable( _rxTargetStorage ) ); } catch( const IOException& ) { throw; } catch( const RuntimeException& ) { throw; } @@ -980,16 +1235,7 @@ void SAL_CALL ODatabaseDocument::storeToURL( const ::rtl::OUString& _rURL, const throw; } - Exception aExcept; - aError >>= aExcept; - - ::rtl::OUString sErrorMessage = extractExceptionMessage( m_pImpl->m_aContext, aError ); - sErrorMessage = ResourceManager::loadString( - RID_STR_ERROR_WHILE_SAVING, - "$location$", _rURL, - "$message$", sErrorMessage - ); - throw IOException( sErrorMessage, *this ); + impl_throwIOExceptionCausedBySave_throw( aError, _rURL ); } m_aEventNotifier.notifyDocumentEventAsync( "OnSaveToDone", NULL, makeAny( _rURL ) ); @@ -1145,8 +1391,25 @@ Reference< XNameAccess > ODatabaseDocument::impl_getDocumentContainer_throw( ODa Reference< XNameAccess > xContainer = rContainerRef; if ( !xContainer.is() ) { - TContentPtr& rContainerData( m_pImpl->getObjectContainer( _eType ) ); - rContainerRef = xContainer = new ODocumentContainer( m_pImpl->m_aContext.getLegacyServiceFactory(), *this, rContainerData, bFormsContainer ); + Any aValue; + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > xMy(*this); + if ( dbtools::getDataSourceSetting(xMy,bFormsContainer ? "Forms" : "Reports",aValue) ) + { + ::rtl::OUString sSupportService; + aValue >>= sSupportService; + if ( sSupportService.getLength() ) + { + Sequence<Any> aArgs(1); + aArgs[0] <<= NamedValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DatabaseDocument")),makeAny(xMy)); + xContainer.set(m_pImpl->m_aContext.createComponentWithArguments(sSupportService,aArgs),UNO_QUERY); + rContainerRef = xContainer; + } + } + if ( !xContainer.is() ) + { + TContentPtr& rContainerData( m_pImpl->getObjectContainer( _eType ) ); + rContainerRef = xContainer = new ODocumentContainer( m_pImpl->m_aContext.getLegacyServiceFactory(), *this, rContainerData, bFormsContainer ); + } impl_reparent_nothrow( xContainer ); } return xContainer; diff --git a/dbaccess/source/core/dataaccess/databasedocument.hxx b/dbaccess/source/core/dataaccess/databasedocument.hxx index d90310015f70..d2aa57130d18 100644 --- a/dbaccess/source/core/dataaccess/databasedocument.hxx +++ b/dbaccess/source/core/dataaccess/databasedocument.hxx @@ -57,11 +57,12 @@ #include <com/sun/star/frame/XLoadable.hpp> #include <com/sun/star/document/XEventBroadcaster.hpp> #include <com/sun/star/document/XDocumentEventBroadcaster.hpp> +#include <com/sun/star/document/XDocumentRecovery.hpp> /** === end UNO includes === **/ -#if ! defined(INCLUDED_COMPHELPER_IMPLBASE_VAR_HXX_16) -#define INCLUDED_COMPHELPER_IMPLBASE_VAR_HXX_16 -#define COMPHELPER_IMPLBASE_INTERFACE_NUMBER 16 +#if ! defined(INCLUDED_COMPHELPER_IMPLBASE_VAR_HXX_17) +#define INCLUDED_COMPHELPER_IMPLBASE_VAR_HXX_17 +#define COMPHELPER_IMPLBASE_INTERFACE_NUMBER 17 #include <comphelper/implbase_var.hxx> #endif @@ -121,8 +122,12 @@ public: ); /** to be called when a controller is set as current controller + @return <TRUE/> + if and only if the controller connection indicates that loading the document is finished. This + is the case if the given controller has previously been connected, and it was the first controller + ever for which this happened. */ - void onSetCurrentController( + bool onSetCurrentController( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XController >& _rxController ); @@ -140,7 +145,7 @@ private: //============================================================ //= ODatabaseDocument //============================================================ -typedef ::comphelper::WeakComponentImplHelper16 < ::com::sun::star::frame::XModel2 +typedef ::comphelper::WeakComponentImplHelper17 < ::com::sun::star::frame::XModel2 , ::com::sun::star::util::XModifiable , ::com::sun::star::frame::XStorable , ::com::sun::star::document::XEventBroadcaster @@ -156,6 +161,7 @@ typedef ::comphelper::WeakComponentImplHelper16 < ::com::sun::star::frame::XMo , ::com::sun::star::script::provider::XScriptProviderSupplier , ::com::sun::star::document::XEventsSupplier , ::com::sun::star::frame::XLoadable + , ::com::sun::star::document::XDocumentRecovery > ODatabaseDocument_OfficeDocument; typedef ::cppu::ImplHelper3< ::com::sun::star::frame::XTitle @@ -204,6 +210,7 @@ class ODatabaseDocument :public ModelDependentComponent // ModelDepe InitState m_eInitState; bool m_bClosing; bool m_bAllowDocumentScripting; + bool m_bHasBeenRecovered; enum StoreType { SAVE, SAVE_AS }; /** stores the document to the given URL, rebases it to the respective new storage, if necessary, resets @@ -221,7 +228,7 @@ class ODatabaseDocument :public ModelDependentComponent // ModelDepe */ void impl_storeAs_throw( const ::rtl::OUString& _rURL, - const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue>& _rArguments, + const ::comphelper::NamedValueCollection& _rArguments, const StoreType _eType, DocumentGuard& _rGuard ) @@ -422,6 +429,11 @@ public: virtual void SAL_CALL initNew( ) throw (::com::sun::star::frame::DoubleInitializationException, ::com::sun::star::io::IOException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); virtual void SAL_CALL load( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lArguments ) throw (::com::sun::star::frame::DoubleInitializationException, ::com::sun::star::io::IOException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + // css.document.XDocumentRecovery + virtual ::sal_Bool SAL_CALL wasModifiedSinceLastSave() throw ( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL storeToRecoveryFile( const ::rtl::OUString& i_TargetLocation, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& i_MediaDescriptor ) throw ( ::com::sun::star::uno::RuntimeException, ::com::sun::star::io::IOException, ::com::sun::star::lang::WrappedTargetException ); + virtual void SAL_CALL recoverFromFile( const ::rtl::OUString& i_SourceLocation, const ::rtl::OUString& i_SalvagedFile, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& i_MediaDescriptor ) throw ( ::com::sun::star::uno::RuntimeException, ::com::sun::star::io::IOException, ::com::sun::star::lang::WrappedTargetException ); + // XTitle virtual ::rtl::OUString SAL_CALL getTitle( ) throw (::com::sun::star::uno::RuntimeException); virtual void SAL_CALL setTitle( const ::rtl::OUString& sTitle ) throw (::com::sun::star::uno::RuntimeException); @@ -598,6 +610,31 @@ private: const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& _rMediaDescriptor, DocumentGuard& _rDocGuard ) const; + + + /** impl-version of attachResource + + @param i_rLogicalDocumentURL + denotes the logical URL of the document, to be reported by getURL/getLocation + @param i_rMediaDescriptor + denotes additional document parameters + @param _rDocGuard + is the guard which currently protects the document instance + + */ + sal_Bool impl_attachResource( + const ::rtl::OUString& i_rLogicalDocumentURL, + const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& i_rMediaDescriptor, + DocumentGuard& _rDocGuard + ); + + /** throws an IOException with the message as defined in the RID_STR_ERROR_WHILE_SAVING resource, wrapping + the given caught non-IOException error + */ + void impl_throwIOExceptionCausedBySave_throw( + const ::com::sun::star::uno::Any& i_rError, + const ::rtl::OUString& i_rTargetURL + ) const; }; /** an extended version of the ModelMethodGuard, which also cares for the initialization state diff --git a/dbaccess/source/core/dataaccess/datasource.cxx b/dbaccess/source/core/dataaccess/datasource.cxx index 286ef1887710..b5cf356c2115 100644 --- a/dbaccess/source/core/dataaccess/datasource.cxx +++ b/dbaccess/source/core/dataaccess/datasource.cxx @@ -39,6 +39,7 @@ #include "SharedConnection.hxx" #include "databasedocument.hxx" + /** === begin UNO includes === **/ #include <com/sun/star/beans/NamedValue.hpp> #include <com/sun/star/beans/PropertyAttribute.hpp> @@ -67,6 +68,7 @@ #include <comphelper/sequence.hxx> #include <comphelper/string.hxx> #include <connectivity/dbexception.hxx> +#include <connectivity/dbtools.hxx> #include <cppuhelper/typeprovider.hxx> #include <tools/debug.hxx> #include <tools/diagnose_ex.h> @@ -1337,8 +1339,24 @@ Reference< XNameAccess > SAL_CALL ODatabaseSource::getQueryDefinitions( ) throw( Reference< XNameAccess > xContainer = m_pImpl->m_xCommandDefinitions; if ( !xContainer.is() ) { - TContentPtr& rContainerData( m_pImpl->getObjectContainer( ODatabaseModelImpl::E_QUERY ) ); - xContainer = new OCommandContainer( m_pImpl->m_aContext.getLegacyServiceFactory(), *this, rContainerData, sal_False ); + Any aValue; + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > xMy(*this); + if ( dbtools::getDataSourceSetting(xMy,"CommandDefinitions",aValue) ) + { + ::rtl::OUString sSupportService; + aValue >>= sSupportService; + if ( sSupportService.getLength() ) + { + Sequence<Any> aArgs(1); + aArgs[0] <<= NamedValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DataSource")),makeAny(xMy)); + xContainer.set(m_pImpl->m_aContext.createComponentWithArguments(sSupportService,aArgs),UNO_QUERY); + } + } + if ( !xContainer.is() ) + { + TContentPtr& rContainerData( m_pImpl->getObjectContainer( ODatabaseModelImpl::E_QUERY ) ); + xContainer = new OCommandContainer( m_pImpl->m_aContext.getLegacyServiceFactory(), *this, rContainerData, sal_False ); + } m_pImpl->m_xCommandDefinitions = xContainer; } return xContainer; diff --git a/dbaccess/source/core/dataaccess/documentcontainer.cxx b/dbaccess/source/core/dataaccess/documentcontainer.cxx index 4f5277f5ed8b..d9427eff0463 100644 --- a/dbaccess/source/core/dataaccess/documentcontainer.cxx +++ b/dbaccess/source/core/dataaccess/documentcontainer.cxx @@ -82,6 +82,7 @@ #endif #include "core_resource.hxx" #include "core_resource.hrc" +#include <comphelper/namedvaluecollection.hxx> #include <vcl/svapp.hxx> #include <vos/mutex.hxx> @@ -202,6 +203,20 @@ Reference< XInterface > SAL_CALL ODocumentContainer::createInstance( const ::rtl { return createInstanceWithArguments( aServiceSpecifier, Sequence< Any >() ); } + +namespace +{ + template< class TYPE > + void lcl_extractAndRemove( ::comphelper::NamedValueCollection& io_rArguments, const ::rtl::OUString& i_rName, TYPE& o_rValue ) + { + if ( io_rArguments.has( i_rName ) ) + { + io_rArguments.get_ensureType( i_rName, o_rValue ); + io_rArguments.remove( i_rName ); + } + } +} + // ----------------------------------------------------------------------------- Reference< XInterface > SAL_CALL ODocumentContainer::createInstanceWithArguments( const ::rtl::OUString& ServiceSpecifier, const Sequence< Any >& _aArguments ) throw (Exception, RuntimeException) { @@ -211,36 +226,47 @@ Reference< XInterface > SAL_CALL ODocumentContainer::createInstanceWithArguments { MutexGuard aGuard(m_aMutex); - ::rtl::OUString sName, sPersistentName, sURL, sMediaType; + // extrat known arguments + ::rtl::OUString sName, sPersistentName, sURL, sMediaType, sDocServiceName; Reference< XCommandProcessor > xCopyFrom; Reference< XConnection > xConnection; + sal_Bool bAsTemplate( sal_False ); Sequence< sal_Int8 > aClassID; - sal_Bool bAsTemplate = sal_False; ::comphelper::NamedValueCollection aArgs( _aArguments ); - sName = aArgs.getOrDefault( (::rtl::OUString)PROPERTY_NAME, sName ); - sPersistentName = aArgs.getOrDefault( (::rtl::OUString)PROPERTY_PERSISTENT_NAME, sPersistentName ); - xCopyFrom = aArgs.getOrDefault( (::rtl::OUString)PROPERTY_EMBEDDEDOBJECT, xCopyFrom ); - sURL = aArgs.getOrDefault( (::rtl::OUString)PROPERTY_URL, sURL ); - xConnection = aArgs.getOrDefault( (::rtl::OUString)PROPERTY_ACTIVE_CONNECTION, xConnection ); - bAsTemplate = aArgs.getOrDefault( (::rtl::OUString)PROPERTY_AS_TEMPLATE, bAsTemplate ); - sMediaType = aArgs.getOrDefault( (::rtl::OUString)INFO_MEDIATYPE, sMediaType ); - - if ( aArgs.has( "ClassID" ) ) + lcl_extractAndRemove( aArgs, PROPERTY_NAME, sName ); + lcl_extractAndRemove( aArgs, PROPERTY_PERSISTENT_NAME, sPersistentName ); + lcl_extractAndRemove( aArgs, PROPERTY_URL, sURL ); + lcl_extractAndRemove( aArgs, PROPERTY_EMBEDDEDOBJECT, xCopyFrom ); + lcl_extractAndRemove( aArgs, PROPERTY_ACTIVE_CONNECTION, xConnection ); + lcl_extractAndRemove( aArgs, PROPERTY_AS_TEMPLATE, bAsTemplate ); + lcl_extractAndRemove( aArgs, INFO_MEDIATYPE, sMediaType ); + lcl_extractAndRemove( aArgs, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DocumentServiceName" ) ), sDocServiceName ); + + // ClassID has two allowed types, so a special treatment here + Any aClassIDArg = aArgs.get( "ClassID" ); + if ( aClassIDArg.hasValue() ) { - Any aClassIDValue = aArgs.get( "ClassID" ); - // class IDs might be passed as byte sequence ... - if ( !( aClassIDValue >>= aClassID ) ) + if ( !( aClassIDArg >>= aClassID ) ) { - // ... or as string - ::rtl::OUString sClassID; - aClassIDValue >>= sClassID; - aClassID = ::comphelper::MimeConfigurationHelper::GetSequenceClassIDRepresentation( sClassID ); + // Extended for usage also with a string + ::rtl::OUString sClassIDString; + if ( !( aClassIDArg >>= sClassIDString ) ) + throw IllegalArgumentException( ::rtl::OUString(), *this, 2 ); + + aClassID = ::comphelper::MimeConfigurationHelper::GetSequenceClassIDRepresentation( sClassIDString ); } + +#if OSL_DEBUG_LEVEL > 0 + ::rtl::OUString sClassIDString = ::comphelper::MimeConfigurationHelper::GetStringClassIDRepresentation( aClassID ); + (void)sClassIDString; +#endif + aArgs.remove( "ClassID" ); } + // Everything which now is still present in the arguments is passed to the embedded object + const Sequence< PropertyValue > aCreationArgs( aArgs.getPropertyValues() ); const ODefinitionContainer_Impl& rDefinitions( getDefinitions() ); - sal_Bool bNew = ( 0 == sPersistentName.getLength() ); if ( bNew ) { @@ -273,8 +299,18 @@ Reference< XInterface > SAL_CALL ODocumentContainer::createInstanceWithArguments } else { - if ( bNeedClassID && sMediaType.getLength() ) - ODocumentDefinition::GetDocumentServiceFromMediaType( sMediaType, m_aContext, aClassID ); + if ( bNeedClassID ) + { + if ( sMediaType.getLength() ) + ODocumentDefinition::GetDocumentServiceFromMediaType( sMediaType, m_aContext, aClassID ); + else if ( sDocServiceName.getLength() ) + { + ::comphelper::MimeConfigurationHelper aConfigHelper( m_aContext.getLegacyServiceFactory() ); + const Sequence< NamedValue > aProps( aConfigHelper.GetObjectPropsByDocumentName( sDocServiceName ) ); + const ::comphelper::NamedValueCollection aMediaTypeProps( aProps ); + aClassID = aMediaTypeProps.getOrDefault( "ClassID", Sequence< sal_Int8 >() ); + } + } } } @@ -293,7 +329,16 @@ Reference< XInterface > SAL_CALL ODocumentContainer::createInstanceWithArguments else pElementImpl = aFind->second; - xContent = new ODocumentDefinition( *this, m_aContext.getLegacyServiceFactory(), pElementImpl, m_bFormsContainer, aClassID, xConnection ); + ::rtl::Reference< ODocumentDefinition > pDocDef = new ODocumentDefinition( *this, m_aContext.getLegacyServiceFactory(), pElementImpl, m_bFormsContainer ); + if ( aClassID.getLength() ) + { + pDocDef->initialLoad( aClassID, aCreationArgs, xConnection ); + } + else + { + OSL_ENSURE( aCreationArgs.getLength() == 0, "ODocumentContainer::createInstance: additional creation args are lost, if you do not provide a class ID." ); + } + xContent = pDocDef.get(); if ( sURL.getLength() ) { @@ -551,28 +596,15 @@ Reference< XComponent > SAL_CALL ODocumentContainer::loadComponentFromURL( const { Command aCommand; - static const ::rtl::OUString s_sOpenMode = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("OpenMode")); - const PropertyValue* pIter = Arguments.getConstArray(); - const PropertyValue* pEnd = pIter + Arguments.getLength(); - for( ; pIter != pEnd ; ++pIter) - { - if ( pIter->Name == s_sOpenMode ) - { - pIter->Value >>= aCommand.Name; - break; - } - } - if ( !aCommand.Name.getLength() ) // default mode - aCommand.Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("open")); + ::comphelper::NamedValueCollection aArgs( Arguments ); + aCommand.Name = aArgs.getOrDefault( "OpenMode", ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "open" ) ) ); + aArgs.remove( "OpenMode" ); + OpenCommandArgument2 aOpenCommand; aOpenCommand.Mode = OpenMode::DOCUMENT; + aArgs.put( "OpenCommandArgument", aOpenCommand ); - Sequence< PropertyValue > aArguments(Arguments); - sal_Int32 nLen = aArguments.getLength(); - aArguments.realloc(nLen + 1); - - aArguments[nLen].Value <<= aOpenCommand; - aCommand.Argument <<= aArguments; + aCommand.Argument <<= aArgs.getPropertyValues(); xComp.set(xContent->execute(aCommand,xContent->createCommandIdentifier(),Reference< XCommandEnvironment >()),UNO_QUERY); } } @@ -664,6 +696,24 @@ void SAL_CALL ODocumentContainer::replaceByHierarchicalName( const ::rtl::OUStri xNameContainer->replaceByName(sName,_aElement); } + +// ----------------------------------------------------------------------------- +::rtl::OUString SAL_CALL ODocumentContainer::getHierarchicalName() throw (RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + return impl_getHierarchicalName( false ); +} + +// ----------------------------------------------------------------------------- +::rtl::OUString SAL_CALL ODocumentContainer::composeHierarchicalName( const ::rtl::OUString& i_rRelativeName ) throw (IllegalArgumentException, NoSupportException, RuntimeException) +{ + ::rtl::OUStringBuffer aBuffer; + aBuffer.append( getHierarchicalName() ); + aBuffer.append( sal_Unicode( '/' ) ); + aBuffer.append( i_rRelativeName ); + return aBuffer.makeStringAndClear(); +} + // ----------------------------------------------------------------------------- ::rtl::Reference<OContentHelper> ODocumentContainer::getContent(const ::rtl::OUString& _sName) const { diff --git a/dbaccess/source/core/dataaccess/documentcontainer.hxx b/dbaccess/source/core/dataaccess/documentcontainer.hxx index 9e26ea62d4b5..c1a9c424d7d3 100644 --- a/dbaccess/source/core/dataaccess/documentcontainer.hxx +++ b/dbaccess/source/core/dataaccess/documentcontainer.hxx @@ -31,8 +31,8 @@ #ifndef _DBA_CORE_DEFINITIONCONTAINER_HXX_ #include "definitioncontainer.hxx" #endif -#ifndef _CPPUHELPER_IMPLBASE4_HXX_ -#include <cppuhelper/implbase4.hxx> +#ifndef _CPPUHELPER_IMPLBASE5_HXX_ +#include <cppuhelper/implbase5.hxx> #endif #ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_ #include <com/sun/star/lang/XMultiServiceFactory.hpp> @@ -43,6 +43,9 @@ #ifndef _COM_SUN_STAR_CONTAINER_XHIERARCHICALNAMECONTAINER_HPP_ #include <com/sun/star/container/XHierarchicalNameContainer.hpp> #endif +#ifndef _COM_SUN_STAR_CONTAINER_XHIERARCHICALNAME_HPP_ +#include <com/sun/star/container/XHierarchicalName.hpp> +#endif #ifndef _COM_SUN_STAR_EMBED_XTRANSACTEDOBJECT_HPP_ #include <com/sun/star/embed/XTransactedObject.hpp> #endif @@ -60,9 +63,10 @@ namespace dbaccess { //........................................................................ -typedef ::cppu::ImplHelper4 < ::com::sun::star::frame::XComponentLoader +typedef ::cppu::ImplHelper5 < ::com::sun::star::frame::XComponentLoader , ::com::sun::star::lang::XMultiServiceFactory , ::com::sun::star::container::XHierarchicalNameContainer + , ::com::sun::star::container::XHierarchicalName , ::com::sun::star::embed::XTransactedObject > ODocumentContainer_Base; //========================================================================== @@ -111,6 +115,10 @@ public: virtual void SAL_CALL insertByHierarchicalName( const ::rtl::OUString& aName, const ::com::sun::star::uno::Any& aElement ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::ElementExistException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); virtual void SAL_CALL removeByHierarchicalName( const ::rtl::OUString& Name ) throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + // XHierarchicalName + virtual ::rtl::OUString SAL_CALL getHierarchicalName( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL composeHierarchicalName( const ::rtl::OUString& aRelativeName ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException); + // XNameContainer virtual void SAL_CALL removeByName( const ::rtl::OUString& _rName ) throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); diff --git a/dbaccess/source/core/dataaccess/documentdefinition.cxx b/dbaccess/source/core/dataaccess/documentdefinition.cxx index 70c59c0eca98..ffc1ea3db6eb 100644 --- a/dbaccess/source/core/dataaccess/documentdefinition.cxx +++ b/dbaccess/source/core/dataaccess/documentdefinition.cxx @@ -249,6 +249,7 @@ #include <com/sun/star/io/WrongFormatException.hpp> #include <com/sun/star/sdb/application/XDatabaseDocumentUI.hpp> #include <com/sun/star/sdb/application/DatabaseObject.hpp> +#include <com/sun/star/util/XModifiable2.hpp> using namespace ::com::sun::star; using namespace view; @@ -415,6 +416,40 @@ namespace dbaccess }; //================================================================== + // LockModifiable + //================================================================== + class LockModifiable + { + public: + LockModifiable( const Reference< XInterface >& i_rModifiable ) + :m_xModifiable( i_rModifiable, UNO_QUERY ) + { + OSL_ENSURE( m_xModifiable.is(), "LockModifiable::LockModifiable: invalid component!" ); + if ( m_xModifiable.is() ) + { + if ( !m_xModifiable->isSetModifiedEnabled() ) + { + // somebody already locked that, no need to lock it, again, and no need to unlock it later + m_xModifiable.clear(); + } + else + { + m_xModifiable->disableSetModified(); + } + } + } + + ~LockModifiable() + { + if ( m_xModifiable.is() ) + m_xModifiable->enableSetModified(); + } + + private: + Reference< XModifiable2 > m_xModifiable; + }; + + //================================================================== // LifetimeCoupler //================================================================== typedef ::cppu::WeakImplHelper1 < css::lang::XEventListener @@ -531,6 +566,15 @@ namespace dbaccess } } } +#if OSL_DEBUG_LEVEL > 0 + // alternative, shorter approach + const Sequence< NamedValue > aProps( aConfigHelper.GetObjectPropsByMediaType( _rMediaType ) ); + const ::comphelper::NamedValueCollection aMediaTypeProps( aProps ); + const ::rtl::OUString sAlternativeResult = aMediaTypeProps.getOrDefault( "ObjectDocumentServiceName", ::rtl::OUString() ); + OSL_ENSURE( sAlternativeResult == sResult, "ODocumentDefinition::GetDocumentServiceFromMediaType: failed, this approach is *not* equivalent (1)!" ); + const Sequence< sal_Int8 > aAlternativeClassID = aMediaTypeProps.getOrDefault( "ClassID", Sequence< sal_Int8 >() ); + OSL_ENSURE( aAlternativeClassID == _rClassId, "ODocumentDefinition::GetDocumentServiceFromMediaType: failed, this approach is *not* equivalent (2)!" ); +#endif } catch ( Exception& ) { @@ -545,14 +589,9 @@ namespace dbaccess DBG_NAME(ODocumentDefinition) //-------------------------------------------------------------------------- -ODocumentDefinition::ODocumentDefinition(const Reference< XInterface >& _rxContainer - , const Reference< XMultiServiceFactory >& _xORB - ,const TContentPtr& _pImpl - , sal_Bool _bForm - , const Sequence< sal_Int8 >& _aClassID - ,const Reference<XConnection>& _xConnection - ) - :OContentHelper(_xORB,_rxContainer,_pImpl) +ODocumentDefinition::ODocumentDefinition( const Reference< XInterface >& _rxContainer, const Reference< XMultiServiceFactory >& _xORB, + const TContentPtr& _pImpl, sal_Bool _bForm ) + :OContentHelper(_xORB,_rxContainer,_pImpl) ,OPropertyStateContainer(OContentHelper::rBHelper) ,m_pInterceptor(NULL) ,m_bForm(_bForm) @@ -563,9 +602,19 @@ ODocumentDefinition::ODocumentDefinition(const Reference< XInterface >& _rxConta { DBG_CTOR(ODocumentDefinition, NULL); registerProperties(); - if ( _aClassID.getLength() ) - loadEmbeddedObject( _xConnection, _aClassID, Sequence< PropertyValue >(), false, false ); } + +//-------------------------------------------------------------------------- +void ODocumentDefinition::initialLoad( const Sequence< sal_Int8 >& i_rClassID, const Sequence< PropertyValue >& i_rCreationArgs, + const Reference< XConnection >& i_rConnection ) +{ + OSL_ENSURE( i_rClassID.getLength(), "ODocumentDefinition::initialLoad: illegal class ID!" ); + if ( !i_rClassID.getLength() ) + return; + + loadEmbeddedObject( i_rConnection, i_rClassID, i_rCreationArgs, false, false ); +} + //-------------------------------------------------------------------------- ODocumentDefinition::~ODocumentDefinition() { @@ -628,15 +677,39 @@ IMPLEMENT_SERVICE_INFO1(ODocumentDefinition,"com.sun.star.comp.dba.ODocumentDefi //-------------------------------------------------------------------------- void ODocumentDefinition::registerProperties() { - registerProperty(PROPERTY_NAME, PROPERTY_ID_NAME, PropertyAttribute::BOUND | PropertyAttribute::READONLY | PropertyAttribute::CONSTRAINED, - &m_pImpl->m_aProps.aTitle, ::getCppuType(&m_pImpl->m_aProps.aTitle)); - registerProperty(PROPERTY_AS_TEMPLATE, PROPERTY_ID_AS_TEMPLATE, PropertyAttribute::BOUND | PropertyAttribute::READONLY | PropertyAttribute::CONSTRAINED, - &m_pImpl->m_aProps.bAsTemplate, ::getCppuType(&m_pImpl->m_aProps.bAsTemplate)); - registerProperty(PROPERTY_PERSISTENT_NAME, PROPERTY_ID_PERSISTENT_NAME, PropertyAttribute::BOUND | PropertyAttribute::READONLY | PropertyAttribute::CONSTRAINED, - &m_pImpl->m_aProps.sPersistentName, ::getCppuType(&m_pImpl->m_aProps.sPersistentName)); - registerProperty(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("IsForm")), PROPERTY_ID_IS_FORM, PropertyAttribute::BOUND | PropertyAttribute::READONLY | PropertyAttribute::CONSTRAINED, - &m_bForm, ::getCppuType(&m_bForm)); +#define REGISTER_PROPERTY( name, location ) \ + registerProperty( PROPERTY_##name, PROPERTY_ID_##name, PropertyAttribute::READONLY, &location, ::getCppuType( &location ) ); + +#define REGISTER_PROPERTY_BV( name, location ) \ + registerProperty( PROPERTY_##name, PROPERTY_ID_##name, PropertyAttribute::CONSTRAINED | PropertyAttribute::BOUND | PropertyAttribute::READONLY, &location, ::getCppuType( &location ) ); + + REGISTER_PROPERTY_BV( NAME, m_pImpl->m_aProps.aTitle ); + REGISTER_PROPERTY ( AS_TEMPLATE, m_pImpl->m_aProps.bAsTemplate ); + REGISTER_PROPERTY ( PERSISTENT_NAME, m_pImpl->m_aProps.sPersistentName ); + REGISTER_PROPERTY ( IS_FORM, m_bForm ); +} + +// ----------------------------------------------------------------------------- +void SAL_CALL ODocumentDefinition::getFastPropertyValue( Any& o_rValue, sal_Int32 i_nHandle ) const +{ + if ( i_nHandle == PROPERTY_ID_PERSISTENT_PATH ) + { + ::rtl::OUString sPersistentPath; + if ( m_pImpl->m_aProps.sPersistentName.getLength() ) + { + ::rtl::OUStringBuffer aBuffer; + aBuffer.append( ODatabaseModelImpl::getObjectContainerStorageName( m_bForm ? ODatabaseModelImpl::E_FORM : ODatabaseModelImpl::E_REPORT ) ); + aBuffer.append( sal_Unicode( '/' ) ); + aBuffer.append( m_pImpl->m_aProps.sPersistentName ); + sPersistentPath = aBuffer.makeStringAndClear(); + } + o_rValue <<= sPersistentPath; + return; + } + + OPropertyStateContainer::getFastPropertyValue( o_rValue, i_nHandle ); } + // ----------------------------------------------------------------------------- Reference< XPropertySetInfo > SAL_CALL ODocumentDefinition::getPropertySetInfo( ) throw(RuntimeException) { @@ -654,10 +727,21 @@ IPropertyArrayHelper& ODocumentDefinition::getInfoHelper() //-------------------------------------------------------------------------- IPropertyArrayHelper* ODocumentDefinition::createArrayHelper( ) const { + // properties maintained by our base class (see registerProperties) Sequence< Property > aProps; - describeProperties(aProps); - return new OPropertyArrayHelper(aProps); + describeProperties( aProps ); + + // properties not maintained by our base class + Sequence< Property > aManualProps( 1 ); + aManualProps[0].Name = PROPERTY_PERSISTENT_PATH; + aManualProps[0].Handle = PROPERTY_ID_PERSISTENT_PATH; + aManualProps[0].Type = ::getCppuType( static_cast< const ::rtl::OUString* >( NULL ) ); + aManualProps[0].Attributes = PropertyAttribute::READONLY; + + return new OPropertyArrayHelper( ::comphelper::concatSequences( aProps, aManualProps ) ); } + +// ----------------------------------------------------------------------------- class OExecuteImpl { sal_Bool& m_rbSet; @@ -665,6 +749,7 @@ public: OExecuteImpl(sal_Bool& _rbSet) : m_rbSet(_rbSet){ m_rbSet=sal_True; } ~OExecuteImpl(){ m_rbSet = sal_False; } }; + // ----------------------------------------------------------------------------- namespace { @@ -694,7 +779,7 @@ void ODocumentDefinition::impl_removeFrameFromDesktop_throw( const ::comphelper: } // ----------------------------------------------------------------------------- -void ODocumentDefinition::impl_onActivateEmbeddedObject_nothrow() +void ODocumentDefinition::impl_onActivateEmbeddedObject_nothrow( const bool i_bReactivated ) { try { @@ -718,10 +803,10 @@ void ODocumentDefinition::impl_onActivateEmbeddedObject_nothrow() // ensure that we ourself are kept alive as long as the embedded object's frame is // opened - LifetimeCoupler::couple( *this, Reference< XComponent >( xFrame, UNO_QUERY_THROW ) ); + LifetimeCoupler::couple( *this, xFrame.get() ); // init the edit view - if ( m_bForm && m_bOpenInDesign ) + if ( m_bForm && m_bOpenInDesign && !i_bReactivated ) impl_initFormEditView( xController ); } catch( const RuntimeException& ) @@ -831,6 +916,9 @@ void ODocumentDefinition::impl_initFormEditView( const Reference< XController >& Reference< XViewSettingsSupplier > xSettingsSupplier( _rxController, UNO_QUERY_THROW ); Reference< XPropertySet > xViewSettings( xSettingsSupplier->getViewSettings(), UNO_QUERY_THROW ); + // the below code could indirectly tamper with the "modified" flag of the model, temporarily disable this + LockModifiable aLockModify( _rxController->getModel() ); + // The visual area size can be changed by the setting of the following properties // so it should be restored later PreserveVisualAreaSize aPreserveVisAreaSize( _rxController->getModel() ); @@ -848,9 +936,6 @@ void ODocumentDefinition::impl_initFormEditView( const Reference< XController >& xViewSettings->setPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ShowOnlineLayout")),makeAny(sal_True)); xViewSettings->setPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("RasterSubdivisionX")),makeAny(sal_Int32(5))); xViewSettings->setPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("RasterSubdivisionY")),makeAny(sal_Int32(5))); - - Reference< XModifiable > xModifiable( _rxController->getModel(), UNO_QUERY_THROW ); - xModifiable->setModified( sal_False ); } catch( const Exception& ) { @@ -859,6 +944,39 @@ void ODocumentDefinition::impl_initFormEditView( const Reference< XController >& } // ----------------------------------------------------------------------------- +void ODocumentDefinition::impl_showOrHideComponent_throw( const bool i_bShow ) +{ + const sal_Int32 nCurrentState = m_xEmbeddedObject.is() ? m_xEmbeddedObject->getCurrentState() : EmbedStates::LOADED; + switch ( nCurrentState ) + { + default: + case EmbedStates::LOADED: + throw embed::WrongStateException( ::rtl::OUString(), *this ); + + case EmbedStates::RUNNING: + if ( !i_bShow ) + // fine, a running (and not yet active) object is never visible + return; + { + LockModifiable aLockModify( impl_getComponent_throw() ); + m_xEmbeddedObject->changeState( EmbedStates::ACTIVE ); + impl_onActivateEmbeddedObject_nothrow( false ); + } + break; + + case EmbedStates::ACTIVE: + { + Reference< XModel > xEmbeddedDoc( impl_getComponent_throw( true ), UNO_QUERY_THROW ); + Reference< XController > xEmbeddedController( xEmbeddedDoc->getCurrentController(), UNO_SET_THROW ); + Reference< XFrame > xEmbeddedFrame( xEmbeddedController->getFrame(), UNO_SET_THROW ); + Reference< XWindow > xEmbeddedWindow( xEmbeddedFrame->getContainerWindow(), UNO_SET_THROW ); + xEmbeddedWindow->setVisible( i_bShow ); + } + break; + } +} + +// ----------------------------------------------------------------------------- Any ODocumentDefinition::onCommandOpenSomething( const Any& _rOpenArgument, const bool _bActivate, const Reference< XCommandEnvironment >& _rxEnvironment ) { @@ -871,7 +989,7 @@ Any ODocumentDefinition::onCommandOpenSomething( const Any& _rOpenArgument, cons // for the document, default to the interaction handler as used for loading the DB doc // This might be overwritten below, when examining _rOpenArgument. - ::comphelper::NamedValueCollection aDBDocArgs( m_pImpl->m_pDataSource->getResource() ); + const ::comphelper::NamedValueCollection& aDBDocArgs( m_pImpl->m_pDataSource->getMediaDescriptor() ); Reference< XInteractionHandler > xHandler( aDBDocArgs.getOrDefault( "InteractionHandler", Reference< XInteractionHandler >() ) ); if ( xHandler.is() ) aDocumentArgs.put( "InteractionHandler", xHandler ); @@ -963,10 +1081,6 @@ Any ODocumentDefinition::onCommandOpenSomething( const Any& _rOpenArgument, cons } aDocumentArgs.put( "MacroExecutionMode", *aDocumentMacroMode ); - - if ( xConnection.is() ) - m_xLastKnownConnection = xConnection; - if ( ( nOpenMode == OpenMode::ALL ) || ( nOpenMode == OpenMode::FOLDERS ) || ( nOpenMode == OpenMode::DOCUMENTS ) @@ -1030,8 +1144,14 @@ Any ODocumentDefinition::onCommandOpenSomething( const Any& _rOpenArgument, cons if ( _bActivate && !bOpenHidden ) { + LockModifiable aLockModify( impl_getComponent_throw() ); m_xEmbeddedObject->changeState( EmbedStates::ACTIVE ); - ODocumentDefinition::impl_onActivateEmbeddedObject_nothrow(); + impl_onActivateEmbeddedObject_nothrow( false ); + } + else + { + // ensure that we ourself are kept alive as long as the document is open + LifetimeCoupler::couple( *this, xModel.get() ); } if ( !m_bForm && m_pImpl->m_aProps.bAsTemplate && !m_bOpenInDesign ) @@ -1077,14 +1197,17 @@ Any SAL_CALL ODocumentDefinition::execute( const Command& aCommand, sal_Int32 Co sal_Int32 nCurrentState = m_xEmbeddedObject->getCurrentState(); bool bIsActive = ( nCurrentState == EmbedStates::ACTIVE ); - // exception: new-style reports always create a new document when "open" is executed - Reference< report::XReportDefinition > xReportDefinition( getComponent(), UNO_QUERY ); - bool bIsAliveNewStyleReport = ( xReportDefinition.is() && ( bOpen || bOpenForMail ) ); - - if ( bIsActive && !bIsAliveNewStyleReport ) + if ( bIsActive ) { - ODocumentDefinition::impl_onActivateEmbeddedObject_nothrow(); - return makeAny( getComponent() ); + // exception: new-style reports always create a new document when "open" is executed + Reference< report::XReportDefinition > xReportDefinition( impl_getComponent_throw( false ), UNO_QUERY ); + bool bIsAliveNewStyleReport = ( xReportDefinition.is() && ( bOpen || bOpenForMail ) ); + + if ( !bIsAliveNewStyleReport ) + { + impl_onActivateEmbeddedObject_nothrow( true ); + return makeAny( getComponent() ); + } } } @@ -1117,16 +1240,6 @@ Any SAL_CALL ODocumentDefinition::execute( const Command& aCommand, sal_Int32 Co Reference< XStorage> xStorage = getContainerStorage(); // ----------------------------------------------------------------------------- xStorage->copyElementTo(m_pImpl->m_aProps.sPersistentName,xDest,sPersistentName); - /*loadEmbeddedObject( true ); - Reference<XEmbedPersist> xPersist(m_xEmbeddedObject,UNO_QUERY); - if ( xPersist.is() ) - { - xPersist->storeToEntry(xStorage,sPersistentName,Sequence<PropertyValue>(),Sequence<PropertyValue>()); - xPersist->storeOwn(); - m_xEmbeddedObject->changeState(EmbedStates::LOADED); - } - else - throw CommandAbortedException();*/ } else if ( aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "preview" ) ) ) { @@ -1182,6 +1295,14 @@ Any SAL_CALL ODocumentDefinition::execute( const Command& aCommand, sal_Int32 Co { aRet <<= impl_close_throw(); } + else if ( aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "show" ) ) ) + { + impl_showOrHideComponent_throw( true ); + } + else if ( aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "hide" ) ) ) + { + impl_showOrHideComponent_throw( false ); + } else { aRet = OContentHelper::execute(aCommand,CommandId,Environment); @@ -1361,7 +1482,7 @@ sal_Bool ODocumentDefinition::save(sal_Bool _bApprove) pRequest->addContinuation(pAbort); // create the handler, let it handle the request - Reference< XInteractionHandler > xHandler( m_aContext.createComponent( (::rtl::OUString)SERVICE_SDB_INTERACTION_HANDLER ), UNO_QUERY ); + Reference< XInteractionHandler > xHandler( m_aContext.createComponent( (::rtl::OUString)SERVICE_TASK_INTERACTION_HANDLER ), UNO_QUERY ); if ( xHandler.is() ) xHandler->handle(xRequest); @@ -1371,16 +1492,16 @@ sal_Bool ODocumentDefinition::save(sal_Bool _bApprove) return sal_True; if ( pDocuSave && pDocuSave->wasSelected() ) { - ::osl::MutexGuard aGuard(m_aMutex); - Reference<XNameContainer> xNC(pDocuSave->getContent(),UNO_QUERY); - if ( xNC.is() ) - { - m_pImpl->m_aProps.aTitle = pDocuSave->getName(); - Reference< XContent> xContent = this; - xNC->insertByName(pDocuSave->getName(),makeAny(xContent)); + Reference<XNameContainer> xNC( pDocuSave->getContent(), UNO_QUERY_THROW ); - updateDocumentTitle(); - } + ::osl::ResettableMutexGuard aGuard( m_aMutex ); + NameChangeNotifier aNameChangeAndNotify( *this, pDocuSave->getName(), aGuard ); + m_pImpl->m_aProps.aTitle = pDocuSave->getName(); + + Reference< XContent> xContent = this; + xNC->insertByName(pDocuSave->getName(),makeAny(xContent)); + + updateDocumentTitle(); } } @@ -1436,7 +1557,7 @@ sal_Bool ODocumentDefinition::saveAs() pRequest->addContinuation(pAbort); // create the handler, let it handle the request - Reference< XInteractionHandler > xHandler(m_aContext.createComponent(::rtl::OUString(SERVICE_SDB_INTERACTION_HANDLER)), UNO_QUERY); + Reference< XInteractionHandler > xHandler(m_aContext.createComponent(::rtl::OUString(SERVICE_TASK_INTERACTION_HANDLER)), UNO_QUERY); if ( xHandler.is() ) xHandler->handle(xRequest); @@ -1578,8 +1699,30 @@ sal_Bool ODocumentDefinition::objectSupportsEmbeddedScripts() const } // ----------------------------------------------------------------------------- +void ODocumentDefinition::separateOpenCommandArguments( const Sequence< PropertyValue >& i_rOpenCommandArguments, + ::comphelper::NamedValueCollection& o_rDocumentLoadArgs, ::comphelper::NamedValueCollection& o_rEmbeddedObjectDescriptor ) +{ + ::comphelper::NamedValueCollection aOpenCommandArguments( i_rOpenCommandArguments ); + + const sal_Char* pObjectDescriptorArgs[] = + { + "RecoveryStorage" + }; + for ( size_t i=0; i < sizeof( pObjectDescriptorArgs ) / sizeof( pObjectDescriptorArgs[0] ); ++i ) + { + if ( aOpenCommandArguments.has( pObjectDescriptorArgs[i] ) ) + { + o_rEmbeddedObjectDescriptor.put( pObjectDescriptorArgs[i], aOpenCommandArguments.get( pObjectDescriptorArgs[i] ) ); + aOpenCommandArguments.remove( pObjectDescriptorArgs[i] ); + } + } + + o_rDocumentLoadArgs.merge( aOpenCommandArguments, false ); +} + +// ----------------------------------------------------------------------------- Sequence< PropertyValue > ODocumentDefinition::fillLoadArgs( const Reference< XConnection>& _xConnection, const bool _bSuppressMacros, const bool _bReadOnly, - const Sequence< PropertyValue >& _rAdditionalArgs, Sequence< PropertyValue >& _out_rEmbeddedObjectDescriptor ) + const Sequence< PropertyValue >& i_rOpenCommandArguments, Sequence< PropertyValue >& _out_rEmbeddedObjectDescriptor ) { // ......................................................................... // (re-)create interceptor, and put it into the descriptor of the embedded object @@ -1598,6 +1741,10 @@ Sequence< PropertyValue > ODocumentDefinition::fillLoadArgs( const Reference< XC aEmbeddedDescriptor.put( "OutplaceDispatchInterceptor", xInterceptor ); // ......................................................................... + ::comphelper::NamedValueCollection aMediaDesc; + separateOpenCommandArguments( i_rOpenCommandArguments, aMediaDesc, aEmbeddedDescriptor ); + + // ......................................................................... // create the OutplaceFrameProperties, and put them into the descriptor of the embedded object ::comphelper::NamedValueCollection OutplaceFrameProperties; OutplaceFrameProperties.put( "TopWindow", (sal_Bool)sal_True ); @@ -1630,11 +1777,12 @@ Sequence< PropertyValue > ODocumentDefinition::fillLoadArgs( const Reference< XC aEmbeddedDescriptor.put( "EmbeddedScriptSupport", (sal_Bool)objectSupportsEmbeddedScripts() ); // ......................................................................... - // pass the descriptor of the embedded object to the caller - aEmbeddedDescriptor >>= _out_rEmbeddedObjectDescriptor; + // tell the embedded object to not participate in the document recovery game - the DB doc will handle it + aEmbeddedDescriptor.put( "DocumentRecoverySupport", (sal_Bool)sal_False ); // ......................................................................... - ::comphelper::NamedValueCollection aMediaDesc( _rAdditionalArgs ); + // pass the descriptor of the embedded object to the caller + aEmbeddedDescriptor >>= _out_rEmbeddedObjectDescriptor; // ......................................................................... // create the ComponentData, and put it into the document's media descriptor @@ -1657,8 +1805,8 @@ Sequence< PropertyValue > ODocumentDefinition::fillLoadArgs( const Reference< XC return aMediaDesc.getPropertyValues(); } // ----------------------------------------------------------------------------- -void ODocumentDefinition::loadEmbeddedObject( const Reference< XConnection >& _xConnection, const Sequence< sal_Int8 >& _aClassID, - const Sequence< PropertyValue >& _rAdditionalArgs, const bool _bSuppressMacros, const bool _bReadOnly ) +void ODocumentDefinition::loadEmbeddedObject( const Reference< XConnection >& i_rConnection, const Sequence< sal_Int8 >& _aClassID, + const Sequence< PropertyValue >& i_rOpenCommandArguments, const bool _bSuppressMacros, const bool _bReadOnly ) { if ( !m_xEmbeddedObject.is() ) { @@ -1684,7 +1832,7 @@ void ODocumentDefinition::loadEmbeddedObject( const Reference< XConnection >& _x // the com.sun.star.report.pentaho.SOReportJobFactory is not present. if ( !m_bForm && !sDocumentService.equalsAscii("com.sun.star.text.TextDocument")) { - // we seems to be a new report, check if report extension is present. + // we seem to be a "new style" report, check if report extension is present. Reference< XContentEnumerationAccess > xEnumAccess( m_aContext.getLegacyServiceFactory(), UNO_QUERY ); const ::rtl::OUString sReportEngineServiceName = ::dbtools::getDefaultReportEngineServiceName(m_aContext.getLegacyServiceFactory()); Reference< XEnumeration > xEnumDrivers = xEnumAccess->createContentEnumeration(sReportEngineServiceName); @@ -1710,7 +1858,7 @@ void ODocumentDefinition::loadEmbeddedObject( const Reference< XConnection >& _x Sequence< PropertyValue > aEmbeddedObjectDescriptor; Sequence< PropertyValue > aLoadArgs( fillLoadArgs( - _xConnection, _bSuppressMacros, _bReadOnly, _rAdditionalArgs, aEmbeddedObjectDescriptor ) ); + i_rConnection, _bSuppressMacros, _bReadOnly, i_rOpenCommandArguments, aEmbeddedObjectDescriptor ) ); m_xEmbeddedObject.set(xEmbedFactory->createInstanceUserInit(aClassID ,sDocumentService @@ -1732,8 +1880,9 @@ void ODocumentDefinition::loadEmbeddedObject( const Reference< XConnection >& _x m_xEmbeddedObject->changeState(EmbedStates::RUNNING); if ( bSetSize ) { - awt::Size aSize( DEFAULT_WIDTH, DEFAULT_HEIGHT ); + LockModifiable aLockModify( impl_getComponent_throw( false ) ); + awt::Size aSize( DEFAULT_WIDTH, DEFAULT_HEIGHT ); m_xEmbeddedObject->setVisualAreaSize(Aspects::MSOLE_CONTENT,aSize); } } @@ -1755,7 +1904,7 @@ void ODocumentDefinition::loadEmbeddedObject( const Reference< XConnection >& _x Sequence< PropertyValue > aEmbeddedObjectDescriptor; Sequence< PropertyValue > aLoadArgs( fillLoadArgs( - _xConnection, _bSuppressMacros, _bReadOnly, _rAdditionalArgs, aEmbeddedObjectDescriptor ) ); + i_rConnection, _bSuppressMacros, _bReadOnly, i_rOpenCommandArguments, aEmbeddedObjectDescriptor ) ); Reference<XCommonEmbedPersist> xCommon(m_xEmbeddedObject,UNO_QUERY); OSL_ENSURE(xCommon.is(),"unsupported interface!"); @@ -1772,21 +1921,25 @@ void ODocumentDefinition::loadEmbeddedObject( const Reference< XConnection >& _x // then just re-set some model parameters try { - Reference< XModel > xModel( getComponent(), UNO_QUERY_THROW ); - Sequence< PropertyValue > aArgs = xModel->getArgs(); - - ::comphelper::NamedValueCollection aMediaDesc( aArgs ); - ::comphelper::NamedValueCollection aArguments( _rAdditionalArgs ); - aMediaDesc.merge( aArguments, sal_False ); - - lcl_putLoadArgs( aMediaDesc, optional_bool(), optional_bool() ); + // ensure the media descriptor doesn't contain any values which are intended for the + // EmbeddedObjectDescriptor only + ::comphelper::NamedValueCollection aEmbeddedObjectDescriptor; + ::comphelper::NamedValueCollection aNewMediaDesc; + separateOpenCommandArguments( i_rOpenCommandArguments, aNewMediaDesc, aEmbeddedObjectDescriptor ); + + // merge the new media descriptor into the existing media descriptor + const Reference< XModel > xModel( getComponent(), UNO_QUERY_THROW ); + const Sequence< PropertyValue > aArgs = xModel->getArgs(); + ::comphelper::NamedValueCollection aExistentMediaDesc( aArgs ); + aExistentMediaDesc.merge( aNewMediaDesc, sal_False ); + + lcl_putLoadArgs( aExistentMediaDesc, optional_bool(), optional_bool() ); // don't put _bSuppressMacros and _bReadOnly here - if the document was already // loaded, we should not tamper with its settings. // #i88977# / 2008-05-05 / frank.schoenheit@sun.com // #i86872# / 2008-03-13 / frank.schoenheit@sun.com - aMediaDesc >>= aArgs; - xModel->attachResource( xModel->getURL(), aArgs ); + xModel->attachResource( xModel->getURL(), aExistentMediaDesc.getPropertyValues() ); } catch( const Exception& ) { @@ -1812,6 +1965,9 @@ void ODocumentDefinition::loadEmbeddedObject( const Reference< XConnection >& _x DBG_UNHANDLED_EXCEPTION(); } } + + if ( i_rConnection.is() ) + m_xLastKnownConnection = i_rConnection; } // ----------------------------------------------------------------------------- @@ -1863,18 +2019,18 @@ void ODocumentDefinition::onCommandGetDocumentProperties( Any& _rProps ) } } // ----------------------------------------------------------------------------- -Reference< util::XCloseable> ODocumentDefinition::getComponent() throw (RuntimeException) +Reference< util::XCloseable > ODocumentDefinition::impl_getComponent_throw( const bool i_ForceCreate ) { OSL_ENSURE(m_xEmbeddedObject.is(),"Illegal call for embeddedObject"); - Reference< util::XCloseable> xComp; + Reference< util::XCloseable > xComp; if ( m_xEmbeddedObject.is() ) { - int nOldState = m_xEmbeddedObject->getCurrentState(); - int nState = nOldState; - if ( nOldState == EmbedStates::LOADED ) + int nState = m_xEmbeddedObject->getCurrentState(); + if ( ( nState == EmbedStates::LOADED ) && i_ForceCreate ) { m_xEmbeddedObject->changeState( EmbedStates::RUNNING ); - nState = EmbedStates::RUNNING; + nState = m_xEmbeddedObject->getCurrentState(); + OSL_ENSURE( nState == EmbedStates::RUNNING, "ODocumentDefinition::impl_getComponent_throw: could not switch to RUNNING!" ); } if ( nState == EmbedStates::ACTIVE || nState == EmbedStates::RUNNING ) @@ -1891,6 +2047,13 @@ Reference< util::XCloseable> ODocumentDefinition::getComponent() throw (RuntimeE } // ----------------------------------------------------------------------------- +Reference< util::XCloseable > ODocumentDefinition::getComponent() throw (RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + return impl_getComponent_throw( true ); +} + +// ----------------------------------------------------------------------------- namespace { Reference< XDatabaseDocumentUI > lcl_getDatabaseDocumentUI( ODatabaseModelImpl& _rModelImpl ) @@ -2011,13 +2174,29 @@ void SAL_CALL ODocumentDefinition::store( ) throw (WrappedTargetException, Runt return bSuccess; } +// ----------------------------------------------------------------------------- +::rtl::OUString SAL_CALL ODocumentDefinition::getHierarchicalName() throw (RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + return impl_getHierarchicalName( false ); +} + +// ----------------------------------------------------------------------------- +::rtl::OUString SAL_CALL ODocumentDefinition::composeHierarchicalName( const ::rtl::OUString& i_rRelativeName ) throw (IllegalArgumentException, NoSupportException, RuntimeException) +{ + ::rtl::OUStringBuffer aBuffer; + aBuffer.append( getHierarchicalName() ); + aBuffer.append( sal_Unicode( '/' ) ); + aBuffer.append( i_rRelativeName ); + return aBuffer.makeStringAndClear(); +} // ----------------------------------------------------------------------------- void SAL_CALL ODocumentDefinition::rename( const ::rtl::OUString& _rNewName ) throw (SQLException, ElementExistException, RuntimeException) { try { - osl::ClearableGuard< osl::Mutex > aGuard(m_aMutex); + ::osl::ResettableMutexGuard aGuard(m_aMutex); if ( _rNewName.equals( m_pImpl->m_aProps.aTitle ) ) return; @@ -2026,16 +2205,9 @@ void SAL_CALL ODocumentDefinition::rename( const ::rtl::OUString& _rNewName ) th if ( _rNewName.indexOf( '/' ) != -1 ) m_aErrorHelper.raiseException( ErrorCondition::DB_OBJECT_NAME_WITH_SLASHES, *this ); - sal_Int32 nHandle = PROPERTY_ID_NAME; - Any aOld = makeAny( m_pImpl->m_aProps.aTitle ); - Any aNew = makeAny( _rNewName ); - - aGuard.clear(); - fire(&nHandle, &aNew, &aOld, 1, sal_True ); + NameChangeNotifier aNameChangeAndNotify( *this, _rNewName, aGuard ); m_pImpl->m_aProps.aTitle = _rNewName; - fire(&nHandle, &aNew, &aOld, 1, sal_False ); - ::osl::ClearableGuard< ::osl::Mutex > aGuard2( m_aMutex ); if ( m_xEmbeddedObject.is() && m_xEmbeddedObject->getCurrentState() == EmbedStates::ACTIVE ) updateDocumentTitle(); } @@ -2076,7 +2248,11 @@ bool ODocumentDefinition::prepareClose() // by the embedding component. Thus, we do the suspend call here. // #i49370# / 2005-06-09 / frank.schoenheit@sun.com - Reference< XModel > xModel( getComponent(), UNO_QUERY ); + Reference< util::XCloseable > xComponent( impl_getComponent_throw( false ) ); + if ( !xComponent.is() ) + return true; + + Reference< XModel > xModel( xComponent, UNO_QUERY ); Reference< XController > xController; if ( xModel.is() ) xController = xModel->getCurrentController(); @@ -2190,6 +2366,43 @@ void SAL_CALL ODocumentDefinition::notifyClosing( const lang::EventObject& /*Sou void SAL_CALL ODocumentDefinition::disposing( const lang::EventObject& /*Source*/ ) throw (uno::RuntimeException) { } + +// ----------------------------------------------------------------------------- +void ODocumentDefinition::firePropertyChange( sal_Int32 i_nHandle, const Any& i_rNewValue, const Any& i_rOldValue, + sal_Bool i_bVetoable, const NotifierAccess ) +{ + fire( &i_nHandle, &i_rNewValue, &i_rOldValue, 1, i_bVetoable ); +} + +// ============================================================================= +// NameChangeNotifier +// ============================================================================= +// ----------------------------------------------------------------------------- +NameChangeNotifier::NameChangeNotifier( ODocumentDefinition& i_rDocumentDefinition, const ::rtl::OUString& i_rNewName, + ::osl::ResettableMutexGuard& i_rClearForNotify ) + :m_rDocumentDefinition( i_rDocumentDefinition ) + ,m_aOldValue( makeAny( i_rDocumentDefinition.getCurrentName() ) ) + ,m_aNewValue( makeAny( i_rNewName ) ) + ,m_rClearForNotify( i_rClearForNotify ) +{ + impl_fireEvent_throw( sal_True ); +} + +// ----------------------------------------------------------------------------- +NameChangeNotifier::~NameChangeNotifier() +{ + impl_fireEvent_throw( sal_False ); +} + +// ----------------------------------------------------------------------------- +void NameChangeNotifier::impl_fireEvent_throw( const sal_Bool i_bVetoable ) +{ + m_rClearForNotify.clear(); + m_rDocumentDefinition.firePropertyChange( + PROPERTY_ID_NAME, m_aNewValue, m_aOldValue, i_bVetoable, ODocumentDefinition::NotifierAccess() ); + m_rClearForNotify.reset(); +} + //........................................................................ } // namespace dbaccess //........................................................................ diff --git a/dbaccess/source/core/dataaccess/documentdefinition.hxx b/dbaccess/source/core/dataaccess/documentdefinition.hxx index b2ca8f49f7bb..76427ea78baf 100644 --- a/dbaccess/source/core/dataaccess/documentdefinition.hxx +++ b/dbaccess/source/core/dataaccess/documentdefinition.hxx @@ -31,8 +31,8 @@ #ifndef _CPPUHELPER_PROPSHLP_HXX #include <cppuhelper/propshlp.hxx> #endif -#ifndef _CPPUHELPER_IMPLBASE3_HXX_ -#include <cppuhelper/implbase3.hxx> +#ifndef _CPPUHELPER_IMPLBASE4_HXX_ +#include <cppuhelper/implbase4.hxx> #endif #ifndef DBA_CONTENTHELPER_HXX #include "ContentHelper.hxx" @@ -63,6 +63,12 @@ #endif #include <com/sun/star/sdb/XSubDocument.hpp> #include <com/sun/star/util/XCloseListener.hpp> +#include <com/sun/star/container/XHierarchicalName.hpp> + +namespace comphelper +{ + class NamedValueCollection; +} //........................................................................ namespace dbaccess @@ -76,9 +82,10 @@ namespace dbaccess //= document //========================================================================== -typedef ::cppu::ImplHelper3 < ::com::sun::star::embed::XComponentSupplier +typedef ::cppu::ImplHelper4 < ::com::sun::star::embed::XComponentSupplier , ::com::sun::star::sdb::XSubDocument , ::com::sun::star::util::XCloseListener + , ::com::sun::star::container::XHierarchicalName > ODocumentDefinition_Base; class ODocumentDefinition @@ -104,14 +111,18 @@ protected: public: ODocumentDefinition( - const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxContainer - ,const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& - ,const TContentPtr& _pImpl - ,sal_Bool _bForm - ,const ::com::sun::star::uno::Sequence< sal_Int8 >& _aClassID = ::com::sun::star::uno::Sequence< sal_Int8 >() - ,const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection>& _xConnection = ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection>() + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxContainer, + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >&, + const TContentPtr& _pImpl, + sal_Bool _bForm ); + void initialLoad( + const ::com::sun::star::uno::Sequence< sal_Int8 >& i_rClassID, + const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& i_rCreationArgs, + const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& i_rConnection + ); + // com::sun::star::lang::XTypeProvider DECLARE_TYPEPROVIDER( ); @@ -124,6 +135,12 @@ public: // ::com::sun::star::beans::XPropertySet virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) throw(::com::sun::star::uno::RuntimeException); + // OPropertySetHelper + virtual void SAL_CALL getFastPropertyValue( + ::com::sun::star::uno::Any& o_rValue, + sal_Int32 i_nHandle + ) const; + // XComponentSupplier virtual ::com::sun::star::uno::Reference< ::com::sun::star::util::XCloseable > SAL_CALL getComponent( ) throw (::com::sun::star::uno::RuntimeException); @@ -133,6 +150,10 @@ public: virtual void SAL_CALL store( ) throw (::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); virtual ::sal_Bool SAL_CALL close( ) throw (::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + // XHierarchicalName + virtual ::rtl::OUString SAL_CALL getHierarchicalName( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL composeHierarchicalName( const ::rtl::OUString& aRelativeName ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException); + // OPropertySetHelper virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(); @@ -194,10 +215,20 @@ public: ::com::sun::star::uno::Sequence< sal_Int8 >& _rClassId ); + struct NotifierAccess { friend class NameChangeNotifier; private: NotifierAccess() { } }; + const ::rtl::OUString& getCurrentName() const { return m_pImpl->m_aProps.aTitle; } + void firePropertyChange( + sal_Int32 i_nHandle, + const ::com::sun::star::uno::Any& i_rNewValue, + const ::com::sun::star::uno::Any& i_rOldValue, + sal_Bool i_bVetoable, + const NotifierAccess + ); + private: /** does necessary initializations after our embedded object has been switched to ACTIVE */ - void impl_onActivateEmbeddedObject_nothrow(); + void impl_onActivateEmbeddedObject_nothrow( const bool i_bReactivated ); /** initializes a newly created view/controller of a form which is displaying our embedded object @@ -220,19 +251,27 @@ private: /** opens the UI for this sub document */ ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > - impl_openUI_nolck_throw( bool _bForEditing ); + impl_openUI_nolck_throw( bool _bForEditing ); /** stores our document, if it's already loaded */ - void - impl_store_throw(); + void impl_store_throw(); /** closes our document, if it's open */ - bool - impl_close_throw(); + bool impl_close_throw(); + + /** returns our component, creates it if necessary + */ + ::com::sun::star::uno::Reference< ::com::sun::star::util::XCloseable > + impl_getComponent_throw( const bool i_ForceCreate = true ); + + /** shows or hides our component + + The embedded object must exist, and be in state LOADED, at least. + */ + void impl_showOrHideComponent_throw( const bool i_bShow ); -private: // OPropertyArrayUsageHelper virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const; @@ -244,7 +283,6 @@ private: // OContentHelper overridables virtual ::rtl::OUString determineContentType() const; -private: /** fills the load arguments */ ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > @@ -252,10 +290,30 @@ private: const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection>& _xConnection, const bool _bSuppressMacros, const bool _bReadOnly, - const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& _rAdditionalArgs, + const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& i_rOpenCommandArguments, ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& _out_rEmbeddedObjectDescriptor ); + /** splits the given arguments to an "open*" command into arguments for loading the document, and arguments to be + put into the EmbeddedObjectDescriptor + + Any values already present in <code>o_rDocumentLoadArgs</code> and <code>o_rEmbeddedObjectDescriptor</code> + will be overwritten by values from <code>i_rOpenCommandArguments</code>, if applicable, otherwise they will + be preserved. + + @param i_rOpenCommandArguments + the arguments passed to the "open*" command at the content + @param o_rDocumentLoadArgs + the arguments to be passed when actually loading the embedded document. + @param o_rEmbeddedObjectDescriptor + the EmbeddedObjectDescriptor to be passed when initializing the embedded object + */ + void separateOpenCommandArguments( + const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& i_rOpenCommandArguments, + ::comphelper::NamedValueCollection& o_rDocumentLoadArgs, + ::comphelper::NamedValueCollection& o_rEmbeddedObjectDescriptor + ); + /** loads the EmbeddedObject if not already loaded @param _aClassID If set, it will be used to create the embedded object. @@ -321,6 +379,27 @@ private: const bool _bActivate, const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >& _rxEnvironment ); +private: + using ::cppu::OPropertySetHelper::getFastPropertyValue; +}; + +class NameChangeNotifier +{ +public: + NameChangeNotifier( + ODocumentDefinition& i_rDocumentDefinition, + const ::rtl::OUString& i_rNewName, + ::osl::ResettableMutexGuard& i_rClearForNotify + ); + ~NameChangeNotifier(); + +private: + ODocumentDefinition& m_rDocumentDefinition; + const ::com::sun::star::uno::Any m_aOldValue; + const ::com::sun::star::uno::Any m_aNewValue; + mutable ::osl::ResettableMutexGuard& m_rClearForNotify; + + void impl_fireEvent_throw( const sal_Bool i_bVetoable ); }; //........................................................................ diff --git a/dbaccess/source/core/dataaccess/makefile.mk b/dbaccess/source/core/dataaccess/makefile.mk index 5d804e911ae7..831eae349858 100644 --- a/dbaccess/source/core/dataaccess/makefile.mk +++ b/dbaccess/source/core/dataaccess/makefile.mk @@ -61,7 +61,7 @@ SLOFILES= \ $(SLO)$/ModelImpl.obj \ $(SLO)$/documentevents.obj \ $(SLO)$/documenteventexecutor.obj \ - $(SLO)$/documenteventnotifier.obj + $(SLO)$/documenteventnotifier.obj \ # --- Targets ---------------------------------- diff --git a/dbaccess/source/core/inc/ContentHelper.hxx b/dbaccess/source/core/inc/ContentHelper.hxx index 6d3a8a59e0e9..10c5df0cd5f3 100644 --- a/dbaccess/source/core/inc/ContentHelper.hxx +++ b/dbaccess/source/core/inc/ContentHelper.hxx @@ -107,10 +107,12 @@ namespace dbaccess sal_Bool bAsTemplate; // AsTemplate ::rtl::OUString sPersistentName;// persistent name of the document - // @@@ Add other properties supported by your content. - ContentProperties() - : bIsDocument( sal_True ), bIsFolder( sal_False ), bAsTemplate( sal_False ) {} + :bIsDocument( sal_True ) + ,bIsFolder( sal_False ) + ,bAsTemplate( sal_False ) + { + } }; class OContentHelper_Impl diff --git a/dbaccess/source/core/inc/View.hxx b/dbaccess/source/core/inc/View.hxx new file mode 100644 index 000000000000..4e96a1882423 --- /dev/null +++ b/dbaccess/source/core/inc/View.hxx @@ -0,0 +1,91 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: View.hxx,v $ + * $Revision: 1.3 $ + * + * 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. + * + ************************************************************************/ + +#ifndef DBACCESS_VIEW_HXX +#define DBACCESS_VIEW_HXX + +#include "connectivity/sdbcx/VView.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/sdbcx/XAlterView.hpp> +#include <com/sun/star/sdb/tools/XViewAccess.hpp> +/** === end UNO includes === **/ + +#include <comphelper/uno3.hxx> +#include <cppuhelper/implbase1.hxx> + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + + //==================================================================== + //= View + //==================================================================== + typedef ::connectivity::sdbcx::OView View_Base; + typedef ::cppu::ImplHelper1< ::com::sun::star::sdbcx::XAlterView > View_IBASE; + class View :public View_Base + ,public View_IBASE + { + public: + View( + const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _rxConnection, + sal_Bool _bCaseSensitive, + const ::rtl::OUString& _rCatalogName, + const ::rtl::OUString& _rSchemaName, + const ::rtl::OUString& _rName + ); + + // UNO + DECLARE_XINTERFACE() + DECLARE_XTYPEPROVIDER() + + // XAlterView + virtual void SAL_CALL alterCommand( const ::rtl::OUString& NewCommand ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + protected: + virtual ~View(); + + protected: + // OPropertyContainer + virtual void SAL_CALL getFastPropertyValue( ::com::sun::star::uno::Any& _rValue, sal_Int32 _nHandle ) const; + + private: + ::com::sun::star::uno::Reference< ::com::sun::star::sdb::tools::XViewAccess> m_xViewAccess; + sal_Int32 m_nCommandHandle; + private: + using View_Base::getFastPropertyValue; + }; + +//........................................................................ +} // namespace dbaccess +//........................................................................ + +#endif // DBACCESS_VIEW_HXX diff --git a/dbaccess/source/core/inc/definitioncolumn.hxx b/dbaccess/source/core/inc/definitioncolumn.hxx index 1e8219845d3e..d77aad2b6efd 100644 --- a/dbaccess/source/core/inc/definitioncolumn.hxx +++ b/dbaccess/source/core/inc/definitioncolumn.hxx @@ -164,7 +164,8 @@ namespace dbaccess public: OQueryColumn( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet>& _rxParserColumn, - const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _rxConnection + const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _rxConnection, + const ::rtl::OUString& _sNewName ); // XTypeProvider diff --git a/dbaccess/source/core/inc/recovery/dbdocrecovery.hxx b/dbaccess/source/core/inc/recovery/dbdocrecovery.hxx new file mode 100644 index 000000000000..4aa124dc7015 --- /dev/null +++ b/dbaccess/source/core/inc/recovery/dbdocrecovery.hxx @@ -0,0 +1,92 @@ +/************************************************************************* +* 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. +************************************************************************/ + +#ifndef DBACCESS_DBDOCRECOVERY_HXX +#define DBACCESS_DBDOCRECOVERY_HXX + +#include "dbaccessdllapi.h" + +/** === begin UNO includes === **/ +#include <com/sun/star/embed/XStorage.hpp> +#include <com/sun/star/frame/XController.hpp> +/** === end UNO includes === **/ + +#include <vector> +#include <memory> + +namespace comphelper +{ + class ComponentContext; +} + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + + //==================================================================== + //= DatabaseDocumentRecovery + //==================================================================== + struct DatabaseDocumentRecovery_Data; + class DBACCESS_DLLPRIVATE DatabaseDocumentRecovery + { + public: + DatabaseDocumentRecovery( + const ::comphelper::ComponentContext& i_rContext + ); + ~DatabaseDocumentRecovery(); + + /** saves the modified sub components of the given controller(s) to the "recovery" sub storage of the document + storage. + + @throws ::com::sun::star::uno::Exception + in case of an error. + */ + void saveModifiedSubComponents( + const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& i_rTargetStorage, + const ::std::vector< ::com::sun::star::uno::Reference< ::com::sun::star::frame::XController > >& i_rControllers + ); + + /** recovery sub components from the given document storage, if applicable + + If the given document storage does not contain a recovery folder, the method silently returns. + + @throws ::com::sun::star::uno::Exception + in case of an error. + */ + void recoverSubDocuments( + const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& i_rDocumentStorage, + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XController >& i_rTargetController + ); + + private: + const ::std::auto_ptr< DatabaseDocumentRecovery_Data > m_pData; + }; + +//........................................................................ +} // namespace dbaccess +//........................................................................ + +#endif // DBACCESS_DBDOCRECOVERY_HXX diff --git a/dbaccess/source/core/inc/sdbcoretools.hxx b/dbaccess/source/core/inc/sdbcoretools.hxx index 6e26bf55b254..d6044a6b9110 100644 --- a/dbaccess/source/core/inc/sdbcoretools.hxx +++ b/dbaccess/source/core/inc/sdbcoretools.hxx @@ -28,8 +28,14 @@ #ifndef DBACORE_SDBCORETOOLS_HXX #define DBACORE_SDBCORETOOLS_HXX +/** === begin UNO includes === **/ #include <com/sun/star/util/XNumberFormatsSupplier.hpp> #include <com/sun/star/sdbc/XConnection.hpp> +#include <com/sun/star/embed/XStorage.hpp> +#include <com/sun/star/io/IOException.hpp> +#include <com/sun/star/lang/WrappedTargetException.hpp> +#include <com/sun/star/uno/RuntimeException.hpp> +/** === end UNO includes === **/ namespace comphelper { @@ -49,32 +55,32 @@ namespace dbaccess getDataSource( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxDependentObject ); // ----------------------------------------------------------------------------- - /** retrieves a particular indirect data source setting - - @param _rxDataSource - a data source component - @param _pAsciiSettingsName - the ASCII name of the setting to obtain - @param _rSettingsValue - the value of the setting, upon successfull return - - @return - <FALSE/> if the setting is not present in the <member scope="com::sun::star::sdb">DataSource::Info</member> - member of the data source - <TRUE/> otherwise - */ - bool getDataSourceSetting( - const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxDataSource, - const sal_Char* _pAsciiSettingsName, - ::com::sun::star::uno::Any& /* [out] */ _rSettingsValue - ); // ----------------------------------------------------------------------------- /** retrieves a to-be-displayed string for a given caught exception; */ ::rtl::OUString extractExceptionMessage( const ::comphelper::ComponentContext& _rContext, const ::com::sun::star::uno::Any& _rError ); -//......................................................................... + namespace tools + { + namespace stor + { + bool storageIsWritable_nothrow( + const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& _rxStorage + ); + + /// commits a given storage if it's not readonly + bool commitStorageIfWriteable( + const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& _rxStorage + ) + SAL_THROW(( + ::com::sun::star::io::IOException, + ::com::sun::star::lang::WrappedTargetException + )); + } + + } + } // namespace dbaccess //......................................................................... diff --git a/dbaccess/source/core/inc/table.hxx b/dbaccess/source/core/inc/table.hxx index 1f2c68889c93..95e984949619 100644 --- a/dbaccess/source/core/inc/table.hxx +++ b/dbaccess/source/core/inc/table.hxx @@ -28,58 +28,24 @@ #ifndef _DBA_CORE_TABLE_HXX_ #define _DBA_CORE_TABLE_HXX_ -#ifndef _COM_SUN_STAR_SDBCX_XCOLUMNSSUPPLIER_HPP_ #include <com/sun/star/sdbcx/XColumnsSupplier.hpp> -#endif -#ifndef _COM_SUN_STAR_SDBCX_XDATADESCRIPTORFACTORY_HPP_ #include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp> -#endif -#ifndef _COM_SUN_STAR_SDBCX_XINDEXESSUPPLIER_HPP_ #include <com/sun/star/sdbcx/XIndexesSupplier.hpp> -#endif -#ifndef _COM_SUN_STAR_SDBCX_XKEYSSUPPLIER_HPP_ #include <com/sun/star/sdbcx/XKeysSupplier.hpp> -#endif -#ifndef _COM_SUN_STAR_SDBCX_XRENAME_HPP_ #include <com/sun/star/sdbcx/XRename.hpp> -#endif -#ifndef _COM_SUN_STAR_SDBCX_XALTERTABLE_HPP_ #include <com/sun/star/sdbcx/XAlterTable.hpp> -#endif -#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_ #include <com/sun/star/lang/XServiceInfo.hpp> -#endif -#ifndef _COM_SUN_STAR_SDBC_XROW_HPP_ #include <com/sun/star/sdbc/XRow.hpp> -#endif -#ifndef _COM_SUN_STAR_SDBC_XCONNECTION_HPP_ #include <com/sun/star/sdbc/XConnection.hpp> -#endif -#ifndef _CPPUHELPER_COMPBASE2_HXX_ #include <cppuhelper/compbase7.hxx> -#endif -#ifndef _DBASHARED_APITOOLS_HXX_ #include "apitools.hxx" -#endif -#ifndef _DBA_CORE_DATASETTINGS_HXX_ #include "datasettings.hxx" -#endif -#ifndef _DBA_COREAPI_COLUMN_HXX_ #include <column.hxx> -#endif -#ifndef _CONNECTIVITY_COMMONTOOLS_HXX_ #include <connectivity/CommonTools.hxx> -#endif -#ifndef CONNECTIVITY_TABLEHELPER_HXX #include <connectivity/TTableHelper.hxx> -#endif -#ifndef _COMPHELPER_UNO3_HXX_ #include <comphelper/uno3.hxx> -#endif -#ifndef COMPHELPER_IDPROPERTYARRAYUSAGEHELPER_HXX #include <comphelper/IdPropArrayHelper.hxx> -#endif namespace dbaccess { diff --git a/dbaccess/source/core/misc/DatabaseDataProvider.cxx b/dbaccess/source/core/misc/DatabaseDataProvider.cxx index 631993f7343a..c45f9f98b8a0 100644 --- a/dbaccess/source/core/misc/DatabaseDataProvider.cxx +++ b/dbaccess/source/core/misc/DatabaseDataProvider.cxx @@ -34,6 +34,7 @@ #include <connectivity/FValue.hxx> #include <connectivity/dbtools.hxx> #include <rtl/ustrbuf.hxx> +#include <rtl/math.hxx> #include <com/sun/star/task/XInteractionHandler.hpp> #include <com/sun/star/sdb/XCompletedExecution.hpp> @@ -630,7 +631,14 @@ void DatabaseDataProvider::impl_fillInternalDataProvider_throw(sal_Bool _bHasCat for (sal_Int32 j = _bHasCategories ? 2 : 1,i = 0; j <= nCount; ++j,++i) { aValue.fill(j,aColumnTypes[j-1],xRow); - aRow.push_back(aValue.getDouble()); + if ( aValue.isNull() ) + { + double nValue; + ::rtl::math::setNan( &nValue ); + aRow.push_back(nValue); + } + else + aRow.push_back(aValue.getDouble()); } // for (sal_Int32 j = 2,i = 0; j <= nCount; ++j,++i) aDataValues.push_back(aRow); } // while( xRes->next() && (!m_RowLimit || nRowCount < m_RowLimit) ) diff --git a/dbaccess/source/core/misc/dbastrings.cxx b/dbaccess/source/core/misc/dbastrings.cxx index 55424aea0e57..80f1427842e8 100644 --- a/dbaccess/source/core/misc/dbastrings.cxx +++ b/dbaccess/source/core/misc/dbastrings.cxx @@ -43,6 +43,7 @@ namespace dbaccess //============================================================ //= Properties //============================================================ - IMPLEMENT_CONSTASCII_USTRING(PROPERTY_APPLYFORMDESIGNMODE, "ApplyFormDesignMode"); - + IMPLEMENT_CONSTASCII_USTRING( PROPERTY_APPLYFORMDESIGNMODE, "ApplyFormDesignMode" ); + IMPLEMENT_CONSTASCII_USTRING( PROPERTY_IS_FORM, "IsForm" ); + IMPLEMENT_CONSTASCII_USTRING( PROPERTY_PERSISTENT_PATH, "PersistentPath" ); } diff --git a/dbaccess/source/core/misc/sdbcoretools.cxx b/dbaccess/source/core/misc/sdbcoretools.cxx index 907a36a13f83..dea2328dc907 100644 --- a/dbaccess/source/core/misc/sdbcoretools.cxx +++ b/dbaccess/source/core/misc/sdbcoretools.cxx @@ -38,6 +38,8 @@ #include <com/sun/star/util/XModifiable.hpp> #include <com/sun/star/sdb/XDocumentDataSource.hpp> #include <com/sun/star/task/XInteractionRequestStringResolver.hpp> +#include <com/sun/star/embed/XTransactedObject.hpp> +#include <com/sun/star/embed/ElementModes.hpp> /** === end UNO includes === **/ #include <tools/diagnose_ex.h> @@ -55,10 +57,12 @@ namespace dbaccess using namespace ::com::sun::star::uno; using namespace ::com::sun::star::lang; using namespace ::com::sun::star::util; + using namespace ::com::sun::star::io; using namespace ::com::sun::star::sdbc; using namespace ::com::sun::star::sdb; using namespace ::com::sun::star::beans; using namespace ::com::sun::star::task; + using namespace ::com::sun::star::embed; using namespace ::com::sun::star::container; // ========================================================================= @@ -88,39 +92,6 @@ namespace dbaccess return xReturn; } - // ------------------------------------------------------------------------- - bool getDataSourceSetting( const Reference< XInterface >& _rxDataSource, const sal_Char* _pAsciiSettingsName, - Any& /* [out] */ _rSettingsValue ) - { - bool bIsPresent = false; - try - { - Reference< XPropertySet > xDataSource( _rxDataSource, UNO_QUERY ); - OSL_ENSURE( xDataSource.is(), "getDataSourceSetting: invalid data source object!" ); - if ( !xDataSource.is() ) - return false; - - Sequence< PropertyValue > aSettings; - OSL_VERIFY( xDataSource->getPropertyValue( PROPERTY_INFO ) >>= aSettings ); - const PropertyValue* pSetting = aSettings.getConstArray(); - const PropertyValue* pSettingEnd = aSettings.getConstArray() + aSettings.getLength(); - for ( ; pSetting != pSettingEnd; ++pSetting ) - { - if ( pSetting->Name.equalsAscii( _pAsciiSettingsName ) ) - { - _rSettingsValue = pSetting->Value; - bIsPresent = true; - break; - } - } - } - catch( const Exception& ) - { - OSL_ENSURE( sal_False, "getDataSourceSetting: caught an exception!" ); - } - return bIsPresent; - } - // ----------------------------------------------------------------------------- ::rtl::OUString extractExceptionMessage( const ::comphelper::ComponentContext& _rContext, const Any& _rError ) { @@ -160,7 +131,44 @@ namespace dbaccess return sDisplayMessage; } -// ----------------------------------------------------------------------------- + namespace tools { namespace stor { + + // ----------------------------------------------------------------------------- + bool storageIsWritable_nothrow( const Reference< XStorage >& _rxStorage ) + { + if ( !_rxStorage.is() ) + return false; + + sal_Int32 nMode = ElementModes::READ; + try + { + Reference< XPropertySet > xStorageProps( _rxStorage, UNO_QUERY_THROW ); + xStorageProps->getPropertyValue( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OpenMode" ) ) ) >>= nMode; + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + return ( nMode & ElementModes::WRITE ) != 0; + } + + // ----------------------------------------------------------------------------- + bool commitStorageIfWriteable( const Reference< XStorage >& _rxStorage ) SAL_THROW(( IOException, WrappedTargetException, RuntimeException )) + { + bool bSuccess = false; + Reference< XTransactedObject > xTrans( _rxStorage, UNO_QUERY ); + if ( xTrans.is() ) + { + if ( storageIsWritable_nothrow( _rxStorage ) ) + xTrans->commit(); + bSuccess = true; + } + return bSuccess; + } + + } } // tools::stor + //......................................................................... } // namespace dbaccess //......................................................................... diff --git a/dbaccess/source/core/recovery/dbdocrecovery.cxx b/dbaccess/source/core/recovery/dbdocrecovery.cxx new file mode 100644 index 000000000000..6f31f17682fd --- /dev/null +++ b/dbaccess/source/core/recovery/dbdocrecovery.cxx @@ -0,0 +1,436 @@ +/************************************************************************* +* 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" + +#include "recovery/dbdocrecovery.hxx" +#include "sdbcoretools.hxx" +#include "storagetextstream.hxx" +#include "subcomponentrecovery.hxx" +#include "subcomponents.hxx" +#include "dbastrings.hrc" + +/** === begin UNO includes === **/ +#include <com/sun/star/sdb/application/XDatabaseDocumentUI.hpp> +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/document/XStorageBasedDocument.hpp> +#include <com/sun/star/io/XTextOutputStream.hpp> +#include <com/sun/star/io/XTextInputStream.hpp> +#include <com/sun/star/io/XActiveDataSource.hpp> +#include <com/sun/star/io/XActiveDataSink.hpp> +#include <com/sun/star/util/XModifiable.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +/** === end UNO includes === **/ + +#include <comphelper/componentcontext.hxx> +#include <comphelper/namedvaluecollection.hxx> +#include <rtl/ustrbuf.hxx> +#include <tools/diagnose_ex.h> + +#include <algorithm> + +//........................................................................ +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::lang::XComponent; + using ::com::sun::star::document::XStorageBasedDocument; + using ::com::sun::star::beans::PropertyValue; + using ::com::sun::star::io::XStream; + using ::com::sun::star::io::XTextOutputStream; + using ::com::sun::star::io::XActiveDataSource; + using ::com::sun::star::io::XTextInputStream; + using ::com::sun::star::io::XActiveDataSink; + using ::com::sun::star::frame::XModel; + using ::com::sun::star::util::XModifiable; + using ::com::sun::star::beans::XPropertySet; + using ::com::sun::star::lang::XMultiServiceFactory; + /** === end UNO using === **/ + + namespace ElementModes = ::com::sun::star::embed::ElementModes; + + //==================================================================== + //= helpers + //==================================================================== + namespace + { + // ......................................................................... + static void lcl_getPersistentRepresentation( const MapStringToCompDesc::value_type& i_rComponentDesc, ::rtl::OUStringBuffer& o_rBuffer ) + { + 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' ) ); + } + + // ......................................................................... + static bool lcl_extractCompDesc( const ::rtl::OUString& i_rIniLine, ::rtl::OUString& o_rStorName, SubComponentDescriptor& o_rCompDesc ) + { + 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; + } + + // ......................................................................... + static const ::rtl::OUString& lcl_getRecoveryDataSubStorageName() + { + static const ::rtl::OUString s_sRecDataStorName( RTL_CONSTASCII_USTRINGPARAM( "recovery" ) ); + return s_sRecDataStorName; + } + // ......................................................................... + static const ::rtl::OUString& lcl_getObjectMapStreamName() + { + static const ::rtl::OUString s_sObjectMapStreamName( RTL_CONSTASCII_USTRINGPARAM( "storage-component-map.ini" ) ); + return s_sObjectMapStreamName; + } + + // ......................................................................... + static const ::rtl::OUString& lcl_getMapStreamEncodingName() + { + static const ::rtl::OUString s_sMapStreamEncodingName( RTL_CONSTASCII_USTRINGPARAM( "UTF-8" ) ); + return s_sMapStreamEncodingName; + } + + // ......................................................................... + static void lcl_writeObjectMap_throw( const ::comphelper::ComponentContext& 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, lcl_getObjectMapStreamName() ); + + aTextOutput.writeLine( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "[storages]" ) ) ); + + for ( MapStringToCompDesc::const_iterator stor = i_mapStorageToCompDesc.begin(); + stor != i_mapStorageToCompDesc.end(); + ++stor + ) + { + ::rtl::OUStringBuffer aLine; + lcl_getPersistentRepresentation( *stor, aLine ); + + aTextOutput.writeLine( aLine.makeStringAndClear() ); + } + + aTextOutput.writeLine(); + } + + // ......................................................................... + static bool lcl_isSectionStart( const ::rtl::OUString& i_rIniLine, ::rtl::OUString& o_rSectionName ) + { + 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; + } + + // ......................................................................... + static void lcl_stripTrailingLineFeed( ::rtl::OUString& io_rLine ) + { + const sal_Int32 nLen = io_rLine.getLength(); + if ( ( nLen > 0 ) && ( io_rLine.getStr()[ nLen - 1 ] == '\n' ) ) + io_rLine = io_rLine.copy( 0, nLen - 1 ); + } + + // ......................................................................... + static void lcl_readObjectMap_throw( const ::comphelper::ComponentContext& i_rContext, const Reference< XStorage >& i_rStorage, + 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; + } + } + + // ......................................................................... + static void lcl_markModified( const Reference< XComponent >& i_rSubComponent ) + { + const Reference< XModifiable > xModify( i_rSubComponent, UNO_QUERY ); + if ( !xModify.is() ) + { + OSL_ENSURE( false, "lcl_markModified: unhandled case!" ); + return; + } + + xModify->setModified( sal_True ); + } + } + + //==================================================================== + //= DatabaseDocumentRecovery_Data + //==================================================================== + struct DBACCESS_DLLPRIVATE DatabaseDocumentRecovery_Data + { + const ::comphelper::ComponentContext aContext; + + DatabaseDocumentRecovery_Data( const ::comphelper::ComponentContext& i_rContext ) + :aContext( i_rContext ) + { + } + }; + + //==================================================================== + //= DatabaseDocumentRecovery + //==================================================================== + //-------------------------------------------------------------------- + DatabaseDocumentRecovery::DatabaseDocumentRecovery( const ::comphelper::ComponentContext& 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( lcl_getRecoveryDataSubStorageName() ) ) + i_rTargetStorage->removeElement( lcl_getRecoveryDataSubStorageName() ); + Reference< XStorage > xRecoveryStorage = i_rTargetStorage->openStorageElement( lcl_getRecoveryDataSubStorageName(), 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 ( ::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 ); + aComponentRecovery.saveToRecoveryStorage( xRecoveryStorage, aMapCompDescs ); + } + } + + for ( MapCompTypeToCompDescs::const_iterator map = aMapCompDescs.begin(); + map != aMapCompDescs.end(); + ++map + ) + { + Reference< XStorage > xComponentsStor( xRecoveryStorage->openStorageElement( + SubComponentRecovery::getComponentsStorageName( map->first ), ElementModes::WRITE | ElementModes::NOCREATE ) ); + lcl_writeObjectMap_throw( m_pData->aContext, xComponentsStor, map->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( 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( SubComponentRecovery::getComponentsStorageName( aKnownTypes[i] ) ) ) + continue; + + Reference< XStorage > xComponentsStor( xRecoveryStorage->openStorageElement( + SubComponentRecovery::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 + ) + { + const SubComponentType eComponentType = map->first; + + // the storage for all components of the current type + Reference< XStorage > xComponentsStor( xRecoveryStorage->openStorageElement( + SubComponentRecovery::getComponentsStorageName( eComponentType ), ElementModes::READ ), UNO_QUERY_THROW ); + + // loop thru all components of this type + for ( MapStringToCompDesc::const_iterator stor = map->second.begin(); + stor != map->second.end(); + ++stor + ) + { + const ::rtl::OUString sComponentName( stor->second.sName ); + 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 '" ); + message.append( ::rtl::OUStringToOString( SubComponentRecovery::getComponentsStorageName( eComponentType ), RTL_TEXTENCODING_ASCII_US ) ); + message.append( "', but required per map file!" ); + OSL_ENSURE( false, message.makeStringAndClear() ); + #endif + 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( stor->first, ElementModes::READ ) ); + SubComponentRecovery aComponentRecovery( m_pData->aContext, xDocumentUI, eComponentType ); + Reference< XComponent > xSubComponent( aComponentRecovery.recoverFromStorage( xCompStor, sComponentName, stor->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( lcl_getRecoveryDataSubStorageName() ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + +//........................................................................ +} // namespace dbaccess +//........................................................................ diff --git a/dbaccess/source/core/recovery/makefile.mk b/dbaccess/source/core/recovery/makefile.mk new file mode 100644 index 000000000000..c13334bbc9d9 --- /dev/null +++ b/dbaccess/source/core/recovery/makefile.mk @@ -0,0 +1,58 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.10.2.3 $ +# +# 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. +# +#************************************************************************* + +PRJ=..$/..$/.. +PRJINC=$(PRJ)$/source +PRJNAME=dbaccess +TARGET=recovery + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ---------------------------------- + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/util$/dba.pmk + +# --- Files ------------------------------------- + +SLOFILES= \ + $(SLO)$/dbdocrecovery.obj \ + $(SLO)$/subcomponentloader.obj \ + $(SLO)$/storagestream.obj \ + $(SLO)$/storagexmlstream.obj \ + $(SLO)$/storagetextstream.obj \ + $(SLO)$/subcomponentrecovery.obj \ + $(SLO)$/settingsimport.obj + +# --- Targets ---------------------------------- + +.INCLUDE : target.mk + diff --git a/dbaccess/source/core/recovery/settingsimport.cxx b/dbaccess/source/core/recovery/settingsimport.cxx new file mode 100644 index 000000000000..566bf42ae847 --- /dev/null +++ b/dbaccess/source/core/recovery/settingsimport.cxx @@ -0,0 +1,294 @@ +/************************************************************************* +* 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" + +#include "settingsimport.hxx" + +/** === begin UNO includes === **/ +/** === end UNO includes === **/ + +#include <tools/diagnose_ex.h> +#include <xmloff/xmltoken.hxx> +#include <xmloff/xmluconv.hxx> + +//........................................................................ +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::xml::sax::XAttributeList; + /** === end UNO using === **/ + + //==================================================================== + //= SettingsImport + //==================================================================== + //-------------------------------------------------------------------- + SettingsImport::SettingsImport() + :m_refCount( 0 ) + { + } + + //-------------------------------------------------------------------- + SettingsImport::~SettingsImport() + { + } + + //-------------------------------------------------------------------- + oslInterlockedCount SAL_CALL SettingsImport::acquire() + { + return osl_incrementInterlockedCount( &m_refCount ); + } + + //-------------------------------------------------------------------- + oslInterlockedCount SAL_CALL SettingsImport::release() + { + oslInterlockedCount newCount = osl_decrementInterlockedCount( &m_refCount ); + if ( newCount == 0 ) + delete this; + return newCount; + } + + //-------------------------------------------------------------------- + void SettingsImport::startElement( const Reference< XAttributeList >& i_rAttributes ) + { + // find the name of the setting + if ( i_rAttributes.is() ) + { + m_sItemName = i_rAttributes->getValueByName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "config:name" ) ) ); + m_sItemType = i_rAttributes->getValueByName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "config:type" ) ) ); + } + } + + //-------------------------------------------------------------------- + void SettingsImport::endElement() + { + } + + //-------------------------------------------------------------------- + void SettingsImport::characters( const ::rtl::OUString& i_rCharacters ) + { + m_aCharacters.append( i_rCharacters ); + } + + //-------------------------------------------------------------------- + void SettingsImport::split( const ::rtl::OUString& i_rElementName, ::rtl::OUString& o_rNamespace, ::rtl::OUString& o_rLocalName ) + { + o_rNamespace = ::rtl::OUString(); + 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.equalsAscii( "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 ::rtl::OUString& i_rElementName ) + { + (void)i_rElementName; + return this; + } + + //==================================================================== + //= OfficeSettingsImport + //==================================================================== + //-------------------------------------------------------------------- + OfficeSettingsImport::OfficeSettingsImport( ::comphelper::NamedValueCollection& o_rSettings ) + :m_rSettings( o_rSettings ) + { + } + + //-------------------------------------------------------------------- + OfficeSettingsImport::~OfficeSettingsImport() + { + } + + //-------------------------------------------------------------------- + ::rtl::Reference< SettingsImport > OfficeSettingsImport::nextState( const ::rtl::OUString& i_rElementName ) + { + // separate the namespace part from the element name + ::rtl::OUString sNamespace; + ::rtl::OUString sLocalName; + split( i_rElementName, sNamespace, sLocalName ); + + if ( sLocalName.equalsAscii( "config-item-set" ) ) + return new ConfigItemSetImport( m_rSettings ); + +#if OSL_DEBUG_LEVEL > 0 + ::rtl::OString sMessage( "unknown (or unsupported at this place) element name '" ); + sMessage += ::rtl::OUStringToOString( i_rElementName, RTL_TEXTENCODING_UTF8 ); + sMessage += "', ignoring"; + OSL_ENSURE( false, sMessage.getStr() ); +#endif + return new IgnoringSettingsImport; + } + + //==================================================================== + //= ConfigItemImport + //==================================================================== + //-------------------------------------------------------------------- + ConfigItemImport::ConfigItemImport( ::comphelper::NamedValueCollection& o_rSettings ) + :m_rSettings( o_rSettings ) + { + } + + //-------------------------------------------------------------------- + ConfigItemImport::~ConfigItemImport() + { + } + + //-------------------------------------------------------------------- + ::rtl::Reference< SettingsImport > ConfigItemImport::nextState( const ::rtl::OUString& i_rElementName ) + { + OSL_ENSURE( false, "ConfigItemImport::nextState: unexpected: this class is responsible for child-less items only!" ); + (void)i_rElementName; + return new IgnoringSettingsImport; + } + + //-------------------------------------------------------------------- + void ConfigItemImport::endElement() + { + SettingsImport::endElement(); + + const ::rtl::OUString sItemName( getItemName() ); + ENSURE_OR_RETURN_VOID( sItemName.getLength(), "no item name -> no item value" ); + Any aValue; + getItemValue( aValue ); + m_rSettings.put( sItemName, aValue ); + } + + //-------------------------------------------------------------------- + void ConfigItemImport::getItemValue( ::com::sun::star::uno::Any& o_rValue ) const + { + o_rValue.clear(); + + // the characters building up th evalue + ::rtl::OUStringBuffer aCharacters( getAccumulatedCharacters() ); + const ::rtl::OUString sValue = aCharacters.makeStringAndClear(); + + const ::rtl::OUString& rItemType( getItemType() ); + ENSURE_OR_RETURN_VOID( rItemType.getLength(), "no item type -> no item value" ); + + if ( ::xmloff::token::IsXMLToken( rItemType, ::xmloff::token::XML_INT ) ) + { + sal_Int32 nValue(0); + if ( SvXMLUnitConverter::convertNumber( nValue, sValue ) ) + o_rValue <<= nValue; + else + { + OSL_ENSURE( false, "ConfigItemImport::getItemValue: could not convert an int value!" ); + } + } + else if ( ::xmloff::token::IsXMLToken( rItemType, ::xmloff::token::XML_BOOLEAN ) ) + { + sal_Bool nValue( sal_False ); + if ( SvXMLUnitConverter::convertBool( nValue, sValue ) ) + o_rValue <<= nValue; + else + { + OSL_ENSURE( false, "ConfigItemImport::getItemValue: could not convert a boolean value!" ); + } + } + else if ( ::xmloff::token::IsXMLToken( rItemType, ::xmloff::token::XML_STRING ) ) + { + o_rValue <<= sValue; + } +#if OSL_DEBUG_LEVEL > 0 + else + { + ::rtl::OString sMessage( "ConfigItemImport::getItemValue: unsupported item type '" ); + sMessage += ::rtl::OUStringToOString( rItemType, RTL_TEXTENCODING_UTF8 ); + sMessage += "', ignoring"; + OSL_ENSURE( false, sMessage.getStr() ); + } +#endif + } + + //==================================================================== + //= ConfigItemSetImport + //==================================================================== + //-------------------------------------------------------------------- + ConfigItemSetImport::ConfigItemSetImport( ::comphelper::NamedValueCollection& o_rSettings ) + :ConfigItemImport( o_rSettings ) + { + } + + //-------------------------------------------------------------------- + ConfigItemSetImport::~ConfigItemSetImport() + { + } + + //-------------------------------------------------------------------- + ::rtl::Reference< SettingsImport > ConfigItemSetImport::nextState( const ::rtl::OUString& i_rElementName ) + { + // separate the namespace part from the element name + ::rtl::OUString sNamespace; + ::rtl::OUString sLocalName; + split( i_rElementName, sNamespace, sLocalName ); + + if ( sLocalName.equalsAscii( "config-item-set" ) ) + return new ConfigItemSetImport( m_aChildSettings ); + if ( sLocalName.equalsAscii( "config-item" ) ) + return new ConfigItemImport( m_aChildSettings ); + +#if OSL_DEBUG_LEVEL > 0 + ::rtl::OString sMessage( "unknown element name '" ); + sMessage += ::rtl::OUStringToOString( i_rElementName, RTL_TEXTENCODING_UTF8 ); + sMessage += "', ignoring"; + OSL_ENSURE( false, sMessage.getStr() ); +#endif + return new IgnoringSettingsImport; + } + + //-------------------------------------------------------------------- + void ConfigItemSetImport::getItemValue( Any& o_rValue ) const + { + o_rValue <<= m_aChildSettings.getPropertyValues(); + } + +//........................................................................ +} // namespace dbaccess +//........................................................................ diff --git a/dbaccess/source/core/recovery/settingsimport.hxx b/dbaccess/source/core/recovery/settingsimport.hxx new file mode 100644 index 000000000000..3415092ee93a --- /dev/null +++ b/dbaccess/source/core/recovery/settingsimport.hxx @@ -0,0 +1,190 @@ +/************************************************************************* +* 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. +************************************************************************/ + +#ifndef SETTINGSIMPORT_HXX +#define SETTINGSIMPORT_HXX + +/** === begin UNO includes === **/ +#include <com/sun/star/xml/sax/XAttributeList.hpp> +/** === end UNO includes === **/ + +#include <comphelper/namedvaluecollection.hxx> +#include <rtl/ref.hxx> +#include <rtl/ustrbuf.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 ::rtl::IReference + { + public: + SettingsImport(); + + // IReference + virtual oslInterlockedCount SAL_CALL acquire(); + virtual oslInterlockedCount SAL_CALL release(); + + // own overriables + virtual ::rtl::Reference< SettingsImport > nextState( + const ::rtl::OUString& i_rElementName + ) = 0; + virtual void startElement( + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& i_rAttributes + ); + virtual void endElement(); + virtual void characters( const ::rtl::OUString& i_rCharacters ); + + protected: + virtual ~SettingsImport(); + + protected: + static void split( const ::rtl::OUString& i_rElementName, ::rtl::OUString& o_rNamespace, ::rtl::OUString& o_rLocalName ); + + protected: + const ::rtl::OUString& getItemName() const { return m_sItemName; } + const ::rtl::OUString& getItemType() const { return m_sItemType; } + const ::rtl::OUStringBuffer& getAccumulatedCharacters() const { return m_aCharacters; } + + private: + oslInterlockedCount m_refCount; + // value of the config:name attribute, if any + ::rtl::OUString m_sItemName; + // value of the config:type attribute, if any + ::rtl::OUString m_sItemType; + // accumulated characters, if any + ::rtl::OUStringBuffer m_aCharacters; + }; + + //==================================================================== + //= IgnoringSettingsImport + //==================================================================== + class IgnoringSettingsImport : public SettingsImport + { + public: + IgnoringSettingsImport() + { + } + + // SettingsImport overridables + virtual ::rtl::Reference< SettingsImport > nextState( + const ::rtl::OUString& i_rElementName + ); + + private: + ~IgnoringSettingsImport() + { + } + }; + + //==================================================================== + //= OfficeSettingsImport + //==================================================================== + class OfficeSettingsImport : public SettingsImport + { + public: + OfficeSettingsImport( ::comphelper::NamedValueCollection& o_rSettings ); + + // SettingsImport overridables + virtual ::rtl::Reference< SettingsImport > nextState( + const ::rtl::OUString& i_rElementName + ); + + protected: + ~OfficeSettingsImport(); + + private: + // the settings collection to which |this| will contribute a single setting + ::comphelper::NamedValueCollection& m_rSettings; + }; + + //==================================================================== + //= ConfigItemSetImport + //==================================================================== + class ConfigItemImport : public SettingsImport + { + public: + ConfigItemImport( ::comphelper::NamedValueCollection& o_rSettings ); + + protected: + ~ConfigItemImport(); + + public: + // SettingsImport overridables + virtual ::rtl::Reference< SettingsImport > nextState( + const ::rtl::OUString& i_rElementName + ); + virtual void endElement(); + + protected: + // own overridables + /// retrieves the value represented by the element + virtual void getItemValue( ::com::sun::star::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: + ConfigItemSetImport( ::comphelper::NamedValueCollection& o_rSettings ); + + protected: + ~ConfigItemSetImport(); + + public: + // SettingsImport overridables + virtual ::rtl::Reference< SettingsImport > nextState( + const ::rtl::OUString& i_rElementName + ); + + protected: + // ConfigItemImport overridables + virtual void getItemValue( ::com::sun::star::uno::Any& o_rValue ) const; + + private: + /// the settings represented by our child elements + ::comphelper::NamedValueCollection m_aChildSettings; + }; + +//........................................................................ +} // namespace dbaccess +//........................................................................ + +#endif // SETTINGSIMPORT_HXX diff --git a/dbaccess/source/core/recovery/storagestream.cxx b/dbaccess/source/core/recovery/storagestream.cxx new file mode 100644 index 000000000000..ec6ff49a6098 --- /dev/null +++ b/dbaccess/source/core/recovery/storagestream.cxx @@ -0,0 +1,126 @@ +/************************************************************************* +* 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" + +#include "storagestream.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/embed/ElementModes.hpp> +/** === end UNO includes === **/ + +#include <tools/diagnose_ex.h> + +//........................................................................ +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::io::XStream; + /** === end UNO using === **/ + namespace ElementModes = ::com::sun::star::embed::ElementModes; + + //==================================================================== + //= StorageOutputStream + //==================================================================== + //-------------------------------------------------------------------- + StorageOutputStream::StorageOutputStream( const ::comphelper::ComponentContext& i_rContext, + const Reference< XStorage >& i_rParentStorage, + const ::rtl::OUString& i_rStreamName + ) + :m_rContext( i_rContext ) + { + ENSURE_OR_THROW( i_rParentStorage.is(), "illegal stream" ); + + const Reference< XStream > xStream( + i_rParentStorage->openStreamElement( i_rStreamName, ElementModes::READWRITE ), UNO_QUERY_THROW ); + m_xOutputStream.set( xStream->getOutputStream(), UNO_SET_THROW ); + } + + //-------------------------------------------------------------------- + StorageOutputStream::~StorageOutputStream() + { + } + + //-------------------------------------------------------------------- + void StorageOutputStream::close() + { + ENSURE_OR_RETURN_VOID( m_xOutputStream.is(), "already closed" ); + m_xOutputStream->closeOutput(); + m_xOutputStream.clear(); + + // if you add additional functionality here, be aware that there are derived classes which + // (legitimately) do not call this method here. + } + + //==================================================================== + //= StorageInputStream + //==================================================================== + //-------------------------------------------------------------------- + StorageInputStream::StorageInputStream( const ::comphelper::ComponentContext& i_rContext, + const Reference< XStorage >& i_rParentStorage, + const ::rtl::OUString& i_rStreamName + ) + :m_rContext( i_rContext ) + { + ENSURE_OR_THROW( i_rParentStorage.is(), "illegal stream" ); + + const Reference< XStream > xStream( + i_rParentStorage->openStreamElement( i_rStreamName, ElementModes::READ ), UNO_QUERY_THROW ); + m_xInputStream.set( xStream->getInputStream(), UNO_SET_THROW ); + } + + //-------------------------------------------------------------------- + StorageInputStream::~StorageInputStream() + { + } + + //-------------------------------------------------------------------- + void StorageInputStream::close() + { + ENSURE_OR_RETURN_VOID( m_xInputStream.is(), "already closed" ); + m_xInputStream->closeInput(); + m_xInputStream.clear(); + + // if you add additional functionality here, be aware that there are derived classes which + // (legitimately) do not call this method here. + } + +//........................................................................ +} // namespace dbaccess +//........................................................................ diff --git a/dbaccess/source/core/recovery/storagestream.hxx b/dbaccess/source/core/recovery/storagestream.hxx new file mode 100644 index 000000000000..2485cfac24cb --- /dev/null +++ b/dbaccess/source/core/recovery/storagestream.hxx @@ -0,0 +1,109 @@ +/************************************************************************* +* 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. +************************************************************************/ + +#ifndef STORAGESTREAM_HXX +#define STORAGESTREAM_HXX + +#include "dbaccessdllapi.h" + +/** === begin UNO includes === **/ +#include <com/sun/star/embed/XStorage.hpp> +/** === end UNO includes === **/ + +namespace comphelper +{ + class ComponentContext; +} + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + + //==================================================================== + //= StorageOutputStream + //==================================================================== + /** convenience wrapper around a stream living in a storage + */ + class DBACCESS_DLLPRIVATE StorageOutputStream + { + public: + StorageOutputStream( + const ::comphelper::ComponentContext& i_rContext, + const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& i_rParentStorage, + const ::rtl::OUString& i_rStreamName + ); + virtual ~StorageOutputStream(); + + /** simply calls closeOutput on our output stream, override to extend/modify this behavior + */ + virtual void close(); + + protected: + const ::comphelper::ComponentContext& getContext() const { return m_rContext; } + const ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream >& + getOutputStream() const { return m_xOutputStream; } + + private: + const ::comphelper::ComponentContext& m_rContext; + ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream > + m_xOutputStream; + }; + + //==================================================================== + //= StorageInputStream + //==================================================================== + /** convenience wrapper around a stream living in a storage + */ + class DBACCESS_DLLPRIVATE StorageInputStream + { + public: + StorageInputStream( + const ::comphelper::ComponentContext& i_rContext, + const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& i_rParentStorage, + const ::rtl::OUString& i_rStreamName + ); + virtual ~StorageInputStream(); + + /** simply calls closeInput on our input stream, override to extend/modify this behavior + */ + virtual void close(); + + protected: + const ::comphelper::ComponentContext& getContext() const { return m_rContext; } + const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& + getInputStream() const { return m_xInputStream; } + + private: + const ::comphelper::ComponentContext& m_rContext; + ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > + m_xInputStream; + }; + +//........................................................................ +} // namespace dbaccess +//........................................................................ + +#endif // STORAGESTREAM_HXX diff --git a/dbaccess/source/core/recovery/storagetextstream.cxx b/dbaccess/source/core/recovery/storagetextstream.cxx new file mode 100644 index 000000000000..af1b832b67b3 --- /dev/null +++ b/dbaccess/source/core/recovery/storagetextstream.cxx @@ -0,0 +1,130 @@ +/************************************************************************* +* 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" + +#include "storagetextstream.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/io/XTextOutputStream.hpp> +#include <com/sun/star/io/XActiveDataSource.hpp> +/** === end UNO includes === **/ + +#include <comphelper/componentcontext.hxx> +#include <tools/diagnose_ex.h> + +//...................................................................................................................... +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::io::XTextOutputStream; + using ::com::sun::star::io::XActiveDataSource; + /** === end UNO using === **/ + + //================================================================================================================== + //= StorageTextOutputStream_Data + //================================================================================================================== + struct StorageTextOutputStream_Data + { + Reference< XTextOutputStream > xTextOutput; + }; + + //================================================================================================================== + //= helper + //================================================================================================================== + namespace + { + //-------------------------------------------------------------------------------------------------------------- + static const ::rtl::OUString& lcl_getTextStreamEncodingName() + { + static const ::rtl::OUString s_sMapStreamEncodingName( RTL_CONSTASCII_USTRINGPARAM( "UTF-8" ) ); + return s_sMapStreamEncodingName; + } + + //-------------------------------------------------------------------------------------------------------------- + static const ::rtl::OUString& lcl_getLineFeed() + { + static const ::rtl::OUString s_sLineFeed( sal_Unicode( '\n' ) ); + return s_sLineFeed; + } + } + + //================================================================================================================== + //= StorageTextOutputStream + //================================================================================================================== + //------------------------------------------------------------------------------------------------------------------ + StorageTextOutputStream::StorageTextOutputStream( const ::comphelper::ComponentContext& i_rContext, + const Reference< XStorage >& i_rParentStorage, + const ::rtl::OUString& i_rStreamName + ) + :StorageOutputStream( i_rContext, i_rParentStorage, i_rStreamName ) + ,m_pData( new StorageTextOutputStream_Data ) + { + m_pData->xTextOutput.set( i_rContext.createComponent( "com.sun.star.io.TextOutputStream" ), UNO_QUERY_THROW ); + m_pData->xTextOutput->setEncoding( lcl_getTextStreamEncodingName() ); + + Reference< XActiveDataSource > xDataSource( m_pData->xTextOutput, UNO_QUERY_THROW ); + xDataSource->setOutputStream( getOutputStream() ); + } + + //------------------------------------------------------------------------------------------------------------------ + StorageTextOutputStream::~StorageTextOutputStream() + { + } + + //------------------------------------------------------------------------------------------------------------------ + void StorageTextOutputStream::writeLine( const ::rtl::OUString& i_rLine ) + { + ENSURE_OR_RETURN_VOID( m_pData->xTextOutput.is(), "no text output" ); + + m_pData->xTextOutput->writeString( i_rLine ); + m_pData->xTextOutput->writeString( lcl_getLineFeed() ); + } + + //------------------------------------------------------------------------------------------------------------------ + void StorageTextOutputStream::writeLine() + { + ENSURE_OR_RETURN_VOID( m_pData->xTextOutput.is(), "no text output" ); + + m_pData->xTextOutput->writeString( lcl_getLineFeed() ); + } + +//...................................................................................................................... +} // namespace dbaccess +//...................................................................................................................... diff --git a/dbaccess/source/core/recovery/storagetextstream.hxx b/dbaccess/source/core/recovery/storagetextstream.hxx new file mode 100644 index 000000000000..08d02008f1a4 --- /dev/null +++ b/dbaccess/source/core/recovery/storagetextstream.hxx @@ -0,0 +1,66 @@ +/************************************************************************* +* 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. +************************************************************************/ + +#ifndef STORAGETEXTSTREAM_HXX +#define STORAGETEXTSTREAM_HXX + +#include "storagestream.hxx" + +/** === begin UNO includes === **/ +/** === end UNO includes === **/ + +#include <memory> + +//...................................................................................................................... +namespace dbaccess +{ +//...................................................................................................................... + + //================================================================================================================== + //= StorageTextStream + //================================================================================================================== + struct StorageTextOutputStream_Data; + class DBACCESS_DLLPRIVATE StorageTextOutputStream : public StorageOutputStream + { + public: + StorageTextOutputStream( + const ::comphelper::ComponentContext& i_rContext, + const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& i_rParentStorage, + const ::rtl::OUString& i_rStreamName + ); + ~StorageTextOutputStream(); + + void writeLine( const ::rtl::OUString& i_rLine ); + void writeLine(); + + private: + ::std::auto_ptr< StorageTextOutputStream_Data > m_pData; + }; + +//...................................................................................................................... +} // namespace dbaccess +//...................................................................................................................... + +#endif // STORAGETEXTSTREAM_HXX diff --git a/dbaccess/source/core/recovery/storagexmlstream.cxx b/dbaccess/source/core/recovery/storagexmlstream.cxx new file mode 100644 index 000000000000..8405cce75903 --- /dev/null +++ b/dbaccess/source/core/recovery/storagexmlstream.cxx @@ -0,0 +1,197 @@ +/************************************************************************* +* 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" + +#include "storagexmlstream.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/xml/sax/XDocumentHandler.hpp> +#include <com/sun/star/io/XActiveDataSource.hpp> +#include <com/sun/star/xml/sax/XParser.hpp> +/** === end UNO includes === **/ + +#include <comphelper/componentcontext.hxx> +#include <cppuhelper/implbase1.hxx> +#include <rtl/ref.hxx> +#include <tools/diagnose_ex.h> +#include <xmloff/attrlist.hxx> + +#include <stack> + +//...................................................................................................................... +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::xml::sax::XDocumentHandler; + using ::com::sun::star::xml::sax::XAttributeList; + using ::com::sun::star::io::XStream; + using ::com::sun::star::io::XOutputStream; + using ::com::sun::star::io::XActiveDataSource; + using ::com::sun::star::xml::sax::XParser; + using ::com::sun::star::xml::sax::InputSource; + /** === end UNO using === **/ + + //================================================================================================================== + //= StorageXMLOutputStream_Data + //================================================================================================================== + struct StorageXMLOutputStream_Data + { + Reference< XDocumentHandler > xHandler; + ::std::stack< ::rtl::OUString > aElements; + ::rtl::Reference< SvXMLAttributeList > xAttributes; + }; + + //================================================================================================================== + //= StorageXMLOutputStream + //================================================================================================================== + //------------------------------------------------------------------------------------------------------------------ + StorageXMLOutputStream::StorageXMLOutputStream( const ::comphelper::ComponentContext& i_rContext, + const Reference< XStorage >& i_rParentStorage, + const ::rtl::OUString& i_rStreamName ) + :StorageOutputStream( i_rContext, i_rParentStorage, i_rStreamName ) + ,m_pData( new StorageXMLOutputStream_Data ) + { + const Reference< XActiveDataSource > xSaxWriter( i_rContext.createComponent( "com.sun.star.xml.sax.Writer" ), UNO_QUERY_THROW ); + 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 ::rtl::OUString& i_rName, const ::rtl::OUString& i_rValue ) const + { + m_pData->xAttributes->AddAttribute( i_rName, i_rValue ); + } + + //------------------------------------------------------------------------------------------------------------------ + void StorageXMLOutputStream::startElement( const ::rtl::OUString& i_rElementName ) const + { + ENSURE_OR_RETURN_VOID( m_pData->xHandler.is(), "no document handler" ); + + m_pData->xHandler->startElement( i_rElementName, m_pData->xAttributes.get() ); + 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 ::rtl::OUString sElementName( m_pData->aElements.top() ); + m_pData->xHandler->endElement( sElementName ); + m_pData->aElements.pop(); + } + + //------------------------------------------------------------------------------------------------------------------ + void StorageXMLOutputStream::ignorableWhitespace( const ::rtl::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 ::rtl::OUString& i_rCharacters ) const + { + ENSURE_OR_RETURN_VOID( m_pData->xHandler.is(), "no document handler" ); + + m_pData->xHandler->characters( i_rCharacters ); + } + + //================================================================================================================== + //= StorageXMLInputStream_Data + //================================================================================================================== + struct StorageXMLInputStream_Data + { + Reference< XParser > xParser; + }; + + //================================================================================================================== + //= StorageXMLInputStream + //================================================================================================================== + //------------------------------------------------------------------------------------------------------------------ + StorageXMLInputStream::StorageXMLInputStream( const ::comphelper::ComponentContext& i_rContext, + const Reference< XStorage >& i_rParentStorage, + const ::rtl::OUString& i_rStreamName ) + :StorageInputStream( i_rContext, i_rParentStorage, i_rStreamName ) + ,m_pData( new StorageXMLInputStream_Data ) + { + m_pData->xParser.set( i_rContext.createComponent( "com.sun.star.xml.sax.Parser" ), UNO_QUERY_THROW ); + } + + //------------------------------------------------------------------------------------------------------------------ + void StorageXMLInputStream::import( const Reference< XDocumentHandler >& i_rHandler ) + { + ENSURE_OR_THROW( i_rHandler.is(), "illegal document handler (NULL)" ); + + InputSource aInputSource; + aInputSource.aInputStream = getInputStream(); + + m_pData->xParser->setDocumentHandler( i_rHandler ); + m_pData->xParser->parseStream( aInputSource ); + } + + //------------------------------------------------------------------------------------------------------------------ + StorageXMLInputStream::~StorageXMLInputStream() + { + } + +//...................................................................................................................... +} // namespace dbaccess +//...................................................................................................................... diff --git a/dbaccess/source/core/recovery/storagexmlstream.hxx b/dbaccess/source/core/recovery/storagexmlstream.hxx new file mode 100644 index 000000000000..10a8aaaed5de --- /dev/null +++ b/dbaccess/source/core/recovery/storagexmlstream.hxx @@ -0,0 +1,113 @@ +/************************************************************************* +* 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. +************************************************************************/ + +#ifndef STORAGEXMLSTREAM_HXX +#define STORAGEXMLSTREAM_HXX + +#include "storagestream.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/embed/XStorage.hpp> +#include <com/sun/star/xml/sax/XDocumentHandler.hpp> +/** === end UNO includes === **/ + +#include <memory> + +namespace comphelper +{ + class ComponentContext; +} + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + + //==================================================================== + //= StorageXMLOutputStream + //==================================================================== + struct StorageXMLOutputStream_Data; + class DBACCESS_DLLPRIVATE StorageXMLOutputStream : public StorageOutputStream + { + public: + StorageXMLOutputStream( + const ::comphelper::ComponentContext& i_rContext, + const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& i_rParentStorage, + const ::rtl::OUString& i_rStreamName + ); + ~StorageXMLOutputStream(); + + // StorageOutputStream overridables + virtual void close(); + + void addAttribute( const ::rtl::OUString& i_rName, const ::rtl::OUString& i_rValue ) const; + + void startElement( const ::rtl::OUString& i_rElementName ) const; + void endElement() const; + + void ignorableWhitespace( const ::rtl::OUString& i_rWhitespace ) const; + void characters( const ::rtl::OUString& i_rCharacters ) const; + + private: + StorageXMLOutputStream(); // never implemented + StorageXMLOutputStream( const StorageXMLOutputStream& ); // never implemented + StorageXMLOutputStream& operator=( const StorageXMLOutputStream& ); // never implemented + + private: + ::std::auto_ptr< StorageXMLOutputStream_Data > m_pData; + }; + + //==================================================================== + //= StorageXMLInputStream + //==================================================================== + struct StorageXMLInputStream_Data; + class DBACCESS_DLLPRIVATE StorageXMLInputStream : public StorageInputStream + { + public: + StorageXMLInputStream( + const ::comphelper::ComponentContext& i_rContext, + const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& i_rParentStorage, + const ::rtl::OUString& i_rStreamName + ); + ~StorageXMLInputStream(); + + void import( + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XDocumentHandler >& i_rHandler + ); + + private: + StorageXMLInputStream(); // never implemented + StorageXMLInputStream( const StorageXMLInputStream& ); // never implemented + StorageXMLInputStream& operator=( const StorageXMLInputStream& ); // never implemented + + private: + ::std::auto_ptr< StorageXMLInputStream_Data > m_pData; + }; + +//........................................................................ +} // namespace dbaccess +//........................................................................ + +#endif // STORAGEXMLSTREAM_HXX diff --git a/dbaccess/source/core/recovery/subcomponentloader.cxx b/dbaccess/source/core/recovery/subcomponentloader.cxx new file mode 100644 index 000000000000..5fd120a5009b --- /dev/null +++ b/dbaccess/source/core/recovery/subcomponentloader.cxx @@ -0,0 +1,200 @@ +/************************************************************************* +* 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" + +#include "subcomponentloader.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/ucb/Command.hpp> +#include <com/sun/star/frame/XController2.hpp> +/** === end UNO includes === **/ + +#include <tools/diagnose_ex.h> + +//........................................................................ +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::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; + /** === end UNO using === **/ + + //==================================================================== + //= SubComponentLoader + //==================================================================== + struct DBACCESS_DLLPRIVATE SubComponentLoader_Data + { + const Reference< XCommandProcessor > xDocDefCommands; + const Reference< XComponent > xNonDocComponent; + Reference< XWindow > xAppComponentWindow; + + SubComponentLoader_Data( const Reference< XCommandProcessor >& i_rDocumentDefinition ) + :xDocDefCommands( i_rDocumentDefinition, UNO_SET_THROW ) + ,xNonDocComponent() + { + } + + SubComponentLoader_Data( const Reference< XComponent >& i_rNonDocumentComponent ) + :xDocDefCommands() + ,xNonDocComponent( i_rNonDocumentComponent, UNO_SET_THROW ) + { + } + }; + + //==================================================================== + //= helper + //==================================================================== + namespace + { + //................................................................ + void lcl_onWindowShown_nothrow( const SubComponentLoader_Data& i_rData ) + { + try + { + if ( i_rData.xDocDefCommands.is() ) + { + Command aCommandOpen; + aCommandOpen.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "show" ) ); + + const sal_Int32 nCommandIdentifier = i_rData.xDocDefCommands->createCommandIdentifier(); + i_rData.xDocDefCommands->execute( aCommandOpen, nCommandIdentifier, NULL ); + } + else + { + const Reference< XController > xController( i_rData.xNonDocComponent, UNO_QUERY_THROW ); + const Reference< XFrame > xFrame( xController->getFrame(), UNO_SET_THROW ); + const Reference< XWindow > xWindow( xFrame->getContainerWindow(), UNO_SET_THROW ); + xWindow->setVisible( sal_True ); + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + } + + //==================================================================== + //= SubComponentLoader + //==================================================================== + //-------------------------------------------------------------------- + SubComponentLoader::SubComponentLoader( const Reference< XController >& i_rApplicationController, + const Reference< XCommandProcessor >& i_rSubDocumentDefinition ) + :m_pData( new SubComponentLoader_Data( 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 ); + m_pData->xAppComponentWindow.set( xController->getComponentWindow(), UNO_SET_THROW ); + + osl_incrementInterlockedCount( &m_refCount ); + { + m_pData->xAppComponentWindow->addWindowListener( this ); + } + osl_decrementInterlockedCount( &m_refCount ); + } + + //-------------------------------------------------------------------- + SubComponentLoader::SubComponentLoader( const Reference< XController >& i_rApplicationController, + const Reference< XComponent >& i_rNonDocumentComponent ) + :m_pData( new SubComponentLoader_Data( 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 ); + m_pData->xAppComponentWindow.set( xController->getComponentWindow(), UNO_SET_THROW ); + + osl_incrementInterlockedCount( &m_refCount ); + { + m_pData->xAppComponentWindow->addWindowListener( this ); + } + osl_decrementInterlockedCount( &m_refCount ); + } + + //-------------------------------------------------------------------- + SubComponentLoader::~SubComponentLoader() + { + delete m_pData, m_pData = NULL; + } + + //-------------------------------------------------------------------- + void SAL_CALL SubComponentLoader::windowResized( const WindowEvent& i_rEvent ) throw (RuntimeException) + { + // not interested in + (void)i_rEvent; + } + + //-------------------------------------------------------------------- + void SAL_CALL SubComponentLoader::windowMoved( const WindowEvent& i_rEvent ) throw (RuntimeException) + { + // not interested in + (void)i_rEvent; + } + + //-------------------------------------------------------------------- + void SAL_CALL SubComponentLoader::windowShown( const EventObject& i_rEvent ) throw (RuntimeException) + { + (void)i_rEvent; + + lcl_onWindowShown_nothrow( *m_pData ); + m_pData->xAppComponentWindow->removeWindowListener( this ); + } + + //-------------------------------------------------------------------- + void SAL_CALL SubComponentLoader::windowHidden( const EventObject& i_rEvent ) throw (RuntimeException) + { + // not interested in + (void)i_rEvent; + } + + //-------------------------------------------------------------------- + void SAL_CALL SubComponentLoader::disposing( const EventObject& i_rEvent ) throw (RuntimeException) + { + // not interested in + (void)i_rEvent; + } + +//........................................................................ +} // namespace dbaccess +//........................................................................ diff --git a/dbaccess/source/core/recovery/subcomponentloader.hxx b/dbaccess/source/core/recovery/subcomponentloader.hxx new file mode 100644 index 000000000000..f3bec5b6b39e --- /dev/null +++ b/dbaccess/source/core/recovery/subcomponentloader.hxx @@ -0,0 +1,87 @@ +/************************************************************************* +* 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. +************************************************************************/ + +#ifndef SUBCOMPONENTLOADER_HXX +#define SUBCOMPONENTLOADER_HXX + +#include "dbaccessdllapi.h" + +/** === begin UNO includes === **/ +#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> +/** === end UNO includes === **/ + +#include <cppuhelper/implbase1.hxx> + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + + //==================================================================== + //= SubComponentLoader + //==================================================================== + typedef ::cppu::WeakImplHelper1 < ::com::sun::star::awt::XWindowListener + > SubComponentLoader_Base; + struct SubComponentLoader_Data; + /** is a helper class which loads/opens a given sub component as soon as the main application + window becomes visible. + */ + class DBACCESS_DLLPRIVATE SubComponentLoader : public SubComponentLoader_Base + { + public: + SubComponentLoader( + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XController >& i_rApplicationController, + const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandProcessor >& i_rSubDocumentDefinition + ); + + SubComponentLoader( + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XController >& i_rApplicationController, + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent >& i_rNonDocumentComponent + ); + + // XWindowListener + virtual void SAL_CALL windowResized( const ::com::sun::star::awt::WindowEvent& e ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL windowMoved( const ::com::sun::star::awt::WindowEvent& e ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL windowShown( const ::com::sun::star::lang::EventObject& e ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL windowHidden( const ::com::sun::star::lang::EventObject& e ) throw (::com::sun::star::uno::RuntimeException); + + // XEventListener + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException); + + protected: + virtual ~SubComponentLoader(); + + private: + SubComponentLoader_Data* m_pData; + }; + +//........................................................................ +} // namespace dbaccess +//........................................................................ + +#endif // SUBCOMPONENTLOADER_HXX diff --git a/dbaccess/source/core/recovery/subcomponentrecovery.cxx b/dbaccess/source/core/recovery/subcomponentrecovery.cxx new file mode 100644 index 000000000000..0ae69402faeb --- /dev/null +++ b/dbaccess/source/core/recovery/subcomponentrecovery.cxx @@ -0,0 +1,702 @@ +/************************************************************************* +* 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" + +#include "subcomponentrecovery.hxx" + +#include "sdbcoretools.hxx" +#include "storagexmlstream.hxx" +#include "subcomponentloader.hxx" +#include "settingsimport.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/frame/XModuleManager.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> +/** === end UNO includes === **/ + +#include <comphelper/namedvaluecollection.hxx> +#include <connectivity/dbtools.hxx> +#include <tools/diagnose_ex.h> +#include <xmloff/XMLSettingsExportContext.hxx> +#include <xmloff/SettingsExportHelper.hxx> + +//........................................................................ +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::lang::XMultiServiceFactory; + using ::com::sun::star::embed::XStorage; + using ::com::sun::star::sdb::application::XDatabaseDocumentUI; + using ::com::sun::star::beans::Pair; + using ::com::sun::star::frame::XModuleManager; + using ::com::sun::star::lang::XComponent; + using ::com::sun::star::frame::XModel; + using ::com::sun::star::frame::XController; + using ::com::sun::star::beans::XPropertySet; + using ::com::sun::star::beans::PropertyValue; + using ::com::sun::star::document::XStorageBasedDocument; + using ::com::sun::star::ucb::XCommandProcessor; + using ::com::sun::star::container::XHierarchicalNameAccess; + using ::com::sun::star::sdb::XFormDocumentsSupplier; + using ::com::sun::star::sdb::XReportDocumentsSupplier; + using ::com::sun::star::xml::sax::SAXException; + using ::com::sun::star::xml::sax::XLocator; + using ::com::sun::star::xml::sax::XDocumentHandler; + using ::com::sun::star::xml::sax::XAttributeList; + /** === end UNO using === **/ + + namespace ElementModes = ::com::sun::star::embed::ElementModes; + + + //==================================================================== + //= helper + //==================================================================== + namespace + { + // ......................................................................... + static const ::rtl::OUString& lcl_getComponentStorageBaseName( const SubComponentType i_eType ) + { + static const ::rtl::OUString s_sFormBaseName( RTL_CONSTASCII_USTRINGPARAM( "form" ) ); + static const ::rtl::OUString s_sReportBaseName( RTL_CONSTASCII_USTRINGPARAM( "report" ) ); + static const ::rtl::OUString s_sTableBaseName( RTL_CONSTASCII_USTRINGPARAM( "table" ) ); + static const ::rtl::OUString s_sQueryBaseName( RTL_CONSTASCII_USTRINGPARAM( "query" ) ); + + switch ( i_eType ) + { + case FORM: + return s_sFormBaseName; + case REPORT: + return s_sReportBaseName; + case TABLE: + return s_sTableBaseName; + case QUERY: + return s_sQueryBaseName; + default: + break; + } + + OSL_ENSURE( false, "lcl_getComponentStorageBaseName: unimplemented case!" ); + static const ::rtl::OUString s_sFallback; + return s_sFallback; + } + + // ......................................................................... + static 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; + } + + // ......................................................................... + static 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 ); + } + + // ......................................................................... + static Reference< XCommandProcessor > lcl_getSubComponentDef_nothrow( const Reference< XDatabaseDocumentUI >& i_rAppUI, + const SubComponentType i_eType, const ::rtl::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", NULL ); + + 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(); + } + return xCommandProcessor; + } + + // ......................................................................... + static const ::rtl::OUString& lcl_getSettingsStreamName() + { + static const ::rtl::OUString s_sStatementStreamName( RTL_CONSTASCII_USTRINGPARAM( "settings.xml" ) ); + return s_sStatementStreamName; + } + + // ......................................................................... + static const ::rtl::OUString& lcl_getCurrentQueryDesignName() + { + static const ::rtl::OUString s_sQuerySettingsName( RTL_CONSTASCII_USTRINGPARAM( "ooo:current-query-design" ) ); + return s_sQuerySettingsName; + } + } + + //==================================================================== + //= SettingsExportContext + //==================================================================== + class DBACCESS_DLLPRIVATE SettingsExportContext : public ::xmloff::XMLSettingsExportContext + { + public: + SettingsExportContext( const ::comphelper::ComponentContext& 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 ::rtl::OUString& i_rValue ); + virtual void AddAttribute( enum ::xmloff::token::XMLTokenEnum i_eName, enum ::xmloff::token::XMLTokenEnum i_eValue ); + virtual void StartElement( enum ::xmloff::token::XMLTokenEnum i_eName, const sal_Bool i_bIgnoreWhitespace ); + virtual void EndElement ( const sal_Bool i_bIgnoreWhitespace ); + virtual void Characters( const ::rtl::OUString& i_rCharacters ); + + virtual ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > + GetServiceFactory() const; + + private: + ::rtl::OUString impl_prefix( const ::xmloff::token::XMLTokenEnum i_eToken ) + { + ::rtl::OUStringBuffer aQualifiedName( m_aNamespace ); + aQualifiedName.append( sal_Unicode( ':' ) ); + aQualifiedName.append( ::xmloff::token::GetXMLToken( i_eToken ) ); + return aQualifiedName.makeStringAndClear(); + } + + private: + const ::comphelper::ComponentContext& m_rContext; + const StorageXMLOutputStream& m_rDelegator; + const ::rtl::OUStringBuffer m_aNamespace; + }; + + //-------------------------------------------------------------------- + void SettingsExportContext::AddAttribute( enum ::xmloff::token::XMLTokenEnum i_eName, const ::rtl::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, const sal_Bool i_bIgnoreWhitespace ) + { + if ( i_bIgnoreWhitespace ) + m_rDelegator.ignorableWhitespace( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " " ) ) ); + + m_rDelegator.startElement( impl_prefix( i_eName ) ); + } + + //-------------------------------------------------------------------- + void SettingsExportContext::EndElement( const sal_Bool i_bIgnoreWhitespace ) + { + if ( i_bIgnoreWhitespace ) + m_rDelegator.ignorableWhitespace( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " " ) ) ); + m_rDelegator.endElement(); + } + + //-------------------------------------------------------------------- + void SettingsExportContext::Characters( const ::rtl::OUString& i_rCharacters ) + { + m_rDelegator.characters( i_rCharacters ); + } + + //-------------------------------------------------------------------- + Reference< XMultiServiceFactory > SettingsExportContext::GetServiceFactory() const + { + return m_rContext.getLegacyServiceFactory(); + } + + //================================================================================================================== + //= SettingsDocumentHandler + //================================================================================================================== + typedef ::cppu::WeakImplHelper1 < XDocumentHandler + > SettingsDocumentHandler_Base; + class DBACCESS_DLLPRIVATE SettingsDocumentHandler : public SettingsDocumentHandler_Base + { + public: + SettingsDocumentHandler() + { + } + + protected: + virtual ~SettingsDocumentHandler() + { + } + + public: + // XDocumentHandler + virtual void SAL_CALL startDocument( ) throw (SAXException, RuntimeException); + virtual void SAL_CALL endDocument( ) throw (SAXException, RuntimeException); + virtual void SAL_CALL startElement( const ::rtl::OUString& aName, const Reference< XAttributeList >& xAttribs ) throw (SAXException, RuntimeException); + virtual void SAL_CALL endElement( const ::rtl::OUString& aName ) throw (SAXException, RuntimeException); + virtual void SAL_CALL characters( const ::rtl::OUString& aChars ) throw (SAXException, RuntimeException); + virtual void SAL_CALL ignorableWhitespace( const ::rtl::OUString& aWhitespaces ) throw (SAXException, RuntimeException); + virtual void SAL_CALL processingInstruction( const ::rtl::OUString& aTarget, const ::rtl::OUString& aData ) throw (SAXException, RuntimeException); + virtual void SAL_CALL setDocumentLocator( const Reference< XLocator >& xLocator ) throw (SAXException, RuntimeException); + + 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( ) throw (SAXException, RuntimeException) + { + } + + //-------------------------------------------------------------------- + void SAL_CALL SettingsDocumentHandler::endDocument( ) throw (SAXException, RuntimeException) + { + } + + //-------------------------------------------------------------------- + void SAL_CALL SettingsDocumentHandler::startElement( const ::rtl::OUString& i_Name, const Reference< XAttributeList >& i_Attribs ) throw (SAXException, RuntimeException) + { + ::rtl::Reference< SettingsImport > pNewState; + + if ( m_aStates.empty() ) + { + if ( i_Name.equalsAscii( "office:settings" ) ) + { + pNewState = new OfficeSettingsImport( m_aSettings ); + } + else + { + OSL_ENSURE( false, "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 ::rtl::OUString& i_Name ) throw (SAXException, RuntimeException) + { + ENSURE_OR_THROW( !m_aStates.empty(), "no active element" ); + (void)i_Name; + + ::rtl::Reference< SettingsImport > pCurrentState( m_aStates.top() ); + pCurrentState->endElement(); + m_aStates.pop(); + } + + //-------------------------------------------------------------------- + void SAL_CALL SettingsDocumentHandler::characters( const ::rtl::OUString& i_Chars ) throw (SAXException, RuntimeException) + { + 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 ::rtl::OUString& aWhitespaces ) throw (SAXException, RuntimeException) + { + // ignore them - that's why they're called "ignorable" + (void)aWhitespaces; + } + + //-------------------------------------------------------------------- + void SAL_CALL SettingsDocumentHandler::processingInstruction( const ::rtl::OUString& i_Target, const ::rtl::OUString& i_Data ) throw (SAXException, RuntimeException) + { + OSL_ENSURE( false, "SettingsDocumentHandler::processingInstruction: unexpected ..." ); + (void)i_Target; + (void)i_Data; + } + + //-------------------------------------------------------------------- + void SAL_CALL SettingsDocumentHandler::setDocumentLocator( const Reference< XLocator >& i_Locator ) throw (SAXException, RuntimeException) + { + (void)i_Locator; + } + + //==================================================================== + //= SubComponentRecovery + //==================================================================== + //-------------------------------------------------------------------- + const ::rtl::OUString SubComponentRecovery::getComponentsStorageName( const SubComponentType i_eType ) + { + 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" ) ); + + switch ( i_eType ) + { + 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; + } + + OSL_ENSURE( false, "SubComponentRecovery::getComponentsStorageName: unimplemented case!" ); + static const ::rtl::OUString s_sFallback; + return s_sFallback; + } + + //-------------------------------------------------------------------- + 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 ::rtl::OUString& rStorageName( getComponentsStorageName( m_eType ) ); + const Reference< XStorage > xComponentsStorage( i_rRecoveryStorage->openStorageElement( + rStorageName, ElementModes::READWRITE ), UNO_QUERY_THROW ); + + // find a free sub storage name, and create Yet Another Sub Storage + const ::rtl::OUString& rBaseName( lcl_getComponentStorageBaseName( m_eType ) ); + const ::rtl::OUString sStorName = ::dbtools::createUniqueName( xComponentsStorage.get(), rBaseName, true ); + const Reference< XStorage > xObjectStor( xComponentsStorage->openStorageElement( + sStorName, ElementModes::READWRITE ), UNO_QUERY_THROW ); + + switch ( m_eType ) + { + case FORM: + case REPORT: + impl_saveSubDocument_throw( xObjectStor ); + break; + + case QUERY: + impl_saveQueryDesign_throw( xObjectStor ); + break; + + default: + // TODO + OSL_ENSURE( false, "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, ::rtl::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< 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: + m_aCompDesc.bForEditing = !lcl_determineReadOnly( m_xComponent ); + 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!" ); + } + + //-------------------------------------------------------------------- + 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( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CurrentQueryDesign" ) ) ) >>= aCurrentQueryDesign ); + + // write the query design + StorageXMLOutputStream aDesignOutput( m_rContext, i_rObjectStorage, lcl_getSettingsStreamName() ); + SettingsExportContext aSettingsExportContext( m_rContext, aDesignOutput ); + + const ::rtl::OUString sWhitespace( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " " ) ) ); + + aDesignOutput.startElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "office:settings" ) ) ); + aDesignOutput.ignorableWhitespace( sWhitespace ); + + XMLSettingsExportHelper aSettingsExporter( aSettingsExportContext ); + aSettingsExporter.exportAllSettings( aCurrentQueryDesign, lcl_getCurrentQueryDesignName() ); + + 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 ::rtl::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.getLength() ) + { + 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 ); + Reference< XInterface > xLoader( *new SubComponentLoader( xController, xDocDefinition ) ); + (void)xLoader; + } + + return xSubComponent; + } + + //-------------------------------------------------------------------- + Reference< XComponent > SubComponentRecovery::impl_recoverQueryDesign_throw( const Reference< XStorage >& i_rRecoveryStorage, + const ::rtl::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, lcl_getSettingsStreamName() ); + + ::rtl::Reference< SettingsDocumentHandler > pDocHandler( new SettingsDocumentHandler ); + aDesignInput.import( pDocHandler.get() ); + + const ::comphelper::NamedValueCollection& rSettings( pDocHandler->getSettings() ); + const Any aCurrentQueryDesign = rSettings.get( lcl_getCurrentQueryDesignName() ); +#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.getLength() ) + { + 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 ); + Reference< XInterface > xLoader( *new SubComponentLoader( xController, xSubComponent ) ); + (void)xLoader; + + return xSubComponent; + } + + //-------------------------------------------------------------------- + Reference< XComponent > SubComponentRecovery::recoverFromStorage( const Reference< XStorage >& i_rRecoveryStorage, + const ::rtl::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_ENSURE( false, "SubComponentRecovery::recoverFromStorage: unimplemented case!" ); + break; + } + return xSubComponent; + } + +//........................................................................ +} // namespace dbaccess +//........................................................................ diff --git a/dbaccess/source/core/recovery/subcomponentrecovery.hxx b/dbaccess/source/core/recovery/subcomponentrecovery.hxx new file mode 100644 index 000000000000..2cec262937a8 --- /dev/null +++ b/dbaccess/source/core/recovery/subcomponentrecovery.hxx @@ -0,0 +1,126 @@ +/************************************************************************* +* 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. +************************************************************************/ + +#ifndef SUBCOMPONENTRECOVERY_HXX +#define SUBCOMPONENTRECOVERY_HXX + +#include "subcomponents.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/sdb/application/XDatabaseDocumentUI.hpp> +#include <com/sun/star/embed/XStorage.hpp> +/** === end UNO includes === **/ + +#include <comphelper/componentcontext.hxx> + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + + //==================================================================== + //= SubComponentRecovery + //==================================================================== + class DBACCESS_DLLPRIVATE SubComponentRecovery + { + public: + SubComponentRecovery( const ::comphelper::ComponentContext& i_rContext, const ::com::sun::star::uno::Reference< ::com::sun::star::sdb::application::XDatabaseDocumentUI >& i_rController, + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent >& i_rComponent ) + :m_rContext( i_rContext ) + ,m_xDocumentUI( i_rController, ::com::sun::star::uno::UNO_SET_THROW ) + ,m_xComponent( i_rComponent ) + ,m_eType( UNKNOWN ) + ,m_aCompDesc() + { + impl_identifyComponent_throw(); + } + + SubComponentRecovery( const ::comphelper::ComponentContext& i_rContext, const ::com::sun::star::uno::Reference< ::com::sun::star::sdb::application::XDatabaseDocumentUI >& i_rController, + const SubComponentType i_eType ) + :m_rContext( i_rContext ) + ,m_xDocumentUI( i_rController, ::com::sun::star::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 ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& i_rRecoveryStorage, + MapCompTypeToCompDescs& io_mapCompDescs + ); + + // only to be used after being constructed with a type + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > + recoverFromStorage( + const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& i_rRecoveryStorage, + const ::rtl::OUString& i_rComponentName, + const bool i_bForEditing + ); + + static const ::rtl::OUString getComponentsStorageName( const SubComponentType i_eType ); + + private: + void impl_saveSubDocument_throw( + const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& i_rObjectStorage + ); + + void impl_saveQueryDesign_throw( + const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& i_rObjectStorage + ); + + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > + impl_recoverSubDocument_throw( + const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& i_rRecoveryStorage, + const ::rtl::OUString& i_rComponentName, + const bool i_bForEditing + ); + + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > + impl_recoverQueryDesign_throw( + const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& i_rRecoveryStorage, + const ::rtl::OUString& i_rComponentName, + const bool i_bForEditing + ); + + void impl_identifyComponent_throw(); + + private: + const ::comphelper::ComponentContext& m_rContext; + ::com::sun::star::uno::Reference< ::com::sun::star::sdb::application::XDatabaseDocumentUI > + m_xDocumentUI; + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > + m_xComponent; + SubComponentType m_eType; + SubComponentDescriptor m_aCompDesc; + }; + + +//........................................................................ +} // namespace dbaccess +//........................................................................ + +#endif // SUBCOMPONENTRECOVERY_HXX diff --git a/dbaccess/source/core/recovery/subcomponents.hxx b/dbaccess/source/core/recovery/subcomponents.hxx new file mode 100644 index 000000000000..d1ba0ccb1966 --- /dev/null +++ b/dbaccess/source/core/recovery/subcomponents.hxx @@ -0,0 +1,88 @@ +/************************************************************************* +* 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. +************************************************************************/ + +#ifndef SUBCOMPONENTS_HXX +#define SUBCOMPONENTS_HXX + +#include "dbaccessdllapi.h" + +/** === begin UNO includes === **/ +#include <com/sun/star/sdb/application/DatabaseObject.hpp> +/** === end UNO includes === **/ + +#include <rtl/ustring.hxx> + +#include <hash_map> +#include <map> + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + + namespace DatabaseObject = ::com::sun::star::sdb::application::DatabaseObject; + + // ------------------------------------------------------------------- + enum SubComponentType + { + TABLE = DatabaseObject::TABLE, + QUERY = DatabaseObject::QUERY, + FORM = DatabaseObject::FORM, + REPORT = DatabaseObject::REPORT, + + RELATION_DESIGN = 1000, + + UNKNOWN = 10001 + }; + + // ------------------------------------------------------------------- + struct DBACCESS_DLLPRIVATE SubComponentDescriptor + { + ::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; + + +//........................................................................ +} // namespace dbaccess +//........................................................................ + +#endif // SUBCOMPONENTS_HXX |