diff options
Diffstat (limited to 'dbaccess/source/core')
169 files changed, 57929 insertions, 0 deletions
diff --git a/dbaccess/source/core/api/BookmarkSet.cxx b/dbaccess/source/core/api/BookmarkSet.cxx new file mode 100644 index 000000000000..b5b9ec0ec787 --- /dev/null +++ b/dbaccess/source/core/api/BookmarkSet.cxx @@ -0,0 +1,278 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" +#ifndef DBACCESS_CORE_API_BOOKMARKSET_HXX +#include "BookmarkSet.hxx" +#endif +#ifndef _DBA_CORE_RESOURCE_HXX_ +#include "core_resource.hxx" +#endif +#ifndef _DBA_CORE_RESOURCE_HRC_ +#include "core_resource.hrc" +#endif +#ifndef _COM_SUN_STAR_SDBC_XRESULTSETUPDATE_HPP_ +#include <com/sun/star/sdbc/XResultSetUpdate.hpp> +#endif +#ifndef _DBHELPER_DBEXCEPTION_HXX_ +#include <connectivity/dbexception.hxx> +#endif +#include <rtl/logfile.hxx> + +#include <limits> + +using namespace dbaccess; +using namespace ::connectivity; +using namespace ::dbtools; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbc; +// using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +// using namespace ::cppu; +using namespace ::osl; + +void OBookmarkSet::construct(const Reference< XResultSet>& _xDriverSet,const ::rtl::OUString& i_sRowSetFilter) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OBookmarkSet::construct" ); + OCacheSet::construct(_xDriverSet,i_sRowSetFilter); + m_xRowLocate.set(_xDriverSet,UNO_QUERY); +} +// ----------------------------------------------------------------------------- +Any SAL_CALL OBookmarkSet::getBookmark() throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OBookmarkSet::getBookmark" ); + return m_xRowLocate->getBookmark(); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OBookmarkSet::moveToBookmark( const Any& bookmark ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OBookmarkSet::moveToBookmark" ); + return m_xRowLocate->moveToBookmark(bookmark); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OBookmarkSet::moveRelativeToBookmark( const Any& bookmark, sal_Int32 rows ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OBookmarkSet::moveRelativeToBookmark" ); + return m_xRowLocate->moveRelativeToBookmark(bookmark,rows); +} +// ------------------------------------------------------------------------- +sal_Int32 SAL_CALL OBookmarkSet::compareBookmarks( const Any& _first, const Any& _second ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OBookmarkSet::compareBookmarks" ); + return m_xRowLocate->compareBookmarks(_first,_second); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OBookmarkSet::hasOrderedBookmarks( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OBookmarkSet::hasOrderedBookmarks" ); + return m_xRowLocate->hasOrderedBookmarks(); +} +// ------------------------------------------------------------------------- +sal_Int32 SAL_CALL OBookmarkSet::hashBookmark( const Any& bookmark ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OBookmarkSet::hashBookmark" ); + return m_xRowLocate->hashBookmark(bookmark); +} +// ------------------------------------------------------------------------- +// ::com::sun::star::sdbcx::XDeleteRows +Sequence< sal_Int32 > SAL_CALL OBookmarkSet::deleteRows( const Sequence< Any >& rows ,const connectivity::OSQLTable& /*_xTable*/) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OBookmarkSet::deleteRows" ); + Reference< ::com::sun::star::sdbcx::XDeleteRows> xDeleteRow(m_xRowLocate,UNO_QUERY); + if(xDeleteRow.is()) + { + return xDeleteRow->deleteRows(rows); + } + return Sequence< sal_Int32 >(); +} +// ------------------------------------------------------------------------- +void SAL_CALL OBookmarkSet::insertRow( const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& /*_xTable*/ ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OBookmarkSet::insertRow" ); + Reference<XRowUpdate> xUpdRow(m_xRowLocate,UNO_QUERY); + if(!xUpdRow.is()) + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_NO_XROWUPDATE ), SQL_GENERAL_ERROR, *this ); + + Reference<XResultSetUpdate> xUpd(m_xRowLocate,UNO_QUERY); + if(xUpd.is()) + { + xUpd->moveToInsertRow(); + sal_Int32 i = 1; + connectivity::ORowVector< ORowSetValue > ::Vector::iterator aEnd = _rInsertRow->get().end(); + for(connectivity::ORowVector< ORowSetValue > ::Vector::iterator aIter = _rInsertRow->get().begin()+1;aIter != aEnd;++aIter,++i) + { + aIter->setSigned(m_aSignedFlags[i-1]); + updateColumn(i,xUpdRow,*aIter); + } + xUpd->insertRow(); + (*_rInsertRow->get().begin()) = m_xRowLocate->getBookmark(); + } + else + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_NO_XRESULTSETUPDATE ), SQL_GENERAL_ERROR, *this ); +} +// ------------------------------------------------------------------------- +void SAL_CALL OBookmarkSet::updateRow(const ORowSetRow& _rInsertRow ,const ORowSetRow& _rOrginalRow,const connectivity::OSQLTable& /*_xTable*/ ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OBookmarkSet::updateRow" ); + // OCacheSet::updateRow( _rInsertRow,_rOrginalRow,_xTable); + Reference<XRowUpdate> xUpdRow(m_xRowLocate,UNO_QUERY); + if(!xUpdRow.is()) + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_NO_XROWUPDATE ), SQL_GENERAL_ERROR, *this ); + + sal_Int32 i = 1; + connectivity::ORowVector< ORowSetValue > ::Vector::const_iterator aOrgIter = _rOrginalRow->get().begin()+1; + connectivity::ORowVector< ORowSetValue > ::Vector::iterator aEnd = _rInsertRow->get().end(); + for(connectivity::ORowVector< ORowSetValue > ::Vector::iterator aIter = _rInsertRow->get().begin()+1;aIter != aEnd;++aIter,++i,++aOrgIter) + { + aIter->setSigned(aOrgIter->isSigned()); + updateColumn(i,xUpdRow,*aIter); + } + + + Reference<XResultSetUpdate> xUpd(m_xRowLocate,UNO_QUERY); + if(xUpd.is()) + xUpd->updateRow(); + else + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_NO_XRESULTSETUPDATE ), SQL_GENERAL_ERROR, *this ); +} +// ------------------------------------------------------------------------- +void SAL_CALL OBookmarkSet::deleteRow(const ORowSetRow& /*_rDeleteRow*/ ,const connectivity::OSQLTable& /*_xTable*/ ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OBookmarkSet::deleteRow" ); + Reference<XResultSetUpdate> xUpd(m_xRowLocate,UNO_QUERY); + + xUpd->deleteRow(); +} +// ------------------------------------------------------------------------- +void SAL_CALL OBookmarkSet::cancelRowUpdates( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OBookmarkSet::cancelRowUpdates" ); +} +// ------------------------------------------------------------------------- +void SAL_CALL OBookmarkSet::moveToInsertRow( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OBookmarkSet::moveToInsertRow" ); + Reference<XResultSetUpdate> xUpd(m_xRowLocate,UNO_QUERY); + if(xUpd.is()) + xUpd->moveToInsertRow(); +} +// ------------------------------------------------------------------------- +void SAL_CALL OBookmarkSet::moveToCurrentRow( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OBookmarkSet::moveToCurrentRow" ); +} +// ------------------------------------------------------------------------- +void OBookmarkSet::fillValueRow(ORowSetRow& _rRow,sal_Int32 _nPosition) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OBookmarkSet::fillValueRow" ); + OCacheSet::fillValueRow(_rRow,_nPosition); +} +// ------------------------------------------------------------------------- +void OBookmarkSet::updateColumn(sal_Int32 nPos,Reference< XRowUpdate > _xParameter,const ORowSetValue& _rValue) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OBookmarkSet::updateColumn" ); + if(_rValue.isBound() && _rValue.isModified()) + { + if(_rValue.isNull()) + _xParameter->updateNull(nPos); + else + { + + switch(_rValue.getTypeKind()) + { + case DataType::DECIMAL: + case DataType::NUMERIC: + _xParameter->updateNumericObject(nPos,_rValue.makeAny(),m_xSetMetaData->getScale(nPos)); + break; + case DataType::CHAR: + case DataType::VARCHAR: + //case DataType::DECIMAL: + //case DataType::NUMERIC: + _xParameter->updateString(nPos,_rValue); + break; + case DataType::BIGINT: + if ( _rValue.isSigned() ) + _xParameter->updateLong(nPos,_rValue); + else + _xParameter->updateString(nPos,_rValue); + break; + case DataType::BIT: + case DataType::BOOLEAN: + _xParameter->updateBoolean(nPos,_rValue); + break; + case DataType::TINYINT: + if ( _rValue.isSigned() ) + _xParameter->updateByte(nPos,_rValue); + else + _xParameter->updateShort(nPos,_rValue); + break; + case DataType::SMALLINT: + if ( _rValue.isSigned() ) + _xParameter->updateShort(nPos,_rValue); + else + _xParameter->updateInt(nPos,_rValue); + break; + case DataType::INTEGER: + if ( _rValue.isSigned() ) + _xParameter->updateInt(nPos,_rValue); + else + _xParameter->updateLong(nPos,_rValue); + break; + case DataType::FLOAT: + _xParameter->updateFloat(nPos,_rValue); + break; + case DataType::DOUBLE: + case DataType::REAL: + _xParameter->updateDouble(nPos,_rValue); + break; + case DataType::DATE: + _xParameter->updateDate(nPos,_rValue); + break; + case DataType::TIME: + _xParameter->updateTime(nPos,_rValue); + break; + case DataType::TIMESTAMP: + _xParameter->updateTimestamp(nPos,_rValue); + break; + case DataType::BINARY: + case DataType::VARBINARY: + case DataType::LONGVARBINARY: + _xParameter->updateBytes(nPos,_rValue); + break; + case DataType::BLOB: + case DataType::CLOB: + _xParameter->updateObject(nPos,_rValue.getAny()); + break; + } + } + } +} + diff --git a/dbaccess/source/core/api/BookmarkSet.hxx b/dbaccess/source/core/api/BookmarkSet.hxx new file mode 100644 index 000000000000..36d3c90c7969 --- /dev/null +++ b/dbaccess/source/core/api/BookmarkSet.hxx @@ -0,0 +1,75 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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_CORE_API_BOOKMARKSET_HXX +#define DBACCESS_CORE_API_BOOKMARKSET_HXX + +#ifndef DBACCESS_CORE_API_CACHESET_HXX +#include "CacheSet.hxx" +#endif +#ifndef _COM_SUN_STAR_SDBC_XROWUPDATE_HPP_ +#include <com/sun/star/sdbc/XRowUpdate.hpp> +#endif + +namespace dbaccess +{ + // this set is used when we have a bookmarkable set from the driver + class OBookmarkSet : public OCacheSet + { + ::com::sun::star::uno::Reference< ::com::sun::star::sdbcx::XRowLocate> m_xRowLocate; + + void updateColumn(sal_Int32 nPos,::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowUpdate > _xParameter,const connectivity::ORowSetValue& _rValue); + public: + OBookmarkSet() + {} + ~OBookmarkSet() + { + m_xRowLocate = NULL; + } + + virtual void construct(const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet>& _xDriverSet,const ::rtl::OUString& i_sRowSetFilter); + virtual void fillValueRow(ORowSetRow& _rRow,sal_Int32 _nPosition); + // ::com::sun::star::sdbcx::XRowLocate + virtual ::com::sun::star::uno::Any SAL_CALL getBookmark() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL moveToBookmark( const ::com::sun::star::uno::Any& bookmark ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL moveRelativeToBookmark( const ::com::sun::star::uno::Any& bookmark, sal_Int32 rows ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL compareBookmarks( const ::com::sun::star::uno::Any& first, const ::com::sun::star::uno::Any& second ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL hasOrderedBookmarks( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL hashBookmark( const ::com::sun::star::uno::Any& bookmark ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + // ::com::sun::star::sdbcx::XDeleteRows + virtual ::com::sun::star::uno::Sequence< sal_Int32 > SAL_CALL deleteRows( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& rows ,const connectivity::OSQLTable& _xTable) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + // ::com::sun::star::sdbc::XResultSetUpdate + virtual void SAL_CALL insertRow( const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& _xTable ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateRow(const ORowSetRow& _rInsertRow,const ORowSetRow& _rOrginalRow,const connectivity::OSQLTable& _xTable ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL deleteRow(const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& _xTable ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL cancelRowUpdates( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL moveToInsertRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL moveToCurrentRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + }; +} +#endif // DBACCESS_CORE_API_BOOKMARKSET_HXX + diff --git a/dbaccess/source/core/api/CIndexColumn.hxx b/dbaccess/source/core/api/CIndexColumn.hxx new file mode 100644 index 000000000000..948d472ef88c --- /dev/null +++ b/dbaccess/source/core/api/CIndexColumn.hxx @@ -0,0 +1,59 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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_INDEXCOLUMN_HXX_ +#define DBACCESS_INDEXCOLUMN_HXX_ + +#ifndef _CONNECTIVITY_ADABAS_COLUMN_HXX_ +#include "adabas/BColumn.hxx" +#endif + +namespace connectivity +{ + namespace adabas + { + class OIndexColumn : public OAdabasColumn + { + protected: + sal_Bool m_IsAscending; + public: + OIndexColumn(); + OIndexColumn( sal_Bool _IsAscending, + const ::rtl::OUString& _Name, + const ::rtl::OUString& _TypeName, + const ::rtl::OUString& _DefaultValue, + sal_Int32 _IsNullable, + sal_Int32 _Precision, + sal_Int32 _Scale, + sal_Int32 _Type, + sal_Bool _IsAutoIncrement); + + virtual void construct(); + }; + } +} +#endif // DBACCESS_INDEXCOLUMN_HXX_ diff --git a/dbaccess/source/core/api/CIndexes.cxx b/dbaccess/source/core/api/CIndexes.cxx new file mode 100644 index 000000000000..3fdd9cc4de1a --- /dev/null +++ b/dbaccess/source/core/api/CIndexes.cxx @@ -0,0 +1,123 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" +#ifndef DBACCESS_INDEXES_HXX_ +#include "CIndexes.hxx" +#endif +#ifndef _COM_SUN_STAR_SDBC_XROW_HPP_ +#include <com/sun/star/sdbc/XRow.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XRESULTSET_HPP_ +#include <com/sun/star/sdbc/XResultSet.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_INDEXTYPE_HPP_ +#include <com/sun/star/sdbc/IndexType.hpp> +#endif +#ifndef DBACCESS_SHARED_DBASTRINGS_HRC +#include "dbastrings.hrc" +#endif +#ifndef _CONNECTIVITY_DBTOOLS_HXX_ +#include <connectivity/dbtools.hxx> +#endif +#ifndef _COMPHELPER_EXTRACT_HXX_ +#include <comphelper/extract.hxx> +#endif +#ifndef _TOOLS_DEBUG_HXX +#include <tools/debug.hxx> +#endif + + +using namespace connectivity; +using namespace connectivity::sdbcx; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +using namespace dbaccess; +using namespace cppu; + + +ObjectType OIndexes::createObject(const ::rtl::OUString& _rName) +{ + ObjectType xRet; + if ( m_xIndexes.is() && m_xIndexes->hasByName(_rName) ) + xRet.set(m_xIndexes->getByName(_rName),UNO_QUERY); + else + xRet = OIndexesHelper::createObject(_rName); + + return xRet; +} +// ------------------------------------------------------------------------- +Reference< XPropertySet > OIndexes::createDescriptor() +{ + Reference<XDataDescriptorFactory> xData( m_xIndexes,UNO_QUERY); + if(xData.is()) + return xData->createDataDescriptor(); + else + return OIndexesHelper::createDescriptor(); +} +// ------------------------------------------------------------------------- +// XAppend +ObjectType OIndexes::appendObject( const ::rtl::OUString& _rForName, const Reference< XPropertySet >& descriptor ) +{ + Reference<XAppend> xData( m_xIndexes,UNO_QUERY); + if ( !xData.is() ) + return OIndexesHelper::appendObject( _rForName, descriptor ); + + xData->appendByDescriptor(descriptor); + return createObject( _rForName ); +} +// ------------------------------------------------------------------------- +// XDrop +void OIndexes::dropObject(sal_Int32 _nPos,const ::rtl::OUString _sElementName) +{ + if ( m_xIndexes.is() ) + { + Reference<XDrop> xData( m_xIndexes,UNO_QUERY); + if ( xData.is() ) + xData->dropByName(_sElementName); + } + else + OIndexesHelper::dropObject(_nPos,_sElementName); +} +// ------------------------------------------------------------------------- +void SAL_CALL OIndexes::disposing(void) +{ + if ( m_xIndexes.is() ) + clear_NoDispose(); + else + OIndexesHelper::disposing(); +} +// ----------------------------------------------------------------------------- + + + + diff --git a/dbaccess/source/core/api/CIndexes.hxx b/dbaccess/source/core/api/CIndexes.hxx new file mode 100644 index 000000000000..c461204754be --- /dev/null +++ b/dbaccess/source/core/api/CIndexes.hxx @@ -0,0 +1,58 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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_INDEXES_HXX_ +#define DBACCESS_INDEXES_HXX_ + +#ifndef CONNECTIVITY_INDEXESHELPER_HXX +#include "connectivity/TIndexes.hxx" +#endif + +namespace dbaccess +{ + class OIndexes : public connectivity::OIndexesHelper + { + ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > m_xIndexes; + protected: + virtual connectivity::sdbcx::ObjectType createObject(const ::rtl::OUString& _rName); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > createDescriptor(); + virtual connectivity::sdbcx::ObjectType appendObject( const ::rtl::OUString& _rForName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& descriptor ); + virtual void dropObject(sal_Int32 _nPos,const ::rtl::OUString _sElementName); + public: + OIndexes(connectivity::OTableHelper* _pTable, + ::osl::Mutex& _rMutex, + const ::std::vector< ::rtl::OUString> &_rVector, + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& _rxIndexes + ) : connectivity::OIndexesHelper(_pTable,_rMutex,_rVector) + ,m_xIndexes(_rxIndexes) + {} + + virtual void SAL_CALL disposing(void); + }; +} + +#endif // DBACCESS_INDEXES_HXX_ diff --git a/dbaccess/source/core/api/CRowSetColumn.cxx b/dbaccess/source/core/api/CRowSetColumn.cxx new file mode 100644 index 000000000000..12a7d16e8716 --- /dev/null +++ b/dbaccess/source/core/api/CRowSetColumn.cxx @@ -0,0 +1,111 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#include "dbastrings.hrc" +#include "apitools.hxx" +#include "CRowSetColumn.hxx" + +#include <com/sun/star/sdb/XColumn.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> + +#include <comphelper/types.hxx> +#include <cppuhelper/typeprovider.hxx> + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::beans; + +//.............................................................................. +namespace dbaccess +{ +//.............................................................................. + +//------------------------------------------------------------------------------ +ORowSetColumn::ORowSetColumn( const Reference < XResultSetMetaData >& _xMetaData, const Reference < XRow >& _xRow, sal_Int32 _nPos, + const Reference< XDatabaseMetaData >& _rxDBMeta, const ::rtl::OUString& _rDescription, const ::rtl::OUString& i_sLabel,ORowSetCacheIterator& _rColumnValue ) + :ORowSetDataColumn( _xMetaData, _xRow, NULL, _nPos, _rxDBMeta, _rDescription, i_sLabel,_rColumnValue ) +{ +} + +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper* ORowSetColumn::createArrayHelper( ) const +{ + const sal_Int32 nDerivedProperties = 21; + Sequence< Property> aDerivedProperties( nDerivedProperties ); + Property* pDesc = aDerivedProperties.getArray(); + sal_Int32 nPos = 0; + + DECL_PROP1( CATALOGNAME, ::rtl::OUString, READONLY ); + DECL_PROP1( DISPLAYSIZE, sal_Int32, READONLY ); + DECL_PROP1_BOOL( ISAUTOINCREMENT, READONLY ); + DECL_PROP1_BOOL( ISCASESENSITIVE, READONLY ); + DECL_PROP1_BOOL( ISCURRENCY, READONLY ); + DECL_PROP1_BOOL( ISDEFINITELYWRITABLE, READONLY ); + DECL_PROP1( ISNULLABLE, sal_Int32, READONLY ); + DECL_PROP1_BOOL( ISREADONLY, BOUND ); + DECL_PROP1_BOOL( ISROWVERSION, READONLY ); + DECL_PROP1_BOOL( ISSEARCHABLE, READONLY ); + DECL_PROP1_BOOL( ISSIGNED, READONLY ); + DECL_PROP1_BOOL( ISWRITABLE, READONLY ); + DECL_PROP1( LABEL, ::rtl::OUString, READONLY ); + DECL_PROP1( PRECISION, sal_Int32, READONLY ); + DECL_PROP1( SCALE, sal_Int32, READONLY ); + DECL_PROP1( SCHEMANAME, ::rtl::OUString, READONLY ); + DECL_PROP1( SERVICENAME, ::rtl::OUString, READONLY ); + DECL_PROP1( TABLENAME, ::rtl::OUString, READONLY ); + DECL_PROP1( TYPE, sal_Int32, READONLY ); + DECL_PROP1( TYPENAME, ::rtl::OUString, READONLY ); + DECL_PROP2( VALUE, Any, READONLY, BOUND ); + OSL_ENSURE( nPos == nDerivedProperties, "ORowSetColumn::createArrayHelper: inconsistency!" ); + + Sequence< Property > aRegisteredProperties; + describeProperties( aRegisteredProperties ); + + return new ::cppu::OPropertyArrayHelper( ::comphelper::concatSequences( aDerivedProperties, aRegisteredProperties ), sal_False ); +} + +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper& ORowSetColumn::getInfoHelper() +{ + return *static_cast< ::comphelper::OPropertyArrayUsageHelper< ORowSetColumn >* >(this)->getArrayHelper(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ORowSetColumn::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any& rValue )throw (Exception) +{ + OSL_ENSURE( nHandle != PROPERTY_ID_VALUE, "ORowSetColumn::setFastPropertyValue_NoBroadcast: hmm? This property is marked as READONLY!" ); + if ( nHandle != PROPERTY_ID_VALUE ) + ORowSetDataColumn::setFastPropertyValue_NoBroadcast( nHandle, rValue ); +} + +//.............................................................................. +} // namespace dbaccess +//.............................................................................. diff --git a/dbaccess/source/core/api/CRowSetColumn.hxx b/dbaccess/source/core/api/CRowSetColumn.hxx new file mode 100644 index 000000000000..043837f44589 --- /dev/null +++ b/dbaccess/source/core/api/CRowSetColumn.hxx @@ -0,0 +1,66 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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_CORE_API_CROWSETCOLUMN_HXX +#define DBACCESS_CORE_API_CROWSETCOLUMN_HXX + +#ifndef DBACCESS_CORE_API_ROWSETROW_HXX +#include "RowSetRow.hxx" +#endif +#ifndef _CONNECTIVITY_COMMONTOOLS_HXX_ +#include <connectivity/CommonTools.hxx> +#endif +#ifndef _COMPHELPER_PROPERTY_ARRAY_HELPER_HXX_ +#include <comphelper/proparrhlp.hxx> +#endif +#ifndef DBACCESS_CORE_API_CROWSETDATACOLUMN_HXX +#include "CRowSetDataColumn.hxx" +#endif + +namespace dbaccess +{ + class ORowSetColumn; + class ORowSetColumn :public ORowSetDataColumn + ,public ::comphelper::OPropertyArrayUsageHelper< ORowSetColumn > + + { + public: + ORowSetColumn( const ::com::sun::star::uno::Reference < ::com::sun::star::sdbc::XResultSetMetaData >& _xMetaData, + const ::com::sun::star::uno::Reference < ::com::sun::star::sdbc::XRow >& _xRow, + sal_Int32 _nPos, + const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XDatabaseMetaData >& _rxDBMeta, + const ::rtl::OUString& _rDescription, + const ::rtl::OUString& i_sLabel, + ORowSetCacheIterator& _rColumnValue); + + virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const; + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(); + virtual void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 nHandle,const ::com::sun::star::uno::Any& rValue )throw (::com::sun::star::uno::Exception ); + }; + +} + +#endif // DBACCESS_CORE_API_CROWSETCOLUMN_HXX diff --git a/dbaccess/source/core/api/CRowSetDataColumn.cxx b/dbaccess/source/core/api/CRowSetDataColumn.cxx new file mode 100644 index 000000000000..9bdcda88c93d --- /dev/null +++ b/dbaccess/source/core/api/CRowSetDataColumn.cxx @@ -0,0 +1,292 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#ifndef _DBACORE_DATACOLUMN_HXX_ +#include "CRowSetDataColumn.hxx" +#endif +#ifndef DBACCESS_SHARED_DBASTRINGS_HRC +#include "dbastrings.hrc" +#endif +#ifndef _DBASHARED_APITOOLS_HXX_ +#include "apitools.hxx" +#endif +#ifndef _COMPHELPER_TYPES_HXX_ +#include <comphelper/types.hxx> +#endif +#ifndef _CPPUHELPER_TYPEPROVIDER_HXX_ +#include <cppuhelper/typeprovider.hxx> +#endif +#ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBUTE_HPP_ +#include <com/sun/star/beans/PropertyAttribute.hpp> +#endif +#ifndef _TOOLS_DEBUG_HXX +#include <tools/debug.hxx> +#endif + +using namespace dbaccess; +using namespace comphelper; +using namespace connectivity; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +// using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; +using namespace cppu; +using namespace osl; + +DBG_NAME(ORowSetDataColumn) +// ------------------------------------------------------------------------- +ORowSetDataColumn::ORowSetDataColumn( const Reference < XResultSetMetaData >& _xMetaData, + const Reference < XRow >& _xRow, + const Reference < XRowUpdate >& _xRowUpdate, + sal_Int32 _nPos, + const Reference< XDatabaseMetaData >& _rxDBMeta, + const ::rtl::OUString& _rDescription, + const ::rtl::OUString& i_sLabel, + const ORowSetCacheIterator& _rColumnValue) + :ODataColumn(_xMetaData,_xRow,_xRowUpdate,_nPos,_rxDBMeta) + ,m_aColumnValue(_rColumnValue) + ,m_sLabel(i_sLabel) + ,m_aDescription(_rDescription) +{ + DBG_CTOR(ORowSetDataColumn,NULL); + OColumnSettings::registerProperties( *this ); + registerProperty( PROPERTY_DESCRIPTION, PROPERTY_ID_DESCRIPTION, PropertyAttribute::READONLY, &m_aDescription, ::getCppuType( &m_aDescription ) ); +} +// ------------------------------------------------------------------------- +ORowSetDataColumn::~ORowSetDataColumn() +{ + DBG_DTOR(ORowSetDataColumn,NULL); +} +// ------------------------------------------------------------------------- +// comphelper::OPropertyArrayUsageHelper +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper* ORowSetDataColumn::createArrayHelper( ) const +{ + const sal_Int32 nDerivedProperties = 21; + Sequence< Property> aDerivedProperties( nDerivedProperties ); + Property* pDesc = aDerivedProperties.getArray(); + sal_Int32 nPos = 0; + + DECL_PROP1( CATALOGNAME, ::rtl::OUString, READONLY ); + DECL_PROP1( DISPLAYSIZE, sal_Int32, READONLY ); + DECL_PROP1_BOOL( ISAUTOINCREMENT, READONLY ); + DECL_PROP1_BOOL( ISCASESENSITIVE, READONLY ); + DECL_PROP1_BOOL( ISCURRENCY, READONLY ); + DECL_PROP1_BOOL( ISDEFINITELYWRITABLE, READONLY ); + DECL_PROP1( ISNULLABLE, sal_Int32, READONLY ); + DECL_PROP1_BOOL( ISREADONLY, BOUND ); + DECL_PROP1_BOOL( ISROWVERSION, READONLY ); + DECL_PROP1_BOOL( ISSEARCHABLE, READONLY ); + DECL_PROP1_BOOL( ISSIGNED, READONLY ); + DECL_PROP1_BOOL( ISWRITABLE, READONLY ); + DECL_PROP1( LABEL, ::rtl::OUString, READONLY ); + DECL_PROP1( PRECISION, sal_Int32, READONLY ); + DECL_PROP1( SCALE, sal_Int32, READONLY ); + DECL_PROP1( SCHEMANAME, ::rtl::OUString, READONLY ); + DECL_PROP1( SERVICENAME, ::rtl::OUString, READONLY ); + DECL_PROP1( TABLENAME, ::rtl::OUString, READONLY ); + DECL_PROP1( TYPE, sal_Int32, READONLY ); + DECL_PROP1( TYPENAME, ::rtl::OUString, READONLY ); + DECL_PROP1( VALUE, Any, BOUND ); + OSL_ENSURE( nPos == nDerivedProperties, "ORowSetDataColumn::createArrayHelper: inconsistency!" ); + + Sequence< Property > aRegisteredProperties; + describeProperties( aRegisteredProperties ); + + return new ::cppu::OPropertyArrayHelper( ::comphelper::concatSequences( aDerivedProperties, aRegisteredProperties ), sal_False ); +} + +// cppu::OPropertySetHelper +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper& ORowSetDataColumn::getInfoHelper() +{ + return *static_cast< ::comphelper::OPropertyArrayUsageHelper< ORowSetDataColumn >* >(this)->getArrayHelper(); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSetDataColumn::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const +{ + if ( PROPERTY_ID_VALUE == nHandle ) + { + if ( !m_aColumnValue.isNull() && m_aColumnValue->isValid() ) + { + ::osl::Mutex* pMutex = m_aColumnValue.getMutex(); + ::osl::MutexGuard aGuard( *pMutex ); +#if OSL_DEBUG_LEVEL > 0 + ORowSetRow aRow = *m_aColumnValue; +#endif + OSL_ENSURE((sal_Int32)aRow->get().size() > m_nPos,"Pos is greater than size of vector"); + rValue = ((*m_aColumnValue)->get())[m_nPos].makeAny(); + } + } + else if ( PROPERTY_ID_LABEL == nHandle && m_sLabel.getLength() ) + rValue <<= m_sLabel; + else + ODataColumn::getFastPropertyValue( rValue, nHandle ); +} + +// ------------------------------------------------------------------------- +void SAL_CALL ORowSetDataColumn::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any& rValue )throw (Exception) +{ + switch( nHandle ) + { + case PROPERTY_ID_VALUE: + updateObject(rValue); + break; + case PROPERTY_ID_ISREADONLY: + { + sal_Bool bVal = sal_False; + rValue >>= bVal; + m_isReadOnly.reset(bVal); + } + break; + default: + ODataColumn::setFastPropertyValue_NoBroadcast( nHandle,rValue ); + break; + } +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ORowSetDataColumn::convertFastPropertyValue( Any & rConvertedValue, + Any & rOldValue, + sal_Int32 nHandle, + const Any& rValue ) throw (IllegalArgumentException) +{ + sal_Bool bModified = sal_False; + switch( nHandle ) + { + case PROPERTY_ID_VALUE: + { + rConvertedValue = rValue; + getFastPropertyValue(rOldValue, PROPERTY_ID_VALUE); + bModified = rConvertedValue != rOldValue; + } + break; + case PROPERTY_ID_ISREADONLY: + { + rConvertedValue = rValue; + getFastPropertyValue(rOldValue, PROPERTY_ID_ISREADONLY); + bModified = rConvertedValue != rOldValue; + } + break; + default: + bModified = ODataColumn::convertFastPropertyValue(rConvertedValue, rOldValue, nHandle, rValue); + break; + } + + return bModified; +} +//-------------------------------------------------------------------------- +Sequence< sal_Int8 > ORowSetDataColumn::getImplementationId() throw (RuntimeException) +{ + static OImplementationId * pId = 0; + if (! pId) + { + MutexGuard aGuard( Mutex::getGlobalMutex() ); + if (! pId) + { + static OImplementationId aId; + pId = &aId; + } + } + return pId->getImplementationId(); +} +// ------------------------------------------------------------------------- +void ORowSetDataColumn::fireValueChange(const ORowSetValue& _rOldValue) +{ + if ( !m_aColumnValue.isNull() && m_aColumnValue->isValid() && (!(((*m_aColumnValue)->get())[m_nPos] == _rOldValue)) ) + { + sal_Int32 nHandle = PROPERTY_ID_VALUE; + m_aOldValue = _rOldValue.makeAny(); + Any aNew = ((*m_aColumnValue)->get())[m_nPos].makeAny(); + + fire(&nHandle, &aNew, &m_aOldValue, 1, sal_False ); + } + else if ( !m_aColumnValue.isNull() && !_rOldValue.isNull() ) + { + sal_Int32 nHandle = PROPERTY_ID_VALUE; + m_aOldValue = _rOldValue.makeAny(); + Any aNew; + + fire(&nHandle, &aNew, &m_aOldValue, 1, sal_False ); + } +} +// ----------------------------------------------------------------------------- +DBG_NAME(ORowSetDataColumns ) +ORowSetDataColumns::ORowSetDataColumns( + sal_Bool _bCase, + const ::vos::ORef< ::connectivity::OSQLColumns>& _rColumns, + ::cppu::OWeakObject& _rParent, + ::osl::Mutex& _rMutex, + const ::std::vector< ::rtl::OUString> &_rVector + ) : connectivity::sdbcx::OCollection(_rParent,_bCase,_rMutex,_rVector) + ,m_aColumns(_rColumns) +{ + DBG_CTOR(ORowSetDataColumns ,NULL); +} +// ----------------------------------------------------------------------------- +ORowSetDataColumns::~ORowSetDataColumns() +{ + DBG_DTOR(ORowSetDataColumns ,NULL); +} +// ----------------------------------------------------------------------------- +sdbcx::ObjectType ORowSetDataColumns::createObject(const ::rtl::OUString& _rName) +{ + connectivity::sdbcx::ObjectType xNamed; + + ::comphelper::UStringMixEqual aCase(isCaseSensitive()); + ::connectivity::OSQLColumns::Vector::const_iterator first = ::connectivity::find(m_aColumns->get().begin(),m_aColumns->get().end(),_rName,aCase); + if(first != m_aColumns->get().end()) + xNamed.set(*first,UNO_QUERY); + + return xNamed; +} +// ----------------------------------------------------------------------------- +void SAL_CALL ORowSetDataColumns::disposing(void) +{ + // clear_NoDispose(); + ORowSetDataColumns_BASE::disposing(); + m_aColumns = NULL; + // m_aColumns.clear(); +} +// ----------------------------------------------------------------------------- +void ORowSetDataColumns::assign(const ::vos::ORef< ::connectivity::OSQLColumns>& _rColumns,const ::std::vector< ::rtl::OUString> &_rVector) +{ + m_aColumns = _rColumns; + reFill(_rVector); +} +// ----------------------------------------------------------------------------- +void ORowSetDataColumns::impl_refresh() throw(::com::sun::star::uno::RuntimeException) +{ +} +// ----------------------------------------------------------------------------- + + diff --git a/dbaccess/source/core/api/CRowSetDataColumn.hxx b/dbaccess/source/core/api/CRowSetDataColumn.hxx new file mode 100644 index 000000000000..e5009d4d6f7c --- /dev/null +++ b/dbaccess/source/core/api/CRowSetDataColumn.hxx @@ -0,0 +1,113 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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_CORE_API_CROWSETDATACOLUMN_HXX +#define DBACCESS_CORE_API_CROWSETDATACOLUMN_HXX + +#include "datacolumn.hxx" +#include "RowSetRow.hxx" +#include "RowSetCacheIterator.hxx" +#include "columnsettings.hxx" + +#include <connectivity/CommonTools.hxx> +#include <comphelper/proparrhlp.hxx> + +namespace dbaccess +{ + class ORowSetDataColumn; + typedef ::comphelper::OPropertyArrayUsageHelper<ORowSetDataColumn> ORowSetDataColumn_PROP; + + class ORowSetDataColumn : public ODataColumn, + public OColumnSettings, + public ORowSetDataColumn_PROP + { + protected: + ORowSetCacheIterator m_aColumnValue; + ::com::sun::star::uno::Any m_aOldValue; + + ::rtl::OUString m_sLabel; + ::rtl::OUString m_aDescription; // description + ORowSetBase* m_pRowSet; + + virtual ~ORowSetDataColumn(); + public: + ORowSetDataColumn(const ::com::sun::star::uno::Reference < ::com::sun::star::sdbc::XResultSetMetaData >& _xMetaData, + const ::com::sun::star::uno::Reference < ::com::sun::star::sdbc::XRow >& _xRow, + const ::com::sun::star::uno::Reference < ::com::sun::star::sdbc::XRowUpdate >& _xRowUpdate, + sal_Int32 _nPos, + const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XDatabaseMetaData >& _rxDBMeta, + const ::rtl::OUString& _rDescription, + const ::rtl::OUString& i_sLabel, + const ORowSetCacheIterator& _rColumnValue); + + + // com::sun::star::lang::XTypeProvider + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() throw (::com::sun::star::uno::RuntimeException); + // comphelper::OPropertyArrayUsageHelper + virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const; + + // cppu::OPropertySetHelper + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(); + + virtual sal_Bool SAL_CALL convertFastPropertyValue( ::com::sun::star::uno::Any & rConvertedValue, + ::com::sun::star::uno::Any & rOldValue, + sal_Int32 nHandle, + const ::com::sun::star::uno::Any& rValue ) throw (::com::sun::star::lang::IllegalArgumentException); + virtual void SAL_CALL getFastPropertyValue( ::com::sun::star::uno::Any& rValue, sal_Int32 nHandle ) const; + virtual void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const ::com::sun::star::uno::Any& rValue )throw (::com::sun::star::uno::Exception); + + virtual void fireValueChange(const ::connectivity::ORowSetValue& _rOldValue); + protected: + using ODataColumn::getFastPropertyValue; + }; + // ------------------------------------------------------------------------- +// typedef connectivity::ORefVector< ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet> > +// ORowSetDataColumns_COLLECTION; + + typedef connectivity::sdbcx::OCollection ORowSetDataColumns_BASE; + class ORowSetDataColumns : public ORowSetDataColumns_BASE + { + ::vos::ORef< ::connectivity::OSQLColumns> m_aColumns; + protected: + virtual connectivity::sdbcx::ObjectType createObject(const ::rtl::OUString& _rName); + virtual void impl_refresh() throw(::com::sun::star::uno::RuntimeException); + public: + ORowSetDataColumns( + sal_Bool _bCase, + const ::vos::ORef< ::connectivity::OSQLColumns>& _rColumns, + ::cppu::OWeakObject& _rParent, + ::osl::Mutex& _rMutex, + const ::std::vector< ::rtl::OUString> &_rVector + ); + virtual ~ORowSetDataColumns(); + // only the name is identical to ::cppu::OComponentHelper + virtual void SAL_CALL disposing(void); + void assign(const ::vos::ORef< ::connectivity::OSQLColumns>& _rColumns,const ::std::vector< ::rtl::OUString> &_rVector); + }; +} + +#endif + diff --git a/dbaccess/source/core/api/CacheSet.cxx b/dbaccess/source/core/api/CacheSet.cxx new file mode 100644 index 000000000000..dd64e835adb4 --- /dev/null +++ b/dbaccess/source/core/api/CacheSet.cxx @@ -0,0 +1,753 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" +#ifndef DBACCESS_CORE_API_CACHESET_HXX +#include "CacheSet.hxx" +#endif +#ifndef _DBA_CORE_RESOURCE_HXX_ +#include "core_resource.hxx" +#endif +#ifndef _DBA_CORE_RESOURCE_HRC_ +#include "core_resource.hrc" +#endif +#ifndef _COM_SUN_STAR_SDBCX_COMPAREBOOKMARK_HPP_ +#include <com/sun/star/sdbcx/CompareBookmark.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XRESULTSETMETADATASUPPLIER_HPP_ +#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_ +#include <com/sun/star/beans/XPropertySet.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XDATABASEMETADATA_HPP_ +#include <com/sun/star/sdbc/XDatabaseMetaData.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XPREPAREDSTATEMENT_HPP_ +#include <com/sun/star/sdbc/XPreparedStatement.hpp> +#endif +#include <com/sun/star/sdbc/ColumnValue.hpp> +#ifndef _COM_SUN_STAR_SDBC_XPARAMETERS_HPP_ +#include <com/sun/star/sdbc/XParameters.hpp> +#endif +#ifndef DBACCESS_SHARED_DBASTRINGS_HRC +#include "dbastrings.hrc" +#endif +#ifndef _COM_SUN_STAR_SDBCX_XKEYSSUPPLIER_HPP_ +#include <com/sun/star/sdbcx/XKeysSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBCX_XINDEXESSUPPLIER_HPP_ +#include <com/sun/star/sdbcx/XIndexesSupplier.hpp> +#endif + +#include <limits> + +#ifndef _CONNECTIVITY_DBTOOLS_HXX_ +#include <connectivity/dbtools.hxx> +#endif +#ifndef _COM_SUN_STAR_SDBCX_KEYTYPE_HPP_ +#include <com/sun/star/sdbcx/KeyType.hpp> +#endif +#ifndef _COMPHELPER_EXTRACT_HXX_ +#include <comphelper/extract.hxx> +#endif +#ifndef _COM_SUN_STAR_IO_XINPUTSTREAM_HPP_ +#include <com/sun/star/io/XInputStream.hpp> +#endif +#ifndef _COMPHELPER_TYPES_HXX_ +#include <comphelper/types.hxx> +#endif +#ifndef _TOOLS_DEBUG_HXX +#include <tools/debug.hxx> +#endif +#include <rtl/ustrbuf.hxx> +#include <rtl/logfile.hxx> + +using namespace comphelper; + +using namespace dbaccess; +using namespace dbtools; +using namespace connectivity; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbc; +// using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::io; +// using namespace ::cppu; +using namespace ::osl; + +DBG_NAME(OCacheSet) +// ------------------------------------------------------------------------- +OCacheSet::OCacheSet() + :m_bInserted(sal_False) + ,m_bUpdated(sal_False) + ,m_bDeleted(sal_False) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::OCacheSet" ); + DBG_CTOR(OCacheSet,NULL); + +} +// ------------------------------------------------------------------------- +::rtl::OUString OCacheSet::getIdentifierQuoteString() const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::getIdentifierQuoteString" ); + ::rtl::OUString sQuote; + Reference<XDatabaseMetaData> xMeta; + if ( m_xConnection.is() && (xMeta = m_xConnection->getMetaData()).is() ) + sQuote = xMeta->getIdentifierQuoteString(); + return sQuote; +} +// ------------------------------------------------------------------------- +void OCacheSet::construct( const Reference< XResultSet>& _xDriverSet,const ::rtl::OUString& /*i_sRowSetFilter*/) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::construct" ); + OSL_ENSURE(_xDriverSet.is(),"Invalid resultSet"); + if(_xDriverSet.is()) + { + m_xDriverSet = _xDriverSet; + m_xDriverRow.set(_xDriverSet,UNO_QUERY); + m_xSetMetaData = Reference<XResultSetMetaDataSupplier>(_xDriverSet,UNO_QUERY)->getMetaData(); + if ( m_xSetMetaData.is() ) + { + const sal_Int32 nCount = m_xSetMetaData->getColumnCount(); + m_aNullable.realloc(nCount); + m_aSignedFlags.realloc(nCount); + m_aColumnTypes.realloc(nCount); + sal_Bool* pNullableIter = m_aNullable.getArray(); + sal_Bool* pSignedIter = m_aSignedFlags.getArray(); + sal_Int32* pColumnIter = m_aColumnTypes.getArray(); + for (sal_Int32 i=1; i <= nCount; ++i,++pSignedIter,++pColumnIter,++pNullableIter) + { + *pNullableIter = m_xSetMetaData->isNullable(i) != ColumnValue::NO_NULLS; + *pSignedIter = m_xSetMetaData->isSigned(i); + *pColumnIter = m_xSetMetaData->getColumnType(i); + } + } + Reference< XStatement> xStmt(m_xDriverSet->getStatement(),UNO_QUERY); + if(xStmt.is()) + m_xConnection = xStmt->getConnection(); + else + { + Reference< XPreparedStatement> xPrepStmt(m_xDriverSet->getStatement(),UNO_QUERY); + if ( xPrepStmt.is() ) + m_xConnection = xPrepStmt->getConnection(); + } + } +} +// ------------------------------------------------------------------------- +OCacheSet::~OCacheSet() +{ + try + { + m_xDriverSet = NULL; + m_xDriverRow = NULL; + m_xSetMetaData = NULL; + m_xConnection = NULL; + } + catch(Exception&) + { + OSL_ENSURE(0,"Exception occured"); + } + catch(...) + { + OSL_ENSURE(0,"Unknown Exception occured"); + } + + DBG_DTOR(OCacheSet,NULL); +} +// ----------------------------------------------------------------------------- +void OCacheSet::fillTableName(const Reference<XPropertySet>& _xTable) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::fillTableName" ); + OSL_ENSURE(_xTable.is(),"OCacheSet::fillTableName: PropertySet is empty!"); + if(!m_aComposedTableName.getLength() && _xTable.is() ) + { + Reference<XDatabaseMetaData> xMeta(m_xConnection->getMetaData()); + m_aComposedTableName = composeTableName(xMeta + ,comphelper::getString(_xTable->getPropertyValue(PROPERTY_CATALOGNAME)) + ,comphelper::getString(_xTable->getPropertyValue(PROPERTY_SCHEMANAME)) + ,comphelper::getString(_xTable->getPropertyValue(PROPERTY_NAME)) + ,sal_True + ,::dbtools::eInDataManipulation); + } +} +// ------------------------------------------------------------------------- +void SAL_CALL OCacheSet::insertRow( const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& _xTable ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::insertRow" ); + ::rtl::OUStringBuffer aSql(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("INSERT INTO "))); + Reference<XPropertySet> xSet(_xTable,UNO_QUERY); + fillTableName(xSet); + + aSql.append(m_aComposedTableName); + aSql.append(::rtl::OUString::createFromAscii(" ( ")); + // set values and column names + ::rtl::OUStringBuffer aValues = ::rtl::OUString::createFromAscii(" VALUES ( "); + static ::rtl::OUString aPara(RTL_CONSTASCII_USTRINGPARAM("?,")); + ::rtl::OUString aQuote = getIdentifierQuoteString(); + static ::rtl::OUString aComma(RTL_CONSTASCII_USTRINGPARAM(",")); + sal_Int32 i = 1; + ORowVector< ORowSetValue >::Vector::const_iterator aIter = _rInsertRow->get().begin()+1; + connectivity::ORowVector< ORowSetValue > ::Vector::iterator aEnd = _rInsertRow->get().end(); + for(; aIter != aEnd;++aIter) + { + aSql.append(::dbtools::quoteName( aQuote,m_xSetMetaData->getColumnName(i++))); + aSql.append(aComma); + aValues.append(aPara); + } + + aSql.setCharAt(aSql.getLength()-1,')'); + aValues.setCharAt(aValues.getLength()-1,')'); + + aSql.append(aValues.makeStringAndClear()); + // now create end execute the prepared statement + { + Reference< XPreparedStatement > xPrep(m_xConnection->prepareStatement(aSql.makeStringAndClear())); + Reference< XParameters > xParameter(xPrep,UNO_QUERY); + i = 1; + for(aIter = _rInsertRow->get().begin()+1; aIter != aEnd;++aIter,++i) + { + if(aIter->isNull()) + xParameter->setNull(i,aIter->getTypeKind()); + else + setParameter(i,xParameter,*aIter,m_xSetMetaData->getColumnType(i),m_xSetMetaData->getScale(i)); + } + + m_bInserted = xPrep->executeUpdate() > 0; + } + +// ::rtl::OUString aCountSql = ::rtl::OUString::createFromAscii("SELECT COUNT(*) FROM "); +// aCountSql += m_aComposedTableName; +// try +// { +// Reference< XStatement > xStmt(m_xConnection->createStatement()); +// Reference<XResultSet> xRes(xStmt->executeQuery(aCountSql)); +// if(xRes.is() && xRes->next()) +// { +// Reference<XRow> xRow(xRes,UNO_QUERY); +// } +// } +// catch(SQLException&) +// { +// } + + // TODO set the bookmark in the insert row +} +// ------------------------------------------------------------------------- +void OCacheSet::fillParameters( const ORowSetRow& _rRow + ,const connectivity::OSQLTable& _xTable + ,::rtl::OUStringBuffer& _sCondition + ,::rtl::OUStringBuffer& _sParameter + ,::std::list< sal_Int32>& _rOrgValues) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::fillParameters" ); + // use keys and indexes for excat postioning + // first the keys + Reference<XPropertySet> xSet(_xTable,UNO_QUERY); + const Reference<XNameAccess> xPrimaryKeyColumns = getPrimaryKeyColumns_throw(xSet); + // second the indexes + Reference<XIndexesSupplier> xIndexSup(_xTable,UNO_QUERY); + Reference<XIndexAccess> xIndexes; + if(xIndexSup.is()) + xIndexes.set(xIndexSup->getIndexes(),UNO_QUERY); + + // Reference<XColumnsSupplier> + Reference<XPropertySet> xIndexColsSup; + Reference<XNameAccess> xIndexColumns; + ::std::vector< Reference<XNameAccess> > aAllIndexColumns; + if(xIndexes.is()) + { + for(sal_Int32 j=0;j<xIndexes->getCount();++j) + { + xIndexColsSup.set(xIndexes->getByIndex(j),UNO_QUERY); + if( xIndexColsSup.is() + && comphelper::getBOOL(xIndexColsSup->getPropertyValue(PROPERTY_ISUNIQUE)) + && !comphelper::getBOOL(xIndexColsSup->getPropertyValue(PROPERTY_ISPRIMARYKEYINDEX)) + ) + aAllIndexColumns.push_back(Reference<XColumnsSupplier>(xIndexColsSup,UNO_QUERY)->getColumns()); + } + } + + ::rtl::OUString aColumnName; + + static ::rtl::OUString aPara = ::rtl::OUString::createFromAscii("?,"); + static ::rtl::OUString aAnd = ::rtl::OUString::createFromAscii(" AND "); + + ::rtl::OUString aQuote = getIdentifierQuoteString(); + + sal_Int32 nCheckCount = 1; // index for the orginal values + sal_Int32 i = 1; + + ::rtl::OUString sIsNull(RTL_CONSTASCII_USTRINGPARAM(" IS NULL")); + ::rtl::OUString sParam(RTL_CONSTASCII_USTRINGPARAM(" = ?")); + ORowVector< ORowSetValue >::Vector::const_iterator aIter = _rRow->get().begin()+1; + ORowVector< ORowSetValue >::Vector::const_iterator aEnd = _rRow->get().end()+1; + for(; aIter != aEnd;++aIter,++nCheckCount,++i) + { + aColumnName = m_xSetMetaData->getColumnName(i); + if(xPrimaryKeyColumns.is() && xPrimaryKeyColumns->hasByName(aColumnName)) + { + _sCondition.append(::dbtools::quoteName( aQuote,aColumnName)); + if(aIter->isNull()) + _sCondition.append(sIsNull); + else + _sCondition.append(sParam); + _sCondition.append(aAnd); + _rOrgValues.push_back(nCheckCount); + + } // if(xPrimaryKeyColumns.is() && xPrimaryKeyColumns->hasByName(aColumnName)) + ::std::vector< Reference<XNameAccess> >::const_iterator aIndexEnd = aAllIndexColumns.end(); + for( ::std::vector< Reference<XNameAccess> >::const_iterator aIndexIter = aAllIndexColumns.begin(); + aIndexIter != aIndexEnd;++aIndexIter) + { + if((*aIndexIter)->hasByName(aColumnName)) + { + _sCondition.append(::dbtools::quoteName( aQuote,aColumnName)); + if(aIter->isNull()) + _sCondition.append(sIsNull); + else + _sCondition.append(sParam); + _sCondition.append(aAnd); + _rOrgValues.push_back(nCheckCount); + break; + } + } + if(aIter->isModified()) + { + _sParameter.append(::dbtools::quoteName( aQuote,aColumnName)); + _sParameter.append(aPara); + } + } +} +// ------------------------------------------------------------------------- +void SAL_CALL OCacheSet::updateRow(const ORowSetRow& _rInsertRow ,const ORowSetRow& _rOrginalRow,const connectivity::OSQLTable& _xTable ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::updateRow" ); + Reference<XPropertySet> xSet(_xTable,UNO_QUERY); + fillTableName(xSet); + + ::rtl::OUStringBuffer aSql = ::rtl::OUString::createFromAscii("UPDATE "); + aSql.append(m_aComposedTableName); + aSql.append(::rtl::OUString::createFromAscii(" SET ")); + // list all cloumns that should be set + + ::rtl::OUStringBuffer aCondition; + ::std::list< sal_Int32> aOrgValues; + fillParameters(_rInsertRow,_xTable,aCondition,aSql,aOrgValues); + aSql.setCharAt(aSql.getLength()-1,' '); + if ( aCondition.getLength() ) + { + aCondition.setLength(aCondition.getLength()-5); + + aSql.append(::rtl::OUString::createFromAscii(" WHERE ")); + aSql.append(aCondition.makeStringAndClear()); + } + else + ::dbtools::throwSQLException( + DBACORE_RESSTRING( RID_STR_NO_UPDATE_MISSING_CONDITION ), SQL_GENERAL_ERROR, *this ); + + // now create end execute the prepared statement + Reference< XPreparedStatement > xPrep(m_xConnection->prepareStatement(aSql.makeStringAndClear())); + Reference< XParameters > xParameter(xPrep,UNO_QUERY); + sal_Int32 i = 1; + connectivity::ORowVector< ORowSetValue > ::Vector::iterator aEnd = _rInsertRow->get().end(); + for(ORowVector< ORowSetValue >::Vector::const_iterator aIter = _rInsertRow->get().begin()+1; aIter != aEnd;++aIter) + { + if(aIter->isModified()) + { + setParameter(i,xParameter,*aIter,m_xSetMetaData->getColumnType(i),m_xSetMetaData->getScale(i)); + ++i; + } + } // for(ORowVector< ORowSetValue >::Vector::const_iterator aIter = _rInsertRow->get().begin()+1; aIter != aEnd;++aIter) + ::std::list< sal_Int32>::const_iterator aOrgValueEnd = aOrgValues.end(); + for(::std::list< sal_Int32>::const_iterator aOrgValue = aOrgValues.begin(); aOrgValue != aOrgValueEnd;++aOrgValue,++i) + { + setParameter(i,xParameter,(_rOrginalRow->get())[*aOrgValue],m_xSetMetaData->getColumnType(i),m_xSetMetaData->getScale(i)); + } + + m_bUpdated = xPrep->executeUpdate() > 0; +} +// ------------------------------------------------------------------------- +void SAL_CALL OCacheSet::deleteRow(const ORowSetRow& _rDeleteRow ,const connectivity::OSQLTable& _xTable ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::deleteRow" ); + Reference<XPropertySet> xSet(_xTable,UNO_QUERY); + fillTableName(xSet); + + ::rtl::OUStringBuffer aSql = ::rtl::OUString::createFromAscii("DELETE FROM "); + aSql.append(m_aComposedTableName); + aSql.append(::rtl::OUString::createFromAscii(" WHERE ")); + + // list all cloumns that should be set + ::rtl::OUString aQuote = getIdentifierQuoteString(); + static ::rtl::OUString aAnd = ::rtl::OUString::createFromAscii(" AND "); + + // use keys and indexes for excat postioning + // first the keys + const Reference<XNameAccess> xPrimaryKeyColumns = getPrimaryKeyColumns_throw(xSet); + // second the indexes + Reference<XIndexesSupplier> xIndexSup(_xTable,UNO_QUERY); + Reference<XIndexAccess> xIndexes; + if(xIndexSup.is()) + xIndexes.set(xIndexSup->getIndexes(),UNO_QUERY); + + // Reference<XColumnsSupplier> + Reference<XPropertySet> xIndexColsSup; + Reference<XNameAccess> xIndexColumns; + ::std::vector< Reference<XNameAccess> > aAllIndexColumns; + if(xIndexes.is()) + { + for(sal_Int32 j=0;j<xIndexes->getCount();++j) + { + xIndexColsSup.set(xIndexes->getByIndex(j),UNO_QUERY); + if( xIndexColsSup.is() + && comphelper::getBOOL(xIndexColsSup->getPropertyValue(PROPERTY_ISUNIQUE)) + && !comphelper::getBOOL(xIndexColsSup->getPropertyValue(PROPERTY_ISPRIMARYKEYINDEX)) + ) + aAllIndexColumns.push_back(Reference<XColumnsSupplier>(xIndexColsSup,UNO_QUERY)->getColumns()); + } + } + + ::rtl::OUStringBuffer aColumnName; + ::std::list< sal_Int32> aOrgValues; + fillParameters(_rDeleteRow,_xTable,aSql,aColumnName,aOrgValues); + + aSql.setLength(aSql.getLength()-5); + + // now create end execute the prepared statement + Reference< XPreparedStatement > xPrep(m_xConnection->prepareStatement(aSql.makeStringAndClear())); + Reference< XParameters > xParameter(xPrep,UNO_QUERY); + sal_Int32 i = 1; + ::std::list< sal_Int32>::const_iterator aOrgValueEnd = aOrgValues.end(); + for(::std::list< sal_Int32>::const_iterator j = aOrgValues.begin(); j != aOrgValueEnd;++j,++i) + { + setParameter(i,xParameter,(_rDeleteRow->get())[*j],m_xSetMetaData->getColumnType(i),m_xSetMetaData->getScale(i)); + } + + m_bDeleted = xPrep->executeUpdate() > 0; +} +// ------------------------------------------------------------------------- +void OCacheSet::setParameter(sal_Int32 nPos + ,const Reference< XParameters >& _xParameter + ,const ORowSetValue& _rValue + ,sal_Int32 _nType + ,sal_Int32 _nScale) const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::setParameter" ); + sal_Int32 nType = ( _nType != DataType::OTHER ) ? _nType : _rValue.getTypeKind(); + ::dbtools::setObjectWithInfo(_xParameter,nPos,_rValue,nType,_nScale); +} +// ------------------------------------------------------------------------- +void OCacheSet::fillValueRow(ORowSetRow& _rRow,sal_Int32 _nPosition) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::fillValueRow" ); + Any aBookmark = getBookmark(); + if(!aBookmark.hasValue()) + aBookmark = makeAny(_nPosition); + + connectivity::ORowVector< ORowSetValue >::Vector::iterator aIter = _rRow->get().begin(); + connectivity::ORowVector< ORowSetValue >::Vector::iterator aEnd = _rRow->get().end(); + (*aIter) = aBookmark; + ++aIter; + for(sal_Int32 i=1;aIter != aEnd;++aIter,++i) + { + aIter->setSigned(m_aSignedFlags[i-1]); + aIter->fill(i,m_aColumnTypes[i-1],m_aNullable[i-1],this); + } +} +// ----------------------------------------------------------------------------- +sal_Bool SAL_CALL OCacheSet::wasNull( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::wasNull" ); + return m_xDriverRow->wasNull(); +} +// ------------------------------------------------------------------------- +::rtl::OUString SAL_CALL OCacheSet::getString( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::getString" ); + return m_xDriverRow->getString(columnIndex); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OCacheSet::getBoolean( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::getBoolean" ); + return m_xDriverRow->getBoolean(columnIndex); +} +// ------------------------------------------------------------------------- +sal_Int8 SAL_CALL OCacheSet::getByte( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::getByte" ); + return m_xDriverRow->getByte(columnIndex); +} +// ------------------------------------------------------------------------- +sal_Int16 SAL_CALL OCacheSet::getShort( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::getShort" ); + return m_xDriverRow->getShort(columnIndex); +} +// ------------------------------------------------------------------------- +sal_Int32 SAL_CALL OCacheSet::getInt( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::getInt" ); + return m_xDriverRow->getInt(columnIndex); +} +// ------------------------------------------------------------------------- +sal_Int64 SAL_CALL OCacheSet::getLong( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::getLong" ); + return m_xDriverRow->getLong(columnIndex); +} +// ------------------------------------------------------------------------- +float SAL_CALL OCacheSet::getFloat( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::getFloat" ); + return m_xDriverRow->getFloat(columnIndex); +} +// ------------------------------------------------------------------------- +double SAL_CALL OCacheSet::getDouble( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::getDouble" ); + return m_xDriverRow->getDouble(columnIndex); +} +// ------------------------------------------------------------------------- +Sequence< sal_Int8 > SAL_CALL OCacheSet::getBytes( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::getBytes" ); + return m_xDriverRow->getBytes(columnIndex); +} +// ------------------------------------------------------------------------- +::com::sun::star::util::Date SAL_CALL OCacheSet::getDate( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::getDate" ); + return m_xDriverRow->getDate(columnIndex); +} +// ------------------------------------------------------------------------- +::com::sun::star::util::Time SAL_CALL OCacheSet::getTime( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::getTime" ); + return m_xDriverRow->getTime(columnIndex); +} +// ------------------------------------------------------------------------- +::com::sun::star::util::DateTime SAL_CALL OCacheSet::getTimestamp( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::getTimestamp" ); + return m_xDriverRow->getTimestamp(columnIndex); +} +// ------------------------------------------------------------------------- +Reference< ::com::sun::star::io::XInputStream > SAL_CALL OCacheSet::getBinaryStream( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::getBinaryStream" ); + return m_xDriverRow->getBinaryStream(columnIndex); +} +// ------------------------------------------------------------------------- +Reference< ::com::sun::star::io::XInputStream > SAL_CALL OCacheSet::getCharacterStream( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::getCharacterStream" ); + return m_xDriverRow->getCharacterStream(columnIndex); +} +// ------------------------------------------------------------------------- +Any SAL_CALL OCacheSet::getObject( sal_Int32 columnIndex, const Reference< ::com::sun::star::container::XNameAccess >& typeMap ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::getObject" ); + return m_xDriverRow->getObject(columnIndex,typeMap); +} +// ------------------------------------------------------------------------- +Reference< XRef > SAL_CALL OCacheSet::getRef( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::getRef" ); + return m_xDriverRow->getRef(columnIndex); +} +// ------------------------------------------------------------------------- +Reference< XBlob > SAL_CALL OCacheSet::getBlob( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::getBlob" ); + return m_xDriverRow->getBlob(columnIndex); +} +// ------------------------------------------------------------------------- +Reference< XClob > SAL_CALL OCacheSet::getClob( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::getClob" ); + return m_xDriverRow->getClob(columnIndex); +} +// ------------------------------------------------------------------------- +Reference< XArray > SAL_CALL OCacheSet::getArray( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::getArray" ); + return m_xDriverRow->getArray(columnIndex); +} +// ------------------------------------------------------------------------- +// XResultSet +sal_Bool SAL_CALL OCacheSet::next( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::next" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + return m_xDriverSet->next(); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OCacheSet::isBeforeFirst( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::isBeforeFirst" ); + return m_xDriverSet->isBeforeFirst(); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OCacheSet::isAfterLast( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::isAfterLast" ); + return m_xDriverSet->isAfterLast(); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OCacheSet::isFirst( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::isFirst" ); + return m_xDriverSet->isFirst(); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OCacheSet::isLast( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::isLast" ); + return m_xDriverSet->isLast(); +} +// ------------------------------------------------------------------------- +void SAL_CALL OCacheSet::beforeFirst( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::beforeFirst" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + m_xDriverSet->beforeFirst(); +} +// ------------------------------------------------------------------------- +void SAL_CALL OCacheSet::afterLast( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::afterLast" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + m_xDriverSet->afterLast(); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OCacheSet::first( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::first" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + return m_xDriverSet->first(); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OCacheSet::last( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::last" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + return m_xDriverSet->last(); +} +// ------------------------------------------------------------------------- +sal_Int32 SAL_CALL OCacheSet::getRow( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::getRow" ); + return m_xDriverSet->getRow(); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OCacheSet::absolute( sal_Int32 row ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::absolute" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + return m_xDriverSet->absolute(row); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OCacheSet::relative( sal_Int32 rows ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::relative" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + return m_xDriverSet->relative(rows); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OCacheSet::previous( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::previous" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + return m_xDriverSet->previous(); +} +// ------------------------------------------------------------------------- +void SAL_CALL OCacheSet::refreshRow( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::refreshRow" ); + m_xDriverSet->refreshRow(); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OCacheSet::rowUpdated( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::rowUpdated" ); + return m_xDriverSet->rowUpdated(); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OCacheSet::rowInserted( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::rowInserted" ); + return m_xDriverSet->rowInserted(); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OCacheSet::rowDeleted( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::rowDeleted" ); + return m_xDriverSet->rowDeleted(); +} +// ------------------------------------------------------------------------- +Reference< XInterface > SAL_CALL OCacheSet::getStatement( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::getStatement" ); + return m_xDriverSet->getStatement(); +} +// ----------------------------------------------------------------------------- +bool OCacheSet::isResultSetChanged() const +{ + return false; +} +// ----------------------------------------------------------------------------- +void OCacheSet::reset(const Reference< XResultSet>& /*_xDriverSet*/) +{ + OSL_ENSURE(0,"Illegal call!"); +} +// ----------------------------------------------------------------------------- +void OCacheSet::mergeColumnValues(sal_Int32 i_nColumnIndex,ORowSetValueVector::Vector& /*io_aInsertRow*/,ORowSetValueVector::Vector& /*io_aRow*/,::std::vector<sal_Int32>& o_aChangedColumns) +{ + o_aChangedColumns.push_back(i_nColumnIndex); +} +// ----------------------------------------------------------------------------- +bool OCacheSet::columnValuesUpdated(ORowSetValueVector::Vector& /*io_aCachedRow*/,const ORowSetValueVector::Vector& /*io_aRow*/) +{ + return false; +} +// ----------------------------------------------------------------------------- +bool OCacheSet::updateColumnValues(const ORowSetValueVector::Vector& /*io_aCachedRow*/,ORowSetValueVector::Vector& /*io_aRow*/,const ::std::vector<sal_Int32>& /*i_aChangedColumns*/) +{ + return true; +} +// ----------------------------------------------------------------------------- +void OCacheSet::fillMissingValues(ORowSetValueVector::Vector& /*io_aRow*/) const +{ +} +// ----------------------------------------------------------------------------- + diff --git a/dbaccess/source/core/api/CacheSet.hxx b/dbaccess/source/core/api/CacheSet.hxx new file mode 100644 index 000000000000..ef3503fa5e4e --- /dev/null +++ b/dbaccess/source/core/api/CacheSet.hxx @@ -0,0 +1,179 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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_CORE_API_CACHESET_HXX +#define DBACCESS_CORE_API_CACHESET_HXX + +#ifndef _COM_SUN_STAR_SDBC_XROW_HPP_ +#include <com/sun/star/sdbc/XRow.hpp> +#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 _COM_SUN_STAR_SDBC_XRESULTSET_HPP_ +#include <com/sun/star/sdbc/XResultSet.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XCONNECTION_HPP_ +#include <com/sun/star/sdbc/XConnection.hpp> +#endif +#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_ +#include <com/sun/star/beans/XPropertySet.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBCX_XROWLOCATE_HPP_ +#include <com/sun/star/sdbcx/XRowLocate.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBCX_XDELETEROWS_HPP_ +#include <com/sun/star/sdbcx/XDeleteRows.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBCX_COMPAREBOOKMARK_HPP_ +#include <com/sun/star/sdbcx/CompareBookmark.hpp> +#endif +#ifndef DBACCESS_CORE_API_ROWSETROW_HXX +#include "RowSetRow.hxx" +#endif +#ifndef _CPPUHELPER_IMPLBASE1_HXX_ +#include <cppuhelper/implbase1.hxx> +#endif + +#include <list> +namespace rtl +{ + class OUStringBuffer; +} +namespace com{ namespace sun { namespace star{namespace sdbc{ class XParameters; } } } } + +namespace dbaccess +{ + class OCacheSet : public ::cppu::WeakImplHelper1< ::com::sun::star::sdbc::XRow> + { + protected: + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet> m_xDriverSet; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRow> m_xDriverRow; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSetMetaData> m_xSetMetaData; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection> m_xConnection; + + ::com::sun::star::uno::Sequence<sal_Bool> m_aNullable; + ::com::sun::star::uno::Sequence<sal_Bool> m_aSignedFlags; + ::com::sun::star::uno::Sequence<sal_Int32> m_aColumnTypes; + ORowSetRow m_aInsertRow; + ::rtl::OUString m_aComposedTableName; + sal_Bool m_bInserted; + sal_Bool m_bUpdated; + sal_Bool m_bDeleted; + + OCacheSet(); + virtual ~OCacheSet(); + + void setParameter(sal_Int32 nPos + ,const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XParameters >& _xParameter + ,const connectivity::ORowSetValue& _rValue + ,sal_Int32 _nType + ,sal_Int32 _nScale + ) const; + void fillParameters( const ORowSetRow& _rRow + ,const connectivity::OSQLTable& _xTable + ,::rtl::OUStringBuffer& _sCondition + ,::rtl::OUStringBuffer& _sParameter + ,::std::list< sal_Int32>& _rOrgValues); + void fillTableName(const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet>& _xTable) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + ::rtl::OUString getIdentifierQuoteString() const; + public: + + // late constructor + virtual void construct(const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet>& _xDriverSet,const ::rtl::OUString& i_sRowSetFilter); + virtual void fillValueRow(ORowSetRow& _rRow,sal_Int32 _nPosition); + + // ::com::sun::star::sdbc::XRow + virtual sal_Bool SAL_CALL wasNull( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getString( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL getBoolean( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int8 SAL_CALL getByte( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int16 SAL_CALL getShort( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getInt( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int64 SAL_CALL getLong( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual float SAL_CALL getFloat( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual double SAL_CALL getDouble( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getBytes( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::util::Date SAL_CALL getDate( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::util::Time SAL_CALL getTime( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::util::DateTime SAL_CALL getTimestamp( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getBinaryStream( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getCharacterStream( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Any SAL_CALL getObject( sal_Int32 columnIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& typeMap ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRef > SAL_CALL getRef( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XBlob > SAL_CALL getBlob( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XClob > SAL_CALL getClob( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XArray > SAL_CALL getArray( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + // ::com::sun::star::sdbc::XResultSet + virtual sal_Bool SAL_CALL next( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isBeforeFirst( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isAfterLast( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isFirst( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isLast( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL beforeFirst( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL afterLast( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL first( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL last( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL absolute( sal_Int32 row ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL relative( sal_Int32 rows ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL previous( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL refreshRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL rowUpdated( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL rowInserted( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL rowDeleted( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL getStatement( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + // ::com::sun::star::sdbcx::XRowLocate + virtual ::com::sun::star::uno::Any SAL_CALL getBookmark() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) = 0; + virtual sal_Bool SAL_CALL moveToBookmark( const ::com::sun::star::uno::Any& bookmark ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) = 0; + virtual sal_Bool SAL_CALL moveRelativeToBookmark( const ::com::sun::star::uno::Any& bookmark, sal_Int32 rows ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) = 0; + virtual sal_Int32 SAL_CALL compareBookmarks( const ::com::sun::star::uno::Any& first, const ::com::sun::star::uno::Any& second ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) = 0; + virtual sal_Bool SAL_CALL hasOrderedBookmarks( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) = 0; + virtual sal_Int32 SAL_CALL hashBookmark( const ::com::sun::star::uno::Any& bookmark ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) = 0; + // ::com::sun::star::sdbcx::XDeleteRows + virtual ::com::sun::star::uno::Sequence< sal_Int32 > SAL_CALL deleteRows( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& rows,const connectivity::OSQLTable& _xTable ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) = 0; + // ::com::sun::star::sdbc::XResultSetUpdate + virtual void SAL_CALL insertRow( const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& _xTable ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateRow( const ORowSetRow& _rInsertRow,const ORowSetRow& _rOrginalRow,const connectivity::OSQLTable& _xTable ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) = 0; + virtual void SAL_CALL deleteRow( const ORowSetRow& _rDeleteRow,const connectivity::OSQLTable& _xTable ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) = 0; + virtual void SAL_CALL cancelRowUpdates( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) = 0; + virtual void SAL_CALL moveToInsertRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) = 0; + virtual void SAL_CALL moveToCurrentRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) = 0; + + virtual bool isResultSetChanged() const; + virtual void reset(const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet>& _xDriverSet); + virtual void mergeColumnValues(sal_Int32 i_nColumnIndex,ORowSetValueVector::Vector& io_aInsertRow,ORowSetValueVector::Vector& io_aRow,::std::vector<sal_Int32>& o_aChangedColumns); + virtual bool columnValuesUpdated(ORowSetValueVector::Vector& o_aCachedRow,const ORowSetValueVector::Vector& i_aRow); + virtual bool updateColumnValues(const ORowSetValueVector::Vector& io_aCachedRow,ORowSetValueVector::Vector& io_aRow,const ::std::vector<sal_Int32>& i_aChangedColumns); + virtual void fillMissingValues(ORowSetValueVector::Vector& io_aRow) const; + }; +} +#endif //DBACCESS_CORE_API_CACHESET_HXX + diff --git a/dbaccess/source/core/api/FilteredContainer.cxx b/dbaccess/source/core/api/FilteredContainer.cxx new file mode 100644 index 000000000000..aa20bf080e4d --- /dev/null +++ b/dbaccess/source/core/api/FilteredContainer.cxx @@ -0,0 +1,498 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove + +#include "precompiled_dbaccess.hxx" + +#include "dbastrings.hrc" +#include "FilteredContainer.hxx" +#include "RefreshListener.hxx" +#include "sdbcoretools.hxx" +#include <com/sun/star/sdbc/XRow.hpp> +#include <connectivity/dbtools.hxx> +#include <tools/wldcrd.hxx> +#include <tools/diagnose_ex.h> +#include <rtl/logfile.hxx> +#include <boost/optional.hpp> + +namespace dbaccess +{ + using namespace dbtools; + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::sdbc; + using namespace ::com::sun::star::sdb; + using namespace ::com::sun::star::sdbcx; + using namespace ::com::sun::star::util; + using namespace ::com::sun::star::container; + using namespace ::osl; + using namespace ::comphelper; + using namespace ::cppu; + using namespace ::connectivity::sdbcx; + +//------------------------------------------------------------------------------ +/** creates a vector of WildCards and reduce the _rTableFilter of the length of WildsCards +*/ +sal_Int32 createWildCardVector(Sequence< ::rtl::OUString >& _rTableFilter, ::std::vector< WildCard >& _rOut) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "api", "Ocke.Janssen@sun.com", "OFilteredContainer::createWildCardVector" ); + // for wildcard search : remove all table filters which are a wildcard expression and build a WilCard + // for them + ::rtl::OUString* pTableFilters = _rTableFilter.getArray(); + ::rtl::OUString* pEnd = pTableFilters + _rTableFilter.getLength(); + sal_Int32 nShiftPos = 0; + for (sal_Int32 i=0; pEnd != pTableFilters; ++pTableFilters,++i) + { + if (pTableFilters->indexOf('%') != -1) + { + _rOut.push_back(WildCard(pTableFilters->replace('%', '*'))); + } + else + { + if (nShiftPos != i) + { + _rTableFilter.getArray()[nShiftPos] = _rTableFilter.getArray()[i]; + } + ++nShiftPos; + } + } + // now aTableFilter contains nShiftPos non-wc-strings and aWCSearch all wc-strings + _rTableFilter.realloc(nShiftPos); + return nShiftPos; +} + + // ------------------------------------------------------------------------- + bool lcl_isElementAllowed( const ::rtl::OUString& _rName, + const Sequence< ::rtl::OUString >& _rTableFilter, + const ::std::vector< WildCard >& _rWCSearch ) + { + sal_Int32 nTableFilterLen = _rTableFilter.getLength(); + + const ::rtl::OUString* tableFilter = _rTableFilter.getConstArray(); + const ::rtl::OUString* tableFilterEnd = _rTableFilter.getConstArray() + nTableFilterLen; + bool bFilterMatch = ::std::find( tableFilter, tableFilterEnd, _rName ) != tableFilterEnd; + // the table is allowed to "pass" if we had no filters at all or any of the non-wildcard filters matches + if (!bFilterMatch && !_rWCSearch.empty()) + { // or if one of the wildcrad expression matches + for ( ::std::vector< WildCard >::const_iterator aLoop = _rWCSearch.begin(); + aLoop != _rWCSearch.end() && !bFilterMatch; + ++aLoop + ) + bFilterMatch = aLoop->Matches( _rName ); + } + + return bFilterMatch; + } + + //-------------------------------------------------------------------------- + typedef ::boost::optional< ::rtl::OUString > OptionalString; + struct TableInfo + { + OptionalString sComposedName; + OptionalString sType; + OptionalString sCatalog; + OptionalString sSchema; + OptionalString sName; + + TableInfo( const ::rtl::OUString& _composedName ) + :sComposedName( _composedName ) + { + } + + TableInfo( const ::rtl::OUString& _catalog, const ::rtl::OUString& _schema, const ::rtl::OUString& _name, + const ::rtl::OUString& _type ) + :sComposedName() + ,sType( _type ) + ,sCatalog( _catalog ) + ,sSchema( _schema ) + ,sName( _name ) + { + } + }; + typedef ::std::vector< TableInfo > TableInfos; + + //-------------------------------------------------------------------------- + void lcl_ensureComposedName( TableInfo& _io_tableInfo, const Reference< XDatabaseMetaData >& _metaData ) + { + if ( !_metaData.is() ) + throw RuntimeException(); + + if ( !_io_tableInfo.sComposedName ) + { + OSL_ENSURE( !!_io_tableInfo.sCatalog && !!_io_tableInfo.sSchema && !!_io_tableInfo.sName, "lcl_ensureComposedName: How should I composed the name from nothing!?" ); + + _io_tableInfo.sComposedName = OptionalString( + composeTableName( _metaData, *_io_tableInfo.sCatalog, *_io_tableInfo.sSchema, *_io_tableInfo.sName, + sal_False, ::dbtools::eInDataManipulation ) + ); + } + } + + //-------------------------------------------------------------------------- + void lcl_ensureType( TableInfo& _io_tableInfo, const Reference< XDatabaseMetaData >& _metaData, const Reference< XNameAccess >& _masterContainer ) + { + if ( !!_io_tableInfo.sType ) + return; + + lcl_ensureComposedName( _io_tableInfo, _metaData ); + + if ( !_masterContainer.is() ) + throw RuntimeException(); + + ::rtl::OUString sTypeName; + try + { + Reference< XPropertySet > xTable( _masterContainer->getByName( *_io_tableInfo.sComposedName ), UNO_QUERY_THROW ); + OSL_VERIFY( xTable->getPropertyValue( PROPERTY_TYPE ) >>= sTypeName ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + _io_tableInfo.sType = OptionalString( sTypeName ); + } + + //-------------------------------------------------------------------------- + connectivity::TStringVector lcl_filter( const TableInfos& _unfilteredTables, + const Sequence< ::rtl::OUString >& _tableFilter, const Sequence< ::rtl::OUString >& _tableTypeFilter, + const Reference< XDatabaseMetaData >& _metaData, const Reference< XNameAccess >& _masterContainer ) + { + TableInfos aFilteredTables; + + // first, filter for the table names + sal_Int32 nTableFilterCount = _tableFilter.getLength(); + sal_Bool dontFilterTableNames = ( ( nTableFilterCount == 1 ) && _tableFilter[0].equalsAsciiL( "%", 1 ) ); + if( dontFilterTableNames ) + { + aFilteredTables = _unfilteredTables; + } + else + { + // for wildcard search : remove all table filters which are a wildcard expression and build a WilCard + // for them + ::std::vector< WildCard > aWildCardTableFilter; + Sequence< ::rtl::OUString > aNonWildCardTableFilter = _tableFilter; + nTableFilterCount = createWildCardVector( aNonWildCardTableFilter, aWildCardTableFilter ); + + TableInfos aUnfilteredTables( _unfilteredTables ); + aUnfilteredTables.reserve( nTableFilterCount + ( aWildCardTableFilter.size() * 10 ) ); + + for ( TableInfos::iterator table = aUnfilteredTables.begin(); + table != aUnfilteredTables.end(); + ++table + ) + { + lcl_ensureComposedName( *table, _metaData ); + + if ( lcl_isElementAllowed( *table->sComposedName, aNonWildCardTableFilter, aWildCardTableFilter ) ) + aFilteredTables.push_back( *table ); + } + } + + // second, filter for the table types + sal_Int32 nTableTypeFilterCount = _tableTypeFilter.getLength(); + sal_Bool dontFilterTableTypes = ( ( nTableTypeFilterCount == 1 ) && _tableTypeFilter[0].equalsAsciiL( "%", 1 ) ); + dontFilterTableTypes = dontFilterTableTypes || ( nTableTypeFilterCount == 0 ); + // (for TableTypeFilter, unlike TableFilter, "empty" means "do not filter at all") + if ( !dontFilterTableTypes ) + { + TableInfos aUnfilteredTables; + aUnfilteredTables.swap( aFilteredTables ); + + const ::rtl::OUString* pTableTypeFilterBegin = _tableTypeFilter.getConstArray(); + const ::rtl::OUString* pTableTypeFilterEnd = pTableTypeFilterBegin + _tableTypeFilter.getLength(); + + for ( TableInfos::iterator table = aUnfilteredTables.begin(); + table != aUnfilteredTables.end(); + ++table + ) + { + // ensure that we know the table type + lcl_ensureType( *table, _metaData, _masterContainer ); + + if ( ::std::find( pTableTypeFilterBegin, pTableTypeFilterEnd, *table->sType ) != pTableTypeFilterEnd ) + aFilteredTables.push_back( *table ); + } + } + + connectivity::TStringVector aReturn; + for ( TableInfos::iterator table = aFilteredTables.begin(); + table != aFilteredTables.end(); + ++table + ) + { + lcl_ensureComposedName( *table, _metaData ); + aReturn.push_back( *table->sComposedName ); + } + return aReturn; + } + + //========================================================================== + //= OViewContainer + //========================================================================== + OFilteredContainer::OFilteredContainer(::cppu::OWeakObject& _rParent, + ::osl::Mutex& _rMutex, + const Reference< XConnection >& _xCon, + sal_Bool _bCase, + IRefreshListener* _pRefreshListener, + ::dbtools::IWarningsContainer* _pWarningsContainer + ,oslInterlockedCount& _nInAppend) + :OCollection(_rParent,_bCase,_rMutex,::std::vector< ::rtl::OUString>()) + ,m_bConstructed(sal_False) + ,m_pWarningsContainer(_pWarningsContainer) + ,m_pRefreshListener(_pRefreshListener) + ,m_nInAppend(_nInAppend) + ,m_xConnection(_xCon) + { + } + // ------------------------------------------------------------------------- + void OFilteredContainer::construct(const Reference< XNameAccess >& _rxMasterContainer, + const Sequence< ::rtl::OUString >& _rTableFilter, + const Sequence< ::rtl::OUString >& _rTableTypeFilter) + { + try + { + Reference<XConnection> xCon = m_xConnection; + if ( xCon.is() ) + m_xMetaData = xCon->getMetaData(); + } + catch(SQLException&) + { + DBG_UNHANDLED_EXCEPTION(); + } + + m_xMasterContainer = _rxMasterContainer; + + if ( m_xMasterContainer.is() ) + { + addMasterContainerListener(); + + TableInfos aUnfilteredTables; + + Sequence< ::rtl::OUString > aNames = m_xMasterContainer->getElementNames(); + const ::rtl::OUString* name = aNames.getConstArray(); + const ::rtl::OUString* nameEnd = name + aNames.getLength(); + for ( ; name != nameEnd; ++name ) + aUnfilteredTables.push_back( TableInfo( *name ) ); + + reFill( lcl_filter( aUnfilteredTables, + _rTableFilter, _rTableTypeFilter, m_xMetaData, m_xMasterContainer ) ); + + m_bConstructed = sal_True; + } + else + { + construct( _rTableFilter, _rTableTypeFilter ); + } + } + //------------------------------------------------------------------------------ + void OFilteredContainer::construct(const Sequence< ::rtl::OUString >& _rTableFilter, const Sequence< ::rtl::OUString >& _rTableTypeFilter) + { + // build sorted versions of the filter sequences, so the visibility decision is faster + Sequence< ::rtl::OUString > aTableFilter(_rTableFilter); + sal_Int32 nTableFilterLen = aTableFilter.getLength(); + + // for wildcard search : remove all table filters which are a wildcard expression and build a WilCard + // for them + ::std::vector< WildCard > aWCSearch; + nTableFilterLen = createWildCardVector(aTableFilter,aWCSearch); + + try + { + Reference< XConnection > xCon( m_xConnection, UNO_SET_THROW ); + m_xMetaData.set( xCon->getMetaData(), UNO_SET_THROW ); + + // create a table table filter suitable for the XDatabaseMetaData::getTables call, + // taking into account both the externally-provided table type filter, and any + // table type restriction which is inherent to the container + Sequence< ::rtl::OUString > aTableTypeFilter; + ::rtl::OUString sInherentTableTypeRestriction( getTableTypeRestriction() ); + if ( sInherentTableTypeRestriction.getLength() ) + { + if ( _rTableTypeFilter.getLength() != 0 ) + { + const ::rtl::OUString* tableType = _rTableTypeFilter.getConstArray(); + const ::rtl::OUString* tableTypeEnd = tableType + _rTableTypeFilter.getLength(); + for ( ; tableType != tableTypeEnd; ++tableType ) + { + if ( *tableType == sInherentTableTypeRestriction ) + break; + } + if ( tableType == tableTypeEnd ) + { // the only table type which can be part of this container is not allowed + // by the externally provided table type filter. + m_bConstructed = sal_True; + return; + } + } + aTableTypeFilter.realloc( 1 ); + aTableTypeFilter[0] = sInherentTableTypeRestriction; + } + else + { + // no container-inherent restriction for the table types + if ( _rTableTypeFilter.getLength() == 0 ) + { // no externally-provided table type filter => use the default filter + getAllTableTypeFilter( aTableTypeFilter ); + } + else + { + aTableTypeFilter = _rTableTypeFilter; + } + } + + static const ::rtl::OUString sAll = ::rtl::OUString::createFromAscii("%"); + Reference< XResultSet > xTables = m_xMetaData->getTables( Any(), sAll, sAll, aTableTypeFilter ); + Reference< XRow > xCurrentRow( xTables, UNO_QUERY_THROW ); + + TableInfos aUnfilteredTables; + + ::rtl::OUString sCatalog, sSchema, sName, sType; + while ( xTables->next() ) + { + sCatalog = xCurrentRow->getString(1); + sSchema = xCurrentRow->getString(2); + sName = xCurrentRow->getString(3); + sType = xCurrentRow->getString(4); + + aUnfilteredTables.push_back( TableInfo( sCatalog, sSchema, sName, sType ) ); + } + + reFill( lcl_filter( aUnfilteredTables, + _rTableFilter, aTableTypeFilter, m_xMetaData, NULL ) ); + + disposeComponent( xTables ); + } + catch (const Exception&) + { + DBG_UNHANDLED_EXCEPTION(); + disposing(); + return; + } + + m_bConstructed = sal_True; + } + + //------------------------------------------------------------------------------ + void OFilteredContainer::disposing() + { + OCollection::disposing(); + + if ( m_xMasterContainer.is() ) + removeMasterContainerListener(); + + m_xMasterContainer = NULL; + m_xMetaData = NULL; + m_pWarningsContainer = NULL; + m_pRefreshListener = NULL; + m_bConstructed = sal_False; + } + + // ------------------------------------------------------------------------- + void OFilteredContainer::impl_refresh() throw(RuntimeException) + { + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "api", "Ocke.Janssen@sun.com", "OFilteredContainer::impl_refresh" ); + if ( m_pRefreshListener ) + { + m_bConstructed = sal_False; + Reference<XRefreshable> xRefresh(m_xMasterContainer,UNO_QUERY); + if ( xRefresh.is() ) + xRefresh->refresh(); + m_pRefreshListener->refresh(this); + } + } + + // ----------------------------------------------------------------------------- + ::rtl::OUString OFilteredContainer::getNameForObject(const ObjectType& _xObject) + { + OSL_ENSURE( _xObject.is(), "OFilteredContainer::getNameForObject: Object is NULL!" ); + return ::dbtools::composeTableName( m_xMetaData, _xObject, ::dbtools::eInDataManipulation, false, false, false ); + } + + // ----------------------------------------------------------------------------- + // multiple to obtain all tables from XDatabaseMetaData::getTables, via passing a particular + // table type filter: + // adhere to the standard, which requests to pass a NULL table type filter, if + // you want to retrieve all tables + #define FILTER_MODE_STANDARD 0 + // only pass %, which is not allowed by the standard, but understood by some drivers + #define FILTER_MODE_WILDCARD 1 + // only pass TABLE and VIEW + #define FILTER_MODE_FIXED 2 + // do the thing which showed to be the safest way, understood by nearly all + // drivers, even the ones which do not understand the standard + #define FILTER_MODE_MIX_ALL 3 + + void OFilteredContainer::getAllTableTypeFilter( Sequence< ::rtl::OUString >& /* [out] */ _rFilter ) const + { + sal_Int32 nFilterMode = FILTER_MODE_MIX_ALL; + // for compatibility reasons, this is the default: we used this way before we + // introduced the TableTypeFilterMode setting + + // obtain the data source we belong to, and the TableTypeFilterMode setting + Any aFilterModeSetting; + if ( getDataSourceSetting( getDataSource( (Reference< XInterface >)m_rParent ), "TableTypeFilterMode", aFilterModeSetting ) ) + { + OSL_VERIFY( aFilterModeSetting >>= nFilterMode ); + } + + const ::rtl::OUString sAll( RTL_CONSTASCII_USTRINGPARAM( "%" ) ); + const ::rtl::OUString sView( RTL_CONSTASCII_USTRINGPARAM( "VIEW" ) ); + const ::rtl::OUString sTable( RTL_CONSTASCII_USTRINGPARAM( "TABLE" ) ); + + switch ( nFilterMode ) + { + default: + OSL_ENSURE( sal_False, "OTableContainer::getAllTableTypeFilter: unknown TableTypeFilterMode!" ); + case FILTER_MODE_MIX_ALL: + _rFilter.realloc( 3 ); + _rFilter[0] = sView; + _rFilter[1] = sTable; + _rFilter[2] = sAll; + break; + case FILTER_MODE_FIXED: + _rFilter.realloc( 2 ); + _rFilter[0] = sView; + _rFilter[1] = sTable; + break; + case FILTER_MODE_WILDCARD: + _rFilter.realloc( 1 ); + _rFilter[0] = sAll; + break; + case FILTER_MODE_STANDARD: + _rFilter.realloc( 0 ); + break; + } + } + +// .............................................................................. +} // namespace +// .............................................................................. + + diff --git a/dbaccess/source/core/api/HelperCollections.cxx b/dbaccess/source/core/api/HelperCollections.cxx new file mode 100644 index 000000000000..2e536b5c2e26 --- /dev/null +++ b/dbaccess/source/core/api/HelperCollections.cxx @@ -0,0 +1,122 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" +#ifndef DBA_HELPERCOLLECTIONS_HXX +#include "HelperCollections.hxx" +#endif + +#ifndef DBACCESS_SHARED_DBASTRINGS_HRC +#include "dbastrings.hrc" +#endif + +namespace dbaccess +{ + using namespace dbtools; + using namespace comphelper; + using namespace connectivity; + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::sdbc; + using namespace ::com::sun::star::sdb; + using namespace ::com::sun::star::sdbcx; + using namespace ::com::sun::star::container; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::script; + using namespace ::cppu; + using namespace ::osl; + // ----------------------------------------------------------------------------- + OPrivateColumns::OPrivateColumns(const ::vos::ORef< ::connectivity::OSQLColumns>& _rColumns, + sal_Bool _bCase, + ::cppu::OWeakObject& _rParent, + ::osl::Mutex& _rMutex, + const ::std::vector< ::rtl::OUString> &_rVector, + sal_Bool _bUseAsIndex + ) : sdbcx::OCollection(_rParent,_bCase,_rMutex,_rVector,_bUseAsIndex) + ,m_aColumns(_rColumns) + { + } + + // ------------------------------------------------------------------------- + OPrivateColumns* OPrivateColumns::createWithIntrinsicNames( const ::vos::ORef< ::connectivity::OSQLColumns >& _rColumns, + sal_Bool _bCase, ::cppu::OWeakObject& _rParent, ::osl::Mutex& _rMutex ) + { + ::std::vector< ::rtl::OUString > aNames; aNames.reserve( _rColumns->get().size() ); + + ::rtl::OUString sColumName; + for ( ::connectivity::OSQLColumns::Vector::const_iterator column = _rColumns->get().begin(); + column != _rColumns->get().end(); + ++column + ) + { + Reference< XPropertySet > xColumn( *column, UNO_QUERY_THROW ); + xColumn->getPropertyValue( PROPERTY_NAME ) >>= sColumName; + aNames.push_back( sColumName ); + } + return new OPrivateColumns( _rColumns, _bCase, _rParent, _rMutex, aNames, sal_False ); + } + + // ------------------------------------------------------------------------- + void SAL_CALL OPrivateColumns::disposing(void) + { + m_aColumns = NULL; + clear_NoDispose(); + // we're not owner of the objects we're holding, instead the object we got in our ctor is + // So we're not allowed to dispose our elements. + OPrivateColumns_Base::disposing(); + } + // ------------------------------------------------------------------------- + connectivity::sdbcx::ObjectType OPrivateColumns::createObject(const ::rtl::OUString& _rName) + { + if ( m_aColumns.isValid() ) + { + ::connectivity::OSQLColumns::Vector::const_iterator aIter = find(m_aColumns->get().begin(),m_aColumns->get().end(),_rName,isCaseSensitive()); + if(aIter == m_aColumns->get().end()) + aIter = findRealName(m_aColumns->get().begin(),m_aColumns->get().end(),_rName,isCaseSensitive()); + + if(aIter != m_aColumns->get().end()) + return connectivity::sdbcx::ObjectType(*aIter,UNO_QUERY); + + OSL_ENSURE(0,"Column not found in collection!"); + } + return NULL; + } + // ------------------------------------------------------------------------- + connectivity::sdbcx::ObjectType OPrivateTables::createObject(const ::rtl::OUString& _rName) + { + if ( !m_aTables.empty() ) + { + OSQLTables::iterator aIter = m_aTables.find(_rName); + OSL_ENSURE(aIter != m_aTables.end(),"Table not found!"); + OSL_ENSURE(aIter->second.is(),"Table is null!"); + return connectivity::sdbcx::ObjectType(m_aTables.find(_rName)->second,UNO_QUERY); + } + return NULL; + } + // ----------------------------------------------------------------------------- +} diff --git a/dbaccess/source/core/api/HelperCollections.hxx b/dbaccess/source/core/api/HelperCollections.hxx new file mode 100644 index 000000000000..1169a20b0750 --- /dev/null +++ b/dbaccess/source/core/api/HelperCollections.hxx @@ -0,0 +1,128 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 DBA_HELPERCOLLECTIONS_HXX +#define DBA_HELPERCOLLECTIONS_HXX + +#ifndef _CONNECTIVITY_SDBCX_COLLECTION_HXX_ +#include "connectivity/sdbcx/VCollection.hxx" +#endif +#ifndef _CONNECTIVITY_DBTOOLS_HXX_ +#include <connectivity/dbtools.hxx> +#endif +#ifndef _DBHELPER_DBCONVERSION_HXX_ +#include <connectivity/dbconversion.hxx> +#endif +#ifndef _CONNECTIVITY_SDBCX_COLUMN_HXX_ +#include <connectivity/PColumn.hxx> +#endif +#ifndef _VOS_REF_HXX_ +#include <vos/ref.hxx> +#endif + +namespace dbaccess +{ + using namespace dbtools; + using namespace comphelper; + using namespace connectivity; + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::sdbc; + using namespace ::com::sun::star::sdb; + using namespace ::com::sun::star::sdbcx; + using namespace ::com::sun::star::container; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::script; + using namespace ::cppu; + using namespace ::osl; + // ----------------------------------------------------------------------------- + typedef connectivity::sdbcx::OCollection OPrivateColumns_Base; + class OPrivateColumns : public OPrivateColumns_Base + { + ::vos::ORef< ::connectivity::OSQLColumns> m_aColumns; + protected: + virtual connectivity::sdbcx::ObjectType createObject(const ::rtl::OUString& _rName); + virtual void impl_refresh() throw(RuntimeException) {} + virtual Reference< XPropertySet > createDescriptor() + { + return NULL; + } + public: + OPrivateColumns(const ::vos::ORef< ::connectivity::OSQLColumns>& _rColumns, + sal_Bool _bCase, + ::cppu::OWeakObject& _rParent, + ::osl::Mutex& _rMutex, + const ::std::vector< ::rtl::OUString> &_rVector, + sal_Bool _bUseAsIndex = sal_False + ); + + /** creates a columns instance as above, but taking the names from the columns itself + */ + static OPrivateColumns* createWithIntrinsicNames( + const ::vos::ORef< ::connectivity::OSQLColumns >& _rColumns, + sal_Bool _bCase, + ::cppu::OWeakObject& _rParent, + ::osl::Mutex& _rMutex + ); + + virtual void SAL_CALL disposing(void); + }; + typedef connectivity::sdbcx::OCollection OPrivateTables_BASE; + + //========================================================================== + //= OPrivateTables + //========================================================================== + class OPrivateTables : public OPrivateTables_BASE + { + OSQLTables m_aTables; + protected: + virtual connectivity::sdbcx::ObjectType createObject(const ::rtl::OUString& _rName); + virtual void impl_refresh() throw(RuntimeException) {} + virtual Reference< XPropertySet > createDescriptor() + { + return NULL; + } + public: + OPrivateTables( const OSQLTables& _rTables, + sal_Bool _bCase, + ::cppu::OWeakObject& _rParent, + ::osl::Mutex& _rMutex, + const ::std::vector< ::rtl::OUString> &_rVector + ) : sdbcx::OCollection(_rParent,_bCase,_rMutex,_rVector) + ,m_aTables(_rTables) + { + } + virtual void SAL_CALL disposing(void) + { + clear_NoDispose(); + // we're not owner of the objects we're holding, instead the object we got in our ctor is + // So we're not allowed to dispose our elements. + m_aTables.clear(); + OPrivateTables_BASE::disposing(); + } + }; +} +#endif // DBA_HELPERCOLLECTIONS_HXX diff --git a/dbaccess/source/core/api/KeySet.cxx b/dbaccess/source/core/api/KeySet.cxx new file mode 100644 index 000000000000..6ee7a2b8ea4c --- /dev/null +++ b/dbaccess/source/core/api/KeySet.cxx @@ -0,0 +1,1691 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle andor its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#ifndef DBACCESS_CORE_API_KEYSET_HXX +#include "KeySet.hxx" +#endif +#ifndef _DBA_CORE_RESOURCE_HXX_ +#include "core_resource.hxx" +#endif +#ifndef _DBA_CORE_RESOURCE_HRC_ +#include "core_resource.hrc" +#endif +#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_ +#include <com/sun/star/beans/XPropertySet.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XDATABASEMETADATA_HPP_ +#include <com/sun/star/sdbc/XDatabaseMetaData.hpp> +#endif +#include <com/sun/star/sdbc/ColumnValue.hpp> +#ifndef _COM_SUN_STAR_SDBC_XPREPAREDSTATEMENT_HPP_ +#include <com/sun/star/sdbc/XPreparedStatement.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBCxParameterS_HPP_ +#include <com/sun/star/sdbc/XParameters.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XGENERATEDRESULTSET_HPP_ +#include <com/sun/star/sdbc/XGeneratedResultSet.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XCOLUMNLOCATE_HPP_ +#include <com/sun/star/sdbc/XColumnLocate.hpp> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XINDEXACCESS_HPP_ +#include <com/sun/star/container/XIndexAccess.hpp> +#endif +#ifndef DBACCESS_SHARED_DBASTRINGS_HRC +#include "dbastrings.hrc" +#endif +#ifndef _DBASHARED_APITOOLS_HXX_ +#include "apitools.hxx" +#endif +#ifndef _COM_SUN_STAR_SDBCX_XKEYSSUPPLIER_HPP_ +#include <com/sun/star/sdbcx/XKeysSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_SDB_XSINGLESELECTQUERYCOMPOSER_HPP_ +#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBCX_XINDEXESSUPPLIER_HPP_ +#include <com/sun/star/sdbcx/XIndexesSupplier.hpp> +#endif +#ifndef _CPPUHELPER_TYPEPROVIDER_HXX_ +#include <cppuhelper/typeprovider.hxx> +#endif +#ifndef _COMPHELPER_TYPES_HXX_ +#include <comphelper/types.hxx> +#endif +#ifndef _COM_SUN_STAR_SDBCX_KEYTYPE_HPP_ +#include <com/sun/star/sdbcx/KeyType.hpp> +#endif +#ifndef _CONNECTIVITY_DBTOOLS_HXX_ +#include <connectivity/dbtools.hxx> +#endif +#ifndef _DBHELPER_DBEXCEPTION_HXX_ +#include <connectivity/dbexception.hxx> +#endif +#include <list> +#include <algorithm> +#include <string.h> +#ifndef _COM_SUN_STAR_IO_XINPUTSTREAM_HPP_ +#include <com/sun/star/io/XInputStream.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBCX_XTABLESSUPPLIER_HPP_ +#include <com/sun/star/sdbcx/XTablesSupplier.hpp> +#endif +#ifndef DBACCESS_CORE_API_QUERYCOMPOSER_HXX +#include "querycomposer.hxx" +#endif +#ifndef DBACCESS_SOURCE_CORE_INC_COMPOSERTOOLS_HXX +#include "composertools.hxx" +#endif +#ifndef _TOOLS_DEBUG_HXX +#include <tools/debug.hxx> +#endif +#include <string.h> +#include <rtl/logfile.hxx> +#include "PrivateRow.hxx" + +using namespace dbaccess; +using namespace ::connectivity; +using namespace ::dbtools; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star; +using namespace ::cppu; +using namespace ::osl; + +namespace +{ + void lcl_fillIndexColumns(const Reference<XIndexAccess>& _xIndexes, ::std::vector< Reference<XNameAccess> >& _rAllIndexColumns) + { + if ( _xIndexes.is() ) + { + Reference<XPropertySet> xIndexColsSup; + sal_Int32 nCount = _xIndexes->getCount(); + for(sal_Int32 j = 0 ; j < nCount ; ++j) + { + xIndexColsSup.set(_xIndexes->getByIndex(j),UNO_QUERY); + if( xIndexColsSup.is() + && comphelper::getBOOL(xIndexColsSup->getPropertyValue(PROPERTY_ISUNIQUE)) + && !comphelper::getBOOL(xIndexColsSup->getPropertyValue(PROPERTY_ISPRIMARYKEYINDEX)) + ) + _rAllIndexColumns.push_back(Reference<XColumnsSupplier>(xIndexColsSup,UNO_QUERY)->getColumns()); + } + } + } +} +DBG_NAME(OKeySet) +// ------------------------------------------------------------------------- +OKeySet::OKeySet(const connectivity::OSQLTable& _xTable, + const Reference< XIndexAccess>& _xTableKeys, + const ::rtl::OUString& _rUpdateTableName, // this can be the alias or the full qualified name + const Reference< XSingleSelectQueryAnalyzer >& _xComposer, + const ORowSetValueVector& _aParameterValueForCache) + :m_aParameterValueForCache(_aParameterValueForCache) + ,m_pKeyColumnNames(NULL) + ,m_pColumnNames(NULL) + ,m_pParameterNames(NULL) + ,m_pForeignColumnNames(NULL) + ,m_xTable(_xTable) + ,m_xTableKeys(_xTableKeys) + ,m_xComposer(_xComposer) + ,m_sUpdateTableName(_rUpdateTableName) + ,m_bRowCountFinal(sal_False) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::OKeySet" ); + DBG_CTOR(OKeySet,NULL); + +} +// ----------------------------------------------------------------------------- +OKeySet::~OKeySet() +{ + try + { + ::comphelper::disposeComponent(m_xStatement); + } + catch(Exception&) + { + m_xStatement = NULL; + } + catch(...) + { + OSL_ENSURE(0,"Unknown Exception occured"); + } + m_xComposer = NULL; + + DBG_DTOR(OKeySet,NULL); +} +void OKeySet::initColumns() +{ + Reference<XDatabaseMetaData> xMeta = m_xConnection->getMetaData(); + bool bCase = (xMeta.is() && xMeta->storesMixedCaseQuotedIdentifiers()) ? true : false; + m_pKeyColumnNames.reset( new SelectColumnsMetaData(bCase) ); + m_pColumnNames.reset( new SelectColumnsMetaData(bCase) ); + m_pParameterNames.reset( new SelectColumnsMetaData(bCase) ); + m_pForeignColumnNames.reset( new SelectColumnsMetaData(bCase) ); +} +void OKeySet::findTableColumnsMatching_throw(const Any& i_aTable + ,const Reference<XDatabaseMetaData>& i_xMeta + ,const Reference<XNameAccess>& i_xQueryColumns) +{ + // first ask the database itself for the best columns which can be used + Sequence< ::rtl::OUString> aBestColumnNames; + Reference<XNameAccess> xKeyColumns = getPrimaryKeyColumns_throw(i_aTable); + if ( xKeyColumns.is() ) + aBestColumnNames = xKeyColumns->getElementNames(); + + const Reference<XColumnsSupplier> xTblColSup(i_aTable,UNO_QUERY_THROW); + const Reference<XNameAccess> xTblColumns = xTblColSup->getColumns(); + // locate parameter in select columns + Reference<XParametersSupplier> xParaSup(m_xComposer,UNO_QUERY); + Reference<XIndexAccess> xQueryParameters = xParaSup->getParameters(); + const sal_Int32 nParaCount = xQueryParameters->getCount(); + Sequence< ::rtl::OUString> aParameterColumns(nParaCount); + for(sal_Int32 i = 0; i< nParaCount;++i) + { + Reference<XPropertySet> xPara(xQueryParameters->getByIndex(i),UNO_QUERY_THROW); + xPara->getPropertyValue(PROPERTY_REALNAME) >>= aParameterColumns[i]; + } + + if ( m_sUpdateTableName.getLength() ) + { + ::dbaccess::getColumnPositions(i_xQueryColumns,aBestColumnNames,m_sUpdateTableName,(*m_pKeyColumnNames),true); + ::dbaccess::getColumnPositions(i_xQueryColumns,xTblColumns->getElementNames(),m_sUpdateTableName,(*m_pColumnNames),true); + ::dbaccess::getColumnPositions(i_xQueryColumns,aParameterColumns,m_sUpdateTableName,(*m_pParameterNames),true); + } + else + { + ::rtl::OUString sCatalog,sSchema,sTable; + Reference<XPropertySet> xTableProp(i_aTable,UNO_QUERY); + Any aCatalog = xTableProp->getPropertyValue(PROPERTY_CATALOGNAME); + aCatalog >>= sCatalog; + xTableProp->getPropertyValue(PROPERTY_SCHEMANAME) >>= sSchema; + xTableProp->getPropertyValue(PROPERTY_NAME) >>= sTable; + const ::rtl::OUString sComposedUpdateTableName = dbtools::composeTableName( i_xMeta, sCatalog, sSchema, sTable, sal_False, ::dbtools::eInDataManipulation ); + ::dbaccess::getColumnPositions(i_xQueryColumns,aBestColumnNames,sComposedUpdateTableName,(*m_pKeyColumnNames),true); + ::dbaccess::getColumnPositions(i_xQueryColumns,xTblColumns->getElementNames(),sComposedUpdateTableName,(*m_pColumnNames),true); + ::dbaccess::getColumnPositions(i_xQueryColumns,aParameterColumns,sComposedUpdateTableName,(*m_pParameterNames),true); + } + + SelectColumnsMetaData::const_iterator aPosIter = m_pKeyColumnNames->begin(); + SelectColumnsMetaData::const_iterator aPosEnd = m_pKeyColumnNames->end(); + for(;aPosIter != aPosEnd;++aPosIter) + { + if ( xTblColumns->hasByName(aPosIter->second.sRealName) ) + { + Reference<XPropertySet> xProp(xTblColumns->getByName(aPosIter->second.sRealName),UNO_QUERY); + sal_Bool bAuto = sal_False; + if( (xProp->getPropertyValue(PROPERTY_ISAUTOINCREMENT) >>= bAuto) && bAuto) + m_aAutoColumns.push_back(aPosIter->first); + } + } +} +::rtl::OUStringBuffer OKeySet::createKeyFilter() +{ + static ::rtl::OUString aAnd = ::rtl::OUString::createFromAscii(" AND "); + const ::rtl::OUString aQuote = getIdentifierQuoteString(); + ::rtl::OUStringBuffer aFilter; + static ::rtl::OUString s_sDot(RTL_CONSTASCII_USTRINGPARAM(".")); + static ::rtl::OUString s_sParam(RTL_CONSTASCII_USTRINGPARAM(" = ?")); + // create the where clause + Reference<XDatabaseMetaData> xMeta = m_xConnection->getMetaData(); + SelectColumnsMetaData::iterator aPosEnd = m_pKeyColumnNames->end(); + for(SelectColumnsMetaData::iterator aPosIter = m_pKeyColumnNames->begin();aPosIter != aPosEnd;) + { + aFilter.append(::dbtools::quoteTableName( xMeta,aPosIter->second.sTableName,::dbtools::eInDataManipulation)); + aFilter.append(s_sDot); + aFilter.append(::dbtools::quoteName( aQuote,aPosIter->second.sRealName)); + aFilter.append(s_sParam); + ++aPosIter; + if(aPosIter != aPosEnd) + aFilter.append(aAnd); + } + return aFilter; +} +// ----------------------------------------------------------------------------- +void OKeySet::construct(const Reference< XResultSet>& _xDriverSet,const ::rtl::OUString& i_sRowSetFilter) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::construct" ); + OCacheSet::construct(_xDriverSet,i_sRowSetFilter); + initColumns(); + + Reference<XNameAccess> xKeyColumns = getKeyColumns(); + Reference<XDatabaseMetaData> xMeta = m_xConnection->getMetaData(); + Reference<XColumnsSupplier> xQueryColSup(m_xComposer,UNO_QUERY); + const Reference<XNameAccess> xQueryColumns = xQueryColSup->getColumns(); + findTableColumnsMatching_throw(makeAny(m_xTable),xMeta,xQueryColumns); + + // the first row is empty because it's now easier for us to distinguish when we are beforefirst or first + // without extra varaible to be set + m_aKeyMap.insert(OKeySetMatrix::value_type(0,OKeySetValue(NULL,::std::pair<sal_Int32,Reference<XRow> >(0,NULL)))); + m_aKeyIter = m_aKeyMap.begin(); + + ::rtl::OUStringBuffer aFilter = createKeyFilter(); + + Reference< XSingleSelectQueryComposer> xSourceComposer(m_xComposer,UNO_QUERY); + Reference< XMultiServiceFactory > xFactory(m_xConnection, UNO_QUERY_THROW); + Reference<XSingleSelectQueryComposer> xAnalyzer(xFactory->createInstance(SERVICE_NAME_SINGLESELECTQUERYCOMPOSER),UNO_QUERY); + xAnalyzer->setElementaryQuery(xSourceComposer->getElementaryQuery()); + Reference<XTablesSupplier> xTabSup(xAnalyzer,uno::UNO_QUERY); + Reference<XNameAccess> xSelectTables(xTabSup->getTables(),uno::UNO_QUERY); + const Sequence< ::rtl::OUString> aSeq = xSelectTables->getElementNames(); + if ( aSeq.getLength() > 1 ) // special handling for join + { + static ::rtl::OUString aAnd = ::rtl::OUString::createFromAscii(" AND "); + const ::rtl::OUString aQuote = getIdentifierQuoteString(); + static ::rtl::OUString s_sDot(RTL_CONSTASCII_USTRINGPARAM(".")); + static ::rtl::OUString s_sParam(RTL_CONSTASCII_USTRINGPARAM(" = ?")); + const ::rtl::OUString* pIter = aSeq.getConstArray(); + const ::rtl::OUString* pEnd = pIter + aSeq.getLength(); + for(;pIter != pEnd;++pIter) + { + if ( *pIter != m_sUpdateTableName ) + { + connectivity::OSQLTable xSelColSup(xSelectTables->getByName(*pIter),uno::UNO_QUERY); + Reference<XPropertySet> xProp(xSelColSup,uno::UNO_QUERY); + ::rtl::OUString sSelectTableName = ::dbtools::composeTableName( xMeta, xProp, ::dbtools::eInDataManipulation, false, false, false ); + + ::dbaccess::getColumnPositions(xQueryColumns,xSelColSup->getColumns()->getElementNames(),sSelectTableName,(*m_pForeignColumnNames)); + + SelectColumnsMetaData::iterator aPosEnd = (*m_pForeignColumnNames).end(); + for(SelectColumnsMetaData::iterator aPosIter = (*m_pForeignColumnNames).begin();aPosIter != aPosEnd;++aPosIter) + { + // look for columns not in the source columns to use them as filter as well + // if ( !xSourceColumns->hasByName(aPosIter->first) ) + { + if ( aFilter.getLength() ) + aFilter.append(aAnd); + aFilter.append(::dbtools::quoteName( aQuote,sSelectTableName)); + aFilter.append(s_sDot); + aFilter.append(::dbtools::quoteName( aQuote,aPosIter->second.sRealName)); + aFilter.append(s_sParam); + } + } + break; + } + } + } // if ( aSeq.getLength() > 1 ) // special handling for join + executeStatement(aFilter,i_sRowSetFilter,xAnalyzer); +} +void OKeySet::executeStatement(::rtl::OUStringBuffer& io_aFilter,const ::rtl::OUString& i_sRowSetFilter,Reference<XSingleSelectQueryComposer>& io_xAnalyzer) +{ + bool bFilterSet = i_sRowSetFilter.getLength() != 0; + if ( bFilterSet ) + { + FilterCreator aFilterCreator; + aFilterCreator.append( i_sRowSetFilter ); + aFilterCreator.append( io_aFilter.makeStringAndClear() ); + io_aFilter = aFilterCreator.getComposedAndClear(); + } + io_xAnalyzer->setFilter(io_aFilter.makeStringAndClear()); + if ( bFilterSet ) + { + Sequence< Sequence< PropertyValue > > aFilter2 = io_xAnalyzer->getStructuredFilter(); + const Sequence< PropertyValue >* pOr = aFilter2.getConstArray(); + const Sequence< PropertyValue >* pOrEnd = pOr + aFilter2.getLength(); + for(;pOr != pOrEnd;++pOr) + { + const PropertyValue* pAnd = pOr->getConstArray(); + const PropertyValue* pAndEnd = pAnd + pOr->getLength(); + for(;pAnd != pAndEnd;++pAnd) + { + ::rtl::OUString sValue; + if ( !(pAnd->Value >>= sValue) || !(sValue.equalsAscii("?") || sValue.matchAsciiL(":",1,0)) ) + { // we have a criteria which has to be taken into account for updates + m_aFilterColumns.push_back(pAnd->Name); + } + } + } + } + m_xStatement = m_xConnection->prepareStatement(io_xAnalyzer->getQueryWithSubstitution()); + ::comphelper::disposeComponent(io_xAnalyzer); +} +// ------------------------------------------------------------------------- +Any SAL_CALL OKeySet::getBookmark() throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getBookmark" ); + OSL_ENSURE(m_aKeyIter != m_aKeyMap.end() && m_aKeyIter != m_aKeyMap.begin(), + "getBookmark is only possible when we stand on a valid row!"); + return makeAny(m_aKeyIter->first); +} + +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OKeySet::moveToBookmark( const Any& bookmark ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::moveToBookmark" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + m_aKeyIter = m_aKeyMap.find(::comphelper::getINT32(bookmark)); + return m_aKeyIter != m_aKeyMap.end(); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OKeySet::moveRelativeToBookmark( const Any& bookmark, sal_Int32 rows ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::moveRelativeToBookmark" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + m_aKeyIter = m_aKeyMap.find(::comphelper::getINT32(bookmark)); + if(m_aKeyIter != m_aKeyMap.end()) + { + relative(rows); + } + + return !isBeforeFirst() && !isAfterLast(); +} +// ------------------------------------------------------------------------- +sal_Int32 SAL_CALL OKeySet::compareBookmarks( const Any& _first, const Any& _second ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::compareBookmarks" ); + sal_Int32 nFirst = 0, nSecond = 0; + _first >>= nFirst; + _second >>= nSecond; + + return (nFirst != nSecond) ? CompareBookmark::NOT_EQUAL : CompareBookmark::EQUAL; +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OKeySet::hasOrderedBookmarks( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::hasOrderedBookmarks" ); + return sal_True; +} +// ------------------------------------------------------------------------- +sal_Int32 SAL_CALL OKeySet::hashBookmark( const Any& bookmark ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::hashBookmark" ); + return ::comphelper::getINT32(bookmark); +} +// ------------------------------------------------------------------------- +// ::com::sun::star::sdbcx::XDeleteRows +Sequence< sal_Int32 > SAL_CALL OKeySet::deleteRows( const Sequence< Any >& rows ,const connectivity::OSQLTable& _xTable) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::deleteRows" ); + Reference<XPropertySet> xSet(_xTable,UNO_QUERY); + fillTableName(xSet); + + ::rtl::OUStringBuffer aSql = ::rtl::OUString::createFromAscii("DELETE FROM "); + aSql.append(m_aComposedTableName); + aSql.append(::rtl::OUString::createFromAscii(" WHERE ")); + + // list all cloumns that should be set + const ::rtl::OUString aQuote = getIdentifierQuoteString(); + static ::rtl::OUString aAnd = ::rtl::OUString::createFromAscii(" AND "); + static ::rtl::OUString aOr = ::rtl::OUString::createFromAscii(" OR "); + static ::rtl::OUString aEqual = ::rtl::OUString::createFromAscii(" = ?"); + + + // use keys and indexes for excat postioning + // first the keys + Reference<XNameAccess> xKeyColumns = getKeyColumns(); + + ::rtl::OUStringBuffer aCondition = ::rtl::OUString::createFromAscii("( "); + + SelectColumnsMetaData::const_iterator aIter = (*m_pKeyColumnNames).begin(); + SelectColumnsMetaData::const_iterator aPosEnd = (*m_pKeyColumnNames).end(); + for(;aIter != aPosEnd;++aIter) + { + aCondition.append(::dbtools::quoteName( aQuote,aIter->second.sRealName)); + aCondition.append(aEqual); + aCondition.append(aAnd); + } + aCondition.setLength(aCondition.getLength()-5); + const ::rtl::OUString sCon( aCondition.makeStringAndClear() ); + + const Any* pBegin = rows.getConstArray(); + const Any* pEnd = pBegin + rows.getLength(); + + Sequence< Any > aKeys; + for(;pBegin != pEnd;++pBegin) + { + aSql.append(sCon); + aSql.append(aOr); + } + aSql.setLength(aSql.getLength()-3); + + // now create end execute the prepared statement + + Reference< XPreparedStatement > xPrep(m_xConnection->prepareStatement(aSql.makeStringAndClear())); + Reference< XParameters > xParameter(xPrep,UNO_QUERY); + + pBegin = rows.getConstArray(); + sal_Int32 i=1; + for(;pBegin != pEnd;++pBegin) + { + m_aKeyIter = m_aKeyMap.find(::comphelper::getINT32(*pBegin)); + if(m_aKeyIter != m_aKeyMap.end()) + { + connectivity::ORowVector< ORowSetValue >::Vector::iterator aKeyIter = m_aKeyIter->second.first->get().begin(); + connectivity::ORowVector< ORowSetValue >::Vector::iterator aKeyEnd = m_aKeyIter->second.first->get().end(); + SelectColumnsMetaData::const_iterator aPosIter = (*m_pKeyColumnNames).begin(); + for(sal_uInt16 j = 0;aKeyIter != aKeyEnd;++aKeyIter,++j,++aPosIter) + { + setParameter(i++,xParameter,*aKeyIter,aPosIter->second.nType,aPosIter->second.nScale); + } + } + } + + sal_Bool bOk = xPrep->executeUpdate() > 0; + Sequence< sal_Int32 > aRet(rows.getLength()); + memset(aRet.getArray(),bOk,sizeof(sal_Int32)*aRet.getLength()); + if(bOk) + { + pBegin = rows.getConstArray(); + pEnd = pBegin + rows.getLength(); + + for(;pBegin != pEnd;++pBegin) + { + sal_Int32 nPos = 0; + *pBegin >>= nPos; + if(m_aKeyIter == m_aKeyMap.find(nPos) && m_aKeyIter != m_aKeyMap.end()) + ++m_aKeyIter; + m_aKeyMap.erase(nPos); + m_bDeleted = sal_True; + } + } + return aRet; +} +// ------------------------------------------------------------------------- +void SAL_CALL OKeySet::updateRow(const ORowSetRow& _rInsertRow ,const ORowSetRow& _rOrginalRow,const connectivity::OSQLTable& _xTable ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::updateRow" ); + Reference<XPropertySet> xSet(_xTable,UNO_QUERY); + fillTableName(xSet); + + ::rtl::OUStringBuffer aSql = ::rtl::OUString::createFromAscii("UPDATE "); + aSql.append(m_aComposedTableName); + aSql.append(::rtl::OUString::createFromAscii(" SET ")); + // list all cloumns that should be set + static ::rtl::OUString aPara = ::rtl::OUString::createFromAscii(" = ?,"); + ::rtl::OUString aQuote = getIdentifierQuoteString(); + static ::rtl::OUString aAnd = ::rtl::OUString::createFromAscii(" AND "); + ::rtl::OUString sIsNull(RTL_CONSTASCII_USTRINGPARAM(" IS NULL")); + ::rtl::OUString sParam(RTL_CONSTASCII_USTRINGPARAM(" = ?")); + + // use keys and indexes for excat postioning + // first the keys + Reference<XNameAccess> xKeyColumns = getKeyColumns(); + + // second the indexes + Reference<XIndexesSupplier> xIndexSup(_xTable,UNO_QUERY); + Reference<XIndexAccess> xIndexes; + if ( xIndexSup.is() ) + xIndexes.set(xIndexSup->getIndexes(),UNO_QUERY); + + + ::std::vector< Reference<XNameAccess> > aAllIndexColumns; + lcl_fillIndexColumns(xIndexes,aAllIndexColumns); + + ::rtl::OUString aColumnName; + ::rtl::OUStringBuffer sKeyCondition,sIndexCondition; + ::std::vector<sal_Int32> aIndexColumnPositions; + + const sal_Int32 nOldLength = aSql.getLength(); + sal_Int32 i = 1; + // here we build the condition part for the update statement + SelectColumnsMetaData::const_iterator aIter = m_pColumnNames->begin(); + SelectColumnsMetaData::const_iterator aEnd = m_pColumnNames->end(); + for(;aIter != aEnd;++aIter,++i) + { + //if(xKeyColumns.is() && xKeyColumns->hasByName(aIter->first)) + if ( m_pKeyColumnNames->find(aIter->first) != m_pKeyColumnNames->end() ) + { + sKeyCondition.append(::dbtools::quoteName( aQuote,aIter->second.sRealName)); + if((_rOrginalRow->get())[aIter->second.nPosition].isNull()) + sKeyCondition.append(sIsNull); + else + sKeyCondition.append(sParam); + sKeyCondition.append(aAnd); + } + else + { + ::std::vector< Reference<XNameAccess> >::const_iterator aIndexEnd = aAllIndexColumns.end(); + for( ::std::vector< Reference<XNameAccess> >::const_iterator aIndexIter = aAllIndexColumns.begin(); + aIndexIter != aIndexEnd;++aIndexIter) + { + if((*aIndexIter)->hasByName(aIter->first)) + { + sIndexCondition.append(::dbtools::quoteName( aQuote,aIter->second.sRealName)); + if((_rOrginalRow->get())[aIter->second.nPosition].isNull()) + sIndexCondition.append(sIsNull); + else + { + sIndexCondition.append(sParam); + aIndexColumnPositions.push_back(aIter->second.nPosition); + } + sIndexCondition.append(aAnd); + break; + } + } + } + if((_rInsertRow->get())[aIter->second.nPosition].isModified()) + { + aSql.append(::dbtools::quoteName( aQuote,aIter->second.sRealName)); + aSql.append(aPara); + } + } + + if( aSql.getLength() != nOldLength ) + { + aSql.setLength(aSql.getLength()-1); + } + else + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_NO_VALUE_CHANGED ), SQL_GENERAL_ERROR, m_xConnection ); + + if(sKeyCondition.getLength() || sIndexCondition.getLength()) + { + aSql.append(::rtl::OUString::createFromAscii(" WHERE ")); + if(sKeyCondition.getLength() && sIndexCondition.getLength()) + { + aSql.append(sKeyCondition.makeStringAndClear()); + aSql.append(sIndexCondition.makeStringAndClear()); + } + else if(sKeyCondition.getLength()) + { + aSql.append(sKeyCondition.makeStringAndClear()); + } + else if(sIndexCondition.getLength()) + { + aSql.append(sIndexCondition.makeStringAndClear()); + } + aSql.setLength(aSql.getLength()-5); // remove the last AND + } + else + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_NO_CONDITION_FOR_PK ), SQL_GENERAL_ERROR, m_xConnection ); + + // now create end execute the prepared statement + + ::rtl::OUString sEmpty; + executeUpdate(_rInsertRow ,_rOrginalRow,aSql.makeStringAndClear(),sEmpty,aIndexColumnPositions); +} +// ----------------------------------------------------------------------------- +void OKeySet::executeUpdate(const ORowSetRow& _rInsertRow ,const ORowSetRow& _rOrginalRow,const ::rtl::OUString& i_sSQL,const ::rtl::OUString& i_sTableName,const ::std::vector<sal_Int32>& _aIndexColumnPositions) +{ + // now create end execute the prepared statement + Reference< XPreparedStatement > xPrep(m_xConnection->prepareStatement(i_sSQL)); + Reference< XParameters > xParameter(xPrep,UNO_QUERY); + + bool bRefetch = true; + Reference<XRow> xRow; + sal_Int32 i = 1; + // first the set values + SelectColumnsMetaData::const_iterator aIter = m_pColumnNames->begin(); + SelectColumnsMetaData::const_iterator aEnd = m_pColumnNames->end(); + sal_uInt16 j = 0; + for(;aIter != aEnd;++aIter,++j) + { + if ( !i_sTableName.getLength() || aIter->second.sTableName == i_sTableName ) + { + sal_Int32 nPos = aIter->second.nPosition; + if((_rInsertRow->get())[nPos].isModified()) + { + if ( bRefetch ) + { + bRefetch = ::std::find(m_aFilterColumns.begin(),m_aFilterColumns.end(),aIter->second.sRealName) == m_aFilterColumns.end(); + } + impl_convertValue_throw(_rInsertRow,aIter->second); + (_rInsertRow->get())[nPos].setSigned((_rOrginalRow->get())[nPos].isSigned()); + setParameter(i++,xParameter,(_rInsertRow->get())[nPos],aIter->second.nType,aIter->second.nScale); + } + } + } + // and then the values of the where condition + aIter = m_pKeyColumnNames->begin(); + aEnd = m_pKeyColumnNames->end(); + j = 0; + for(;aIter != aEnd;++aIter,++j) + { + if ( !i_sTableName.getLength() || aIter->second.sTableName == i_sTableName ) + { + setParameter(i++,xParameter,(_rOrginalRow->get())[aIter->second.nPosition],aIter->second.nType,aIter->second.nScale); + } + } + if ( !_aIndexColumnPositions.empty() ) + { + // now we have to set the index values + ::std::vector<sal_Int32>::const_iterator aIdxColIter = _aIndexColumnPositions.begin(); + ::std::vector<sal_Int32>::const_iterator aIdxColEnd = _aIndexColumnPositions.end(); + j = 0; + aIter = m_pColumnNames->begin(); + for(;aIdxColIter != aIdxColEnd;++aIdxColIter,++i,++j,++aIter) + { + setParameter(i,xParameter,(_rOrginalRow->get())[*aIdxColIter],(_rOrginalRow->get())[*aIdxColIter].getTypeKind(),aIter->second.nScale); + } + } + const sal_Int32 nRowsUpdated = xPrep->executeUpdate(); + m_bUpdated = nRowsUpdated > 0; + if(m_bUpdated) + { + const sal_Int32 nBookmark = ::comphelper::getINT32((_rInsertRow->get())[0].getAny()); + m_aKeyIter = m_aKeyMap.find(nBookmark); + m_aKeyIter->second.second.first = 2; + m_aKeyIter->second.second.second = xRow; + copyRowValue(_rInsertRow,m_aKeyIter->second.first,nBookmark); + tryRefetch(_rInsertRow,bRefetch); + } +} +// ------------------------------------------------------------------------- +void SAL_CALL OKeySet::insertRow( const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& _xTable ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::insertRow" ); + ::rtl::OUStringBuffer aSql(::rtl::OUString::createFromAscii("INSERT INTO ")); + Reference<XPropertySet> xSet(_xTable,UNO_QUERY); + fillTableName(xSet); + + aSql.append(m_aComposedTableName); + aSql.append(::rtl::OUString::createFromAscii(" ( ")); + // set values and column names + ::rtl::OUStringBuffer aValues(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" VALUES ( "))); + static ::rtl::OUString aPara(RTL_CONSTASCII_USTRINGPARAM("?,")); + ::rtl::OUString aQuote = getIdentifierQuoteString(); + static ::rtl::OUString aComma(RTL_CONSTASCII_USTRINGPARAM(",")); + + SelectColumnsMetaData::const_iterator aIter = m_pColumnNames->begin(); + SelectColumnsMetaData::const_iterator aEnd = m_pColumnNames->end(); + sal_Int32 j = 1; + bool bRefetch = true; + sal_Bool bModified = sal_False; + for(;aIter != aEnd;++aIter,++j) + { + if((_rInsertRow->get())[aIter->second.nPosition].isModified()) + { + if ( bRefetch ) + { + bRefetch = ::std::find(m_aFilterColumns.begin(),m_aFilterColumns.end(),aIter->second.sRealName) == m_aFilterColumns.end(); + } + aSql.append(::dbtools::quoteName( aQuote,aIter->second.sRealName)); + aSql.append(aComma); + aValues.append(aPara); + bModified = sal_True; + } + } + if ( !bModified ) + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_NO_VALUE_CHANGED ), SQL_GENERAL_ERROR, m_xConnection ); + + aSql.setCharAt(aSql.getLength()-1,')'); + aValues.setCharAt(aValues.getLength()-1,')'); + aSql.append(aValues.makeStringAndClear()); + // now create,fill and execute the prepared statement + ::rtl::OUString sEmpty; + executeInsert(_rInsertRow,aSql.makeStringAndClear(),sEmpty,bRefetch); +} +// ------------------------------------------------------------------------- +void OKeySet::executeInsert( const ORowSetRow& _rInsertRow,const ::rtl::OUString& i_sSQL,const ::rtl::OUString& i_sTableName,bool bRefetch ) +{ + // now create,fill and execute the prepared statement + Reference< XPreparedStatement > xPrep(m_xConnection->prepareStatement(i_sSQL)); + Reference< XParameters > xParameter(xPrep,UNO_QUERY); + + SelectColumnsMetaData::const_iterator aIter = m_pColumnNames->begin(); + SelectColumnsMetaData::const_iterator aEnd = m_pColumnNames->end(); + for(sal_Int32 i = 1;aIter != aEnd;++aIter) + { + if ( !i_sTableName.getLength() || aIter->second.sTableName == i_sTableName ) + { + const sal_Int32 nPos = aIter->second.nPosition; + if((_rInsertRow->get())[nPos].isModified()) + { + if((_rInsertRow->get())[nPos].isNull()) + xParameter->setNull(i++,(_rInsertRow->get())[nPos].getTypeKind()); + else + { + impl_convertValue_throw(_rInsertRow,aIter->second); + (_rInsertRow->get())[nPos].setSigned(m_aSignedFlags[nPos-1]); + setParameter(i++,xParameter,(_rInsertRow->get())[nPos],aIter->second.nType,aIter->second.nScale); + } + } + } + } + + m_bInserted = xPrep->executeUpdate() > 0; + sal_Bool bAutoValuesFetched = sal_False; + if ( m_bInserted ) + { + // first insert the default values into the insertrow + aIter = m_pColumnNames->begin(); + for(;aIter != aEnd;++aIter) + { + if ( !(_rInsertRow->get())[aIter->second.nPosition].isModified() ) + (_rInsertRow->get())[aIter->second.nPosition] = aIter->second.sDefaultValue; + } + try + { + Reference< XGeneratedResultSet > xGRes(xPrep, UNO_QUERY); + if ( xGRes.is() ) + { + Reference< XResultSet > xRes = xGRes->getGeneratedValues(); + Reference< XRow > xRow(xRes,UNO_QUERY); + if ( xRow.is() && xRes->next() ) + { + Reference< XResultSetMetaDataSupplier > xMdSup(xRes,UNO_QUERY); + Reference< XResultSetMetaData > xMd = xMdSup->getMetaData(); + sal_Int32 nColumnCount = xMd->getColumnCount(); + ::std::vector< ::rtl::OUString >::iterator aAutoIter = m_aAutoColumns.begin(); + ::std::vector< ::rtl::OUString >::iterator aAutoEnd = m_aAutoColumns.end(); + for (sal_Int32 i = 1;aAutoIter != aAutoEnd && i <= nColumnCount; ++aAutoIter,++i) + { +#if OSL_DEBUG_LEVEL > 1 + ::rtl::OUString sColumnName( xMd->getColumnName(i) ); +#endif + SelectColumnsMetaData::iterator aFind = m_pKeyColumnNames->find(*aAutoIter); + if ( aFind != m_pKeyColumnNames->end() ) + (_rInsertRow->get())[aFind->second.nPosition].fill(i,aFind->second.nType,aFind->second.bNullable,xRow); + } + bAutoValuesFetched = sal_True; + } + } + } + catch(Exception&) + { + OSL_ENSURE(0,"Could not execute GeneratedKeys() stmt"); + } + } + + ::comphelper::disposeComponent(xPrep); + + if ( !i_sTableName.getLength() && !bAutoValuesFetched && m_bInserted ) + { + // first check if all key column values were set + const ::rtl::OUString sMax(RTL_CONSTASCII_USTRINGPARAM(" MAX(")); + const ::rtl::OUString sMaxEnd(RTL_CONSTASCII_USTRINGPARAM("),")); + const ::rtl::OUString sQuote = getIdentifierQuoteString(); + ::rtl::OUString sMaxStmt; + aEnd = m_pKeyColumnNames->end(); + ::std::vector< ::rtl::OUString >::iterator aAutoIter = m_aAutoColumns.begin(); + ::std::vector< ::rtl::OUString >::iterator aAutoEnd = m_aAutoColumns.end(); + for (;aAutoIter != aAutoEnd; ++aAutoIter) + { + // we will only fetch values which are keycolumns + SelectColumnsMetaData::iterator aFind = m_pKeyColumnNames->find(*aAutoIter); + if ( aFind != aEnd ) + { + sMaxStmt += sMax; + sMaxStmt += ::dbtools::quoteName( sQuote,aFind->second.sRealName +); + sMaxStmt += sMaxEnd; + } + } + + if(sMaxStmt.getLength()) + { + sMaxStmt = sMaxStmt.replaceAt(sMaxStmt.getLength()-1,1,::rtl::OUString::createFromAscii(" ")); + ::rtl::OUString sStmt = ::rtl::OUString::createFromAscii("SELECT "); + sStmt += sMaxStmt; + sStmt += ::rtl::OUString::createFromAscii("FROM "); + ::rtl::OUString sCatalog,sSchema,sTable; + ::dbtools::qualifiedNameComponents(m_xConnection->getMetaData(),m_sUpdateTableName,sCatalog,sSchema,sTable,::dbtools::eInDataManipulation); + sStmt += ::dbtools::composeTableNameForSelect( m_xConnection, sCatalog, sSchema, sTable ); + try + { + // now fetch the autoincrement values + Reference<XStatement> xStatement = m_xConnection->createStatement(); + Reference<XResultSet> xRes = xStatement->executeQuery(sStmt); + Reference<XRow> xRow(xRes,UNO_QUERY); + if(xRow.is() && xRes->next()) + { + aAutoIter = m_aAutoColumns.begin(); + for (sal_Int32 i=1;aAutoIter != aAutoEnd; ++aAutoIter,++i) + { + // we will only fetch values which are keycolumns + SelectColumnsMetaData::iterator aFind = m_pKeyColumnNames->find(*aAutoIter); + if ( aFind != aEnd ) + (_rInsertRow->get())[aFind->second.nPosition].fill(i,aFind->second.nType,aFind->second.bNullable,xRow); + } + } + ::comphelper::disposeComponent(xStatement); + } + catch(SQLException&) + { + OSL_ENSURE(0,"Could not fetch with MAX() "); + } + } + } + if ( m_bInserted ) + { + OKeySetMatrix::iterator aKeyIter = m_aKeyMap.end(); + --aKeyIter; + ORowSetRow aKeyRow = new connectivity::ORowVector< ORowSetValue >(m_pKeyColumnNames->size()); + copyRowValue(_rInsertRow,aKeyRow,aKeyIter->first + 1); + + m_aKeyIter = m_aKeyMap.insert(OKeySetMatrix::value_type(aKeyIter->first + 1,OKeySetValue(aKeyRow,::std::pair<sal_Int32,Reference<XRow> >(1,NULL)))).first; + // now we set the bookmark for this row + (_rInsertRow->get())[0] = makeAny((sal_Int32)m_aKeyIter->first); + tryRefetch(_rInsertRow,bRefetch); + } +} +void OKeySet::tryRefetch(const ORowSetRow& _rInsertRow,bool bRefetch) +{ + if ( bRefetch ) + { + // we just areassign the base members + try + { + Reference< XParameters > xParameter(m_xStatement,UNO_QUERY); + OSL_ENSURE(xParameter.is(),"No Parameter interface!"); + xParameter->clearParameters(); + + sal_Int32 nPos=1; + connectivity::ORowVector< ORowSetValue >::Vector::const_iterator aParaIter; + connectivity::ORowVector< ORowSetValue >::Vector::const_iterator aParaEnd; + OUpdatedParameter::iterator aUpdateFind = m_aUpdatedParameter.find(m_aKeyIter->first); + if ( aUpdateFind == m_aUpdatedParameter.end() ) + { + aParaIter = m_aParameterValueForCache.get().begin(); + aParaEnd = m_aParameterValueForCache.get().end(); + } + else + { + aParaIter = aUpdateFind->second.get().begin(); + aParaEnd = aUpdateFind->second.get().end(); + } + + for(++aParaIter;aParaIter != aParaEnd;++aParaIter,++nPos) + { + ::dbtools::setObjectWithInfo( xParameter, nPos, aParaIter->makeAny(), aParaIter->getTypeKind() ); + } + connectivity::ORowVector< ORowSetValue >::Vector::const_iterator aIter2 = m_aKeyIter->second.first->get().begin(); + SelectColumnsMetaData::const_iterator aPosIter = (*m_pKeyColumnNames).begin(); + SelectColumnsMetaData::const_iterator aPosEnd = (*m_pKeyColumnNames).end(); + for(;aPosIter != aPosEnd;++aPosIter,++aIter2,++nPos) + setParameter(nPos,xParameter,*aIter2,aPosIter->second.nType,aPosIter->second.nScale); + aPosIter = (*m_pForeignColumnNames).begin(); + aPosEnd = (*m_pForeignColumnNames).end(); + for(;aPosIter != aPosEnd;++aPosIter,++aIter2,++nPos) + setParameter(nPos,xParameter,*aIter2,aPosIter->second.nType,aPosIter->second.nScale); + + m_xSet = m_xStatement->executeQuery(); + OSL_ENSURE(m_xSet.is(),"No resultset form statement!"); + bRefetch = m_xSet->next(); + } + catch(Exception) + { + bRefetch = false; + } + } + if ( !bRefetch ) + { + m_aKeyIter->second.second.second = new OPrivateRow(_rInsertRow->get()); + } +} +// ----------------------------------------------------------------------------- +void OKeySet::copyRowValue(const ORowSetRow& _rInsertRow,ORowSetRow& _rKeyRow,sal_Int32 i_nBookmark) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::copyRowValue" ); + connectivity::ORowVector< ORowSetValue >::Vector::iterator aIter = _rKeyRow->get().begin(); + + // check the if the parameter values have been changed + OSL_ENSURE((m_aParameterValueForCache.get().size()-1) == m_pParameterNames->size(),"OKeySet::copyRowValue: Parameter values and names differ!"); + connectivity::ORowVector< ORowSetValue >::Vector::const_iterator aParaValuesIter = m_aParameterValueForCache.get().begin() +1; + + bool bChanged = false; + SelectColumnsMetaData::const_iterator aParaIter = (*m_pParameterNames).begin(); + SelectColumnsMetaData::const_iterator aParaEnd = (*m_pParameterNames).end(); + for(sal_Int32 i = 1;aParaIter != aParaEnd;++aParaIter,++aParaValuesIter,++i) + { + ORowSetValue aValue(*aParaValuesIter); + aValue.setSigned(m_aSignedFlags[aParaIter->second.nPosition]); + if ( (_rInsertRow->get())[aParaIter->second.nPosition] != aValue ) + { + ORowSetValueVector aCopy(m_aParameterValueForCache); + (aCopy.get())[i] = (_rInsertRow->get())[aParaIter->second.nPosition]; + m_aUpdatedParameter[i_nBookmark] = aCopy; + bChanged = true; + } + } + if ( !bChanged ) + { + m_aUpdatedParameter.erase(i_nBookmark); + } + + // update the key values + SelectColumnsMetaData::const_iterator aPosIter = (*m_pKeyColumnNames).begin(); + SelectColumnsMetaData::const_iterator aPosEnd = (*m_pKeyColumnNames).end(); + for(;aPosIter != aPosEnd;++aPosIter,++aIter) + { + *aIter = (_rInsertRow->get())[aPosIter->second.nPosition]; + impl_convertValue_throw(_rKeyRow,aPosIter->second); + aIter->setTypeKind(aPosIter->second.nType); + } +} +// ------------------------------------------------------------------------- +void SAL_CALL OKeySet::deleteRow(const ORowSetRow& _rDeleteRow,const connectivity::OSQLTable& _xTable ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::deleteRow" ); + Reference<XPropertySet> xSet(_xTable,UNO_QUERY); + fillTableName(xSet); + + ::rtl::OUStringBuffer aSql = ::rtl::OUString::createFromAscii("DELETE FROM "); + aSql.append(m_aComposedTableName); + aSql.append(::rtl::OUString::createFromAscii(" WHERE ")); + + // list all cloumns that should be set + ::rtl::OUString aQuote = getIdentifierQuoteString(); + static ::rtl::OUString aAnd = ::rtl::OUString::createFromAscii(" AND "); + + // use keys and indexes for excat postioning + Reference<XNameAccess> xKeyColumns = getKeyColumns(); + // second the indexes + Reference<XIndexesSupplier> xIndexSup(_xTable,UNO_QUERY); + Reference<XIndexAccess> xIndexes; + if ( xIndexSup.is() ) + xIndexes.set(xIndexSup->getIndexes(),UNO_QUERY); + + // Reference<XColumnsSupplier> + ::std::vector< Reference<XNameAccess> > aAllIndexColumns; + lcl_fillIndexColumns(xIndexes,aAllIndexColumns); + + ::rtl::OUString aColumnName; + ::rtl::OUStringBuffer sIndexCondition; + ::std::vector<sal_Int32> aIndexColumnPositions; + SelectColumnsMetaData::const_iterator aIter = m_pColumnNames->begin(); + SelectColumnsMetaData::const_iterator aEnd = m_pColumnNames->end(); + + sal_Int32 i = 1; + for(i = 1;aIter != aEnd;++aIter,++i) + { + if ( m_pKeyColumnNames->find(aIter->first) != m_pKeyColumnNames->end() ) + { + aSql.append(::dbtools::quoteName( aQuote,aIter->second.sRealName)); + if((_rDeleteRow->get())[aIter->second.nPosition].isNull()) + { + OSL_ENSURE(0,"can a primary key be null"); + aSql.append(::rtl::OUString::createFromAscii(" IS NULL")); + } + else + aSql.append(::rtl::OUString::createFromAscii(" = ?")); + aSql.append(aAnd); + } + else + { + ::std::vector< Reference<XNameAccess> >::const_iterator aIndexEnd = aAllIndexColumns.end(); + for( ::std::vector< Reference<XNameAccess> >::const_iterator aIndexIter = aAllIndexColumns.begin(); + aIndexIter != aIndexEnd;++aIndexIter) + { + if((*aIndexIter)->hasByName(aIter->first)) + { + sIndexCondition.append(::dbtools::quoteName( aQuote,aIter->second.sRealName)); + if((_rDeleteRow->get())[aIter->second.nPosition].isNull()) + sIndexCondition.append(::rtl::OUString::createFromAscii(" IS NULL")); + else + { + sIndexCondition.append(::rtl::OUString::createFromAscii(" = ?")); + aIndexColumnPositions.push_back(aIter->second.nPosition); + } + sIndexCondition.append(aAnd); + + break; + } + } + } + } + aSql.append(sIndexCondition.makeStringAndClear()); + aSql.setLength(aSql.getLength()-5); + + // now create end execute the prepared statement + Reference< XPreparedStatement > xPrep(m_xConnection->prepareStatement(aSql.makeStringAndClear())); + Reference< XParameters > xParameter(xPrep,UNO_QUERY); + + aIter = (*m_pKeyColumnNames).begin(); + aEnd = (*m_pKeyColumnNames).end(); + i = 1; + for(;aIter != aEnd;++aIter,++i) + { + setParameter(i,xParameter,(_rDeleteRow->get())[aIter->second.nPosition],aIter->second.nType,aIter->second.nScale); + } + + // now we have to set the index values + ::std::vector<sal_Int32>::iterator aIdxColIter = aIndexColumnPositions.begin(); + ::std::vector<sal_Int32>::iterator aIdxColEnd = aIndexColumnPositions.end(); + aIter = m_pColumnNames->begin(); + for(;aIdxColIter != aIdxColEnd;++aIdxColIter,++i,++aIter) + { + setParameter(i,xParameter,(_rDeleteRow->get())[*aIdxColIter],(_rDeleteRow->get())[*aIdxColIter].getTypeKind(),aIter->second.nScale); + } + + m_bDeleted = xPrep->executeUpdate() > 0; + + if(m_bDeleted) + { + sal_Int32 nBookmark = ::comphelper::getINT32((_rDeleteRow->get())[0].getAny()); + if(m_aKeyIter == m_aKeyMap.find(nBookmark) && m_aKeyIter != m_aKeyMap.end()) + ++m_aKeyIter; + m_aKeyMap.erase(nBookmark); + m_bDeleted = sal_True; + } +} +// ------------------------------------------------------------------------- +void SAL_CALL OKeySet::cancelRowUpdates( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::cancelRowUpdates" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; +} +// ------------------------------------------------------------------------- +void SAL_CALL OKeySet::moveToInsertRow( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::moveToInsertRow" ); +} +// ------------------------------------------------------------------------- +void SAL_CALL OKeySet::moveToCurrentRow( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::moveToCurrentRow" ); +} +// ------------------------------------------------------------------------- +Reference<XNameAccess> OKeySet::getKeyColumns() const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getKeyColumns" ); + // use keys and indexes for excat postioning + // first the keys + + Reference<XIndexAccess> xKeys = m_xTableKeys; + if ( !xKeys.is() ) + { + Reference<XPropertySet> xSet(m_xTable,UNO_QUERY); + const Reference<XNameAccess> xPrimaryKeyColumns = getPrimaryKeyColumns_throw(xSet); + return xPrimaryKeyColumns; + } + + Reference<XColumnsSupplier> xKeyColsSup; + Reference<XNameAccess> xKeyColumns; + if(xKeys.is()) + { + Reference<XPropertySet> xProp; + sal_Int32 nCount = xKeys->getCount(); + for(sal_Int32 i = 0;i< nCount;++i) + { + xProp.set(xKeys->getByIndex(i),UNO_QUERY); + if ( xProp.is() ) + { + sal_Int32 nKeyType = 0; + xProp->getPropertyValue(PROPERTY_TYPE) >>= nKeyType; + if(KeyType::PRIMARY == nKeyType) + { + xKeyColsSup.set(xProp,UNO_QUERY); + OSL_ENSURE(xKeyColsSup.is(),"Columnsupplier is null!"); + xKeyColumns = xKeyColsSup->getColumns(); + break; + } + } + } + } + + return xKeyColumns; +} +// ----------------------------------------------------------------------------- +sal_Bool SAL_CALL OKeySet::next( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::next" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + + if(isAfterLast()) + return sal_False; + if(!m_bRowCountFinal) // not yet all records fetched + { + ++m_aKeyIter; // this is possible because we stand on begin() and this is the "beforefirst" row + if(m_aKeyIter == m_aKeyMap.end() && !fetchRow()) + m_aKeyIter = m_aKeyMap.end(); + } + else if(!isAfterLast()) + ++m_aKeyIter; + + refreshRow(); + return !isAfterLast(); +} +// ----------------------------------------------------------------------------- +sal_Bool SAL_CALL OKeySet::isBeforeFirst( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::isBeforeFirst" ); + return m_aKeyIter == m_aKeyMap.begin(); +} +// ----------------------------------------------------------------------------- +sal_Bool SAL_CALL OKeySet::isAfterLast( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::isAfterLast" ); + return m_bRowCountFinal && m_aKeyIter == m_aKeyMap.end(); +} +// ----------------------------------------------------------------------------- +sal_Bool SAL_CALL OKeySet::isFirst( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::isFirst" ); + OKeySetMatrix::iterator aTemp = m_aKeyMap.begin(); + ++aTemp; + return m_aKeyIter == aTemp && m_aKeyIter != m_aKeyMap.end(); +} +// ----------------------------------------------------------------------------- +sal_Bool SAL_CALL OKeySet::isLast( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::isLast" ); + if(!m_bRowCountFinal) + return sal_False; + + OKeySetMatrix::iterator aTemp = m_aKeyMap.end(); + --aTemp; + return m_aKeyIter == aTemp; +} +// ----------------------------------------------------------------------------- +void SAL_CALL OKeySet::beforeFirst( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::beforeFirst" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + m_aKeyIter = m_aKeyMap.begin(); + m_xRow = NULL; + ::comphelper::disposeComponent(m_xSet); +} +// ----------------------------------------------------------------------------- +void SAL_CALL OKeySet::afterLast( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::afterLast" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + fillAllRows(); + m_aKeyIter = m_aKeyMap.end(); + m_xRow = NULL; + ::comphelper::disposeComponent(m_xSet); +} +// ----------------------------------------------------------------------------- +sal_Bool SAL_CALL OKeySet::first( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::first" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + m_aKeyIter = m_aKeyMap.begin(); + ++m_aKeyIter; + if(m_aKeyIter == m_aKeyMap.end() && !fetchRow()) + m_aKeyIter = m_aKeyMap.end(); + + refreshRow(); + return m_aKeyIter != m_aKeyMap.end() && m_aKeyIter != m_aKeyMap.begin(); +} +// ----------------------------------------------------------------------------- +sal_Bool SAL_CALL OKeySet::last( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::last" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + fillAllRows(); + + m_aKeyIter = m_aKeyMap.end(); + --m_aKeyIter; + refreshRow(); + return m_aKeyIter != m_aKeyMap.end() && m_aKeyIter != m_aKeyMap.begin(); +} +// ----------------------------------------------------------------------------- +sal_Int32 SAL_CALL OKeySet::getRow( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getRow" ); + OSL_ENSURE(!isAfterLast(),"getRow is not allowed when afterlast record!"); + OSL_ENSURE(!isBeforeFirst(),"getRow is not allowed when beforefirst record!"); + + return ::std::distance(m_aKeyMap.begin(),m_aKeyIter); +} +// ----------------------------------------------------------------------------- +sal_Bool SAL_CALL OKeySet::absolute( sal_Int32 row ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::absolute" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + OSL_ENSURE(row,"absolute(0) isn't allowed!"); + if(row < 0) + { + if(!m_bRowCountFinal) + fillAllRows(); + + for(;row < 0 && m_aKeyIter != m_aKeyMap.begin();++row) + m_aKeyIter--; + } + else + { + if(row >= (sal_Int32)m_aKeyMap.size()) + { + if(!m_bRowCountFinal) + { + sal_Bool bNext = sal_True; + for(sal_Int32 i=m_aKeyMap.size()-1;i < row && bNext;++i) + bNext = fetchRow(); + } + else + m_aKeyIter = m_aKeyMap.end(); + } + else + { + m_aKeyIter = m_aKeyMap.begin(); + for(;row > 0 && m_aKeyIter != m_aKeyMap.end();--row) + ++m_aKeyIter; + } + } + refreshRow(); + + return m_aKeyIter != m_aKeyMap.end() && m_aKeyIter != m_aKeyMap.begin(); +} +// ----------------------------------------------------------------------------- +sal_Bool SAL_CALL OKeySet::relative( sal_Int32 rows ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::relative" ); + if(!rows) + { + refreshRow(); + return sal_True; + } + return absolute(getRow()+rows); +} +// ----------------------------------------------------------------------------- +sal_Bool SAL_CALL OKeySet::previous( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::previous" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + if(m_aKeyIter != m_aKeyMap.begin()) + { + --m_aKeyIter; + refreshRow(); + } + return m_aKeyIter != m_aKeyMap.begin(); +} +// ----------------------------------------------------------------------------- +void SAL_CALL OKeySet::refreshRow() throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::refreshRow" ); + if(isBeforeFirst() || isAfterLast() || !m_xStatement.is()) + return; + + m_xRow = NULL; + ::comphelper::disposeComponent(m_xSet); + + if ( m_aKeyIter->second.second.second.is() ) + { + m_xRow = m_aKeyIter->second.second.second; + return; + } + // we just areassign the base members + Reference< XParameters > xParameter(m_xStatement,UNO_QUERY); + OSL_ENSURE(xParameter.is(),"No Parameter interface!"); + xParameter->clearParameters(); + + sal_Int32 nPos=1; + connectivity::ORowVector< ORowSetValue >::Vector::const_iterator aParaIter; + connectivity::ORowVector< ORowSetValue >::Vector::const_iterator aParaEnd; + OUpdatedParameter::iterator aUpdateFind = m_aUpdatedParameter.find(m_aKeyIter->first); + if ( aUpdateFind == m_aUpdatedParameter.end() ) + { + aParaIter = m_aParameterValueForCache.get().begin(); + aParaEnd = m_aParameterValueForCache.get().end(); + } + else + { + aParaIter = aUpdateFind->second.get().begin(); + aParaEnd = aUpdateFind->second.get().end(); + } + + for(++aParaIter;aParaIter != aParaEnd;++aParaIter,++nPos) + { + ::dbtools::setObjectWithInfo( xParameter, nPos, aParaIter->makeAny(), aParaIter->getTypeKind() ); + } + + // now set the primary key column values + connectivity::ORowVector< ORowSetValue >::Vector::const_iterator aIter = m_aKeyIter->second.first->get().begin(); + SelectColumnsMetaData::const_iterator aPosIter = (*m_pKeyColumnNames).begin(); + SelectColumnsMetaData::const_iterator aPosEnd = (*m_pKeyColumnNames).end(); + for(;aPosIter != aPosEnd;++aPosIter,++aIter,++nPos) + setParameter(nPos,xParameter,*aIter,aPosIter->second.nType,aPosIter->second.nScale); + aPosIter = (*m_pForeignColumnNames).begin(); + aPosEnd = (*m_pForeignColumnNames).end(); + for(;aPosIter != aPosEnd;++aPosIter,++aIter,++nPos) + setParameter(nPos,xParameter,*aIter,aPosIter->second.nType,aPosIter->second.nScale); + + m_xSet = m_xStatement->executeQuery(); + OSL_ENSURE(m_xSet.is(),"No resultset form statement!"); + sal_Bool bOK = m_xSet->next(); + if ( !bOK ) + m_aKeyIter = m_aKeyMap.end(); + m_xRow.set(m_xSet,UNO_QUERY); + OSL_ENSURE(m_xRow.is(),"No row form statement!"); +} +// ----------------------------------------------------------------------------- +sal_Bool OKeySet::fetchRow() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::fetchRow" ); + // fetch the next row and append on the keyset + sal_Bool bRet = sal_False; + if ( !m_bRowCountFinal ) + bRet = m_xDriverSet->next(); + if ( bRet ) + { + ORowSetRow aKeyRow = new connectivity::ORowVector< ORowSetValue >((*m_pKeyColumnNames).size() + m_pForeignColumnNames->size()); + connectivity::ORowVector< ORowSetValue >::Vector::iterator aIter = aKeyRow->get().begin(); + // first fetch the values needed for the key column + SelectColumnsMetaData::const_iterator aPosIter = (*m_pKeyColumnNames).begin(); + SelectColumnsMetaData::const_iterator aPosEnd = (*m_pKeyColumnNames).end(); + for(;aPosIter != aPosEnd;++aPosIter,++aIter) + { + const SelectColumnDescription& rColDesc = aPosIter->second; + aIter->fill(rColDesc.nPosition,rColDesc.nType,rColDesc.bNullable,m_xDriverRow); + } + // now fetch the values from the missing columns from other tables + aPosIter = (*m_pForeignColumnNames).begin(); + aPosEnd = (*m_pForeignColumnNames).end(); + for(;aPosIter != aPosEnd;++aPosIter,++aIter) + { + const SelectColumnDescription& rColDesc = aPosIter->second; + aIter->fill(rColDesc.nPosition,rColDesc.nType,rColDesc.bNullable,m_xDriverRow); + } + m_aKeyIter = m_aKeyMap.insert(OKeySetMatrix::value_type(m_aKeyMap.rbegin()->first+1,OKeySetValue(aKeyRow,::std::pair<sal_Int32,Reference<XRow> >(0,NULL)))).first; + } + else + m_bRowCountFinal = sal_True; + return bRet; +} +// ------------------------------------------------------------------------- +void OKeySet::fillAllRows() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::fillAllRows" ); + if(!m_bRowCountFinal) + { + while(fetchRow()) + ; + } +} +// XRow +sal_Bool SAL_CALL OKeySet::wasNull( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::wasNull" ); + return m_xRow->wasNull(); +} +// ------------------------------------------------------------------------- +::rtl::OUString SAL_CALL OKeySet::getString( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getString" ); + OSL_ENSURE(m_xRow.is(),"m_xRow is null!"); + return m_xRow->getString(columnIndex); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OKeySet::getBoolean( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getBoolean" ); + OSL_ENSURE(m_xRow.is(),"m_xRow is null!"); + return m_xRow->getBoolean(columnIndex); +} +// ------------------------------------------------------------------------- +sal_Int8 SAL_CALL OKeySet::getByte( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getByte" ); + OSL_ENSURE(m_xRow.is(),"m_xRow is null!"); + return m_xRow->getByte(columnIndex); +} +// ------------------------------------------------------------------------- +sal_Int16 SAL_CALL OKeySet::getShort( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getShort" ); + OSL_ENSURE(m_xRow.is(),"m_xRow is null!"); + return m_xRow->getShort(columnIndex); +} +// ------------------------------------------------------------------------- +sal_Int32 SAL_CALL OKeySet::getInt( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getInt" ); + OSL_ENSURE(m_xRow.is(),"m_xRow is null!"); + return m_xRow->getInt(columnIndex); +} +// ------------------------------------------------------------------------- +sal_Int64 SAL_CALL OKeySet::getLong( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getLong" ); + OSL_ENSURE(m_xRow.is(),"m_xRow is null!"); + return m_xRow->getLong(columnIndex); +} +// ------------------------------------------------------------------------- +float SAL_CALL OKeySet::getFloat( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getFloat" ); + OSL_ENSURE(m_xRow.is(),"m_xRow is null!"); + return m_xRow->getFloat(columnIndex); +} +// ------------------------------------------------------------------------- +double SAL_CALL OKeySet::getDouble( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getDouble" ); + OSL_ENSURE(m_xRow.is(),"m_xRow is null!"); + return m_xRow->getDouble(columnIndex); +} +// ------------------------------------------------------------------------- +Sequence< sal_Int8 > SAL_CALL OKeySet::getBytes( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getBytes" ); + OSL_ENSURE(m_xRow.is(),"m_xRow is null!"); + return m_xRow->getBytes(columnIndex); +} +// ------------------------------------------------------------------------- +::com::sun::star::util::Date SAL_CALL OKeySet::getDate( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getDate" ); + OSL_ENSURE(m_xRow.is(),"m_xRow is null!"); + return m_xRow->getDate(columnIndex); +} +// ------------------------------------------------------------------------- +::com::sun::star::util::Time SAL_CALL OKeySet::getTime( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getTime" ); + OSL_ENSURE(m_xRow.is(),"m_xRow is null!"); + return m_xRow->getTime(columnIndex); +} +// ------------------------------------------------------------------------- +::com::sun::star::util::DateTime SAL_CALL OKeySet::getTimestamp( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getTimestamp" ); + OSL_ENSURE(m_xRow.is(),"m_xRow is null!"); + return m_xRow->getTimestamp(columnIndex); +} +// ------------------------------------------------------------------------- +Reference< ::com::sun::star::io::XInputStream > SAL_CALL OKeySet::getBinaryStream( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getBinaryStream" ); + OSL_ENSURE(m_xRow.is(),"m_xRow is null!"); + return m_xRow->getBinaryStream(columnIndex); +} +// ------------------------------------------------------------------------- +Reference< ::com::sun::star::io::XInputStream > SAL_CALL OKeySet::getCharacterStream( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getCharacterStream" ); + OSL_ENSURE(m_xRow.is(),"m_xRow is null!"); + return m_xRow->getCharacterStream(columnIndex); +} +// ------------------------------------------------------------------------- +Any SAL_CALL OKeySet::getObject( sal_Int32 columnIndex, const Reference< ::com::sun::star::container::XNameAccess >& typeMap ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getObject" ); + OSL_ENSURE(m_xRow.is(),"m_xRow is null!"); + return m_xRow->getObject(columnIndex,typeMap); +} +// ------------------------------------------------------------------------- +Reference< XRef > SAL_CALL OKeySet::getRef( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getRef" ); + OSL_ENSURE(m_xRow.is(),"m_xRow is null!"); + return m_xRow->getRef(columnIndex); +} +// ------------------------------------------------------------------------- +Reference< XBlob > SAL_CALL OKeySet::getBlob( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getBlob" ); + OSL_ENSURE(m_xRow.is(),"m_xRow is null!"); + return m_xRow->getBlob(columnIndex); +} +// ------------------------------------------------------------------------- +Reference< XClob > SAL_CALL OKeySet::getClob( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getClob" ); + OSL_ENSURE(m_xRow.is(),"m_xRow is null!"); + return m_xRow->getClob(columnIndex); +} +// ------------------------------------------------------------------------- +Reference< XArray > SAL_CALL OKeySet::getArray( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getArray" ); + OSL_ENSURE(m_xRow.is(),"m_xRow is null!"); + return m_xRow->getArray(columnIndex); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OKeySet::rowUpdated( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::rowUpdated" ); + return m_aKeyIter != m_aKeyMap.begin() && m_aKeyIter != m_aKeyMap.end() && m_aKeyIter->second.second.first == 2; +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OKeySet::rowInserted( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::rowInserted" ); + return m_aKeyIter != m_aKeyMap.begin() && m_aKeyIter != m_aKeyMap.end() && m_aKeyIter->second.second.first == 1; +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OKeySet::rowDeleted( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::rowDeleted" ); + sal_Bool bDeleted = m_bDeleted; + m_bDeleted = sal_False; + return bDeleted; +} +// ----------------------------------------------------------------------------- +::rtl::OUString OKeySet::getComposedTableName(const ::rtl::OUString& _sCatalog, + const ::rtl::OUString& _sSchema, + const ::rtl::OUString& _sTable) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getComposedTableName" ); + ::rtl::OUString aComposedName; + Reference<XDatabaseMetaData> xMetaData = m_xConnection->getMetaData(); + + if( xMetaData.is() && xMetaData->supportsTableCorrelationNames() ) + { + aComposedName = ::dbtools::composeTableName( xMetaData, _sCatalog, _sSchema, _sTable, sal_False, ::dbtools::eInDataManipulation ); + // first we have to check if the composed tablename is in the select clause or if an alias is used + Reference<XTablesSupplier> xTabSup(m_xComposer,UNO_QUERY); + Reference<XNameAccess> xSelectTables = xTabSup->getTables(); + OSL_ENSURE(xSelectTables.is(),"No Select tables!"); + if(xSelectTables.is()) + { + if(!xSelectTables->hasByName(aComposedName)) + { // the composed name isn't used in the select clause so we have to find out which name is used instead + ::rtl::OUString sCatalog,sSchema,sTable; + ::dbtools::qualifiedNameComponents(xMetaData,m_sUpdateTableName,sCatalog,sSchema,sTable,::dbtools::eInDataManipulation); + aComposedName = ::dbtools::composeTableNameForSelect( m_xConnection, sCatalog, sSchema, sTable ); + } + else + aComposedName = ::dbtools::composeTableNameForSelect( m_xConnection, _sCatalog, _sSchema, _sTable ); + } + } + else + aComposedName = ::dbtools::composeTableNameForSelect( m_xConnection, _sCatalog, _sSchema, _sTable ); + + return aComposedName; +} +// ----------------------------------------------------------------------------- +namespace dbaccess +{ + +void getColumnPositions(const Reference<XNameAccess>& _rxQueryColumns, + const ::com::sun::star::uno::Sequence< ::rtl::OUString >& _aColumnNames, + const ::rtl::OUString& _rsUpdateTableName, + SelectColumnsMetaData& o_rColumnNames, + bool i_bAppendTableName) + { + // get the real name of the columns + Sequence< ::rtl::OUString> aSelNames(_rxQueryColumns->getElementNames()); + const ::rtl::OUString* pSelIter = aSelNames.getConstArray(); + const ::rtl::OUString* pSelEnd = pSelIter + aSelNames.getLength(); + + const ::rtl::OUString* pTblColumnIter = _aColumnNames.getConstArray(); + const ::rtl::OUString* pTblColumnEnd = pTblColumnIter + _aColumnNames.getLength(); + + + ::comphelper::UStringMixLess aTmp(o_rColumnNames.key_comp()); + ::comphelper::UStringMixEqual bCase(static_cast< ::comphelper::UStringMixLess*>(&aTmp)->isCaseSensitive()); + + for(sal_Int32 nPos = 1;pSelIter != pSelEnd;++pSelIter,++nPos) + { + Reference<XPropertySet> xQueryColumnProp(_rxQueryColumns->getByName(*pSelIter),UNO_QUERY_THROW); + ::rtl::OUString sRealName,sTableName; + OSL_ENSURE(xQueryColumnProp->getPropertySetInfo()->hasPropertyByName(PROPERTY_REALNAME),"Property REALNAME not available!"); + OSL_ENSURE(xQueryColumnProp->getPropertySetInfo()->hasPropertyByName(PROPERTY_TABLENAME),"Property TABLENAME not available!"); + xQueryColumnProp->getPropertyValue(PROPERTY_REALNAME) >>= sRealName; + xQueryColumnProp->getPropertyValue(PROPERTY_TABLENAME) >>= sTableName; + + for(;pTblColumnIter != pTblColumnEnd;++pTblColumnIter) + { + if(bCase(sRealName,*pTblColumnIter) && bCase(_rsUpdateTableName,sTableName) && o_rColumnNames.find(*pTblColumnIter) == o_rColumnNames.end()) + { + sal_Int32 nType = 0; + xQueryColumnProp->getPropertyValue(PROPERTY_TYPE) >>= nType; + sal_Int32 nScale = 0; + xQueryColumnProp->getPropertyValue(PROPERTY_SCALE) >>= nScale; + ::rtl::OUString sColumnDefault; + if ( xQueryColumnProp->getPropertySetInfo()->hasPropertyByName(PROPERTY_DEFAULTVALUE) ) + xQueryColumnProp->getPropertyValue(PROPERTY_DEFAULTVALUE) >>= sColumnDefault; + + sal_Int32 nNullable = ColumnValue::NULLABLE_UNKNOWN; + OSL_VERIFY( xQueryColumnProp->getPropertyValue( PROPERTY_ISNULLABLE ) >>= nNullable ); + + if ( i_bAppendTableName ) + { + ::rtl::OUStringBuffer sName; + sName.append(sTableName); + sName.appendAscii("."); + sName.append(sRealName); + SelectColumnDescription aColDesc( nPos, nType,nScale,nNullable != sdbc::ColumnValue::NO_NULLS, sColumnDefault ); + aColDesc.sRealName = sRealName; + aColDesc.sTableName = sTableName; + o_rColumnNames[sName.makeStringAndClear()] = aColDesc; + } + else + o_rColumnNames[sRealName] = SelectColumnDescription( nPos, nType,nScale,nNullable != sdbc::ColumnValue::NO_NULLS, sColumnDefault ); + + break; + } + } + pTblColumnIter = _aColumnNames.getConstArray(); + } + } +} +// ----------------------------------------------------------------------------- +void OKeySet::impl_convertValue_throw(const ORowSetRow& _rInsertRow,const SelectColumnDescription& i_aMetaData) +{ + ORowSetValue& aValue((_rInsertRow->get())[i_aMetaData.nPosition]); + switch(i_aMetaData.nType) + { + case DataType::DECIMAL: + case DataType::NUMERIC: + { + ::rtl::OUString sValue = aValue.getString(); + sal_Int32 nIndex = sValue.indexOf('.'); + if ( nIndex != -1 ) + { + aValue = sValue.copy(0,::std::min(sValue.getLength(),nIndex + (i_aMetaData.nScale > 0 ? i_aMetaData.nScale + 1 : 0))); + } + } + break; + default: + break; + } +} +// ----------------------------------------------------------------------------- + diff --git a/dbaccess/source/core/api/KeySet.hxx b/dbaccess/source/core/api/KeySet.hxx new file mode 100644 index 000000000000..212ec237699e --- /dev/null +++ b/dbaccess/source/core/api/KeySet.hxx @@ -0,0 +1,231 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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_CORE_API_KEYSET_HXX +#define DBACCESS_CORE_API_KEYSET_HXX + +#ifndef DBACCESS_CORE_API_CACHESET_HXX +#include "CacheSet.hxx" +#endif + +#ifndef _CPPUHELPER_IMPLBASE1_HXX_ +#include <cppuhelper/implbase1.hxx> +#endif +#include <memory> +#include <map> + +#ifndef _COM_SUN_STAR_LANG_XUNOTUNNEL_HPP_ +#include <com/sun/star/lang/XUnoTunnel.hpp> +#endif +#include <com/sun/star/sdb/XSingleSelectQueryAnalyzer.hpp> +#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp> +#ifndef _COMPHELPER_STLTYPES_HXX_ +#include <comphelper/stl_types.hxx> +#endif + +namespace dbaccess +{ + struct SelectColumnDescription + { + ::rtl::OUString sRealName; // may be empty + ::rtl::OUString sTableName; // may be empty + ::rtl::OUString sDefaultValue; + sal_Int32 nPosition; + sal_Int32 nType; + sal_Int32 nScale; + sal_Bool bNullable; + + + + SelectColumnDescription() + :nPosition( 0 ) + ,nType( 0 ) + ,nScale( 0 ) + ,bNullable(sal_False) + { + } + + SelectColumnDescription( sal_Int32 _nPosition, sal_Int32 _nType, sal_Int32 _nScale,sal_Bool _bNullable, const ::rtl::OUString& _rDefaultValue ) + :sDefaultValue( _rDefaultValue ) + ,nPosition( _nPosition ) + ,nType( _nType ) + ,nScale( _nScale ) + ,bNullable(_bNullable) + { + } + }; + typedef ::std::map< ::rtl::OUString, SelectColumnDescription, ::comphelper::UStringMixLess > SelectColumnsMetaData; + + // the elements of _rxQueryColumns must have the properties PROPERTY_REALNAME and PROPERTY_TABLENAME + void getColumnPositions(const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& _rxQueryColumns, + const ::com::sun::star::uno::Sequence< ::rtl::OUString >& _rColumnNames, + const ::rtl::OUString& _rsUpdateTableName, + SelectColumnsMetaData& o_rColumnNames /* out */, + bool i_bAppendTableName = false); + + typedef ::std::pair<ORowSetRow,::std::pair<sal_Int32,::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRow> > > OKeySetValue; + typedef ::std::map<sal_Int32,OKeySetValue > OKeySetMatrix; + typedef ::std::map<sal_Int32,ORowSetValueVector > OUpdatedParameter; + // is used when the source supports keys + class OKeySet : public OCacheSet + { + protected: + OKeySetMatrix m_aKeyMap; + OKeySetMatrix::iterator m_aKeyIter; + + ::std::vector< ::rtl::OUString > m_aAutoColumns; // contains all columns which are autoincrement ones + + OUpdatedParameter m_aUpdatedParameter; // contains all parameter which have been updated and are needed for refetching + ORowSetValueVector m_aParameterValueForCache; + ::std::auto_ptr<SelectColumnsMetaData> m_pKeyColumnNames; // contains all key column names + ::std::auto_ptr<SelectColumnsMetaData> m_pColumnNames; // contains all column names + ::std::auto_ptr<SelectColumnsMetaData> m_pParameterNames; // contains all parameter names + ::std::auto_ptr<SelectColumnsMetaData> m_pForeignColumnNames; // contains all column names of the rest + connectivity::OSQLTable m_xTable; // reference to our table + ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess> m_xTableKeys; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XPreparedStatement> m_xStatement; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet> m_xSet; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRow> m_xRow; + ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XSingleSelectQueryAnalyzer > m_xComposer; + ::rtl::OUString m_sUpdateTableName; + ::std::vector< ::rtl::OUString > m_aFilterColumns; + + sal_Bool m_bRowCountFinal; + + /** + getComposedTableName return the composed table name for the query + @param _sCatalog the catalogname may be empty + @param _sSchema the schemaname may be empty + @param _sTable the tablename + + @return the composed name + */ + ::rtl::OUString getComposedTableName( const ::rtl::OUString& _sCatalog, + const ::rtl::OUString& _sSchema, + const ::rtl::OUString& _sTable); + + /** copies the values from the insert row into the key row + * + * \param _rInsertRow the row which was inserted + * \param _rKeyRow The current key row of the row set. + + \param i_nBookmark The bookmark is used to update the parameter + */ + void copyRowValue(const ORowSetRow& _rInsertRow,ORowSetRow& _rKeyRow,sal_Int32 i_nBookmark); + + ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > getKeyColumns() const; + void fillAllRows(); + sal_Bool fetchRow(); + + void impl_convertValue_throw(const ORowSetRow& _rInsertRow,const SelectColumnDescription& i_aMetaData); + void initColumns(); + void findTableColumnsMatching_throw( const ::com::sun::star::uno::Any& i_aTable + ,const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XDatabaseMetaData>& i_xMeta + ,const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess>& i_xQueryColumns); + ::rtl::OUStringBuffer createKeyFilter(); + void tryRefetch(const ORowSetRow& _rInsertRow,bool bRefetch); + void executeUpdate(const ORowSetRow& _rInsertRow ,const ORowSetRow& _rOrginalRow,const ::rtl::OUString& i_sSQL,const ::rtl::OUString& i_sTableName,const ::std::vector<sal_Int32>& _aIndexColumnPositions = ::std::vector<sal_Int32>()); + void executeInsert( const ORowSetRow& _rInsertRow,const ::rtl::OUString& i_sSQL,const ::rtl::OUString& i_sTableName = ::rtl::OUString(),bool bRefetch = false); + void executeStatement(::rtl::OUStringBuffer& io_aFilter,const ::rtl::OUString& i_sRowSetFilter,::com::sun::star::uno::Reference< ::com::sun::star::sdb::XSingleSelectQueryComposer>& io_xAnalyzer); + + virtual ~OKeySet(); + public: + OKeySet(const connectivity::OSQLTable& _xTable, + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess>& _xTableKeys, + const ::rtl::OUString& _rUpdateTableName, + const ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XSingleSelectQueryAnalyzer >& _xComposer, + const ORowSetValueVector& _aParameterValueForCache); + + // late ctor which can throw exceptions + virtual void construct(const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet>& _xDriverSet,const ::rtl::OUString& i_sRowSetFilter); + + // ::com::sun::star::sdbc::XRow + virtual sal_Bool SAL_CALL wasNull( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getString( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL getBoolean( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int8 SAL_CALL getByte( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int16 SAL_CALL getShort( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getInt( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int64 SAL_CALL getLong( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual float SAL_CALL getFloat( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual double SAL_CALL getDouble( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getBytes( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::util::Date SAL_CALL getDate( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::util::Time SAL_CALL getTime( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::util::DateTime SAL_CALL getTimestamp( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getBinaryStream( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getCharacterStream( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Any SAL_CALL getObject( sal_Int32 columnIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& typeMap ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRef > SAL_CALL getRef( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XBlob > SAL_CALL getBlob( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XClob > SAL_CALL getClob( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XArray > SAL_CALL getArray( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + + virtual sal_Bool SAL_CALL rowUpdated( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL rowInserted( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL rowDeleted( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + // ::com::sun::star::sdbc::XResultSet + virtual sal_Bool SAL_CALL next( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isBeforeFirst( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isAfterLast( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isFirst( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isLast( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL beforeFirst( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL afterLast( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL first( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL last( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL absolute( sal_Int32 row ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL relative( sal_Int32 rows ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL previous( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL refreshRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + // ::com::sun::star::sdbcx::XRowLocate + virtual ::com::sun::star::uno::Any SAL_CALL getBookmark() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + // ------------------------------------------------------------------------- + virtual sal_Bool SAL_CALL moveToBookmark( const ::com::sun::star::uno::Any& bookmark ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + // ------------------------------------------------------------------------- + virtual sal_Bool SAL_CALL moveRelativeToBookmark( const ::com::sun::star::uno::Any& bookmark, sal_Int32 rows ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + // ------------------------------------------------------------------------- + virtual sal_Int32 SAL_CALL compareBookmarks( const ::com::sun::star::uno::Any& first, const ::com::sun::star::uno::Any& second ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + // ------------------------------------------------------------------------- + virtual sal_Bool SAL_CALL hasOrderedBookmarks( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + // ------------------------------------------------------------------------- + virtual sal_Int32 SAL_CALL hashBookmark( const ::com::sun::star::uno::Any& bookmark ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + // ------------------------------------------------------------------------- + // ::com::sun::star::sdbcx::XDeleteRows + virtual ::com::sun::star::uno::Sequence< sal_Int32 > SAL_CALL deleteRows( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& rows ,const connectivity::OSQLTable& _xTable) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + // ::com::sun::star::sdbc::XResultSetUpdate + virtual void SAL_CALL updateRow(const ORowSetRow& _rInsertRow,const ORowSetRow& _rOrginalRow,const connectivity::OSQLTable& _xTable ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL deleteRow(const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& _xTable ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL insertRow( const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& _xTable ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL cancelRowUpdates( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL moveToInsertRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL moveToCurrentRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + }; +} +#endif // DBACCESS_CORE_API_KEYSET_HXX + diff --git a/dbaccess/source/core/api/OptimisticSet.cxx b/dbaccess/source/core/api/OptimisticSet.cxx new file mode 100644 index 000000000000..2a9ac96ce82b --- /dev/null +++ b/dbaccess/source/core/api/OptimisticSet.cxx @@ -0,0 +1,764 @@ +/************************************************************************* + * + * 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: OptimisticSet.cxx,v $ + * $Revision: 1.73 $ + * + * 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 "OptimisticSet.hxx" +#include "core_resource.hxx" +#include "core_resource.hrc" +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/sdbc/XDatabaseMetaData.hpp> +#include <com/sun/star/sdbc/ColumnValue.hpp> +#include <com/sun/star/sdbc/XPreparedStatement.hpp> +#include <com/sun/star/sdbc/XParameters.hpp> +#include <com/sun/star/sdbc/XGeneratedResultSet.hpp> +#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp> +#include <com/sun/star/sdb/SQLFilterOperator.hpp> +#include <com/sun/star/sdbc/XColumnLocate.hpp> +#include <com/sun/star/container/XIndexAccess.hpp> +#include "dbastrings.hrc" +#include "apitools.hxx" +#include <com/sun/star/sdbcx/XKeysSupplier.hpp> +#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp> +#include <com/sun/star/sdbcx/XIndexesSupplier.hpp> +#include <cppuhelper/typeprovider.hxx> +#include <comphelper/types.hxx> +#include <com/sun/star/sdbcx/KeyType.hpp> +#include <connectivity/dbtools.hxx> +#include <connectivity/dbexception.hxx> +#include <list> +#include <algorithm> +#include <string.h> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/sdbcx/XTablesSupplier.hpp> +#include "querycomposer.hxx" +#include "composertools.hxx" +#include <tools/debug.hxx> +#include <string.h> +#include <rtl/logfile.hxx> + +using namespace dbaccess; +using namespace ::connectivity; +using namespace ::dbtools; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star; +using namespace ::cppu; +using namespace ::osl; + +DECLARE_STL_USTRINGACCESS_MAP(::rtl::OUStringBuffer,TSQLStatements); +namespace +{ + void lcl_fillKeyCondition(const ::rtl::OUString& i_sTableName,const ::rtl::OUString& i_sQuotedColumnName,const ORowSetValue& i_aValue,TSQLStatements& io_aKeyConditions) + { + ::rtl::OUStringBuffer& rKeyCondition = io_aKeyConditions[i_sTableName]; + if ( rKeyCondition.getLength() ) + rKeyCondition.appendAscii(" AND "); + rKeyCondition.append(i_sQuotedColumnName); + if ( i_aValue.isNull() ) + rKeyCondition.appendAscii(" IS NULL"); + else + rKeyCondition.appendAscii(" = ?"); + } +} + +DBG_NAME(OptimisticSet) +// ------------------------------------------------------------------------- +OptimisticSet::OptimisticSet(const ::comphelper::ComponentContext& _rContext, + const Reference< XConnection>& i_xConnection, + const Reference< XSingleSelectQueryAnalyzer >& _xComposer, + const ORowSetValueVector& _aParameterValueForCache) + :OKeySet(NULL,NULL,::rtl::OUString(),_xComposer,_aParameterValueForCache) + ,m_aSqlParser( _rContext.getLegacyServiceFactory() ) + ,m_aSqlIterator( i_xConnection, Reference<XTablesSupplier>(_xComposer,UNO_QUERY)->getTables(), m_aSqlParser, NULL ) + ,m_bResultSetChanged(false) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OptimisticSet::OptimisticSet" ); + DBG_CTOR(OptimisticSet,NULL); +} +// ----------------------------------------------------------------------------- +OptimisticSet::~OptimisticSet() +{ + DBG_DTOR(OptimisticSet,NULL); +} +// ----------------------------------------------------------------------------- +void OptimisticSet::construct(const Reference< XResultSet>& _xDriverSet,const ::rtl::OUString& i_sRowSetFilter) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OptimisticSet::construct" ); + OCacheSet::construct(_xDriverSet,i_sRowSetFilter); + initColumns(); + + Reference<XDatabaseMetaData> xMeta = m_xConnection->getMetaData(); + Reference<XColumnsSupplier> xQueryColSup(m_xComposer,UNO_QUERY); + const Reference<XNameAccess> xQueryColumns = xQueryColSup->getColumns(); + const Reference<XTablesSupplier> xTabSup(m_xComposer,UNO_QUERY); + const Reference<XNameAccess> xTables = xTabSup->getTables(); + const Sequence< ::rtl::OUString> aTableNames = xTables->getElementNames(); + const ::rtl::OUString* pTableNameIter = aTableNames.getConstArray(); + const ::rtl::OUString* pTableNameEnd = pTableNameIter + aTableNames.getLength(); + for( ; pTableNameIter != pTableNameEnd ; ++pTableNameIter) + { + findTableColumnsMatching_throw(xTables->getByName(*pTableNameIter),xMeta,xQueryColumns); + } + + // the first row is empty because it's now easier for us to distinguish when we are beforefirst or first + // without extra variable to be set + m_aKeyMap.insert(OKeySetMatrix::value_type(0,OKeySetValue(NULL,::std::pair<sal_Int32,Reference<XRow> >(0,NULL)))); + m_aKeyIter = m_aKeyMap.begin(); + + ::rtl::OUStringBuffer aFilter = createKeyFilter(); + + Reference< XSingleSelectQueryComposer> xSourceComposer(m_xComposer,UNO_QUERY); + Reference< XMultiServiceFactory > xFactory(m_xConnection, UNO_QUERY_THROW); + Reference<XSingleSelectQueryComposer> xAnalyzer(xFactory->createInstance(SERVICE_NAME_SINGLESELECTQUERYCOMPOSER),UNO_QUERY); + ::rtl::OUString sQuery = xSourceComposer->getQuery(); + xAnalyzer->setElementaryQuery(xSourceComposer->getElementaryQuery()); + // check for joins + ::rtl::OUString aErrorMsg; + ::std::auto_ptr<OSQLParseNode> pStatementNode( m_aSqlParser.parseTree( aErrorMsg, sQuery ) ); + m_aSqlIterator.setParseTree( pStatementNode.get() ); + m_aSqlIterator.traverseAll(); + fillJoinedColumns_throw(m_aSqlIterator.getJoinConditions()); + + const ::rtl::OUString sComposerFilter = m_xComposer->getFilter(); + if ( i_sRowSetFilter.getLength() || (sComposerFilter.getLength() && sComposerFilter != i_sRowSetFilter) ) + { + FilterCreator aFilterCreator; + if ( sComposerFilter.getLength() && sComposerFilter != i_sRowSetFilter ) + aFilterCreator.append( sComposerFilter ); + aFilterCreator.append( i_sRowSetFilter ); + aFilterCreator.append( aFilter.makeStringAndClear() ); + aFilter = aFilterCreator.getComposedAndClear(); + } + xAnalyzer->setFilter(aFilter.makeStringAndClear()); + m_xStatement = m_xConnection->prepareStatement(xAnalyzer->getQueryWithSubstitution()); + ::comphelper::disposeComponent(xAnalyzer); +} +// ------------------------------------------------------------------------- +// ::com::sun::star::sdbcx::XDeleteRows +Sequence< sal_Int32 > SAL_CALL OptimisticSet::deleteRows( const Sequence< Any >& /*rows*/ ,const connectivity::OSQLTable& /*_xTable*/) throw(SQLException, RuntimeException) +{ + Sequence< sal_Int32 > aRet; + return aRet; +} +// ------------------------------------------------------------------------- +void SAL_CALL OptimisticSet::updateRow(const ORowSetRow& _rInsertRow ,const ORowSetRow& _rOrginalRow,const connectivity::OSQLTable& /*_xTable*/ ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OptimisticSet::updateRow" ); + if ( m_aJoinedKeyColumns.empty() ) + throw SQLException(); + // list all cloumns that should be set + static ::rtl::OUString s_sPara = ::rtl::OUString::createFromAscii(" = ?"); + ::rtl::OUString aQuote = getIdentifierQuoteString(); + static ::rtl::OUString aAnd = ::rtl::OUString::createFromAscii(" AND "); + ::rtl::OUString sIsNull(RTL_CONSTASCII_USTRINGPARAM(" IS NULL")); + ::rtl::OUString sParam(RTL_CONSTASCII_USTRINGPARAM(" = ?")); + + ::rtl::OUString aColumnName; + ::rtl::OUStringBuffer sKeyCondition; + ::std::map< ::rtl::OUString,bool > aResultSetChanged; + TSQLStatements aKeyConditions; + TSQLStatements aIndexConditions; + TSQLStatements aSql; + + // sal_Int32 i = 1; + // here we build the condition part for the update statement + SelectColumnsMetaData::const_iterator aIter = m_pColumnNames->begin(); + SelectColumnsMetaData::const_iterator aEnd = m_pColumnNames->end(); + for(;aIter != aEnd;++aIter) + { + if ( aResultSetChanged.find( aIter->second.sTableName ) == aResultSetChanged.end() ) + aResultSetChanged[aIter->second.sTableName] = false; + const ::rtl::OUString sQuotedColumnName = ::dbtools::quoteName( aQuote,aIter->second.sRealName); + if ( m_pKeyColumnNames->find(aIter->first) != m_pKeyColumnNames->end() ) + { + aResultSetChanged[aIter->second.sTableName] = m_aJoinedKeyColumns.find(aIter->second.nPosition) != m_aJoinedKeyColumns.end(); + lcl_fillKeyCondition(aIter->second.sTableName,sQuotedColumnName,(_rOrginalRow->get())[aIter->second.nPosition],aKeyConditions); + } + if((_rInsertRow->get())[aIter->second.nPosition].isModified()) + { + if ( m_aJoinedKeyColumns.find(aIter->second.nPosition) != m_aJoinedKeyColumns.end() ) + throw SQLException(); + + ::std::map<sal_Int32,sal_Int32>::const_iterator aJoinIter = m_aJoinedColumns.find(aIter->second.nPosition); + if ( aJoinIter != m_aJoinedColumns.end() ) + { + (_rInsertRow->get())[aJoinIter->second] = (_rInsertRow->get())[aIter->second.nPosition]; + } + ::rtl::OUStringBuffer& rPart = aSql[aIter->second.sTableName]; + if ( rPart.getLength() ) + rPart.appendAscii(", "); + rPart.append(sQuotedColumnName); + rPart.append(s_sPara); + } + } + + if( aSql.empty() ) + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_NO_VALUE_CHANGED ), SQL_GENERAL_ERROR, m_xConnection ); + + if( aKeyConditions.empty() ) + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_NO_CONDITION_FOR_PK ), SQL_GENERAL_ERROR, m_xConnection ); + + static const ::rtl::OUString s_sUPDATE(RTL_CONSTASCII_USTRINGPARAM("UPDATE ")); + static const ::rtl::OUString s_sSET(RTL_CONSTASCII_USTRINGPARAM(" SET ")); + + Reference<XDatabaseMetaData> xMetaData = m_xConnection->getMetaData(); + + TSQLStatements::iterator aSqlIter = aSql.begin(); + TSQLStatements::iterator aSqlEnd = aSql.end(); + for(;aSqlIter != aSqlEnd ; ++aSqlIter) + { + if ( aSqlIter->second.getLength() ) + { + m_bResultSetChanged = m_bResultSetChanged || aResultSetChanged[aSqlIter->first]; + ::rtl::OUStringBuffer sSql(s_sUPDATE); + ::rtl::OUString sCatalog,sSchema,sTable; + ::dbtools::qualifiedNameComponents(xMetaData,aSqlIter->first,sCatalog,sSchema,sTable,::dbtools::eInDataManipulation); + sSql.append( ::dbtools::composeTableNameForSelect( m_xConnection, sCatalog, sSchema, sTable ) ); + sSql.append(s_sSET); + sSql.append(aSqlIter->second); + ::rtl::OUStringBuffer& rCondition = aKeyConditions[aSqlIter->first]; + bool bAddWhere = true; + if ( rCondition.getLength() ) + { + bAddWhere = false; + sSql.appendAscii(" WHERE "); + sSql.append( rCondition ); + } + executeUpdate(_rInsertRow ,_rOrginalRow,sSql.makeStringAndClear(),aSqlIter->first); + } + } +} +// ------------------------------------------------------------------------- +void SAL_CALL OptimisticSet::insertRow( const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& /*_xTable*/ ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OptimisticSet::insertRow" ); + TSQLStatements aSql; + TSQLStatements aParameter; + TSQLStatements aKeyConditions; + ::std::map< ::rtl::OUString,bool > aResultSetChanged; + ::rtl::OUString aQuote = getIdentifierQuoteString(); + static ::rtl::OUString aAnd = ::rtl::OUString::createFromAscii(" AND "); + ::rtl::OUString sIsNull(RTL_CONSTASCII_USTRINGPARAM(" IS NULL")); + ::rtl::OUString sParam(RTL_CONSTASCII_USTRINGPARAM(" = ?")); + + // here we build the condition part for the update statement + SelectColumnsMetaData::const_iterator aIter = m_pColumnNames->begin(); + SelectColumnsMetaData::const_iterator aEnd = m_pColumnNames->end(); + for(;aIter != aEnd;++aIter) + { + if ( aResultSetChanged.find( aIter->second.sTableName ) == aResultSetChanged.end() ) + aResultSetChanged[aIter->second.sTableName] = false; + + const ::rtl::OUString sQuotedColumnName = ::dbtools::quoteName( aQuote,aIter->second.sRealName); + if ( (_rInsertRow->get())[aIter->second.nPosition].isModified() ) + { + if ( m_aJoinedKeyColumns.find(aIter->second.nPosition) != m_aJoinedKeyColumns.end() ) + { + lcl_fillKeyCondition(aIter->second.sTableName,sQuotedColumnName,(_rInsertRow->get())[aIter->second.nPosition],aKeyConditions); + aResultSetChanged[aIter->second.sTableName] = true; + } + ::std::map<sal_Int32,sal_Int32>::const_iterator aJoinIter = m_aJoinedColumns.find(aIter->second.nPosition); + if ( aJoinIter != m_aJoinedColumns.end() ) + { + (_rInsertRow->get())[aJoinIter->second] = (_rInsertRow->get())[aIter->second.nPosition]; + } + ::rtl::OUStringBuffer& rPart = aSql[aIter->second.sTableName]; + if ( rPart.getLength() ) + rPart.appendAscii(", "); + rPart.append(sQuotedColumnName); + ::rtl::OUStringBuffer& rParam = aParameter[aIter->second.sTableName]; + if ( rParam.getLength() ) + rParam.appendAscii(", "); + rParam.appendAscii("?"); + } + } + if ( aParameter.empty() ) + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_NO_VALUE_CHANGED ), SQL_GENERAL_ERROR, m_xConnection ); + + Reference<XDatabaseMetaData> xMetaData = m_xConnection->getMetaData(); + static const ::rtl::OUString s_sINSERT(RTL_CONSTASCII_USTRINGPARAM("INSERT INTO ")); + static const ::rtl::OUString s_sVALUES(RTL_CONSTASCII_USTRINGPARAM(") VALUES ( ")); + TSQLStatements::iterator aSqlIter = aSql.begin(); + TSQLStatements::iterator aSqlEnd = aSql.end(); + for(;aSqlIter != aSqlEnd ; ++aSqlIter) + { + if ( aSqlIter->second.getLength() ) + { + m_bResultSetChanged = m_bResultSetChanged || aResultSetChanged[aSqlIter->first]; + ::rtl::OUStringBuffer sSql(s_sINSERT); + ::rtl::OUString sCatalog,sSchema,sTable; + ::dbtools::qualifiedNameComponents(xMetaData,aSqlIter->first,sCatalog,sSchema,sTable,::dbtools::eInDataManipulation); + ::rtl::OUString sComposedTableName = ::dbtools::composeTableNameForSelect( m_xConnection, sCatalog, sSchema, sTable ); + sSql.append(sComposedTableName); + sSql.appendAscii(" ( "); + sSql.append(aSqlIter->second); + sSql.append(s_sVALUES); + sSql.append(aParameter[aSqlIter->first]); + sSql.appendAscii(" )"); + + ::rtl::OUStringBuffer& rCondition = aKeyConditions[aSqlIter->first]; + if ( rCondition.getLength() ) + { + ::rtl::OUStringBuffer sQuery; + sQuery.appendAscii("SELECT "); + sQuery.append(aSqlIter->second); + sQuery.appendAscii(" FROM "); + sQuery.append(sComposedTableName); + sQuery.appendAscii(" WHERE "); + sQuery.append(rCondition); + + try + { + Reference< XPreparedStatement > xPrep(m_xConnection->prepareStatement(sQuery.makeStringAndClear())); + Reference< XParameters > xParameter(xPrep,UNO_QUERY); + // and then the values of the where condition + SelectColumnsMetaData::iterator aKeyCol = m_pKeyColumnNames->begin(); + SelectColumnsMetaData::iterator aKeysEnd = m_pKeyColumnNames->end(); + sal_Int32 i = 1; + for(;aKeyCol != aKeysEnd;++aKeyCol) + { + if ( aKeyCol->second.sTableName == aSqlIter->first ) + { + setParameter(i++,xParameter,(_rInsertRow->get())[aKeyCol->second.nPosition],aKeyCol->second.nType,aKeyCol->second.nScale); + } + } + Reference<XResultSet> xRes = xPrep->executeQuery(); + Reference<XRow> xRow(xRes,UNO_QUERY); + if ( xRow.is() && xRes->next() ) + { + m_bResultSetChanged = true; + continue; + } + } + catch(const SQLException&) + { + } + } + + executeInsert(_rInsertRow,sSql.makeStringAndClear(),aSqlIter->first); + } + } +} +// ------------------------------------------------------------------------- +void SAL_CALL OptimisticSet::deleteRow(const ORowSetRow& _rDeleteRow,const connectivity::OSQLTable& /*_xTable*/ ) throw(SQLException, RuntimeException) +{ + ::rtl::OUString sParam(RTL_CONSTASCII_USTRINGPARAM(" = ?")); + ::rtl::OUString sIsNull(RTL_CONSTASCII_USTRINGPARAM(" IS NULL")); + static const ::rtl::OUString s_sAnd(RTL_CONSTASCII_USTRINGPARAM(" AND ")); + ::rtl::OUString aQuote = getIdentifierQuoteString(); + ::rtl::OUString aColumnName; + ::rtl::OUStringBuffer sKeyCondition,sIndexCondition; + ::std::vector<sal_Int32> aIndexColumnPositions; + TSQLStatements aKeyConditions; + TSQLStatements aIndexConditions; + TSQLStatements aSql; + + // sal_Int32 i = 1; + // here we build the condition part for the update statement + SelectColumnsMetaData::const_iterator aIter = m_pColumnNames->begin(); + SelectColumnsMetaData::const_iterator aEnd = m_pColumnNames->end(); + for(;aIter != aEnd;++aIter) + { + if ( m_aJoinedKeyColumns.find(aIter->second.nPosition) == m_aJoinedKeyColumns.end() && m_pKeyColumnNames->find(aIter->first) != m_pKeyColumnNames->end() ) + { + // only delete rows which aren't the key in the join + const ::rtl::OUString sQuotedColumnName = ::dbtools::quoteName( aQuote,aIter->second.sRealName); + lcl_fillKeyCondition(aIter->second.sTableName,sQuotedColumnName,(_rDeleteRow->get())[aIter->second.nPosition],aKeyConditions); + } + } + Reference<XDatabaseMetaData> xMetaData = m_xConnection->getMetaData(); + TSQLStatements::iterator aSqlIter = aKeyConditions.begin(); + TSQLStatements::iterator aSqlEnd = aKeyConditions.end(); + for(;aSqlIter != aSqlEnd ; ++aSqlIter) + { + ::rtl::OUStringBuffer& rCondition = aSqlIter->second; + if ( rCondition.getLength() ) + { + ::rtl::OUStringBuffer sSql; + sSql.appendAscii("DELETE FROM "); + ::rtl::OUString sCatalog,sSchema,sTable; + ::dbtools::qualifiedNameComponents(xMetaData,aSqlIter->first,sCatalog,sSchema,sTable,::dbtools::eInDataManipulation); + sSql.append( ::dbtools::composeTableNameForSelect( m_xConnection, sCatalog, sSchema, sTable ) ); + sSql.appendAscii(" WHERE "); + sSql.append( rCondition ); + executeDelete(_rDeleteRow,sSql.makeStringAndClear(),aSqlIter->first); + } + } +} +// ------------------------------------------------------------------------- +void OptimisticSet::executeDelete(const ORowSetRow& _rDeleteRow,const ::rtl::OUString& i_sSQL,const ::rtl::OUString& i_sTableName) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OptimisticSet::executeDelete" ); + + // now create end execute the prepared statement + Reference< XPreparedStatement > xPrep(m_xConnection->prepareStatement(i_sSQL)); + Reference< XParameters > xParameter(xPrep,UNO_QUERY); + + SelectColumnsMetaData::const_iterator aIter = m_pKeyColumnNames->begin(); + SelectColumnsMetaData::const_iterator aEnd = m_pKeyColumnNames->end(); + sal_Int32 i = 1; + for(;aIter != aEnd;++aIter) + { + if ( aIter->second.sTableName == i_sTableName ) + setParameter(i++,xParameter,(_rDeleteRow->get())[aIter->second.nPosition],aIter->second.nType,aIter->second.nScale); + } + m_bDeleted = xPrep->executeUpdate() > 0; + + if(m_bDeleted) + { + sal_Int32 nBookmark = ::comphelper::getINT32((_rDeleteRow->get())[0].getAny()); + if(m_aKeyIter == m_aKeyMap.find(nBookmark) && m_aKeyIter != m_aKeyMap.end()) + ++m_aKeyIter; + m_aKeyMap.erase(nBookmark); + m_bDeleted = sal_True; + } +} +// ----------------------------------------------------------------------------- +::rtl::OUString OptimisticSet::getComposedTableName(const ::rtl::OUString& /*_sCatalog*/, + const ::rtl::OUString& /*_sSchema*/, + const ::rtl::OUString& /*_sTable*/) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OptimisticSet::getComposedTableName" ); + ::rtl::OUString aComposedName; +/* + Reference<XDatabaseMetaData> xMetaData = m_xConnection->getMetaData(); + + if( xMetaData.is() && xMetaData->supportsTableCorrelationNames() ) + { + aComposedName = ::dbtools::composeTableName( xMetaData, _sCatalog, _sSchema, _sTable, sal_False, ::dbtools::eInDataManipulation ); + // first we have to check if the composed tablename is in the select clause or if an alias is used + Reference<XTablesSupplier> xTabSup(m_xComposer,UNO_QUERY); + Reference<XNameAccess> xSelectTables = xTabSup->getTables(); + OSL_ENSURE(xSelectTables.is(),"No Select tables!"); + if(xSelectTables.is()) + { + if(!xSelectTables->hasByName(aComposedName)) + { // the composed name isn't used in the select clause so we have to find out which name is used instead + ::rtl::OUString sCatalog,sSchema,sTable; + ::dbtools::qualifiedNameComponents(xMetaData,m_sUpdateTableName,sCatalog,sSchema,sTable,::dbtools::eInDataManipulation); + aComposedName = ::dbtools::composeTableNameForSelect( m_xConnection, sCatalog, sSchema, sTable ); + } + else + aComposedName = ::dbtools::composeTableNameForSelect( m_xConnection, _sCatalog, _sSchema, _sTable ); + } + } + else + aComposedName = ::dbtools::composeTableNameForSelect( m_xConnection, _sCatalog, _sSchema, _sTable ); +*/ + return aComposedName; +} +// ----------------------------------------------------------------------------- +void OptimisticSet::fillJoinedColumns_throw(const ::std::vector< TNodePair >& i_aJoinColumns) +{ + ::std::vector< TNodePair >::const_iterator aIter = i_aJoinColumns.begin(); + for(;aIter != i_aJoinColumns.end();++aIter) + { + ::rtl::OUString sColumnName,sTableName; + m_aSqlIterator.getColumnRange(aIter->first,sColumnName,sTableName); + ::rtl::OUStringBuffer sLeft,sRight; + sLeft.append(sTableName); + sLeft.appendAscii("."); + sLeft.append(sColumnName); + m_aSqlIterator.getColumnRange(aIter->second,sColumnName,sTableName); + sRight.append(sTableName); + sRight.appendAscii("."); + sRight.append(sColumnName); + fillJoinedColumns_throw(sLeft.makeStringAndClear(),sRight.makeStringAndClear()); + } +} +// ----------------------------------------------------------------------------- +void OptimisticSet::fillJoinedColumns_throw(const ::rtl::OUString& i_sLeftColumn,const ::rtl::OUString& i_sRightColumn) +{ + sal_Int32 nLeft = 0,nRight = 0; + SelectColumnsMetaData::const_iterator aLeftIter = m_pKeyColumnNames->find(i_sLeftColumn); + SelectColumnsMetaData::const_iterator aRightIter = m_pKeyColumnNames->find(i_sRightColumn); + + bool bLeftKey = aLeftIter != m_pKeyColumnNames->end(); + if ( bLeftKey ) + { + nLeft = aLeftIter->second.nPosition; + } + else + { + aLeftIter = m_pColumnNames->find(i_sLeftColumn); + if ( aLeftIter != m_pColumnNames->end() ) + nLeft = aLeftIter->second.nPosition; + } + + bool bRightKey = aRightIter != m_pKeyColumnNames->end(); + if ( bRightKey ) + { + nRight = aRightIter->second.nPosition; + } + else + { + aRightIter = m_pColumnNames->find(i_sRightColumn); + if ( aRightIter != m_pColumnNames->end() ) + nRight = aRightIter->second.nPosition; + } + + if (bLeftKey) + m_aJoinedKeyColumns[nLeft] = nRight; + else + m_aJoinedColumns[nLeft] = nRight; + if (bRightKey) + m_aJoinedKeyColumns[nRight] = nLeft; + else + m_aJoinedColumns[nRight] = nLeft; +} +// ----------------------------------------------------------------------------- +bool OptimisticSet::isResultSetChanged() const +{ + bool bOld = m_bResultSetChanged; + m_bResultSetChanged = false; + return bOld; +} +// ----------------------------------------------------------------------------- +void OptimisticSet::reset(const Reference< XResultSet>& _xDriverSet) +{ + OCacheSet::construct(_xDriverSet,::rtl::OUString()); + m_bRowCountFinal = sal_False; + m_aKeyMap.clear(); + m_aKeyMap.insert(OKeySetMatrix::value_type(0,OKeySetValue(NULL,::std::pair<sal_Int32,Reference<XRow> >(0,NULL)))); + m_aKeyIter = m_aKeyMap.begin(); +} +// ----------------------------------------------------------------------------- +void OptimisticSet::mergeColumnValues(sal_Int32 i_nColumnIndex,ORowSetValueVector::Vector& io_aInsertRow,ORowSetValueVector::Vector& io_aRow,::std::vector<sal_Int32>& o_aChangedColumns) +{ + o_aChangedColumns.push_back(i_nColumnIndex); + ::std::map<sal_Int32,sal_Int32>::const_iterator aJoinIter = m_aJoinedColumns.find(i_nColumnIndex); + if ( aJoinIter != m_aJoinedColumns.end() ) + { + io_aRow[aJoinIter->second] = io_aRow[i_nColumnIndex]; + io_aInsertRow[aJoinIter->second] = io_aInsertRow[i_nColumnIndex]; + io_aRow[aJoinIter->second].setModified(); + o_aChangedColumns.push_back(aJoinIter->second); + } +} +namespace +{ + struct PositionFunctor : ::std::unary_function<SelectColumnsMetaData::value_type,bool> + { + sal_Int32 m_nPos; + PositionFunctor(sal_Int32 i_nPos) + : m_nPos(i_nPos) + { + } + + inline bool operator()(const SelectColumnsMetaData::value_type& _aType) + { + return m_nPos == _aType.second.nPosition; + } + }; + struct TableNameFunctor : ::std::unary_function<SelectColumnsMetaData::value_type,bool> + { + ::rtl::OUString m_sTableName; + TableNameFunctor(const ::rtl::OUString& i_sTableName) + : m_sTableName(i_sTableName) + { + } + + inline bool operator()(const SelectColumnsMetaData::value_type& _aType) + { + return m_sTableName == _aType.second.sTableName; + } + }; +} +// ----------------------------------------------------------------------------- +bool OptimisticSet::updateColumnValues(const ORowSetValueVector::Vector& io_aCachedRow,ORowSetValueVector::Vector& io_aRow,const ::std::vector<sal_Int32>& i_aChangedColumns) +{ + bool bRet = false; + ::std::vector<sal_Int32>::const_iterator aColIdxIter = i_aChangedColumns.begin(); + for(;aColIdxIter != i_aChangedColumns.end();++aColIdxIter) + { + SelectColumnsMetaData::const_iterator aFind = ::std::find_if(m_pKeyColumnNames->begin(),m_pKeyColumnNames->end(),PositionFunctor(*aColIdxIter)); + if ( aFind != m_pKeyColumnNames->end() ) + { + const ::rtl::OUString sTableName = aFind->second.sTableName; + aFind = ::std::find_if(m_pKeyColumnNames->begin(),m_pKeyColumnNames->end(),TableNameFunctor(sTableName)); + while( aFind != m_pKeyColumnNames->end() ) + { + io_aRow[aFind->second.nPosition].setSigned(io_aCachedRow[aFind->second.nPosition].isSigned()); + if ( io_aCachedRow[aFind->second.nPosition] != io_aRow[aFind->second.nPosition] ) + break; + ++aFind; + } + if ( aFind == m_pKeyColumnNames->end() ) + { + bRet = true; + SelectColumnsMetaData::const_iterator aIter = m_pColumnNames->begin(); + SelectColumnsMetaData::const_iterator aEnd = m_pColumnNames->end(); + for ( ;aIter != aEnd;++aIter ) + { + if ( aIter->second.sTableName == sTableName ) + { + io_aRow[aIter->second.nPosition] = io_aCachedRow[aIter->second.nPosition]; + io_aRow[aIter->second.nPosition].setModified(); + } + } + } + } + } + return bRet; +} +// ----------------------------------------------------------------------------- +bool OptimisticSet::columnValuesUpdated(ORowSetValueVector::Vector& o_aCachedRow,const ORowSetValueVector::Vector& i_aRow) +{ + bool bRet = false; + SelectColumnsMetaData::const_iterator aIter = m_pColumnNames->begin(); + SelectColumnsMetaData::const_iterator aEnd = m_pColumnNames->end(); + for(;aIter != aEnd;++aIter) + { + SelectColumnsMetaData::const_iterator aFind = ::std::find_if(m_pKeyColumnNames->begin(),m_pKeyColumnNames->end(),PositionFunctor(aIter->second.nPosition)); + if ( aFind != m_pKeyColumnNames->end() ) + { + const ::rtl::OUString sTableName = aFind->second.sTableName; + aFind = ::std::find_if(m_pKeyColumnNames->begin(),m_pKeyColumnNames->end(),TableNameFunctor(sTableName)); + while( aFind != m_pKeyColumnNames->end() ) + { + o_aCachedRow[aFind->second.nPosition].setSigned(i_aRow[aFind->second.nPosition].isSigned()); + if ( o_aCachedRow[aFind->second.nPosition] != i_aRow[aFind->second.nPosition] ) + break; + ++aFind; + } + if ( aFind == m_pKeyColumnNames->end() ) + { + bRet = true; + SelectColumnsMetaData::const_iterator aIter2 = m_pColumnNames->begin(); + SelectColumnsMetaData::const_iterator aEnd2 = m_pColumnNames->end(); + for ( ;aIter2 != aEnd2;++aIter2 ) + { + if ( aIter2->second.sTableName == sTableName ) + { + o_aCachedRow[aIter2->second.nPosition] = i_aRow[aIter2->second.nPosition]; + o_aCachedRow[aIter2->second.nPosition].setModified(); + } + } + fillMissingValues(o_aCachedRow); + } + } + } + return bRet; +} +// ----------------------------------------------------------------------------- +void OptimisticSet::fillMissingValues(ORowSetValueVector::Vector& io_aRow) const +{ + TSQLStatements aSql; + TSQLStatements aKeyConditions; + ::std::map< ::rtl::OUString,bool > aResultSetChanged; + ::rtl::OUString aQuote = getIdentifierQuoteString(); + static ::rtl::OUString aAnd = ::rtl::OUString::createFromAscii(" AND "); + ::rtl::OUString sIsNull(RTL_CONSTASCII_USTRINGPARAM(" IS NULL")); + ::rtl::OUString sParam(RTL_CONSTASCII_USTRINGPARAM(" = ?")); + // here we build the condition part for the update statement + SelectColumnsMetaData::const_iterator aColIter = m_pColumnNames->begin(); + SelectColumnsMetaData::const_iterator aColEnd = m_pColumnNames->end(); + for(;aColIter != aColEnd;++aColIter) + { + const ::rtl::OUString sQuotedColumnName = ::dbtools::quoteName( aQuote,aColIter->second.sRealName); + if ( m_aJoinedKeyColumns.find(aColIter->second.nPosition) != m_aJoinedKeyColumns.end() ) + { + lcl_fillKeyCondition(aColIter->second.sTableName,sQuotedColumnName,io_aRow[aColIter->second.nPosition],aKeyConditions); + } + ::rtl::OUStringBuffer& rPart = aSql[aColIter->second.sTableName]; + if ( rPart.getLength() ) + rPart.appendAscii(", "); + rPart.append(sQuotedColumnName); + } + Reference<XDatabaseMetaData> xMetaData = m_xConnection->getMetaData(); + TSQLStatements::iterator aSqlIter = aSql.begin(); + TSQLStatements::iterator aSqlEnd = aSql.end(); + for(;aSqlIter != aSqlEnd ; ++aSqlIter) + { + if ( aSqlIter->second.getLength() ) + { + ::rtl::OUStringBuffer& rCondition = aKeyConditions[aSqlIter->first]; + if ( rCondition.getLength() ) + { + ::rtl::OUString sCatalog,sSchema,sTable; + ::dbtools::qualifiedNameComponents(xMetaData,aSqlIter->first,sCatalog,sSchema,sTable,::dbtools::eInDataManipulation); + ::rtl::OUString sComposedTableName = ::dbtools::composeTableNameForSelect( m_xConnection, sCatalog, sSchema, sTable ); + ::rtl::OUStringBuffer sQuery; + sQuery.appendAscii("SELECT "); + sQuery.append(aSqlIter->second); + sQuery.appendAscii(" FROM "); + sQuery.append(sComposedTableName); + sQuery.appendAscii(" WHERE "); + sQuery.append(rCondition.makeStringAndClear()); + + try + { + Reference< XPreparedStatement > xPrep(m_xConnection->prepareStatement(sQuery.makeStringAndClear())); + Reference< XParameters > xParameter(xPrep,UNO_QUERY); + // and then the values of the where condition + SelectColumnsMetaData::iterator aKeyIter = m_pKeyColumnNames->begin(); + SelectColumnsMetaData::iterator aKeyEnd = m_pKeyColumnNames->end(); + sal_Int32 i = 1; + for(;aKeyIter != aKeyEnd;++aKeyIter) + { + if ( aKeyIter->second.sTableName == aSqlIter->first ) + { + setParameter(i++,xParameter,io_aRow[aKeyIter->second.nPosition],aKeyIter->second.nType,aKeyIter->second.nScale); + } + } + Reference<XResultSet> xRes = xPrep->executeQuery(); + Reference<XRow> xRow(xRes,UNO_QUERY); + if ( xRow.is() && xRes->next() ) + { + i = 1; + aColIter = m_pColumnNames->begin(); + for(;aColIter != aColEnd;++aColIter) + { + if ( aColIter->second.sTableName == aSqlIter->first ) + { + io_aRow[aColIter->second.nPosition].fill(i++,aColIter->second.nType,aColIter->second.bNullable,xRow); + io_aRow[aColIter->second.nPosition].setModified(); + } + } + } + } + catch(const SQLException&) + { + } + } + } + } +} +// ----------------------------------------------------------------------------- + diff --git a/dbaccess/source/core/api/OptimisticSet.hxx b/dbaccess/source/core/api/OptimisticSet.hxx new file mode 100644 index 000000000000..ba0a04c8b773 --- /dev/null +++ b/dbaccess/source/core/api/OptimisticSet.hxx @@ -0,0 +1,109 @@ +/************************************************************************* + * + * 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: KeySet.hxx,v $ + * $Revision: 1.30 $ + * + * 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_CORE_API_OPTIMISTICSET_HXX +#define DBACCESS_CORE_API_OPTIMISTICSET_HXX + +#include "KeySet.hxx" +#include <cppuhelper/implbase1.hxx> + +#include <connectivity/sqlparse.hxx> +#include <connectivity/sqliterator.hxx> + +#include <com/sun/star/lang/XUnoTunnel.hpp> +#include <com/sun/star/sdb/XSingleSelectQueryAnalyzer.hpp> +#include <comphelper/stl_types.hxx> +#include <comphelper/componentcontext.hxx> + +namespace dbaccess +{ + // is used when the source supports keys + class OptimisticSet : public OKeySet + { + ::connectivity::OSQLParser m_aSqlParser; + ::connectivity::OSQLParseTreeIterator m_aSqlIterator; + + ::std::map<sal_Int32,sal_Int32> m_aJoinedColumns; + ::std::map<sal_Int32,sal_Int32> m_aJoinedKeyColumns; + + + mutable bool m_bResultSetChanged; + + /** + getComposedTableName return the composed table name for the query + @param _sCatalog the catalogname may be empty + @param _sSchema the schemaname may be empty + @param _sTable the tablename + + @return the composed name + */ + ::rtl::OUString getComposedTableName( const ::rtl::OUString& _sCatalog, + const ::rtl::OUString& _sSchema, + const ::rtl::OUString& _sTable); + + void impl_convertValue_throw(const ORowSetRow& _rInsertRow,const SelectColumnDescription& i_aMetaData); + + void executeDelete(const ORowSetRow& _rDeleteRow,const ::rtl::OUString& i_sSQL,const ::rtl::OUString& i_sTableName); + void fillJoinedColumns_throw(const ::std::vector< ::connectivity::TNodePair>& i_aJoinColumns); + void fillJoinedColumns_throw(const ::rtl::OUString& i_sLeftColumn,const ::rtl::OUString& i_sRightColumn); + protected: + virtual ~OptimisticSet(); + public: + OptimisticSet(const ::comphelper::ComponentContext& _rContext, + const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection>& i_xConnection, + const ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XSingleSelectQueryAnalyzer >& _xComposer, + const ORowSetValueVector& _aParameterValueForCache); + + // late ctor which can throw exceptions + virtual void construct(const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet>& _xDriverSet,const ::rtl::OUString& i_sRowSetFilter); + + // ------------------------------------------------------------------------- + // ::com::sun::star::sdbcx::XDeleteRows + virtual ::com::sun::star::uno::Sequence< sal_Int32 > SAL_CALL deleteRows( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& rows ,const connectivity::OSQLTable& _xTable) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + // ::com::sun::star::sdbc::XResultSetUpdate + virtual void SAL_CALL updateRow(const ORowSetRow& _rInsertRow,const ORowSetRow& _rOrginalRow,const connectivity::OSQLTable& _xTable ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL deleteRow(const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& _xTable ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL insertRow( const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& _xTable ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // CacheSet + virtual bool isResultSetChanged() const; + virtual void reset(const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet>& _xDriverSet); + virtual void mergeColumnValues(sal_Int32 i_nColumnIndex,ORowSetValueVector::Vector& io_aInsertRow,ORowSetValueVector::Vector& io_aRow,::std::vector<sal_Int32>& o_aChangedColumns); + virtual bool columnValuesUpdated(ORowSetValueVector::Vector& o_aCachedRow,const ORowSetValueVector::Vector& i_aRow); + virtual bool updateColumnValues(const ORowSetValueVector::Vector& io_aCachedRow,ORowSetValueVector::Vector& io_aRow,const ::std::vector<sal_Int32>& i_aChangedColumns); + virtual void fillMissingValues(ORowSetValueVector::Vector& io_aRow) const; + + bool isReadOnly() const { return m_aJoinedKeyColumns.empty(); } + const ::std::map<sal_Int32,sal_Int32>& getJoinedColumns() const { return m_aJoinedColumns; } + const ::std::map<sal_Int32,sal_Int32>& getJoinedKeyColumns() const { return m_aJoinedKeyColumns; } + }; +} +#endif // DBACCESS_CORE_API_OPTIMISTICSET_HXX + diff --git a/dbaccess/source/core/api/PrivateRow.cxx b/dbaccess/source/core/api/PrivateRow.cxx new file mode 100644 index 000000000000..939e335b4cb3 --- /dev/null +++ b/dbaccess/source/core/api/PrivateRow.cxx @@ -0,0 +1,142 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle andor its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" +#include "PrivateRow.hxx" + +using namespace dbaccess; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star; + +::sal_Bool SAL_CALL OPrivateRow::wasNull( ) throw (SQLException, RuntimeException) + { + return m_aRow[m_nPos].isNull(); + } + ::rtl::OUString SAL_CALL OPrivateRow::getString( ::sal_Int32 columnIndex ) throw (SQLException, RuntimeException) + { + m_nPos = columnIndex; + return m_aRow[m_nPos]; + } + ::sal_Bool SAL_CALL OPrivateRow::getBoolean( ::sal_Int32 columnIndex ) throw (SQLException, RuntimeException) + { + m_nPos = columnIndex; + return m_aRow[m_nPos]; + } + ::sal_Int8 SAL_CALL OPrivateRow::getByte( ::sal_Int32 columnIndex ) throw (SQLException, RuntimeException) + { + m_nPos = columnIndex; + return m_aRow[m_nPos]; + } + ::sal_Int16 SAL_CALL OPrivateRow::getShort( ::sal_Int32 columnIndex ) throw (SQLException, RuntimeException) + { + m_nPos = columnIndex; + return m_aRow[m_nPos]; + } + ::sal_Int32 SAL_CALL OPrivateRow::getInt( ::sal_Int32 columnIndex ) throw (SQLException, RuntimeException) + { + m_nPos = columnIndex; + return m_aRow[m_nPos]; + } + ::sal_Int64 SAL_CALL OPrivateRow::getLong( ::sal_Int32 columnIndex ) throw (SQLException, RuntimeException) + { + m_nPos = columnIndex; + return m_aRow[m_nPos]; + } + float SAL_CALL OPrivateRow::getFloat( ::sal_Int32 columnIndex ) throw (SQLException, RuntimeException) + { + m_nPos = columnIndex; + return m_aRow[m_nPos]; + } + double SAL_CALL OPrivateRow::getDouble( ::sal_Int32 columnIndex ) throw (SQLException, RuntimeException) + { + m_nPos = columnIndex; + return m_aRow[m_nPos]; + } + Sequence< ::sal_Int8 > SAL_CALL OPrivateRow::getBytes( ::sal_Int32 columnIndex ) throw (SQLException, RuntimeException) + { + m_nPos = columnIndex; + return m_aRow[m_nPos]; + } + ::com::sun::star::util::Date SAL_CALL OPrivateRow::getDate( ::sal_Int32 columnIndex ) throw (SQLException, RuntimeException) + { + m_nPos = columnIndex; + return m_aRow[m_nPos]; + } + ::com::sun::star::util::Time SAL_CALL OPrivateRow::getTime( ::sal_Int32 columnIndex ) throw (SQLException, RuntimeException) + { + m_nPos = columnIndex; + return m_aRow[m_nPos]; + } + ::com::sun::star::util::DateTime SAL_CALL OPrivateRow::getTimestamp( ::sal_Int32 columnIndex ) throw (SQLException, RuntimeException) + { + m_nPos = columnIndex; + return m_aRow[m_nPos]; + } + Reference< ::com::sun::star::io::XInputStream > SAL_CALL OPrivateRow::getBinaryStream( ::sal_Int32 columnIndex ) throw (SQLException, RuntimeException) + { + m_nPos = columnIndex; + return Reference< ::com::sun::star::io::XInputStream >(m_aRow[m_nPos].makeAny(),UNO_QUERY); + } + Reference< ::com::sun::star::io::XInputStream > SAL_CALL OPrivateRow::getCharacterStream( ::sal_Int32 columnIndex ) throw (SQLException, RuntimeException) + { + m_nPos = columnIndex; + return Reference< ::com::sun::star::io::XInputStream >(m_aRow[m_nPos].makeAny(),UNO_QUERY); + } + Any SAL_CALL OPrivateRow::getObject( ::sal_Int32 columnIndex, const Reference< ::com::sun::star::container::XNameAccess >& ) throw (SQLException, RuntimeException) + { + m_nPos = columnIndex; + return m_aRow[m_nPos].makeAny(); + } + Reference< XRef > SAL_CALL OPrivateRow::getRef( ::sal_Int32 columnIndex ) throw (SQLException, RuntimeException) + { + m_nPos = columnIndex; + return Reference< XRef >(m_aRow[m_nPos].makeAny(),UNO_QUERY); + } + Reference< XBlob > SAL_CALL OPrivateRow::getBlob( ::sal_Int32 columnIndex ) throw (SQLException, RuntimeException) + { + m_nPos = columnIndex; + return Reference< XBlob >(m_aRow[m_nPos].makeAny(),UNO_QUERY); + } + Reference< XClob > SAL_CALL OPrivateRow::getClob( ::sal_Int32 columnIndex ) throw (SQLException, RuntimeException) + { + m_nPos = columnIndex; + return Reference< XClob >(m_aRow[m_nPos].makeAny(),UNO_QUERY); + } + Reference< XArray > SAL_CALL OPrivateRow::getArray( ::sal_Int32 columnIndex ) throw (SQLException, RuntimeException) + { + m_nPos = columnIndex; + return Reference< XArray >(m_aRow[m_nPos].makeAny(),UNO_QUERY); + } + diff --git a/dbaccess/source/core/api/PrivateRow.hxx b/dbaccess/source/core/api/PrivateRow.hxx new file mode 100644 index 000000000000..82dd97232c92 --- /dev/null +++ b/dbaccess/source/core/api/PrivateRow.hxx @@ -0,0 +1,69 @@ +/************************************************************************* + * + * 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: OptimisticSet.cxx,v $ + * $Revision: 1.73 $ + * + * 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 PRIVATE_ROW_HXX +#define PRIVATE_ROW_HXX + +#include <cppuhelper/implbase1.hxx> +#include <com/sun/star/sdbc/XRow.hpp> +#include "RowSetRow.hxx" + +namespace dbaccess +{ + class OPrivateRow : public ::cppu::WeakImplHelper1< ::com::sun::star::sdbc::XRow> + { + ORowSetValueVector::Vector m_aRow; + sal_Int32 m_nPos; + public: + OPrivateRow(const ORowSetValueVector::Vector& i_aRow) : m_aRow(i_aRow),m_nPos(0) + { + } + virtual ::sal_Bool SAL_CALL wasNull( ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getString( ::sal_Int32 columnIndex ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::sal_Bool SAL_CALL getBoolean( ::sal_Int32 columnIndex ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::sal_Int8 SAL_CALL getByte( ::sal_Int32 columnIndex ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::sal_Int16 SAL_CALL getShort( ::sal_Int32 columnIndex ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::sal_Int32 SAL_CALL getInt( ::sal_Int32 columnIndex ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::sal_Int64 SAL_CALL getLong( ::sal_Int32 columnIndex ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual float SAL_CALL getFloat( ::sal_Int32 columnIndex ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual double SAL_CALL getDouble( ::sal_Int32 columnIndex ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::sal_Int8 > SAL_CALL getBytes( ::sal_Int32 columnIndex ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::util::Date SAL_CALL getDate( ::sal_Int32 columnIndex ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::util::Time SAL_CALL getTime( ::sal_Int32 columnIndex ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::util::DateTime SAL_CALL getTimestamp( ::sal_Int32 columnIndex ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getBinaryStream( ::sal_Int32 columnIndex ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getCharacterStream( ::sal_Int32 columnIndex ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Any SAL_CALL getObject( ::sal_Int32 columnIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& typeMap ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRef > SAL_CALL getRef( ::sal_Int32 columnIndex ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XBlob > SAL_CALL getBlob( ::sal_Int32 columnIndex ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XClob > SAL_CALL getClob( ::sal_Int32 columnIndex ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XArray > SAL_CALL getArray( ::sal_Int32 columnIndex ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + }; +} // dbaccess +#endif // PRIVATE_ROW_HXX diff --git a/dbaccess/source/core/api/RowSet.cxx b/dbaccess/source/core/api/RowSet.cxx new file mode 100644 index 000000000000..829155709119 --- /dev/null +++ b/dbaccess/source/core/api/RowSet.cxx @@ -0,0 +1,3057 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#include "RowSet.hxx" +#include "dbastrings.hrc" +#include "sdbcoretools.hxx" +#include "SingleSelectQueryComposer.hxx" +#include "module_dba.hxx" +#include "sdbcoretools.hxx" +#include "CRowSetColumn.hxx" +#include "CRowSetDataColumn.hxx" +#include "RowSetCache.hxx" +#include "core_resource.hrc" +#include "core_resource.hxx" +#include "tablecontainer.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/container/XChild.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/sdb/CommandType.hpp> +#include <com/sun/star/sdb/ErrorCondition.hpp> +#include <com/sun/star/sdb/RowChangeAction.hpp> +#include <com/sun/star/sdb/RowSetVetoException.hpp> +#include <com/sun/star/sdb/XCompletedConnection.hpp> +#include <com/sun/star/sdb/XParametersSupplier.hpp> +#include <com/sun/star/sdb/XQueriesSupplier.hpp> +#include <com/sun/star/sdbc/FetchDirection.hpp> +#include <com/sun/star/sdbc/ResultSetConcurrency.hpp> +#include <com/sun/star/sdbc/XDataSource.hpp> +#include <com/sun/star/sdbc/XDriverAccess.hpp> +#include <com/sun/star/sdbcx/CompareBookmark.hpp> +#include <com/sun/star/sdbcx/Privilege.hpp> +#include <com/sun/star/sdbcx/XDataDefinitionSupplier.hpp> +#include <com/sun/star/uno/XNamingService.hpp> +#include <com/sun/star/util/XNumberFormatsSupplier.hpp> +/** === end UNO includes === **/ + +#include <comphelper/componentcontext.hxx> +#include <comphelper/extract.hxx> +#include <comphelper/interaction.hxx> +#include <comphelper/property.hxx> +#include <comphelper/seqstream.hxx> +#include <comphelper/sequence.hxx> +#include <comphelper/types.hxx> +#include <comphelper/uno3.hxx> +#include <connectivity/BlobHelper.hxx> +#include <connectivity/dbconversion.hxx> +#include <connectivity/dbexception.hxx> +#include <connectivity/dbtools.hxx> +#include <cppuhelper/exc_hlp.hxx> +#include <cppuhelper/interfacecontainer.h> +#include <cppuhelper/typeprovider.hxx> +#include <rtl/logfile.hxx> +#include <unotools/syslocale.hxx> +#include <tools/debug.hxx> +#include <tools/diagnose_ex.h> +#include <unotools/configmgr.hxx> + +using namespace utl; +using namespace dbaccess; +using namespace connectivity; +using namespace comphelper; +using namespace dbtools; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::task; +using namespace ::com::sun::star::util; +using namespace ::cppu; +using namespace ::osl; + +//-------------------------------------------------------------------------- +extern "C" void SAL_CALL createRegistryInfo_ORowSet() +{ + static ::dba::OAutoRegistration< ORowSet > aAutoRegistration; +} +// ----------------------------------------------------------------------------- + +#define NOTIFY_LISTERNERS_CHECK(_rListeners,T,method) \ + Sequence< Reference< XInterface > > aListenerSeq = _rListeners.getElements(); \ + \ + const Reference< XInterface >* pxIntBegin = aListenerSeq.getConstArray(); \ + const Reference< XInterface >* pxInt = pxIntBegin + aListenerSeq.getLength(); \ + \ + _rGuard.clear(); \ + sal_Bool bCheck = sal_True; \ + while( pxInt > pxIntBegin && bCheck ) \ + { \ + try \ + { \ + while( pxInt > pxIntBegin && bCheck ) \ + { \ + --pxInt; \ + bCheck = static_cast< T* >( pxInt->get() )->method(aEvt); \ + } \ + } \ + catch( RuntimeException& ) \ + { \ + } \ + } \ + _rGuard.reset(); + + +//.................................................................. +namespace dbaccess +{ +//.................................................................. +//-------------------------------------------------------------------------- +Reference< XInterface > ORowSet_CreateInstance(const Reference< XMultiServiceFactory >& _rxFactory) +{ + return *(new ORowSet(_rxFactory)); +} +//-------------------------------------------------------------------------- +ORowSet::ORowSet( const Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB ) + :ORowSet_BASE1(m_aMutex) + ,ORowSetBase( _rxORB, ORowSet_BASE1::rBHelper, &m_aMutex ) + ,m_pParameters( NULL ) + ,m_aRowsetListeners(*m_pMutex) + ,m_aApproveListeners(*m_pMutex) + ,m_aRowsChangeListener(*m_pMutex) + ,m_pTables(NULL) + ,m_nFetchDirection(FetchDirection::FORWARD) + ,m_nFetchSize(50) + ,m_nMaxFieldSize(0) + ,m_nMaxRows(0) + ,m_nQueryTimeOut(0) + ,m_nCommandType(CommandType::COMMAND) + ,m_nTransactionIsolation(0) + ,m_nPrivileges(0) + ,m_nInAppend(0) + ,m_bUseEscapeProcessing(sal_True) + ,m_bApplyFilter(sal_False) + ,m_bCommandFacetsDirty( sal_True ) + ,m_bModified(sal_False) + ,m_bRebuildConnOnExecute(sal_False) + ,m_bIsBookmarable(sal_True) + ,m_bNew(sal_False) + ,m_bCanUpdateInsertedRows(sal_True) + ,m_bOwnConnection(sal_False) +{ + m_nResultSetType = ResultSetType::SCROLL_SENSITIVE; + m_nResultSetConcurrency = ResultSetConcurrency::UPDATABLE; + m_pMySelf = this; + m_aActiveConnection <<= m_xActiveConnection; + + sal_Int32 nRBT = PropertyAttribute::READONLY | PropertyAttribute::BOUND | PropertyAttribute::TRANSIENT; + sal_Int32 nRT = PropertyAttribute::READONLY | PropertyAttribute::TRANSIENT; + sal_Int32 nBT = PropertyAttribute::BOUND | PropertyAttribute::TRANSIENT; + + m_aPrematureParamValues.get().resize( 0 ); + + // sdb.RowSet Properties + registerMayBeVoidProperty(PROPERTY_ACTIVE_CONNECTION,PROPERTY_ID_ACTIVE_CONNECTION, PropertyAttribute::MAYBEVOID|PropertyAttribute::TRANSIENT|PropertyAttribute::BOUND, &m_aActiveConnection, ::getCppuType(reinterpret_cast< Reference< XConnection >* >(NULL))); + registerProperty(PROPERTY_DATASOURCENAME, PROPERTY_ID_DATASOURCENAME, PropertyAttribute::BOUND, &m_aDataSourceName, ::getCppuType(reinterpret_cast< ::rtl::OUString*>(NULL))); + registerProperty(PROPERTY_COMMAND, PROPERTY_ID_COMMAND, PropertyAttribute::BOUND, &m_aCommand, ::getCppuType(reinterpret_cast< ::rtl::OUString*>(NULL))); + registerProperty(PROPERTY_COMMAND_TYPE, PROPERTY_ID_COMMAND_TYPE, PropertyAttribute::BOUND, &m_nCommandType, ::getCppuType(reinterpret_cast< sal_Int32*>(NULL))); + registerProperty(PROPERTY_ACTIVECOMMAND, PROPERTY_ID_ACTIVECOMMAND, nRBT, &m_aActiveCommand, ::getCppuType(reinterpret_cast< ::rtl::OUString*>(NULL))); + registerProperty(PROPERTY_IGNORERESULT, PROPERTY_ID_IGNORERESULT, PropertyAttribute::BOUND, &m_bIgnoreResult, ::getBooleanCppuType()); + registerProperty(PROPERTY_FILTER, PROPERTY_ID_FILTER, PropertyAttribute::BOUND, &m_aFilter, ::getCppuType(reinterpret_cast< ::rtl::OUString*>(NULL))); + registerProperty(PROPERTY_HAVING_CLAUSE, PROPERTY_ID_HAVING_CLAUSE, PropertyAttribute::BOUND, &m_aHavingClause, ::getCppuType(reinterpret_cast< ::rtl::OUString*>(NULL))); + registerProperty(PROPERTY_GROUP_BY, PROPERTY_ID_GROUP_BY, PropertyAttribute::BOUND, &m_aGroupBy, ::getCppuType(reinterpret_cast< ::rtl::OUString*>(NULL))); + registerProperty(PROPERTY_APPLYFILTER, PROPERTY_ID_APPLYFILTER, PropertyAttribute::BOUND, &m_bApplyFilter, ::getBooleanCppuType()); + registerProperty(PROPERTY_ORDER, PROPERTY_ID_ORDER, PropertyAttribute::BOUND, &m_aOrder, ::getCppuType(reinterpret_cast< ::rtl::OUString*>(NULL))); + registerProperty(PROPERTY_PRIVILEGES, PROPERTY_ID_PRIVILEGES, nRT, &m_nPrivileges, ::getCppuType(reinterpret_cast< sal_Int32*>(NULL))); + registerProperty(PROPERTY_ISMODIFIED, PROPERTY_ID_ISMODIFIED, nBT, &m_bModified, ::getBooleanCppuType()); + registerProperty(PROPERTY_ISNEW, PROPERTY_ID_ISNEW, nRBT, &m_bNew, ::getBooleanCppuType()); + registerProperty(PROPERTY_SINGLESELECTQUERYCOMPOSER,PROPERTY_ID_SINGLESELECTQUERYCOMPOSER, nRT, &m_xComposer, ::getCppuType(reinterpret_cast< Reference< XSingleSelectQueryComposer >* >(NULL))); + + // sdbcx.ResultSet Properties + registerProperty(PROPERTY_ISBOOKMARKABLE, PROPERTY_ID_ISBOOKMARKABLE, nRT, &m_bIsBookmarable, ::getBooleanCppuType()); + registerProperty(PROPERTY_CANUPDATEINSERTEDROWS,PROPERTY_ID_CANUPDATEINSERTEDROWS, nRT, &m_bCanUpdateInsertedRows, ::getBooleanCppuType()); + // sdbc.ResultSet Properties + registerProperty(PROPERTY_RESULTSETCONCURRENCY, PROPERTY_ID_RESULTSETCONCURRENCY, PropertyAttribute::TRANSIENT, &m_nResultSetConcurrency,::getCppuType(reinterpret_cast< sal_Int32*>(NULL))); + registerProperty(PROPERTY_RESULTSETTYPE, PROPERTY_ID_RESULTSETTYPE, PropertyAttribute::TRANSIENT, &m_nResultSetType, ::getCppuType(reinterpret_cast< sal_Int32*>(NULL))); + registerProperty(PROPERTY_FETCHDIRECTION, PROPERTY_ID_FETCHDIRECTION, PropertyAttribute::TRANSIENT, &m_nFetchDirection, ::getCppuType(reinterpret_cast< sal_Int32*>(NULL))); + registerProperty(PROPERTY_FETCHSIZE, PROPERTY_ID_FETCHSIZE, PropertyAttribute::TRANSIENT, &m_nFetchSize, ::getCppuType(reinterpret_cast< sal_Int32*>(NULL))); + + // sdbc.RowSet Properties + registerProperty(PROPERTY_URL, PROPERTY_ID_URL, 0, &m_aURL, ::getCppuType(reinterpret_cast< ::rtl::OUString*>(NULL))); + registerProperty(PROPERTY_TRANSACTIONISOLATION, PROPERTY_ID_TRANSACTIONISOLATION, PropertyAttribute::TRANSIENT, &m_nTransactionIsolation,::getCppuType(reinterpret_cast< sal_Int32*>(NULL))); + registerMayBeVoidProperty(PROPERTY_TYPEMAP, PROPERTY_ID_TYPEMAP, PropertyAttribute::MAYBEVOID|PropertyAttribute::TRANSIENT, &m_aTypeMap, ::getCppuType(reinterpret_cast< Reference< XNameAccess >* >(NULL))); + registerProperty(PROPERTY_ESCAPE_PROCESSING,PROPERTY_ID_ESCAPE_PROCESSING, PropertyAttribute::BOUND, &m_bUseEscapeProcessing,::getBooleanCppuType() ); + registerProperty(PROPERTY_QUERYTIMEOUT, PROPERTY_ID_QUERYTIMEOUT, PropertyAttribute::TRANSIENT, &m_nQueryTimeOut, ::getCppuType(reinterpret_cast< sal_Int32*>(NULL))); + registerProperty(PROPERTY_MAXFIELDSIZE, PROPERTY_ID_MAXFIELDSIZE, PropertyAttribute::TRANSIENT, &m_nMaxFieldSize, ::getCppuType(reinterpret_cast< sal_Int32*>(NULL))); + registerProperty(PROPERTY_MAXROWS, PROPERTY_ID_MAXROWS, 0, &m_nMaxRows, ::getCppuType(reinterpret_cast< sal_Int32*>(NULL)) ); + registerProperty(PROPERTY_USER, PROPERTY_ID_USER, PropertyAttribute::TRANSIENT, &m_aUser, ::getCppuType(reinterpret_cast< ::rtl::OUString*>(NULL))); + registerProperty(PROPERTY_PASSWORD, PROPERTY_ID_PASSWORD, PropertyAttribute::TRANSIENT, &m_aPassword, ::getCppuType(reinterpret_cast< ::rtl::OUString*>(NULL))); + + registerProperty(PROPERTY_UPDATE_CATALOGNAME, PROPERTY_ID_UPDATE_CATALOGNAME, PropertyAttribute::BOUND, &m_aUpdateCatalogName, ::getCppuType(reinterpret_cast< ::rtl::OUString*>(NULL))); + registerProperty(PROPERTY_UPDATE_SCHEMANAME, PROPERTY_ID_UPDATE_SCHEMANAME, PropertyAttribute::BOUND, &m_aUpdateSchemaName, ::getCppuType(reinterpret_cast< ::rtl::OUString*>(NULL))); + registerProperty(PROPERTY_UPDATE_TABLENAME, PROPERTY_ID_UPDATE_TABLENAME, PropertyAttribute::BOUND, &m_aUpdateTableName, ::getCppuType(reinterpret_cast< ::rtl::OUString*>(NULL))); +} + +ORowSet::~ORowSet() +{ + if ( !m_rBHelper.bDisposed && !m_rBHelper.bInDispose ) + { + OSL_ENSURE(0, "Please check who doesn't dispose this component!"); + osl_incrementInterlockedCount( &m_refCount ); + dispose(); + } +} + +// ----------------------------------------------------------------------------- +void ORowSet::getPropertyDefaultByHandle( sal_Int32 _nHandle, Any& _rDefault ) const +{ + switch( _nHandle ) + { + case PROPERTY_ID_COMMAND_TYPE: + _rDefault <<= static_cast<sal_Int32>(CommandType::COMMAND); + break; + case PROPERTY_ID_IGNORERESULT: + _rDefault <<= sal_False; + break; + case PROPERTY_ID_APPLYFILTER: + _rDefault <<= sal_False; + break; + case PROPERTY_ID_ISMODIFIED: + _rDefault <<= sal_False; + break; + case PROPERTY_ID_ISBOOKMARKABLE: + _rDefault <<= sal_True; + break; + case PROPERTY_ID_CANUPDATEINSERTEDROWS: + _rDefault <<= sal_True; + break; + case PROPERTY_ID_RESULTSETTYPE: + _rDefault <<= ResultSetType::SCROLL_INSENSITIVE; + break; + case PROPERTY_ID_RESULTSETCONCURRENCY: + _rDefault <<= ResultSetConcurrency::UPDATABLE; + break; + case PROPERTY_ID_FETCHDIRECTION: + _rDefault <<= FetchDirection::FORWARD; + break; + case PROPERTY_ID_FETCHSIZE: + _rDefault <<= static_cast<sal_Int32>(1); + break; + case PROPERTY_ID_ESCAPE_PROCESSING: + _rDefault <<= sal_True; + break; + case PROPERTY_ID_MAXROWS: + _rDefault <<= sal_Int32( 0 ); + break; + case PROPERTY_ID_FILTER: + case PROPERTY_ID_HAVING_CLAUSE: + case PROPERTY_ID_GROUP_BY: + case PROPERTY_ID_ORDER: + case PROPERTY_ID_UPDATE_CATALOGNAME: + case PROPERTY_ID_UPDATE_SCHEMANAME: + case PROPERTY_ID_UPDATE_TABLENAME: + _rDefault <<= ::rtl::OUString(); + break; + } +} +// ------------------------------------------------------------------------- +// typedef ::comphelper::OPropertyArrayUsageHelper<ORowSet> ORowSet_Prop; + +void SAL_CALL ORowSet::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any& rValue) throw (Exception) +{ + switch(nHandle) + { + case PROPERTY_ID_ISMODIFIED: + m_bModified = cppu::any2bool(rValue); + break; + case PROPERTY_ID_FETCHDIRECTION: + if( m_nResultSetType == ResultSetType::FORWARD_ONLY) + throw Exception(); // else run through + default: + OPropertyStateContainer::setFastPropertyValue_NoBroadcast(nHandle,rValue); + } + + if ( ( nHandle == PROPERTY_ID_ACTIVE_CONNECTION ) + || ( nHandle == PROPERTY_ID_DATASOURCENAME ) + || ( nHandle == PROPERTY_ID_COMMAND ) + || ( nHandle == PROPERTY_ID_COMMAND_TYPE ) + || ( nHandle == PROPERTY_ID_IGNORERESULT ) + || ( nHandle == PROPERTY_ID_FILTER ) + || ( nHandle == PROPERTY_ID_HAVING_CLAUSE ) + || ( nHandle == PROPERTY_ID_GROUP_BY ) + || ( nHandle == PROPERTY_ID_APPLYFILTER ) + || ( nHandle == PROPERTY_ID_ORDER ) + || ( nHandle == PROPERTY_ID_URL ) + || ( nHandle == PROPERTY_ID_USER ) + ) + { + m_bCommandFacetsDirty = sal_True; + } + + + switch(nHandle) + { + case PROPERTY_ID_ACTIVE_CONNECTION: + // the new connection + { + Reference< XConnection > xNewConnection(m_aActiveConnection,UNO_QUERY); + setActiveConnection(xNewConnection, sal_False); + } + + m_bOwnConnection = sal_False; + m_bRebuildConnOnExecute = sal_False; + break; + + case PROPERTY_ID_DATASOURCENAME: + if(!m_xStatement.is()) + { + Reference< XConnection > xNewConn; + Any aNewConn; + aNewConn <<= xNewConn; + setFastPropertyValue(PROPERTY_ID_ACTIVE_CONNECTION, aNewConn); + } + else + m_bRebuildConnOnExecute = sal_True; + break; + case PROPERTY_ID_FETCHSIZE: + if(m_pCache) + { + m_pCache->setMaxRowSize(m_nFetchSize); + fireRowcount(); + } + break; + case PROPERTY_ID_URL: + // is the connection-to-be-built determined by the url (which is the case if m_aDataSourceName is empty) ? + if (!m_aDataSourceName.getLength()) + { + // are we active at the moment ? + if (m_xStatement.is()) + // yes -> the next execute needs to rebuild our connection because of this new property + m_bRebuildConnOnExecute = sal_True; + else + { // no -> drop our active connection (if we have one) as it doesn't correspond to this new property value anymore + Reference< XConnection > xNewConn; + Any aNewConn; + aNewConn <<= xNewConn; + setFastPropertyValue(PROPERTY_ID_ACTIVE_CONNECTION, aNewConn); + } + } + m_bOwnConnection = sal_True; + break; + case PROPERTY_ID_TYPEMAP: + ::cppu::extractInterface(m_xTypeMap,m_aTypeMap); + break; + default: + break; + }; +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::getFastPropertyValue(Any& rValue,sal_Int32 nHandle) const +{ + if(m_pCache) + { + switch(nHandle) + { + case PROPERTY_ID_ISMODIFIED: + rValue.setValue(&m_bModified,::getCppuBooleanType()); + break; + case PROPERTY_ID_ISNEW: + rValue.setValue(&m_bNew,::getCppuBooleanType()); + break; + case PROPERTY_ID_PRIVILEGES: + rValue <<= m_pCache->m_nPrivileges; + break; + case PROPERTY_ID_ACTIVE_CONNECTION: + rValue <<= m_xActiveConnection; + break; + case PROPERTY_ID_TYPEMAP: + rValue <<= m_xTypeMap; + break; + default: + ORowSetBase::getFastPropertyValue(rValue,nHandle); + }; + } + else + { + switch(nHandle) + { + case PROPERTY_ID_ACTIVE_CONNECTION: + rValue <<= m_xActiveConnection; + break; + case PROPERTY_ID_TYPEMAP: + rValue <<= m_xTypeMap; + break; + default: + ORowSetBase::getFastPropertyValue(rValue,nHandle); + } + } +} +// ------------------------------------------------------------------------- +// com::sun::star::XTypeProvider +Sequence< Type > SAL_CALL ORowSet::getTypes() throw (RuntimeException) +{ + OTypeCollection aTypes(::getCppuType( (const Reference< XPropertySet > *)0 ), + ::getCppuType( (const Reference< XFastPropertySet > *)0 ), + ::getCppuType( (const Reference< XMultiPropertySet > *)0 ), + ::comphelper::concatSequences(ORowSet_BASE1::getTypes(),ORowSetBase::getTypes())); + return aTypes.getTypes(); +} +// ------------------------------------------------------------------------- +Sequence< sal_Int8 > SAL_CALL ORowSet::getImplementationId() throw (RuntimeException) +{ + static OImplementationId * pId = 0; + if (! pId) + { + MutexGuard aGuard( Mutex::getGlobalMutex() ); + if (! pId) + { + static OImplementationId aId; + pId = &aId; + } + } + return pId->getImplementationId(); +} +// ------------------------------------------------------------------------- + +// com::sun::star::XInterface +Any SAL_CALL ORowSet::queryInterface( const Type & rType ) throw (RuntimeException) +{ + return ORowSet_BASE1::queryInterface( rType); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::acquire() throw() +{ + ORowSet_BASE1::acquire(); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::release() throw() +{ + ORowSet_BASE1::release(); +} +// ------------------------------------------------------------------------- + +// com::sun::star::XUnoTunnel +sal_Int64 SAL_CALL ORowSet::getSomething( const Sequence< sal_Int8 >& rId ) throw(RuntimeException) +{ + if (rId.getLength() == 16 && 0 == rtl_compareMemory(getImplementationId().getConstArray(), rId.getConstArray(), 16 ) ) + return reinterpret_cast<sal_Int64>(this); + + return 0; +} +// ------------------------------------------------------------------------- +// com::sun::star::XAggregation +Any SAL_CALL ORowSet::queryAggregation( const Type& rType ) throw(RuntimeException) +{ + Any aRet(ORowSetBase::queryInterface(rType)); + if (!aRet.hasValue()) + aRet = ORowSet_BASE1::queryAggregation(rType); + return aRet; +} +//------------------------------------------------------------------------------ +rtl::OUString ORowSet::getImplementationName_static( ) throw(RuntimeException) +{ + return rtl::OUString::createFromAscii("com.sun.star.comp.dba.ORowSet"); +} +// ------------------------------------------------------------------------- +// ::com::sun::star::XServiceInfo +::rtl::OUString SAL_CALL ORowSet::getImplementationName( ) throw(RuntimeException) +{ + return getImplementationName_static(); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ORowSet::supportsService( const ::rtl::OUString& _rServiceName ) throw(RuntimeException) +{ + return ::comphelper::findValue(getSupportedServiceNames(), _rServiceName, sal_True).getLength() != 0; +} +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > ORowSet::getSupportedServiceNames_static( ) throw (RuntimeException) +{ + Sequence< rtl::OUString > aSNS( 5 ); + aSNS[0] = SERVICE_SDBC_RESULTSET; + aSNS[1] = SERVICE_SDBC_ROWSET; + aSNS[2] = SERVICE_SDBCX_RESULTSET; + aSNS[3] = SERVICE_SDB_RESULTSET; + aSNS[4] = SERVICE_SDB_ROWSET; + return aSNS; +} +// ------------------------------------------------------------------------- +Sequence< ::rtl::OUString > SAL_CALL ORowSet::getSupportedServiceNames( ) throw(RuntimeException) +{ + return getSupportedServiceNames_static(); +} +//------------------------------------------------------------------------------ +Reference< XInterface > ORowSet::Create(const Reference< XComponentContext >& _rxContext) +{ + ::comphelper::ComponentContext aContext( _rxContext ); + return ORowSet_CreateInstance( aContext.getLegacyServiceFactory() ); +} +// ------------------------------------------------------------------------- +// OComponentHelper +void SAL_CALL ORowSet::disposing() +{ + OPropertyStateContainer::disposing(); + + MutexGuard aGuard(m_aMutex); + EventObject aDisposeEvent; + aDisposeEvent.Source = static_cast< XComponent* >(this); + m_aRowsetListeners.disposeAndClear( aDisposeEvent ); + m_aApproveListeners.disposeAndClear( aDisposeEvent ); + m_aRowsChangeListener.disposeAndClear( aDisposeEvent ); + + freeResources( true ); + + // remove myself as dispose listener + Reference< XComponent > xComponent(m_xActiveConnection, UNO_QUERY); + if (xComponent.is()) + { + Reference<XEventListener> xEvt; + query_aggregation(this,xEvt); + xComponent->removeEventListener(xEvt); + } + + m_aActiveConnection = Any(); // the any conatains a reference too + if(m_bOwnConnection) + ::comphelper::disposeComponent(m_xActiveConnection); + m_xActiveConnection = NULL; + + + ORowSetBase::disposing(); +} +// ------------------------------------------------------------------------- +void ORowSet::freeResources( bool _bComplete ) +{ + MutexGuard aGuard(m_aMutex); + + // free all clones + connectivity::OWeakRefArray::iterator aEnd = m_aClones.end(); + for (connectivity::OWeakRefArray::iterator i = m_aClones.begin(); aEnd != i; i++) + { + Reference< XComponent > xComp(i->get(), UNO_QUERY); + if (xComp.is()) + xComp->dispose(); + } + m_aClones.clear(); + + if ( _bComplete ) + { + // the columns must be disposed before the querycomposer is disposed because + // their owner can be the composer + TDataColumns().swap(m_aDataColumns);// clear and resize capacity + m_xColumns = NULL; + if ( m_pColumns ) + m_pColumns->disposing(); + // dispose the composer to avoid that everbody knows that the querycomposer is eol + try { ::comphelper::disposeComponent( m_xComposer ); } + catch(Exception&) + { + DBG_UNHANDLED_EXCEPTION(); + m_xComposer = NULL; + } + + // let our warnings container forget the reference to the (possibly disposed) old result set + m_aWarnings.setExternalWarnings( NULL ); + + DELETEZ(m_pCache); + + impl_resetTables_nothrow(); + + m_xStatement = NULL; + m_xTypeMap = NULL; + + m_aBookmark = Any(); + m_bBeforeFirst = sal_True; + m_bAfterLast = sal_False; + m_bNew = sal_False; + m_bModified = sal_False; + m_bLastKnownRowCountFinal = sal_False; + m_nLastKnownRowCount = 0; + if ( m_aOldRow.isValid() ) + m_aOldRow->clearRow(); + + impl_disposeParametersContainer_nothrow(); + + m_bCommandFacetsDirty = sal_True; + } +} + +// ------------------------------------------------------------------------- +void ORowSet::setActiveConnection( Reference< XConnection >& _rxNewConn, sal_Bool _bFireEvent ) +{ + if (_rxNewConn.get() == m_xActiveConnection.get()) + // nothing to do + return; + + // remove the event listener for the old connection + Reference< XComponent > xComponent(m_xActiveConnection, UNO_QUERY); + if (xComponent.is()) + { + Reference<XEventListener> xListener; + query_aggregation(this, xListener); + xComponent->removeEventListener(xListener); + } + + // if we owned the connection, remember it for later disposing + if(m_bOwnConnection) + m_xOldConnection = m_xActiveConnection; + + // for firing the PropertyChangeEvent + sal_Int32 nHandle = PROPERTY_ID_ACTIVE_CONNECTION; + Any aOldConnection; aOldConnection <<= m_xActiveConnection; + Any aNewConnection; aNewConnection <<= _rxNewConn; + + // set the new connection + m_xActiveConnection = _rxNewConn; + if (m_xActiveConnection.is()) + m_aActiveConnection <<= m_xActiveConnection; + else + m_aActiveConnection.clear(); + + // fire the event + if (_bFireEvent) + fire(&nHandle, &aNewConnection, &aOldConnection, 1, sal_False); + + // register as event listener for the new connection + xComponent.set(m_xActiveConnection,UNO_QUERY); + if (xComponent.is()) + { + Reference<XEventListener> xListener; + query_aggregation(this, xListener); + xComponent->addEventListener(xListener); + } +} + +// ------------------------------------------------------------------------- +// ::com::sun::star::XEventListener +void SAL_CALL ORowSet::disposing( const ::com::sun::star::lang::EventObject& Source ) throw(RuntimeException) +{ + // close rowset because the connection is going to be deleted (someone told me :-) + Reference<XConnection> xCon(Source.Source,UNO_QUERY); + if(m_xActiveConnection == xCon) + { + close(); + { + MutexGuard aGuard( m_aMutex ); + Reference< XConnection > xXConnection; + setActiveConnection( xXConnection ); + } + } +} +// ------------------------------------------------------------------------- + +// XCloseable +void SAL_CALL ORowSet::close( ) throw(SQLException, RuntimeException) +{ + { + MutexGuard aGuard( m_aMutex ); + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + } + // additionals things to set + freeResources( true ); +} +// ------------------------------------------------------------------------- +// comphelper::OPropertyArrayUsageHelper +::cppu::IPropertyArrayHelper* ORowSet::createArrayHelper( ) const +{ + Sequence< Property > aProps; + describeProperties(aProps); + return new ::cppu::OPropertyArrayHelper(aProps); +} +// ------------------------------------------------------------------------- +// cppu::OPropertySetHelper +::cppu::IPropertyArrayHelper& SAL_CALL ORowSet::getInfoHelper() +{ + typedef ::comphelper::OPropertyArrayUsageHelper<ORowSet> ORowSet_PROP; + return *ORowSet_PROP::getArrayHelper(); +} +// ----------------------------------------------------------------------------- +void ORowSet::updateValue(sal_Int32 columnIndex,const ORowSetValue& x) +{ + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( *m_pMutex ); + checkUpdateConditions(columnIndex); + checkUpdateIterator(); + + ORowSetValueVector::Vector& rRow = ((*m_aCurrentRow)->get()); + ORowSetNotifier aNotify(this,rRow); + m_pCache->updateValue(columnIndex,x,rRow,aNotify.getChangedColumns()); + aNotify.firePropertyChange(); +} +// ------------------------------------------------------------------------- +// XRowUpdate +void SAL_CALL ORowSet::updateNull( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( *m_pMutex ); + checkUpdateConditions(columnIndex); + checkUpdateIterator(); + + ORowSetValueVector::Vector& rRow = ((*m_aCurrentRow)->get()); + ORowSetNotifier aNotify(this,rRow); + m_pCache->updateNull(columnIndex,rRow,aNotify.getChangedColumns()); + aNotify.firePropertyChange(); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::updateBoolean( sal_Int32 columnIndex, sal_Bool x ) throw(SQLException, RuntimeException) +{ + updateValue(columnIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::updateByte( sal_Int32 columnIndex, sal_Int8 x ) throw(SQLException, RuntimeException) +{ + updateValue(columnIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::updateShort( sal_Int32 columnIndex, sal_Int16 x ) throw(SQLException, RuntimeException) +{ + updateValue(columnIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::updateInt( sal_Int32 columnIndex, sal_Int32 x ) throw(SQLException, RuntimeException) +{ + updateValue(columnIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::updateLong( sal_Int32 columnIndex, sal_Int64 x ) throw(SQLException, RuntimeException) +{ + updateValue(columnIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::updateFloat( sal_Int32 columnIndex, float x ) throw(SQLException, RuntimeException) +{ + updateValue(columnIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::updateDouble( sal_Int32 columnIndex, double x ) throw(SQLException, RuntimeException) +{ + updateValue(columnIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::updateString( sal_Int32 columnIndex, const ::rtl::OUString& x ) throw(SQLException, RuntimeException) +{ + updateValue(columnIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::updateBytes( sal_Int32 columnIndex, const Sequence< sal_Int8 >& x ) throw(SQLException, RuntimeException) +{ + updateValue(columnIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::updateDate( sal_Int32 columnIndex, const ::com::sun::star::util::Date& x ) throw(SQLException, RuntimeException) +{ + updateValue(columnIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::updateTime( sal_Int32 columnIndex, const ::com::sun::star::util::Time& x ) throw(SQLException, RuntimeException) +{ + updateValue(columnIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::updateTimestamp( sal_Int32 columnIndex, const ::com::sun::star::util::DateTime& x ) throw(SQLException, RuntimeException) +{ + updateValue(columnIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::updateBinaryStream( sal_Int32 columnIndex, const Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(SQLException, RuntimeException) +{ + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + ::osl::MutexGuard aGuard( *m_pMutex ); + checkUpdateConditions(columnIndex); + checkUpdateIterator(); + + //if(((*m_aCurrentRow)->get())[columnIndex].getTypeKind() == DataType::BLOB) + //{ + // ::connectivity::ORowSetValue aOldValue = ((*m_aCurrentRow)->get())[columnIndex]; + // m_pCache->updateBinaryStream(columnIndex,x,length); + // ((*m_aCurrentRow)->get())[columnIndex] = makeAny(x); + // ((*m_aCurrentRow)->get())[columnIndex].setTypeKind(DataType::BLOB); + // firePropertyChange(columnIndex-1 ,aOldValue); + // fireProperty(PROPERTY_ID_ISMODIFIED,sal_True,sal_False); + //} + //else + { + Sequence<sal_Int8> aSeq; + if(x.is()) + x->readBytes(aSeq,length); + updateValue(columnIndex,aSeq); + } +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::updateCharacterStream( sal_Int32 columnIndex, const Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(SQLException, RuntimeException) +{ + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + ::osl::MutexGuard aGuard( *m_pMutex ); + checkUpdateConditions(columnIndex); + checkUpdateIterator(); + ORowSetValueVector::Vector& rRow = ((*m_aCurrentRow)->get()); + ORowSetNotifier aNotify(this,rRow); + m_pCache->updateCharacterStream(columnIndex,x,length,rRow,aNotify.getChangedColumns()); + aNotify.firePropertyChange(); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::updateObject( sal_Int32 columnIndex, const Any& x ) throw(SQLException, RuntimeException) +{ + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + ::osl::MutexGuard aGuard( *m_pMutex ); + checkUpdateConditions(columnIndex); + checkUpdateIterator(); + + Any aNewValue = x; + + if ( m_pColumns ) + { + Reference<XPropertySet> xColumn(m_pColumns->getByIndex(columnIndex-1),UNO_QUERY); + sal_Int32 nColType = 0; + xColumn->getPropertyValue(PROPERTY_TYPE) >>= nColType; + switch( nColType ) + { + case DataType::DATE: + case DataType::TIME: + case DataType::TIMESTAMP: + { + double nValue = 0; + if ( x >>= nValue ) + { + if ( DataType::TIMESTAMP == nColType ) + aNewValue <<= dbtools::DBTypeConversion::toDateTime( nValue ); + else if ( DataType::DATE == nColType ) + aNewValue <<= dbtools::DBTypeConversion::toDate( nValue ); + else + aNewValue <<= dbtools::DBTypeConversion::toTime( nValue ); + } + break; + } + } + } + + if (!::dbtools::implUpdateObject(this, columnIndex, aNewValue)) + { // there is no other updateXXX call which can handle the value in x + ORowSetValueVector::Vector& rRow = ((*m_aCurrentRow)->get()); + ORowSetNotifier aNotify(this,rRow); + m_pCache->updateObject(columnIndex,aNewValue,rRow,aNotify.getChangedColumns()); + aNotify.firePropertyChange(); + } +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::updateNumericObject( sal_Int32 columnIndex, const Any& x, sal_Int32 scale ) throw(SQLException, RuntimeException) +{ + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + ::osl::MutexGuard aGuard( *m_pMutex ); + checkUpdateConditions(columnIndex); + checkUpdateIterator(); + ORowSetValueVector::Vector& rRow = ((*m_aCurrentRow)->get()); + ORowSetNotifier aNotify(this,rRow); + m_pCache->updateNumericObject(columnIndex,x,scale,rRow,aNotify.getChangedColumns()); + aNotify.firePropertyChange(); +} +// ------------------------------------------------------------------------- + +// XResultSetUpdate +void SAL_CALL ORowSet::insertRow( ) throw(SQLException, RuntimeException) +{ + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + // insertRow is not allowd when + // standing not on the insert row nor + // when the row isn't modified + // or the concurency is read only + ::osl::ResettableMutexGuard aGuard( *m_pMutex ); + + if(!m_pCache || !m_bNew || !m_bModified || m_nResultSetConcurrency == ResultSetConcurrency::READ_ONLY) + throwFunctionSequenceException(*this); + + if(m_bModified) + { + // remember old value for fire + sal_Bool bOld = m_bNew; + + ORowSetRow aOldValues; + if ( !m_aCurrentRow.isNull() ) + aOldValues = new ORowSetValueVector( m_aCurrentRow->getBody() ); + Sequence<Any> aChangedBookmarks; + RowsChangeEvent aEvt(*this,RowChangeAction::INSERT,1,aChangedBookmarks); + notifyAllListenersRowBeforeChange(aGuard,aEvt); + + ::std::vector< Any > aBookmarks; + sal_Bool bInserted = m_pCache->insertRow(aBookmarks); + + // make sure that our row is set to the new inserted row before clearing the insert flags in the cache + m_pCache->resetInsertRow(bInserted); + + // notification order + // - column values + setCurrentRow( sal_False, sal_True, aOldValues, aGuard ); // we don't move here + + // read-only flag restored + impl_restoreDataColumnsWriteable_throw(); + + // - rowChanged + notifyAllListenersRowChanged(aGuard,aEvt); + + if ( !aBookmarks.empty() ) + { + RowsChangeEvent aUpEvt(*this,RowChangeAction::UPDATE,aBookmarks.size(),Sequence<Any>(&(*aBookmarks.begin()),aBookmarks.size())); + notifyAllListenersRowChanged(aGuard,aUpEvt); + } + + // - IsModified + if(!m_bModified) + fireProperty(PROPERTY_ID_ISMODIFIED,sal_False,sal_True); + OSL_ENSURE( !m_bModified, "ORowSet::insertRow: just updated, but _still_ modified?" ); + + // - IsNew + if(m_bNew != bOld) + fireProperty(PROPERTY_ID_ISNEW,m_bNew,bOld); + + // - RowCount/IsRowCountFinal + fireRowcount(); + } +} +// ------------------------------------------------------------------------- +sal_Int32 SAL_CALL ORowSet::getRow( ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( *m_pMutex ); + checkCache(); + + // check if we are inserting a row + return (m_pCache && ( m_pCache->m_bNew || m_bModified )) ? 0 : ORowSetBase::getRow(); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::updateRow( ) throw(SQLException, RuntimeException) +{ + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + // not allowed when standing on insert row + ::osl::ResettableMutexGuard aGuard( *m_pMutex ); + if ( !m_pCache || m_nResultSetConcurrency == ResultSetConcurrency::READ_ONLY || m_bNew || ((m_pCache->m_nPrivileges & Privilege::UPDATE ) != Privilege::UPDATE) ) + throwFunctionSequenceException(*this); + + + if(m_bModified) + { + ORowSetRow aOldValues; + if ( !m_aCurrentRow.isNull() ) + aOldValues = new ORowSetValueVector( m_aCurrentRow->getBody() ); + + Sequence<Any> aChangedBookmarks; + RowsChangeEvent aEvt(*this,RowChangeAction::UPDATE,1,aChangedBookmarks); + notifyAllListenersRowBeforeChange(aGuard,aEvt); + + ::std::vector< Any > aBookmarks; + m_pCache->updateRow(m_aCurrentRow.operator ->(),aBookmarks); + if ( !aBookmarks.empty() ) + aEvt.Bookmarks = Sequence<Any>(&(*aBookmarks.begin()),aBookmarks.size()); + aEvt.Rows += aBookmarks.size(); + m_aBookmark = m_pCache->getBookmark(); + m_aCurrentRow = m_pCache->m_aMatrixIter; + if ( m_pCache->m_aMatrixIter != m_pCache->getEnd() && (*m_pCache->m_aMatrixIter).isValid() ) + { + if ( m_pCache->isResultSetChanged() ) + { + impl_rebuild_throw(aGuard); + } + else + { + m_aOldRow->setRow(new ORowSetValueVector(m_aCurrentRow->getBody())); + + // notification order + // - column values + ORowSetBase::firePropertyChange(aOldValues); + } + // - rowChanged + notifyAllListenersRowChanged(aGuard,aEvt); + + // - IsModified + if(!m_bModified) + fireProperty(PROPERTY_ID_ISMODIFIED,sal_False,sal_True); + OSL_ENSURE( !m_bModified, "ORowSet::updateRow: just updated, but _still_ modified?" ); + + // - RowCount/IsRowCountFinal + fireRowcount(); + } + else if ( !m_bAfterLast ) // the update went rong + { + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_UPDATE_FAILED ), SQL_INVALID_CURSOR_POSITION, *this ); + } + } +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::deleteRow( ) throw(SQLException, RuntimeException) +{ + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + + ::osl::ResettableMutexGuard aGuard( *m_pMutex ); + checkCache(); + + if ( m_bBeforeFirst || m_bAfterLast ) + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_NO_DELETE_BEFORE_AFTER ), SQL_INVALID_CURSOR_POSITION, *this ); + if ( m_bNew ) + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_NO_DELETE_INSERT_ROW ), SQL_INVALID_CURSOR_POSITION, *this ); + if ( m_nResultSetConcurrency == ResultSetConcurrency::READ_ONLY ) + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_RESULT_IS_READONLY ), SQL_FUNCTION_SEQUENCE_ERROR, *this ); + if ( ( m_pCache->m_nPrivileges & Privilege::DELETE ) != Privilege::DELETE ) + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_NO_DELETE_PRIVILEGE ), SQL_FUNCTION_SEQUENCE_ERROR, *this ); + if ( rowDeleted() ) + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_ROW_ALREADY_DELETED ), SQL_FUNCTION_SEQUENCE_ERROR, *this ); + + // this call position the cache indirect + Any aBookmarkToDelete( m_aBookmark ); + positionCache( MOVE_NONE_REFRESH_ONLY ); + sal_Int32 nDeletePosition = m_pCache->getRow(); + + notifyRowSetAndClonesRowDelete( aBookmarkToDelete ); + + ORowSetRow aOldValues; + if ( m_pCache->m_aMatrixIter != m_pCache->getEnd() && m_pCache->m_aMatrixIter->isValid() ) + aOldValues = new ORowSetValueVector( m_pCache->m_aMatrixIter->getBody() ); + + Sequence<Any> aChangedBookmarks; + RowsChangeEvent aEvt(*this,RowChangeAction::DELETE,1,aChangedBookmarks); + notifyAllListenersRowBeforeChange(aGuard,aEvt); + + m_pCache->deleteRow(); + notifyRowSetAndClonesRowDeleted( aBookmarkToDelete, nDeletePosition ); + + ORowSetNotifier aNotifier( this ); + // this will call cancelRowModification on the cache if necessary + + // notification order + // - rowChanged + notifyAllListenersRowChanged(aGuard,aEvt); + + // - IsModified + // - IsNew + aNotifier.fire( ); + + // - RowCount/IsRowCountFinal + fireRowcount(); +} + +// ------------------------------------------------------------------------- +void ORowSet::implCancelRowUpdates( sal_Bool _bNotifyModified ) SAL_THROW( ( SQLException, RuntimeException ) ) +{ + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( *m_pMutex ); + if ( m_bBeforeFirst || m_bAfterLast || rowDeleted() ) + return; // nothing to do so return + + checkCache(); + // cancelRowUpdates is not allowed when: + // - standing on the insert row + // - the concurrency is read only + // - the current row is deleted + if ( m_bNew || m_nResultSetConcurrency == ResultSetConcurrency::READ_ONLY ) + throwFunctionSequenceException(*this); + + positionCache( MOVE_NONE_REFRESH_ONLY ); + + ORowSetRow aOldValues; + if ( !m_aCurrentRow.isNull() ) + aOldValues = new ORowSetValueVector( m_aCurrentRow->getBody() ); + + m_pCache->cancelRowUpdates(); + + m_aBookmark = m_pCache->getBookmark(); + m_aCurrentRow = m_pCache->m_aMatrixIter; + m_aCurrentRow.setBookmark(m_aBookmark); + + // notification order + // - column values + ORowSetBase::firePropertyChange(aOldValues); + // IsModified + if( !m_bModified && _bNotifyModified ) + fireProperty(PROPERTY_ID_ISMODIFIED,sal_False,sal_True); +} + +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::cancelRowUpdates( ) throw(SQLException, RuntimeException) +{ + implCancelRowUpdates( sal_True ); +} + +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::addRowSetListener( const Reference< XRowSetListener >& listener ) throw(RuntimeException) +{ + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( m_aColumnsMutex ); + if(listener.is()) + m_aRowsetListeners.addInterface(listener); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::removeRowSetListener( const Reference< XRowSetListener >& listener ) throw(RuntimeException) +{ + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( m_aColumnsMutex ); + if(listener.is()) + m_aRowsetListeners.removeInterface(listener); +} +// ----------------------------------------------------------------------------- +void ORowSet::notifyAllListeners(::osl::ResettableMutexGuard& _rGuard) +{ + EventObject aEvt(*m_pMySelf); + _rGuard.clear(); + m_aRowsetListeners.notifyEach( &XRowSetListener::rowSetChanged, aEvt ); + _rGuard.reset(); +} +// ------------------------------------------------------------------------- +void ORowSet::notifyAllListenersCursorMoved(::osl::ResettableMutexGuard& _rGuard) +{ + EventObject aEvt(*m_pMySelf); + _rGuard.clear(); + m_aRowsetListeners.notifyEach( &XRowSetListener::cursorMoved, aEvt ); + _rGuard.reset(); +} +// ------------------------------------------------------------------------- +void ORowSet::notifyAllListenersRowChanged(::osl::ResettableMutexGuard& _rGuard, const RowsChangeEvent& aEvt) +{ + _rGuard.clear(); + m_aRowsetListeners.notifyEach( &XRowSetListener::rowChanged, (EventObject)aEvt ); + m_aRowsChangeListener.notifyEach( &XRowsChangeListener::rowsChanged, aEvt ); + _rGuard.reset(); +} +// ------------------------------------------------------------------------- +sal_Bool ORowSet::notifyAllListenersCursorBeforeMove(::osl::ResettableMutexGuard& _rGuard) +{ + EventObject aEvt(*m_pMySelf); + NOTIFY_LISTERNERS_CHECK(m_aApproveListeners,XRowSetApproveListener,approveCursorMove); + return bCheck; +} +// ------------------------------------------------------------------------- +void ORowSet::notifyAllListenersRowBeforeChange(::osl::ResettableMutexGuard& _rGuard,const RowChangeEvent &aEvt) +{ + NOTIFY_LISTERNERS_CHECK(m_aApproveListeners,XRowSetApproveListener,approveRowChange); + if ( !bCheck ) + m_aErrors.raiseTypedException( sdb::ErrorCondition::ROW_SET_OPERATION_VETOED, *this, ::cppu::UnoType< RowSetVetoException >::get() ); +} +// ------------------------------------------------------------------------- +void ORowSet::fireRowcount() +{ + sal_Int32 nCurrentRowCount( impl_getRowCount() ); + sal_Bool bCurrentRowCountFinal( m_pCache->m_bRowCountFinal ); + + if ( m_nLastKnownRowCount != nCurrentRowCount ) + { + sal_Int32 nHandle = PROPERTY_ID_ROWCOUNT; + Any aNew,aOld; + aNew <<= nCurrentRowCount; aOld <<= m_nLastKnownRowCount; + fire(&nHandle,&aNew,&aOld,1,sal_False); + m_nLastKnownRowCount = nCurrentRowCount; + } + if ( !m_bLastKnownRowCountFinal && ( m_bLastKnownRowCountFinal != bCurrentRowCountFinal ) ) + { + sal_Int32 nHandle = PROPERTY_ID_ISROWCOUNTFINAL; + Any aNew,aOld; + aNew <<= bCurrentRowCountFinal; + aOld <<= m_bLastKnownRowCountFinal; + fire(&nHandle,&aNew,&aOld,1,sal_False); + m_bLastKnownRowCountFinal = bCurrentRowCountFinal; + } +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::moveToInsertRow( ) throw(SQLException, RuntimeException) +{ + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + + ::osl::ResettableMutexGuard aGuard( *m_pMutex ); + checkPositioningAllowed(); + if ( ( m_pCache->m_nPrivileges & Privilege::INSERT ) != Privilege::INSERT ) + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_NO_INSERT_PRIVILEGE ), SQL_GENERAL_ERROR, *this ); + + if ( notifyAllListenersCursorBeforeMove( aGuard ) ) + { + // remember old value for fire + ORowSetRow aOldValues; + if ( rowDeleted() ) + { + positionCache( MOVE_FORWARD ); + m_pCache->next(); + setCurrentRow( sal_True, sal_False, aOldValues, aGuard); + } + else + positionCache( MOVE_NONE_REFRESH_ONLY ); + + // check before because the resultset could be empty + if ( !m_bBeforeFirst + && !m_bAfterLast + && m_pCache->m_aMatrixIter != m_pCache->getEnd() + && m_pCache->m_aMatrixIter->isValid() + ) + aOldValues = new ORowSetValueVector( m_pCache->m_aMatrixIter->getBody() ); + + const sal_Bool bNewState = m_bNew; + const sal_Bool bModState = m_bModified; + + m_pCache->moveToInsertRow(); + m_aCurrentRow = m_pCache->m_aInsertRow; + + // set read-only flag to false + impl_setDataColumnsWriteable_throw(); + + // notification order + // - column values + ORowSetBase::firePropertyChange(aOldValues); + + // - cursorMoved + notifyAllListenersCursorMoved(aGuard); + + // - IsModified + if ( bModState != m_bModified ) + fireProperty( PROPERTY_ID_ISMODIFIED, m_bModified, bModState ); + + // - IsNew + if ( bNewState != m_bNew ) + fireProperty( PROPERTY_ID_ISNEW, m_bNew, bNewState ); + + // - RowCount/IsRowCountFinal + fireRowcount(); + } +} +// ------------------------------------------------------------------------- +void ORowSet::impl_setDataColumnsWriteable_throw() +{ + impl_restoreDataColumnsWriteable_throw(); + TDataColumns::iterator aIter = m_aDataColumns.begin(); + m_aReadOnlyDataColumns.resize(m_aDataColumns.size(),false); + ::std::bit_vector::iterator aReadIter = m_aReadOnlyDataColumns.begin(); + for(;aIter != m_aDataColumns.end();++aIter,++aReadIter) + { + sal_Bool bReadOnly = sal_False; + (*aIter)->getPropertyValue(PROPERTY_ISREADONLY) >>= bReadOnly; + *aReadIter = bReadOnly; + + (*aIter)->setPropertyValue(PROPERTY_ISREADONLY,makeAny(sal_False)); + } +} +// ------------------------------------------------------------------------- +void ORowSet::impl_restoreDataColumnsWriteable_throw() +{ + TDataColumns::iterator aIter = m_aDataColumns.begin(); + ::std::bit_vector::iterator aReadIter = m_aReadOnlyDataColumns.begin(); + for(;aReadIter != m_aReadOnlyDataColumns.end();++aIter,++aReadIter) + { + (*aIter)->setPropertyValue(PROPERTY_ISREADONLY,makeAny((sal_Bool)*aReadIter )); + } + m_aReadOnlyDataColumns.clear(); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::moveToCurrentRow( ) throw(SQLException, RuntimeException) +{ + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + + ::osl::ResettableMutexGuard aGuard( *m_pMutex ); + checkPositioningAllowed(); + + if ( !m_pCache->m_bNew && !m_bModified ) + // nothing to do if we're not on the insertion row, and not modified otherwise + return; + + if ( rowDeleted() ) + // this would perhaps even justify a RuntimeException .... + // if the current row is deleted, then no write access to this row should be possible. So, + // m_bModified should be true. Also, as soon as somebody calls moveToInsertRow, + // our current row should not be deleted anymore. So, we should not have survived the above + // check "if ( !m_pCache->m_bNew && !m_bModified )" + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_ROW_ALREADY_DELETED ), SQL_FUNCTION_SEQUENCE_ERROR, *this ); + + if ( notifyAllListenersCursorBeforeMove( aGuard ) ) + { + positionCache( MOVE_NONE_REFRESH_ONLY ); + + ORowSetNotifier aNotifier( this ); + + // notification order + // - cursorMoved + notifyAllListenersCursorMoved(aGuard); + + // - IsModified + // - IsNew + aNotifier.fire(); + } +} +// ------------------------------------------------------------------------- +// XRow +sal_Bool SAL_CALL ORowSet::wasNull( ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( *m_pMutex ); + checkCache(); + + return ( m_pCache && isInsertRow() ) ? ((*m_pCache->m_aInsertRow)->get())[m_nLastColumnIndex].isNull() : ORowSetBase::wasNull(); +} +// ----------------------------------------------------------------------------- +const ORowSetValue& ORowSet::getInsertValue(sal_Int32 columnIndex) +{ + checkCache(); + + if ( m_pCache && isInsertRow() ) + return ((*m_pCache->m_aInsertRow)->get())[m_nLastColumnIndex = columnIndex]; + + return getValue(columnIndex); +} +// ------------------------------------------------------------------------- +::rtl::OUString SAL_CALL ORowSet::getString( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( *m_pMutex ); + return getInsertValue(columnIndex); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ORowSet::getBoolean( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( *m_pMutex ); + return getInsertValue(columnIndex); +} +// ------------------------------------------------------------------------- +sal_Int8 SAL_CALL ORowSet::getByte( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( *m_pMutex ); + return getInsertValue(columnIndex); +} +// ------------------------------------------------------------------------- +sal_Int16 SAL_CALL ORowSet::getShort( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( *m_pMutex ); + return getInsertValue(columnIndex); +} +// ------------------------------------------------------------------------- +sal_Int32 SAL_CALL ORowSet::getInt( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( *m_pMutex ); + return getInsertValue(columnIndex); +} +// ------------------------------------------------------------------------- +sal_Int64 SAL_CALL ORowSet::getLong( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( *m_pMutex ); + return getInsertValue(columnIndex); +} +// ------------------------------------------------------------------------- +float SAL_CALL ORowSet::getFloat( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( *m_pMutex ); + return getInsertValue(columnIndex); +} +// ------------------------------------------------------------------------- +double SAL_CALL ORowSet::getDouble( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( *m_pMutex ); + return getInsertValue(columnIndex); +} +// ------------------------------------------------------------------------- +Sequence< sal_Int8 > SAL_CALL ORowSet::getBytes( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( *m_pMutex ); + return getInsertValue(columnIndex); +} +// ------------------------------------------------------------------------- +::com::sun::star::util::Date SAL_CALL ORowSet::getDate( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( *m_pMutex ); + return getInsertValue(columnIndex); +} +// ------------------------------------------------------------------------- +::com::sun::star::util::Time SAL_CALL ORowSet::getTime( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( *m_pMutex ); + return getInsertValue(columnIndex); +} +// ------------------------------------------------------------------------- +::com::sun::star::util::DateTime SAL_CALL ORowSet::getTimestamp( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( *m_pMutex ); + return getInsertValue(columnIndex); +} +// ------------------------------------------------------------------------- +Reference< ::com::sun::star::io::XInputStream > SAL_CALL ORowSet::getBinaryStream( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( *m_pMutex ); + if ( m_pCache && isInsertRow() ) + { + checkCache(); + return new ::comphelper::SequenceInputStream(((*m_pCache->m_aInsertRow)->get())[m_nLastColumnIndex = columnIndex].getSequence()); + } + + return ORowSetBase::getBinaryStream(columnIndex); +} +// ------------------------------------------------------------------------- +Reference< ::com::sun::star::io::XInputStream > SAL_CALL ORowSet::getCharacterStream( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( *m_pMutex ); + if(m_pCache && isInsertRow() ) + { + checkCache(); + return new ::comphelper::SequenceInputStream(((*m_pCache->m_aInsertRow)->get())[m_nLastColumnIndex = columnIndex].getSequence()); + } + + return ORowSetBase::getCharacterStream(columnIndex); +} +// ------------------------------------------------------------------------- +Any SAL_CALL ORowSet::getObject( sal_Int32 columnIndex, const Reference< XNameAccess >& /*typeMap*/ ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( *m_pMutex ); + return getInsertValue(columnIndex).makeAny(); +} +// ------------------------------------------------------------------------- +Reference< XRef > SAL_CALL ORowSet::getRef( sal_Int32 /*columnIndex*/ ) throw(SQLException, RuntimeException) +{ + return Reference< XRef >(); +} +// ------------------------------------------------------------------------- +Reference< XBlob > SAL_CALL ORowSet::getBlob( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + if ( m_pCache && isInsertRow() ) + { + checkCache(); + return new ::connectivity::BlobHelper(((*m_pCache->m_aInsertRow)->get())[m_nLastColumnIndex = columnIndex].getSequence()); + } + return ORowSetBase::getBlob(columnIndex); +} +// ------------------------------------------------------------------------- +Reference< XClob > SAL_CALL ORowSet::getClob( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + return Reference< XClob >(getInsertValue(columnIndex).makeAny(),UNO_QUERY); +} +// ------------------------------------------------------------------------- +Reference< XArray > SAL_CALL ORowSet::getArray( sal_Int32 /*columnIndex*/ ) throw(SQLException, RuntimeException) +{ + return Reference< XArray >(); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::executeWithCompletion( const Reference< XInteractionHandler >& _rxHandler ) throw(SQLException, RuntimeException) +{ + if (!_rxHandler.is()) + execute(); + + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + + // tell everybody that we will change the result set + approveExecution(); + + ResettableMutexGuard aGuard( m_aMutex ); + + try + { + freeResources( m_bCommandFacetsDirty ); + + // calc the connection to be used + if (m_xActiveConnection.is() && m_bRebuildConnOnExecute) + { + // there was a setProperty(ActiveConnection), but a setProperty(DataSource) _after_ that, too + Reference< XConnection > xXConnection; + setActiveConnection( xXConnection ); + } + calcConnection( _rxHandler ); + m_bRebuildConnOnExecute = sal_False; + + Reference< XSingleSelectQueryComposer > xComposer = getCurrentSettingsComposer( this, m_aContext.getLegacyServiceFactory() ); + Reference<XParametersSupplier> xParameters(xComposer, UNO_QUERY); + + Reference<XIndexAccess> xParamsAsIndicies = xParameters.is() ? xParameters->getParameters() : Reference<XIndexAccess>(); + const sal_Int32 nParamCount = xParamsAsIndicies.is() ? xParamsAsIndicies->getCount() : 0; + if ( m_aParametersSet.size() < (size_t)nParamCount ) + m_aParametersSet.resize( nParamCount ,false); + + ::dbtools::askForParameters( xComposer, this, m_xActiveConnection, _rxHandler,m_aParametersSet ); + } + // ensure that only the allowed exceptions leave this block + catch(SQLException&) + { + throw; + } + catch(RuntimeException&) + { + throw; + } + catch(Exception&) + { + DBG_ERROR("ORowSet::executeWithCompletion: caught an unexpected exception type while filling in the parameters!"); + } + + // we're done with the parameters, now for the real execution + + // do the real execute + execute_NoApprove_NoNewConn(aGuard); +} + +// ------------------------------------------------------------------------- +Reference< XIndexAccess > SAL_CALL ORowSet::getParameters( ) throw (RuntimeException) +{ + ::osl::MutexGuard aGuard( *m_pMutex ); + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + + if ( m_bCommandFacetsDirty ) + // need to rebuild the parameters, since some property which contributes to the + // complete command, and thus the parameters, changed + impl_disposeParametersContainer_nothrow(); + + if ( !m_pParameters.get() && m_aCommand.getLength() ) + { + try + { + ::rtl::OUString sNotInterestedIn; + impl_initComposer_throw( sNotInterestedIn ); + } + catch( const Exception& ) + { + // silence it + } + } + + return m_pParameters.get(); +} + +// ------------------------------------------------------------------------- +void ORowSet::approveExecution() throw (RowSetVetoException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aColumnsMutex ); + EventObject aEvt(*this); + + OInterfaceIteratorHelper aApproveIter( m_aApproveListeners ); + while ( aApproveIter.hasMoreElements() ) + { + Reference< XRowSetApproveListener > xListener( static_cast< XRowSetApproveListener* >( aApproveIter.next() ) ); + try + { + if ( xListener.is() && !xListener->approveRowSetChange( aEvt ) ) + throw RowSetVetoException(); + } + catch ( const DisposedException& e ) + { + if ( e.Context == xListener ) + aApproveIter.remove(); + } + catch ( const RuntimeException& ) { throw; } + catch ( const RowSetVetoException& ) { throw; } + catch ( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } +} +// ------------------------------------------------------------------------- +// XRowSet +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::execute( ) throw(SQLException, RuntimeException) +{ + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + + // tell everybody that we will change the result set + approveExecution(); + + ResettableMutexGuard aGuard( m_aMutex ); + freeResources( m_bCommandFacetsDirty ); + + // calc the connection to be used + if (m_xActiveConnection.is() && m_bRebuildConnOnExecute) { + // there was a setProperty(ActiveConnection), but a setProperty(DataSource) _after_ that, too + Reference< XConnection> xXConnection; + setActiveConnection( xXConnection ); + } + + calcConnection(NULL); + m_bRebuildConnOnExecute = sal_False; + + // do the real execute + execute_NoApprove_NoNewConn(aGuard); +} + +//------------------------------------------------------------------------------ +void ORowSet::setStatementResultSetType( const Reference< XPropertySet >& _rxStatement, sal_Int32 _nDesiredResultSetType, sal_Int32 _nDesiredResultSetConcurrency ) +{ + OSL_ENSURE( _rxStatement.is(), "ORowSet::setStatementResultSetType: invalid statement - this will crash!" ); + + sal_Int32 nResultSetType( _nDesiredResultSetType ); + sal_Int32 nResultSetConcurrency( _nDesiredResultSetConcurrency ); + + // there *might* be a data source setting which tells use to be more defensive with those settings + // #i15113# / 2005-02-10 / frank.schoenheit@sun.com + sal_Bool bRespectDriverRST = sal_False; + Any aSetting; + if ( getDataSourceSetting( ::dbaccess::getDataSource( m_xActiveConnection ), "RespectDriverResultSetType", aSetting ) ) + { + OSL_VERIFY( aSetting >>= bRespectDriverRST ); + } + + if ( bRespectDriverRST ) + { + // try type/concurrency settings with decreasing usefullness, and rely on what the connection claims + // to support + Reference< XDatabaseMetaData > xMeta( m_xActiveConnection->getMetaData() ); + + sal_Int32 nCharacteristics[5][2] = + { { ResultSetType::SCROLL_SENSITIVE, ResultSetConcurrency::UPDATABLE }, + { ResultSetType::SCROLL_INSENSITIVE, ResultSetConcurrency::UPDATABLE }, + { ResultSetType::SCROLL_SENSITIVE, ResultSetConcurrency::READ_ONLY }, + { ResultSetType::SCROLL_INSENSITIVE, ResultSetConcurrency::READ_ONLY }, + { ResultSetType::FORWARD_ONLY, ResultSetConcurrency::READ_ONLY } + }; + 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]; + + // don't try type/concurrency pairs which are more featured than what our caller requested + if ( nResultSetType > _nDesiredResultSetType ) + continue; + if ( nResultSetConcurrency > _nDesiredResultSetConcurrency ) + continue; + + if ( xMeta.is() && xMeta->supportsResultSetConcurrency( nResultSetType, nResultSetConcurrency ) ) + break; + } + } + + _rxStatement->setPropertyValue( PROPERTY_RESULTSETTYPE, makeAny( nResultSetType ) ); + _rxStatement->setPropertyValue( PROPERTY_RESULTSETCONCURRENCY, makeAny( nResultSetConcurrency ) ); +} + +// ----------------------------------------------------------------------------- +Reference< XResultSet > ORowSet::impl_prepareAndExecute_throw() +{ + ::rtl::OUString sCommandToExecute; + sal_Bool bUseEscapeProcessing = impl_initComposer_throw( sCommandToExecute ); + + Reference< XResultSet> xResultSet; + try + { + m_xStatement = m_xActiveConnection->prepareStatement( sCommandToExecute ); + if ( !m_xStatement.is() ) + { + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_INTERNAL_ERROR ), SQL_GENERAL_ERROR, *this ); + } + + Reference< XPropertySet > xStatementProps( m_xStatement, UNO_QUERY_THROW ); + // set the result set type and concurrency + try + { + xStatementProps->setPropertyValue( PROPERTY_USEBOOKMARKS, makeAny( sal_True ) ); + setStatementResultSetType( xStatementProps, m_nResultSetType, m_nResultSetConcurrency ); + } + catch ( const Exception& ) + { + // this exception doesn't matter here because when we catch an exception + // then the driver doesn't support this feature + } + m_aParameterValueForCache.get().resize(1); + Reference< XParameters > xParam( m_xStatement, UNO_QUERY_THROW ); + size_t nParamCount( m_pParameters.is() ? m_pParameters->size() : m_aPrematureParamValues.get().size() ); + for ( size_t i=1; i<=nParamCount; ++i ) + { + ORowSetValue& rParamValue( getParameterStorage( (sal_Int32)i ) ); + ::dbtools::setObjectWithInfo( xParam, i, rParamValue.makeAny(), rParamValue.getTypeKind() ); + m_aParameterValueForCache.get().push_back(rParamValue); + } + + xResultSet = m_xStatement->executeQuery(); + } + catch( const SQLException& ) + { + SQLExceptionInfo aError( ::cppu::getCaughtException() ); + OSL_ENSURE( aError.isValid(), "ORowSet::impl_prepareAndExecute_throw: caught an SQLException which we cannot analyze!" ); + + // append information about what we were actually going to execute + try + { + String sQuery = bUseEscapeProcessing && m_xComposer.is() ? m_xComposer->getQuery() : m_aActiveCommand; + String sInfo( DBA_RES_PARAM( RID_STR_COMMAND_LEADING_TO_ERROR, "$command$", sQuery ) ); + aError.append( SQLExceptionInfo::SQL_CONTEXT, sInfo ); + } + catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); } + + // propagate + aError.doThrow(); + } + + return xResultSet; +} + +// ----------------------------------------------------------------------------- +void ORowSet::impl_initializeColumnSettings_nothrow( const Reference< XPropertySet >& _rxTemplateColumn, const Reference< XPropertySet >& _rxRowSetColumn ) +{ + OSL_ENSURE( _rxTemplateColumn.is() && _rxRowSetColumn.is(), + "ORowSet::impl_initializeColumnSettings_nothrow: this will crash!" ); + + bool bHaveAnyColumnSetting = false; + try + { + Reference< XPropertySetInfo > xInfo( _rxTemplateColumn->getPropertySetInfo(), UNO_QUERY_THROW ); + + // a number of properties is plain copied + const ::rtl::OUString aPropertyNames[] = { + PROPERTY_ALIGN, PROPERTY_RELATIVEPOSITION, PROPERTY_WIDTH, PROPERTY_HIDDEN, PROPERTY_CONTROLMODEL, + PROPERTY_HELPTEXT, PROPERTY_CONTROLDEFAULT + }; + for ( size_t i=0; i<sizeof( aPropertyNames ) / sizeof( aPropertyNames[0] ); ++i ) + { + if ( xInfo->hasPropertyByName( aPropertyNames[i] ) ) + { + _rxRowSetColumn->setPropertyValue( aPropertyNames[i], _rxTemplateColumn->getPropertyValue( aPropertyNames[i] ) ); + bHaveAnyColumnSetting = true; + } + } + + // the format key is slightly more complex + sal_Int32 nFormatKey = 0; + if( xInfo->hasPropertyByName( PROPERTY_NUMBERFORMAT ) ) + { + _rxTemplateColumn->getPropertyValue( PROPERTY_NUMBERFORMAT ) >>= nFormatKey; + bHaveAnyColumnSetting = true; + } + if ( !nFormatKey && m_xNumberFormatTypes.is() ) + nFormatKey = ::dbtools::getDefaultNumberFormat( _rxTemplateColumn, m_xNumberFormatTypes, SvtSysLocale().GetLocaleData().getLocale() ); + _rxRowSetColumn->setPropertyValue( PROPERTY_NUMBERFORMAT, makeAny( nFormatKey ) ); + } + catch(Exception&) + { + DBG_UNHANDLED_EXCEPTION(); + return; + } + + if ( bHaveAnyColumnSetting ) + return; + + // the template column could not provide *any* setting. Okay, probably it's a parser column, which + // does not offer those. However, perhaps the template column referes to a table column, which we + // can use as new template column + try + { + Reference< XPropertySetInfo > xInfo( _rxTemplateColumn->getPropertySetInfo(), UNO_QUERY_THROW ); + if ( !xInfo->hasPropertyByName( PROPERTY_TABLENAME ) ) + // no chance + return; + + ::rtl::OUString sTableName; + OSL_VERIFY( _rxTemplateColumn->getPropertyValue( PROPERTY_TABLENAME ) >>= sTableName ); + + Reference< XNameAccess > xTables( impl_getTables_throw(), UNO_QUERY_THROW ); + if ( !xTables->hasByName( sTableName ) ) + // no chance + return; + + Reference< XColumnsSupplier > xTableColSup( xTables->getByName( sTableName ), UNO_QUERY_THROW ); + Reference< XNameAccess > xTableCols( xTableColSup->getColumns(), UNO_QUERY_THROW ); + + ::rtl::OUString sTableColumnName; + + // get the "Name" or (preferred) "RealName" property of the column + ::rtl::OUString sNamePropertyName( PROPERTY_NAME ); + if ( xInfo->hasPropertyByName( PROPERTY_REALNAME ) ) + sNamePropertyName = PROPERTY_REALNAME; + OSL_VERIFY( _rxTemplateColumn->getPropertyValue( sNamePropertyName ) >>= sTableColumnName ); + + if ( !xTableCols->hasByName( sTableColumnName ) ) + return; + + Reference< XPropertySet > xTableColumn( xTableCols->getByName( sTableColumnName ), UNO_QUERY_THROW ); + impl_initializeColumnSettings_nothrow( xTableColumn, _rxRowSetColumn ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } +} + +// ----------------------------------------------------------------------------- +void ORowSet::execute_NoApprove_NoNewConn(ResettableMutexGuard& _rClearForNotification) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "frank.schoenheit@sun.com", "ORowSet::execute_NoApprove_NoNewConn" ); + + // now we can dispose our old connection + ::comphelper::disposeComponent(m_xOldConnection); + m_xOldConnection = NULL; + + // do we need a new statement + if ( m_bCommandFacetsDirty ) + { + m_xStatement = NULL; + m_xComposer = NULL; + + Reference< XResultSet > xResultSet( impl_prepareAndExecute_throw() ); + + // let our warnings container forget the reference to the (possibly disposed) old result set + m_aWarnings.setExternalWarnings( NULL ); + // clear all current warnings + m_aWarnings.clearWarnings(); + // let the warnings container know about the new "external warnings" + m_aWarnings.setExternalWarnings( Reference< XWarningsSupplier >( xResultSet, UNO_QUERY ) ); + + ::rtl::OUString aComposedUpdateTableName; + if ( m_aUpdateTableName.getLength() ) + aComposedUpdateTableName = composeTableName( m_xActiveConnection->getMetaData(), m_aUpdateCatalogName, m_aUpdateSchemaName, m_aUpdateTableName, sal_False, ::dbtools::eInDataManipulation ); + + { + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "frank.schoenheit@sun.com", "ORowSet::execute_NoApprove_NoNewConn: creating cache" ); + m_pCache = new ORowSetCache( xResultSet, m_xComposer.get(), m_aContext, aComposedUpdateTableName, m_bModified, m_bNew,m_aParameterValueForCache,m_aFilter ); + if ( m_nResultSetConcurrency == ResultSetConcurrency::READ_ONLY ) + { + m_nPrivileges = Privilege::SELECT; + m_pCache->m_nPrivileges = Privilege::SELECT; + } + m_pCache->setMaxRowSize(m_nFetchSize); + m_aCurrentRow = m_pCache->createIterator(this); + m_aOldRow = m_pCache->registerOldRow(); + } + + // get the locale + // ConfigManager* pConfigMgr = ConfigManager::GetConfigManager(); + Locale aLocale = SvtSysLocale().GetLocaleData().getLocale(); + // pConfigMgr->GetDirectConfigProperty(ConfigManager::LOCALE) >>= aLocale; + + // get the numberformatTypes + OSL_ENSURE(m_xActiveConnection.is(),"No ActiveConnection"); + Reference< XNumberFormatTypes> xNumberFormatTypes; + Reference< XNumberFormatsSupplier> xNumberFormat = ::dbtools::getNumberFormats(m_xActiveConnection); + if ( xNumberFormat.is() ) + m_xNumberFormatTypes.set(xNumberFormat->getNumberFormats(),UNO_QUERY); + + ::vos::ORef< ::connectivity::OSQLColumns> aColumns = new ::connectivity::OSQLColumns(); + ::std::vector< ::rtl::OUString> aNames; + ::rtl::OUString aDescription; + sal_Int32 nFormatKey = 0; + + const ::std::map<sal_Int32,sal_Int32>& rKeyColumns = m_pCache->getKeyColumns(); + if(!m_xColumns.is()) + { + RTL_LOGFILE_CONTEXT_AUTHOR( aColumnCreateLog, "dbaccess", "frank.schoenheit@sun.com", "ORowSet::execute_NoApprove_NoNewConn::creating columns" ); + // use the meta data + Reference<XResultSetMetaDataSupplier> xMetaSup(m_xStatement,UNO_QUERY); + try + { + Reference<XResultSetMetaData> xMetaData = xMetaSup->getMetaData(); + if ( xMetaData.is() ) + { + sal_Int32 nCount = xMetaData->getColumnCount(); + m_aDataColumns.reserve(nCount+1); + aColumns->get().reserve(nCount+1); + DECLARE_STL_USTRINGACCESS_MAP(int,StringMap); + StringMap aColumnMap; + for (sal_Int32 i = 0 ; i < nCount; ++i) + { + // retrieve the name of the column + ::rtl::OUString sName = xMetaData->getColumnName(i + 1); + // check for duplicate entries + if(aColumnMap.find(sName) != aColumnMap.end()) + { + ::rtl::OUString sAlias(sName); + sal_Int32 searchIndex=1; + while(aColumnMap.find(sAlias) != aColumnMap.end()) + { + (sAlias = sName) += ::rtl::OUString::valueOf(searchIndex++); + } + sName = sAlias; + } + ORowSetDataColumn* pColumn = new ORowSetDataColumn( getMetaData(), + this, + this, + i+1, + m_xActiveConnection->getMetaData(), + aDescription, + ::rtl::OUString(), + m_aCurrentRow); + aColumnMap.insert(StringMap::value_type(sName,0)); + aColumns->get().push_back(pColumn); + pColumn->setName(sName); + aNames.push_back(sName); + m_aDataColumns.push_back(pColumn); + + pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_ISREADONLY,makeAny(rKeyColumns.find(i+1) != rKeyColumns.end())); + + try + { + nFormatKey = 0; + if(m_xNumberFormatTypes.is()) + nFormatKey = ::dbtools::getDefaultNumberFormat(pColumn,m_xNumberFormatTypes,aLocale); + + + pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_NUMBERFORMAT,makeAny(nFormatKey)); + pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_RELATIVEPOSITION,makeAny(sal_Int32(i+1))); + pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_WIDTH,makeAny(sal_Int32(227))); + pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_ALIGN,makeAny((sal_Int32)0)); + pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_HIDDEN,::cppu::bool2any(sal_False)); + } + catch(Exception&) + { + } + } + } + } + catch (SQLException&) + { + } + } + else + { + // create the rowset columns + Reference< XResultSetMetaData > xMeta( getMetaData(), UNO_QUERY_THROW ); + sal_Int32 nCount = xMeta->getColumnCount(); + m_aDataColumns.reserve(nCount+1); + aColumns->get().reserve(nCount+1); + ::std::set< Reference< XPropertySet > > aAllColumns; + + for(sal_Int32 i=1; i <= nCount ;++i) + { + ::rtl::OUString sName = xMeta->getColumnName(i); + ::rtl::OUString sColumnLabel = xMeta->getColumnLabel(i); + + // retrieve the column number |i| + Reference<XPropertySet> xColumn; + { + sal_Bool bReFetchName = sal_False; + if (m_xColumns->hasByName(sColumnLabel)) + m_xColumns->getByName(sColumnLabel) >>= xColumn; + if (!xColumn.is() && m_xColumns->hasByName(sName)) + m_xColumns->getByName(sName) >>= xColumn; + + // check if column already in the list we need another + if ( aAllColumns.find( xColumn ) != aAllColumns.end() ) + { + xColumn = NULL; + bReFetchName = sal_True; + sColumnLabel = ::rtl::OUString(); + } + 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()) + { + xIndexAccess->getByIndex(i-1) >>= xColumn; + } + else + { + Sequence< ::rtl::OUString> aSeq = m_xColumns->getElementNames(); + if( i <= aSeq.getLength()) + { + m_xColumns->getByName(aSeq.getConstArray()[i-1]) >>= xColumn; + } + } + } + if(bReFetchName && xColumn.is()) + xColumn->getPropertyValue(PROPERTY_NAME) >>= sName; + aAllColumns.insert( xColumn ); + } + + // create a RowSetDataColumn + { + Reference<XPropertySetInfo> xInfo = xColumn.is() ? xColumn->getPropertySetInfo() : Reference<XPropertySetInfo>(); + if(xInfo.is() && xInfo->hasPropertyByName(PROPERTY_DESCRIPTION)) + aDescription = comphelper::getString(xColumn->getPropertyValue(PROPERTY_DESCRIPTION)); + + ::rtl::OUString sParseLabel; + if ( xColumn.is() ) + { + xColumn->getPropertyValue(PROPERTY_LABEL) >>= sParseLabel; + } + ORowSetDataColumn* pColumn = new ORowSetDataColumn( getMetaData(), + this, + this, + i, + m_xActiveConnection->getMetaData(), + aDescription, + sParseLabel, + m_aCurrentRow); + aColumns->get().push_back(pColumn); + + pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_ISREADONLY,makeAny(rKeyColumns.find(i) != rKeyColumns.end())); + + if(!sColumnLabel.getLength()) + { + if(xColumn.is()) + xColumn->getPropertyValue(PROPERTY_NAME) >>= sColumnLabel; + else + sColumnLabel = DBACORE_RESSTRING( RID_STR_EXPRESSION1 ); + } + pColumn->setName(sColumnLabel); + aNames.push_back(sColumnLabel); + m_aDataColumns.push_back(pColumn); + + if ( xColumn.is() ) + impl_initializeColumnSettings_nothrow( xColumn, pColumn ); + } + } + } + // now create the columns we need + if(m_pColumns) + m_pColumns->assign(aColumns,aNames); + else + { + Reference<XDatabaseMetaData> xMeta = m_xActiveConnection->getMetaData(); + m_pColumns = new ORowSetDataColumns(xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers(), + aColumns,*this,m_aColumnsMutex,aNames); + } + } + checkCache(); + // notify the rowset listeners + notifyAllListeners(_rClearForNotification); +} +// ------------------------------------------------------------------------- +// XRowSetApproveBroadcaster +void SAL_CALL ORowSet::addRowSetApproveListener( const Reference< XRowSetApproveListener >& listener ) throw(RuntimeException) +{ + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( m_aColumnsMutex ); + + m_aApproveListeners.addInterface(listener); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::removeRowSetApproveListener( const Reference< XRowSetApproveListener >& listener ) throw(RuntimeException) +{ + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( m_aColumnsMutex ); + + m_aApproveListeners.removeInterface(listener); +} +// XRowsChangeBroadcaster +void SAL_CALL ORowSet::addRowsChangeListener( const Reference< XRowsChangeListener >& listener ) throw(RuntimeException) +{ + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( m_aColumnsMutex ); + + m_aRowsChangeListener.addInterface(listener); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::removeRowsChangeListener( const Reference< XRowsChangeListener >& listener ) throw(RuntimeException) +{ + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( m_aColumnsMutex ); + + m_aRowsChangeListener.removeInterface(listener); +} +// ------------------------------------------------------------------------- + +// XResultSetAccess +Reference< XResultSet > SAL_CALL ORowSet::createResultSet( ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aColumnsMutex ); + + if(m_xStatement.is()) + { + ORowSetClone* pClone = new ORowSetClone( m_aContext, *this, m_pMutex ); + Reference< XResultSet > xRet(pClone); + m_aClones.push_back(WeakReferenceHelper(xRet)); + return xRet; + } + return Reference< XResultSet >(); +} +// ------------------------------------------------------------------------- + +// ::com::sun::star::util::XCancellable +void SAL_CALL ORowSet::cancel( ) throw(RuntimeException) +{ + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); +} +// ------------------------------------------------------------------------- + +// ::com::sun::star::sdbcx::XDeleteRows +Sequence< sal_Int32 > SAL_CALL ORowSet::deleteRows( const Sequence< Any >& rows ) throw(SQLException, RuntimeException) +{ + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + + if(!m_pCache || m_nResultSetConcurrency == ResultSetConcurrency::READ_ONLY) + throwFunctionSequenceException(*this); + + ::osl::ResettableMutexGuard aGuard( *m_pMutex ); + + Sequence<Any> aChangedBookmarks; + RowsChangeEvent aEvt(*this,RowChangeAction::DELETE,rows.getLength(),aChangedBookmarks); + // notify the rowset listeners + notifyAllListenersRowBeforeChange(aGuard,aEvt); + + Sequence< sal_Int32 > aResults( rows.getLength() ); + const Any* row = rows.getConstArray(); + const Any* rowEnd = rows.getConstArray() + rows.getLength(); + sal_Int32* result = aResults.getArray(); + for ( ; row != rowEnd; ++row, ++result ) + { + *result = 0; + if ( !m_pCache->moveToBookmark( *row ) ) + continue; + sal_Int32 nDeletePosition = m_pCache->getRow(); + + // first notify the clones so that they can save their position + notifyRowSetAndClonesRowDelete( *row ); + + // now delete the row + if ( !m_pCache->deleteRow() ) + continue; + *result = 1; + // now notify that we have deleted + notifyRowSetAndClonesRowDeleted( *row, nDeletePosition ); + } + aEvt.Rows = aResults.getLength(); + + // we have to check if we stand on the insert row and if so we have to reset it + ORowSetNotifier aNotifier( this ); + // this will call cancelRowModification on the cache if necessary + // notification order + // - rowChanged + notifyAllListenersRowChanged(aGuard,aEvt); + + // - IsModified + // - IsNew + aNotifier.fire(); + + // - RowCount/IsRowCountFinal + fireRowcount(); + + return aResults; +} +// ----------------------------------------------------------------------------- +void ORowSet::notifyRowSetAndClonesRowDelete( const Any& _rBookmark ) +{ + // notify ourself + onDeleteRow( _rBookmark ); + // notify the clones + connectivity::OWeakRefArray::iterator aEnd = m_aClones.end(); + for (connectivity::OWeakRefArray::iterator i = m_aClones.begin(); aEnd != i; i++) + { + Reference< XUnoTunnel > xTunnel(i->get(),UNO_QUERY); + if(xTunnel.is()) + { + ORowSetClone* pClone = reinterpret_cast<ORowSetClone*>(xTunnel->getSomething(ORowSetClone::getUnoTunnelImplementationId())); + if(pClone) + pClone->onDeleteRow( _rBookmark ); + } + } +} +//------------------------------------------------------------------------------ +void ORowSet::notifyRowSetAndClonesRowDeleted( const Any& _rBookmark, sal_Int32 _nPos ) +{ + // notify ourself + onDeletedRow( _rBookmark, _nPos ); + // notify the clones + connectivity::OWeakRefArray::iterator aEnd = m_aClones.end(); + for (connectivity::OWeakRefArray::iterator i = m_aClones.begin(); aEnd != i; i++) + { + Reference< XUnoTunnel > xTunnel(i->get(),UNO_QUERY); + if(xTunnel.is()) + { + ORowSetClone* pClone = reinterpret_cast<ORowSetClone*>(xTunnel->getSomething(ORowSetClone::getUnoTunnelImplementationId())); + if(pClone) + pClone->onDeletedRow( _rBookmark, _nPos ); + } + } +} +//------------------------------------------------------------------------------ +Reference< XConnection > ORowSet::calcConnection(const Reference< XInteractionHandler >& _rxHandler) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + if (!m_xActiveConnection.is()) + { + Reference< XConnection > xNewConn; + if ( m_aDataSourceName.getLength() ) + { + Reference< XNameAccess > xDatabaseContext( + m_aContext.createComponent( (::rtl::OUString)SERVICE_SDB_DATABASECONTEXT ), + UNO_QUERY_THROW ); + try + { + Reference< XDataSource > xDataSource( xDatabaseContext->getByName( m_aDataSourceName ), UNO_QUERY_THROW ); + + // try connecting with the interaction handler + Reference< XCompletedConnection > xComplConn( xDataSource, UNO_QUERY ); + if ( _rxHandler.is() && xComplConn.is() ) + { + xNewConn = xComplConn->connectWithCompletion( _rxHandler ); + } + else + { + xNewConn = xDataSource->getConnection( m_aUser, m_aPassword ); + } + } + catch ( const SQLException& e ) + { + throw; + } + catch ( const Exception& e ) + { + Any aError = ::cppu::getCaughtException(); + ::rtl::OUString sMessage = ResourceManager::loadString( RID_NO_SUCH_DATA_SOURCE, + "$name$", m_aDataSourceName, "$error$", extractExceptionMessage( m_aContext, aError ) ); + ::dbtools::throwGenericSQLException( sMessage, *this ); + } + } + setActiveConnection(xNewConn); + m_bOwnConnection = sal_True; + } + return m_xActiveConnection; +} +//------------------------------------------------------------------------------ +Reference< XNameAccess > ORowSet::impl_getTables_throw() +{ + Reference< XNameAccess > xTables; + + Reference< XTablesSupplier > xTablesAccess( m_xActiveConnection, UNO_QUERY ); + if ( xTablesAccess.is() ) + { + xTables.set( xTablesAccess->getTables(), UNO_QUERY_THROW ); + } + else if ( m_pTables ) + { + xTables = m_pTables; + } + else + { + if ( !m_xActiveConnection.is() ) + throw SQLException(DBA_RES(RID_STR_CONNECTION_INVALID),*this,SQLSTATE_GENERAL,1000,Any() ); + + sal_Bool bCase = sal_True; + try + { + Reference<XDatabaseMetaData> xMeta = m_xActiveConnection->getMetaData(); + bCase = xMeta.is() && xMeta->storesMixedCaseQuotedIdentifiers(); + } + catch(SQLException&) + { + DBG_UNHANDLED_EXCEPTION(); + } + + m_pTables = new OTableContainer(*this,m_aMutex,m_xActiveConnection,bCase,NULL,NULL,NULL,m_nInAppend); + xTables = m_pTables; + Sequence< ::rtl::OUString> aTableFilter(1); + aTableFilter[0] = ::rtl::OUString::createFromAscii("%"); + m_pTables->construct(aTableFilter,Sequence< ::rtl::OUString>()); + } + + return xTables; +} + +//------------------------------------------------------------------------------ +void ORowSet::impl_resetTables_nothrow() +{ + if ( !m_pTables ) + return; + + try + { + m_pTables->dispose(); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + DELETEZ( m_pTables ); +} + +//------------------------------------------------------------------------------ +sal_Bool ORowSet::impl_initComposer_throw( ::rtl::OUString& _out_rCommandToExecute ) +{ + sal_Bool bUseEscapeProcessing = impl_buildActiveCommand_throw( ); + _out_rCommandToExecute = m_aActiveCommand; + if ( !bUseEscapeProcessing ) + return bUseEscapeProcessing; + + Reference< XMultiServiceFactory > xFactory( m_xActiveConnection, UNO_QUERY ); + if ( xFactory.is() ) + { + try + { + ::comphelper::disposeComponent( m_xComposer ); + m_xComposer.set( xFactory->createInstance( SERVICE_NAME_SINGLESELECTQUERYCOMPOSER ), UNO_QUERY_THROW ); + } + catch (const Exception& ) { m_xComposer = NULL; } + } + if ( !m_xComposer.is() ) + m_xComposer = new OSingleSelectQueryComposer( impl_getTables_throw(), m_xActiveConnection, m_aContext ); + + m_xComposer->setCommand( m_aCommand,m_nCommandType ); + m_aActiveCommand = m_xComposer->getQuery(); + + m_xComposer->setFilter( m_bApplyFilter ? m_aFilter : ::rtl::OUString() ); + m_xComposer->setHavingClause( m_bApplyFilter ? m_aHavingClause : ::rtl::OUString() ); + + if ( m_bIgnoreResult ) + { // append a "0=1" filter + // don't simply overwrite an existent filter, this would lead to problems if this existent + // filter contains paramters (since a keyset may add parameters itself) + // 2003-12-12 - #23418# - fs@openoffice.org + m_xComposer->setElementaryQuery( m_xComposer->getQuery( ) ); + m_xComposer->setFilter( ::rtl::OUString::createFromAscii( "0 = 1" ) ); + } + + m_xComposer->setOrder( m_aOrder ); + m_xComposer->setGroup( m_aGroupBy ); + + if ( !m_xColumns.is() ) + { + Reference< XColumnsSupplier > xCols( m_xComposer, UNO_QUERY_THROW ); + m_xColumns = xCols->getColumns(); + } + + impl_initParametersContainer_nothrow(); + + _out_rCommandToExecute = m_xComposer->getQueryWithSubstitution(); + + return bUseEscapeProcessing; +} + +//------------------------------------------------------------------------------ +sal_Bool ORowSet::impl_buildActiveCommand_throw() +{ + // create the sql command + // from a table name or get the command out of a query (not a view) + // the last use the command as it is + sal_Bool bDoEscapeProcessing = m_bUseEscapeProcessing; + + m_aActiveCommand = ::rtl::OUString(); + ::rtl::OUString sCommand; + + if ( !m_aCommand.getLength() ) + return bDoEscapeProcessing; + + switch (m_nCommandType) + { + case CommandType::TABLE: + { + impl_resetTables_nothrow(); + if ( bDoEscapeProcessing ) + { + Reference< XNameAccess > xTables( impl_getTables_throw() ); + if ( xTables->hasByName(m_aCommand) ) + { +/* + Reference< XPropertySet > xTable; + try + { + xTables->getByName( m_aCommand ) >>= xTable; + } + catch(const WrappedTargetException& e) + { + SQLException e2; + if ( e.TargetException >>= e2 ) + throw e2; + } + catch(Exception&) + { + DBG_UNHANDLED_EXCEPTION(); + } + + Reference<XColumnsSupplier> xSup(xTable,UNO_QUERY); + if ( xSup.is() ) + m_xColumns = xSup->getColumns(); + + sCommand = rtl::OUString::createFromAscii("SELECT * FROM "); + ::rtl::OUString sCatalog, sSchema, sTable; + ::dbtools::qualifiedNameComponents( m_xActiveConnection->getMetaData(), m_aCommand, sCatalog, sSchema, sTable, ::dbtools::eInDataManipulation ); + sCommand += ::dbtools::composeTableNameForSelect( m_xActiveConnection, sCatalog, sSchema, sTable ); +*/ + } + else + { + String sMessage( DBACORE_RESSTRING( RID_STR_TABLE_DOES_NOT_EXIST ) ); + sMessage.SearchAndReplaceAscii( "$table$", m_aCommand ); + throwGenericSQLException(sMessage,*this); + } + } + else + { + sCommand = rtl::OUString::createFromAscii("SELECT * FROM "); + ::rtl::OUString sCatalog, sSchema, sTable; + ::dbtools::qualifiedNameComponents( m_xActiveConnection->getMetaData(), m_aCommand, sCatalog, sSchema, sTable, ::dbtools::eInDataManipulation ); + sCommand += ::dbtools::composeTableNameForSelect( m_xActiveConnection, sCatalog, sSchema, sTable ); + } + } + break; + + case CommandType::QUERY: + { + Reference< XQueriesSupplier > xQueriesAccess(m_xActiveConnection, UNO_QUERY); + if (xQueriesAccess.is()) + { + Reference< ::com::sun::star::container::XNameAccess > xQueries(xQueriesAccess->getQueries()); + if (xQueries->hasByName(m_aCommand)) + { + Reference< XPropertySet > xQuery(xQueries->getByName(m_aCommand),UNO_QUERY); + OSL_ENSURE(xQuery.is(),"ORowSet::impl_buildActiveCommand_throw: Query is NULL!"); + if ( xQuery.is() ) + { + 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; + xQuery->getPropertyValue(PROPERTY_UPDATE_SCHEMANAME) >>= aSchema; + xQuery->getPropertyValue(PROPERTY_UPDATE_TABLENAME) >>= aTable; + if(aTable.getLength()) + m_aUpdateTableName = composeTableName( m_xActiveConnection->getMetaData(), aCatalog, aSchema, aTable, sal_False, ::dbtools::eInDataManipulation ); +/* + Reference<XColumnsSupplier> xSup(xQuery,UNO_QUERY); + if(xSup.is()) + m_xColumns = xSup->getColumns(); +*/ + } + } + else + { + String sMessage( DBACORE_RESSTRING( RID_STR_QUERY_DOES_NOT_EXIST ) ); + sMessage.SearchAndReplaceAscii( "$table$", m_aCommand ); + throwGenericSQLException(sMessage,*this); + } + } + else + throw SQLException(DBA_RES(RID_STR_NO_XQUERIESSUPPLIER),*this,::rtl::OUString(),0,Any()); + } + break; + + default: + sCommand = m_aCommand; + break; + } + + m_aActiveCommand = sCommand; + + if ( !m_aActiveCommand.getLength() && !bDoEscapeProcessing ) + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_NO_SQL_COMMAND ), SQL_FUNCTION_SEQUENCE_ERROR, *this ); + + return bDoEscapeProcessing; +} + +//------------------------------------------------------------------------------ +void ORowSet::impl_initParametersContainer_nothrow() +{ + OSL_PRECOND( !m_pParameters.is(), "ORowSet::impl_initParametersContainer_nothrow: already initialized the parameters!" ); + + m_pParameters = new param::ParameterWrapperContainer( m_xComposer.get() ); + // copy the premature parameters into the final ones + size_t nParamCount( ::std::min( m_pParameters->size(), m_aPrematureParamValues.get().size() ) ); + for ( size_t i=0; i<nParamCount; ++i ) + { + (*m_pParameters)[i] = m_aPrematureParamValues.get()[i]; + } +} + +//------------------------------------------------------------------------------ +void ORowSet::impl_disposeParametersContainer_nothrow() +{ + if ( !m_pParameters.is() ) + return; + + // copy the actual values to our "premature" ones, to preserve them for later use + size_t nParamCount( m_pParameters->size() ); + m_aPrematureParamValues.get().resize( nParamCount ); + for ( size_t i=0; i<nParamCount; ++i ) + { + m_aPrematureParamValues.get()[i] = (*m_pParameters)[i]; + } + + m_pParameters->dispose(); + m_pParameters = NULL; +} + +// ----------------------------------------------------------------------------- +ORowSetValue& ORowSet::getParameterStorage(sal_Int32 parameterIndex) +{ + ::connectivity::checkDisposed( ORowSet_BASE1::rBHelper.bDisposed ); + if ( parameterIndex < 1 ) + throwInvalidIndexException( *this ); + + if ( m_aParametersSet.size() < (size_t)parameterIndex ) + m_aParametersSet.resize( parameterIndex ,false); + m_aParametersSet[parameterIndex - 1] = true; + + if ( m_aParametersSet.size() < (size_t)parameterIndex ) + m_aParametersSet.resize( parameterIndex ,false); + m_aParametersSet[parameterIndex - 1] = true; + + if ( m_pParameters.is() ) + { + if ( m_bCommandFacetsDirty ) + // need to rebuild the parameters, since some property which contributes to the + // complete command, and thus the parameters, changed + impl_disposeParametersContainer_nothrow(); + if ( m_pParameters.is() ) + { + if ( (size_t)parameterIndex > m_pParameters->size() ) + throwInvalidIndexException( *this ); + return (*m_pParameters)[ parameterIndex - 1 ]; + } + } + + if ( m_aPrematureParamValues.get().size() < (size_t)parameterIndex ) + m_aPrematureParamValues.get().resize( parameterIndex ); + return m_aPrematureParamValues.get()[ parameterIndex - 1 ]; +} +// ------------------------------------------------------------------------- +// XParameters +void SAL_CALL ORowSet::setNull( sal_Int32 parameterIndex, sal_Int32 /*sqlType*/ ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aColumnsMutex ); + + getParameterStorage( parameterIndex ).setNull(); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::setObjectNull( sal_Int32 parameterIndex, sal_Int32 sqlType, const ::rtl::OUString& /*typeName*/ ) throw(SQLException, RuntimeException) +{ + setNull( parameterIndex, sqlType ); +} +// ----------------------------------------------------------------------------- +void ORowSet::setParameter(sal_Int32 parameterIndex, const ORowSetValue& x) +{ + ::osl::MutexGuard aGuard( m_aColumnsMutex ); + + getParameterStorage( parameterIndex ) = x; +} + +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::setBoolean( sal_Int32 parameterIndex, sal_Bool x ) throw(SQLException, RuntimeException) +{ + setParameter(parameterIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::setByte( sal_Int32 parameterIndex, sal_Int8 x ) throw(SQLException, RuntimeException) +{ + setParameter(parameterIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::setShort( sal_Int32 parameterIndex, sal_Int16 x ) throw(SQLException, RuntimeException) +{ + setParameter(parameterIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::setInt( sal_Int32 parameterIndex, sal_Int32 x ) throw(SQLException, RuntimeException) +{ + setParameter(parameterIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::setLong( sal_Int32 parameterIndex, sal_Int64 x ) throw(SQLException, RuntimeException) +{ + setParameter(parameterIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::setFloat( sal_Int32 parameterIndex, float x ) throw(SQLException, RuntimeException) +{ + setParameter(parameterIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::setDouble( sal_Int32 parameterIndex, double x ) throw(SQLException, RuntimeException) +{ + setParameter(parameterIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::setString( sal_Int32 parameterIndex, const ::rtl::OUString& x ) throw(SQLException, RuntimeException) +{ + setParameter(parameterIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::setBytes( sal_Int32 parameterIndex, const Sequence< sal_Int8 >& x ) throw(SQLException, RuntimeException) +{ + setParameter(parameterIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::setDate( sal_Int32 parameterIndex, const ::com::sun::star::util::Date& x ) throw(SQLException, RuntimeException) +{ + setParameter(parameterIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::setTime( sal_Int32 parameterIndex, const ::com::sun::star::util::Time& x ) throw(SQLException, RuntimeException) +{ + setParameter(parameterIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::setTimestamp( sal_Int32 parameterIndex, const ::com::sun::star::util::DateTime& x ) throw(SQLException, RuntimeException) +{ + setParameter(parameterIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::setBinaryStream( sal_Int32 parameterIndex, const Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aColumnsMutex ); + ORowSetValue& rParamValue( getParameterStorage( parameterIndex ) ); + + try + { + Sequence <sal_Int8> aData; + x->readBytes(aData, length); + rParamValue = aData; + x->closeInput(); + } + catch( Exception& ) + { + throw SQLException(); + } +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::setCharacterStream( sal_Int32 parameterIndex, const Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aColumnsMutex ); + ORowSetValue& rParamValue( getParameterStorage( parameterIndex ) ); + try + { + Sequence <sal_Int8> aData; + rtl::OUString aDataStr; + // the data is given as character data and the length defines the character length + sal_Int32 nSize = x->readBytes(aData, length * sizeof(sal_Unicode)); + if (nSize / sizeof(sal_Unicode)) + aDataStr = rtl::OUString((sal_Unicode*)aData.getConstArray(), nSize / sizeof(sal_Unicode)); + rParamValue = aDataStr; + rParamValue.setTypeKind( DataType::LONGVARCHAR ); + x->closeInput(); + } + catch( Exception& ) + { + throw SQLException(); + } +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::setObject( sal_Int32 parameterIndex, const Any& x ) throw(SQLException, RuntimeException) +{ + if ( !::dbtools::implSetObject( this, parameterIndex, x ) ) + { // there is no other setXXX call which can handle the value in x + throw SQLException(); + } +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::setObjectWithInfo( sal_Int32 parameterIndex, const Any& x, sal_Int32 targetSqlType, sal_Int32 /*scale*/ ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aColumnsMutex ); + ORowSetValue& rParamValue( getParameterStorage( parameterIndex ) ); + setObject( parameterIndex, x ); + rParamValue.setTypeKind( targetSqlType ); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::setRef( sal_Int32 /*parameterIndex*/, const Reference< XRef >& /*x*/ ) throw(SQLException, RuntimeException) +{ + ::dbtools::throwFeatureNotImplementedException( "XParameters::setRef", *this ); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::setBlob( sal_Int32 /*parameterIndex*/, const Reference< XBlob >& /*x*/ ) throw(SQLException, RuntimeException) +{ + ::dbtools::throwFeatureNotImplementedException( "XParameters::setBlob", *this ); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::setClob( sal_Int32 /*parameterIndex*/, const Reference< XClob >& /*x*/ ) throw(SQLException, RuntimeException) +{ + ::dbtools::throwFeatureNotImplementedException( "XParameters::setClob", *this ); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::setArray( sal_Int32 /*parameterIndex*/, const Reference< XArray >& /*x*/ ) throw(SQLException, RuntimeException) +{ + ::dbtools::throwFeatureNotImplementedException( "XParameters::setArray", *this ); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::clearParameters( ) throw(SQLException, RuntimeException) +{ + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( m_aColumnsMutex ); + + size_t nParamCount( m_pParameters.is() ? m_pParameters->size() : m_aPrematureParamValues.get().size() ); + for ( size_t i=1; i<=nParamCount; ++i ) + getParameterStorage( (sal_Int32)i ).setNull(); + m_aParametersSet.clear(); +} + +// ------------------------------------------------------------------------- +Any SAL_CALL ORowSet::getWarnings( ) throw (SQLException, RuntimeException) +{ + return m_aWarnings.getWarnings(); +} + +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::clearWarnings( ) throw (SQLException, RuntimeException) +{ + m_aWarnings.clearWarnings(); +} +// ----------------------------------------------------------------------------- +void ORowSet::doCancelModification( ) +{ + //OSL_ENSURE( isModification(), "ORowSet::doCancelModification: invalid call (no cache!)!" ); + if ( isModification() ) + { + // read-only flag restored + impl_restoreDataColumnsWriteable_throw(); + m_pCache->cancelRowModification(); + } + m_bModified = sal_False; +} + +// ----------------------------------------------------------------------------- +sal_Bool ORowSet::isModification( ) +{ + return isNew(); +} + +// ----------------------------------------------------------------------------- +sal_Bool ORowSet::isModified( ) +{ + return m_bModified; +} + +// ----------------------------------------------------------------------------- +sal_Bool ORowSet::isNew( ) +{ + return m_bNew; +} + +// ----------------------------------------------------------------------------- +void ORowSet::checkUpdateIterator() +{ + if(!m_bModified && !m_bNew) + { + m_pCache->setUpdateIterator(m_aCurrentRow); + m_aCurrentRow = m_pCache->m_aInsertRow; + m_bModified = sal_True; + } // if(!m_bModified && !m_bNew) + else if ( m_bNew ) // here we are modifing a value + m_bModified = sal_True; +} +// ----------------------------------------------------------------------------- +void ORowSet::checkUpdateConditions(sal_Int32 columnIndex) +{ + checkCache(); + if ( m_nResultSetConcurrency == ResultSetConcurrency::READ_ONLY) + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_RESULT_IS_READONLY ), SQL_GENERAL_ERROR, *this ); + + if ( rowDeleted() ) + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_ROW_ALREADY_DELETED ), SQL_INVALID_CURSOR_POSITION, *this ); + + if ( m_aCurrentRow.isNull() ) + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_INVALID_CURSOR_STATE ), SQL_INVALID_CURSOR_STATE, *this ); + + if ( columnIndex <= 0 || sal_Int32((*m_aCurrentRow)->get().size()) <= columnIndex ) + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_INVALID_INDEX ), SQL_INVALID_DESCRIPTOR_INDEX, *this ); +} +// ----------------------------------------------------------------------------- +void SAL_CALL ORowSet::refreshRow( ) throw(SQLException, RuntimeException) +{ + + ORowSetNotifier aNotifier( this ); + // this will call cancelRowModification on the cache if necessary + + // notification order: + if ( m_bModified && m_pCache ) + // - column values + implCancelRowUpdates( sal_False ); // do _not_ notify the IsModify - will do this ourself below + + ORowSetBase::refreshRow(); + + // - IsModified + // - IsNew + aNotifier.fire( ); +} +// ----------------------------------------------------------------------------- +void ORowSet::impl_rebuild_throw(::osl::ResettableMutexGuard& _rGuard) +{ + Reference< XResultSet > xResultSet( m_xStatement->executeQuery() ); + m_aWarnings.setExternalWarnings( Reference< XWarningsSupplier >( xResultSet, UNO_QUERY ) ); + m_pCache->reset(xResultSet); + notifyAllListeners(_rGuard); +} +// *********************************************************** +// ORowSetClone +// *********************************************************** +DBG_NAME(ORowSetClone); +//-------------------------------------------------------------------------- +ORowSetClone::ORowSetClone( const ::comphelper::ComponentContext& _rContext, ORowSet& rParent, ::osl::Mutex* _pMutex ) + :OSubComponent(m_aMutex, rParent) + ,ORowSetBase( _rContext, OComponentHelper::rBHelper, _pMutex ) + ,m_pParent(&rParent) + ,m_nFetchDirection(rParent.m_nFetchDirection) + ,m_nFetchSize(rParent.m_nFetchSize) + ,m_bIsBookmarable(sal_True) +{ + DBG_CTOR(ORowSetClone, NULL); + + m_nResultSetType = rParent.m_nResultSetType; + m_nResultSetConcurrency = ResultSetConcurrency::READ_ONLY; + m_pMySelf = this; + m_bClone = sal_True; + m_bBeforeFirst = rParent.m_bBeforeFirst; + m_bAfterLast = rParent.m_bAfterLast; + m_pCache = rParent.m_pCache; + m_aBookmark = rParent.m_aBookmark; + m_aCurrentRow = m_pCache->createIterator(this); + m_xNumberFormatTypes = rParent.m_xNumberFormatTypes; + + m_aOldRow = m_pCache->registerOldRow(); + + ::vos::ORef< ::connectivity::OSQLColumns> aColumns = new ::connectivity::OSQLColumns(); + ::std::vector< ::rtl::OUString> aNames; + + ::rtl::OUString aDescription; + // ConfigManager* pConfigMgr = ConfigManager::GetConfigManager(); + // Locale aLocale; + // pConfigMgr->GetDirectConfigProperty(ConfigManager::LOCALE) >>= aLocale; + Locale aLocale = SvtSysLocale().GetLocaleData().getLocale(); + + if ( rParent.m_pColumns ) + { + Sequence< ::rtl::OUString> aSeq = rParent.m_pColumns->getElementNames(); + const ::rtl::OUString* pIter = aSeq.getConstArray(); + const ::rtl::OUString* pEnd = pIter + aSeq.getLength(); + aColumns->get().reserve(aSeq.getLength()+1); + for(sal_Int32 i=1;pIter != pEnd ;++pIter,++i) + { + Reference<XPropertySet> xColumn; + rParent.m_pColumns->getByName(*pIter) >>= xColumn; + if(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_DESCRIPTION)) + aDescription = comphelper::getString(xColumn->getPropertyValue(PROPERTY_DESCRIPTION)); + + ::rtl::OUString sParseLabel; + xColumn->getPropertyValue(PROPERTY_LABEL) >>= sParseLabel; + ORowSetColumn* pColumn = new ORowSetColumn( rParent.getMetaData(), + this, + i, + rParent.m_xActiveConnection->getMetaData(), + aDescription, + sParseLabel, + m_aCurrentRow); + aColumns->get().push_back(pColumn); + pColumn->setName(*pIter); + aNames.push_back(*pIter); + m_aDataColumns.push_back(pColumn); + + pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_ALIGN,xColumn->getPropertyValue(PROPERTY_ALIGN)); + sal_Int32 nFormatKey = 0; + xColumn->getPropertyValue(PROPERTY_NUMBERFORMAT) >>= nFormatKey; + if(!nFormatKey && xColumn.is() && m_xNumberFormatTypes.is()) + nFormatKey = ::dbtools::getDefaultNumberFormat(xColumn,m_xNumberFormatTypes,aLocale); + pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_NUMBERFORMAT,makeAny(nFormatKey)); + pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_RELATIVEPOSITION,xColumn->getPropertyValue(PROPERTY_RELATIVEPOSITION)); + pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_WIDTH,xColumn->getPropertyValue(PROPERTY_WIDTH)); + pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_HIDDEN,xColumn->getPropertyValue(PROPERTY_HIDDEN)); + pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_CONTROLMODEL,xColumn->getPropertyValue(PROPERTY_CONTROLMODEL)); + pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_HELPTEXT,xColumn->getPropertyValue(PROPERTY_HELPTEXT)); + pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_CONTROLDEFAULT,xColumn->getPropertyValue(PROPERTY_CONTROLDEFAULT)); + + } // for(sal_Int32 i=1;pIter != pEnd ;++pIter,++i) + } + Reference<XDatabaseMetaData> xMeta = rParent.m_xActiveConnection->getMetaData(); + m_pColumns = new ORowSetDataColumns(xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers(), + aColumns,*this,m_aMutex,aNames); + + sal_Int32 nRT = PropertyAttribute::READONLY | PropertyAttribute::TRANSIENT; + + // sdb.RowSet Properties + // registerProperty(PROPERTY_CURSORNAME, PROPERTY_ID_CURSORNAME, PropertyAttribute::READONLY, &m_aDataSourceName, ::getCppuType(reinterpret_cast< ::rtl::OUString*>(NULL))); + registerMayBeVoidProperty(PROPERTY_ACTIVE_CONNECTION,PROPERTY_ID_ACTIVE_CONNECTION, PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY, &rParent.m_aActiveConnection, ::getCppuType(reinterpret_cast< Reference< XConnection >* >(NULL))); + registerProperty(PROPERTY_RESULTSETCONCURRENCY, PROPERTY_ID_RESULTSETCONCURRENCY, PropertyAttribute::READONLY, &m_nResultSetConcurrency,::getCppuType(reinterpret_cast< sal_Int32*>(NULL))); + registerProperty(PROPERTY_RESULTSETTYPE, PROPERTY_ID_RESULTSETTYPE, PropertyAttribute::READONLY, &m_nResultSetType, ::getCppuType(reinterpret_cast< sal_Int32*>(NULL))); + registerProperty(PROPERTY_FETCHDIRECTION, PROPERTY_ID_FETCHDIRECTION, PropertyAttribute::TRANSIENT, &m_nFetchDirection, ::getCppuType(reinterpret_cast< sal_Int32*>(NULL))); + registerProperty(PROPERTY_FETCHSIZE, PROPERTY_ID_FETCHSIZE, PropertyAttribute::TRANSIENT, &m_nFetchSize, ::getCppuType(reinterpret_cast< sal_Int32*>(NULL))); + registerProperty(PROPERTY_ISBOOKMARKABLE, PROPERTY_ID_ISBOOKMARKABLE, nRT, &m_bIsBookmarable, ::getBooleanCppuType()); +} + +//-------------------------------------------------------------------------- +ORowSetClone::~ORowSetClone() +{ + DBG_DTOR(ORowSetClone, NULL); +} +// com::sun::star::XTypeProvider +//-------------------------------------------------------------------------- +Sequence< Type > ORowSetClone::getTypes() throw (RuntimeException) +{ + return ::comphelper::concatSequences(OSubComponent::getTypes(),ORowSetBase::getTypes()); +} +// com::sun::star::XInterface +//-------------------------------------------------------------------------- +Any ORowSetClone::queryInterface( const Type & rType ) throw (RuntimeException) +{ + Any aRet = ORowSetBase::queryInterface(rType); + if(!aRet.hasValue()) + aRet = OSubComponent::queryInterface(rType); + return aRet; +} +//------------------------------------------------------------------------------ +void ORowSetClone::acquire() throw() +{ + OSubComponent::acquire(); +} + +//------------------------------------------------------------------------------ +void ORowSetClone::release() throw() +{ + OSubComponent::release(); +} + +// XServiceInfo +//------------------------------------------------------------------------------ +rtl::OUString ORowSetClone::getImplementationName( ) throw(RuntimeException) +{ + return rtl::OUString::createFromAscii("com.sun.star.sdb.ORowSetClone"); +} + +//------------------------------------------------------------------------------ +sal_Bool ORowSetClone::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException) +{ + return ::comphelper::findValue(getSupportedServiceNames(), _rServiceName, sal_True).getLength() != 0; +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > ORowSetClone::getSupportedServiceNames( ) throw (RuntimeException) +{ + Sequence< ::rtl::OUString > aSNS( 2 ); + aSNS[0] = SERVICE_SDBC_RESULTSET; + aSNS[1] = SERVICE_SDB_RESULTSET; + return aSNS; +} + +// OComponentHelper +//------------------------------------------------------------------------------ +void ORowSetClone::disposing() +{ + MutexGuard aGuard( m_aMutex ); + ORowSetBase::disposing(); + + m_pParent = NULL; + m_pMutex = &m_aMutex; // this must be done here because someone could hold a ref to us and try to do something + OSubComponent::disposing(); +} + +// XCloseable +//------------------------------------------------------------------------------ +void ORowSetClone::close(void) throw( SQLException, RuntimeException ) +{ + { + MutexGuard aGuard( m_aMutex ); + if (OComponentHelper::rBHelper.bDisposed) + throw DisposedException(); + } + dispose(); +} +// ------------------------------------------------------------------------- + +// comphelper::OPropertyArrayUsageHelper +::cppu::IPropertyArrayHelper* ORowSetClone::createArrayHelper( ) const +{ + Sequence< Property > aProps; + describeProperties(aProps); + return new ::cppu::OPropertyArrayHelper(aProps); +} +// ------------------------------------------------------------------------- + +// cppu::OPropertySetHelper +::cppu::IPropertyArrayHelper& SAL_CALL ORowSetClone::getInfoHelper() +{ + typedef ::comphelper::OPropertyArrayUsageHelper<ORowSetClone> ORowSetClone_PROP; + return *ORowSetClone_PROP::getArrayHelper(); +} +// ------------------------------------------------------------------------- +//-------------------------------------------------------------------------- +Sequence< sal_Int8 > ORowSetClone::getUnoTunnelImplementationId() +{ + static ::cppu::OImplementationId * pId = 0; + if (! pId) + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if (! pId) + { + static ::cppu::OImplementationId aId; + pId = &aId; + } + } + return pId->getImplementationId(); +} +// ----------------------------------------------------------------------------- +// com::sun::star::XUnoTunnel +sal_Int64 SAL_CALL ORowSetClone::getSomething( const Sequence< sal_Int8 >& rId ) throw(RuntimeException) +{ + if (rId.getLength() == 16 && 0 == rtl_compareMemory(getUnoTunnelImplementationId().getConstArray(), rId.getConstArray(), 16 ) ) + return reinterpret_cast<sal_Int64>(this); + + return 0; +} +// ----------------------------------------------------------------------------- +void SAL_CALL ORowSetClone::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any& rValue) throw (Exception) +{ + if ( nHandle == PROPERTY_ID_FETCHSIZE ) + { + if ( m_pParent ) + m_pParent->setFastPropertyValue_NoBroadcast( nHandle, rValue ); + } + + OPropertyStateContainer::setFastPropertyValue_NoBroadcast(nHandle,rValue); +} + +// ----------------------------------------------------------------------------- +void ORowSetClone::doCancelModification( ) +{ + //OSL_ENSURE( sal_False, "ORowSetClone::doCancelModification: invalid call!" ); +} + +// ----------------------------------------------------------------------------- +sal_Bool ORowSetClone::isModification( ) +{ + return sal_False; +} + +// ----------------------------------------------------------------------------- +sal_Bool ORowSetClone::isModified( ) +{ + return sal_False; +} + +// ----------------------------------------------------------------------------- +sal_Bool ORowSetClone::isNew( ) +{ + return sal_False; +} + +// ------------------------------------------------------------------------- +void SAL_CALL ORowSetClone::execute( ) throw(SQLException, RuntimeException) +{ + throwFunctionNotSupportedException( "RowSetClone::XRowSet::execute", *this ); +} + +// ------------------------------------------------------------------------- +void SAL_CALL ORowSetClone::addRowSetListener( const Reference< XRowSetListener >& ) throw(RuntimeException) +{ + throwFunctionNotSupportedException( "RowSetClone::XRowSet", *this ); +} + +// ------------------------------------------------------------------------- +void SAL_CALL ORowSetClone::removeRowSetListener( const Reference< XRowSetListener >& ) throw(RuntimeException) +{ + throwFunctionNotSupportedException( "RowSetClone::XRowSet", *this ); +} + +} // dbaccess diff --git a/dbaccess/source/core/api/RowSet.hxx b/dbaccess/source/core/api/RowSet.hxx new file mode 100644 index 000000000000..8a85237cb928 --- /dev/null +++ b/dbaccess/source/core/api/RowSet.hxx @@ -0,0 +1,544 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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_CORE_API_ROWSET_HXX +#define DBACCESS_CORE_API_ROWSET_HXX + +#include "apitools.hxx" +#include "RowSetBase.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/sdbc/XPreparedStatement.hpp> +#include <com/sun/star/sdbc/XConnection.hpp> +#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp> +#include <com/sun/star/sdb/XResultSetAccess.hpp> +#include <com/sun/star/sdbc/XRowSetListener.hpp> +#include <com/sun/star/sdbc/XRowUpdate.hpp> +#include <com/sun/star/sdbc/XResultSetUpdate.hpp> +#include <com/sun/star/sdbc/XParameters.hpp> +#include <com/sun/star/sdb/XRowSetApproveBroadcaster.hpp> +#include <com/sun/star/sdbc/ResultSetType.hpp> +#include <com/sun/star/util/XCancellable.hpp> +#include <com/sun/star/sdbcx/XDeleteRows.hpp> +#include <com/sun/star/sdb/XCompletedExecution.hpp> +#include <com/sun/star/sdb/RowSetVetoException.hpp> +#include <com/sun/star/sdb/XSingleSelectQueryAnalyzer.hpp> +#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp> +#include <com/sun/star/sdb/XParametersSupplier.hpp> +#include <com/sun/star/sdb/XRowsChangeBroadcaster.hpp> +/** === end UNO includes === **/ + +#include <cppuhelper/compbase12.hxx> +#include <connectivity/paramwrapper.hxx> +#include <connectivity/FValue.hxx> +#include <connectivity/warningscontainer.hxx> + +namespace dbaccess +{ + typedef ::cppu::WeakAggComponentImplHelper12 < ::com::sun::star::sdb::XResultSetAccess + , ::com::sun::star::sdb::XRowSetApproveBroadcaster + , ::com::sun::star::sdb::XRowsChangeBroadcaster + , ::com::sun::star::sdbcx::XDeleteRows + , ::com::sun::star::sdbc::XParameters + , ::com::sun::star::lang::XEventListener + , ::com::sun::star::sdbc::XResultSetUpdate + , ::com::sun::star::sdbc::XRowUpdate + , ::com::sun::star::util::XCancellable + , ::com::sun::star::sdb::XCompletedExecution + , ::com::sun::star::sdb::XParametersSupplier + , ::com::sun::star::sdbc::XWarningsSupplier + > ORowSet_BASE1; + + class OTableContainer; + class ORowSet : public comphelper::OBaseMutex + , public ORowSet_BASE1 + , public ORowSetBase + , public ::comphelper::OPropertyArrayUsageHelper<ORowSet> + { + friend class ORowSetClone; + + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection > m_xOldConnection; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection > m_xActiveConnection; + ::com::sun::star::uno::Any m_aActiveConnection; + ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > m_xTypeMap; + ::com::sun::star::uno::Any m_aTypeMap; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XPreparedStatement > m_xStatement; + ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XSingleSelectQueryComposer > m_xComposer; + ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > m_xColumns; // the columns from a table or query + + connectivity::OWeakRefArray m_aClones; + /** our parameters as XPropertySet instances and ORowSetValue instances + */ + ::dbtools::param::ParametersContainerRef m_pParameters; + /** our parameters values, used when we do not yet have a parameters container + (since we have not been executed, yet) + */ + ORowSetValueVector m_aPrematureParamValues; + ORowSetValueVector m_aParameterValueForCache; + ::std::bit_vector m_aParametersSet; + ::std::bit_vector m_aReadOnlyDataColumns; + + ::cppu::OInterfaceContainerHelper m_aRowsetListeners; + ::cppu::OInterfaceContainerHelper m_aApproveListeners; + ::cppu::OInterfaceContainerHelper m_aRowsChangeListener; + + ::dbtools::WarningsContainer m_aWarnings; + + OTableContainer* m_pTables; + + rtl::OUString m_aCommand; + rtl::OUString m_aDataSourceName; + rtl::OUString m_aURL; + rtl::OUString m_aUser; + rtl::OUString m_aPassword; + rtl::OUString m_aFilter; + rtl::OUString m_aHavingClause; + rtl::OUString m_aGroupBy; + rtl::OUString m_aOrder; + rtl::OUString m_aActiveCommand; + rtl::OUString m_aCursorName; + rtl::OUString m_aUpdateCatalogName; // is set by a query + rtl::OUString m_aUpdateSchemaName; // is set by a query + rtl::OUString m_aUpdateTableName; // is set by a query + + sal_Int32 m_nFetchDirection; + sal_Int32 m_nFetchSize; + sal_Int32 m_nMaxFieldSize; + sal_Int32 m_nMaxRows; + sal_Int32 m_nQueryTimeOut; + sal_Int32 m_nCommandType; + sal_Int32 m_nTransactionIsolation; + sal_Int32 m_nPrivileges; + sal_Int32 m_nLastKnownRowCount; + oslInterlockedCount m_nInAppend; + sal_Bool m_bLastKnownRowCountFinal; + sal_Bool m_bUseEscapeProcessing ; + sal_Bool m_bApplyFilter ; + sal_Bool m_bCommandFacetsDirty; // any of the facets which define the active command is dirty + sal_Bool m_bModified ; + sal_Bool m_bRebuildConnOnExecute ; + sal_Bool m_bIsBookmarable ; + sal_Bool m_bNew ; + sal_Bool m_bCanUpdateInsertedRows; + sal_Bool m_bOwnConnection; + + private: + /** builds m_aActiveCommand from our settings + + @return + whether we should use escape processing before executing the actual command. This is determined + from our own EscapeProcessing property, and possibly overruled by the respective property + of a query we're based on. + */ + sal_Bool impl_buildActiveCommand_throw(); + + /** initializes our query composer, and everything which has to do with it + + If we don't use escape processing, then we don't have a composer, and everything + related to it. Nonetheless, _out_rCommandToExecute and the return value are properly + initialized. + + @param _out_rCommandToExecute + The command which is to be executed, according to the current settings - + it is built from our active command plus our current filter/order criterions. + + @return + whether we should use escape processing before executing the actual command. This is determined + from our own EscapeProcessing property, and possibly overruled by the respective property + of a query we're based on. + Effectively, this value determines whether or not we actually have an composer (m_xComposer) + and dependent information (such as the parameters container). + + @precond + m_xActiveConnection points to a valid SDB-level connection + + @throws com::sun::star::sdb::SQLException + if an database-related error occured + + @throws com::sun::star::uno::RuntimeException + if any of the components involved throws a com::sun::star::uno::RuntimeException + */ + sal_Bool impl_initComposer_throw( ::rtl::OUString& _out_rCommandToExecute ); + + /** returns the table container of our active connection + + If our connection is able to provide a tables container, this one is returned. + Else, if m_pTables is not <NULL/>, this one will returned. + Else, m_pTables will be constructed and returned. + + @precond m_xActiveConnection is not <NULL/> + @throws ::com::sun::star::sdbc::SQLException + if retrieving or constructing the tables container goes wrong + + @see impl_resetTables_nothrow + */ + ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > + impl_getTables_throw(); + + /** cleans up m_pTables, and resets it to <NULL/> + */ + void impl_resetTables_nothrow(); + + /** prepares and executes our command + */ + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet > + impl_prepareAndExecute_throw(); + + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection > calcConnection(const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& _rxHandler) throw( ::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException ); + // free clones and ParseTree. Plus, if _bComplete is <TRUE/>, *all* other associated resources + void freeResources( bool _bComplete ); + + /// informs the clones (and ourself) that we are going to delete a record with a given bookmark + void notifyRowSetAndClonesRowDelete( const ::com::sun::star::uno::Any& _rBookmark ); + + /// inform the clones (and ourself) that we have deleted a record with a given bookmark + void notifyRowSetAndClonesRowDeleted( const ::com::sun::star::uno::Any& _rBookmark, sal_Int32 _nPos ); + + void checkUpdateIterator(); + const connectivity::ORowSetValue& getInsertValue(sal_Int32 columnIndex); + void setParameter(sal_Int32 parameterIndex, const connectivity::ORowSetValue& x); + // resizes the parameter vector if nescessary + ::connectivity::ORowSetValue& getParameterStorage( sal_Int32 parameterIndex ); + + void updateValue(sal_Int32 columnIndex,const connectivity::ORowSetValue& x); + void checkUpdateConditions(sal_Int32 columnIndex); + void impl_rebuild_throw(::osl::ResettableMutexGuard& _rGuard); + // set all data columns to writeable + void impl_setDataColumnsWriteable_throw(); + // restore the old state of the data column read-only state + void impl_restoreDataColumnsWriteable_throw(); + + protected: + virtual void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const ::com::sun::star::uno::Any& rValue) throw (::com::sun::star::uno::Exception); + virtual void SAL_CALL getFastPropertyValue(::com::sun::star::uno::Any& rValue,sal_Int32 nHandle) const; + virtual void getPropertyDefaultByHandle( sal_Int32 _nHandle, ::com::sun::star::uno::Any& _rDefault ) const; + + virtual void fireRowcount(); + void notifyAllListenersRowBeforeChange(::osl::ResettableMutexGuard& _rGuard,const ::com::sun::star::sdb::RowChangeEvent &rEvt); + void notifyAllListenersRowChanged(::osl::ResettableMutexGuard& _rGuard,const ::com::sun::star::sdb::RowsChangeEvent& rEvt); + virtual sal_Bool notifyAllListenersCursorBeforeMove(::osl::ResettableMutexGuard& _rGuard); + virtual void notifyAllListenersCursorMoved(::osl::ResettableMutexGuard& _rGuard); + virtual void notifyAllListeners(::osl::ResettableMutexGuard& _rGuard); + + virtual void doCancelModification( ); + virtual sal_Bool isModification( ); + virtual sal_Bool isModified( ); + virtual sal_Bool isNew( ); + + virtual ~ORowSet(); + + public: + ORowSet(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >&); + + // com::sun::star::lang::XTypeProvider + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes() throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() throw (::com::sun::star::uno::RuntimeException); + + // com::sun::star::uno::XInterface + virtual ::com::sun::star::uno::Any SAL_CALL queryInterface( const ::com::sun::star::uno::Type & rType ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL acquire() throw(); + virtual void SAL_CALL release() throw(); + + // com::sun::star::lang::XUnoTunnel + virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& aIdentifier ) throw(::com::sun::star::uno::RuntimeException); + + // com::sun::star::uno::XAggregation + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation( const ::com::sun::star::uno::Type& aType ) throw(::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::lang::XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw(::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::lang::XServiceInfo - static methods + static ::com::sun::star::uno::Sequence< ::rtl::OUString > getSupportedServiceNames_static(void) throw( ::com::sun::star::uno::RuntimeException ); + static ::rtl::OUString getImplementationName_static(void) throw( ::com::sun::star::uno::RuntimeException ); + static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > + SAL_CALL Create(const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >&); + + // OComponentHelper + virtual void SAL_CALL disposing(void); + + // ::com::sun::star::lang::XEventListener + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw(::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbc::XCloseable + virtual void SAL_CALL close( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // comphelper::OPropertyArrayUsageHelper + virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const; + + // cppu::OPropertySetHelper + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(); + + // ::com::sun::star::sdbc::XResultSet + virtual sal_Int32 SAL_CALL getRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL refreshRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // XCompletedExecution + virtual void SAL_CALL executeWithCompletion( const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& handler ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // XParametersSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess > SAL_CALL getParameters( ) throw (::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbc::XRow + virtual sal_Bool SAL_CALL wasNull( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getString( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL getBoolean( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int8 SAL_CALL getByte( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int16 SAL_CALL getShort( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getInt( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int64 SAL_CALL getLong( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual float SAL_CALL getFloat( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual double SAL_CALL getDouble( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getBytes( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::util::Date SAL_CALL getDate( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::util::Time SAL_CALL getTime( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::util::DateTime SAL_CALL getTimestamp( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getBinaryStream( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getCharacterStream( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Any SAL_CALL getObject( sal_Int32 columnIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& typeMap ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRef > SAL_CALL getRef( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XBlob > SAL_CALL getBlob( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XClob > SAL_CALL getClob( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XArray > SAL_CALL getArray( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbc::XRowUpdate + virtual void SAL_CALL updateNull( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateBoolean( sal_Int32 columnIndex, sal_Bool x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateByte( sal_Int32 columnIndex, sal_Int8 x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateShort( sal_Int32 columnIndex, sal_Int16 x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateInt( sal_Int32 columnIndex, sal_Int32 x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateLong( sal_Int32 columnIndex, sal_Int64 x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateFloat( sal_Int32 columnIndex, float x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateDouble( sal_Int32 columnIndex, double x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateString( sal_Int32 columnIndex, const ::rtl::OUString& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateBytes( sal_Int32 columnIndex, const ::com::sun::star::uno::Sequence< sal_Int8 >& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateDate( sal_Int32 columnIndex, const ::com::sun::star::util::Date& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateTime( sal_Int32 columnIndex, const ::com::sun::star::util::Time& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateTimestamp( sal_Int32 columnIndex, const ::com::sun::star::util::DateTime& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateBinaryStream( sal_Int32 columnIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateCharacterStream( sal_Int32 columnIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateObject( sal_Int32 columnIndex, const ::com::sun::star::uno::Any& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateNumericObject( sal_Int32 columnIndex, const ::com::sun::star::uno::Any& x, sal_Int32 scale ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbc::XResultSetUpdate + virtual void SAL_CALL insertRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL deleteRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL cancelRowUpdates( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL moveToInsertRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL moveToCurrentRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbc::XRowSet + virtual void SAL_CALL execute( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addRowSetListener( const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowSetListener >& listener ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeRowSetListener( const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowSetListener >& listener ) throw(::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdb::XRowSetApproveBroadcaster + virtual void SAL_CALL addRowSetApproveListener( const ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XRowSetApproveListener >& listener ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeRowSetApproveListener( const ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XRowSetApproveListener >& listener ) throw(::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdb::XRowsChangeBroadcaster + virtual void SAL_CALL addRowsChangeListener( const ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XRowsChangeListener >& listener ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeRowsChangeListener( const ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XRowsChangeListener >& listener ) throw(::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdb::XResultSetAccess + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet > SAL_CALL createResultSet( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::util::XCancellable + virtual void SAL_CALL cancel( ) throw(::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbcx::XDeleteRows + virtual ::com::sun::star::uno::Sequence< sal_Int32 > SAL_CALL deleteRows( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& rows ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // XParameters + virtual void SAL_CALL setNull( sal_Int32 parameterIndex, sal_Int32 sqlType ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setObjectNull( sal_Int32 parameterIndex, sal_Int32 sqlType, const ::rtl::OUString& typeName ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setBoolean( sal_Int32 parameterIndex, sal_Bool x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setByte( sal_Int32 parameterIndex, sal_Int8 x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setShort( sal_Int32 parameterIndex, sal_Int16 x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setInt( sal_Int32 parameterIndex, sal_Int32 x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setLong( sal_Int32 parameterIndex, sal_Int64 x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setFloat( sal_Int32 parameterIndex, float x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setDouble( sal_Int32 parameterIndex, double x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setString( sal_Int32 parameterIndex, const ::rtl::OUString& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setBytes( sal_Int32 parameterIndex, const ::com::sun::star::uno::Sequence< sal_Int8 >& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setDate( sal_Int32 parameterIndex, const ::com::sun::star::util::Date& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setTime( sal_Int32 parameterIndex, const ::com::sun::star::util::Time& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setTimestamp( sal_Int32 parameterIndex, const ::com::sun::star::util::DateTime& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setBinaryStream( sal_Int32 parameterIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setCharacterStream( sal_Int32 parameterIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setObject( sal_Int32 parameterIndex, const ::com::sun::star::uno::Any& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setObjectWithInfo( sal_Int32 parameterIndex, const ::com::sun::star::uno::Any& x, sal_Int32 targetSqlType, sal_Int32 scale ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setRef( sal_Int32 parameterIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRef >& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setBlob( sal_Int32 parameterIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XBlob >& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setClob( sal_Int32 parameterIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XClob >& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setArray( sal_Int32 parameterIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XArray >& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL clearParameters( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // XWarningsSupplier + virtual ::com::sun::star::uno::Any SAL_CALL getWarnings( ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL clearWarnings( ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + protected: + /** implement the <method>execute</method>, without calling the approve listeners and without building a new + connection + @param _rClearForNotification mutex to clear before doing the final notifications + */ + void execute_NoApprove_NoNewConn(::osl::ResettableMutexGuard& _rClearForNotification); + + /** call the RowSetApproveListeners<p/> + throws an RowSetVetoException if one of the listeners vetoed + */ + void approveExecution() throw (::com::sun::star::sdb::RowSetVetoException, ::com::sun::star::uno::RuntimeException); + + /// set m_xActiveConnection, fire a PropertyChangeEvent if necessary, do the event listener handling etc + void setActiveConnection( ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _rxNewConn, sal_Bool _bFireEvent = sal_True ); + + void implCancelRowUpdates( sal_Bool _bNotifyModified ) SAL_THROW( ( ::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException ) ); + + /** sets the given result set type/concurrency at the given statement, while respecting + possibly related data source settings + */ + void setStatementResultSetType( + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxStatement, + sal_Int32 _nDesiredResultSetType, + sal_Int32 _nDesiredResultSetConcurrency + ); + + /** initializes a given RowSet column with the ColumnSettings (width, format, hidden, etc.) from a + template column. + + If the template column supports any of the known column settings, they're plain copied. If not, + the template column is examined for a TableName and Name property, and the table column described + by those is used to find and copy the column settings. + */ + void impl_initializeColumnSettings_nothrow( + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxTemplateColumn, + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxRowSetColumn + ); + + /** initializes our parameters container (m_pParameters) according to the parameter columns as + obtained from our composer + */ + void impl_initParametersContainer_nothrow(); + /** disposes our parameters container + */ + void impl_disposeParametersContainer_nothrow(); + + protected: + using ORowSetBase::getFastPropertyValue; + using ORowSetBase::firePropertyChange; + using ORowSetBase::doCancelModification; + using ORowSetBase::isModification; + using ORowSetBase::isModified; + using ORowSetBase::isNew; + }; + + + //************************************************************ + // ORowSetClone + //************************************************************ + class ORowSetClone : public comphelper::OBaseMutex + ,public OSubComponent + ,public ORowSetBase + ,public ::comphelper::OPropertyArrayUsageHelper < ORowSetClone > + { + protected: + ORowSet* m_pParent; + sal_Int32 m_nFetchDirection; + sal_Int32 m_nFetchSize; + sal_Bool m_bIsBookmarable; + + protected: + // the clone can not insert anything + virtual void doCancelModification( ); + virtual sal_Bool isModification( ); + virtual sal_Bool isModified( ); + virtual sal_Bool isNew( ); + + virtual void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const ::com::sun::star::uno::Any& rValue) throw (::com::sun::star::uno::Exception); + public: + ORowSetClone( const ::comphelper::ComponentContext& _rContext, ORowSet& rParent, ::osl::Mutex* _pMutex ); + virtual ~ORowSetClone(); + + // com::sun::star::lang::XTypeProvider + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes() throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() throw (::com::sun::star::uno::RuntimeException) + { + return getUnoTunnelImplementationId(); + } + + // com::sun::star::uno::XInterface + virtual ::com::sun::star::uno::Any SAL_CALL queryInterface( const ::com::sun::star::uno::Type & rType ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL acquire() throw(); + virtual void SAL_CALL release() throw(); + + // ::com::sun::star::lang::XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw(::com::sun::star::uno::RuntimeException); + + // com::sun::star::lang::XUnoTunnel + virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& aIdentifier ) throw(::com::sun::star::uno::RuntimeException); + static ::com::sun::star::uno::Sequence< sal_Int8 > getUnoTunnelImplementationId(); + + // OComponentHelper + virtual void SAL_CALL disposing(void); + + // ::com::sun::star::sdbc::XCloseable + virtual void SAL_CALL close( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // 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) + { + return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper()); + } + + // ::com::sun::star::sdbc::XRowSet + virtual void SAL_CALL execute( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addRowSetListener( const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowSetListener >& listener ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeRowSetListener( const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowSetListener >& listener ) throw(::com::sun::star::uno::RuntimeException); + + // comphelper::OPropertyArrayUsageHelper + virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const; + + // cppu::OPropertySetHelper + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(); + + protected: + using ORowSetBase::doCancelModification; + using ORowSetBase::isModification; + using ORowSetBase::isModified; + using ORowSetBase::isNew; + using ORowSetBase::rowDeleted; + }; + +} +#endif // DBACCESS_CORE_API_ROWSET_HXX + diff --git a/dbaccess/source/core/api/RowSetBase.cxx b/dbaccess/source/core/api/RowSetBase.cxx new file mode 100644 index 000000000000..57157cf4f998 --- /dev/null +++ b/dbaccess/source/core/api/RowSetBase.cxx @@ -0,0 +1,1577 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#include "RowSetBase.hxx" +#include "CRowSetDataColumn.hxx" +#include <connectivity/sdbcx/VCollection.hxx> +#include "RowSetCache.hxx" +#include "dbastrings.hrc" +#include "core_resource.hrc" +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/sdbcx/CompareBookmark.hpp> +#include <com/sun/star/sdbc/ResultSetConcurrency.hpp> +#include <com/sun/star/lang/Locale.hpp> +#include <com/sun/star/util/NumberFormat.hpp> +#include <comphelper/sequence.hxx> +#include <comphelper/extract.hxx> +#include <comphelper/seqstream.hxx> +#include <connectivity/dbexception.hxx> +#include <osl/thread.h> +#include <tools/debug.hxx> +#include <rtl/logfile.hxx> + +using namespace dbaccess; +using namespace connectivity; +using namespace connectivity::sdbcx; +using namespace comphelper; +using namespace dbtools; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; +using namespace ::cppu; +using namespace ::osl; + +namespace dbaccess +{ + +// ========================================================================= +// = OEmptyCollection +// ========================================================================= +// ------------------------------------------------------------------------- +class OEmptyCollection : public sdbcx::OCollection +{ +protected: + virtual void impl_refresh() throw(RuntimeException); + virtual connectivity::sdbcx::ObjectType createObject(const ::rtl::OUString& _rName); +public: + OEmptyCollection(::cppu::OWeakObject& _rParent,::osl::Mutex& _rMutex) : OCollection(_rParent,sal_True,_rMutex,::std::vector< ::rtl::OUString>()){} +}; +// ----------------------------------------------------------------------------- +void OEmptyCollection::impl_refresh() throw(RuntimeException) +{ +} +// ----------------------------------------------------------------------------- +connectivity::sdbcx::ObjectType OEmptyCollection::createObject(const ::rtl::OUString& /*_rName*/) +{ + return connectivity::sdbcx::ObjectType(); +} +// ----------------------------------------------------------------------------- + +// ========================================================================= +// = ORowSetBase +// ========================================================================= +DBG_NAME(ORowSetBase) +// ------------------------------------------------------------------------- +ORowSetBase::ORowSetBase( const ::comphelper::ComponentContext& _rContext, ::cppu::OBroadcastHelper& _rBHelper, ::osl::Mutex* _pMutex ) + :OPropertyStateContainer(_rBHelper) + ,m_pMutex(_pMutex) + ,m_pCache(NULL) + ,m_pColumns(NULL) + ,m_rBHelper(_rBHelper) + ,m_pEmptyCollection( NULL ) + ,m_aContext( _rContext ) + ,m_aErrors( _rContext ) + ,m_nLastColumnIndex(-1) + ,m_nDeletedPosition(-1) + ,m_nResultSetType( ResultSetType::FORWARD_ONLY ) + ,m_nResultSetConcurrency( ResultSetConcurrency::READ_ONLY ) + ,m_bClone(sal_False) + ,m_bIgnoreResult(sal_False) + ,m_bBeforeFirst(sal_True) // changed from sal_False + ,m_bAfterLast(sal_False) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::ORowSetBase" ); + DBG_CTOR(ORowSetBase,NULL); + + sal_Int32 nRBT = PropertyAttribute::READONLY | PropertyAttribute::BOUND | PropertyAttribute::TRANSIENT; + + sal_Int32 nInitialRowCountValue = 0; + sal_Bool bInitialRowCountFinalValue( sal_False ); + registerPropertyNoMember( PROPERTY_ROWCOUNT, PROPERTY_ID_ROWCOUNT, nRBT, ::getCppuType( &nInitialRowCountValue ), &nInitialRowCountValue ); + registerPropertyNoMember( PROPERTY_ISROWCOUNTFINAL, PROPERTY_ID_ISROWCOUNTFINAL, nRBT, ::getBooleanCppuType(), &bInitialRowCountFinalValue ); +} +// ----------------------------------------------------------------------------- +ORowSetBase::~ORowSetBase() +{ + if(m_pColumns) + { + TDataColumns().swap(m_aDataColumns); + m_pColumns->acquire(); + m_pColumns->disposing(); + delete m_pColumns; + m_pColumns = NULL; + } + + if ( m_pEmptyCollection ) + delete m_pEmptyCollection; + + DBG_DTOR(ORowSetBase,NULL); +} +// com::sun::star::lang::XTypeProvider +//-------------------------------------------------------------------------- +Sequence< Type > ORowSetBase::getTypes() throw (RuntimeException) +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getTypes" ); + return ::comphelper::concatSequences(ORowSetBase_BASE::getTypes(),OPropertyStateContainer::getTypes()); +} +// com::sun::star::uno::XInterface +//-------------------------------------------------------------------------- +Any ORowSetBase::queryInterface( const Type & rType ) throw (RuntimeException) +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::queryInterface" ); + Any aRet = ORowSetBase_BASE::queryInterface(rType); + if(!aRet.hasValue()) + aRet = OPropertyStateContainer::queryInterface(rType); + return aRet; +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSetBase::getFastPropertyValue(Any& rValue,sal_Int32 nHandle) const +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getFastPropertyValue" ); + if(m_pCache) + { + switch(nHandle) + { + case PROPERTY_ID_ROWCOUNT: + rValue <<= impl_getRowCount(); + break; + case PROPERTY_ID_ISROWCOUNTFINAL: + rValue.setValue(&m_pCache->m_bRowCountFinal,::getCppuBooleanType()); + break; + default: + OPropertyStateContainer::getFastPropertyValue(rValue,nHandle); + }; + } + else + OPropertyStateContainer::getFastPropertyValue(rValue,nHandle); +} +// ------------------------------------------------------------------------- +// OComponentHelper +void SAL_CALL ORowSetBase::disposing(void) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::disposing" ); + MutexGuard aGuard(*m_pMutex); + + if ( m_pColumns ) + { + TDataColumns().swap(m_aDataColumns); + m_pColumns->disposing(); + } + if ( m_pCache ) + { + m_pCache->deregisterOldRow(m_aOldRow); + m_pCache->deleteIterator(this); + } + m_pCache = NULL; +} +// ------------------------------------------------------------------------- +// comphelper::OPropertyArrayUsageHelper +::cppu::IPropertyArrayHelper* ORowSetBase::createArrayHelper( ) const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::createArrayHelper" ); + Sequence< Property > aProps; + describeProperties(aProps); + return new ::cppu::OPropertyArrayHelper(aProps); +} +// ------------------------------------------------------------------------- +// cppu::OPropertySetHelper +::cppu::IPropertyArrayHelper& SAL_CALL ORowSetBase::getInfoHelper() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getInfoHelper" ); + return *const_cast<ORowSetBase*>(this)->getArrayHelper(); +} +// ------------------------------------------------------------------------- +// XRow +sal_Bool SAL_CALL ORowSetBase::wasNull( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::wasNull" ); + ::osl::MutexGuard aGuard( *m_pMutex ); + checkCache(); + return impl_wasNull(); +} +// ----------------------------------------------------------------------------- +sal_Bool ORowSetBase::impl_wasNull() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::impl_wasNull" ); + return ((m_nLastColumnIndex != -1) && !m_aCurrentRow.isNull() && m_aCurrentRow != m_pCache->getEnd() && m_aCurrentRow->isValid()) ? ((*m_aCurrentRow)->get())[m_nLastColumnIndex].isNull() : sal_True; +} + +// ----------------------------------------------------------------------------- +const ORowSetValue& ORowSetBase::getValue(sal_Int32 columnIndex) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getValue" ); + checkCache(); + return impl_getValue(columnIndex); +} +// ----------------------------------------------------------------------------- +const ORowSetValue& ORowSetBase::impl_getValue(sal_Int32 columnIndex) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::impl_getValue" ); + if ( m_bBeforeFirst || m_bAfterLast ) + { + OSL_ENSURE(0,"ORowSetBase::getValue: Illegal call here (we're before first or after last)!"); + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_CURSOR_BEFORE_OR_AFTER ), SQL_INVALID_CURSOR_POSITION, *m_pMySelf ); + } + + if ( impl_rowDeleted() ) + { + return m_aEmptyValue; + } + + bool bValidCurrentRow = ( !m_aCurrentRow.isNull() && m_aCurrentRow != m_pCache->getEnd() && m_aCurrentRow->isValid() ); + if ( !bValidCurrentRow ) + { + // currentrow is null when the clone moves the window + positionCache( MOVE_NONE_REFRESH_ONLY ); + m_aCurrentRow = m_pCache->m_aMatrixIter; + OSL_ENSURE(!m_aCurrentRow.isNull(),"ORowSetBase::getValue: we don't stand on a valid row! Row is null."); + + bValidCurrentRow = ( !m_aCurrentRow.isNull() && m_aCurrentRow != m_pCache->getEnd() && m_aCurrentRow->isValid() ); + } + + if ( bValidCurrentRow ) + { +#if OSL_DEBUG_LEVEL > 0 + ORowSetMatrix::iterator aCacheEnd; + ORowSetMatrix::iterator aCurrentRow; + aCacheEnd = m_pCache->getEnd(); + aCurrentRow = m_aCurrentRow; + ORowSetCacheMap::iterator aCacheIter = m_aCurrentRow.getIter(); + sal_Int32 n = aCacheIter->first; + n = n; + ORowSetCacheIterator_Helper aHelper = aCacheIter->second; + ORowSetMatrix::iterator k = aHelper.aIterator; + for (; k != m_pCache->getEnd(); ++k) + { + ORowSetValueVector* pTemp = k->getBodyPtr(); + OSL_ENSURE( pTemp != (void*)0xfeeefeee,"HALT!" ); + } +#endif + OSL_ENSURE(!m_aCurrentRow.isNull() && m_aCurrentRow < m_pCache->getEnd() && aCacheIter != m_pCache->m_aCacheIterators.end(),"Invalid iterator set for currentrow!"); +#if OSL_DEBUG_LEVEL > 0 + ORowSetRow rRow = (*m_aCurrentRow); + OSL_ENSURE(rRow.isValid() && static_cast<sal_uInt16>(columnIndex) < (rRow->get()).size(),"Invalid size of vector!"); +#endif + return ((*m_aCurrentRow)->get())[m_nLastColumnIndex = columnIndex]; + } + + // we should normally never reach this + return m_aEmptyValue; +} +// ------------------------------------------------------------------------- +::rtl::OUString SAL_CALL ORowSetBase::getString( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getString" ); + ::osl::MutexGuard aGuard( *m_pMutex ); + return getValue(columnIndex); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ORowSetBase::getBoolean( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getBoolean" ); + ::osl::MutexGuard aGuard( *m_pMutex ); + return getValue(columnIndex); +} +// ------------------------------------------------------------------------- +sal_Int8 SAL_CALL ORowSetBase::getByte( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getByte" ); + ::osl::MutexGuard aGuard( *m_pMutex ); + return getValue(columnIndex); +} +// ------------------------------------------------------------------------- +sal_Int16 SAL_CALL ORowSetBase::getShort( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getShort" ); + ::osl::MutexGuard aGuard( *m_pMutex ); + return getValue(columnIndex); +} +// ------------------------------------------------------------------------- +sal_Int32 SAL_CALL ORowSetBase::getInt( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getInt" ); + ::osl::MutexGuard aGuard( *m_pMutex ); + return getValue(columnIndex); +} +// ------------------------------------------------------------------------- +sal_Int64 SAL_CALL ORowSetBase::getLong( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getLong" ); + ::osl::MutexGuard aGuard( *m_pMutex ); + return getValue(columnIndex); +} +// ------------------------------------------------------------------------- +float SAL_CALL ORowSetBase::getFloat( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getFloat" ); + ::osl::MutexGuard aGuard( *m_pMutex ); + return getValue(columnIndex); +} +// ------------------------------------------------------------------------- +double SAL_CALL ORowSetBase::getDouble( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getDouble" ); + ::osl::MutexGuard aGuard( *m_pMutex ); + return getValue(columnIndex); +} +// ------------------------------------------------------------------------- +Sequence< sal_Int8 > SAL_CALL ORowSetBase::getBytes( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getBytes" ); + ::osl::MutexGuard aGuard( *m_pMutex ); + return getValue(columnIndex); +} +// ------------------------------------------------------------------------- +::com::sun::star::util::Date SAL_CALL ORowSetBase::getDate( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getDate" ); + ::osl::MutexGuard aGuard( *m_pMutex ); + return getValue(columnIndex); +} +// ------------------------------------------------------------------------- +::com::sun::star::util::Time SAL_CALL ORowSetBase::getTime( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getTime" ); + ::osl::MutexGuard aGuard( *m_pMutex ); + return getValue(columnIndex); +} +// ------------------------------------------------------------------------- +::com::sun::star::util::DateTime SAL_CALL ORowSetBase::getTimestamp( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getTimestamp" ); + ::osl::MutexGuard aGuard( *m_pMutex ); + return getValue(columnIndex); +} +// ------------------------------------------------------------------------- +Reference< ::com::sun::star::io::XInputStream > SAL_CALL ORowSetBase::getBinaryStream( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getBinaryStream" ); + ::osl::MutexGuard aGuard( *m_pMutex ); + checkCache(); + + if ( m_bBeforeFirst || m_bAfterLast ) + { + OSL_ENSURE(0,"ORowSetBase::getBinaryStream: Illegal call here (we're before first or after last)!"); + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_CURSOR_BEFORE_OR_AFTER ), SQL_INVALID_CURSOR_POSITION, *m_pMySelf ); + } + + if ( impl_rowDeleted() ) + { + return NULL; + } + + bool bValidCurrentRow = ( !m_aCurrentRow.isNull() && m_aCurrentRow != m_pCache->getEnd() && m_aCurrentRow->isValid() ); + if ( !bValidCurrentRow ) + { + positionCache( MOVE_NONE_REFRESH_ONLY ); + m_aCurrentRow = m_pCache->m_aMatrixIter; + OSL_ENSURE(!m_aCurrentRow.isNull(),"ORowSetBase::getBinaryStream: we don't stand on a valid row! Row is null."); + + bValidCurrentRow = ( !m_aCurrentRow.isNull() && m_aCurrentRow != m_pCache->getEnd() && m_aCurrentRow->isValid() ); + } + + if ( bValidCurrentRow ) + return new ::comphelper::SequenceInputStream(((*m_aCurrentRow)->get())[m_nLastColumnIndex = columnIndex].getSequence()); + + // we should normally never reach this + return Reference< ::com::sun::star::io::XInputStream >(); +} +// ------------------------------------------------------------------------- +Reference< ::com::sun::star::io::XInputStream > SAL_CALL ORowSetBase::getCharacterStream( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getCharacterStream" ); + return getBinaryStream(columnIndex); +} +// ------------------------------------------------------------------------- +Any SAL_CALL ORowSetBase::getObject( sal_Int32 columnIndex, const Reference< XNameAccess >& /*typeMap*/ ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getObject" ); + ::osl::MutexGuard aGuard( *m_pMutex ); + checkCache(); + + return getValue(columnIndex).makeAny(); +} +// ------------------------------------------------------------------------- +Reference< XRef > SAL_CALL ORowSetBase::getRef( sal_Int32 /*columnIndex*/ ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getRef" ); + ::dbtools::throwFeatureNotImplementedException( "XRow::getRef", *m_pMySelf ); + return NULL; +} +// ------------------------------------------------------------------------- +Reference< XBlob > SAL_CALL ORowSetBase::getBlob( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getBlob" ); + return Reference< XBlob >(getValue(columnIndex).makeAny(),UNO_QUERY); +} +// ------------------------------------------------------------------------- +Reference< XClob > SAL_CALL ORowSetBase::getClob( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getClob" ); + return Reference< XClob >(getValue(columnIndex).makeAny(),UNO_QUERY); +} +// ------------------------------------------------------------------------- +Reference< XArray > SAL_CALL ORowSetBase::getArray( sal_Int32 /*columnIndex*/ ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getArray" ); + ::dbtools::throwFeatureNotImplementedException( "XRow::getArray", *m_pMySelf ); + return NULL; +} +// ------------------------------------------------------------------------- +// ::com::sun::star::sdbcx::XRowLocate +Any SAL_CALL ORowSetBase::getBookmark( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getBookmark" ); + DBG_TRACE2("DBACCESS ORowSetBase::getBookmark() Clone = %i ID = %i\n",m_bClone,osl_getThreadIdentifier(NULL)); + ::connectivity::checkDisposed(m_rBHelper.bDisposed); + ::osl::MutexGuard aGuard( *m_pMutex ); + checkCache(); + + if ( m_bBeforeFirst || m_bAfterLast ) + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_NO_BOOKMARK_BEFORE_OR_AFTER ), SQL_INVALID_CURSOR_POSITION, *m_pMySelf ); + + if ( impl_rowDeleted() ) + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_NO_BOOKMARK_DELETED ), SQL_INVALID_CURSOR_POSITION, *m_pMySelf ); + + OSL_ENSURE( m_aBookmark.hasValue(), "ORowSetBase::getBookmark: bookmark has no value!" ); + return m_aBookmark; +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ORowSetBase::moveToBookmark( const Any& bookmark ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::moveToBookmark" ); + DBG_TRACE2("DBACCESS ORowSetBase::moveToBookmark(Any) Clone = %i ID = %i\n",m_bClone,osl_getThreadIdentifier(NULL)); + OSL_ENSURE(bookmark.hasValue(),"ORowSetBase::moveToBookmark bookmark has no value!"); + ::osl::ResettableMutexGuard aGuard( *m_pMutex ); + + if(!bookmark.hasValue() || m_nResultSetType == ResultSetType::FORWARD_ONLY) + { + if(bookmark.hasValue()) + OSL_ENSURE(0,"MoveToBookmark is not possible when we are only forward"); + else + OSL_ENSURE(0,"Bookmark is not valid"); + throwFunctionSequenceException(*m_pMySelf); + } + + + checkCache(); + + sal_Bool bRet( notifyAllListenersCursorBeforeMove( aGuard ) ); + if ( bRet ) + { + // check if we are inserting a row + sal_Bool bWasNew = m_pCache->m_bNew || impl_rowDeleted(); + + ORowSetNotifier aNotifier( this ); + // this will call cancelRowModification on the cache if necessary + + ORowSetRow aOldValues = getOldRow(bWasNew); + + bRet = m_pCache->moveToBookmark(bookmark); + doCancelModification( ); + if(bRet) + { + // notification order + // - column values + // - cursorMoved + setCurrentRow( sal_True, sal_True, aOldValues, aGuard ); + } + else + { + movementFailed(); + } + + // - IsModified + // - IsNew + aNotifier.fire( ); + } + DBG_TRACE2("DBACCESS ORowSetBase::moveToBookmark(Any) = %i Clone = %i\n",bRet,m_bClone); + return bRet; +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ORowSetBase::moveRelativeToBookmark( const Any& bookmark, sal_Int32 rows ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::moveRelativeToBookmark" ); + DBG_TRACE2("DBACCESS ORowSetBase::moveRelativeToBookmark(Any,%i) Clone = %i\n",rows,m_bClone); + ::connectivity::checkDisposed(m_rBHelper.bDisposed); + + ::osl::ResettableMutexGuard aGuard( *m_pMutex ); + + checkPositioningAllowed(); + + sal_Bool bRet( notifyAllListenersCursorBeforeMove( aGuard ) ); + if ( bRet ) + { + // check if we are inserting a row + sal_Bool bWasNew = m_pCache->m_bNew || rowDeleted(); + + ORowSetNotifier aNotifier( this ); + // this will call cancelRowModification on the cache if necessary + + ORowSetRow aOldValues = getOldRow(bWasNew); + + bRet = m_pCache->moveRelativeToBookmark(bookmark,rows); + doCancelModification( ); + if(bRet) + { + // notification order + // - column values + // - cursorMoved + setCurrentRow( sal_True, sal_True, aOldValues, aGuard ); + } + else + movementFailed(); + + // - IsModified + // - IsNew + aNotifier.fire( ); + + // RowCount/IsRowCountFinal + fireRowcount(); + } + DBG_TRACE3("DBACCESS ORowSetBase::moveRelativeToBookmark(Any,%i) = %i Clone = %i\n",rows,bRet,m_bClone); + return bRet; +} +// ------------------------------------------------------------------------- +sal_Int32 SAL_CALL ORowSetBase::compareBookmarks( const Any& _first, const Any& _second ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::compareBookmarks" ); + ::osl::MutexGuard aGuard( *m_pMutex ); + checkCache(); + return m_pCache->compareBookmarks(_first,_second); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ORowSetBase::hasOrderedBookmarks( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::hasOrderedBookmarks" ); + ::osl::MutexGuard aGuard( *m_pMutex ); + checkCache(); + return m_pCache->hasOrderedBookmarks(); +} +// ------------------------------------------------------------------------- +sal_Int32 SAL_CALL ORowSetBase::hashBookmark( const Any& bookmark ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::hashBookmark" ); + ::osl::MutexGuard aGuard( *m_pMutex ); + checkCache(); + return m_pCache->hashBookmark(bookmark); +} +// ------------------------------------------------------------------------- +// ------------------------------------------------------------------------- +// XResultSetMetaDataSupplier +Reference< XResultSetMetaData > SAL_CALL ORowSetBase::getMetaData( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getMetaData" ); + ::connectivity::checkDisposed(m_rBHelper.bDisposed); + + Reference< XResultSetMetaData > xMeta; + if(m_pCache) + xMeta = m_pCache->getMetaData(); + + return xMeta; +} +// ------------------------------------------------------------------------- + +// XColumnLocate +sal_Int32 SAL_CALL ORowSetBase::findColumn( const ::rtl::OUString& columnName ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::findColumn" ); + ::connectivity::checkDisposed(m_rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( m_aColumnsMutex ); + // it is possible to save some time her when we remember the names - position relation in a map + return m_pColumns ? m_pColumns->findColumn(columnName) : sal_Int32(0); +} +// ------------------------------------------------------------------------- + +// ::com::sun::star::sdbcx::XColumnsSupplier +Reference< XNameAccess > SAL_CALL ORowSetBase::getColumns( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getColumns" ); + ::connectivity::checkDisposed(m_rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( m_aColumnsMutex ); + if(!m_pColumns) + { + if (!m_pEmptyCollection) + m_pEmptyCollection = new OEmptyCollection(*m_pMySelf,m_aColumnsMutex); + return m_pEmptyCollection; + } + + return m_pColumns; +} +// ------------------------------------------------------------------------- +// XResultSet +sal_Bool SAL_CALL ORowSetBase::next( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::next" ); + DBG_TRACE2("DBACCESS ORowSetBase::next() Clone = %i ID = %i\n",m_bClone,osl_getThreadIdentifier(NULL)); + ::osl::ResettableMutexGuard aGuard( *m_pMutex ); + checkCache(); + + sal_Bool bRet( notifyAllListenersCursorBeforeMove( aGuard ) ); + if ( bRet ) + { + // check if we are inserting a row + sal_Bool bWasNew = m_pCache->m_bNew || impl_rowDeleted(); + + ORowSetNotifier aNotifier( this ); + // this will call cancelRowModification on the cache if necessary + + ORowSetRow aOldValues = getOldRow(bWasNew); + + positionCache( MOVE_FORWARD ); + sal_Bool bAfterLast = m_pCache->isAfterLast(); + bRet = m_pCache->next(); + doCancelModification( ); + + + if ( bRet || bAfterLast != m_pCache->isAfterLast() ) + { + // notification order + // - column values + // - cursorMoved + setCurrentRow( bRet, sal_True, aOldValues, aGuard ); + OSL_ENSURE(!m_bBeforeFirst,"BeforeFirst is true. I don't know why?"); + } + else + { + // moved after the last row + movementFailed(); + OSL_ENSURE(m_bAfterLast,"AfterLast is false. I don't know why?"); + } + + // - IsModified + // - IsNew + aNotifier.fire(); + + // - RowCount/IsRowCountFinal + fireRowcount(); + } + DBG_TRACE3("DBACCESS ORowSetBase::next() = %i Clone = %i ID = %i\n",bRet,m_bClone,osl_getThreadIdentifier(NULL)); + return bRet; +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ORowSetBase::isBeforeFirst( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::isBeforeFirst" ); + ::connectivity::checkDisposed(m_rBHelper.bDisposed); + ::osl::MutexGuard aGuard( *m_pMutex ); + checkCache(); + + DBG_TRACE2("DBACCESS ORowSetBase::isBeforeFirst() = %i Clone = %i\n",m_bBeforeFirst,m_bClone); + + return m_bBeforeFirst; +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ORowSetBase::isAfterLast( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::isAfterLast" ); + ::connectivity::checkDisposed(m_rBHelper.bDisposed); + ::osl::MutexGuard aGuard( *m_pMutex ); + checkCache(); + DBG_TRACE2("DBACCESS ORowSetBase::isAfterLast() = %i Clone = %i\n",m_bAfterLast,m_bClone); + + return m_bAfterLast; +} +// ------------------------------------------------------------------------- +sal_Bool ORowSetBase::isOnFirst() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::isOnFirst" ); + return isFirst(); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ORowSetBase::isFirst( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::isFirst" ); + DBG_TRACE2("DBACCESS ORowSetBase::isFirst() Clone = %i ID = %i\n",m_bClone,osl_getThreadIdentifier(NULL)); + + ::connectivity::checkDisposed(m_rBHelper.bDisposed); + ::osl::MutexGuard aGuard( *m_pMutex ); + checkCache(); + + if ( m_bBeforeFirst || m_bAfterLast ) + return sal_False; + + if ( impl_rowDeleted() ) + return ( m_nDeletedPosition == 1 ); + + positionCache( MOVE_NONE_REFRESH_ONLY ); + sal_Bool bIsFirst = m_pCache->isFirst(); + + DBG_TRACE2("DBACCESS ORowSetBase::isFirst() = %i Clone = %i\n",bIsFirst,m_bClone); + return bIsFirst; +} +// ------------------------------------------------------------------------- +sal_Bool ORowSetBase::isOnLast() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::isOnLast" ); + return isLast(); +} +// ----------------------------------------------------------------------------- +sal_Bool SAL_CALL ORowSetBase::isLast( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::isLast" ); + DBG_TRACE2("DBACCESS ORowSetBase::isLast() Clone = %i ID = %i\n",m_bClone,osl_getThreadIdentifier(NULL)); + ::connectivity::checkDisposed(m_rBHelper.bDisposed); + ::osl::MutexGuard aGuard( *m_pMutex ); + checkCache(); + + if ( m_bBeforeFirst || m_bAfterLast ) + return sal_False; + + if ( impl_rowDeleted() ) + { + if ( !m_pCache->m_bRowCountFinal ) + return sal_False; + else + return ( m_nDeletedPosition == impl_getRowCount() ); + } + + positionCache( MOVE_NONE_REFRESH_ONLY ); + sal_Bool bIsLast = m_pCache->isLast(); + + DBG_TRACE2("DBACCESS ORowSetBase::isLast() = %i Clone = %i\n",bIsLast,m_bClone); + return bIsLast; +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSetBase::beforeFirst( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::beforeFirst" ); + DBG_TRACE2("DBACCESS ORowSetBase::beforeFirst() Clone = %i ID = %i\n",m_bClone,osl_getThreadIdentifier(NULL)); + ::connectivity::checkDisposed(m_rBHelper.bDisposed); + ::osl::ResettableMutexGuard aGuard( *m_pMutex ); + + checkPositioningAllowed(); + + // check if we are inserting a row + sal_Bool bWasNew = m_pCache->m_bNew || impl_rowDeleted(); + + if((bWasNew || !m_bBeforeFirst) && notifyAllListenersCursorBeforeMove(aGuard) ) + { + ORowSetNotifier aNotifier( this ); + // this will call cancelRowModification on the cache if necessary + + if ( !m_bBeforeFirst ) + { + ORowSetRow aOldValues = getOldRow(bWasNew); + m_pCache->beforeFirst(); + doCancelModification( ); + + // notification order + // - column values + // - cursorMoved + setCurrentRow( sal_True, sal_True, aOldValues, aGuard ); + + // - IsModified + // - Isnew + aNotifier.fire(); + + // - RowCount/IsRowCountFinal + fireRowcount(); + } + + // to be done _after_ the notifications! + m_aOldRow->clearRow(); + } + DBG_TRACE2("DBACCESS ORowSetBase::beforeFirst() Clone = %i ID = %i\n",m_bClone,osl_getThreadIdentifier(NULL)); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSetBase::afterLast( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::afterLast" ); + DBG_TRACE2("DBACCESS ORowSetBase::afterLast() Clone = %i ID = %i\n",m_bClone,osl_getThreadIdentifier(NULL)); + ::connectivity::checkDisposed(m_rBHelper.bDisposed); + + ::osl::ResettableMutexGuard aGuard( *m_pMutex ); + checkPositioningAllowed(); + + sal_Bool bWasNew = m_pCache->m_bNew || impl_rowDeleted(); + + if((bWasNew || !m_bAfterLast) && notifyAllListenersCursorBeforeMove(aGuard) ) + { + // check if we are inserting a row + ORowSetNotifier aNotifier( this ); + // this will call cancelRowModification on the cache if necessary + + if(!m_bAfterLast) + { + ORowSetRow aOldValues = getOldRow(bWasNew); + + m_pCache->afterLast(); + doCancelModification( ); + + // notification order + // - column values + // - cursorMoved + setCurrentRow( sal_True, sal_True, aOldValues, aGuard ); + + // - IsModified + // - Isnew + aNotifier.fire(); + + // - RowCount/IsRowCountFinal + fireRowcount(); + } + } + DBG_TRACE2("DBACCESS ORowSetBase::afterLast() Clone = %i ID = %i\n",m_bClone,osl_getThreadIdentifier(NULL)); +} +// ----------------------------------------------------------------------------- +sal_Bool SAL_CALL ORowSetBase::move( ::std::mem_fun_t<sal_Bool,ORowSetBase>& _aCheckFunctor, + ::std::mem_fun_t<sal_Bool,ORowSetCache>& _aMovementFunctor) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::move" ); + DBG_TRACE2("DBACCESS ORowSetBase::move() Clone = %i ID = %i\n",m_bClone,osl_getThreadIdentifier(NULL)); + ::connectivity::checkDisposed(m_rBHelper.bDisposed); + ::osl::ResettableMutexGuard aGuard( *m_pMutex ); + checkPositioningAllowed(); + + sal_Bool bRet( notifyAllListenersCursorBeforeMove( aGuard ) ); + if( bRet ) + { + // check if we are inserting a row + sal_Bool bWasNew = m_pCache->m_bNew || rowDeleted(); + + ORowSetNotifier aNotifier( this ); + // this will call cancelRowModification on the cache if necessary + + ORowSetRow aOldValues = getOldRow(bWasNew); + + sal_Bool bMoved = ( bWasNew || !_aCheckFunctor(this) ); + + bRet = _aMovementFunctor(m_pCache); + doCancelModification( ); + + if ( bRet ) + { + // notification order + // - column values + // - cursorMoved + setCurrentRow( bMoved, sal_True, aOldValues, aGuard ); + } + else + { // first goes wrong so there is no row + movementFailed(); + } + + // - IsModified + // - IsNew + aNotifier.fire(); + + // - RowCount/IsRowCountFinal + fireRowcount(); + } + DBG_TRACE2("DBACCESS ORowSetBase::move() = %i Clone = %i\n",bRet,m_bClone); + return bRet; +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ORowSetBase::first( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::first" ); + DBG_TRACE2("DBACCESS ORowSetBase::first() Clone = %i ID = %i\n",m_bClone,osl_getThreadIdentifier(NULL)); + ::std::mem_fun_t<sal_Bool,ORowSetBase> ioF_tmp(&ORowSetBase::isOnFirst); + ::std::mem_fun_t<sal_Bool,ORowSetCache> F_tmp(&ORowSetCache::first); + return move(ioF_tmp,F_tmp); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ORowSetBase::last( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::last" ); + DBG_TRACE2("DBACCESS ORowSetBase::last() Clone = %i ID = %i\n",m_bClone,osl_getThreadIdentifier(NULL)); + ::std::mem_fun_t<sal_Bool,ORowSetBase> ioL_tmp(&ORowSetBase::isOnLast); + ::std::mem_fun_t<sal_Bool,ORowSetCache> L_tmp(&ORowSetCache::last); + return move(ioL_tmp,L_tmp); +} +// ------------------------------------------------------------------------- +sal_Int32 SAL_CALL ORowSetBase::getRow( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getRow" ); + DBG_TRACE2("DBACCESS ORowSetBase::getRow() Clone = %i ID = %i\n",m_bClone,osl_getThreadIdentifier(NULL)); + ::osl::MutexGuard aGuard( *m_pMutex ); + + checkCache(); + return impl_getRow(); +} +// ------------------------------------------------------------------------- +sal_Int32 ORowSetBase::impl_getRow() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::impl_getRow" ); + sal_Int32 nPos = 0; + if ( m_bBeforeFirst ) + nPos = 0; + else if ( m_bAfterLast ) + nPos = impl_getRowCount() + 1; + else if ( impl_rowDeleted() ) + nPos = m_nDeletedPosition; + else if ( !m_bClone && m_pCache->m_bNew ) + nPos = 0; + else + { + if ( m_pCache->isAfterLast() + || m_pCache->isBeforeFirst() + || ( m_pCache->compareBookmarks( m_aBookmark, m_pCache->getBookmark() ) != CompareBookmark::EQUAL ) + ) + { + positionCache( MOVE_NONE_REFRESH_ONLY ); + } + nPos = m_pCache->getRow(); + } + DBG_TRACE3("DBACCESS ORowSetBase::impl_getRow() = %i Clone = %i ID = %i\n",nPos,m_bClone,osl_getThreadIdentifier(NULL)); + return nPos; +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ORowSetBase::absolute( sal_Int32 row ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::absolute" ); + DBG_TRACE2("DBACCESS ORowSetBase::absolute(%i) Clone = %i\n",row,m_bClone); + ::connectivity::checkDisposed(m_rBHelper.bDisposed); + ::osl::ResettableMutexGuard aGuard( *m_pMutex ); + checkPositioningAllowed(); + + sal_Bool bRet = ( row > 0 ) + && notifyAllListenersCursorBeforeMove( aGuard ); + if ( bRet ) + { + // check if we are inserting a row + sal_Bool bWasNew = m_pCache->m_bNew || rowDeleted(); + + ORowSetNotifier aNotifier( this ); + // this will call cancelRowModification on the cache if necessary + + ORowSetRow aOldValues = getOldRow(bWasNew); + + bRet = m_pCache->absolute(row); + doCancelModification( ); + + if(bRet) + { + // notification order + // - column values + // - cursorMoved + setCurrentRow( sal_True, sal_True, aOldValues, aGuard ); + } + else + { // absolute movement goes wrong we stand left or right side of the rows + movementFailed(); + } + + // - IsModified + // - IsNew + aNotifier.fire(); + + // - RowCount/IsRowCountFinal + fireRowcount(); + } + DBG_TRACE3("DBACCESS ORowSetBase::absolute(%i) = %i Clone = %i\n",row,bRet,m_bClone); + return bRet; +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ORowSetBase::relative( sal_Int32 rows ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::relative" ); + DBG_TRACE2("DBACCESS ORowSetBase::relative(%i) Clone = %i\n",rows,m_bClone); + ::connectivity::checkDisposed(m_rBHelper.bDisposed); + + ::osl::ResettableMutexGuard aGuard( *m_pMutex ); + + if(!rows) + return sal_True; // in this case do nothing + + checkPositioningAllowed(); + + sal_Bool bRet = + ( ( !m_bAfterLast || rows <= 0 ) + && ( !m_bBeforeFirst || rows >= 0 ) + && notifyAllListenersCursorBeforeMove( aGuard ) + ); + + if ( bRet ) + { + // check if we are inserting a row + sal_Bool bWasNew = m_pCache->m_bNew || rowDeleted(); + + ORowSetNotifier aNotifier( this ); + // this will call cancelRowModification on the cache if necessary + + ORowSetRow aOldValues = getOldRow(bWasNew); + + positionCache( rows > 0 ? MOVE_FORWARD : MOVE_BACKWARD ); + bRet = m_pCache->relative(rows); + doCancelModification( ); + + if(bRet) + { + // notification order + // - column values + // - cursorMoved + setCurrentRow( sal_True, sal_True, aOldValues, aGuard ); + } + else + { + movementFailed(); + } + + // - IsModified + // - IsNew + aNotifier.fire(); + + // - RowCount/IsRowCountFinal + fireRowcount(); + } + DBG_TRACE3("DBACCESS ORowSetBase::relative(%i) = %i Clone = %i\n",rows,bRet,m_bClone); + return bRet; +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ORowSetBase::previous( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::previous" ); + DBG_TRACE2("DBACCESS ORowSetBase::previous() Clone = %i ID = %i\n",m_bClone,osl_getThreadIdentifier(NULL)); + ::connectivity::checkDisposed(m_rBHelper.bDisposed); + ::osl::ResettableMutexGuard aGuard( *m_pMutex ); + + checkPositioningAllowed(); + + sal_Bool bRet = !m_bBeforeFirst + && notifyAllListenersCursorBeforeMove(aGuard); + + if ( bRet ) + { + // check if we are inserting a row + sal_Bool bWasNew = m_pCache->m_bNew || rowDeleted(); + + ORowSetNotifier aNotifier( this ); + // this will call cancelRowModification on the cache if necessary + + ORowSetRow aOldValues = getOldRow(bWasNew); + + positionCache( MOVE_BACKWARD ); + bRet = m_pCache->previous(); + doCancelModification( ); + + // if m_bBeforeFirst is false and bRet is false than we stood on the first row + if(!m_bBeforeFirst || bRet) + { + // notification order + // - column values + // - cursorMoved + setCurrentRow( sal_True, sal_True, aOldValues, aGuard ); + } + else + { + DBG_ERROR( "ORowSetBase::previous: inconsistency!" ); + // we should never reach this place, as we should not get into this whole branch if m_bBeforeFirst + // was |true| from the beginning + movementFailed(); + } + + // - IsModified + // - IsNew + aNotifier.fire(); + + // - RowCount/IsRowCountFinal + fireRowcount(); + } + DBG_TRACE2("DBACCESS ORowSetBase::previous() = %i Clone = %i\n",bRet,m_bClone); + return bRet; +} +// ----------------------------------------------------------------------------- +void ORowSetBase::setCurrentRow( sal_Bool _bMoved, sal_Bool _bDoNotify, const ORowSetRow& _rOldValues, ::osl::ResettableMutexGuard& _rGuard ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::setCurrentRow" ); + DBG_TRACE2("DBACCESS ORowSetBase::setCurrentRow() Clone = %i ID = %i\n",m_bClone,osl_getThreadIdentifier(NULL)); + m_bBeforeFirst = m_pCache->isBeforeFirst(); + m_bAfterLast = m_pCache->isAfterLast(); + //m_pCache->resetInsertRow(sal_True); + + if(!(m_bBeforeFirst || m_bAfterLast)) + { + m_aBookmark = m_pCache->getBookmark(); + OSL_ENSURE(m_aBookmark.hasValue(),"Bookmark has no value!"); + m_aCurrentRow = m_pCache->m_aMatrixIter; + OSL_ENSURE(!m_aCurrentRow.isNull(),"CurrentRow is null!"); + m_aCurrentRow.setBookmark(m_aBookmark); + OSL_ENSURE(!m_aCurrentRow.isNull() && m_aCurrentRow != m_pCache->getEnd(),"Position of matrix iterator isn't valid!"); + OSL_ENSURE(m_aCurrentRow->isValid(),"Currentrow isn't valid"); + OSL_ENSURE(m_aBookmark.hasValue(),"Bookmark has no value!"); + +#if OSL_DEBUG_LEVEL > 0 + sal_Int32 nOldRow = m_pCache->getRow(); +#endif + positionCache( MOVE_NONE_REFRESH_ONLY ); +#if OSL_DEBUG_LEVEL > 0 + sal_Int32 nNewRow = m_pCache->getRow(); +#endif + OSL_ENSURE(nOldRow == nNewRow,"Old position is not equal to new postion"); + m_aCurrentRow = m_pCache->m_aMatrixIter; + OSL_ENSURE(!m_aCurrentRow.isNull(),"CurrentRow is nul after positionCache!"); +#if OSL_DEBUG_LEVEL > 0 + ORowSetRow rRow = (*m_aCurrentRow); + OSL_ENSURE(rRow.isValid() ,"Invalid size of vector!"); +#endif + // the cache could repositioned so we need to adjust the cache + // #104144# OJ + if ( _bMoved && m_aCurrentRow.isNull() ) + { + positionCache( MOVE_NONE_REFRESH_ONLY ); + m_aCurrentRow = m_pCache->m_aMatrixIter; + OSL_ENSURE(!m_aCurrentRow.isNull(),"CurrentRow is nul after positionCache!"); + } + } + else + { + m_aOldRow->clearRow(); + m_aCurrentRow = m_pCache->getEnd(); + m_aBookmark = Any(); + m_aCurrentRow.setBookmark(m_aBookmark); + } + + // notification order + // - column values + if ( _bDoNotify ) + firePropertyChange(_rOldValues); + + // TODO: can this be done before the notifications? + if(!(m_bBeforeFirst || m_bAfterLast) && !m_aCurrentRow.isNull() && m_aCurrentRow->isValid() && m_aCurrentRow != m_pCache->getEnd()) + m_aOldRow->setRow(new ORowSetValueVector(m_aCurrentRow->getBody())); + + if ( _bMoved && _bDoNotify ) + // - cursorMoved + notifyAllListenersCursorMoved( _rGuard ); + + DBG_TRACE2("DBACCESS ORowSetBase::setCurrentRow() Clone = %i ID = %i\n",m_bClone,osl_getThreadIdentifier(NULL)); +} +// ----------------------------------------------------------------------------- +void ORowSetBase::checkPositioningAllowed() throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::checkPositioningAllowed" ); + if(!m_pCache || m_nResultSetType == ResultSetType::FORWARD_ONLY) + throwFunctionSequenceException(*m_pMySelf); +} +//------------------------------------------------------------------------------ +Reference< XInterface > ORowSetBase::getStatement(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getStatement" ); + return NULL; +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSetBase::refreshRow( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::refreshRow" ); + ::connectivity::checkDisposed(m_rBHelper.bDisposed); + ::osl::MutexGuard aGuard( *m_pMutex ); + checkCache(); + if ( impl_rowDeleted() ) + throwSQLException( "The current row is deleted", SQL_INVALID_CURSOR_STATE, Reference< XRowSet >( this ) ); + + if(!(m_bBeforeFirst || m_bAfterLast)) + { + positionCache( MOVE_NONE_REFRESH_ONLY ); + m_pCache->refreshRow(); + } +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ORowSetBase::rowUpdated( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::rowUpdated" ); + ::osl::MutexGuard aGuard( *m_pMutex ); + checkCache(); + + if ( impl_rowDeleted() ) + return sal_False; + + return m_pCache->rowUpdated(); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ORowSetBase::rowInserted( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::rowInserted" ); + ::osl::MutexGuard aGuard( *m_pMutex ); + + checkCache(); + + if ( impl_rowDeleted() ) + return sal_False; + + return m_pCache->rowInserted(); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ORowSetBase::rowDeleted( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::rowDeleted" ); + ::osl::MutexGuard aGuard( *m_pMutex ); + checkCache(); + return impl_rowDeleted(); +} +// ------------------------------------------------------------------------- +sal_Bool ORowSetBase::impl_rowDeleted( ) +{ + return !m_aBookmark.hasValue() && !m_bBeforeFirst && !m_bAfterLast; +} +// ------------------------------------------------------------------------- +// XWarningsSupplier +Any SAL_CALL ORowSetBase::getWarnings( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getWarnings" ); + ::osl::MutexGuard aGuard( *m_pMutex ); + + if ( m_pCache ) + { + Reference< XWarningsSupplier > xWarnings( m_pCache->m_xSet.get(), UNO_QUERY ); + if ( xWarnings.is() ) + return xWarnings->getWarnings(); + } + + return Any(); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSetBase::clearWarnings( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::clearWarnings" ); + ::osl::MutexGuard aGuard( *m_pMutex ); + + if ( m_pCache ) + { + Reference< XWarningsSupplier > xWarnings( m_pCache->m_xSet.get(), UNO_QUERY ); + if ( xWarnings.is() ) + xWarnings->clearWarnings(); + } +} +// ------------------------------------------------------------------------- +void ORowSetBase::firePropertyChange(const ORowSetRow& _rOldRow) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::firePropertyChange" ); + DBG_TRACE2("DBACCESS ORowSetBase::firePropertyChange() Clone = %i ID = %i\n",m_bClone,osl_getThreadIdentifier(NULL)); + OSL_ENSURE(m_pColumns,"Columns can not be NULL here!"); +#if OSL_DEBUG_LEVEL > 1 + sal_Bool bNull; + ORowSetMatrix::iterator atest; + bNull = m_aCurrentRow.isNull(); + atest = m_aCurrentRow; +#endif + sal_Int32 i=0; + try + { + TDataColumns::iterator aEnd = m_aDataColumns.end(); + for(TDataColumns::iterator aIter = m_aDataColumns.begin();aIter != aEnd;++aIter,++i) // #104278# OJ ++i inserted + (*aIter)->fireValueChange(_rOldRow.isValid() ? (_rOldRow->get())[i+1] : ::connectivity::ORowSetValue()); + } + catch(Exception&) + { + OSL_ENSURE(0,"firePropertyChange: Exception"); + } + DBG_TRACE2("DBACCESS ORowSetBase::firePropertyChange() Clone = %i ID = %i\n",m_bClone,osl_getThreadIdentifier(NULL)); +} +// ------------------------------------------------------------------------- +void ORowSetBase::firePropertyChange(sal_Int32 _nPos,const ::connectivity::ORowSetValue& _rOldValue) +{ + OSL_ENSURE(_nPos < (sal_Int32)m_aDataColumns.size(),"nPos is invalid!"); + m_aDataColumns[_nPos]->fireValueChange(_rOldValue); +} +// ----------------------------------------------------------------------------- +void ORowSetBase::fireRowcount() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::fireRowcount" ); +} + +// ----------------------------------------------------------------------------- +sal_Bool ORowSetBase::notifyAllListenersCursorBeforeMove(::osl::ResettableMutexGuard& /*_rGuard*/) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::notifyAllListenersCursorBeforeMove" ); + return sal_True; +} + +// ----------------------------------------------------------------------------- +void ORowSetBase::notifyAllListenersCursorMoved(::osl::ResettableMutexGuard& /*_rGuard*/) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::notifyAllListenersCursorMoved" ); +} + +// ----------------------------------------------------------------------------- +void ORowSetBase::notifyAllListeners(::osl::ResettableMutexGuard& /*_rGuard*/) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::notifyAllListeners" ); +} + +// ----------------------------------------------------------------------------- +void ORowSetBase::fireProperty( sal_Int32 _nProperty, sal_Bool _bNew, sal_Bool _bOld ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::fireProperty" ); + Any aNew = bool2any( _bNew ); + Any aOld = bool2any( _bOld ); + fire( &_nProperty, &aNew, &aOld, 1, sal_False ); +} + +// ----------------------------------------------------------------------------- +void ORowSetBase::positionCache( CursorMoveDirection _ePrepareForDirection ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::positionCache" ); + DBG_TRACE2("DBACCESS ORowSetBase::positionCache() Clone = %i ID = %i\n",m_bClone,osl_getThreadIdentifier(NULL)); + + sal_Bool bSuccess = sal_False; + if ( m_aBookmark.hasValue() ) + { + bSuccess = m_pCache->moveToBookmark( m_aBookmark ); + } + else + { + if ( m_bBeforeFirst ) + { + bSuccess = m_pCache->beforeFirst(); + } + else if ( m_bAfterLast ) + { + bSuccess = m_pCache->afterLast(); + } + else + { + OSL_ENSURE( m_nDeletedPosition >= 1, "ORowSetBase::positionCache: no bookmark, and no valid 'deleted position'!" ); + switch ( _ePrepareForDirection ) + { + case MOVE_FORWARD: + if ( m_nDeletedPosition > 1 ) + bSuccess = m_pCache->absolute( m_nDeletedPosition - 1 ); + else + { + m_pCache->beforeFirst(); + bSuccess = sal_True; + } + break; + + case MOVE_BACKWARD: + if ( m_pCache->m_bRowCountFinal && ( m_nDeletedPosition == impl_getRowCount() ) ) + { + m_pCache->afterLast(); + bSuccess = sal_True; + } + else + bSuccess = m_pCache->absolute( m_nDeletedPosition ); + break; + + case MOVE_NONE_REFRESH_ONLY: + bSuccess = sal_False; // will be asserted below + break; + } + } + } + OSL_ENSURE( bSuccess, "ORowSetBase::positionCache: failed!" ); + + DBG_TRACE2("DBACCESS ORowSetBase::positionCache() Clone = %i ID = %i\n",m_bClone,osl_getThreadIdentifier(NULL)); +} +// ----------------------------------------------------------------------------- +void ORowSetBase::checkCache() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::checkCache" ); + ::connectivity::checkDisposed(m_rBHelper.bDisposed); + if(!m_pCache) + throwFunctionSequenceException(*m_pMySelf); +} +// ----------------------------------------------------------------------------- +void ORowSetBase::movementFailed() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::movementFailed" ); + DBG_TRACE2("DBACCESS ORowSetBase::movementFailed() Clone = %i ID = %i\n",m_bClone,osl_getThreadIdentifier(NULL)); + m_aOldRow->clearRow(); + m_aCurrentRow = m_pCache->getEnd(); + m_bBeforeFirst = m_pCache->isBeforeFirst(); + m_bAfterLast = m_pCache->isAfterLast(); + m_aBookmark = Any(); + m_aCurrentRow.setBookmark(m_aBookmark); + OSL_ENSURE(m_bBeforeFirst || m_bAfterLast,"BeforeFirst or AfterLast is wrong!"); + DBG_TRACE2("DBACCESS ORowSetBase::movementFailed() Clone = %i ID = %i\n",m_bClone,osl_getThreadIdentifier(NULL)); +} +// ----------------------------------------------------------------------------- +ORowSetRow ORowSetBase::getOldRow(sal_Bool _bWasNew) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getOldRow" ); + OSL_ENSURE(m_aOldRow.isValid(),"RowSetRowHElper isn't valid!"); + ORowSetRow aOldValues; + if ( !_bWasNew && m_aOldRow->getRow().isValid() ) + aOldValues = new ORowSetValueVector( m_aOldRow->getRow().getBody()); // remember the old values + return aOldValues; +} +// ----------------------------------------------------------------------------- +void ORowSetBase::getPropertyDefaultByHandle( sal_Int32 /*_nHandle*/, Any& _rDefault ) const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getPropertyDefaultByHandle" ); + _rDefault.clear(); +} +// ----------------------------------------------------------------------------- +void ORowSetBase::onDeleteRow( const Any& _rBookmark ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::onDeleteRow" ); + if ( rowDeleted() ) + // not interested in + return; + + ::osl::MutexGuard aGuard( *m_pMutex ); + //OSL_ENSURE( m_aBookmark.hasValue(), "ORowSetBase::onDeleteRow: Bookmark isn't valid!" ); + if ( compareBookmarks( _rBookmark, m_aBookmark ) == 0 ) + { + positionCache( MOVE_NONE_REFRESH_ONLY ); + m_nDeletedPosition = m_pCache->getRow(); + } +} +// ----------------------------------------------------------------------------- +void ORowSetBase::onDeletedRow( const Any& _rBookmark, sal_Int32 _nPos ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::onDeletedRow" ); + if ( rowDeleted() ) + { + // if we're a clone, and on a deleted row, and the main RowSet deleted another + // row (only the main RowSet can, clones can't), which is *before* our + // deleted position, then we have to adjust this position + if ( m_bClone && ( _nPos < m_nDeletedPosition ) ) + --m_nDeletedPosition; + return; + } + + ::osl::MutexGuard aGuard( *m_pMutex ); + if ( compareBookmarks( _rBookmark, m_aBookmark ) == 0 ) + { + m_aOldRow->clearRow(); + m_aCurrentRow = m_pCache->getEnd(); + m_aBookmark = Any(); + m_aCurrentRow.setBookmark( m_aBookmark ); + } +} +// ----------------------------------------------------------------------------- +sal_Int32 ORowSetBase::impl_getRowCount() const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::impl_getRowCount" ); + sal_Int32 nRowCount( m_pCache->m_nRowCount ); + if ( const_cast< ORowSetBase* >( this )->rowDeleted() && !m_pCache->m_bNew ) + ++nRowCount; + return nRowCount; +} +// ============================================================================= +struct ORowSetNotifierImpl +{ + ::std::vector<sal_Int32> aChangedColumns; + ::std::vector<Any> aChangedBookmarks; + ORowSetValueVector::Vector aRow; + +}; +DBG_NAME(ORowSetNotifier) +// ----------------------------------------------------------------------------- +ORowSetNotifier::ORowSetNotifier( ORowSetBase* _pRowSet ) + :m_pRowSet( _pRowSet ) + ,m_bWasNew( sal_False ) + ,m_bWasModified( sal_False ) +#ifdef DBG_UTIL + ,m_bNotifyCalled( sal_False ) +#endif +{ + DBG_CTOR(ORowSetNotifier,NULL); + + OSL_ENSURE( m_pRowSet, "ORowSetNotifier::ORowSetNotifier: invalid row set. This wil crash." ); + + // remember the "inserted" and "modified" state for later firing + m_bWasNew = m_pRowSet->isNew( ORowSetBase::GrantNotifierAccess() ); + m_bWasModified = m_pRowSet->isModified( ORowSetBase::GrantNotifierAccess() ); + + // if the row set is on the insert row, then we need to cancel this + if ( m_pRowSet->isModification( ORowSetBase::GrantNotifierAccess() ) ) + m_pRowSet->doCancelModification( ORowSetBase::GrantNotifierAccess() ); +} +// ----------------------------------------------------------------------------- +ORowSetNotifier::ORowSetNotifier( ORowSetBase* _pRowSet,const ORowSetValueVector::Vector& i_aRow ) + :m_pImpl(new ORowSetNotifierImpl) + ,m_pRowSet( _pRowSet ) + ,m_bWasNew( sal_False ) + ,m_bWasModified( sal_False ) +#ifdef DBG_UTIL + ,m_bNotifyCalled( sal_False ) +#endif +{ + DBG_CTOR(ORowSetNotifier,NULL); + + OSL_ENSURE( m_pRowSet, "ORowSetNotifier::ORowSetNotifier: invalid row set. This wil crash." ); + m_pImpl->aRow = i_aRow; // yes, create a copy to store the old values +} +// ----------------------------------------------------------------------------- +ORowSetNotifier::~ORowSetNotifier( ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetNotifier::~ORowSetNotifier" ); + DBG_DTOR(ORowSetNotifier,NULL); +} + +// ----------------------------------------------------------------------------- +void ORowSetNotifier::fire() +{ + // we're not interested in firing changes FALSE->TRUE, only TRUE->FALSE. + // (the former would be quite pathological, e.g. after a failed movement) + + if ( m_bWasModified + && ( m_bWasModified != m_pRowSet->isModified( ORowSetBase::GrantNotifierAccess() ) ) + ) + m_pRowSet->fireProperty( PROPERTY_ID_ISMODIFIED, sal_False, sal_True, ORowSetBase::GrantNotifierAccess() ); + + if ( m_bWasNew + && ( m_bWasNew != m_pRowSet->isNew( ORowSetBase::GrantNotifierAccess() ) ) + ) + m_pRowSet->fireProperty( PROPERTY_ID_ISNEW, sal_False, sal_True, ORowSetBase::GrantNotifierAccess() ); + +#ifdef DBG_UTIL + m_bNotifyCalled = sal_True; +#endif +} +// ----------------------------------------------------------------------------- +::std::vector<sal_Int32>& ORowSetNotifier::getChangedColumns() const +{ + OSL_ENSURE(m_pImpl.get(),"Illegal CTor call, use the other one!"); + return m_pImpl->aChangedColumns; +} +// ----------------------------------------------------------------------------- +::std::vector<Any>& ORowSetNotifier::getChangedBookmarks() const +{ + OSL_ENSURE(m_pImpl.get(),"Illegal CTor call, use the other one!"); + return m_pImpl->aChangedBookmarks; +} +// ----------------------------------------------------------------------------- +void ORowSetNotifier::firePropertyChange() +{ + OSL_ENSURE(m_pImpl.get(),"Illegal CTor call, use the other one!"); + if( m_pImpl.get() ) + { + ::std::vector<sal_Int32>::iterator aIter = m_pImpl->aChangedColumns.begin(); + for(;aIter != m_pImpl->aChangedColumns.end();++aIter) + { + m_pRowSet->firePropertyChange((*aIter)-1 ,m_pImpl->aRow[(*aIter)-1], ORowSetBase::GrantNotifierAccess()); + } + m_pRowSet->fireProperty(PROPERTY_ID_ISMODIFIED,sal_True,sal_False, ORowSetBase::GrantNotifierAccess()); + } +} +} // namespace dbaccess diff --git a/dbaccess/source/core/api/RowSetBase.hxx b/dbaccess/source/core/api/RowSetBase.hxx new file mode 100644 index 000000000000..9a7e9182e1d0 --- /dev/null +++ b/dbaccess/source/core/api/RowSetBase.hxx @@ -0,0 +1,463 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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_CORE_API_ROWSETBASE_HXX +#define DBACCESS_CORE_API_ROWSETBASE_HXX + +#ifndef _CPPUHELPER_IMPLBASE10_HXX_ +#include <cppuhelper/implbase10.hxx> +#endif +#ifndef _COM_SUN_STAR_SDBCX_XCOLUMNSSUPPLIER_HPP_ +#include <com/sun/star/sdbcx/XColumnsSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XROW_HPP_ +#include <com/sun/star/sdbc/XRow.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XCOLUMNLOCATE_HPP_ +#include <com/sun/star/sdbc/XColumnLocate.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XCLOSEABLE_HPP_ +#include <com/sun/star/sdbc/XCloseable.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBCX_XROWLOCATE_HPP_ +#include <com/sun/star/sdbcx/XRowLocate.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XRESULTSETMETADATASUPPLIER_HPP_ +#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XWARNINGSSUPPLIER_HPP_ +#include <com/sun/star/sdbc/XWarningsSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_ +#include <com/sun/star/lang/XServiceInfo.hpp> +#endif +#ifndef _COM_SUN_STAR_LANG_XUNOTUNNEL_HPP_ +#include <com/sun/star/lang/XUnoTunnel.hpp> +#endif +#ifndef _CPPUHELPER_INTERFACECONTAINER_H_ +#include <cppuhelper/interfacecontainer.h> +#endif +#ifndef CONNECTIVITY_SQLERROR_HXX +#include <connectivity/sqlerror.hxx> +#endif +#ifndef _CONNECTIVITY_COMMONTOOLS_HXX_ +#include <connectivity/CommonTools.hxx> +#endif +#ifndef COMPHELPER_PROPERTYSTATECONTAINER_HXX +#include <comphelper/propertystatecontainer.hxx> +#endif +#ifndef _COMPHELPER_PROPERTY_ARRAY_HELPER_HXX_ +#include <comphelper/proparrhlp.hxx> +#endif +#ifndef _COM_SUN_STAR_SDBC_XROWSET_HPP_ +#include <com/sun/star/sdbc/XRowSet.hpp> +#endif +#ifndef _COM_SUN_STAR_UTIL_XNUMBERFORMATTYPES_HPP_ +#include <com/sun/star/util/XNumberFormatTypes.hpp> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_ +#include <com/sun/star/container/XNameAccess.hpp> +#endif +#ifndef DBACCESS_CORE_API_ROWSETROW_HXX +#include "RowSetRow.hxx" +#endif +#ifndef _COMPHELPER_BROADCASTHELPER_HXX_ +#include <comphelper/broadcasthelper.hxx> +#endif +#ifndef DBACCESS_ROWSETCACHEITERATOR_HXX +#include "RowSetCacheIterator.hxx" +#endif +#include "core_resource.hxx" +#include <comphelper/componentcontext.hxx> + +#include <functional> + + +namespace com { namespace sun { namespace star { + namespace sdb { struct RowChangeEvent; } + namespace lang { struct Locale; } +} } } + +namespace dbaccess +{ + class OEmptyCollection; + + typedef ::cppu::ImplHelper10< ::com::sun::star::sdbcx::XRowLocate, + ::com::sun::star::sdbc::XRow, + ::com::sun::star::sdbc::XResultSetMetaDataSupplier, + ::com::sun::star::sdbc::XWarningsSupplier, + ::com::sun::star::sdbc::XColumnLocate, + ::com::sun::star::sdbcx::XColumnsSupplier, + ::com::sun::star::lang::XServiceInfo, + ::com::sun::star::sdbc::XRowSet, + ::com::sun::star::sdbc::XCloseable, + ::com::sun::star::lang::XUnoTunnel> ORowSetBase_BASE; + + class ORowSetCache; + class ORowSetDataColumns; + class ORowSetCacheIterator; + class ORowSetDataColumn; + class ORowSetBase : public ORowSetBase_BASE, + public ::comphelper::OPropertyStateContainer, + public ::comphelper::OPropertyArrayUsageHelper<ORowSetBase> // this class hold the static property info + { + OModuleClient m_aModuleClient; + protected: + typedef ::std::vector<ORowSetDataColumn*> TDataColumns; + ::osl::Mutex* m_pMutex; // this the mutex form the rowset itself + ::osl::Mutex m_aRowCountMutex, // mutex for rowcount changes + // we need a extra mutex for columns to prevend deadlock when setting new values + // for a row + m_aColumnsMutex; + + ::com::sun::star::uno::Any m_aBookmark; + ORowSetCacheIterator m_aCurrentRow; // contains the actual fetched row + TORowSetOldRowHelperRef m_aOldRow; + TDataColumns m_aDataColumns; // holds the columns as m_pColumns but know the implementation class + connectivity::ORowSetValue m_aEmptyValue; // only for error case + + ::cppu::OWeakObject* m_pMySelf; // set by derived classes + ORowSetCache* m_pCache; // the cache is used by the rowset and his clone (shared) + ORowSetDataColumns* m_pColumns; // represent the select columns + ::cppu::OBroadcastHelper& m_rBHelper; // must be set from the derived classes + // is used when the formatkey for database types is set + ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatTypes> m_xNumberFormatTypes; + OEmptyCollection* m_pEmptyCollection; + + ::comphelper::ComponentContext m_aContext; + ::connectivity::SQLError m_aErrors; + + sal_Int32 m_nLastColumnIndex; // the last column ask for, used for wasNull() + sal_Int32 m_nDeletedPosition; // is set only when a row was deleted + sal_Int32 m_nResultSetType; // fetch property + sal_Int32 m_nResultSetConcurrency; + sal_Bool m_bClone; // I'm clone or not + sal_Bool m_bIgnoreResult ; + sal_Bool m_bBeforeFirst : 1; + sal_Bool m_bAfterLast : 1; + + protected: + ORowSetBase( + const ::comphelper::ComponentContext& _rContext, + ::cppu::OBroadcastHelper& _rBHelper, + ::osl::Mutex* _pMutex + ); + + // fire a notification for all that are listening on column::VALUE property + void firePropertyChange(const ORowSetRow& _rOldRow); + // fire a change for one column + // _nPos starts at zero + void firePropertyChange(sal_Int32 _nPos,const ::connectivity::ORowSetValue& _rNewValue); + + // fire if rowcount changed + virtual void fireRowcount(); + // notify row changed + virtual sal_Bool notifyAllListenersCursorBeforeMove(::osl::ResettableMutexGuard& _rGuard); + // notify cursor moved + virtual void notifyAllListenersCursorMoved(::osl::ResettableMutexGuard& _rGuard); + // notify all that rowset changed + virtual void notifyAllListeners(::osl::ResettableMutexGuard& _rGuard); + + // cancel the insertion, if necessary (means if we're on the insert row) + virtual void doCancelModification( ) = 0; + // return <TRUE/> if and only if we're using the insert row (means: we're updating _or_ inserting) + virtual sal_Bool isModification( ) = 0; + // return <TRUE/> if and only if the current row is modified + // TODO: isn't this the same as isModification? + virtual sal_Bool isModified( ) = 0; + // return <TRUE/> if and only if the current row is the insert row + virtual sal_Bool isNew( ) = 0; + // notify the change of a boolean property + void fireProperty( sal_Int32 _nProperty, sal_Bool _bNew, sal_Bool _bOld ); + + // OPropertyStateContainer + virtual void getPropertyDefaultByHandle( sal_Int32 _nHandle, ::com::sun::star::uno::Any& _rDefault ) const; + virtual void SAL_CALL getFastPropertyValue(::com::sun::star::uno::Any& rValue,sal_Int32 nHandle) const; + + enum CursorMoveDirection + { + /// denotes a cursor move forward + MOVE_FORWARD, + /// denotes a cursor move backwards + MOVE_BACKWARD, + /// denotes no cursor move at all, used when the current row is to be refreshed only + MOVE_NONE_REFRESH_ONLY + }; + /** positions the cache in preparation of a cursor move + + Normally, the cache is simply moved to our bookmark (m_aBookmark). If however the current + row is deleted, then the cache is properly positioned for a following cursor movement in the + given direction. + + @param _ePrepareForDirection + the direction into which the cursor should be moved after the call. If we're currently not on + a deleted row, this parameter is ignored, since in this case the cache is simply moved to + m_aBookmark.</br> + If, however, we're currently on a deleted row, this is used to properly position the cache + using <member>m_nDeletedPosition</member>.<br/> + In this case, MOVE_NONE_REFRESH_ONLY is not supported. This is because the deleted row + (to which the RowSet currently points to) is not present in the cache. So, you cannot move the + cache to this row. + */ + void positionCache( CursorMoveDirection _ePrepareForDirection ); + + // returns a value of a column of the current row + const connectivity::ORowSetValue& getValue(sal_Int32 columnIndex); + // the cache has to be checked before calling this method + const connectivity::ORowSetValue& impl_getValue(sal_Int32 columnIndex); + // sets the current and the bookmark + void setCurrentRow( sal_Bool _bMoved, sal_Bool _bDoNotify, const ORowSetRow& _rOldValues, ::osl::ResettableMutexGuard& _rGuard); + void checkPositioningAllowed() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + // checks if the cache is null + void checkCache(); + // sets the bookmark to Any() + // m_aCurrentRow to end of matrix + // m_aOldRow to NULL + void movementFailed(); + + ORowSetRow getOldRow(sal_Bool _bWasNew); + /** move the cache the postion defined by the member functor + @param _aCheckFunctor + Return <TRUE/> when we already stand on the row we want to. + @param _aMovementFunctor + The mehtod used to move. + @return + <TRUE/> if movement was successful. + */ + sal_Bool SAL_CALL move( ::std::mem_fun_t<sal_Bool,ORowSetBase>& _aCheckFunctor, + ::std::mem_fun_t<sal_Bool,ORowSetCache>& _aMovementFunctor); + + /** same meaning as isFirst. Only need by mem_fun + @return + <TRUE/> if so. + */ + sal_Bool isOnFirst(); + /** same meaning as isLast. Only need by mem_fun + @return + <TRUE/> if so. + */ + sal_Bool isOnLast(); + + /** returns the current row count + + This function takes into account that we might actually be positioned on a + deleted row, so that m_pCache->m_nRowCount does not really reflect the actual + count. + + @precond + Our mutext is locked. + */ + sal_Int32 impl_getRowCount() const; + + // the checkCache has to be called before calling this methods + sal_Bool impl_wasNull(); + sal_Int32 impl_getRow(); + sal_Bool impl_rowDeleted(); + + public: + virtual ~ORowSetBase(); + + // OComponentHelper + virtual void SAL_CALL disposing(void); + + // 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) + { + return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper()); + } + + // comphelper::OPropertyArrayUsageHelper + virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const; + + // cppu::OPropertySetHelper + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(); + + // com::sun::star::lang::XTypeProvider + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes() throw (::com::sun::star::uno::RuntimeException); + + // com::sun::star::uno::XInterface + virtual ::com::sun::star::uno::Any SAL_CALL queryInterface( const ::com::sun::star::uno::Type & rType ) throw (::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbc::XWarningsSupplier + virtual ::com::sun::star::uno::Any SAL_CALL getWarnings( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL clearWarnings( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbc::XResultSetMetaDataSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSetMetaData > SAL_CALL getMetaData( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbc::XColumnLocate + virtual sal_Int32 SAL_CALL findColumn( const ::rtl::OUString& columnName ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbcx::XColumnsSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > SAL_CALL getColumns( ) throw(::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbc::XRow + virtual sal_Bool SAL_CALL wasNull( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getString( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL getBoolean( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int8 SAL_CALL getByte( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int16 SAL_CALL getShort( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getInt( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int64 SAL_CALL getLong( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual float SAL_CALL getFloat( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual double SAL_CALL getDouble( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getBytes( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::util::Date SAL_CALL getDate( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::util::Time SAL_CALL getTime( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::util::DateTime SAL_CALL getTimestamp( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getBinaryStream( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getCharacterStream( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Any SAL_CALL getObject( sal_Int32 columnIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& typeMap ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRef > SAL_CALL getRef( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XBlob > SAL_CALL getBlob( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XClob > SAL_CALL getClob( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XArray > SAL_CALL getArray( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbcx::XRowLocate + virtual ::com::sun::star::uno::Any SAL_CALL getBookmark( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL moveToBookmark( const ::com::sun::star::uno::Any& bookmark ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL moveRelativeToBookmark( const ::com::sun::star::uno::Any& bookmark, sal_Int32 rows ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL compareBookmarks( const ::com::sun::star::uno::Any& first, const ::com::sun::star::uno::Any& second ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL hasOrderedBookmarks( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL hashBookmark( const ::com::sun::star::uno::Any& bookmark ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbc::XResultSet + virtual sal_Bool SAL_CALL next( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isBeforeFirst( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isAfterLast( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isFirst( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isLast( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL beforeFirst( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL afterLast( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL first( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL last( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL absolute( sal_Int32 row ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL relative( sal_Int32 rows ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL previous( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL refreshRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL rowUpdated( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL rowInserted( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL rowDeleted( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL getStatement( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbc::XRowSet + virtual void SAL_CALL execute( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) = 0; + virtual void SAL_CALL addRowSetListener( const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowSetListener >& listener ) throw(::com::sun::star::uno::RuntimeException) = 0; + virtual void SAL_CALL removeRowSetListener( const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowSetListener >& listener ) throw(::com::sun::star::uno::RuntimeException) = 0; + + // is called when the rowset is going to delete this bookmark _rBookmark + void onDeleteRow( const ::com::sun::star::uno::Any& _rBookmark ); + // is called when the rowset has deleted this bookmark _rBookmark + void onDeletedRow( const ::com::sun::star::uno::Any& _rBookmark, sal_Int32 _nPos ); + + // ========================================================== + // granular access control + struct GrantNotifierAccess { friend class ORowSetNotifier; private: GrantNotifierAccess () { } }; + + // cancel the insertion, if necessary (means if we're on the insert row) + inline void doCancelModification( const GrantNotifierAccess& ) { doCancelModification(); } + inline sal_Bool isModification( const GrantNotifierAccess& ) { return isModification(); } + inline sal_Bool isModified( const GrantNotifierAccess& ) { return isModified(); } + inline sal_Bool isNew( const GrantNotifierAccess& ) { return isNew(); } + inline sal_Bool isInsertRow() { return isNew() || isModified(); } + inline void fireProperty( sal_Int32 _nProperty, sal_Bool _bNew, sal_Bool _bOld, const GrantNotifierAccess& ) + { + fireProperty( _nProperty, _bNew, _bOld ); + } + inline void firePropertyChange(sal_Int32 _nPos,const ::connectivity::ORowSetValue& _rNewValue, const GrantNotifierAccess& ) + { + firePropertyChange(_nPos,_rNewValue); + } + using ::comphelper::OPropertyStateContainer::getFastPropertyValue; + + ::osl::Mutex* getMutex() const { return m_pMutex; } + }; + + // ======================================================================== + /** eases the handling of the doCancelModification and notifyCancelInsert methods + + <p>The class can only be used on the stack, within a method of ORowSetBase (or derivees)</p> + */ + struct ORowSetNotifierImpl; + class ORowSetNotifier + { + private: + ::std::auto_ptr<ORowSetNotifierImpl> m_pImpl; + ORowSetBase* m_pRowSet; + // not aquired! This is not necessary because this class here is to be used on the stack within + // a method of ORowSetBase (or derivees) + sal_Bool m_bWasNew; + sal_Bool m_bWasModified; + +#ifdef DBG_UTIL + sal_Bool m_bNotifyCalled; +#endif + + public: + /** constructs the object, and cancels the insertion + + @see ORowSetBase::doCancelModification + */ + ORowSetNotifier( ORowSetBase* m_pRowSet ); + + /** use this one to consturct an vector for change value notification + */ + ORowSetNotifier( ORowSetBase* m_pRowSet,const ORowSetValueVector::Vector& i_aRow ); + + // destructs the object. <member>fire</member> has to be called before. + ~ORowSetNotifier( ); + + /** notifies the insertion + + <p>This has <em>not</em> been put into the destructor by intention!<br/> + + The destructor is called during stack unwinding in case of an exception, so if we would do + listener notification there, this would have the potential of another exception during stack + unwinding, which would terminate the application.</p> + + @see ORowSetBase::notifyCancelInsert + */ + void fire(); + + /** notifies value change events and notifies IsModified + @param i_aChangedColumns the index of the changed value columns + @param i_aRow the old values + @see ORowSetBase::notifyCancelInsert + */ + void firePropertyChange(); + + /** use this one to store the inde of the changed column values + */ + ::std::vector<sal_Int32>& getChangedColumns() const; + ::std::vector<com::sun::star::uno::Any>& getChangedBookmarks() const; + + }; + +} // end of namespace + +#endif // DBACCESS_CORE_API_ROWSETBASE_HXX + diff --git a/dbaccess/source/core/api/RowSetCache.cxx b/dbaccess/source/core/api/RowSetCache.cxx new file mode 100644 index 000000000000..92e29ac784ba --- /dev/null +++ b/dbaccess/source/core/api/RowSetCache.cxx @@ -0,0 +1,1722 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#ifndef _COMPHELPER_SEQSTREAM_HXX +#include <comphelper/seqstream.hxx> +#endif +#ifndef _COMPHELPER_UNO3_HXX_ +#include <comphelper/uno3.hxx> +#endif +#ifndef _COMPHELPER_EXTRACT_HXX_ +#include <comphelper/extract.hxx> +#endif +#ifndef _COM_SUN_STAR_SDBCX_XKEYSSUPPLIER_HPP_ +#include <com/sun/star/sdbcx/XKeysSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBCX_XTABLESSUPPLIER_HPP_ +#include <com/sun/star/sdbcx/XTablesSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBCX_KEYTYPE_HPP_ +#include <com/sun/star/sdbcx/KeyType.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_RESULTSETCONCURRENCY_HPP_ +#include <com/sun/star/sdbc/ResultSetConcurrency.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_COLUMNVALUE_HPP_ +#include <com/sun/star/sdbc/ColumnValue.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBCX_XCOLUMNSSUPPLIER_HPP_ +#include <com/sun/star/sdbcx/XColumnsSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBCX_PRIVILEGE_HPP_ +#include <com/sun/star/sdbcx/Privilege.hpp> +#endif +#ifndef _DBACORE_DATACOLUMN_HXX_ +#include "CRowSetDataColumn.hxx" +#endif +#ifndef DBACCESS_CORE_API_CROWSETCOLUMN_HXX +#include "CRowSetColumn.hxx" +#endif +#ifndef DBACCESS_CORE_API_ROWSETBASE_HXX +#include "RowSetBase.hxx" +#endif +#include <connectivity/dbexception.hxx> +#include <connectivity/sqlparse.hxx> +#include <connectivity/sqlnode.hxx> +#include <connectivity/dbtools.hxx> +#include <connectivity/sqliterator.hxx> +#ifndef _COMPHELPER_PROPERTY_HXX_ +#include <comphelper/property.hxx> +#endif +#ifndef _COM_SUN_STAR_SDBCX_COMPAREBOOKMARK_HPP_ +#include <com/sun/star/sdbcx/CompareBookmark.hpp> +#endif +#ifndef _TOOLS_DEBUG_HXX +#include <tools/debug.hxx> +#endif + +#include <algorithm> +#ifndef DBACCESS_CORE_API_ROWSETCACHE_HXX +#include "RowSetCache.hxx" +#endif +#ifndef _DBA_CORE_RESOURCE_HXX_ +#include "core_resource.hxx" +#endif +#ifndef _DBA_CORE_RESOURCE_HRC_ +#include "core_resource.hrc" +#endif +#ifndef DBACCESS_CORE_API_BOOKMARKSET_HXX +#include "BookmarkSet.hxx" +#endif +#ifndef DBACCESS_CORE_API_STATICSET_HXX +#include "StaticSet.hxx" +#endif +#ifndef DBACCESS_CORE_API_KEYSET_HXX +#include "KeySet.hxx" +#endif +#ifndef DBACCESS_SHARED_DBASTRINGS_HRC +#include "dbastrings.hrc" +#endif +#include "WrappedResultSet.hxx" +#include "OptimisticSet.hxx" + +using namespace dbaccess; +using namespace dbtools; +using namespace connectivity; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +using namespace ::cppu; +using namespace ::osl; + +#define CHECK_MATRIX_POS(M) OSL_ENSURE(((M) >= static_cast<ORowSetMatrix::difference_type>(0)) && ((M) < static_cast<sal_Int32>(m_pMatrix->size())),"Position is invalid!") + +DBG_NAME(ORowSetCache) +// ------------------------------------------------------------------------- +ORowSetCache::ORowSetCache(const Reference< XResultSet >& _xRs, + const Reference< XSingleSelectQueryAnalyzer >& _xAnalyzer, + const ::comphelper::ComponentContext& _rContext, + const ::rtl::OUString& _rUpdateTableName, + sal_Bool& _bModified, + sal_Bool& _bNew, + const ORowSetValueVector& _aParameterValueForCache, + const ::rtl::OUString& i_sRowSetFilter) + :m_xSet(_xRs) + ,m_xMetaData(Reference< XResultSetMetaDataSupplier >(_xRs,UNO_QUERY)->getMetaData()) + ,m_aContext( _rContext ) + ,m_pCacheSet(NULL) + ,m_pMatrix(NULL) + ,m_pInsertMatrix(NULL) + ,m_nLastColumnIndex(0) + ,m_nFetchSize(0) + ,m_nRowCount(0) + ,m_nPrivileges( Privilege::SELECT ) + ,m_nPosition(0) + ,m_nStartPos(0) + ,m_nEndPos(0) + ,m_bRowCountFinal(sal_False) + ,m_bBeforeFirst(sal_True) + ,m_bAfterLast( sal_False ) + ,m_bUpdated(sal_False) + ,m_bModified(_bModified) + ,m_bNew(_bNew) +{ + DBG_CTOR(ORowSetCache,NULL); + + // first try if the result can be used to do inserts and updates + try + { + Reference< XResultSetUpdate> xUp(_xRs,UNO_QUERY_THROW); + Reference< XPropertySet> xProp(_xRs,UNO_QUERY); + Reference< XPropertySetInfo > xPropInfo = xProp->getPropertySetInfo(); + sal_Bool bBookmarkable = xPropInfo->hasPropertyByName(PROPERTY_ISBOOKMARKABLE) && + any2bool(xProp->getPropertyValue(PROPERTY_ISBOOKMARKABLE)) && Reference< XRowLocate >(_xRs, UNO_QUERY).is(); + if ( bBookmarkable ) + { + xUp->moveToInsertRow(); + xUp->cancelRowUpdates(); + _xRs->beforeFirst(); + m_nPrivileges = Privilege::SELECT|Privilege::DELETE|Privilege::INSERT|Privilege::UPDATE; + m_pCacheSet = new WrappedResultSet(); + m_xCacheSet = m_pCacheSet; + m_pCacheSet->construct(_xRs,i_sRowSetFilter); + return; + } + } + catch(const Exception& ex) + { + (void)ex; + } + _xRs->beforeFirst(); + + // check if all keys of the updateable table are fetched + sal_Bool bAllKeysFound = sal_False; + sal_Int32 nTablesCount = 0; + + Reference< XPropertySet> xProp(_xRs,UNO_QUERY); + Reference< XPropertySetInfo > xPropInfo = xProp->getPropertySetInfo(); + sal_Bool bNeedKeySet = !(xPropInfo->hasPropertyByName(PROPERTY_ISBOOKMARKABLE) && + any2bool(xProp->getPropertyValue(PROPERTY_ISBOOKMARKABLE)) && Reference< XRowLocate >(_xRs, UNO_QUERY).is() ); + bNeedKeySet = bNeedKeySet || (xPropInfo->hasPropertyByName(PROPERTY_RESULTSETCONCURRENCY) && + ::comphelper::getINT32(xProp->getPropertyValue(PROPERTY_RESULTSETCONCURRENCY)) == ResultSetConcurrency::READ_ONLY); + + Reference< XIndexAccess> xUpdateTableKeys; + ::rtl::OUString aUpdateTableName = _rUpdateTableName; + Reference< XConnection> xConnection; + // first we need a connection + Reference< XStatement> xStmt(_xRs->getStatement(),UNO_QUERY); + if(xStmt.is()) + xConnection = xStmt->getConnection(); + else + { + Reference< XPreparedStatement> xPrepStmt(_xRs->getStatement(),UNO_QUERY); + xConnection = xPrepStmt->getConnection(); + } + OSL_ENSURE(xConnection.is(),"No connection!"); + if(_xAnalyzer.is()) + { + try + { + Reference<XTablesSupplier> xTabSup(_xAnalyzer,UNO_QUERY); + OSL_ENSURE(xTabSup.is(),"ORowSet::execute composer isn't a tablesupplier!"); + Reference<XNameAccess> xTables = xTabSup->getTables(); + Sequence< ::rtl::OUString> aTableNames = xTables->getElementNames(); + if ( aTableNames.getLength() > 1 && !_rUpdateTableName.getLength() && bNeedKeySet ) + {// here we have a join or union and nobody told us which table to update, so we update them all + m_nPrivileges = Privilege::SELECT|Privilege::DELETE|Privilege::INSERT|Privilege::UPDATE; + OptimisticSet* pCursor = new OptimisticSet(m_aContext,xConnection,_xAnalyzer,_aParameterValueForCache); + m_pCacheSet = pCursor; + m_xCacheSet = m_pCacheSet; + try + { + m_pCacheSet->construct(_xRs,i_sRowSetFilter); + if ( pCursor->isReadOnly() ) + m_nPrivileges = Privilege::SELECT; + m_aKeyColumns = pCursor->getJoinedKeyColumns(); + return; + } + catch(const Exception&) + { + } + } + else + { + if(_rUpdateTableName.getLength() && xTables->hasByName(_rUpdateTableName)) + xTables->getByName(_rUpdateTableName) >>= m_aUpdateTable; + else if(xTables->getElementNames().getLength()) + { + aUpdateTableName = xTables->getElementNames()[0]; + xTables->getByName(aUpdateTableName) >>= m_aUpdateTable; + } + Reference<XIndexAccess> xIndexAccess(xTables,UNO_QUERY); + if(xIndexAccess.is()) + nTablesCount = xIndexAccess->getCount(); + else + nTablesCount = xTables->getElementNames().getLength(); + + if(m_aUpdateTable.is() && nTablesCount < 3) // for we can't handle more than 2 tables in our keyset + { + Reference<XPropertySet> xSet(m_aUpdateTable,UNO_QUERY); + const Reference<XNameAccess> xPrimaryKeyColumns = dbtools::getPrimaryKeyColumns_throw(xSet); + if ( xPrimaryKeyColumns.is() ) + { + Reference<XColumnsSupplier> xColSup(_xAnalyzer,UNO_QUERY); + if ( xColSup.is() ) + { + Reference<XNameAccess> xSelColumns = xColSup->getColumns(); + Reference<XDatabaseMetaData> xMeta = xConnection->getMetaData(); + SelectColumnsMetaData aColumnNames(xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers() ? true : false); + ::dbaccess::getColumnPositions(xSelColumns,xPrimaryKeyColumns->getElementNames(),aUpdateTableName,aColumnNames); + bAllKeysFound = !aColumnNames.empty() && sal_Int32(aColumnNames.size()) == xPrimaryKeyColumns->getElementNames().getLength(); + } + } + } + } + } + catch(Exception&) + { + } + } + + // first check if resultset is bookmarkable + if(!bNeedKeySet) + { + try + { + m_pCacheSet = new OBookmarkSet(); + m_xCacheSet = m_pCacheSet; + m_pCacheSet->construct(_xRs,i_sRowSetFilter); + + // check privileges + m_nPrivileges = Privilege::SELECT; + if(Reference<XResultSetUpdate>(_xRs,UNO_QUERY).is()) // this interface is optional so we have to check it + { + Reference<XPropertySet> xTable(m_aUpdateTable,UNO_QUERY); + if(xTable.is() && xTable->getPropertySetInfo()->hasPropertyByName(PROPERTY_PRIVILEGES)) + { + m_nPrivileges = 0; + xTable->getPropertyValue(PROPERTY_PRIVILEGES) >>= m_nPrivileges; + if(!m_nPrivileges) + m_nPrivileges = Privilege::SELECT; + } + } + } + catch(const SQLException&) + { + bNeedKeySet = sal_True; + } + + } + if(bNeedKeySet) + { + // need to check if we could handle this select clause + bAllKeysFound = bAllKeysFound && (nTablesCount == 1 || checkJoin(xConnection,_xAnalyzer,aUpdateTableName)); + + // || !(comphelper::hasProperty(PROPERTY_CANUPDATEINSERTEDROWS,xProp) && any2bool(xProp->getPropertyValue(PROPERTY_CANUPDATEINSERTEDROWS))) + + // oj removed because keyset uses only the next// || (xProp->getPropertySetInfo()->hasPropertyByName(PROPERTY_RESULTSETTYPE) && comphelper::getINT32(xProp->getPropertyValue(PROPERTY_RESULTSETTYPE)) == ResultSetType::FORWARD_ONLY) + if(!bAllKeysFound ) + { + m_pCacheSet = new OStaticSet(); + m_xCacheSet = m_pCacheSet; + m_pCacheSet->construct(_xRs,i_sRowSetFilter); + m_nPrivileges = Privilege::SELECT; + } + else + { + Reference<XDatabaseMetaData> xMeta = xConnection->getMetaData(); + SelectColumnsMetaData aColumnNames(xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers() ? true : false); + Reference<XColumnsSupplier> xColSup(_xAnalyzer,UNO_QUERY); + Reference<XNameAccess> xSelColumns = xColSup->getColumns(); + Reference<XNameAccess> xColumns = m_aUpdateTable->getColumns(); + ::dbaccess::getColumnPositions(xSelColumns,xColumns->getElementNames(),aUpdateTableName,aColumnNames); + + // check privileges + m_nPrivileges = Privilege::SELECT; + sal_Bool bNoInsert = sal_False; + + Sequence< ::rtl::OUString> aNames(xColumns->getElementNames()); + const ::rtl::OUString* pIter = aNames.getConstArray(); + const ::rtl::OUString* pEnd = pIter + aNames.getLength(); + for(;pIter != pEnd;++pIter) + { + Reference<XPropertySet> xColumn(xColumns->getByName(*pIter),UNO_QUERY); + OSL_ENSURE(xColumn.is(),"Column in table is null!"); + if(xColumn.is()) + { + sal_Int32 nNullable = 0; + xColumn->getPropertyValue(PROPERTY_ISNULLABLE) >>= nNullable; + if(nNullable == ColumnValue::NO_NULLS && aColumnNames.find(*pIter) == aColumnNames.end()) + { // we found a column where null is not allowed so we can't insert new values + bNoInsert = sal_True; + break; // one column is enough + } + } + } + + OKeySet* pKeySet = new OKeySet(m_aUpdateTable,xUpdateTableKeys,aUpdateTableName ,_xAnalyzer,_aParameterValueForCache); + try + { + m_pCacheSet = pKeySet; + m_xCacheSet = m_pCacheSet; + pKeySet->construct(_xRs,i_sRowSetFilter); + + if(Reference<XResultSetUpdate>(_xRs,UNO_QUERY).is()) // this interface is optional so we have to check it + { + Reference<XPropertySet> xTable(m_aUpdateTable,UNO_QUERY); + if(xTable.is() && xTable->getPropertySetInfo()->hasPropertyByName(PROPERTY_PRIVILEGES)) + { + m_nPrivileges = 0; + xTable->getPropertyValue(PROPERTY_PRIVILEGES) >>= m_nPrivileges; + if(!m_nPrivileges) + m_nPrivileges = Privilege::SELECT; + } + } + if(bNoInsert) + m_nPrivileges |= ~Privilege::INSERT; // remove the insert privilege + } + catch(const SQLException&) + { + // we couldn't create a keyset here so we have to create a static cache + if ( m_pCacheSet ) + m_pCacheSet = NULL; + m_xCacheSet = NULL; + m_pCacheSet = new OStaticSet(); + m_xCacheSet = m_pCacheSet; + m_pCacheSet->construct(_xRs,i_sRowSetFilter); + m_nPrivileges = Privilege::SELECT; + } + } + + } + // last check + if(!bAllKeysFound && xProp->getPropertySetInfo()->hasPropertyByName(PROPERTY_RESULTSETCONCURRENCY) && + ::comphelper::getINT32(xProp->getPropertyValue(PROPERTY_RESULTSETCONCURRENCY)) == ResultSetConcurrency::READ_ONLY) + m_nPrivileges = Privilege::SELECT; +} + +// ------------------------------------------------------------------------- +ORowSetCache::~ORowSetCache() +{ + m_pCacheSet = NULL; + m_xCacheSet = NULL; + if(m_pMatrix) + { + m_pMatrix->clear(); + delete m_pMatrix; + } + + if(m_pInsertMatrix) + { + m_pInsertMatrix->clear(); + delete m_pInsertMatrix; + } + m_xSet = WeakReference< XResultSet>(); + m_xMetaData = NULL; + m_aUpdateTable = NULL; + + DBG_DTOR(ORowSetCache,NULL); +} + +// ------------------------------------------------------------------------- +void ORowSetCache::setMaxRowSize(sal_Int32 _nSize) +{ + + if(_nSize == m_nFetchSize) + return; + + m_nFetchSize = _nSize; + if(!m_pMatrix) + { + m_pMatrix = new ORowSetMatrix(_nSize); + m_aMatrixIter = m_pMatrix->end(); + m_aMatrixEnd = m_pMatrix->end(); + + m_pInsertMatrix = new ORowSetMatrix(1); // a little bit overkill but ??? :-) + m_aInsertRow = m_pInsertMatrix->end(); + } + else + { + // now correct the iterator in our iterator vector + ::std::vector<sal_Int32> aPositions; + ::std::map<sal_Int32,sal_Bool> aCacheIterToChange; + // first get the positions where they stand now + ORowSetCacheMap::iterator aCacheIter = m_aCacheIterators.begin(); + ORowSetCacheMap::iterator aCacheEnd = m_aCacheIterators.end(); + for(;aCacheIter != aCacheEnd;++aCacheIter) + { + aCacheIterToChange[aCacheIter->first] = sal_False; + if ( !aCacheIter->second.pRowSet->isInsertRow() + /*&& aCacheIter->second.aIterator != m_pMatrix->end()*/ && !m_bModified ) + { + ptrdiff_t nDist = (aCacheIter->second.aIterator - m_pMatrix->begin()); + aPositions.push_back(nDist); + aCacheIterToChange[aCacheIter->first] = sal_True; + } + } + sal_Int32 nKeyPos = (m_aMatrixIter - m_pMatrix->begin()); + m_pMatrix->resize(_nSize); + + if ( nKeyPos < _nSize ) + m_aMatrixIter = m_pMatrix->begin() + nKeyPos; + else + m_aMatrixIter = m_pMatrix->end(); + m_aMatrixEnd = m_pMatrix->end(); + + // now adjust their positions because a resize invalid all iterators + ::std::vector<sal_Int32>::const_iterator aIter = aPositions.begin(); + ::std::map<sal_Int32,sal_Bool>::const_iterator aPosChangeIter = aCacheIterToChange.begin(); + for( aCacheIter = m_aCacheIterators.begin(); + aPosChangeIter != aCacheIterToChange.end(); + ++aPosChangeIter,++aCacheIter) + { + if ( aPosChangeIter->second ) + { + CHECK_MATRIX_POS(*aIter); + if ( *aIter < _nSize ) + aCacheIter->second.aIterator = m_pMatrix->begin() + *aIter++; + else + aCacheIter->second.aIterator = m_pMatrix->end(); + } + } + } + if(!m_nPosition) + { + sal_Int32 nNewSt = 1; + fillMatrix(nNewSt,_nSize+1); + m_nStartPos = 0; + m_nEndPos = _nSize; + } +} +// ------------------------------------------------------------------------- + +// XResultSetMetaDataSupplier +Reference< XResultSetMetaData > ORowSetCache::getMetaData( ) +{ + return m_xMetaData; +} +// ------------------------------------------------------------------------- +Any lcl_getBookmark(ORowSetValue& i_aValue,OCacheSet* i_pCacheSet) +{ + switch ( i_aValue.getTypeKind() ) + { + case DataType::TINYINT: + case DataType::SMALLINT: + case DataType::INTEGER: + return makeAny((sal_Int32)i_aValue); + default: + if ( i_pCacheSet && i_aValue.isNull()) + i_aValue = i_pCacheSet->getBookmark(); + return i_aValue.getAny(); + } +} +// ------------------------------------------------------------------------- +// ::com::sun::star::sdbcx::XRowLocate +Any ORowSetCache::getBookmark( ) +{ + + if(m_bAfterLast) + throwFunctionSequenceException(m_xSet.get()); + + if ( m_aMatrixIter >= m_pMatrix->end() || m_aMatrixIter < m_pMatrix->begin() || !(*m_aMatrixIter).isValid()) + { + return Any(); // this is allowed here because the rowset knowns what it is doing + } + + return lcl_getBookmark(((*m_aMatrixIter)->get())[0],m_pCacheSet); +} +// ------------------------------------------------------------------------- +sal_Bool ORowSetCache::moveToBookmark( const Any& bookmark ) +{ + if ( m_pCacheSet->moveToBookmark(bookmark) ) + { + m_bBeforeFirst = sal_False; + m_nPosition = m_pCacheSet->getRow(); + + checkPositionFlags(); + + if(!m_bAfterLast) + { + moveWindow(); + checkPositionFlags(); + if ( !m_bAfterLast ) + { + m_aMatrixIter = calcPosition(); + OSL_ENSURE(m_aMatrixIter->isValid(),"Iterator after moveToBookmark not valid"); + } + else + m_aMatrixIter = m_pMatrix->end(); + } + else + m_aMatrixIter = m_pMatrix->end(); + } + else + return sal_False; + + return m_aMatrixIter != m_pMatrix->end() && (*m_aMatrixIter).isValid(); +} +// ------------------------------------------------------------------------- +sal_Bool ORowSetCache::moveRelativeToBookmark( const Any& bookmark, sal_Int32 rows ) +{ + sal_Bool bRet( moveToBookmark( bookmark ) ); + if ( bRet ) + { + m_nPosition = m_pCacheSet->getRow() + rows; + absolute(m_nPosition); + // for(sal_Int32 i=0;i<rows && m_aMatrixIter != m_pMatrix->end();++i,++m_aMatrixIter) ; + + bRet = m_aMatrixIter != m_pMatrix->end() && (*m_aMatrixIter).isValid(); + } + + return bRet; +} +// ------------------------------------------------------------------------- +sal_Int32 ORowSetCache::compareBookmarks( const Any& _first, const Any& _second ) +{ + return (!_first.hasValue() || !_second.hasValue()) ? CompareBookmark::NOT_COMPARABLE : m_pCacheSet->compareBookmarks(_first,_second); +} +// ------------------------------------------------------------------------- +sal_Bool ORowSetCache::hasOrderedBookmarks( ) +{ + return m_pCacheSet->hasOrderedBookmarks(); +} +// ------------------------------------------------------------------------- +sal_Int32 ORowSetCache::hashBookmark( const Any& bookmark ) +{ + return m_pCacheSet->hashBookmark(bookmark); +} +// XRowUpdate +// ----------------------------------------------------------------------------- +void ORowSetCache::updateNull(sal_Int32 columnIndex,ORowSetValueVector::Vector& io_aRow + ,::std::vector<sal_Int32>& o_ChangedColumns + ) +{ + checkUpdateConditions(columnIndex); + + ORowSetValueVector::Vector& rInsert = ((*m_aInsertRow)->get()); + rInsert[columnIndex].setBound(sal_True); + rInsert[columnIndex].setNull(); + rInsert[columnIndex].setModified(); + io_aRow[columnIndex].setNull(); + + m_pCacheSet->mergeColumnValues(columnIndex,rInsert,io_aRow,o_ChangedColumns); + impl_updateRowFromCache_throw(io_aRow,o_ChangedColumns); +} +// ----------------------------------------------------------------------------- +void ORowSetCache::updateValue(sal_Int32 columnIndex,const ORowSetValue& x + ,ORowSetValueVector::Vector& io_aRow + ,::std::vector<sal_Int32>& o_ChangedColumns + ) +{ + checkUpdateConditions(columnIndex); + + ORowSetValueVector::Vector& rInsert = ((*m_aInsertRow)->get()); + rInsert[columnIndex].setBound(sal_True); + rInsert[columnIndex] = x; + rInsert[columnIndex].setModified(); + io_aRow[columnIndex] = rInsert[columnIndex]; + + m_pCacheSet->mergeColumnValues(columnIndex,rInsert,io_aRow,o_ChangedColumns); + impl_updateRowFromCache_throw(io_aRow,o_ChangedColumns); +} +// ------------------------------------------------------------------------- +void ORowSetCache::updateCharacterStream( sal_Int32 columnIndex, const Reference< ::com::sun::star::io::XInputStream >& x + , sal_Int32 length,ORowSetValueVector::Vector& io_aRow + ,::std::vector<sal_Int32>& o_ChangedColumns + ) +{ + checkUpdateConditions(columnIndex); + + Sequence<sal_Int8> aSeq; + if(x.is()) + x->readBytes(aSeq,length); + + ORowSetValueVector::Vector& rInsert = ((*m_aInsertRow)->get()); + rInsert[columnIndex].setBound(sal_True); + rInsert[columnIndex] = aSeq; + rInsert[columnIndex].setModified(); + io_aRow[columnIndex] = makeAny(x); + + m_pCacheSet->mergeColumnValues(columnIndex,rInsert,io_aRow,o_ChangedColumns); + impl_updateRowFromCache_throw(io_aRow,o_ChangedColumns); +} +// ------------------------------------------------------------------------- +void ORowSetCache::updateObject( sal_Int32 columnIndex, const Any& x + ,ORowSetValueVector::Vector& io_aRow + ,::std::vector<sal_Int32>& o_ChangedColumns + ) +{ + checkUpdateConditions(columnIndex); + + ORowSetValueVector::Vector& rInsert = ((*m_aInsertRow)->get()); + rInsert[columnIndex].setBound(sal_True); + rInsert[columnIndex] = x; + rInsert[columnIndex].setModified(); + io_aRow[columnIndex] = rInsert[columnIndex]; + + m_pCacheSet->mergeColumnValues(columnIndex,rInsert,io_aRow,o_ChangedColumns); + impl_updateRowFromCache_throw(io_aRow,o_ChangedColumns); +} +// ------------------------------------------------------------------------- +void ORowSetCache::updateNumericObject( sal_Int32 columnIndex, const Any& x, sal_Int32 /*scale*/ + ,ORowSetValueVector::Vector& io_aRow + ,::std::vector<sal_Int32>& o_ChangedColumns + ) +{ + checkUpdateConditions(columnIndex); + + ORowSetValueVector::Vector& rInsert = ((*m_aInsertRow)->get()); + rInsert[columnIndex].setBound(sal_True); + rInsert[columnIndex] = x; + rInsert[columnIndex].setModified(); + io_aRow[columnIndex] = rInsert[columnIndex]; + + m_pCacheSet->mergeColumnValues(columnIndex,rInsert,io_aRow,o_ChangedColumns); + impl_updateRowFromCache_throw(io_aRow,o_ChangedColumns); +} +// ------------------------------------------------------------------------- +// XResultSet +sal_Bool ORowSetCache::next( ) +{ + if(!isAfterLast()) + { + m_bBeforeFirst = sal_False; + ++m_nPosition; + + // after we increment the position we have to check if we are already after the last row + checkPositionFlags(); + if(!m_bAfterLast) + { + moveWindow(); + + OSL_ENSURE(((m_nPosition - m_nStartPos) - 1) < (sal_Int32)m_pMatrix->size(),"Position is behind end()!"); + m_aMatrixIter = calcPosition(); + checkPositionFlags(); + } + } + + return !m_bAfterLast; +} +// ------------------------------------------------------------------------- +sal_Bool ORowSetCache::isBeforeFirst( ) +{ + // return !m_nPosition; + + return m_bBeforeFirst; +} +// ------------------------------------------------------------------------- +sal_Bool ORowSetCache::isAfterLast( ) +{ + + return m_bAfterLast; +} +// ------------------------------------------------------------------------- +sal_Bool ORowSetCache::isFirst( ) +{ + + return m_nPosition == 1; // ask resultset for +} +// ------------------------------------------------------------------------- +sal_Bool ORowSetCache::isLast( ) +{ + // return m_bRowCountFinal ? (m_nPosition==m_nRowCount) : m_pCacheSet->isLast(); + + return m_nPosition == m_nRowCount; +} +// ------------------------------------------------------------------------- +sal_Bool ORowSetCache::beforeFirst( ) +{ + + + if(!m_bBeforeFirst) + { + m_bAfterLast = sal_False; + m_nPosition = 0; + m_bBeforeFirst = sal_True; + m_pCacheSet->beforeFirst(); + moveWindow(); + m_aMatrixIter = m_pMatrix->end(); + } + return sal_True; +} +// ------------------------------------------------------------------------- +sal_Bool ORowSetCache::afterLast( ) +{ + + + if(!m_bAfterLast) + { + m_bBeforeFirst = sal_False; + m_bAfterLast = sal_True; + + if(!m_bRowCountFinal) + { + m_pCacheSet->last(); + m_bRowCountFinal = sal_True; + m_nRowCount = m_pCacheSet->getRow();// + 1 removed + } + m_pCacheSet->afterLast(); + + m_nPosition = 0; + m_aMatrixIter = m_pMatrix->end(); + } + return sal_True; +} +// ------------------------------------------------------------------------- +sal_Bool ORowSetCache::fillMatrix(sal_Int32& _nNewStartPos,sal_Int32 _nNewEndPos) +{ + OSL_ENSURE(_nNewStartPos != _nNewEndPos,"ORowSetCache::fillMatrix: StartPos and EndPos can not be equal!"); + // fill the whole window with new data + ORowSetMatrix::iterator aIter = m_pMatrix->begin(); + sal_Bool bCheck = m_pCacheSet->absolute(_nNewStartPos); // -1 no need to + + sal_Int32 i=_nNewStartPos; + for(;i<_nNewEndPos;++i,++aIter) + { + if(bCheck) + { + if(!aIter->isValid()) + *aIter = new ORowSetValueVector(m_xMetaData->getColumnCount()); + m_pCacheSet->fillValueRow(*aIter,i); + } + else + { // there are no more rows found so we can fetch some before start + + if(!m_bRowCountFinal) + { + if(m_pCacheSet->previous()) // because we stand after the last row + m_nRowCount = m_pCacheSet->getRow(); // here we have the row count + if(!m_nRowCount) + m_nRowCount = i-1; // it can be that getRow return zero + m_bRowCountFinal = sal_True; + } + if(m_nRowCount > m_nFetchSize) + { + ORowSetMatrix::iterator aEnd = aIter; + ORowSetMatrix::iterator aRealEnd = m_pMatrix->end(); + sal_Int32 nPos = m_nRowCount - m_nFetchSize + 1; + _nNewStartPos = nPos; + bCheck = m_pCacheSet->absolute(_nNewStartPos); + + for(;bCheck && aIter != aRealEnd;++aIter) + { + if(bCheck) + { + if(!aIter->isValid()) + *aIter = new ORowSetValueVector(m_xMetaData->getColumnCount()); + m_pCacheSet->fillValueRow(*aIter,nPos++); + } + bCheck = m_pCacheSet->next(); + } + if(aIter != aEnd) + ::std::rotate(m_pMatrix->begin(),aEnd,aRealEnd); + } + break; + } + bCheck = m_pCacheSet->next(); + } + // m_nStartPos = _nNewStartPos; + // we have to read one row forward to enshure that we know when we are on last row + // but only when we don't know it already + if(!m_bRowCountFinal) + { + if(!m_pCacheSet->next()) + { + if(m_pCacheSet->previous()) // because we stand after the last row + m_nRowCount = m_pCacheSet->getRow(); // here we have the row count + m_bRowCountFinal = sal_True; + } + else + m_nRowCount = std::max(i,m_nRowCount); + + } + return bCheck; +} +// ------------------------------------------------------------------------- +sal_Bool ORowSetCache::moveWindow() +{ + + sal_Bool bRet = sal_True; + + sal_Int32 nDiff = (sal_Int32)(m_nFetchSize*0.5 -0.5); + sal_Int32 nNewStartPos = (m_nPosition - nDiff); + // sal_Int32 nNewEndPos = (m_nPosition+m_nFetchSize*0.5); + sal_Int32 nNewEndPos = nNewStartPos + m_nFetchSize; + + if ( m_nPosition <= m_nStartPos ) + { // the window is behind the new start pos + if(!m_nStartPos) + return sal_False; + // the new position should be the nPos - nFetchSize/2 + if ( nNewEndPos > m_nStartPos ) + { // but the two regions are overlapping + // fill the rows behind the new end + + ORowSetMatrix::iterator aEnd; // the iterator we need for rotate + ORowSetMatrix::iterator aIter; // the iterator we fill with new values + + sal_Bool bCheck = sal_True; + if ( nNewStartPos < 1 ) + { + bCheck = m_pCacheSet->first(); + // aEnd = m_pMatrix->begin() + (sal_Int32)(m_nFetchSize*0.5); + OSL_ENSURE((nNewEndPos - m_nStartPos - nNewStartPos) < (sal_Int32)m_pMatrix->size(),"Position is behind end()!"); + aEnd = m_pMatrix->begin() + (nNewEndPos - m_nStartPos - nNewStartPos); + aIter = aEnd; + m_nStartPos = 0; + } + else + { + OSL_ENSURE((nNewEndPos - m_nStartPos -1) < (sal_Int32)m_pMatrix->size(),"Position is behind end()!"); + aEnd = m_pMatrix->begin() + ((nNewEndPos - m_nStartPos)-1); + aIter = m_pMatrix->begin() + ((nNewEndPos - m_nStartPos)-1); + bCheck = m_pCacheSet->absolute(nNewStartPos); + m_nStartPos = nNewStartPos -1; + } + + if ( bCheck ) + { + sal_Int32 nPos = m_nStartPos; + bCheck = fill(aIter,m_pMatrix->end(),nPos,bCheck); + + ::std::rotate(m_pMatrix->begin(),aEnd,m_pMatrix->end()); + // now correct the iterator in our iterator vector + // rotateCacheIterator(aEnd-m_pMatrix->begin()); //can't be used because they decrement and here we need to increment + ptrdiff_t nNewDist = aEnd - m_pMatrix->begin(); + ptrdiff_t nOffSet = m_pMatrix->end() - aEnd; + ORowSetCacheMap::iterator aCacheIter = m_aCacheIterators.begin(); + ORowSetCacheMap::iterator aCacheEnd = m_aCacheIterators.end(); + for(;aCacheIter != aCacheEnd;++aCacheIter) + { + if ( !aCacheIter->second.pRowSet->isInsertRow() + && aCacheIter->second.aIterator != m_pMatrix->end() && !m_bModified ) + { + ptrdiff_t nDist = (aCacheIter->second.aIterator - m_pMatrix->begin()); + if ( nDist >= nNewDist ) + { + aCacheIter->second.aIterator = m_pMatrix->end(); + } + else + { +#if OSL_DEBUG_LEVEL > 0 + ORowSetMatrix::iterator aOldPos; + aOldPos = aCacheIter->second.aIterator; +#endif + CHECK_MATRIX_POS( ((aOldPos - m_pMatrix->begin()) + nOffSet) ); + aCacheIter->second.aIterator += nOffSet; +#if OSL_DEBUG_LEVEL > 0 + ORowSetMatrix::iterator aCurrentPos; + aCurrentPos = aCacheIter->second.aIterator; +#endif + OSL_ENSURE(aCacheIter->second.aIterator >= m_pMatrix->begin() + && aCacheIter->second.aIterator < m_pMatrix->end(),"Iterator out of area!"); + } + } + } + } + else + { // normaly this should never happen + OSL_ENSURE(0,"What the hell is happen here!"); + return sal_False; + } + } + else + {// no rows can be reused so fill again + if(nNewStartPos < 1) // special case + { + m_nStartPos = 0; + + rotateCacheIterator(static_cast<sal_Int16>(m_nFetchSize+1)); // static_cast<sal_Int16>(m_nFetchSize+1) + + m_pCacheSet->beforeFirst(); + + sal_Bool bCheck; + ORowSetMatrix::iterator aIter = m_pMatrix->begin(); + for(sal_Int32 i=0;i<m_nFetchSize;++i,++aIter) + { + bCheck = m_pCacheSet->next(); + if ( bCheck ) + { + if(!aIter->isValid()) + *aIter = new ORowSetValueVector(m_xMetaData->getColumnCount()); + m_pCacheSet->fillValueRow(*aIter,i+1); + } + else + *aIter = NULL; + } + } + else + bRet = reFillMatrix(nNewStartPos,nNewEndPos); + } + } + else if(m_nPosition > m_nStartPos) + { // the new start pos is above the startpos of the window + + if(m_nPosition <= (m_nStartPos+m_nFetchSize)) + { // position in window + OSL_ENSURE((m_nPosition - m_nStartPos -1) < (sal_Int32)m_pMatrix->size(),"Position is behind end()!"); + m_aMatrixIter = calcPosition(); + if(!m_aMatrixIter->isValid()) + { + sal_Bool bOk( m_pCacheSet->absolute( m_nPosition ) ); + if ( bOk ) + { + *m_aMatrixIter = new ORowSetValueVector(m_xMetaData->getColumnCount()); + m_pCacheSet->fillValueRow(*m_aMatrixIter,m_nPosition); + // we have to read one row forward to ensure that we know when we are on last row + // but only when we don't know it already + if ( !m_bRowCountFinal ) + { + bOk = m_pCacheSet->absolute( m_nPosition + 1 ); + if ( bOk ) + m_nRowCount = std::max(sal_Int32(m_nPosition+1),m_nRowCount); + } + } + if(!bOk) + { + if(!m_bRowCountFinal) + { + // because we stand after the last row + m_nRowCount = m_pCacheSet->previous() ? m_pCacheSet->getRow() : 0;// + 1 removed + m_bRowCountFinal = sal_True; + } + } + } + } + else if(nNewStartPos < (m_nStartPos+m_nFetchSize)) + { // position behind window but the region is overlapping + // the rows from begin() to (begin + nNewStartPos - m_nStartPos) can be refilled with the new rows + // the rows behind this can be reused + ORowSetMatrix::iterator aIter = m_pMatrix->begin(); + CHECK_MATRIX_POS(nNewStartPos - m_nStartPos - 1); + ORowSetMatrix::iterator aEnd = m_pMatrix->begin() + (nNewStartPos - m_nStartPos - 1); + + sal_Int32 nPos = m_nStartPos + m_nFetchSize + 1; + sal_Bool bCheck = m_pCacheSet->absolute(nPos); + bCheck = fill(aIter,aEnd,nPos,bCheck); // refill the region wew don't need anymore + +// // we know that this is the current maximal rowcount here +// if ( !m_bRowCountFinal && bCheck ) +// m_nRowCount = std::max(nPos,m_nRowCount); + // we have to read one row forward to enshure that we know when we are on last row + // but only when we don't know it already + sal_Bool bOk = sal_True; + if(bCheck && !m_bRowCountFinal) + bOk = m_pCacheSet->next(); + // bind end to front + if(bCheck) + { // rotate the end to the front + ::std::rotate(m_pMatrix->begin(),aIter,m_pMatrix->end()); + // now correct the iterator in our iterator vector + rotateCacheIterator( (sal_Int16)( aIter - m_pMatrix->begin() ) ); + m_nStartPos = nNewStartPos - 1; // must be -1 + // now I can say how many rows we have + if(!bOk) + { + m_pCacheSet->previous(); // because we stand after the last row + m_nRowCount = nPos; // here we have the row count + m_bRowCountFinal = sal_True; + } + else if(!m_bRowCountFinal) + m_nRowCount = std::max(++nPos,m_nRowCount); + } + else + { // the end was reached before end() so we can set the start before nNewStartPos + + m_nStartPos += (aIter - m_pMatrix->begin()); + // m_nStartPos = (aIter - m_pMatrix->begin()); + ::std::rotate(m_pMatrix->begin(),aIter,m_pMatrix->end()); + // now correct the iterator in our iterator vector + rotateCacheIterator( (sal_Int16)( aIter - m_pMatrix->begin() ) ); + + if ( !m_bRowCountFinal ) + { + m_pCacheSet->previous(); // because we stand after the last row + m_nRowCount = std::max(m_nRowCount,--nPos); // here we have the row count + OSL_ENSURE(nPos == m_pCacheSet->getRow(),"nPos isn't valid!"); + m_bRowCountFinal = sal_True; + } + // TODO check + // m_nStartPos = (nNewStartPos+m_nRowCount) - m_nFetchSize ; + if(m_nStartPos < 0) + m_nStartPos = 0; + } + // here we need only to check if the begining row is valid. If not we have to fetch it. + if(!m_pMatrix->begin()->isValid()) + { + aIter = m_pMatrix->begin(); + + nPos = m_nStartPos; + bCheck = m_pCacheSet->absolute(m_nStartPos); + for(; !aIter->isValid() && bCheck;++aIter) + { + OSL_ENSURE(aIter != m_pMatrix->end(),"Invalid iterator"); + bCheck = m_pCacheSet->next(); + if ( bCheck ) // resultset stands on right position + { + *aIter = new ORowSetValueVector(m_xMetaData->getColumnCount()); + m_pCacheSet->fillValueRow(*aIter,++nPos); + } + } + } + } + else // no rows can be reused so fill again + bRet = reFillMatrix(nNewStartPos,nNewEndPos); + } + + if(!m_bRowCountFinal) + m_nRowCount = std::max(m_nPosition,m_nRowCount); + OSL_ENSURE(m_nStartPos >= 0,"ORowSetCache::moveWindow: m_nStartPos is less than 0!"); + + return bRet; +} +// ------------------------------------------------------------------------- +sal_Bool ORowSetCache::first( ) +{ + // first move to the first row + // then check if the cache window is at the begining + // when not postionize the window and fill it with data + // smart moving of the window -> clear only the rows whom are out of range + sal_Bool bRet = m_pCacheSet->first(); + if(bRet) + { + m_bBeforeFirst = m_bAfterLast = sal_False; + m_nPosition = 1; + moveWindow(); + m_aMatrixIter = m_pMatrix->begin(); + } + else + { + m_bRowCountFinal = m_bBeforeFirst = m_bAfterLast = sal_True; + m_nRowCount = m_nPosition = 0; + + OSL_ENSURE(m_bBeforeFirst || m_bNew,"ORowSetCache::first return false and BeforeFirst isn't true"); + m_aMatrixIter = m_pMatrix->end(); + } + return bRet; +} +// ------------------------------------------------------------------------- +sal_Bool ORowSetCache::last( ) +{ + sal_Bool bRet = m_pCacheSet->last(); + if(bRet) + { + m_bBeforeFirst = m_bAfterLast = sal_False; + if(!m_bRowCountFinal) + { + m_bRowCountFinal = sal_True; + m_nRowCount = m_nPosition = m_pCacheSet->getRow(); // not + 1 + } + m_nPosition = m_pCacheSet->getRow(); + moveWindow(); + // we have to repositioning because moveWindow can modify the cache + m_pCacheSet->last(); +// if(m_nPosition > m_nFetchSize) +// m_aMatrixIter = m_pMatrix->end() -1; +// else +// m_aMatrixIter = m_pMatrix->begin() + m_nPosition - 1; + OSL_ENSURE(((m_nPosition - m_nStartPos) - 1) < (sal_Int32)m_pMatrix->size(),"Position is behind end()!"); + m_aMatrixIter = calcPosition(); + } + else + { + m_bRowCountFinal = m_bBeforeFirst = m_bAfterLast = sal_True; + m_nRowCount = m_nPosition = 0; + OSL_ENSURE(m_bBeforeFirst,"ORowSetCache::last return false and BeforeFirst isn't true"); + m_aMatrixIter = m_pMatrix->end(); + } +#if OSL_DEBUG_LEVEL > 1 + if(bRet) + { + OSL_ENSURE((*m_aMatrixIter).isValid(),"ORowSetCache::last: Row not valid!"); + } +#endif + + return bRet; +} +// ------------------------------------------------------------------------- +sal_Int32 ORowSetCache::getRow( ) +{ + return (isBeforeFirst() || isAfterLast()) ? 0 : m_nPosition; +} +// ------------------------------------------------------------------------- +sal_Bool ORowSetCache::absolute( sal_Int32 row ) +{ + if(!row ) + throw SQLException(DBACORE_RESSTRING(RID_STR_NO_ABS_ZERO),NULL,SQLSTATE_GENERAL,1000,Any() ); + + if(row < 0) + { + // here we have to scroll from the last row to backward so we have to go to last row and + // and two the previous + if(m_bRowCountFinal || last()) + { + m_nPosition = m_nRowCount + row + 1; // + row because row is negative and +1 because row==-1 means last row + if(m_nPosition < 1) + { + m_bBeforeFirst = sal_True; + m_bAfterLast = sal_False; + m_aMatrixIter = m_pMatrix->end(); + } + else + { + m_bBeforeFirst = sal_False; + m_bAfterLast = m_nPosition > m_nRowCount; + moveWindow(); + OSL_ENSURE(((m_nPosition - m_nStartPos) - 1) < (sal_Int32)m_pMatrix->size(),"Position is behind end()!"); + m_aMatrixIter = calcPosition(); + } + } + else + m_aMatrixIter = m_pMatrix->end(); + } + else + { + m_nPosition = row; + // the position flags + m_bBeforeFirst = sal_False; + checkPositionFlags(); + + if(!m_bAfterLast) + { + moveWindow(); + checkPositionFlags(); + if(!m_bAfterLast) + m_aMatrixIter = calcPosition(); + else + m_aMatrixIter = m_pMatrix->end(); + } + else + m_aMatrixIter = m_pMatrix->end(); + } + + return !(m_bAfterLast || m_bBeforeFirst); +} +// ------------------------------------------------------------------------- +sal_Bool ORowSetCache::relative( sal_Int32 rows ) +{ + sal_Bool bErg = sal_True; + if(rows) + { + sal_Int32 nNewPosition = m_nPosition + rows; + + if ( m_bBeforeFirst && rows > 0 ) + nNewPosition = rows; + else if ( m_bRowCountFinal && m_bAfterLast && rows < 0 ) + nNewPosition = m_nRowCount + 1 + rows; + else + if ( m_bBeforeFirst || ( m_bRowCountFinal && m_bAfterLast ) ) + throw SQLException( DBACORE_RESSTRING( RID_STR_NO_RELATIVE ), NULL, SQLSTATE_GENERAL, 1000, Any() ); + if ( nNewPosition ) + { + bErg = absolute( nNewPosition ); + bErg = bErg && !isAfterLast() && !isBeforeFirst(); + } + else + { + m_bBeforeFirst = sal_True; + bErg = sal_False; + } + } + return bErg; +} +// ------------------------------------------------------------------------- +sal_Bool ORowSetCache::previous( ) +{ + sal_Bool bRet = sal_False; + if(!isBeforeFirst()) + { + if(m_bAfterLast) // we stand after the last row so one before is the last row + bRet = last(); + else + { + m_bAfterLast = sal_False; + --m_nPosition; + moveWindow(); + OSL_ENSURE(((m_nPosition - m_nStartPos) - 1) < (sal_Int32)m_pMatrix->size(),"Position is behind end()!"); + + checkPositionFlags(); + + if(!m_nPosition) + { + m_bBeforeFirst = sal_True; + m_aMatrixIter = m_pMatrix->end(); + } + else + { + m_aMatrixIter = calcPosition(); + bRet = (*m_aMatrixIter).isValid(); + } + } + } + return bRet; +} +// ------------------------------------------------------------------------- +void ORowSetCache::refreshRow( ) +{ + if(isAfterLast()) + throw SQLException(DBACORE_RESSTRING(RID_STR_NO_REFESH_AFTERLAST),NULL,SQLSTATE_GENERAL,1000,Any() ); + OSL_ENSURE(m_aMatrixIter != m_pMatrix->end(),"refreshRow() called for invalid row!"); + m_pCacheSet->refreshRow(); + m_pCacheSet->fillValueRow(*m_aMatrixIter,m_nPosition); + if ( m_bNew ) + { + cancelRowModification(); + } +} +// ------------------------------------------------------------------------- +sal_Bool ORowSetCache::rowUpdated( ) +{ + return m_pCacheSet->rowUpdated(); +} +// ------------------------------------------------------------------------- +sal_Bool ORowSetCache::rowInserted( ) +{ + return m_pCacheSet->rowInserted(); +} +// ------------------------------------------------------------------------- +// XResultSetUpdate +sal_Bool ORowSetCache::insertRow(::std::vector< Any >& o_aBookmarks) +{ + if ( !m_bNew || !m_aInsertRow->isValid() ) + throw SQLException(DBACORE_RESSTRING(RID_STR_NO_MOVETOINSERTROW_CALLED),NULL,SQLSTATE_GENERAL,1000,Any() ); + + m_pCacheSet->insertRow(*m_aInsertRow,m_aUpdateTable); + + sal_Bool bRet( rowInserted() ); + if ( bRet ) + { + ++m_nRowCount; + Any aBookmark = ((*m_aInsertRow)->get())[0].makeAny(); + m_bAfterLast = m_bBeforeFirst = sal_False; + if(aBookmark.hasValue()) + { + moveToBookmark(aBookmark); + // update the cached values + ORowSetValueVector::Vector& rCurrentRow = ((*m_aMatrixIter))->get(); + ORowSetMatrix::iterator aIter = m_pMatrix->begin(); + for(;aIter != m_pMatrix->end();++aIter) + { + if ( m_aMatrixIter != aIter && aIter->isValid() && m_pCacheSet->columnValuesUpdated((*aIter)->get(),rCurrentRow) ) + { + o_aBookmarks.push_back(lcl_getBookmark((*aIter)->get()[0],m_pCacheSet)); + } + } + } + else + { + OSL_ENSURE(0,"There must be a bookmark after the row was inserted!"); + } + } + return bRet; +} +// ------------------------------------------------------------------------- +void ORowSetCache::resetInsertRow(sal_Bool _bClearInsertRow) +{ + if ( _bClearInsertRow ) + clearInsertRow(); + m_bNew = sal_False; + m_bModified = sal_False; +} +// ------------------------------------------------------------------------- +void ORowSetCache::cancelRowModification() +{ + // clear the insertrow references -> implies that the current row of the rowset changes as well + ORowSetCacheMap::iterator aCacheIter = m_aCacheIterators.begin(); + ORowSetCacheMap::iterator aCacheEnd = m_aCacheIterators.end(); + for(;aCacheIter != aCacheEnd;++aCacheIter) + { + if ( aCacheIter->second.pRowSet->isInsertRow() && aCacheIter->second.aIterator == m_aInsertRow ) + aCacheIter->second.aIterator = m_pMatrix->end(); + } // for(;aCacheIter != aCacheEnd;++aCacheIter) + resetInsertRow(sal_False); +} +// ------------------------------------------------------------------------- +void ORowSetCache::updateRow( ORowSetMatrix::iterator& _rUpdateRow,::std::vector< Any >& o_aBookmarks ) +{ + if(isAfterLast() || isBeforeFirst()) + throw SQLException(DBACORE_RESSTRING(RID_STR_NO_UPDATEROW),NULL,SQLSTATE_GENERAL,1000,Any() ); + + Any aBookmark = ((*_rUpdateRow)->get())[0].makeAny(); + OSL_ENSURE(aBookmark.hasValue(),"Bookmark must have a value!"); + // here we don't have to reposition our CacheSet, when we try to update a row, + // the row was already fetched + moveToBookmark(aBookmark); + m_pCacheSet->updateRow(*_rUpdateRow,*m_aMatrixIter,m_aUpdateTable); + // refetch the whole row + (*m_aMatrixIter) = NULL; + + if ( moveToBookmark(aBookmark) ) + { + // update the cached values + ORowSetValueVector::Vector& rCurrentRow = ((*m_aMatrixIter))->get(); + ORowSetMatrix::iterator aIter = m_pMatrix->begin(); + for(;aIter != m_pMatrix->end();++aIter) + { + if ( m_aMatrixIter != aIter && aIter->isValid() && m_pCacheSet->columnValuesUpdated((*aIter)->get(),rCurrentRow) ) + { + o_aBookmarks.push_back(lcl_getBookmark((*aIter)->get()[0],m_pCacheSet)); + } + } + } + + m_bModified = sal_False; +} +// ------------------------------------------------------------------------- +bool ORowSetCache::deleteRow( ) +{ + if(isAfterLast() || isBeforeFirst()) + throw SQLException(DBACORE_RESSTRING(RID_STR_NO_DELETEROW),NULL,SQLSTATE_GENERAL,1000,Any() ); + + // m_pCacheSet->absolute(m_nPosition); + m_pCacheSet->deleteRow(*m_aMatrixIter,m_aUpdateTable); + if ( !m_pCacheSet->rowDeleted() ) + return false; + + --m_nRowCount; + OSL_ENSURE(((m_nPosition - m_nStartPos) - 1) < (sal_Int32)m_pMatrix->size(),"Position is behind end()!"); + ORowSetMatrix::iterator aPos = calcPosition(); + (*aPos) = NULL; + + ORowSetMatrix::iterator aEnd = m_pMatrix->end(); + for(++aPos;aPos != aEnd && aPos->isValid();++aPos) + { + *(aPos-1) = *aPos; + (*aPos) = NULL; + } + m_aMatrixIter = m_pMatrix->end(); + + --m_nPosition; + return true; +} +// ------------------------------------------------------------------------- +void ORowSetCache::cancelRowUpdates( ) +{ + m_bNew = m_bModified = sal_False; + if(!m_nPosition) + { + OSL_ENSURE(0,"cancelRowUpdates:Invalid positions pos == 0"); + ::dbtools::throwFunctionSequenceException(NULL); + } + + if(m_pCacheSet->absolute(m_nPosition)) + m_pCacheSet->fillValueRow(*m_aMatrixIter,m_nPosition); + else + { + OSL_ENSURE(0,"cancelRowUpdates couldn't position right with absolute"); + ::dbtools::throwFunctionSequenceException(NULL); + } +} +// ------------------------------------------------------------------------- +void ORowSetCache::moveToInsertRow( ) +{ + m_bNew = sal_True; + m_bUpdated = m_bAfterLast = sal_False; + + m_aInsertRow = m_pInsertMatrix->begin(); + if(!m_aInsertRow->isValid()) + *m_aInsertRow = new ORowSetValueVector(m_xMetaData->getColumnCount()); + + // we don't unbound the bookmark column + ORowSetValueVector::Vector::iterator aIter = (*m_aInsertRow)->get().begin()+1; + ORowSetValueVector::Vector::iterator aEnd = (*m_aInsertRow)->get().end(); + for(sal_Int32 i = 1;aIter != aEnd;++aIter,++i) + { + aIter->setBound(sal_False); + aIter->setModified(sal_False); + aIter->setNull(); + aIter->setTypeKind(m_xMetaData->getColumnType(i)); + } +} +// ------------------------------------------------------------------------- +ORowSetCacheIterator ORowSetCache::createIterator(ORowSetBase* _pRowSet) +{ + + ORowSetCacheIterator_Helper aHelper; + aHelper.aIterator = m_pMatrix->end(); + aHelper.pRowSet = _pRowSet; + return ORowSetCacheIterator(m_aCacheIterators.insert(m_aCacheIterators.begin(),ORowSetCacheMap::value_type(m_aCacheIterators.size()+1,aHelper)),this,_pRowSet); +} +// ----------------------------------------------------------------------------- +void ORowSetCache::deleteIterator(const ORowSetBase* _pRowSet) +{ + ORowSetCacheMap::iterator aCacheIter = m_aCacheIterators.begin(); + for(;aCacheIter != m_aCacheIterators.end();) + { + if ( aCacheIter->second.pRowSet == _pRowSet ) + { + m_aCacheIterators.erase(aCacheIter); + aCacheIter = m_aCacheIterators.begin(); + } // if ( aCacheIter->second.pRowSet == _pRowSet ) + else + ++aCacheIter; + } +} +// ----------------------------------------------------------------------------- +void ORowSetCache::rotateCacheIterator(ORowSetMatrix::difference_type _nDist) +{ + if(_nDist) + { + // now correct the iterator in our iterator vector + ORowSetCacheMap::iterator aCacheIter = m_aCacheIterators.begin(); + ORowSetCacheMap::iterator aCacheEnd = m_aCacheIterators.end(); + for(;aCacheIter != aCacheEnd;++aCacheIter) + { + if ( !aCacheIter->second.pRowSet->isInsertRow() + && aCacheIter->second.aIterator != m_pMatrix->end() && !m_bModified ) + { + ptrdiff_t nDist = (aCacheIter->second.aIterator - m_pMatrix->begin()); + if(nDist < _nDist) + { + aCacheIter->second.aIterator = m_pMatrix->end(); + } + else + { + OSL_ENSURE((aCacheIter->second.aIterator - m_pMatrix->begin()) >= _nDist,"Invalid Dist value!"); + aCacheIter->second.aIterator -= _nDist; + OSL_ENSURE(aCacheIter->second.aIterator >= m_pMatrix->begin() + && aCacheIter->second.aIterator < m_pMatrix->end(),"Iterator out of area!"); + } + } + } + } +} +// ------------------------------------------------------------------------- +void ORowSetCache::setUpdateIterator(const ORowSetMatrix::iterator& _rOriginalRow) +{ + m_aInsertRow = m_pInsertMatrix->begin(); + if(!m_aInsertRow->isValid()) + *m_aInsertRow = new ORowSetValueVector(m_xMetaData->getColumnCount()); + + (*(*m_aInsertRow)) = (*(*_rOriginalRow)); + // we don't unbound the bookmark column + ORowSetValueVector::Vector::iterator aIter = (*m_aInsertRow)->get().begin(); + ORowSetValueVector::Vector::iterator aEnd = (*m_aInsertRow)->get().end(); + for(;aIter != aEnd;++aIter) + aIter->setModified(sal_False); +} +// ----------------------------------------------------------------------------- +void ORowSetCache::checkPositionFlags() +{ + if(m_bRowCountFinal) + { + m_bAfterLast = m_nPosition > m_nRowCount; + if(m_bAfterLast) + m_nPosition = 0;//m_nRowCount; + } +} +// ----------------------------------------------------------------------------- +void ORowSetCache::checkUpdateConditions(sal_Int32 columnIndex) +{ + if(m_bAfterLast || columnIndex >= (sal_Int32)(*m_aInsertRow)->get().size()) + throwFunctionSequenceException(m_xSet.get()); +} +//------------------------------------------------------------------------------ +sal_Bool ORowSetCache::checkInnerJoin(const ::connectivity::OSQLParseNode *pNode,const Reference< XConnection>& _xConnection,const ::rtl::OUString& _sUpdateTableName) +{ + sal_Bool bOk = sal_False; + if (pNode->count() == 3 && // Ausdruck is geklammert + SQL_ISPUNCTUATION(pNode->getChild(0),"(") && + SQL_ISPUNCTUATION(pNode->getChild(2),")")) + { + bOk = checkInnerJoin(pNode->getChild(1),_xConnection,_sUpdateTableName); + } + else if ((SQL_ISRULE(pNode,search_condition) || SQL_ISRULE(pNode,boolean_term)) && // AND/OR-Verknuepfung: + pNode->count() == 3) + { + // nur AND Verknüpfung zulassen + if ( SQL_ISTOKEN(pNode->getChild(1),AND) ) + bOk = checkInnerJoin(pNode->getChild(0),_xConnection,_sUpdateTableName) + && checkInnerJoin(pNode->getChild(2),_xConnection,_sUpdateTableName); + } + else if (SQL_ISRULE(pNode,comparison_predicate)) + { + // only the comparison of columns is allowed + DBG_ASSERT(pNode->count() == 3,"checkInnerJoin: Fehler im Parse Tree"); + if (!(SQL_ISRULE(pNode->getChild(0),column_ref) && + SQL_ISRULE(pNode->getChild(2),column_ref) && + pNode->getChild(1)->getNodeType() == SQL_NODE_EQUAL)) + { + bOk = sal_False; + } + ::rtl::OUString sColumnName,sTableRange; + OSQLParseTreeIterator::getColumnRange( pNode->getChild(0), _xConnection, sColumnName, sTableRange ); + bOk = sTableRange == _sUpdateTableName; + if ( !bOk ) + { + OSQLParseTreeIterator::getColumnRange( pNode->getChild(2), _xConnection, sColumnName, sTableRange ); + bOk = sTableRange == _sUpdateTableName; + } + } + return bOk; +} +// ----------------------------------------------------------------------------- +sal_Bool ORowSetCache::checkJoin(const Reference< XConnection>& _xConnection, + const Reference< XSingleSelectQueryAnalyzer >& _xAnalyzer, + const ::rtl::OUString& _sUpdateTableName ) +{ + sal_Bool bOk = sal_False; + ::rtl::OUString sSql = _xAnalyzer->getQuery(); + ::rtl::OUString sErrorMsg; + ::connectivity::OSQLParser aSqlParser( m_aContext.getLegacyServiceFactory() ); + ::std::auto_ptr< ::connectivity::OSQLParseNode> pSqlParseNode( aSqlParser.parseTree(sErrorMsg,sSql)); + if ( pSqlParseNode.get() && SQL_ISRULE(pSqlParseNode, select_statement) ) + { + OSQLParseNode* pTableRefCommalist = pSqlParseNode->getByRule(::connectivity::OSQLParseNode::table_ref_commalist); + OSL_ENSURE(pTableRefCommalist,"NO tables why!?"); + if(pTableRefCommalist && pTableRefCommalist->count() == 1) + { + // we found only one element so it must some kind of join here + OSQLParseNode* pJoin = pTableRefCommalist->getByRule(::connectivity::OSQLParseNode::qualified_join); + if(pJoin) + { // we are only intereseted in qualified joins like RIGHT or LEFT + OSQLParseNode* pJoinType = pJoin->getChild(1); + OSQLParseNode* pOuterType = NULL; + if(SQL_ISRULE(pJoinType,join_type) && pJoinType->count() == 2) + pOuterType = pJoinType->getChild(0); + else if(SQL_ISRULE(pJoinType,outer_join_type)) + pOuterType = pJoinType; + + sal_Bool bCheck = sal_False; + sal_Bool bLeftSide = sal_False; + if(pOuterType) + { // found outer join + bLeftSide = SQL_ISTOKEN(pOuterType->getChild(0),LEFT); + bCheck = bLeftSide || SQL_ISTOKEN(pOuterType->getChild(0),RIGHT); + } + + if(bCheck) + { // here we know that we have to check on which side our table resides + const OSQLParseNode* pTableRef = pJoin->getByRule(::connectivity::OSQLParseNode::qualified_join); + if(bLeftSide) + pTableRef = pJoin->getChild(0); + else + pTableRef = pJoin->getChild(3); + OSL_ENSURE(SQL_ISRULE(pTableRef,table_ref),"Must be a tableref here!"); + + ::rtl::OUString sTableRange = OSQLParseNode::getTableRange(pTableRef); + if(!sTableRange.getLength()) + pTableRef->getChild(0)->parseNodeToStr( sTableRange, _xConnection, NULL, sal_False, sal_False ); + bOk = sTableRange == _sUpdateTableName; + } + } + } + else + { + OSQLParseNode* pWhereOpt = pSqlParseNode->getChild(3)->getChild(1); + if ( pWhereOpt && !pWhereOpt->isLeaf() ) + bOk = checkInnerJoin(pWhereOpt->getChild(1),_xConnection,_sUpdateTableName); + } + } + return bOk; +} +// ----------------------------------------------------------------------------- +void ORowSetCache::clearInsertRow() +{ + // we don't unbound the bookmark column + if ( m_aInsertRow != m_pInsertMatrix->end() && m_aInsertRow->isValid() ) + { + ORowSetValueVector::Vector::iterator aIter = (*m_aInsertRow)->get().begin()+1; + ORowSetValueVector::Vector::iterator aEnd = (*m_aInsertRow)->get().end(); + for(;aIter != aEnd;++aIter) + { + aIter->setBound(sal_False); + aIter->setModified(sal_False); + aIter->setNull(); + } // for(;aIter != (*m_aInsertRow)->end();++aIter) + } +} +// ----------------------------------------------------------------------------- +ORowSetMatrix::iterator ORowSetCache::calcPosition() const +{ + sal_Int32 nValue = (m_nPosition - m_nStartPos) - 1; + CHECK_MATRIX_POS(nValue); + return ( nValue < 0 || nValue >= static_cast<sal_Int32>(m_pMatrix->size()) ) ? m_pMatrix->end() : (m_pMatrix->begin() + nValue); +} +// ----------------------------------------------------------------------------- + +TORowSetOldRowHelperRef ORowSetCache::registerOldRow() +{ + TORowSetOldRowHelperRef pRef = new ORowSetOldRowHelper(ORowSetRow()); + m_aOldRows.push_back(pRef); + return pRef; +} +// ----------------------------------------------------------------------------- +void ORowSetCache::deregisterOldRow(const TORowSetOldRowHelperRef& _rRow) +{ + TOldRowSetRows::iterator aOldRowEnd = m_aOldRows.end(); + for (TOldRowSetRows::iterator aOldRowIter = m_aOldRows.begin(); aOldRowIter != aOldRowEnd; ++aOldRowIter) + { + if ( aOldRowIter->getBodyPtr() == _rRow.getBodyPtr() ) + { + m_aOldRows.erase(aOldRowIter); + break; + } + + } +} +// ----------------------------------------------------------------------------- +sal_Bool ORowSetCache::reFillMatrix(sal_Int32 _nNewStartPos,sal_Int32 _nNewEndPos) +{ + TOldRowSetRows::iterator aOldRowEnd = m_aOldRows.end(); + for (TOldRowSetRows::iterator aOldRowIter = m_aOldRows.begin(); aOldRowIter != aOldRowEnd; ++aOldRowIter) + { + if ( aOldRowIter->isValid() && aOldRowIter->getBody().getRow().isValid() ) + aOldRowIter->getBody().setRow(new ORowSetValueVector(aOldRowIter->getBody().getRow().getBody()) ); + } + sal_Int32 nNewSt = _nNewStartPos; + sal_Bool bRet = fillMatrix(nNewSt,_nNewEndPos); + m_nStartPos = nNewSt - 1; + rotateCacheIterator(static_cast<sal_Int16>(m_nFetchSize+1)); // forces that every iterator will be set to null + return bRet; +} +// ----------------------------------------------------------------------------- +sal_Bool ORowSetCache::fill(ORowSetMatrix::iterator& _aIter,const ORowSetMatrix::iterator& _aEnd,sal_Int32& _nPos,sal_Bool _bCheck) +{ + sal_Int32 nColumnCount = m_xMetaData->getColumnCount(); + for(; _bCheck && _aIter != _aEnd;) + { + if ( !_aIter->isValid() ) + *_aIter = new ORowSetValueVector(nColumnCount); + else + { + TOldRowSetRows::iterator aOldRowEnd = m_aOldRows.end(); + for (TOldRowSetRows::iterator aOldRowIter = m_aOldRows.begin(); aOldRowIter != aOldRowEnd; ++aOldRowIter) + { + if ( aOldRowIter->getBody().getRow().isEqualBody(*_aIter) ) + *_aIter = new ORowSetValueVector(nColumnCount); + } + } + m_pCacheSet->fillValueRow(*_aIter++,++_nPos); + _bCheck = m_pCacheSet->next(); + } + return _bCheck; +} +// ----------------------------------------------------------------------------- +bool ORowSetCache::isResultSetChanged() const +{ + return m_pCacheSet->isResultSetChanged(); +} +// ----------------------------------------------------------------------------- +void ORowSetCache::reset(const Reference< XResultSet>& _xDriverSet) +{ + m_xMetaData.set(Reference< XResultSetMetaDataSupplier >(_xDriverSet,UNO_QUERY)->getMetaData()); + m_pCacheSet->reset(_xDriverSet); + + m_bRowCountFinal = sal_False; + m_nRowCount = 0; + reFillMatrix(m_nStartPos+1,m_nEndPos+1); +} +// ----------------------------------------------------------------------------- +void ORowSetCache::impl_updateRowFromCache_throw(ORowSetValueVector::Vector& io_aRow + ,::std::vector<sal_Int32>& o_ChangedColumns) +{ + if ( o_ChangedColumns.size() > 1 ) + { + ORowSetMatrix::iterator aIter = m_pMatrix->begin(); + for(;aIter != m_pMatrix->end();++aIter) + { + if ( aIter->isValid() && m_pCacheSet->updateColumnValues((*aIter)->get(),io_aRow,o_ChangedColumns)) + { + break; + } + } + + if ( aIter == m_pMatrix->end() ) + { + m_pCacheSet->fillMissingValues(io_aRow); + } + } +} +// ----------------------------------------------------------------------------- diff --git a/dbaccess/source/core/api/RowSetCache.hxx b/dbaccess/source/core/api/RowSetCache.hxx new file mode 100644 index 000000000000..76e1d7145752 --- /dev/null +++ b/dbaccess/source/core/api/RowSetCache.hxx @@ -0,0 +1,273 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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_CORE_API_ROWSETCACHE_HXX +#define DBACCESS_CORE_API_ROWSETCACHE_HXX + +#ifndef _CONNECTIVITY_COMMONTOOLS_HXX_ +#include <connectivity/CommonTools.hxx> +#endif +#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_ +#include <com/sun/star/lang/XServiceInfo.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XPREPAREDSTATEMENT_HPP_ +#include <com/sun/star/sdbc/XPreparedStatement.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XCONNECTION_HPP_ +#include <com/sun/star/sdbc/XConnection.hpp> +#endif +#ifndef _COM_SUN_STAR_SDB_XSINGLESELECTQUERYANALYZER_HPP_ +#include <com/sun/star/sdb/XSingleSelectQueryAnalyzer.hpp> +#endif +#ifndef _COM_SUN_STAR_SDB_XSINGLESELECTQUERYANALYZER_HPP_ +#include <com/sun/star/sdb/XSingleSelectQueryAnalyzer.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XRESULTSETMETADATASUPPLIER_HPP_ +#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XWARNINGSSUPPLIER_HPP_ +#include <com/sun/star/sdbc/XWarningsSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_SDB_XRESULTSETACCESS_HPP_ +#include <com/sun/star/sdb/XResultSetAccess.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XROW_HPP_ +#include <com/sun/star/sdbc/XRow.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XCOLUMNLOCATE_HPP_ +#include <com/sun/star/sdbc/XColumnLocate.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBCX_XROWLOCATE_HPP_ +#include <com/sun/star/sdbcx/XRowLocate.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XROWUPDATE_HPP_ +#include <com/sun/star/sdbc/XRowUpdate.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XRESULTSETUPDATE_HPP_ +#include <com/sun/star/sdbc/XResultSetUpdate.hpp> +#endif +#ifndef _COM_SUN_STAR_SDB_XROWSETAPPROVEBROADCASTER_HPP_ +#include <com/sun/star/sdb/XRowSetApproveBroadcaster.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_RESULTSETTYPE_HPP_ +#include <com/sun/star/sdbc/ResultSetType.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBCX_XDELETEROWS_HPP_ +#include <com/sun/star/sdbcx/XDeleteRows.hpp> +#endif +#ifndef _CPPUHELPER_COMPBASE11_HXX_ +#include <cppuhelper/compbase11.hxx> +#endif +#ifndef _COMPHELPER_PROPERTYCONTAINER_HXX_ +#include <comphelper/propertycontainer.hxx> +#endif +#ifndef COMPHELPER_COMPONENTCONTEXT_HXX +#include <comphelper/componentcontext.hxx> +#endif +#ifndef _CPPUHELPER_IMPLBASE5_HXX_ +#include <cppuhelper/implbase5.hxx> +#endif +#ifndef _COMPHELPER_PROPERTY_ARRAY_HELPER_HXX_ +#include <comphelper/proparrhlp.hxx> +#endif +#ifndef DBACCESS_CORE_API_ROWSETROW_HXX +#include "RowSetRow.hxx" +#endif +#ifndef DBACCESS_ROWSETCACHEITERATOR_HXX +#include "RowSetCacheIterator.hxx" +#endif + +namespace connectivity +{ + class OSQLParseNode; +} +namespace dbaccess +{ + class OCacheSet; + class ORowSetDataColumns; + class ORowSetCacheClone; + + class ORowSetCache + { + friend class ORowSetBase; + friend class ORowSet; + friend class ORowSetClone; + friend class ORowSetCacheIterator; + + typedef ::std::vector< TORowSetOldRowHelperRef > TOldRowSetRows; + + ::std::map<sal_Int32,sal_Int32> m_aKeyColumns; + //the set can be static, bookmarkable or keyset + ::com::sun::star::uno::WeakReference< ::com::sun::star::sdbc::XResultSet> m_xSet; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSetMetaData > m_xMetaData; // must be before m_aInsertRow + ::comphelper::ComponentContext m_aContext; + + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRow> m_xCacheSet; + + OCacheSet* m_pCacheSet; // is a bookmarkable, keyset or static resultset + ORowSetMatrix* m_pMatrix; // represent the table struct + ORowSetMatrix::iterator m_aMatrixIter; // represent a row of the table + ORowSetMatrix::iterator m_aMatrixEnd; // present the row behind the last row of the table + ORowSetCacheMap m_aCacheIterators; + TOldRowSetRows m_aOldRows; + + ORowSetMatrix* m_pInsertMatrix; // represent the rows which should be inserted normally this is only one + ORowSetMatrix::iterator m_aInsertRow; // represent a insert row + + // ORowSetRow m_aInsertRow; // present the row that should be inserted + sal_Int32 m_nLastColumnIndex; // the last column ask for, used for wasNull() + + connectivity::OSQLTable m_aUpdateTable; // used for updates/deletes and inserts + + sal_Int32 m_nFetchSize; + sal_Int32 m_nRowCount; + sal_Int32 m_nPrivileges; + sal_Int32 m_nPosition; // 0 means beforefirst + + sal_Int32 m_nStartPos; // start pos of the window zero based + sal_Int32 m_nEndPos; // end pos of the window zero based + + sal_Bool m_bRowCountFinal ; + sal_Bool m_bBeforeFirst ; + sal_Bool m_bAfterLast ; + sal_Bool m_bUpdated ; + sal_Bool& m_bModified ; // points to the rowset member m_bModified + sal_Bool& m_bNew ; // points to the rowset member m_bNew + + sal_Bool fill(ORowSetMatrix::iterator& _aIter,const ORowSetMatrix::iterator& _aEnd,sal_Int32& _nPos,sal_Bool _bCheck); + sal_Bool reFillMatrix(sal_Int32 _nNewStartPos,sal_Int32 nNewEndPos); + sal_Bool fillMatrix(sal_Int32 &_nNewStartPos,sal_Int32 _nNewEndPos); + sal_Bool moveWindow(); + // returns true when a keyset needs to be created. + sal_Bool impl_createBookmarkSet_nothrow(const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet >& _xRs); + + void firePropertyChange(sal_Int32 _nColumnIndex,const ::connectivity::ORowSetValue& _rOldValue); + + void rotateCacheIterator(ORowSetMatrix::difference_type _nDist); + void updateValue(sal_Int32 columnIndex + ,const connectivity::ORowSetValue& x + ,ORowSetValueVector::Vector& io_aRow + ,::std::vector<sal_Int32>& o_ChangedColumns + ); + + void impl_updateRowFromCache_throw(ORowSetValueVector::Vector& io_aRow + ,::std::vector<sal_Int32>& o_ChangedColumns + ); + // checks and set the flags isAfterLast isLast and position when afterlast is true + void checkPositionFlags(); + void checkUpdateConditions(sal_Int32 columnIndex); + sal_Bool checkJoin( const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection>& _xConnection, + const ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XSingleSelectQueryAnalyzer >& _xComposer, + const ::rtl::OUString& _sUpdateTableName); + sal_Bool checkInnerJoin(const ::connectivity::OSQLParseNode *pNode + ,const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection>& _xConnection + ,const ::rtl::OUString& _sUpdateTableName); + + // clears the insert row + void clearInsertRow(); + ORowSetMatrix::iterator calcPosition() const; + + protected: + ORowSetMatrix::iterator& getEnd() { return m_aMatrixEnd;} + // is called when after a moveToInsertRow a movement (next, etc) was called + void cancelRowModification(); + public: + ORowSetCache(const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet >& _xRs, + const ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XSingleSelectQueryAnalyzer >& _xAnalyzer, + const ::comphelper::ComponentContext& _rContext, + const ::rtl::OUString& _rUpdateTableName, + sal_Bool& _bModified, + sal_Bool& _bNew, + const ORowSetValueVector& _aParameterValueForCache, + const ::rtl::OUString& i_sRowSetFilter); + ~ORowSetCache(); + + + // called from the rowset when a updateXXX was called for the first time + void setUpdateIterator(const ORowSetMatrix::iterator& _rOriginalRow); + ORowSetCacheIterator createIterator(ORowSetBase* _pRowSet); + void deleteIterator(const ORowSetBase* _pRowSet); + // sets the size of the matrix + void setMaxRowSize(sal_Int32 _nSize); + + TORowSetOldRowHelperRef registerOldRow(); + void deregisterOldRow(const TORowSetOldRowHelperRef& _rRow); + + // ::com::sun::star::sdbc::XResultSetMetaDataSupplier + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSetMetaData > getMetaData( ); + + // ::com::sun::star::sdbcx::XRowLocate + ::com::sun::star::uno::Any getBookmark( ); + sal_Bool moveToBookmark( const ::com::sun::star::uno::Any& bookmark ); + sal_Bool moveRelativeToBookmark( const ::com::sun::star::uno::Any& bookmark, sal_Int32 rows ); + sal_Int32 compareBookmarks( const ::com::sun::star::uno::Any& first, const ::com::sun::star::uno::Any& second ); + sal_Bool hasOrderedBookmarks( ); + sal_Int32 hashBookmark( const ::com::sun::star::uno::Any& bookmark ); + + // ::com::sun::star::sdbc::XRowUpdate + void updateCharacterStream( sal_Int32 columnIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length,ORowSetValueVector::Vector& io_aRow,::std::vector<sal_Int32>& o_ChangedColumns + ); + void updateObject( sal_Int32 columnIndex, const ::com::sun::star::uno::Any& x,ORowSetValueVector::Vector& io_aRow ,::std::vector<sal_Int32>& o_ChangedColumns); + void updateNumericObject( sal_Int32 columnIndex, const ::com::sun::star::uno::Any& x, sal_Int32 scale,ORowSetValueVector::Vector& io_aRow ,::std::vector<sal_Int32>& o_ChangedColumns); + void updateNull(sal_Int32 columnIndex + ,ORowSetValueVector::Vector& io_aRow + ,::std::vector<sal_Int32>& o_ChangedColumns + ); + + // ::com::sun::star::sdbc::XResultSet + sal_Bool next( ); + sal_Bool isBeforeFirst( ); + sal_Bool isAfterLast( ); + sal_Bool isFirst( ); + sal_Bool isLast( ); + sal_Bool beforeFirst( ); + sal_Bool afterLast( ); + sal_Bool first( ); + sal_Bool last( ); + sal_Int32 getRow( ); + sal_Bool absolute( sal_Int32 row ); + sal_Bool relative( sal_Int32 rows ); + sal_Bool previous( ); + void refreshRow( ); + sal_Bool rowUpdated( ); + sal_Bool rowInserted( ); + + // ::com::sun::star::sdbc::XResultSetUpdate + sal_Bool insertRow(::std::vector< ::com::sun::star::uno::Any >& o_aBookmarks); + void resetInsertRow(sal_Bool _bClearInsertRow); + + void updateRow( ORowSetMatrix::iterator& _rUpdateRow,::std::vector< ::com::sun::star::uno::Any >& o_aBookmarks ); + bool deleteRow(); + void cancelRowUpdates( ); + void moveToInsertRow( ); + + const ::std::map<sal_Int32,sal_Int32>& getKeyColumns() const { return m_aKeyColumns; } + bool isResultSetChanged() const; + void reset(const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet>& _xDriverSet); + }; +} +#endif + diff --git a/dbaccess/source/core/api/RowSetCacheIterator.cxx b/dbaccess/source/core/api/RowSetCacheIterator.cxx new file mode 100644 index 000000000000..29d3f38278f4 --- /dev/null +++ b/dbaccess/source/core/api/RowSetCacheIterator.cxx @@ -0,0 +1,152 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" +#ifndef DBACCESS_ROWSETCACHEITERATOR_HXX +#include "RowSetCacheIterator.hxx" +#endif +#ifndef DBACCESS_CORE_API_ROWSETCACHE_HXX +#include "RowSetCache.hxx" +#endif +#ifndef DBACCESS_CORE_API_ROWSETBASE_HXX +#include "RowSetBase.hxx" +#endif +#include <rtl/logfile.hxx> + +using namespace dbaccess; +ORowSetCacheIterator::ORowSetCacheIterator(const ORowSetCacheIterator& _rRH) +: m_aIter(_rRH.m_aIter) +, m_pCache(_rRH.m_pCache) +,m_pRowSet(_rRH.m_pRowSet) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetCacheIterator::ORowSetCacheIterator" ); +} +// ----------------------------------------------------------------------------- +ORowSetCacheIterator::operator ORowSetMatrix::iterator() +{ + return m_aIter->second.aIterator; +} +// ----------------------------------------------------------------------------- +ORowSetCacheIterator& ORowSetCacheIterator::operator =(const ORowSetCacheIterator& _rRH) +{ + if(this == &_rRH) + return *this; + + m_pCache = _rRH.m_pCache; + m_aIter = _rRH.m_aIter; + m_pRowSet = _rRH.m_pRowSet; + + return *this; +} +// ----------------------------------------------------------------------------- +ORowSetCacheIterator& ORowSetCacheIterator::operator =(const ORowSetMatrix::iterator& _rIter) +{ + m_aIter->second.aIterator = _rIter; + return *this; +} +// ----------------------------------------------------------------------------- +ORowSetRow& ORowSetCacheIterator::operator *() +{ + return *m_aIter->second.aIterator; +} +// ----------------------------------------------------------------------------- +const ORowSetRow& ORowSetCacheIterator::operator *() const +{ + if ( !m_pRowSet->isInsertRow() && m_aIter->second.aIterator == m_pCache->m_pMatrix->end() ) + { + OSL_ENSURE(m_aIter->second.aBookmark.hasValue(),"bookmark has no value!"); + OSL_VERIFY(m_pCache->moveToBookmark(m_aIter->second.aBookmark)); + m_aIter->second.aIterator = m_pCache->m_aMatrixIter; + } + return *m_aIter->second.aIterator; +} +// ----------------------------------------------------------------------------- +ORowSetMatrix::iterator& ORowSetCacheIterator::operator ->() +{ + return m_aIter->second.aIterator; +} +// ----------------------------------------------------------------------------- +const ORowSetMatrix::iterator& ORowSetCacheIterator::operator ->() const +{ + if ( !m_pRowSet->isInsertRow() && m_aIter->second.aIterator == m_pCache->m_pMatrix->end() ) + { + OSL_ENSURE(m_aIter->second.aBookmark.hasValue(),"bookmark has no value!"); + OSL_VERIFY(m_pCache->moveToBookmark(m_aIter->second.aBookmark)); + m_aIter->second.aIterator = m_pCache->m_aMatrixIter; + } + return m_aIter->second.aIterator; +} +// ----------------------------------------------------------------------------- +bool ORowSetCacheIterator::operator <=(const ORowSetMatrix::iterator& _rRH) const +{ + return m_aIter->second.aIterator <= _rRH; +} +// ----------------------------------------------------------------------------- +bool ORowSetCacheIterator::operator <(const ORowSetMatrix::iterator& _rRH) const +{ + return m_aIter->second.aIterator < _rRH; +} +// ----------------------------------------------------------------------------- +bool ORowSetCacheIterator::operator !=(const ORowSetMatrix::iterator& _rRH) const +{ + return m_aIter->second.aIterator != _rRH; +} +// ----------------------------------------------------------------------------- +bool ORowSetCacheIterator::operator ==(const ORowSetMatrix::iterator& _rRH) const +{ + return m_aIter->second.aIterator == _rRH; +} +// ----------------------------------------------------------------------------- +void ORowSetCacheIterator::setBookmark(const ::com::sun::star::uno::Any& _rBookmark) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetCacheIterator::setBookmark" ); + m_aIter->second.aBookmark = _rBookmark; +} +// ----------------------------------------------------------------------------- +sal_Bool ORowSetCacheIterator::isNull() const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetCacheIterator::isNull" ); + sal_Bool bRet = !m_pCache || !m_pRowSet || m_aIter == m_pCache->m_aCacheIterators.end(); + if ( !bRet ) + { + ORowSetCacheIterator_Helper aHelper = m_aIter->second; + bRet = ( m_pRowSet->isInsertRow() + ? + m_aIter->second.aIterator == m_pCache->m_pInsertMatrix->end() + : + m_aIter->second.aIterator == m_pCache->m_pMatrix->end() + ); + } + return bRet; +} +// ----------------------------------------------------------------------------- +::osl::Mutex* ORowSetCacheIterator::getMutex() const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetCacheIterator::getMutex" ); + return m_pRowSet ? m_pRowSet->getMutex() : NULL; +} diff --git a/dbaccess/source/core/api/RowSetCacheIterator.hxx b/dbaccess/source/core/api/RowSetCacheIterator.hxx new file mode 100644 index 000000000000..6c4c1a8576ce --- /dev/null +++ b/dbaccess/source/core/api/RowSetCacheIterator.hxx @@ -0,0 +1,92 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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_ROWSETCACHEITERATOR_HXX +#define DBACCESS_ROWSETCACHEITERATOR_HXX + +#ifndef DBACCESS_CORE_API_ROWSETROW_HXX +#include "RowSetRow.hxx" +#endif +#ifndef _COMPHELPER_STLTYPES_HXX_ +#include <comphelper/stl_types.hxx> +#endif + +namespace dbaccess +{ + class ORowSetBase; + typedef struct + { + ORowSetMatrix::iterator aIterator; + ::com::sun::star::uno::Any aBookmark; + ORowSetBase* pRowSet; + } ORowSetCacheIterator_Helper; + + DECLARE_STL_STDKEY_MAP(sal_Int32,ORowSetCacheIterator_Helper,ORowSetCacheMap); + + class ORowSetCache; + class ORowSetCacheIterator + { + friend class ORowSetCache; + ORowSetCacheMap::iterator m_aIter; + ORowSetCache* m_pCache; + ORowSetBase* m_pRowSet; + protected: + ORowSetCacheIterator(const ORowSetCacheMap::iterator& _rIter,ORowSetCache* _pCache,ORowSetBase* _pRowSet) + : m_aIter(_rIter) + ,m_pCache(_pCache) + ,m_pRowSet(_pRowSet) + { + } + public: + ORowSetCacheIterator() :m_aIter(),m_pCache(NULL),m_pRowSet(NULL){} + ORowSetCacheIterator(const ORowSetCacheIterator& _rRH); + ORowSetCacheIterator& operator =(const ORowSetCacheIterator&); + + sal_Bool isNull() const; + ORowSetCacheIterator& operator =(const ORowSetMatrix::iterator&); + operator ORowSetMatrix::iterator(); + + ORowSetRow& operator *(); + const ORowSetRow& operator *() const; + + ORowSetMatrix::iterator& operator ->(); + const ORowSetMatrix::iterator& operator ->() const; + + bool operator <=(const ORowSetMatrix::iterator& _rRH) const; + bool operator <(const ORowSetMatrix::iterator& _rRH) const; + bool operator !=(const ORowSetMatrix::iterator& _rRH) const; + bool operator ==(const ORowSetMatrix::iterator& _rRH) const; + + void setBookmark(const ::com::sun::star::uno::Any& _rBookmark); + ::com::sun::star::uno::Any getBookmark() const { return m_aIter->second.aBookmark; } + ::osl::Mutex* getMutex() const; + + ORowSetCacheMap::iterator getIter() const { return m_aIter; } + }; +} +#endif // DBACCESS_ROWSETCACHEITERATOR_HXX + + diff --git a/dbaccess/source/core/api/RowSetRow.hxx b/dbaccess/source/core/api/RowSetRow.hxx new file mode 100644 index 000000000000..1178c2990b83 --- /dev/null +++ b/dbaccess/source/core/api/RowSetRow.hxx @@ -0,0 +1,108 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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_CORE_API_ROWSETROW_HXX +#define DBACCESS_CORE_API_ROWSETROW_HXX + +#ifndef _VOS_REF_HXX_ +#include <vos/ref.hxx> +#endif +#ifndef _CONNECTIVITY_COMMONTOOLS_HXX_ +#include <connectivity/CommonTools.hxx> +#endif +#ifndef _CONNECTIVITY_FILE_VALUE_HXX_ +#include "connectivity/FValue.hxx" +#endif +#ifndef _COMPHELPER_TYPES_HXX_ +#include <comphelper/types.hxx> +#endif + +namespace dbaccess +{ + typedef connectivity::ORowVector< connectivity::ORowSetValue > ORowSetValueVector; + typedef ::vos::ORef< ORowSetValueVector > ORowSetRow; + typedef ::std::vector< ORowSetRow > ORowSetMatrix; + + class ORowSetOldRowHelper + { + oslInterlockedCount m_refCount; + ORowSetRow m_aRow; + + ORowSetOldRowHelper& operator=(const ORowSetOldRowHelper& _rRH); + ORowSetOldRowHelper(const ORowSetOldRowHelper& _rRh); + public: + ORowSetOldRowHelper() : m_refCount(0){} + ORowSetOldRowHelper(const ORowSetRow& _rRow) + : m_refCount(0) + , m_aRow(_rRow) + {} +// ORowSetOldRowHelper(const ORowSetOldRowHelper& _rRh) +// : m_refCount(0) +// , m_aRow(_rRh.m_aRow) +// {} + + void acquire() + { + osl_incrementInterlockedCount( &m_refCount ); + } + void release() + { + if (! osl_decrementInterlockedCount( &m_refCount )) + delete this; + } + inline ORowSetRow getRow() const { return m_aRow; } + inline void clearRow() { m_aRow = NULL; } + inline void setRow(const ORowSetRow& _rRow) { m_aRow = _rRow; } + }; + + typedef ::vos::ORef< ORowSetOldRowHelper > TORowSetOldRowHelperRef; + + class ORowSetValueCompare + { + const ::com::sun::star::uno::Any& m_rAny; + public: + ORowSetValueCompare(const ::com::sun::star::uno::Any& _rAny) : m_rAny(_rAny){} + + sal_Bool operator ()(const ORowSetRow& _rRH) + { + switch((_rRH->get())[0].getTypeKind()) + { + case ::com::sun::star::sdbc::DataType::TINYINT: + case ::com::sun::star::sdbc::DataType::SMALLINT: + case ::com::sun::star::sdbc::DataType::INTEGER: + return comphelper::getINT32(m_rAny) == (sal_Int32)(_rRH->get())[0]; + default: + { + ::com::sun::star::uno::Sequence<sal_Int8> aSeq; + m_rAny >>= aSeq; + return aSeq == (_rRH->get())[0]; + } + } + } + }; +} +#endif // DBACCESS_CORE_API_ROWSETROW_HXX + diff --git a/dbaccess/source/core/api/SingleSelectQueryComposer.cxx b/dbaccess/source/core/api/SingleSelectQueryComposer.cxx new file mode 100644 index 000000000000..2f9a58c975b7 --- /dev/null +++ b/dbaccess/source/core/api/SingleSelectQueryComposer.cxx @@ -0,0 +1,1875 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#include "composertools.hxx" +#include "core_resource.hrc" +#include "core_resource.hxx" +#include "dbastrings.hrc" +#include "HelperCollections.hxx" +#include "SingleSelectQueryComposer.hxx" +#include "sdbcoretools.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/container/XChild.hpp> +#include <com/sun/star/i18n/XLocaleData.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/sdb/BooleanComparisonMode.hpp> +#include <com/sun/star/sdb/SQLFilterOperator.hpp> +#include <com/sun/star/sdb/XQueriesSupplier.hpp> +#include <com/sun/star/sdb/CommandType.hpp> +#include <com/sun/star/sdbc/ColumnSearch.hpp> +#include <com/sun/star/sdbc/DataType.hpp> +#include <com/sun/star/sdbc/XResultSetMetaData.hpp> +#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp> +#include <com/sun/star/sdbc/XParameters.hpp> +#include <com/sun/star/uno/XAggregation.hpp> +#include <com/sun/star/util/XNumberFormatter.hpp> +/** === end UNO includes === **/ + +#include <comphelper/processfactory.hxx> +#include <comphelper/sequence.hxx> +#include <comphelper/types.hxx> +#include <cppuhelper/typeprovider.hxx> +#include <rtl/logfile.hxx> +#include <unotools/syslocale.hxx> +#include <tools/debug.hxx> +#include <tools/diagnose_ex.h> +#include <unotools/configmgr.hxx> +#include <unotools/sharedunocomponent.hxx> + +#include <memory> + +using namespace ::dbaccess; +using namespace ::dbtools; +using namespace ::comphelper; +using namespace ::connectivity; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::i18n; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::script; +using namespace ::com::sun::star::util; +using namespace ::cppu; +using namespace ::osl; +using namespace ::utl; + +namespace dbaccess { +namespace BooleanComparisonMode = ::com::sun::star::sdb::BooleanComparisonMode; +} + +#define STR_SELECT ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SELECT ")) +#define STR_FROM ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" FROM ")) +#define STR_WHERE ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" WHERE ")) +#define STR_GROUP_BY ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" GROUP BY ")) +#define STR_HAVING ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" HAVING ")) +#define STR_ORDER_BY ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" ORDER BY ")) +#define STR_AND ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" AND ")) +#define STR_OR ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" OR ")) +#define STR_LIKE ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" LIKE ")) +#define STR_EQUAL ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" = ")) +#define L_BRACKET ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("(")) +#define R_BRACKET ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(")")) +#define COMMA ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(",")) + +// ------------------------------------------------------------------------- +namespace +{ + // ..................................................................... + /** parses the given statement, using the given parser, returns a parse node representing + the statement + + If the statement cannot be parsed, an error is thrown. + */ + const OSQLParseNode* parseStatement_throwError( OSQLParser& _rParser, const ::rtl::OUString& _rStatement, const Reference< XInterface >& _rxContext ) + { + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "frank.schoenheit@sun.com", "SingleSelectQueryComposer.cxx::parseStatement_throwError" ); + ::rtl::OUString aErrorMsg; + const OSQLParseNode* pNewSqlParseNode = _rParser.parseTree( aErrorMsg, _rStatement ); + if ( !pNewSqlParseNode ) + { + ::rtl::OUString sSQLStateGeneralError( getStandardSQLState( SQL_GENERAL_ERROR ) ); + SQLException aError2( aErrorMsg, _rxContext, sSQLStateGeneralError, 1000, Any() ); + SQLException aError1( _rStatement, _rxContext, sSQLStateGeneralError, 1000, makeAny( aError2 ) ); + throw SQLException(_rParser.getContext().getErrorMessage(OParseContext::ERROR_GENERAL),_rxContext,sSQLStateGeneralError,1000,makeAny(aError1)); + } + return pNewSqlParseNode; + } + + // ..................................................................... + /** checks whether the given parse node describes a valid single select statement, throws + an error if not + */ + void checkForSingleSelect_throwError( const OSQLParseNode* pStatementNode, OSQLParseTreeIterator& _rIterator, + const Reference< XInterface >& _rxContext, const ::rtl::OUString& _rOriginatingCommand ) + { + const OSQLParseNode* pOldNode = _rIterator.getParseTree(); + + // determine the statement type + _rIterator.setParseTree( pStatementNode ); + _rIterator.traverseAll(); + bool bIsSingleSelect = ( _rIterator.getStatementType() == SQL_STATEMENT_SELECT ); + + // throw the error, if necessary + if ( !bIsSingleSelect || SQL_ISRULE( pStatementNode, union_statement ) ) // #i4229# OJ + { + // restore the old node before throwing the exception + _rIterator.setParseTree( pOldNode ); + // and now really ... + SQLException aError1( _rOriginatingCommand, _rxContext, getStandardSQLState( SQL_GENERAL_ERROR ), 1000, Any() ); + throw SQLException( DBACORE_RESSTRING( RID_STR_ONLY_QUERY ), _rxContext, + getStandardSQLState( SQL_GENERAL_ERROR ), 1000, makeAny( aError1 ) ); + } + + delete pOldNode; + } + + // ..................................................................... + /** combines parseStatement_throwError and checkForSingleSelect_throwError + */ + void parseAndCheck_throwError( OSQLParser& _rParser, const ::rtl::OUString& _rStatement, + OSQLParseTreeIterator& _rIterator, const Reference< XInterface >& _rxContext ) + { + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "frank.schoenheit@sun.com", "SingleSelectQueryComposer.cxx::parseAndCheck_throwError" ); + const OSQLParseNode* pNode = parseStatement_throwError( _rParser, _rStatement, _rxContext ); + checkForSingleSelect_throwError( pNode, _rIterator, _rxContext, _rStatement ); + } + + // ..................................................................... + /** transforms a parse node describing a complete statement into a pure select + statement, without any filter/order/groupby/having clauses + */ + ::rtl::OUString getPureSelectStatement( const OSQLParseNode* _pRootNode, Reference< XConnection > _rxConnection ) + { + ::rtl::OUString sSQL = STR_SELECT; + _pRootNode->getChild(1)->parseNodeToStr( sSQL, _rxConnection ); + _pRootNode->getChild(2)->parseNodeToStr( sSQL, _rxConnection ); + sSQL += STR_FROM; + _pRootNode->getChild(3)->getChild(0)->getChild(1)->parseNodeToStr( sSQL, _rxConnection ); + return sSQL; + } + + /** resets an SQL iterator, including deletion of the parse tree, and disposal if desired + */ + void resetIterator( OSQLParseTreeIterator& _rIterator, bool _bDispose ) + { + const OSQLParseNode* pSqlParseNode = _rIterator.getParseTree(); + _rIterator.setParseTree(NULL); + delete pSqlParseNode; + if ( _bDispose ) + _rIterator.dispose(); + } + void lcl_addFilterCriteria_throw(sal_Int32 i_nFilterOperator,const ::rtl::OUString& i_sValue,::rtl::OUStringBuffer& o_sRet) + { + switch( i_nFilterOperator ) + { + case SQLFilterOperator::EQUAL: + o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" = "))); + o_sRet.append(i_sValue); + break; + case SQLFilterOperator::NOT_EQUAL: + o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" <> "))); + o_sRet.append(i_sValue); + break; + case SQLFilterOperator::LESS: + o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" < "))); + o_sRet.append(i_sValue); + break; + case SQLFilterOperator::GREATER: + o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" > "))); + o_sRet.append(i_sValue); + break; + case SQLFilterOperator::LESS_EQUAL: + o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" <= "))); + o_sRet.append(i_sValue); + break; + case SQLFilterOperator::GREATER_EQUAL: + o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" >= "))); + o_sRet.append(i_sValue); + break; + case SQLFilterOperator::LIKE: + o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" LIKE "))); + o_sRet.append(i_sValue); + break; + case SQLFilterOperator::NOT_LIKE: + o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" NOT LIKE "))); + o_sRet.append(i_sValue); + break; + case SQLFilterOperator::SQLNULL: + o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" IS NULL")) ); + break; + case SQLFilterOperator::NOT_SQLNULL: + o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" IS NOT NULL")) ); + break; + default: + throw SQLException(); + } + } + +} + +DBG_NAME(OSingleSelectQueryComposer) +// ------------------------------------------------------------------------- +OSingleSelectQueryComposer::OSingleSelectQueryComposer(const Reference< XNameAccess>& _rxTables, + const Reference< XConnection>& _xConnection, + const ::comphelper::ComponentContext& _rContext ) + :OSubComponent(m_aMutex,_xConnection) + ,OPropertyContainer(m_aBHelper) + ,m_aSqlParser( _rContext.getLegacyServiceFactory() ) + ,m_aSqlIterator( _xConnection, _rxTables, m_aSqlParser, NULL ) + ,m_aAdditiveIterator( _xConnection, _rxTables, m_aSqlParser, NULL ) + ,m_aElementaryParts( (size_t)SQLPartCount ) + ,m_xConnection(_xConnection) + ,m_xMetaData(_xConnection->getMetaData()) + ,m_xConnectionTables( _rxTables ) + ,m_aContext( _rContext ) + ,m_pTables(NULL) + ,m_nBoolCompareMode( BooleanComparisonMode::EQUAL_INTEGER ) + ,m_nCommandType(CommandType::COMMAND) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::OSingleSelectQueryComposer" ); + DBG_CTOR(OSingleSelectQueryComposer,NULL); + + if ( !m_aContext.is() || !m_xConnection.is() || !m_xConnectionTables.is() ) + throw IllegalArgumentException(); + + registerProperty(PROPERTY_ORIGINAL,PROPERTY_ID_ORIGINAL,PropertyAttribute::BOUND|PropertyAttribute::READONLY,&m_sOrignal,::getCppuType(&m_sOrignal)); + + m_aCurrentColumns.resize(4); + + m_aLocale = SvtSysLocale().GetLocaleData().getLocale(); + m_xNumberFormatsSupplier = dbtools::getNumberFormats( m_xConnection, sal_True, m_aContext.getLegacyServiceFactory() ); + Reference< XLocaleData > xLocaleData; + m_aContext.createComponent( "com.sun.star.i18n.LocaleData", xLocaleData ); + LocaleDataItem aData = xLocaleData->getLocaleItem(m_aLocale); + m_sDecimalSep = aData.decimalSeparator; + OSL_ENSURE(m_sDecimalSep.getLength() == 1,"OSingleSelectQueryComposer::OSingleSelectQueryComposer decimal separator is not 1 length"); + try + { + Any aValue; + Reference<XInterface> xDs = dbaccess::getDataSource(_xConnection); + if ( dbtools::getDataSourceSetting(xDs,static_cast <rtl::OUString> (PROPERTY_BOOLEANCOMPARISONMODE),aValue) ) + { + OSL_VERIFY( aValue >>= m_nBoolCompareMode ); + } + Reference< XQueriesSupplier > xQueriesAccess(m_xConnection, UNO_QUERY); + if (xQueriesAccess.is()) + m_xConnectionQueries = xQueriesAccess->getQueries(); + } + catch(Exception&) + { + } +} +// ------------------------------------------------------------------------- +OSingleSelectQueryComposer::~OSingleSelectQueryComposer() +{ + DBG_DTOR(OSingleSelectQueryComposer,NULL); + ::std::vector<OPrivateColumns*>::iterator aColIter = m_aColumnsCollection.begin(); + ::std::vector<OPrivateColumns*>::iterator aEnd = m_aColumnsCollection.end(); + for(;aColIter != aEnd;++aColIter) + delete *aColIter; + + ::std::vector<OPrivateTables*>::iterator aTabIter = m_aTablesCollection.begin(); + ::std::vector<OPrivateTables*>::iterator aTabEnd = m_aTablesCollection.end(); + for(;aTabIter != aTabEnd;++aTabIter) + delete *aTabIter; +} +// ------------------------------------------------------------------------- +// OComponentHelper +void SAL_CALL OSingleSelectQueryComposer::disposing(void) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::disposing" ); + OSubComponent::disposing(); + + MutexGuard aGuard(m_aMutex); + + resetIterator( m_aSqlIterator, true ); + resetIterator( m_aAdditiveIterator, true ); + + m_xConnectionTables = NULL; + m_xConnection = NULL; + + clearCurrentCollections(); +} +IMPLEMENT_FORWARD_XINTERFACE3(OSingleSelectQueryComposer,OSubComponent,OSingleSelectQueryComposer_BASE,OPropertyContainer) +IMPLEMENT_SERVICE_INFO1(OSingleSelectQueryComposer,"org.openoffice.comp.dba.OSingleSelectQueryComposer",SERVICE_NAME_SINGLESELECTQUERYCOMPOSER) +IMPLEMENT_TYPEPROVIDER3(OSingleSelectQueryComposer,OSubComponent,OSingleSelectQueryComposer_BASE,OPropertyContainer) +IMPLEMENT_PROPERTYCONTAINER_DEFAULTS(OSingleSelectQueryComposer) + +// ------------------------------------------------------------------------- +// com::sun::star::lang::XUnoTunnel +sal_Int64 SAL_CALL OSingleSelectQueryComposer::getSomething( const Sequence< sal_Int8 >& rId ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getSomething" ); + if (rId.getLength() == 16 && 0 == rtl_compareMemory(getImplementationId().getConstArray(), rId.getConstArray(), 16 ) ) + return reinterpret_cast<sal_Int64>(this); + + return sal_Int64(0); +} + +// ------------------------------------------------------------------------- +// XSingleSelectQueryAnalyzer +::rtl::OUString SAL_CALL OSingleSelectQueryComposer::getQuery( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getQuery" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + ::osl::MutexGuard aGuard( m_aMutex ); + + TGetParseNode F_tmp(&OSQLParseTreeIterator::getParseTree); + return getStatementPart(F_tmp,m_aSqlIterator); +} + +// ------------------------------------------------------------------------- +void SAL_CALL OSingleSelectQueryComposer::setQuery( const ::rtl::OUString& command ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "frank.schoenheit@sun.com", "OSingleSelectQueryComposer::setQuery" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( m_aMutex ); + m_nCommandType = CommandType::COMMAND; + // first clear the tables and columns + clearCurrentCollections(); + // now set the new one + setQuery_Impl(command); + m_sOrignal = command; + + // reset the additive iterator to the same statement + parseAndCheck_throwError( m_aSqlParser, m_sOrignal, m_aAdditiveIterator, *this ); + + // we have no "elementary" parts anymore (means filter/groupby/having/order clauses) + for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) ) + m_aElementaryParts[ eLoopParts ] = ::rtl::OUString(); +} +// ------------------------------------------------------------------------- +void SAL_CALL OSingleSelectQueryComposer::setCommand( const ::rtl::OUString& Command,sal_Int32 _nCommandType ) throw(SQLException, RuntimeException) +{ + ::rtl::OUStringBuffer sSQL; + switch(_nCommandType) + { + case CommandType::COMMAND: + setElementaryQuery(Command); + return; + case CommandType::TABLE: + if ( m_xConnectionTables->hasByName(Command) ) + { + sSQL.appendAscii("SELECT * FROM "); + Reference< XPropertySet > xTable; + try + { + m_xConnectionTables->getByName( Command ) >>= xTable; + } + catch(const WrappedTargetException& e) + { + SQLException e2; + if ( e.TargetException >>= e2 ) + throw e2; + } + catch(Exception&) + { + DBG_UNHANDLED_EXCEPTION(); + } + + sSQL.append(dbtools::composeTableNameForSelect(m_xConnection,xTable)); + } + else + { + String sMessage( DBACORE_RESSTRING( RID_STR_TABLE_DOES_NOT_EXIST ) ); + sMessage.SearchAndReplaceAscii( "$table$", Command ); + throwGenericSQLException(sMessage,*this); + } + break; + case CommandType::QUERY: + if ( m_xConnectionQueries->hasByName(Command) ) + { + + Reference<XPropertySet> xQuery(m_xConnectionQueries->getByName(Command),UNO_QUERY); + ::rtl::OUString sCommand; + xQuery->getPropertyValue(PROPERTY_COMMAND) >>= sCommand; + sSQL.append(sCommand); + } + else + { + String sMessage( DBACORE_RESSTRING( RID_STR_QUERY_DOES_NOT_EXIST ) ); + sMessage.SearchAndReplaceAscii( "$table$", Command ); + throwGenericSQLException(sMessage,*this); + } + + break; + default: + break; + } + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( m_aMutex ); + m_nCommandType = _nCommandType; + m_sCommand = Command; + // first clear the tables and columns + clearCurrentCollections(); + // now set the new one + ::rtl::OUString sCommand = sSQL.makeStringAndClear(); + setElementaryQuery(sCommand); + m_sOrignal = sCommand; +/* + // reset the additive iterator to the same statement + parseAndCheck_throwError( m_aSqlParser, m_sOrignal, m_aAdditiveIterator, *this ); + + // we have no "elementary" parts anymore (means filter/groupby/having/order clauses) + for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) ) + m_aElementaryParts[ eLoopParts ] = ::rtl::OUString(); +*/ +} +// ----------------------------------------------------------------------------- +void OSingleSelectQueryComposer::setQuery_Impl( const ::rtl::OUString& command ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "frank.schoenheit@sun.com", "OSingleSelectQueryComposer::setQuery_Impl" ); + // parse this + parseAndCheck_throwError( m_aSqlParser, command, m_aSqlIterator, *this ); + + // strip it from all clauses, to have the pure SELECT statement + m_aPureSelectSQL = getPureSelectStatement( m_aSqlIterator.getParseTree(), m_xConnection ); + + // update columns and tables + // why? Shouldn't this be done on request only? + // otherwise nothing is working anymore :-) +// getColumns(); + getTables(); +} +// ----------------------------------------------------------------------------- +Sequence< Sequence< PropertyValue > > SAL_CALL OSingleSelectQueryComposer::getStructuredHavingClause( ) throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getStructuredHavingClause" ); + TGetParseNode F_tmp(&OSQLParseTreeIterator::getSimpleHavingTree); + return getStructuredCondition(F_tmp); +} +// ------------------------------------------------------------------------- +Sequence< Sequence< PropertyValue > > SAL_CALL OSingleSelectQueryComposer::getStructuredFilter( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getStructuredFilter" ); + TGetParseNode F_tmp(&OSQLParseTreeIterator::getSimpleWhereTree); + return getStructuredCondition(F_tmp); +} +// ----------------------------------------------------------------------------- +void SAL_CALL OSingleSelectQueryComposer::appendHavingClauseByColumn( const Reference< XPropertySet >& column, sal_Bool andCriteria,sal_Int32 filterOperator ) throw (SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::appendHavingClauseByColumn" ); + ::std::mem_fun1_t<bool,OSingleSelectQueryComposer,::rtl::OUString> F_tmp(&OSingleSelectQueryComposer::implSetHavingClause); + setConditionByColumn(column,andCriteria,F_tmp,filterOperator); +} +// ----------------------------------------------------------------------------- +void SAL_CALL OSingleSelectQueryComposer::appendFilterByColumn( const Reference< XPropertySet >& column, sal_Bool andCriteria,sal_Int32 filterOperator ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::appendFilterByColumn" ); + ::std::mem_fun1_t<bool,OSingleSelectQueryComposer,::rtl::OUString> F_tmp(&OSingleSelectQueryComposer::implSetFilter); + setConditionByColumn(column,andCriteria,F_tmp,filterOperator); +} +// ----------------------------------------------------------------------------- +::rtl::OUString OSingleSelectQueryComposer::impl_getColumnName_throw(const Reference< XPropertySet >& column) +{ + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + + getColumns(); + if ( !column.is() + || !m_aCurrentColumns[SelectColumns] + || !column->getPropertySetInfo()->hasPropertyByName(PROPERTY_NAME) + ) + { + String sError(DBACORE_RESSTRING(RID_STR_COLUMN_UNKNOWN_PROP)); + sError.SearchAndReplaceAscii("%value", ::rtl::OUString(PROPERTY_NAME)); + SQLException aErr(sError,*this,SQLSTATE_GENERAL,1000,Any() ); + throw SQLException(DBACORE_RESSTRING(RID_STR_COLUMN_NOT_VALID),*this,SQLSTATE_GENERAL,1000,makeAny(aErr) ); + } + + ::rtl::OUString aName,aNewName; + column->getPropertyValue(PROPERTY_NAME) >>= aName; + + if ( !m_xMetaData->supportsOrderByUnrelated() && m_aCurrentColumns[SelectColumns] && !m_aCurrentColumns[SelectColumns]->hasByName(aName)) + { + String sError(DBACORE_RESSTRING(RID_STR_COLUMN_MUST_VISIBLE)); + sError.SearchAndReplaceAscii("%name", aName); + throw SQLException(sError,*this,SQLSTATE_GENERAL,1000,Any() ); + } + + // filter anhaengen + // select ohne where und order by aufbauen + ::rtl::OUString aQuote = m_xMetaData->getIdentifierQuoteString(); + if ( m_aCurrentColumns[SelectColumns]->hasByName(aName) ) + { + Reference<XPropertySet> xColumn; + m_aCurrentColumns[SelectColumns]->getByName(aName) >>= xColumn; + OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_REALNAME),"Property REALNAME not available!"); + OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_TABLENAME),"Property TABLENAME not available!"); + OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Function"))),"Property FUNCTION not available!"); + + ::rtl::OUString sRealName,sTableName; + xColumn->getPropertyValue(PROPERTY_REALNAME) >>= sRealName; + xColumn->getPropertyValue(PROPERTY_TABLENAME) >>= sTableName; + sal_Bool bFunction = sal_False; + xColumn->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Function"))) >>= bFunction; + if ( sRealName == aName ) + { + if ( bFunction ) + aNewName = aName; + else + { + if(sTableName.indexOf('.',0) != -1) + { + ::rtl::OUString aCatlog,aSchema,aTable; + ::dbtools::qualifiedNameComponents(m_xMetaData,sTableName,aCatlog,aSchema,aTable,::dbtools::eInDataManipulation); + sTableName = ::dbtools::composeTableName( m_xMetaData, aCatlog, aSchema, aTable, sal_True, ::dbtools::eInDataManipulation ); + } + else + sTableName = ::dbtools::quoteName(aQuote,sTableName); + + aNewName = sTableName; + aNewName += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".")); + aNewName += ::dbtools::quoteName(aQuote,sRealName); + } + } + else + aNewName = ::dbtools::quoteName(aQuote,aName); + } + else + aNewName = getTableAlias(column) + ::dbtools::quoteName(aQuote,aName); + return aNewName; +} +// ------------------------------------------------------------------------- +void SAL_CALL OSingleSelectQueryComposer::appendOrderByColumn( const Reference< XPropertySet >& column, sal_Bool ascending ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::appendOrderByColumn" ); + ::osl::MutexGuard aGuard( m_aMutex ); + ::rtl::OUString sColumnName( impl_getColumnName_throw(column) ); + ::rtl::OUString sOrder = getOrder(); + if ( (sOrder.getLength() != 0) && sColumnName.getLength() ) + sOrder += COMMA; + sOrder += sColumnName; + if ( !ascending && sColumnName.getLength() ) + sOrder += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" DESC ")); + + setOrder(sOrder); +} + +// ------------------------------------------------------------------------- +void SAL_CALL OSingleSelectQueryComposer::appendGroupByColumn( const Reference< XPropertySet >& column) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::appendGroupByColumn" ); + ::osl::MutexGuard aGuard( m_aMutex ); + ::rtl::OUString sColumnName( impl_getColumnName_throw(column) ); + OrderCreator aComposer; + aComposer.append( getGroup() ); + aComposer.append( sColumnName ); + setGroup( aComposer.getComposedAndClear() ); +} +// ------------------------------------------------------------------------- +::rtl::OUString OSingleSelectQueryComposer::composeStatementFromParts( const ::std::vector< ::rtl::OUString >& _rParts ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::composeStatementFromParts" ); + DBG_ASSERT( _rParts.size() == (size_t)SQLPartCount, "OSingleSelectQueryComposer::composeStatementFromParts: invalid parts array!" ); + + ::rtl::OUStringBuffer aSql( m_aPureSelectSQL ); + for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) ) + if ( _rParts[ eLoopParts ].getLength() ) + { + aSql.append( getKeyword( eLoopParts ) ); + aSql.append( _rParts[ eLoopParts ] ); + } + + return aSql.makeStringAndClear(); +} + +// ------------------------------------------------------------------------- +::rtl::OUString SAL_CALL OSingleSelectQueryComposer::getElementaryQuery() throw (::com::sun::star::uno::RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getElementaryQuery" ); + return composeStatementFromParts( m_aElementaryParts ); +} + +// ------------------------------------------------------------------------- +void SAL_CALL OSingleSelectQueryComposer::setElementaryQuery( const ::rtl::OUString& _rElementary ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "frank.schoenheit@sun.com", "OSingleSelectQueryComposer::setElementaryQuery" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + ::osl::MutexGuard aGuard( m_aMutex ); + + // remember the 4 current "additive" clauses + ::std::vector< ::rtl::OUString > aAdditiveClauses( SQLPartCount ); + for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) ) + aAdditiveClauses[ eLoopParts ] = getSQLPart( eLoopParts, m_aAdditiveIterator, sal_False ); + + // clear the tables and columns + clearCurrentCollections(); + // set and parse the new query + setQuery_Impl( _rElementary ); + + // get the 4 elementary parts of the statement + for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) ) + m_aElementaryParts[ eLoopParts ] = getSQLPart( eLoopParts, m_aSqlIterator, sal_False ); + + // reset the the AdditiveIterator: m_aPureSelectSQL may have changed + try + { + parseAndCheck_throwError( m_aSqlParser, composeStatementFromParts( aAdditiveClauses ), m_aAdditiveIterator, *this ); + } + catch( const Exception& e ) + { + (void)e; + DBG_ERROR( "OSingleSelectQueryComposer::setElementaryQuery: there should be no error anymore for the additive statement!" ); + // every part of the additive statement should have passed other tests already, and should not + // be able to cause any errors ... me thinks + } +} + +// ------------------------------------------------------------------------- +namespace +{ + ::rtl::OUString getComposedClause( const ::rtl::OUString _rElementaryClause, const ::rtl::OUString _rAdditionalClause, + TokenComposer& _rComposer, const ::rtl::OUString _rKeyword ) + { + _rComposer.clear(); + _rComposer.append( _rElementaryClause ); + _rComposer.append( _rAdditionalClause ); + ::rtl::OUString sComposed = _rComposer.getComposedAndClear(); + if ( sComposed.getLength() ) + sComposed = _rKeyword + sComposed; + return sComposed; + } +} + +// ------------------------------------------------------------------------- +void OSingleSelectQueryComposer::setSingleAdditiveClause( SQLPart _ePart, const ::rtl::OUString& _rClause ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setSingleAdditiveClause" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + ::osl::MutexGuard aGuard( m_aMutex ); + + // if nothing is changed, do nothing + if ( getSQLPart( _ePart, m_aAdditiveIterator, sal_False ) == _rClause ) + return; + + // collect the 4 single parts as they're currently set + ::std::vector< ::rtl::OUString > aClauses; + aClauses.reserve( (size_t)SQLPartCount ); + for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) ) + aClauses.push_back( getSQLPart( eLoopParts, m_aSqlIterator, sal_True ) ); + + // overwrite the one part in question here + ::std::auto_ptr< TokenComposer > pComposer; + if ( ( _ePart == Where ) || ( _ePart == Having ) ) + pComposer.reset( new FilterCreator ); + else + pComposer.reset( new OrderCreator ); + aClauses[ _ePart ] = getComposedClause( m_aElementaryParts[ _ePart ], _rClause, + *pComposer, getKeyword( _ePart ) ); + + // construct the complete statement + ::rtl::OUStringBuffer aSql(m_aPureSelectSQL); + for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) ) + aSql.append(aClauses[ eLoopParts ]); + + // set the query + setQuery_Impl(aSql.makeStringAndClear()); + + // clear column collections which (might) have changed + clearColumns( ParameterColumns ); + if ( _ePart == Order ) + clearColumns( OrderColumns ); + if ( _ePart == Group ) + clearColumns( GroupByColumns ); + + // also, since the "additive filter" change, we need to rebuild our "additive" statement + aSql = m_aPureSelectSQL; + // again, first get all the old additive parts + for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) ) + aClauses[ eLoopParts ] = getSQLPart( eLoopParts, m_aAdditiveIterator, sal_True ); + // then overwrite the one in question + aClauses[ _ePart ] = getComposedClause( ::rtl::OUString(), _rClause, *pComposer, getKeyword( _ePart ) ); + // and parse it, so that m_aAdditiveIterator is up to date + for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) ) + aSql.append(aClauses[ eLoopParts ]); + try + { + parseAndCheck_throwError( m_aSqlParser, aSql.makeStringAndClear(), m_aAdditiveIterator, *this ); + } + catch( const Exception& e ) + { + (void)e; + DBG_ERROR( "OSingleSelectQueryComposer::setSingleAdditiveClause: there should be no error anymore for the additive statement!" ); + // every part of the additive statement should have passed other tests already, and should not + // be able to cause any errors ... me thinks + } +} + +// ------------------------------------------------------------------------- +void SAL_CALL OSingleSelectQueryComposer::setFilter( const ::rtl::OUString& filter ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setFilter" ); + setSingleAdditiveClause( Where, filter ); +} + +// ------------------------------------------------------------------------- +void SAL_CALL OSingleSelectQueryComposer::setOrder( const ::rtl::OUString& order ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setOrder" ); + setSingleAdditiveClause( Order, order ); +} +// ----------------------------------------------------------------------------- +void SAL_CALL OSingleSelectQueryComposer::setGroup( const ::rtl::OUString& group ) throw (SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setGroup" ); + setSingleAdditiveClause( Group, group ); +} +// ------------------------------------------------------------------------- +void SAL_CALL OSingleSelectQueryComposer::setHavingClause( const ::rtl::OUString& filter ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setHavingClause" ); + setSingleAdditiveClause( Having, filter ); +} + +// ------------------------------------------------------------------------- +// XTablesSupplier +Reference< XNameAccess > SAL_CALL OSingleSelectQueryComposer::getTables( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getTables" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( m_aMutex ); + if ( !m_pTables ) + { + const OSQLTables& aTables = m_aSqlIterator.getTables(); + ::std::vector< ::rtl::OUString> aNames; + OSQLTables::const_iterator aEnd = aTables.end(); + for(OSQLTables::const_iterator aIter = aTables.begin(); aIter != aEnd;++aIter) + aNames.push_back(aIter->first); + + m_pTables = new OPrivateTables(aTables,m_xMetaData->supportsMixedCaseQuotedIdentifiers(),*this,m_aMutex,aNames); + } + + return m_pTables; +} +// ------------------------------------------------------------------------- +// XColumnsSupplier +Reference< XNameAccess > SAL_CALL OSingleSelectQueryComposer::getColumns( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getColumns" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + ::osl::MutexGuard aGuard( m_aMutex ); + if ( !!m_aCurrentColumns[SelectColumns] ) + return m_aCurrentColumns[SelectColumns]; + + ::std::vector< ::rtl::OUString> aNames; + ::vos::ORef< OSQLColumns> aSelectColumns; + sal_Bool bCase = sal_True; + Reference< XNameAccess> xQueryColumns; + if ( m_nCommandType == CommandType::QUERY ) + { + Reference<XColumnsSupplier> xSup(m_xConnectionQueries->getByName(m_sCommand),UNO_QUERY); + if(xSup.is()) + xQueryColumns = xSup->getColumns(); + } + + do { + + try + { + SharedUNOComponent< XStatement, DisposableComponent > xStatement; + SharedUNOComponent< XPreparedStatement, DisposableComponent > xPreparedStatement; + + bCase = m_xMetaData->supportsMixedCaseQuotedIdentifiers(); + aSelectColumns = m_aSqlIterator.getSelectColumns(); + + ::rtl::OUStringBuffer aSQL; + aSQL.append( m_aPureSelectSQL ); + aSQL.append( STR_WHERE ); + + // preserve the original WHERE clause + // #i102234# / 2009-06-02 / frank.schoenheit@sun.com + ::rtl::OUString sOriginalWhereClause = getSQLPart( Where, m_aSqlIterator, sal_False ); + if ( sOriginalWhereClause.getLength() ) + { + aSQL.appendAscii( " ( 0 = 1 ) AND ( " ); + aSQL.append( sOriginalWhereClause ); + aSQL.appendAscii( " ) " ); + } + else + { + aSQL.appendAscii( " ( 0 = 1 ) " ); + } + + ::rtl::OUString sGroupBy = getSQLPart( Group, m_aSqlIterator, sal_True ); + if ( sGroupBy.getLength() ) + aSQL.append( sGroupBy ); + + ::rtl::OUString sSQL( aSQL.makeStringAndClear() ); + // normalize the statement so that it doesn't contain any application-level features anymore + ::rtl::OUString sError; + const ::std::auto_ptr< OSQLParseNode > pStatementTree( m_aSqlParser.parseTree( sError, sSQL, false ) ); + DBG_ASSERT( pStatementTree.get(), "OSingleSelectQueryComposer::getColumns: could not parse the column retrieval statement!" ); + if ( pStatementTree.get() ) + if ( !pStatementTree->parseNodeToExecutableStatement( sSQL, m_xConnection, m_aSqlParser, NULL ) ) + break; + + Reference< XResultSetMetaData > xResultSetMeta; + Reference< XResultSetMetaDataSupplier > xResMetaDataSup; + try + { + xPreparedStatement.set( m_xConnection->prepareStatement( sSQL ), UNO_QUERY_THROW ); + xResMetaDataSup.set( xPreparedStatement, UNO_QUERY_THROW ); + xResultSetMeta.set( xResMetaDataSup->getMetaData(), UNO_QUERY_THROW ); + } + catch( const Exception& ) { } + + try + { + if ( !xResultSetMeta.is() ) + { + xStatement.reset( Reference< XStatement >( m_xConnection->createStatement(), UNO_QUERY_THROW ) ); + Reference< XPropertySet > xStatementProps( xStatement, UNO_QUERY_THROW ); + try { xStatementProps->setPropertyValue( PROPERTY_ESCAPE_PROCESSING, makeAny( sal_False ) ); } + catch ( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); } + xResMetaDataSup.set( xStatement->executeQuery( sSQL ), UNO_QUERY_THROW ); + xResultSetMeta.set( xResMetaDataSup->getMetaData(), UNO_QUERY_THROW ); + } + } + catch( const Exception& ) + { + //@see issue http://qa.openoffice.org/issues/show_bug.cgi?id=110111 + // access returns a different order of column names when executing select * from + // and asking the columns from the metadata. + Reference< XParameters > xParameters( xPreparedStatement, UNO_QUERY_THROW ); + Reference< XIndexAccess > xPara = getParameters(); + for(sal_Int32 i = 1;i <= xPara->getCount();++i) + xParameters->setNull(i,DataType::VARCHAR); + xResMetaDataSup.set(xPreparedStatement->executeQuery(), UNO_QUERY_THROW ); + xResultSetMeta.set( xResMetaDataSup->getMetaData(), UNO_QUERY_THROW ); + } + + if ( aSelectColumns->get().empty() ) + { + // This is a valid case. If we can syntactically parse the query, but not semantically + // (e.g. because it is based on a table we do not know), then there will be no SelectColumns + aSelectColumns = ::connectivity::parse::OParseColumn::createColumnsForResultSet( xResultSetMeta, m_xMetaData ,xQueryColumns); + break; + } + + const ::comphelper::UStringMixEqual aCaseCompare( bCase ); + const ::comphelper::TStringMixEqualFunctor aCaseCompareFunctor( bCase ); + typedef ::std::set< size_t > SizeTSet; + SizeTSet aUsedSelectColumns; + ::connectivity::parse::OParseColumn::StringMap aColumnNames; + + sal_Int32 nCount = xResultSetMeta->getColumnCount(); + OSL_ENSURE( (size_t) nCount == aSelectColumns->get().size(), "OSingleSelectQueryComposer::getColumns: inconsistent column counts, this might result in wrong columns!" ); + for(sal_Int32 i=1;i<=nCount;++i) + { + ::rtl::OUString sColumnName = xResultSetMeta->getColumnName(i); + ::rtl::OUString sColumnLabel; + if ( xQueryColumns.is() && xQueryColumns->hasByName(sColumnName) ) + { + Reference<XPropertySet> xQueryColumn(xQueryColumns->getByName(sColumnName),UNO_QUERY_THROW); + xQueryColumn->getPropertyValue(PROPERTY_LABEL) >>= sColumnLabel; + } + else + sColumnLabel = xResultSetMeta->getColumnLabel(i); + sal_Bool bFound = sal_False; + OSQLColumns::Vector::const_iterator aFind = ::connectivity::find(aSelectColumns->get().begin(),aSelectColumns->get().end(),sColumnLabel,aCaseCompare); + size_t nFoundSelectColumnPos = aFind - aSelectColumns->get().begin(); + if ( aFind != aSelectColumns->get().end() ) + { + if ( aUsedSelectColumns.find( nFoundSelectColumnPos ) != aUsedSelectColumns.end() ) + { // we found a column name which exists twice + // so we start after the first found + do + { + aFind = ::connectivity::findRealName(++aFind,aSelectColumns->get().end(),sColumnName,aCaseCompare); + nFoundSelectColumnPos = aFind - aSelectColumns->get().begin(); + } + while ( ( aUsedSelectColumns.find( nFoundSelectColumnPos ) != aUsedSelectColumns.end() ) + && ( aFind != aSelectColumns->get().end() ) + ); + } + if ( aFind != aSelectColumns->get().end() ) + { + (*aFind)->getPropertyValue(PROPERTY_NAME) >>= sColumnName; + aUsedSelectColumns.insert( nFoundSelectColumnPos ); + aNames.push_back(sColumnName); + bFound = sal_True; + } + } + + if ( bFound ) + continue; + + OSQLColumns::Vector::const_iterator aRealFind = ::connectivity::findRealName( + aSelectColumns->get().begin(), aSelectColumns->get().end(), sColumnName, aCaseCompare ); + + if ( i > static_cast< sal_Int32>( aSelectColumns->get().size() ) ) + { + aSelectColumns->get().push_back( + ::connectivity::parse::OParseColumn::createColumnForResultSet( xResultSetMeta, m_xMetaData, i ,aColumnNames) + ); + OSL_ENSURE( aSelectColumns->get().size() == (size_t)i, "OSingleSelectQueryComposer::getColumns: inconsistency!" ); + } + else if ( aRealFind == aSelectColumns->get().end() ) + { + // we can now only look if we found it under the realname propertery + // here we have to make the assumption that the position is correct + OSQLColumns::Vector::iterator aFind2 = aSelectColumns->get().begin() + i-1; + Reference<XPropertySet> xProp(*aFind2,UNO_QUERY); + if ( !xProp.is() || !xProp->getPropertySetInfo()->hasPropertyByName( PROPERTY_REALNAME ) ) + continue; + + ::connectivity::parse::OParseColumn* pColumn = new ::connectivity::parse::OParseColumn(xProp,bCase); + pColumn->setFunction(::comphelper::getBOOL(xProp->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Function"))))); + pColumn->setAggregateFunction(::comphelper::getBOOL(xProp->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AggregateFunction"))))); + + ::rtl::OUString sRealName; + xProp->getPropertyValue(PROPERTY_REALNAME) >>= sRealName; + ::std::vector< ::rtl::OUString>::iterator aFindName; + if ( !sColumnName.getLength() ) + xProp->getPropertyValue(PROPERTY_NAME) >>= sColumnName; + + + aFindName = ::std::find_if(aNames.begin(),aNames.end(),::std::bind2nd(aCaseCompareFunctor,sColumnName)); + sal_Int32 j = 0; + while ( aFindName != aNames.end() ) + { + sColumnName += ::rtl::OUString::valueOf(++j); + aFindName = ::std::find_if(aNames.begin(),aNames.end(),::std::bind2nd(aCaseCompareFunctor,sColumnName)); + } + + pColumn->setName(sColumnName); + pColumn->setRealName(sRealName); + pColumn->setTableName(::comphelper::getString(xProp->getPropertyValue(PROPERTY_TABLENAME))); + + (aSelectColumns->get())[i-1] = pColumn; + } + else + continue; + + aUsedSelectColumns.insert( (size_t)(i - 1) ); + aNames.push_back( sColumnName ); + } + } + catch(const Exception&) + { + } + + } while ( false ); + + if ( aNames.empty() ) + m_aCurrentColumns[ SelectColumns ] = OPrivateColumns::createWithIntrinsicNames( aSelectColumns, bCase, *this, m_aMutex ); + else + m_aCurrentColumns[ SelectColumns ] = new OPrivateColumns( aSelectColumns, bCase, *this, m_aMutex, aNames ); + + return m_aCurrentColumns[SelectColumns]; +} +// ------------------------------------------------------------------------- +sal_Bool OSingleSelectQueryComposer::setORCriteria(OSQLParseNode* pCondition, OSQLParseTreeIterator& _rIterator, + ::std::vector< ::std::vector < PropertyValue > >& rFilters, const Reference< ::com::sun::star::util::XNumberFormatter > & xFormatter) const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setORCriteria" ); + // Runde Klammern um den Ausdruck + if (pCondition->count() == 3 && + SQL_ISPUNCTUATION(pCondition->getChild(0),"(") && + SQL_ISPUNCTUATION(pCondition->getChild(2),")")) + { + return setORCriteria(pCondition->getChild(1), _rIterator, rFilters, xFormatter); + } + // oder Verknuepfung + // a searchcondition can only look like this: search_condition SQL_TOKEN_OR boolean_term + else if (SQL_ISRULE(pCondition,search_condition)) + { + sal_Bool bResult = sal_True; + for (int i = 0; bResult && i < 3; i+=2) + { + // Ist das erste Element wieder eine OR-Verknuepfung? + // Dann rekursiv absteigen ... + //if (!i && SQL_ISRULE(pCondition->getChild(i),search_condition)) + if (SQL_ISRULE(pCondition->getChild(i),search_condition)) + bResult = setORCriteria(pCondition->getChild(i), _rIterator, rFilters, xFormatter); + else + { + rFilters.push_back( ::std::vector < PropertyValue >()); + bResult = setANDCriteria(pCondition->getChild(i), _rIterator, rFilters[rFilters.size() - 1], xFormatter); + } + } + return bResult; + } + else + { + rFilters.push_back(::std::vector < PropertyValue >()); + return setANDCriteria(pCondition, _rIterator, rFilters[rFilters.size() - 1], xFormatter); + } +} + +//-------------------------------------------------------------------------------------------------- +sal_Bool OSingleSelectQueryComposer::setANDCriteria( OSQLParseNode * pCondition, + OSQLParseTreeIterator& _rIterator, ::std::vector < PropertyValue >& rFilter, const Reference< XNumberFormatter > & xFormatter) const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setANDCriteria" ); + // Runde Klammern + if (SQL_ISRULE(pCondition,boolean_primary)) + { + // this should not occur + DBG_ERROR("boolean_primary in And-Criteria"); + return sal_False; + } + // Das erste Element ist (wieder) eine AND-Verknuepfung + else if ( SQL_ISRULE(pCondition,boolean_term) && pCondition->count() == 3 ) + { + return setANDCriteria(pCondition->getChild(0), _rIterator, rFilter, xFormatter) && + setANDCriteria(pCondition->getChild(2), _rIterator, rFilter, xFormatter); + } + else if (SQL_ISRULE(pCondition, comparison_predicate)) + { + return setComparsionPredicate(pCondition,_rIterator,rFilter,xFormatter); + } + else if (SQL_ISRULE(pCondition,like_predicate) || + SQL_ISRULE(pCondition,test_for_null) || + SQL_ISRULE(pCondition,in_predicate) || + SQL_ISRULE(pCondition,all_or_any_predicate) || + SQL_ISRULE(pCondition,between_predicate)) + { + if (SQL_ISRULE(pCondition->getChild(0), column_ref)) + { + PropertyValue aItem; + ::rtl::OUString aValue; + ::rtl::OUString aColumnName; + + + // pCondition->parseNodeToStr(aValue,m_xMetaData, xFormatter, m_aLocale,static_cast<sal_Char>(m_sDecimalSep.toChar())); + pCondition->parseNodeToStr( aValue, m_xConnection, NULL ); + // pCondition->getChild(0)->parseNodeToStr(aColumnName,m_xMetaData, xFormatter, m_aLocale,static_cast<sal_Char>(m_sDecimalSep.toChar())); + pCondition->getChild(0)->parseNodeToStr( aColumnName, m_xConnection, NULL ); + + // don't display the column name + aValue = aValue.copy(aColumnName.getLength()); + aValue = aValue.trim(); + + aItem.Name = getColumnName(pCondition->getChild(0),_rIterator); + aItem.Value <<= aValue; + aItem.Handle = 0; // just to know that this is not one the known ones + if ( SQL_ISRULE(pCondition,like_predicate) ) + { + if ( SQL_ISTOKEN(pCondition->getChild(1)->getChild(0),NOT) ) + aItem.Handle = SQLFilterOperator::NOT_LIKE; + else + aItem.Handle = SQLFilterOperator::LIKE; + } + else if (SQL_ISRULE(pCondition,test_for_null)) + { + if (SQL_ISTOKEN(pCondition->getChild(1)->getChild(2),NOT) ) + aItem.Handle = SQLFilterOperator::NOT_SQLNULL; + else + aItem.Handle = SQLFilterOperator::SQLNULL; + } + else if (SQL_ISRULE(pCondition,in_predicate)) + { + OSL_ENSURE( false, "OSingleSelectQueryComposer::setANDCriteria: in_predicate not implemented!" ); + } + else if (SQL_ISRULE(pCondition,all_or_any_predicate)) + { + OSL_ENSURE( false, "OSingleSelectQueryComposer::setANDCriteria: all_or_any_predicate not implemented!" ); + } + else if (SQL_ISRULE(pCondition,between_predicate)) + { + OSL_ENSURE( false, "OSingleSelectQueryComposer::setANDCriteria: between_predicate not implemented!" ); + } + + rFilter.push_back(aItem); + } + else + return sal_False; + } + else if (SQL_ISRULE(pCondition,existence_test) || + SQL_ISRULE(pCondition,unique_test)) + { + // this couldn't be handled here, too complex + // as we need a field name + return sal_False; + } + else + return sal_False; + + return sal_True; +} +// ----------------------------------------------------------------------------- +sal_Int32 OSingleSelectQueryComposer::getPredicateType(OSQLParseNode * _pPredicate) const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getPredicateType" ); + sal_Int32 nPredicate = SQLFilterOperator::EQUAL; + switch (_pPredicate->getNodeType()) + { + case SQL_NODE_EQUAL: + nPredicate = SQLFilterOperator::EQUAL; + break; + case SQL_NODE_NOTEQUAL: + nPredicate = SQLFilterOperator::NOT_EQUAL; + break; + case SQL_NODE_LESS: + nPredicate = SQLFilterOperator::LESS; + break; + case SQL_NODE_LESSEQ: + nPredicate = SQLFilterOperator::LESS_EQUAL; + break; + case SQL_NODE_GREAT: + nPredicate = SQLFilterOperator::GREATER; + break; + case SQL_NODE_GREATEQ: + nPredicate = SQLFilterOperator::GREATER_EQUAL; + break; + default: + OSL_ENSURE(0,"Wrong NodeType!"); + } + return nPredicate; +} +//------------------------------------------------------------------------------ +sal_Bool OSingleSelectQueryComposer::setComparsionPredicate(OSQLParseNode * pCondition, OSQLParseTreeIterator& _rIterator, + ::std::vector < PropertyValue >& rFilter, const Reference< ::com::sun::star::util::XNumberFormatter > & xFormatter) const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setComparsionPredicate" ); + DBG_ASSERT(SQL_ISRULE(pCondition, comparison_predicate),"setComparsionPredicate: pCondition ist kein ComparsionPredicate"); + if (SQL_ISRULE(pCondition->getChild(0), column_ref) || + SQL_ISRULE(pCondition->getChild(pCondition->count()-1), column_ref)) + { + PropertyValue aItem; + ::rtl::OUString aValue; + sal_uInt32 nPos; + if (SQL_ISRULE(pCondition->getChild(0), column_ref)) + { + nPos = 0; + sal_uInt32 i=1; + + aItem.Handle = getPredicateType(pCondition->getChild(i)); + // don't display the equal + if (pCondition->getChild(i)->getNodeType() == SQL_NODE_EQUAL) + i++; + + // go forward + for (;i < pCondition->count();i++) + pCondition->getChild(i)->parseNodeToPredicateStr( + aValue, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>(m_sDecimalSep.toChar() ) ); + } + else if (SQL_ISRULE(pCondition->getChild(pCondition->count()-1), column_ref)) + { + nPos = pCondition->count()-1; + + sal_Int32 i = pCondition->count() - 2; + switch (pCondition->getChild(i)->getNodeType()) + { + case SQL_NODE_EQUAL: + // don't display the equal + i--; + aItem.Handle = SQLFilterOperator::EQUAL; + break; + case SQL_NODE_NOTEQUAL: + i--; + aItem.Handle = SQLFilterOperator::NOT_EQUAL; + break; + case SQL_NODE_LESS: + // take the opposite as we change the order + i--; + aValue = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(">=")); + aItem.Handle = SQLFilterOperator::GREATER_EQUAL; + break; + case SQL_NODE_LESSEQ: + // take the opposite as we change the order + i--; + aValue = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(">")); + aItem.Handle = SQLFilterOperator::GREATER; + break; + case SQL_NODE_GREAT: + // take the opposite as we change the order + i--; + aValue = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("<=")); + aItem.Handle = SQLFilterOperator::LESS_EQUAL; + break; + case SQL_NODE_GREATEQ: + // take the opposite as we change the order + i--; + aValue = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("<")); + aItem.Handle = SQLFilterOperator::LESS; + break; + default: + break; + } + + // go backward + for (; i >= 0; i--) + pCondition->getChild(i)->parseNodeToPredicateStr( + aValue, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>( m_sDecimalSep.toChar() ) ); + } + else + return sal_False; + + aItem.Name = getColumnName(pCondition->getChild(nPos),_rIterator); + aItem.Value <<= aValue; + rFilter.push_back(aItem); + } + else if (SQL_ISRULE(pCondition->getChild(0), set_fct_spec ) || + SQL_ISRULE(pCondition->getChild(0), general_set_fct)) + { + PropertyValue aItem; + ::rtl::OUString aValue; + ::rtl::OUString aColumnName; + + pCondition->parseNodeToPredicateStr(aValue, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>( m_sDecimalSep.toChar() ) ); + pCondition->getChild(0)->parseNodeToPredicateStr( aColumnName, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>( m_sDecimalSep .toChar() ) ); + + // don't display the column name + aValue = aValue.copy(aColumnName.getLength()); + aValue.trim(); + + aItem.Name = getColumnName(pCondition->getChild(0),_rIterator); + aItem.Value <<= aValue; + aItem.Handle = pCondition->getNodeType(); + rFilter.push_back(aItem); + } + else // kann sich nur um einen Expr. Ausdruck handeln + { + PropertyValue aItem; + ::rtl::OUString aName, aValue; + + OSQLParseNode *pLhs = pCondition->getChild(0); + OSQLParseNode *pRhs = pCondition->getChild(2); + + // Feldnamen + sal_uInt16 i; + for (i=0;i< pLhs->count();i++) + pLhs->getChild(i)->parseNodeToPredicateStr( aName, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>( m_sDecimalSep.toChar() ) ); + + // Kriterium + aItem.Handle = pCondition->getChild(1)->getNodeType(); + aValue = pCondition->getChild(1)->getTokenValue(); + for(i=0;i< pRhs->count();i++) + pRhs->getChild(i)->parseNodeToPredicateStr(aValue, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>( m_sDecimalSep.toChar() ) ); + + aItem.Name = aName; + aItem.Value <<= aValue; + rFilter.push_back(aItem); + } + return sal_True; +} +// functions for analysing SQL +//-------------------------------------------------------------------------------------------------- +::rtl::OUString OSingleSelectQueryComposer::getColumnName( ::connectivity::OSQLParseNode* pColumnRef, OSQLParseTreeIterator& _rIterator ) const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getColumnName" ); + ::rtl::OUString aTableRange, aColumnName; + _rIterator.getColumnRange(pColumnRef,aColumnName,aTableRange); + return aColumnName; +} +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL OSingleSelectQueryComposer::getFilter( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getFilter" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + ::osl::MutexGuard aGuard( m_aMutex ); + return getSQLPart(Where,m_aAdditiveIterator,sal_False); +} +// ------------------------------------------------------------------------- +::rtl::OUString SAL_CALL OSingleSelectQueryComposer::getOrder( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getOrder" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + ::osl::MutexGuard aGuard( m_aMutex ); + return getSQLPart(Order,m_aAdditiveIterator,sal_False); +} +// ------------------------------------------------------------------------- +::rtl::OUString SAL_CALL OSingleSelectQueryComposer::getGroup( ) throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getGroup" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + ::osl::MutexGuard aGuard( m_aMutex ); + return getSQLPart(Group,m_aAdditiveIterator,sal_False); +} +// ----------------------------------------------------------------------------- +::rtl::OUString OSingleSelectQueryComposer::getHavingClause() throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getHavingClause" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + ::osl::MutexGuard aGuard( m_aMutex ); + return getSQLPart(Having,m_aAdditiveIterator,sal_False); +} +// ----------------------------------------------------------------------------- +::rtl::OUString OSingleSelectQueryComposer::getTableAlias(const Reference< XPropertySet >& column) const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getTableAlias" ); + ::rtl::OUString sReturn; + if(m_pTables && m_pTables->getCount() > 1) + { + ::rtl::OUString aCatalog,aSchema,aTable,aComposedName,aColumnName; + column->getPropertyValue(PROPERTY_CATALOGNAME) >>= aCatalog; + column->getPropertyValue(PROPERTY_SCHEMANAME) >>= aSchema; + column->getPropertyValue(PROPERTY_TABLENAME) >>= aTable; + column->getPropertyValue(PROPERTY_NAME) >>= aColumnName; + + Sequence< ::rtl::OUString> aNames(m_pTables->getElementNames()); + const ::rtl::OUString* pBegin = aNames.getConstArray(); + const ::rtl::OUString* pEnd = pBegin + aNames.getLength(); + + if(!aTable.getLength()) + { // we don't found a table name, now we must search every table for this column + for(;pBegin != pEnd;++pBegin) + { + Reference<XColumnsSupplier> xColumnsSupp; + m_pTables->getByName(*pBegin) >>= xColumnsSupp; + + if(xColumnsSupp.is() && xColumnsSupp->getColumns()->hasByName(aColumnName)) + { +// Reference<XPropertySet> xTableProp(xColumnsSupp,UNO_QUERY); +// xTableProp->getPropertyValue(PROPERTY_CATALOGNAME) >>= aCatalog; +// xTableProp->getPropertyValue(PROPERTY_SCHEMANAME) >>= aSchema; +// xTableProp->getPropertyValue(PROPERTY_NAME) >>= aTable; + aTable = *pBegin; + break; + } + } + } + else + { + aComposedName = ::dbtools::composeTableName( m_xMetaData, aCatalog, aSchema, aTable, sal_False, ::dbtools::eInDataManipulation ); + + // first check if this is the table we want to or has it a tablealias + + if(!m_pTables->hasByName(aComposedName)) + { + ::comphelper::UStringMixLess aTmp(m_aAdditiveIterator.getTables().key_comp()); + ::comphelper::UStringMixEqual aComp(static_cast< ::comphelper::UStringMixLess*>(&aTmp)->isCaseSensitive()); + for(;pBegin != pEnd;++pBegin) + { + Reference<XPropertySet> xTableProp; + m_pTables->getByName(*pBegin) >>= xTableProp; + OSL_ENSURE(xTableProp.is(),"Table isn't a propertyset!"); + if(xTableProp.is()) + { + ::rtl::OUString aCatalog2,aSchema2,aTable2; + xTableProp->getPropertyValue(PROPERTY_CATALOGNAME) >>= aCatalog2; + xTableProp->getPropertyValue(PROPERTY_SCHEMANAME) >>= aSchema2; + xTableProp->getPropertyValue(PROPERTY_NAME) >>= aTable2; + if(aComp(aCatalog,aCatalog2) && aComp(aSchema,aSchema2) && aComp(aTable,aTable2)) + { + aCatalog = aCatalog2; + aSchema = aSchema2; + aTable = aTable2; + break; + } + } + } + } + } + if(pBegin != pEnd) + { + sReturn = ::dbtools::composeTableName( m_xMetaData, aCatalog, aSchema, aTable, sal_True, ::dbtools::eInDataManipulation ); + sReturn += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".")); + } + } + return sReturn; +} +// ----------------------------------------------------------------------------- +Reference< XIndexAccess > SAL_CALL OSingleSelectQueryComposer::getParameters( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getParameters" ); + // now set the Parameters + if ( !m_aCurrentColumns[ParameterColumns] ) + { + ::vos::ORef< OSQLColumns> aCols = m_aSqlIterator.getParameters(); + ::std::vector< ::rtl::OUString> aNames; + OSQLColumns::Vector::const_iterator aEnd = aCols->get().end(); + for(OSQLColumns::Vector::const_iterator aIter = aCols->get().begin(); aIter != aEnd;++aIter) + aNames.push_back(getString((*aIter)->getPropertyValue(PROPERTY_NAME))); + m_aCurrentColumns[ParameterColumns] = new OPrivateColumns(aCols,m_xMetaData->supportsMixedCaseQuotedIdentifiers(),*this,m_aMutex,aNames,sal_True); + } + + return m_aCurrentColumns[ParameterColumns]; +} +// ----------------------------------------------------------------------------- +void OSingleSelectQueryComposer::clearColumns( const EColumnType _eType ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::clearColumns" ); + OPrivateColumns* pColumns = m_aCurrentColumns[ _eType ]; + if ( pColumns != NULL ) + { + pColumns->disposing(); + m_aColumnsCollection.push_back( pColumns ); + m_aCurrentColumns[ _eType ] = NULL; + } +} +// ----------------------------------------------------------------------------- +void OSingleSelectQueryComposer::clearCurrentCollections() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::clearCurrentCollections" ); + ::std::vector<OPrivateColumns*>::iterator aIter = m_aCurrentColumns.begin(); + ::std::vector<OPrivateColumns*>::iterator aEnd = m_aCurrentColumns.end(); + for (;aIter != aEnd;++aIter) + { + if ( *aIter ) + { + (*aIter)->disposing(); + m_aColumnsCollection.push_back(*aIter); + *aIter = NULL; + } + } + + if(m_pTables) + { + m_pTables->disposing(); + m_aTablesCollection.push_back(m_pTables); + m_pTables = NULL; + } +} +// ----------------------------------------------------------------------------- +Reference< XIndexAccess > OSingleSelectQueryComposer::setCurrentColumns( EColumnType _eType, + const ::vos::ORef< OSQLColumns >& _rCols ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setCurrentColumns" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( m_aMutex ); + // now set the group columns + if ( !m_aCurrentColumns[_eType] ) + { + ::std::vector< ::rtl::OUString> aNames; + OSQLColumns::Vector::const_iterator aEnd = _rCols->get().end(); + for(OSQLColumns::Vector::const_iterator aIter = _rCols->get().begin(); aIter != aEnd;++aIter) + aNames.push_back(getString((*aIter)->getPropertyValue(PROPERTY_NAME))); + m_aCurrentColumns[_eType] = new OPrivateColumns(_rCols,m_xMetaData->supportsMixedCaseQuotedIdentifiers(),*this,m_aMutex,aNames,sal_True); + } + + return m_aCurrentColumns[_eType]; +} +// ----------------------------------------------------------------------------- +Reference< XIndexAccess > SAL_CALL OSingleSelectQueryComposer::getGroupColumns( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getGroupColumns" ); + return setCurrentColumns( GroupByColumns, m_aAdditiveIterator.getGroupColumns() ); +} +// ------------------------------------------------------------------------- +Reference< XIndexAccess > SAL_CALL OSingleSelectQueryComposer::getOrderColumns( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getOrderColumns" ); + return setCurrentColumns( OrderColumns, m_aAdditiveIterator.getOrderColumns() ); +} +// ----------------------------------------------------------------------------- +::rtl::OUString SAL_CALL OSingleSelectQueryComposer::getQueryWithSubstitution( ) throw (SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getQueryWithSubstitution" ); + ::osl::MutexGuard aGuard( m_aMutex ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + + ::rtl::OUString sSqlStatement( getQuery() ); + + const OSQLParseNode* pStatementNode = m_aSqlIterator.getParseTree(); + if ( pStatementNode ) + { + SQLException aError; + if ( !pStatementNode->parseNodeToExecutableStatement( sSqlStatement, m_xConnection, m_aSqlParser, &aError ) ) + throw SQLException( aError ); + } + + return sSqlStatement; +} +// ----------------------------------------------------------------------------- +::rtl::OUString OSingleSelectQueryComposer::getStatementPart( TGetParseNode& _aGetFunctor, OSQLParseTreeIterator& _rIterator ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getStatementPart" ); + ::rtl::OUString sResult; + + const OSQLParseNode* pNode = _aGetFunctor( &_rIterator ); + if ( pNode ) + pNode->parseNodeToStr( sResult, m_xConnection ); + + return sResult; +} +// ----------------------------------------------------------------------------- +namespace +{ + ::rtl::OUString lcl_getCondition(const Sequence< Sequence< PropertyValue > >& filter ) + { + ::rtl::OUStringBuffer sRet; + const Sequence< PropertyValue >* pOrIter = filter.getConstArray(); + const Sequence< PropertyValue >* pOrEnd = pOrIter + filter.getLength(); + while ( pOrIter != pOrEnd ) + { + if ( pOrIter->getLength() ) + { + sRet.append(L_BRACKET); + const PropertyValue* pAndIter = pOrIter->getConstArray(); + const PropertyValue* pAndEnd = pAndIter + pOrIter->getLength(); + while ( pAndIter != pAndEnd ) + { + sRet.append(pAndIter->Name); + ::rtl::OUString sValue; + pAndIter->Value >>= sValue; + lcl_addFilterCriteria_throw(pAndIter->Handle,sValue,sRet); + ++pAndIter; + if ( pAndIter != pAndEnd ) + sRet.append(STR_AND); + } + sRet.append(R_BRACKET); + } + ++pOrIter; + if ( pOrIter != pOrEnd && sRet.getLength() ) + sRet.append(STR_OR); + } + return sRet.makeStringAndClear(); + } +} +// ----------------------------------------------------------------------------- +void SAL_CALL OSingleSelectQueryComposer::setStructuredFilter( const Sequence< Sequence< PropertyValue > >& filter ) throw (SQLException, ::com::sun::star::lang::IllegalArgumentException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setStructuredFilter" ); + setFilter(lcl_getCondition(filter)); +} +// ----------------------------------------------------------------------------- +void SAL_CALL OSingleSelectQueryComposer::setStructuredHavingClause( const Sequence< Sequence< PropertyValue > >& filter ) throw (SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setStructuredHavingClause" ); + setHavingClause(lcl_getCondition(filter)); +} +// ----------------------------------------------------------------------------- +void OSingleSelectQueryComposer::setConditionByColumn( const Reference< XPropertySet >& column, sal_Bool andCriteria ,::std::mem_fun1_t<bool,OSingleSelectQueryComposer,::rtl::OUString>& _aSetFunctor,sal_Int32 filterOperator) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setConditionByColumn" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + + if ( !column.is() + || !column->getPropertySetInfo()->hasPropertyByName(PROPERTY_VALUE) + || !column->getPropertySetInfo()->hasPropertyByName(PROPERTY_NAME) + || !column->getPropertySetInfo()->hasPropertyByName(PROPERTY_TYPE)) + throw SQLException(DBACORE_RESSTRING(RID_STR_COLUMN_NOT_VALID),*this,SQLSTATE_GENERAL,1000,Any() ); + + sal_Int32 nType = 0; + column->getPropertyValue(PROPERTY_TYPE) >>= nType; + sal_Int32 nSearchable = dbtools::getSearchColumnFlag(m_xConnection,nType); + if(nSearchable == ColumnSearch::NONE) + throw SQLException(DBACORE_RESSTRING(RID_STR_COLUMN_NOT_SEARCHABLE),*this,SQLSTATE_GENERAL,1000,Any() ); + + ::osl::MutexGuard aGuard( m_aMutex ); + + ::rtl::OUString aName; + column->getPropertyValue(PROPERTY_NAME) >>= aName; + + Any aValue; + column->getPropertyValue(PROPERTY_VALUE) >>= aValue; + + ::rtl::OUStringBuffer aSQL; + const ::rtl::OUString aQuote = m_xMetaData->getIdentifierQuoteString(); + getColumns(); + + if ( m_aCurrentColumns[SelectColumns] && m_aCurrentColumns[SelectColumns]->hasByName(aName) ) + { + Reference<XPropertySet> xColumn; + m_aCurrentColumns[SelectColumns]->getByName(aName) >>= xColumn; + OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_REALNAME),"Property REALNAME not available!"); + OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_TABLENAME),"Property TABLENAME not available!"); + OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AggregateFunction"))),"Property AggregateFunctionnot available!"); + + ::rtl::OUString sRealName,sTableName; + xColumn->getPropertyValue(PROPERTY_REALNAME) >>= sRealName; + xColumn->getPropertyValue(PROPERTY_TABLENAME) >>= sTableName; + if(sTableName.indexOf('.',0) != -1) + { + ::rtl::OUString aCatlog,aSchema,aTable; + ::dbtools::qualifiedNameComponents(m_xMetaData,sTableName,aCatlog,aSchema,aTable,::dbtools::eInDataManipulation); + sTableName = ::dbtools::composeTableName( m_xMetaData, aCatlog, aSchema, aTable, sal_True, ::dbtools::eInDataManipulation ); + } + else + sTableName = ::dbtools::quoteName(aQuote,sTableName); + + if ( !::comphelper::getBOOL(xColumn->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Function")))) ) + { + aSQL = sTableName; + aSQL.appendAscii( "." ); + aSQL.append( ::dbtools::quoteName( aQuote, sRealName ) ); + } + else + aSQL = sRealName; + + } + else + { + aSQL = getTableAlias( column ); + aSQL.append( ::dbtools::quoteName( aQuote, aName ) ); + } + + + if ( aValue.hasValue() ) + { + if( !m_xTypeConverter.is() ) + m_aContext.createComponent( "com.sun.star.script.Converter", m_xTypeConverter ); + OSL_ENSURE(m_xTypeConverter.is(),"NO typeconverter!"); + + if ( nType != DataType::BOOLEAN && DataType::BIT != nType ) + { + ::rtl::OUString sEmpty; + lcl_addFilterCriteria_throw(filterOperator,sEmpty,aSQL); + } + + switch(nType) + { + case DataType::VARCHAR: + case DataType::CHAR: + case DataType::LONGVARCHAR: + aSQL.append( DBTypeConversion::toSQLString( nType, aValue, sal_True, m_xTypeConverter ) ); + break; + case DataType::CLOB: + { + Reference< XClob > xClob(aValue,UNO_QUERY); + if ( xClob.is() ) + { + const ::sal_Int64 nLength = xClob->length(); + if ( sal_Int64(nLength + aSQL.getLength() + STR_LIKE.getLength() ) < sal_Int64(SAL_MAX_INT32) ) + { + aSQL.appendAscii("'"); + aSQL.append( xClob->getSubString(1,(sal_Int32)nLength) ); + aSQL.appendAscii("'"); + } + } + else + { + aSQL.append( DBTypeConversion::toSQLString( nType, aValue, sal_True, m_xTypeConverter ) ); + } + } + break; + case DataType::VARBINARY: + case DataType::BINARY: + case DataType::LONGVARBINARY: + { + Sequence<sal_Int8> aSeq; + if(aValue >>= aSeq) + { + if(nSearchable == ColumnSearch::CHAR) + { + aSQL.appendAscii( "\'" ); + } + aSQL.appendAscii( "0x" ); + const sal_Int8* pBegin = aSeq.getConstArray(); + const sal_Int8* pEnd = pBegin + aSeq.getLength(); + for(;pBegin != pEnd;++pBegin) + { + aSQL.append( (sal_Int32)*pBegin, 16 ).getStr(); + } + if(nSearchable == ColumnSearch::CHAR) + aSQL.appendAscii( "\'" ); + } + else + throw SQLException(DBACORE_RESSTRING(RID_STR_NOT_SEQUENCE_INT8),*this,SQLSTATE_GENERAL,1000,Any() ); + } + break; + case DataType::BIT: + case DataType::BOOLEAN: + { + sal_Bool bValue = sal_False; + m_xTypeConverter->convertToSimpleType(aValue, TypeClass_BOOLEAN) >>= bValue; + + ::rtl::OUString sColumnExp = aSQL.makeStringAndClear(); + getBoleanComparisonPredicate( sColumnExp, bValue, m_nBoolCompareMode, aSQL ); + } + break; + default: + aSQL.append( DBTypeConversion::toSQLString( nType, aValue, sal_True, m_xTypeConverter ) ); + break; + } + } + else + { + sal_Int32 nFilterOp = filterOperator; + if ( filterOperator != SQLFilterOperator::SQLNULL && filterOperator != SQLFilterOperator::NOT_SQLNULL ) + nFilterOp = SQLFilterOperator::SQLNULL; + ::rtl::OUString sEmpty; + lcl_addFilterCriteria_throw(nFilterOp,sEmpty,aSQL); + } + + // filter anhaengen + // select ohne where und order by aufbauen + ::rtl::OUString sFilter = getFilter(); + + if ( sFilter.getLength() && aSQL.getLength() ) + { + ::rtl::OUString sTemp(L_BRACKET); + sTemp += sFilter; + sTemp += R_BRACKET; + sTemp += andCriteria ? STR_AND : STR_OR; + sFilter = sTemp; + } + sFilter += aSQL.makeStringAndClear(); + + // add the filter and the sort order + _aSetFunctor(this,sFilter); +} +// ----------------------------------------------------------------------------- +Sequence< Sequence< PropertyValue > > OSingleSelectQueryComposer::getStructuredCondition( TGetParseNode& _aGetFunctor ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getStructuredCondition" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + + MutexGuard aGuard(m_aMutex); + + Sequence< Sequence< PropertyValue > > aFilterSeq; + ::rtl::OUString sFilter = getStatementPart( _aGetFunctor, m_aAdditiveIterator ); + + if ( sFilter.getLength() != 0 ) + { + ::rtl::OUString aSql(m_aPureSelectSQL); + // build a temporary parse node + const OSQLParseNode* pTempNode = m_aAdditiveIterator.getParseTree(); + + aSql += STR_WHERE; + aSql += sFilter; + + ::rtl::OUString aErrorMsg; + ::std::auto_ptr<OSQLParseNode> pSqlParseNode( m_aSqlParser.parseTree(aErrorMsg,aSql)); + if ( pSqlParseNode.get() ) + { + m_aAdditiveIterator.setParseTree(pSqlParseNode.get()); + // normalize the filter + OSQLParseNode* pWhereNode = const_cast<OSQLParseNode*>(m_aAdditiveIterator.getWhereTree()); + + OSQLParseNode* pCondition = pWhereNode->getChild(1); + #if OSL_DEBUG_LEVEL > 0 + ::rtl::OUString sCondition; + pCondition->parseNodeToStr( sCondition, m_xConnection ); + #endif + OSQLParseNode::negateSearchCondition(pCondition); + + pCondition = pWhereNode->getChild(1); + #if OSL_DEBUG_LEVEL > 0 + sCondition = ::rtl::OUString(); + pCondition->parseNodeToStr( sCondition, m_xConnection ); + #endif + OSQLParseNode::disjunctiveNormalForm(pCondition); + + pCondition = pWhereNode->getChild(1); + #if OSL_DEBUG_LEVEL > 0 + sCondition = ::rtl::OUString(); + pCondition->parseNodeToStr( sCondition, m_xConnection ); + #endif + OSQLParseNode::absorptions(pCondition); + + pCondition = pWhereNode->getChild(1); + #if OSL_DEBUG_LEVEL > 0 + sCondition = ::rtl::OUString(); + pCondition->parseNodeToStr( sCondition, m_xConnection ); + #endif + if ( pCondition ) + { + ::std::vector< ::std::vector < PropertyValue > > aFilters; + Reference< XNumberFormatter > xFormatter; + m_aContext.createComponent( "com.sun.star.util.NumberFormatter", xFormatter ); + xFormatter->attachNumberFormatsSupplier( m_xNumberFormatsSupplier ); + + if (setORCriteria(pCondition, m_aAdditiveIterator, aFilters, xFormatter)) + { + aFilterSeq.realloc(aFilters.size()); + Sequence<PropertyValue>* pFilters = aFilterSeq.getArray(); + ::std::vector< ::std::vector < PropertyValue > >::const_iterator aEnd = aFilters.end(); + ::std::vector< ::std::vector < PropertyValue > >::const_iterator i = aFilters.begin(); + for ( ; i != aEnd ; ++i) + { + const ::std::vector < PropertyValue >& rProperties = *i; + pFilters->realloc(rProperties.size()); + PropertyValue* pFilter = pFilters->getArray(); + ::std::vector < PropertyValue >::const_iterator j = rProperties.begin(); + ::std::vector < PropertyValue >::const_iterator aEnd2 = rProperties.end(); + for ( ; j != aEnd2 ; ++j) + { + *pFilter = *j; + ++pFilter; + } + ++pFilters; + } + } + } + // restore + m_aAdditiveIterator.setParseTree(pTempNode); + } + } + return aFilterSeq; +} +// ----------------------------------------------------------------------------- +::rtl::OUString OSingleSelectQueryComposer::getKeyword( SQLPart _ePart ) const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getKeyword" ); + ::rtl::OUString sKeyword; + switch(_ePart) + { + default: + OSL_ENSURE( 0, "OSingleSelectQueryComposer::getKeyWord: Invalid enum value!" ); + // no break, fallback to WHERE + case Where: + sKeyword = STR_WHERE; + break; + case Group: + sKeyword = STR_GROUP_BY; + break; + case Having: + sKeyword = STR_HAVING; + break; + case Order: + sKeyword = STR_ORDER_BY; + break; + } + return sKeyword; +} + +// ----------------------------------------------------------------------------- +::rtl::OUString OSingleSelectQueryComposer::getSQLPart( SQLPart _ePart, OSQLParseTreeIterator& _rIterator, sal_Bool _bWithKeyword ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getSQLPart" ); + TGetParseNode F_tmp(&OSQLParseTreeIterator::getSimpleWhereTree); + ::rtl::OUString sKeyword( getKeyword( _ePart ) ); + switch(_ePart) + { + case Where: + F_tmp = TGetParseNode(&OSQLParseTreeIterator::getSimpleWhereTree); + break; + case Group: + F_tmp = TGetParseNode (&OSQLParseTreeIterator::getSimpleGroupByTree); + break; + case Having: + F_tmp = TGetParseNode(&OSQLParseTreeIterator::getSimpleHavingTree); + break; + case Order: + F_tmp = TGetParseNode(&OSQLParseTreeIterator::getSimpleOrderTree); + break; + default: + OSL_ENSURE(0,"Invalid enum value!"); + } + + ::rtl::OUString sRet = getStatementPart( F_tmp, _rIterator ); + if ( _bWithKeyword && sRet.getLength() ) + sRet = sKeyword + sRet; + return sRet; +} +// ----------------------------------------------------------------------------- diff --git a/dbaccess/source/core/api/StaticSet.cxx b/dbaccess/source/core/api/StaticSet.cxx new file mode 100644 index 000000000000..de768b6ceb8e --- /dev/null +++ b/dbaccess/source/core/api/StaticSet.cxx @@ -0,0 +1,392 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#ifndef DBACCESS_CORE_API_STATICSET_HXX +#include "StaticSet.hxx" +#endif +#ifndef _COM_SUN_STAR_SDBCX_COMPAREBOOKMARK_HPP_ +#include <com/sun/star/sdbcx/CompareBookmark.hpp> +#endif +#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_ +#include <com/sun/star/beans/XPropertySet.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XDATABASEMETADATA_HPP_ +#include <com/sun/star/sdbc/XDatabaseMetaData.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XPREPAREDSTATEMENT_HPP_ +#include <com/sun/star/sdbc/XPreparedStatement.hpp> +#endif +#ifndef DBACCESS_SHARED_DBASTRINGS_HRC +#include "dbastrings.hrc" +#endif +#ifndef _DBASHARED_APITOOLS_HXX_ +#include "apitools.hxx" +#endif +#ifndef _CONNECTIVITY_COMMONTOOLS_HXX_ +#include <connectivity/CommonTools.hxx> +#endif +#ifndef _COMPHELPER_TYPES_HXX_ +#include <comphelper/types.hxx> +#endif +#include <rtl/logfile.hxx> + +using namespace dbaccess; +using namespace connectivity; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbc; +// using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +// using namespace ::cppu; +using namespace ::osl; + +// ------------------------------------------------------------------------- +void OStaticSet::fillValueRow(ORowSetRow& _rRow,sal_Int32 /*_nPosition*/) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::fillValueRow" ); + _rRow = *m_aSetIter; +} +// ------------------------------------------------------------------------- +// ::com::sun::star::sdbcx::XRowLocate +Any SAL_CALL OStaticSet::getBookmark() throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::getBookmark" ); + return makeAny(getRow()); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OStaticSet::moveToBookmark( const Any& bookmark ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::moveToBookmark" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + return absolute(::comphelper::getINT32(bookmark)); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OStaticSet::moveRelativeToBookmark( const Any& bookmark, sal_Int32 rows ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::moveRelativeToBookmark" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + return absolute(::comphelper::getINT32(bookmark)+rows); +} +// ------------------------------------------------------------------------- +sal_Int32 SAL_CALL OStaticSet::compareBookmarks( const Any& _first, const Any& _second ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::compareBookmarks" ); + sal_Int32 nFirst = 0, nSecond = 0; + _first >>= nFirst; + _second >>= nSecond; + return (nFirst < nSecond) ? CompareBookmark::LESS : ((nFirst > nSecond) ? CompareBookmark::GREATER : CompareBookmark::EQUAL); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OStaticSet::hasOrderedBookmarks( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::hasOrderedBookmarks" ); + return sal_True; +} +// ------------------------------------------------------------------------- +sal_Int32 SAL_CALL OStaticSet::hashBookmark( const Any& bookmark ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::hashBookmark" ); + return ::comphelper::getINT32(bookmark); +} +// ------------------------------------------------------------------------- +sal_Bool OStaticSet::fetchRow() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::fetchRow" ); + sal_Bool bRet = sal_False; + if ( !m_bEnd ) + bRet = m_xDriverSet->next(); + if ( bRet ) + { + m_aSet.push_back(new connectivity::ORowVector< connectivity::ORowSetValue >(m_xSetMetaData->getColumnCount())); + m_aSetIter = m_aSet.end() - 1; + ((*m_aSetIter)->get())[0] = getRow(); + OCacheSet::fillValueRow(*m_aSetIter,((*m_aSetIter)->get())[0]); + } + else + m_bEnd = sal_True; + return bRet; +} +// ------------------------------------------------------------------------- +void OStaticSet::fillAllRows() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::fillAllRows" ); + if(!m_bEnd) + { + while(m_xDriverSet->next()) + { + ORowSetRow pRow = new connectivity::ORowVector< connectivity::ORowSetValue >(m_xSetMetaData->getColumnCount()); + m_aSet.push_back(pRow); + m_aSetIter = m_aSet.end() - 1; + (pRow->get())[0] = getRow(); + OCacheSet::fillValueRow(pRow,(pRow->get())[0]); + } + m_bEnd = sal_True; + } +} +// ------------------------------------------------------------------------- +// XResultSet +sal_Bool SAL_CALL OStaticSet::next( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::next" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + + if(isAfterLast()) + return sal_False; + if(!m_bEnd) // not yet all records fetched + { + ++m_aSetIter; + if(m_aSetIter == m_aSet.end() && !fetchRow()) + m_aSetIter = m_aSet.end(); + } + else if(!isAfterLast()) + ++m_aSetIter; + return !isAfterLast(); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OStaticSet::isBeforeFirst( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::isBeforeFirst" ); + return m_aSetIter == m_aSet.begin(); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OStaticSet::isAfterLast( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::isAfterLast" ); + return m_aSetIter == m_aSet.end() && m_bEnd; +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OStaticSet::isFirst( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::isFirst" ); + return m_aSetIter == m_aSet.begin()+1; +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OStaticSet::isLast( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::isLast" ); + return m_aSetIter == m_aSet.end()-1 && m_bEnd; +} +// ------------------------------------------------------------------------- +void SAL_CALL OStaticSet::beforeFirst( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::beforeFirst" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + m_aSetIter = m_aSet.begin(); +} +// ------------------------------------------------------------------------- +void SAL_CALL OStaticSet::afterLast( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::afterLast" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + fillAllRows(); + m_aSetIter = m_aSet.end(); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OStaticSet::first( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::first" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + m_aSetIter = m_aSet.begin()+1; + if(m_aSetIter == m_aSet.end() && !fetchRow()) + m_aSetIter = m_aSet.end(); + + return m_aSetIter != m_aSet.end(); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OStaticSet::last( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::last" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + fillAllRows(); + m_aSetIter = m_aSet.end()-1; + + return !isBeforeFirst() && !isAfterLast(); +} +// ------------------------------------------------------------------------- +sal_Int32 SAL_CALL OStaticSet::getRow( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::getRow" ); + OSL_ENSURE(!isAfterLast(),"getRow is not allowed when afterlast record!"); + OSL_ENSURE(!isBeforeFirst(),"getRow is not allowed when beforefirst record!"); + + sal_Int32 nPos = m_aSet.size() - (m_aSet.end() - m_aSetIter); + OSL_ENSURE(nPos > 0,"RowPos is < 0"); + return nPos; +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OStaticSet::absolute( sal_Int32 row ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::absolute" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + OSL_ENSURE(row,"OStaticSet::absolute: INVALID row number!"); + // if row greater 0 than count from end - row means last + if(row < 0) + { + if(!m_bEnd) + fillAllRows(); + + sal_Int32 nRow = getRow(); + nRow += row; + if(nRow <= (sal_Int32)m_aSet.size()) + m_aSetIter = m_aSet.begin() + nRow; + else + m_aSetIter = m_aSet.begin(); + } + else if(row > 0) + { + if(row >= (sal_Int32)m_aSet.size()) + { + if(!m_bEnd) + { + sal_Bool bNext = sal_True; + for(sal_Int32 i=m_aSet.size()-1;i < row && bNext;++i) + bNext = fetchRow(); + } + + if(row > (sal_Int32)m_aSet.size()) + m_aSetIter = m_aSet.end(); // check again + else + m_aSetIter = m_aSet.begin() + row; + } + else + m_aSetIter = m_aSet.begin() + row; + } + + return m_aSetIter != m_aSet.end() && m_aSetIter != m_aSet.begin(); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OStaticSet::relative( sal_Int32 rows ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::relative" ); + if(!rows) + return sal_True; + + sal_Int32 nCurPos = getRow(); + return absolute(nCurPos+rows); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OStaticSet::previous( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::previous" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + + if(m_aSetIter != m_aSet.begin()) + --m_aSetIter; + + return m_aSetIter != m_aSet.begin(); +} +// ------------------------------------------------------------------------- +void SAL_CALL OStaticSet::refreshRow( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::refreshRow" ); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OStaticSet::rowUpdated( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::rowUpdated" ); + return m_bUpdated; +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OStaticSet::rowInserted( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::rowInserted" ); + return m_bInserted; +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OStaticSet::rowDeleted( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::rowDeleted" ); + return m_bDeleted; +} +// ------------------------------------------------------------------------- +Sequence< sal_Int32 > SAL_CALL OStaticSet::deleteRows( const Sequence< Any >& rows,const connectivity::OSQLTable& _xTable ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::deleteRows" ); + Sequence< sal_Int32 > aRet(rows.getLength()); + const Any* pBegin = rows.getConstArray(); + const Any* pEnd = pBegin + rows.getLength(); + for(sal_Int32 i=0;pBegin != pEnd; ++pBegin,++i) + { + deleteRow(*(m_aSet.begin() + comphelper::getINT32(*pBegin)),_xTable); + aRet.getArray()[i] = m_bDeleted; + } + return aRet; +} +// ------------------------------------------------------------------------- +void SAL_CALL OStaticSet::insertRow( const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& _xTable ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::insertRow" ); + OCacheSet::insertRow( _rInsertRow,_xTable); + if(m_bInserted) + { + m_aSet.push_back(new ORowVector< ORowSetValue >(*_rInsertRow)); // we don't know where the new row is so we append it to the current rows + m_aSetIter = m_aSet.end() - 1; + ((*m_aSetIter)->get())[0] = (_rInsertRow->get())[0] = getBookmark(); + m_bEnd = sal_False; + } +} +// ------------------------------------------------------------------------- +void SAL_CALL OStaticSet::updateRow(const ORowSetRow& _rInsertRow ,const ORowSetRow& _rOrginalRow,const connectivity::OSQLTable& _xTable ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::updateRow" ); + OCacheSet::updateRow( _rInsertRow,_rOrginalRow,_xTable); +} +// ------------------------------------------------------------------------- +void SAL_CALL OStaticSet::deleteRow(const ORowSetRow& _rDeleteRow ,const connectivity::OSQLTable& _xTable ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::deleteRow" ); + OCacheSet::deleteRow(_rDeleteRow,_xTable); + if(m_bDeleted) + { + ORowSetMatrix::iterator aPos = m_aSet.begin()+(_rDeleteRow->get())[0].getInt32(); + if(aPos == (m_aSet.end()-1)) + m_aSetIter = m_aSet.end(); + m_aSet.erase(aPos); + } +} +// ------------------------------------------------------------------------- +void SAL_CALL OStaticSet::cancelRowUpdates( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::cancelRowUpdates" ); +} +// ------------------------------------------------------------------------- +void SAL_CALL OStaticSet::moveToInsertRow( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::moveToInsertRow" ); +} +// ------------------------------------------------------------------------- +void SAL_CALL OStaticSet::moveToCurrentRow( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::moveToCurrentRow" ); +} +// ------------------------------------------------------------------------- + diff --git a/dbaccess/source/core/api/StaticSet.hxx b/dbaccess/source/core/api/StaticSet.hxx new file mode 100644 index 000000000000..676044cb61f9 --- /dev/null +++ b/dbaccess/source/core/api/StaticSet.hxx @@ -0,0 +1,93 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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_CORE_API_STATICSET_HXX +#define DBACCESS_CORE_API_STATICSET_HXX + +#ifndef DBACCESS_CORE_API_CACHESET_HXX +#include "CacheSet.hxx" +#endif + +namespace dbaccess +{ + // is used when nothing is supported by the driver + // we use a snapshot + class OStaticSet : public OCacheSet + { + ORowSetMatrix m_aSet; + ORowSetMatrix::iterator m_aSetIter; + sal_Bool m_bEnd; + sal_Bool fetchRow(); + void fillAllRows(); + public: + OStaticSet() + : m_aSetIter(m_aSet.end()) + , m_bEnd(sal_False) + { + m_aSet.push_back(NULL); // this is the beforefirst record + } + + virtual void fillValueRow(ORowSetRow& _rRow,sal_Int32 _nPosition); + // ::com::sun::star::sdbcx::XRowLocate + virtual ::com::sun::star::uno::Any SAL_CALL getBookmark() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL moveToBookmark( const ::com::sun::star::uno::Any& bookmark ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL moveRelativeToBookmark( const ::com::sun::star::uno::Any& bookmark, sal_Int32 rows ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL compareBookmarks( const ::com::sun::star::uno::Any& first, const ::com::sun::star::uno::Any& second ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL hasOrderedBookmarks( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL hashBookmark( const ::com::sun::star::uno::Any& bookmark ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbc::XResultSet + virtual sal_Bool SAL_CALL next( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isBeforeFirst( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isAfterLast( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isFirst( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isLast( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL beforeFirst( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL afterLast( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL first( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL last( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL absolute( sal_Int32 row ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL relative( sal_Int32 rows ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL previous( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL refreshRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL rowUpdated( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL rowInserted( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL rowDeleted( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + // ::com::sun::star::sdbcx::XDeleteRows + virtual ::com::sun::star::uno::Sequence< sal_Int32 > SAL_CALL deleteRows( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& rows,const connectivity::OSQLTable& _xTable ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + // ::com::sun::star::sdbc::XResultSetUpdate + virtual void SAL_CALL insertRow( const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& _xTable ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateRow(const ORowSetRow& _rInsertRow,const ORowSetRow& _rOrginalRow,const connectivity::OSQLTable& _xTable ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL deleteRow(const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& _xTable ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL cancelRowUpdates( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL moveToInsertRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL moveToCurrentRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + }; +} +#endif //DBACCESS_CORE_API_STATICSET_HXX + diff --git a/dbaccess/source/core/api/TableDeco.cxx b/dbaccess/source/core/api/TableDeco.cxx new file mode 100644 index 000000000000..a296833ab6ef --- /dev/null +++ b/dbaccess/source/core/api/TableDeco.cxx @@ -0,0 +1,758 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#ifndef _DBA_CORE_TABLEDECORATOR_HXX_ +#include "TableDeco.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 + +#ifndef _CPPUHELPER_TYPEPROVIDER_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_PROPERTY_HXX_ +#include <comphelper/property.hxx> +#endif +#ifndef _COMPHELPER_TYPES_HXX_ +#include <comphelper/types.hxx> +#endif +#ifndef _COM_SUN_STAR_UTIL_XREFRESHLISTENER_HPP_ +#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 +#ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBUTE_HPP_ +#include <com/sun/star/beans/PropertyAttribute.hpp> +#endif +#ifndef _CONNECTIVITY_DBTOOLS_HXX_ +#include <connectivity/dbtools.hxx> +#endif +#ifndef _DBHELPER_DBEXCEPTION_HXX_ +#include <connectivity/dbexception.hxx> +#endif +#ifndef _CONNECTIVITY_DBTOOLS_HXX_ +#include <connectivity/dbtools.hxx> +#endif +#ifndef _COMPHELPER_EXTRACT_HXX_ +#include <comphelper/extract.hxx> +#endif +#ifndef DBA_CONTAINERMEDIATOR_HXX +#include "ContainerMediator.hxx" +#endif +#include <rtl/logfile.hxx> + +using namespace dbaccess; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::container; +using namespace ::osl; +using namespace ::comphelper; +using namespace ::dbtools; +using namespace ::cppu; + +//========================================================================== +//= ODBTableDecorator +//========================================================================== +DBG_NAME(ODBTableDecorator) +// ----------------------------------------------------------------------------- +ODBTableDecorator::ODBTableDecorator( const Reference< XConnection >& _rxConnection, const Reference< XColumnsSupplier >& _rxNewTable, + const Reference< XNumberFormatsSupplier >& _rxNumberFormats, const Reference< XNameAccess >& _xColumnDefinitions ) throw(SQLException) + :OTableDescriptor_BASE(m_aMutex) + ,ODataSettings(OTableDescriptor_BASE::rBHelper) + ,m_xTable(_rxNewTable) + ,m_xColumnDefinitions(_xColumnDefinitions) + ,m_xConnection( _rxConnection ) + ,m_xMetaData( _rxConnection.is() ? _rxConnection->getMetaData() : Reference< XDatabaseMetaData >() ) + ,m_xNumberFormats( _rxNumberFormats ) + ,m_nPrivileges(-1) + ,m_pColumns(NULL) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::ODBTableDecorator" ); + DBG_CTOR(ODBTableDecorator, NULL); + ODataSettings::registerPropertiesFor(this); +} +// ------------------------------------------------------------------------- +ODBTableDecorator::~ODBTableDecorator() +{ + DBG_DTOR(ODBTableDecorator, NULL); + if ( m_pColumns ) + delete m_pColumns; +} + +//-------------------------------------------------------------------------- +Sequence< sal_Int8 > ODBTableDecorator::getImplementationId() throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::getImplementationId" ); + static OImplementationId * pId = 0; + if (! pId) + { + MutexGuard aGuard( Mutex::getGlobalMutex() ); + if (! pId) + { + static OImplementationId aId; + pId = &aId; + } + } + return pId->getImplementationId(); +} + +// OComponentHelper +//------------------------------------------------------------------------------ +void SAL_CALL ODBTableDecorator::disposing() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::disposing" ); + OPropertySetHelper::disposing(); + OTableDescriptor_BASE::disposing(); + + MutexGuard aGuard(m_aMutex); + m_xTable = NULL; + m_xMetaData = NULL; + m_pTables = NULL; + m_xColumnDefinitions = NULL; + m_xNumberFormats = NULL; + if ( m_pColumns ) + m_pColumns->disposing(); + m_xColumnMediator = NULL; +} +// ----------------------------------------------------------------------------- +sal_Bool SAL_CALL ODBTableDecorator::convertFastPropertyValue( + Any & rConvertedValue, + Any & rOldValue, + sal_Int32 nHandle, + const Any& rValue ) + throw (::com::sun::star::lang::IllegalArgumentException) +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::convertFastPropertyValue" ); + sal_Bool bRet = sal_True; + switch(nHandle) + { + case PROPERTY_ID_PRIVILEGES: + case PROPERTY_ID_FILTER: + case PROPERTY_ID_ORDER: + case PROPERTY_ID_APPLYFILTER: + case PROPERTY_ID_FONT: + case PROPERTY_ID_ROW_HEIGHT: + case PROPERTY_ID_TEXTCOLOR: + case PROPERTY_ID_TEXTLINECOLOR: + case PROPERTY_ID_TEXTEMPHASIS: + case PROPERTY_ID_TEXTRELIEF: + case PROPERTY_ID_FONTCHARWIDTH: + case PROPERTY_ID_FONTCHARSET: + case PROPERTY_ID_FONTFAMILY: + case PROPERTY_ID_FONTHEIGHT: + case PROPERTY_ID_FONTKERNING: + case PROPERTY_ID_FONTNAME: + case PROPERTY_ID_FONTORIENTATION: + case PROPERTY_ID_FONTPITCH: + case PROPERTY_ID_FONTSLANT: + case PROPERTY_ID_FONTSTRIKEOUT: + case PROPERTY_ID_FONTSTYLENAME: + case PROPERTY_ID_FONTUNDERLINE: + case PROPERTY_ID_FONTWEIGHT: + case PROPERTY_ID_FONTWIDTH: + case PROPERTY_ID_FONTWORDLINEMODE: + case PROPERTY_ID_FONTTYPE: + bRet = ODataSettings::convertFastPropertyValue(rConvertedValue, rOldValue,nHandle,rValue); + break; + + default: + { + Any aValue; + getFastPropertyValue(aValue,nHandle); + bRet = ::comphelper::tryPropertyValue(rConvertedValue,rOldValue,rValue,aValue,::getCppuType(reinterpret_cast< ::rtl::OUString*>(NULL))); + } + break; // we assume that it works + } + return bRet; +} +// ----------------------------------------------------------------------------- +void ODBTableDecorator::setFastPropertyValue_NoBroadcast(sal_Int32 _nHandle, const Any& _rValue) throw (Exception) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::setFastPropertyValue_NoBroadcast" ); + switch(_nHandle) + { + case PROPERTY_ID_PRIVILEGES: + OSL_ENSURE(0,"Property is readonly!"); + case PROPERTY_ID_FILTER: + case PROPERTY_ID_ORDER: + case PROPERTY_ID_APPLYFILTER: + case PROPERTY_ID_FONT: + case PROPERTY_ID_ROW_HEIGHT: + case PROPERTY_ID_TEXTCOLOR: + case PROPERTY_ID_TEXTLINECOLOR: + case PROPERTY_ID_TEXTEMPHASIS: + case PROPERTY_ID_TEXTRELIEF: + case PROPERTY_ID_FONTCHARWIDTH: + case PROPERTY_ID_FONTCHARSET: + case PROPERTY_ID_FONTFAMILY: + case PROPERTY_ID_FONTHEIGHT: + case PROPERTY_ID_FONTKERNING: + case PROPERTY_ID_FONTNAME: + case PROPERTY_ID_FONTORIENTATION: + case PROPERTY_ID_FONTPITCH: + case PROPERTY_ID_FONTSLANT: + case PROPERTY_ID_FONTSTRIKEOUT: + case PROPERTY_ID_FONTSTYLENAME: + case PROPERTY_ID_FONTUNDERLINE: + case PROPERTY_ID_FONTWEIGHT: + case PROPERTY_ID_FONTWIDTH: + case PROPERTY_ID_FONTWORDLINEMODE: + case PROPERTY_ID_FONTTYPE: + + ODataSettings::setFastPropertyValue_NoBroadcast(_nHandle, _rValue); + break; + case PROPERTY_ID_CATALOGNAME: + { + Reference<XPropertySet> xProp(m_xTable,UNO_QUERY); + xProp->setPropertyValue(PROPERTY_CATALOGNAME,_rValue); + } + break; + case PROPERTY_ID_SCHEMANAME: + { + Reference<XPropertySet> xProp(m_xTable,UNO_QUERY); + xProp->setPropertyValue(PROPERTY_SCHEMANAME,_rValue); + } + break; + case PROPERTY_ID_NAME: + { + Reference<XPropertySet> xProp(m_xTable,UNO_QUERY); + xProp->setPropertyValue(PROPERTY_NAME,_rValue); + } + break; + case PROPERTY_ID_DESCRIPTION: + { + Reference<XPropertySet> xProp(m_xTable,UNO_QUERY); + xProp->setPropertyValue(PROPERTY_DESCRIPTION,_rValue); + } + break; + case PROPERTY_ID_TYPE: + { + Reference<XPropertySet> xProp(m_xTable,UNO_QUERY); + xProp->setPropertyValue(PROPERTY_TYPE,_rValue); + } + break; + } +} +//------------------------------------------------------------------------------ +void ODBTableDecorator::getFastPropertyValue(Any& _rValue, sal_Int32 _nHandle) const +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::getFastPropertyValue" ); + switch(_nHandle) + { + case PROPERTY_ID_PRIVILEGES: + { + if ( -1 == m_nPrivileges ) + fillPrivileges(); + Reference<XPropertySet> xProp(m_xTable,UNO_QUERY); + Reference<XPropertySetInfo> xInfo = xProp->getPropertySetInfo(); + if ( xInfo->hasPropertyByName(PROPERTY_PRIVILEGES) ) + { + _rValue <<= m_nPrivileges; + break; + } + } + // run through + + case PROPERTY_ID_FILTER: + case PROPERTY_ID_ORDER: + case PROPERTY_ID_APPLYFILTER: + case PROPERTY_ID_FONT: + case PROPERTY_ID_ROW_HEIGHT: + case PROPERTY_ID_TEXTCOLOR: + case PROPERTY_ID_TEXTLINECOLOR: + case PROPERTY_ID_TEXTEMPHASIS: + case PROPERTY_ID_TEXTRELIEF: + case PROPERTY_ID_FONTCHARWIDTH: + case PROPERTY_ID_FONTCHARSET: + case PROPERTY_ID_FONTFAMILY: + case PROPERTY_ID_FONTHEIGHT: + case PROPERTY_ID_FONTKERNING: + case PROPERTY_ID_FONTNAME: + case PROPERTY_ID_FONTORIENTATION: + case PROPERTY_ID_FONTPITCH: + case PROPERTY_ID_FONTSLANT: + case PROPERTY_ID_FONTSTRIKEOUT: + case PROPERTY_ID_FONTSTYLENAME: + case PROPERTY_ID_FONTUNDERLINE: + case PROPERTY_ID_FONTWEIGHT: + case PROPERTY_ID_FONTWIDTH: + case PROPERTY_ID_FONTWORDLINEMODE: + case PROPERTY_ID_FONTTYPE: + ODataSettings::getFastPropertyValue(_rValue, _nHandle); + break; + case PROPERTY_ID_CATALOGNAME: + { + Reference<XPropertySet> xProp(m_xTable,UNO_QUERY); + _rValue = xProp->getPropertyValue(PROPERTY_CATALOGNAME); + } + break; + case PROPERTY_ID_SCHEMANAME: + { + Reference<XPropertySet> xProp(m_xTable,UNO_QUERY); + _rValue = xProp->getPropertyValue(PROPERTY_SCHEMANAME); + } + break; + case PROPERTY_ID_NAME: + { + Reference<XPropertySet> xProp(m_xTable,UNO_QUERY); + _rValue = xProp->getPropertyValue(PROPERTY_NAME); + } + break; + case PROPERTY_ID_DESCRIPTION: + { + Reference<XPropertySet> xProp(m_xTable,UNO_QUERY); + _rValue = xProp->getPropertyValue(PROPERTY_DESCRIPTION); + } + break; + case PROPERTY_ID_TYPE: + { + Reference<XPropertySet> xProp(m_xTable,UNO_QUERY); + _rValue = xProp->getPropertyValue(PROPERTY_TYPE); + } + break; + default: + OSL_ENSURE(0,"Invalid Handle for table"); + } +} +// ------------------------------------------------------------------------- +void ODBTableDecorator::construct() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::construct" ); + sal_Bool bNotFound = sal_True; + Reference<XPropertySet> xProp(m_xTable,UNO_QUERY); + if ( xProp.is() ) + { + Reference<XPropertySetInfo> xInfo = xProp->getPropertySetInfo(); + bNotFound = !xInfo->hasPropertyByName(PROPERTY_PRIVILEGES); + } + if ( bNotFound ) + registerProperty(PROPERTY_PRIVILEGES, PROPERTY_ID_PRIVILEGES, PropertyAttribute::BOUND | PropertyAttribute::READONLY, + &m_nPrivileges, ::getCppuType(static_cast<sal_Int32*>(NULL))); +} +// ----------------------------------------------------------------------------- +::cppu::IPropertyArrayHelper* ODBTableDecorator::createArrayHelper(sal_Int32 /*_nId*/) const +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::createArrayHelper" ); + Reference<XPropertySet> xProp(m_xTable,UNO_QUERY); + Reference<XPropertySetInfo> xInfo = xProp->getPropertySetInfo(); + + Sequence< Property > aTableProps = xInfo->getProperties(); + Property* pIter = aTableProps.getArray(); + Property* pEnd = pIter + aTableProps.getLength(); + for (;pIter != pEnd ; ++pIter) + { + if (0 == pIter->Name.compareToAscii(PROPERTY_CATALOGNAME)) + pIter->Handle = PROPERTY_ID_CATALOGNAME; + else if (0 ==pIter->Name.compareToAscii(PROPERTY_SCHEMANAME)) + pIter->Handle = PROPERTY_ID_SCHEMANAME; + else if (0 ==pIter->Name.compareToAscii(PROPERTY_NAME)) + pIter->Handle = PROPERTY_ID_NAME; + else if (0 ==pIter->Name.compareToAscii(PROPERTY_DESCRIPTION)) + pIter->Handle = PROPERTY_ID_DESCRIPTION; + else if (0 ==pIter->Name.compareToAscii(PROPERTY_TYPE)) + pIter->Handle = PROPERTY_ID_TYPE; + else if (0 ==pIter->Name.compareToAscii(PROPERTY_PRIVILEGES)) + pIter->Handle = PROPERTY_ID_PRIVILEGES; + } + + describeProperties(aTableProps); + + return new ::cppu::OPropertyArrayHelper(aTableProps); +} +// ----------------------------------------------------------------------------- +::cppu::IPropertyArrayHelper & SAL_CALL ODBTableDecorator::getInfoHelper() +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::getInfoHelper" ); + Reference<XPropertySet> xProp(m_xTable,UNO_QUERY); + + Reference<XPropertySetInfo> xInfo = xProp->getPropertySetInfo(); + bool bIsDescriptor = (xInfo->getPropertyByName(PROPERTY_NAME).Attributes & PropertyAttribute::READONLY) == 0; + + return *ODBTableDecorator_PROP::getArrayHelper( bIsDescriptor ? 0 : 1 ); + + // TODO: this is a HACK, and prone to errors + // The OIdPropertyArrayUsageHelper is intended for classes where there exists a known, limited + // number of different property set infos (distinguished by the ID), all implemented by this very + // same class. + // However, in this case here we have an unknown, potentially unlimited number of different + // property set infos: Depending on the table for which we act as decorator, different property + // sets might exist. +} +// ------------------------------------------------------------------------- +// XServiceInfo +IMPLEMENT_SERVICE_INFO1(ODBTableDecorator, "com.sun.star.sdb.dbaccess.ODBTableDecorator", SERVICE_SDBCX_TABLE) +// ------------------------------------------------------------------------- +Any SAL_CALL ODBTableDecorator::queryInterface( const Type & rType ) throw(RuntimeException) +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::queryInterface" ); + Any aRet; + if(m_xTable.is()) + { + aRet = m_xTable->queryInterface(rType); + if(aRet.hasValue()) + { // now we know that our table supports this type so we return ourself + aRet = OTableDescriptor_BASE::queryInterface(rType); + if(!aRet.hasValue()) + aRet = ODataSettings::queryInterface(rType); + } + } + + return aRet; +} +// ------------------------------------------------------------------------- +Sequence< Type > SAL_CALL ODBTableDecorator::getTypes( ) throw(RuntimeException) +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::getTypes" ); + Reference<XTypeProvider> xTypes(m_xTable,UNO_QUERY); + OSL_ENSURE(xTypes.is(),"Table must be a TypePropvider!"); + return xTypes->getTypes(); +} + +// ----------------------------------------------------------------------------- +// XRename, +//------------------------------------------------------------------------------ +void SAL_CALL ODBTableDecorator::rename( const ::rtl::OUString& _rNewName ) throw(SQLException, ElementExistException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::rename" ); + ::osl::MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OTableDescriptor_BASE::rBHelper.bDisposed); + Reference<XRename> xRename(m_xTable,UNO_QUERY); + if(xRename.is()) + { +// ::rtl::OUString sOldName; +// Reference<XPropertySet> xProp(m_xTable,UNO_QUERY); +// xProp->getPropertyValue(PROPERTY_NAME) >>= sOldName; + xRename->rename(_rNewName); + } + else // not supported + throw SQLException(DBACORE_RESSTRING(RID_STR_NO_TABLE_RENAME),*this,SQLSTATE_GENERAL,1000,Any() ); +} + +// XAlterTable, +//------------------------------------------------------------------------------ +void SAL_CALL ODBTableDecorator::alterColumnByName( const ::rtl::OUString& _rName, const Reference< XPropertySet >& _rxDescriptor ) throw(SQLException, NoSuchElementException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::alterColumnByName" ); + ::osl::MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OTableDescriptor_BASE::rBHelper.bDisposed); + Reference<XAlterTable> xAlter(m_xTable,UNO_QUERY); + if(xAlter.is()) + { + xAlter->alterColumnByName(_rName,_rxDescriptor); + } + else + throw SQLException(DBACORE_RESSTRING(RID_STR_COLUMN_ALTER_BY_NAME),*this,SQLSTATE_GENERAL,1000,Any() ); + if(m_pColumns) + m_pColumns->refresh(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODBTableDecorator::alterColumnByIndex( sal_Int32 _nIndex, const Reference< XPropertySet >& _rxDescriptor ) throw(SQLException, IndexOutOfBoundsException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::alterColumnByIndex" ); + ::osl::MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OTableDescriptor_BASE::rBHelper.bDisposed); + Reference<XAlterTable> xAlter(m_xTable,UNO_QUERY); + if(xAlter.is()) + { + xAlter->alterColumnByIndex(_nIndex,_rxDescriptor); + if(m_pColumns) + m_pColumns->refresh(); + } + else // not supported + throw SQLException(DBACORE_RESSTRING(RID_STR_COLUMN_ALTER_BY_INDEX),*this,SQLSTATE_GENERAL,1000,Any() ); +} +// ----------------------------------------------------------------------------- +Reference< XNameAccess> ODBTableDecorator::getIndexes() throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::getIndexes" ); + ::osl::MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OTableDescriptor_BASE::rBHelper.bDisposed); + return Reference< XIndexesSupplier>(m_xTable,UNO_QUERY)->getIndexes(); +} +// ------------------------------------------------------------------------- +Reference< XIndexAccess> ODBTableDecorator::getKeys() throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::getKeys" ); + ::osl::MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OTableDescriptor_BASE::rBHelper.bDisposed); + return Reference< XKeysSupplier>(m_xTable,UNO_QUERY)->getKeys(); +} +// ------------------------------------------------------------------------- +Reference< XNameAccess> ODBTableDecorator::getColumns() throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::getColumns" ); + ::osl::MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OTableDescriptor_BASE::rBHelper.bDisposed); + + if(!m_pColumns) + refreshColumns(); + + return m_pColumns; +} +// ----------------------------------------------------------------------------- +::rtl::OUString SAL_CALL ODBTableDecorator::getName() throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::getName" ); + ::osl::MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OTableDescriptor_BASE::rBHelper.bDisposed); + Reference<XNamed> xName(m_xTable,UNO_QUERY); + OSL_ENSURE(xName.is(),"Table should support the XNamed interface"); + return xName->getName(); +} +// ----------------------------------------------------------------------------- +sal_Int64 SAL_CALL ODBTableDecorator::getSomething( const Sequence< sal_Int8 >& rId ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::getSomething" ); + if (rId.getLength() == 16 && 0 == rtl_compareMemory(getUnoTunnelImplementationId().getConstArray(), rId.getConstArray(), 16 ) ) + return reinterpret_cast<sal_Int64>(this); + + sal_Int64 nRet = 0; + Reference<XUnoTunnel> xTunnel(m_xTable,UNO_QUERY); + if(xTunnel.is()) + nRet = xTunnel->getSomething(rId); + return nRet; +} +// ----------------------------------------------------------------------------- +Sequence< sal_Int8 > ODBTableDecorator::getUnoTunnelImplementationId() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::getUnoTunnelImplementationId" ); + static ::cppu::OImplementationId * pId = 0; + if (! pId) + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if (! pId) + { + static ::cppu::OImplementationId aId; + pId = &aId; + } + } + return pId->getImplementationId(); +} +// ----------------------------------------------------------------------------- +void ODBTableDecorator::fillPrivileges() const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::fillPrivileges" ); + // somebody is asking for the privileges an we do not know them, yet + m_nPrivileges = 0; + try + { + Reference<XPropertySet> xProp(m_xTable,UNO_QUERY); + if ( xProp.is() ) + { + if ( xProp->getPropertySetInfo()->hasPropertyByName(PROPERTY_PRIVILEGES) ) + { + xProp->getPropertyValue(PROPERTY_PRIVILEGES) >>= m_nPrivileges; + } + if ( m_nPrivileges == 0 ) // second chance + { + ::rtl::OUString sCatalog,sSchema,sName; + xProp->getPropertyValue(PROPERTY_CATALOGNAME) >>= sCatalog; + xProp->getPropertyValue(PROPERTY_SCHEMANAME) >>= sSchema; + xProp->getPropertyValue(PROPERTY_NAME) >>= sName; + m_nPrivileges = ::dbtools::getTablePrivileges(getMetaData(),sCatalog,sSchema, sName); + } + } + } + catch(const SQLException& e) + { + (void)e; + DBG_ERROR("ODBTableDecorator::ODBTableDecorator : could not collect the privileges !"); + } +} +// ----------------------------------------------------------------------------- +Reference< XPropertySet > SAL_CALL ODBTableDecorator::createDataDescriptor( ) throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::createDataDescriptor" ); + ::osl::MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OTableDescriptor_BASE::rBHelper.bDisposed); + + Reference< XDataDescriptorFactory > xFactory( m_xTable, UNO_QUERY ); + DBG_ASSERT( xFactory.is(), "ODBTableDecorator::createDataDescriptor: invalid table!" ); + Reference< XColumnsSupplier > xColsSupp; + if ( xFactory.is() ) + xColsSupp = xColsSupp.query( xFactory->createDataDescriptor() ); + + return new ODBTableDecorator( + m_xConnection, + xColsSupp, + m_xNumberFormats, + NULL + ); +} +// ----------------------------------------------------------------------------- +Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL ODBTableDecorator::getPropertySetInfo( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::getPropertySetInfo" ); + return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper()); +} +// ----------------------------------------------------------------------------- +void ODBTableDecorator::refreshColumns() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::refreshColumns" ); + ::osl::MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OTableDescriptor_BASE::rBHelper.bDisposed); + + ::std::vector< ::rtl::OUString> aVector; + + Reference<XNameAccess> xNames; + if(m_xTable.is()) + { + xNames = m_xTable->getColumns(); + if(xNames.is()) + { + Sequence< ::rtl::OUString> aNames = xNames->getElementNames(); + const ::rtl::OUString* pIter = aNames.getConstArray(); + const ::rtl::OUString* pEnd = pIter + aNames.getLength(); + for(;pIter != pEnd;++pIter) + aVector.push_back(*pIter); + } + } + if(!m_pColumns) + { + OColumns* pCol = new OColumns(*this,m_aMutex,xNames,m_xMetaData.is() && m_xMetaData->supportsMixedCaseQuotedIdentifiers(),aVector, + this,this, + m_xMetaData.is() && m_xMetaData->supportsAlterTableWithAddColumn(), + m_xMetaData.is() && m_xMetaData->supportsAlterTableWithDropColumn()); + + pCol->setParent(*this); + OContainerMediator* pMediator = new OContainerMediator( pCol, m_xColumnDefinitions, m_xConnection, OContainerMediator::eColumns ); + m_xColumnMediator = pMediator; + pCol->setMediator( pMediator ); + m_pColumns = pCol; + } + else + m_pColumns->reFill(aVector); +} +// ----------------------------------------------------------------------------- +OColumn* ODBTableDecorator::createColumn(const ::rtl::OUString& _rName) const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::createColumn" ); + OColumn* pReturn = NULL; + + Reference<XNameAccess> xNames; + if ( m_xTable.is() ) + { + xNames = m_xTable->getColumns(); + + if ( xNames.is() && xNames->hasByName(_rName) ) + { + Reference<XPropertySet> xProp(xNames->getByName(_rName),UNO_QUERY); + + Reference<XPropertySet> xColumnDefintion; + if ( m_xColumnDefinitions.is() && m_xColumnDefinitions->hasByName(_rName)) + xColumnDefintion.set(m_xColumnDefinitions->getByName(_rName),UNO_QUERY); + + pReturn = new OTableColumnWrapper( xProp, xColumnDefintion, false ); + } + } + return pReturn; +} +// ----------------------------------------------------------------------------- +void ODBTableDecorator::columnAppended( const Reference< XPropertySet >& /*_rxSourceDescriptor*/ ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::columnAppended" ); + // not interested in +} +// ----------------------------------------------------------------------------- +void ODBTableDecorator::columnDropped(const ::rtl::OUString& _sName) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::columnDropped" ); + Reference<XDrop> xDrop(m_xColumnDefinitions,UNO_QUERY); + if ( xDrop.is() && m_xColumnDefinitions->hasByName(_sName) ) + xDrop->dropByName(_sName); +} + +// ----------------------------------------------------------------------------- +Reference< XPropertySet > ODBTableDecorator::createColumnDescriptor() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::createColumnDescriptor" ); + Reference<XDataDescriptorFactory> xNames; + if(m_xTable.is()) + xNames.set(m_xTable->getColumns(),UNO_QUERY); + Reference< XPropertySet > xRet; + if ( xNames.is() ) + xRet = new OTableColumnDescriptorWrapper( xNames->createDataDescriptor(), false, true ); + return xRet; +} +// ----------------------------------------------------------------------------- +void SAL_CALL ODBTableDecorator::acquire() throw() +{ + OTableDescriptor_BASE::acquire(); +} +// ----------------------------------------------------------------------------- +void SAL_CALL ODBTableDecorator::release() throw() +{ + OTableDescriptor_BASE::release(); +} + +// ----------------------------------------------------------------------------- +void SAL_CALL ODBTableDecorator::setName( const ::rtl::OUString& /*aName*/ ) throw (::com::sun::star::uno::RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::setName" ); + throwFunctionNotSupportedException( "XNamed::setName", *this ); +} + +// ----------------------------------------------------------------------------- + + 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/WrappedResultSet.cxx b/dbaccess/source/core/api/WrappedResultSet.cxx new file mode 100644 index 000000000000..22e8f61383ac --- /dev/null +++ b/dbaccess/source/core/api/WrappedResultSet.cxx @@ -0,0 +1,255 @@ +/************************************************************************* + * + * 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: BookmarkSet.cxx,v $ + * $Revision: 1.21 $ + * + * 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 "WrappedResultSet.hxx" +#include "core_resource.hxx" +#include "core_resource.hrc" +#include <com/sun/star/sdbc/XResultSetUpdate.hpp> +#include <connectivity/dbexception.hxx> +#include <rtl/logfile.hxx> + +#include <limits> + +using namespace dbaccess; +using namespace ::connectivity; +using namespace ::dbtools; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbc; +// using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +// using namespace ::cppu; +using namespace ::osl; + +void WrappedResultSet::construct(const Reference< XResultSet>& _xDriverSet,const ::rtl::OUString& i_sRowSetFilter) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "WrappedResultSet::construct" ); + OCacheSet::construct(_xDriverSet,i_sRowSetFilter); + m_xUpd.set(_xDriverSet,UNO_QUERY_THROW); + m_xRowLocate.set(_xDriverSet,UNO_QUERY_THROW); + m_xUpdRow.set(_xDriverSet,UNO_QUERY_THROW); +} +// ----------------------------------------------------------------------------- +Any SAL_CALL WrappedResultSet::getBookmark() throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "WrappedResultSet::getBookmark" ); + if ( m_xRowLocate.is() ) + { + return m_xRowLocate->getBookmark( ); + } + return makeAny(m_xDriverSet->getRow()); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL WrappedResultSet::moveToBookmark( const Any& bookmark ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "WrappedResultSet::moveToBookmark" ); + return m_xRowLocate->moveToBookmark( bookmark ); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL WrappedResultSet::moveRelativeToBookmark( const Any& bookmark, sal_Int32 rows ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "WrappedResultSet::moveRelativeToBookmark" ); + return m_xRowLocate->moveRelativeToBookmark( bookmark,rows ); +} +// ------------------------------------------------------------------------- +sal_Int32 SAL_CALL WrappedResultSet::compareBookmarks( const Any& _first, const Any& _second ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "WrappedResultSet::compareBookmarks" ); + return m_xRowLocate->compareBookmarks( _first,_second ); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL WrappedResultSet::hasOrderedBookmarks( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "WrappedResultSet::hasOrderedBookmarks" ); + return m_xRowLocate->hasOrderedBookmarks(); +} +// ------------------------------------------------------------------------- +sal_Int32 SAL_CALL WrappedResultSet::hashBookmark( const Any& bookmark ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "WrappedResultSet::hashBookmark" ); + return m_xRowLocate->hashBookmark(bookmark); +} +// ------------------------------------------------------------------------- +// ::com::sun::star::sdbcx::XDeleteRows +Sequence< sal_Int32 > SAL_CALL WrappedResultSet::deleteRows( const Sequence< Any >& rows ,const connectivity::OSQLTable& /*_xTable*/) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "WrappedResultSet::deleteRows" ); + Reference< ::com::sun::star::sdbcx::XDeleteRows> xDeleteRow(m_xRowLocate,UNO_QUERY); + if(xDeleteRow.is()) + { + return xDeleteRow->deleteRows(rows); + } + return Sequence< sal_Int32 >(); +} +// ------------------------------------------------------------------------- +void SAL_CALL WrappedResultSet::insertRow( const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& /*_xTable*/ ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "WrappedResultSet::insertRow" ); + + m_xUpd->moveToInsertRow(); + sal_Int32 i = 1; + connectivity::ORowVector< ORowSetValue > ::Vector::iterator aEnd = _rInsertRow->get().end(); + for(connectivity::ORowVector< ORowSetValue > ::Vector::iterator aIter = _rInsertRow->get().begin()+1;aIter != aEnd;++aIter,++i) + { + aIter->setSigned(m_aSignedFlags[i-1]); + updateColumn(i,m_xUpdRow,*aIter); + } + m_xUpd->insertRow(); + (*_rInsertRow->get().begin()) = getBookmark(); +} +// ------------------------------------------------------------------------- +void SAL_CALL WrappedResultSet::updateRow(const ORowSetRow& _rInsertRow ,const ORowSetRow& _rOrginalRow,const connectivity::OSQLTable& /*_xTable*/ ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "WrappedResultSet::updateRow" ); + sal_Int32 i = 1; + connectivity::ORowVector< ORowSetValue > ::Vector::const_iterator aOrgIter = _rOrginalRow->get().begin()+1; + connectivity::ORowVector< ORowSetValue > ::Vector::iterator aEnd = _rInsertRow->get().end(); + for(connectivity::ORowVector< ORowSetValue > ::Vector::iterator aIter = _rInsertRow->get().begin()+1;aIter != aEnd;++aIter,++i,++aOrgIter) + { + aIter->setSigned(aOrgIter->isSigned()); + updateColumn(i,m_xUpdRow,*aIter); + } + m_xUpd->updateRow(); +} +// ------------------------------------------------------------------------- +void SAL_CALL WrappedResultSet::deleteRow(const ORowSetRow& /*_rDeleteRow*/ ,const connectivity::OSQLTable& /*_xTable*/ ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "WrappedResultSet::deleteRow" ); + m_xUpd->deleteRow(); +} +// ------------------------------------------------------------------------- +void SAL_CALL WrappedResultSet::cancelRowUpdates( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "WrappedResultSet::cancelRowUpdates" ); + m_xUpd->cancelRowUpdates(); +} +// ------------------------------------------------------------------------- +void SAL_CALL WrappedResultSet::moveToInsertRow( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "WrappedResultSet::moveToInsertRow" ); + m_xUpd->moveToInsertRow(); +} +// ------------------------------------------------------------------------- +void SAL_CALL WrappedResultSet::moveToCurrentRow( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "WrappedResultSet::moveToCurrentRow" ); + m_xUpd->moveToCurrentRow(); +} +// ------------------------------------------------------------------------- +void WrappedResultSet::fillValueRow(ORowSetRow& _rRow,sal_Int32 _nPosition) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "WrappedResultSet::fillValueRow" ); + OCacheSet::fillValueRow(_rRow,_nPosition); +} +// ------------------------------------------------------------------------- +void WrappedResultSet::updateColumn(sal_Int32 nPos,Reference< XRowUpdate > _xParameter,const ORowSetValue& _rValue) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "WrappedResultSet::updateColumn" ); + if(_rValue.isBound() && _rValue.isModified()) + { + if(_rValue.isNull()) + _xParameter->updateNull(nPos); + else + { + + switch(_rValue.getTypeKind()) + { + case DataType::DECIMAL: + case DataType::NUMERIC: + _xParameter->updateNumericObject(nPos,_rValue.makeAny(),m_xSetMetaData->getScale(nPos)); + break; + case DataType::CHAR: + case DataType::VARCHAR: + //case DataType::DECIMAL: + //case DataType::NUMERIC: + _xParameter->updateString(nPos,_rValue); + break; + case DataType::BIGINT: + if ( _rValue.isSigned() ) + _xParameter->updateLong(nPos,_rValue); + else + _xParameter->updateString(nPos,_rValue); + break; + case DataType::BIT: + case DataType::BOOLEAN: + _xParameter->updateBoolean(nPos,_rValue); + break; + case DataType::TINYINT: + if ( _rValue.isSigned() ) + _xParameter->updateByte(nPos,_rValue); + else + _xParameter->updateShort(nPos,_rValue); + break; + case DataType::SMALLINT: + if ( _rValue.isSigned() ) + _xParameter->updateShort(nPos,_rValue); + else + _xParameter->updateInt(nPos,_rValue); + break; + case DataType::INTEGER: + if ( _rValue.isSigned() ) + _xParameter->updateInt(nPos,_rValue); + else + _xParameter->updateLong(nPos,_rValue); + break; + case DataType::FLOAT: + _xParameter->updateFloat(nPos,_rValue); + break; + case DataType::DOUBLE: + case DataType::REAL: + _xParameter->updateDouble(nPos,_rValue); + break; + case DataType::DATE: + _xParameter->updateDate(nPos,_rValue); + break; + case DataType::TIME: + _xParameter->updateTime(nPos,_rValue); + break; + case DataType::TIMESTAMP: + _xParameter->updateTimestamp(nPos,_rValue); + break; + case DataType::BINARY: + case DataType::VARBINARY: + case DataType::LONGVARBINARY: + _xParameter->updateBytes(nPos,_rValue); + break; + case DataType::BLOB: + case DataType::CLOB: + _xParameter->updateObject(nPos,_rValue.getAny()); + break; + } + } + } +} + diff --git a/dbaccess/source/core/api/WrappedResultSet.hxx b/dbaccess/source/core/api/WrappedResultSet.hxx new file mode 100644 index 000000000000..082811748e6a --- /dev/null +++ b/dbaccess/source/core/api/WrappedResultSet.hxx @@ -0,0 +1,79 @@ +/************************************************************************* + * + * 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: BookmarkSet.hxx,v $ + * $Revision: 1.11 $ + * + * 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_CORE_API_WRAPPEDRESULTSET_HXX +#define DBACCESS_CORE_API_WRAPPEDRESULTSET_HXX + +#ifndef DBACCESS_CORE_API_CACHESET_HXX +#include "CacheSet.hxx" +#endif +#include <com/sun/star/sdbc/XRowUpdate.hpp> +#include <com/sun/star/sdbc/XResultSetUpdate.hpp> + +namespace dbaccess +{ + // this set is used when we have a bookmarkable set from the driver + class WrappedResultSet : public OCacheSet + { + ::com::sun::star::uno::Reference< ::com::sun::star::sdbcx::XRowLocate> m_xRowLocate; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSetUpdate> m_xUpd; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowUpdate> m_xUpdRow; + + void updateColumn(sal_Int32 nPos,::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowUpdate > _xParameter,const connectivity::ORowSetValue& _rValue); + public: + WrappedResultSet() + {} + ~WrappedResultSet() + { + m_xRowLocate = NULL; + } + + virtual void construct(const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet>& _xDriverSet,const ::rtl::OUString& i_sRowSetFilter); + virtual void fillValueRow(ORowSetRow& _rRow,sal_Int32 _nPosition); + // ::com::sun::star::sdbcx::XRowLocate + virtual ::com::sun::star::uno::Any SAL_CALL getBookmark() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL moveToBookmark( const ::com::sun::star::uno::Any& bookmark ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL moveRelativeToBookmark( const ::com::sun::star::uno::Any& bookmark, sal_Int32 rows ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL compareBookmarks( const ::com::sun::star::uno::Any& first, const ::com::sun::star::uno::Any& second ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL hasOrderedBookmarks( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL hashBookmark( const ::com::sun::star::uno::Any& bookmark ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + // ::com::sun::star::sdbcx::XDeleteRows + virtual ::com::sun::star::uno::Sequence< sal_Int32 > SAL_CALL deleteRows( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& rows ,const connectivity::OSQLTable& _xTable) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + // ::com::sun::star::sdbc::XResultSetUpdate + virtual void SAL_CALL insertRow( const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& _xTable ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateRow(const ORowSetRow& _rInsertRow,const ORowSetRow& _rOrginalRow,const connectivity::OSQLTable& _xTable ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL deleteRow(const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& _xTable ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL cancelRowUpdates( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL moveToInsertRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL moveToCurrentRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + }; +} +#endif // DBACCESS_CORE_API_WRAPPEDRESULTSET_HXX + diff --git a/dbaccess/source/core/api/callablestatement.cxx b/dbaccess/source/core/api/callablestatement.cxx new file mode 100644 index 000000000000..22057ff7a9f6 --- /dev/null +++ b/dbaccess/source/core/api/callablestatement.cxx @@ -0,0 +1,344 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" +#ifndef _DBA_COREAPI_CALLABLESTATEMENT_HXX_ +#include <callablestatement.hxx> +#endif +#ifndef _COM_SUN_STAR_LANG_DISPOSEDEXCEPTION_HPP_ +#include <com/sun/star/lang/DisposedException.hpp> +#endif +#ifndef _CPPUHELPER_TYPEPROVIDER_HXX_ +#include <cppuhelper/typeprovider.hxx> +#endif +#ifndef _COMPHELPER_PROPERTY_HXX_ +#include <comphelper/property.hxx> +#endif +#ifndef _TOOLS_DEBUG_HXX //autogen +#include <tools/debug.hxx> +#endif +#ifndef DBACCESS_SHARED_DBASTRINGS_HRC +#include "dbastrings.hrc" +#endif +#include <rtl/logfile.hxx> + +using namespace dbaccess; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::cppu; +using namespace ::osl; + +// com::sun::star::lang::XTypeProvider +//-------------------------------------------------------------------------- +Sequence< Type > OCallableStatement::getTypes() throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::getTypes" ); + OTypeCollection aTypes(::getCppuType( (const Reference< XRow > *)0 ), + ::getCppuType( (const Reference< XOutParameters > *)0 ), + OPreparedStatement::getTypes() ); + + return aTypes.getTypes(); +} + +//-------------------------------------------------------------------------- +Sequence< sal_Int8 > OCallableStatement::getImplementationId() throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::getImplementationId" ); + static OImplementationId * pId = 0; + if (! pId) + { + MutexGuard aGuard( Mutex::getGlobalMutex() ); + if (! pId) + { + static OImplementationId aId; + pId = &aId; + } + } + return pId->getImplementationId(); +} + +// com::sun::star::uno::XInterface +//-------------------------------------------------------------------------- +Any OCallableStatement::queryInterface( const Type & rType ) throw (RuntimeException) +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::queryInterface" ); + Any aIface = OPreparedStatement::queryInterface( rType ); + if (!aIface.hasValue()) + aIface = ::cppu::queryInterface( + rType, + static_cast< XRow * >( this ), + static_cast< XOutParameters * >( this )); + return aIface; +} + +//-------------------------------------------------------------------------- +void OCallableStatement::acquire() throw () +{ + OPreparedStatement::acquire(); +} + +//-------------------------------------------------------------------------- +void OCallableStatement::release() throw () +{ + OPreparedStatement::release(); +} + +// XServiceInfo +//------------------------------------------------------------------------------ +rtl::OUString OCallableStatement::getImplementationName( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::getImplementationName" ); + return rtl::OUString::createFromAscii("com.sun.star.sdb.OCallableStatement"); +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > OCallableStatement::getSupportedServiceNames( ) throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::getSupportedServiceNames" ); + Sequence< ::rtl::OUString > aSNS( 2 ); + aSNS.getArray()[0] = SERVICE_SDBC_CALLABLESTATEMENT; + aSNS.getArray()[1] = SERVICE_SDB_CALLABLESTATEMENT; + return aSNS; +} + +// XOutParameters +//------------------------------------------------------------------------------ +void SAL_CALL OCallableStatement::registerOutParameter( sal_Int32 parameterIndex, sal_Int32 sqlType, const ::rtl::OUString& typeName ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::registerOutParameter" ); + MutexGuard aGuard(m_aMutex); + + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + + Reference< XOutParameters >(m_xAggregateAsSet, UNO_QUERY)->registerOutParameter( parameterIndex, sqlType, typeName ); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OCallableStatement::registerNumericOutParameter( sal_Int32 parameterIndex, sal_Int32 sqlType, sal_Int32 scale ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::registerNumericOutParameter" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + Reference< XOutParameters >(m_xAggregateAsSet, UNO_QUERY)->registerNumericOutParameter( parameterIndex, sqlType, scale ); +} + +// XRow +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL OCallableStatement::wasNull( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::wasNull" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY)->wasNull(); +} + +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL OCallableStatement::getString( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::getString" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY)->getString( columnIndex ); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL OCallableStatement::getBoolean( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::getBoolean" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY)->getBoolean( columnIndex ); +} + +//------------------------------------------------------------------------------ +sal_Int8 SAL_CALL OCallableStatement::getByte( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::getByte" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY)->getByte( columnIndex ); +} + +//------------------------------------------------------------------------------ +sal_Int16 SAL_CALL OCallableStatement::getShort( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::getShort" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY)->getShort( columnIndex ); +} + +//------------------------------------------------------------------------------ +sal_Int32 SAL_CALL OCallableStatement::getInt( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::getInt" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY)->getInt( columnIndex ); +} + +//------------------------------------------------------------------------------ +sal_Int64 SAL_CALL OCallableStatement::getLong( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::getLong" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY)->getLong( columnIndex ); +} + +//------------------------------------------------------------------------------ +float SAL_CALL OCallableStatement::getFloat( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::getFloat" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY)->getFloat( columnIndex ); +} + +//------------------------------------------------------------------------------ +double SAL_CALL OCallableStatement::getDouble( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::getDouble" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY)->getDouble( columnIndex ); +} + +//------------------------------------------------------------------------------ +Sequence< sal_Int8 > SAL_CALL OCallableStatement::getBytes( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::getBytes" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY)->getBytes( columnIndex ); +} + +//------------------------------------------------------------------------------ +::com::sun::star::util::Date SAL_CALL OCallableStatement::getDate( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::getDate" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY)->getDate( columnIndex ); +} + +//------------------------------------------------------------------------------ +::com::sun::star::util::Time SAL_CALL OCallableStatement::getTime( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::getTime" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY)->getTime( columnIndex ); +} + +//------------------------------------------------------------------------------ +::com::sun::star::util::DateTime SAL_CALL OCallableStatement::getTimestamp( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::getTimestamp" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY)->getTimestamp( columnIndex ); +} + +//------------------------------------------------------------------------------ +Reference< ::com::sun::star::io::XInputStream > SAL_CALL OCallableStatement::getBinaryStream( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::getBinaryStream" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY)->getBinaryStream( columnIndex ); +} + +//------------------------------------------------------------------------------ +Reference< ::com::sun::star::io::XInputStream > SAL_CALL OCallableStatement::getCharacterStream( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::getCharacterStream" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY)->getCharacterStream( columnIndex ); +} + +//------------------------------------------------------------------------------ +Any SAL_CALL OCallableStatement::getObject( sal_Int32 columnIndex, const Reference< ::com::sun::star::container::XNameAccess >& typeMap ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::getObject" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY)->getObject( columnIndex, typeMap ); +} + +//------------------------------------------------------------------------------ +Reference< XRef > SAL_CALL OCallableStatement::getRef( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::getRef" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY)->getRef( columnIndex ); +} + +//------------------------------------------------------------------------------ +Reference< XBlob > SAL_CALL OCallableStatement::getBlob( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::getBlob" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY)->getBlob( columnIndex ); +} + +//------------------------------------------------------------------------------ +Reference< XClob > SAL_CALL OCallableStatement::getClob( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::getClob" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY)->getClob( columnIndex ); +} + +//------------------------------------------------------------------------------ +Reference< XArray > SAL_CALL OCallableStatement::getArray( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::getArray" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY)->getArray( columnIndex ); +} + + diff --git a/dbaccess/source/core/api/column.cxx b/dbaccess/source/core/api/column.cxx new file mode 100644 index 000000000000..292bf5694793 --- /dev/null +++ b/dbaccess/source/core/api/column.cxx @@ -0,0 +1,481 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#include "ContainerMediator.hxx" +#include "apitools.hxx" +#include "column.hxx" +#include "core_resource.hrc" +#include "core_resource.hxx" +#include "dbastrings.hrc" +#include "sdbcoretools.hxx" + +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/sdbc/ColumnValue.hpp> +#include <com/sun/star/sdbc/DataType.hpp> + +#include <comphelper/basicio.hxx> +#include <comphelper/enumhelper.hxx> +#include <comphelper/extract.hxx> +#include <comphelper/property.hxx> +#include <comphelper/seqstream.hxx> +#include <comphelper/sequence.hxx> +#include <comphelper/types.hxx> +#include <connectivity/TTableHelper.hxx> +#include <connectivity/dbexception.hxx> +#include <connectivity/dbtools.hxx> +#include <cppuhelper/typeprovider.hxx> +#include <osl/diagnose.h> +#include <tools/debug.hxx> + +#include <algorithm> + +using namespace dbaccess; +using namespace connectivity; +using namespace connectivity; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::util; +using namespace ::osl; +using namespace ::comphelper; +using namespace ::cppu; + +DBG_NAME(OColumn) + +//============================================================ +//= OColumn +//============================================================ +//-------------------------------------------------------------------------- +OColumn::OColumn( const bool _bNameIsReadOnly ) + :OColumnBase( m_aMutex ) + ,::comphelper::OPropertyContainer( OColumnBase::rBHelper ) +{ + DBG_CTOR(OColumn, NULL); + + registerProperty( PROPERTY_NAME, PROPERTY_ID_NAME, _bNameIsReadOnly ? PropertyAttribute::READONLY : 0, + &m_sName, ::getCppuType( &m_sName ) ); +} + +//-------------------------------------------------------------------------- +OColumn::~OColumn() +{ + DBG_DTOR(OColumn, NULL); +} + +// com::sun::star::lang::XTypeProvider +//-------------------------------------------------------------------------- +Sequence< Type > OColumn::getTypes() throw (RuntimeException) +{ + return ::comphelper::concatSequences( + OColumnBase::getTypes(), + ::comphelper::OPropertyContainer::getTypes() + ); +} + +// com::sun::star::uno::XInterface +IMPLEMENT_FORWARD_XINTERFACE2( OColumn, OColumnBase, ::comphelper::OPropertyContainer ) + +// ::com::sun::star::lang::XServiceInfo +//------------------------------------------------------------------------------ +rtl::OUString OColumn::getImplementationName( ) throw(RuntimeException) +{ + return rtl::OUString::createFromAscii("com.sun.star.sdb.OColumn"); +} + +//------------------------------------------------------------------------------ +sal_Bool OColumn::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException) +{ + return ::comphelper::findValue(getSupportedServiceNames(), _rServiceName, sal_True).getLength() != 0; +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > OColumn::getSupportedServiceNames( ) throw (RuntimeException) +{ + Sequence< ::rtl::OUString > aSNS( 1 ); + aSNS[0] = SERVICE_SDBCX_COLUMN; + return aSNS; +} + +// OComponentHelper +//------------------------------------------------------------------------------ +void OColumn::disposing() +{ + OPropertyContainer::disposing(); +} + +// com::sun::star::beans::XPropertySet +//------------------------------------------------------------------------------ +Reference< XPropertySetInfo > OColumn::getPropertySetInfo() throw (RuntimeException) +{ + return createPropertySetInfo( getInfoHelper() ) ; +} + +// ----------------------------------------------------------------------------- +::rtl::OUString SAL_CALL OColumn::getName( ) throw(::com::sun::star::uno::RuntimeException) +{ + return m_sName; +} +// ----------------------------------------------------------------------------- +void SAL_CALL OColumn::setName( const ::rtl::OUString& _rName ) throw(::com::sun::star::uno::RuntimeException) +{ + m_sName = _rName; +} + +// ----------------------------------------------------------------------------- +void OColumn::fireValueChange(const ::connectivity::ORowSetValue& /*_rOldValue*/) +{ + DBG_ERROR( "OColumn::fireValueChange: not implemented!" ); +} + +//------------------------------------------------------------------------------ +void OColumn::registerProperty( const ::rtl::OUString& _rName, sal_Int32 _nHandle, sal_Int32 _nAttributes, void* _pPointerToMember, const Type& _rMemberType ) +{ + ::comphelper::OPropertyContainer::registerProperty( _rName, _nHandle, _nAttributes, _pPointerToMember, _rMemberType ); +} + +//------------------------------------------------------------------------------ +void OColumn::registerMayBeVoidProperty( const ::rtl::OUString& _rName, sal_Int32 _nHandle, sal_Int32 _nAttributes, Any* _pPointerToMember, const Type& _rExpectedType ) +{ + ::comphelper::OPropertyContainer::registerMayBeVoidProperty( _rName, _nHandle, _nAttributes, _pPointerToMember, _rExpectedType ); +} + +//------------------------------------------------------------------------------ +void OColumn::registerPropertyNoMember( const ::rtl::OUString& _rName, sal_Int32 _nHandle, sal_Int32 _nAttributes, const Type& _rType, const void* _pInitialValue ) +{ + ::comphelper::OPropertyContainer::registerPropertyNoMember( _rName, _nHandle, _nAttributes, _rType, _pInitialValue ); +} + +//============================================================ +//= OColumns +//============================================================ +DBG_NAME(OColumns); + +//-------------------------------------------------------------------------- +OColumns::OColumns(::cppu::OWeakObject& _rParent, + ::osl::Mutex& _rMutex, + sal_Bool _bCaseSensitive,const ::std::vector< ::rtl::OUString> &_rVector, + IColumnFactory* _pColFactory, + ::connectivity::sdbcx::IRefreshableColumns* _pRefresh, + sal_Bool _bAddColumn, + sal_Bool _bDropColumn, + sal_Bool _bUseHardRef) + : OColumns_BASE(_rParent,_bCaseSensitive,_rMutex,_rVector,_bUseHardRef) + ,m_pMediator(NULL) + ,m_xDrvColumns(NULL) + ,m_pColFactoryImpl(_pColFactory) + ,m_pRefreshColumns(_pRefresh) + ,m_bInitialized(sal_False) + ,m_bAddColumn(_bAddColumn) + ,m_bDropColumn(_bDropColumn) +{ + DBG_CTOR(OColumns, NULL); +} + +// ------------------------------------------------------------------------- +OColumns::OColumns(::cppu::OWeakObject& _rParent, ::osl::Mutex& _rMutex, + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& _rxDrvColumns, + sal_Bool _bCaseSensitive,const ::std::vector< ::rtl::OUString> &_rVector, + IColumnFactory* _pColFactory, + ::connectivity::sdbcx::IRefreshableColumns* _pRefresh, + sal_Bool _bAddColumn, + sal_Bool _bDropColumn, + sal_Bool _bUseHardRef) + : OColumns_BASE(_rParent,_bCaseSensitive,_rMutex,_rVector,_bUseHardRef) + ,m_pMediator(NULL) + ,m_xDrvColumns(_rxDrvColumns) + ,m_pColFactoryImpl(_pColFactory) + ,m_pRefreshColumns(_pRefresh) + ,m_bInitialized(sal_False) + ,m_bAddColumn(_bAddColumn) + ,m_bDropColumn(_bDropColumn) +{ + DBG_CTOR(OColumns, NULL); +} +//-------------------------------------------------------------------------- +OColumns::~OColumns() +{ + DBG_DTOR(OColumns, NULL); +} + +// XServiceInfo +//------------------------------------------------------------------------------ +rtl::OUString OColumns::getImplementationName( ) throw(RuntimeException) +{ + return rtl::OUString::createFromAscii("com.sun.star.sdb.OColumns"); +} + +//------------------------------------------------------------------------------ +sal_Bool OColumns::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException) +{ + return ::comphelper::findValue(getSupportedServiceNames(), _rServiceName, sal_True).getLength() != 0; +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > OColumns::getSupportedServiceNames( ) throw (RuntimeException) +{ + Sequence< ::rtl::OUString > aSNS( 1 ); + aSNS[0] = SERVICE_SDBCX_CONTAINER; + return aSNS; +} + +//------------------------------------------------------------------ +void OColumns::append( const ::rtl::OUString& _rName, OColumn* _pColumn ) +{ + MutexGuard aGuard(m_rMutex); + + OSL_ENSURE( _pColumn, "OColumns::append: invalid column!" ); + OSL_ENSURE( !m_pElements->exists( _rName ),"OColumns::append: Column already exists"); + + _pColumn->m_sName = _rName; + + // now really insert the column + insertElement( _rName, _pColumn ); +} + +//------------------------------------------------------------------ +void OColumns::clearColumns() +{ + MutexGuard aGuard(m_rMutex); + disposing(); +} + +// ----------------------------------------------------------------------------- +void SAL_CALL OColumns::disposing(void) +{ + MutexGuard aGuard(m_rMutex); + m_xDrvColumns = NULL; + m_pMediator = NULL; + m_pColFactoryImpl = NULL; + OColumns_BASE::disposing(); +} + +// ------------------------------------------------------------------------- +void OColumns::impl_refresh() throw(::com::sun::star::uno::RuntimeException) +{ + if (m_pRefreshColumns) + m_pRefreshColumns->refreshColumns(); +} + +// ------------------------------------------------------------------------- +connectivity::sdbcx::ObjectType OColumns::createObject(const ::rtl::OUString& _rName) +{ + OSL_ENSURE(m_pColFactoryImpl, "OColumns::createObject: no column factory!"); + + connectivity::sdbcx::ObjectType xRet; + if ( m_pColFactoryImpl ) + { + xRet = m_pColFactoryImpl->createColumn(_rName); + Reference<XChild> xChild(xRet,UNO_QUERY); + if ( xChild.is() ) + xChild->setParent(static_cast<XChild*>(static_cast<TXChild*>(this))); + } + + Reference<XPropertySet> xDest(xRet,UNO_QUERY); + if ( m_pMediator && xDest.is() ) + m_pMediator->notifyElementCreated(_rName,xDest); + + return xRet; +} +// ------------------------------------------------------------------------- +Reference< XPropertySet > OColumns::createDescriptor() +{ + if ( m_pColFactoryImpl ) + { + Reference<XPropertySet> xRet = m_pColFactoryImpl->createColumnDescriptor(); + Reference<XChild> xChild(xRet,UNO_QUERY); + if ( xChild.is() ) + xChild->setParent(static_cast<XChild*>(static_cast<TXChild*>(this))); + return xRet; + } + else + return Reference< XPropertySet >(); +} +// ------------------------------------------------------------------------- +Any SAL_CALL OColumns::queryInterface( const Type & rType ) throw(RuntimeException) +{ + Any aRet; + if(m_xDrvColumns.is()) + { + aRet = m_xDrvColumns->queryInterface(rType); + if ( aRet.hasValue() ) + aRet = OColumns_BASE::queryInterface( rType); + if ( !aRet.hasValue() ) + aRet = TXChild::queryInterface( rType); + return aRet; + } + else if(!m_pTable || (m_pTable && !m_pTable->isNew())) + { + if(!m_bAddColumn && rType == getCppuType( (Reference<XAppend>*)0)) + return Any(); + if(!m_bDropColumn && rType == getCppuType( (Reference<XDrop>*)0)) + return Any(); + } + + aRet = OColumns_BASE::queryInterface( rType); + if ( !aRet.hasValue() ) + aRet = TXChild::queryInterface( rType); + return aRet; +} +// ------------------------------------------------------------------------- +Sequence< Type > SAL_CALL OColumns::getTypes( ) throw(RuntimeException) +{ + sal_Bool bAppendFound = sal_False,bDropFound = sal_False; + + sal_Int32 nSize = 0; + Type aAppendType = getCppuType( (Reference<XAppend>*)0); + Type aDropType = getCppuType( (Reference<XDrop>*)0); + if(m_xDrvColumns.is()) + { + Reference<XTypeProvider> xTypes(m_xDrvColumns,UNO_QUERY); + Sequence< Type > aTypes(xTypes->getTypes()); + + Sequence< Type > aSecTypes(OColumns_BASE::getTypes()); + + + const Type* pBegin = aTypes.getConstArray(); + const Type* pEnd = pBegin + aTypes.getLength(); + for (;pBegin != pEnd ; ++pBegin) + { + if(aAppendType == *pBegin) + bAppendFound = sal_True; + else if(aDropType == *pBegin) + bDropFound = sal_True; + } + nSize = (bDropFound ? (bAppendFound ? 0 : 1) : (bAppendFound ? 1 : 2)); + } + else + { + nSize = ((m_pTable && m_pTable->isNew()) ? 0 : + ((m_bDropColumn ? + (m_bAddColumn ? 0 : 1) : (m_bAddColumn ? 1 : 2)))); + bDropFound = (m_pTable && m_pTable->isNew()) || m_bDropColumn; + bAppendFound = (m_pTable && m_pTable->isNew()) || m_bAddColumn; + } + Sequence< Type > aTypes(::comphelper::concatSequences(OColumns_BASE::getTypes(),TXChild::getTypes())); + Sequence< Type > aRet(aTypes.getLength() - nSize); + + const Type* pBegin = aTypes.getConstArray(); + const Type* pEnd = pBegin + aTypes.getLength(); + for(sal_Int32 i=0;pBegin != pEnd ;++pBegin) + { + if(*pBegin != aAppendType && *pBegin != aDropType) + aRet.getArray()[i++] = *pBegin; + else if(bDropFound && *pBegin == aDropType) + aRet.getArray()[i++] = *pBegin; + else if(bAppendFound && *pBegin == aAppendType) + aRet.getArray()[i++] = *pBegin; + } + return aRet; +} +// ------------------------------------------------------------------------- +// XAppend +sdbcx::ObjectType OColumns::appendObject( const ::rtl::OUString& _rForName, const Reference< XPropertySet >& descriptor ) +{ + sdbcx::ObjectType xReturn; + + Reference< XAppend > xAppend( m_xDrvColumns, UNO_QUERY ); + if ( xAppend.is() ) + { + xAppend->appendByDescriptor(descriptor); + xReturn = createObject( _rForName ); + } + else if ( m_pTable && !m_pTable->isNew() ) + { + if ( m_bAddColumn ) + { + 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)) ); + } + else + xReturn = cloneDescriptor( descriptor ); + + if ( m_pColFactoryImpl ) + m_pColFactoryImpl->columnAppended( descriptor ); + + ::dbaccess::notifyDataSourceModified(m_xParent,sal_True); + + return xReturn; +} +// ------------------------------------------------------------------------- +// XDrop +void OColumns::dropObject(sal_Int32 _nPos,const ::rtl::OUString _sElementName) +{ + Reference< XDrop > xDrop( m_xDrvColumns, UNO_QUERY ); + if ( xDrop.is() ) + { + xDrop->dropByName( _sElementName ); + } + else if ( m_pTable && !m_pTable->isNew() ) + { + if ( m_bDropColumn ) + { + 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)) ); + } + + if ( m_pColFactoryImpl ) + m_pColFactoryImpl->columnDropped(_sElementName); + + ::dbaccess::notifyDataSourceModified(m_xParent,sal_True); +} +// ----------------------------------------------------------------------------- + +Reference< XInterface > SAL_CALL OColumns::getParent( ) throw (RuntimeException) +{ + ::osl::MutexGuard aGuard(m_rMutex); + return m_xParent; +} +// ----------------------------------------------------------------------------- +void SAL_CALL OColumns::setParent( const Reference< XInterface >& _xParent ) throw (NoSupportException, RuntimeException) +{ + ::osl::MutexGuard aGuard(m_rMutex); + m_xParent = _xParent; +} +// ----------------------------------------------------------------------------- diff --git a/dbaccess/source/core/api/columnsettings.cxx b/dbaccess/source/core/api/columnsettings.cxx new file mode 100644 index 000000000000..a88879ca5eb8 --- /dev/null +++ b/dbaccess/source/core/api/columnsettings.cxx @@ -0,0 +1,182 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * +************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#include "columnsettings.hxx" +#include "dbastrings.hrc" + +/** === begin UNO includes === **/ +#include <com/sun/star/beans/PropertyAttribute.hpp> +/** === end UNO includes === **/ + +#include <cppuhelper/typeprovider.hxx> +#include <comphelper/property.hxx> +#include <tools/debug.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::lang::IllegalArgumentException; + using ::com::sun::star::beans::XPropertySet; + using ::com::sun::star::beans::XPropertySetInfo; + /** === end UNO using === **/ + namespace PropertyAttribute = ::com::sun::star::beans::PropertyAttribute; + + //============================================================================== + //= OColumnSettings + //============================================================================== + DBG_NAME( OColumnSettings ) + //------------------------------------------------------------------------------ + OColumnSettings::OColumnSettings() + :m_bHidden(sal_False) + { + DBG_CTOR( OColumnSettings, NULL ); + } + + //------------------------------------------------------------------------------ + OColumnSettings::~OColumnSettings() + { + DBG_DTOR( OColumnSettings, NULL ); + } + + //------------------------------------------------------------------------------ + void OColumnSettings::registerProperties( IPropertyContainer& _rPropertyContainer ) + { + const sal_Int32 nBoundAttr = PropertyAttribute::BOUND; + const sal_Int32 nMayBeVoidAttr = PropertyAttribute::MAYBEVOID | nBoundAttr; + + const Type& rSalInt32Type = ::getCppuType( static_cast< sal_Int32* >( NULL ) ); + const Type& rStringType = ::getCppuType( static_cast< ::rtl::OUString* >( NULL ) ); + + _rPropertyContainer.registerMayBeVoidProperty( PROPERTY_ALIGN, PROPERTY_ID_ALIGN, nMayBeVoidAttr, &m_aAlignment, rSalInt32Type ); + _rPropertyContainer.registerMayBeVoidProperty( PROPERTY_NUMBERFORMAT, PROPERTY_ID_NUMBERFORMAT, nMayBeVoidAttr, &m_aFormatKey, rSalInt32Type ); + _rPropertyContainer.registerMayBeVoidProperty( PROPERTY_RELATIVEPOSITION, PROPERTY_ID_RELATIVEPOSITION, nMayBeVoidAttr, &m_aRelativePosition, rSalInt32Type ); + _rPropertyContainer.registerMayBeVoidProperty( PROPERTY_WIDTH, PROPERTY_ID_WIDTH, nMayBeVoidAttr, &m_aWidth, rSalInt32Type ); + _rPropertyContainer.registerMayBeVoidProperty( PROPERTY_HELPTEXT, PROPERTY_ID_HELPTEXT, nMayBeVoidAttr, &m_aHelpText, rStringType ); + _rPropertyContainer.registerMayBeVoidProperty( PROPERTY_CONTROLDEFAULT, PROPERTY_ID_CONTROLDEFAULT, nMayBeVoidAttr, &m_aControlDefault, rStringType ); + _rPropertyContainer.registerProperty( PROPERTY_CONTROLMODEL, PROPERTY_ID_CONTROLMODEL, nBoundAttr, &m_xControlModel, ::getCppuType( &m_xControlModel ) ); + _rPropertyContainer.registerProperty( PROPERTY_HIDDEN, PROPERTY_ID_HIDDEN, nBoundAttr, &m_bHidden, ::getCppuType( &m_bHidden ) ); + } + + //------------------------------------------------------------------------------ + bool OColumnSettings::isColumnSettingProperty( const sal_Int32 _nPropertyHandle ) + { + return ( _nPropertyHandle == PROPERTY_ID_ALIGN ) + || ( _nPropertyHandle == PROPERTY_ID_NUMBERFORMAT ) + || ( _nPropertyHandle == PROPERTY_ID_RELATIVEPOSITION ) + || ( _nPropertyHandle == PROPERTY_ID_WIDTH ) + || ( _nPropertyHandle == PROPERTY_ID_HELPTEXT ) + || ( _nPropertyHandle == PROPERTY_ID_CONTROLDEFAULT ) + || ( _nPropertyHandle == PROPERTY_ID_CONTROLMODEL ) + || ( _nPropertyHandle == PROPERTY_ID_HIDDEN ); + } + + //------------------------------------------------------------------------------ + bool OColumnSettings::isDefaulted( const sal_Int32 _nPropertyHandle, const Any& _rPropertyValue ) + { + switch ( _nPropertyHandle ) + { + case PROPERTY_ID_ALIGN: + case PROPERTY_ID_NUMBERFORMAT: + case PROPERTY_ID_RELATIVEPOSITION: + case PROPERTY_ID_WIDTH: + case PROPERTY_ID_HELPTEXT: + case PROPERTY_ID_CONTROLDEFAULT: + return !_rPropertyValue.hasValue(); + + case PROPERTY_ID_CONTROLMODEL: + return !Reference< XPropertySet >( _rPropertyValue, UNO_QUERY ).is(); + + case PROPERTY_ID_HIDDEN: + { + sal_Bool bHidden = sal_False; + OSL_VERIFY( _rPropertyValue >>= bHidden ); + return !bHidden; + } + } + OSL_ENSURE( false, "OColumnSettings::isDefaulted: illegal property handle!" ); + return sal_False; + } + + //------------------------------------------------------------------------------ + bool OColumnSettings::hasDefaultSettings( const Reference< XPropertySet >& _rxColumn ) + { + ENSURE_OR_THROW( _rxColumn.is(), "illegal column" ); + try + { + Reference< XPropertySetInfo > xPSI( _rxColumn->getPropertySetInfo(), UNO_SET_THROW ); + + struct PropertyDescriptor + { + ::rtl::OUString sName; + sal_Int32 nHandle; + }; + PropertyDescriptor aProps[] = + { + { PROPERTY_ALIGN, PROPERTY_ID_ALIGN }, + { PROPERTY_NUMBERFORMAT, PROPERTY_ID_NUMBERFORMAT }, + { PROPERTY_RELATIVEPOSITION, PROPERTY_ID_RELATIVEPOSITION }, + { PROPERTY_WIDTH, PROPERTY_ID_WIDTH }, + { PROPERTY_HELPTEXT, PROPERTY_ID_HELPTEXT }, + { PROPERTY_CONTROLDEFAULT, PROPERTY_ID_CONTROLDEFAULT }, + { PROPERTY_CONTROLMODEL, PROPERTY_ID_CONTROLMODEL }, + { PROPERTY_HIDDEN, PROPERTY_ID_HIDDEN } + }; + + for ( size_t i=0; i < sizeof( aProps ) / sizeof( aProps[0] ); ++i ) + { + if ( xPSI->hasPropertyByName( aProps[i].sName ) ) + if ( !isDefaulted( aProps[i].nHandle, _rxColumn->getPropertyValue( aProps[i].sName ) ) ) + return false; + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + return true; + } + +//........................................................................ +} // namespace dbaccess +//........................................................................ diff --git a/dbaccess/source/core/api/datacolumn.cxx b/dbaccess/source/core/api/datacolumn.cxx new file mode 100644 index 000000000000..cb1be701cb99 --- /dev/null +++ b/dbaccess/source/core/api/datacolumn.cxx @@ -0,0 +1,485 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" +#ifndef _DBACORE_DATACOLUMN_HXX_ +#include "datacolumn.hxx" +#endif +#ifndef _COM_SUN_STAR_LANG_DISPOSEDEXCEPTION_HPP_ +#include <com/sun/star/lang/DisposedException.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XRESULTSETMETADATASUPPLIER_HPP_ +#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_DATATYPE_HPP_ +#include <com/sun/star/sdbc/DataType.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_COLUMNVALUE_HPP_ +#include <com/sun/star/sdbc/ColumnValue.hpp> +#endif +#ifndef _CPPUHELPER_TYPEPROVIDER_HXX_ +#include <cppuhelper/typeprovider.hxx> +#endif +#ifndef _TOOLS_DEBUG_HXX +#include <tools/debug.hxx> +#endif +#ifndef DBACCESS_SHARED_DBASTRINGS_HRC +#include "dbastrings.hrc" +#endif +#ifndef _DBASHARED_APITOOLS_HXX_ +#include "apitools.hxx" +#endif + +using namespace dbaccess; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::container; +using namespace ::osl; +using namespace ::comphelper; +using namespace ::cppu; + +DBG_NAME(ODataColumn) +//-------------------------------------------------------------------------- +ODataColumn::ODataColumn( + const Reference < XResultSetMetaData >& _xMetaData, + const Reference < XRow >& _xRow, + const Reference < XRowUpdate >& _xRowUpdate, + sal_Int32 _nPos, + const Reference< XDatabaseMetaData >& _rxDBMeta) + :OResultColumn(_xMetaData, _nPos, _rxDBMeta) + ,m_xRow(_xRow) + ,m_xRowUpdate(_xRowUpdate) +{ + DBG_CTOR(ODataColumn,NULL); +} +// ----------------------------------------------------------------------------- +ODataColumn::~ODataColumn() +{ + DBG_DTOR(ODataColumn,NULL); +} + +// com::sun::star::lang::XTypeProvider +//-------------------------------------------------------------------------- +Sequence< Type > ODataColumn::getTypes() throw (RuntimeException) +{ + OTypeCollection aTypes(::getCppuType( (const Reference< XColumn > *)0 ), + ::getCppuType( (const Reference< XColumnUpdate > *)0 ), + OColumn::getTypes()); + return aTypes.getTypes(); +} + +//-------------------------------------------------------------------------- +Sequence< sal_Int8 > ODataColumn::getImplementationId() throw (RuntimeException) +{ + static OImplementationId * pId = 0; + if (! pId) + { + MutexGuard aGuard( Mutex::getGlobalMutex() ); + if (! pId) + { + static OImplementationId aId; + pId = &aId; + } + } + return pId->getImplementationId(); +} + +//------------------------------------------------------------------------------ +Any SAL_CALL ODataColumn::queryInterface( const Type & _rType ) throw (RuntimeException) +{ + Any aReturn = OResultColumn::queryInterface(_rType); + if (!aReturn.hasValue()) + aReturn = ::cppu::queryInterface(_rType, + static_cast< XColumn* >(this), + static_cast< XColumnUpdate* >(this) + ); + return aReturn; +} + +// XServiceInfo +//------------------------------------------------------------------------------ +rtl::OUString ODataColumn::getImplementationName( ) throw(RuntimeException) +{ + return rtl::OUString::createFromAscii("com.sun.star.sdb.ODataColumn"); +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > ODataColumn::getSupportedServiceNames( ) throw (RuntimeException) +{ + Sequence< ::rtl::OUString > aSNS( 3 ); + aSNS[0] = SERVICE_SDBCX_COLUMN; + aSNS[1] = SERVICE_SDB_RESULTCOLUMN; + aSNS[2] = SERVICE_SDB_DATACOLUMN; + return aSNS; +} + +// OComponentHelper +//------------------------------------------------------------------------------ +void ODataColumn::disposing() +{ + OResultColumn::disposing(); + + m_xRow = NULL; + m_xRowUpdate = NULL; +} + +// ::com::sun::star::sdb::XColumn +//------------------------------------------------------------------------------ +sal_Bool ODataColumn::wasNull(void) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(!m_xRow.is()); + + return m_xRow->wasNull(); +} + +//------------------------------------------------------------------------------ +rtl::OUString ODataColumn::getString(void) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(!m_xRow.is()); + + return m_xRow->getString(m_nPos); +} + +//------------------------------------------------------------------------------ +sal_Bool ODataColumn::getBoolean(void) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(!m_xRow.is()); + + return m_xRow->getBoolean(m_nPos); +} + +//------------------------------------------------------------------------------ +sal_Int8 ODataColumn::getByte(void) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(!m_xRow.is()); + + return m_xRow->getByte(m_nPos); +} + +//------------------------------------------------------------------------------ +sal_Int16 ODataColumn::getShort(void) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(!m_xRow.is()); + + return m_xRow->getShort(m_nPos); +} + +//------------------------------------------------------------------------------ +sal_Int32 ODataColumn::getInt(void) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(!m_xRow.is()); + + return m_xRow->getInt(m_nPos); +} + +//------------------------------------------------------------------------------ +sal_Int64 ODataColumn::getLong(void) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(!m_xRow.is()); + + return m_xRow->getLong(m_nPos); +} + +//------------------------------------------------------------------------------ +float ODataColumn::getFloat(void) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(!m_xRow.is()); + + return m_xRow->getFloat(m_nPos); +} +//------------------------------------------------------------------------------ +double ODataColumn::getDouble(void) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(!m_xRow.is()); + + return m_xRow->getDouble(m_nPos); +} + +//------------------------------------------------------------------------------ +Sequence< sal_Int8 > ODataColumn::getBytes(void) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(!m_xRow.is()); + + return m_xRow->getBytes(m_nPos); +} +//------------------------------------------------------------------------------ +com::sun::star::util::Date ODataColumn::getDate(void) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(!m_xRow.is()); + + return m_xRow->getDate(m_nPos); +} + +//------------------------------------------------------------------------------ +com::sun::star::util::Time ODataColumn::getTime(void) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(!m_xRow.is()); + + return m_xRow->getTime(m_nPos); +} +//------------------------------------------------------------------------------ +com::sun::star::util::DateTime ODataColumn::getTimestamp(void) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(!m_xRow.is()); + + return m_xRow->getTimestamp(m_nPos); +} + +//------------------------------------------------------------------------------ +Reference< ::com::sun::star::io::XInputStream > ODataColumn::getBinaryStream(void) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(!m_xRow.is()); + + return m_xRow->getBinaryStream(m_nPos); +} + +//------------------------------------------------------------------------------ +Reference< ::com::sun::star::io::XInputStream > ODataColumn::getCharacterStream(void) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(!m_xRow.is()); + + return m_xRow->getCharacterStream(m_nPos); +} + +//------------------------------------------------------------------------------ +Any ODataColumn::getObject(const Reference< ::com::sun::star::container::XNameAccess > & typeMap) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(!m_xRow.is()); + + return m_xRow->getObject(m_nPos, typeMap); +} + +//------------------------------------------------------------------------------ +Reference< XRef > ODataColumn::getRef(void) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(!m_xRow.is()); + + return m_xRow->getRef(m_nPos); +} + +//------------------------------------------------------------------------------ +Reference< XBlob > ODataColumn::getBlob(void) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(!m_xRow.is()); + + return m_xRow->getBlob(m_nPos); +} + +//------------------------------------------------------------------------------ +Reference< XClob > ODataColumn::getClob(void) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(!m_xRow.is()); + + return m_xRow->getClob(m_nPos); +} + +//------------------------------------------------------------------------------ +Reference< XArray > ODataColumn::getArray(void) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(!m_xRow.is()); + + return m_xRow->getArray(m_nPos); +} + +// ::com::sun::star::sdb::XColumnUpdate +//------------------------------------------------------------------------------ +void ODataColumn::updateNull(void) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard( m_aMutex ); + ::connectivity::checkDisposed(!m_xRowUpdate.is()); + + m_xRowUpdate->updateNull(m_nPos); +} + +//------------------------------------------------------------------------------ +void ODataColumn::updateBoolean(sal_Bool x) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard( m_aMutex ); + ::connectivity::checkDisposed(!m_xRowUpdate.is()); + + m_xRowUpdate->updateBoolean(m_nPos, x); +} + +//------------------------------------------------------------------------------ +void ODataColumn::updateByte(sal_Int8 x) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard( m_aMutex ); + ::connectivity::checkDisposed(!m_xRowUpdate.is()); + + m_xRowUpdate->updateByte(m_nPos, x); +} + +//------------------------------------------------------------------------------ +void ODataColumn::updateShort(sal_Int16 x) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard( m_aMutex ); + ::connectivity::checkDisposed(!m_xRowUpdate.is()); + + m_xRowUpdate->updateShort(m_nPos, x); +} + +//------------------------------------------------------------------------------ +void ODataColumn::updateInt(sal_Int32 x) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard( m_aMutex ); + ::connectivity::checkDisposed(!m_xRowUpdate.is()); + + m_xRowUpdate->updateInt(m_nPos, x); +} + +//------------------------------------------------------------------------------ +void ODataColumn::updateLong(sal_Int64 x) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard( m_aMutex ); + ::connectivity::checkDisposed(!m_xRowUpdate.is()); + + m_xRowUpdate->updateLong(m_nPos, x); +} + +//------------------------------------------------------------------------------ +void ODataColumn::updateFloat(float x) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard( m_aMutex ); + ::connectivity::checkDisposed(!m_xRowUpdate.is()); + + m_xRowUpdate->updateFloat(m_nPos, x); +} + +//------------------------------------------------------------------------------ +void ODataColumn::updateDouble(double x) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard( m_aMutex ); + ::connectivity::checkDisposed(!m_xRowUpdate.is()); + + m_xRowUpdate->updateDouble(m_nPos, x); +} + +//------------------------------------------------------------------------------ +void ODataColumn::updateString(const rtl::OUString& x) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard( m_aMutex ); + ::connectivity::checkDisposed(!m_xRowUpdate.is()); + + m_xRowUpdate->updateString(m_nPos, x); +} + +//------------------------------------------------------------------------------ +void ODataColumn::updateBytes(const Sequence< sal_Int8 >& x) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard( m_aMutex ); + ::connectivity::checkDisposed(!m_xRowUpdate.is()); + + m_xRowUpdate->updateBytes(m_nPos, x); +} + +//------------------------------------------------------------------------------ +void ODataColumn::updateDate(const com::sun::star::util::Date& x) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard( m_aMutex ); + ::connectivity::checkDisposed(!m_xRowUpdate.is()); + + m_xRowUpdate->updateDate(m_nPos, x); +} + +//------------------------------------------------------------------------------ +void ODataColumn::updateTime(const ::com::sun::star::util::Time& x) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard( m_aMutex ); + ::connectivity::checkDisposed(!m_xRowUpdate.is()); + + m_xRowUpdate->updateTime(m_nPos, x); +} + +//------------------------------------------------------------------------------ +void ODataColumn::updateTimestamp(const ::com::sun::star::util::DateTime& x) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard( m_aMutex ); + ::connectivity::checkDisposed(!m_xRowUpdate.is()); + + m_xRowUpdate->updateTimestamp(m_nPos, x); +} + +//------------------------------------------------------------------------------ +void ODataColumn::updateCharacterStream(const Reference< ::com::sun::star::io::XInputStream > & x, sal_Int32 length) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard( m_aMutex ); + ::connectivity::checkDisposed(!m_xRowUpdate.is()); + + m_xRowUpdate->updateCharacterStream(m_nPos, x, length); +} + +//------------------------------------------------------------------------------ +void ODataColumn::updateBinaryStream(const Reference< ::com::sun::star::io::XInputStream > & x, sal_Int32 length) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard( m_aMutex ); + ::connectivity::checkDisposed(!m_xRowUpdate.is()); + + m_xRowUpdate->updateBinaryStream(m_nPos, x, length); +} + +//------------------------------------------------------------------------------ +void ODataColumn::updateNumericObject(const Any& x, sal_Int32 scale) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard( m_aMutex ); + ::connectivity::checkDisposed(!m_xRowUpdate.is()); + + m_xRowUpdate->updateNumericObject(m_nPos, x, scale); +} + +//------------------------------------------------------------------------------ +void ODataColumn::updateObject(const Any& x) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard( m_aMutex ); + ::connectivity::checkDisposed(!m_xRowUpdate.is()); + + m_xRowUpdate->updateObject(m_nPos, x); +} + diff --git a/dbaccess/source/core/api/datacolumn.hxx b/dbaccess/source/core/api/datacolumn.hxx new file mode 100644 index 000000000000..3c18fd4d830d --- /dev/null +++ b/dbaccess/source/core/api/datacolumn.hxx @@ -0,0 +1,129 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 _DBACORE_DATACOLUMN_HXX_ +#define _DBACORE_DATACOLUMN_HXX_ + +#ifndef _COM_SUN_STAR_SDBC_XROWUPDATE_HPP_ +#include <com/sun/star/sdbc/XRowUpdate.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XROW_HPP_ +#include <com/sun/star/sdbc/XRow.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XRESULTSETMETADATA_HDL_ +#include <com/sun/star/sdbc/XResultSetMetaData.hdl> +#endif +#ifndef _COM_SUN_STAR_SDB_XCOLUMN_HPP_ +#include <com/sun/star/sdb/XColumn.hpp> +#endif +#ifndef _COM_SUN_STAR_SDB_XCOLUMNUPDATE_HPP_ +#include <com/sun/star/sdb/XColumnUpdate.hpp> +#endif +#ifndef _DBA_COREAPI_RESULTCOLUMN_HXX_ +#include <resultcolumn.hxx> +#endif +namespace dbaccess +{ + //************************************************************ + // ODataColumn + //************************************************************ + class ODataColumn : public OResultColumn, + public ::com::sun::star::sdb::XColumn, + public ::com::sun::star::sdb::XColumnUpdate + { + protected: + ::com::sun::star::uno::Reference < ::com::sun::star::sdbc::XRow > m_xRow; + ::com::sun::star::uno::Reference < ::com::sun::star::sdbc::XRowUpdate > m_xRowUpdate; + + virtual ~ODataColumn(); + public: + ODataColumn (const ::com::sun::star::uno::Reference < ::com::sun::star::sdbc::XResultSetMetaData >& _xMetaData, + const ::com::sun::star::uno::Reference < ::com::sun::star::sdbc::XRow >& _xRow, + const ::com::sun::star::uno::Reference < ::com::sun::star::sdbc::XRowUpdate >& _xRowUpdate, + sal_Int32 _nPos, + const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XDatabaseMetaData >& _rxDBMeta); + + // com::sun::star::lang::XTypeProvider + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes() throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() throw (::com::sun::star::uno::RuntimeException); + + // com::sun::star::uno::XInterface + virtual ::com::sun::star::uno::Any SAL_CALL queryInterface( const ::com::sun::star::uno::Type & rType ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL acquire() throw() { OResultColumn::acquire(); } + virtual void SAL_CALL release() throw() { OResultColumn::release(); } + + // ::com::sun::star::lang::XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw(::com::sun::star::uno::RuntimeException); + + // cppu::OComponentHelper + virtual void SAL_CALL disposing(void); + + // ::com::sun::star::sdb::XColumn + virtual sal_Bool SAL_CALL wasNull( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getString( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL getBoolean( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int8 SAL_CALL getByte( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int16 SAL_CALL getShort( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getInt( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int64 SAL_CALL getLong( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual float SAL_CALL getFloat( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual double SAL_CALL getDouble( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getBytes( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::util::Date SAL_CALL getDate( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::util::Time SAL_CALL getTime( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::util::DateTime SAL_CALL getTimestamp( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getBinaryStream( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getCharacterStream( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Any SAL_CALL getObject( const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& typeMap ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRef > SAL_CALL getRef( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XBlob > SAL_CALL getBlob( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XClob > SAL_CALL getClob( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XArray > SAL_CALL getArray( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdb::XColumnUpdate + virtual void SAL_CALL updateNull( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateBoolean( sal_Bool x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateByte( sal_Int8 x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateShort( sal_Int16 x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateInt( sal_Int32 x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateLong( sal_Int64 x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateFloat( float x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateDouble( double x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateString( const ::rtl::OUString& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateBytes( const ::com::sun::star::uno::Sequence< sal_Int8 >& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateDate( const ::com::sun::star::util::Date& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateTime( const ::com::sun::star::util::Time& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateTimestamp( const ::com::sun::star::util::DateTime& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateBinaryStream( const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateCharacterStream( const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateObject( const ::com::sun::star::uno::Any& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateNumericObject( const ::com::sun::star::uno::Any& x, sal_Int32 scale ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + }; +} +#endif // _DBACORE_RESULTCOLUMN_HXX_ + diff --git a/dbaccess/source/core/api/datasettings.cxx b/dbaccess/source/core/api/datasettings.cxx new file mode 100644 index 000000000000..2f5a01fd7004 --- /dev/null +++ b/dbaccess/source/core/api/datasettings.cxx @@ -0,0 +1,254 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#ifndef _DBA_CORE_DATASETTINGS_HXX_ +#include "datasettings.hxx" +#endif +#ifndef _DBASHARED_APITOOLS_HXX_ +#include "apitools.hxx" +#endif +#ifndef DBACCESS_SHARED_DBASTRINGS_HRC +#include "dbastrings.hrc" +#endif +#ifndef _OSL_DIAGNOSE_H_ +#include <osl/diagnose.h> +#endif +#ifndef _COMPHELPER_PROPERTY_HXX_ +#include <comphelper/property.hxx> +#endif +#ifndef _COMPHELPER_TYPES_HXX_ +#include <comphelper/types.hxx> +#endif +#ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBUTE_HPP_ +#include <com/sun/star/beans/PropertyAttribute.hpp> +#endif +#ifndef _SV_SVAPP_HXX +#include <vcl/svapp.hxx> +#endif +#ifndef _COM_SUN_STAR_AWT_FONTWEIGHT_HPP_ +#include <com/sun/star/awt/FontWeight.hpp> +#endif +#ifndef _COM_SUN_STAR_AWT_FONTEMPHASISMARK_HPP_ +#include <com/sun/star/awt/FontEmphasisMark.hpp> +#endif +#ifndef _COM_SUN_STAR_AWT_FONTRELIEF_HPP_ +#include <com/sun/star/awt/FontRelief.hpp> +#endif + +#ifndef _COM_SUN_STAR_AWT_FONTWIDTH_HPP_ +#include <com/sun/star/awt/FontWidth.hpp> +#endif + + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::comphelper; +using namespace ::cppu; + +//........................................................................ +namespace dbaccess +{ +//========================================================================== +//= ODataSettings +//========================================================================== +//-------------------------------------------------------------------------- +void ODataSettings::registerPropertiesFor(ODataSettings_Base* _pItem) +{ + if ( m_bQuery ) + { + registerProperty(PROPERTY_HAVING_CLAUSE, PROPERTY_ID_HAVING_CLAUSE, PropertyAttribute::BOUND, + &_pItem->m_sHavingClause, ::getCppuType(&_pItem->m_sHavingClause)); + + registerProperty(PROPERTY_GROUP_BY, PROPERTY_ID_GROUP_BY, PropertyAttribute::BOUND, + &_pItem->m_sGroupBy, ::getCppuType(&_pItem->m_sGroupBy)); + } + + registerProperty(PROPERTY_FILTER, PROPERTY_ID_FILTER, PropertyAttribute::BOUND, + &_pItem->m_sFilter, ::getCppuType(&_pItem->m_sFilter)); + + registerProperty(PROPERTY_ORDER, PROPERTY_ID_ORDER, PropertyAttribute::BOUND, + &_pItem->m_sOrder, ::getCppuType(&_pItem->m_sOrder)); + + registerProperty(PROPERTY_APPLYFILTER, PROPERTY_ID_APPLYFILTER, PropertyAttribute::BOUND, + &_pItem->m_bApplyFilter, ::getBooleanCppuType()); + + registerProperty(PROPERTY_FONT, PROPERTY_ID_FONT, PropertyAttribute::BOUND, + &_pItem->m_aFont, ::getCppuType(&_pItem->m_aFont)); + + registerMayBeVoidProperty(PROPERTY_ROW_HEIGHT, PROPERTY_ID_ROW_HEIGHT, PropertyAttribute::BOUND | PropertyAttribute::MAYBEVOID, + &_pItem->m_aRowHeight, ::getCppuType(static_cast<sal_Int32*>(NULL))); + + registerMayBeVoidProperty(PROPERTY_TEXTCOLOR, PROPERTY_ID_TEXTCOLOR, PropertyAttribute::BOUND | PropertyAttribute::MAYBEVOID, + &_pItem->m_aTextColor, ::getCppuType(static_cast<sal_Int32*>(NULL))); + + registerMayBeVoidProperty(PROPERTY_TEXTLINECOLOR, PROPERTY_ID_TEXTLINECOLOR, PropertyAttribute::BOUND | PropertyAttribute::MAYBEVOID, + &_pItem->m_aTextLineColor, ::getCppuType(static_cast<sal_Int32*>(NULL))); + + registerProperty(PROPERTY_TEXTEMPHASIS, PROPERTY_ID_TEXTEMPHASIS, PropertyAttribute::BOUND, + &_pItem->m_nFontEmphasis, ::getCppuType(&_pItem->m_nFontEmphasis)); + + registerProperty(PROPERTY_TEXTRELIEF, PROPERTY_ID_TEXTRELIEF, PropertyAttribute::BOUND,&_pItem->m_nFontRelief, ::getCppuType(&_pItem->m_nFontRelief)); + + registerProperty(PROPERTY_FONTNAME, PROPERTY_ID_FONTNAME, PropertyAttribute::BOUND,&_pItem->m_aFont.Name, ::getCppuType(&_pItem->m_aFont.Name)); + registerProperty(PROPERTY_FONTHEIGHT, PROPERTY_ID_FONTHEIGHT, PropertyAttribute::BOUND,&_pItem->m_aFont.Height, ::getCppuType(&_pItem->m_aFont.Height)); + registerProperty(PROPERTY_FONTWIDTH, PROPERTY_ID_FONTWIDTH, PropertyAttribute::BOUND,&_pItem->m_aFont.Width, ::getCppuType(&_pItem->m_aFont.Width)); + registerProperty(PROPERTY_FONTSTYLENAME, PROPERTY_ID_FONTSTYLENAME, PropertyAttribute::BOUND,&_pItem->m_aFont.StyleName, ::getCppuType(&_pItem->m_aFont.StyleName)); + registerProperty(PROPERTY_FONTFAMILY, PROPERTY_ID_FONTFAMILY, PropertyAttribute::BOUND,&_pItem->m_aFont.Family, ::getCppuType(&_pItem->m_aFont.Family)); + registerProperty(PROPERTY_FONTCHARSET, PROPERTY_ID_FONTCHARSET, PropertyAttribute::BOUND,&_pItem->m_aFont.CharSet, ::getCppuType(&_pItem->m_aFont.CharSet)); + registerProperty(PROPERTY_FONTPITCH, PROPERTY_ID_FONTPITCH, PropertyAttribute::BOUND,&_pItem->m_aFont.Pitch, ::getCppuType(&_pItem->m_aFont.Pitch)); + registerProperty(PROPERTY_FONTCHARWIDTH, PROPERTY_ID_FONTCHARWIDTH, PropertyAttribute::BOUND,&_pItem->m_aFont.CharacterWidth, ::getCppuType(&_pItem->m_aFont.CharacterWidth)); + registerProperty(PROPERTY_FONTWEIGHT, PROPERTY_ID_FONTWEIGHT, PropertyAttribute::BOUND,&_pItem->m_aFont.Weight, ::getCppuType(&_pItem->m_aFont.Weight)); + registerProperty(PROPERTY_FONTSLANT, PROPERTY_ID_FONTSLANT, PropertyAttribute::BOUND,&_pItem->m_aFont.Slant, ::getCppuType(&_pItem->m_aFont.Slant)); + registerProperty(PROPERTY_FONTUNDERLINE, PROPERTY_ID_FONTUNDERLINE, PropertyAttribute::BOUND,&_pItem->m_aFont.Underline, ::getCppuType(&_pItem->m_aFont.Underline)); + registerProperty(PROPERTY_FONTSTRIKEOUT, PROPERTY_ID_FONTSTRIKEOUT, PropertyAttribute::BOUND,&_pItem->m_aFont.Strikeout, ::getCppuType(&_pItem->m_aFont.Strikeout)); + registerProperty(PROPERTY_FONTORIENTATION, PROPERTY_ID_FONTORIENTATION, PropertyAttribute::BOUND,&_pItem->m_aFont.Orientation, ::getCppuType(&_pItem->m_aFont.Orientation)); + registerProperty(PROPERTY_FONTKERNING, PROPERTY_ID_FONTKERNING, PropertyAttribute::BOUND,&_pItem->m_aFont.Kerning, ::getCppuType(&_pItem->m_aFont.Kerning)); + registerProperty(PROPERTY_FONTWORDLINEMODE, PROPERTY_ID_FONTWORDLINEMODE,PropertyAttribute::BOUND,&_pItem->m_aFont.WordLineMode, ::getCppuType(&_pItem->m_aFont.WordLineMode)); + registerProperty(PROPERTY_FONTTYPE, PROPERTY_ID_FONTTYPE, PropertyAttribute::BOUND,&_pItem->m_aFont.Type, ::getCppuType(&_pItem->m_aFont.Type)); +} + +//-------------------------------------------------------------------------- +ODataSettings::ODataSettings(OBroadcastHelper& _rBHelper,sal_Bool _bQuery) + :OPropertyStateContainer(_rBHelper) + ,ODataSettings_Base() + ,m_bQuery(_bQuery) +{ +} + +//-------------------------------------------------------------------------- +ODataSettings_Base::ODataSettings_Base() + :m_bApplyFilter(sal_False) + ,m_aFont(::comphelper::getDefaultFont()) + ,m_nFontEmphasis(::com::sun::star::awt::FontEmphasisMark::NONE) + ,m_nFontRelief(::com::sun::star::awt::FontRelief::NONE) +{ +} + +//-------------------------------------------------------------------------- +ODataSettings_Base::ODataSettings_Base(const ODataSettings_Base& _rSource) + :m_sFilter( _rSource.m_sFilter ) + ,m_sHavingClause( _rSource.m_sHavingClause ) + ,m_sGroupBy( _rSource.m_sGroupBy ) + ,m_sOrder( _rSource.m_sOrder ) + ,m_bApplyFilter( _rSource.m_bApplyFilter ) + ,m_aFont( _rSource.m_aFont ) + ,m_aRowHeight( _rSource.m_aRowHeight ) + ,m_aTextColor( _rSource.m_aTextColor ) + ,m_aTextLineColor( _rSource.m_aTextLineColor ) + ,m_nFontEmphasis( _rSource.m_nFontEmphasis ) + ,m_nFontRelief( _rSource.m_nFontRelief ) +{ +} + +// ----------------------------------------------------------------------------- +ODataSettings_Base::~ODataSettings_Base() +{ +} + +// ----------------------------------------------------------------------------- +void ODataSettings::getPropertyDefaultByHandle( sal_Int32 _nHandle, Any& _rDefault ) const +{ + static ::com::sun::star::awt::FontDescriptor aFD = ::comphelper::getDefaultFont(); + switch( _nHandle ) + { + case PROPERTY_ID_HAVING_CLAUSE: + case PROPERTY_ID_GROUP_BY: + case PROPERTY_ID_FILTER: + case PROPERTY_ID_ORDER: + _rDefault <<= ::rtl::OUString(); + break; + case PROPERTY_ID_FONT: + _rDefault <<= ::comphelper::getDefaultFont(); + break; + case PROPERTY_ID_APPLYFILTER: + _rDefault <<= sal_False; + break; + case PROPERTY_ID_TEXTRELIEF: + _rDefault <<= ::com::sun::star::awt::FontRelief::NONE; + break; + case PROPERTY_ID_TEXTEMPHASIS: + _rDefault <<= ::com::sun::star::awt::FontEmphasisMark::NONE; + break; + case PROPERTY_ID_FONTNAME: + _rDefault <<= aFD.Name; + break; + case PROPERTY_ID_FONTHEIGHT: + _rDefault <<= aFD.Height; + break; + case PROPERTY_ID_FONTWIDTH: + _rDefault <<= aFD.Width; + break; + case PROPERTY_ID_FONTSTYLENAME: + _rDefault <<= aFD.StyleName; + break; + case PROPERTY_ID_FONTFAMILY: + _rDefault <<= aFD.Family; + break; + case PROPERTY_ID_FONTCHARSET: + _rDefault <<= aFD.CharSet; + break; + case PROPERTY_ID_FONTPITCH: + _rDefault <<= aFD.Pitch; + break; + case PROPERTY_ID_FONTCHARWIDTH: + _rDefault <<= aFD.CharacterWidth; + break; + case PROPERTY_ID_FONTWEIGHT: + _rDefault <<= aFD.Weight; + break; + case PROPERTY_ID_FONTSLANT: + _rDefault <<= aFD.Slant; + break; + case PROPERTY_ID_FONTUNDERLINE: + _rDefault <<= aFD.Underline; + break; + case PROPERTY_ID_FONTSTRIKEOUT: + _rDefault <<= aFD.Strikeout; + break; + case PROPERTY_ID_FONTORIENTATION: + _rDefault <<= aFD.Orientation; + break; + case PROPERTY_ID_FONTKERNING: + _rDefault <<= aFD.Kerning; + break; + case PROPERTY_ID_FONTWORDLINEMODE: + _rDefault <<= aFD.WordLineMode; + break; + case PROPERTY_ID_FONTTYPE: + _rDefault <<= aFD.Type; + break; + } +} +//........................................................................ +} // namespace dbaccess +//........................................................................ + diff --git a/dbaccess/source/core/api/definitioncolumn.cxx b/dbaccess/source/core/api/definitioncolumn.cxx new file mode 100644 index 000000000000..4620abd661f3 --- /dev/null +++ b/dbaccess/source/core/api/definitioncolumn.cxx @@ -0,0 +1,673 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#include "apitools.hxx" +#include "dbastrings.hrc" +#include "definitioncolumn.hxx" +#include "sdbcoretools.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/sdbcx/XTablesSupplier.hpp> +/** === end UNO includes === **/ + +#include <comphelper/property.hxx> +#include <comphelper/types.hxx> +#include <connectivity/dbtools.hxx> +#include <cppuhelper/typeprovider.hxx> +#include <tools/debug.hxx> +#include <tools/diagnose_ex.h> + +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::container; +using namespace ::cppu; +using namespace ::comphelper; +using namespace ::osl; +using namespace dbaccess; + +#define HAS_DESCRIPTION 0x00000001 +#define HAS_DEFAULTVALUE 0x00000002 +#define HAS_ROWVERSION 0x00000004 +#define HAS_AUTOINCREMENT_CREATION 0x00000008 + +//============================================================ +//= OTableColumnDescriptor +//============================================================ +IMPLEMENT_FORWARD_XINTERFACE2(OTableColumnDescriptor,OColumn,TXChild) + +//------------------------------------------------------------------------------ +void OTableColumnDescriptor::impl_registerProperties() +{ + sal_Int32 nDefaultAttr = m_bActAsDescriptor ? 0 : PropertyAttribute::READONLY; + + registerProperty( PROPERTY_TYPENAME, PROPERTY_ID_TYPENAME, nDefaultAttr, &m_aTypeName, ::getCppuType( &m_aTypeName ) ); + registerProperty( PROPERTY_DESCRIPTION, PROPERTY_ID_DESCRIPTION, nDefaultAttr, &m_aDescription, ::getCppuType( &m_aDescription ) ); + registerProperty( PROPERTY_DEFAULTVALUE, PROPERTY_ID_DEFAULTVALUE, nDefaultAttr, &m_aDefaultValue, ::getCppuType( &m_aDefaultValue ) ); + + if ( m_bActAsDescriptor ) + registerProperty( PROPERTY_AUTOINCREMENTCREATION, PROPERTY_ID_AUTOINCREMENTCREATION, nDefaultAttr, &m_aAutoIncrementValue, ::getCppuType( &m_aAutoIncrementValue ) ); + + registerProperty( PROPERTY_TYPE, PROPERTY_ID_TYPE, nDefaultAttr, &m_nType, ::getCppuType( &m_nType ) ); + registerProperty( PROPERTY_PRECISION, PROPERTY_ID_PRECISION, nDefaultAttr, &m_nPrecision, ::getCppuType( &m_nPrecision ) ); + registerProperty( PROPERTY_SCALE, PROPERTY_ID_SCALE, nDefaultAttr, &m_nScale, ::getCppuType( &m_nScale ) ); + registerProperty( PROPERTY_ISNULLABLE, PROPERTY_ID_ISNULLABLE, nDefaultAttr, &m_nIsNullable, ::getCppuType( &m_nIsNullable ) ); + registerProperty( PROPERTY_ISAUTOINCREMENT, PROPERTY_ID_ISAUTOINCREMENT, nDefaultAttr, &m_bAutoIncrement, ::getCppuType( &m_bAutoIncrement ) ); + registerProperty( PROPERTY_ISROWVERSION, PROPERTY_ID_ISROWVERSION, nDefaultAttr, &m_bRowVersion, ::getCppuType( &m_bRowVersion ) ); + registerProperty( PROPERTY_ISCURRENCY, PROPERTY_ID_ISCURRENCY, nDefaultAttr, &m_bCurrency, ::getCppuType( &m_bCurrency ) ); + + OColumnSettings::registerProperties( *this ); +} + +//-------------------------------------------------------------------------- +IMPLEMENT_GET_IMPLEMENTATION_ID( OTableColumnDescriptor ) + +// ::com::sun::star::lang::XServiceInfo +//------------------------------------------------------------------------------ +rtl::OUString OTableColumnDescriptor::getImplementationName( ) throw (RuntimeException) +{ + return rtl::OUString::createFromAscii("com.sun.star.sdb.OTableColumnDescriptor"); +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > OTableColumnDescriptor::getSupportedServiceNames( ) throw (RuntimeException) +{ + Sequence< ::rtl::OUString > aSNS( 2 ); + aSNS[0] = m_bActAsDescriptor ? SERVICE_SDBCX_COLUMNDESCRIPTOR : SERVICE_SDBCX_COLUMN; + aSNS[1] = SERVICE_SDB_COLUMNSETTINGS; + return aSNS; +} + +// comphelper::OPropertyArrayUsageHelper +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper* OTableColumnDescriptor::createArrayHelper( ) const +{ + Sequence< Property > aProps; + describeProperties( aProps ); + return new ::cppu::OPropertyArrayHelper( aProps ); +} + +// cppu::OPropertySetHelper +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper& OTableColumnDescriptor::getInfoHelper() +{ + return *static_cast< ::comphelper::OPropertyArrayUsageHelper< OTableColumnDescriptor >* >(this)->getArrayHelper(); +} + +//------------------------------------------------------------------------------ +void OTableColumnDescriptor::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue ) throw (Exception) +{ + OColumn::setFastPropertyValue_NoBroadcast( nHandle, rValue ); + ::dbaccess::notifyDataSourceModified( m_xParent, sal_True ); +} + +// ----------------------------------------------------------------------------- +Reference< XInterface > SAL_CALL OTableColumnDescriptor::getParent( ) throw (RuntimeException) +{ + ::osl::MutexGuard aGuard(m_aMutex); + return m_xParent; +} +// ----------------------------------------------------------------------------- +void SAL_CALL OTableColumnDescriptor::setParent( const Reference< XInterface >& _xParent ) throw (NoSupportException, RuntimeException) +{ + ::osl::MutexGuard aGuard(m_aMutex); + m_xParent = _xParent; +} +//============================================================ +//= OTableColumn +//============================================================ +DBG_NAME(OTableColumn); + +// ------------------------------------------------------------------------- +OTableColumn::OTableColumn( const ::rtl::OUString& _rName ) + :OTableColumnDescriptor( false /* do not act as descriptor */ ) +{ + DBG_CTOR(OTableColumn,NULL); + m_sName = _rName; +} + +// ----------------------------------------------------------------------------- +OTableColumn::~OTableColumn() +{ + DBG_DTOR(OTableColumn,NULL); +} + +//-------------------------------------------------------------------------- +IMPLEMENT_GET_IMPLEMENTATION_ID( OTableColumn ) + +//------------------------------------------------------------------------------ +rtl::OUString OTableColumn::getImplementationName( ) throw (RuntimeException) +{ + return rtl::OUString::createFromAscii("com.sun.star.sdb.OTableColumn"); +} + +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper& SAL_CALL OTableColumn::getInfoHelper() +{ + return *OTableColumn_PBase::getArrayHelper(); +} + +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper* OTableColumn::createArrayHelper( ) const +{ + return OTableColumnDescriptor::createArrayHelper(); +} + +// ========================================================================= +//= OQueryColumn +// ========================================================================= +DBG_NAME( OQueryColumn ); + +// ------------------------------------------------------------------------- +OQueryColumn::OQueryColumn( const Reference< XPropertySet >& _rxParserColumn, const Reference< XConnection >& _rxConnection,const ::rtl::OUString i_sLabel ) + :OTableColumnDescriptor( false /* do not act as descriptor */ ) + ,m_sLabel(i_sLabel) +{ + const sal_Int32 nPropAttr = PropertyAttribute::READONLY; + registerProperty( PROPERTY_CATALOGNAME, PROPERTY_ID_CATALOGNAME, nPropAttr, &m_sCatalogName, ::getCppuType( &m_sCatalogName ) ); + registerProperty( PROPERTY_SCHEMANAME, PROPERTY_ID_SCHEMANAME, nPropAttr, &m_sSchemaName, ::getCppuType( &m_sSchemaName ) ); + registerProperty( PROPERTY_TABLENAME, PROPERTY_ID_TABLENAME, nPropAttr, &m_sTableName, ::getCppuType( &m_sTableName ) ); + registerProperty( PROPERTY_REALNAME, PROPERTY_ID_REALNAME, nPropAttr, &m_sRealName, ::getCppuType( &m_sRealName ) ); + registerProperty( PROPERTY_LABEL, PROPERTY_ID_LABEL, nPropAttr, &m_sLabel, ::getCppuType( &m_sLabel ) ); + + DBG_CTOR( OQueryColumn, NULL ); + + OSL_VERIFY( _rxParserColumn->getPropertyValue( PROPERTY_TYPENAME ) >>= m_aTypeName ); + OSL_VERIFY( _rxParserColumn->getPropertyValue( PROPERTY_ISNULLABLE ) >>= m_nIsNullable ); + OSL_VERIFY( _rxParserColumn->getPropertyValue( PROPERTY_PRECISION ) >>= m_nPrecision ); + OSL_VERIFY( _rxParserColumn->getPropertyValue( PROPERTY_SCALE ) >>= m_nScale ); + 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 ); + + m_bRowVersion = sal_False; + + Reference< XPropertySetInfo > xPSI( _rxParserColumn->getPropertySetInfo(), UNO_SET_THROW ); + if ( xPSI->hasPropertyByName( PROPERTY_DEFAULTVALUE ) ) + OSL_VERIFY( _rxParserColumn->getPropertyValue( PROPERTY_DEFAULTVALUE ) >>= m_aDefaultValue ); + + // copy some optional properties from the parser column + struct PropertyDescriptor + { + ::rtl::OUString sName; + sal_Int32 nHandle; + }; + PropertyDescriptor aProps[] = + { + { PROPERTY_CATALOGNAME, PROPERTY_ID_CATALOGNAME }, + { PROPERTY_SCHEMANAME, PROPERTY_ID_SCHEMANAME }, + { PROPERTY_TABLENAME, PROPERTY_ID_TABLENAME }, + { PROPERTY_REALNAME, PROPERTY_ID_REALNAME } + }; + for ( size_t i=0; i < sizeof( aProps ) / sizeof( aProps[0] ); ++i ) + { + if ( xPSI->hasPropertyByName( aProps[i].sName ) ) + setFastPropertyValue_NoBroadcast( aProps[i].nHandle, _rxParserColumn->getPropertyValue( aProps[i].sName ) ); + } + + // determine the table column we're based on + osl_incrementInterlockedCount( &m_refCount ); + { + m_xOriginalTableColumn = impl_determineOriginalTableColumn( _rxConnection ); + } + osl_decrementInterlockedCount( &m_refCount ); +} + +//-------------------------------------------------------------------------- +OQueryColumn::~OQueryColumn() +{ + DBG_DTOR( OQueryColumn, NULL ); +} + +//-------------------------------------------------------------------------- +Reference< XPropertySet > OQueryColumn::impl_determineOriginalTableColumn( const Reference< XConnection >& _rxConnection ) +{ + OSL_PRECOND( _rxConnection.is(), "OQueryColumn::impl_determineOriginalTableColumn: illegal connection!" ); + if ( !_rxConnection.is() ) + return NULL; + + Reference< XPropertySet > xOriginalTableColumn; + try + { + // determine the composed table name, plus the column name, as indicated by the + // respective properties + ::rtl::OUString sCatalog, sSchema, sTable; + OSL_VERIFY( getPropertyValue( PROPERTY_CATALOGNAME ) >>= sCatalog ); + OSL_VERIFY( getPropertyValue( PROPERTY_SCHEMANAME ) >>= sSchema ); + OSL_VERIFY( getPropertyValue( PROPERTY_TABLENAME ) >>= sTable ); + if ( !sCatalog.getLength() && !sSchema.getLength() && !sTable.getLength() ) + return NULL; + + ::rtl::OUString sComposedTableName = ::dbtools::composeTableName( + _rxConnection->getMetaData(), sCatalog, sSchema, sTable, sal_False, ::dbtools::eComplete ); + + // retrieve the table in question + Reference< XTablesSupplier > xSuppTables( _rxConnection, UNO_QUERY_THROW ); + Reference< XNameAccess > xTables( xSuppTables->getTables(), UNO_QUERY_THROW ); + if ( !xTables->hasByName( sComposedTableName ) ) + return NULL; + + Reference< XColumnsSupplier > xSuppCols( xTables->getByName( sComposedTableName ), UNO_QUERY_THROW ); + Reference< XNameAccess > xColumns( xSuppCols->getColumns(), UNO_QUERY_THROW ); + + ::rtl::OUString sColumn; + OSL_VERIFY( getPropertyValue( PROPERTY_REALNAME ) >>= sColumn ); + if ( !xColumns->hasByName( sColumn ) ) + return NULL; + + xOriginalTableColumn.set( xColumns->getByName( sColumn ), UNO_QUERY ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + return xOriginalTableColumn; +} + +//-------------------------------------------------------------------------- +IMPLEMENT_GET_IMPLEMENTATION_ID( OQueryColumn ) + +//-------------------------------------------------------------------------- +::rtl::OUString SAL_CALL OQueryColumn::getImplementationName( ) throw(RuntimeException) +{ + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.comp.dbaccess.OQueryColumn" ) ); +} + +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper& SAL_CALL OQueryColumn::getInfoHelper() +{ + return *OQueryColumn_PBase::getArrayHelper(); +} + +//-------------------------------------------------------------------------- +::cppu::IPropertyArrayHelper* OQueryColumn::createArrayHelper() const +{ + return OTableColumnDescriptor::createArrayHelper(); +} + +//-------------------------------------------------------------------------- +void SAL_CALL OQueryColumn::getFastPropertyValue( Any& _rValue, sal_Int32 _nHandle ) const +{ + OTableColumnDescriptor::getFastPropertyValue( _rValue, _nHandle ); + + // special treatment for column settings: + if ( !OColumnSettings::isColumnSettingProperty( _nHandle ) ) + return; + + // If the setting has its default value, then try to obtain the value from the table column which + // this query column is based on + if ( !OColumnSettings::isDefaulted( _nHandle, _rValue ) ) + return; + + if ( !m_xOriginalTableColumn.is() ) + return; + + try + { + // determine original property name + ::rtl::OUString sPropName; + sal_Int16 nAttributes( 0 ); + const_cast< OQueryColumn* >( this )->getInfoHelper().fillPropertyMembersByHandle( &sPropName, &nAttributes, _nHandle ); + OSL_ENSURE( sPropName.getLength(), "OColumnWrapper::impl_getPropertyNameFromHandle: property not found!" ); + + _rValue = m_xOriginalTableColumn->getPropertyValue( sPropName ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } +} + +//========================================================================== +//= OColumnWrapper +//========================================================================== +DBG_NAME(OColumnWrapper); +//-------------------------------------------------------------------------- +OColumnWrapper::OColumnWrapper( const Reference< XPropertySet > & rCol, const bool _bNameIsReadOnly ) + :OColumn( _bNameIsReadOnly ) + ,m_xAggregate(rCol) + ,m_nColTypeID(-1) +{ + DBG_CTOR(OColumnWrapper,NULL); + // which type of aggregate property do we have? + // we distingish the properties by the containment of optional properties + m_nColTypeID = 0; + if ( m_xAggregate.is() ) + { + Reference <XPropertySetInfo > xInfo(m_xAggregate->getPropertySetInfo()); + m_nColTypeID |= xInfo->hasPropertyByName(PROPERTY_DESCRIPTION) ? HAS_DESCRIPTION : 0; + m_nColTypeID |= xInfo->hasPropertyByName(PROPERTY_DEFAULTVALUE) ? HAS_DEFAULTVALUE : 0; + m_nColTypeID |= xInfo->hasPropertyByName(PROPERTY_ISROWVERSION) ? HAS_ROWVERSION : 0; + m_nColTypeID |= xInfo->hasPropertyByName(PROPERTY_AUTOINCREMENTCREATION) ? HAS_AUTOINCREMENT_CREATION : 0; + + m_xAggregate->getPropertyValue(PROPERTY_NAME) >>= m_sName; + } +} +// ----------------------------------------------------------------------------- +OColumnWrapper::~OColumnWrapper() +{ + DBG_DTOR(OColumnWrapper,NULL); +} + +//------------------------------------------------------------------------------ +::rtl::OUString OColumnWrapper::impl_getPropertyNameFromHandle( const sal_Int32 _nHandle ) const +{ + ::rtl::OUString sPropName; + sal_Int16 nAttributes( 0 ); + const_cast< OColumnWrapper* >( this )->getInfoHelper().fillPropertyMembersByHandle( &sPropName, &nAttributes, _nHandle ); + OSL_ENSURE( sPropName.getLength(), "OColumnWrapper::impl_getPropertyNameFromHandle: property not found!" ); + return sPropName; +} + +//------------------------------------------------------------------------------ +void OColumnWrapper::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const +{ + // derived classes are free to either use the OPropertyContainer(Helper) mechanisms for properties, + // or to declare additional properties which are to be forwarded to the wrapped object. So we need + // to distinguish those cases. + if ( OColumn::isRegisteredProperty( nHandle ) ) + { + OColumn::getFastPropertyValue( rValue, nHandle ); + } + else + { + rValue = m_xAggregate->getPropertyValue( impl_getPropertyNameFromHandle( nHandle ) ); + } +} + +//------------------------------------------------------------------------------ +sal_Bool OColumnWrapper::convertFastPropertyValue( Any & rConvertedValue, Any & rOldValue, sal_Int32 nHandle, + const Any& rValue ) throw (IllegalArgumentException) +{ + sal_Bool bModified( sal_False ); + if ( OColumn::isRegisteredProperty( nHandle ) ) + { + bModified = OColumn::convertFastPropertyValue( rConvertedValue, rOldValue, nHandle, rValue ); + } + else + { + getFastPropertyValue( rOldValue, nHandle ); + if ( rOldValue != rValue ) + { + rConvertedValue = rValue; + bModified = sal_True; + } + } + return bModified; +} + +//------------------------------------------------------------------------------ +void OColumnWrapper::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue ) throw (Exception) +{ + if ( OColumn::isRegisteredProperty( nHandle ) ) + { + OColumn::setFastPropertyValue_NoBroadcast( nHandle, rValue ); + } + else + { + m_xAggregate->setPropertyValue( impl_getPropertyNameFromHandle( nHandle ), rValue ); + } +} + +// ----------------------------------------------------------------------------- +sal_Int64 SAL_CALL OColumnWrapper::getSomething( const Sequence< sal_Int8 >& aIdentifier ) throw(RuntimeException) +{ + Reference< XUnoTunnel > xTunnel( m_xAggregate, UNO_QUERY); + if ( xTunnel.is() ) + return xTunnel->getSomething( aIdentifier ); + return 0; +} + +//============================================================ +//= OTableColumnDescriptorWrapper +//============================================================ +//-------------------------------------------------------------------------- +OTableColumnDescriptorWrapper::OTableColumnDescriptorWrapper( const Reference< XPropertySet >& _rCol, const bool _bPureWrap, const bool _bIsDescriptor ) + :OColumnWrapper( _rCol, !_bIsDescriptor ) + ,m_bPureWrap( _bPureWrap ) + ,m_bIsDescriptor( _bIsDescriptor ) +{ + // let the ColumnSettings register its properties + OColumnSettings::registerProperties( *this ); +} + +// com::sun::star::lang::XTypeProvider +//-------------------------------------------------------------------------- +IMPLEMENT_GET_IMPLEMENTATION_ID( OTableColumnDescriptorWrapper ) + +// ::com::sun::star::lang::XServiceInfo +//------------------------------------------------------------------------------ +rtl::OUString OTableColumnDescriptorWrapper::getImplementationName( ) throw (RuntimeException) +{ + return rtl::OUString::createFromAscii("com.sun.star.sdb.OTableColumnDescriptorWrapper"); +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > OTableColumnDescriptorWrapper::getSupportedServiceNames( ) throw (RuntimeException) +{ + Sequence< ::rtl::OUString > aSNS( 2 ); + aSNS[0] = SERVICE_SDBCX_COLUMNDESCRIPTOR; + aSNS[1] = SERVICE_SDB_COLUMNSETTINGS; + return aSNS; +} + +// comphelper::OPropertyArrayUsageHelper +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper* OTableColumnDescriptorWrapper::createArrayHelper( sal_Int32 nId ) const +{ + const sal_Int32 nHaveAlways = 7; + + // Which optional properties are contained? + sal_Int32 nHaveOptionally = 0; + if (nId & HAS_DESCRIPTION) + ++nHaveOptionally; + if (nId & HAS_DEFAULTVALUE) + ++nHaveOptionally; + if (nId & HAS_ROWVERSION) + ++nHaveOptionally; + if ( nId & HAS_AUTOINCREMENT_CREATION ) + ++nHaveOptionally; + + const sal_Int32 nPropertyCount( nHaveAlways + nHaveOptionally ); + Sequence< Property > aTableDescProperties( nPropertyCount ); + Property* pDesc = aTableDescProperties.getArray(); + sal_Int32 nPos = 0; + + DECL_PROP0_BOOL( ISAUTOINCREMENT ); + DECL_PROP0_BOOL( ISCURRENCY ); + DECL_PROP0( ISNULLABLE, sal_Int32 ); + DECL_PROP0( PRECISION, sal_Int32 ); + DECL_PROP0( SCALE, sal_Int32 ); + DECL_PROP0( TYPE, sal_Int32 ); + DECL_PROP0( TYPENAME, ::rtl::OUString ); + + if ( nId & HAS_AUTOINCREMENT_CREATION ) + { + DECL_PROP1( AUTOINCREMENTCREATION, ::rtl::OUString, MAYBEVOID ); + } + if ( nId & HAS_DEFAULTVALUE ) + { + DECL_PROP0( DEFAULTVALUE, ::rtl::OUString ); + } + if ( nId & HAS_DESCRIPTION ) + { + DECL_PROP0( DESCRIPTION, ::rtl::OUString ); + } + if ( nId & HAS_ROWVERSION ) + { + DECL_PROP0_BOOL( ISROWVERSION ); + } + + OSL_ENSURE( nPos == nPropertyCount, "OTableColumnDescriptorWrapper::createArrayHelper: something went wrong!" ); + + if ( !m_bIsDescriptor ) + { + for ( Property* prop = aTableDescProperties.getArray(); + prop != aTableDescProperties.getArray() + aTableDescProperties.getLength(); + ++prop + ) + { + prop->Attributes |= PropertyAttribute::READONLY; + } + } + + // finally also describe the properties which are maintained by our base class, in particular the OPropertyContainerHelper + Sequence< Property > aBaseProperties; + describeProperties( aBaseProperties ); + + Sequence< Property > aAllProperties( ::comphelper::concatSequences( aTableDescProperties, aBaseProperties ) ); + return new ::cppu::OPropertyArrayHelper( aAllProperties, sal_False ); +} + +// cppu::OPropertySetHelper +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper& OTableColumnDescriptorWrapper::getInfoHelper() +{ + return *static_cast< OIdPropertyArrayUsageHelper< OTableColumnDescriptorWrapper >* >(this)->getArrayHelper(m_nColTypeID); +} + +//------------------------------------------------------------------------------ +void OTableColumnDescriptorWrapper::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const +{ + if ( m_bPureWrap ) + { + rValue = m_xAggregate->getPropertyValue( impl_getPropertyNameFromHandle( nHandle ) ); + } + else + { + OColumnWrapper::getFastPropertyValue( rValue, nHandle ); + } +} + +//------------------------------------------------------------------------------ +sal_Bool OTableColumnDescriptorWrapper::convertFastPropertyValue( Any & rConvertedValue, Any & rOldValue, sal_Int32 nHandle, const Any& rValue ) throw (IllegalArgumentException) +{ + sal_Bool bModified(sal_False); + if ( m_bPureWrap ) + { + // do not delegate to OColumnWrapper: It would, for the properties which were registered with registerProperty, + // ask the OPropertyContainer base class, which is not what we want here. + // TODO: the whole "m_bPureWrap"-thingie is strange. We should have a dedicated class doing this wrapping, + // not a class which normally serves other purposes, and only sometimes does a "pure wrap". It makes the + // code unnecessarily hard to maintain, and error prone. + rOldValue = m_xAggregate->getPropertyValue( impl_getPropertyNameFromHandle( nHandle ) ); + if ( rOldValue != rValue ) + { + rConvertedValue = rValue; + bModified = sal_True; + } + } + else + { + bModified = OColumnWrapper::convertFastPropertyValue( rConvertedValue, rOldValue, nHandle, rValue ); + } + return bModified; +} + +//------------------------------------------------------------------------------ +void OTableColumnDescriptorWrapper::setFastPropertyValue_NoBroadcast( + sal_Int32 nHandle, + const Any& rValue + ) + throw (Exception) +{ + if ( m_bPureWrap ) + { + m_xAggregate->setPropertyValue( impl_getPropertyNameFromHandle( nHandle ), rValue ); + } + else + { + OColumnWrapper::setFastPropertyValue_NoBroadcast( nHandle, rValue ); + } +} + +//============================================================ +//= OTableColumnWrapper +//============================================================ +//-------------------------------------------------------------------------- +OTableColumnWrapper::OTableColumnWrapper( const Reference< XPropertySet >& rCol, const Reference< XPropertySet >& _xColDefintion, + const bool _bPureWrap ) + :OTableColumnDescriptorWrapper( rCol, _bPureWrap, false ) +{ + osl_incrementInterlockedCount( &m_refCount ); + if ( _xColDefintion.is() ) + { + try + { + ::comphelper::copyProperties( _xColDefintion, this ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + osl_decrementInterlockedCount( &m_refCount ); +} + +//-------------------------------------------------------------------------- +OTableColumnWrapper::~OTableColumnWrapper() +{ +} + +//-------------------------------------------------------------------------- +IMPLEMENT_GET_IMPLEMENTATION_ID( OTableColumnWrapper ) + +//------------------------------------------------------------------------------ +rtl::OUString OTableColumnWrapper::getImplementationName( ) throw (RuntimeException) +{ + return rtl::OUString::createFromAscii( "com.sun.star.sdb.OTableColumnWrapper" ); +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > OTableColumnWrapper::getSupportedServiceNames( ) throw (RuntimeException) +{ + Sequence< ::rtl::OUString > aSNS( 2 ); + aSNS[0] = SERVICE_SDBCX_COLUMN; + aSNS[1] = SERVICE_SDB_COLUMNSETTINGS; + return aSNS; +} + +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper& OTableColumnWrapper::getInfoHelper() +{ + return *static_cast< OIdPropertyArrayUsageHelper< OTableColumnWrapper >* >(this)->getArrayHelper(m_nColTypeID); +} + +// comphelper::OPropertyArrayUsageHelper +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper* OTableColumnWrapper::createArrayHelper( sal_Int32 nId ) const +{ + return OTableColumnDescriptorWrapper::createArrayHelper( nId ); +} + diff --git a/dbaccess/source/core/api/makefile.mk b/dbaccess/source/core/api/makefile.mk new file mode 100644 index 000000000000..9a4dc9d8ec52 --- /dev/null +++ b/dbaccess/source/core/api/makefile.mk @@ -0,0 +1,82 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# 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. +# +#************************************************************************* + +PRJ=..$/..$/.. +PRJINC=$(PRJ)$/source +PRJNAME=dbaccess +TARGET=api + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ---------------------------------- + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/util$/dba.pmk + +# --- Files ------------------------------------- +SLOFILES= \ + $(SLO)$/querydescriptor.obj \ + $(SLO)$/FilteredContainer.obj \ + $(SLO)$/TableDeco.obj \ + $(SLO)$/RowSetCacheIterator.obj \ + $(SLO)$/RowSet.obj \ + $(SLO)$/column.obj \ + $(SLO)$/RowSetBase.obj \ + $(SLO)$/CRowSetDataColumn.obj \ + $(SLO)$/CRowSetColumn.obj \ + $(SLO)$/querycomposer.obj \ + $(SLO)$/CIndexes.obj \ + $(SLO)$/BookmarkSet.obj \ + $(SLO)$/KeySet.obj \ + $(SLO)$/StaticSet.obj \ + $(SLO)$/CacheSet.obj \ + $(SLO)$/RowSetCache.obj \ + $(SLO)$/definitioncolumn.obj \ + $(SLO)$/resultcolumn.obj \ + $(SLO)$/datacolumn.obj \ + $(SLO)$/resultset.obj \ + $(SLO)$/statement.obj \ + $(SLO)$/preparedstatement.obj \ + $(SLO)$/callablestatement.obj \ + $(SLO)$/query.obj \ + $(SLO)$/querycontainer.obj \ + $(SLO)$/table.obj \ + $(SLO)$/viewcontainer.obj \ + $(SLO)$/tablecontainer.obj \ + $(SLO)$/SingleSelectQueryComposer.obj \ + $(SLO)$/HelperCollections.obj \ + $(SLO)$/datasettings.obj \ + $(SLO)$/View.obj \ + $(SLO)$/WrappedResultSet.obj \ + $(SLO)$/OptimisticSet.obj \ + $(SLO)$/PrivateRow.obj \ + $(SLO)$/columnsettings.obj + +# --- Targets ---------------------------------- + +.INCLUDE : target.mk + diff --git a/dbaccess/source/core/api/preparedstatement.cxx b/dbaccess/source/core/api/preparedstatement.cxx new file mode 100644 index 000000000000..98c7c1c74b65 --- /dev/null +++ b/dbaccess/source/core/api/preparedstatement.cxx @@ -0,0 +1,473 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#include "dbastrings.hrc" + +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/sdbc/XConnection.hpp> +#include <com/sun/star/sdbc/XDatabaseMetaData.hpp> + +#include <comphelper/property.hxx> +#include <comphelper/sequence.hxx> +#include <cppuhelper/typeprovider.hxx> +#include <preparedstatement.hxx> +#include <resultcolumn.hxx> +#include <resultset.hxx> +#include <tools/debug.hxx> +#include <tools/diagnose_ex.h> + +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::cppu; +using namespace ::osl; +using namespace dbaccess; + +DBG_NAME(OPreparedStatement) + +//-------------------------------------------------------------------------- +OPreparedStatement::OPreparedStatement(const Reference< XConnection > & _xConn, + const Reference< XInterface > & _xStatement) + :OStatementBase(_xConn, _xStatement) +{ + DBG_CTOR(OPreparedStatement, NULL); + m_xAggregateAsParameters = Reference< XParameters >( m_xAggregateAsSet, UNO_QUERY_THROW ); + + Reference<XDatabaseMetaData> xMeta = _xConn->getMetaData(); + m_pColumns = new OColumns(*this, m_aMutex, xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers(),::std::vector< ::rtl::OUString>(), NULL,NULL); +} + +//-------------------------------------------------------------------------- +OPreparedStatement::~OPreparedStatement() +{ + m_pColumns->acquire(); + m_pColumns->disposing(); + delete m_pColumns; + + DBG_DTOR(OPreparedStatement, NULL); +} + +// com::sun::star::lang::XTypeProvider +//-------------------------------------------------------------------------- +Sequence< Type > OPreparedStatement::getTypes() throw (RuntimeException) +{ + OTypeCollection aTypes(::getCppuType( (const Reference< XServiceInfo > *)0 ), + ::getCppuType( (const Reference< XPreparedStatement > *)0 ), + ::getCppuType( (const Reference< XParameters > *)0 ), + ::getCppuType( (const Reference< XResultSetMetaDataSupplier > *)0 ), + ::getCppuType( (const Reference< XColumnsSupplier > *)0 ), + OStatementBase::getTypes() ); + + return aTypes.getTypes(); +} + +//-------------------------------------------------------------------------- +Sequence< sal_Int8 > OPreparedStatement::getImplementationId() throw (RuntimeException) +{ + static OImplementationId * pId = 0; + if (! pId) + { + MutexGuard aGuard( Mutex::getGlobalMutex() ); + if (! pId) + { + static OImplementationId aId; + pId = &aId; + } + } + return pId->getImplementationId(); +} + +// com::sun::star::uno::XInterface +//-------------------------------------------------------------------------- +Any OPreparedStatement::queryInterface( const Type & rType ) throw (RuntimeException) +{ + Any aIface = OStatementBase::queryInterface( rType ); + if (!aIface.hasValue()) + aIface = ::cppu::queryInterface( + rType, + static_cast< XServiceInfo * >( this ), + static_cast< XParameters * >( this ), + static_cast< XColumnsSupplier * >( this ), + static_cast< XResultSetMetaDataSupplier * >( this ), + static_cast< XPreparedBatchExecution * >( this ), + static_cast< XMultipleResults * >( this ), + static_cast< XPreparedStatement * >( this )); + return aIface; +} + +//-------------------------------------------------------------------------- +void OPreparedStatement::acquire() throw () +{ + OStatementBase::acquire(); +} + +//-------------------------------------------------------------------------- +void OPreparedStatement::release() throw () +{ + OStatementBase::release(); +} + +// XServiceInfo +//------------------------------------------------------------------------------ +rtl::OUString OPreparedStatement::getImplementationName( ) throw(RuntimeException) +{ + return rtl::OUString::createFromAscii("com.sun.star.sdb.OPreparedStatement"); +} + +//------------------------------------------------------------------------------ +sal_Bool OPreparedStatement::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException) +{ + return ::comphelper::findValue(getSupportedServiceNames(), _rServiceName, sal_True).getLength() != 0; +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > OPreparedStatement::getSupportedServiceNames( ) throw (RuntimeException) +{ + Sequence< ::rtl::OUString > aSNS( 2 ); + aSNS.getArray()[0] = SERVICE_SDBC_PREPAREDSTATEMENT; + aSNS.getArray()[1] = SERVICE_SDB_PREPAREDSTATMENT; + return aSNS; +} + +// OComponentHelper +//------------------------------------------------------------------------------ +void OPreparedStatement::disposing() +{ + { + MutexGuard aGuard(m_aMutex); + m_pColumns->disposing(); + m_xAggregateAsParameters = NULL; + } + OStatementBase::disposing(); +} + +// ::com::sun::star::sdbcx::XColumnsSupplier +//------------------------------------------------------------------------------ +Reference< ::com::sun::star::container::XNameAccess > OPreparedStatement::getColumns(void) throw( RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + // do we have to populate the columns + if (!m_pColumns->isInitialized()) + { + try + { + Reference< XResultSetMetaDataSupplier > xSuppMeta( m_xAggregateAsSet, UNO_QUERY_THROW ); + Reference< XResultSetMetaData > xMetaData( xSuppMeta->getMetaData(), UNO_SET_THROW ); + + Reference< XConnection > xConn( getConnection(), UNO_SET_THROW ); + Reference< XDatabaseMetaData > xDBMeta( xConn->getMetaData(), UNO_SET_THROW ); + + for (sal_Int32 i = 0, nCount = xMetaData->getColumnCount(); i < nCount; ++i) + { + // retrieve the name of the column + rtl::OUString aName = xMetaData->getColumnName(i + 1); + OResultColumn* pColumn = new OResultColumn(xMetaData, i + 1, xDBMeta); + m_pColumns->append(aName, pColumn); + } + } + catch (const SQLException& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + m_pColumns->setInitialized(); + } + return m_pColumns; +} + +// XResultSetMetaDataSupplier +//------------------------------------------------------------------------------ +Reference< XResultSetMetaData > OPreparedStatement::getMetaData(void) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + return Reference< XResultSetMetaDataSupplier >( m_xAggregateAsSet, UNO_QUERY_THROW )->getMetaData(); +} + +// XPreparedStatement +//------------------------------------------------------------------------------ +Reference< XResultSet > OPreparedStatement::executeQuery() throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + disposeResultSet(); + + Reference< XResultSet > xResultSet; + Reference< XResultSet > xDrvResultSet = Reference< XPreparedStatement >( m_xAggregateAsSet, UNO_QUERY_THROW )->executeQuery(); + if (xDrvResultSet.is()) + { + xResultSet = new OResultSet(xDrvResultSet, *this, m_pColumns->isCaseSensitive()); + + // keep the resultset weak + m_aResultSet = xResultSet; + } + return xResultSet; +} + +//------------------------------------------------------------------------------ +sal_Int32 OPreparedStatement::executeUpdate() throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + disposeResultSet(); + + return Reference< XPreparedStatement >( m_xAggregateAsSet, UNO_QUERY_THROW )->executeUpdate(); +} + +//------------------------------------------------------------------------------ +sal_Bool OPreparedStatement::execute() throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + disposeResultSet(); + + return Reference< XPreparedStatement >( m_xAggregateAsSet, UNO_QUERY_THROW )->execute(); +} + +//------------------------------------------------------------------------------ +Reference< XConnection > OPreparedStatement::getConnection(void) throw( SQLException, RuntimeException ) +{ + return Reference< XConnection > (m_xParent, UNO_QUERY); +} + +// XParameters +//------------------------------------------------------------------------------ +void SAL_CALL OPreparedStatement::setNull( sal_Int32 parameterIndex, sal_Int32 sqlType ) throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + m_xAggregateAsParameters->setNull(parameterIndex, sqlType); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OPreparedStatement::setObjectNull( sal_Int32 parameterIndex, sal_Int32 sqlType, const ::rtl::OUString& typeName ) throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + m_xAggregateAsParameters->setObjectNull(parameterIndex, sqlType, typeName); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OPreparedStatement::setBoolean( sal_Int32 parameterIndex, sal_Bool x ) throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + m_xAggregateAsParameters->setBoolean(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OPreparedStatement::setByte( sal_Int32 parameterIndex, sal_Int8 x ) throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + m_xAggregateAsParameters->setByte(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OPreparedStatement::setShort( sal_Int32 parameterIndex, sal_Int16 x ) throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + m_xAggregateAsParameters->setShort(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OPreparedStatement::setInt( sal_Int32 parameterIndex, sal_Int32 x ) throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + m_xAggregateAsParameters->setInt(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OPreparedStatement::setLong( sal_Int32 parameterIndex, sal_Int64 x ) throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + m_xAggregateAsParameters->setLong(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OPreparedStatement::setFloat( sal_Int32 parameterIndex, float x ) throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + m_xAggregateAsParameters->setFloat(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OPreparedStatement::setDouble( sal_Int32 parameterIndex, double x ) throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + m_xAggregateAsParameters->setDouble(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OPreparedStatement::setString( sal_Int32 parameterIndex, const ::rtl::OUString& x ) throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + m_xAggregateAsParameters->setString(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OPreparedStatement::setBytes( sal_Int32 parameterIndex, const Sequence< sal_Int8 >& x ) throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + m_xAggregateAsParameters->setBytes(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OPreparedStatement::setDate( sal_Int32 parameterIndex, const ::com::sun::star::util::Date& x ) throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + m_xAggregateAsParameters->setDate(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OPreparedStatement::setTime( sal_Int32 parameterIndex, const ::com::sun::star::util::Time& x ) throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + m_xAggregateAsParameters->setTime(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OPreparedStatement::setTimestamp( sal_Int32 parameterIndex, const ::com::sun::star::util::DateTime& x ) throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + m_xAggregateAsParameters->setTimestamp(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OPreparedStatement::setBinaryStream( sal_Int32 parameterIndex, const Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + m_xAggregateAsParameters->setBinaryStream(parameterIndex, x, length); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OPreparedStatement::setCharacterStream( sal_Int32 parameterIndex, const Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + m_xAggregateAsParameters->setCharacterStream(parameterIndex, x, length); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OPreparedStatement::setObject( sal_Int32 parameterIndex, const Any& x ) throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + m_xAggregateAsParameters->setObject(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OPreparedStatement::setObjectWithInfo( sal_Int32 parameterIndex, const Any& x, sal_Int32 targetSqlType, sal_Int32 scale ) throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + m_xAggregateAsParameters->setObjectWithInfo(parameterIndex, x, targetSqlType, scale); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OPreparedStatement::setRef( sal_Int32 parameterIndex, const Reference< XRef >& x ) throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + m_xAggregateAsParameters->setRef(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OPreparedStatement::setBlob( sal_Int32 parameterIndex, const Reference< XBlob >& x ) throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + m_xAggregateAsParameters->setBlob(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OPreparedStatement::setClob( sal_Int32 parameterIndex, const Reference< XClob >& x ) throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + m_xAggregateAsParameters->setClob(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OPreparedStatement::setArray( sal_Int32 parameterIndex, const Reference< XArray >& x ) throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + m_xAggregateAsParameters->setArray(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OPreparedStatement::clearParameters( ) throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + m_xAggregateAsParameters->clearParameters(); +} + diff --git a/dbaccess/source/core/api/query.cxx b/dbaccess/source/core/api/query.cxx new file mode 100644 index 000000000000..f4cc3cf34714 --- /dev/null +++ b/dbaccess/source/core/api/query.cxx @@ -0,0 +1,445 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#ifndef _DBA_COREAPI_QUERY_HXX_ +#include "query.hxx" +#endif +#ifndef DBACCESS_SHARED_DBASTRINGS_HRC +#include "dbastrings.hrc" +#endif +#ifndef DBTOOLS_WARNINGSCONTAINER_HXX +#include <connectivity/warningscontainer.hxx> +#endif +#ifndef DBA_HELPERCOLLECTIONS_HXX +#include "HelperCollections.hxx" +#endif +#ifndef _DBA_CORE_RESOURCE_HXX_ +#include "core_resource.hxx" +#endif +#ifndef _DBA_CORE_RESOURCE_HRC_ +#include "core_resource.hrc" +#endif + +#ifndef _CPPUHELPER_QUERYINTERFACE_HXX_ +#include <cppuhelper/queryinterface.hxx> +#endif +#ifndef _TOOLS_DEBUG_HXX +#include <tools/debug.hxx> +#endif +#ifndef TOOLS_DIAGNOSE_EX_H +#include <tools/diagnose_ex.h> +#endif +#ifndef _COMPHELPER_PROPERTY_AGGREGATION_HXX_ +#include <comphelper/propagg.hxx> +#endif +#ifndef _COMPHELPER_SEQUENCE_HXX_ +#include <comphelper/sequence.hxx> +#endif + +/** === begin UNO includes === **/ +#ifndef _COM_SUN_STAR_SDBC_XCONNECTION_HPP_ +#include <com/sun/star/sdbc/XConnection.hpp> +#endif +#ifndef _COM_SUN_STAR_LANG_DISPOSEDEXCEPTION_HPP_ +#include <com/sun/star/lang/DisposedException.hpp> +#endif +#ifndef _COM_SUN_STAR_SDB_XSINGLESELECTQUERYCOMPOSER_HPP_ +#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XRESULTSETMETADATASUPPLIER_HPP_ +#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp> +#endif +/** === end UNO includes === **/ + +#ifndef _COMPHELPER_TYPES_HXX_ +#include <comphelper/types.hxx> +#endif +#ifndef _COMPHELPER_PROPERTY_HXX_ +#include <comphelper/property.hxx> +#endif +#ifndef UNOTOOLS_INC_SHAREDUNOCOMPONENT_HXX +#include <unotools/sharedunocomponent.hxx> +#endif +#ifndef _DBACORE_DEFINITIONCOLUMN_HXX_ +#include "definitioncolumn.hxx" +#endif + +#include <functional> + +#ifndef DBACORE_SDBCORETOOLS_HXX +#include "sdbcoretools.hxx" +#endif +#ifndef DBACCESS_CORE_API_QUERYCOMPOSER_HXX +#include "querycomposer.hxx" +#endif +#ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBUTE_HPP_ +#include <com/sun/star/beans/PropertyAttribute.hpp> +#endif +#ifndef DBA_CONTAINERMEDIATOR_HXX +#include "ContainerMediator.hxx" +#endif + +using namespace dbaccess; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::comphelper; +using namespace ::osl; +using namespace ::cppu; +using namespace ::utl; + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + +//========================================================================== +//= OQuery +//========================================================================== +DBG_NAME(OQuery) +//-------------------------------------------------------------------------- +OQuery::OQuery( const Reference< XPropertySet >& _rxCommandDefinition + ,const Reference< XConnection >& _rxConn + ,const Reference< XMultiServiceFactory >& _xORB) + :OContentHelper(_xORB,NULL,TContentPtr(new OContentHelper_Impl)) + ,OQueryDescriptor_Base(m_aMutex,*this) + ,ODataSettings(OContentHelper::rBHelper,sal_True) + ,m_xCommandDefinition(_rxCommandDefinition) + ,m_xConnection(_rxConn) + ,m_pColumnMediator( NULL ) + ,m_pWarnings( NULL ) + ,m_bCaseSensitiv(sal_True) + ,m_eDoingCurrently(NONE) +{ + DBG_CTOR(OQuery, NULL); + registerProperties(); + ODataSettings::registerPropertiesFor(this); + + osl_incrementInterlockedCount(&m_refCount); + DBG_ASSERT(m_xCommandDefinition.is(), "OQuery::OQuery : invalid CommandDefinition object !"); + if ( m_xCommandDefinition.is() ) + { + try + { + ::comphelper::copyProperties(_rxCommandDefinition,this); + } + catch(Exception&) + { + OSL_ENSURE(sal_False, "OQueryDescriptor_Base::OQueryDescriptor_Base: caught an exception!"); + } + + m_xCommandDefinition->addPropertyChangeListener(::rtl::OUString(), this); + // m_xCommandDefinition->addPropertyChangeListener(PROPERTY_NAME, this); + m_xCommandPropInfo = m_xCommandDefinition->getPropertySetInfo(); + } + DBG_ASSERT(m_xConnection.is(), "OQuery::OQuery : invalid connection !"); + osl_decrementInterlockedCount(&m_refCount); +} + +//-------------------------------------------------------------------------- +OQuery::~OQuery() +{ + DBG_DTOR(OQuery, NULL); +} +// ----------------------------------------------------------------------------- +IMPLEMENT_IMPLEMENTATION_ID(OQuery); +IMPLEMENT_GETTYPES3(OQuery,OQueryDescriptor_Base,ODataSettings,OContentHelper); +IMPLEMENT_FORWARD_XINTERFACE3( OQuery,OContentHelper,OQueryDescriptor_Base,ODataSettings) +//-------------------------------------------------------------------------- +void OQuery::rebuildColumns() +{ + OSL_PRECOND( getColumnCount() == 0, "OQuery::rebuildColumns: column container should be empty!" ); + // the base class' definition of rebuildColumns promised that clearColumns is called before rebuildColumns + + try + { + m_pColumnMediator = NULL; + + Reference<XColumnsSupplier> xColSup(m_xCommandDefinition,UNO_QUERY); + Reference< XNameAccess > xColumnDefinitions; + if ( xColSup.is() ) + { + xColumnDefinitions = xColSup->getColumns(); + if ( xColumnDefinitions.is() ) + m_pColumnMediator = new OContainerMediator( m_pColumns, xColumnDefinitions, m_xConnection, OContainerMediator::eColumns ); + } + + // fill the columns with columns from the statement + Reference< XMultiServiceFactory > xFactory( m_xConnection, UNO_QUERY_THROW ); + SharedUNOComponent< XSingleSelectQueryComposer, DisposableComponent > xComposer( + Reference< XSingleSelectQueryComposer >( xFactory->createInstance( SERVICE_NAME_SINGLESELECTQUERYCOMPOSER ), UNO_QUERY_THROW ) ); + + Reference< XNameAccess > xColumns; + Reference< XIndexAccess > xColumnsIndexed; + try + { + xComposer->setQuery( m_sCommand ); + Reference< XColumnsSupplier > xCols( xComposer, UNO_QUERY_THROW ); + xColumns.set( xCols->getColumns(), UNO_QUERY_THROW ); + xColumnsIndexed.set( xColumns, UNO_QUERY_THROW ); + } + catch( const SQLException& ) { } + + SharedUNOComponent< XPreparedStatement, DisposableComponent > xPreparedStatement; + if ( !xColumns.is() || ( xColumnsIndexed->getCount() == 0 ) ) + { // the QueryComposer could not parse it. Try a lean version. + xPreparedStatement.set( m_xConnection->prepareStatement( m_sCommand ), UNO_QUERY_THROW ); + Reference< XResultSetMetaDataSupplier > xResMetaDataSup( xPreparedStatement, UNO_QUERY_THROW ); + Reference< XResultSetMetaData > xResultSetMeta( xResMetaDataSup->getMetaData() ); + if ( !xResultSetMeta.is() ) + { + ::rtl::OUString sError( DBA_RES( RID_STR_STATEMENT_WITHOUT_RESULT_SET ) ); + ::dbtools::throwSQLException( sError, SQL_GENERAL_ERROR, *this ); + } + + Reference< XDatabaseMetaData > xDBMeta( m_xConnection->getMetaData(), UNO_QUERY_THROW ); + ::vos::ORef< OSQLColumns > aParseColumns( + ::connectivity::parse::OParseColumn::createColumnsForResultSet( xResultSetMeta, xDBMeta,xColumnDefinitions ) ); + xColumns = OPrivateColumns::createWithIntrinsicNames( + aParseColumns, xDBMeta->storesMixedCaseQuotedIdentifiers(), *this, m_aMutex ); + if ( !xColumns.is() ) + throw RuntimeException(); + } + + Sequence< ::rtl::OUString> aNames = xColumns->getElementNames(); + 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( *pIter ),UNO_QUERY); + ::rtl::OUString sLabel = *pIter; + if ( xColumnDefinitions.is() && xColumnDefinitions->hasByName(*pIter) ) + { + Reference<XPropertySet> xCommandColumn(xColumnDefinitions->getByName( *pIter ),UNO_QUERY); + xCommandColumn->getPropertyValue(PROPERTY_LABEL) >>= sLabel; + } + OQueryColumn* pColumn = new OQueryColumn( xSource, m_xConnection, sLabel); + Reference< XChild > xChild( *pColumn, UNO_QUERY_THROW ); + xChild->setParent( *this ); + + implAppendColumn( *pIter, pColumn ); + Reference< XPropertySet > xDest( *pColumn, UNO_QUERY_THROW ); + if ( m_pColumnMediator.is() ) + m_pColumnMediator->notifyElementCreated( *pIter, xDest ); + } + } + catch( const SQLContext& e ) + { + if ( m_pWarnings ) + m_pWarnings->appendWarning( e ); + } + catch( const SQLWarning& e ) + { + if ( m_pWarnings ) + m_pWarnings->appendWarning( e ); + } + catch( const SQLException& e ) + { + if ( m_pWarnings ) + m_pWarnings->appendWarning( e ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } +} + +// XServiceInfo +//-------------------------------------------------------------------------- +IMPLEMENT_SERVICE_INFO3(OQuery, "com.sun.star.sdb.dbaccess.OQuery", SERVICE_SDB_DATASETTINGS, SERVICE_SDB_QUERY, SERVICE_SDB_QUERYDEFINITION) + +// ::com::sun::star::beans::XPropertyChangeListener +//-------------------------------------------------------------------------- +void SAL_CALL OQuery::propertyChange( const PropertyChangeEvent& _rSource ) throw(RuntimeException) +{ + sal_Int32 nOwnHandle = -1; + { + MutexGuard aGuard(m_aMutex); + + DBG_ASSERT(_rSource.Source.get() == Reference< XInterface >(m_xCommandDefinition, UNO_QUERY).get(), + "OQuery::propertyChange : where did this call come from ?"); + + if (m_eDoingCurrently == SETTING_PROPERTIES) + // we're setting the property ourself, so we will do the neccessary notifications later + return; + + // forward this to our own member holding a copy of the property value + if (getArrayHelper()->hasPropertyByName(_rSource.PropertyName)) + { + Property aOwnProp = getArrayHelper()->getPropertyByName(_rSource.PropertyName); + nOwnHandle = aOwnProp.Handle; + ODataSettings::setFastPropertyValue_NoBroadcast(nOwnHandle, _rSource.NewValue); + // don't use our own setFastPropertyValue_NoBroadcast, this would forward it to the CommandSettings, + // again + // and don't use the "real" setPropertyValue, this is to expensive and not sure to succeed + } + else + { + DBG_ERROR("OQuery::propertyChange : my CommandDefinition has more properties than I do !"); + } + } + + fire(&nOwnHandle, &_rSource.NewValue, &_rSource.OldValue, 1, sal_False); +} + +//-------------------------------------------------------------------------- +void SAL_CALL OQuery::disposing( const EventObject& _rSource ) throw (RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + + (void)_rSource; + DBG_ASSERT(_rSource.Source.get() == Reference< XInterface >(m_xCommandDefinition, UNO_QUERY).get(), + "OQuery::disposing : where did this call come from ?"); + + m_xCommandDefinition->removePropertyChangeListener(::rtl::OUString(), this); + m_xCommandDefinition = NULL; +} + +// XDataDescriptorFactory +//-------------------------------------------------------------------------- +Reference< XPropertySet > SAL_CALL OQuery::createDataDescriptor( ) throw(RuntimeException) +{ + return new OQueryDescriptor(*this); +} + +// pseudo-XComponent +//-------------------------------------------------------------------------- +void SAL_CALL OQuery::disposing() +{ + MutexGuard aGuard(m_aMutex); + if (m_xCommandDefinition.is()) + { + m_xCommandDefinition->removePropertyChangeListener(::rtl::OUString(), this); + m_xCommandDefinition = NULL; + } + disposeColumns(); + + m_pWarnings = NULL; +} + +//-------------------------------------------------------------------------- +void OQuery::setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle, const Any& _rValue ) throw (Exception) +{ + ODataSettings::setFastPropertyValue_NoBroadcast(_nHandle, _rValue); + ::rtl::OUString sAggPropName; + sal_Int16 nAttr = 0; + if (getInfoHelper().fillPropertyMembersByHandle(&sAggPropName,&nAttr,_nHandle) && + m_xCommandPropInfo.is() && + m_xCommandPropInfo->hasPropertyByName(sAggPropName)) + { // the base class holds the property values itself, but we have to forward this to our CommandDefinition + + m_eDoingCurrently = SETTING_PROPERTIES; + OAutoActionReset(this); + m_xCommandDefinition->setPropertyValue(sAggPropName, _rValue); + + if ( PROPERTY_ID_COMMAND == _nHandle ) + // the columns are out of date if we are based on a new statement .... + // 90573 - 16.08.2001 - frank.schoenheit@sun.com + setColumnsOutOfDate(); + } +} + +//-------------------------------------------------------------------------- +Reference< XPropertySetInfo > SAL_CALL OQuery::getPropertySetInfo( ) throw(RuntimeException) +{ + return createPropertySetInfo( getInfoHelper() ) ; +} + +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper& OQuery::getInfoHelper() +{ + return *getArrayHelper(); +} + +//-------------------------------------------------------------------------- +::cppu::IPropertyArrayHelper* OQuery::createArrayHelper( ) const +{ + Sequence< Property > aProps; + // our own props + describeProperties(aProps); + return new ::cppu::OPropertyArrayHelper(aProps); +} +// ----------------------------------------------------------------------------- +OColumn* OQuery::createColumn(const ::rtl::OUString& /*_rName*/) const +{ + return NULL; +} +// ----------------------------------------------------------------------------- +void SAL_CALL OQuery::rename( const ::rtl::OUString& newName ) throw (SQLException, ElementExistException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + Reference<XRename> xRename(m_xCommandDefinition,UNO_QUERY); + OSL_ENSURE(xRename.is(),"No XRename interface!"); + if(xRename.is()) + xRename->rename(newName); +} +// ----------------------------------------------------------------------------- +void OQuery::registerProperties() +{ + // the properties which OCommandBase supplies (it has no own registration, as it's not derived from + // a OPropertyStateContainer) + registerProperty(PROPERTY_NAME, PROPERTY_ID_NAME, PropertyAttribute::BOUND|PropertyAttribute::CONSTRAINED, + &m_sElementName, ::getCppuType(&m_sElementName)); + + registerProperty(PROPERTY_COMMAND, PROPERTY_ID_COMMAND, PropertyAttribute::BOUND, + &m_sCommand, ::getCppuType(&m_sCommand)); + + registerProperty(PROPERTY_ESCAPE_PROCESSING, PROPERTY_ID_ESCAPE_PROCESSING, PropertyAttribute::BOUND, + &m_bEscapeProcessing, ::getBooleanCppuType()); + + registerProperty(PROPERTY_UPDATE_TABLENAME, PROPERTY_ID_UPDATE_TABLENAME, PropertyAttribute::BOUND, + &m_sUpdateTableName, ::getCppuType(&m_sUpdateTableName)); + + registerProperty(PROPERTY_UPDATE_SCHEMANAME, PROPERTY_ID_UPDATE_SCHEMANAME, PropertyAttribute::BOUND, + &m_sUpdateSchemaName, ::getCppuType(&m_sUpdateSchemaName)); + + registerProperty(PROPERTY_UPDATE_CATALOGNAME, PROPERTY_ID_UPDATE_CATALOGNAME, PropertyAttribute::BOUND, + &m_sUpdateCatalogName, ::getCppuType(&m_sUpdateCatalogName)); + + registerProperty(PROPERTY_LAYOUTINFORMATION, PROPERTY_ID_LAYOUTINFORMATION, PropertyAttribute::BOUND, + &m_aLayoutInformation, ::getCppuType(&m_aLayoutInformation)); +} + +// ----------------------------------------------------------------------------- +::rtl::OUString OQuery::determineContentType() const +{ + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "application/vnd.org.openoffice.DatabaseQuery" ) ); +} + +// ----------------------------------------------------------------------------- +//........................................................................ +} // namespace dbaccess +//........................................................................ + diff --git a/dbaccess/source/core/api/query.hxx b/dbaccess/source/core/api/query.hxx new file mode 100644 index 000000000000..81e3a38c7862 --- /dev/null +++ b/dbaccess/source/core/api/query.hxx @@ -0,0 +1,186 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 _DBA_COREAPI_QUERY_HXX_ +#define _DBA_COREAPI_QUERY_HXX_ + +#ifndef _DBA_COREAPI_QUERYDESCRIPTOR_HXX_ +#include "querydescriptor.hxx" +#endif +#ifndef _CPPUHELPER_IMPLBASE3_HXX_ +#include <cppuhelper/implbase3.hxx> +#endif +#ifndef _COM_SUN_STAR_SDBCX_XDATADESCRIPTORFACTORY_HPP_ +#include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp> +#endif +#ifndef _COM_SUN_STAR_BEANS_XPROPERTYCHANGELISTENER_HPP_ +#include <com/sun/star/beans/XPropertyChangeListener.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XCONNECTION_HPP_ +#include <com/sun/star/sdbc/XConnection.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBCX_XRENAME_HPP_ +#include <com/sun/star/sdbcx/XRename.hpp> +#endif +#ifndef DBA_CONTENTHELPER_HXX +#include "ContentHelper.hxx" +#endif + +#include <map> + +namespace dbtools +{ + class IWarningsContainer; +} + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + +//========================================================================== +//= OQuery - an object implementing the sdb.Query service +//========================================================================== +typedef ::cppu::ImplHelper3 < ::com::sun::star::sdbcx::XDataDescriptorFactory, + ::com::sun::star::beans::XPropertyChangeListener, + ::com::sun::star::sdbcx::XRename + > OQuery_Base; +class OQuery; +class OColumn; +typedef ::comphelper::OPropertyArrayUsageHelper< OQuery > OQuery_ArrayHelperBase; + + +class OQuery :public OContentHelper + ,public OQueryDescriptor_Base + ,public OQuery_Base + ,public OQuery_ArrayHelperBase + ,public ODataSettings +{ + friend struct TRelease; + +public: + typedef ::std::map< ::rtl::OUString,OColumn*,::comphelper::UStringMixLess> TNameColumnMap; + +protected: +// TNameColumnMap m_aColumnMap; // contains all columnnames to columns + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > m_xCommandDefinition; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection > m_xConnection; + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > m_xCommandPropInfo; + ::rtl::Reference< OContainerMediator > m_pColumnMediator; + ::dbtools::IWarningsContainer* m_pWarnings; + sal_Bool m_bCaseSensitiv : 1; // assume case sensitivity of the column names ? + + // possible actions on our "aggregate" + enum AGGREGATE_ACTION { NONE, SETTING_PROPERTIES, FLUSHING }; + AGGREGATE_ACTION m_eDoingCurrently; + + // ------------------------------------------------------------------------ + /** a class which automatically resets m_eDoingCurrently in it's destructor + */ + class OAutoActionReset; // just for the following friend declaration + friend class OAutoActionReset; + class OAutoActionReset + { + OQuery* m_pActor; + public: + OAutoActionReset(OQuery* _pActor) : m_pActor(_pActor) { } + ~OAutoActionReset() { m_pActor->m_eDoingCurrently = NONE; } + }; + +protected: + virtual ~OQuery(); + +// OPropertyArrayUsageHelper + virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const; + ::cppu::IPropertyArrayHelper* getArrayHelper() { return OQuery_ArrayHelperBase::getArrayHelper(); } + +public: + OQuery( + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxCommandDefinition, + const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _rxConn, + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _xORB + ); + +// com::sun::star::lang::XTypeProvider + DECLARE_TYPEPROVIDER( ); + +// ::com::sun::star::uno::XInterface + DECLARE_XINTERFACE( ) + +// ::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 ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(); + +// ::com::sun::star::lang::XServiceInfo + DECLARE_SERVICE_INFO(); + +// ::com::sun::star::sdbcx::XDataDescriptorFactory + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > SAL_CALL createDataDescriptor( ) throw(::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::beans::XPropertyChangeListener + virtual void SAL_CALL propertyChange( const ::com::sun::star::beans::PropertyChangeEvent& evt ) throw(::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::lang::XEventListener + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& _rSource ) throw (::com::sun::star::uno::RuntimeException); + +// OPropertySetHelper + virtual void SAL_CALL setFastPropertyValue_NoBroadcast( + sal_Int32 nHandle, + const ::com::sun::star::uno::Any& rValue ) + throw (::com::sun::star::uno::Exception); + +public: + // the caller is responsible for the lifetime! + void setWarningsContainer( ::dbtools::IWarningsContainer* _pWarnings ) { m_pWarnings = _pWarnings; } + ::dbtools::IWarningsContainer* getWarningsContainer( ) const { return m_pWarnings; } + + // XRename + virtual void SAL_CALL rename( const ::rtl::OUString& newName ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::container::ElementExistException, ::com::sun::star::uno::RuntimeException); + +protected: + virtual void SAL_CALL disposing(); + + virtual OColumn* createColumn(const ::rtl::OUString& _rName) const; + + virtual void rebuildColumns( ); + + // OContentHelper overridables + virtual ::rtl::OUString determineContentType() const; + +private: + void registerProperties(); +}; + +//........................................................................ +} // namespace dbaccess +//........................................................................ + +#endif // _DBA_COREAPI_QUERY_HXX_ + + diff --git a/dbaccess/source/core/api/querycomposer.cxx b/dbaccess/source/core/api/querycomposer.cxx new file mode 100644 index 000000000000..ea0a3617e9ba --- /dev/null +++ b/dbaccess/source/core/api/querycomposer.cxx @@ -0,0 +1,406 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#ifndef _COM_SUN_STAR_LANG_DISPOSEDEXCEPTION_HPP_ +#include <com/sun/star/lang/DisposedException.hpp> +#endif +#ifndef _COM_SUN_STAR_UTIL_XNUMBERFORMATTER_HPP_ +#include <com/sun/star/util/XNumberFormatter.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_COLUMNSEARCH_HPP_ +#include <com/sun/star/sdbc/ColumnSearch.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_DATATYPE_HPP_ +#include <com/sun/star/sdbc/DataType.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XRESULTSETMETADATASUPPLIER_HPP_ +#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XRESULTSETMETADATA_HPP_ +#include <com/sun/star/sdbc/XResultSetMetaData.hpp> +#endif +#ifndef _COM_SUN_STAR_LANG_SERVICENOTREGISTEREDEXCEPTION_HPP_ +#include <com/sun/star/lang/ServiceNotRegisteredException.hpp> +#endif +#ifndef _COMPHELPER_SEQUENCE_HXX_ +#include <comphelper/sequence.hxx> +#endif +#ifndef _COM_SUN_STAR_UNO_XAGGREGATION_HPP_ +#include <com/sun/star/uno/XAggregation.hpp> +#endif +#ifndef _COMPHELPER_SEQUENCE_HXX_ +#include <comphelper/sequence.hxx> +#endif +#ifndef _COMPHELPER_PROCESSFACTORY_HXX_ +#include <comphelper/processfactory.hxx> +#endif +#ifndef DBACCESS_SHARED_DBASTRINGS_HRC +#include "dbastrings.hrc" +#endif +#ifndef _CPPUHELPER_TYPEPROVIDER_HXX_ +#include <cppuhelper/typeprovider.hxx> +#endif +#ifndef _UTL_CONFIGMGR_HXX_ +#include <unotools/configmgr.hxx> +#endif +#ifndef _COMPHELPER_TYPES_HXX_ +#include <comphelper/types.hxx> +#endif +#ifndef _TOOLS_DEBUG_HXX +#include <tools/debug.hxx> +#endif +#ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBUTE_HPP_ +#include <com/sun/star/beans/PropertyAttribute.hpp> +#endif +#ifndef _COM_SUN_STAR_I18N_XLOCALEDATA_HPP_ +#include <com/sun/star/i18n/XLocaleData.hpp> +#endif +#ifndef INCLUDED_SVTOOLS_SYSLOCALE_HXX +#include <unotools/syslocale.hxx> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XCHILD_HPP_ +#include <com/sun/star/container/XChild.hpp> +#endif +#include <com/sun/star/sdb/SQLFilterOperator.hpp> +#ifndef DBACCESS_CORE_API_QUERYCOMPOSER_HXX +#include "querycomposer.hxx" +#endif +#ifndef DBA_HELPERCOLLECTIONS_HXX +#include "HelperCollections.hxx" +#endif +#ifndef DBACCESS_SOURCE_CORE_INC_COMPOSERTOOLS_HXX +#include "composertools.hxx" +#endif +#include <algorithm> +#include <rtl/logfile.hxx> + +using namespace dbaccess; +using namespace dbtools; +using namespace comphelper; +using namespace connectivity; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::i18n; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::script; +using namespace ::cppu; +using namespace ::osl; +using namespace ::utl; + + +DBG_NAME(OQueryComposer) +// ------------------------------------------------------------------------- +OQueryComposer::OQueryComposer(const Reference< XConnection>& _xConnection) + : OSubComponent(m_aMutex,_xConnection) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OQueryComposer::OQueryComposer" ); + DBG_CTOR(OQueryComposer,NULL); + OSL_ENSURE(_xConnection.is()," Connection cant be null!"); + + Reference<XMultiServiceFactory> xFac( _xConnection, UNO_QUERY_THROW ); + m_xComposer.set( xFac->createInstance( SERVICE_NAME_SINGLESELECTQUERYCOMPOSER ), UNO_QUERY_THROW ); + m_xComposerHelper.set( xFac->createInstance( SERVICE_NAME_SINGLESELECTQUERYCOMPOSER ), UNO_QUERY_THROW ); +} +// ------------------------------------------------------------------------- +OQueryComposer::~OQueryComposer() +{ + DBG_DTOR(OQueryComposer,NULL); +} +// ----------------------------------------------------------------------------- +void SAL_CALL OQueryComposer::disposing() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OQueryComposer::disposing" ); + ::comphelper::disposeComponent(m_xComposerHelper); + ::comphelper::disposeComponent(m_xComposer); +} +// ------------------------------------------------------------------------- +// ::com::sun::star::lang::XTypeProvider +Sequence< Type > SAL_CALL OQueryComposer::getTypes() throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OQueryComposer::getTypes" ); + return ::comphelper::concatSequences(OSubComponent::getTypes(),OQueryComposer_BASE::getTypes()); +} +// ------------------------------------------------------------------------- +Sequence< sal_Int8 > SAL_CALL OQueryComposer::getImplementationId() throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OQueryComposer::getImplementationId" ); + static OImplementationId * pId = 0; + if (! pId) + { + MutexGuard aGuard( Mutex::getGlobalMutex() ); + if (! pId) + { + static OImplementationId aId; + pId = &aId; + } + } + return pId->getImplementationId(); +} +// ------------------------------------------------------------------------- +// com::sun::star::lang::XUnoTunnel +sal_Int64 SAL_CALL OQueryComposer::getSomething( const Sequence< sal_Int8 >& rId ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OQueryComposer::getSomething" ); + if (rId.getLength() == 16 && 0 == rtl_compareMemory(getImplementationId().getConstArray(), rId.getConstArray(), 16 ) ) + return reinterpret_cast<sal_Int64>(this); + + return 0; +} +// ------------------------------------------------------------------------- +Any SAL_CALL OQueryComposer::queryInterface( const Type & rType ) throw(RuntimeException) +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OQueryComposer::queryInterface" ); + Any aRet = OSubComponent::queryInterface(rType); + if(!aRet.hasValue()) + aRet = OQueryComposer_BASE::queryInterface(rType); + return aRet; +} +// ------------------------------------------------------------------------- +// XServiceInfo +//------------------------------------------------------------------------------ +rtl::OUString OQueryComposer::getImplementationName( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OQueryComposer::getImplementationName" ); + return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sdb.dbaccess.OQueryComposer")); +} +//------------------------------------------------------------------------------ +sal_Bool OQueryComposer::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OQueryComposer::supportsService" ); + return ::comphelper::findValue(getSupportedServiceNames(), _rServiceName, sal_True).getLength() != 0; +} +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > OQueryComposer::getSupportedServiceNames( ) throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OQueryComposer::getSupportedServiceNames" ); + Sequence< rtl::OUString > aSNS( 1 ); + aSNS[0] = SERVICE_SDB_SQLQUERYCOMPOSER; + return aSNS; +} +// ------------------------------------------------------------------------- +// XSQLQueryComposer +::rtl::OUString SAL_CALL OQueryComposer::getQuery( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OQueryComposer::getQuery" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( m_aMutex ); + Reference<XPropertySet> xProp(m_xComposer,UNO_QUERY); + ::rtl::OUString sQuery; + if ( xProp.is() ) + xProp->getPropertyValue(PROPERTY_ORIGINAL) >>= sQuery; + return sQuery; +} +// ------------------------------------------------------------------------- +void SAL_CALL OQueryComposer::setQuery( const ::rtl::OUString& command ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OQueryComposer::setQuery" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( m_aMutex ); + m_aFilters.clear(); + m_xComposer->setQuery(command); + m_sOrgFilter = m_xComposer->getFilter(); + m_sOrgOrder = m_xComposer->getOrder(); +} +// ------------------------------------------------------------------------- +::rtl::OUString SAL_CALL OQueryComposer::getComposedQuery( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OQueryComposer::getComposedQuery" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + + MutexGuard aGuard(m_aMutex); + + return m_xComposer->getQuery(); +} +// ------------------------------------------------------------------------- +::rtl::OUString SAL_CALL OQueryComposer::getFilter( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OQueryComposer::getFilter" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + MutexGuard aGuard(m_aMutex); + FilterCreator aFilterCreator; + aFilterCreator = ::std::for_each(m_aFilters.begin(),m_aFilters.end(),aFilterCreator); + return aFilterCreator.getComposedAndClear(); +} +// ------------------------------------------------------------------------- +Sequence< Sequence< PropertyValue > > SAL_CALL OQueryComposer::getStructuredFilter( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OQueryComposer::getStructuredFilter" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + + MutexGuard aGuard(m_aMutex); + return m_xComposer->getStructuredFilter(); +} +// ------------------------------------------------------------------------- +::rtl::OUString SAL_CALL OQueryComposer::getOrder( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OQueryComposer::getOrder" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( m_aMutex ); + OrderCreator aOrderCreator; + aOrderCreator = ::std::for_each(m_aOrders.begin(),m_aOrders.end(),aOrderCreator); + return aOrderCreator.getComposedAndClear(); +} +// ----------------------------------------------------------------------------- +void SAL_CALL OQueryComposer::appendFilterByColumn( const Reference< XPropertySet >& column ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OQueryComposer::appendFilterByColumn" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + ::osl::MutexGuard aGuard( m_aMutex ); + + m_xComposerHelper->setQuery(getQuery()); + m_xComposerHelper->setFilter(::rtl::OUString()); + sal_Int32 nOp = SQLFilterOperator::EQUAL; + if ( column.is() ) + { + sal_Int32 nType = 0; + column->getPropertyValue(PROPERTY_TYPE) >>= nType; + switch(nType) + { + case DataType::VARCHAR: + case DataType::CHAR: + case DataType::LONGVARCHAR: + nOp = SQLFilterOperator::LIKE; + break; + default: + nOp = SQLFilterOperator::EQUAL; + } + } + m_xComposerHelper->appendFilterByColumn(column,sal_True,nOp); + + FilterCreator aFilterCreator; + aFilterCreator.append(getFilter()); + aFilterCreator.append(m_xComposerHelper->getFilter()); + + setFilter( aFilterCreator.getComposedAndClear() ); +} +// ------------------------------------------------------------------------- +void SAL_CALL OQueryComposer::appendOrderByColumn( const Reference< XPropertySet >& column, sal_Bool ascending ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OQueryComposer::appendOrderByColumn" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + ::osl::MutexGuard aGuard( m_aMutex ); + + m_xComposerHelper->setQuery(getQuery()); + m_xComposerHelper->setOrder(::rtl::OUString()); + m_xComposerHelper->appendOrderByColumn(column,ascending); + + OrderCreator aOrderCreator; + aOrderCreator.append(getOrder()); + aOrderCreator.append(m_xComposerHelper->getOrder()); + + setOrder(aOrderCreator.getComposedAndClear()); +} +// ------------------------------------------------------------------------- +void SAL_CALL OQueryComposer::setFilter( const ::rtl::OUString& filter ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OQueryComposer::setFilter" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( m_aMutex ); + FilterCreator aFilterCreator; + aFilterCreator.append(m_sOrgFilter); + aFilterCreator.append(filter); + + m_aFilters.clear(); + if ( filter.getLength() ) + m_aFilters.push_back(filter); + + m_xComposer->setFilter( aFilterCreator.getComposedAndClear() ); +} +// ------------------------------------------------------------------------- +void SAL_CALL OQueryComposer::setOrder( const ::rtl::OUString& order ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OQueryComposer::setOrder" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( m_aMutex ); + + OrderCreator aOrderCreator; + aOrderCreator.append(m_sOrgOrder); + aOrderCreator.append(order); + + m_aOrders.clear(); + if ( order.getLength() ) + m_aOrders.push_back(order); + + m_xComposer->setOrder(aOrderCreator.getComposedAndClear()); +} +// ------------------------------------------------------------------------- +// XTablesSupplier +Reference< XNameAccess > SAL_CALL OQueryComposer::getTables( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OQueryComposer::getTables" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( m_aMutex ); + return Reference<XTablesSupplier>(m_xComposer,UNO_QUERY)->getTables(); +} +// ------------------------------------------------------------------------- +// XColumnsSupplier +Reference< XNameAccess > SAL_CALL OQueryComposer::getColumns( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OQueryComposer::getColumns" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( m_aMutex ); + return Reference<XColumnsSupplier>(m_xComposer,UNO_QUERY)->getColumns(); +} +// ------------------------------------------------------------------------- +Reference< XIndexAccess > SAL_CALL OQueryComposer::getParameters( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OQueryComposer::getParameters" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( m_aMutex ); + return Reference<XParametersSupplier>(m_xComposer,UNO_QUERY)->getParameters(); +} +// ----------------------------------------------------------------------------- +void SAL_CALL OQueryComposer::acquire() throw() +{ + OSubComponent::acquire(); +} +// ----------------------------------------------------------------------------- +void SAL_CALL OQueryComposer::release() throw() +{ + OSubComponent::release(); +} +// ----------------------------------------------------------------------------- + + + + + diff --git a/dbaccess/source/core/api/querycontainer.cxx b/dbaccess/source/core/api/querycontainer.cxx new file mode 100644 index 000000000000..043912259aff --- /dev/null +++ b/dbaccess/source/core/api/querycontainer.cxx @@ -0,0 +1,475 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#ifndef _DBA_CORE_QUERYCONTAINER_HXX_ +#include "querycontainer.hxx" +#endif +#ifndef DBACCESS_SHARED_DBASTRINGS_HRC +#include "dbastrings.hrc" +#endif +#ifndef _DBA_COREAPI_QUERY_HXX_ +#include "query.hxx" +#endif +#ifndef DBACCESS_OBJECTNAMEAPPROVAL_HXX +#include "objectnameapproval.hxx" +#endif +#ifndef DBA_CONTAINERLISTENER_HXX +#include "ContainerListener.hxx" +#endif +#ifndef DBACCESS_VETO_HXX +#include "veto.hxx" +#endif + +/** === begin UNO includes === **/ +#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_ +#include <com/sun/star/beans/XPropertySet.hpp> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XCONTAINER_HPP_ +#include <com/sun/star/container/XContainer.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XCONNECTION_HPP_ +#include <com/sun/star/sdbc/XConnection.hpp> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XCONTAINERAPPROVEBROADCASTER_HPP_ +#include <com/sun/star/container/XContainerApproveBroadcaster.hpp> +#endif +/** === end UNO includes === **/ + +#ifndef _DBHELPER_DBEXCEPTION_HXX_ +#include <connectivity/dbexception.hxx> +#endif + +#ifndef _TOOLS_DEBUG_HXX +#include <tools/debug.hxx> +#endif +#ifndef _COMPHELPER_ENUMHELPER_HXX_ +#include <comphelper/enumhelper.hxx> +#endif +#ifndef _COMPHELPER_UNO3_HXX_ +#include <comphelper/uno3.hxx> +#endif +#ifndef _COMPHELPER_PROPERTY_HXX_ +#include <comphelper/property.hxx> +#endif +#ifndef _COMPHELPER_SEQUENCE_HXX_ +#include <comphelper/sequence.hxx> +#endif +#ifndef _COMPHELPER_EXTRACT_HXX_ +#include <comphelper/extract.hxx> +#endif +#ifndef _CPPUHELPER_EXC_HLP_HXX_ +#include <cppuhelper/exc_hlp.hxx> +#endif + +using namespace dbtools; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::ucb; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::util; +using namespace ::osl; +using namespace ::comphelper; +using namespace ::cppu; + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + +//========================================================================== +//= OQueryContainer +//========================================================================== +DBG_NAME(OQueryContainer) +//------------------------------------------------------------------------------ +OQueryContainer::OQueryContainer( + const Reference< XNameContainer >& _rxCommandDefinitions + , const Reference< XConnection >& _rxConn + , const Reference< XMultiServiceFactory >& _rxORB, + ::dbtools::IWarningsContainer* _pWarnings) + :ODefinitionContainer(_rxORB,NULL,TContentPtr(new ODefinitionContainer_Impl)) + ,m_pWarnings( _pWarnings ) + ,m_xCommandDefinitions(_rxCommandDefinitions) + ,m_xConnection(_rxConn) +{ + DBG_CTOR(OQueryContainer, NULL); + + increment(m_refCount); + { + m_pCommandsListener = new OContainerListener( *this, m_aMutex ); + m_pCommandsListener->acquire(); + + Reference< XContainer > xContainer( m_xCommandDefinitions, UNO_QUERY_THROW ); + xContainer->addContainerListener( m_pCommandsListener ); + + Reference< XContainerApproveBroadcaster > xContainerApprove( m_xCommandDefinitions, UNO_QUERY_THROW ); + xContainerApprove->addContainerApproveListener( m_pCommandsListener ); + + // fill my structures + ODefinitionContainer_Impl& rDefinitions( getDefinitions() ); + Sequence< ::rtl::OUString > sDefinitionNames = m_xCommandDefinitions->getElementNames(); + const ::rtl::OUString* pDefinitionName = sDefinitionNames.getConstArray(); + const ::rtl::OUString* pEnd = pDefinitionName + sDefinitionNames.getLength(); + for ( ; pDefinitionName != pEnd; ++pDefinitionName ) + { + rDefinitions.insert( *pDefinitionName, TContentPtr() ); + m_aDocuments.push_back(m_aDocumentMap.insert(Documents::value_type(*pDefinitionName,Documents::mapped_type())).first); + } + } + decrement(m_refCount); + + setElementApproval( PContainerApprove( new ObjectNameApproval( _rxConn, ObjectNameApproval::TypeQuery ) ) ); +} + +//------------------------------------------------------------------------------ +OQueryContainer::~OQueryContainer() +{ + DBG_DTOR(OQueryContainer, NULL); + // dispose(); + // maybe we're already disposed, but this should be uncritical +} +// ----------------------------------------------------------------------------- +IMPLEMENT_FORWARD_XINTERFACE2( OQueryContainer,ODefinitionContainer,OQueryContainer_Base) + +//------------------------------------------------------------------------------ +IMPLEMENT_FORWARD_XTYPEPROVIDER2( OQueryContainer,ODefinitionContainer,OQueryContainer_Base) + +//------------------------------------------------------------------------------ +void OQueryContainer::disposing() +{ + ODefinitionContainer::disposing(); + MutexGuard aGuard(m_aMutex); + if ( !m_xCommandDefinitions.is() ) + // already disposed + return; + + if ( m_pCommandsListener ) + { + Reference< XContainer > xContainer( m_xCommandDefinitions, UNO_QUERY ); + xContainer->removeContainerListener( m_pCommandsListener ); + Reference< XContainerApproveBroadcaster > xContainerApprove( m_xCommandDefinitions, UNO_QUERY ); + xContainerApprove->removeContainerApproveListener( m_pCommandsListener ); + + m_pCommandsListener->dispose(); + m_pCommandsListener->release(); + m_pCommandsListener = NULL; + } + + m_xCommandDefinitions = NULL; + m_xConnection = NULL; +} + +// XServiceInfo +//------------------------------------------------------------------------------ +IMPLEMENT_SERVICE_INFO2(OQueryContainer, "com.sun.star.sdb.dbaccess.OQueryContainer", SERVICE_SDBCX_CONTAINER, SERVICE_SDB_QUERIES) + +// XDataDescriptorFactory +//-------------------------------------------------------------------------- +Reference< XPropertySet > SAL_CALL OQueryContainer::createDataDescriptor( ) throw(RuntimeException) +{ + return new OQueryDescriptor(); +} + +// XAppend +//------------------------------------------------------------------------------ +void SAL_CALL OQueryContainer::appendByDescriptor( const Reference< XPropertySet >& _rxDesc ) throw(SQLException, ElementExistException, RuntimeException) +{ + ResettableMutexGuard aGuard(m_aMutex); + if ( !m_xCommandDefinitions.is() ) + throw DisposedException( ::rtl::OUString(), *this ); + + // first clone this object's CommandDefinition part + Reference< XPropertySet > xCommandDefinitionPart( m_aContext.createComponent( (::rtl::OUString)SERVICE_SDB_QUERYDEFINITION ), UNO_QUERY_THROW ); + ::comphelper::copyProperties( _rxDesc, xCommandDefinitionPart ); + // TODO : the columns part of the descriptor has to be copied + + // create a wrapper for the object (*before* inserting into our command definition container) + Reference< XContent > xNewObject( implCreateWrapper( Reference< XContent>( xCommandDefinitionPart, UNO_QUERY_THROW ) ) ); + + ::rtl::OUString sNewObjectName; + _rxDesc->getPropertyValue(PROPERTY_NAME) >>= sNewObjectName; + + try + { + notifyByName( aGuard, sNewObjectName, xNewObject, NULL, E_INSERTED, ApproveListeners ); + } + catch( const Exception& ) + { + disposeComponent( xNewObject ); + disposeComponent( xCommandDefinitionPart ); + throw; + } + + // insert the basic object into the definition container + { + m_eDoingCurrently = INSERTING; + OAutoActionReset aAutoReset(this); + m_xCommandDefinitions->insertByName(sNewObjectName, makeAny(xCommandDefinitionPart)); + } + + implAppend( sNewObjectName, xNewObject ); + notifyByName( aGuard, sNewObjectName, xNewObject, NULL, E_INSERTED, ContainerListemers ); +} + +// XDrop +//------------------------------------------------------------------------------ +void SAL_CALL OQueryContainer::dropByName( const ::rtl::OUString& _rName ) throw(SQLException, NoSuchElementException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + if ( !checkExistence(_rName) ) + throw NoSuchElementException(_rName,*this); + + if ( !m_xCommandDefinitions.is() ) + throw DisposedException( ::rtl::OUString(), *this ); + + // now simply forward the remove request to the CommandDefinition container, we're a listener for the removal + // and thus we do everything neccessary in ::elementRemoved + m_xCommandDefinitions->removeByName(_rName); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OQueryContainer::dropByIndex( sal_Int32 _nIndex ) throw(SQLException, IndexOutOfBoundsException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + if ((_nIndex<0) || (_nIndex>getCount())) + throw IndexOutOfBoundsException(); + + if ( !m_xCommandDefinitions.is() ) + throw DisposedException( ::rtl::OUString(), *this ); + + ::rtl::OUString sName; + Reference<XPropertySet> xProp(Reference<XIndexAccess>(m_xCommandDefinitions,UNO_QUERY)->getByIndex(_nIndex),UNO_QUERY); + if ( xProp.is() ) + xProp->getPropertyValue(PROPERTY_NAME) >>= sName; + + dropByName(sName); +} +//------------------------------------------------------------------------------ +void SAL_CALL OQueryContainer::elementInserted( const ::com::sun::star::container::ContainerEvent& _rEvent ) throw(::com::sun::star::uno::RuntimeException) +{ + Reference< XContent > xNewElement; + ::rtl::OUString sElementName; + _rEvent.Accessor >>= sElementName; + { + MutexGuard aGuard(m_aMutex); + if (INSERTING == m_eDoingCurrently) + // nothing to do, we're inserting via an "appendByDescriptor" + return; + + DBG_ASSERT(sElementName.getLength(), "OQueryContainer::elementInserted : invalid name !"); + DBG_ASSERT(m_aDocumentMap.find(sElementName) == m_aDocumentMap.end(), "OQueryContainer::elementInserted : oops .... we're inconsistent with our master container !"); + if (!sElementName.getLength() || hasByName(sElementName)) + return; + + // insert an own new element + xNewElement = implCreateWrapper(sElementName); + } + insertByName(sElementName,makeAny(xNewElement)); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OQueryContainer::elementRemoved( const ::com::sun::star::container::ContainerEvent& _rEvent ) throw(::com::sun::star::uno::RuntimeException) +{ + ::rtl::OUString sAccessor; + _rEvent.Accessor >>= sAccessor; + { + DBG_ASSERT(sAccessor.getLength(), "OQueryContainer::elementRemoved : invalid name !"); + DBG_ASSERT(m_aDocumentMap.find(sAccessor) != m_aDocumentMap.end(), "OQueryContainer::elementRemoved : oops .... we're inconsistent with our master container !"); + if ( !sAccessor.getLength() || !hasByName(sAccessor) ) + return; + } + removeByName(sAccessor); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OQueryContainer::elementReplaced( const ::com::sun::star::container::ContainerEvent& _rEvent ) throw(::com::sun::star::uno::RuntimeException) +{ + Reference< XPropertySet > xReplacedElement; + Reference< XContent > xNewElement; + ::rtl::OUString sAccessor; + _rEvent.Accessor >>= sAccessor; + + { + MutexGuard aGuard(m_aMutex); + DBG_ASSERT(sAccessor.getLength(), "OQueryContainer::elementReplaced : invalid name !"); + DBG_ASSERT(m_aDocumentMap.find(sAccessor) != m_aDocumentMap.end(), "OQueryContainer::elementReplaced : oops .... we're inconsistent with our master container !"); + if (!sAccessor.getLength() || !hasByName(sAccessor)) + return; + + xNewElement = implCreateWrapper(sAccessor); + } + + replaceByName(sAccessor,makeAny(xNewElement)); +} + +//------------------------------------------------------------------------------ +Reference< XVeto > SAL_CALL OQueryContainer::approveInsertElement( const ContainerEvent& Event ) throw (WrappedTargetException, RuntimeException) +{ + ::rtl::OUString sName; + OSL_VERIFY( Event.Accessor >>= sName ); + Reference< XContent > xElement( Event.Element, UNO_QUERY_THROW ); + + Reference< XVeto > xReturn; + try + { + getElementApproval()->approveElement( sName, xElement.get() ); + } + catch( const Exception& ) + { + xReturn = new Veto( ::rtl::OUString(), ::cppu::getCaughtException() ); + } + return xReturn; +} + +//------------------------------------------------------------------------------ +Reference< XVeto > SAL_CALL OQueryContainer::approveReplaceElement( const ContainerEvent& /*Event*/ ) throw (WrappedTargetException, RuntimeException) +{ + return NULL; +} + +//------------------------------------------------------------------------------ +Reference< XVeto > SAL_CALL OQueryContainer::approveRemoveElement( const ContainerEvent& /*Event*/ ) throw (WrappedTargetException, RuntimeException) +{ + return NULL; +} + +//------------------------------------------------------------------------------ +void SAL_CALL OQueryContainer::disposing( const ::com::sun::star::lang::EventObject& _rSource ) throw(::com::sun::star::uno::RuntimeException) +{ + if (_rSource.Source.get() == Reference< XInterface >(m_xCommandDefinitions, UNO_QUERY).get()) + { // our "master container" (with the command definitions) is beeing disposed + DBG_ERROR("OQueryContainer::disposing : nobody should dispose the CommandDefinition container before disposing my connection !"); + dispose(); + } + else + { + Reference< XContent > xSource(_rSource.Source, UNO_QUERY); + // it's one of our documents .... + Documents::iterator aIter = m_aDocumentMap.begin(); + Documents::iterator aEnd = m_aDocumentMap.end(); + for (;aIter != aEnd;++aIter ) + { + if ( xSource == aIter->second.get() ) + { + m_xCommandDefinitions->removeByName(aIter->first); + break; + } + } + ODefinitionContainer::disposing(_rSource); + } +} + +// ----------------------------------------------------------------------------- +::rtl::OUString OQueryContainer::determineContentType() const +{ + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "application/vnd.org.openoffice.DatabaseQueryContainer" ) ); +} + +// ----------------------------------------------------------------------------- +Reference< XContent > OQueryContainer::implCreateWrapper(const ::rtl::OUString& _rName) +{ + Reference< XContent > xObject(m_xCommandDefinitions->getByName(_rName),UNO_QUERY); + return implCreateWrapper(xObject); +} + +//-------------------------------------------------------------------------- +Reference< XContent > OQueryContainer::implCreateWrapper(const Reference< XContent >& _rxCommandDesc) +{ + Reference<XNameContainer> xContainer(_rxCommandDesc,UNO_QUERY); + Reference< XContent > xReturn; + if ( xContainer .is() ) + { + xReturn = new OQueryContainer( xContainer, m_xConnection, m_aContext.getLegacyServiceFactory(), m_pWarnings ); + } + else + { + OQuery* pNewObject = new OQuery( Reference< XPropertySet >( _rxCommandDesc, UNO_QUERY ), m_xConnection, m_aContext.getLegacyServiceFactory() ); + xReturn = pNewObject; + + pNewObject->setWarningsContainer( m_pWarnings ); +// pNewObject->getColumns(); + // Why? This is expensive. If you comment this in 'cause you really need it, be sure to run the + // QueryInQuery test in dbaccess/qa/complex/dbaccess ... + } + + return xReturn; +} +//-------------------------------------------------------------------------- +Reference< XContent > OQueryContainer::createObject( const ::rtl::OUString& _rName) +{ + return implCreateWrapper(_rName); +} +// ----------------------------------------------------------------------------- +sal_Bool OQueryContainer::checkExistence(const ::rtl::OUString& _rName) +{ + sal_Bool bRet = sal_False; + if ( !m_bInPropertyChange ) + { + bRet = m_xCommandDefinitions->hasByName(_rName); + Documents::iterator aFind = m_aDocumentMap.find(_rName); + if ( !bRet && aFind != m_aDocumentMap.end() ) + { + m_aDocuments.erase( ::std::find(m_aDocuments.begin(),m_aDocuments.end(),aFind)); + m_aDocumentMap.erase(aFind); + } + else if ( bRet && aFind == m_aDocumentMap.end() ) + { + implAppend(_rName,NULL); + } + } + return bRet; +} +//-------------------------------------------------------------------------- +sal_Bool SAL_CALL OQueryContainer::hasElements( ) throw (RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + return m_xCommandDefinitions->hasElements(); +} +// ----------------------------------------------------------------------------- +sal_Int32 SAL_CALL OQueryContainer::getCount( ) throw(RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + return Reference<XIndexAccess>(m_xCommandDefinitions,UNO_QUERY)->getCount(); +} +// ----------------------------------------------------------------------------- +Sequence< ::rtl::OUString > SAL_CALL OQueryContainer::getElementNames( ) throw(RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + + return m_xCommandDefinitions->getElementNames(); +} + +//........................................................................ +} // namespace dbaccess +//........................................................................ + diff --git a/dbaccess/source/core/api/querydescriptor.cxx b/dbaccess/source/core/api/querydescriptor.cxx new file mode 100644 index 000000000000..0fb61dbd1f64 --- /dev/null +++ b/dbaccess/source/core/api/querydescriptor.cxx @@ -0,0 +1,323 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#ifndef _DBA_COREAPI_QUERYDESCRIPTOR_HXX_ +#include "querydescriptor.hxx" +#endif +#ifndef _DBASHARED_APITOOLS_HXX_ +#include "apitools.hxx" +#endif +#ifndef DBACCESS_SHARED_DBASTRINGS_HRC +#include "dbastrings.hrc" +#endif +#ifndef _COMPHELPER_PROPERTY_HXX_ +#include <comphelper/property.hxx> +#endif +#ifndef _COMPHELPER_SEQUENCE_HXX_ +#include <comphelper/sequence.hxx> +#endif +#ifndef _CPPUHELPER_TYPEPROVIDER_HXX_ +#include <cppuhelper/typeprovider.hxx> +#endif +#ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBUTE_HPP_ +#include <com/sun/star/beans/PropertyAttribute.hpp> +#endif +#ifndef _DBACORE_DEFINITIONCOLUMN_HXX_ +#include "definitioncolumn.hxx" +#endif +#ifndef _TOOLS_DEBUG_HXX +#include <tools/debug.hxx> +#endif + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::util; +using namespace ::comphelper; +using namespace ::osl; +using namespace ::cppu; + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + +//========================================================================== +//= OQueryDescriptor +//========================================================================== +DBG_NAME(OQueryDescriptor) +//-------------------------------------------------------------------------- +OQueryDescriptor::OQueryDescriptor() + :OQueryDescriptor_Base(m_aMutex,*this) + ,ODataSettings(m_aBHelper,sal_True) +{ + DBG_CTOR(OQueryDescriptor,NULL); + registerProperties(); + ODataSettings::registerPropertiesFor(this); +} + +//-------------------------------------------------------------------------- +OQueryDescriptor::OQueryDescriptor(const OQueryDescriptor_Base& _rSource) + :OQueryDescriptor_Base(_rSource,*this) + ,ODataSettings(m_aBHelper,sal_True) +{ + DBG_CTOR(OQueryDescriptor,NULL); + registerProperties(); + ODataSettings::registerPropertiesFor(this); +} +// ----------------------------------------------------------------------------- +OQueryDescriptor::~OQueryDescriptor() +{ + DBG_DTOR(OQueryDescriptor,NULL); +} +// ----------------------------------------------------------------------------- +IMPLEMENT_TYPEPROVIDER2(OQueryDescriptor,OQueryDescriptor_Base,ODataSettings); +IMPLEMENT_FORWARD_XINTERFACE3( OQueryDescriptor,OWeakObject,OQueryDescriptor_Base,ODataSettings) +//-------------------------------------------------------------------------- +void OQueryDescriptor::registerProperties() +{ + // the properties which OCommandBase supplies (it has no own registration, as it's not derived from + // a OPropertyStateContainer) + registerProperty(PROPERTY_NAME, PROPERTY_ID_NAME, PropertyAttribute::BOUND|PropertyAttribute::CONSTRAINED, + &m_sElementName, ::getCppuType(&m_sElementName)); + + registerProperty(PROPERTY_COMMAND, PROPERTY_ID_COMMAND, PropertyAttribute::BOUND, + &m_sCommand, ::getCppuType(&m_sCommand)); + + registerProperty(PROPERTY_ESCAPE_PROCESSING, PROPERTY_ID_ESCAPE_PROCESSING, PropertyAttribute::BOUND, + &m_bEscapeProcessing, ::getBooleanCppuType()); + + registerProperty(PROPERTY_UPDATE_TABLENAME, PROPERTY_ID_UPDATE_TABLENAME, PropertyAttribute::BOUND, + &m_sUpdateTableName, ::getCppuType(&m_sUpdateTableName)); + + registerProperty(PROPERTY_UPDATE_SCHEMANAME, PROPERTY_ID_UPDATE_SCHEMANAME, PropertyAttribute::BOUND, + &m_sUpdateSchemaName, ::getCppuType(&m_sUpdateSchemaName)); + + registerProperty(PROPERTY_UPDATE_CATALOGNAME, PROPERTY_ID_UPDATE_CATALOGNAME, PropertyAttribute::BOUND, + &m_sUpdateCatalogName, ::getCppuType(&m_sUpdateCatalogName)); + + registerProperty(PROPERTY_LAYOUTINFORMATION, PROPERTY_ID_LAYOUTINFORMATION, PropertyAttribute::BOUND, + &m_aLayoutInformation, ::getCppuType(&m_aLayoutInformation)); +} +// ----------------------------------------------------------------------------- +//-------------------------------------------------------------------------- +Reference< XPropertySetInfo > SAL_CALL OQueryDescriptor::getPropertySetInfo( ) throw(RuntimeException) +{ + return createPropertySetInfo( getInfoHelper() ) ; +} + +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper& OQueryDescriptor::getInfoHelper() +{ + return *getArrayHelper(); +} +//-------------------------------------------------------------------------- +::cppu::IPropertyArrayHelper* OQueryDescriptor::createArrayHelper( ) const +{ + Sequence< Property > aProps; + describeProperties(aProps); + return new ::cppu::OPropertyArrayHelper(aProps); +} + +// ----------------------------------------------------------------------------- +DBG_NAME(OQueryDescriptor_Base); +//-------------------------------------------------------------------------- +OQueryDescriptor_Base::OQueryDescriptor_Base(::osl::Mutex& _rMutex,::cppu::OWeakObject& _rMySelf) + :m_bColumnsOutOfDate(sal_True) + ,m_rMutex(_rMutex) +{ + DBG_CTOR(OQueryDescriptor_Base,NULL); + m_pColumns = new OColumns(_rMySelf, m_rMutex, sal_True,::std::vector< ::rtl::OUString>(), this,this); +} +//-------------------------------------------------------------------------- +OQueryDescriptor_Base::OQueryDescriptor_Base(const OQueryDescriptor_Base& _rSource,::cppu::OWeakObject& _rMySelf) + :m_bColumnsOutOfDate(sal_True) + ,m_rMutex(_rSource.m_rMutex) +{ + DBG_CTOR(OQueryDescriptor_Base,NULL); + m_pColumns = new OColumns(_rMySelf, m_rMutex, sal_True,::std::vector< ::rtl::OUString>(), this,this); + + m_sCommand = _rSource.m_sCommand; + m_bEscapeProcessing = _rSource.m_bEscapeProcessing; + m_sUpdateTableName = _rSource.m_sUpdateTableName; + m_sUpdateSchemaName = _rSource.m_sUpdateSchemaName; + m_sUpdateCatalogName = _rSource.m_sUpdateCatalogName; + m_aLayoutInformation = _rSource.m_aLayoutInformation; +} + +//-------------------------------------------------------------------------- +OQueryDescriptor_Base::~OQueryDescriptor_Base() +{ + m_pColumns->acquire(); + m_pColumns->disposing(); + delete m_pColumns; + + DBG_DTOR(OQueryDescriptor_Base,NULL); +} +// ----------------------------------------------------------------------------- +sal_Int64 SAL_CALL OQueryDescriptor_Base::getSomething( const Sequence< sal_Int8 >& _rIdentifier ) throw(RuntimeException) +{ + if (_rIdentifier.getLength() != 16) + return 0; + + if (0 == rtl_compareMemory(getImplementationId().getConstArray(), _rIdentifier.getConstArray(), 16 ) ) + return reinterpret_cast<sal_Int64>(this); + + return 0; +} +//-------------------------------------------------------------------------- +IMPLEMENT_IMPLEMENTATION_ID(OQueryDescriptor_Base) +//-------------------------------------------------------------------------- +void OQueryDescriptor_Base::setColumnsOutOfDate( sal_Bool _bOutOfDate ) +{ + m_bColumnsOutOfDate = _bOutOfDate; + if ( !m_bColumnsOutOfDate ) + m_pColumns->setInitialized(); +} + +//-------------------------------------------------------------------------- +void OQueryDescriptor_Base::implAppendColumn( const ::rtl::OUString& _rName, OColumn* _pColumn ) +{ + m_pColumns->append( _rName, _pColumn ); +} + +//-------------------------------------------------------------------------- +void OQueryDescriptor_Base::clearColumns( ) +{ + m_pColumns->clearColumns(); + + setColumnsOutOfDate(); +} + +//-------------------------------------------------------------------------- +Reference< XNameAccess > SAL_CALL OQueryDescriptor_Base::getColumns( ) throw (RuntimeException) +{ + MutexGuard aGuard(m_rMutex); + + if ( isColumnsOutOfDate() ) + { + // clear the current columns + clearColumns(); + + // do this before rebuildColumns. This prevents recursion, e.g. in the case where we + // have queries with cyclic references: + // foo := SELECT * FROM bar + // bar := SELECT * FROM foo + setColumnsOutOfDate( sal_False ); + + // rebuild them + try + { + rebuildColumns(); + } + catch ( const Exception& ) + { + setColumnsOutOfDate( sal_True ); + throw; + } + } + + return m_pColumns; +} + +//-------------------------------------------------------------------------- +::rtl::OUString SAL_CALL OQueryDescriptor_Base::getImplementationName( ) throw(RuntimeException) +{ + return ::rtl::OUString::createFromAscii("com.sun.star.sdb.OQueryDescriptor"); +} + +//-------------------------------------------------------------------------- +sal_Bool SAL_CALL OQueryDescriptor_Base::supportsService( const ::rtl::OUString& _rServiceName ) throw(RuntimeException) +{ + return ::comphelper::findValue(getSupportedServiceNames(), _rServiceName, sal_True).getLength() != 0; +} + +//-------------------------------------------------------------------------- +Sequence< ::rtl::OUString > SAL_CALL OQueryDescriptor_Base::getSupportedServiceNames( ) throw(RuntimeException) +{ + Sequence< ::rtl::OUString > aSupported(2); + aSupported.getArray()[0] = SERVICE_SDB_DATASETTINGS; + aSupported.getArray()[1] = SERVICE_SDB_QUERYDESCRIPTOR; + return aSupported; +} +//-------------------------------------------------------------------------- +void OQueryDescriptor_Base::disposeColumns() +{ + m_pColumns->disposing(); +} + +// ----------------------------------------------------------------------------- +void OQueryDescriptor_Base::columnAppended( const Reference< XPropertySet >& /*_rxSourceDescriptor*/ ) +{ + // not interested in +} + +// ----------------------------------------------------------------------------- +void OQueryDescriptor_Base::columnDropped(const ::rtl::OUString& /*_sName*/) +{ + // not interested in +} + +// ----------------------------------------------------------------------------- +Reference< XPropertySet > OQueryDescriptor_Base::createColumnDescriptor() +{ + OSL_ENSURE( false, "OQueryDescriptor_Base::createColumnDescriptor: called why?" ); + return NULL; +} + +// ----------------------------------------------------------------------------- +void OQueryDescriptor_Base::rebuildColumns( ) +{ +} + +// ----------------------------------------------------------------------------- +// IRefreshableColumns +void OQueryDescriptor_Base::refreshColumns() +{ + MutexGuard aGuard( m_rMutex ); + + clearColumns(); + rebuildColumns(); +} + +//------------------------------------------------------------------------------ +OColumn* OQueryDescriptor_Base::createColumn( const ::rtl::OUString& /*_rName*/ ) const +{ + // creating a column/descriptor for a query/descriptor does not make sense at all + return NULL; +} +// ----------------------------------------------------------------------------- +//........................................................................ +} // namespace dbaccess +//........................................................................ + + diff --git a/dbaccess/source/core/api/querydescriptor.hxx b/dbaccess/source/core/api/querydescriptor.hxx new file mode 100644 index 000000000000..2f27b4b9c628 --- /dev/null +++ b/dbaccess/source/core/api/querydescriptor.hxx @@ -0,0 +1,183 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 _DBA_COREAPI_QUERYDESCRIPTOR_HXX_ +#define _DBA_COREAPI_QUERYDESCRIPTOR_HXX_ + +#ifndef _CPPUHELPER_IMPLBASE3_HXX_ +#include <cppuhelper/implbase3.hxx> +#endif +#ifndef _COMPHELPER_PROPERTY_ARRAY_HELPER_HXX_ +#include <comphelper/proparrhlp.hxx> +#endif +#ifndef _OSL_MUTEX_HXX_ +#include <osl/mutex.hxx> +#endif + +#ifndef _COM_SUN_STAR_SDBCX_XCOLUMNSSUPPLIER_HPP_ +#include <com/sun/star/sdbcx/XColumnsSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_ +#include <com/sun/star/lang/XServiceInfo.hpp> +#endif +#ifndef _COM_SUN_STAR_LANG_XUNOTUNNEL_HPP_ +#include <com/sun/star/lang/XUnoTunnel.hpp> +#endif + +#ifndef _DBASHARED_APITOOLS_HXX_ +#include "apitools.hxx" +#endif +#ifndef _DBA_COREAPI_COLUMN_HXX_ +#include "column.hxx" +#endif +#ifndef _DBA_CORE_DATASETTINGS_HXX_ +#include "datasettings.hxx" +#endif +#ifndef _DBA_CORE_COMMANDBASE_HXX_ +#include "commandbase.hxx" +#endif +#ifndef _COMPHELPER_BROADCASTHELPER_HXX_ +#include <comphelper/broadcasthelper.hxx> +#endif +#ifndef _COMPHELPER_UNO3_HXX_ +#include <comphelper/uno3.hxx> +#endif + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + +//========================================================================== +//= OQueryDescriptor_Base - a query descriptor (as the name suggests :) +//========================================================================== +typedef ::cppu::ImplHelper3< + ::com::sun::star::sdbcx::XColumnsSupplier, + ::com::sun::star::lang::XUnoTunnel, + ::com::sun::star::lang::XServiceInfo > OQueryDescriptor_BASE; + +class OQueryDescriptor_Base + :public OQueryDescriptor_BASE + ,public OCommandBase + ,public IColumnFactory + ,public ::connectivity::sdbcx::IRefreshableColumns +{ +private: + sal_Bool m_bColumnsOutOfDate : 1; // the columns have to be rebuild on the next getColumns ? + ::osl::Mutex& m_rMutex; + +protected: + OColumns* m_pColumns; // our column descriptions + ::rtl::OUString m_sElementName; + virtual ~OQueryDescriptor_Base(); + + void setColumnsOutOfDate( sal_Bool _bOutOfDate = sal_True ); + sal_Bool isColumnsOutOfDate() const { return m_bColumnsOutOfDate; } + + sal_Int32 getColumnCount() const { return m_pColumns ? m_pColumns->getCount() : 0; } + void clearColumns( ); + + void implAppendColumn( const ::rtl::OUString& _rName, OColumn* _pColumn ); + +public: + OQueryDescriptor_Base(::osl::Mutex& _rMutex,::cppu::OWeakObject& _rMySelf); + /** constructs the object with a UNO QueryDescriptor. If you use this ctor, the resulting object + won't have any column informations (the column container will be empty) + */ + OQueryDescriptor_Base(const OQueryDescriptor_Base& _rSource,::cppu::OWeakObject& _rMySelf); + +// ::com::sun::star::sdbcx::XColumnsSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > SAL_CALL getColumns( ) throw(::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::lang::XUnoTunnel + virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& aIdentifier ) throw(::com::sun::star::uno::RuntimeException); + DECLARE_IMPLEMENTATION_ID( ); + +// ::com::sun::star::lang::XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw(::com::sun::star::uno::RuntimeException); + +protected: + +// IColumnFactory + virtual OColumn* createColumn(const ::rtl::OUString& _rName) const; + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > createColumnDescriptor(); + virtual void columnAppended( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxSourceDescriptor ); + virtual void columnDropped(const ::rtl::OUString& _sName); + + /** rebuild our columns set + + clearColumns has already been called before, do <em>NOT</em> call it, again + */ + virtual void rebuildColumns( ); + + virtual void disposeColumns(); + + // IRefreshableColumns overridables + virtual void refreshColumns(); +}; + +class OQueryDescriptor : public comphelper::OMutexAndBroadcastHelper + ,public ::cppu::OWeakObject + ,public OQueryDescriptor_Base + ,public ::comphelper::OPropertyArrayUsageHelper< OQueryDescriptor_Base > + ,public ODataSettings +{ + OQueryDescriptor(const OQueryDescriptor&); + void operator =(const OQueryDescriptor&); + // helper + void registerProperties(); +protected: + // OPropertyArrayUsageHelper + virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const; + + // OPropertySetHelper + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(); + + virtual ~OQueryDescriptor(); +public: + OQueryDescriptor(); + OQueryDescriptor(const OQueryDescriptor_Base& _rSource); + + // com::sun::star::lang::XTypeProvider + DECLARE_TYPEPROVIDER( ); + +// ::com::sun::star::uno::XInterface + DECLARE_XINTERFACE( ) + + // ::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); + +}; +//........................................................................ +} // namespace dbaccess +//........................................................................ + +#endif // _DBA_COREAPI_QUERYDESCRIPTOR_HXX_ + + diff --git a/dbaccess/source/core/api/resultcolumn.cxx b/dbaccess/source/core/api/resultcolumn.cxx new file mode 100644 index 000000000000..02195693bba1 --- /dev/null +++ b/dbaccess/source/core/api/resultcolumn.cxx @@ -0,0 +1,357 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" +#ifndef _DBACORE_RESULTCOLUMN_HXX_ +#include "resultcolumn.hxx" +#endif +#ifndef _COM_SUN_STAR_LANG_DISPOSEDEXCEPTION_HPP_ +#include <com/sun/star/lang/DisposedException.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XRESULTSETMETADATASUPPLIER_HPP_ +#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_DATATYPE_HPP_ +#include <com/sun/star/sdbc/DataType.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_COLUMNVALUE_HPP_ +#include <com/sun/star/sdbc/ColumnValue.hpp> +#endif +#ifndef _CPPUHELPER_TYPEPROVIDER_HXX_ +#include <cppuhelper/typeprovider.hxx> +#endif +#ifndef _TOOLS_DEBUG_HXX +#include <tools/debug.hxx> +#endif +#ifndef TOOLS_DIAGNOSE_EX_H +#include <tools/diagnose_ex.h> +#endif +#ifndef DBACCESS_SHARED_DBASTRINGS_HRC +#include "dbastrings.hrc" +#endif +#ifndef _DBASHARED_APITOOLS_HXX_ +#include "apitools.hxx" +#endif +#ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBUTE_HPP_ +#include <com/sun/star/beans/PropertyAttribute.hpp> +#endif +#ifndef _CPPUHELPER_EXC_HLP_HXX_ +#include <cppuhelper/exc_hlp.hxx> +#endif +#ifndef _OSL_THREAD_H_ +#include <osl/thread.h> +#endif + +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::container; +using namespace ::osl; +using namespace ::comphelper; +using namespace ::cppu; +using namespace dbaccess; + +DBG_NAME(OResultColumn) +//-------------------------------------------------------------------------- +OResultColumn::OResultColumn( const Reference < XResultSetMetaData >& _xMetaData, sal_Int32 _nPos, + const Reference< XDatabaseMetaData >& _rxDBMeta ) + :OColumn( true ) + ,m_xMetaData( _xMetaData ) + ,m_xDBMetaData( _rxDBMeta ) + ,m_nPos( _nPos ) +{ + DBG_CTOR(OResultColumn,NULL); +} +// ----------------------------------------------------------------------------- +void OResultColumn::impl_determineIsRowVersion_nothrow() +{ + if ( m_aIsRowVersion.hasValue() ) + return; + m_aIsRowVersion <<= (sal_Bool)(sal_False); + + OSL_ENSURE( m_xDBMetaData.is(), "OResultColumn::impl_determineIsRowVersion_nothrow: no DBMetaData!" ); + if ( !m_xDBMetaData.is() ) + return; + + try + { + ::rtl::OUString sCatalog, sSchema, sTable, sColumnName; + getPropertyValue( PROPERTY_CATALOGNAME ) >>= sCatalog; + getPropertyValue( PROPERTY_SCHEMANAME ) >>= sSchema; + getPropertyValue( PROPERTY_TABLENAME ) >>= sTable; + getPropertyValue( PROPERTY_NAME ) >>= sColumnName; + + try + { + Reference< XResultSet > xVersionColumns = m_xDBMetaData->getVersionColumns( + makeAny( sCatalog ), sSchema, sTable ); + if ( xVersionColumns.is() ) // allowed to be NULL + { + Reference< XRow > xResultRow( xVersionColumns, UNO_QUERY_THROW ); + while ( xVersionColumns->next() ) + { + if ( xResultRow->getString( 2 ) == sColumnName ) + { + m_aIsRowVersion <<= (sal_Bool)(sal_True); + break; + } + } + } + } + catch(const SQLException&) + { + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } +} +// ----------------------------------------------------------------------------- +OResultColumn::~OResultColumn() +{ + DBG_DTOR(OResultColumn,NULL); +} +// com::sun::star::lang::XTypeProvider +//-------------------------------------------------------------------------- +Sequence< sal_Int8 > OResultColumn::getImplementationId() throw (RuntimeException) +{ + static OImplementationId * pId = 0; + if (! pId) + { + MutexGuard aGuard( Mutex::getGlobalMutex() ); + if (! pId) + { + static OImplementationId aId; + pId = &aId; + } + } + return pId->getImplementationId(); +} + +// XServiceInfo +//------------------------------------------------------------------------------ +rtl::OUString OResultColumn::getImplementationName( ) throw(RuntimeException) +{ + return rtl::OUString::createFromAscii("com.sun.star.sdb.OResultColumn"); +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > OResultColumn::getSupportedServiceNames( ) throw (RuntimeException) +{ + Sequence< ::rtl::OUString > aSNS( 2 ); + aSNS[0] = SERVICE_SDBCX_COLUMN; + aSNS[1] = SERVICE_SDB_RESULTCOLUMN; + return aSNS; +} + +// OComponentHelper +//------------------------------------------------------------------------------ +void OResultColumn::disposing() +{ + OColumn::disposing(); + + MutexGuard aGuard(m_aMutex); + m_xMetaData = NULL; +} + +// comphelper::OPropertyArrayUsageHelper +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper* OResultColumn::createArrayHelper( ) const +{ + BEGIN_PROPERTY_HELPER(21) + DECL_PROP1(CATALOGNAME, ::rtl::OUString, READONLY); + DECL_PROP1(DISPLAYSIZE, sal_Int32, READONLY); + DECL_PROP1_BOOL(ISAUTOINCREMENT, READONLY); + DECL_PROP1_BOOL(ISCASESENSITIVE, READONLY); + DECL_PROP1_BOOL(ISCURRENCY, READONLY); + DECL_PROP1_BOOL(ISDEFINITELYWRITABLE, READONLY); + DECL_PROP1(ISNULLABLE, sal_Int32, READONLY); + DECL_PROP1_BOOL(ISREADONLY, READONLY); + DECL_PROP1_BOOL(ISROWVERSION, READONLY); + DECL_PROP1_BOOL(ISSEARCHABLE, READONLY); + DECL_PROP1_BOOL(ISSIGNED, READONLY); + DECL_PROP1_BOOL(ISWRITABLE, READONLY); + DECL_PROP1(LABEL, ::rtl::OUString, READONLY); + DECL_PROP1(NAME, ::rtl::OUString, READONLY); + DECL_PROP1(PRECISION, sal_Int32, READONLY); + DECL_PROP1(SCALE, sal_Int32, READONLY); + DECL_PROP1(SCHEMANAME, ::rtl::OUString, READONLY); + DECL_PROP1(SERVICENAME, ::rtl::OUString, READONLY); + DECL_PROP1(TABLENAME, ::rtl::OUString, READONLY); + DECL_PROP1(TYPE, sal_Int32, READONLY); + DECL_PROP1(TYPENAME, ::rtl::OUString, READONLY); + END_PROPERTY_HELPER(); +} + +// cppu::OPropertySetHelper +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper& OResultColumn::getInfoHelper() +{ + return *static_cast< ::comphelper::OPropertyArrayUsageHelper< OResultColumn >* >(this)->getArrayHelper(); +} + +//------------------------------------------------------------------------------ +namespace +{ + template< typename TYPE > + void obtain( Any& _out_rValue, ::boost::optional< TYPE > _rCache, const sal_Int32 _nPos, const Reference < XResultSetMetaData >& _rxResultMeta, TYPE (SAL_CALL XResultSetMetaData::*Getter)( sal_Int32 ) ) + { + if ( !_rCache ) + _rCache.reset( (_rxResultMeta.get()->*Getter)( _nPos ) ); + _out_rValue <<= *_rCache; + } +} + +//------------------------------------------------------------------------------ +void OResultColumn::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const +{ + try + { + if ( OColumn::isRegisteredProperty( nHandle ) ) + { + OColumn::getFastPropertyValue( rValue, nHandle ); + } + else + { + switch (nHandle) + { + case PROPERTY_ID_ISROWVERSION: + const_cast< OResultColumn* >( this )->impl_determineIsRowVersion_nothrow(); + rValue = m_aIsRowVersion; + break; + case PROPERTY_ID_TABLENAME: + rValue <<= m_xMetaData->getTableName(m_nPos); + break; + case PROPERTY_ID_SCHEMANAME: + rValue <<= m_xMetaData->getSchemaName(m_nPos); + break; + case PROPERTY_ID_CATALOGNAME: + rValue <<= m_xMetaData->getCatalogName(m_nPos); + break; + case PROPERTY_ID_ISSIGNED: + obtain( rValue, m_isSigned, m_nPos, m_xMetaData, &XResultSetMetaData::isSigned ); + break; + case PROPERTY_ID_ISCURRENCY: + obtain( rValue, m_isCurrency, m_nPos, m_xMetaData, &XResultSetMetaData::isCurrency ); + break; + case PROPERTY_ID_ISSEARCHABLE: + obtain( rValue, m_bSearchable, m_nPos, m_xMetaData, &XResultSetMetaData::isSearchable ); + break; + case PROPERTY_ID_ISCASESENSITIVE: + obtain( rValue, m_isCaseSensitive, m_nPos, m_xMetaData, &XResultSetMetaData::isCaseSensitive ); + break; + case PROPERTY_ID_ISREADONLY: + obtain( rValue, m_isReadOnly, m_nPos, m_xMetaData, &XResultSetMetaData::isReadOnly ); + break; + case PROPERTY_ID_ISWRITABLE: + obtain( rValue, m_isWritable, m_nPos, m_xMetaData, &XResultSetMetaData::isWritable ); + break; + case PROPERTY_ID_ISDEFINITELYWRITABLE: + obtain( rValue, m_isDefinitelyWritable, m_nPos, m_xMetaData, &XResultSetMetaData::isDefinitelyWritable ); + break; + case PROPERTY_ID_ISAUTOINCREMENT: + obtain( rValue, m_isAutoIncrement, m_nPos, m_xMetaData, &XResultSetMetaData::isAutoIncrement ); + break; + case PROPERTY_ID_SERVICENAME: + rValue <<= m_xMetaData->getColumnServiceName(m_nPos); + break; + case PROPERTY_ID_LABEL: + obtain( rValue, m_sColumnLabel, m_nPos, m_xMetaData, &XResultSetMetaData::getColumnLabel ); + break; + case PROPERTY_ID_DISPLAYSIZE: + obtain( rValue, m_nColumnDisplaySize, m_nPos, m_xMetaData, &XResultSetMetaData::getColumnDisplaySize ); + break; + case PROPERTY_ID_TYPE: + obtain( rValue, m_nColumnType, m_nPos, m_xMetaData, &XResultSetMetaData::getColumnType ); + break; + case PROPERTY_ID_PRECISION: + obtain( rValue, m_nPrecision, m_nPos, m_xMetaData, &XResultSetMetaData::getPrecision ); + break; + case PROPERTY_ID_SCALE: + obtain( rValue, m_nScale, m_nPos, m_xMetaData, &XResultSetMetaData::getScale ); + break; + case PROPERTY_ID_ISNULLABLE: + obtain( rValue, m_isNullable, m_nPos, m_xMetaData, &XResultSetMetaData::isNullable ); + break; + case PROPERTY_ID_TYPENAME: + rValue <<= m_xMetaData->getColumnTypeName(m_nPos); + break; + default: + OSL_ENSURE( false, "OResultColumn::getFastPropertyValue: unknown property handle!" ); + break; + } + } + } + catch (SQLException& ) + { + // default handling if we caught an exception + switch (nHandle) + { + case PROPERTY_ID_LABEL: + case PROPERTY_ID_TYPENAME: + case PROPERTY_ID_SERVICENAME: + case PROPERTY_ID_TABLENAME: + case PROPERTY_ID_SCHEMANAME: + case PROPERTY_ID_CATALOGNAME: + // empty string'S + rValue <<= rtl::OUString(); + break; + case PROPERTY_ID_ISROWVERSION: + case PROPERTY_ID_ISAUTOINCREMENT: + case PROPERTY_ID_ISWRITABLE: + case PROPERTY_ID_ISDEFINITELYWRITABLE: + case PROPERTY_ID_ISCASESENSITIVE: + case PROPERTY_ID_ISSEARCHABLE: + case PROPERTY_ID_ISCURRENCY: + case PROPERTY_ID_ISSIGNED: + { + sal_Bool bVal = sal_False; + rValue.setValue(&bVal, getBooleanCppuType()); + } break; + case PROPERTY_ID_ISREADONLY: + { + sal_Bool bVal = sal_True; + rValue.setValue(&bVal, getBooleanCppuType()); + } break; + case PROPERTY_ID_SCALE: + case PROPERTY_ID_PRECISION: + case PROPERTY_ID_DISPLAYSIZE: + rValue <<= sal_Int32(0); + break; + case PROPERTY_ID_TYPE: + rValue <<= sal_Int32(DataType::SQLNULL); + break; + case PROPERTY_ID_ISNULLABLE: + rValue <<= ColumnValue::NULLABLE_UNKNOWN; + break; + } + } +} + diff --git a/dbaccess/source/core/api/resultcolumn.hxx b/dbaccess/source/core/api/resultcolumn.hxx new file mode 100644 index 000000000000..7e1842241cf6 --- /dev/null +++ b/dbaccess/source/core/api/resultcolumn.hxx @@ -0,0 +1,101 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 _DBACORE_RESULTCOLUMN_HXX_ +#define _DBACORE_RESULTCOLUMN_HXX_ + +#ifndef _COM_SUN_STAR_SDBC_XRESULTSETMETADATA_HDL_ +#include <com/sun/star/sdbc/XResultSetMetaData.hdl> +#endif +#ifndef _DBA_COREAPI_COLUMN_HXX_ +#include <column.hxx> +#endif +#include <boost/optional.hpp> +namespace dbaccess +{ + //************************************************************ + // OResultColumn + //************************************************************ + class OResultColumn : public OColumn, + public ::comphelper::OPropertyArrayUsageHelper < OResultColumn > + { + protected: + ::com::sun::star::uno::Reference < ::com::sun::star::sdbc::XResultSetMetaData > m_xMetaData; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XDatabaseMetaData > m_xDBMetaData; + sal_Int32 m_nPos; + ::com::sun::star::uno::Any m_aIsRowVersion; + mutable ::boost::optional< sal_Bool > m_isSigned; + mutable ::boost::optional< sal_Bool > m_isCurrency; + mutable ::boost::optional< sal_Bool > m_bSearchable; + mutable ::boost::optional< sal_Bool > m_isCaseSensitive; + mutable ::boost::optional< sal_Bool > m_isReadOnly; + mutable ::boost::optional< sal_Bool > m_isWritable; + mutable ::boost::optional< sal_Bool > m_isDefinitelyWritable; + mutable ::boost::optional< sal_Bool > m_isAutoIncrement; + mutable ::boost::optional< sal_Int32 > m_isNullable; + mutable ::boost::optional< ::rtl::OUString > m_sColumnLabel; + mutable ::boost::optional< sal_Int32 > m_nColumnDisplaySize; + mutable ::boost::optional< sal_Int32 > m_nColumnType; + mutable ::boost::optional< sal_Int32 > m_nPrecision; + mutable ::boost::optional< sal_Int32 > m_nScale; + + virtual ~OResultColumn(); + public: + OResultColumn( + const ::com::sun::star::uno::Reference < ::com::sun::star::sdbc::XResultSetMetaData >& _xMetaData, + sal_Int32 _nPos, + const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XDatabaseMetaData >& _rxDBMeta ); + + // com::sun::star::lang::XTypeProvider + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() throw (::com::sun::star::uno::RuntimeException); + + // com::sun::star::lang::XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw(::com::sun::star::uno::RuntimeException); + + // cppu::OComponentHelper + virtual void SAL_CALL disposing(void); + + // comphelper::OPropertyArrayUsageHelper + virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const; + + // cppu::OPropertySetHelper + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(); + virtual void SAL_CALL getFastPropertyValue( + ::com::sun::star::uno::Any& rValue, + sal_Int32 nHandle + ) const; + + private: + void impl_determineIsRowVersion_nothrow(); + + protected: + using ::cppu::OPropertySetHelper::getFastPropertyValue; + }; +} +#endif // _DBACORE_RESULTCOLUMN_HXX_ + diff --git a/dbaccess/source/core/api/resultset.cxx b/dbaccess/source/core/api/resultset.cxx new file mode 100644 index 000000000000..0f1be7553ad6 --- /dev/null +++ b/dbaccess/source/core/api/resultset.cxx @@ -0,0 +1,1208 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" +#ifndef _DBA_COREAPI_RESULTSET_HXX_ +#include <resultset.hxx> +#endif +#ifndef DBACCESS_SHARED_DBASTRINGS_HRC +#include "dbastrings.hrc" +#endif +#ifndef _DBASHARED_APITOOLS_HXX_ +#include "apitools.hxx" +#endif +#ifndef _COM_SUN_STAR_LANG_DISPOSEDEXCEPTION_HPP_ +#include <com/sun/star/lang/DisposedException.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_RESULTSETTYPE_HPP_ +#include <com/sun/star/sdbc/ResultSetType.hpp> +#endif +#ifndef _CPPUHELPER_TYPEPROVIDER_HXX_ +#include <cppuhelper/typeprovider.hxx> +#endif +#ifndef _COMPHELPER_PROPERTY_HXX_ +#include <comphelper/property.hxx> +#endif +#ifndef _COMPHELPER_SEQUENCE_HXX_ +#include <comphelper/sequence.hxx> +#endif +#ifndef _COMPHELPER_TYPES_HXX_ +#include <comphelper/types.hxx> +#endif +#ifndef _TOOLS_DEBUG_HXX //autogen +#include <tools/debug.hxx> +#endif +#ifndef TOOLS_DIAGNOSE_EX_H +#include <tools/diagnose_ex.h> +#endif +#ifndef _DBA_COREAPI_DATACOLUMN_HXX_ +#include <datacolumn.hxx> +#endif +#ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBUTE_HPP_ +#include <com/sun/star/beans/PropertyAttribute.hpp> +#endif +#ifndef _DBHELPER_DBEXCEPTION_HXX_ +#include <connectivity/dbexception.hxx> +#endif +#ifndef _CONNECTIVITY_DBTOOLS_HXX_ +#include <connectivity/dbtools.hxx> +#endif +#ifndef _CPPUHELPER_EXC_HLP_HXX_ +#include <cppuhelper/exc_hlp.hxx> +#endif +#ifndef _OSL_THREAD_H_ +#include <osl/thread.h> +#endif +#include <rtl/logfile.hxx> + + +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +//using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::container; +using namespace ::cppu; +using namespace ::osl; +using namespace dbaccess; +using namespace dbtools; + +DBG_NAME(OResultSet) + +//-------------------------------------------------------------------------- +OResultSet::OResultSet(const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet >& _xResultSet, + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _xStatement, + sal_Bool _bCaseSensitive) + :OResultSetBase(m_aMutex) + ,OPropertySetHelper(OResultSetBase::rBHelper) + ,m_xDelegatorResultSet(_xResultSet) + ,m_aWarnings( Reference< XWarningsSupplier >( _xResultSet, UNO_QUERY ) ) + ,m_bIsBookmarkable(sal_False) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::OResultSet" ); + DBG_CTOR(OResultSet, NULL); + + m_pColumns = new OColumns(*this, m_aMutex, _bCaseSensitive, ::std::vector< ::rtl::OUString>(), NULL,NULL); + + try + { + m_aStatement = _xStatement; + m_xDelegatorResultSetUpdate = m_xDelegatorResultSetUpdate.query( m_xDelegatorResultSet ); + m_xDelegatorRow = m_xDelegatorRow.query( m_xDelegatorResultSet ); + m_xDelegatorRowUpdate = m_xDelegatorRowUpdate.query( m_xDelegatorResultSet ); + + Reference< XPropertySet > xSet(m_xDelegatorResultSet, UNO_QUERY); + xSet->getPropertyValue(PROPERTY_RESULTSETTYPE) >>= m_nResultSetType; + xSet->getPropertyValue(PROPERTY_RESULTSETCONCURRENCY) >>= m_nResultSetConcurrency; + + // test for Bookmarks + if (ResultSetType::FORWARD_ONLY != m_nResultSetType) + { + Reference <XPropertySetInfo > xInfo(xSet->getPropertySetInfo()); + if (xInfo->hasPropertyByName(PROPERTY_ISBOOKMARKABLE)) + { + m_bIsBookmarkable = ::comphelper::getBOOL(xSet->getPropertyValue(PROPERTY_ISBOOKMARKABLE)); + OSL_ENSURE( !m_bIsBookmarkable || Reference< XRowLocate >(m_xDelegatorResultSet, UNO_QUERY).is(), + "OResultSet::OResultSet: aggregate is inconsistent in it's bookmarkable attribute!" ); + m_bIsBookmarkable = m_bIsBookmarkable && Reference< XRowLocate >(m_xDelegatorResultSet, UNO_QUERY).is(); + } + } + } + catch(Exception&) + { + } +} + +//-------------------------------------------------------------------------- +OResultSet::~OResultSet() +{ + m_pColumns->acquire(); + m_pColumns->disposing(); + delete m_pColumns; + + DBG_DTOR(OResultSet, NULL); +} + +// com::sun::star::lang::XTypeProvider +//-------------------------------------------------------------------------- +Sequence< Type > OResultSet::getTypes() throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getTypes" ); + OTypeCollection aTypes(::getCppuType( (const Reference< XPropertySet > *)0 ), + OResultSetBase::getTypes()); + + return aTypes.getTypes(); +} + +//-------------------------------------------------------------------------- +Sequence< sal_Int8 > OResultSet::getImplementationId() throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getImplementationId" ); + static OImplementationId * pId = 0; + if (! pId) + { + MutexGuard aGuard( Mutex::getGlobalMutex() ); + if (! pId) + { + static OImplementationId aId; + pId = &aId; + } + } + return pId->getImplementationId(); +} + +// com::sun::star::uno::XInterface +//-------------------------------------------------------------------------- +Any OResultSet::queryInterface( const Type & rType ) throw (RuntimeException) +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::queryInterface" ); + Any aIface = OResultSetBase::queryInterface( rType ); + if (!aIface.hasValue()) + aIface = ::cppu::queryInterface( + rType, + static_cast< XPropertySet * >( this )); + + return aIface; +} + +//-------------------------------------------------------------------------- +void OResultSet::acquire() throw () +{ + OResultSetBase::acquire(); +} + +//-------------------------------------------------------------------------- +void OResultSet::release() throw () +{ + OResultSetBase::release(); +} + + +// OResultSetBase +//------------------------------------------------------------------------------ +void OResultSet::disposing() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::disposing" ); + OPropertySetHelper::disposing(); + + MutexGuard aGuard(m_aMutex); + + // free the columns + m_pColumns->disposing(); + + // close the pending result set + Reference< XCloseable > (m_xDelegatorResultSet, UNO_QUERY)->close(); + + m_xDelegatorResultSet = NULL; + m_xDelegatorRow = NULL; + m_xDelegatorRowUpdate = NULL; + + m_aStatement = Reference< XInterface >(); +} + +// XCloseable +//------------------------------------------------------------------------------ +void OResultSet::close(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::close" ); + { + MutexGuard aGuard( m_aMutex ); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + } + dispose(); +} + +// XServiceInfo +//------------------------------------------------------------------------------ +rtl::OUString OResultSet::getImplementationName( ) throw(RuntimeException) +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getImplementationName" ); + return rtl::OUString::createFromAscii("com.sun.star.sdb.OResultSet"); +} + +//------------------------------------------------------------------------------ +sal_Bool OResultSet::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException) +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::supportsService" ); + return ::comphelper::findValue(getSupportedServiceNames(), _rServiceName, sal_True).getLength() != 0; +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > OResultSet::getSupportedServiceNames( ) throw (RuntimeException) +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getSupportedServiceNames" ); + Sequence< ::rtl::OUString > aSNS( 2 ); + aSNS[0] = SERVICE_SDBC_RESULTSET; + aSNS[1] = SERVICE_SDB_RESULTSET; + return aSNS; +} + +// com::sun::star::beans::XPropertySet +//------------------------------------------------------------------------------ +Reference< XPropertySetInfo > OResultSet::getPropertySetInfo() throw (RuntimeException) +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getPropertySetInfo" ); + return createPropertySetInfo( getInfoHelper() ) ; +} + +// comphelper::OPropertyArrayUsageHelper +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper* OResultSet::createArrayHelper( ) const +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::createArrayHelper" ); + BEGIN_PROPERTY_HELPER(6) + DECL_PROP1(CURSORNAME, ::rtl::OUString, READONLY); + DECL_PROP0(FETCHDIRECTION, sal_Int32); + DECL_PROP0(FETCHSIZE, sal_Int32); + DECL_PROP1_BOOL(ISBOOKMARKABLE, READONLY); + DECL_PROP1(RESULTSETCONCURRENCY, sal_Int32, READONLY); + DECL_PROP1(RESULTSETTYPE, sal_Int32, READONLY); + END_PROPERTY_HELPER(); +} + +// cppu::OPropertySetHelper +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper& OResultSet::getInfoHelper() +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getInfoHelper" ); + return *getArrayHelper(); +} + +//------------------------------------------------------------------------------ +sal_Bool OResultSet::convertFastPropertyValue(Any & rConvertedValue, Any & rOldValue, sal_Int32 nHandle, const Any& rValue ) throw( IllegalArgumentException ) +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::convertFastPropertyValue" ); + // be lazy ... + rConvertedValue = rValue; + getFastPropertyValue( rOldValue, nHandle ); + return sal_True; +} + +//------------------------------------------------------------------------------ +void OResultSet::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue ) throw (Exception) +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::setFastPropertyValue_NoBroadcast" ); + // set it for the driver result set + Reference< XPropertySet > xSet(m_xDelegatorResultSet, UNO_QUERY); + switch (nHandle) + { + case PROPERTY_ID_FETCHDIRECTION: + xSet->setPropertyValue(PROPERTY_FETCHDIRECTION, rValue); + break; + case PROPERTY_ID_FETCHSIZE: + xSet->setPropertyValue(PROPERTY_FETCHSIZE, rValue); + break; + default: + DBG_ERROR("unknown Property"); + } +} + +//------------------------------------------------------------------------------ +void OResultSet::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getFastPropertyValue" ); + switch (nHandle) + { + case PROPERTY_ID_ISBOOKMARKABLE: + { + sal_Bool bVal = m_bIsBookmarkable; + rValue.setValue(&bVal, getBooleanCppuType()); + } break; + default: + { + // get the property name + ::rtl::OUString aPropName; + sal_Int16 nAttributes; + const_cast<OResultSet*>(this)->getInfoHelper(). + fillPropertyMembersByHandle(&aPropName, &nAttributes, nHandle); + OSL_ENSURE(aPropName.getLength(), "property not found?"); + + // now read the value + rValue = Reference< XPropertySet >(m_xDelegatorResultSet, UNO_QUERY)->getPropertyValue(aPropName); + } + } +} + +// XWarningsSupplier +//------------------------------------------------------------------------------ +Any OResultSet::getWarnings(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getWarnings" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + return m_aWarnings.getWarnings(); +} + +//------------------------------------------------------------------------------ +void OResultSet::clearWarnings(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::clearWarnings" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + m_aWarnings.clearWarnings(); +} + +// ::com::sun::star::sdbc::XResultSetMetaDataSupplier +//------------------------------------------------------------------------------ +Reference< XResultSetMetaData > OResultSet::getMetaData(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getMetaData" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return Reference< XResultSetMetaDataSupplier >(m_xDelegatorResultSet, UNO_QUERY)->getMetaData(); +} + +// ::com::sun::star::sdbc::XColumnLocate +//------------------------------------------------------------------------------ +sal_Int32 OResultSet::findColumn(const rtl::OUString& columnName) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::findColumn" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return Reference< XColumnLocate >(m_xDelegatorResultSet, UNO_QUERY)->findColumn(columnName); +} + +//------------------------------------------------------------------------------ +namespace +{ + static Reference< XDatabaseMetaData > lcl_getDBMetaDataFromStatement_nothrow( const Reference< XInterface >& _rxStatement ) + { + Reference< XDatabaseMetaData > xDBMetaData; + try + { + Reference< XStatement > xStatement( _rxStatement, UNO_QUERY ); + Reference< XPreparedStatement > xPreparedStatement( _rxStatement, UNO_QUERY ); + Reference< XConnection > xConn; + if ( xStatement.is() ) + xConn = xStatement->getConnection(); + else if ( xPreparedStatement.is() ) + xConn = xPreparedStatement->getConnection(); + if ( xConn.is() ) + xDBMetaData = xConn->getMetaData(); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + return xDBMetaData; + } +} +// ::com::sun::star::sdbcx::XColumnsSupplier +//------------------------------------------------------------------------------ +Reference< ::com::sun::star::container::XNameAccess > OResultSet::getColumns(void) throw( RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getColumns" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + // do we have to populate the columns + if (!m_pColumns->isInitialized()) + { + // get the metadata + Reference< XResultSetMetaData > xMetaData = Reference< XResultSetMetaDataSupplier >(m_xDelegatorResultSet, UNO_QUERY)->getMetaData(); + + sal_Int32 nColCount = 0; + // do we have columns + try + { + Reference< XDatabaseMetaData > xDBMetaData( lcl_getDBMetaDataFromStatement_nothrow( getStatement() ) ); + nColCount = xMetaData->getColumnCount(); + + for ( sal_Int32 i = 0; i < nColCount; ++i) + { + // retrieve the name of the column + rtl::OUString sName = xMetaData->getColumnName(i + 1); + ODataColumn* pColumn = new ODataColumn(xMetaData, m_xDelegatorRow, m_xDelegatorRowUpdate, i + 1, xDBMetaData); + + // don't silently assume that the name is unique - result set implementations + // are allowed to return duplicate names, but we are required to have + // unique column names + if ( m_pColumns->hasByName( sName ) ) + sName = ::dbtools::createUniqueName( m_pColumns, sName ); + + m_pColumns->append( sName, pColumn ); + } + } + catch ( const SQLException& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + m_pColumns->setInitialized(); + + #if OSL_DEBUG_LEVEL > 0 + // some sanity checks. Especially in case we auto-adjusted the column names above, + // this might be reasonable + try + { + const Reference< XNameAccess > xColNames( static_cast< XNameAccess* >( m_pColumns ), UNO_SET_THROW ); + const Sequence< ::rtl::OUString > aNames( xColNames->getElementNames() ); + OSL_POSTCOND( aNames.getLength() == nColCount, + "OResultSet::getColumns: invalid column count!" ); + for ( const ::rtl::OUString* pName = aNames.getConstArray(); + pName != aNames.getConstArray() + aNames.getLength(); + ++pName + ) + { + Reference< XPropertySet > xColProps( xColNames->getByName( *pName ), UNO_QUERY_THROW ); + ::rtl::OUString sName; + OSL_VERIFY( xColProps->getPropertyValue( PROPERTY_NAME ) >>= sName ); + OSL_POSTCOND( sName == *pName, "OResultSet::getColumns: invalid column name!" ); + } + + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + #endif + } + return m_pColumns; +} + +// ::com::sun::star::sdbc::XRow +//------------------------------------------------------------------------------ +sal_Bool OResultSet::wasNull(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::wasNull" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorRow->wasNull(); +} +//------------------------------------------------------------------------------ +rtl::OUString OResultSet::getString(sal_Int32 columnIndex) throw( SQLException, RuntimeException ) +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getString" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorRow->getString(columnIndex); +} +//------------------------------------------------------------------------------ +sal_Bool OResultSet::getBoolean(sal_Int32 columnIndex) throw( SQLException, RuntimeException ) +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getBoolean" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorRow->getBoolean(columnIndex); +} +//------------------------------------------------------------------------------ +sal_Int8 OResultSet::getByte(sal_Int32 columnIndex) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getByte" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorRow->getByte(columnIndex); +} +//------------------------------------------------------------------------------ +sal_Int16 OResultSet::getShort(sal_Int32 columnIndex) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getShort" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorRow->getShort(columnIndex); +} +//------------------------------------------------------------------------------ +sal_Int32 OResultSet::getInt(sal_Int32 columnIndex) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getInt" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorRow->getInt(columnIndex); +} +//------------------------------------------------------------------------------ +sal_Int64 OResultSet::getLong(sal_Int32 columnIndex) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getLong" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorRow->getLong(columnIndex); +} +//------------------------------------------------------------------------------ +float OResultSet::getFloat(sal_Int32 columnIndex) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getFloat" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorRow->getFloat(columnIndex); +} +//------------------------------------------------------------------------------ +double OResultSet::getDouble(sal_Int32 columnIndex) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getDouble" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorRow->getDouble(columnIndex); +} +//------------------------------------------------------------------------------ +Sequence< sal_Int8 > OResultSet::getBytes(sal_Int32 columnIndex) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getBytes" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorRow->getBytes(columnIndex); +} +//------------------------------------------------------------------------------ +::com::sun::star::util::Date OResultSet::getDate(sal_Int32 columnIndex) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getDate" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorRow->getDate(columnIndex); +} +//------------------------------------------------------------------------------ +::com::sun::star::util::Time OResultSet::getTime(sal_Int32 columnIndex) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getTime" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorRow->getTime(columnIndex); +} +//------------------------------------------------------------------------------ +::com::sun::star::util::DateTime OResultSet::getTimestamp(sal_Int32 columnIndex) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getTimestamp" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorRow->getTimestamp(columnIndex); +} +//------------------------------------------------------------------------------ +Reference< ::com::sun::star::io::XInputStream > OResultSet::getBinaryStream(sal_Int32 columnIndex) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getBinaryStream" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorRow->getBinaryStream(columnIndex); +} +//------------------------------------------------------------------------------ +Reference< ::com::sun::star::io::XInputStream > OResultSet::getCharacterStream(sal_Int32 columnIndex) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getCharacterStream" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorRow->getCharacterStream(columnIndex); +} +//------------------------------------------------------------------------------ +Any OResultSet::getObject(sal_Int32 columnIndex, const Reference< ::com::sun::star::container::XNameAccess > & typeMap) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getObject" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorRow->getObject(columnIndex, typeMap); +} +//------------------------------------------------------------------------------ +Reference< XRef > OResultSet::getRef(sal_Int32 columnIndex) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getRef" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorRow->getRef(columnIndex); +} +//------------------------------------------------------------------------------ +Reference< XBlob > OResultSet::getBlob(sal_Int32 columnIndex) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getBlob" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorRow->getBlob(columnIndex); +} +//------------------------------------------------------------------------------ +Reference< XClob > OResultSet::getClob(sal_Int32 columnIndex) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getClob" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorRow->getClob(columnIndex); +} +//------------------------------------------------------------------------------ +Reference< XArray > OResultSet::getArray(sal_Int32 columnIndex) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getArray" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorRow->getArray(columnIndex); +} + +// ::com::sun::star::sdbc::XRowUpdate +//------------------------------------------------------------------------------ +void OResultSet::updateNull(sal_Int32 columnIndex) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::updateNull" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkReadOnly(); + + m_xDelegatorRowUpdate->updateNull(columnIndex); +} + +//------------------------------------------------------------------------------ +void OResultSet::updateBoolean(sal_Int32 columnIndex, sal_Bool x) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::updateBoolean" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkReadOnly(); + + m_xDelegatorRowUpdate->updateBoolean(columnIndex, x); +} +//------------------------------------------------------------------------------ +void OResultSet::updateByte(sal_Int32 columnIndex, sal_Int8 x) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::updateByte" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkReadOnly(); + + m_xDelegatorRowUpdate->updateByte(columnIndex, x); +} +//------------------------------------------------------------------------------ +void OResultSet::updateShort(sal_Int32 columnIndex, sal_Int16 x) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::updateShort" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkReadOnly(); + + m_xDelegatorRowUpdate->updateShort(columnIndex, x); +} +//------------------------------------------------------------------------------ +void OResultSet::updateInt(sal_Int32 columnIndex, sal_Int32 x) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::updateInt" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkReadOnly(); + + m_xDelegatorRowUpdate->updateInt(columnIndex, x); +} +//------------------------------------------------------------------------------ +void OResultSet::updateLong(sal_Int32 columnIndex, sal_Int64 x) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::updateLong" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkReadOnly(); + + m_xDelegatorRowUpdate->updateLong(columnIndex, x); +} +//------------------------------------------------------------------------------ +void OResultSet::updateFloat(sal_Int32 columnIndex, float x) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::updateFloat" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkReadOnly(); + + m_xDelegatorRowUpdate->updateFloat(columnIndex, x); +} +//------------------------------------------------------------------------------ +void OResultSet::updateDouble(sal_Int32 columnIndex, double x) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::updateDouble" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkReadOnly(); + + m_xDelegatorRowUpdate->updateDouble(columnIndex, x); +} +//------------------------------------------------------------------------------ +void OResultSet::updateString(sal_Int32 columnIndex, const rtl::OUString& x) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::updateString" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkReadOnly(); + + m_xDelegatorRowUpdate->updateString(columnIndex, x); +} +//------------------------------------------------------------------------------ +void OResultSet::updateBytes(sal_Int32 columnIndex, const Sequence< sal_Int8 >& x) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::updateBytes" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkReadOnly(); + + m_xDelegatorRowUpdate->updateBytes(columnIndex, x); +} +//------------------------------------------------------------------------------ +void OResultSet::updateDate(sal_Int32 columnIndex, const ::com::sun::star::util::Date& x) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::updateDate" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkReadOnly(); + + m_xDelegatorRowUpdate->updateDate(columnIndex, x); +} +//------------------------------------------------------------------------------ +void OResultSet::updateTime(sal_Int32 columnIndex, const ::com::sun::star::util::Time& x) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::updateTime" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkReadOnly(); + + m_xDelegatorRowUpdate->updateTime(columnIndex, x); +} +//------------------------------------------------------------------------------ +void OResultSet::updateTimestamp(sal_Int32 columnIndex, const ::com::sun::star::util::DateTime& x) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::updateTimestamp" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkReadOnly(); + + m_xDelegatorRowUpdate->updateTimestamp(columnIndex, x); +} +//------------------------------------------------------------------------------ +void OResultSet::updateBinaryStream(sal_Int32 columnIndex, const Reference< ::com::sun::star::io::XInputStream > & x, sal_Int32 length) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::updateBinaryStream" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkReadOnly(); + + m_xDelegatorRowUpdate->updateBinaryStream(columnIndex, x, length); +} +//------------------------------------------------------------------------------ +void OResultSet::updateCharacterStream(sal_Int32 columnIndex, const Reference< ::com::sun::star::io::XInputStream > & x, sal_Int32 length) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::updateCharacterStream" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkReadOnly(); + + m_xDelegatorRowUpdate->updateCharacterStream(columnIndex, x, length); +} +//------------------------------------------------------------------------------ +void OResultSet::updateNumericObject(sal_Int32 columnIndex, const Any& x, sal_Int32 scale) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::updateNumericObject" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkReadOnly(); + + m_xDelegatorRowUpdate->updateNumericObject(columnIndex, x, scale); +} + +//------------------------------------------------------------------------------ +void OResultSet::updateObject(sal_Int32 columnIndex, const Any& x) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::updateObject" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkReadOnly(); + + m_xDelegatorRowUpdate->updateObject(columnIndex, x); +} + +// ::com::sun::star::sdbc::XResultSet +//------------------------------------------------------------------------------ +sal_Bool OResultSet::next(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::next" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorResultSet->next(); +} + +//------------------------------------------------------------------------------ +sal_Bool OResultSet::isBeforeFirst(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::isBeforeFirst" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorResultSet->isBeforeFirst(); +} + +//------------------------------------------------------------------------------ +sal_Bool OResultSet::isAfterLast(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::isAfterLast" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorResultSet->isAfterLast(); +} + +//------------------------------------------------------------------------------ +sal_Bool OResultSet::isFirst(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::isFirst" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorResultSet->isFirst(); +} + +//------------------------------------------------------------------------------ +sal_Bool OResultSet::isLast(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::isLast" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorResultSet->isLast(); +} + +//------------------------------------------------------------------------------ +void OResultSet::beforeFirst(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::beforeFirst" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + m_xDelegatorResultSet->beforeFirst(); +} + +//------------------------------------------------------------------------------ +void OResultSet::afterLast(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::afterLast" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + m_xDelegatorResultSet->afterLast(); +} + +//------------------------------------------------------------------------------ +sal_Bool OResultSet::first(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::first" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorResultSet->first(); +} + +//------------------------------------------------------------------------------ +sal_Bool OResultSet::last(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::last" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorResultSet->last(); +} + +//------------------------------------------------------------------------------ +sal_Int32 OResultSet::getRow(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getRow" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorResultSet->getRow(); +} + +//------------------------------------------------------------------------------ +sal_Bool OResultSet::absolute(sal_Int32 row) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::absolute" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorResultSet->absolute(row); +} + +//------------------------------------------------------------------------------ +sal_Bool OResultSet::relative(sal_Int32 rows) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::relative" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorResultSet->relative(rows); +} + +//------------------------------------------------------------------------------ +sal_Bool OResultSet::previous(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::previous" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorResultSet->previous(); +} + +//------------------------------------------------------------------------------ +void OResultSet::refreshRow(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::refreshRow" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + m_xDelegatorResultSet->refreshRow(); +} + +//------------------------------------------------------------------------------ +sal_Bool OResultSet::rowUpdated(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::rowUpdated" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorResultSet->rowUpdated(); +} + +//------------------------------------------------------------------------------ +sal_Bool OResultSet::rowInserted(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::rowInserted" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorResultSet->rowInserted(); +} + +//------------------------------------------------------------------------------ +sal_Bool OResultSet::rowDeleted(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::rowDeleted" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorResultSet->rowDeleted(); +} + +//------------------------------------------------------------------------------ +Reference< XInterface > OResultSet::getStatement(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getStatement" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_aStatement; +} + +// ::com::sun::star::sdbcx::XRowLocate +//------------------------------------------------------------------------------ +Any OResultSet::getBookmark(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getBookmark" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkBookmarkable(); + + return Reference< XRowLocate >(m_xDelegatorResultSet, UNO_QUERY)->getBookmark(); +} + +//------------------------------------------------------------------------------ +sal_Bool OResultSet::moveToBookmark(const Any& bookmark) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::moveToBookmark" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkBookmarkable(); + + return Reference< XRowLocate >(m_xDelegatorResultSet, UNO_QUERY)->moveToBookmark(bookmark); +} + +//------------------------------------------------------------------------------ +sal_Bool OResultSet::moveRelativeToBookmark(const Any& bookmark, sal_Int32 rows) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::moveRelativeToBookmark" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkBookmarkable(); + + return Reference< XRowLocate >(m_xDelegatorResultSet, UNO_QUERY)->moveRelativeToBookmark(bookmark, rows); +} + +//------------------------------------------------------------------------------ +sal_Int32 OResultSet::compareBookmarks(const Any& _first, const Any& _second) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::compareBookmarks" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkBookmarkable(); + + return Reference< XRowLocate >(m_xDelegatorResultSet, UNO_QUERY)->compareBookmarks(_first, _second); +} + +//------------------------------------------------------------------------------ +sal_Bool OResultSet::hasOrderedBookmarks(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::hasOrderedBookmarks" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkBookmarkable(); + + return Reference< XRowLocate >(m_xDelegatorResultSet, UNO_QUERY)->hasOrderedBookmarks(); +} + +//------------------------------------------------------------------------------ +sal_Int32 OResultSet::hashBookmark(const Any& bookmark) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::hashBookmark" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkBookmarkable(); + + return Reference< XRowLocate >(m_xDelegatorResultSet, UNO_QUERY)->hashBookmark(bookmark); +} + +// ::com::sun::star::sdbc::XResultSetUpdate +//------------------------------------------------------------------------------ +void OResultSet::insertRow(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::insertRow" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkReadOnly(); + + m_xDelegatorResultSetUpdate->insertRow(); +} + +//------------------------------------------------------------------------------ +void OResultSet::updateRow(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::updateRow" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkReadOnly(); + + m_xDelegatorResultSetUpdate->updateRow(); +} + +//------------------------------------------------------------------------------ +void OResultSet::deleteRow(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::deleteRow" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkReadOnly(); + + m_xDelegatorResultSetUpdate->deleteRow(); +} + +//------------------------------------------------------------------------------ +void OResultSet::cancelRowUpdates(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::cancelRowUpdates" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkReadOnly(); + + m_xDelegatorResultSetUpdate->cancelRowUpdates(); +} + +//------------------------------------------------------------------------------ +void OResultSet::moveToInsertRow(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::moveToInsertRow" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkReadOnly(); + + m_xDelegatorResultSetUpdate->moveToInsertRow(); +} + +//------------------------------------------------------------------------------ +void OResultSet::moveToCurrentRow(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::moveToCurrentRow" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkReadOnly(); + + m_xDelegatorResultSetUpdate->moveToCurrentRow(); +} + +// ----------------------------------------------------------------------------- +void OResultSet::checkReadOnly() const +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::checkReadOnly" ); + if ( ( m_nResultSetConcurrency == ResultSetConcurrency::READ_ONLY ) + || !m_xDelegatorResultSetUpdate.is() + ) + throwSQLException( "The result set is read-only.", SQL_GENERAL_ERROR, *const_cast< OResultSet* >( this ) ); +} + +// ----------------------------------------------------------------------------- +void OResultSet::checkBookmarkable() const +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::checkBookmarkable" ); + if ( !m_bIsBookmarkable ) + throwSQLException( "The result set does not have bookmark support.", SQL_GENERAL_ERROR, *const_cast< OResultSet* >( this ) ); +} +// ----------------------------------------------------------------------------- + diff --git a/dbaccess/source/core/api/resultset.hxx b/dbaccess/source/core/api/resultset.hxx new file mode 100644 index 000000000000..cc765919c313 --- /dev/null +++ b/dbaccess/source/core/api/resultset.hxx @@ -0,0 +1,278 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 _DBA_COREAPI_RESULTSET_HXX_ +#define _DBA_COREAPI_RESULTSET_HXX_ + +#ifndef _DBA_COREAPI_COLUMN_HXX_ +#include "column.hxx" +#endif +#ifndef DBTOOLS_WARNINGSCONTAINER_HXX +#include <connectivity/warningscontainer.hxx> +#endif + +#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_ +#include <com/sun/star/lang/XServiceInfo.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XSTATEMENT_HPP_ +#include <com/sun/star/sdbc/XStatement.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XCLOSEABLE_HPP_ +#include <com/sun/star/sdbc/XCloseable.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XRESULTSETMETADATASUPPLIER_HPP_ +#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XWARNINGSSUPPLIER_HPP_ +#include <com/sun/star/sdbc/XWarningsSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBCX_XCOLUMNSSUPPLIER_HPP_ +#include <com/sun/star/sdbcx/XColumnsSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XRESULTSET_HPP_ +#include <com/sun/star/sdbc/XResultSet.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XROW_HPP_ +#include <com/sun/star/sdbc/XRow.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XCOLUMNLOCATE_HPP_ +#include <com/sun/star/sdbc/XColumnLocate.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBCX_XROWLOCATE_HPP_ +#include <com/sun/star/sdbcx/XRowLocate.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XROWUPDATE_HPP_ +#include <com/sun/star/sdbc/XRowUpdate.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XRESULTSETUPDATE_HPP_ +#include <com/sun/star/sdbc/XResultSetUpdate.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_RESULTSETCONCURRENCY_HPP_ +#include <com/sun/star/sdbc/ResultSetConcurrency.hpp> +#endif + +#ifndef _CPPUHELPER_PROPSHLP_HXX +#include <cppuhelper/propshlp.hxx> +#endif +#ifndef _COMPHELPER_PROPERTY_ARRAY_HELPER_HXX_ +#include <comphelper/proparrhlp.hxx> +#endif +#ifndef _OSL_DIAGNOSE_H_ +#include <osl/diagnose.h> +#endif +#ifndef _CPPUHELPER_COMPBASE11_HXX_ +#include <cppuhelper/compbase11.hxx> +#endif +#ifndef _COMPHELPER_BROADCASTHELPER_HXX_ +#include <comphelper/broadcasthelper.hxx> +#endif + +namespace dbaccess +{ + typedef ::cppu::WeakComponentImplHelper11< ::com::sun::star::sdbc::XWarningsSupplier, + ::com::sun::star::sdbc::XResultSet, + ::com::sun::star::sdbc::XResultSetMetaDataSupplier, + ::com::sun::star::sdbc::XRow, + ::com::sun::star::sdbc::XCloseable, + ::com::sun::star::sdbc::XColumnLocate, + ::com::sun::star::sdbcx::XRowLocate, + ::com::sun::star::sdbcx::XColumnsSupplier, + ::com::sun::star::sdbc::XResultSetUpdate, + ::com::sun::star::sdbc::XRowUpdate, + ::com::sun::star::lang::XServiceInfo > OResultSetBase; + + typedef ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface> ONoWeakStatement; + + //************************************************************ + // OResultSet + //************************************************************ + class OResultSet : public comphelper::OBaseMutex, + public OResultSetBase, + public ::cppu::OPropertySetHelper, + public ::comphelper::OPropertyArrayUsageHelper < OResultSet > + { + protected: + ONoWeakStatement m_aStatement; + + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet > m_xDelegatorResultSet; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSetUpdate > m_xDelegatorResultSetUpdate; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRow > m_xDelegatorRow; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowUpdate > m_xDelegatorRowUpdate; + + ::dbtools::WarningsContainer m_aWarnings; + OColumns* m_pColumns; + sal_Int32 m_nResultSetType; + sal_Int32 m_nResultSetConcurrency; + sal_Bool m_bIsBookmarkable : 1; + + public: + OResultSet(const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet >& _xResultSet, + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _xStatement, + sal_Bool _bCaseSensitive); + virtual ~OResultSet(); + + // ::com::sun::star::lang::XTypeProvider + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes() throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() throw (::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::uno::XInterface + virtual ::com::sun::star::uno::Any SAL_CALL queryInterface( const ::com::sun::star::uno::Type & rType ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL acquire() throw(); + virtual void SAL_CALL release() throw(); + + // ::com::sun::star::lang::XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw(::com::sun::star::uno::RuntimeException); + + // ::cppu::OComponentHelper + virtual void SAL_CALL disposing(void); + + // ::com::sun::star::sdbc::XCloseable + virtual void SAL_CALL close( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // 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); + + // comphelper::OPropertyArrayUsageHelper + virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const; + + // cppu::OPropertySetHelper + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(); + + virtual sal_Bool SAL_CALL convertFastPropertyValue( + ::com::sun::star::uno::Any & rConvertedValue, + ::com::sun::star::uno::Any & rOldValue, + sal_Int32 nHandle, + const ::com::sun::star::uno::Any& rValue ) + throw (::com::sun::star::lang::IllegalArgumentException); + virtual void SAL_CALL setFastPropertyValue_NoBroadcast( + sal_Int32 nHandle, + const ::com::sun::star::uno::Any& rValue + ) + throw (::com::sun::star::uno::Exception); + virtual void SAL_CALL getFastPropertyValue( ::com::sun::star::uno::Any& rValue, sal_Int32 nHandle ) const; + + // ::com::sun::star::sdbc::XWarningsSupplier + virtual ::com::sun::star::uno::Any SAL_CALL getWarnings( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL clearWarnings( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbc::XResultSetMetaDataSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSetMetaData > SAL_CALL getMetaData( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbc::XColumnLocate + virtual sal_Int32 SAL_CALL findColumn( const ::rtl::OUString& columnName ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbcx::XColumnsSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > SAL_CALL getColumns( ) throw(::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbc::XRow + virtual sal_Bool SAL_CALL wasNull( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getString( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL getBoolean( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int8 SAL_CALL getByte( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int16 SAL_CALL getShort( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getInt( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int64 SAL_CALL getLong( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual float SAL_CALL getFloat( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual double SAL_CALL getDouble( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getBytes( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::util::Date SAL_CALL getDate( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::util::Time SAL_CALL getTime( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::util::DateTime SAL_CALL getTimestamp( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getBinaryStream( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getCharacterStream( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Any SAL_CALL getObject( sal_Int32 columnIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& typeMap ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRef > SAL_CALL getRef( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XBlob > SAL_CALL getBlob( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XClob > SAL_CALL getClob( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XArray > SAL_CALL getArray( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbc::XResultSet + virtual sal_Bool SAL_CALL next( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isBeforeFirst( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isAfterLast( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isFirst( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isLast( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL beforeFirst( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL afterLast( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL first( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL last( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL absolute( sal_Int32 row ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL relative( sal_Int32 rows ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL previous( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL refreshRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL rowUpdated( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL rowInserted( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL rowDeleted( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL getStatement( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbcx::XRowLocate + virtual ::com::sun::star::uno::Any SAL_CALL getBookmark( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL moveToBookmark( const ::com::sun::star::uno::Any& bookmark ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL moveRelativeToBookmark( const ::com::sun::star::uno::Any& bookmark, sal_Int32 rows ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL compareBookmarks( const ::com::sun::star::uno::Any& first, const ::com::sun::star::uno::Any& second ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL hasOrderedBookmarks( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL hashBookmark( const ::com::sun::star::uno::Any& bookmark ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbc::XResultSetUpdate + virtual void SAL_CALL insertRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL deleteRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL cancelRowUpdates( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL moveToInsertRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL moveToCurrentRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbc::XRowUpdate + virtual void SAL_CALL updateNull( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateBoolean( sal_Int32 columnIndex, sal_Bool x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateByte( sal_Int32 columnIndex, sal_Int8 x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateShort( sal_Int32 columnIndex, sal_Int16 x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateInt( sal_Int32 columnIndex, sal_Int32 x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateLong( sal_Int32 columnIndex, sal_Int64 x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateFloat( sal_Int32 columnIndex, float x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateDouble( sal_Int32 columnIndex, double x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateString( sal_Int32 columnIndex, const ::rtl::OUString& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateBytes( sal_Int32 columnIndex, const ::com::sun::star::uno::Sequence< sal_Int8 >& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateDate( sal_Int32 columnIndex, const ::com::sun::star::util::Date& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateTime( sal_Int32 columnIndex, const ::com::sun::star::util::Time& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateTimestamp( sal_Int32 columnIndex, const ::com::sun::star::util::DateTime& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateBinaryStream( sal_Int32 columnIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateCharacterStream( sal_Int32 columnIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateObject( sal_Int32 columnIndex, const ::com::sun::star::uno::Any& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateNumericObject( sal_Int32 columnIndex, const ::com::sun::star::uno::Any& x, sal_Int32 scale ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + protected: + void checkReadOnly() const; + void checkBookmarkable() const; + + private: + using ::cppu::OPropertySetHelper::getFastPropertyValue; + }; +} +#endif // _DBA_COREAPI_RESULTSET_HXX_ + diff --git a/dbaccess/source/core/api/statement.cxx b/dbaccess/source/core/api/statement.cxx new file mode 100644 index 000000000000..05ef557f2582 --- /dev/null +++ b/dbaccess/source/core/api/statement.cxx @@ -0,0 +1,696 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" +#ifndef _DBA_COREAPI_STATEMENT_HXX_ +#include <statement.hxx> +#endif +#ifndef _DBA_COREAPI_RESULTSET_HXX_ +#include <resultset.hxx> +#endif +#ifndef DBACCESS_SHARED_DBASTRINGS_HRC +#include "dbastrings.hrc" +#endif +#ifndef _COM_SUN_STAR_LANG_DISPOSEDEXCEPTION_HPP_ +#include <com/sun/star/lang/DisposedException.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XDATABASEMETADATA_HPP_ +#include <com/sun/star/sdbc/XDatabaseMetaData.hpp> +#endif +#ifndef _COMPHELPER_SEQUENCE_HXX_ +#include <comphelper/sequence.hxx> +#endif +#ifndef _CPPUHELPER_TYPEPROVIDER_HXX_ +#include <cppuhelper/typeprovider.hxx> +#endif +#ifndef _COMPHELPER_PROPERTY_HXX_ +#include <comphelper/property.hxx> +#endif +#ifndef _COMPHELPER_TYPES_HXX_ +#include <comphelper/types.hxx> +#endif +#ifndef _TOOLS_DEBUG_HXX //autogen +#include <tools/debug.hxx> +#endif +#ifndef TOOLS_DIAGNOSE_EX_H +#include <tools/diagnose_ex.h> +#endif +#ifndef _DBHELPER_DBEXCEPTION_HXX_ +#include <connectivity/dbexception.hxx> +#endif +#include <rtl/logfile.hxx> + +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::cppu; +using namespace ::osl; +using namespace dbaccess; +using namespace dbtools; + +DBG_NAME(OStatementBase) + +//-------------------------------------------------------------------------- +OStatementBase::OStatementBase(const Reference< XConnection > & _xConn, + const Reference< XInterface > & _xStatement) + :OSubComponent(m_aMutex, _xConn) + ,OPropertySetHelper(OComponentHelper::rBHelper) + ,m_bUseBookmarks( sal_False ) + ,m_bEscapeProcessing( sal_True ) + +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::OStatementBase" ); + DBG_CTOR(OStatementBase, NULL); + OSL_ENSURE(_xStatement.is() ,"Statement is NULL!"); + m_xAggregateAsSet.set(_xStatement,UNO_QUERY); + m_xAggregateAsCancellable = Reference< ::com::sun::star::util::XCancellable > (m_xAggregateAsSet, UNO_QUERY); +} + +//-------------------------------------------------------------------------- +OStatementBase::~OStatementBase() +{ + DBG_DTOR(OStatementBase, NULL); +} + +// com::sun::star::lang::XTypeProvider +//-------------------------------------------------------------------------- +Sequence< Type > OStatementBase::getTypes() throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::getTypes" ); + OTypeCollection aTypes(::getCppuType( (const Reference< XPropertySet > *)0 ), + ::getCppuType( (const Reference< XWarningsSupplier > *)0 ), + ::getCppuType( (const Reference< XCloseable > *)0 ), + ::getCppuType( (const Reference< XMultipleResults > *)0 ), + ::getCppuType( (const Reference< ::com::sun::star::util::XCancellable > *)0 ), + OSubComponent::getTypes() ); + Reference< XGeneratedResultSet > xGRes(m_xAggregateAsSet, UNO_QUERY); + if ( xGRes.is() ) + aTypes = OTypeCollection(::getCppuType( (const Reference< XGeneratedResultSet > *)0 ),aTypes.getTypes()); + Reference< XPreparedBatchExecution > xPreparedBatchExecution(m_xAggregateAsSet, UNO_QUERY); + if ( xPreparedBatchExecution.is() ) + aTypes = OTypeCollection(::getCppuType( (const Reference< XPreparedBatchExecution > *)0 ),aTypes.getTypes()); + + return aTypes.getTypes(); +} + +// com::sun::star::uno::XInterface +//-------------------------------------------------------------------------- +Any OStatementBase::queryInterface( const Type & rType ) throw (RuntimeException) +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::queryInterface" ); + Any aIface = OSubComponent::queryInterface( rType ); + if (!aIface.hasValue()) + { + aIface = ::cppu::queryInterface( + rType, + static_cast< XPropertySet * >( this ), + static_cast< XWarningsSupplier * >( this ), + static_cast< XCloseable * >( this ), + static_cast< XMultipleResults * >( this ), + static_cast< ::com::sun::star::util::XCancellable * >( this )); + if ( !aIface.hasValue() ) + { + Reference< XGeneratedResultSet > xGRes(m_xAggregateAsSet, UNO_QUERY); + if ( ::getCppuType( (const Reference< XGeneratedResultSet > *)0 ) == rType && xGRes.is() ) + aIface = ::cppu::queryInterface(rType,static_cast< XGeneratedResultSet * >( this )); + } // if ( !aIface.hasValue() ) + if ( !aIface.hasValue() ) + { + Reference< XPreparedBatchExecution > xGRes(m_xAggregateAsSet, UNO_QUERY); + if ( ::getCppuType( (const Reference< XPreparedBatchExecution > *)0 ) == rType && xGRes.is() ) + aIface = ::cppu::queryInterface(rType,static_cast< XPreparedBatchExecution * >( this )); + } + } + return aIface; +} + +//-------------------------------------------------------------------------- +void OStatementBase::acquire() throw () +{ + OSubComponent::acquire(); +} + +//-------------------------------------------------------------------------- +void OStatementBase::release() throw () +{ + OSubComponent::release(); +} + +//------------------------------------------------------------------------------ +void OStatementBase::disposeResultSet() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::disposeResultSet" ); + // free the cursor if alive + Reference< XComponent > xComp(m_aResultSet.get(), UNO_QUERY); + if (xComp.is()) + xComp->dispose(); + m_aResultSet = NULL; +} + +// OComponentHelper +//------------------------------------------------------------------------------ +void OStatementBase::disposing() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::disposing" ); + OPropertySetHelper::disposing(); + + MutexGuard aGuard(m_aMutex); + + // free pending results + disposeResultSet(); + + // free the original statement + { + MutexGuard aCancelGuard(m_aCancelMutex); + m_xAggregateAsCancellable = NULL; + } + + if ( m_xAggregateAsSet.is() ) + { + try + { + Reference< XCloseable > (m_xAggregateAsSet, UNO_QUERY)->close(); + } + catch(RuntimeException& ) + {// don't care for anymore + } + } + m_xAggregateAsSet = NULL; + + // free the parent at last + OSubComponent::disposing(); +} + +// XCloseable +//------------------------------------------------------------------------------ +void OStatementBase::close(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::close" ); + { + MutexGuard aGuard( m_aMutex ); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + } + dispose(); +} + +// OPropertySetHelper +//------------------------------------------------------------------------------ +Reference< XPropertySetInfo > OStatementBase::getPropertySetInfo() throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::getPropertySetInfo" ); + return createPropertySetInfo( getInfoHelper() ) ; +} + +// comphelper::OPropertyArrayUsageHelper +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper* OStatementBase::createArrayHelper( ) const +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::createArrayHelper" ); + BEGIN_PROPERTY_HELPER(10) + DECL_PROP0(CURSORNAME, ::rtl::OUString); + DECL_PROP0_BOOL(ESCAPE_PROCESSING); + DECL_PROP0(FETCHDIRECTION, sal_Int32); + DECL_PROP0(FETCHSIZE, sal_Int32); + DECL_PROP0(MAXFIELDSIZE, sal_Int32); + DECL_PROP0(MAXROWS, sal_Int32); + DECL_PROP0(QUERYTIMEOUT, sal_Int32); + DECL_PROP0(RESULTSETCONCURRENCY, sal_Int32); + DECL_PROP0(RESULTSETTYPE, sal_Int32); + DECL_PROP0_BOOL(USEBOOKMARKS); + END_PROPERTY_HELPER(); +} + +// cppu::OPropertySetHelper +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper& OStatementBase::getInfoHelper() +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::getInfoHelper" ); + return *getArrayHelper(); +} + +//------------------------------------------------------------------------------ +sal_Bool OStatementBase::convertFastPropertyValue( Any & rConvertedValue, Any & rOldValue, sal_Int32 nHandle, const Any& rValue ) throw( IllegalArgumentException ) +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::convertFastPropertyValue" ); + sal_Bool bModified(sal_False); + switch (nHandle) + { + case PROPERTY_ID_USEBOOKMARKS: + bModified = ::comphelper::tryPropertyValue( rConvertedValue, rOldValue, rValue, m_bUseBookmarks ); + break; + + case PROPERTY_ID_ESCAPE_PROCESSING: + bModified = ::comphelper::tryPropertyValue( rConvertedValue, rOldValue, rValue, m_bEscapeProcessing ); + break; + + default: + if ( m_xAggregateAsSet.is() ) + { + // get the property name + ::rtl::OUString sPropName; + getInfoHelper().fillPropertyMembersByHandle( &sPropName, NULL, nHandle ); + + // now set the value + Any aCurrentValue = m_xAggregateAsSet->getPropertyValue( sPropName ); + if ( aCurrentValue != rValue ) + { + rOldValue = aCurrentValue; + rConvertedValue = rValue; + bModified = sal_True; + } + } + break; + } + return bModified; +} + +//------------------------------------------------------------------------------ +void OStatementBase::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue ) throw (Exception) +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::setFastPropertyValue_NoBroadcast" ); + switch ( nHandle ) + { + case PROPERTY_ID_USEBOOKMARKS: + { + m_bUseBookmarks = ::comphelper::getBOOL( rValue ); + if ( m_xAggregateAsSet.is() && m_xAggregateAsSet->getPropertySetInfo()->hasPropertyByName( PROPERTY_USEBOOKMARKS ) ) + m_xAggregateAsSet->setPropertyValue( PROPERTY_USEBOOKMARKS, rValue ); + } + break; + + case PROPERTY_ID_ESCAPE_PROCESSING: + m_bEscapeProcessing = ::comphelper::getBOOL( rValue ); + if ( m_xAggregateAsSet.is() ) + m_xAggregateAsSet->setPropertyValue( PROPERTY_ESCAPE_PROCESSING, rValue ); + break; + + default: + if ( m_xAggregateAsSet.is() ) + { + ::rtl::OUString sPropName; + getInfoHelper().fillPropertyMembersByHandle( &sPropName, NULL, nHandle ); + m_xAggregateAsSet->setPropertyValue( sPropName, rValue ); + } + break; + } +} + +//------------------------------------------------------------------------------ +void OStatementBase::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::getFastPropertyValue" ); + switch (nHandle) + { + case PROPERTY_ID_USEBOOKMARKS: + rValue <<= m_bUseBookmarks; + break; + + case PROPERTY_ID_ESCAPE_PROCESSING: + // don't rely on our aggregate - if it implements this wrong, and always returns + // TRUE here, then we would loop in impl_doEscapeProcessing_nothrow + rValue <<= m_bEscapeProcessing; + break; + + default: + if ( m_xAggregateAsSet.is() ) + { + ::rtl::OUString sPropName; + const_cast< OStatementBase* >( this )->getInfoHelper().fillPropertyMembersByHandle( &sPropName, NULL, nHandle ); + rValue = m_xAggregateAsSet->getPropertyValue( sPropName ); + } + break; + } +} + +// XWarningsSupplier +//------------------------------------------------------------------------------ +Any OStatementBase::getWarnings(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::getWarnings" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + return Reference< XWarningsSupplier >(m_xAggregateAsSet, UNO_QUERY)->getWarnings(); +} + +//------------------------------------------------------------------------------ +void OStatementBase::clearWarnings(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::clearWarnings" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + Reference< XWarningsSupplier >(m_xAggregateAsSet, UNO_QUERY)->clearWarnings(); +} + +// ::com::sun::star::util::XCancellable +//------------------------------------------------------------------------------ +void OStatementBase::cancel(void) throw( RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::cancel" ); + // no blocking as cancel is typically called from a different thread + ClearableMutexGuard aCancelGuard(m_aCancelMutex); + if (m_xAggregateAsCancellable.is()) + m_xAggregateAsCancellable->cancel(); + // else do nothing +} + +// XMultipleResults +//------------------------------------------------------------------------------ +Reference< XResultSet > SAL_CALL OStatementBase::getResultSet( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::getResultSet" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + // first check the meta data + Reference<XDatabaseMetaData> xMeta = Reference< XConnection > (m_xParent, UNO_QUERY)->getMetaData(); + if (!xMeta.is() && !xMeta->supportsMultipleResultSets()) + throwFunctionSequenceException(*this); + + return Reference< XMultipleResults >(m_xAggregateAsSet, UNO_QUERY)->getResultSet(); +} + +//------------------------------------------------------------------------------ +sal_Int32 SAL_CALL OStatementBase::getUpdateCount( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::getUpdateCount" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + // first check the meta data + Reference<XDatabaseMetaData> xMeta = Reference< XConnection > (m_xParent, UNO_QUERY)->getMetaData(); + if (!xMeta.is() && !xMeta->supportsMultipleResultSets()) + throwFunctionSequenceException(*this); + + return Reference< XMultipleResults >(m_xAggregateAsSet, UNO_QUERY)->getUpdateCount(); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL OStatementBase::getMoreResults( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::getMoreResults" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + // first check the meta data + Reference<XDatabaseMetaData> xMeta = Reference< XConnection > (m_xParent, UNO_QUERY)->getMetaData(); + if (!xMeta.is() && !xMeta->supportsMultipleResultSets()) + throwFunctionSequenceException(*this); + throwFunctionSequenceException(*this); + + // free the previous results + disposeResultSet(); + + return Reference< XMultipleResults >(m_xAggregateAsSet, UNO_QUERY)->getMoreResults(); +} + +// XPreparedBatchExecution +//------------------------------------------------------------------------------ +void SAL_CALL OStatementBase::addBatch( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::addBatch" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + // first check the meta data + Reference<XDatabaseMetaData> xMeta = Reference< XConnection > (m_xParent, UNO_QUERY)->getMetaData(); + if (!xMeta.is() && !xMeta->supportsBatchUpdates()) + throwFunctionSequenceException(*this); + + Reference< XPreparedBatchExecution >(m_xAggregateAsSet, UNO_QUERY)->addBatch(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OStatementBase::clearBatch( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::clearBatch" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + // first check the meta data + Reference<XDatabaseMetaData> xMeta = Reference< XConnection > (m_xParent, UNO_QUERY)->getMetaData(); + if (!xMeta.is() && !xMeta->supportsBatchUpdates()) + throwFunctionSequenceException(*this); + + Reference< XPreparedBatchExecution >(m_xAggregateAsSet, UNO_QUERY)->clearBatch(); +} + +//------------------------------------------------------------------------------ +Sequence< sal_Int32 > SAL_CALL OStatementBase::executeBatch( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::executeBatch" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + // first check the meta data + Reference<XDatabaseMetaData> xMeta = Reference< XConnection > (m_xParent, UNO_QUERY)->getMetaData(); + if (!xMeta.is() && !xMeta->supportsBatchUpdates()) + throwFunctionSequenceException(*this); + + // free the previous results + disposeResultSet(); + + return Reference< XPreparedBatchExecution >(m_xAggregateAsSet, UNO_QUERY)->executeBatch(); +} +// ----------------------------------------------------------------------------- +Reference< XResultSet > SAL_CALL OStatementBase::getGeneratedValues( ) throw (SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::getGeneratedValues" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + Reference< XGeneratedResultSet > xGRes(m_xAggregateAsSet, UNO_QUERY); + + if ( xGRes.is() ) + return xGRes->getGeneratedValues( ); + return Reference< XResultSet >(); +} + +//************************************************************ +// OStatement +//************************************************************ +//------------------------------------------------------------------------------ +OStatement::OStatement( const Reference< XConnection >& _xConn, const Reference< XInterface > & _xStatement ) + :OStatementBase( _xConn, _xStatement ) + ,m_bAttemptedComposerCreation( false ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatement::OStatement" ); + m_xAggregateStatement.set( _xStatement, UNO_QUERY_THROW ); +} + +//------------------------------------------------------------------------------ +IMPLEMENT_FORWARD_XINTERFACE2( OStatement, OStatementBase, OStatement_IFACE ); +IMPLEMENT_FORWARD_XTYPEPROVIDER2( OStatement, OStatementBase, OStatement_IFACE ); + +// XServiceInfo +//------------------------------------------------------------------------------ +rtl::OUString OStatement::getImplementationName( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatement::getImplementationName" ); + return rtl::OUString::createFromAscii("com.sun.star.sdb.OStatement"); +} + +//------------------------------------------------------------------------------ +sal_Bool OStatement::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatement::supportsService" ); + return ::comphelper::findValue(getSupportedServiceNames(), _rServiceName, sal_True).getLength() != 0; +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > OStatement::getSupportedServiceNames( ) throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatement::getSupportedServiceNames" ); + Sequence< ::rtl::OUString > aSNS( 1 ); + aSNS.getArray()[0] = SERVICE_SDBC_STATEMENT; + return aSNS; +} + +// XStatement +//------------------------------------------------------------------------------ +Reference< XResultSet > OStatement::executeQuery( const rtl::OUString& _rSQL ) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatement::executeQuery" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + disposeResultSet(); + Reference< XResultSet > xResultSet; + + ::rtl::OUString sSQL( impl_doEscapeProcessing_nothrow( _rSQL ) ); + + Reference< XResultSet > xInnerResultSet = m_xAggregateStatement->executeQuery( sSQL ); + Reference< XConnection > xConnection( m_xParent, UNO_QUERY_THROW ); + + if ( xInnerResultSet.is() ) + { + Reference< XDatabaseMetaData > xMeta = xConnection->getMetaData(); + sal_Bool bCaseSensitive = xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers(); + xResultSet = new OResultSet( xInnerResultSet, *this, bCaseSensitive ); + + // keep the resultset weak + m_aResultSet = xResultSet; + } + + return xResultSet; +} + +//------------------------------------------------------------------------------ +sal_Int32 OStatement::executeUpdate( const rtl::OUString& _rSQL ) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatement::executeUpdate" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + disposeResultSet(); + + ::rtl::OUString sSQL( impl_doEscapeProcessing_nothrow( _rSQL ) ); + return m_xAggregateStatement->executeUpdate( sSQL ); +} + +//------------------------------------------------------------------------------ +sal_Bool OStatement::execute( const rtl::OUString& _rSQL ) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatement::execute" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + disposeResultSet(); + + ::rtl::OUString sSQL( impl_doEscapeProcessing_nothrow( _rSQL ) ); + return m_xAggregateStatement->execute( sSQL ); +} +//------------------------------------------------------------------------------ +void OStatement::addBatch( const rtl::OUString& _rSQL ) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatement::execute" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + // first check the meta data + Reference<XDatabaseMetaData> xMeta = Reference< XConnection > (m_xParent, UNO_QUERY)->getMetaData(); + if (!xMeta.is() && !xMeta->supportsBatchUpdates()) + throwFunctionSequenceException(*this); + + ::rtl::OUString sSQL( impl_doEscapeProcessing_nothrow( _rSQL ) ); + Reference< XBatchExecution >(m_xAggregateAsSet, UNO_QUERY)->addBatch( sSQL ); +} +//------------------------------------------------------------------------------ +void OStatement::clearBatch( ) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatement::execute" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + // first check the meta data + Reference<XDatabaseMetaData> xMeta = Reference< XConnection > (m_xParent, UNO_QUERY)->getMetaData(); + if (!xMeta.is() && !xMeta->supportsBatchUpdates()) + throwFunctionSequenceException(*this); + + Reference< XBatchExecution >(m_xAggregateAsSet, UNO_QUERY)->clearBatch(); +} +//------------------------------------------------------------------------------ +Sequence< sal_Int32 > OStatement::executeBatch( ) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatement::execute" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + // first check the meta data + Reference<XDatabaseMetaData> xMeta = Reference< XConnection > (m_xParent, UNO_QUERY)->getMetaData(); + if (!xMeta.is() && !xMeta->supportsBatchUpdates()) + throwFunctionSequenceException(*this); + return Reference< XBatchExecution >(m_xAggregateAsSet, UNO_QUERY)->executeBatch( ); +} + +//------------------------------------------------------------------------------ +Reference< XConnection > OStatement::getConnection(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatement::getConnection" ); + return Reference< XConnection >( m_xParent, UNO_QUERY ); +} + +// ----------------------------------------------------------------------------- +void SAL_CALL OStatement::disposing() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatement::disposing" ); + OStatementBase::disposing(); + m_xComposer.clear(); + m_xAggregateStatement.clear(); +} + +// ----------------------------------------------------------------------------- +::rtl::OUString OStatement::impl_doEscapeProcessing_nothrow( const ::rtl::OUString& _rSQL ) const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatement::impl_doEscapeProcessing_nothrow" ); + if ( !m_bEscapeProcessing ) + return _rSQL; + try + { + if ( !impl_ensureComposer_nothrow() ) + return _rSQL; + + bool bParseable = false; + try { m_xComposer->setQuery( _rSQL ); bParseable = true; } + catch( const SQLException& ) { } + + if ( !bParseable ) + // if we cannot parse it, silently accept this. The driver is probably able to cope with it then + return _rSQL; + + ::rtl::OUString sLowLevelSQL = m_xComposer->getQueryWithSubstitution(); + return sLowLevelSQL; + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + return _rSQL; +} + +// ----------------------------------------------------------------------------- +bool OStatement::impl_ensureComposer_nothrow() const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatement::impl_ensureComposer_nothrow" ); + if ( m_bAttemptedComposerCreation ) + return m_xComposer.is(); + + const_cast< OStatement* >( this )->m_bAttemptedComposerCreation = true; + try + { + Reference< XMultiServiceFactory > xFactory( m_xParent, UNO_QUERY_THROW ); + const_cast< OStatement* >( this )->m_xComposer.set( xFactory->createInstance( SERVICE_NAME_SINGLESELECTQUERYCOMPOSER ), UNO_QUERY_THROW ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + return m_xComposer.is(); +} diff --git a/dbaccess/source/core/api/table.cxx b/dbaccess/source/core/api/table.cxx new file mode 100644 index 000000000000..e33098f74f4c --- /dev/null +++ b/dbaccess/source/core/api/table.cxx @@ -0,0 +1,417 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#include "table.hxx" +#include <definitioncolumn.hxx> +#include "dbastrings.hrc" +#include "core_resource.hxx" +#include "core_resource.hrc" +#include "CIndexes.hxx" + +#include <tools/debug.hxx> +#include <cppuhelper/typeprovider.hxx> +#include <comphelper/enumhelper.hxx> +#include <comphelper/container.hxx> +#include <comphelper/sequence.hxx> +#include <comphelper/types.hxx> +//#include <comphelper/extract.hxx> +#include <com/sun/star/util/XRefreshListener.hpp> +#include <com/sun/star/sdbc/XConnection.hpp> +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/sdbcx/Privilege.hpp> +#include <com/sun/star/sdbc/XResultSetMetaData.hpp> +#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp> + +#include <connectivity/TKeys.hxx> +#include <connectivity/dbtools.hxx> +#include <connectivity/dbexception.hxx> + +#include "sdbcoretools.hxx" +#include "ContainerMediator.hxx" +#include <rtl/logfile.hxx> + +using namespace dbaccess; +using namespace connectivity; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::container; +using namespace ::osl; +using namespace ::comphelper; +using namespace ::cppu; + +typedef ::std::map <sal_Int32, OTableColumn*, std::less <sal_Int32> > OColMap; + +//========================================================================== +//= ODBTable +//========================================================================== +DBG_NAME(ODBTable) +//-------------------------------------------------------------------------- +ODBTable::ODBTable(connectivity::sdbcx::OCollection* _pTables + ,const Reference< XConnection >& _rxConn + ,const ::rtl::OUString& _rCatalog + ,const ::rtl::OUString& _rSchema + ,const ::rtl::OUString& _rName + ,const ::rtl::OUString& _rType + ,const ::rtl::OUString& _rDesc + ,const Reference< XNameAccess >& _xColumnDefinitions) throw(SQLException) + :OTable_Base(_pTables,_rxConn,_rxConn->getMetaData().is() && _rxConn->getMetaData()->supportsMixedCaseQuotedIdentifiers(), _rName, _rType, _rDesc, _rSchema, _rCatalog ) + ,m_xColumnDefinitions(_xColumnDefinitions) + ,m_nPrivileges(0) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTable::ODBTable" ); + DBG_CTOR(ODBTable, NULL); + DBG_ASSERT(getMetaData().is(), "ODBTable::ODBTable : invalid conn !"); + DBG_ASSERT(_rName.getLength(), "ODBTable::ODBTable : name !"); + // TODO : think about collecting the privileges here, as we can't ensure that in getFastPropertyValue, where + // we do this at the moment, the statement needed can be supplied by the connection (for example the SQL-Server + // ODBC driver does not allow more than one statement per connection, and in getFastPropertyValue it's more + // likely that it's already used up than it's here.) +} +// ----------------------------------------------------------------------------- +ODBTable::ODBTable(connectivity::sdbcx::OCollection* _pTables + ,const Reference< XConnection >& _rxConn) + throw(SQLException) + :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" ); +} +// ------------------------------------------------------------------------- +ODBTable::~ODBTable() +{ + DBG_DTOR(ODBTable, NULL); +} +// ----------------------------------------------------------------------------- +IMPLEMENT_FORWARD_REFCOUNT(ODBTable,OTable_Base) + +//-------------------------------------------------------------------------- +OColumn* ODBTable::createColumn(const ::rtl::OUString& _rName) const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTable::createColumn" ); + OColumn* pReturn = NULL; + + Reference<XPropertySet> xProp; + if ( m_xDriverColumns.is() && m_xDriverColumns->hasByName(_rName) ) + { + xProp.set(m_xDriverColumns->getByName(_rName),UNO_QUERY); + } + else + { + OColumns* pColumns = static_cast<OColumns*>(m_pColumns); + xProp.set(pColumns->createBaseObject(_rName),UNO_QUERY); + } + + Reference<XPropertySet> xColumnDefintion; + if ( m_xColumnDefinitions.is() && m_xColumnDefinitions->hasByName(_rName) ) + xColumnDefintion.set(m_xColumnDefinitions->getByName(_rName),UNO_QUERY); + pReturn = new OTableColumnWrapper( xProp, xColumnDefintion, false ); + + return pReturn; +} +// ----------------------------------------------------------------------------- +void ODBTable::columnAppended( const Reference< XPropertySet >& /*_rxSourceDescriptor*/ ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTable::columnAppended" ); + // not interested in +} +// ----------------------------------------------------------------------------- +void ODBTable::columnDropped(const ::rtl::OUString& _sName) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTable::columnDropped" ); + Reference<XDrop> xDrop(m_xColumnDefinitions,UNO_QUERY); + if ( xDrop.is() && m_xColumnDefinitions->hasByName(_sName) ) + { + xDrop->dropByName(_sName); + } +} +//-------------------------------------------------------------------------- +Sequence< sal_Int8 > ODBTable::getImplementationId() throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTable::getImplementationId" ); + static OImplementationId * pId = 0; + if (! pId) + { + MutexGuard aGuard( Mutex::getGlobalMutex() ); + if (! pId) + { + static OImplementationId aId; + pId = &aId; + } + } + return pId->getImplementationId(); +} + +// OComponentHelper +//------------------------------------------------------------------------------ +void SAL_CALL ODBTable::disposing() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTable::disposing" ); + OPropertySetHelper::disposing(); + OTable_Base::disposing(); + m_xColumnDefinitions = NULL; + m_xDriverColumns = NULL; + m_pColumnMediator = NULL; +} + +//------------------------------------------------------------------------------ +void ODBTable::getFastPropertyValue(Any& _rValue, sal_Int32 _nHandle) const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTable::getFastPropertyValue" ); + if ((PROPERTY_ID_PRIVILEGES == _nHandle) && (-1 == m_nPrivileges)) + { // somebody is asking for the privileges an we do not know them, yet + const_cast<ODBTable*>(this)->m_nPrivileges = ::dbtools::getTablePrivileges(getMetaData(),m_CatalogName,m_SchemaName, m_Name); + } + + OTable_Base::getFastPropertyValue(_rValue, _nHandle); +} +// ------------------------------------------------------------------------- +void ODBTable::construct() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTable::construct" ); + ::osl::MutexGuard aGuard(m_aMutex); + + // we don't collect the privileges here, this is potentially expensive. Instead we determine them on request. + // (see getFastPropertyValue) + m_nPrivileges = -1; + + OTable_Base::construct(); + + registerProperty(PROPERTY_FILTER, PROPERTY_ID_FILTER, PropertyAttribute::BOUND, + &m_sFilter, ::getCppuType(&m_sFilter)); + + registerProperty(PROPERTY_ORDER, PROPERTY_ID_ORDER, PropertyAttribute::BOUND, + &m_sOrder, ::getCppuType(&m_sOrder)); + + registerProperty(PROPERTY_APPLYFILTER, PROPERTY_ID_APPLYFILTER, PropertyAttribute::BOUND, + &m_bApplyFilter, ::getBooleanCppuType()); + + registerProperty(PROPERTY_FONT, PROPERTY_ID_FONT, PropertyAttribute::BOUND, + &m_aFont, ::getCppuType(&m_aFont)); + + registerMayBeVoidProperty(PROPERTY_ROW_HEIGHT, PROPERTY_ID_ROW_HEIGHT, PropertyAttribute::BOUND | PropertyAttribute::MAYBEVOID, + &m_aRowHeight, ::getCppuType(static_cast<sal_Int32*>(NULL))); + + registerMayBeVoidProperty(PROPERTY_TEXTCOLOR, PROPERTY_ID_TEXTCOLOR, PropertyAttribute::BOUND | PropertyAttribute::MAYBEVOID, + &m_aTextColor, ::getCppuType(static_cast<sal_Int32*>(NULL))); + + registerProperty(PROPERTY_PRIVILEGES, PROPERTY_ID_PRIVILEGES, PropertyAttribute::BOUND | PropertyAttribute::READONLY, + &m_nPrivileges, ::getCppuType(static_cast<sal_Int32*>(NULL))); + + registerMayBeVoidProperty(PROPERTY_TEXTLINECOLOR, PROPERTY_ID_TEXTLINECOLOR, PropertyAttribute::BOUND | PropertyAttribute::MAYBEVOID, + &m_aTextLineColor, ::getCppuType(static_cast<sal_Int32*>(NULL))); + + registerProperty(PROPERTY_TEXTEMPHASIS, PROPERTY_ID_TEXTEMPHASIS, PropertyAttribute::BOUND, + &m_nFontEmphasis, ::getCppuType(&m_nFontEmphasis)); + + registerProperty(PROPERTY_TEXTRELIEF, PROPERTY_ID_TEXTRELIEF, PropertyAttribute::BOUND, + &m_nFontRelief, ::getCppuType(&m_nFontRelief)); + + registerProperty(PROPERTY_FONTNAME, PROPERTY_ID_FONTNAME, PropertyAttribute::BOUND,&m_aFont.Name, ::getCppuType(&m_aFont.Name)); + registerProperty(PROPERTY_FONTHEIGHT, PROPERTY_ID_FONTHEIGHT, PropertyAttribute::BOUND,&m_aFont.Height, ::getCppuType(&m_aFont.Height)); + registerProperty(PROPERTY_FONTWIDTH, PROPERTY_ID_FONTWIDTH, PropertyAttribute::BOUND,&m_aFont.Width, ::getCppuType(&m_aFont.Width)); + registerProperty(PROPERTY_FONTSTYLENAME, PROPERTY_ID_FONTSTYLENAME, PropertyAttribute::BOUND,&m_aFont.StyleName, ::getCppuType(&m_aFont.StyleName)); + registerProperty(PROPERTY_FONTFAMILY, PROPERTY_ID_FONTFAMILY, PropertyAttribute::BOUND,&m_aFont.Family, ::getCppuType(&m_aFont.Family)); + registerProperty(PROPERTY_FONTCHARSET, PROPERTY_ID_FONTCHARSET, PropertyAttribute::BOUND,&m_aFont.CharSet, ::getCppuType(&m_aFont.CharSet)); + registerProperty(PROPERTY_FONTPITCH, PROPERTY_ID_FONTPITCH, PropertyAttribute::BOUND,&m_aFont.Pitch, ::getCppuType(&m_aFont.Pitch)); + registerProperty(PROPERTY_FONTCHARWIDTH, PROPERTY_ID_FONTCHARWIDTH, PropertyAttribute::BOUND,&m_aFont.CharacterWidth, ::getCppuType(&m_aFont.CharacterWidth)); + registerProperty(PROPERTY_FONTWEIGHT, PROPERTY_ID_FONTWEIGHT, PropertyAttribute::BOUND,&m_aFont.Weight, ::getCppuType(&m_aFont.Weight)); + registerProperty(PROPERTY_FONTSLANT, PROPERTY_ID_FONTSLANT, PropertyAttribute::BOUND,&m_aFont.Slant, ::getCppuType(&m_aFont.Slant)); + registerProperty(PROPERTY_FONTUNDERLINE, PROPERTY_ID_FONTUNDERLINE, PropertyAttribute::BOUND,&m_aFont.Underline, ::getCppuType(&m_aFont.Underline)); + registerProperty(PROPERTY_FONTSTRIKEOUT, PROPERTY_ID_FONTSTRIKEOUT, PropertyAttribute::BOUND,&m_aFont.Strikeout, ::getCppuType(&m_aFont.Strikeout)); + registerProperty(PROPERTY_FONTORIENTATION, PROPERTY_ID_FONTORIENTATION, PropertyAttribute::BOUND,&m_aFont.Orientation, ::getCppuType(&m_aFont.Orientation)); + registerProperty(PROPERTY_FONTKERNING, PROPERTY_ID_FONTKERNING, PropertyAttribute::BOUND,&m_aFont.Kerning, ::getCppuType(&m_aFont.Kerning)); + registerProperty(PROPERTY_FONTWORDLINEMODE, PROPERTY_ID_FONTWORDLINEMODE,PropertyAttribute::BOUND,&m_aFont.WordLineMode, ::getCppuType(&m_aFont.WordLineMode)); + registerProperty(PROPERTY_FONTTYPE, PROPERTY_ID_FONTTYPE, PropertyAttribute::BOUND,&m_aFont.Type, ::getCppuType(&m_aFont.Type)); + + refreshColumns(); +} +// ----------------------------------------------------------------------------- +::cppu::IPropertyArrayHelper* ODBTable::createArrayHelper( sal_Int32 _nId) const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTable::createArrayHelper" ); + Sequence< Property > aProps; + describeProperties(aProps); + if(!_nId) + { + Property* pIter = aProps.getArray(); + Property* pEnd = pIter + aProps.getLength(); + for(;pIter != pEnd;++pIter) + { + 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; + } + } + + return new ::cppu::OPropertyArrayHelper(aProps); +} +// ----------------------------------------------------------------------------- +::cppu::IPropertyArrayHelper & SAL_CALL ODBTable::getInfoHelper() +{ + return *ODBTable_PROP::getArrayHelper(isNew() ? 1 : 0); +} +// ------------------------------------------------------------------------- +// XServiceInfo +IMPLEMENT_SERVICE_INFO1(ODBTable, "com.sun.star.sdb.dbaccess.ODBTable", SERVICE_SDBCX_TABLE) +// ------------------------------------------------------------------------- +Any SAL_CALL ODBTable::queryInterface( const Type & rType ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTable::getInfoHelper" ); + if(rType == getCppuType( (Reference<XRename>*)0) && !getRenameService().is() ) + return Any(); + if(rType == getCppuType( (Reference<XAlterTable>*)0) && !getAlterService().is() ) + return Any(); + return OTable_Base::queryInterface( rType); +} +// ------------------------------------------------------------------------- +Sequence< Type > SAL_CALL ODBTable::getTypes( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTable::getTypes" ); + Type aRenameType = getCppuType( (Reference<XRename>*)0); + Type aAlterType = getCppuType( (Reference<XAlterTable>*)0); + + Sequence< Type > aTypes(OTable_Base::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 != aRenameType || getRenameService().is()) && (*pIter != aAlterType || getAlterService().is())) + aOwnTypes.push_back(*pIter); + } + + Type* pTypes = aOwnTypes.empty() ? 0 : &aOwnTypes[0]; + return Sequence< Type >(pTypes, aOwnTypes.size()); +} +// XRename, +//------------------------------------------------------------------------------ +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" ); + ::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, +//------------------------------------------------------------------------------ +void SAL_CALL ODBTable::alterColumnByName( const ::rtl::OUString& _rName, const Reference< XPropertySet >& _rxDescriptor ) throw(SQLException, NoSuchElementException, RuntimeException) +{ + 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 ( !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(); +} +// ----------------------------------------------------------------------------- +sal_Int64 SAL_CALL ODBTable::getSomething( const Sequence< sal_Int8 >& rId ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTable::getSomething" ); + sal_Int64 nRet(0); + if (rId.getLength() == 16 && 0 == rtl_compareMemory(getUnoTunnelImplementationId().getConstArray(), rId.getConstArray(), 16 ) ) + nRet = reinterpret_cast<sal_Int64>(this); + else + nRet = OTable_Base::getSomething(rId); + + return nRet; +} +// ----------------------------------------------------------------------------- +Sequence< sal_Int8 > ODBTable::getUnoTunnelImplementationId() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTable::getUnoTunnelImplementationId" ); + static ::cppu::OImplementationId * pId = 0; + if (! pId) + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if (! pId) + { + static ::cppu::OImplementationId aId; + pId = &aId; + } + } + return pId->getImplementationId(); +} +// ----------------------------------------------------------------------------- +Reference< XPropertySet > ODBTable::createColumnDescriptor() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTable::createColumnDescriptor" ); + return new OTableColumnDescriptor( true ); +} +// ----------------------------------------------------------------------------- +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, + 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 ); + pCol->setMediator( m_pColumnMediator.get() ); + return pCol; +} +// ----------------------------------------------------------------------------- +sdbcx::OCollection* ODBTable::createKeys(const TStringVector& _rNames) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTable::createKeys" ); + return new connectivity::OKeysHelper(this,m_aMutex,_rNames); +} +// ----------------------------------------------------------------------------- +sdbcx::OCollection* ODBTable::createIndexes(const TStringVector& _rNames) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTable::createIndexes" ); + return new OIndexes(this,m_aMutex,_rNames,NULL); +} +// ----------------------------------------------------------------------------- diff --git a/dbaccess/source/core/api/tablecontainer.cxx b/dbaccess/source/core/api/tablecontainer.cxx new file mode 100644 index 000000000000..76d6ac063441 --- /dev/null +++ b/dbaccess/source/core/api/tablecontainer.cxx @@ -0,0 +1,516 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#include "tablecontainer.hxx" +#include "dbastrings.hrc" +#include "table.hxx" +#include <comphelper/property.hxx> +#include <comphelper/processfactory.hxx> +#include <tools/debug.hxx> +#include <comphelper/enumhelper.hxx> +#include "core_resource.hxx" +#include "core_resource.hrc" +#include <com/sun/star/sdb/CommandType.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/beans/PropertyState.hpp> +#include <com/sun/star/beans/XPropertyState.hpp> +#include <com/sun/star/sdbc/XConnection.hpp> +#include <com/sun/star/sdbc/XDatabaseMetaData.hpp> +#include <com/sun/star/sdbcx/XColumnsSupplier.hpp> +#include <com/sun/star/sdbcx/XTablesSupplier.hpp> +#include <com/sun/star/sdbc/KeyRule.hpp> +#include <com/sun/star/sdbcx/KeyType.hpp> +#include <com/sun/star/sdbc/ColumnValue.hpp> +#include <com/sun/star/sdbc/XRow.hpp> +#include <comphelper/types.hxx> +#include <connectivity/dbtools.hxx> +#include <comphelper/extract.hxx> +#include <connectivity/dbexception.hxx> +#include "TableDeco.hxx" +#include "sdbcoretools.hxx" +#include "ContainerMediator.hxx" +#include "definitioncolumn.hxx" +#include "objectnameapproval.hxx" +#include <tools/string.hxx> +#include <rtl/logfile.hxx> +#ifndef TOOLS_DIAGNOSE_EX_H +#include <tools/diagnose_ex.h> +#endif +#ifndef TOOLS_DIAGNOSE_EX_H +#include <tools/diagnose_ex.h> +#endif + +using namespace dbaccess; +using namespace dbtools; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::util; +using namespace ::osl; +using namespace ::comphelper; +using namespace ::cppu; +using namespace ::connectivity::sdbcx; + +namespace +{ + sal_Bool lcl_isPropertySetDefaulted(const Sequence< ::rtl::OUString>& _aNames,const Reference<XPropertySet>& _xProp) + { + Reference<XPropertyState> xState(_xProp,UNO_QUERY); + if ( xState.is() ) + { + const ::rtl::OUString* pIter = _aNames.getConstArray(); + const ::rtl::OUString* pEnd = pIter + _aNames.getLength(); + for(;pIter != pEnd;++pIter) + { + try + { + PropertyState aState = xState->getPropertyState(*pIter); + if ( aState != PropertyState_DEFAULT_VALUE ) + break; + } + catch(Exception) + { + OSL_ENSURE( 0, "lcl_isPropertySetDefaulted: Exception caught!" ); + } + } + return ( pIter == pEnd ); + } + return sal_False; + } +} +//========================================================================== +//= OTableContainer +//========================================================================== +DBG_NAME(OTableContainer) +//------------------------------------------------------------------------------ +OTableContainer::OTableContainer(::cppu::OWeakObject& _rParent, + ::osl::Mutex& _rMutex, + const Reference< XConnection >& _xCon, + sal_Bool _bCase, + const Reference< XNameContainer >& _xTableDefinitions, + IRefreshListener* _pRefreshListener, + ::dbtools::IWarningsContainer* _pWarningsContainer + ,oslInterlockedCount& _nInAppend) + :OFilteredContainer(_rParent,_rMutex,_xCon,_bCase,_pRefreshListener,_pWarningsContainer,_nInAppend) + ,m_xTableDefinitions(_xTableDefinitions) + ,m_pTableMediator( NULL ) + ,m_bInDrop(sal_False) +{ + DBG_CTOR(OTableContainer, NULL); +} + +//------------------------------------------------------------------------------ +OTableContainer::~OTableContainer() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "api", "Ocke.Janssen@sun.com", "OTableContainer::OTableContainer" ); + // dispose(); + DBG_DTOR(OTableContainer, NULL); +} + +// ----------------------------------------------------------------------------- +void OTableContainer::removeMasterContainerListener() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "api", "Ocke.Janssen@sun.com", "OTableContainer::removeMasterContainerListener" ); + try + { + Reference<XContainer> xCont( m_xMasterContainer, UNO_QUERY_THROW ); + xCont->removeContainerListener( this ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } +} + +// ----------------------------------------------------------------------------- +::rtl::OUString OTableContainer::getTableTypeRestriction() const +{ + // no restriction at all (other than the ones provided externally) + return ::rtl::OUString(); +} + +// ----------------------------------------------------------------------------- +// XServiceInfo +//------------------------------------------------------------------------------ +IMPLEMENT_SERVICE_INFO2(OTableContainer, "com.sun.star.sdb.dbaccess.OTableContainer", SERVICE_SDBCX_CONTAINER, SERVICE_SDBCX_TABLES) + +// ----------------------------------------------------------------------------- +namespace +{ +void lcl_createDefintionObject(const ::rtl::OUString& _rName + ,const Reference< XNameContainer >& _xTableDefinitions + ,Reference<XPropertySet>& _xTableDefinition + ,Reference<XNameAccess>& _xColumnDefinitions + ,sal_Bool _bModified) +{ + if ( _xTableDefinitions.is() ) + { + if ( _xTableDefinitions->hasByName(_rName) ) + _xTableDefinition.set(_xTableDefinitions->getByName(_rName),UNO_QUERY); + else + { + Sequence< Any > aArguments(1); + PropertyValue aValue; + // set as folder + aValue.Name = PROPERTY_NAME; + aValue.Value <<= _rName; + aArguments[0] <<= aValue; + _xTableDefinition.set(::comphelper::getProcessServiceFactory()->createInstanceWithArguments(SERVICE_SDB_TABLEDEFINITION,aArguments),UNO_QUERY); + _xTableDefinitions->insertByName(_rName,makeAny(_xTableDefinition)); + ::dbaccess::notifyDataSourceModified(_xTableDefinitions,_bModified); + } + Reference<XColumnsSupplier> xColumnsSupplier(_xTableDefinition,UNO_QUERY); + if ( xColumnsSupplier.is() ) + _xColumnDefinitions = xColumnsSupplier->getColumns(); + } +} +// ------------------------------------------------------------------------- +} +// ------------------------------------------------------------------------- +connectivity::sdbcx::ObjectType OTableContainer::createObject(const ::rtl::OUString& _rName) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "api", "Ocke.Janssen@sun.com", "OTableContainer::createObject" ); + Reference<XColumnsSupplier > xSup; + if(m_xMasterContainer.is() && m_xMasterContainer->hasByName(_rName)) + xSup.set(m_xMasterContainer->getByName(_rName),UNO_QUERY); + + connectivity::sdbcx::ObjectType xRet; + if ( m_xMetaData.is() ) + { + Reference<XPropertySet> xTableDefinition; + Reference<XNameAccess> xColumnDefinitions; + lcl_createDefintionObject(_rName,m_xTableDefinitions,xTableDefinition,xColumnDefinitions,sal_False); + + if ( xSup.is() ) + { + ODBTableDecorator* pTable = new ODBTableDecorator( m_xConnection, xSup, ::dbtools::getNumberFormats( m_xConnection ) ,xColumnDefinitions); + xRet = pTable; + pTable->construct(); + } + else + { + ::rtl::OUString sCatalog,sSchema,sTable; + ::dbtools::qualifiedNameComponents(m_xMetaData, + _rName, + sCatalog, + sSchema, + sTable, + ::dbtools::eInDataManipulation); + Any aCatalog; + if(sCatalog.getLength()) + aCatalog <<= sCatalog; + ::rtl::OUString sType,sDescription; + Sequence< ::rtl::OUString> aTypeFilter; + getAllTableTypeFilter( aTypeFilter ); + + Reference< XResultSet > xRes = m_xMetaData.is() ? m_xMetaData->getTables(aCatalog,sSchema,sTable,aTypeFilter) : Reference< XResultSet >(); + if(xRes.is() && xRes->next()) + { + Reference< XRow > xRow(xRes,UNO_QUERY); + if(xRow.is()) + { + sType = xRow->getString(4); + sDescription = xRow->getString(5); + } + } + ::comphelper::disposeComponent(xRes); + ODBTable* pTable = new ODBTable(this + ,m_xConnection + ,sCatalog + ,sSchema + ,sTable + ,sType + ,sDescription + ,xColumnDefinitions); + xRet = pTable; + pTable->construct(); + } + Reference<XPropertySet> xDest(xRet,UNO_QUERY); + if ( xTableDefinition.is() ) + ::comphelper::copyProperties(xTableDefinition,xDest); + + if ( !m_pTableMediator.is() ) + m_pTableMediator = new OContainerMediator( + this, m_xTableDefinitions.get(), m_xConnection, OContainerMediator::eTables ); + if ( m_pTableMediator.is() ) + m_pTableMediator->notifyElementCreated(_rName,xDest); + } + + return xRet; +} +// ----------------------------------------------------------------------------- +Reference< XPropertySet > OTableContainer::createDescriptor() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "api", "Ocke.Janssen@sun.com", "OTableContainer::createDescriptor" ); + Reference< XPropertySet > xRet; + + // frist we have to look if the master tables does support this + // and if then create a table object as well with the master tables + Reference<XColumnsSupplier > xMasterColumnsSup; + Reference<XDataDescriptorFactory> xDataFactory(m_xMasterContainer,UNO_QUERY); + if ( xDataFactory.is() && m_xMetaData.is() ) + { + xMasterColumnsSup = Reference< XColumnsSupplier >( xDataFactory->createDataDescriptor(), UNO_QUERY ); + ODBTableDecorator* pTable = new ODBTableDecorator( m_xConnection, xMasterColumnsSup, ::dbtools::getNumberFormats( m_xConnection ) ,NULL); + xRet = pTable; + pTable->construct(); + } + else + { + ODBTable* pTable = new ODBTable(this, m_xConnection); + xRet = pTable; + pTable->construct(); + } + return xRet; +} +// ----------------------------------------------------------------------------- +// XAppend +ObjectType OTableContainer::appendObject( const ::rtl::OUString& _rForName, const Reference< XPropertySet >& descriptor ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "api", "Ocke.Janssen@sun.com", "OTableContainer::appendObject" ); + // append the new table with a create stmt + ::rtl::OUString aName = getString(descriptor->getPropertyValue(PROPERTY_NAME)); + if(m_xMasterContainer.is() && m_xMasterContainer->hasByName(aName)) + { + String sMessage(DBACORE_RESSTRING(RID_STR_TABLE_IS_FILTERED)); + sMessage.SearchAndReplaceAscii("$name$", aName); + throw SQLException(sMessage,static_cast<XTypeProvider*>(static_cast<OFilteredContainer*>(this)),SQLSTATE_GENERAL,1000,Any()); + } + + Reference< XConnection > xConnection( m_xConnection.get(), UNO_QUERY ); + PContainerApprove pApprove( new ObjectNameApproval( xConnection, ObjectNameApproval::TypeTable ) ); + pApprove->approveElement( aName, descriptor ); + + try + { + EnsureReset aReset(m_nInAppend); + Reference<XAppend> xAppend(m_xMasterContainer,UNO_QUERY); + if(xAppend.is()) + { + xAppend->appendByDescriptor(descriptor); + } + else + { + ::rtl::OUString aSql = ::dbtools::createSqlCreateTableStatement(descriptor,m_xConnection); + + Reference<XConnection> xCon = m_xConnection; + OSL_ENSURE(xCon.is(),"Connection is null!"); + if ( xCon.is() ) + { + Reference< XStatement > xStmt = xCon->createStatement( ); + if ( xStmt.is() ) + xStmt->execute(aSql); + ::comphelper::disposeComponent(xStmt); + } + } + } + catch(Exception&) + { + throw; + } + + Reference<XPropertySet> xTableDefinition; + Reference<XNameAccess> xColumnDefinitions; + lcl_createDefintionObject(getNameForObject(descriptor),m_xTableDefinitions,xTableDefinition,xColumnDefinitions,sal_False); + Reference<XColumnsSupplier> xSup(descriptor,UNO_QUERY); + Reference<XDataDescriptorFactory> xFac(xColumnDefinitions,UNO_QUERY); + Reference<XAppend> xAppend(xColumnDefinitions,UNO_QUERY); + sal_Bool bModified = sal_False; + if ( xSup.is() && xColumnDefinitions.is() && xFac.is() && xAppend.is() ) + { + Reference<XNameAccess> xNames = xSup->getColumns(); + if ( xNames.is() ) + { + Reference<XPropertySet> xProp = xFac->createDataDescriptor(); + Sequence< ::rtl::OUString> aSeq = xNames->getElementNames(); + const ::rtl::OUString* pIter = aSeq.getConstArray(); + const ::rtl::OUString* pEnd = pIter + aSeq.getLength(); + for(;pIter != pEnd;++pIter) + { + if ( !xColumnDefinitions->hasByName(*pIter) ) + { + Reference<XPropertySet> xColumn(xNames->getByName(*pIter),UNO_QUERY); + if ( !OColumnSettings::hasDefaultSettings( xColumn ) ) + { + ::comphelper::copyProperties( xColumn, xProp ); + xAppend->appendByDescriptor( xProp ); + bModified = sal_True; + } + } + } + } + } + const static ::rtl::OUString s_pTableProps[] = { ::rtl::OUString(PROPERTY_FILTER), ::rtl::OUString(PROPERTY_ORDER) + , ::rtl::OUString(PROPERTY_APPLYFILTER), ::rtl::OUString(PROPERTY_FONT) + , ::rtl::OUString(PROPERTY_ROW_HEIGHT), ::rtl::OUString(PROPERTY_TEXTCOLOR) + , ::rtl::OUString(PROPERTY_TEXTLINECOLOR), ::rtl::OUString(PROPERTY_TEXTEMPHASIS) + , ::rtl::OUString(PROPERTY_TEXTRELIEF) }; + Sequence< ::rtl::OUString> aNames(s_pTableProps,sizeof(s_pTableProps)/sizeof(s_pTableProps[0])); + if ( bModified || !lcl_isPropertySetDefaulted(aNames,xTableDefinition) ) + ::dbaccess::notifyDataSourceModified(m_xTableDefinitions,sal_True); + + return createObject( _rForName ); +} +// ------------------------------------------------------------------------- +// XDrop +void OTableContainer::dropObject(sal_Int32 _nPos,const ::rtl::OUString _sElementName) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "api", "Ocke.Janssen@sun.com", "OTableContainer::dropObject" ); + m_bInDrop = sal_True; + try + { + Reference< XDrop > xDrop(m_xMasterContainer,UNO_QUERY); + if(xDrop.is()) + xDrop->dropByName(_sElementName); + else + { + ::rtl::OUString sCatalog,sSchema,sTable,sComposedName; + + sal_Bool bIsView = sal_False; + Reference<XPropertySet> xTable(getObject(_nPos),UNO_QUERY); + if ( xTable.is() && m_xMetaData.is() ) + { + if( m_xMetaData.is() && m_xMetaData->supportsCatalogsInTableDefinitions() ) + xTable->getPropertyValue(PROPERTY_CATALOGNAME) >>= sCatalog; + if( m_xMetaData.is() && m_xMetaData->supportsSchemasInTableDefinitions() ) + xTable->getPropertyValue(PROPERTY_SCHEMANAME) >>= sSchema; + xTable->getPropertyValue(PROPERTY_NAME) >>= sTable; + + sComposedName = ::dbtools::composeTableName( m_xMetaData, sCatalog, sSchema, sTable, sal_True, ::dbtools::eInTableDefinitions ); + + ::rtl::OUString sType; + xTable->getPropertyValue(PROPERTY_TYPE) >>= sType; + bIsView = sType.equalsIgnoreAsciiCase(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("VIEW"))); + } + + if(!sComposedName.getLength()) + ::dbtools::throwFunctionSequenceException(static_cast<XTypeProvider*>(static_cast<OFilteredContainer*>(this))); + + ::rtl::OUString aSql = ::rtl::OUString::createFromAscii("DROP "); + + // #104282# OJ + if ( bIsView ) // here we have a view + aSql += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("VIEW ")); + else + aSql += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("TABLE ")); + aSql += sComposedName; + Reference<XConnection> xCon = m_xConnection; + OSL_ENSURE(xCon.is(),"Connection is null!"); + if ( xCon.is() ) + { + Reference< XStatement > xStmt = xCon->createStatement( ); + if(xStmt.is()) + xStmt->execute(aSql); + ::comphelper::disposeComponent(xStmt); + } + } + + if ( m_xTableDefinitions.is() && m_xTableDefinitions->hasByName(_sElementName) ) + { + m_xTableDefinitions->removeByName(_sElementName); + } + } + catch(Exception&) + { + m_bInDrop = sal_False; + throw; + } + m_bInDrop = sal_False; +} +// ----------------------------------------------------------------------------- +void SAL_CALL OTableContainer::elementInserted( const ContainerEvent& Event ) throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "api", "Ocke.Janssen@sun.com", "OTableContainer::elementInserted" ); + ::osl::MutexGuard aGuard(m_rMutex); + ::rtl::OUString sName; + Event.Accessor >>= sName; + if ( !m_nInAppend && !hasByName(sName) ) + { + if(!m_xMasterContainer.is() || m_xMasterContainer->hasByName(sName)) + { + ObjectType xName = createObject(sName); + insertElement(sName,xName); + // and notify our listeners + ContainerEvent aEvent(static_cast<XContainer*>(this), makeAny(sName), makeAny(xName), Any()); + m_aContainerListeners.notifyEach( &XContainerListener::elementInserted, aEvent ); + } + } +} +// ----------------------------------------------------------------------------- +void SAL_CALL OTableContainer::elementRemoved( const ContainerEvent& /*Event*/ ) throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "api", "Ocke.Janssen@sun.com", "OTableContainer::elementRemoved" ); +} +// ----------------------------------------------------------------------------- +void SAL_CALL OTableContainer::elementReplaced( const ContainerEvent& Event ) throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "api", "Ocke.Janssen@sun.com", "OTableContainer::elementReplaced" ); + // create a new config entry + { + ::rtl::OUString sOldComposedName,sNewComposedName; + Event.ReplacedElement >>= sOldComposedName; + Event.Accessor >>= sNewComposedName; + + renameObject(sOldComposedName,sNewComposedName); + } +} +// ----------------------------------------------------------------------------- +void SAL_CALL OTableContainer::disposing() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "api", "Ocke.Janssen@sun.com", "OTableContainer::disposing" ); + OFilteredContainer::disposing(); + // say our listeners goobye + m_xTableDefinitions = NULL; + m_pTableMediator = NULL; +} +// ----------------------------------------------------------------------------- +void SAL_CALL OTableContainer::disposing( const ::com::sun::star::lang::EventObject& /*Source*/ ) throw (::com::sun::star::uno::RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "api", "Ocke.Janssen@sun.com", "OTableContainer::disposing" ); +} + +// ----------------------------------------------------------------------------- +void OTableContainer::addMasterContainerListener() +{ + try + { + Reference< XContainer > xCont( m_xMasterContainer, UNO_QUERY_THROW ); + xCont->addContainerListener( this ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } +} + diff --git a/dbaccess/source/core/api/viewcontainer.cxx b/dbaccess/source/core/api/viewcontainer.cxx new file mode 100644 index 000000000000..0fc2542bfa4a --- /dev/null +++ b/dbaccess/source/core/api/viewcontainer.cxx @@ -0,0 +1,274 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#include "viewcontainer.hxx" +#include "dbastrings.hrc" +#include "core_resource.hxx" +#include "core_resource.hrc" +#include "View.hxx" + +#include <tools/debug.hxx> +#include <tools/wldcrd.hxx> +#include <comphelper/enumhelper.hxx> +#include <comphelper/types.hxx> +#include <connectivity/dbtools.hxx> +#include <comphelper/extract.hxx> +#include <connectivity/dbexception.hxx> +#include <rtl/ustrbuf.hxx> + +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/sdbc/XConnection.hpp> +#include <com/sun/star/sdbc/XDatabaseMetaData.hpp> +#include <com/sun/star/sdbc/KeyRule.hpp> +#include <com/sun/star/sdbc/ColumnValue.hpp> +#include <com/sun/star/sdbc/XRow.hpp> +#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; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::container; +using namespace ::osl; +using namespace ::comphelper; +using namespace ::cppu; +using namespace ::connectivity::sdbcx; + +//========================================================================== +//= OViewContainer +//========================================================================== +DBG_NAME(OViewContainer) +//------------------------------------------------------------------------------ +OViewContainer::OViewContainer(::cppu::OWeakObject& _rParent + ,::osl::Mutex& _rMutex + ,const Reference< XConnection >& _xCon + ,sal_Bool _bCase + ,IRefreshListener* _pRefreshListener + ,::dbtools::IWarningsContainer* _pWarningsContainer + ,oslInterlockedCount& _nInAppend) + :OFilteredContainer(_rParent,_rMutex,_xCon,_bCase,_pRefreshListener,_pWarningsContainer,_nInAppend) + ,m_bInElementRemoved(false) +{ + DBG_CTOR(OViewContainer, NULL); +} + +//------------------------------------------------------------------------------ +OViewContainer::~OViewContainer() +{ + // dispose(); + DBG_DTOR(OViewContainer, NULL); +} +//------------------------------------------------------------------------------ +// XServiceInfo +//------------------------------------------------------------------------------ +IMPLEMENT_SERVICE_INFO2(OViewContainer, "com.sun.star.sdb.dbaccess.OViewContainer", SERVICE_SDBCX_CONTAINER, SERVICE_SDBCX_TABLES) +// ----------------------------------------------------------------------------- +ObjectType OViewContainer::createObject(const ::rtl::OUString& _rName) +{ + ObjectType xProp; + if ( m_xMasterContainer.is() && m_xMasterContainer->hasByName(_rName) ) + xProp.set(m_xMasterContainer->getByName(_rName),UNO_QUERY); + + if ( !xProp.is() ) + { + ::rtl::OUString sCatalog,sSchema,sTable; + ::dbtools::qualifiedNameComponents(m_xMetaData, + _rName, + sCatalog, + sSchema, + sTable, + ::dbtools::eInDataManipulation); + return new View(m_xConnection, + isCaseSensitive(), + sCatalog, + sSchema, + sTable + ); + } + + return xProp; +} +// ----------------------------------------------------------------------------- +Reference< XPropertySet > OViewContainer::createDescriptor() +{ + Reference< XPropertySet > xRet; + // frist we have to look if the master tables does support this + // and if then create a table object as well with the master tables + Reference<XColumnsSupplier > xMasterColumnsSup; + Reference<XDataDescriptorFactory> xDataFactory(m_xMasterContainer,UNO_QUERY); + if(xDataFactory.is()) + xRet = xDataFactory->createDataDescriptor(); + else + xRet = new ::connectivity::sdbcx::OView(isCaseSensitive(),m_xMetaData); + + return xRet; +} +// ----------------------------------------------------------------------------- +// XAppend +ObjectType OViewContainer::appendObject( const ::rtl::OUString& _rForName, const Reference< XPropertySet >& descriptor ) +{ + // append the new table with a create stmt + ::rtl::OUString aName = getString(descriptor->getPropertyValue(PROPERTY_NAME)); + + Reference<XAppend> xAppend(m_xMasterContainer,UNO_QUERY); + Reference< XPropertySet > xProp = descriptor; + if(xAppend.is()) + { + EnsureReset aReset(m_nInAppend); + + xAppend->appendByDescriptor(descriptor); + if(m_xMasterContainer->hasByName(aName)) + xProp.set(m_xMasterContainer->getByName(aName),UNO_QUERY); + } + else + { + ::rtl::OUString sComposedName = ::dbtools::composeTableName( m_xMetaData, descriptor, ::dbtools::eInTableDefinitions, false, false, true ); + if(!sComposedName.getLength()) + ::dbtools::throwFunctionSequenceException(static_cast<XTypeProvider*>(static_cast<OFilteredContainer*>(this))); + + ::rtl::OUString sCommand; + descriptor->getPropertyValue(PROPERTY_COMMAND) >>= sCommand; + + ::rtl::OUStringBuffer aSQL; + aSQL.appendAscii( "CREATE VIEW " ); + aSQL.append ( sComposedName ); + aSQL.appendAscii( " AS " ); + aSQL.append ( sCommand ); + + Reference<XConnection> xCon = m_xConnection; + OSL_ENSURE(xCon.is(),"Connection is null!"); + if ( xCon.is() ) + { + ::utl::SharedUNOComponent< XStatement > xStmt( xCon->createStatement() ); + if ( xStmt.is() ) + xStmt->execute( aSQL.makeStringAndClear() ); + } + } + + return createObject( _rForName ); +} +// ------------------------------------------------------------------------- +// XDrop +void OViewContainer::dropObject(sal_Int32 _nPos,const ::rtl::OUString _sElementName) +{ + if ( !m_bInElementRemoved ) + { + Reference< XDrop > xDrop(m_xMasterContainer,UNO_QUERY); + if(xDrop.is()) + xDrop->dropByName(_sElementName); + else + { + ::rtl::OUString sCatalog,sSchema,sTable,sComposedName; + + Reference<XPropertySet> xTable(getObject(_nPos),UNO_QUERY); + if ( xTable.is() ) + { + xTable->getPropertyValue(PROPERTY_CATALOGNAME) >>= sCatalog; + xTable->getPropertyValue(PROPERTY_SCHEMANAME) >>= sSchema; + xTable->getPropertyValue(PROPERTY_NAME) >>= sTable; + + sComposedName = ::dbtools::composeTableName( m_xMetaData, sCatalog, sSchema, sTable, sal_True, ::dbtools::eInTableDefinitions ); + } + + if(!sComposedName.getLength()) + ::dbtools::throwFunctionSequenceException(static_cast<XTypeProvider*>(static_cast<OFilteredContainer*>(this))); + + ::rtl::OUString aSql = ::rtl::OUString::createFromAscii("DROP VIEW "); + aSql += sComposedName; + Reference<XConnection> xCon = m_xConnection; + OSL_ENSURE(xCon.is(),"Connection is null!"); + if ( xCon.is() ) + { + Reference< XStatement > xStmt = xCon->createStatement( ); + if(xStmt.is()) + xStmt->execute(aSql); + ::comphelper::disposeComponent(xStmt); + } + } + } +} +// ----------------------------------------------------------------------------- +void SAL_CALL OViewContainer::elementInserted( const ContainerEvent& Event ) throw (RuntimeException) +{ + ::osl::MutexGuard aGuard(m_rMutex); + ::rtl::OUString sName; + if ( ( Event.Accessor >>= sName ) + && ( !m_nInAppend ) + && ( !hasByName( sName ) ) + ) + { + Reference<XPropertySet> xProp(Event.Element,UNO_QUERY); + ::rtl::OUString sType; + xProp->getPropertyValue(PROPERTY_TYPE) >>= sType; + if ( sType == ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("VIEW")) ) + insertElement(sName,createObject(sName)); + } +} +// ----------------------------------------------------------------------------- +void SAL_CALL OViewContainer::elementRemoved( const ContainerEvent& Event ) throw (RuntimeException) +{ + ::osl::MutexGuard aGuard(m_rMutex); + ::rtl::OUString sName; + if ( (Event.Accessor >>= sName) && hasByName(sName) ) + { + m_bInElementRemoved = true; + try + { + dropByName(sName); + } + catch(Exception&) + { + m_bInElementRemoved = sal_False; + throw; + } + m_bInElementRemoved = false; + } +} +// ----------------------------------------------------------------------------- +void SAL_CALL OViewContainer::disposing( const ::com::sun::star::lang::EventObject& /*Source*/ ) throw (RuntimeException) +{ +} +// ----------------------------------------------------------------------------- +void SAL_CALL OViewContainer::elementReplaced( const ContainerEvent& /*Event*/ ) throw (RuntimeException) +{ +} +// ----------------------------------------------------------------------------- +::rtl::OUString OViewContainer::getTableTypeRestriction() const +{ + // no restriction at all (other than the ones provided externally) + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "VIEW" ) ); +} diff --git a/dbaccess/source/core/dataaccess/ComponentDefinition.cxx b/dbaccess/source/core/dataaccess/ComponentDefinition.cxx new file mode 100644 index 000000000000..10361a3aa280 --- /dev/null +++ b/dbaccess/source/core/dataaccess/ComponentDefinition.cxx @@ -0,0 +1,328 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#ifndef DBA_COREDATAACESS_COMPONENTDEFINITION_HXX +#include "ComponentDefinition.hxx" +#endif +#ifndef _DBASHARED_APITOOLS_HXX_ +#include "apitools.hxx" +#endif +#ifndef DBACCESS_SHARED_DBASTRINGS_HRC +#include "dbastrings.hrc" +#endif +#include "module_dba.hxx" + +#ifndef _TOOLS_DEBUG_HXX +#include <tools/debug.hxx> +#endif +#ifndef _COMPHELPER_SEQUENCE_HXX_ +#include <comphelper/sequence.hxx> +#endif +#ifndef _COM_SUN_STAR_LANG_DISPOSEDEXCEPTION_HPP_ +#include <com/sun/star/lang/DisposedException.hpp> +#endif +#ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBUTE_HPP_ +#include <com/sun/star/beans/PropertyAttribute.hpp> +#endif +#ifndef _COMPHELPER_PROPERTY_HXX_ +#include <comphelper/property.hxx> +#endif +#ifndef _DBACORE_DEFINITIONCOLUMN_HXX_ +#include "definitioncolumn.hxx" +#endif +#include <cppuhelper/implbase1.hxx> +#include <comphelper/componentcontext.hxx> + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::lang; + +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::osl; +using namespace ::comphelper; +using namespace ::cppu; + +extern "C" void SAL_CALL createRegistryInfo_OComponentDefinition() +{ + static ::dba::OAutoRegistration< ::dbaccess::OComponentDefinition > aAutoRegistration; +} + +//........................................................................ +namespace dbaccess +{ +//........................................................................ +/// helper class for column property change events which holds the OComponentDefinition weak +typedef ::cppu::WeakImplHelper1 < XPropertyChangeListener > TColumnPropertyListener_BASE; +class OColumnPropertyListener : public TColumnPropertyListener_BASE +{ + OComponentDefinition* m_pComponent; + + OColumnPropertyListener(const OColumnPropertyListener&); + void operator =(const OColumnPropertyListener&); +protected: + virtual ~OColumnPropertyListener(){} +public: + OColumnPropertyListener(OComponentDefinition* _pComponent) : m_pComponent(_pComponent){} + // XPropertyChangeListener + virtual void SAL_CALL propertyChange( const PropertyChangeEvent& /*_rEvent*/ ) throw (RuntimeException) + { + if ( m_pComponent ) + m_pComponent->notifyDataSourceModified(); + } + // XEventListener + virtual void SAL_CALL disposing( const EventObject& /*_rSource*/ ) throw (RuntimeException) + { + } + void clear() { m_pComponent = NULL; } +}; +DBG_NAME(OComponentDefinition_Impl) +OComponentDefinition_Impl::OComponentDefinition_Impl() +{ + DBG_CTOR(OComponentDefinition_Impl,NULL); +} +// ----------------------------------------------------------------------------- +OComponentDefinition_Impl::~OComponentDefinition_Impl() +{ + DBG_DTOR(OComponentDefinition_Impl,NULL); +} +//========================================================================== +//= OComponentDefinition +//========================================================================== +//-------------------------------------------------------------------------- +DBG_NAME(OComponentDefinition) +//-------------------------------------------------------------------------- +void OComponentDefinition::registerProperties() +{ + m_xColumnPropertyListener = ::comphelper::ImplementationReference<OColumnPropertyListener,XPropertyChangeListener>(new OColumnPropertyListener(this)); + OComponentDefinition_Impl& rDefinition( getDefinition() ); + ODataSettings::registerPropertiesFor( &rDefinition ); + + registerProperty(PROPERTY_NAME, PROPERTY_ID_NAME, PropertyAttribute::BOUND | PropertyAttribute::READONLY|PropertyAttribute::CONSTRAINED, + &rDefinition.m_aProps.aTitle, ::getCppuType(&rDefinition.m_aProps.aTitle)); + + if ( m_bTable ) + { + registerProperty(PROPERTY_SCHEMANAME, PROPERTY_ID_SCHEMANAME, PropertyAttribute::BOUND, + &rDefinition.m_sSchemaName, ::getCppuType(&rDefinition.m_sSchemaName)); + + registerProperty(PROPERTY_CATALOGNAME, PROPERTY_ID_CATALOGNAME, PropertyAttribute::BOUND, + &rDefinition.m_sCatalogName, ::getCppuType(&rDefinition.m_sCatalogName)); + } +} + +//-------------------------------------------------------------------------- +OComponentDefinition::OComponentDefinition(const Reference< XMultiServiceFactory >& _xORB + ,const Reference< XInterface >& _xParentContainer + ,const TContentPtr& _pImpl + ,sal_Bool _bTable) + :OContentHelper(_xORB,_xParentContainer,_pImpl) + ,ODataSettings(OContentHelper::rBHelper,!_bTable) + ,m_bTable(_bTable) +{ + DBG_CTOR(OComponentDefinition, NULL); + registerProperties(); +} +//-------------------------------------------------------------------------- +OComponentDefinition::~OComponentDefinition() +{ + DBG_DTOR(OComponentDefinition, NULL); +} + +//-------------------------------------------------------------------------- +OComponentDefinition::OComponentDefinition( const Reference< XInterface >& _rxContainer + ,const ::rtl::OUString& _rElementName + ,const Reference< XMultiServiceFactory >& _xORB + ,const TContentPtr& _pImpl + ,sal_Bool _bTable) + :OContentHelper(_xORB,_rxContainer,_pImpl) + ,ODataSettings(OContentHelper::rBHelper,!_bTable) + ,m_bTable(_bTable) +{ + DBG_CTOR(OComponentDefinition, NULL); + registerProperties(); + + m_pImpl->m_aProps.aTitle = _rElementName; + DBG_ASSERT(m_pImpl->m_aProps.aTitle.getLength() != 0, "OComponentDefinition::OComponentDefinition : invalid name !"); +} + +//-------------------------------------------------------------------------- +IMPLEMENT_IMPLEMENTATION_ID(OComponentDefinition); +IMPLEMENT_GETTYPES3(OComponentDefinition,ODataSettings,OContentHelper,OComponentDefinition_BASE); +IMPLEMENT_FORWARD_XINTERFACE3( OComponentDefinition,OContentHelper,ODataSettings,OComponentDefinition_BASE) +//-------------------------------------------------------------------------- +::rtl::OUString OComponentDefinition::getImplementationName_static( ) throw(RuntimeException) +{ + return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.dba.OComponentDefinition")); +} + +//-------------------------------------------------------------------------- +::rtl::OUString SAL_CALL OComponentDefinition::getImplementationName( ) throw(RuntimeException) +{ + return getImplementationName_static(); +} + +//-------------------------------------------------------------------------- +Sequence< ::rtl::OUString > OComponentDefinition::getSupportedServiceNames_static( ) throw(RuntimeException) +{ + Sequence< ::rtl::OUString > aServices(2); + aServices.getArray()[0] = SERVICE_SDB_TABLEDEFINITION; + aServices.getArray()[1] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.ucb.Content")); + + return aServices; +} + +//-------------------------------------------------------------------------- +Sequence< ::rtl::OUString > SAL_CALL OComponentDefinition::getSupportedServiceNames( ) throw(RuntimeException) +{ + return getSupportedServiceNames_static(); +} +//------------------------------------------------------------------------------ +Reference< XInterface > OComponentDefinition::Create( const Reference< XComponentContext >& _rxContext ) +{ + ::comphelper::ComponentContext aContext( _rxContext ); + return *(new OComponentDefinition( aContext.getLegacyServiceFactory(), NULL, TContentPtr( new OComponentDefinition_Impl ) ) ); +} +// ----------------------------------------------------------------------------- +void SAL_CALL OComponentDefinition::disposing() +{ + OContentHelper::disposing(); + if ( m_pColumns.get() ) + m_pColumns->disposing(); + m_xColumnPropertyListener->clear(); + m_xColumnPropertyListener.dispose(); +} +// ----------------------------------------------------------------------------- +IPropertyArrayHelper& OComponentDefinition::getInfoHelper() +{ + return *getArrayHelper(); +} +//-------------------------------------------------------------------------- +IPropertyArrayHelper* OComponentDefinition::createArrayHelper( ) const +{ + Sequence< Property > aProps; + describeProperties(aProps); + return new OPropertyArrayHelper(aProps); +} +//-------------------------------------------------------------------------- +Reference< XPropertySetInfo > SAL_CALL OComponentDefinition::getPropertySetInfo( ) throw(RuntimeException) +{ + Reference<XPropertySetInfo> xInfo( createPropertySetInfo( getInfoHelper() ) ); + return xInfo; +} + +// ----------------------------------------------------------------------------- +::rtl::OUString OComponentDefinition::determineContentType() const +{ + return m_bTable + ? ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "application/vnd.org.openoffice.DatabaseTable" ) ) + : ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "application/vnd.org.openoffice.DatabaseCommandDefinition" ) ); +} + +// ----------------------------------------------------------------------------- +Reference< XNameAccess> OComponentDefinition::getColumns() throw (RuntimeException) +{ + ::osl::MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OContentHelper::rBHelper.bDisposed); + + if ( !m_pColumns.get() ) + { + ::std::vector< ::rtl::OUString> aNames; + + const OComponentDefinition_Impl& rDefinition( getDefinition() ); + aNames.reserve( rDefinition.size() ); + + OComponentDefinition_Impl::const_iterator aIter = rDefinition.begin(); + OComponentDefinition_Impl::const_iterator aEnd = rDefinition.end(); + for ( ; aIter != aEnd; ++aIter ) + aNames.push_back( aIter->first ); + + m_pColumns.reset( new OColumns( *this, m_aMutex, sal_True, aNames, this, NULL, sal_True, sal_False, sal_False ) ); + m_pColumns->setParent( *this ); + } + return m_pColumns.get(); +} +// ----------------------------------------------------------------------------- +OColumn* OComponentDefinition::createColumn(const ::rtl::OUString& _rName) const +{ + const OComponentDefinition_Impl& rDefinition( getDefinition() ); + OComponentDefinition_Impl::const_iterator aFind = rDefinition.find( _rName ); + if ( aFind != rDefinition.end() ) + { + aFind->second->addPropertyChangeListener(::rtl::OUString(),m_xColumnPropertyListener.getRef()); + return new OTableColumnWrapper( aFind->second, aFind->second, true ); + } + OSL_ENSURE( false, "OComponentDefinition::createColumn: is this a valid case?" ); + // This here is the last place creating a OTableColumn, and somehow /me thinks it is not needed ... + return new OTableColumn( _rName ); +} +// ----------------------------------------------------------------------------- +Reference< XPropertySet > OComponentDefinition::createColumnDescriptor() +{ + return new OTableColumnDescriptor( true ); +} +// ----------------------------------------------------------------------------- +void OComponentDefinition::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any& rValue) throw (Exception) +{ + ODataSettings::setFastPropertyValue_NoBroadcast(nHandle,rValue); + notifyDataSourceModified(); +} +// ----------------------------------------------------------------------------- +void OComponentDefinition::columnDropped(const ::rtl::OUString& _sName) +{ + getDefinition().erase( _sName ); + notifyDataSourceModified(); +} +// ----------------------------------------------------------------------------- +void OComponentDefinition::columnAppended( const Reference< XPropertySet >& _rxSourceDescriptor ) +{ + ::rtl::OUString sName; + _rxSourceDescriptor->getPropertyValue( PROPERTY_NAME ) >>= sName; + + Reference<XPropertySet> xColDesc = new OTableColumnDescriptor( true ); + ::comphelper::copyProperties( _rxSourceDescriptor, xColDesc ); + getDefinition().insert( sName, xColDesc ); + + // formerly, here was a setParent at the xColDesc. The parent used was an adapter (ChildHelper_Impl) + // which held another XChild weak, and forwarded all getParent requests to this other XChild. + // m_pColumns was used for this. This was nonsense, since m_pColumns dies when our instance dies, + // but xColDesc will live longer than this. So effectively, the setParent call was pretty useless. + // + // The intention for this parenting was that the column descriptor is able to find the data source, + // by traveling up the parent hierachy until there's an XDataSource. This didn't work (which + // for instance causes #i65023#). We need another way to properly ensure this. + + notifyDataSourceModified(); +} + +//........................................................................ +} // namespace dbaccess +//........................................................................ + diff --git a/dbaccess/source/core/dataaccess/ComponentDefinition.hxx b/dbaccess/source/core/dataaccess/ComponentDefinition.hxx new file mode 100644 index 000000000000..834e7a9979fa --- /dev/null +++ b/dbaccess/source/core/dataaccess/ComponentDefinition.hxx @@ -0,0 +1,207 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 DBA_COREDATAACESS_COMPONENTDEFINITION_HXX +#define DBA_COREDATAACESS_COMPONENTDEFINITION_HXX + +#ifndef _DBA_CORE_COMMANDBASE_HXX_ +#include "commandbase.hxx" +#endif +#ifndef _COMPHELPER_PROPERTYCONTAINER_HXX_ +#include <comphelper/propertycontainer.hxx> +#endif +#ifndef _COM_SUN_STAR_SDBCX_XRENAME_HPP_ +#include <com/sun/star/sdbcx/XRename.hpp> +#endif +#ifndef _CPPUHELPER_IMPLBASE1_HXX_ +#include <cppuhelper/implbase1.hxx> +#endif +#ifndef _COMPHELPER_PROPERTY_ARRAY_HELPER_HXX_ +#include <comphelper/proparrhlp.hxx> +#endif +#ifndef _DBA_CORE_DATASETTINGS_HXX_ +#include "datasettings.hxx" +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_ +#include <com/sun/star/container/XNameAccess.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBCX_XCOLUMNSSUPPLIER_HPP_ +#include <com/sun/star/sdbcx/XColumnsSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_BEANS_XPROPERTYCHANGELISTENER_HPP_ +#include <com/sun/star/beans/XPropertyChangeListener.hpp> +#endif +#ifndef _COM_SUN_STAR_UNO_XCOMPONENTCONTEXT_HPP_ +#include <com/sun/star/uno/XComponentContext.hpp> +#endif +#ifndef DBA_CONTENTHELPER_HXX +#include "ContentHelper.hxx" +#endif +#ifndef _DBASHARED_APITOOLS_HXX_ +#include "apitools.hxx" +#endif +#ifndef _DBA_COREAPI_COLUMN_HXX_ +#include <column.hxx> +#endif +#include <comphelper/implementationreference.hxx> + +#include <memory> +//........................................................................ +namespace dbaccess +{ +//........................................................................ + + typedef ::cppu::ImplHelper1< ::com::sun::star::sdbcx::XColumnsSupplier > OComponentDefinition_BASE; + + class OComponentDefinition_Impl : public OContentHelper_Impl + ,public ODataSettings_Base + { + public: + typedef ::std::map < ::rtl::OUString + , ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > + > Columns; + typedef Columns::iterator iterator; + typedef Columns::const_iterator const_iterator; + + private: + Columns m_aColumns; + + public: + ::rtl::OUString m_sSchemaName; + ::rtl::OUString m_sCatalogName; + + public: + OComponentDefinition_Impl(); + virtual ~OComponentDefinition_Impl(); + + inline size_t size() const { return m_aColumns.size(); } + + inline const_iterator begin() const { return m_aColumns.begin(); } + inline const_iterator end() const { return m_aColumns.end(); } + + inline const_iterator find( const ::rtl::OUString& _rName ) const { return m_aColumns.find( _rName ); } + + inline void erase( const ::rtl::OUString& _rName ) { m_aColumns.erase( _rName ); } + + inline void insert( const ::rtl::OUString& _rName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxColumn ) + { + OSL_PRECOND( m_aColumns.find( _rName ) == m_aColumns.end(), "OComponentDefinition_Impl::insert: there's already an element with this name!" ); + m_aColumns.insert( Columns::value_type( _rName, _rxColumn ) ); + } + }; + +class OColumnPropertyListener; +//========================================================================= +//= OComponentDefinition - a database "document" which describes a query +//========================================================================= +class OComponentDefinition :public OContentHelper + ,public ODataSettings + ,public IColumnFactory + ,public OComponentDefinition_BASE + ,public ::comphelper::OPropertyArrayUsageHelper< OComponentDefinition > +{ + OComponentDefinition(); + +protected: + ::std::auto_ptr< OColumns > m_pColumns; + ::comphelper::ImplementationReference< OColumnPropertyListener,::com::sun::star::beans::XPropertyChangeListener> + m_xColumnPropertyListener; + sal_Bool m_bTable; + + virtual ~OComponentDefinition(); + virtual void SAL_CALL disposing(); + + +protected: + OComponentDefinition(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& + ,const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _xParentContainer + ,const TContentPtr& _pImpl + ,sal_Bool _bTable = sal_True); + + const OComponentDefinition_Impl& getDefinition() const { return dynamic_cast< const OComponentDefinition_Impl& >( *m_pImpl.get() ); } + OComponentDefinition_Impl& getDefinition() { return dynamic_cast< OComponentDefinition_Impl& >( *m_pImpl.get() ); } +public: + + OComponentDefinition( + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxContainer + ,const ::rtl::OUString& _rElementName + ,const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& + ,const TContentPtr& _pImpl + ,sal_Bool _bTable = sal_True + ); + +// com::sun::star::lang::XTypeProvider + DECLARE_TYPEPROVIDER( ); + +// ::com::sun::star::uno::XInterface + DECLARE_XINTERFACE( ) + +// ::com::sun::star::lang::XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw(::com::sun::star::uno::RuntimeException); + + static ::com::sun::star::uno::Sequence< ::rtl::OUString > getSupportedServiceNames_static(void) throw( ::com::sun::star::uno::RuntimeException ); + static ::rtl::OUString getImplementationName_static(void) throw( ::com::sun::star::uno::RuntimeException ); + static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL + Create(const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >&); + +// ::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); + + // XColumnsSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > SAL_CALL getColumns( ) throw (::com::sun::star::uno::RuntimeException); + + // OPropertySetHelper + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(); + + // IColumnFactory + virtual OColumn* createColumn(const ::rtl::OUString& _rName) const; + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > createColumnDescriptor(); + virtual void columnAppended( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxSourceDescriptor ); + virtual void columnDropped(const ::rtl::OUString& _sName); + virtual void notifyDataSourceModified() { OContentHelper::notifyDataSourceModified(); } + +protected: +// OPropertyArrayUsageHelper + virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const; + + virtual void SAL_CALL setFastPropertyValue_NoBroadcast( + sal_Int32 nHandle, + const ::com::sun::star::uno::Any& rValue) throw (::com::sun::star::uno::Exception); + + // OContentHelper overridables + virtual ::rtl::OUString determineContentType() const; + +private: + void registerProperties(); +}; + +//........................................................................ +} // namespace dbaccess +//........................................................................ + +#endif // DBA_COREDATAACESS_COMPONENTDEFINITION_HXX diff --git a/dbaccess/source/core/dataaccess/ContentHelper.cxx b/dbaccess/source/core/dataaccess/ContentHelper.cxx new file mode 100644 index 000000000000..3ed2649caabe --- /dev/null +++ b/dbaccess/source/core/dataaccess/ContentHelper.cxx @@ -0,0 +1,762 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" +#ifndef DBA_CONTENTHELPER_HXX +#include "ContentHelper.hxx" +#endif +#ifndef _UCBHELPER_CANCELCOMMANDEXECUTION_HXX_ +#include <ucbhelper/cancelcommandexecution.hxx> +#endif +#ifndef _COMPHELPER_PROPERTY_HXX_ +#include <comphelper/property.hxx> +#endif +#ifndef _COM_SUN_STAR_UCB_UNSUPPORTEDCOMMANDEXCEPTION_HPP_ +#include <com/sun/star/ucb/UnsupportedCommandException.hpp> +#endif +#ifndef _COM_SUN_STAR_LANG_ILLEGALARGUMENTEXCEPTION_HPP_ +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#endif +#ifndef _COM_SUN_STAR_LANG_ILLEGALACCESSEXCEPTION_HPP_ +#include <com/sun/star/lang/IllegalAccessException.hpp> +#endif +#ifndef _COM_SUN_STAR_IO_XOUTPUTSTREAM_HPP_ +#include <com/sun/star/io/XOutputStream.hpp> +#endif +#ifndef _COM_SUN_STAR_IO_XACTIVEDATASINK_HPP_ +#include <com/sun/star/io/XActiveDataSink.hpp> +#endif +#ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBUTE_HPP_ +#include <com/sun/star/beans/PropertyAttribute.hpp> +#endif +#ifndef _UCBHELPER_PROPERTYVALUESET_HXX +#include <ucbhelper/propertyvalueset.hxx> +#endif +#ifndef _UCBHELPER_CONTENTIDENTIFIER_HXX +#include <ucbhelper/contentidentifier.hxx> +#endif +#ifndef DBA_UCPRESULTSET_HXX +#include "myucp_resultset.hxx" +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XNAMECONTAINER_HPP_ +#include <com/sun/star/container/XNameContainer.hpp> +#endif +#ifndef DBACORE_SDBCORETOOLS_HXX +#include "sdbcoretools.hxx" +#endif +#ifndef DBACCESS_SHARED_DBASTRINGS_HRC +#include "dbastrings.hrc" +#endif +#ifndef _TOOLS_DEBUG_HXX +#include <tools/debug.hxx> +#endif + + +namespace dbaccess +{ +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::ucb; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::embed; +using namespace ::com::sun::star::container; +using namespace ::comphelper; +using namespace ::cppu; + +// ----------------------------------------------------------------------------- +DBG_NAME(OContentHelper_Impl) +OContentHelper_Impl::OContentHelper_Impl() +{ + DBG_CTOR(OContentHelper_Impl,NULL); +} +// ----------------------------------------------------------------------------- +OContentHelper_Impl::~OContentHelper_Impl() +{ + DBG_DTOR(OContentHelper_Impl,NULL); +} +// ----------------------------------------------------------------------------- + +OContentHelper::OContentHelper(const Reference< XMultiServiceFactory >& _xORB + ,const Reference< XInterface >& _xParentContainer + ,const TContentPtr& _pImpl) + : OContentHelper_COMPBASE(m_aMutex) + ,m_aContentListeners(m_aMutex) + ,m_aPropertyChangeListeners(m_aMutex) + ,m_xParentContainer(_xParentContainer) + ,m_aContext( _xORB ) + ,m_aErrorHelper( m_aContext ) + ,m_pImpl(_pImpl) + ,m_nCommandId(0) +{ +} +//-------------------------------------------------------------------------- +void SAL_CALL OContentHelper::disposing() +{ + ::osl::MutexGuard aGuard(m_aMutex); + + // say our listeners goobye + EventObject aEvt(*this); + m_aContentListeners.disposeAndClear(aEvt); + + m_xParentContainer = NULL; +} +// ----------------------------------------------------------------------------- +IMPLEMENT_SERVICE_INFO1(OContentHelper,"com.sun.star.comp.sdb.Content","com.sun.star.ucb.Content"); +IMPLEMENT_IMPLEMENTATION_ID(OContentHelper) +// ----------------------------------------------------------------------------- +// XContent +Reference< XContentIdentifier > SAL_CALL OContentHelper::getIdentifier( ) throw (RuntimeException) +{ + ::osl::MutexGuard aGuard(m_aMutex); + ::rtl::OUStringBuffer aIdentifier; + aIdentifier.appendAscii( "private:" ); + aIdentifier.append( impl_getHierarchicalName( true ) ); + return new ::ucbhelper::ContentIdentifier( m_aContext.getLegacyServiceFactory(), aIdentifier.makeStringAndClear() ); +} +// ----------------------------------------------------------------------------- +::rtl::OUString OContentHelper::impl_getHierarchicalName( bool _includingRootContainer ) const +{ + ::rtl::OUStringBuffer aHierarchicalName( m_pImpl->m_aProps.aTitle ); + Reference< XInterface > xParent = m_xParentContainer; + while( xParent.is() ) + { + Reference<XPropertySet> xProp( xParent, UNO_QUERY ); + Reference< XChild > xChild( xParent, UNO_QUERY ); + xParent.set( xChild.is() ? xChild->getParent() : Reference< XInterface >(), UNO_QUERY ); + if ( xProp.is() && xParent.is() ) + { + ::rtl::OUString sName; + xProp->getPropertyValue( PROPERTY_NAME ) >>= sName; + + ::rtl::OUString sPrevious = aHierarchicalName.makeStringAndClear(); + aHierarchicalName.append( sName ); + aHierarchicalName.append( sal_Unicode( '/' ) ); + aHierarchicalName.append( sPrevious ); + } + } + ::rtl::OUString sHierarchicalName( aHierarchicalName.makeStringAndClear() ); + if ( !_includingRootContainer ) + sHierarchicalName = sHierarchicalName.copy( sHierarchicalName.indexOf( '/' ) + 1 ); + return sHierarchicalName; +} + +// ----------------------------------------------------------------------------- +::rtl::OUString SAL_CALL OContentHelper::getContentType() throw (RuntimeException) +{ + ::osl::MutexGuard aGuard(m_aMutex); + + if ( !m_pImpl->m_aProps.aContentType ) + { // content type not yet retrieved + m_pImpl->m_aProps.aContentType.reset( determineContentType() ); + } + + return *m_pImpl->m_aProps.aContentType; +} +// ----------------------------------------------------------------------------- +void SAL_CALL OContentHelper::addContentEventListener( const Reference< XContentEventListener >& _rxListener ) throw (RuntimeException) +{ + ::osl::MutexGuard aGuard(m_aMutex); + if ( _rxListener.is() ) + m_aContentListeners.addInterface(_rxListener); +} +// ----------------------------------------------------------------------------- +void SAL_CALL OContentHelper::removeContentEventListener( const Reference< XContentEventListener >& _rxListener ) throw (RuntimeException) +{ + ::osl::MutexGuard aGuard(m_aMutex); + if (_rxListener.is()) + m_aContentListeners.removeInterface(_rxListener); +} +// ----------------------------------------------------------------------------- + +// XCommandProcessor +sal_Int32 SAL_CALL OContentHelper::createCommandIdentifier( ) throw (RuntimeException) +{ + ::osl::MutexGuard aGuard(m_aMutex); + // Just increase counter on every call to generate an identifier. + return ++m_nCommandId; +} +// ----------------------------------------------------------------------------- +Any SAL_CALL OContentHelper::execute( const Command& aCommand, sal_Int32 /*CommandId*/, const Reference< XCommandEnvironment >& Environment ) throw (Exception, CommandAbortedException, RuntimeException) +{ + Any aRet; + if ( aCommand.Name.compareToAscii( "getPropertyValues" ) == 0 ) + { + ////////////////////////////////////////////////////////////////// + // getPropertyValues + ////////////////////////////////////////////////////////////////// + + Sequence< Property > Properties; + if ( !( aCommand.Argument >>= Properties ) ) + { + OSL_ENSURE( sal_False, "Wrong argument type!" ); + ucbhelper::cancelCommandExecution( + makeAny( IllegalArgumentException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + aRet <<= getPropertyValues( Properties); + } + else if ( aCommand.Name.compareToAscii( "setPropertyValues" ) == 0 ) + { + ////////////////////////////////////////////////////////////////// + // setPropertyValues + ////////////////////////////////////////////////////////////////// + + Sequence< PropertyValue > aProperties; + if ( !( aCommand.Argument >>= aProperties ) ) + { + OSL_ENSURE( sal_False, "Wrong argument type!" ); + ucbhelper::cancelCommandExecution( + makeAny( IllegalArgumentException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + if ( !aProperties.getLength() ) + { + OSL_ENSURE( sal_False, "No properties!" ); + ucbhelper::cancelCommandExecution( + makeAny( IllegalArgumentException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + aRet <<= setPropertyValues( aProperties, Environment ); + } + else if ( aCommand.Name.compareToAscii( "getPropertySetInfo" ) == 0 ) + { + ////////////////////////////////////////////////////////////////// + // getPropertySetInfo + ////////////////////////////////////////////////////////////////// + + Reference<XPropertySet> xProp(*this,UNO_QUERY); + if ( xProp.is() ) + aRet <<= xProp->getPropertySetInfo(); + // aRet <<= getPropertySetInfo(); // TODO + } + else + { + ////////////////////////////////////////////////////////////////// + // Unsupported command + ////////////////////////////////////////////////////////////////// + + OSL_ENSURE( sal_False, "Content::execute - unsupported command!" ); + + ucbhelper::cancelCommandExecution( + makeAny( UnsupportedCommandException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ) ) ), + Environment ); + // Unreachable + } + + return aRet; +} +// ----------------------------------------------------------------------------- +void SAL_CALL OContentHelper::abort( sal_Int32 /*CommandId*/ ) throw (RuntimeException) +{ +} +// ----------------------------------------------------------------------------- + +// XPropertiesChangeNotifier +void SAL_CALL OContentHelper::addPropertiesChangeListener( const Sequence< ::rtl::OUString >& PropertyNames, const Reference< XPropertiesChangeListener >& Listener ) throw (RuntimeException) +{ + ::osl::MutexGuard aGuard(m_aMutex); + sal_Int32 nCount = PropertyNames.getLength(); + if ( !nCount ) + { + // Note: An empty sequence means a listener for "all" properties. + m_aPropertyChangeListeners.addInterface(::rtl::OUString(), Listener ); + } + else + { + const ::rtl::OUString* pSeq = PropertyNames.getConstArray(); + + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + const ::rtl::OUString& rName = pSeq[ n ]; + if ( rName.getLength() ) + m_aPropertyChangeListeners.addInterface(rName, Listener ); + } + } +} +// ----------------------------------------------------------------------------- +void SAL_CALL OContentHelper::removePropertiesChangeListener( const Sequence< ::rtl::OUString >& PropertyNames, const Reference< XPropertiesChangeListener >& Listener ) throw (RuntimeException) +{ + ::osl::MutexGuard aGuard(m_aMutex); + sal_Int32 nCount = PropertyNames.getLength(); + if ( !nCount ) + { + // Note: An empty sequence means a listener for "all" properties. + m_aPropertyChangeListeners.removeInterface( ::rtl::OUString(), Listener ); + } + else + { + const ::rtl::OUString* pSeq = PropertyNames.getConstArray(); + + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + const ::rtl::OUString& rName = pSeq[ n ]; + if ( rName.getLength() ) + m_aPropertyChangeListeners.removeInterface( rName, Listener ); + } + } +} +// ----------------------------------------------------------------------------- + +// XPropertyContainer +void SAL_CALL OContentHelper::addProperty( const ::rtl::OUString& /*Name*/, sal_Int16 /*Attributes*/, const Any& /*DefaultValue*/ ) throw (PropertyExistException, IllegalTypeException, IllegalArgumentException, RuntimeException) +{ + DBG_ERROR( "OContentHelper::addProperty: not implemented!" ); +} +// ----------------------------------------------------------------------------- +void SAL_CALL OContentHelper::removeProperty( const ::rtl::OUString& /*Name*/ ) throw (UnknownPropertyException, NotRemoveableException, RuntimeException) +{ + DBG_ERROR( "OContentHelper::removeProperty: not implemented!" ); +} +// ----------------------------------------------------------------------------- +// XInitialization +void SAL_CALL OContentHelper::initialize( const Sequence< Any >& _aArguments ) throw(Exception, RuntimeException) +{ + const Any* pBegin = _aArguments.getConstArray(); + const Any* pEnd = pBegin + _aArguments.getLength(); + PropertyValue aValue;; + for(;pBegin != pEnd;++pBegin) + { + *pBegin >>= aValue; + if ( aValue.Name.equalsAscii("Parent") ) + { + m_xParentContainer.set(aValue.Value,UNO_QUERY); + } + else if ( aValue.Name.equalsAscii(PROPERTY_NAME) ) + { + aValue.Value >>= m_pImpl->m_aProps.aTitle; + } + else if ( aValue.Name.equalsAscii(PROPERTY_PERSISTENT_NAME) ) + { + aValue.Value >>= m_pImpl->m_aProps.sPersistentName; + } + } +} +// ----------------------------------------------------------------------------- +Sequence< Any > OContentHelper::setPropertyValues(const Sequence< PropertyValue >& rValues,const Reference< XCommandEnvironment >& /*xEnv*/ ) +{ + osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); + + Sequence< Any > aRet( rValues.getLength() ); + Sequence< PropertyChangeEvent > aChanges( rValues.getLength() ); + sal_Int32 nChanged = 0; + + PropertyChangeEvent aEvent; + aEvent.Source = static_cast< cppu::OWeakObject * >( this ); + aEvent.Further = sal_False; + aEvent.PropertyHandle = -1; + + const PropertyValue* pValues = rValues.getConstArray(); + sal_Int32 nCount = rValues.getLength(); + + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + const PropertyValue& rValue = pValues[ n ]; + + if ( rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) ) + { + // Read-only property! + aRet[ n ] <<= IllegalAccessException( + rtl::OUString::createFromAscii( + "Property is read-only!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + else if ( rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) ) + { + // Read-only property! + aRet[ n ] <<= IllegalAccessException( + rtl::OUString::createFromAscii( + "Property is read-only!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + else if ( rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) ) + { + // Read-only property! + aRet[ n ] <<= IllegalAccessException( + rtl::OUString::createFromAscii( + "Property is read-only!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + else if ( rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) + { + rtl::OUString aNewValue; + if ( rValue.Value >>= aNewValue ) + { + if ( aNewValue != m_pImpl->m_aProps.aTitle ) + { + aEvent.PropertyName = rValue.Name; + aEvent.OldValue = makeAny( m_pImpl->m_aProps.aTitle ); + + try + { + impl_rename_throw( aNewValue ,false); + OSL_ENSURE( m_pImpl->m_aProps.aTitle == aNewValue, "OContentHelper::setPropertyValues('Title'): rename did not work!" ); + + aEvent.NewValue = makeAny( aNewValue ); + aChanges.getArray()[ nChanged ] = aEvent; + nChanged++; + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "OContentHelper::setPropertyValues('Title'): caught an exception while renaming!" ); + } + } + else + { + // Old value equals new value. No error! + } + } + else + { + aRet[ n ] <<= IllegalTypeException( + rtl::OUString::createFromAscii( + "Property value has wrong type!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + } + + // @@@ Process other properties supported directly. +#if 0 + else if ( rValue.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "xxxxxx" ) ) ) + { + } +#endif + else + { + aRet[ n ] <<= Exception( + rtl::OUString::createFromAscii( + "No property set for storing the value!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } + } + + if ( nChanged > 0 ) + { + // @@@ Save changes. +// storeData(); + + notifyDataSourceModified(); + aGuard.clear(); + aChanges.realloc( nChanged ); + notifyPropertiesChange( aChanges ); + } + + return aRet; +} +// ----------------------------------------------------------------------------- +//========================================================================= +// static +Reference< XRow > OContentHelper::getPropertyValues( const Sequence< Property >& rProperties) +{ + // Note: Empty sequence means "get values of all supported properties". + + rtl::Reference< ::ucbhelper::PropertyValueSet > xRow = new ::ucbhelper::PropertyValueSet( m_aContext.getLegacyServiceFactory() ); + + sal_Int32 nCount = rProperties.getLength(); + if ( nCount ) + { + const Property* pProps = rProperties.getConstArray(); + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + const Property& rProp = pProps[ n ]; + + // Process Core properties. + + if ( rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) ) + { + xRow->appendString ( rProp, getContentType() ); + } + else if ( rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) + { + xRow->appendString ( rProp, m_pImpl->m_aProps.aTitle ); + } + else if ( rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) ) + { + xRow->appendBoolean( rProp, m_pImpl->m_aProps.bIsDocument ); + } + else if ( rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) ) + { + xRow->appendBoolean( rProp, m_pImpl->m_aProps.bIsFolder ); + } + else + xRow->appendVoid(rProp); + + // @@@ Process other properties supported directly. +#if 0 + else if ( rProp.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "xxxxxx" ) ) ) + { + } +#endif + } + } + else + { + // Append all Core Properties. + xRow->appendString ( + Property( rtl::OUString::createFromAscii( "ContentType" ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + PropertyAttribute::BOUND + | PropertyAttribute::READONLY ), + getContentType() ); + xRow->appendString ( + Property( rtl::OUString::createFromAscii( "Title" ), + -1, + getCppuType( static_cast< const rtl::OUString * >( 0 ) ), + PropertyAttribute::BOUND ), + m_pImpl->m_aProps.aTitle ); + xRow->appendBoolean( + Property( rtl::OUString::createFromAscii( "IsDocument" ), + -1, + getCppuBooleanType(), + PropertyAttribute::BOUND + | PropertyAttribute::READONLY ), + m_pImpl->m_aProps.bIsDocument ); + xRow->appendBoolean( + Property( rtl::OUString::createFromAscii( "IsFolder" ), + -1, + getCppuBooleanType(), + PropertyAttribute::BOUND + | PropertyAttribute::READONLY ), + m_pImpl->m_aProps.bIsFolder ); + + // @@@ Append other properties supported directly. + } + + return Reference< XRow >( xRow.get() ); +} +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +void OContentHelper::notifyPropertiesChange( const Sequence< PropertyChangeEvent >& evt ) const +{ + + sal_Int32 nCount = evt.getLength(); + if ( nCount ) + { + // First, notify listeners interested in changes of every property. + OInterfaceContainerHelper* pAllPropsContainer = m_aPropertyChangeListeners.getContainer( ::rtl::OUString() ); + if ( pAllPropsContainer ) + { + OInterfaceIteratorHelper aIter( *pAllPropsContainer ); + while ( aIter.hasMoreElements() ) + { + // Propagate event. + Reference< XPropertiesChangeListener > xListener( aIter.next(), UNO_QUERY ); + if ( xListener.is() ) + xListener->propertiesChange( evt ); + } + } + + typedef Sequence< PropertyChangeEvent > PropertyEventSequence; + typedef ::std::map< XPropertiesChangeListener*, PropertyEventSequence* > PropertiesEventListenerMap; + PropertiesEventListenerMap aListeners; + + + const PropertyChangeEvent* propertyChangeEvent = evt.getConstArray(); + + for ( sal_Int32 n = 0; n < nCount; ++n, ++propertyChangeEvent ) + { + const PropertyChangeEvent& rEvent = *propertyChangeEvent; + const ::rtl::OUString& rName = rEvent.PropertyName; + + OInterfaceContainerHelper* pPropsContainer = m_aPropertyChangeListeners.getContainer( rName ); + if ( pPropsContainer ) + { + OInterfaceIteratorHelper aIter( *pPropsContainer ); + while ( aIter.hasMoreElements() ) + { + PropertyEventSequence* propertyEvents = NULL; + + XPropertiesChangeListener* pListener = static_cast< XPropertiesChangeListener * >( aIter.next() ); + PropertiesEventListenerMap::iterator it = aListeners.find( pListener ); + if ( it == aListeners.end() ) + { + // Not in map - create and insert new entry. + propertyEvents = new PropertyEventSequence( nCount ); + aListeners[ pListener ] = propertyEvents; + } + else + propertyEvents = (*it).second; + + if ( propertyEvents ) + (*propertyEvents)[n] = rEvent; + } + } + } + + // Notify listeners. + PropertiesEventListenerMap::iterator it = aListeners.begin(); + while ( !aListeners.empty() ) + { + XPropertiesChangeListener* pListener = + static_cast< XPropertiesChangeListener * >( (*it).first ); + PropertyEventSequence* pSeq = (*it).second; + + // Remove current element. + aListeners.erase( it ); + + // Propagate event. + pListener->propertiesChange( *pSeq ); + + delete pSeq; + + it = aListeners.begin(); + } + } +} +// ----------------------------------------------------------------------------- +// com::sun::star::lang::XUnoTunnel +//------------------------------------------------------------------ +sal_Int64 OContentHelper::getSomething( const Sequence< sal_Int8 > & rId ) throw (RuntimeException) +{ + if (rId.getLength() == 16 && 0 == rtl_compareMemory(getUnoTunnelImplementationId().getConstArray(), rId.getConstArray(), 16 ) ) + return reinterpret_cast<sal_Int64>(this); + + return 0; +} + +// ----------------------------------------------------------------------------- +OContentHelper* OContentHelper::getImplementation( const Reference< XInterface >& _rxComponent ) +{ + OContentHelper* pContent( NULL ); + + Reference< XUnoTunnel > xUnoTunnel( _rxComponent, UNO_QUERY ); + if ( xUnoTunnel.is() ) + pContent = reinterpret_cast< OContentHelper* >( xUnoTunnel->getSomething( getUnoTunnelImplementationId() ) ); + + return pContent; +} + +// ----------------------------------------------------------------------------- +Reference< XInterface > SAL_CALL OContentHelper::getParent( ) throw (RuntimeException) +{ + ::osl::MutexGuard aGuard(m_aMutex); + return m_xParentContainer; +} +// ----------------------------------------------------------------------------- +void SAL_CALL OContentHelper::setParent( const Reference< XInterface >& _xParent ) throw (NoSupportException, RuntimeException) +{ + ::osl::MutexGuard aGuard(m_aMutex); + m_xParentContainer = _xParent; +} + +// ----------------------------------------------------------------------------- +void OContentHelper::impl_rename_throw(const ::rtl::OUString& _sNewName,bool _bNotify ) +{ + osl::ClearableGuard< osl::Mutex > aGuard(m_aMutex); + if ( _sNewName.equals( m_pImpl->m_aProps.aTitle ) ) + return; + try + { + Sequence< PropertyChangeEvent > aChanges( 1 ); + + aChanges[0].Source = static_cast< cppu::OWeakObject * >( this ); + aChanges[0].Further = sal_False; + aChanges[0].PropertyName = PROPERTY_NAME; + aChanges[0].PropertyHandle = PROPERTY_ID_NAME; + aChanges[0].OldValue <<= m_pImpl->m_aProps.aTitle; + aChanges[0].NewValue <<= _sNewName; + + aGuard.clear(); + + m_pImpl->m_aProps.aTitle = _sNewName; + if ( _bNotify ) + notifyPropertiesChange( aChanges ); + notifyDataSourceModified(); + } + catch(const PropertyVetoException&) + { + throw ElementExistException(_sNewName,*this); + } +} +// ----------------------------------------------------------------------------- +void SAL_CALL OContentHelper::rename( const ::rtl::OUString& newName ) throw (SQLException, ElementExistException, RuntimeException) +{ + + impl_rename_throw(newName); + //Reference<XNameContainer> xNameCont(m_xParentContainer,UNO_QUERY); + //if ( xNameCont.is() ) + //{ + // if ( xNameCont->hasByName(newName) ) + // throw ElementExistException(newName,*this); + + // try + // { + // if ( xNameCont->hasByName(m_pImpl->m_aProps.aTitle) ) + // xNameCont->removeByName(m_pImpl->m_aProps.aTitle); + + // m_pImpl->m_aProps.aTitle = newName; + // xNameCont->insertByName(m_pImpl->m_aProps.aTitle,makeAny(Reference<XContent>(*this,UNO_QUERY))); + // notifyDataSourceModified(); + // } + // catch(IllegalArgumentException) + // { + // throw SQLException(); + // } + // catch(NoSuchElementException) + // { + // throw SQLException(); + // } + // catch(WrappedTargetException) + // { + // throw SQLException(); + // } + //} + //else + // m_pImpl->m_aProps.aTitle = newName; + +} +// ----------------------------------------------------------------------------- +void OContentHelper::notifyDataSourceModified() +{ + ::dbaccess::notifyDataSourceModified(m_xParentContainer,sal_True); +} +//........................................................................ +} // namespace dbaccess +//........................................................................ + diff --git a/dbaccess/source/core/dataaccess/ModelImpl.cxx b/dbaccess/source/core/dataaccess/ModelImpl.cxx new file mode 100644 index 000000000000..ee50bea00dd0 --- /dev/null +++ b/dbaccess/source/core/dataaccess/ModelImpl.cxx @@ -0,0 +1,1502 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#include "commandcontainer.hxx" +#include "connection.hxx" +#include "core_resource.hrc" +#include "core_resource.hxx" +#include "databasecontext.hxx" +#include "databasedocument.hxx" +#include "datasource.hxx" +#include "dbastrings.hrc" +#include "ModelImpl.hxx" +#include "userinformation.hxx" +#include "sdbcoretools.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/container/XSet.hpp> +#include <com/sun/star/document/MacroExecMode.hpp> +#include <com/sun/star/embed/XTransactedObject.hpp> +#include <com/sun/star/embed/XTransactionBroadcaster.hpp> +#include <com/sun/star/sdb/BooleanComparisonMode.hpp> +#include <com/sun/star/script/DocumentScriptLibraryContainer.hpp> +#include <com/sun/star/script/DocumentDialogLibraryContainer.hpp> +#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp> +#include <com/sun/star/form/XLoadable.hpp> +/** === end UNO includes === **/ + +#include <comphelper/interaction.hxx> +#include <comphelper/mediadescriptor.hxx> +#include <comphelper/seqstream.hxx> +#include <comphelper/sequence.hxx> +#include <connectivity/dbexception.hxx> +#include <cppuhelper/exc_hlp.hxx> +#include <cppuhelper/typeprovider.hxx> +#include <rtl/digest.h> +#include <sfx2/signaturestate.hxx> +#include <tools/debug.hxx> +#include <tools/diagnose_ex.h> +#include <tools/errcode.hxx> +#include <tools/urlobj.hxx> +#include <unotools/sharedunocomponent.hxx> + +#include <algorithm> + +using namespace ::com::sun::star::document; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::embed; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::task; +using namespace ::com::sun::star::ucb; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::view; +using namespace ::com::sun::star::task; +using namespace ::com::sun::star::reflection; +using namespace ::com::sun::star::script; +using namespace ::cppu; +using namespace ::osl; +using namespace ::vos; +using namespace ::dbtools; +using namespace ::comphelper; +namespace css = ::com::sun::star; + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + +//============================================================ +//= VosMutexFacade +//============================================================ +//------------------------------------------------------------------------ +VosMutexFacade::VosMutexFacade( ::osl::Mutex& _rMutex ) + :m_rMutex( _rMutex ) +{ +} + +//------------------------------------------------------------------------ +void SAL_CALL VosMutexFacade::acquire() +{ + m_rMutex.acquire(); +} + +//------------------------------------------------------------------------ +sal_Bool SAL_CALL VosMutexFacade::tryToAcquire() +{ + return m_rMutex.tryToAcquire(); +} + +//------------------------------------------------------------------------ +void SAL_CALL VosMutexFacade::release() +{ + m_rMutex.release(); +} + +//============================================================ +//= DocumentStorageAccess +//============================================================ +DBG_NAME( DocumentStorageAccess ) +class DocumentStorageAccess : public ::cppu::WeakImplHelper2< XDocumentSubStorageSupplier + , XTransactionListener > +{ + typedef ::std::map< ::rtl::OUString, Reference< XStorage > > NamedStorages; + + ::osl::Mutex m_aMutex; + /// all sub storages which we ever gave to the outer world + NamedStorages m_aExposedStorages; + ODatabaseModelImpl* m_pModelImplementation; + bool m_bPropagateCommitToRoot; + bool m_bDisposingSubStorages; + +public: + DocumentStorageAccess( ODatabaseModelImpl& _rModelImplementation ) + :m_pModelImplementation( &_rModelImplementation ) + ,m_bPropagateCommitToRoot( true ) + ,m_bDisposingSubStorages( false ) + { + DBG_CTOR( DocumentStorageAccess, NULL ); + } + +protected: + ~DocumentStorageAccess() + { + DBG_DTOR( DocumentStorageAccess, NULL ); + } + +public: + void dispose(); + + // XDocumentSubStorageSupplier + virtual Reference< XStorage > SAL_CALL getDocumentSubStorage( const ::rtl::OUString& aStorageName, ::sal_Int32 _nMode ) throw (RuntimeException); + virtual Sequence< ::rtl::OUString > SAL_CALL getDocumentSubStoragesNames( ) throw (IOException, RuntimeException); + + // XTransactionListener + virtual void SAL_CALL preCommit( const ::com::sun::star::lang::EventObject& aEvent ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL commited( const ::com::sun::star::lang::EventObject& aEvent ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL preRevert( const ::com::sun::star::lang::EventObject& aEvent ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL reverted( const ::com::sun::star::lang::EventObject& aEvent ) 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); + + /// disposes all storages managed by this instance + void disposeStorages(); + + /// disposes all known sub storages + void commitStorages() SAL_THROW(( IOException, RuntimeException )); + + /// commits the dedicated "database" storage + bool commitEmbeddedStorage( bool _bPreventRootCommits ); + +private: + /** opens the sub storage with the given name, in the given mode + */ + Reference< XStorage > impl_openSubStorage_nothrow( const ::rtl::OUString& _rStorageName, sal_Int32 _nMode ); + + void impl_suspendCommitPropagation() + { + OSL_ENSURE( m_bPropagateCommitToRoot, "DocumentStorageAccess::impl_suspendCommitPropagation: already suspended" ); + m_bPropagateCommitToRoot = false; + } + void impl_resumeCommitPropagation() + { + OSL_ENSURE( !m_bPropagateCommitToRoot, "DocumentStorageAccess::impl_resumeCommitPropagation: not suspended" ); + m_bPropagateCommitToRoot = true; + } + +}; + +//-------------------------------------------------------------------------- +void DocumentStorageAccess::dispose() +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + for ( NamedStorages::iterator loop = m_aExposedStorages.begin(); + loop != m_aExposedStorages.end(); + ++loop + ) + { + try + { + Reference< XTransactionBroadcaster > xBroadcaster( loop->second, UNO_QUERY ); + if ( xBroadcaster.is() ) + xBroadcaster->removeTransactionListener( this ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + m_aExposedStorages.clear(); + + m_pModelImplementation = NULL; +} + +//-------------------------------------------------------------------------- +Reference< XStorage > DocumentStorageAccess::impl_openSubStorage_nothrow( const ::rtl::OUString& _rStorageName, sal_Int32 _nDesiredMode ) +{ + OSL_ENSURE( _rStorageName.getLength(),"ODatabaseModelImpl::impl_openSubStorage_nothrow: Invalid storage name!" ); + + Reference< XStorage > xStorage; + try + { + Reference< XStorage > xRootStorage( m_pModelImplementation->getOrCreateRootStorage() ); + if ( xRootStorage.is() ) + { + sal_Int32 nRealMode = m_pModelImplementation->m_bDocumentReadOnly ? ElementModes::READ : _nDesiredMode; + if ( nRealMode == ElementModes::READ ) + { + Reference< XNameAccess > xSubStorageNames( xRootStorage, UNO_QUERY ); + if ( xSubStorageNames.is() && !xSubStorageNames->hasByName( _rStorageName ) ) + return xStorage; + } + + xStorage = xRootStorage->openStorageElement( _rStorageName, nRealMode ); + + Reference< XTransactionBroadcaster > xBroad( xStorage, UNO_QUERY ); + if ( xBroad.is() ) + xBroad->addTransactionListener( this ); + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + return xStorage; +} + +//-------------------------------------------------------------------------- +void DocumentStorageAccess::disposeStorages() +{ + m_bDisposingSubStorages = true; + + NamedStorages::iterator aEnd = m_aExposedStorages.end(); + for ( NamedStorages::iterator aIter = m_aExposedStorages.begin(); + aIter != aEnd ; + ++aIter + ) + { + try + { + ::comphelper::disposeComponent( aIter->second ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + m_aExposedStorages.clear(); + + m_bDisposingSubStorages = false; +} + +//-------------------------------------------------------------------------- +void DocumentStorageAccess::commitStorages() SAL_THROW(( IOException, RuntimeException )) +{ + try + { + for ( NamedStorages::const_iterator aIter = m_aExposedStorages.begin(); + aIter != m_aExposedStorages.end(); + ++aIter + ) + { + tools::stor::commitStorageIfWriteable( aIter->second ); + } + } + catch(const WrappedTargetException&) + { + // WrappedTargetException not allowed to leave + throw IOException(); + } +} + +//-------------------------------------------------------------------------- +bool DocumentStorageAccess::commitEmbeddedStorage( bool _bPreventRootCommits ) +{ + if ( _bPreventRootCommits ) + impl_suspendCommitPropagation(); + + bool bSuccess = false; + try + { + NamedStorages::const_iterator pos = m_aExposedStorages.find( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "database" ) ) ); + if ( pos != m_aExposedStorages.end() ) + bSuccess = tools::stor::commitStorageIfWriteable( pos->second ); + } + catch( Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + if ( _bPreventRootCommits ) + impl_resumeCommitPropagation(); + + return bSuccess; + +} + +//-------------------------------------------------------------------------- +Reference< XStorage > SAL_CALL DocumentStorageAccess::getDocumentSubStorage( const ::rtl::OUString& aStorageName, ::sal_Int32 _nDesiredMode ) throw (RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + NamedStorages::iterator pos = m_aExposedStorages.find( aStorageName ); + if ( pos == m_aExposedStorages.end() ) + { + Reference< XStorage > xResult = impl_openSubStorage_nothrow( aStorageName, _nDesiredMode ); + pos = m_aExposedStorages.insert( NamedStorages::value_type( aStorageName, xResult ) ).first; + } + + return pos->second; +} + +//-------------------------------------------------------------------------- +Sequence< ::rtl::OUString > SAL_CALL DocumentStorageAccess::getDocumentSubStoragesNames( ) throw (IOException, RuntimeException) +{ + Reference< XStorage > xRootStor( m_pModelImplementation->getRootStorage() ); + if ( !xRootStor.is() ) + return Sequence< ::rtl::OUString >(); + + ::std::vector< ::rtl::OUString > aNames; + + Reference< XNameAccess > xNames( xRootStor, UNO_QUERY_THROW ); + Sequence< ::rtl::OUString > aElementNames( xNames->getElementNames() ); + for ( sal_Int32 i=0; i<aElementNames.getLength(); ++i ) + { + if ( xRootStor->isStorageElement( aElementNames[i] ) ) + aNames.push_back( aElementNames[i] ); + } + return aNames.empty() + ? Sequence< ::rtl::OUString >() + : Sequence< ::rtl::OUString >( &aNames[0], aNames.size() ); +} + +//-------------------------------------------------------------------------- +void SAL_CALL DocumentStorageAccess::preCommit( const css::lang::EventObject& /*aEvent*/ ) throw (Exception, RuntimeException) +{ + // not interested in +} + +//-------------------------------------------------------------------------- +void SAL_CALL DocumentStorageAccess::commited( const css::lang::EventObject& aEvent ) throw (RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( m_pModelImplementation ) + m_pModelImplementation->setModified( sal_True ); + + if ( m_pModelImplementation && m_bPropagateCommitToRoot ) + { + Reference< XStorage > xStorage( aEvent.Source, UNO_QUERY ); + + // check if this is the dedicated "database" sub storage + NamedStorages::const_iterator pos = m_aExposedStorages.find( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "database" ) ) ); + if ( ( pos != m_aExposedStorages.end() ) + && ( pos->second == xStorage ) + ) + { + // if so, also commit the root storage + m_pModelImplementation->commitRootStorage(); + } + } +} + +//-------------------------------------------------------------------------- +void SAL_CALL DocumentStorageAccess::preRevert( const css::lang::EventObject& /*aEvent*/ ) throw (Exception, RuntimeException) +{ + // not interested in +} + +//-------------------------------------------------------------------------- +void SAL_CALL DocumentStorageAccess::reverted( const css::lang::EventObject& /*aEvent*/ ) throw (RuntimeException) +{ + // not interested in +} + +//-------------------------------------------------------------------------- +void SAL_CALL DocumentStorageAccess::disposing( const css::lang::EventObject& Source ) throw ( RuntimeException ) +{ + OSL_ENSURE( Reference< XStorage >( Source.Source, UNO_QUERY ).is(), "DocumentStorageAccess::disposing: No storage? What's this?" ); + + if ( m_bDisposingSubStorages ) + return; + + for ( NamedStorages::iterator find = m_aExposedStorages.begin(); + find != m_aExposedStorages.end(); + ++find + ) + if ( find->second == Source.Source ) + { + m_aExposedStorages.erase( find ); + break; + } +} + +//============================================================ +//= ODatabaseModelImpl +//============================================================ +DBG_NAME(ODatabaseModelImpl) +//-------------------------------------------------------------------------- +ODatabaseModelImpl::ODatabaseModelImpl( const Reference< XMultiServiceFactory >& _rxFactory, ODatabaseContext& _rDBContext ) + :m_xModel() + ,m_xDataSource() + ,m_pStorageAccess( NULL ) + ,m_aMutex() + ,m_aMutexFacade( m_aMutex ) + ,m_aContainer(4) + ,m_aMacroMode( *this ) + ,m_nImposedMacroExecMode( MacroExecMode::NEVER_EXECUTE ) + ,m_pDBContext( &_rDBContext ) + ,m_refCount(0) + ,m_aEmbeddedMacros() + ,m_bModificationLock( false ) + ,m_bDocumentInitialized( false ) + ,m_aContext( _rxFactory ) + ,m_nLoginTimeout(0) + ,m_bReadOnly(sal_False) + ,m_bPasswordRequired(sal_False) + ,m_bSuppressVersionColumns(sal_True) + ,m_bModified(sal_False) + ,m_bDocumentReadOnly(sal_False) + ,m_pSharedConnectionManager(NULL) + ,m_nControllerLockCount(0) +{ + // some kind of default + DBG_CTOR(ODatabaseModelImpl,NULL); + m_sConnectURL = ::rtl::OUString::createFromAscii("jdbc:"); + m_aTableFilter.realloc(1); + m_aTableFilter[0] = ::rtl::OUString::createFromAscii("%"); + impl_construct_nothrow(); +} + +//-------------------------------------------------------------------------- +ODatabaseModelImpl::ODatabaseModelImpl( + const ::rtl::OUString& _rRegistrationName, + const Reference< XMultiServiceFactory >& _rxFactory, + ODatabaseContext& _rDBContext + ) + :m_xModel() + ,m_xDataSource() + ,m_pStorageAccess( NULL ) + ,m_aMutex() + ,m_aMutexFacade( m_aMutex ) + ,m_aContainer(4) + ,m_aMacroMode( *this ) + ,m_nImposedMacroExecMode( MacroExecMode::NEVER_EXECUTE ) + ,m_pDBContext( &_rDBContext ) + ,m_refCount(0) + ,m_aEmbeddedMacros() + ,m_bModificationLock( false ) + ,m_bDocumentInitialized( false ) + ,m_aContext( _rxFactory ) + ,m_sName(_rRegistrationName) + ,m_nLoginTimeout(0) + ,m_bReadOnly(sal_False) + ,m_bPasswordRequired(sal_False) + ,m_bSuppressVersionColumns(sal_True) + ,m_bModified(sal_False) + ,m_bDocumentReadOnly(sal_False) + ,m_pSharedConnectionManager(NULL) + ,m_nControllerLockCount(0) +{ + DBG_CTOR(ODatabaseModelImpl,NULL); + impl_construct_nothrow(); +} + +//-------------------------------------------------------------------------- +ODatabaseModelImpl::~ODatabaseModelImpl() +{ + DBG_DTOR(ODatabaseModelImpl,NULL); +} + +// ----------------------------------------------------------------------------- +void ODatabaseModelImpl::impl_construct_nothrow() +{ + // create the property bag to hold the settings (also known as "Info" property) + try + { + // the set of property value types in the bag is limited: + Sequence< Type > aAllowedTypes(6); + Type* pAllowedType = aAllowedTypes.getArray(); + *pAllowedType++ = ::getCppuType( static_cast< sal_Bool* >( NULL ) ); + *pAllowedType++ = ::getCppuType( static_cast< double* >( NULL ) ); + *pAllowedType++ = ::getCppuType( static_cast< ::rtl::OUString* >( NULL ) ); + *pAllowedType++ = ::getCppuType( static_cast< sal_Int32* >( NULL ) ); + *pAllowedType++ = ::getCppuType( static_cast< sal_Int16* >( NULL ) ); + *pAllowedType++ = ::getCppuType( static_cast< Sequence< Any >* >( NULL ) ); + + Sequence< Any > aInitArgs( 2 ); + aInitArgs[0] <<= NamedValue( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "AutomaticAddition" ) ), + makeAny( (sal_Bool)sal_True ) + ); + aInitArgs[1] <<= NamedValue( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "AllowedTypes" ) ), + makeAny( aAllowedTypes ) + ); + + m_xSettings.set( m_aContext.createComponentWithArguments( "com.sun.star.beans.PropertyBag", aInitArgs ), UNO_QUERY_THROW ); + + // insert the default settings + Reference< XPropertyContainer > xContainer( m_xSettings, UNO_QUERY_THROW ); + Reference< XSet > xSettingsSet( m_xSettings, UNO_QUERY_THROW ); + const AsciiPropertyValue* pSettings = getDefaultDataSourceSettings(); + for ( ; pSettings->AsciiName; ++pSettings ) + { + if ( !pSettings->DefaultValue.hasValue() ) + { + Property aProperty( + ::rtl::OUString::createFromAscii( pSettings->AsciiName ), + -1, + pSettings->ValueType, + PropertyAttribute::BOUND | PropertyAttribute::MAYBEDEFAULT | PropertyAttribute::MAYBEVOID + ); + xSettingsSet->insert( makeAny( aProperty ) ); + } + else + { + xContainer->addProperty( + ::rtl::OUString::createFromAscii( pSettings->AsciiName ), + PropertyAttribute::BOUND | PropertyAttribute::MAYBEDEFAULT, + pSettings->DefaultValue + ); + } + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + m_pDBContext->appendAtTerminateListener(*this); +} + +// ----------------------------------------------------------------------------- +namespace +{ + // ......................................................................... + ::rtl::OUString lcl_getContainerStorageName_throw( ODatabaseModelImpl::ObjectType _eType ) + { + const sal_Char* pAsciiName( NULL ); + switch ( _eType ) + { + case ODatabaseModelImpl::E_FORM: pAsciiName = "forms"; break; + case ODatabaseModelImpl::E_REPORT: pAsciiName = "reports"; break; + case ODatabaseModelImpl::E_QUERY: pAsciiName = "queries"; break; + case ODatabaseModelImpl::E_TABLE: pAsciiName = "tables"; break; + default: + throw RuntimeException(); + } + return ::rtl::OUString::createFromAscii( pAsciiName ); + } + + // ......................................................................... + bool lcl_hasObjectWithMacros_throw( const ODefinitionContainer_Impl& _rObjectDefinitions, const Reference< XStorage >& _rxContainerStorage ) + { + bool bSomeDocHasMacros = false; + + for ( ODefinitionContainer_Impl::const_iterator object = _rObjectDefinitions.begin(); + ( object != _rObjectDefinitions.end() ) && !bSomeDocHasMacros; + ++object + ) + { +#if OSL_DEBUG_LEVEL > 0 + const ::rtl::OUString& rName( object->first ); (void)rName; +#endif + + const TContentPtr& rDefinition( object->second ); + const ::rtl::OUString& rPersistentName( rDefinition->m_aProps.sPersistentName ); + + if ( !rPersistentName.getLength() ) + { // it's a logical sub folder used to organize the real objects + const ODefinitionContainer_Impl& rSubFoldersObjectDefinitions( dynamic_cast< const ODefinitionContainer_Impl& >( *rDefinition.get() ) ); + bSomeDocHasMacros = lcl_hasObjectWithMacros_throw( rSubFoldersObjectDefinitions, _rxContainerStorage ); + continue; + } + + bSomeDocHasMacros = ODatabaseModelImpl::objectHasMacros( _rxContainerStorage, rPersistentName ); + } + return bSomeDocHasMacros; + } + + // ......................................................................... + bool lcl_hasObjectsWithMacros_nothrow( ODatabaseModelImpl& _rModel, const ODatabaseModelImpl::ObjectType _eType ) + { + bool bSomeDocHasMacros = false; + + const OContentHelper_Impl& rContainerData( *_rModel.getObjectContainer( _eType ).get() ); + const ODefinitionContainer_Impl& rObjectDefinitions = dynamic_cast< const ODefinitionContainer_Impl& >( rContainerData ); + + try + { + Reference< XStorage > xContainerStorage( _rModel.getStorage( _eType, ElementModes::READWRITE ) ); + // note the READWRITE here: If the storage already existed before, then the OpenMode will + // be ignored, anyway. + // If the storage did not yet exist, then it will be created. If the database document + // is read-only, the OpenMode will be automatically downgraded to READ. Otherwise, + // the storage will in fact be created as READWRITE. While this is not strictly necessary + // for this particular use case here, it is required since the storage is *cached*, and + // later use cases will need the READWRITE mode. + + if ( xContainerStorage.is() ) + bSomeDocHasMacros = lcl_hasObjectWithMacros_throw( rObjectDefinitions, xContainerStorage ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + // be on the safe side: If we can't reliably determine whether there are macros, + // assume there actually are. Better this way, than the other way round. + bSomeDocHasMacros = true; + } + + return bSomeDocHasMacros; + } +} + +// ----------------------------------------------------------------------------- +bool ODatabaseModelImpl::objectHasMacros( const Reference< XStorage >& _rxContainerStorage, const ::rtl::OUString& _rPersistentName ) +{ + OSL_PRECOND( _rxContainerStorage.is(), "ODatabaseModelImpl::objectHasMacros: this will crash!" ); + + bool bHasMacros = true; + try + { + if ( !_rxContainerStorage->hasByName( _rPersistentName ) ) + return false; + + Reference< XStorage > xObjectStor( _rxContainerStorage->openStorageElement( + _rPersistentName, ElementModes::READ ) ); + + bHasMacros = ::sfx2::DocumentMacroMode::storageHasMacros( xObjectStor ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + return bHasMacros; +} + +// ----------------------------------------------------------------------------- +void ODatabaseModelImpl::reset() +{ + m_bReadOnly = sal_False; + ::std::vector< TContentPtr > aEmptyContainers( 4 ); + m_aContainer.swap( aEmptyContainers ); + + if ( m_pStorageAccess ) + { + m_pStorageAccess->dispose(); + m_pStorageAccess->release(); + m_pStorageAccess = NULL; + } +} +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseModelImpl::disposing( const ::com::sun::star::lang::EventObject& Source ) throw(RuntimeException) +{ + Reference<XConnection> xCon(Source.Source,UNO_QUERY); + if ( xCon.is() ) + { + bool bStore = false; + OWeakConnectionArray::iterator aEnd = m_aConnections.end(); + for (OWeakConnectionArray::iterator i = m_aConnections.begin(); aEnd != i; ++i) + { + if ( xCon == i->get() ) + { + *i = OWeakConnection(); + bStore = true; + break; + } + } + + if ( bStore ) + commitRootStorage(); + } + else + { + OSL_ENSURE( false, "ODatabaseModelImpl::disposing: where does this come from?" ); + } +} +//------------------------------------------------------------------------------ +void ODatabaseModelImpl::clearConnections() +{ + OWeakConnectionArray aConnections; + aConnections.swap( m_aConnections ); + + Reference< XConnection > xConn; + OWeakConnectionArray::iterator aEnd = aConnections.end(); + for ( OWeakConnectionArray::iterator i = aConnections.begin(); aEnd != i; ++i ) + { + xConn = *i; + if ( xConn.is() ) + { + try + { + xConn->close(); + } + catch(const Exception&) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + } + + m_pSharedConnectionManager = NULL; + m_xSharedConnectionManager = NULL; +} +//------------------------------------------------------------------------------ +void ODatabaseModelImpl::dispose() +{ + // dispose the data source and the model + try + { + Reference< XDataSource > xDS( m_xDataSource ); + ::comphelper::disposeComponent( xDS ); + + Reference< XModel > xModel( m_xModel ); + ::comphelper::disposeComponent( xModel ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + m_xDataSource = WeakReference<XDataSource>(); + m_xModel = WeakReference< XModel >(); + + ::std::vector<TContentPtr>::iterator aIter = m_aContainer.begin(); + ::std::vector<TContentPtr>::iterator aEnd = m_aContainer.end(); + for (;aIter != aEnd ; ++aIter) + { + if ( aIter->get() ) + (*aIter)->m_pDataSource = NULL; + } + m_aContainer.clear(); + + clearConnections(); + + m_xNumberFormatsSupplier = NULL; + + try + { + sal_Bool bCouldStore = commitEmbeddedStorage( true ); + // "true" means that committing the embedded storage should not trigger committing the root + // storage. This is because we are going to commit the root storage ourself, anyway + disposeStorages(); + if ( bCouldStore ) + commitRootStorage(); + + impl_switchToStorage_throw( NULL ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + if ( m_pStorageAccess ) + { + m_pStorageAccess->dispose(); + m_pStorageAccess->release(); + m_pStorageAccess = NULL; + } +} +// ----------------------------------------------------------------------------- +const Reference< XNumberFormatsSupplier > & ODatabaseModelImpl::getNumberFormatsSupplier() +{ + if (!m_xNumberFormatsSupplier.is()) + { + // the arguments : the locale of the current user + UserInformation aUserInfo; + Sequence< Any > aArguments(1); + aArguments.getArray()[0] <<= aUserInfo.getUserLanguage(); + + m_xNumberFormatsSupplier.set( + m_aContext.createComponentWithArguments( "com.sun.star.util.NumberFormatsSupplier", aArguments ), UNO_QUERY_THROW ); + DBG_ASSERT(m_xNumberFormatsSupplier.is(), "ODatabaseModelImpl::getNumberFormatsSupplier : could not instantiate the formats supplier !"); + } + return m_xNumberFormatsSupplier; +} + +// ----------------------------------------------------------------------------- +void ODatabaseModelImpl::setDocFileLocation( const ::rtl::OUString& i_rLoadedFrom ) +{ + ENSURE_OR_THROW( i_rLoadedFrom.getLength(), "invalid URL" ); + m_sDocFileLocation = i_rLoadedFrom; +} + +// ----------------------------------------------------------------------------- +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" ) ) + { + ::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_aMediaDescriptor = stripLoadArguments( aMediaDescriptor ); + + impl_switchToLogicalURL( i_rDocumentURL ); +} + +// ----------------------------------------------------------------------------- +::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)!" ); + + ::comphelper::NamedValueCollection aMutableArgs( _rArguments ); + aMutableArgs.remove( "Model" ); + aMutableArgs.remove( "ViewName" ); + return aMutableArgs; +} + +// ----------------------------------------------------------------------------- +void ODatabaseModelImpl::disposeStorages() SAL_THROW(()) +{ + getDocumentStorageAccess()->disposeStorages(); +} + +// ----------------------------------------------------------------------------- +Reference< XSingleServiceFactory > ODatabaseModelImpl::createStorageFactory() const +{ + return Reference< XSingleServiceFactory >( m_aContext.createComponent( "com.sun.star.embed.StorageFactory" ), UNO_QUERY_THROW ); +} +// ----------------------------------------------------------------------------- +void ODatabaseModelImpl::commitRootStorage() +{ + Reference< XStorage > xStorage( getOrCreateRootStorage() ); +#if OSL_DEBUG_LEVEL > 0 + bool bSuccess = +#endif + commitStorageIfWriteable_ignoreErrors( xStorage ); + OSL_ENSURE( bSuccess || !xStorage.is(), + "ODatabaseModelImpl::commitRootStorage: could commit the storage!" ); +} +// ----------------------------------------------------------------------------- +Reference< XStorage > ODatabaseModelImpl::getOrCreateRootStorage() +{ + if ( !m_xDocumentStorage.is() ) + { + Reference< XSingleServiceFactory> xStorageFactory = createStorageFactory(); + if ( xStorageFactory.is() ) + { + Any aSource; + aSource = m_aMediaDescriptor.get( "Stream" ); + if ( !aSource.hasValue() ) + aSource = m_aMediaDescriptor.get( "InputStream" ); + if ( !aSource.hasValue() && m_sDocFileLocation.getLength() ) + aSource <<= m_sDocFileLocation; + // TODO: shouldn't we also check URL? + + OSL_ENSURE( aSource.hasValue(), "ODatabaseModelImpl::getOrCreateRootStorage: no source to create the storage from!" ); + + if ( aSource.hasValue() ) + { + Sequence< Any > aStorageCreationArgs(2); + aStorageCreationArgs[0] = aSource; + aStorageCreationArgs[1] <<= ElementModes::READWRITE; + + Reference< XStorage > xDocumentStorage; + try + { + xDocumentStorage.set( xStorageFactory->createInstanceWithArguments( aStorageCreationArgs ), UNO_QUERY_THROW ); + } + catch( const Exception& ) + { + m_bDocumentReadOnly = sal_True; + aStorageCreationArgs[1] <<= ElementModes::READ; + try + { + xDocumentStorage.set( xStorageFactory->createInstanceWithArguments( aStorageCreationArgs ), UNO_QUERY_THROW ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + impl_switchToStorage_throw( xDocumentStorage ); + } + } + } + return m_xDocumentStorage.getTyped(); +} +// ----------------------------------------------------------------------------- +DocumentStorageAccess* ODatabaseModelImpl::getDocumentStorageAccess() +{ + if ( !m_pStorageAccess ) + { + m_pStorageAccess = new DocumentStorageAccess( *this ); + m_pStorageAccess->acquire(); + } + return m_pStorageAccess; +} + +// ----------------------------------------------------------------------------- +void ODatabaseModelImpl::modelIsDisposing( const bool _wasInitialized, ResetModelAccess ) +{ + m_xModel = Reference< XModel >(); + + // Basic libraries and Dialog libraries are a model facet, though held at this impl class. + // They automatically dispose themself when the model they belong to is being disposed. + // So, to not be tempted to do anything with them, again, we reset them. + m_xBasicLibraries.clear(); + m_xDialogLibraries.clear(); + + m_bDocumentInitialized = _wasInitialized; +} + +// ----------------------------------------------------------------------------- +Reference< XDocumentSubStorageSupplier > ODatabaseModelImpl::getDocumentSubStorageSupplier() +{ + return getDocumentStorageAccess(); +} + +// ----------------------------------------------------------------------------- +bool ODatabaseModelImpl::commitEmbeddedStorage( bool _bPreventRootCommits ) +{ + return getDocumentStorageAccess()->commitEmbeddedStorage( _bPreventRootCommits ); +} + +// ----------------------------------------------------------------------------- +bool ODatabaseModelImpl::commitStorageIfWriteable_ignoreErrors( const Reference< XStorage >& _rxStorage ) SAL_THROW(()) +{ + bool bSuccess = false; + try + { + bSuccess = tools::stor::commitStorageIfWriteable( _rxStorage ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + return bSuccess; +} +// ----------------------------------------------------------------------------- +void ODatabaseModelImpl::setModified( sal_Bool _bModified ) +{ + if ( isModifyLocked() ) + return; + + try + { + Reference< XModifiable > xModi( m_xModel.get(), UNO_QUERY ); + if ( xModi.is() ) + xModi->setModified( _bModified ); + else + m_bModified = _bModified; + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } +} + +// ----------------------------------------------------------------------------- +Reference<XDataSource> ODatabaseModelImpl::getOrCreateDataSource() +{ + Reference<XDataSource> xDs = m_xDataSource; + if ( !xDs.is() ) + { + xDs = new ODatabaseSource(this); + m_xDataSource = xDs; + } + return xDs; +} +// ----------------------------------------------------------------------------- +Reference< XModel> ODatabaseModelImpl::getModel_noCreate() const +{ + return m_xModel; +} +// ----------------------------------------------------------------------------- +Reference< XModel > ODatabaseModelImpl::createNewModel_deliverOwnership( bool _bInitialize ) +{ + Reference< XModel > xModel( m_xModel ); + OSL_PRECOND( !xModel.is(), "ODatabaseModelImpl::createNewModel_deliverOwnership: not to be called if there already is a model!" ); + if ( !xModel.is() ) + { + bool bHadModelBefore = m_bDocumentInitialized; + + xModel = ODatabaseDocument::createDatabaseDocument( this, ODatabaseDocument::FactoryAccess() ); + m_xModel = xModel; + + try + { + Reference< XSet > xModelCollection; + if ( m_aContext.createComponent( "com.sun.star.frame.GlobalEventBroadcaster", xModelCollection ) ) + xModelCollection->insert( makeAny( xModel ) ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + if ( bHadModelBefore ) + { + // do an attachResources + // In case the document is loaded regularly, this is not necessary, as our loader will do it. + // However, in case that the document is implicitly created by asking the data source for the document, + // 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_aMediaDescriptor.getPropertyValues() ); + } + + if ( _bInitialize ) + { + try + { + Reference< XLoadable > xLoad( xModel, UNO_QUERY_THROW ); + xLoad->initNew(); + } + catch( RuntimeException& ) { throw; } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + } + return xModel; +} +// ----------------------------------------------------------------------------- +oslInterlockedCount SAL_CALL ODatabaseModelImpl::acquire() +{ + return osl_incrementInterlockedCount(&m_refCount); +} +// ----------------------------------------------------------------------------- +oslInterlockedCount SAL_CALL ODatabaseModelImpl::release() +{ + if ( osl_decrementInterlockedCount(&m_refCount) == 0 ) + { + acquire(); // prevent multiple releases + m_pDBContext->removeFromTerminateListener(*this); + dispose(); + m_pDBContext->storeTransientProperties(*this); + revokeDataSource(); + delete this; + return 0; + } + return m_refCount; +} +// ----------------------------------------------------------------------------- +void ODatabaseModelImpl::commitStorages() SAL_THROW(( IOException, RuntimeException )) +{ + getDocumentStorageAccess()->commitStorages(); +} + +// ----------------------------------------------------------------------------- +Reference< XStorage > ODatabaseModelImpl::getStorage( const ObjectType _eType, const sal_Int32 _nDesiredMode ) +{ + return getDocumentStorageAccess()->getDocumentSubStorage( getObjectContainerStorageName( _eType ), _nDesiredMode ); +} + +// ----------------------------------------------------------------------------- +const AsciiPropertyValue* ODatabaseModelImpl::getDefaultDataSourceSettings() +{ + static const AsciiPropertyValue aKnownSettings[] = + { + // known JDBC settings + AsciiPropertyValue( "JavaDriverClass", makeAny( ::rtl::OUString() ) ), + AsciiPropertyValue( "JavaDriverClassPath", makeAny( ::rtl::OUString() ) ), + AsciiPropertyValue( "IgnoreCurrency", makeAny( (sal_Bool)sal_False ) ), + // known settings for file-based drivers + AsciiPropertyValue( "Extension", makeAny( ::rtl::OUString() ) ), + AsciiPropertyValue( "CharSet", makeAny( ::rtl::OUString() ) ), + AsciiPropertyValue( "HeaderLine", makeAny( (sal_Bool)sal_True ) ), + AsciiPropertyValue( "FieldDelimiter", makeAny( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "," ) ) ) ), + AsciiPropertyValue( "StringDelimiter", makeAny( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "\"" ) ) ) ), + AsciiPropertyValue( "DecimalDelimiter", makeAny( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "." ) ) ) ), + AsciiPropertyValue( "ThousandDelimiter", makeAny( ::rtl::OUString() ) ), + AsciiPropertyValue( "ShowDeleted", makeAny( (sal_Bool)sal_False ) ), + // known ODBC settings + AsciiPropertyValue( "SystemDriverSettings", makeAny( ::rtl::OUString() ) ), + AsciiPropertyValue( "UseCatalog", makeAny( (sal_Bool)sal_False ) ), + AsciiPropertyValue( "TypeInfoSettings", makeAny( Sequence< Any >()) ), + // settings related to auto increment handling + AsciiPropertyValue( "AutoIncrementCreation", makeAny( ::rtl::OUString() ) ), + AsciiPropertyValue( "AutoRetrievingStatement", makeAny( ::rtl::OUString() ) ), + AsciiPropertyValue( "IsAutoRetrievingEnabled", makeAny( (sal_Bool)sal_False ) ), + // known Adabas D driver setting + AsciiPropertyValue( "ShutdownDatabase", makeAny( (sal_Bool)sal_False ) ), + AsciiPropertyValue( "DataCacheSizeIncrement", makeAny( (sal_Int32)20 ) ), + AsciiPropertyValue( "DataCacheSize", makeAny( (sal_Int32)20 ) ), + AsciiPropertyValue( "ControlUser", makeAny( ::rtl::OUString() ) ), + AsciiPropertyValue( "ControlPassword", makeAny( ::rtl::OUString() ) ), + // known LDAP driver settings + AsciiPropertyValue( "HostName", makeAny( ::rtl::OUString() ) ), + AsciiPropertyValue( "PortNumber", makeAny( (sal_Int32)389 ) ), + AsciiPropertyValue( "BaseDN", makeAny( ::rtl::OUString() ) ), + AsciiPropertyValue( "MaxRowCount", makeAny( (sal_Int32)100 ) ), + // known MySQLNative driver settings + AsciiPropertyValue( "LocalSocket", makeAny( ::rtl::OUString() ) ), + AsciiPropertyValue( "NamedPipe", makeAny( ::rtl::OUString() ) ), + // misc known driver settings + AsciiPropertyValue( "ParameterNameSubstitution", makeAny( (sal_Bool)sal_False ) ), + AsciiPropertyValue( "AddIndexAppendix", makeAny( (sal_Bool)sal_True ) ), + AsciiPropertyValue( "IgnoreDriverPrivileges", makeAny( (sal_Bool)sal_True ) ), + AsciiPropertyValue( "ImplicitCatalogRestriction", ::cppu::UnoType< ::rtl::OUString >::get() ), + AsciiPropertyValue( "ImplicitSchemaRestriction", ::cppu::UnoType< ::rtl::OUString >::get() ), + AsciiPropertyValue( "PrimaryKeySupport", ::cppu::UnoType< sal_Bool >::get() ), + AsciiPropertyValue( "ShowColumnDescription", makeAny( (sal_Bool)sal_False ) ), + // known SDB level settings + AsciiPropertyValue( "NoNameLengthLimit", makeAny( (sal_Bool)sal_False ) ), + AsciiPropertyValue( "AppendTableAliasName", makeAny( (sal_Bool)sal_False ) ), + AsciiPropertyValue( "GenerateASBeforeCorrelationName", makeAny( (sal_Bool)sal_True ) ), + AsciiPropertyValue( "ColumnAliasInOrderBy", makeAny( (sal_Bool)sal_True ) ), + AsciiPropertyValue( "EnableSQL92Check", makeAny( (sal_Bool)sal_False ) ), + AsciiPropertyValue( "BooleanComparisonMode", makeAny( BooleanComparisonMode::EQUAL_INTEGER ) ), + AsciiPropertyValue( "TableTypeFilterMode", makeAny( (sal_Int32)3 ) ), + AsciiPropertyValue( "RespectDriverResultSetType", makeAny( (sal_Bool)sal_False ) ), + AsciiPropertyValue( "UseSchemaInSelect", makeAny( (sal_Bool)sal_True ) ), + AsciiPropertyValue( "UseCatalogInSelect", makeAny( (sal_Bool)sal_True ) ), + AsciiPropertyValue( "EnableOuterJoinEscape", makeAny( (sal_Bool)sal_True ) ), + AsciiPropertyValue( "PreferDosLikeLineEnds", makeAny( (sal_Bool)sal_False ) ), + 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; +} + +// ----------------------------------------------------------------------------- +TContentPtr& ODatabaseModelImpl::getObjectContainer( ObjectType _eType ) +{ + OSL_PRECOND( _eType >= E_FORM && _eType <= E_TABLE, "ODatabaseModelImpl::getObjectContainer: illegal index!" ); + TContentPtr& rContentPtr = m_aContainer[ _eType ]; + + if ( !rContentPtr.get() ) + { + rContentPtr = TContentPtr( new ODefinitionContainer_Impl ); + rContentPtr->m_pDataSource = this; + rContentPtr->m_aProps.aTitle = lcl_getContainerStorageName_throw( _eType ); + } + return rContentPtr; +} + +// ----------------------------------------------------------------------------- +void ODatabaseModelImpl::revokeDataSource() const +{ + if ( m_pDBContext && m_sDocumentURL.getLength() ) + m_pDBContext->revokeDatabaseDocument( *this ); +} + +// ----------------------------------------------------------------------------- +bool ODatabaseModelImpl::adjustMacroMode_AutoReject() +{ + return m_aMacroMode.adjustMacroMode( NULL ); +} + +// ----------------------------------------------------------------------------- +bool ODatabaseModelImpl::checkMacrosOnLoading() +{ + Reference< XInteractionHandler > xInteraction; + xInteraction = m_aMediaDescriptor.getOrDefault( "InteractionHandler", xInteraction ); + return m_aMacroMode.checkMacrosOnLoading( xInteraction ); +} + +// ----------------------------------------------------------------------------- +void ODatabaseModelImpl::resetMacroExecutionMode() +{ + m_aMacroMode = ::sfx2::DocumentMacroMode( *this ); +} + +// ----------------------------------------------------------------------------- +Reference< XStorageBasedLibraryContainer > ODatabaseModelImpl::getLibraryContainer( bool _bScript ) +{ + Reference< XStorageBasedLibraryContainer >& rxContainer( _bScript ? m_xBasicLibraries : m_xDialogLibraries ); + if ( rxContainer.is() ) + return rxContainer; + + Reference< XStorageBasedDocument > xDocument( getModel_noCreate(), UNO_QUERY_THROW ); + // this is only to be called if there already exists a document model - in fact, it is + // to be called by the document model only + + try + { + Reference< XStorageBasedLibraryContainer > (*Factory)( const Reference< XComponentContext >&, const Reference< XStorageBasedDocument >&) + = _bScript ? &DocumentScriptLibraryContainer::create : &DocumentDialogLibraryContainer::create; + + rxContainer.set( + (*Factory)( m_aContext.getUNOContext(), xDocument ), + UNO_QUERY_THROW + ); + } + catch( const RuntimeException& ) + { + throw; + } + catch( const Exception& ) + { + throw WrappedTargetRuntimeException( + ::rtl::OUString(), + xDocument, + ::cppu::getCaughtException() + ); + } + return rxContainer; +} + +// ----------------------------------------------------------------------------- +void ODatabaseModelImpl::storeLibraryContainersTo( const Reference< XStorage >& _rxToRootStorage ) +{ + if ( m_xBasicLibraries.is() ) + m_xBasicLibraries->storeLibrariesToStorage( _rxToRootStorage ); + + if ( m_xDialogLibraries.is() ) + m_xDialogLibraries->storeLibrariesToStorage( _rxToRootStorage ); +} + +// ----------------------------------------------------------------------------- +Reference< XStorage > ODatabaseModelImpl::switchToStorage( const Reference< XStorage >& _rxNewRootStorage ) +{ + if ( !_rxNewRootStorage.is() ) + throw IllegalArgumentException(); + + return impl_switchToStorage_throw( _rxNewRootStorage ); +} + +// ----------------------------------------------------------------------------- +namespace +{ + void lcl_modifyListening( ::sfx2::IModifiableDocument& _rDocument, + const Reference< XStorage >& _rxStorage, ::rtl::Reference< ::sfx2::DocumentStorageModifyListener >& _inout_rListener, + ::vos::IMutex& _rMutex, bool _bListen ) + { + Reference< XModifiable > xModify( _rxStorage, UNO_QUERY ); + OSL_ENSURE( xModify.is() || !_rxStorage.is(), "lcl_modifyListening: storage can't notify us!" ); + + if ( xModify.is() && !_bListen && _inout_rListener.is() ) + { + xModify->removeModifyListener( _inout_rListener.get() ); + } + + if ( _inout_rListener.is() ) + { + _inout_rListener->dispose(); + _inout_rListener = NULL; + } + + if ( xModify.is() && _bListen ) + { + _inout_rListener = new ::sfx2::DocumentStorageModifyListener( _rDocument, _rMutex ); + xModify->addModifyListener( _inout_rListener.get() ); + } + } +} + +// ----------------------------------------------------------------------------- +namespace +{ + static void lcl_rebaseScriptStorage_throw( const Reference< XStorageBasedLibraryContainer >& _rxContainer, + const Reference< XStorage >& _rxNewRootStorage ) + { + if ( _rxContainer.is() ) + { + if ( _rxNewRootStorage.is() ) + _rxContainer->setRootStorage( _rxNewRootStorage ); +// else + // TODO: what to do here? dispose the container? + } + } +} + +// ----------------------------------------------------------------------------- +Reference< XStorage > ODatabaseModelImpl::impl_switchToStorage_throw( const Reference< XStorage >& _rxNewRootStorage ) +{ + // stop listening for modifications at the old storage + lcl_modifyListening( *this, m_xDocumentStorage.getTyped(), m_pStorageModifyListener, m_aMutexFacade, false ); + + // set new storage + m_xDocumentStorage.reset( _rxNewRootStorage, SharedStorage::TakeOwnership ); + + // start listening for modifications + lcl_modifyListening( *this, m_xDocumentStorage.getTyped(), m_pStorageModifyListener, m_aMutexFacade, true ); + + // forward new storage to Basic and Dialog library containers + lcl_rebaseScriptStorage_throw( m_xBasicLibraries, m_xDocumentStorage.getTyped() ); + lcl_rebaseScriptStorage_throw( m_xDialogLibraries, 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::impl_switchToLogicalURL( const ::rtl::OUString& i_rDocumentURL ) +{ + if ( i_rDocumentURL == m_sDocumentURL ) + return; + + const ::rtl::OUString sOldURL( m_sDocumentURL ); + // 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) + ) + { + INetURLObject aURL( i_rDocumentURL ); + if ( aURL.GetProtocol() != INET_PROT_NOT_VALID ) + { + m_sName = i_rDocumentURL; + // TODO: our data source must broadcast the change of the Name property + } + } + + // remember URL + m_sDocumentURL = i_rDocumentURL; + + // 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 ); + else + m_pDBContext->registerDatabaseDocument( *this ); + } +} + +// ----------------------------------------------------------------------------- +::rtl::OUString ODatabaseModelImpl::getObjectContainerStorageName( const ObjectType _eType ) +{ + return lcl_getContainerStorageName_throw( _eType ); +} + +// ----------------------------------------------------------------------------- +sal_Int16 ODatabaseModelImpl::getCurrentMacroExecMode() const +{ + sal_Int16 nCurrentMode = MacroExecMode::NEVER_EXECUTE; + try + { + nCurrentMode = m_aMediaDescriptor.getOrDefault( "MacroExecutionMode", nCurrentMode ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + return nCurrentMode; +} + +// ----------------------------------------------------------------------------- +sal_Bool ODatabaseModelImpl::setCurrentMacroExecMode( sal_uInt16 nMacroMode ) +{ + m_aMediaDescriptor.put( "MacroExecutionMode", nMacroMode ); + return sal_True; +} + +// ----------------------------------------------------------------------------- +::rtl::OUString ODatabaseModelImpl::getDocumentLocation() const +{ + 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. +} + +// ----------------------------------------------------------------------------- +Reference< XStorage > ODatabaseModelImpl::getZipStorageToSign() +{ + // we do not support signing the scripting storages, so we're allowed to + // return <NULL/> here. + return Reference< XStorage >(); +} + +// ----------------------------------------------------------------------------- +ODatabaseModelImpl::EmbeddedMacros ODatabaseModelImpl::determineEmbeddedMacros() +{ + if ( !m_aEmbeddedMacros ) + { + if ( ::sfx2::DocumentMacroMode::storageHasMacros( const_cast< ODatabaseModelImpl* >( this )->getOrCreateRootStorage() ) ) + { + m_aEmbeddedMacros.reset( eDocumentWideMacros ); + } + else if ( lcl_hasObjectsWithMacros_nothrow( const_cast< ODatabaseModelImpl& >( *this ), E_FORM ) + || lcl_hasObjectsWithMacros_nothrow( const_cast< ODatabaseModelImpl& >( *this ), E_REPORT ) + ) + { + m_aEmbeddedMacros.reset( eSubDocumentMacros ); + } + else + { + m_aEmbeddedMacros.reset( eNoMacros ); + } + } + return *m_aEmbeddedMacros; +} + +// ----------------------------------------------------------------------------- +sal_Bool ODatabaseModelImpl::documentStorageHasMacros() const +{ + const_cast< ODatabaseModelImpl* >( this )->determineEmbeddedMacros(); + return ( *m_aEmbeddedMacros != eNoMacros ); +} + +// ----------------------------------------------------------------------------- +Reference< XEmbeddedScripts > ODatabaseModelImpl::getEmbeddedDocumentScripts() const +{ + return Reference< XEmbeddedScripts >( getModel_noCreate(), UNO_QUERY ); +} + +// ----------------------------------------------------------------------------- +sal_Int16 ODatabaseModelImpl::getScriptingSignatureState() +{ + // no support for signatures at the moment + return SIGNATURESTATE_NOSIGNATURES; +} + +// ----------------------------------------------------------------------------- +sal_Bool ODatabaseModelImpl::hasTrustedScriptingSignature( sal_Bool /*bAllowUIToAddAuthor*/ ) +{ + // no support for signatures at the moment + return sal_False; +} + +// ----------------------------------------------------------------------------- +void ODatabaseModelImpl::showBrokenSignatureWarning( const Reference< XInteractionHandler >& /*_rxInteraction*/ ) const +{ + OSL_ENSURE( false, "ODatabaseModelImpl::showBrokenSignatureWarning: signatures can't be broken - we do not support them!" ); +} + +// ----------------------------------------------------------------------------- +void ODatabaseModelImpl::storageIsModified() +{ + setModified( sal_True ); +} + +// ----------------------------------------------------------------------------- +ModelDependentComponent::ModelDependentComponent( const ::rtl::Reference< ODatabaseModelImpl >& _model ) + :m_pImpl( _model ) + ,m_aMutex( _model->getSharedMutex() ) +{ +} + +// ----------------------------------------------------------------------------- +ModelDependentComponent::~ModelDependentComponent() +{ +} + +//........................................................................ +} // namespace dbaccess +//........................................................................ + diff --git a/dbaccess/source/core/dataaccess/ModelImpl.hxx b/dbaccess/source/core/dataaccess/ModelImpl.hxx new file mode 100644 index 000000000000..f83b2230c2b4 --- /dev/null +++ b/dbaccess/source/core/dataaccess/ModelImpl.hxx @@ -0,0 +1,641 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 _DBA_COREDATAACCESS_MODELIMPL_HXX_ +#define _DBA_COREDATAACCESS_MODELIMPL_HXX_ + +#include "apitools.hxx" +#include "bookmarkcontainer.hxx" +#include "ContentHelper.hxx" +#include "core_resource.hxx" +#include "documentevents.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/beans/XPropertyAccess.hpp> +#include <com/sun/star/container/XContainerListener.hpp> +#include <com/sun/star/document/XDocumentSubStorageSupplier.hpp> +#include <com/sun/star/document/XEventListener.hpp> +#include <com/sun/star/document/XStorageBasedDocument.hpp> +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/embed/XStorage.hpp> +#include <com/sun/star/embed/XTransactionListener.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/frame/XStorable.hpp> +#include <com/sun/star/lang/NotInitializedException.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/sdb/XBookmarksSupplier.hpp> +#include <com/sun/star/sdb/XCompletedConnection.hpp> +#include <com/sun/star/sdb/XFormDocumentsSupplier.hpp> +#include <com/sun/star/sdb/XQueryDefinitionsSupplier.hpp> +#include <com/sun/star/sdb/XReportDocumentsSupplier.hpp> +#include <com/sun/star/sdbc/XDataSource.hpp> +#include <com/sun/star/sdbc/XIsolatedConnection.hpp> +#include <com/sun/star/sdbcx/XTablesSupplier.hpp> +#include <com/sun/star/util/XCloseable.hpp> +#include <com/sun/star/util/XFlushable.hpp> +#include <com/sun/star/util/XModifiable.hpp> +#include <com/sun/star/util/XNumberFormatsSupplier.hpp> +#include <com/sun/star/util/XNumberFormatter.hpp> +#include <com/sun/star/util/XRefreshable.hpp> +#include <com/sun/star/sdb/XDocumentDataSource.hpp> +#include <com/sun/star/frame/DoubleInitializationException.hpp> +/** === end UNO includes === **/ + +#include <comphelper/broadcasthelper.hxx> +#include <comphelper/namedvaluecollection.hxx> +#include <comphelper/proparrhlp.hxx> +#include <comphelper/sharedmutex.hxx> +#include <connectivity/CommonTools.hxx> +#include <cppuhelper/propshlp.hxx> +#include <cppuhelper/weakref.hxx> +#include <sfx2/docmacromode.hxx> +#include <sfx2/docstoragemodifylistener.hxx> +#include <tools/string.hxx> +#include <unotools/sharedunocomponent.hxx> +#include <vos/mutex.hxx> + +#include <memory> + +namespace comphelper +{ + class NamedValueCollection; +} + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + +typedef ::com::sun::star::uno::WeakReference< ::com::sun::star::sdbc::XConnection > OWeakConnection; +typedef std::vector< OWeakConnection > OWeakConnectionArray; + +struct AsciiPropertyValue +{ + // note: the canonic member order would be AsciiName / DefaultValue, but + // this crashes on unxlngi6.pro, since there's a bug which somehow results in + // getDefaultDataSourceSettings returning corrupted Any instances then. + ::com::sun::star::uno::Any DefaultValue; + const sal_Char* AsciiName; + const ::com::sun::star::uno::Type& ValueType; + + AsciiPropertyValue() + :DefaultValue( ) + ,AsciiName( NULL ) + ,ValueType( ::cppu::UnoType< ::cppu::UnoVoidType >::get() ) + { + } + + AsciiPropertyValue( const sal_Char* _pAsciiName, const ::com::sun::star::uno::Any& _rDefaultValue ) + :DefaultValue( _rDefaultValue ) + ,AsciiName( _pAsciiName ) + ,ValueType( _rDefaultValue.getValueType() ) + { + OSL_ENSURE( ValueType.getTypeClass() != ::com::sun::star::uno::TypeClass_VOID, + "AsciiPropertyValue::AsciiPropertyValue: NULL values not allowed here, use the other CTOR for this!" ); + } + AsciiPropertyValue( const sal_Char* _pAsciiName, const ::com::sun::star::uno::Type& _rValeType ) + :DefaultValue() + ,AsciiName( _pAsciiName ) + ,ValueType( _rValeType ) + { + OSL_ENSURE( ValueType.getTypeClass() != ::com::sun::star::uno::TypeClass_VOID, + "AsciiPropertyValue::AsciiPropertyValue: VOID property values not supported!" ); + } +}; + +class ODatabaseContext; +class OSharedConnectionManager; + +//============================================================ +//= VosMutexFacade +//============================================================ +/** a class which provides an IMutex interface to an OSL-based mutex +*/ +class VosMutexFacade : public ::vos::IMutex +{ +public: + /** beware of life time: the mutex you pass here must live as least as long + as the VosMutexFacade instance lives. + */ + VosMutexFacade( ::osl::Mutex& _rMutex ); + + // IMutex + virtual void SAL_CALL acquire(); + virtual sal_Bool SAL_CALL tryToAcquire(); + virtual void SAL_CALL release(); + +private: + ::osl::Mutex& m_rMutex; +}; + + +//============================================================ +//= ODatabaseModelImpl +//============================================================ +typedef ::utl::SharedUNOComponent< ::com::sun::star::embed::XStorage > SharedStorage; + +class ODatabaseContext; +class DocumentStorageAccess; +class OSharedConnectionManager; +class ODatabaseModelImpl :public ::rtl::IReference + ,public ::sfx2::IMacroDocumentAccess + ,public ::sfx2::IModifiableDocument +{ +public: + enum ObjectType + { + E_FORM = 0, + E_REPORT = 1, + E_QUERY = 2, + E_TABLE = 3 + }; + + enum EmbeddedMacros + { + // the database document (storage) itself contains macros + eDocumentWideMacros, + // there are sub document( storage)s containing macros + eSubDocumentMacros, + // there are no known macro( storage)s + eNoMacros + }; + +private: + OModuleClient m_aModuleClient; + ::com::sun::star::uno::WeakReference< ::com::sun::star::frame::XModel > m_xModel; + ::com::sun::star::uno::WeakReference< ::com::sun::star::sdbc::XDataSource > m_xDataSource; + + DocumentStorageAccess* m_pStorageAccess; + ::comphelper::SharedMutex m_aMutex; + VosMutexFacade m_aMutexFacade; + ::std::vector< TContentPtr > m_aContainer; // one for each ObjectType + ::sfx2::DocumentMacroMode m_aMacroMode; + sal_Int16 m_nImposedMacroExecMode; + + ::com::sun::star::uno::Reference< ::com::sun::star::script::XStorageBasedLibraryContainer > m_xBasicLibraries; + ::com::sun::star::uno::Reference< ::com::sun::star::script::XStorageBasedLibraryContainer > m_xDialogLibraries; + + SharedStorage m_xDocumentStorage; + ::rtl::Reference< ::sfx2::DocumentStorageModifyListener > m_pStorageModifyListener; + ODatabaseContext* m_pDBContext; + DocumentEventsData m_aDocumentEvents; + + ::comphelper::NamedValueCollection m_aMediaDescriptor; + /// the URL the document was loaded from + ::rtl::OUString m_sDocFileLocation; + + oslInterlockedCount m_refCount; + + /// do we have any object (forms/reports) which contains macros? + ::boost::optional< EmbeddedMacros > m_aEmbeddedMacros; + + /// true if setting the Modified flag of the document is currently locked + bool m_bModificationLock; + + /// true if and only if a database document existed previously (though meanwhile disposed), and was already initialized + bool m_bDocumentInitialized; + + /** the URL which the document should report as it's URL + + This might differ from ->m_sDocFileLocation in case the document was loaded + as part of a crash recovery process. In this case, ->m_sDocFileLocation points to + the temporary file where the DB had been saved to, after a crash. + ->m_sDocumentURL then is the URL of the document which actually had + been recovered. + */ + ::rtl::OUString m_sDocumentURL; + +public: + OWeakConnectionArray m_aConnections; + const ::comphelper::ComponentContext m_aContext; + +public: + ::com::sun::star::uno::WeakReference< ::com::sun::star::container::XNameAccess > m_xCommandDefinitions; + ::com::sun::star::uno::WeakReference< ::com::sun::star::container::XNameAccess > m_xTableDefinitions; + + ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier > + m_xNumberFormatsSupplier; + ::rtl::OUString m_sConnectURL; + ::rtl::OUString m_sName; // transient, our creator has to tell us the title + ::rtl::OUString m_sUser; + ::rtl::OUString m_aPassword; // transient ! + ::rtl::OUString m_sFailedPassword; + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue> + m_aLayoutInformation; + sal_Int32 m_nLoginTimeout; + sal_Bool m_bReadOnly : 1; + sal_Bool m_bPasswordRequired : 1; + sal_Bool m_bSuppressVersionColumns : 1; + sal_Bool m_bModified : 1; + sal_Bool m_bDocumentReadOnly : 1; + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyAccess > + m_xSettings; + ::com::sun::star::uno::Sequence< ::rtl::OUString > m_aTableFilter; + ::com::sun::star::uno::Sequence< ::rtl::OUString > m_aTableTypeFilter; + OSharedConnectionManager* m_pSharedConnectionManager; + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener > + m_xSharedConnectionManager; + sal_uInt16 m_nControllerLockCount; + + void reset(); + + /** determines whether the database document has an embedded data storage + */ + inline bool isEmbeddedDatabase() const { return ( m_sConnectURL.compareToAscii( "sdbc:embedded:", 14 ) == 0 ); } + + /** stores the embedded storage ("database") + + @param _bPreventRootCommits + Normally, committing the embedded storage results in also commiting the root storage + - this is an automatism for data safety reasons. + If you pass <TRUE/> here, committing the root storage is prevented for this particular + call. + @return <TRUE/> if the storage could be commited, otherwise <FALSE/> + */ + bool commitEmbeddedStorage( bool _bPreventRootCommits = false ); + + /// commits all sub storages + void commitStorages() + SAL_THROW(( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException )); + + ODatabaseModelImpl( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxFactory, + ODatabaseContext& _pDBContext + ); + virtual ~ODatabaseModelImpl(); + + ODatabaseModelImpl( + const ::rtl::OUString& _rRegistrationName, + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxFactory, + ODatabaseContext& _rDBContext + ); + + // XEventListener + void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw(::com::sun::star::uno::RuntimeException); + + void setModified( sal_Bool bModified ); + + void dispose(); + + inline ::rtl::OUString getURL() const { return m_sDocumentURL; } + inline ::rtl::OUString getDocFileLocation() const { return m_sDocFileLocation; } + + ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage > + getStorage( + const ObjectType _eType, const sal_Int32 _nDesiredMode = ::com::sun::star::embed::ElementModes::READWRITE ); + +// helper + const ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier >& + getNumberFormatsSupplier(); + + DocumentEventsData& + getDocumentEvents() { return m_aDocumentEvents; } + + const ::comphelper::NamedValueCollection& + getMediaDescriptor() const { return m_aMediaDescriptor; } + + void setResource( + const ::rtl::OUString& _rURL, + const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& _rArgs + ); + void setDocFileLocation( + const ::rtl::OUString& i_rLoadedFrom + ); + + static ::comphelper::NamedValueCollection + stripLoadArguments( const ::comphelper::NamedValueCollection& _rArguments ); + +// other stuff + void flushTables(); + + // disposes all elements in m_aStorages, and clears it + void disposeStorages() SAL_THROW(()); + + /// creates a ->com::sun::star::embed::StorageFactory + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XSingleServiceFactory > + createStorageFactory() const; + + /// commits our storage + void commitRootStorage(); + + /// 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 + ) + SAL_THROW(()); + + void clearConnections(); + + ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage > getOrCreateRootStorage(); + inline ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage > getRootStorage() const { return m_xDocumentStorage.getTyped(); } + inline void resetRootStroage() { impl_switchToStorage_throw( NULL ); } + + /** returns the data source. If it doesn't exist it will be created + */ + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XDataSource> getOrCreateDataSource(); + + /** returns the model, if there already exists one + */ + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > getModel_noCreate() const; + + /** returns a new ->ODatabaseDocument + + @param _bInitializeIfNecessary + calls XLoadable::initNew on the newly created model, if necessary + + @precond + No ->ODatabaseDocument exists so far + + @seealso + getModel_noCreate + */ + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > createNewModel_deliverOwnership( bool _bInitialize ); + + struct ResetModelAccess { friend class ODatabaseDocument; private: ResetModelAccess() { } }; + + /** resets the model to NULL + + Only to be called when the model is being disposed + */ + void modelIsDisposing( const bool _wasInitialized, ResetModelAccess ); + + bool hadInitializedDocument() const { return m_bDocumentInitialized; } + + DocumentStorageAccess* + getDocumentStorageAccess(); + + ::com::sun::star::uno::Reference< ::com::sun::star::document::XDocumentSubStorageSupplier > + getDocumentSubStorageSupplier(); + + inline const ::comphelper::SharedMutex& getSharedMutex() const { return m_aMutex; } + + /** @see osl_incrementInterlockedCount. + */ + virtual oslInterlockedCount SAL_CALL acquire(); + + /** @see osl_decrementInterlockedCount. + */ + virtual oslInterlockedCount SAL_CALL release(); + + /// returns a all known data source settings, including their default values + static const AsciiPropertyValue* getDefaultDataSourceSettings(); + + /** retrieves the requested container of objects (forms/reports/tables/queries) + */ + TContentPtr& getObjectContainer( const ObjectType _eType ); + + /** returns the name of the storage which is used to stored objects of the given type, if applicable + */ + static ::rtl::OUString + getObjectContainerStorageName( const ObjectType _eType ); + + /** revokes the data source registration at the database context + */ + void revokeDataSource() const; + + /** determines whether a given object storage contains macros + */ + static bool objectHasMacros( + const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& _rxContainerStorage, + const ::rtl::OUString& _rPersistentName + ); + + /** determines which kind of embedded macros are present in the document + */ + EmbeddedMacros determineEmbeddedMacros(); + + /** checks our document's macro execution mode, using the interaction handler as supplied with our + load arguments + */ + bool checkMacrosOnLoading(); + + /** adjusts our document's macro execution mode, without using any UI, assuming the user + would reject execution of macros, if she would have been asked. + + If checkMacrosOnLoading has been called before (and thus the macro execution mode + is already adjusted), then the current execution mode is simply returned. + + @return + whether or not macro execution is allowed + */ + bool adjustMacroMode_AutoReject(); + + /** resets our macro execute mode, so next time the checkMacrosOnLoading is called, it will + behave as if it has never been called before + */ + void resetMacroExecutionMode(); + + /** ensures that ->m_xBasicLibraries resp. m_xDialogLibraries exists + + @return + the requested library container. Is never <NULL/>. + + @throws RuntimeException + if something does wrong, which indicates a server error in the installation + */ + ::com::sun::star::uno::Reference< ::com::sun::star::script::XStorageBasedLibraryContainer > + getLibraryContainer( bool _bScript ); + + /** lets our library containers store themself into the given root storage + */ + void storeLibraryContainersTo( const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& _rxToRootStorage ); + + /** rebases the document to the given storage + + No actual committing, copying, saving, whatsoever happens. The storage is just remembered as the documents + new storage, nothing more. + + @throws ::com::sun::star::lang::IllegalArgumentException + if the given storage is <NULL/> + @throws ::com::sun::star::lang::RuntimeException + if any of the invoked operations does so + */ + ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage > + switchToStorage( + const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& _rxNewRootStorage + ); + + /** returns the macro mode imposed by an external instance, which passed it to attachResource + */ + sal_Int16 getImposedMacroExecMode() const + { + return m_nImposedMacroExecMode; + } + void setImposedMacroExecMode( const sal_Int16 _nMacroMode ) + { + m_nImposedMacroExecMode = _nMacroMode; + } + +public: + // IMacroDocumentAccess overridables + virtual sal_Int16 getCurrentMacroExecMode() const; + virtual sal_Bool setCurrentMacroExecMode( sal_uInt16 ); + virtual ::rtl::OUString getDocumentLocation() const; + virtual ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage > getZipStorageToSign(); + virtual sal_Bool documentStorageHasMacros() const; + virtual ::com::sun::star::uno::Reference< ::com::sun::star::document::XEmbeddedScripts > getEmbeddedDocumentScripts() const; + virtual sal_Int16 getScriptingSignatureState(); + virtual sal_Bool hasTrustedScriptingSignature( sal_Bool bAllowUIToAddAuthor ); + virtual void showBrokenSignatureWarning( const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& _rxInteraction ) const; + + // IModifiableDocument + virtual void storageIsModified(); + + // don't use directly, use the ModifyLock class instead + void lockModify() { m_bModificationLock = true; } + void unlockModify() { m_bModificationLock = false; } + bool isModifyLocked() const { return m_bModificationLock; } + +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 +*/ +class ModelDependentComponent +{ +protected: + ::rtl::Reference< ODatabaseModelImpl > m_pImpl; + mutable ::comphelper::SharedMutex m_aMutex; + +protected: + ModelDependentComponent( const ::rtl::Reference< ODatabaseModelImpl >& _model ); + virtual ~ModelDependentComponent(); + + /** returns the component itself + */ + virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > getThis() const = 0; + + inline ::osl::Mutex& getMutex() const + { + return m_aMutex; + } + +public: + struct GuardAccess { friend class ModelMethodGuard; private: GuardAccess() { } }; + + /** returns the mutex used for thread safety + + @throws ::com::sun::star::lang::DisposedException + if m_pImpl is <NULL/>. Usually, you will set this member in your derived + component's <code>dispose</code> method to <NULL/>. + */ + inline ::osl::Mutex& getMutex( GuardAccess ) const + { + return getMutex(); + } + inline ::rtl::Reference< ODatabaseModelImpl > getImpl( GuardAccess ) + { + return m_pImpl; + } + + /// checks whether the component is already disposed, throws a DisposedException if so + inline void checkDisposed() const + { + if ( !m_pImpl.is() ) + throw ::com::sun::star::lang::DisposedException( ::rtl::OUString::createFromAscii( "Component is already disposed." ), getThis() ); + } + + inline void lockModify() + { + m_pImpl->lockModify(); + } + + inline void unlockModify() + { + m_pImpl->unlockModify(); + } +}; + +class ModifyLock +{ +public: + ModifyLock( ModelDependentComponent& _component ) + :m_rComponent( _component ) + { + m_rComponent.lockModify(); + } + + ~ModifyLock() + { + m_rComponent.unlockModify(); + } + +private: + ModelDependentComponent& m_rComponent; +}; + +/** a guard for public methods of objects dependent on a ODatabaseModelImpl instance + + Just put this guard onto the stack at the beginning of your method. Don't bother yourself + with a MutexGuard, checks for being disposed, and the like. +*/ +class ModelMethodGuard : public ::osl::ResettableMutexGuard +{ +private: + typedef ::osl::ResettableMutexGuard BaseMutexGuard; + +public: + /** constructs the guard + + @param _component + the component whose functionality depends on a ODatabaseModelImpl instance + + @throws ::com::sun::star::lang::DisposedException + If the given component is already disposed + */ + ModelMethodGuard( const ModelDependentComponent& _component ) + :BaseMutexGuard( _component.getMutex( ModelDependentComponent::GuardAccess() ) ) + { + _component.checkDisposed(); + } + + ~ModelMethodGuard() + { + } +}; + +//........................................................................ +} // namespace dbaccess +//........................................................................ + +#endif // _DBA_COREDATAACCESS_DATALINK_HXX_ + diff --git a/dbaccess/source/core/dataaccess/SharedConnection.cxx b/dbaccess/source/core/dataaccess/SharedConnection.cxx new file mode 100644 index 000000000000..d2b9f4d5196a --- /dev/null +++ b/dbaccess/source/core/dataaccess/SharedConnection.cxx @@ -0,0 +1,186 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" +#ifndef DBA_CORE_SHARED_CONNECTION_HXX +#include "SharedConnection.hxx" +#endif +#ifndef _TOOLS_DEBUG_HXX +#include <tools/debug.hxx> +#endif + + +namespace dbaccess +{ + using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::container; +// using namespace ::com::sun::star::reflection; +using namespace connectivity; + +DBG_NAME(OSharedConnection) +OSharedConnection::OSharedConnection(Reference< XAggregation >& _rxProxyConnection) + : OSharedConnection_BASE(m_aMutex) +{ + DBG_CTOR(OSharedConnection,NULL); + setDelegation(_rxProxyConnection,m_refCount); +} +// ----------------------------------------------------------------------------- +OSharedConnection::~OSharedConnection() +{ + DBG_DTOR(OSharedConnection,NULL); +} +// ----------------------------------------------------------------------------- +void SAL_CALL OSharedConnection::disposing(void) +{ + OSharedConnection_BASE::disposing(); + OConnectionWrapper::disposing(); +} +// ----------------------------------------------------------------------------- +Reference< XStatement > SAL_CALL OSharedConnection::createStatement( ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(rBHelper.bDisposed); + + + return m_xConnection->createStatement(); +} +// -------------------------------------------------------------------------------- +Reference< XPreparedStatement > SAL_CALL OSharedConnection::prepareStatement( const ::rtl::OUString& sql ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(rBHelper.bDisposed); + + + return m_xConnection->prepareStatement(sql); +} +// -------------------------------------------------------------------------------- +Reference< XPreparedStatement > SAL_CALL OSharedConnection::prepareCall( const ::rtl::OUString& sql ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(rBHelper.bDisposed); + + + return m_xConnection->prepareCall(sql); +} +// -------------------------------------------------------------------------------- +::rtl::OUString SAL_CALL OSharedConnection::nativeSQL( const ::rtl::OUString& sql ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(rBHelper.bDisposed); + + + return m_xConnection->nativeSQL(sql); +} +// -------------------------------------------------------------------------------- +sal_Bool SAL_CALL OSharedConnection::getAutoCommit( ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(rBHelper.bDisposed); + + + return m_xConnection->getAutoCommit(); +} +// -------------------------------------------------------------------------------- +void SAL_CALL OSharedConnection::commit( ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(rBHelper.bDisposed); + + + m_xConnection->commit(); +} +// -------------------------------------------------------------------------------- +void SAL_CALL OSharedConnection::rollback( ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(rBHelper.bDisposed); + + + m_xConnection->rollback(); +} +// -------------------------------------------------------------------------------- +sal_Bool SAL_CALL OSharedConnection::isClosed( ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + return m_xConnection->isClosed(); +} +// -------------------------------------------------------------------------------- +Reference< XDatabaseMetaData > SAL_CALL OSharedConnection::getMetaData( ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(rBHelper.bDisposed); + + + return m_xConnection->getMetaData(); +} +// -------------------------------------------------------------------------------- +sal_Bool SAL_CALL OSharedConnection::isReadOnly( ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(rBHelper.bDisposed); + + + return m_xConnection->isReadOnly(); +} +// -------------------------------------------------------------------------------- +::rtl::OUString SAL_CALL OSharedConnection::getCatalog( ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(rBHelper.bDisposed); + + + return m_xConnection->getCatalog(); +} +// -------------------------------------------------------------------------------- +sal_Int32 SAL_CALL OSharedConnection::getTransactionIsolation( ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(rBHelper.bDisposed); + + + return m_xConnection->getTransactionIsolation(); +} +// -------------------------------------------------------------------------------- +Reference< ::com::sun::star::container::XNameAccess > SAL_CALL OSharedConnection::getTypeMap( ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(rBHelper.bDisposed); + + + return m_xConnection->getTypeMap(); +} +// ----------------------------------------------------------------------------- + +//........................................................................ +} // namespace dbaccess +//........................................................................ + + diff --git a/dbaccess/source/core/dataaccess/SharedConnection.hxx b/dbaccess/source/core/dataaccess/SharedConnection.hxx new file mode 100644 index 000000000000..7691411cd08b --- /dev/null +++ b/dbaccess/source/core/dataaccess/SharedConnection.hxx @@ -0,0 +1,172 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 DBA_CORE_SHARED_CONNECTION_HXX +#define DBA_CORE_SHARED_CONNECTION_HXX + +#ifndef _CONNECTIVITY_CONNECTIONWRAPPER_HXX_ +#include "connectivity/ConnectionWrapper.hxx" +#endif +#ifndef _CPPUHELPER_COMPONENT_HXX_ +#include <cppuhelper/component.hxx> +#endif +#ifndef _CONNECTIVITY_COMMONTOOLS_HXX_ +#include <connectivity/CommonTools.hxx> +#endif +#ifndef _CPPUHELPER_COMPBASE1_HXX_ +#include <cppuhelper/compbase1.hxx> +#endif +#ifndef _COM_SUN_STAR_SDBC_XCONNECTION_HPP_ +#include <com/sun/star/sdbc/XConnection.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XWARNINGSSUPPLIER_HPP_ +#include <com/sun/star/sdbc/XWarningsSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_SQLWARNING_HPP_ +#include <com/sun/star/sdbc/SQLWarning.hpp> +#endif +#ifndef _COM_SUN_STAR_BEANS_PROPERTYVALUE_HPP_ +#include <com/sun/star/beans/PropertyValue.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_SDB_XQUERIESSUPPLIER_HPP_ +#include <com/sun/star/sdb/XQueriesSupplier.hpp> +#endif +#ifndef _COMPHELPER_SEQUENCE_HXX_ +#include <comphelper/sequence.hxx> +#endif + + +namespace dbaccess +{ + //======================================================================================= + //= OSharedConnection: This class implements a simple forwarding of connection calls. + //= All methods will be forwarded with exception of the set methods, which are not allowed + //= to be called on shared connections. Instances of this class will be created when the + //= datasource is asked for not isolated connection. + //======================================================================================= + typedef ::cppu::WeakComponentImplHelper1< ::com::sun::star::sdbc::XConnection + > OSharedConnection_BASE; + typedef ::connectivity::OConnectionWrapper OSharedConnection_BASE2; + + class OSharedConnection : public ::comphelper::OBaseMutex + , public OSharedConnection_BASE + , public OSharedConnection_BASE2 + { + protected: + virtual void SAL_CALL disposing(void); + virtual ~OSharedConnection(); + public: + OSharedConnection(::com::sun::star::uno::Reference< ::com::sun::star::uno::XAggregation >& _rxProxyConnection); + + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId( ) throw (::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL acquire() throw() { OSharedConnection_BASE::acquire(); } + virtual void SAL_CALL release() throw() { OSharedConnection_BASE::release(); } + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes( ) throw (::com::sun::star::uno::RuntimeException) + { + return ::comphelper::concatSequences( + OSharedConnection_BASE::getTypes(), + OSharedConnection_BASE2::getTypes() + ); + } + + virtual ::com::sun::star::uno::Any SAL_CALL queryInterface( const ::com::sun::star::uno::Type& _rType ) throw (::com::sun::star::uno::RuntimeException) + { + ::com::sun::star::uno::Any aReturn = OSharedConnection_BASE::queryInterface(_rType); + if ( !aReturn.hasValue() ) + aReturn = OSharedConnection_BASE2::queryInterface(_rType); + return aReturn; + } + // -------------------------------------------------------------------------------- + // XCloseable + virtual void SAL_CALL close( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) + { + { + ::osl::MutexGuard aGuard( m_aMutex ); + ::connectivity::checkDisposed(rBHelper.bDisposed); + + } + dispose(); + } + + // XConnection + virtual void SAL_CALL setAutoCommit( sal_Bool /*autoCommit*/ ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) + { + throw ::com::sun::star::sdbc::SQLException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("This call is not allowed when sharing connections.")),*this,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("S10000")),0,::com::sun::star::uno::Any()); + } + virtual void SAL_CALL setReadOnly( sal_Bool /*readOnly*/ ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) + { + throw ::com::sun::star::sdbc::SQLException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("This call is not allowed when sharing connections.")),*this,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("S10000")),0,::com::sun::star::uno::Any()); + } + virtual void SAL_CALL setCatalog( const ::rtl::OUString& /*catalog*/ ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) + { + throw ::com::sun::star::sdbc::SQLException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("This call is not allowed when sharing connections.")),*this,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("S10000")),0,::com::sun::star::uno::Any()); + } + virtual void SAL_CALL setTransactionIsolation( sal_Int32 /*level*/ ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) + { + throw ::com::sun::star::sdbc::SQLException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("This call is not allowed when sharing connections.")),*this,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("S10000")),0,::com::sun::star::uno::Any()); + } + virtual void SAL_CALL setTypeMap( const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& /*typeMap*/ ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) + { + throw ::com::sun::star::sdbc::SQLException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("This call is not allowed when sharing connections.")),*this,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("S10000")),0,::com::sun::star::uno::Any()); + } + // XConnection + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XStatement > SAL_CALL createStatement( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XPreparedStatement > SAL_CALL prepareStatement( const ::rtl::OUString& sql ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XPreparedStatement > SAL_CALL prepareCall( const ::rtl::OUString& sql ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL nativeSQL( const ::rtl::OUString& sql ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL getAutoCommit( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL commit( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL rollback( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isClosed( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XDatabaseMetaData > SAL_CALL getMetaData( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isReadOnly( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getCatalog( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getTransactionIsolation( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > SAL_CALL getTypeMap( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + }; + +#ifdef IMPLEMENT_GET_IMPLEMENTATION_ID + IMPLEMENT_GET_IMPLEMENTATION_ID( OSharedConnection ); +#endif +//........................................................................ +} // namespace dbaccess +//........................................................................ +#endif // DBA_CORE_SHARED_CONNECTION_HXX + + diff --git a/dbaccess/source/core/dataaccess/bookmarkcontainer.cxx b/dbaccess/source/core/dataaccess/bookmarkcontainer.cxx new file mode 100644 index 000000000000..08321a0e0053 --- /dev/null +++ b/dbaccess/source/core/dataaccess/bookmarkcontainer.cxx @@ -0,0 +1,421 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#ifndef _DBA_CORE_BOOKMARKCONTAINER_HXX_ +#include "bookmarkcontainer.hxx" +#endif +#ifndef DBACCESS_SHARED_DBASTRINGS_HRC +#include "dbastrings.hrc" +#endif +#ifndef _DBASHARED_APITOOLS_HXX_ +#include "apitools.hxx" +#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 +#ifndef _COMPHELPER_SEQUENCE_HXX_ +#include <comphelper/sequence.hxx> +#endif +#ifndef _COMPHELPER_ENUMHELPER_HXX_ +#include <comphelper/enumhelper.hxx> +#endif +#ifndef _COMPHELPER_EXTRACT_HXX_ +#include <comphelper/extract.hxx> +#endif +#ifndef _COM_SUN_STAR_LANG_XCOMPONENT_HPP_ +#include <com/sun/star/lang/XComponent.hpp> +#endif +#ifndef _COMPHELPER_TYPES_HXX_ +#include <comphelper/types.hxx> +#endif + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::osl; +using namespace ::comphelper; +using namespace ::cppu; + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + +//========================================================================== +//= OBookmarkContainer +//========================================================================== +DBG_NAME(OBookmarkContainer) +//-------------------------------------------------------------------------- +OBookmarkContainer::OBookmarkContainer(OWeakObject& _rParent, Mutex& _rMutex) + :m_rParent(_rParent) + ,m_aContainerListeners(_rMutex) + ,m_rMutex(_rMutex) +{ + DBG_CTOR(OBookmarkContainer, NULL); +} + +//-------------------------------------------------------------------------- +void OBookmarkContainer::dispose() +{ + MutexGuard aGuard(m_rMutex); + + // say our listeners goobye + EventObject aEvt(*this); + m_aContainerListeners.disposeAndClear(aEvt); + + // remove our elements + m_aBookmarksIndexed.clear(); + m_aBookmarks.clear(); +} + +//-------------------------------------------------------------------------- +void SAL_CALL OBookmarkContainer::acquire( ) throw() +{ + m_rParent.acquire(); +} + +//-------------------------------------------------------------------------- +void SAL_CALL OBookmarkContainer::release( ) throw() +{ + m_rParent.release(); +} + +//-------------------------------------------------------------------------- +OBookmarkContainer::~OBookmarkContainer() +{ + DBG_DTOR(OBookmarkContainer, NULL); +} + +// XServiceInfo +//-------------------------------------------------------------------------- +::rtl::OUString SAL_CALL OBookmarkContainer::getImplementationName( ) throw(RuntimeException) +{ + return ::rtl::OUString::createFromAscii("com.sun.star.comp.dba.OBookmarkContainer"); +} + +//-------------------------------------------------------------------------- +sal_Bool SAL_CALL OBookmarkContainer::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException) +{ + MutexGuard aGuard(m_rMutex); + checkValid(sal_False); + return findValue(getSupportedServiceNames(), _rServiceName, sal_True).getLength() != 0; +} + +//-------------------------------------------------------------------------- +Sequence< ::rtl::OUString > SAL_CALL OBookmarkContainer::getSupportedServiceNames( ) throw(RuntimeException) +{ + Sequence< ::rtl::OUString > aReturn(1); + aReturn.getArray()[0] = ::rtl::OUString::createFromAscii("com.sun.star.sdb.DefinitionContainer"); + return aReturn; +} + +// XNameContainer +//-------------------------------------------------------------------------- +void SAL_CALL OBookmarkContainer::insertByName( const ::rtl::OUString& _rName, const Any& aElement ) throw(IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException) +{ + MutexGuard aGuard(m_rMutex); + checkValid(sal_True); + + if (checkExistence(_rName)) + throw ElementExistException(); + + if (0 == _rName.getLength()) + throw IllegalArgumentException(); + + // approve the new object + ::rtl::OUString sNewLink; + if (!(aElement >>= sNewLink)) + throw IllegalArgumentException(); + + + implAppend(_rName, sNewLink); + + // notify the listeners + if (m_aContainerListeners.getLength()) + { + ContainerEvent aEvent(*this, makeAny(_rName), makeAny(sNewLink), Any()); + OInterfaceIteratorHelper aListenerIterator(m_aContainerListeners); + while (aListenerIterator.hasMoreElements()) + static_cast< XContainerListener* >(aListenerIterator.next())->elementInserted(aEvent); + } +} + +//-------------------------------------------------------------------------- +void SAL_CALL OBookmarkContainer::removeByName( const ::rtl::OUString& _rName ) throw(NoSuchElementException, WrappedTargetException, RuntimeException) +{ + ::rtl::OUString sOldBookmark; + { + MutexGuard aGuard(m_rMutex); + checkValid(sal_True); + + // check the arguments + if (!_rName.getLength()) + throw IllegalArgumentException(); + + if (!checkExistence(_rName)) + throw NoSuchElementException(); + + // the old element (for the notifications) + sOldBookmark = m_aBookmarks[_rName]; + + // do the removal + implRemove(_rName); + } + + // notify the listeners + if (m_aContainerListeners.getLength()) + { + ContainerEvent aEvent(*this, makeAny(_rName), makeAny(sOldBookmark), Any()); + OInterfaceIteratorHelper aListenerIterator(m_aContainerListeners); + while (aListenerIterator.hasMoreElements()) + static_cast< XContainerListener* >(aListenerIterator.next())->elementRemoved(aEvent); + } +} + +// XNameReplace +//-------------------------------------------------------------------------- +void SAL_CALL OBookmarkContainer::replaceByName( const ::rtl::OUString& _rName, const Any& aElement ) throw(IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException) +{ + ClearableMutexGuard aGuard(m_rMutex); + checkValid(sal_True); + + // check the arguments + if (!_rName.getLength()) + throw IllegalArgumentException(); + + // do we have such an element? + if (!checkExistence(_rName)) + throw NoSuchElementException(); + + // approve the new object + ::rtl::OUString sNewLink; + if (!(aElement >>= sNewLink)) + throw IllegalArgumentException(); + + // the old element (for the notifications) + ::rtl::OUString sOldLink = m_aBookmarks[_rName]; + + // do the replace + implReplace(_rName, sNewLink); + + // notify the listeners + aGuard.clear(); + if (m_aContainerListeners.getLength()) + { + ContainerEvent aEvent(*this, makeAny(_rName), makeAny(sNewLink), makeAny(sOldLink)); + OInterfaceIteratorHelper aListenerIterator(m_aContainerListeners); + while (aListenerIterator.hasMoreElements()) + static_cast< XContainerListener* >(aListenerIterator.next())->elementReplaced(aEvent); + } +} + +//-------------------------------------------------------------------------- +void SAL_CALL OBookmarkContainer::addContainerListener( const Reference< XContainerListener >& _rxListener ) throw(RuntimeException) +{ + MutexGuard aGuard(m_rMutex); + if (_rxListener.is()) + m_aContainerListeners.addInterface(_rxListener); +} + +//-------------------------------------------------------------------------- +void SAL_CALL OBookmarkContainer::removeContainerListener( const Reference< XContainerListener >& _rxListener ) throw(RuntimeException) +{ + MutexGuard aGuard(m_rMutex); + if (_rxListener.is()) + m_aContainerListeners.removeInterface(_rxListener); +} + +// XElementAccess +//-------------------------------------------------------------------------- +Type SAL_CALL OBookmarkContainer::getElementType( ) throw (RuntimeException) +{ + MutexGuard aGuard(m_rMutex); + checkValid(sal_False); + return ::getCppuType( static_cast< ::rtl::OUString* >(NULL) ); +} + +//-------------------------------------------------------------------------- +sal_Bool SAL_CALL OBookmarkContainer::hasElements( ) throw (RuntimeException) +{ + MutexGuard aGuard(m_rMutex); + checkValid(sal_False); + return !m_aBookmarks.empty(); +} + +// XEnumerationAccess +//-------------------------------------------------------------------------- +Reference< XEnumeration > SAL_CALL OBookmarkContainer::createEnumeration( ) throw(RuntimeException) +{ + MutexGuard aGuard(m_rMutex); + checkValid(sal_False); + return new ::comphelper::OEnumerationByIndex(static_cast<XIndexAccess*>(this)); +} + +//-------------------------------------------------------------------------- +// XIndexAccess +sal_Int32 SAL_CALL OBookmarkContainer::getCount( ) throw(RuntimeException) +{ + MutexGuard aGuard(m_rMutex); + checkValid(sal_False); + return m_aBookmarks.size(); +} + +//-------------------------------------------------------------------------- +Any SAL_CALL OBookmarkContainer::getByIndex( sal_Int32 _nIndex ) throw(IndexOutOfBoundsException, WrappedTargetException, RuntimeException) +{ + MutexGuard aGuard(m_rMutex); + checkValid(sal_False); + + if ((_nIndex < 0) || (_nIndex >= (sal_Int32)m_aBookmarksIndexed.size())) + throw IndexOutOfBoundsException(); + + return makeAny(m_aBookmarksIndexed[_nIndex]->second); +} + +//-------------------------------------------------------------------------- +Any SAL_CALL OBookmarkContainer::getByName( const ::rtl::OUString& _rName ) throw(NoSuchElementException, WrappedTargetException, RuntimeException) +{ + MutexGuard aGuard(m_rMutex); + checkValid(sal_False); + + if (!checkExistence(_rName)) + throw NoSuchElementException(); + + return makeAny(m_aBookmarks[_rName]); +} + +//-------------------------------------------------------------------------- +Sequence< ::rtl::OUString > SAL_CALL OBookmarkContainer::getElementNames( ) throw(RuntimeException) +{ + MutexGuard aGuard(m_rMutex); + checkValid(sal_False); + + Sequence< ::rtl::OUString > aNames(m_aBookmarks.size()); + ::rtl::OUString* pNames = aNames.getArray(); + ; + for ( ConstMapIteratorVectorIterator aNameIter = m_aBookmarksIndexed.begin(); + aNameIter != m_aBookmarksIndexed.end(); + ++pNames, ++aNameIter + ) + { + *pNames = (*aNameIter)->first; + } + + return aNames; +} + +//-------------------------------------------------------------------------- +sal_Bool SAL_CALL OBookmarkContainer::hasByName( const ::rtl::OUString& _rName ) throw(RuntimeException) +{ + MutexGuard aGuard(m_rMutex); + checkValid(sal_False); + + return checkExistence(_rName); +} + +//-------------------------------------------------------------------------- +void OBookmarkContainer::implRemove(const ::rtl::OUString& _rName) +{ + MutexGuard aGuard(m_rMutex); + + // look for the name in the index access vector + MapString2StringIterator aMapPos = m_aBookmarks.end(); + for ( MapIteratorVectorIterator aSearch = m_aBookmarksIndexed.begin(); + aSearch != m_aBookmarksIndexed.end(); + ++aSearch + ) + { +#ifdef DBG_UTIL + ::rtl::OUString sName = (*aSearch)->first; +#endif + if ((*aSearch)->first == _rName) + { + aMapPos = *aSearch; + m_aBookmarksIndexed.erase(aSearch); + break; + } + } + + if (m_aBookmarks.end() == aMapPos) + { + DBG_ERROR("OBookmarkContainer::implRemove: inconsistence!"); + return; + } + + // remove the map entries + m_aBookmarks.erase(aMapPos); +} + +//-------------------------------------------------------------------------- +void OBookmarkContainer::implAppend(const ::rtl::OUString& _rName, const ::rtl::OUString& _rDocumentLocation) +{ + MutexGuard aGuard(m_rMutex); + + OSL_ENSURE(m_aBookmarks.find(_rName) == m_aBookmarks.end(),"Bookmark already known!"); + m_aBookmarksIndexed.push_back(m_aBookmarks.insert( MapString2String::value_type(_rName,_rDocumentLocation)).first); +} + +//-------------------------------------------------------------------------- +void OBookmarkContainer::implReplace(const ::rtl::OUString& _rName, const ::rtl::OUString& _rNewLink) +{ + MutexGuard aGuard(m_rMutex); + DBG_ASSERT(checkExistence(_rName), "OBookmarkContainer::implReplace : invalid name !"); + + m_aBookmarks[_rName] = _rNewLink; +} + +//-------------------------------------------------------------------------- +void OBookmarkContainer::checkValid(sal_Bool /*_bIntendWriteAccess*/) const throw (RuntimeException, DisposedException) +{ +} + +//-------------------------------------------------------------------------- +Reference< XInterface > SAL_CALL OBookmarkContainer::getParent( ) throw (RuntimeException) +{ + return m_rParent; +} + +//-------------------------------------------------------------------------- +void SAL_CALL OBookmarkContainer::setParent( const Reference< XInterface >& /*Parent*/ ) throw (NoSupportException, RuntimeException) +{ + throw NoSupportException(); +} + +//........................................................................ +} // namespace dbaccess +//........................................................................ diff --git a/dbaccess/source/core/dataaccess/bookmarkcontainer.hxx b/dbaccess/source/core/dataaccess/bookmarkcontainer.hxx new file mode 100644 index 000000000000..0a43371c51e5 --- /dev/null +++ b/dbaccess/source/core/dataaccess/bookmarkcontainer.hxx @@ -0,0 +1,208 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 _DBA_CORE_BOOKMARKCONTAINER_HXX_ +#define _DBA_CORE_BOOKMARKCONTAINER_HXX_ + +#ifndef _CPPUHELPER_INTERFACECONTAINER_HXX_ +#include <cppuhelper/interfacecontainer.hxx> +#endif +#ifndef _CPPUHELPER_IMPLBASE6_HXX_ +#include <cppuhelper/implbase6.hxx> +#endif +#ifndef _COMPHELPER_STLTYPES_HXX_ +#include <comphelper/stl_types.hxx> +#endif +#ifndef _OSL_MUTEX_HXX_ +#include <osl/mutex.hxx> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XCHILD_HPP_ +#include <com/sun/star/container/XChild.hpp> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XNAMECONTAINER_HPP_ +#include <com/sun/star/container/XNameContainer.hpp> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XCONTAINER_HPP_ +#include <com/sun/star/container/XContainer.hpp> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XENUMERATIONACCESS_HPP_ +#include <com/sun/star/container/XEnumerationAccess.hpp> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XINDEXACCESS_HPP_ +#include <com/sun/star/container/XIndexAccess.hpp> +#endif +#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_ +#include <com/sun/star/lang/XServiceInfo.hpp> +#endif +#ifndef _COM_SUN_STAR_LANG_XSINGLESERVICEFACTORY_HPP_ +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#endif +#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_ +#include <com/sun/star/beans/XPropertySet.hpp> +#endif +#ifndef _COM_SUN_STAR_LANG_DISPOSEDEXCEPTION_HPP_ +#include <com/sun/star/lang/DisposedException.hpp> +#endif + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + +//========================================================================== +//= OBookmarkContainer - base class of collections of database definition +//= documents +//========================================================================== +typedef ::cppu::WeakImplHelper6 < + ::com::sun::star::container::XIndexAccess + , ::com::sun::star::container::XNameContainer + , ::com::sun::star::container::XEnumerationAccess + , ::com::sun::star::container::XContainer + , ::com::sun::star::lang::XServiceInfo + , ::com::sun::star::container::XChild + > OBookmarkContainer_Base; + +class OBookmarkContainer + :public OBookmarkContainer_Base +{ +protected: + DECLARE_STL_USTRINGACCESS_MAP(::rtl::OUString, MapString2String); + DECLARE_STL_VECTOR(MapString2StringIterator, MapIteratorVector); + + MapString2String m_aBookmarks; // the bookmarks itself + MapIteratorVector m_aBookmarksIndexed; // for index access to the + +protected: + ::cppu::OWeakObject& m_rParent; // for the ref counting + ::cppu::OInterfaceContainerHelper + m_aContainerListeners; + ::osl::Mutex& m_rMutex; + + +public: + /** constructs the container.<BR> + after the construction of the object the creator has to call <code>initialize</code>. + @param _rParent the parent object which is used for ref counting + @param _rMutex the parent's mutex object for access safety + */ + OBookmarkContainer( + ::cppu::OWeakObject& _rParent, + ::osl::Mutex& _rMutex + ); + + /** looks like the dtor ... + */ + virtual ~OBookmarkContainer(); + +// ::com::sun::star::uno::XInterface + virtual void SAL_CALL acquire( ) throw(); + virtual void SAL_CALL release( ) throw(); + +// ::com::sun::star::lang::XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw(::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::container::XElementAccess + virtual ::com::sun::star::uno::Type SAL_CALL getElementType( ) throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL hasElements( ) throw(::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::container::XEnumerationAccess + virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XEnumeration > SAL_CALL createEnumeration( ) throw(::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::container::XIndexAccess + virtual sal_Int32 SAL_CALL getCount( ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Any SAL_CALL getByIndex( sal_Int32 _nIndex ) throw(::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::container::XNameContainer + virtual void SAL_CALL insertByName( const ::rtl::OUString& _rName, 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 removeByName( const ::rtl::OUString& _rName ) throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::container::XNameReplace + virtual void SAL_CALL replaceByName( const ::rtl::OUString& _rName, const ::com::sun::star::uno::Any& aElement ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::container::XNameAccess + virtual ::com::sun::star::uno::Any SAL_CALL getByName( const ::rtl::OUString& aName ) throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getElementNames( ) throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName ) throw(::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::container::XContainer + virtual void SAL_CALL addContainerListener( const ::com::sun::star::uno::Reference< ::com::sun::star::container::XContainerListener >& xListener ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeContainerListener( const ::com::sun::star::uno::Reference< ::com::sun::star::container::XContainerListener >& xListener ) throw(::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::container::XChild + virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL getParent( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setParent( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& Parent ) throw (::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException); + +// helper + /** tell the container to free all resources. After that it's in a state like after the construction, i.e. + you may call <code>initialize</code> again (maybe with another configuration node). + */ + virtual void dispose(); + + +protected: + /** checks whether the object is basically alive, i.e. it has been fully initialized (@see initialize) and + not disposed (@see dispose) + @param _bIntendWriteAccess determines whether or not the caller intends to modify the configuration. + if sal_True and the configuration is readonly, a runtime exception with + a description string is thrown. + */ + void checkValid(sal_Bool _bIntendWriteAccess) const throw (::com::sun::star::uno::RuntimeException, ::com::sun::star::lang::DisposedException); + + /** quickly checks if there already is an element with a given name. No access to the configuration occures, i.e. + if there is such an object which is not already loaded, it won't be loaded now. + @param _rName the object name to check + @return sal_True if there already exists such an object + */ + inline sal_Bool checkExistence(const ::rtl::OUString& _rName); + + void implAppend( + const ::rtl::OUString& _rName, + const ::rtl::OUString& _rDocumentLocation + ); + + void implRemove(const ::rtl::OUString& _rName); + + void implReplace( + const ::rtl::OUString& _rName, + const ::rtl::OUString& _rNewLink); + +}; + +//-------------------------------------------------------------------------- +inline sal_Bool OBookmarkContainer::checkExistence(const ::rtl::OUString& _rName) +{ + return m_aBookmarks.find(_rName) != m_aBookmarks.end(); +} + +//........................................................................ +} // namespace dbaccess +//........................................................................ + +#endif // _DBA_CORE_BOOKMARKCONTAINER_HXX_ + diff --git a/dbaccess/source/core/dataaccess/commandcontainer.cxx b/dbaccess/source/core/dataaccess/commandcontainer.cxx new file mode 100644 index 000000000000..34d7283b1837 --- /dev/null +++ b/dbaccess/source/core/dataaccess/commandcontainer.cxx @@ -0,0 +1,115 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#ifndef _DBA_COREDATAACCESS_COMMANDCONTAINER_HXX_ +#include "commandcontainer.hxx" +#endif +#ifndef _DBA_COREDATAACESS_COMMANDDEFINITION_HXX_ +#include "commanddefinition.hxx" +#endif + +#ifndef _TOOLS_DEBUG_HXX +#include <tools/debug.hxx> +#endif +#ifndef DBACCESS_SHARED_DBASTRINGS_HRC +#include "dbastrings.hrc" +#endif + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::ucb; +using namespace ::osl; +using namespace ::comphelper; +using namespace ::cppu; + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + +//========================================================================== +//= OCommandContainer +//========================================================================== +DBG_NAME(OCommandContainer) +//-------------------------------------------------------------------------- +OCommandContainer::OCommandContainer( const Reference< ::com::sun::star::lang::XMultiServiceFactory >& _xORB + ,const Reference< XInterface >& _xParentContainer + ,const TContentPtr& _pImpl + ,sal_Bool _bTables + ) + :ODefinitionContainer(_xORB,_xParentContainer,_pImpl,!_bTables) + ,m_bTables(_bTables) +{ + DBG_CTOR(OCommandContainer, NULL); +} +//-------------------------------------------------------------------------- +OCommandContainer::~OCommandContainer() +{ + DBG_DTOR(OCommandContainer, NULL); +} +// ----------------------------------------------------------------------------- +IMPLEMENT_FORWARD_XINTERFACE2( OCommandContainer,ODefinitionContainer,OCommandContainer_BASE) +IMPLEMENT_TYPEPROVIDER2(OCommandContainer,ODefinitionContainer,OCommandContainer_BASE); +//-------------------------------------------------------------------------- +Reference< XContent > OCommandContainer::createObject( const ::rtl::OUString& _rName) +{ + const ODefinitionContainer_Impl& rDefinitions( getDefinitions() ); + OSL_ENSURE( rDefinitions.find(_rName) != rDefinitions.end(), "OCommandContainer::createObject: Invalid entry in map!" ); + + const TContentPtr& pElementContent( rDefinitions.find( _rName )->second ); + if ( m_bTables ) + return new OComponentDefinition( *this, _rName, m_aContext.getLegacyServiceFactory(), pElementContent, m_bTables ); + return new OCommandDefinition( *this, _rName, m_aContext.getLegacyServiceFactory(), pElementContent ); +} + +// ----------------------------------------------------------------------------- +Reference< XInterface > SAL_CALL OCommandContainer::createInstanceWithArguments(const Sequence< Any >& /*aArguments*/ ) throw (Exception, RuntimeException) +{ + return createInstance( ); +} + +// ----------------------------------------------------------------------------- +Reference< XInterface > SAL_CALL OCommandContainer::createInstance( ) throw (Exception, RuntimeException) +{ + return m_aContext.createComponent( (::rtl::OUString)( m_bTables ? SERVICE_SDB_TABLEDEFINITION : SERVICE_SDB_COMMAND_DEFINITION ) ); +} + +// ----------------------------------------------------------------------------- +::rtl::OUString OCommandContainer::determineContentType() const +{ + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "application/vnd.org.openoffice.DatabaseCommandDefinitionContainer" ) ); +} + +//........................................................................ +} // namespace dbaccess +//........................................................................ + diff --git a/dbaccess/source/core/dataaccess/commandcontainer.hxx b/dbaccess/source/core/dataaccess/commandcontainer.hxx new file mode 100644 index 000000000000..4528224ce24d --- /dev/null +++ b/dbaccess/source/core/dataaccess/commandcontainer.hxx @@ -0,0 +1,93 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 _DBA_COREDATAACCESS_COMMANDCONTAINER_HXX_ +#define _DBA_COREDATAACCESS_COMMANDCONTAINER_HXX_ + +#ifndef _DBA_CORE_DEFINITIONCONTAINER_HXX_ +#include "definitioncontainer.hxx" +#endif + +#ifndef _COM_SUN_STAR_LANG_XSINGLESERVICEFACTORY_HPP_ +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#endif + +#ifndef _CPPUHELPER_IMPLBASE1_HXX_ +#include <cppuhelper/implbase1.hxx> +#endif + +//........................................................................ +namespace dbaccess +{ +//........................................................................ +//========================================================================== +//= OCommandContainer +//========================================================================== + +typedef ::cppu::ImplHelper1 < ::com::sun::star::lang::XSingleServiceFactory + > OCommandContainer_BASE; + +class OCommandContainer : public ODefinitionContainer + ,public OCommandContainer_BASE +{ + sal_Bool m_bTables; + +public: + /** constructs the container.<BR> + */ + OCommandContainer( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _xORB + ,const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _xParentContainer + ,const TContentPtr& _pImpl + ,sal_Bool _bTables + ); + + DECLARE_XINTERFACE( ) + DECLARE_TYPEPROVIDER( ); + + // XSingleServiceFactory + virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL createInstance( ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL createInstanceWithArguments( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + +protected: + virtual ~OCommandContainer(); + + // ODefinitionContainer + virtual ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContent > createObject(const ::rtl::OUString& _rName); + +protected: + // OContentHelper overridables + virtual ::rtl::OUString determineContentType() const; +}; + +//........................................................................ +} // namespace dbaccess +//........................................................................ + +#endif // _DBA_COREDATAACCESS_COMMANDCONTAINER_HXX_ + + diff --git a/dbaccess/source/core/dataaccess/commanddefinition.cxx b/dbaccess/source/core/dataaccess/commanddefinition.cxx new file mode 100644 index 000000000000..b3b41ff903b8 --- /dev/null +++ b/dbaccess/source/core/dataaccess/commanddefinition.cxx @@ -0,0 +1,179 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#include "commanddefinition.hxx" +#include "apitools.hxx" +#include "dbastrings.hrc" +#include "module_dba.hxx" + +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> + +#include <tools/debug.hxx> +#include <comphelper/sequence.hxx> +#include <comphelper/componentcontext.hxx> + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::osl; +using namespace ::comphelper; +using namespace ::cppu; + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + +//========================================================================== +//= OCommandDefinition +//========================================================================== +extern "C" void SAL_CALL createRegistryInfo_OCommandDefinition() +{ + static ::dba::OAutoRegistration< OCommandDefinition > aAutoRegistration; +} + +//-------------------------------------------------------------------------- +DBG_NAME(OCommandDefinition) +//-------------------------------------------------------------------------- +void OCommandDefinition::registerProperties() +{ + OCommandDefinition_Impl& rCommandDefinition( getCommandDefinition() ); + registerProperty(PROPERTY_COMMAND, PROPERTY_ID_COMMAND, PropertyAttribute::BOUND, + &rCommandDefinition.m_sCommand, ::getCppuType(&rCommandDefinition.m_sCommand)); + + registerProperty(PROPERTY_ESCAPE_PROCESSING, PROPERTY_ID_ESCAPE_PROCESSING, PropertyAttribute::BOUND, + &rCommandDefinition.m_bEscapeProcessing, ::getBooleanCppuType()); + + registerProperty(PROPERTY_UPDATE_TABLENAME, PROPERTY_ID_UPDATE_TABLENAME, PropertyAttribute::BOUND, + &rCommandDefinition.m_sUpdateTableName, ::getCppuType(&rCommandDefinition.m_sUpdateTableName)); + + registerProperty(PROPERTY_UPDATE_SCHEMANAME, PROPERTY_ID_UPDATE_SCHEMANAME, PropertyAttribute::BOUND, + &rCommandDefinition.m_sUpdateSchemaName, ::getCppuType(&rCommandDefinition.m_sUpdateSchemaName)); + + registerProperty(PROPERTY_UPDATE_CATALOGNAME, PROPERTY_ID_UPDATE_CATALOGNAME, PropertyAttribute::BOUND, + &rCommandDefinition.m_sUpdateCatalogName, ::getCppuType(&rCommandDefinition.m_sUpdateCatalogName)); + registerProperty(PROPERTY_LAYOUTINFORMATION, PROPERTY_ID_LAYOUTINFORMATION, PropertyAttribute::BOUND, + &rCommandDefinition.m_aLayoutInformation, ::getCppuType(&rCommandDefinition.m_aLayoutInformation)); +} + +//-------------------------------------------------------------------------- +OCommandDefinition::OCommandDefinition(const Reference< XMultiServiceFactory >& _xORB + ,const Reference< XInterface >& _rxContainer + ,const TContentPtr& _pImpl) + :OComponentDefinition(_xORB,_rxContainer,_pImpl,sal_False) +{ + DBG_CTOR(OCommandDefinition, NULL); + registerProperties(); +} +//-------------------------------------------------------------------------- +OCommandDefinition::~OCommandDefinition() +{ + DBG_DTOR(OCommandDefinition, NULL); +} + +//-------------------------------------------------------------------------- +OCommandDefinition::OCommandDefinition( const Reference< XInterface >& _rxContainer + ,const ::rtl::OUString& _rElementName + ,const Reference< XMultiServiceFactory >& _xORB + ,const TContentPtr& _pImpl) + :OComponentDefinition(_rxContainer,_rElementName,_xORB,_pImpl,sal_False) +{ + DBG_CTOR(OCommandDefinition, NULL); + registerProperties(); +} + +//-------------------------------------------------------------------------- +IMPLEMENT_IMPLEMENTATION_ID(OCommandDefinition); +IMPLEMENT_GETTYPES2(OCommandDefinition,OCommandDefinition_Base,OComponentDefinition); +IMPLEMENT_FORWARD_XINTERFACE2( OCommandDefinition,OComponentDefinition,OCommandDefinition_Base) +IMPLEMENT_PROPERTYCONTAINER_DEFAULTS2(OCommandDefinition,OCommandDefinition_PROP) +//-------------------------------------------------------------------------- +::rtl::OUString OCommandDefinition::getImplementationName_static( ) throw(RuntimeException) +{ + return ::rtl::OUString::createFromAscii("com.sun.star.comp.dba.OCommandDefinition"); +} + +//-------------------------------------------------------------------------- +::rtl::OUString SAL_CALL OCommandDefinition::getImplementationName( ) throw(RuntimeException) +{ + return getImplementationName_static(); +} + +//-------------------------------------------------------------------------- +Sequence< ::rtl::OUString > OCommandDefinition::getSupportedServiceNames_static( ) throw(RuntimeException) +{ + Sequence< ::rtl::OUString > aServices(3); + aServices.getArray()[0] = SERVICE_SDB_QUERYDEFINITION; + aServices.getArray()[1] = SERVICE_SDB_COMMAND_DEFINITION; + aServices.getArray()[2] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.ucb.Content")); + return aServices; +} + +//-------------------------------------------------------------------------- +Sequence< ::rtl::OUString > SAL_CALL OCommandDefinition::getSupportedServiceNames( ) throw(RuntimeException) +{ + return getSupportedServiceNames_static(); +} + +//------------------------------------------------------------------------------ +Reference< XInterface > OCommandDefinition::Create(const Reference< XComponentContext >& _rxContext) +{ + ::comphelper::ComponentContext aContext( _rxContext ); + return *(new OCommandDefinition( aContext.getLegacyServiceFactory(), NULL, TContentPtr( new OCommandDefinition_Impl ) ) ); +} + +// ----------------------------------------------------------------------------- +void SAL_CALL OCommandDefinition::rename( const ::rtl::OUString& newName ) throw (SQLException, ElementExistException, RuntimeException) +{ + try + { + sal_Int32 nHandle = PROPERTY_ID_NAME; + osl::ClearableGuard< osl::Mutex > aGuard(m_aMutex); + Any aOld = makeAny(m_pImpl->m_aProps.aTitle); + aGuard.clear(); + Any aNew = makeAny(newName); + fire(&nHandle, &aNew, &aOld, 1, sal_True ); + + m_pImpl->m_aProps.aTitle = newName; + fire(&nHandle, &aNew, &aOld, 1, sal_False ); + } + catch(const PropertyVetoException&) + { + throw ElementExistException(newName,*this); + } +} +// ----------------------------------------------------------------------------- +//........................................................................ +} // namespace dbaccess +//........................................................................ + diff --git a/dbaccess/source/core/dataaccess/commanddefinition.hxx b/dbaccess/source/core/dataaccess/commanddefinition.hxx new file mode 100644 index 000000000000..6d245324c831 --- /dev/null +++ b/dbaccess/source/core/dataaccess/commanddefinition.hxx @@ -0,0 +1,144 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 _DBA_COREDATAACESS_COMMANDDEFINITION_HXX_ +#define _DBA_COREDATAACESS_COMMANDDEFINITION_HXX_ + +#ifndef _DBA_CORE_COMMANDBASE_HXX_ +#include "commandbase.hxx" +#endif +#ifndef _COMPHELPER_PROPERTYCONTAINER_HXX_ +#include <comphelper/propertycontainer.hxx> +#endif +#ifndef _DBASHARED_APITOOLS_HXX_ +#include "apitools.hxx" +#endif +#ifndef _COMPHELPER_UNO3_HXX_ +#include <comphelper/uno3.hxx> +#endif +#ifndef _COM_SUN_STAR_SDBCX_XRENAME_HPP_ +#include <com/sun/star/sdbcx/XRename.hpp> +#endif +#ifndef _CPPUHELPER_IMPLBASE1_HXX_ +#include <cppuhelper/implbase1.hxx> +#endif +#ifndef _COMPHELPER_PROPERTY_ARRAY_HELPER_HXX_ +#include <comphelper/proparrhlp.hxx> +#endif +#ifndef _DBA_CORE_DATASETTINGS_HXX_ +#include "datasettings.hxx" +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_ +#include <com/sun/star/container/XNameAccess.hpp> +#endif +#ifndef DBA_CONTENTHELPER_HXX +#include "ContentHelper.hxx" +#endif +#ifndef DBA_COREDATAACESS_COMPONENTDEFINITION_HXX +#include "ComponentDefinition.hxx" +#endif + + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + +//========================================================================= +//= OCommandDefinition - a database "document" which describes a query +//========================================================================= + class OCommandDefinition_Impl : public OComponentDefinition_Impl + ,public OCommandBase + { + public: + }; + +typedef ::cppu::ImplHelper1 < ::com::sun::star::sdbcx::XRename + > OCommandDefinition_Base; +class OCommandDefinition; +typedef ::comphelper::OPropertyArrayUsageHelper< OCommandDefinition > + OCommandDefinition_PROP; + + +class OCommandDefinition :public OComponentDefinition + ,public OCommandDefinition_Base + ,public OCommandDefinition_PROP +{ +protected: + virtual ~OCommandDefinition(); + + OCommandDefinition(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& + ,const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _xParentContainer + ,const TContentPtr& _pImpl + ); + + inline const OCommandDefinition_Impl& getCommandDefinition() const { return dynamic_cast< const OCommandDefinition_Impl& >( *m_pImpl.get() ); } + inline OCommandDefinition_Impl& getCommandDefinition() { return dynamic_cast< OCommandDefinition_Impl& >( *m_pImpl.get() ); } + +public: + + OCommandDefinition( + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxContainer + ,const ::rtl::OUString& _rElementName + ,const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& + ,const TContentPtr& _pImpl + ); + +// com::sun::star::lang::XTypeProvider + DECLARE_TYPEPROVIDER( ); + +// ::com::sun::star::uno::XInterface + DECLARE_XINTERFACE( ) + +// ::com::sun::star::lang::XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw(::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::lang::XServiceInfo - static methods + static ::com::sun::star::uno::Sequence< ::rtl::OUString > getSupportedServiceNames_static(void) throw( ::com::sun::star::uno::RuntimeException ); + static ::rtl::OUString getImplementationName_static(void) throw( ::com::sun::star::uno::RuntimeException ); + static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL + Create(const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >&); + + // XRename + virtual void SAL_CALL rename( const ::rtl::OUString& newName ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::container::ElementExistException, ::com::sun::star::uno::RuntimeException); + + // OPropertySetHelper + DECLARE_PROPERTYCONTAINER_DEFAULTS( ); + +private: + // helper + void registerProperties(); +}; + +//........................................................................ +} // namespace dbaccess +//........................................................................ + +#endif // _DBA_COREDATAACESS_COMMANDDEFINITION_HXX_ + + diff --git a/dbaccess/source/core/dataaccess/connection.cxx b/dbaccess/source/core/dataaccess/connection.cxx new file mode 100644 index 000000000000..f543e2665a7e --- /dev/null +++ b/dbaccess/source/core/dataaccess/connection.cxx @@ -0,0 +1,946 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#include "connection.hxx" +#include "dbastrings.hrc" +#include "datasource.hxx" +#include "core_resource.hrc" +#include "core_resource.hxx" +#include "statement.hxx" +#include "preparedstatement.hxx" +#include "callablestatement.hxx" +#include "ContainerMediator.hxx" +#include "SingleSelectQueryComposer.hxx" +#include "querycomposer.hxx" +#include "sdbcoretools.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/sdb/CommandType.hpp> +#include <com/sun/star/sdbc/XDriverAccess.hpp> +#include <com/sun/star/sdbcx/XDataDefinitionSupplier.hpp> +#include <com/sun/star/reflection/XProxyFactory.hpp> +#include <com/sun/star/beans/NamedValue.hpp> +/** === end UNO includes === **/ +#include <connectivity/dbtools.hxx> +#include <connectivity/dbmetadata.hxx> +#include <connectivity/dbexception.hxx> +#include <tools/debug.hxx> +#include <tools/diagnose_ex.h> +#include <comphelper/extract.hxx> +#include <comphelper/uno3.hxx> +#include <comphelper/sequence.hxx> +#include <cppuhelper/typeprovider.hxx> +#include <rtl/logfile.hxx> + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdb::application; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::reflection; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::graphic; +using namespace ::osl; +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 +{ +//........................................................................ + +//========================================================================== +// XServiceInfo +//------------------------------------------------------------------------------ +rtl::OUString OConnection::getImplementationName( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getImplementationName" ); + return rtl::OUString::createFromAscii("com.sun.star.comp.dbaccess.Connection"); +} +//------------------------------------------------------------------------------ +sal_Bool OConnection::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::supportsService" ); + return findValue(getSupportedServiceNames(), _rServiceName, sal_True).getLength() != 0; +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > OConnection::getSupportedServiceNames( ) throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getSupportedServiceNames" ); + Sequence< ::rtl::OUString > aSupported = OConnectionWrapper::getSupportedServiceNames(); + + if ( 0 == findValue( aSupported, SERVICE_SDB_CONNECTION, sal_True ).getLength() ) + { + sal_Int32 nLen = aSupported.getLength(); + aSupported.realloc( nLen + 1 ); + aSupported[ nLen ] = SERVICE_SDB_CONNECTION; + } + + return aSupported; +} + +// XCloseable +//------------------------------------------------------------------------------ +void OConnection::close(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::close" ); + // being closed is the same as being disposed + dispose(); +} + +//------------------------------------------------------------------------------ +sal_Bool OConnection::isClosed(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::isClosed" ); + MutexGuard aGuard(m_aMutex); + return !m_xMasterConnection.is(); +} + +// XConnection +//------------------------------------------------------------------------------ +Reference< XStatement > OConnection::createStatement(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::createStatement" ); + MutexGuard aGuard(m_aMutex); + checkDisposed(); + + Reference< XStatement > xStatement; + Reference< XStatement > xMasterStatement = m_xMasterConnection->createStatement(); + if ( xMasterStatement.is() ) + { + xStatement = new OStatement(this, xMasterStatement); + m_aStatements.push_back(WeakReferenceHelper(xStatement)); + } + return xStatement; +} +//------------------------------------------------------------------------------ +Reference< XPreparedStatement > OConnection::prepareStatement(const rtl::OUString& sql) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::prepareStatement" ); + MutexGuard aGuard(m_aMutex); + checkDisposed(); + + // TODO convert the SQL to SQL the driver understands + Reference< XPreparedStatement > xStatement; + Reference< XPreparedStatement > xMasterStatement = m_xMasterConnection->prepareStatement(sql); + if ( xMasterStatement.is() ) + { + xStatement = new OPreparedStatement(this, xMasterStatement); + m_aStatements.push_back(WeakReferenceHelper(xStatement)); + } + return xStatement; +} + +//------------------------------------------------------------------------------ +Reference< XPreparedStatement > OConnection::prepareCall(const rtl::OUString& sql) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::prepareCall" ); + MutexGuard aGuard(m_aMutex); + checkDisposed(); + + Reference< XPreparedStatement > xStatement; + Reference< XPreparedStatement > xMasterStatement = m_xMasterConnection->prepareCall(sql); + if ( xMasterStatement.is() ) + { + xStatement = new OCallableStatement(this, xMasterStatement); + m_aStatements.push_back(WeakReferenceHelper(xStatement)); + } + return xStatement; +} + +//------------------------------------------------------------------------------ +rtl::OUString OConnection::nativeSQL(const rtl::OUString& sql) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::nativeSQL" ); + MutexGuard aGuard(m_aMutex); + checkDisposed(); + return m_xMasterConnection->nativeSQL(sql); +} + +//------------------------------------------------------------------------------ +void OConnection::setAutoCommit(sal_Bool autoCommit) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::setAutoCommit" ); + MutexGuard aGuard(m_aMutex); + checkDisposed(); + m_xMasterConnection->setAutoCommit(autoCommit); +} + +//------------------------------------------------------------------------------ +sal_Bool OConnection::getAutoCommit(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getAutoCommit" ); + MutexGuard aGuard(m_aMutex); + checkDisposed(); + return m_xMasterConnection->getAutoCommit(); +} + +//------------------------------------------------------------------------------ +void OConnection::commit(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::commit" ); + MutexGuard aGuard(m_aMutex); + checkDisposed(); + m_xMasterConnection->commit(); +} + +//------------------------------------------------------------------------------ +void OConnection::rollback(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::rollback" ); + MutexGuard aGuard(m_aMutex); + checkDisposed(); + m_xMasterConnection->rollback(); +} + +//------------------------------------------------------------------------------ +Reference< XDatabaseMetaData > OConnection::getMetaData(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getMetaData" ); + MutexGuard aGuard(m_aMutex); + checkDisposed(); + return m_xMasterConnection->getMetaData(); +} + +//------------------------------------------------------------------------------ +void OConnection::setReadOnly(sal_Bool readOnly) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::setReadOnly" ); + MutexGuard aGuard(m_aMutex); + checkDisposed(); + m_xMasterConnection->setReadOnly(readOnly); +} + +//------------------------------------------------------------------------------ +sal_Bool OConnection::isReadOnly(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::isReadOnly" ); + MutexGuard aGuard(m_aMutex); + checkDisposed(); + return m_xMasterConnection->isReadOnly(); +} + +//------------------------------------------------------------------------------ +void OConnection::setCatalog(const rtl::OUString& catalog) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::setCatalog" ); + MutexGuard aGuard(m_aMutex); + checkDisposed(); + m_xMasterConnection->setCatalog(catalog); +} + +//------------------------------------------------------------------------------ +rtl::OUString OConnection::getCatalog(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getCatalog" ); + MutexGuard aGuard(m_aMutex); + checkDisposed(); + return m_xMasterConnection->getCatalog(); +} + +//------------------------------------------------------------------------------ +void OConnection::setTransactionIsolation(sal_Int32 level) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::setTransactionIsolation" ); + MutexGuard aGuard(m_aMutex); + checkDisposed(); + m_xMasterConnection->setTransactionIsolation(level); +} + +//------------------------------------------------------------------------------ +sal_Int32 OConnection::getTransactionIsolation(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getTransactionIsolation" ); + MutexGuard aGuard(m_aMutex); + checkDisposed(); + return m_xMasterConnection->getTransactionIsolation(); +} + +//------------------------------------------------------------------------------ +Reference< XNameAccess > OConnection::getTypeMap(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getTypeMap" ); + MutexGuard aGuard(m_aMutex); + checkDisposed(); + return m_xMasterConnection->getTypeMap(); +} + +//------------------------------------------------------------------------------ +void OConnection::setTypeMap(const Reference< XNameAccess > & typeMap) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::setTypeMap" ); + MutexGuard aGuard(m_aMutex); + checkDisposed(); + m_xMasterConnection->setTypeMap(typeMap); +} +//========================================================================== +//= OConnection +//========================================================================== +DBG_NAME(OConnection) +//-------------------------------------------------------------------------- +OConnection::OConnection(ODatabaseSource& _rDB + , Reference< XConnection >& _rxMaster + , const Reference< XMultiServiceFactory >& _rxORB) + :OSubComponent(m_aMutex, static_cast< OWeakObject* >(&_rDB)) + // as the queries reroute their refcounting to us, this m_aMutex is okey. If the queries + // container would do it's own refcounting, it would have to aquire m_pMutex + // same for tables + ,m_aTableFilter(_rDB.m_pImpl->m_aTableFilter) + ,m_aTableTypeFilter(_rDB.m_pImpl->m_aTableTypeFilter) + ,m_aContext( _rxORB ) + ,m_xMasterConnection(_rxMaster) + ,m_pTables(NULL) + ,m_pViews(NULL) + ,m_aWarnings( Reference< XWarningsSupplier >( _rxMaster, UNO_QUERY ) ) + ,m_nInAppend(0) + ,m_bSupportsViews(sal_False) + ,m_bSupportsUsers(sal_False) + ,m_bSupportsGroups(sal_False) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::OConnection" ); + DBG_CTOR(OConnection,NULL); + osl_incrementInterlockedCount(&m_refCount); + + try + { + Reference< XProxyFactory > xProxyFactory( + _rxORB->createInstance(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.reflection.ProxyFactory"))),UNO_QUERY); + Reference<XAggregation> xAgg = xProxyFactory->createProxy(_rxMaster.get()); + setDelegation(xAgg,m_refCount); + DBG_ASSERT(m_xConnection.is(), "OConnection::OConnection : invalid master connection !"); + } + catch(const Exception&) + { + DBG_UNHANDLED_EXCEPTION(); + } + + m_xTableUIProvider = m_xTableUIProvider.query( m_xMasterConnection ); + + try + { + m_xQueries = new OQueryContainer(Reference< XNameContainer >(_rDB.getQueryDefinitions( ),UNO_QUERY), this,_rxORB, &m_aWarnings); + + sal_Bool bCase = sal_True; + Reference<XDatabaseMetaData> xMeta; + try + { + xMeta = getMetaData(); + bCase = xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers(); + } + catch(SQLException&) + { + } + Reference< XNameContainer > xTableDefinitions(_rDB.getTables(),UNO_QUERY); + m_pTables = new OTableContainer( *this, m_aMutex, this, bCase, xTableDefinitions, this, &m_aWarnings,m_nInAppend ); + + // check if we supports types + if ( xMeta.is() ) + { + Reference<XResultSet> xRes = xMeta->getTableTypes(); + if(xRes.is()) + { + ::rtl::OUString sView(RTL_CONSTASCII_USTRINGPARAM("VIEW")); + Reference<XRow> xRow(xRes,UNO_QUERY); + while(xRes->next()) + { + ::rtl::OUString sValue = xRow->getString(1); + if( !xRow->wasNull() && sValue == sView) + { + m_bSupportsViews = sal_True; + break; + } + } + } + // some dbs don't support this type so we should ask if a XViewsSupplier is supported + if(!m_bSupportsViews) + { + Reference< XViewsSupplier > xMaster(getMasterTables(),UNO_QUERY); + + if (xMaster.is() && xMaster->getViews().is()) + m_bSupportsViews = sal_True; + } + if(m_bSupportsViews) + { + m_pViews = new OViewContainer(*this, m_aMutex, this, bCase,this,&m_aWarnings,m_nInAppend); + m_pViews->addContainerListener(m_pTables); + m_pTables->addContainerListener(m_pViews); + } + m_bSupportsUsers = Reference< XUsersSupplier> (getMasterTables(),UNO_QUERY).is(); + m_bSupportsGroups = Reference< XGroupsSupplier> (getMasterTables(),UNO_QUERY).is(); + + impl_checkTableQueryNames_nothrow(); + } + } + catch(const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + osl_decrementInterlockedCount( &m_refCount ); +} + +//-------------------------------------------------------------------------- +OConnection::~OConnection() +{ + delete m_pTables; + delete m_pViews; + DBG_DTOR(OConnection,NULL); +} + + +// XWarningsSupplier +//-------------------------------------------------------------------------- +Any SAL_CALL OConnection::getWarnings() throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getWarnings" ); + MutexGuard aGuard(m_aMutex); + checkDisposed(); + return m_aWarnings.getWarnings(); +} + +//-------------------------------------------------------------------------- +void SAL_CALL OConnection::clearWarnings( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::clearWarnings" ); + MutexGuard aGuard(m_aMutex); + checkDisposed(); + m_aWarnings.clearWarnings(); +} + +//-------------------------------------------------------------------------- +namespace +{ + struct CompareTypeByName : public ::std::binary_function< Type, Type, bool > + { + bool operator() ( const Type& _rLHS, const Type& _rRHS ) const + { + return _rLHS.getTypeName() < _rRHS.getTypeName(); + } + }; + typedef ::std::set< Type, CompareTypeByName > TypeBag; + + void lcl_copyTypes( TypeBag& _out_rTypes, const Sequence< Type >& _rTypes ) + { + ::std::copy( _rTypes.getConstArray(), _rTypes.getConstArray() + _rTypes.getLength(), + ::std::insert_iterator< TypeBag >( _out_rTypes, _out_rTypes.begin() ) ); + } +} +// com::sun::star::lang::XTypeProvider +//-------------------------------------------------------------------------- +Sequence< Type > OConnection::getTypes() throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getTypes" ); + TypeBag aNormalizedTypes; + + lcl_copyTypes( aNormalizedTypes, OSubComponent::getTypes() ); + lcl_copyTypes( aNormalizedTypes, OConnection_Base::getTypes() ); + lcl_copyTypes( aNormalizedTypes, ::connectivity::OConnectionWrapper::getTypes() ); + + if ( !m_bSupportsViews ) + aNormalizedTypes.erase( XViewsSupplier::static_type() ); + if ( !m_bSupportsUsers ) + aNormalizedTypes.erase( XUsersSupplier::static_type() ); + if ( !m_bSupportsGroups ) + aNormalizedTypes.erase( XGroupsSupplier::static_type() ); + + Sequence< Type > aSupportedTypes( aNormalizedTypes.size() ); + ::std::copy( aNormalizedTypes.begin(), aNormalizedTypes.end(), aSupportedTypes.getArray() ); + return aSupportedTypes; +} + +//-------------------------------------------------------------------------- +Sequence< sal_Int8 > OConnection::getImplementationId() throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getImplementationId" ); + return getUnoTunnelImplementationId(); +} + +// com::sun::star::uno::XInterface +//-------------------------------------------------------------------------- +Any OConnection::queryInterface( const Type & rType ) throw (RuntimeException) +{ + if ( !m_bSupportsViews && rType.equals( XViewsSupplier::static_type() ) ) + return Any(); + else if ( !m_bSupportsUsers && rType.equals( XUsersSupplier::static_type() ) ) + return Any(); + else if ( !m_bSupportsGroups && rType.equals( XGroupsSupplier::static_type() ) ) + return Any(); + Any aReturn = OSubComponent::queryInterface( rType ); + if (!aReturn.hasValue()) + { + aReturn = OConnection_Base::queryInterface( rType ); + if (!aReturn.hasValue()) + aReturn = OConnectionWrapper::queryInterface( rType ); + } + return aReturn; +} + +//-------------------------------------------------------------------------- +void OConnection::acquire() throw () +{ + // include this one when you want to see who calls it (call graph) + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::acquire" ); + OSubComponent::acquire(); +} + +//-------------------------------------------------------------------------- +void OConnection::release() throw () +{ + // include this one when you want to see who calls it (call graph) + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::release" ); + OSubComponent::release(); +} + +// OSubComponent +//------------------------------------------------------------------------------ +void OConnection::disposing() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::disposing" ); + MutexGuard aGuard(m_aMutex); + + OSubComponent::disposing(); + OConnectionWrapper::disposing(); + + OWeakRefArrayIterator aEnd = m_aStatements.end(); + for (OWeakRefArrayIterator i = m_aStatements.begin(); aEnd != i; ++i) + { + Reference<XComponent> xComp(i->get(),UNO_QUERY); + ::comphelper::disposeComponent(xComp); + } + m_aStatements.clear(); + m_xMasterTables = NULL; + + if(m_pTables) + m_pTables->dispose(); + if(m_pViews) + m_pViews->dispose(); + + ::comphelper::disposeComponent(m_xQueries); + + OWeakRefArrayIterator aComposerEnd = m_aComposers.end(); + for (OWeakRefArrayIterator j = m_aComposers.begin(); aComposerEnd != j; ++j) + { + Reference<XComponent> xComp(j->get(),UNO_QUERY); + ::comphelper::disposeComponent(xComp); + } + + m_aComposers.clear(); + + try + { + if (m_xMasterConnection.is()) + m_xMasterConnection->close(); + } + catch(Exception) + { + } + m_xMasterConnection = NULL; +} + +// XChild +//------------------------------------------------------------------------------ +Reference< XInterface > OConnection::getParent(void) throw( RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getParent" ); + MutexGuard aGuard(m_aMutex); + checkDisposed(); + return m_xParent; +} + +//------------------------------------------------------------------------------ +void OConnection::setParent(const Reference< XInterface > & /*Parent*/) throw( NoSupportException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::setParent" ); + throw NoSupportException(); +} + +// XSQLQueryComposerFactory +//------------------------------------------------------------------------------ +Reference< XSQLQueryComposer > OConnection::createQueryComposer(void) throw( RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::createQueryComposer" ); + MutexGuard aGuard(m_aMutex); + checkDisposed(); + + // Reference< XNumberFormatsSupplier > xSupplier = pParent->getNumberFormatsSupplier(); + Reference< XSQLQueryComposer > xComposer( new OQueryComposer( this ) ); + m_aComposers.push_back(WeakReferenceHelper(xComposer)); + return xComposer; +} +// ----------------------------------------------------------------------------- +void OConnection::impl_fillTableFilter() +{ + Reference<XPropertySet> xProp(getParent(),UNO_QUERY); + if ( xProp.is() ) + { + xProp->getPropertyValue(PROPERTY_TABLEFILTER) >>= m_aTableFilter; + xProp->getPropertyValue(PROPERTY_TABLETYPEFILTER) >>= m_aTableTypeFilter; + } +} + +// ----------------------------------------------------------------------------- +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 && !m_pTables->isInitialized()) + { + impl_fillTableFilter(); + // check if our "master connection" can supply tables + getMasterTables(); + + if (m_xMasterTables.is() && m_xMasterTables->getTables().is()) + { // yes -> wrap them + m_pTables->construct(m_xMasterTables->getTables(),m_aTableFilter, m_aTableTypeFilter); + } + else + { // no -> use an own container + m_pTables->construct(m_aTableFilter, m_aTableTypeFilter); + } + } + } + else if ( _rToBeRefreshed == Reference< XNameAccess >(m_pViews) ) + { + if (m_pViews && !m_pViews->isInitialized()) + { + impl_fillTableFilter(); + // check if our "master connection" can supply tables + Reference< XViewsSupplier > xMaster(getMasterTables(),UNO_QUERY); + + if (xMaster.is() && xMaster->getViews().is()) + m_pViews->construct(xMaster->getViews(),m_aTableFilter, m_aTableTypeFilter); + else + m_pViews->construct(m_aTableFilter, m_aTableTypeFilter); + } + } +} +// ----------------------------------------------------------------------------- + +// XTablesSupplier +//------------------------------------------------------------------------------ +Reference< XNameAccess > OConnection::getTables() throw( RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getTables" ); + MutexGuard aGuard(m_aMutex); + checkDisposed(); + + refresh(m_pTables); + + return m_pTables; +} +// ----------------------------------------------------------------------------- +Reference< XNameAccess > SAL_CALL OConnection::getViews( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getViews" ); + MutexGuard aGuard(m_aMutex); + checkDisposed(); + + refresh(m_pViews); + + return m_pViews; +} +// XQueriesSupplier +//------------------------------------------------------------------------------ +Reference< XNameAccess > OConnection::getQueries(void) throw( RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getQueries" ); + MutexGuard aGuard(m_aMutex); + checkDisposed(); + + return m_xQueries; +} + +// ::com::sun::star::sdb::XCommandPreparation +//------------------------------------------------------------------------------ +Reference< XPreparedStatement > SAL_CALL OConnection::prepareCommand( const ::rtl::OUString& command, sal_Int32 commandType ) throw(::com::sun::star::sdbc::SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::prepareCommand" ); + MutexGuard aGuard(m_aMutex); + checkDisposed(); + + rtl::OUString aStatement; + switch (commandType) + { + case CommandType::TABLE: + { + aStatement = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SELECT * FROM ")); + + ::rtl::OUString sCatalog, sSchema, sTable; + ::dbtools::qualifiedNameComponents( getMetaData(), command, sCatalog, sSchema, sTable, ::dbtools::eInDataManipulation ); + aStatement += ::dbtools::composeTableNameForSelect( this, sCatalog, sSchema, sTable ); + } + break; + case CommandType::QUERY: + if ( m_xQueries->hasByName(command) ) + { + Reference< XPropertySet > xQuery(m_xQueries->getByName(command),UNO_QUERY); + xQuery->getPropertyValue(PROPERTY_COMMAND) >>= aStatement; + } + break; + default: + aStatement = command; + } + // TODO EscapeProcessing + return prepareStatement(aStatement); +} +// ----------------------------------------------------------------------------- +Reference< XInterface > SAL_CALL OConnection::createInstance( const ::rtl::OUString& _sServiceSpecifier ) throw (Exception, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::createInstance" ); + Reference< XServiceInfo > xRet; + if ( ( SERVICE_NAME_SINGLESELECTQUERYCOMPOSER == _sServiceSpecifier ) + || ( _sServiceSpecifier.equalsAscii( "com.sun.star.sdb.SingleSelectQueryAnalyzer" ) ) + ) + { + 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); +} +// ----------------------------------------------------------------------------- +Reference< XInterface > SAL_CALL OConnection::createInstanceWithArguments( const ::rtl::OUString& _sServiceSpecifier, const Sequence< Any >& /*Arguments*/ ) throw (Exception, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::createInstanceWithArguments" ); + return createInstance(_sServiceSpecifier); +} +// ----------------------------------------------------------------------------- +Sequence< ::rtl::OUString > SAL_CALL OConnection::getAvailableServiceNames( ) throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getAvailableServiceNames" ); + Sequence< ::rtl::OUString > aRet(1); + aRet[0] = SERVICE_NAME_SINGLESELECTQUERYCOMPOSER; + return aRet; +} +// ----------------------------------------------------------------------------- +Reference< XTablesSupplier > OConnection::getMasterTables() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getMasterTables" ); +// check if out "master connection" can supply tables + if(!m_xMasterTables.is()) + { + try + { + Reference<XDatabaseMetaData> xMeta = getMetaData(); + if ( xMeta.is() ) + m_xMasterTables = ::dbtools::getDataDefinitionByURLAndConnection( xMeta->getURL(), m_xMasterConnection, m_aContext.getLegacyServiceFactory() ); + } + catch(SQLException&) + { + } + } + return m_xMasterTables; +} +// ----------------------------------------------------------------------------- +// XUsersSupplier +Reference< XNameAccess > SAL_CALL OConnection::getUsers( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getUsers" ); + MutexGuard aGuard(m_aMutex); + checkDisposed(); + + Reference<XUsersSupplier> xUsr(getMasterTables(),UNO_QUERY); + return xUsr.is() ? xUsr->getUsers() : Reference< XNameAccess >(); +} +// ----------------------------------------------------------------------------- +// XGroupsSupplier +Reference< XNameAccess > SAL_CALL OConnection::getGroups( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getGroups" ); + MutexGuard aGuard(m_aMutex); + checkDisposed(); + Reference<XGroupsSupplier> xGrp(getMasterTables(),UNO_QUERY); + return xGrp.is() ? xGrp->getGroups() : Reference< XNameAccess >(); +} + +// ----------------------------------------------------------------------------- +void OConnection::impl_loadConnectionTools_throw() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::impl_loadConnectionTools_throw" ); + Sequence< Any > aArguments( 1 ); + aArguments[0] <<= NamedValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Connection" ) ), makeAny( Reference< XConnection >( this ) ) ); + + if ( !m_aContext.createComponentWithArguments( "com.sun.star.sdb.tools.ConnectionTools", aArguments, m_xConnectionTools ) ) + throw RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "service not registered: com.sun.star.sdb.tools.ConnectionTools" ) ), *this ); +} + +// ----------------------------------------------------------------------------- +Reference< XTableName > SAL_CALL OConnection::createTableName( ) throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::createTableName" ); + MutexGuard aGuard(m_aMutex); + checkDisposed(); + impl_loadConnectionTools_throw(); + + return m_xConnectionTools->createTableName(); +} + +// ----------------------------------------------------------------------------- +Reference< XObjectNames > SAL_CALL OConnection::getObjectNames( ) throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getObjectNames" ); + MutexGuard aGuard(m_aMutex); + checkDisposed(); + impl_loadConnectionTools_throw(); + + return m_xConnectionTools->getObjectNames(); +} + +// ----------------------------------------------------------------------------- +Reference< XDataSourceMetaData > SAL_CALL OConnection::getDataSourceMetaData( ) throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getDataSourceMetaData" ); + MutexGuard aGuard(m_aMutex); + checkDisposed(); + impl_loadConnectionTools_throw(); + + return m_xConnectionTools->getDataSourceMetaData(); +} +// ----------------------------------------------------------------------------- +Reference< ::com::sun::star::container::XNameAccess > SAL_CALL OConnection::getFieldsByCommandDescriptor( ::sal_Int32 commandType, const ::rtl::OUString& command, ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent >& keepFieldsAlive ) throw (::com::sun::star::sdbc::SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getFieldsByCommandDescriptor" ); + MutexGuard aGuard(m_aMutex); + checkDisposed(); + impl_loadConnectionTools_throw(); + + return m_xConnectionTools->getFieldsByCommandDescriptor(commandType,command,keepFieldsAlive); +} +//-------------------------------------------------------------------- +Reference< XSingleSelectQueryComposer > SAL_CALL OConnection::getComposer( ::sal_Int32 commandType, const ::rtl::OUString& command ) throw (::com::sun::star::uno::RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getComposer" ); + MutexGuard aGuard(m_aMutex); + checkDisposed(); + impl_loadConnectionTools_throw(); + + return m_xConnectionTools->getComposer(commandType,command); +} + +// ----------------------------------------------------------------------------- +void OConnection::impl_checkTableQueryNames_nothrow() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::impl_checkTableQueryNames_nothrow" ); + DatabaseMetaData aMeta( static_cast< XConnection* >( this ) ); + if ( !aMeta.supportsSubqueriesInFrom() ) + // nothing to do + return; + + try + { + Reference< XNameAccess > xTables( getTables() ); + Sequence< ::rtl::OUString > aTableNames( xTables->getElementNames() ); + ::std::set< ::rtl::OUString > aSortedTableNames( aTableNames.getConstArray(), aTableNames.getConstArray() + aTableNames.getLength() ); + + Reference< XNameAccess > xQueries( getQueries() ); + Sequence< ::rtl::OUString > aQueryNames( xQueries->getElementNames() ); + + for ( const ::rtl::OUString* pQueryName = aQueryNames.getConstArray(); + pQueryName != aQueryNames.getConstArray() + aQueryNames.getLength(); + ++pQueryName + ) + { + if ( aSortedTableNames.find( *pQueryName ) != aSortedTableNames.end() ) + { + ::rtl::OUString sConflictWarning( DBACORE_RESSTRING( RID_STR_CONFLICTING_NAMES ) ); + m_aWarnings.appendWarning( sConflictWarning, "01SB0", *this ); + } + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } +} + +// ----------------------------------------------------------------------------- +Reference< XGraphic > SAL_CALL OConnection::getTableIcon( const ::rtl::OUString& _TableName, ::sal_Int32 _ColorMode ) throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getTableIcon" ); + Reference< XGraphic > xReturn; + + // ask our aggregate + if ( m_xTableUIProvider.is() ) + xReturn = m_xTableUIProvider->getTableIcon( _TableName, _ColorMode ); + + // ask ourself + // well, we don't have own functionality here ... + // In the future, we might decide to delegate the complete handling to this interface. + // In this case, we would need to load the icon here. + + return xReturn; +} + +// ----------------------------------------------------------------------------- +Reference< XInterface > SAL_CALL OConnection::getTableEditor( const Reference< XDatabaseDocumentUI >& _DocumentUI, const ::rtl::OUString& _TableName ) throw (IllegalArgumentException, WrappedTargetException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getTableEditor" ); + Reference< XInterface > xReturn; + + // ask our aggregate + if ( m_xTableUIProvider.is() ) + xReturn = m_xTableUIProvider->getTableEditor( _DocumentUI, _TableName ); + + // ask ourself + // well, we don't have own functionality here ... + // In the future, we might decide to delegate the complete handling to this interface. + // In this case, we would need to instantiate an css.sdb.TableDesign here. + + return xReturn; +} + + +//........................................................................ +} // namespace dbaccess +//........................................................................ + diff --git a/dbaccess/source/core/dataaccess/connection.hxx b/dbaccess/source/core/dataaccess/connection.hxx new file mode 100644 index 000000000000..eb80cc2fc7db --- /dev/null +++ b/dbaccess/source/core/dataaccess/connection.hxx @@ -0,0 +1,252 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 _DBA_CORE_CONNECTION_HXX_ +#define _DBA_CORE_CONNECTION_HXX_ + +#include "apitools.hxx" +#include "querycontainer.hxx" +#include "tablecontainer.hxx" +#include "viewcontainer.hxx" +#include "RefreshListener.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/container/XChild.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/sdb/XSQLQueryComposerFactory.hpp> +#include <com/sun/star/sdb/XCommandPreparation.hpp> +#include <com/sun/star/sdbcx/XTablesSupplier.hpp> +#include <com/sun/star/sdbcx/XViewsSupplier.hpp> +#include <com/sun/star/sdbcx/XUsersSupplier.hpp> +#include <com/sun/star/sdbcx/XGroupsSupplier.hpp> +#include <com/sun/star/sdb/XQueriesSupplier.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/sdb/tools/XConnectionTools.hpp> +#include <com/sun/star/sdb/application/XTableUIProvider.hpp> +/** === end UNO includes === **/ + +#if ! defined(INCLUDED_COMPHELPER_IMPLBASE_VAR_HXX_14) +#define INCLUDED_COMPHELPER_IMPLBASE_VAR_HXX_14 +#define COMPHELPER_IMPLBASE_INTERFACE_NUMBER 14 +#include <comphelper/implbase_var.hxx> +#endif +#include <comphelper/componentcontext.hxx> +#include <comphelper/stl_types.hxx> +#include <connectivity/ConnectionWrapper.hxx> +#include <connectivity/warningscontainer.hxx> + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + +//========================================================================== +//========================================================================== +typedef ::comphelper::ImplHelper14 < ::com::sun::star::container::XChild + , ::com::sun::star::sdbcx::XTablesSupplier + , ::com::sun::star::sdbcx::XViewsSupplier + , ::com::sun::star::sdbc::XConnection + , ::com::sun::star::sdbc::XWarningsSupplier + , ::com::sun::star::sdb::XQueriesSupplier + , ::com::sun::star::sdb::XSQLQueryComposerFactory + , ::com::sun::star::sdb::XCommandPreparation + , ::com::sun::star::lang::XServiceInfo + , ::com::sun::star::lang::XMultiServiceFactory + , ::com::sun::star::sdbcx::XUsersSupplier + , ::com::sun::star::sdbcx::XGroupsSupplier + , ::com::sun::star::sdb::tools::XConnectionTools + , ::com::sun::star::sdb::application::XTableUIProvider + > OConnection_Base; + +class ODatabaseSource; +//========================================================================== +//= OConnection +//========================================================================== +class OConnection :public ::comphelper::OBaseMutex + ,public OSubComponent + ,public ::connectivity::OConnectionWrapper + ,public OConnection_Base + ,public IRefreshListener +{ +protected: + ::com::sun::star::uno::Reference< ::com::sun::star::sdbcx::XTablesSupplier > + m_xMasterTables; // just to avoid the recreation of the catalog + OWeakRefArray m_aStatements; + ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > + m_xQueries; + OWeakRefArray m_aComposers; + + // the filter as set on the parent data link at construction of the connection + ::com::sun::star::uno::Sequence< ::rtl::OUString > m_aTableFilter; + ::com::sun::star::uno::Sequence< ::rtl::OUString > m_aTableTypeFilter; + ::comphelper::ComponentContext m_aContext; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection > m_xMasterConnection; + ::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; + ::dbtools::WarningsContainer m_aWarnings; + oslInterlockedCount m_nInAppend; + sal_Bool m_bSupportsViews; // true when the getTableTypes return "VIEW" as type + sal_Bool m_bSupportsUsers; + sal_Bool m_bSupportsGroups; + +protected: + virtual ~OConnection(); +public: + OConnection(ODatabaseSource& _rDB + ,::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _rxMaster + ,const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB); + +// com::sun::star::lang::XTypeProvider + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes() throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() throw (::com::sun::star::uno::RuntimeException); + +// com::sun::star::uno::XInterface + virtual ::com::sun::star::uno::Any SAL_CALL queryInterface( const ::com::sun::star::uno::Type & rType ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL acquire() throw( ); + virtual void SAL_CALL release() throw( ); + +// OComponentHelper + virtual void SAL_CALL disposing(void); + +// ::com::sun::star::container::XChild + virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL getParent( ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setParent( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& Parent ) throw(::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::sdbcx::XTablesSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > SAL_CALL getTables( ) throw(::com::sun::star::uno::RuntimeException); +// ::com::sun::star::sdbcx::XViewsSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > SAL_CALL getViews( ) throw(::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::sdb::XQueriesSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > SAL_CALL getQueries( ) throw(::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::sdb::XSQLQueryComposerFactory + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XSQLQueryComposer > SAL_CALL createQueryComposer( ) throw(::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::sdb::XCommandPreparation + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XPreparedStatement > SAL_CALL prepareCommand( const ::rtl::OUString& command, sal_Int32 commandType ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::sdbc::XWarningsSupplier + virtual ::com::sun::star::uno::Any SAL_CALL getWarnings( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL clearWarnings( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::lang::XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw(::com::sun::star::uno::RuntimeException); + +// XConnection + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XStatement > SAL_CALL createStatement( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XPreparedStatement > SAL_CALL prepareStatement( const ::rtl::OUString& sql ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XPreparedStatement > SAL_CALL prepareCall( const ::rtl::OUString& sql ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL nativeSQL( const ::rtl::OUString& sql ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setAutoCommit( sal_Bool autoCommit ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL getAutoCommit( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL commit( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL rollback( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isClosed( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XDatabaseMetaData > SAL_CALL getMetaData( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setReadOnly( sal_Bool readOnly ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isReadOnly( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setCatalog( const ::rtl::OUString& catalog ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getCatalog( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setTransactionIsolation( sal_Int32 level ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getTransactionIsolation( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > SAL_CALL getTypeMap( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setTypeMap( const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& typeMap ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::sdbc::XCloseable + virtual void SAL_CALL close( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // XMultiServiceFactory + virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL createInstance( const ::rtl::OUString& aServiceSpecifier ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL createInstanceWithArguments( const ::rtl::OUString& ServiceSpecifier, const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& Arguments ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getAvailableServiceNames( ) throw (::com::sun::star::uno::RuntimeException); + + // XUsersSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > SAL_CALL getUsers( ) throw(::com::sun::star::uno::RuntimeException); + // XGroupsSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > SAL_CALL getGroups( ) throw(::com::sun::star::uno::RuntimeException); + + // XConnectionTools + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdb::tools::XTableName > SAL_CALL createTableName( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdb::tools::XObjectNames > SAL_CALL getObjectNames( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdb::tools::XDataSourceMetaData > SAL_CALL getDataSourceMetaData( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > SAL_CALL getFieldsByCommandDescriptor( ::sal_Int32 commandType, const ::rtl::OUString& command, ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent >& keepFieldsAlive ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XSingleSelectQueryComposer > SAL_CALL getComposer( ::sal_Int32 commandType, const ::rtl::OUString& command ) throw (::com::sun::star::uno::RuntimeException); + + // XTableUIProvider + virtual ::com::sun::star::uno::Reference< ::com::sun::star::graphic::XGraphic > SAL_CALL getTableIcon( const ::rtl::OUString& TableName, ::sal_Int32 ColorMode ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL getTableEditor( const ::com::sun::star::uno::Reference< ::com::sun::star::sdb::application::XDatabaseDocumentUI >& DocumentUI, const ::rtl::OUString& TableName ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + + // IRefreshListener + virtual void refresh(const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& _rToBeRefreshed); + +protected: + inline void checkDisposed() throw (::com::sun::star::lang::DisposedException) + { + if ( rBHelper.bDisposed || !m_xConnection.is() ) + throw ::com::sun::star::lang::DisposedException(); + } + + ::com::sun::star::uno::Reference< ::com::sun::star::sdbcx::XTablesSupplier > getMasterTables(); + +private: + /** checks whether or not there are naming conflicts between tables and queries + */ + void impl_checkTableQueryNames_nothrow(); + + /** loads the XConnectionTools implementation which we forward the respective functionality to + + @throws ::com::sun::star::uno::RuntimeException + if the implementation cannot be loaded + + @postcond + m_xConnectionTools is nol <NULL/> + */ + void impl_loadConnectionTools_throw(); + + /** reads the table filter and table type filter from the datasourfce + */ + void impl_fillTableFilter(); +}; + +//........................................................................ +} // namespace dbaccess +//........................................................................ + +#endif // _DBA_CORE_CONNECTION_HXX_ + + diff --git a/dbaccess/source/core/dataaccess/dataaccessdescriptor.cxx b/dbaccess/source/core/dataaccess/dataaccessdescriptor.cxx new file mode 100644 index 000000000000..ad5078825a16 --- /dev/null +++ b/dbaccess/source/core/dataaccess/dataaccessdescriptor.cxx @@ -0,0 +1,348 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#include "dbastrings.hrc" +#include "module_dba.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/sdb/CommandType.hpp> +#include <com/sun/star/sdbc/XConnection.hpp> +#include <com/sun/star/sdbc/XResultSet.hpp> +#include <com/sun/star/sdb/XDataAccessDescriptorFactory.hpp> +/** === end UNO includes === **/ + +#include <comphelper/broadcasthelper.hxx> +#include <comphelper/componentcontext.hxx> +#include <comphelper/proparrhlp.hxx> +#include <comphelper/propertycontainer.hxx> +#include <comphelper/uno3.hxx> +#include <cppuhelper/implbase1.hxx> +#include <cppuhelper/implbase2.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::lang::XServiceInfo; + using ::com::sun::star::lang::XMultiServiceFactory; + using ::com::sun::star::beans::XPropertySetInfo; + using ::com::sun::star::beans::Property; + using ::com::sun::star::sdbc::XConnection; + using ::com::sun::star::sdbc::XResultSet; + using ::com::sun::star::sdb::XDataAccessDescriptorFactory; + using ::com::sun::star::beans::XPropertySet; + using ::com::sun::star::uno::XComponentContext; + using ::com::sun::star::beans::PropertyValue; + /** === end UNO using === **/ + + namespace PropertyAttribute = ::com::sun::star::beans::PropertyAttribute; + namespace CommandType = ::com::sun::star::sdb::CommandType; + + //==================================================================== + //= DataAccessDescriptor + //==================================================================== + typedef ::comphelper::OMutexAndBroadcastHelper DataAccessDescriptor_MutexBase; + + typedef ::cppu::WeakImplHelper1 < XServiceInfo + > DataAccessDescriptor_TypeBase; + + typedef ::comphelper::OPropertyContainer DataAccessDescriptor_PropertyBase; + + class DataAccessDescriptor :public DataAccessDescriptor_MutexBase + ,public DataAccessDescriptor_TypeBase + ,public DataAccessDescriptor_PropertyBase + ,public ::comphelper::OPropertyArrayUsageHelper< DataAccessDescriptor > + { + public: + DataAccessDescriptor( const ::comphelper::ComponentContext& _rContext ); + + // UNO + DECLARE_XINTERFACE() + DECLARE_XTYPEPROVIDER() + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw (RuntimeException); + virtual ::sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (RuntimeException); + virtual Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw (RuntimeException); + + protected: + ~DataAccessDescriptor(); + + protected: + // XPropertySet + virtual Reference< XPropertySetInfo > SAL_CALL getPropertySetInfo() throw(RuntimeException); + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(); + + // OPropertyArrayUsageHelper + virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const; + + private: + ::comphelper::ComponentContext m_aContext; + + // </properties> + ::rtl::OUString m_sDataSourceName; + ::rtl::OUString m_sDatabaseLocation; + ::rtl::OUString m_sConnectionResource; + Sequence< PropertyValue > m_aConnectionInfo; + Reference< XConnection > m_xActiveConnection; + ::rtl::OUString m_sCommand; + sal_Int32 m_nCommandType; + ::rtl::OUString m_sFilter; + ::rtl::OUString m_sOrder; + ::rtl::OUString m_sHavingClause; + ::rtl::OUString m_sGroupBy; + sal_Bool m_bEscapeProcessing; + Reference< XResultSet > m_xResultSet; + Sequence< Any > m_aSelection; + sal_Bool m_bBookmarkSelection; + ::rtl::OUString m_sColumnName; + Reference< XPropertySet > m_xColumn; + // </properties> + }; + +#define REGISTER_PROPERTY( propname, member ) \ + registerProperty( PROPERTY_##propname, PROPERTY_ID_##propname, PropertyAttribute::BOUND, &member, ::getCppuType( &member ) ) + + //-------------------------------------------------------------------- + DataAccessDescriptor::DataAccessDescriptor( const ::comphelper::ComponentContext& _rContext ) + :DataAccessDescriptor_MutexBase() + ,DataAccessDescriptor_TypeBase() + ,DataAccessDescriptor_PropertyBase( m_aBHelper ) + ,m_aContext( _rContext ) + ,m_sDataSourceName() + ,m_sDatabaseLocation() + ,m_sConnectionResource() + ,m_aConnectionInfo() + ,m_xActiveConnection() + ,m_sCommand() + ,m_nCommandType( CommandType::COMMAND ) + ,m_sFilter() + ,m_sOrder() + ,m_sHavingClause() + ,m_sGroupBy() + ,m_bEscapeProcessing( sal_True ) + ,m_xResultSet() + ,m_aSelection() + ,m_bBookmarkSelection( sal_True ) + ,m_sColumnName() + ,m_xColumn() + { + REGISTER_PROPERTY( DATASOURCENAME, m_sDataSourceName ); + REGISTER_PROPERTY( DATABASE_LOCATION, m_sDatabaseLocation ); + REGISTER_PROPERTY( CONNECTION_RESOURCE, m_sConnectionResource ); + REGISTER_PROPERTY( CONNECTION_INFO, m_aConnectionInfo ); + REGISTER_PROPERTY( ACTIVE_CONNECTION, m_xActiveConnection ); + REGISTER_PROPERTY( COMMAND, m_sCommand ); + REGISTER_PROPERTY( COMMAND_TYPE, m_nCommandType ); + REGISTER_PROPERTY( FILTER, m_sFilter ); + REGISTER_PROPERTY( ORDER, m_sOrder ); + REGISTER_PROPERTY( HAVING_CLAUSE, m_sHavingClause ); + REGISTER_PROPERTY( GROUP_BY, m_sGroupBy ); + REGISTER_PROPERTY( ESCAPE_PROCESSING, m_bEscapeProcessing ); + REGISTER_PROPERTY( RESULT_SET, m_xResultSet ); + REGISTER_PROPERTY( SELECTION, m_aSelection ); + REGISTER_PROPERTY( BOOKMARK_SELECTION, m_bBookmarkSelection ); + REGISTER_PROPERTY( COLUMN_NAME, m_sColumnName ); + REGISTER_PROPERTY( COLUMN, m_xColumn ); + } + + //-------------------------------------------------------------------- + DataAccessDescriptor::~DataAccessDescriptor() + { + } + + //-------------------------------------------------------------------- + IMPLEMENT_FORWARD_XINTERFACE2( DataAccessDescriptor, DataAccessDescriptor_TypeBase, DataAccessDescriptor_PropertyBase ); + + //-------------------------------------------------------------------- + IMPLEMENT_FORWARD_XTYPEPROVIDER2( DataAccessDescriptor, DataAccessDescriptor_TypeBase, DataAccessDescriptor_PropertyBase ); + + //-------------------------------------------------------------------- + ::rtl::OUString SAL_CALL DataAccessDescriptor::getImplementationName() throw (RuntimeException) + { + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.dba.DataAccessDescriptor" ) ); + } + + //-------------------------------------------------------------------- + ::sal_Bool SAL_CALL DataAccessDescriptor::supportsService( const ::rtl::OUString& rServiceName ) throw (RuntimeException) + { + Sequence< ::rtl::OUString > aServices( getSupportedServiceNames() ); + const ::rtl::OUString* pStart = aServices.getConstArray(); + const ::rtl::OUString* pEnd = aServices.getConstArray() + aServices.getLength(); + return ::std::find( pStart, pEnd, rServiceName ) != pEnd; + } + + //-------------------------------------------------------------------- + Sequence< ::rtl::OUString > SAL_CALL DataAccessDescriptor::getSupportedServiceNames( ) throw (RuntimeException) + { + Sequence< ::rtl::OUString > aServices(1); + aServices[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sdb.DataAccessDescriptor" ) ); + return aServices; + } + + //------------------------------------------------------------------------- + Reference< XPropertySetInfo > SAL_CALL DataAccessDescriptor::getPropertySetInfo() throw(RuntimeException) + { + Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) ); + return xInfo; + } + + //------------------------------------------------------------------------- + ::cppu::IPropertyArrayHelper& DataAccessDescriptor::getInfoHelper() + { + return *getArrayHelper(); + } + + //------------------------------------------------------------------------------ + ::cppu::IPropertyArrayHelper* DataAccessDescriptor::createArrayHelper( ) const + { + Sequence< Property > aProps; + describeProperties( aProps ); + return new ::cppu::OPropertyArrayHelper( aProps ); + } + + //==================================================================== + //= DataAccessDescriptorFactory + //==================================================================== + typedef ::cppu::WeakImplHelper2 < XServiceInfo + , XDataAccessDescriptorFactory + > DataAccessDescriptorFactory_Base; + class DataAccessDescriptorFactory : public DataAccessDescriptorFactory_Base + { + public: + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw (RuntimeException); + virtual ::sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (RuntimeException); + virtual Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw (RuntimeException); + + // XServiceInfo - static versions + static Sequence< ::rtl::OUString > getSupportedServiceNames_static(void) throw( RuntimeException ); + static ::rtl::OUString getImplementationName_static(void) throw( RuntimeException ); + static Reference< XInterface > Create(const Reference< XComponentContext >& _rxContext); + static ::rtl::OUString getSingletonName_static(); + + // XDataAccessDescriptorFactory + virtual Reference< XPropertySet > SAL_CALL createDataAccessDescriptor( ) throw (RuntimeException); + + protected: + DataAccessDescriptorFactory( const Reference< XComponentContext >& _rxContext ); + ~DataAccessDescriptorFactory(); + + private: + ::comphelper::ComponentContext m_aContext; + }; + + //-------------------------------------------------------------------- + DataAccessDescriptorFactory::DataAccessDescriptorFactory( const Reference< XComponentContext >& _rxContext ) + :m_aContext( _rxContext ) + { + } + + //-------------------------------------------------------------------- + DataAccessDescriptorFactory::~DataAccessDescriptorFactory() + { + } + + //-------------------------------------------------------------------- + ::rtl::OUString DataAccessDescriptorFactory::getSingletonName_static() + { + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sdb.DataAccessDescriptorFactory" ) ); + } + + //-------------------------------------------------------------------- + Sequence< ::rtl::OUString > DataAccessDescriptorFactory::getSupportedServiceNames_static() throw( RuntimeException ) + { + Sequence< ::rtl::OUString > aServices(1); + aServices[0] = getSingletonName_static(); + return aServices; + } + + //-------------------------------------------------------------------- + ::rtl::OUString DataAccessDescriptorFactory::getImplementationName_static() throw( RuntimeException ) + { + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.dba.DataAccessDescriptorFactory" ) ); + } + + //-------------------------------------------------------------------- + Reference< XInterface > DataAccessDescriptorFactory::Create( const Reference< XComponentContext >& _rxContext ) + { + return *( new DataAccessDescriptorFactory( _rxContext ) ); + } + + //-------------------------------------------------------------------- + ::rtl::OUString SAL_CALL DataAccessDescriptorFactory::getImplementationName() throw (RuntimeException) + { + return getImplementationName_static(); + } + + //-------------------------------------------------------------------- + ::sal_Bool SAL_CALL DataAccessDescriptorFactory::supportsService( const ::rtl::OUString& rServiceName ) throw (RuntimeException) + { + Sequence< ::rtl::OUString > aServices( getSupportedServiceNames_static() ); + const ::rtl::OUString* pStart = aServices.getConstArray(); + const ::rtl::OUString* pEnd = aServices.getConstArray() + aServices.getLength(); + return ::std::find( pStart, pEnd, rServiceName ) != pEnd; + } + + //-------------------------------------------------------------------- + Sequence< ::rtl::OUString > SAL_CALL DataAccessDescriptorFactory::getSupportedServiceNames( ) throw (RuntimeException) + { + return getSupportedServiceNames_static(); + } + + //-------------------------------------------------------------------- + Reference< XPropertySet > SAL_CALL DataAccessDescriptorFactory::createDataAccessDescriptor( ) throw (RuntimeException) + { + return new DataAccessDescriptor( m_aContext ); + } + +//........................................................................ +} // namespace dbaccess +//........................................................................ + +//-------------------------------------------------------------------------- +extern "C" void SAL_CALL createRegistryInfo_DataAccessDescriptorFactory() +{ + static ::dba::OSingletonRegistration< ::dbaccess::DataAccessDescriptorFactory > aAutoRegistration; +} diff --git a/dbaccess/source/core/dataaccess/databasecontext.cxx b/dbaccess/source/core/dataaccess/databasecontext.cxx new file mode 100644 index 000000000000..315cbcca3b7e --- /dev/null +++ b/dbaccess/source/core/dataaccess/databasecontext.cxx @@ -0,0 +1,809 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#include "apitools.hxx" +#include "core_resource.hrc" +#include "core_resource.hxx" +#include "databasecontext.hxx" +#include "databasedocument.hxx" +#include "databaseregistrations.hxx" +#include "datasource.hxx" +#include "dbastrings.hrc" +#include "module_dba.hxx" + +/** === being UNO includes === **/ +#include <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/document/MacroExecMode.hpp> +#include <com/sun/star/document/XFilter.hpp> +#include <com/sun/star/document/XImporter.hpp> +#include <com/sun/star/frame/XDesktop.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/frame/XModel2.hpp> +#include <com/sun/star/frame/XTerminateListener.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/registry/InvalidRegistryException.hpp> +#include <com/sun/star/sdbc/XDataSource.hpp> +#include <com/sun/star/task/InteractionClassification.hpp> +#include <com/sun/star/ucb/InteractiveIOException.hpp> +#include <com/sun/star/ucb/IOErrorCode.hpp> +#include <com/sun/star/util/XCloseable.hpp> +/** === end UNO includes === **/ + +#include <basic/basmgr.hxx> +#include <comphelper/enumhelper.hxx> +#include <comphelper/evtlistenerhlp.hxx> +#include <comphelper/namedvaluecollection.hxx> +#include <comphelper/processfactory.hxx> +#include <comphelper/sequence.hxx> +#include <cppuhelper/implbase1.hxx> +#include <cppuhelper/typeprovider.hxx> +#include <cppuhelper/exc_hlp.hxx> +#include <svl/filenotation.hxx> +#include <tools/debug.hxx> +#include <tools/diagnose_ex.h> +#include <tools/fsys.hxx> +#include <tools/urlobj.hxx> +#include <ucbhelper/content.hxx> +#include <unotools/confignode.hxx> +#include <unotools/pathoptions.hxx> +#include <unotools/sharedunocomponent.hxx> +#include <list> +#include <boost/bind.hpp> + +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::document; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::registry; +using namespace ::com::sun::star; +using namespace ::cppu; +using namespace ::osl; +using namespace ::utl; + +using ::com::sun::star::task::InteractionClassification_ERROR; +using ::com::sun::star::ucb::IOErrorCode_NO_FILE; +using ::com::sun::star::ucb::InteractiveIOException; +using ::com::sun::star::ucb::IOErrorCode_NOT_EXISTING; +using ::com::sun::star::ucb::IOErrorCode_NOT_EXISTING_PATH; + +//========================================================================== + +extern "C" void SAL_CALL createRegistryInfo_ODatabaseContext() +{ + static ::dba::OLegacySingletonRegistration< ::dbaccess::ODatabaseContext > aODatabaseContext_AutoRegistration; +} + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + + // ............................................................................. + typedef ::cppu::WeakImplHelper1 < XTerminateListener + > DatabaseDocumentLoader_Base; + class DatabaseDocumentLoader : public DatabaseDocumentLoader_Base + { + private: + Reference< XDesktop > m_xDesktop; + ::std::list< const ODatabaseModelImpl* > m_aDatabaseDocuments; + + public: + DatabaseDocumentLoader( const comphelper::ComponentContext& _aContext); + + inline void append(const ODatabaseModelImpl& _rModelImpl ) + { + m_aDatabaseDocuments.push_back(&_rModelImpl); + } + inline void remove(const ODatabaseModelImpl& _rModelImpl) { m_aDatabaseDocuments.remove(&_rModelImpl); } + + private: + // XTerminateListener + virtual void SAL_CALL queryTermination( const lang::EventObject& Event ) throw (TerminationVetoException, RuntimeException); + virtual void SAL_CALL notifyTermination( const lang::EventObject& Event ) throw (RuntimeException); + // XEventListener + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException); + }; + + // ............................................................................. + DatabaseDocumentLoader::DatabaseDocumentLoader( const comphelper::ComponentContext& _aContext ) + { + acquire(); + try + { + m_xDesktop.set( _aContext.createComponent( (rtl::OUString)SERVICE_FRAME_DESKTOP ), UNO_QUERY_THROW ); + m_xDesktop->addTerminateListener( this ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + struct TerminateFunctor : ::std::unary_function<ODatabaseModelImpl* , void> + { + void operator()( const ODatabaseModelImpl* _pModelImpl ) const + { + try + { + const Reference< XModel2> xModel( _pModelImpl ->getModel_noCreate(),UNO_QUERY_THROW ); + if ( !xModel->getControllers()->hasMoreElements() ) + { + Reference<util::XCloseable> xCloseable(xModel,UNO_QUERY_THROW); + xCloseable->close(sal_False); + } // if ( !xModel->getControllers()->hasMoreElements() ) + } + catch(const CloseVetoException&) + { + throw TerminationVetoException(); + } + } + }; + // ............................................................................. + void SAL_CALL DatabaseDocumentLoader::queryTermination( const lang::EventObject& /*Event*/ ) throw (TerminationVetoException, RuntimeException) + { + ::std::list< const ODatabaseModelImpl* > aCopy(m_aDatabaseDocuments); + ::std::for_each(aCopy.begin(),aCopy.end(),TerminateFunctor()); + } + + // ............................................................................. + void SAL_CALL DatabaseDocumentLoader::notifyTermination( const lang::EventObject& /*Event*/ ) throw (RuntimeException) + { + } + // ............................................................................. + void SAL_CALL DatabaseDocumentLoader::disposing( const lang::EventObject& /*Source*/ ) throw (RuntimeException) + { + } + +//= ODatabaseContext +//========================================================================== +//-------------------------------------------------------------------------- +ODatabaseContext::ODatabaseContext( const Reference< XComponentContext >& _rxContext ) + :DatabaseAccessContext_Base(m_aMutex) + ,m_aContext( _rxContext ) + ,m_aContainerListeners(m_aMutex) +{ + m_pDatabaseDocumentLoader = new DatabaseDocumentLoader( m_aContext ); + ::basic::BasicManagerRepository::registerCreationListener( *this ); + + osl_incrementInterlockedCount( &m_refCount ); + { + m_xDBRegistrationAggregate.set( createDataSourceRegistrations( m_aContext ), UNO_SET_THROW ); + m_xDatabaseRegistrations.set( m_xDBRegistrationAggregate, UNO_QUERY_THROW ); + + m_xDBRegistrationAggregate->setDelegator( *this ); + } + osl_decrementInterlockedCount( &m_refCount ); +} + +//-------------------------------------------------------------------------- +ODatabaseContext::~ODatabaseContext() +{ + ::basic::BasicManagerRepository::revokeCreationListener( *this ); + if ( m_pDatabaseDocumentLoader ) + m_pDatabaseDocumentLoader->release(); + + m_xDBRegistrationAggregate->setDelegator( NULL ); + m_xDBRegistrationAggregate.clear(); + m_xDatabaseRegistrations.clear(); +} + +// Helper +//------------------------------------------------------------------------------ +rtl::OUString ODatabaseContext::getImplementationName_static() throw( RuntimeException ) + +{ + return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.dba.ODatabaseContext")); +} + +//------------------------------------------------------------------------------ +Reference< XInterface > ODatabaseContext::Create(const Reference< XComponentContext >& _rxContext) +{ + return *( new ODatabaseContext( _rxContext ) ); +} + +//------------------------------------------------------------------------------ +Sequence< rtl::OUString > ODatabaseContext::getSupportedServiceNames_static(void) throw( RuntimeException ) +{ + Sequence< ::rtl::OUString > aSNS( 1 ); + aSNS[0] = SERVICE_SDB_DATABASECONTEXT; + return aSNS; +} + +// XServiceInfo +//------------------------------------------------------------------------------ +rtl::OUString ODatabaseContext::getImplementationName( ) throw(RuntimeException) +{ + return getImplementationName_static(); +} + +//------------------------------------------------------------------------------ +sal_Bool ODatabaseContext::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException) +{ + return ::comphelper::findValue(getSupportedServiceNames(), _rServiceName, sal_True).getLength() != 0; +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > ODatabaseContext::getSupportedServiceNames( ) throw (RuntimeException) +{ + return getSupportedServiceNames_static(); +} + +//-------------------------------------------------------------------------- +Reference< XInterface > ODatabaseContext::impl_createNewDataSource() +{ + ::rtl::Reference<ODatabaseModelImpl> pImpl( new ODatabaseModelImpl( m_aContext.getLegacyServiceFactory(), *this ) ); + Reference< XDataSource > xDataSource( pImpl->getOrCreateDataSource() ); + + return xDataSource.get(); +} + +//-------------------------------------------------------------------------- +Reference< XInterface > SAL_CALL ODatabaseContext::createInstance( ) throw (Exception, RuntimeException) +{ + // for convenience of the API user, we ensure the document is fully initialized (effectively: XLoadable::initNew + // has been called at the DatabaseDocument). + return impl_createNewDataSource(); +} + +//-------------------------------------------------------------------------- +Reference< XInterface > SAL_CALL ODatabaseContext::createInstanceWithArguments( const Sequence< Any >& _rArguments ) throw (Exception, RuntimeException) +{ + ::comphelper::NamedValueCollection aArgs( _rArguments ); + ::rtl::OUString sURL = aArgs.getOrDefault( (::rtl::OUString)INFO_POOLURL, ::rtl::OUString() ); + + Reference< XInterface > xDataSource; + if ( sURL.getLength() ) + xDataSource = getObject( sURL ); + + if ( !xDataSource.is() ) + xDataSource = impl_createNewDataSource(); + + return xDataSource; +} +// DatabaseAccessContext_Base +//------------------------------------------------------------------------------ +void ODatabaseContext::disposing() +{ + // notify our listener + com::sun::star::lang::EventObject aDisposeEvent(static_cast< XContainer* >(this)); + m_aContainerListeners.disposeAndClear(aDisposeEvent); + + // dispose the data sources + ObjectCache::iterator aEnd = m_aDatabaseObjects.end(); + for ( ObjectCache::iterator aIter = m_aDatabaseObjects.begin(); + aIter != aEnd; + ++aIter + ) + { + aIter->second->dispose(); + } + m_aDatabaseObjects.clear(); +} + +// XNamingService +//------------------------------------------------------------------------------ +Reference< XInterface > ODatabaseContext::getRegisteredObject(const rtl::OUString& _rName) throw( Exception, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed); + + ::rtl::OUString sURL( getDatabaseLocation( _rName ) ); + + if ( !sURL.getLength() ) + // there is a registration for this name, but no URL + throw IllegalArgumentException(); + + // check if URL is already loaded + Reference< XInterface > xExistent = getObject( sURL ); + if ( xExistent.is() ) + return xExistent; + + return loadObjectFromURL( _rName, sURL ); +} +// ----------------------------------------------------------------------------- +Reference< XInterface > ODatabaseContext::loadObjectFromURL(const ::rtl::OUString& _rName,const ::rtl::OUString& _sURL) +{ + INetURLObject aURL( _sURL ); + if ( aURL.GetProtocol() == INET_PROT_NOT_VALID ) + throw NoSuchElementException( _rName, *this ); + + try + { + ::ucbhelper::Content aContent( _sURL, NULL ); + if ( !aContent.isDocument() ) + throw InteractiveIOException( + _sURL, *this, InteractionClassification_ERROR, IOErrorCode_NO_FILE + ); + } + catch ( const InteractiveIOException& e ) + { + if ( ( e.Code == IOErrorCode_NO_FILE ) + || ( e.Code == IOErrorCode_NOT_EXISTING ) + || ( e.Code == IOErrorCode_NOT_EXISTING_PATH ) + ) + { + // #i40463# #i39187# + String sErrorMessage( DBACORE_RESSTRING( RID_STR_FILE_DOES_NOT_EXIST ) ); + ::svt::OFileNotation aTransformer( _sURL ); + sErrorMessage.SearchAndReplaceAscii( "$file$", aTransformer.get( ::svt::OFileNotation::N_SYSTEM ) ); + + SQLException aError; + aError.Message = sErrorMessage; + + throw WrappedTargetException( _sURL, *this, makeAny( aError ) ); + } + throw WrappedTargetException( _sURL, *this, ::cppu::getCaughtException() ); + } + catch( const Exception& ) + { + throw WrappedTargetException( _sURL, *this, ::cppu::getCaughtException() ); + } + + OSL_ENSURE( m_aDatabaseObjects.find( _sURL ) == m_aDatabaseObjects.end(), + "ODatabaseContext::loadObjectFromURL: not intended for already-cached objects!" ); + + ::rtl::Reference< ODatabaseModelImpl > pModelImpl; + { + pModelImpl.set( new ODatabaseModelImpl( _rName, m_aContext.getLegacyServiceFactory(), *this ) ); + + Reference< XModel > xModel( pModelImpl->createNewModel_deliverOwnership( false ), UNO_SET_THROW ); + Reference< XLoadable > xLoad( xModel, UNO_QUERY_THROW ); + + ::comphelper::NamedValueCollection aArgs; + aArgs.put( "URL", _sURL ); + aArgs.put( "MacroExecutionMode", MacroExecMode::USE_CONFIG ); + aArgs.put( "InteractionHandler", m_aContext.createComponent( "com.sun.star.task.InteractionHandler" ) ); + + Sequence< PropertyValue > aResource( aArgs.getPropertyValues() ); + xLoad->load( aResource ); + xModel->attachResource( _sURL, aResource ); + + ::utl::CloseableComponent aEnsureClose( xModel ); + } + + setTransientProperties( _sURL, *pModelImpl ); + + return pModelImpl->getOrCreateDataSource().get(); +} +// ----------------------------------------------------------------------------- +void ODatabaseContext::appendAtTerminateListener(const ODatabaseModelImpl& _rDataSourceModel) +{ + m_pDatabaseDocumentLoader->append(_rDataSourceModel); +} +// ----------------------------------------------------------------------------- +void ODatabaseContext::removeFromTerminateListener(const ODatabaseModelImpl& _rDataSourceModel) +{ + m_pDatabaseDocumentLoader->remove(_rDataSourceModel); +} +// ----------------------------------------------------------------------------- +void ODatabaseContext::setTransientProperties(const ::rtl::OUString& _sURL, ODatabaseModelImpl& _rDataSourceModel ) +{ + if ( m_aDatasourceProperties.end() == m_aDatasourceProperties.find(_sURL) ) + return; + try + { + ::rtl::OUString sAuthFailedPassword; + Reference< XPropertySet > xDSProps( _rDataSourceModel.getOrCreateDataSource(), UNO_QUERY_THROW ); + const Sequence< PropertyValue >& rSessionPersistentProps = m_aDatasourceProperties[_sURL]; + const PropertyValue* pProp = rSessionPersistentProps.getConstArray(); + const PropertyValue* pPropsEnd = rSessionPersistentProps.getConstArray() + rSessionPersistentProps.getLength(); + for ( ; pProp != pPropsEnd; ++pProp ) + { + if ( pProp->Name.equalsAscii( "AuthFailedPassword" ) ) + { + OSL_VERIFY( pProp->Value >>= sAuthFailedPassword ); + } + else + { + xDSProps->setPropertyValue( pProp->Name, pProp->Value ); + } + } + + _rDataSourceModel.m_sFailedPassword = sAuthFailedPassword; + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } +} + +//------------------------------------------------------------------------------ +void ODatabaseContext::registerObject(const rtl::OUString& _rName, const Reference< XInterface > & _rxObject) throw( Exception, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed); + + if ( !_rName.getLength() ) + throw IllegalArgumentException( ::rtl::OUString(), *this, 1 ); + + Reference< XDocumentDataSource > xDocDataSource( _rxObject, UNO_QUERY ); + Reference< XModel > xModel( xDocDataSource.is() ? xDocDataSource->getDatabaseDocument() : Reference< XOfficeDatabaseDocument >(), UNO_QUERY ); + if ( !xModel.is() ) + throw IllegalArgumentException( ::rtl::OUString(), *this, 2 ); + + ::rtl::OUString sURL = xModel->getURL(); + if ( !sURL.getLength() ) + throw IllegalArgumentException( DBACORE_RESSTRING( RID_STR_DATASOURCE_NOT_STORED ), *this, 2 ); + + registerDatabaseLocation( _rName, sURL ); + + ODatabaseSource::setName( xDocDataSource, _rName, ODatabaseSource::DBContextAccess() ); + + // notify our container listeners + ContainerEvent aEvent(static_cast<XContainer*>(this), makeAny(_rName), makeAny(_rxObject), Any()); + m_aContainerListeners.notifyEach( &XContainerListener::elementInserted, aEvent ); +} + +//------------------------------------------------------------------------------ +void ODatabaseContext::storeTransientProperties( ODatabaseModelImpl& _rModelImpl) +{ + Reference< XPropertySet > xSource( _rModelImpl.getOrCreateDataSource(), UNO_QUERY ); + ::comphelper::NamedValueCollection aRememberProps; + + try + { + // get the info about the properties, check which ones are transient and not readonly + Reference< XPropertySetInfo > xSetInfo; + if (xSource.is()) + xSetInfo = xSource->getPropertySetInfo(); + Sequence< Property > aProperties; + if (xSetInfo.is()) + aProperties = xSetInfo->getProperties(); + + if (aProperties.getLength()) + { + const Property* pProperties = aProperties.getConstArray(); + for ( sal_Int32 i=0; i<aProperties.getLength(); ++i, ++pProperties ) + { + if ( ( ( pProperties->Attributes & PropertyAttribute::TRANSIENT) != 0 ) + && ( ( pProperties->Attributes & PropertyAttribute::READONLY) == 0 ) + ) + { + // found such a property + aRememberProps.put( pProperties->Name, xSource->getPropertyValue( pProperties->Name ) ); + } + } + } + } + catch ( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + // additionally, remember the "failed password", which is not available as property + // #i86178# / 2008-02-19 / frank.schoenheit@sun.com + aRememberProps.put( "AuthFailedPassword", _rModelImpl.m_sFailedPassword ); + + ::rtl::OUString sDocumentURL( _rModelImpl.getURL() ); + if ( m_aDatabaseObjects.find( sDocumentURL ) != m_aDatabaseObjects.end() ) + { + m_aDatasourceProperties[ sDocumentURL ] = aRememberProps.getPropertyValues(); + } + else if ( m_aDatabaseObjects.find( _rModelImpl.m_sName ) != m_aDatabaseObjects.end() ) + { + OSL_ENSURE( false, "ODatabaseContext::storeTransientProperties: a database document register by name? This shouldn't happen anymore!" ); + // all the code should have been changed so that registration is by URL only + m_aDatasourceProperties[ _rModelImpl.m_sName ] = aRememberProps.getPropertyValues(); + } + else + { + OSL_ENSURE( ( sDocumentURL.getLength() == 0 ) && ( _rModelImpl.m_sName.getLength() == 0 ), + "ODatabaseContext::storeTransientProperties: a non-empty data source which I do not know?!" ); + } +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseContext::addContainerListener( const Reference< XContainerListener >& _rxListener ) throw(RuntimeException) +{ + m_aContainerListeners.addInterface(_rxListener); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseContext::removeContainerListener( const Reference< XContainerListener >& _rxListener ) throw(RuntimeException) +{ + m_aContainerListeners.removeInterface(_rxListener); +} + +//------------------------------------------------------------------------------ +void ODatabaseContext::revokeObject(const rtl::OUString& _rName) throw( Exception, RuntimeException ) +{ + ClearableMutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed); + + ::rtl::OUString sURL = getDatabaseLocation( _rName ); + + revokeDatabaseLocation( _rName ); + // will throw if something goes wrong + + if ( m_aDatabaseObjects.find( _rName ) != m_aDatabaseObjects.end() ) + { + m_aDatasourceProperties[ sURL ] = m_aDatasourceProperties[ _rName ]; + } + + // check if URL is already loaded + ObjectCacheIterator aExistent = m_aDatabaseObjects.find( sURL ); + if ( aExistent != m_aDatabaseObjects.end() ) + m_aDatabaseObjects.erase( aExistent ); + + // notify our container listeners + ContainerEvent aEvent( *this, makeAny( _rName ), Any(), Any() ); + aGuard.clear(); + m_aContainerListeners.notifyEach( &XContainerListener::elementRemoved, aEvent ); +} + +//------------------------------------------------------------------------------ +::sal_Bool SAL_CALL ODatabaseContext::hasRegisteredDatabase( const ::rtl::OUString& _Name ) throw (IllegalArgumentException, RuntimeException) +{ + return m_xDatabaseRegistrations->hasRegisteredDatabase( _Name ); +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > SAL_CALL ODatabaseContext::getRegistrationNames() throw (RuntimeException) +{ + return m_xDatabaseRegistrations->getRegistrationNames(); +} + +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL ODatabaseContext::getDatabaseLocation( const ::rtl::OUString& _Name ) throw (IllegalArgumentException, NoSuchElementException, RuntimeException) +{ + return m_xDatabaseRegistrations->getDatabaseLocation( _Name ); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseContext::registerDatabaseLocation( const ::rtl::OUString& _Name, const ::rtl::OUString& _Location ) throw (IllegalArgumentException, ElementExistException, RuntimeException) +{ + m_xDatabaseRegistrations->registerDatabaseLocation( _Name, _Location ); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseContext::revokeDatabaseLocation( const ::rtl::OUString& _Name ) throw (IllegalArgumentException, NoSuchElementException, IllegalAccessException, RuntimeException) +{ + m_xDatabaseRegistrations->revokeDatabaseLocation( _Name ); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseContext::changeDatabaseLocation( const ::rtl::OUString& _Name, const ::rtl::OUString& _NewLocation ) throw (IllegalArgumentException, NoSuchElementException, IllegalAccessException, RuntimeException) +{ + m_xDatabaseRegistrations->changeDatabaseLocation( _Name, _NewLocation ); +} + +//------------------------------------------------------------------------------ +::sal_Bool SAL_CALL ODatabaseContext::isDatabaseRegistrationReadOnly( const ::rtl::OUString& _Name ) throw (IllegalArgumentException, NoSuchElementException, RuntimeException) +{ + return m_xDatabaseRegistrations->isDatabaseRegistrationReadOnly( _Name ); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseContext::addDatabaseRegistrationsListener( const Reference< XDatabaseRegistrationsListener >& _Listener ) throw (RuntimeException) +{ + m_xDatabaseRegistrations->addDatabaseRegistrationsListener( _Listener ); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseContext::removeDatabaseRegistrationsListener( const Reference< XDatabaseRegistrationsListener >& _Listener ) throw (RuntimeException) +{ + m_xDatabaseRegistrations->removeDatabaseRegistrationsListener( _Listener ); +} + +// ::com::sun::star::container::XElementAccess +//------------------------------------------------------------------------------ +Type ODatabaseContext::getElementType( ) throw(RuntimeException) +{ + return::getCppuType(static_cast<Reference<XDataSource>*>(NULL)); +} + +//------------------------------------------------------------------------------ +sal_Bool ODatabaseContext::hasElements(void) throw( RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed); + + return 0 != getElementNames().getLength(); +} + +// ::com::sun::star::container::XEnumerationAccess +//------------------------------------------------------------------------------ +Reference< ::com::sun::star::container::XEnumeration > ODatabaseContext::createEnumeration(void) throw( RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + return new ::comphelper::OEnumerationByName(static_cast<XNameAccess*>(this)); +} + +// ::com::sun::star::container::XNameAccess +//------------------------------------------------------------------------------ +Any ODatabaseContext::getByName(const rtl::OUString& _rName) throw( NoSuchElementException, + WrappedTargetException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed); + if ( !_rName.getLength() ) + throw NoSuchElementException(_rName, *this); + + try + { + Reference< XInterface > xExistent = getObject( _rName ); + if ( xExistent.is() ) + return makeAny( xExistent ); + + // see whether this is an registered name + ::rtl::OUString sURL; + if ( hasRegisteredDatabase( _rName ) ) + { + sURL = getDatabaseLocation( _rName ); + // is the object cached under its URL? + xExistent = getObject( sURL ); + } + else + // interpret the name as URL + sURL = _rName; + + if ( !xExistent.is() ) + // try to load this as URL + xExistent = loadObjectFromURL( _rName, sURL ); + return makeAny( xExistent ); + } + catch (NoSuchElementException&) + { // let these exceptions through + throw; + } + catch (WrappedTargetException&) + { // let these exceptions through + throw; + } + catch (RuntimeException&) + { // let these exceptions through + throw; + } + catch (Exception& e) + { // exceptions other than the speciafied ones -> wrap + Any aError = ::cppu::getCaughtException(); + throw WrappedTargetException(_rName, *this, aError ); + } +} + +//------------------------------------------------------------------------------ +Sequence< rtl::OUString > ODatabaseContext::getElementNames(void) throw( RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed); + + return getRegistrationNames(); +} + +//------------------------------------------------------------------------------ +sal_Bool ODatabaseContext::hasByName(const rtl::OUString& _rName) throw( RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(DatabaseAccessContext_Base::rBHelper.bDisposed); + + return hasRegisteredDatabase( _rName ); +} + +// ----------------------------------------------------------------------------- +Reference< XInterface > ODatabaseContext::getObject( const ::rtl::OUString& _rURL ) +{ + ObjectCacheIterator aFind = m_aDatabaseObjects.find( _rURL ); + Reference< XInterface > xExistent; + if ( aFind != m_aDatabaseObjects.end() ) + xExistent = aFind->second->getOrCreateDataSource(); + return xExistent; +} +// ----------------------------------------------------------------------------- +void ODatabaseContext::registerDatabaseDocument( ODatabaseModelImpl& _rModelImpl ) +{ + ::rtl::OUString sURL( _rModelImpl.getURL() ); +#if OSL_DEBUG_LEVEL > 1 + OSL_TRACE( "DatabaseContext: registering %s", ::rtl::OUStringToOString( sURL, RTL_TEXTENCODING_UTF8 ).getStr() ); +#endif + if ( m_aDatabaseObjects.find( sURL ) == m_aDatabaseObjects.end() ) + { + m_aDatabaseObjects[ sURL ] = &_rModelImpl; + setTransientProperties( sURL, _rModelImpl ); + } + else + OSL_ENSURE( false, "ODatabaseContext::registerDatabaseDocument: already have an object registered for this URL!" ); +} +// ----------------------------------------------------------------------------- +void ODatabaseContext::revokeDatabaseDocument( const ODatabaseModelImpl& _rModelImpl ) +{ + ::rtl::OUString sURL( _rModelImpl.getURL() ); +#if OSL_DEBUG_LEVEL > 1 + OSL_TRACE( "DatabaseContext: deregistering %s", ::rtl::OUStringToOString( sURL, RTL_TEXTENCODING_UTF8 ).getStr() ); +#endif + m_aDatabaseObjects.erase( sURL ); +} +// ----------------------------------------------------------------------------- +void ODatabaseContext::databaseDocumentURLChange( const ::rtl::OUString& _rOldURL, const ::rtl::OUString& _rNewURL ) +{ +#if OSL_DEBUG_LEVEL > 1 + OSL_TRACE( "DatabaseContext: changing registration from %s to %s", + ::rtl::OUStringToOString( _rOldURL, RTL_TEXTENCODING_UTF8 ).getStr(), + ::rtl::OUStringToOString( _rNewURL, RTL_TEXTENCODING_UTF8 ).getStr() ); +#endif + ObjectCache::iterator oldPos = m_aDatabaseObjects.find( _rOldURL ); + ENSURE_OR_THROW( oldPos != m_aDatabaseObjects.end(), "illegal old database document URL" ); + ObjectCache::iterator newPos = m_aDatabaseObjects.find( _rNewURL ); + ENSURE_OR_THROW( newPos == m_aDatabaseObjects.end(), "illegal new database document URL" ); + + m_aDatabaseObjects[ _rNewURL ] = oldPos->second; + m_aDatabaseObjects.erase( oldPos ); +} +// ----------------------------------------------------------------------------- +sal_Int64 SAL_CALL ODatabaseContext::getSomething( const Sequence< sal_Int8 >& rId ) throw(RuntimeException) +{ + if (rId.getLength() == 16 && 0 == rtl_compareMemory(getUnoTunnelImplementationId().getConstArray(), rId.getConstArray(), 16 ) ) + return reinterpret_cast<sal_Int64>(this); + + return 0; +} +// ----------------------------------------------------------------------------- +Sequence< sal_Int8 > ODatabaseContext::getUnoTunnelImplementationId() +{ + static ::cppu::OImplementationId * pId = 0; + if (! pId) + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if (! pId) + { + static ::cppu::OImplementationId aId; + pId = &aId; + } + } + return pId->getImplementationId(); +} + +// ----------------------------------------------------------------------------- +void ODatabaseContext::onBasicManagerCreated( const Reference< XModel >& _rxForDocument, BasicManager& _rBasicManager ) +{ + // if it's a database document ... + Reference< XOfficeDatabaseDocument > xDatabaseDocument( _rxForDocument, UNO_QUERY ); + // ... or a sub document of a database document ... + if ( !xDatabaseDocument.is() ) + { + Reference< XChild > xDocAsChild( _rxForDocument, UNO_QUERY ); + if ( xDocAsChild.is() ) + xDatabaseDocument.set( xDocAsChild->getParent(), UNO_QUERY ); + } + + // ... whose BasicManager has just been created, then add the global DatabaseDocument variable to its scope. + if ( xDatabaseDocument.is() ) + _rBasicManager.SetGlobalUNOConstant( "ThisDatabaseDocument", makeAny( xDatabaseDocument ) ); +} + +//........................................................................ +} // namespace dbaccess +//........................................................................ diff --git a/dbaccess/source/core/dataaccess/databasecontext.hxx b/dbaccess/source/core/dataaccess/databasecontext.hxx new file mode 100644 index 000000000000..dc55ff62b694 --- /dev/null +++ b/dbaccess/source/core/dataaccess/databasecontext.hxx @@ -0,0 +1,213 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 _DBA_COREDATAACCESS_DATABASECONTEXT_HXX_ +#define _DBA_COREDATAACCESS_DATABASECONTEXT_HXX_ + +#include "ModelImpl.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/container/ElementExistException.hpp> +#include <com/sun/star/container/XContainer.hpp> +#include <com/sun/star/container/XEnumerationAccess.hpp> +#include <com/sun/star/container/XHierarchicalNameAccess.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/lang/XEventListener.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/lang/XUnoTunnel.hpp> +#include <com/sun/star/sdb/XDatabaseEnvironment.hpp> +#include <com/sun/star/sdb/XDatabaseRegistrations.hpp> +#include <com/sun/star/uno/XNamingService.hpp> +#include <com/sun/star/uno/XAggregation.hpp> +/** === end UNO includes === **/ + +#include <basic/basicmanagerrepository.hxx> +#include <comphelper/componentcontext.hxx> +#include <comphelper/stl_types.hxx> +#include <cppuhelper/compbase8.hxx> +#include <cppuhelper/interfacecontainer.hxx> + +#include <boost/shared_ptr.hpp> + +// needed for registration +namespace com { namespace sun { namespace star { + namespace lang + { + class XMultiServiceFactory; + class IllegalArgumentException; + } +} } } + +//........................................................................ +namespace dbaccess +{ +//........................................................................ +class DatabaseDocumentLoader; +//============================================================ +//= ODatabaseContext +//============================================================ +::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > + ODatabaseContext_CreateInstance(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >&); + +typedef ::cppu::WeakComponentImplHelper8 < ::com::sun::star::lang::XServiceInfo + , ::com::sun::star::container::XEnumerationAccess + , ::com::sun::star::container::XNameAccess + , ::com::sun::star::uno::XNamingService + , ::com::sun::star::container::XContainer + , ::com::sun::star::lang::XSingleServiceFactory + , ::com::sun::star::lang::XUnoTunnel + , ::com::sun::star::sdb::XDatabaseRegistrations + > DatabaseAccessContext_Base; + +class ODatabaseContext :public DatabaseAccessContext_Base + ,public ::basic::BasicManagerCreationListener +{ +private: + /** loads the given object from the given URL + @throws WrappedTargetException + if an error occurs accessing the URL via the UCB + + */ + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > loadObjectFromURL(const ::rtl::OUString& _rName,const ::rtl::OUString& _sURL); + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > getObject( const ::rtl::OUString& _rURL ); + + /** sets all properties which were transient at the data source. e.g. password + @param _sURL The file URL of the data source + @param _xObject The data source itself. + */ + void setTransientProperties(const ::rtl::OUString& _sURL, ODatabaseModelImpl& _rDataSourceModel ); + + /** creates a new data source + */ + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > + impl_createNewDataSource(); + +protected: + ::osl::Mutex m_aMutex; + ::comphelper::ComponentContext m_aContext; + + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XAggregation > + m_xDBRegistrationAggregate; + ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XDatabaseRegistrations > + m_xDatabaseRegistrations; + + DECLARE_STL_USTRINGACCESS_MAP( ODatabaseModelImpl*, ObjectCache ); + ObjectCache m_aDatabaseObjects; + + DECLARE_STL_USTRINGACCESS_MAP( ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >, PropertyCache ); + PropertyCache m_aDatasourceProperties; + // as we hold our data sources weak, we have to cache all properties on the data sources which are + // transient but stored as long as the session lasts. The database context is the session (as it lives + // as long as the session does), but the data sources may die before the session does, and then be + // recreated afterwards. So it's our (the context's) responsibility to store the session-persistent + // properties. + + ::cppu::OInterfaceContainerHelper m_aContainerListeners; + DatabaseDocumentLoader* m_pDatabaseDocumentLoader; + +public: + ODatabaseContext( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& ); + virtual ~ODatabaseContext(); + + + // OComponentHelper + virtual void SAL_CALL disposing(void); + + // XSingleServiceFactory + virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL createInstance( ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL createInstanceWithArguments( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& _rArguments ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw(::com::sun::star::uno::RuntimeException); + + // XServiceInfo - static methods + static ::com::sun::star::uno::Sequence< ::rtl::OUString > getSupportedServiceNames_static(void) throw( ::com::sun::star::uno::RuntimeException ); + static ::rtl::OUString getImplementationName_static(void) throw( ::com::sun::star::uno::RuntimeException ); + static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > + SAL_CALL Create(const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >&); + + // XElementAccess + virtual ::com::sun::star::uno::Type SAL_CALL getElementType( ) throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL hasElements( ) throw(::com::sun::star::uno::RuntimeException); + + // XEnumerationAccess + virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XEnumeration > SAL_CALL createEnumeration( ) throw(::com::sun::star::uno::RuntimeException); + + // XNameAccess + virtual ::com::sun::star::uno::Any SAL_CALL getByName( const ::rtl::OUString& aName ) throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getElementNames( ) throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName ) throw(::com::sun::star::uno::RuntimeException); + + // XNamingService + virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL getRegisteredObject( const ::rtl::OUString& Name ) throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL registerObject( const ::rtl::OUString& Name, const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& Object ) throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL revokeObject( const ::rtl::OUString& Name ) throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + + // XDatabaseRegistrations + virtual ::sal_Bool SAL_CALL hasRegisteredDatabase( const ::rtl::OUString& Name ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getRegistrationNames() throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getDatabaseLocation( const ::rtl::OUString& Name ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL registerDatabaseLocation( const ::rtl::OUString& Name, const ::rtl::OUString& Location ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::ElementExistException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL revokeDatabaseLocation( const ::rtl::OUString& Name ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::IllegalAccessException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL changeDatabaseLocation( const ::rtl::OUString& Name, const ::rtl::OUString& NewLocation ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::IllegalAccessException, ::com::sun::star::uno::RuntimeException); + virtual ::sal_Bool SAL_CALL isDatabaseRegistrationReadOnly( const ::rtl::OUString& Name ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addDatabaseRegistrationsListener( const ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XDatabaseRegistrationsListener >& Listener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeDatabaseRegistrationsListener( const ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XDatabaseRegistrationsListener >& Listener ) throw (::com::sun::star::uno::RuntimeException); + + // XContainer + virtual void SAL_CALL addContainerListener( const ::com::sun::star::uno::Reference< ::com::sun::star::container::XContainerListener >& xListener ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeContainerListener( const ::com::sun::star::uno::Reference< ::com::sun::star::container::XContainerListener >& xListener ) throw(::com::sun::star::uno::RuntimeException); + + // com::sun::star::lang::XUnoTunnel + virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& aIdentifier ) throw(::com::sun::star::uno::RuntimeException); + static ::com::sun::star::uno::Sequence< sal_Int8 > getUnoTunnelImplementationId(); + + void registerDatabaseDocument( ODatabaseModelImpl& _rModelImpl); + void revokeDatabaseDocument( const ODatabaseModelImpl& _rModelImpl); + void databaseDocumentURLChange(const ::rtl::OUString& _sOldName, const ::rtl::OUString& _sNewName); + void storeTransientProperties( ODatabaseModelImpl& _rModelImpl); + void appendAtTerminateListener(const ODatabaseModelImpl& _rDataSourceModel); + void removeFromTerminateListener(const ODatabaseModelImpl& _rDataSourceModel); + +private: + // BasicManagerCreationListener + virtual void onBasicManagerCreated( + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >& _rxForDocument, + BasicManager& _rBasicManager + ); +}; + +//........................................................................ +} // namespace dbaccess +//........................................................................ + +#endif // _DBA_COREDATAACCESS_DATABASECONTEXT_HXX_ + + diff --git a/dbaccess/source/core/dataaccess/databasedocument.cxx b/dbaccess/source/core/dataaccess/databasedocument.cxx new file mode 100644 index 000000000000..125c54121628 --- /dev/null +++ b/dbaccess/source/core/dataaccess/databasedocument.cxx @@ -0,0 +1,2191 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#include "core_resource.hxx" +#include "core_resource.hrc" +#include "datasource.hxx" +#include "databasedocument.hxx" +#include "dbastrings.hrc" +#include "module_dba.hxx" +#include "documenteventexecutor.hxx" +#include "databasecontext.hxx" +#include "documentcontainer.hxx" +#include "sdbcoretools.hxx" +#include "recovery/dbdocrecovery.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/beans/Optional.hpp> +#include <com/sun/star/document/XExporter.hpp> +#include <com/sun/star/document/XFilter.hpp> +#include <com/sun/star/document/XImporter.hpp> +#include <com/sun/star/embed/EntryInitModes.hpp> +#include <com/sun/star/embed/XEmbedPersist.hpp> +#include <com/sun/star/embed/XTransactedObject.hpp> +#include <com/sun/star/embed/XTransactionBroadcaster.hpp> +#include <com/sun/star/io/XActiveDataSource.hpp> +#include <com/sun/star/io/XSeekable.hpp> +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/io/XTruncate.hpp> +#include <com/sun/star/script/provider/XScriptProviderFactory.hpp> +#include <com/sun/star/task/ErrorCodeIOException.hpp> +#include <com/sun/star/task/XStatusIndicator.hpp> +#include <com/sun/star/task/XStatusIndicatorFactory.hpp> +#include <com/sun/star/ucb/XSimpleFileAccess.hpp> +#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> +#include <comphelper/enumhelper.hxx> +#include <comphelper/genericpropertyset.hxx> +#include <comphelper/interaction.hxx> +#include <comphelper/mediadescriptor.hxx> +#include <comphelper/namedvaluecollection.hxx> +#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> +#include <tools/debug.hxx> +#include <tools/diagnose_ex.h> +#include <tools/errcode.hxx> +#include <tools/urlobj.hxx> + +#include <boost/bind.hpp> + +#include <algorithm> +#include <functional> +#include <list> + +#define MAP_LEN(x) x, sizeof(x) - 1 + +#define MAP_LEN(x) x, sizeof(x) - 1 + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::document; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::embed; +using namespace ::com::sun::star::task; +using namespace ::com::sun::star::view; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star; +using namespace ::com::sun::star::xml::sax; +using namespace ::com::sun::star::script; +using namespace ::com::sun::star::script::provider; +using namespace ::com::sun::star::ui; +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 +{ +//........................................................................ + +//============================================================ +//= ViewMonitor +//============================================================ +//-------------------------------------------------------------------------- +bool ViewMonitor::onControllerConnected( const Reference< XController >& _rxController ) +{ + bool bFirstControllerEver = ( m_bEverHadController == false ); + m_bEverHadController = true; + + m_xLastConnectedController = _rxController; + m_bLastIsFirstEverController = bFirstControllerEver; + + return bFirstControllerEver; +} + +//-------------------------------------------------------------------------- +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 + // first controller ever connected + bool bLoadFinished = ( _rxController == m_xLastConnectedController ) && m_bLastIsFirstEverController; + + // notify the respective events + if ( bLoadFinished ) + m_rEventNotifier.notifyDocumentEventAsync( m_bIsNewDocument ? "OnNew" : "OnLoad" ); + + return bLoadFinished; +} + +//============================================================ +//= ODatabaseDocument +//============================================================ +DBG_NAME(ODatabaseDocument) +//-------------------------------------------------------------------------- +extern "C" void SAL_CALL createRegistryInfo_ODatabaseDocument() +{ + static ::dba::OAutoRegistration< ODatabaseDocument > aAutoRegistration; +} + +//-------------------------------------------------------------------------- +ODatabaseDocument::ODatabaseDocument(const ::rtl::Reference<ODatabaseModelImpl>& _pImpl ) + :ModelDependentComponent( _pImpl ) + ,ODatabaseDocument_OfficeDocument( getMutex() ) + ,m_aModifyListeners( getMutex() ) + ,m_aCloseListener( getMutex() ) + ,m_aStorageListeners( getMutex() ) + ,m_pEventContainer( new DocumentEvents( *this, getMutex(), _pImpl->getDocumentEvents() ) ) + ,m_pEventExecutor( NULL ) // initialized below, ref-count-protected + ,m_aEventNotifier( *this, getMutex() ) + ,m_aViewMonitor( m_aEventNotifier ) + ,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() ); + + osl_incrementInterlockedCount( &m_refCount ); + { + impl_reparent_nothrow( m_xForms ); + impl_reparent_nothrow( m_xReports ); + impl_reparent_nothrow( m_pImpl->m_xTableDefinitions ); + impl_reparent_nothrow( m_pImpl->m_xCommandDefinitions ); + + m_pEventExecutor = new DocumentEventExecutor( m_pImpl->m_aContext, this ); + } + osl_decrementInterlockedCount( &m_refCount ); + + // if there previously was a document instance for the same Impl which was already initialized, + // then consider ourself initialized, too. + // #i94840# + if ( m_pImpl->hadInitializedDocument() ) + { + // Note we set our init-state to "Initializing", not "Initialized". We're created from inside the ModelImpl, + // which is expected to call attachResource in case there was a previous incarnation of the document, + // so we can properly finish our initialization then. + impl_setInitializing(); + + if ( m_pImpl->getURL().getLength() ) + { + // if the previous incarnation of the DatabaseDocument already had an URL, then creating this incarnation + // here is effectively loading the document. + // #i105505# / 2009-10-01 / frank.schoenheit@sun.com + m_aViewMonitor.onLoadedDocument(); + } + } +} + +//-------------------------------------------------------------------------- +ODatabaseDocument::~ODatabaseDocument() +{ + OSL_TRACE( "DD: dtor: %p: %p", this, m_pImpl.get() ); + DBG_DTOR(ODatabaseDocument,NULL); + if ( !ODatabaseDocument_OfficeDocument::rBHelper.bInDispose && !ODatabaseDocument_OfficeDocument::rBHelper.bDisposed ) + { + acquire(); + dispose(); + } + + delete m_pEventContainer, m_pEventContainer = NULL; +} +// ----------------------------------------------------------------------------- +Any SAL_CALL ODatabaseDocument::queryInterface( const Type& _rType ) throw (RuntimeException) +{ + // strip XEmbeddedScripts and XScriptInvocationContext if we have any form/report + // which already contains macros. In this case, the database document itself is not + // allowed to contain macros, too. + if ( !m_bAllowDocumentScripting + && ( _rType.equals( XEmbeddedScripts::static_type() ) + || _rType.equals( XScriptInvocationContext::static_type() ) + ) + ) + return Any(); + + Any aReturn = ODatabaseDocument_OfficeDocument::queryInterface(_rType); + if (!aReturn.hasValue()) + aReturn = ODatabaseDocument_Title::queryInterface(_rType); + return aReturn; +} +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseDocument::acquire( ) throw () +{ + ODatabaseDocument_OfficeDocument::acquire(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODatabaseDocument::release( ) throw () +{ + ODatabaseDocument_OfficeDocument::release(); +} +//------------------------------------------------------------------------------ +Sequence< Type > SAL_CALL ODatabaseDocument::getTypes( ) throw (RuntimeException) +{ + Sequence< Type > aTypes = ::comphelper::concatSequences( + ODatabaseDocument_OfficeDocument::getTypes(), + ODatabaseDocument_Title::getTypes() + ); + + // strip XEmbeddedScripts and XScriptInvocationContext if we have any form/report + // which already contains macros. In this case, the database document itself is not + // allowed to contain macros, too. + if ( !m_bAllowDocumentScripting ) + { + Sequence< Type > aStrippedTypes( aTypes.getLength() ); + Type* pStripTo( aStrippedTypes.getArray() ); + + // strip XEmbeddedScripts, and immediately re-assign to aTypes + aTypes = Sequence< Type >( + pStripTo, + ::std::remove_copy_if( + aTypes.getConstArray(), + aTypes.getConstArray() + aTypes.getLength(), + pStripTo, + ::std::bind2nd( ::std::equal_to< Type >(), XEmbeddedScripts::static_type() ) + ) - pStripTo + ); + + // strip XScriptInvocationContext, and immediately re-assign to aTypes + aTypes = Sequence< Type >( + pStripTo, + ::std::remove_copy_if( + aTypes.getConstArray(), + aTypes.getConstArray() + aTypes.getLength(), + pStripTo, + ::std::bind2nd( ::std::equal_to< Type >(), XScriptInvocationContext::static_type() ) + ) - pStripTo + ); + } + + return aTypes; +} +//------------------------------------------------------------------------------ +Sequence< sal_Int8 > SAL_CALL ODatabaseDocument::getImplementationId( ) throw (RuntimeException) +{ + static ::cppu::OImplementationId * pId = 0; + if (! pId) + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if (! pId) + { + static ::cppu::OImplementationId aId; + pId = &aId; + } + } + return pId->getImplementationId(); +} + +// ----------------------------------------------------------------------------- +// local functions +// ----------------------------------------------------------------------------- +namespace +{ + // ----------------------------------------------------------------------------- + Reference< XStatusIndicator > lcl_extractStatusIndicator( const ::comphelper::NamedValueCollection& _rArguments ) + { + Reference< XStatusIndicator > xStatusIndicator; + return _rArguments.getOrDefault( "StatusIndicator", xStatusIndicator ); + } + + // ----------------------------------------------------------------------------- + static void lcl_triggerStatusIndicator_throw( const ::comphelper::NamedValueCollection& _rArguments, DocumentGuard& _rGuard, const bool _bStart ) + { + Reference< XStatusIndicator > xStatusIndicator( lcl_extractStatusIndicator( _rArguments ) ); + if ( !xStatusIndicator.is() ) + return; + + _rGuard.clear(); + try + { + if ( _bStart ) + xStatusIndicator->start( ::rtl::OUString(), (sal_Int32)1000000 ); + else + xStatusIndicator->end(); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + _rGuard.reset(); + // note that |reset| can throw a DisposedException + } + + // ----------------------------------------------------------------------------- + static void lcl_extractStatusIndicator( const ::comphelper::NamedValueCollection& _rArguments, Sequence< Any >& _rCallArgs ) + { + Reference< XStatusIndicator > xStatusIndicator( lcl_extractStatusIndicator( _rArguments ) ); + if ( !xStatusIndicator.is() ) + return; + + sal_Int32 nLength = _rCallArgs.getLength(); + _rCallArgs.realloc( nLength + 1 ); + _rCallArgs[ nLength ] <<= xStatusIndicator; + } + + // ----------------------------------------------------------------------------- + static void lcl_extractAndStartStatusIndicator( const ::comphelper::NamedValueCollection& _rArguments, Reference< XStatusIndicator >& _rxStatusIndicator, + Sequence< Any >& _rCallArgs ) + { + _rxStatusIndicator = lcl_extractStatusIndicator( _rArguments ); + if ( !_rxStatusIndicator.is() ) + return; + + try + { + _rxStatusIndicator->start( ::rtl::OUString(), (sal_Int32)1000000 ); + + sal_Int32 nLength = _rCallArgs.getLength(); + _rCallArgs.realloc( nLength + 1 ); + _rCallArgs[ nLength ] <<= _rxStatusIndicator; + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + // ----------------------------------------------------------------------------- + static Sequence< PropertyValue > lcl_appendFileNameToDescriptor( const ::comphelper::NamedValueCollection& _rDescriptor, const ::rtl::OUString _rURL ) + { + ::comphelper::NamedValueCollection aMutableDescriptor( _rDescriptor ); + if ( _rURL.getLength() ) + { + aMutableDescriptor.put( "FileName", _rURL ); + aMutableDescriptor.put( "URL", _rURL ); + } + return aMutableDescriptor.getPropertyValues(); + } +} + +// ----------------------------------------------------------------------------- +void ODatabaseDocument::impl_setInitialized() +{ + m_eInitState = Initialized; + + // start event notifications + m_aEventNotifier.onDocumentInitialized(); +} + +// ----------------------------------------------------------------------------- +void ODatabaseDocument::impl_reset_nothrow() +{ + try + { + m_pImpl->clearConnections(); + m_pImpl->disposeStorages(); + m_pImpl->resetRootStroage(); + + clearObjectContainer( m_xForms ); + clearObjectContainer( m_xReports ); + clearObjectContainer( m_pImpl->m_xTableDefinitions ); + clearObjectContainer( m_pImpl->m_xCommandDefinitions ); + + m_eInitState = NotInitialized; + + m_pImpl->reset(); + } + catch(const Exception&) + { + DBG_UNHANDLED_EXCEPTION(); + } + m_pImpl->m_bDocumentReadOnly = sal_False; +} + +// ----------------------------------------------------------------------------- +void ODatabaseDocument::impl_import_nolck_throw( const ::comphelper::ComponentContext _rContext, const Reference< XInterface >& _rxTargetComponent, + const ::comphelper::NamedValueCollection& _rResource ) +{ + Sequence< Any > aFilterCreationArgs; + Reference< XStatusIndicator > xStatusIndicator; + lcl_extractAndStartStatusIndicator( _rResource, xStatusIndicator, aFilterCreationArgs ); + + /** property map for import info set */ + comphelper::PropertyMapEntry aExportInfoMap[] = + { + { MAP_LEN( "BaseURI"), 0,&::getCppuType( (::rtl::OUString *)0 ),beans::PropertyAttribute::MAYBEVOID, 0 }, + { MAP_LEN( "StreamName"), 0,&::getCppuType( (::rtl::OUString *)0 ),beans::PropertyAttribute::MAYBEVOID, 0 }, + { NULL, 0, 0, NULL, 0, 0 } + }; + uno::Reference< beans::XPropertySet > xInfoSet( comphelper::GenericPropertySet_CreateInstance( new comphelper::PropertySetInfo( aExportInfoMap ) ) ); + 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 = aFilterCreationArgs.getLength(); + aFilterCreationArgs.realloc(nCount + 1); + aFilterCreationArgs[nCount] <<= xInfoSet; + + Reference< XImporter > xImporter( + _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 ); + Sequence< PropertyValue > aFilterArgs( ODatabaseModelImpl::stripLoadArguments( _rResource ).getPropertyValues() ); + xFilter->filter( aFilterArgs ); + + if ( xStatusIndicator.is() ) + xStatusIndicator->end(); +} + +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseDocument::initNew( ) throw (DoubleInitializationException, IOException, Exception, RuntimeException) +{ + // SYNCHRONIZED -> + DocumentGuard aGuard( *this, DocumentGuard::InitMethod ); + + impl_reset_nothrow(); + + impl_setInitializing(); + + // create a temporary storage + Reference< XStorage > xTempStor( ::comphelper::OStorageHelper::GetTemporaryStorage( + m_pImpl->m_aContext.getLegacyServiceFactory() ) ); + + // store therein + impl_storeToStorage_throw( xTempStor, Sequence< PropertyValue >(), aGuard ); + + // let the impl know we're now based on this storage + m_pImpl->switchToStorage( xTempStor ); + + // for the newly created document, allow document-wide scripting + m_bAllowDocumentScripting = true; + + impl_setInitialized(); + + m_aEventNotifier.notifyDocumentEventAsync( "OnTitleChanged" ); + + impl_setModified_nothrow( sal_False, aGuard ); + // <- SYNCHRONIZED + + m_aEventNotifier.notifyDocumentEvent( "OnCreate" ); + + impl_notifyStorageChange_nolck_nothrow( xTempStor ); +} + +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseDocument::load( const Sequence< PropertyValue >& _Arguments ) throw (DoubleInitializationException, IOException, Exception, RuntimeException) +{ + // SYNCHRONIZED -> + DocumentGuard aGuard( *this, DocumentGuard::InitMethod ); + + impl_reset_nothrow(); + + ::comphelper::NamedValueCollection aResource( _Arguments ); + if ( aResource.has( "FileName" ) && !aResource.has( "URL" ) ) + // FileName is the compatibility name for URL, so we might have clients passing + // a FileName only. However, some of our code works with the URL only, so ensure + // we have one. + aResource.put( "URL", aResource.get( "FileName" ) ); + if ( aResource.has( "URL" ) && !aResource.has( "FileName" ) ) + // similar ... just in case there is legacy code which expects a FileName only + aResource.put( "FileName", aResource.get( "URL" ) ); + + // now that somebody (perhaps) told us an macro execution mode, remember it as + // ImposedMacroExecMode + m_pImpl->setImposedMacroExecMode( + aResource.getOrDefault( "MacroExecutionMode", m_pImpl->getImposedMacroExecMode() ) ); + + impl_setInitializing(); + try + { + aGuard.clear(); + impl_import_nolck_throw( m_pImpl->m_aContext, *this, aResource ); + aGuard.reset(); + } + catch( const Exception& ) + { + impl_reset_nothrow(); + throw; + } + // tell our view monitor that the document has been loaded - this way it will fire the proper + // event (OnLoad instead of OnCreate) later on + m_aViewMonitor.onLoadedDocument(); + + // note that we do *not* call impl_setInitialized() here: The initialization is only complete + // when the XModel::attachResource has been called, not sooner. + + impl_setModified_nothrow( sal_False, aGuard ); + // <- SYNCHRONIZED +} + +// ----------------------------------------------------------------------------- +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 ); +} + +// ----------------------------------------------------------------------------- +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, + // not this bad mis-using of existing interfaces + return sal_False; + // (we do not support macro signatures, so we can ignore this call) + } + + // 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 + // the load call. + impl_setInitialized(); + + // determine whether the document as a whole, or sub documents, have macros. Especially the latter + // controls the availability of our XEmbeddedScripts and XScriptInvocationContext interfaces, and we + // should know this before anybody actually uses the object. + m_bAllowDocumentScripting = ( m_pImpl->determineEmbeddedMacros() != ODatabaseModelImpl::eSubDocumentMacros ); + + _rDocGuard.clear(); + // <- SYNCHRONIZED + m_aEventNotifier.notifyDocumentEvent( "OnLoadFinished" ); + } + + return sal_True; +} + +// ----------------------------------------------------------------------------- +::rtl::OUString SAL_CALL ODatabaseDocument::getURL( ) throw (RuntimeException) +{ + DocumentGuard aGuard( *this, DocumentGuard::MethodWithoutInit ); + return m_pImpl->getURL(); +} + +// ----------------------------------------------------------------------------- +Sequence< PropertyValue > SAL_CALL ODatabaseDocument::getArgs( ) throw (RuntimeException) +{ + DocumentGuard aGuard( *this, DocumentGuard::MethodWithoutInit ); + return m_pImpl->getMediaDescriptor().getPropertyValues(); +} + +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseDocument::connectController( const Reference< XController >& _xController ) throw (RuntimeException) +{ + 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 ) ); + + bool bFirstControllerEver = m_aViewMonitor.onControllerConnected( _xController ); + if ( !bFirstControllerEver ) + return; + + // check/adjust our macro mode. + m_pImpl->checkMacrosOnLoading(); +} + +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseDocument::disconnectController( const Reference< XController >& _xController ) throw (RuntimeException) +{ + bool bNotifyViewClosed = false; + bool bLastControllerGone = false; + bool bIsClosing = false; + + // SYNCHRONIZED -> + { + DocumentGuard aGuard( *this ); + + Controllers::iterator pos = ::std::find( m_aControllers.begin(), m_aControllers.end(), _xController ); + OSL_ENSURE( pos != m_aControllers.end(), "ODatabaseDocument::disconnectController: don't know this controller!" ); + if ( pos != m_aControllers.end() ) + { + m_aControllers.erase( pos ); + bNotifyViewClosed = true; + } + + if ( m_xCurrentController == _xController ) + m_xCurrentController = NULL; + + bLastControllerGone = m_aControllers.empty(); + bIsClosing = m_bClosing; + } + // <- SYNCHRONIZED + + if ( bNotifyViewClosed ) + m_aEventNotifier.notifyDocumentEvent( "OnViewClosed", Reference< XController2 >( _xController, UNO_QUERY ) ); + + if ( bLastControllerGone && !bIsClosing ) + { + // if this was the last view, close the document as a whole + // #i51157# / 2006-03-16 / frank.schoenheit@sun.com + try + { + close( sal_True ); + } + catch( const CloseVetoException& ) + { + // okay, somebody vetoed and took ownership + } + } +} + +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseDocument::lockControllers( ) throw (RuntimeException) +{ + DocumentGuard aGuard( *this ); + + ++m_pImpl->m_nControllerLockCount; +} + +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseDocument::unlockControllers( ) throw (RuntimeException) +{ + DocumentGuard aGuard( *this ); + + --m_pImpl->m_nControllerLockCount; +} + +// ----------------------------------------------------------------------------- +sal_Bool SAL_CALL ODatabaseDocument::hasControllersLocked( ) throw (RuntimeException) +{ + DocumentGuard aGuard( *this ); + + return m_pImpl->m_nControllerLockCount != 0; +} + +// ----------------------------------------------------------------------------- +Reference< XController > SAL_CALL ODatabaseDocument::getCurrentController() throw (RuntimeException) +{ + DocumentGuard aGuard( *this ); + + return m_xCurrentController.is() ? m_xCurrentController : ( m_aControllers.empty() ? Reference< XController >() : *m_aControllers.begin() ); +} + +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseDocument::setCurrentController( const Reference< XController >& _xController ) throw (NoSuchElementException, RuntimeException) +{ + DocumentGuard aGuard( *this ); + + m_xCurrentController = _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) +{ + DocumentGuard aGuard( *this ); + + Reference< XInterface > xRet; + Reference< XSelectionSupplier > xDocView( getCurrentController(), UNO_QUERY ); + if ( xDocView.is() ) + xRet.set(xDocView->getSelection(),UNO_QUERY); + + return xRet; +} +// ----------------------------------------------------------------------------- + +// XStorable +sal_Bool SAL_CALL ODatabaseDocument::hasLocation( ) throw (RuntimeException) +{ + return getLocation().getLength() > 0; +} +// ----------------------------------------------------------------------------- +::rtl::OUString SAL_CALL ODatabaseDocument::getLocation( ) 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) +{ + DocumentGuard aGuard( *this, DocumentGuard::MethodWithoutInit ); + return m_pImpl->m_bDocumentReadOnly; +} +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseDocument::store( ) throw (IOException, RuntimeException) +{ + DocumentGuard aGuard( *this ); + + ::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!" ); + + 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_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 ), + "ODatabaseDocument::impl_storeAs_throw: you introduced a new type which cannot be handled here!" ); + + // if we're in the process of initializing the document (which effectively means it is an implicit + // initialization triggered in storeAsURL), the we do not notify events, since to an observer, the SaveAs + // should not be noticable + bool bIsInitializationProcess = impl_isInitializing(); + + if ( !bIsInitializationProcess ) + { + _rGuard.clear(); + m_aEventNotifier.notifyDocumentEvent( _eType == SAVE ? "OnSave" : "OnSaveAs", NULL, makeAny( _rURL ) ); + _rGuard.reset(); + } + + Reference< XStorage > xNewRootStorage; + // will be non-NULL if our storage changed + + try + { + ModifyLock aLock( *this ); + // ignore all changes of our "modified" state during storing + + sal_Bool bLocationChanged = ( _rURL != m_pImpl->getDocFileLocation() ); + if ( bLocationChanged ) + { + // create storage for target URL + Reference< XStorage > xTargetStorage( impl_createStorageFor_throw( _rURL ) ); + + if ( m_pImpl->isEmbeddedDatabase() ) + m_pImpl->clearConnections(); + + // commit everything + m_pImpl->commitEmbeddedStorage(); + m_pImpl->commitStorages(); + + // copy own storage to target storage + Reference< XStorage > xCurrentStorage( m_pImpl->getRootStorage() ); + if ( xCurrentStorage.is() ) + xCurrentStorage->copyToStorage( xTargetStorage ); + + 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; + } + + // store to current storage + Reference< XStorage > xCurrentStorage( m_pImpl->getOrCreateRootStorage(), UNO_QUERY_THROW ); + Sequence< PropertyValue > aMediaDescriptor( lcl_appendFileNameToDescriptor( _rArguments, _rURL ) ); + impl_storeToStorage_throw( xCurrentStorage, aMediaDescriptor, _rGuard ); + + // success - tell our impl + 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 ) + impl_setInitialized(); + } + catch( const Exception& ) + { + Any aError = ::cppu::getCaughtException(); + + // notify the failure + if ( !bIsInitializationProcess ) + m_aEventNotifier.notifyDocumentEventAsync( _eType == SAVE ? "OnSaveFailed" : "OnSaveAsFailed", NULL, makeAny( _rURL ) ); + + if ( aError.isExtractableTo( ::cppu::UnoType< IOException >::get() ) + || aError.isExtractableTo( ::cppu::UnoType< RuntimeException >::get() ) + ) + { + // allowed to leave + throw; + } + + impl_throwIOExceptionCausedBySave_throw( aError, _rURL ); + } + + // notify the document event + if ( !bIsInitializationProcess ) + m_aEventNotifier.notifyDocumentEventAsync( _eType == SAVE ? "OnSaveDone" : "OnSaveAsDone", NULL, makeAny( _rURL ) ); + + // reset our "modified" flag, and clear the guard + impl_setModified_nothrow( sal_False, _rGuard ); + // <- SYNCHRONIZED + + // notify storage listeners + if ( xNewRootStorage.is() ) + impl_notifyStorageChange_nolck_nothrow( xNewRootStorage ); +} + +// ----------------------------------------------------------------------------- +Reference< XStorage > ODatabaseDocument::impl_createStorageFor_throw( const ::rtl::OUString& _rURL ) const +{ + Reference < ::com::sun::star::ucb::XSimpleFileAccess > xTempAccess; + m_pImpl->m_aContext.createComponent( ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ,xTempAccess); + Reference< io::XStream > xStream = xTempAccess->openFileReadWrite( _rURL ); + Reference< io::XTruncate > xTruncate(xStream,UNO_QUERY); + if ( xTruncate.is() ) + { + xTruncate->truncate(); + } + Sequence<Any> aParam(2); + aParam[0] <<= xStream; + aParam[1] <<= ElementModes::READWRITE | ElementModes::TRUNCATE; + + Reference< XSingleServiceFactory > xStorageFactory( m_pImpl->createStorageFactory(), UNO_SET_THROW ); + return Reference< XStorage >( xStorageFactory->createInstanceWithArguments( aParam ), UNO_QUERY_THROW ); +} + +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseDocument::storeAsURL( const ::rtl::OUString& _rURL, const Sequence< PropertyValue >& _rArguments ) throw (IOException, RuntimeException) +{ + // SYNCHRONIZED -> + DocumentGuard aGuard( *this, DocumentGuard::MethodWithoutInit ); + + // Normally, a document initialization is done via XLoadable::load or XLoadable::initNew. For convenience + // reasons, and to not break existing API clients, it's allowed to call storeAsURL without having initialized + // the document, in which case the initialization will be done implicitly. + bool bImplicitInitialization = !impl_isInitialized(); + // implicit initialization while another initialization is just running is not possible + if ( bImplicitInitialization && impl_isInitializing() ) + throw DoubleInitializationException(); + + if ( bImplicitInitialization ) + impl_setInitializing(); + + try + { + impl_storeAs_throw( _rURL, _rArguments, SAVE_AS, aGuard ); + // <- SYNCHRONIZED + + // impl_storeAs_throw cleared the lock on our mutex, but the below lines need this lock + // SYNCHRONIZED -> + aGuard.reset(); + + // our title might have changed, potentially at least + // Sadly, we cannot check this: Calling getTitle here and now would not deliver + // an up-to-date result, as the call is delegated to our TitleHelper instance, which itself + // updates its title only if it gets the OnSaveAsDone event (which was sent asynchronously + // by impl_storeAs_throw). So, we simply notify always, and also asynchronously + m_aEventNotifier.notifyDocumentEventAsync( "OnTitleChanged" ); + } + catch( const Exception& ) + { + impl_reset_nothrow(); + throw; + } + + if ( bImplicitInitialization ) + m_bAllowDocumentScripting = true; + + aGuard.clear(); + // <- SYNCHRONIZED + + if ( bImplicitInitialization ) + m_aEventNotifier.notifyDocumentEvent( "OnCreate" ); +} + +// ----------------------------------------------------------------------------- +void ODatabaseDocument::impl_storeToStorage_throw( const Reference< XStorage >& _rxTargetStorage, const Sequence< PropertyValue >& _rMediaDescriptor, + DocumentGuard& _rDocGuard ) const +{ + if ( !_rxTargetStorage.is() ) + throw IllegalArgumentException( ::rtl::OUString(), *const_cast< ODatabaseDocument* >( this ), 1 ); + + if ( !m_pImpl.is() ) + throw DisposedException( ::rtl::OUString(), *const_cast< ODatabaseDocument* >( this ) ); + + try + { + // commit everything + m_pImpl->commitEmbeddedStorage(); + m_pImpl->commitStorages(); + + // copy own storage to target storage + if ( impl_isInitialized() ) + { + Reference< XStorage > xCurrentStorage( m_pImpl->getOrCreateRootStorage(), UNO_QUERY_THROW ); + if ( xCurrentStorage != _rxTargetStorage ) + xCurrentStorage->copyToStorage( _rxTargetStorage ); + } + + // write into target storage + ::comphelper::NamedValueCollection aWriteArgs( _rMediaDescriptor ); + lcl_triggerStatusIndicator_throw( aWriteArgs, _rDocGuard, true ); + impl_writeStorage_throw( _rxTargetStorage, aWriteArgs ); + lcl_triggerStatusIndicator_throw( aWriteArgs, _rDocGuard, false ); + + // commit target storage + OSL_VERIFY( tools::stor::commitStorageIfWriteable( _rxTargetStorage ) ); + } + catch( const IOException& ) { throw; } + catch( const RuntimeException& ) { throw; } + catch ( const Exception& e ) + { + throw IOException( e.Message, *const_cast< ODatabaseDocument* >( this ) ); + } +} + +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseDocument::storeToURL( const ::rtl::OUString& _rURL, const Sequence< PropertyValue >& _rArguments ) throw (IOException, RuntimeException) +{ + DocumentGuard aGuard( *this ); + ModifyLock aLock( *this ); + + { + aGuard.clear(); + m_aEventNotifier.notifyDocumentEvent( "OnSaveTo", NULL, makeAny( _rURL ) ); + aGuard.reset(); + } + + try + { + // create storage for target URL + Reference< XStorage > xTargetStorage( impl_createStorageFor_throw( _rURL ) ); + + // extend media descriptor with URL + Sequence< PropertyValue > aMediaDescriptor( lcl_appendFileNameToDescriptor( _rArguments, _rURL ) ); + + // store to this storage + impl_storeToStorage_throw( xTargetStorage, aMediaDescriptor, aGuard ); + } + catch( const Exception& ) + { + Any aError = ::cppu::getCaughtException(); + m_aEventNotifier.notifyDocumentEventAsync( "OnSaveToFailed", NULL, aError ); + + if ( aError.isExtractableTo( ::cppu::UnoType< IOException >::get() ) + || aError.isExtractableTo( ::cppu::UnoType< RuntimeException >::get() ) + ) + { + // allowed to leave + throw; + } + + impl_throwIOExceptionCausedBySave_throw( aError, _rURL ); + } + + m_aEventNotifier.notifyDocumentEventAsync( "OnSaveToDone", NULL, makeAny( _rURL ) ); +} + +// ----------------------------------------------------------------------------- +// XModifyBroadcaster +void SAL_CALL ODatabaseDocument::addModifyListener( const Reference< XModifyListener >& _xListener ) throw (RuntimeException) +{ + DocumentGuard aGuard( *this ); + m_aModifyListeners.addInterface(_xListener); +} + +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseDocument::removeModifyListener( const Reference< XModifyListener >& _xListener ) throw (RuntimeException) +{ + DocumentGuard aGuard( *this ); + m_aModifyListeners.removeInterface(_xListener); +} + +// ----------------------------------------------------------------------------- +// XModifiable +sal_Bool SAL_CALL ODatabaseDocument::isModified( ) throw (RuntimeException) +{ + DocumentGuard aGuard( *this ); + + return m_pImpl->m_bModified; +} + +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseDocument::setModified( sal_Bool _bModified ) throw (PropertyVetoException, RuntimeException) +{ + DocumentGuard aGuard( *this, DocumentGuard::MethodWithoutInit ); + if ( impl_isInitialized() ) + impl_setModified_nothrow( _bModified, aGuard ); + // it's allowed to call setModified without the document being initialized already. In this case, + // we simply ignore the call - when the initialization is finished, the respective code will set + // a proper "modified" flag +} + +// ----------------------------------------------------------------------------- +void ODatabaseDocument::impl_setModified_nothrow( sal_Bool _bModified, DocumentGuard& _rGuard ) +{ + // SYNCHRONIZED -> + bool bModifiedChanged = ( m_pImpl->m_bModified != _bModified ) && ( !m_pImpl->isModifyLocked() ); + + if ( bModifiedChanged ) + { + m_pImpl->m_bModified = _bModified; + m_aEventNotifier.notifyDocumentEventAsync( "OnModifyChanged" ); + } + _rGuard.clear(); + // <- SYNCHRONIZED + + if ( bModifiedChanged ) + { + lang::EventObject aEvent( *this ); + m_aModifyListeners.notifyEach( &XModifyListener::modified, aEvent ); + } +} + +// ----------------------------------------------------------------------------- +// ::com::sun::star::document::XEventBroadcaster +void SAL_CALL ODatabaseDocument::addEventListener(const uno::Reference< document::XEventListener >& _Listener ) throw (uno::RuntimeException) +{ + m_aEventNotifier.addLegacyEventListener( _Listener ); +} + +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseDocument::removeEventListener( const uno::Reference< document::XEventListener >& _Listener ) throw (uno::RuntimeException) +{ + m_aEventNotifier.removeLegacyEventListener( _Listener ); +} + +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseDocument::addDocumentEventListener( const Reference< XDocumentEventListener >& _Listener ) throw (RuntimeException) +{ + m_aEventNotifier.addDocumentEventListener( _Listener ); +} + +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseDocument::removeDocumentEventListener( const Reference< XDocumentEventListener >& _Listener ) throw (RuntimeException) +{ + m_aEventNotifier.removeDocumentEventListener( _Listener ); +} + +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseDocument::notifyDocumentEvent( const ::rtl::OUString& _EventName, const Reference< XController2 >& _ViewController, const Any& _Supplement ) throw (IllegalArgumentException, NoSupportException, RuntimeException) +{ + if ( !_EventName.getLength() ) + throw IllegalArgumentException( ::rtl::OUString(), *this, 1 ); + + // SYNCHRONIZED -> + DocumentGuard aGuard( *this ); + + if ( !DocumentEvents::needsSynchronousNotification( _EventName ) ) + { + m_aEventNotifier.notifyDocumentEventAsync( _EventName, _ViewController, _Supplement ); + return; + } + aGuard.clear(); + // <- SYNCHRONIZED + + m_aEventNotifier.notifyDocumentEvent( _EventName, _ViewController, _Supplement ); +} + +// ----------------------------------------------------------------------------- +Sequence< PropertyValue > SAL_CALL ODatabaseDocument::getPrinter( ) throw (RuntimeException) +{ + DBG_ERROR( "ODatabaseDocument::getPrinter: not supported!" ); + return Sequence< PropertyValue >(); +} + +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseDocument::setPrinter( const Sequence< PropertyValue >& /*aPrinter*/ ) throw (IllegalArgumentException, RuntimeException) +{ + DBG_ERROR( "ODatabaseDocument::setPrinter: not supported!" ); +} + +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseDocument::print( const Sequence< PropertyValue >& /*xOptions*/ ) throw (IllegalArgumentException, RuntimeException) +{ + DBG_ERROR( "ODatabaseDocument::print: not supported!" ); +} + +// ----------------------------------------------------------------------------- +void ODatabaseDocument::impl_reparent_nothrow( const WeakReference< XNameAccess >& _rxContainer ) +{ + Reference< XChild > xChild( _rxContainer.get(), UNO_QUERY ); + if ( xChild.is() ) + xChild->setParent( *this ); +} +// ----------------------------------------------------------------------------- +void ODatabaseDocument::clearObjectContainer( WeakReference< XNameAccess >& _rxContainer) +{ + Reference< XNameAccess > xContainer = _rxContainer; + ::comphelper::disposeComponent( xContainer ); + + Reference< XChild > xChild( _rxContainer.get(),UNO_QUERY ); + if ( xChild.is() ) + xChild->setParent( NULL ); + _rxContainer = Reference< XNameAccess >(); +} +// ----------------------------------------------------------------------------- +Reference< XNameAccess > ODatabaseDocument::impl_getDocumentContainer_throw( ODatabaseModelImpl::ObjectType _eType ) +{ + if ( ( _eType != ODatabaseModelImpl::E_FORM ) && ( _eType != ODatabaseModelImpl::E_REPORT ) ) + throw IllegalArgumentException(); + + bool bFormsContainer = _eType == ODatabaseModelImpl::E_FORM; + + WeakReference< XNameAccess >& rContainerRef( bFormsContainer ? m_xForms : m_xReports ); + Reference< XNameAccess > xContainer = rContainerRef; + if ( !xContainer.is() ) + { + 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; +} + +// ----------------------------------------------------------------------------- +void ODatabaseDocument::impl_closeControllerFrames_nolck_throw( sal_Bool _bDeliverOwnership ) +{ + Controllers aCopy = m_aControllers; + + Controllers::iterator aEnd = aCopy.end(); + for ( Controllers::iterator aIter = aCopy.begin(); aIter != aEnd ; ++aIter ) + { + if ( !aIter->is() ) + continue; + + try + { + Reference< XCloseable> xFrame( (*aIter)->getFrame(), UNO_QUERY ); + if ( xFrame.is() ) + xFrame->close( _bDeliverOwnership ); + } + catch( const CloseVetoException& ) { throw; } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } +} + +// ----------------------------------------------------------------------------- +struct DisposeControllerFrame : public ::std::unary_function< Reference< XController >, void > +{ + void operator()( const Reference< XController >& _rxController ) const + { + try + { + if ( !_rxController.is() ) + return; + + Reference< XFrame > xFrame( _rxController->getFrame() ); + ::comphelper::disposeComponent( xFrame ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + }; +}; + +// ----------------------------------------------------------------------------- +void ODatabaseDocument::impl_disposeControllerFrames_nothrow() +{ + Controllers aCopy; + aCopy.swap( m_aControllers ); // ensure m_aControllers is empty afterwards + ::std::for_each( aCopy.begin(), aCopy.end(), DisposeControllerFrame() ); +} + +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseDocument::close( sal_Bool _bDeliverOwnership ) throw (CloseVetoException, RuntimeException) +{ + // nearly everything below can/must be done without our mutex locked, the below is just for + // the checks for being disposed and the like + // SYNCHRONIZED -> + { + DocumentGuard aGuard( *this ); + m_bClosing = true; + } + // <- SYNCHRONIZED + + try + { + // allow listeners to veto + lang::EventObject aEvent( *this ); + m_aCloseListener.forEach< XCloseListener >( + boost::bind( &XCloseListener::queryClosing, _1, boost::cref( aEvent ), boost::cref( _bDeliverOwnership ) ) ); + + // notify that we're going to unload + m_aEventNotifier.notifyDocumentEvent( "OnPrepareUnload" ); + + impl_closeControllerFrames_nolck_throw( _bDeliverOwnership ); + + m_aCloseListener.notifyEach( &XCloseListener::notifyClosing, (const lang::EventObject&)aEvent ); + + dispose(); + } + catch ( const Exception& ) + { + ::osl::MutexGuard aGuard( m_aMutex ); + m_bClosing = false; + throw; + } + + // SYNCHRONIZED -> + ::osl::MutexGuard aGuard( m_aMutex ); + m_bClosing = false; + // <- SYNCHRONIZED +} +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseDocument::addCloseListener( const Reference< ::com::sun::star::util::XCloseListener >& Listener ) throw (RuntimeException) +{ + DocumentGuard aGuard( *this ); + m_aCloseListener.addInterface(Listener); +} +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseDocument::removeCloseListener( const Reference< ::com::sun::star::util::XCloseListener >& Listener ) throw (RuntimeException) +{ + DocumentGuard aGuard( *this ); + m_aCloseListener.removeInterface(Listener); +} +// ----------------------------------------------------------------------------- +Reference< XNameAccess > SAL_CALL ODatabaseDocument::getFormDocuments( ) throw (RuntimeException) +{ + DocumentGuard aGuard( *this, DocumentGuard::MethodUsedDuringInit ); + return impl_getDocumentContainer_throw( ODatabaseModelImpl::E_FORM ); +} +// ----------------------------------------------------------------------------- +Reference< XNameAccess > SAL_CALL ODatabaseDocument::getReportDocuments( ) throw (RuntimeException) +{ + DocumentGuard aGuard( *this, DocumentGuard::MethodUsedDuringInit ); + return impl_getDocumentContainer_throw( ODatabaseModelImpl::E_REPORT ); +} + +// ----------------------------------------------------------------------------- +void ODatabaseDocument::WriteThroughComponent( const Reference< XComponent >& xComponent, const sal_Char* pStreamName, + const sal_Char* pServiceName, const Sequence< Any >& _rArguments, const Sequence< PropertyValue >& rMediaDesc, + const Reference<XStorage>& _xStorageToSaveTo ) const +{ + OSL_ENSURE( pStreamName, "Need stream name!" ); + OSL_ENSURE( pServiceName, "Need service name!" ); + + // open stream + ::rtl::OUString sStreamName = ::rtl::OUString::createFromAscii( pStreamName ); + Reference< XStream > xStream = _xStorageToSaveTo->openStreamElement( sStreamName, ElementModes::READWRITE | ElementModes::TRUNCATE ); + if ( !xStream.is() ) + return; + + Reference< XOutputStream > xOutputStream( xStream->getOutputStream() ); + OSL_ENSURE( xOutputStream.is(), "Can't create output stream in package!" ); + if ( !xOutputStream.is() ) + return; + + Reference< XSeekable > xSeek( xOutputStream, UNO_QUERY ); + if ( xSeek.is() ) + xSeek->seek(0); + + Reference< XPropertySet > xStreamProp( xOutputStream, UNO_QUERY_THROW ); + xStreamProp->setPropertyValue( INFO_MEDIATYPE, makeAny( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "text/xml" ) ) ) ); + xStreamProp->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Compressed" ) ), makeAny( (sal_Bool)sal_True ) ); + + // write the stuff + WriteThroughComponent( xOutputStream, xComponent, pServiceName, _rArguments, rMediaDesc ); +} + +void ODatabaseDocument::WriteThroughComponent( const Reference< XOutputStream >& xOutputStream, + const Reference< XComponent >& xComponent, const sal_Char* pServiceName, const Sequence< Any >& _rArguments, + const Sequence< PropertyValue >& rMediaDesc ) const +{ + OSL_ENSURE( xOutputStream.is(), "I really need an output stream!" ); + OSL_ENSURE( xComponent.is(), "Need component!" ); + OSL_ENSURE( NULL != pServiceName, "Need component name!" ); + + // get component + Reference< XActiveDataSource > xSaxWriter; + OSL_VERIFY( m_pImpl->m_aContext.createComponent( "com.sun.star.xml.sax.Writer", xSaxWriter ) ); + if ( !xSaxWriter.is() ) + return; + + // connect XML writer to output stream + xSaxWriter->setOutputStream( xOutputStream ); + + // prepare arguments (prepend doc handler to given arguments) + Reference< XDocumentHandler > xDocHandler( xSaxWriter,UNO_QUERY); + Sequence<Any> aArgs( 1 + _rArguments.getLength() ); + aArgs[0] <<= xDocHandler; + for ( sal_Int32 i = 0; i < _rArguments.getLength(); ++i ) + aArgs[ i+1 ] = _rArguments[i]; + + // get filter component + Reference< XExporter > xExporter; + OSL_VERIFY( m_pImpl->m_aContext.createComponentWithArguments( pServiceName, aArgs, xExporter ) ); + if ( !xExporter.is() ) + return; + + // connect model and filter + xExporter->setSourceDocument( xComponent ); + + // filter + Reference< XFilter > xFilter( xExporter, UNO_QUERY_THROW ); + xFilter->filter( rMediaDesc ); +} + +// ----------------------------------------------------------------------------- +void ODatabaseDocument::impl_writeStorage_throw( const Reference< XStorage >& _rxTargetStorage, const ::comphelper::NamedValueCollection& _rMediaDescriptor ) const +{ + // extract status indicator + Sequence< Any > aDelegatorArguments; + lcl_extractStatusIndicator( _rMediaDescriptor, aDelegatorArguments ); + + /** property map for export info set */ + comphelper::PropertyMapEntry aExportInfoMap[] = + { + { MAP_LEN( "BaseURI"), 0,&::getCppuType( (::rtl::OUString *)0 ),beans::PropertyAttribute::MAYBEVOID, 0 }, + { MAP_LEN( "StreamName"), 0,&::getCppuType( (::rtl::OUString *)0 ),beans::PropertyAttribute::MAYBEVOID, 0 }, + { MAP_LEN( "UsePrettyPrinting" ), 0, &::getCppuType((sal_Bool*)0), beans::PropertyAttribute::MAYBEVOID, 0}, + { NULL, 0, 0, NULL, 0, 0 } + }; + uno::Reference< beans::XPropertySet > xInfoSet( comphelper::GenericPropertySet_CreateInstance( new comphelper::PropertySetInfo( aExportInfoMap ) ) ); + + SvtSaveOptions aSaveOpt; + xInfoSet->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("UsePrettyPrinting")), uno::makeAny(aSaveOpt.IsPrettyPrinting())); + if ( aSaveOpt.IsSaveRelFSys() ) + xInfoSet->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("BaseURI")), uno::makeAny(_rMediaDescriptor.getOrDefault("URL",::rtl::OUString()))); + + ::rtl::OUString aVersion; + SvtSaveOptions::ODFDefaultVersion nDefVersion = aSaveOpt.GetODFDefaultVersion(); + + // older versions can not have this property set, it exists only starting from ODF1.2 + if ( nDefVersion >= SvtSaveOptions::ODFVER_012 ) + aVersion = ODFVER_012_TEXT; + + if ( aVersion.getLength() ) + { + try + { + xInfoSet->setPropertyValue( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Version" )), uno::makeAny( aVersion ) ); + } + catch( uno::Exception& ) + { + } + } + + sal_Int32 nArgsLen = aDelegatorArguments.getLength(); + aDelegatorArguments.realloc(nArgsLen+1); + aDelegatorArguments[nArgsLen++] <<= xInfoSet; + + Reference< XPropertySet > xProp( _rxTargetStorage, UNO_QUERY_THROW ); + xProp->setPropertyValue( INFO_MEDIATYPE, makeAny( (rtl::OUString)MIMETYPE_OASIS_OPENDOCUMENT_DATABASE ) ); + + Reference< XComponent > xComponent( *const_cast< ODatabaseDocument* >( this ), UNO_QUERY_THROW ); + + Sequence< PropertyValue > aMediaDescriptor; + _rMediaDescriptor >>= aMediaDescriptor; + + xInfoSet->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("StreamName")), uno::makeAny(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("settings.xml")))); + WriteThroughComponent( xComponent, "settings.xml", "com.sun.star.comp.sdb.XMLSettingsExporter", + aDelegatorArguments, aMediaDescriptor, _rxTargetStorage ); + + xInfoSet->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("StreamName")), uno::makeAny(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("content.xml")))); + WriteThroughComponent( xComponent, "content.xml", "com.sun.star.comp.sdb.DBExportFilter", + aDelegatorArguments, aMediaDescriptor, _rxTargetStorage ); + + m_pImpl->storeLibraryContainersTo( _rxTargetStorage ); +} + +// ----------------------------------------------------------------------------- +Reference< XUIConfigurationManager > SAL_CALL ODatabaseDocument::getUIConfigurationManager( ) throw (RuntimeException) +{ + DocumentGuard aGuard( *this ); + + if ( !m_xUIConfigurationManager.is() ) + { + m_pImpl->m_aContext.createComponent( "com.sun.star.ui.UIConfigurationManager", m_xUIConfigurationManager ); + Reference< XUIConfigurationStorage > xUIConfigStorage( m_xUIConfigurationManager, UNO_QUERY ); + if ( xUIConfigStorage.is() ) + { + rtl::OUString aUIConfigFolderName( RTL_CONSTASCII_USTRINGPARAM( "Configurations2" )); + Reference< XStorage > xConfigStorage; + + // First try to open with READWRITE and then READ + xConfigStorage = getDocumentSubStorage( aUIConfigFolderName, ElementModes::READWRITE ); + if ( xConfigStorage.is() ) + { + rtl::OUString aUIConfigMediaType( RTL_CONSTASCII_USTRINGPARAM( "application/vnd.sun.xml.ui.configuration" )); + rtl::OUString aMediaType; + Reference< XPropertySet > xPropSet( xConfigStorage, UNO_QUERY ); + Any a = xPropSet->getPropertyValue( INFO_MEDIATYPE ); + if ( !( a >>= aMediaType ) || ( aMediaType.getLength() == 0 )) + { + a <<= aUIConfigMediaType; + xPropSet->setPropertyValue( INFO_MEDIATYPE, a ); + } + } + else + xConfigStorage = getDocumentSubStorage( aUIConfigFolderName, ElementModes::READ ); + + // initialize ui configuration manager with document substorage + xUIConfigStorage->setStorage( xConfigStorage ); + } + } + + return m_xUIConfigurationManager; +} +// ----------------------------------------------------------------------------- +Reference< XStorage > SAL_CALL ODatabaseDocument::getDocumentSubStorage( const ::rtl::OUString& aStorageName, sal_Int32 nMode ) throw (RuntimeException) +{ + DocumentGuard aGuard( *this ); + + Reference< XDocumentSubStorageSupplier > xStorageAccess( m_pImpl->getDocumentSubStorageSupplier() ); + return xStorageAccess->getDocumentSubStorage( aStorageName, nMode ); +} +// ----------------------------------------------------------------------------- +Sequence< ::rtl::OUString > SAL_CALL ODatabaseDocument::getDocumentSubStoragesNames( ) throw (::com::sun::star::io::IOException, RuntimeException) +{ + Reference< XDocumentSubStorageSupplier > xStorageAccess( m_pImpl->getDocumentSubStorageSupplier() ); + return xStorageAccess->getDocumentSubStoragesNames(); +} + +//------------------------------------------------------------------------------ +void ODatabaseDocument::impl_notifyStorageChange_nolck_nothrow( const Reference< XStorage >& _rxNewRootStorage ) +{ + Reference< XInterface > xMe( *const_cast< ODatabaseDocument* >( this ) ); + + m_aStorageListeners.forEach< XStorageChangeListener >( + boost::bind( &XStorageChangeListener::notifyStorageChange, _1, boost::cref( xMe ), boost::cref( _rxNewRootStorage ) ) ); +} + +//------------------------------------------------------------------------------ +void ODatabaseDocument::disposing() +{ + OSL_TRACE( "DD: disp: %p: %p", this, m_pImpl.get() ); + if ( !m_pImpl.is() ) + { + // this means that we're already disposed + DBG_ASSERT( ODatabaseDocument_OfficeDocument::rBHelper.bDisposed, "ODatabaseDocument::disposing: no impl anymore, but not yet disposed!" ); + return; + } + + if ( impl_isInitialized() ) + m_aEventNotifier.notifyDocumentEvent( "OnUnload" ); + + Reference< XModel > xHoldAlive( this ); + + m_aEventNotifier.disposing(); + + lang::EventObject aDisposeEvent(static_cast<XWeak*>(this)); + m_aModifyListeners.disposeAndClear( aDisposeEvent ); + m_aCloseListener.disposeAndClear( aDisposeEvent ); + m_aStorageListeners.disposeAndClear( aDisposeEvent ); + + // this is the list of objects which we currently hold as member. Upon resetting + // those members, we can (potentially) release the last reference to them, in which + // case they will be deleted - if they're C++ implementations, that is :). + // Some of those implementations are offending enough to require the SolarMutex, which + // means we should not release the last reference while our own mutex is locked ... + ::std::list< Reference< XInterface > > aKeepAlive; + + // SYNCHRONIZED -> + ::osl::ClearableMutexGuard aGuard( m_aMutex ); + + DBG_ASSERT( m_aControllers.empty(), "ODatabaseDocument::disposing: there still are controllers!" ); + // normally, nobody should explicitly dispose, but only XCloseable::close the document. And upon + // closing, our controllers are closed, too + + aKeepAlive.push_back( m_xUIConfigurationManager ); + m_xUIConfigurationManager = NULL; + + clearObjectContainer( m_xForms ); + clearObjectContainer( m_xReports ); + + // reset the macro mode: in case the our impl struct stays alive (e.g. because our DataSource + // object still exists), and somebody subsequently re-opens the document, we want to have + // the security warning, again. + m_pImpl->resetMacroExecutionMode(); + + // similar argueing for our ViewMonitor + m_aViewMonitor.reset(); + + // tell our Impl to forget us + m_pImpl->modelIsDisposing( impl_isInitialized(), ODatabaseModelImpl::ResetModelAccess() ); + + // now, at the latest, the controller array should be empty. Controllers are + // expected to listen for our disposal, and disconnect then + DBG_ASSERT( m_aControllers.empty(), "ODatabaseDocument::disposing: there still are controllers!" ); + impl_disposeControllerFrames_nothrow(); + + aKeepAlive.push_back( m_xModuleManager ); + m_xModuleManager.clear(); + + aKeepAlive.push_back( m_xTitleHelper ); + m_xTitleHelper.clear(); + + m_pImpl.clear(); + + aGuard.clear(); + // <- SYNCHRONIZED + + aKeepAlive.clear(); +} +// ----------------------------------------------------------------------------- +// XComponent +void SAL_CALL ODatabaseDocument::dispose( ) throw (RuntimeException) +{ + ::cppu::WeakComponentImplHelperBase::dispose(); +} +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseDocument::addEventListener( const Reference< lang::XEventListener >& _xListener ) throw (RuntimeException) +{ + ::cppu::WeakComponentImplHelperBase::addEventListener( _xListener ); +} +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseDocument::removeEventListener( const Reference< lang::XEventListener >& _xListener ) throw (RuntimeException) +{ + ::cppu::WeakComponentImplHelperBase::removeEventListener( _xListener ); +} +// XServiceInfo +//------------------------------------------------------------------------------ +rtl::OUString ODatabaseDocument::getImplementationName( ) throw(RuntimeException) +{ + return getImplementationName_static(); +} + +//------------------------------------------------------------------------------ +rtl::OUString ODatabaseDocument::getImplementationName_static( ) throw(RuntimeException) +{ + return rtl::OUString::createFromAscii("com.sun.star.comp.dba.ODatabaseDocument"); +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > ODatabaseDocument::getSupportedServiceNames( ) throw (RuntimeException) +{ + return getSupportedServiceNames_static(); +} + +//------------------------------------------------------------------------------ +Reference< XInterface > ODatabaseDocument::Create( const Reference< XComponentContext >& _rxContext ) +{ + ::comphelper::ComponentContext aContext( _rxContext ); + Reference< XUnoTunnel > xDBContextTunnel( aContext.createComponent( (::rtl::OUString)SERVICE_SDB_DATABASECONTEXT ), UNO_QUERY_THROW ); + ODatabaseContext* pContext = reinterpret_cast< ODatabaseContext* >( xDBContextTunnel->getSomething( ODatabaseContext::getUnoTunnelImplementationId() ) ); + + ::rtl::Reference<ODatabaseModelImpl> pImpl( new ODatabaseModelImpl( aContext.getLegacyServiceFactory(), *pContext ) ); + Reference< XModel > xModel( pImpl->createNewModel_deliverOwnership( false ) ); + return xModel.get(); +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > ODatabaseDocument::getSupportedServiceNames_static( ) throw (RuntimeException) +{ + Sequence< ::rtl::OUString > aSNS( 2 ); + aSNS[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sdb.OfficeDatabaseDocument")); + aSNS[1] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.document.OfficeDocument")); + return aSNS; +} + +//------------------------------------------------------------------------------ +sal_Bool ODatabaseDocument::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException) +{ + return ::comphelper::findValue(getSupportedServiceNames(), _rServiceName, sal_True).getLength() != 0; +} +// ----------------------------------------------------------------------------- +Reference< XDataSource > SAL_CALL ODatabaseDocument::getDataSource() throw (RuntimeException) +{ + DocumentGuard aGuard( *this, DocumentGuard::MethodWithoutInit ); + return m_pImpl->getOrCreateDataSource(); +} + +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseDocument::loadFromStorage( const Reference< XStorage >& /*xStorage*/, const Sequence< PropertyValue >& /*aMediaDescriptor*/ ) throw (IllegalArgumentException, DoubleInitializationException, IOException, Exception, RuntimeException) +{ + DocumentGuard aGuard( *this ); + + throw Exception( + DBACORE_RESSTRING( RID_STR_NO_EMBEDDING ), + *this + ); +} + +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseDocument::storeToStorage( const Reference< XStorage >& _rxStorage, const Sequence< PropertyValue >& _rMediaDescriptor ) throw (IllegalArgumentException, IOException, Exception, RuntimeException) +{ + DocumentGuard aGuard( *this ); + impl_storeToStorage_throw( _rxStorage, _rMediaDescriptor, aGuard ); +} + +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseDocument::switchToStorage( const Reference< XStorage >& _rxNewRootStorage ) throw (IllegalArgumentException, IOException, Exception, RuntimeException) +{ + DocumentGuard aGuard( *this ); + + Reference< XStorage > xNewRootStorage( m_pImpl->switchToStorage( _rxNewRootStorage ) ); + + aGuard.clear(); + impl_notifyStorageChange_nolck_nothrow( xNewRootStorage ); +} + +// ----------------------------------------------------------------------------- +Reference< XStorage > SAL_CALL ODatabaseDocument::getDocumentStorage( ) throw (IOException, Exception, RuntimeException) +{ + DocumentGuard aGuard( *this ); + return m_pImpl->getOrCreateRootStorage(); +} + +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseDocument::addStorageChangeListener( const Reference< XStorageChangeListener >& _Listener ) throw (RuntimeException) +{ + DocumentGuard aGuard( *this ); + m_aStorageListeners.addInterface( _Listener ); +} + +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseDocument::removeStorageChangeListener( const Reference< XStorageChangeListener >& _Listener ) throw (RuntimeException) +{ + DocumentGuard aGuard( *this ); + m_aStorageListeners.addInterface( _Listener ); +} + +// ----------------------------------------------------------------------------- +Reference< XStorageBasedLibraryContainer > SAL_CALL ODatabaseDocument::getBasicLibraries() throw (RuntimeException) +{ + DocumentGuard aGuard( *this, DocumentGuard::MethodUsedDuringInit ); + return m_pImpl->getLibraryContainer( true ); +} + +// ----------------------------------------------------------------------------- +Reference< XStorageBasedLibraryContainer > SAL_CALL ODatabaseDocument::getDialogLibraries() throw (RuntimeException) +{ + DocumentGuard aGuard( *this ); + return m_pImpl->getLibraryContainer( false ); +} + +// ----------------------------------------------------------------------------- +::sal_Bool SAL_CALL ODatabaseDocument::getAllowMacroExecution() throw (RuntimeException) +{ + DocumentGuard aGuard( *this ); + return m_pImpl->adjustMacroMode_AutoReject(); +} + +// ----------------------------------------------------------------------------- +Reference< XEmbeddedScripts > SAL_CALL ODatabaseDocument::getScriptContainer() throw (RuntimeException) +{ + DocumentGuard aGuard( *this ); + return this; +} + +// ----------------------------------------------------------------------------- +Reference< provider::XScriptProvider > SAL_CALL ODatabaseDocument::getScriptProvider( ) throw (RuntimeException) +{ + DocumentGuard aGuard( *this ); + + Reference< XScriptProvider > xScriptProvider( m_xScriptProvider ); + if ( !xScriptProvider.is() ) + { + Reference < XScriptProviderFactory > xFactory( + m_pImpl->m_aContext.getSingleton( "com.sun.star.script.provider.theMasterScriptProviderFactory" ), UNO_QUERY_THROW ); + + Any aScriptProviderContext; + if ( m_bAllowDocumentScripting ) + aScriptProviderContext <<= Reference< XModel >( this ); + + xScriptProvider.set( xFactory->createScriptProvider( aScriptProviderContext ), UNO_SET_THROW ); + m_xScriptProvider = xScriptProvider; + } + + return xScriptProvider; +} + +// ----------------------------------------------------------------------------- +Reference< XNameReplace > SAL_CALL ODatabaseDocument::getEvents( ) throw (RuntimeException) +{ + DocumentGuard aGuard( *this, DocumentGuard::MethodUsedDuringInit ); + return m_pEventContainer; +} + +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseDocument::disposing( const ::com::sun::star::lang::EventObject& Source ) throw(RuntimeException) +{ + if ( m_pImpl.is() ) + m_pImpl->disposing(Source); +} + +//------------------------------------------------------------------ +Reference< XInterface > ODatabaseDocument::getThis() const +{ + return *const_cast< ODatabaseDocument* >( this ); +} +// ----------------------------------------------------------------------------- +struct CreateAny : public ::std::unary_function< Reference<XController>, Any> +{ + Any operator() (const Reference<XController>& lhs) const + { + return makeAny(lhs); + } +}; + +// XModel2 +Reference< XEnumeration > SAL_CALL ODatabaseDocument::getControllers( ) throw (RuntimeException) +{ + DocumentGuard aGuard( *this ); + uno::Sequence< Any> aController( m_aControllers.size() ); + ::std::transform( m_aControllers.begin(), m_aControllers.end(), aController.getArray(), CreateAny() ); + return new ::comphelper::OAnyEnumeration(aController); +} +// ----------------------------------------------------------------------------- +Sequence< ::rtl::OUString > SAL_CALL ODatabaseDocument::getAvailableViewControllerNames( ) throw (RuntimeException) +{ + Sequence< ::rtl::OUString > aNames(1); + aNames[0] = SERVICE_SDB_APPLICATIONCONTROLLER; + return aNames; +} +// ----------------------------------------------------------------------------- +Reference< XController2 > SAL_CALL ODatabaseDocument::createDefaultViewController( const Reference< XFrame >& _Frame ) throw (IllegalArgumentException, Exception, RuntimeException) +{ + return createViewController( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Default" ) ), + Sequence< PropertyValue >(), + _Frame + ); +} + +// ----------------------------------------------------------------------------- +Reference< XController2 > SAL_CALL ODatabaseDocument::createViewController( const ::rtl::OUString& _ViewName, const Sequence< PropertyValue >& _Arguments, const Reference< XFrame >& _Frame ) throw (IllegalArgumentException, Exception, RuntimeException) +{ + if ( !_ViewName.equalsAscii( "Default" ) && !_ViewName.equalsAscii( "Preview" ) ) + throw IllegalArgumentException( ::rtl::OUString(), *this, 1 ); + if ( !_Frame.is() ) + throw IllegalArgumentException( ::rtl::OUString(), *this, 3 ); + + DocumentGuard aGuard( *this ); + ::comphelper::ComponentContext aContext( m_pImpl->m_aContext ); + aGuard.clear(); + + Reference< XController2 > xController; + aContext.createComponent( "org.openoffice.comp.dbu.OApplicationController", xController ); + + ::comphelper::NamedValueCollection aInitArgs( _Arguments ); + aInitArgs.put( "Frame", _Frame ); + if ( _ViewName.equalsAscii( "Preview" ) ) + aInitArgs.put( "Preview", sal_Bool( sal_True ) ); + Reference< XInitialization > xInitController( xController, UNO_QUERY_THROW ); + xInitController->initialize( aInitArgs.getWrappedPropertyValues() ); + + return xController; +} + +// ----------------------------------------------------------------------------- +//============================================================================= +Reference< XTitle > ODatabaseDocument::impl_getTitleHelper_throw() +{ + if ( ! m_xTitleHelper.is ()) + { + Reference< XUntitledNumbers > xDesktop( + m_pImpl->m_aContext.createComponent( "com.sun.star.frame.Desktop" ), + UNO_QUERY_THROW ); + uno::Reference< frame::XModel > xThis (getThis(), uno::UNO_QUERY_THROW); + + ::framework::TitleHelper* pHelper = new ::framework::TitleHelper(m_pImpl->m_aContext.getLegacyServiceFactory()); + m_xTitleHelper.set(static_cast< ::cppu::OWeakObject* >(pHelper), uno::UNO_QUERY_THROW); + pHelper->setOwner (xThis ); + pHelper->connectWithUntitledNumbers (xDesktop); + } + + return m_xTitleHelper; +} + +//============================================================================= +uno::Reference< frame::XUntitledNumbers > ODatabaseDocument::impl_getUntitledHelper_throw(const uno::Reference< uno::XInterface >& _xComponent) +{ + if ( !m_xModuleManager.is() ) + m_xModuleManager.set( m_pImpl->m_aContext.createComponent( "com.sun.star.frame.ModuleManager" ), UNO_QUERY_THROW ); + + ::rtl::OUString sModuleId; + try + { + sModuleId = m_xModuleManager->identify( _xComponent ); + } + catch(uno::Exception) + { + // ni + } + uno::Reference< frame::XUntitledNumbers > xNumberedControllers; + + TNumberedController::iterator aFind = m_aNumberedControllers.find(sModuleId); + if ( aFind == m_aNumberedControllers.end() ) + { + uno::Reference< frame::XModel > xThis(static_cast< frame::XModel* >(this), uno::UNO_QUERY_THROW); + ::comphelper::NumberedCollection* pHelper = new ::comphelper::NumberedCollection(); + xNumberedControllers.set(static_cast< ::cppu::OWeakObject* >(pHelper), uno::UNO_QUERY_THROW); + + pHelper->setOwner (xThis); + //pHelper->setUntitledPrefix (::rtl::OUString::createFromAscii(" : ")); + + m_aNumberedControllers.insert(TNumberedController::value_type(sModuleId,xNumberedControllers)); + } + else + xNumberedControllers = aFind->second; + + return xNumberedControllers; +} + +//============================================================================= +// css.frame.XTitle +::rtl::OUString SAL_CALL ODatabaseDocument::getTitle() + throw (uno::RuntimeException) +{ + // SYNCHRONIZED -> + DocumentGuard aGuard( *this, DocumentGuard::MethodUsedDuringInit ); + return impl_getTitleHelper_throw()->getTitle(); +} + +//============================================================================= +// css.frame.XTitle +void SAL_CALL ODatabaseDocument::setTitle( const ::rtl::OUString& sTitle ) + throw (uno::RuntimeException) +{ + // SYNCHRONIZED -> + DocumentGuard aGuard( *this ); + impl_getTitleHelper_throw()->setTitle( sTitle ); + m_aEventNotifier.notifyDocumentEventAsync( "OnTitleChanged" ); + // <- SYNCHRONIZED +} + +//============================================================================= +// css.frame.XTitleChangeBroadcaster +void SAL_CALL ODatabaseDocument::addTitleChangeListener( const uno::Reference< frame::XTitleChangeListener >& xListener ) + throw (uno::RuntimeException) +{ + // SYNCHRONIZED -> + DocumentGuard aGuard( *this ); + + uno::Reference< frame::XTitleChangeBroadcaster > xBroadcaster( impl_getTitleHelper_throw(), uno::UNO_QUERY_THROW ); + xBroadcaster->addTitleChangeListener( xListener ); +} + +//============================================================================= +// css.frame.XTitleChangeBroadcaster +void SAL_CALL ODatabaseDocument::removeTitleChangeListener( const uno::Reference< frame::XTitleChangeListener >& xListener ) + throw (uno::RuntimeException) +{ + // SYNCHRONIZED -> + DocumentGuard aGuard( *this ); + + uno::Reference< frame::XTitleChangeBroadcaster > xBroadcaster( impl_getTitleHelper_throw(), uno::UNO_QUERY_THROW ); + xBroadcaster->removeTitleChangeListener( xListener ); +} + +//============================================================================= +// css.frame.XUntitledNumbers +::sal_Int32 SAL_CALL ODatabaseDocument::leaseNumber( const uno::Reference< uno::XInterface >& xComponent ) + throw (lang::IllegalArgumentException, + uno::RuntimeException ) +{ + DocumentGuard aGuard( *this ); + return impl_getUntitledHelper_throw(xComponent)->leaseNumber (xComponent); +} + +//============================================================================= +// css.frame.XUntitledNumbers +void SAL_CALL ODatabaseDocument::releaseNumber( ::sal_Int32 nNumber ) + throw (lang::IllegalArgumentException, + uno::RuntimeException ) +{ + DocumentGuard aGuard( *this ); + impl_getUntitledHelper_throw()->releaseNumber (nNumber); +} + +//============================================================================= +// css.frame.XUntitledNumbers +void SAL_CALL ODatabaseDocument::releaseNumberForComponent( const uno::Reference< uno::XInterface >& xComponent ) + throw (lang::IllegalArgumentException, + uno::RuntimeException ) +{ + DocumentGuard aGuard( *this ); + impl_getUntitledHelper_throw(xComponent)->releaseNumberForComponent (xComponent); +} + +//============================================================================= +// css.frame.XUntitledNumbers +::rtl::OUString SAL_CALL ODatabaseDocument::getUntitledPrefix() throw (uno::RuntimeException) +{ + return ::rtl::OUString();/*RTL_CONSTASCII_USTRINGPARAM(" : "));*/ +} + +//------------------------------------------------------------------ +//........................................................................ +} // namespace dbaccess +//........................................................................ + + diff --git a/dbaccess/source/core/dataaccess/databasedocument.hxx b/dbaccess/source/core/dataaccess/databasedocument.hxx new file mode 100644 index 000000000000..d2aa57130d18 --- /dev/null +++ b/dbaccess/source/core/dataaccess/databasedocument.hxx @@ -0,0 +1,709 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 _DBA_COREDATAACCESS_DATABASEDOCUMENT_HXX_ +#define _DBA_COREDATAACCESS_DATABASEDOCUMENT_HXX_ + +#include "ModelImpl.hxx" +#include "documenteventnotifier.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp> +#include <com/sun/star/document/XDocumentSubStorageSupplier.hpp> +#include <com/sun/star/frame/XModel2.hpp> +#include <com/sun/star/frame/XTitle.hpp> +#include <com/sun/star/frame/XTitleChangeBroadcaster.hpp> +#include <com/sun/star/frame/XUntitledNumbers.hpp> +#include <com/sun/star/util/XModifiable.hpp> +#include <com/sun/star/frame/XStorable.hpp> +#include <com/sun/star/sdb/XReportDocumentsSupplier.hpp> +#include <com/sun/star/sdb/XFormDocumentsSupplier.hpp> +#include <com/sun/star/util/XCloseable.hpp> +#include <com/sun/star/view/XPrintable.hpp> +#include <com/sun/star/frame/XModuleManager.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/sdb/XOfficeDatabaseDocument.hpp> +#include <com/sun/star/embed/XTransactionListener.hpp> +#include <com/sun/star/document/XStorageBasedDocument.hpp> +#include <com/sun/star/document/XEmbeddedScripts.hpp> +#include <com/sun/star/document/XEventsSupplier.hpp> +#include <com/sun/star/document/XScriptInvocationContext.hpp> +#include <com/sun/star/script/XStorageBasedLibraryContainer.hpp> +#include <com/sun/star/script/provider/XScriptProviderSupplier.hpp> +#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_17) +#define INCLUDED_COMPHELPER_IMPLBASE_VAR_HXX_17 +#define COMPHELPER_IMPLBASE_INTERFACE_NUMBER 17 +#include <comphelper/implbase_var.hxx> +#endif + +#include <cppuhelper/compbase10.hxx> +#include <cppuhelper/implbase3.hxx> +#include <rtl/ref.hxx> + +#include <boost/shared_ptr.hpp> +#include <boost/noncopyable.hpp> + +namespace comphelper { + class NamedValueCollection; +} + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + +class DocumentEvents; +class DocumentEventExecutor; +class DocumentGuard; + +typedef ::std::vector< ::com::sun::star::uno::Reference< ::com::sun::star::frame::XController > > Controllers; + +//============================================================ +//= ViewMonitor +//============================================================ +/** helper class monitoring the views of a document, and firing appropriate events + when views are attached / detached +*/ +class ViewMonitor : public boost::noncopyable +{ +public: + ViewMonitor( DocumentEventNotifier& _rEventNotifier ) + :m_rEventNotifier( _rEventNotifier ) + ,m_bIsNewDocument( true ) + ,m_bEverHadController( false ) + ,m_bLastIsFirstEverController( false ) + ,m_xLastConnectedController() + { + } + + void reset() + { + m_bEverHadController = false; + m_bLastIsFirstEverController = false; + m_xLastConnectedController.clear(); + } + + /** to be called when a view (aka controller) has been connected to the document + @return + <TRUE/> if and only if this was the first-ever controller connected to the document + */ + bool onControllerConnected( + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XController >& _rxController + ); + + /** 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. + */ + bool onSetCurrentController( + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XController >& _rxController + ); + + void onLoadedDocument() { m_bIsNewDocument = false; } + +private: + DocumentEventNotifier& m_rEventNotifier; + bool m_bIsNewDocument; + bool m_bEverHadController; + bool m_bLastIsFirstEverController; + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XController > + m_xLastConnectedController; +}; + +//============================================================ +//= ODatabaseDocument +//============================================================ +typedef ::comphelper::WeakComponentImplHelper17 < ::com::sun::star::frame::XModel2 + , ::com::sun::star::util::XModifiable + , ::com::sun::star::frame::XStorable + , ::com::sun::star::document::XEventBroadcaster + , ::com::sun::star::document::XDocumentEventBroadcaster + , ::com::sun::star::view::XPrintable + , ::com::sun::star::util::XCloseable + , ::com::sun::star::lang::XServiceInfo + , ::com::sun::star::sdb::XOfficeDatabaseDocument + , ::com::sun::star::ui::XUIConfigurationManagerSupplier + , ::com::sun::star::document::XStorageBasedDocument + , ::com::sun::star::document::XEmbeddedScripts + , ::com::sun::star::document::XScriptInvocationContext + , ::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 + , ::com::sun::star::frame::XTitleChangeBroadcaster + , ::com::sun::star::frame::XUntitledNumbers + > ODatabaseDocument_Title; + +class ODatabaseDocument :public ModelDependentComponent // ModelDependentComponent must be first! + ,public ODatabaseDocument_OfficeDocument + ,public ODatabaseDocument_Title +{ + enum InitState + { + NotInitialized, + Initializing, + Initialized + }; + + DECLARE_STL_USTRINGACCESS_MAP(::com::sun::star::uno::Reference< ::com::sun::star::frame::XUntitledNumbers >,TNumberedController); + ::com::sun::star::uno::Reference< ::com::sun::star::ui::XUIConfigurationManager> m_xUIConfigurationManager; + + ::cppu::OInterfaceContainerHelper m_aModifyListeners; + ::cppu::OInterfaceContainerHelper m_aCloseListener; + ::cppu::OInterfaceContainerHelper m_aStorageListeners; + + DocumentEvents* m_pEventContainer; + ::rtl::Reference< DocumentEventExecutor > m_pEventExecutor; + DocumentEventNotifier m_aEventNotifier; + + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XController > m_xCurrentController; + Controllers m_aControllers; + ViewMonitor m_aViewMonitor; + + ::com::sun::star::uno::WeakReference< ::com::sun::star::container::XNameAccess > m_xForms; + ::com::sun::star::uno::WeakReference< ::com::sun::star::container::XNameAccess > m_xReports; + ::com::sun::star::uno::WeakReference< ::com::sun::star::script::provider::XScriptProvider > m_xScriptProvider; + + /** @short such module manager is used to classify new opened documents. */ + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModuleManager > m_xModuleManager; + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XTitle > m_xTitleHelper; + TNumberedController m_aNumberedControllers; + + /** true if and only if the DatabaseDocument's "initNew" or "load" have been called (or, well, + the document has be initialized implicitly - see storeAsURL + */ + 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 + the modified flag, and notifies any listeners as required + + @param _rURL + the URL to store the document to + @param _rArguments + arguments for storing the document (MediaDescriptor) + @param _eType + the type of the store process (Save or SaveAs). The method will automatically + notify the proper events for this type. + @param _rGuard + the instance lock to be released before doing synchronous notifications + */ + void impl_storeAs_throw( + const ::rtl::OUString& _rURL, + const ::comphelper::NamedValueCollection& _rArguments, + const StoreType _eType, + DocumentGuard& _rGuard + ) + throw ( ::com::sun::star::io::IOException + , ::com::sun::star::uno::RuntimeException ); + + /** notifies our storage change listeners that our underlying storage changed + + @param _rxNewRootStorage + the new root storage to be notified. If <NULL/>, it is assumed that no storage change actually + happened, and the listeners are not notified. + */ + void impl_notifyStorageChange_nolck_nothrow( + const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& _rxNewRootStorage + ); + + /// write a single XML stream into the package + void WriteThroughComponent( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > & xComponent, /// the component we export + const sal_Char* pStreamName, /// the stream name + const sal_Char* pServiceName, /// service name of the component + const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any> & rArguments, /// the argument (XInitialization) + const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue> & rMediaDesc,/// output descriptor + const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& _xStorageToSaveTo + ) const; + + + /// write a single output stream + /// (to be called either directly or by WriteThroughComponent(...)) + void WriteThroughComponent( + const ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream >& xOutputStream, + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent >& xComponent, + const sal_Char* pServiceName, + const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& rArguments, + const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue> & rMediaDesc + ) const; + + /** writes the content and settings + @param sURL + The URL + @param lArguments + The media descriptor + @param _xStorageToSaveTo + The storage which should be used for saving + */ + void impl_writeStorage_throw( + const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& _rxTargetStorage, + const ::comphelper::NamedValueCollection& _rMediaDescriptor + ) const; + + // ModelDependentComponent overridables + virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > getThis() const; + + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XTitle > impl_getTitleHelper_throw(); + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XUntitledNumbers > impl_getUntitledHelper_throw( + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _xComponent = ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >()); + +private: + ODatabaseDocument(const ::rtl::Reference<ODatabaseModelImpl>& _pImpl); + // Do NOT create those documents directly, always use ODatabaseModelImpl::getModel. Reason is that + // ODatabaseDocument requires clear ownership, and in turn lifetime synchronisation with the ModelImpl. + // If you create a ODatabaseDocument directly, you might easily create a leak. + // #i50905# / 2005-06-20 / frank.schonheit@sun.com + +protected: + virtual void SAL_CALL disposing(); + + virtual ~ODatabaseDocument(); + +public: + struct FactoryAccess { friend class ODatabaseModelImpl; private: FactoryAccess() { } }; + static ODatabaseDocument* createDatabaseDocument( const ::rtl::Reference<ODatabaseModelImpl>& _pImpl, FactoryAccess /*accessControl*/ ) + { + return new ODatabaseDocument( _pImpl ); + } + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw(::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::lang::XServiceInfo - static methods + static ::com::sun::star::uno::Sequence< ::rtl::OUString > getSupportedServiceNames_static(void) throw( ::com::sun::star::uno::RuntimeException ); + static ::rtl::OUString getImplementationName_static(void) throw( ::com::sun::star::uno::RuntimeException ); + static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > + SAL_CALL Create(const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >&); + + // XInterface + virtual ::com::sun::star::uno::Any SAL_CALL queryInterface(const ::com::sun::star::uno::Type& _rType) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL acquire( ) throw (); + virtual void SAL_CALL release( ) throw (); + + // XTypeProvider + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId( ) 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); + + // XComponent + virtual void SAL_CALL dispose( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& aListener ) throw (::com::sun::star::uno::RuntimeException); + + // XModel + virtual sal_Bool SAL_CALL attachResource( const ::rtl::OUString& URL, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& Arguments ) throw (::com::sun::star::uno::RuntimeException) ; + virtual ::rtl::OUString SAL_CALL getURL( ) throw (::com::sun::star::uno::RuntimeException) ; + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > SAL_CALL getArgs( ) throw (::com::sun::star::uno::RuntimeException) ; + virtual void SAL_CALL connectController( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XController >& Controller ) throw (::com::sun::star::uno::RuntimeException) ; + virtual void SAL_CALL disconnectController( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XController >& Controller ) throw (::com::sun::star::uno::RuntimeException) ; + virtual void SAL_CALL lockControllers( ) throw (::com::sun::star::uno::RuntimeException) ; + virtual void SAL_CALL unlockControllers( ) throw (::com::sun::star::uno::RuntimeException) ; + virtual sal_Bool SAL_CALL hasControllersLocked( ) throw (::com::sun::star::uno::RuntimeException) ; + virtual ::com::sun::star::uno::Reference< ::com::sun::star::frame::XController > SAL_CALL getCurrentController( ) throw (::com::sun::star::uno::RuntimeException) ; + virtual void SAL_CALL setCurrentController( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XController >& Controller ) throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException) ; + virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL getCurrentSelection( ) throw (::com::sun::star::uno::RuntimeException) ; + + // XModel2 + virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XEnumeration > SAL_CALL getControllers( ) throw (::com::sun::star::uno::RuntimeException) ; + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getAvailableViewControllerNames( ) throw (::com::sun::star::uno::RuntimeException) ; + virtual ::com::sun::star::uno::Reference< ::com::sun::star::frame::XController2 > SAL_CALL createDefaultViewController( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& Frame ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) ; + virtual ::com::sun::star::uno::Reference< ::com::sun::star::frame::XController2 > SAL_CALL createViewController( const ::rtl::OUString& ViewName, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& Arguments, const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& Frame ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) ; + + // XStorable + virtual sal_Bool SAL_CALL hasLocation( ) throw (::com::sun::star::uno::RuntimeException) ; + virtual ::rtl::OUString SAL_CALL getLocation( ) throw (::com::sun::star::uno::RuntimeException) ; + virtual sal_Bool SAL_CALL isReadonly( ) throw (::com::sun::star::uno::RuntimeException) ; + virtual void SAL_CALL store( ) throw (::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException) ; + virtual void SAL_CALL storeAsURL( const ::rtl::OUString& sURL, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lArguments ) throw (::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException) ; + virtual void SAL_CALL storeToURL( const ::rtl::OUString& sURL, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lArguments ) throw (::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException) ; + + // XModifyBroadcaster + virtual void SAL_CALL addModifyListener( const ::com::sun::star::uno::Reference< ::com::sun::star::util::XModifyListener >& aListener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeModifyListener( const ::com::sun::star::uno::Reference< ::com::sun::star::util::XModifyListener >& aListener ) throw (::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::util::XModifiable + virtual sal_Bool SAL_CALL isModified( ) throw (::com::sun::star::uno::RuntimeException) ; + virtual void SAL_CALL setModified( sal_Bool bModified ) throw (::com::sun::star::beans::PropertyVetoException, ::com::sun::star::uno::RuntimeException) ; + + // XEventBroadcaster + virtual void SAL_CALL addEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::document::XEventListener >& aListener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::document::XEventListener >& aListener ) throw (::com::sun::star::uno::RuntimeException); + + // XDocumentEventBroadcaster + virtual void SAL_CALL addDocumentEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::document::XDocumentEventListener >& _Listener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeDocumentEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::document::XDocumentEventListener >& _Listener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL notifyDocumentEvent( const ::rtl::OUString& _EventName, const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XController2 >& _ViewController, const ::com::sun::star::uno::Any& _Supplement ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException); + + // XPrintable + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > SAL_CALL getPrinter( ) throw (::com::sun::star::uno::RuntimeException) ; + virtual void SAL_CALL setPrinter( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aPrinter ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) ; + virtual void SAL_CALL print( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& xOptions ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) ; + + // XFormDocumentsSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > SAL_CALL getFormDocuments( ) throw (::com::sun::star::uno::RuntimeException); + + // XReportDocumentsSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > SAL_CALL getReportDocuments( ) throw (::com::sun::star::uno::RuntimeException); + + // XCloseable + virtual void SAL_CALL close( sal_Bool DeliverOwnership ) throw (::com::sun::star::util::CloseVetoException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addCloseListener( const ::com::sun::star::uno::Reference< ::com::sun::star::util::XCloseListener >& Listener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeCloseListener( const ::com::sun::star::uno::Reference< ::com::sun::star::util::XCloseListener >& Listener ) throw (::com::sun::star::uno::RuntimeException); + + // XUIConfigurationManagerSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::ui::XUIConfigurationManager > SAL_CALL getUIConfigurationManager( ) throw (::com::sun::star::uno::RuntimeException); + + // XDocumentSubStorageSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage > SAL_CALL getDocumentSubStorage( const ::rtl::OUString& aStorageName, sal_Int32 nMode ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getDocumentSubStoragesNames( ) throw (::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + + // XOfficeDatabaseDocument + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XDataSource > SAL_CALL getDataSource() throw (::com::sun::star::uno::RuntimeException); + + // XStorageBasedDocument + virtual void SAL_CALL loadFromStorage( const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aMediaDescriptor ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::frame::DoubleInitializationException, ::com::sun::star::io::IOException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL storeToStorage( const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aMediaDescriptor ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::io::IOException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL switchToStorage( const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::io::IOException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage > SAL_CALL getDocumentStorage( ) throw (::com::sun::star::io::IOException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addStorageChangeListener( const ::com::sun::star::uno::Reference< ::com::sun::star::document::XStorageChangeListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeStorageChangeListener( const ::com::sun::star::uno::Reference< ::com::sun::star::document::XStorageChangeListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + + // XEmbeddedScripts + virtual ::com::sun::star::uno::Reference< ::com::sun::star::script::XStorageBasedLibraryContainer > SAL_CALL getBasicLibraries() throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::script::XStorageBasedLibraryContainer > SAL_CALL getDialogLibraries() throw (::com::sun::star::uno::RuntimeException); + virtual ::sal_Bool SAL_CALL getAllowMacroExecution() throw (::com::sun::star::uno::RuntimeException); + + // XScriptInvocationContext + virtual ::com::sun::star::uno::Reference< ::com::sun::star::document::XEmbeddedScripts > SAL_CALL getScriptContainer() throw (::com::sun::star::uno::RuntimeException); + + // XScriptProviderSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::script::provider::XScriptProvider > SAL_CALL getScriptProvider( ) throw (::com::sun::star::uno::RuntimeException); + + // XEventsSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameReplace > SAL_CALL getEvents( ) throw (::com::sun::star::uno::RuntimeException); + + // XLoadable + 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); + + // XTitleChangeBroadcaster + virtual void SAL_CALL addTitleChangeListener( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XTitleChangeListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeTitleChangeListener( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XTitleChangeListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + + // XUntitledNumbers + virtual ::sal_Int32 SAL_CALL leaseNumber( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& xComponent ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL releaseNumber( ::sal_Int32 nNumber ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL releaseNumberForComponent( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& xComponent ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getUntitledPrefix( ) throw (::com::sun::star::uno::RuntimeException); + + /** clears the given object container + + Clearing is done via disposal - the method calls XComponent::dispose at the given object, + which must be one of our impl's or our object containers (m_xForms, m_xReports, + m_xTableDefinitions, m_xCommandDefinitions) + + @param _rxContainer + the container to clear + */ + static void clearObjectContainer( + ::com::sun::star::uno::WeakReference< ::com::sun::star::container::XNameAccess >& _rxContainer); + + /** checks whether the component is already initialized, throws a NotInitializedException if not + */ + inline void checkInitialized() const + { + if ( !impl_isInitialized() ) + throw ::com::sun::star::lang::NotInitializedException( ::rtl::OUString(), getThis() ); + } + + /** checks the document is currently in the initialization phase, or already initialized. + Throws NotInitializedException if not so. + */ + inline void checkNotUninitilized() const + { + if ( impl_isInitialized() || impl_isInitializing() ) + // fine + return; + + throw ::com::sun::star::lang::NotInitializedException( ::rtl::OUString(), getThis() ); + } + + /** checks whether the document is currently being initialized, or already initialized, + throws a DoubleInitializationException if so + */ + inline void checkNotInitialized() const + { + if ( impl_isInitializing() || impl_isInitialized() ) + throw ::com::sun::star::frame::DoubleInitializationException( ::rtl::OUString(), getThis() ); + } + +private: + /** returns whether the model is currently being initialized + */ + bool impl_isInitializing() const { return m_eInitState == Initializing; } + + /** returns whether the model is already initialized, i.e. the XModel's "initNew" or "load" methods have been called + */ + bool impl_isInitialized() const { return m_eInitState == Initialized; } + + /// tells the model it is being initialized now + void impl_setInitializing() { m_eInitState = Initializing; } + + /// tells the model its initialization is done + void impl_setInitialized(); + + /** closes the frames of all connected controllers + + @param _bDeliverOwnership + determines if the ownership should be transfered to the component which + possibly vetos the closing + + @raises ::com::sun::star::util::CloseVetoException + if the closing was vetoed by any instance + */ + void impl_closeControllerFrames_nolck_throw( sal_Bool _bDeliverOwnership ); + + /** disposes the frames of all controllers which are still left in m_aControllers. + */ + void impl_disposeControllerFrames_nothrow(); + + /** does a reparenting at the given object container to ourself + + Calls XChild::setParent at the given object, which must be one of our impl's or our + object containers (m_xForms, m_xReports, m_xTableDefinitions, m_xCommandDefinitions) + */ + void impl_reparent_nothrow( const ::com::sun::star::uno::WeakReference< ::com::sun::star::container::XNameAccess >& _rxContainer ); + + /** retrieves the forms or reports contained, creates and initializes it, if necessary + + @raises DisposedException + if the instance is already disposed + @raises IllegalArgumentException + if <arg>_eType</arg> is not ODatabaseModelImpl::E_FORM and not ODatabaseModelImpl::E_REPORT + */ + ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > + impl_getDocumentContainer_throw( ODatabaseModelImpl::ObjectType _eType ); + + /** resets everything + + @precond + m_pImpl is not <NULLL/> + */ + void + impl_reset_nothrow(); + + /** imports the document from the given resource. + */ + static void + impl_import_nolck_throw( + const ::comphelper::ComponentContext _rContext, + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxTargetComponent, + const ::comphelper::NamedValueCollection& _rResource + ); + + /** creates a storage for the given URL, truncating it if a file with this name already exists + + @throws Exception + if creating the storage failed + + @return + the newly created storage for the file at the given URL + */ + ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage > + impl_createStorageFor_throw( + const ::rtl::OUString& _rURL + ) const; + + /** sets our "modified" flag + + will notify all our respective listeners, if the "modified" state actually changed + + @param _bModified + the (new) flag indicating whether the document is currently modified or not + @param _rGuard + the guard for our instance. At method entry, the guard must hold the lock. At the moment + of method leave, the lock will be released. + @precond + our mutex is locked + @postcond + our mutex is not locked + */ + void impl_setModified_nothrow( sal_Bool _bModified, DocumentGuard& _rGuard ); + + /** stores the document to the given storage + + Note that the document is actually not rebased to this storage, it just stores a copy of itself + to the given target storage. + + @param _rxTargetStorage + denotes the storage to store the document into + @param _rMediaDescriptor + contains additional parameters for storing the document + @param _rDocGuard + a guard which holds the (only) lock to the document, and which will be temporarily + released where necessary (e.g. for notifications, or calling into other components) + + @throws ::com::sun::star::uno::IllegalArgumentException + if the given storage is <NULL/>. + + @throws ::com::sun::star::uno::RuntimeException + when any of the used operations throws it + + @throws ::com::sun::star::io::IOException + when any of the used operations throws it, or any other exception occurs which is no + RuntimeException and no IOException + */ + void impl_storeToStorage_throw( + const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& _rxTargetStorage, + 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 + of the document +*/ +class DocumentGuard : private ModelMethodGuard +{ +public: + enum MethodType + { + // a method which is to initialize the document + InitMethod, + // a default method + DefaultMethod, + // a method which is used (externally) during the initialization phase + MethodUsedDuringInit, + // a method which does not need initialization - use with care! + MethodWithoutInit + }; + + /** constructs the guard + + @param _document + the ODatabaseDocument instance + + @throws ::com::sun::star::lang::DisposedException + If the given component is already disposed + + @throws ::com::sun::star::frame::DoubleInitializationException + if _eType is InitMethod, and the given component is already initialized, or currently being initialized. + + @throws ::com::sun::star::lang::NotInitializedException + if _eType is DefaultMethod, and the given component is not yet initialized; or if _eType + is MethodUsedDuringInit, and the component is still uninitialized, and not in the initialization + phase currently. + */ + DocumentGuard( const ODatabaseDocument& _document, MethodType _eType = DefaultMethod ) + :ModelMethodGuard( _document ) + ,m_document( _document ) + { + switch ( _eType ) + { + case InitMethod: m_document.checkNotInitialized(); break; + case DefaultMethod: m_document.checkInitialized(); break; + case MethodUsedDuringInit: m_document.checkNotUninitilized(); break; + case MethodWithoutInit: break; + } + } + + ~DocumentGuard() + { + } + + void clear() + { + ModelMethodGuard::clear(); + } + void reset() + { + ModelMethodGuard::reset(); + m_document.checkDisposed(); + } + +private: + + const ODatabaseDocument& m_document; +}; + +//........................................................................ +} // namespace dbaccess +//........................................................................ +#endif // _DBA_COREDATAACCESS_DATABASEDOCUMENT_HXX_ diff --git a/dbaccess/source/core/dataaccess/databaseregistrations.cxx b/dbaccess/source/core/dataaccess/databaseregistrations.cxx new file mode 100644 index 000000000000..6a8e7db21236 --- /dev/null +++ b/dbaccess/source/core/dataaccess/databaseregistrations.cxx @@ -0,0 +1,399 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * +************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/sdb/XDatabaseRegistrations.hpp> +/** === end UNO includes === **/ + +#include <comphelper/componentcontext.hxx> +#include <cppuhelper/basemutex.hxx> +#include <cppuhelper/interfacecontainer.hxx> +#include <cppuhelper/implbase1.hxx> +#include <rtl/ustrbuf.hxx> +#include <unotools/pathoptions.hxx> +#include <tools/urlobj.hxx> +#include <unotools/confignode.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::container::NoSuchElementException; + using ::com::sun::star::lang::IllegalArgumentException; + using ::com::sun::star::lang::IllegalAccessException; + using ::com::sun::star::container::ElementExistException; + using ::com::sun::star::sdb::XDatabaseRegistrations; + using ::com::sun::star::sdb::XDatabaseRegistrationsListener; + using ::com::sun::star::sdb::DatabaseRegistrationEvent; + using ::com::sun::star::uno::XAggregation; + /** === end UNO using === **/ + + //-------------------------------------------------------------------- + static const ::rtl::OUString& getConfigurationRootPath() + { + static ::rtl::OUString s_sNodeName = ::rtl::OUString::createFromAscii("org.openoffice.Office.DataAccess/RegisteredNames"); + return s_sNodeName; + } + + //-------------------------------------------------------------------- + const ::rtl::OUString& getLocationNodeName() + { + static ::rtl::OUString s_sNodeName = ::rtl::OUString::createFromAscii( "Location" ); + return s_sNodeName; + } + + //-------------------------------------------------------------------- + const ::rtl::OUString& getNameNodeName() + { + static ::rtl::OUString s_sNodeName = ::rtl::OUString::createFromAscii( "Name" ); + return s_sNodeName; + } + + //==================================================================== + //= DatabaseRegistrations - declaration + //==================================================================== + typedef ::cppu::WeakAggImplHelper1 < XDatabaseRegistrations + > DatabaseRegistrations_Base; + class DatabaseRegistrations :public ::cppu::BaseMutex + ,public DatabaseRegistrations_Base + { + public: + DatabaseRegistrations( const ::comphelper::ComponentContext& _rxContext ); + + protected: + ~DatabaseRegistrations(); + + public: + virtual ::sal_Bool SAL_CALL hasRegisteredDatabase( const ::rtl::OUString& _Name ) throw (IllegalArgumentException, RuntimeException); + virtual Sequence< ::rtl::OUString > SAL_CALL getRegistrationNames() throw (RuntimeException); + virtual ::rtl::OUString SAL_CALL getDatabaseLocation( const ::rtl::OUString& _Name ) throw (IllegalArgumentException, NoSuchElementException, RuntimeException); + virtual void SAL_CALL registerDatabaseLocation( const ::rtl::OUString& _Name, const ::rtl::OUString& _Location ) throw (IllegalArgumentException, ElementExistException, RuntimeException); + virtual void SAL_CALL revokeDatabaseLocation( const ::rtl::OUString& _Name ) throw (IllegalArgumentException, NoSuchElementException, IllegalAccessException, RuntimeException); + virtual void SAL_CALL changeDatabaseLocation( const ::rtl::OUString& Name, const ::rtl::OUString& NewLocation ) throw (IllegalArgumentException, NoSuchElementException, IllegalAccessException, RuntimeException); + virtual ::sal_Bool SAL_CALL isDatabaseRegistrationReadOnly( const ::rtl::OUString& _Name ) throw (IllegalArgumentException, NoSuchElementException, RuntimeException); + virtual void SAL_CALL addDatabaseRegistrationsListener( const Reference< XDatabaseRegistrationsListener >& Listener ) throw (RuntimeException); + virtual void SAL_CALL removeDatabaseRegistrationsListener( const Reference< XDatabaseRegistrationsListener >& Listener ) throw (RuntimeException); + + private: + ::utl::OConfigurationNode + impl_checkValidName_throw( const ::rtl::OUString& _rName, const bool _bMustExist ); + + void impl_checkValidLocation_throw( const ::rtl::OUString& _rLocation ); + + /** retrieves the configuration node whose "Name" sub node has the given value + + Since we separated the name of the registration node from the "Name" value of the registration, we cannot + simply do a "getByName" (equivalent) when we want to retrieve the node for a given registration name. + Instead, we must search all nodes. + + If _bMustExist is <TRUE/>, and a node with the given display name does not exist, then a NoSuchElementException + is thrown. + + If _bMustExist is <FALSE/>, and a node with the given name already exists, then a ElementExistException is + thrown. + + In either case, if no exception is thrown, then a valid node is returned: If the node existed and was allowed + to exist, it is returned, if the node did not yet exist, and was required to not exist, a new node is created. + However, in this case the root node is not yet committed. + */ + ::utl::OConfigurationNode + impl_getNodeForName_throw( const ::rtl::OUString& _rName, const bool _bMustExist ); + + ::utl::OConfigurationNode + impl_getNodeForName_nothrow( const ::rtl::OUString& _rName ); + + private: + ::comphelper::ComponentContext m_aContext; + ::utl::OConfigurationTreeRoot m_aConfigurationRoot; + ::cppu::OInterfaceContainerHelper m_aRegistrationListeners; + }; + + //==================================================================== + //= DatabaseRegistrations - implementation + //==================================================================== + //-------------------------------------------------------------------- + DatabaseRegistrations::DatabaseRegistrations( const ::comphelper::ComponentContext& _rxContext ) + :m_aContext( _rxContext ) + ,m_aConfigurationRoot() + ,m_aRegistrationListeners( m_aMutex ) + { + m_aConfigurationRoot = ::utl::OConfigurationTreeRoot::createWithServiceFactory( + m_aContext.getLegacyServiceFactory(), getConfigurationRootPath(), -1, ::utl::OConfigurationTreeRoot::CM_UPDATABLE ); + } + + //-------------------------------------------------------------------- + DatabaseRegistrations::~DatabaseRegistrations() + { + } + + //-------------------------------------------------------------------- + ::utl::OConfigurationNode DatabaseRegistrations::impl_getNodeForName_nothrow( const ::rtl::OUString& _rName ) + { + Sequence< ::rtl::OUString > aNames( m_aConfigurationRoot.getNodeNames() ); + for ( const ::rtl::OUString* pName = aNames.getConstArray(); + pName != aNames.getConstArray() + aNames.getLength(); + ++pName + ) + { + ::utl::OConfigurationNode aNodeForName = m_aConfigurationRoot.openNode( *pName ); + + ::rtl::OUString sTestName; + OSL_VERIFY( aNodeForName.getNodeValue( getNameNodeName() ) >>= sTestName ); + if ( sTestName == _rName ) + return aNodeForName; + } + return ::utl::OConfigurationNode(); + } + + //-------------------------------------------------------------------- + ::utl::OConfigurationNode DatabaseRegistrations::impl_getNodeForName_throw( const ::rtl::OUString& _rName, const bool _bMustExist ) + { + ::utl::OConfigurationNode aNodeForName( impl_getNodeForName_nothrow( _rName ) ); + + if ( aNodeForName.isValid() ) + { + if ( !_bMustExist ) + throw ElementExistException( _rName, *this ); + + return aNodeForName; + } + + if ( _bMustExist ) + throw NoSuchElementException( _rName, *this ); + + ::rtl::OUString sNewNodeName; + { + ::rtl::OUStringBuffer aNewNodeName; + aNewNodeName.appendAscii( "org.openoffice." ); + aNewNodeName.append( _rName ); + + // make unique + ::rtl::OUStringBuffer aReset( aNewNodeName ); + sNewNodeName = aNewNodeName.makeStringAndClear(); + sal_Int32 i=2; + while ( m_aConfigurationRoot.hasByName( sNewNodeName ) ) + { + aNewNodeName = aReset; + aNewNodeName.appendAscii( " " ); + aNewNodeName.append( i ); + sNewNodeName = aNewNodeName.makeStringAndClear(); + } + } + + ::utl::OConfigurationNode aNewNode( m_aConfigurationRoot.createNode( sNewNodeName ) ); + aNewNode.setNodeValue( getNameNodeName(), makeAny( _rName ) ); + return aNewNode; + } + + //-------------------------------------------------------------------- + ::utl::OConfigurationNode DatabaseRegistrations::impl_checkValidName_throw( const ::rtl::OUString& _rName, const bool _bMustExist ) + { + if ( !m_aConfigurationRoot.isValid() ) + throw RuntimeException( ::rtl::OUString(), *this ); + + if ( !_rName.getLength() ) + throw IllegalArgumentException( ::rtl::OUString(), *this, 1 ); + + return impl_getNodeForName_throw( _rName, _bMustExist ); + } + + //-------------------------------------------------------------------- + void DatabaseRegistrations::impl_checkValidLocation_throw( const ::rtl::OUString& _rLocation ) + { + if ( !_rLocation.getLength() ) + throw IllegalArgumentException( ::rtl::OUString(), *this, 2 ); + + INetURLObject aURL( _rLocation ); + if ( aURL.GetProtocol() == INET_PROT_NOT_VALID ) + throw IllegalArgumentException( ::rtl::OUString(), *this, 2 ); + } + + //-------------------------------------------------------------------- + ::sal_Bool SAL_CALL DatabaseRegistrations::hasRegisteredDatabase( const ::rtl::OUString& _Name ) throw (IllegalArgumentException, RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + ::utl::OConfigurationNode aNodeForName = impl_getNodeForName_nothrow( _Name ); + return aNodeForName.isValid(); + } + + //------------------------------------------------------------------------------ + Sequence< ::rtl::OUString > SAL_CALL DatabaseRegistrations::getRegistrationNames() throw (RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + if ( !m_aConfigurationRoot.isValid() ) + throw RuntimeException( ::rtl::OUString(), *this ); + + Sequence< ::rtl::OUString > aProgrammaticNames( m_aConfigurationRoot.getNodeNames() ); + Sequence< ::rtl::OUString > aDisplayNames( aProgrammaticNames.getLength() ); + ::rtl::OUString* pDisplayName = aDisplayNames.getArray(); + + for ( const ::rtl::OUString* pName = aProgrammaticNames.getConstArray(); + pName != aProgrammaticNames.getConstArray() + aProgrammaticNames.getLength(); + ++pName, ++pDisplayName + ) + { + ::utl::OConfigurationNode aRegistrationNode = m_aConfigurationRoot.openNode( *pName ); + OSL_VERIFY( aRegistrationNode.getNodeValue( getNameNodeName() ) >>= *pDisplayName ); + + } + + return aDisplayNames; + } + + //-------------------------------------------------------------------- + ::rtl::OUString SAL_CALL DatabaseRegistrations::getDatabaseLocation( const ::rtl::OUString& _Name ) throw (IllegalArgumentException, NoSuchElementException, RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + + ::utl::OConfigurationNode aNodeForName = impl_checkValidName_throw( _Name, true ); + + ::rtl::OUString sLocation; + OSL_VERIFY( aNodeForName.getNodeValue( getLocationNodeName() ) >>= sLocation ); + sLocation = SvtPathOptions().SubstituteVariable( sLocation ); + + return sLocation; + } + + //-------------------------------------------------------------------- + void SAL_CALL DatabaseRegistrations::registerDatabaseLocation( const ::rtl::OUString& _Name, const ::rtl::OUString& _Location ) throw (IllegalArgumentException, ElementExistException, RuntimeException) + { + ::osl::ClearableMutexGuard aGuard( m_aMutex ); + + // check + impl_checkValidLocation_throw( _Location ); + ::utl::OConfigurationNode aDataSourceRegistration = impl_checkValidName_throw( _Name, false ); + + // register + aDataSourceRegistration.setNodeValue( getLocationNodeName(), makeAny( _Location ) ); + m_aConfigurationRoot.commit(); + + // notify + DatabaseRegistrationEvent aEvent( *this, _Name, ::rtl::OUString(), _Location ); + aGuard.clear(); + m_aRegistrationListeners.notifyEach( &XDatabaseRegistrationsListener::registeredDatabaseLocation, aEvent ); + } + + //-------------------------------------------------------------------- + void SAL_CALL DatabaseRegistrations::revokeDatabaseLocation( const ::rtl::OUString& _Name ) throw (IllegalArgumentException, NoSuchElementException, IllegalAccessException, RuntimeException) + { + ::osl::ClearableMutexGuard aGuard( m_aMutex ); + + // check + ::utl::OConfigurationNode aNodeForName = impl_checkValidName_throw( _Name, true ); + + // obtain properties for notification + ::rtl::OUString sLocation; + OSL_VERIFY( aNodeForName.getNodeValue( getLocationNodeName() ) >>= sLocation ); + + // revoke + if ( aNodeForName.isReadonly() + || !m_aConfigurationRoot.removeNode( aNodeForName.getLocalName() ) + ) + throw IllegalAccessException( ::rtl::OUString(), *this ); + + m_aConfigurationRoot.commit(); + + // notify + DatabaseRegistrationEvent aEvent( *this, _Name, sLocation, ::rtl::OUString() ); + aGuard.clear(); + m_aRegistrationListeners.notifyEach( &XDatabaseRegistrationsListener::revokedDatabaseLocation, aEvent ); + } + + //-------------------------------------------------------------------- + void SAL_CALL DatabaseRegistrations::changeDatabaseLocation( const ::rtl::OUString& _Name, const ::rtl::OUString& _NewLocation ) throw (IllegalArgumentException, NoSuchElementException, IllegalAccessException, RuntimeException) + { + ::osl::ClearableMutexGuard aGuard( m_aMutex ); + + // check + impl_checkValidLocation_throw( _NewLocation ); + ::utl::OConfigurationNode aDataSourceRegistration = impl_checkValidName_throw( _Name, true ); + + if ( aDataSourceRegistration.isReadonly() ) + throw IllegalAccessException( ::rtl::OUString(), *this ); + + // obtain properties for notification + ::rtl::OUString sOldLocation; + OSL_VERIFY( aDataSourceRegistration.getNodeValue( getLocationNodeName() ) >>= sOldLocation ); + + // change + aDataSourceRegistration.setNodeValue( getLocationNodeName(), makeAny( _NewLocation ) ); + m_aConfigurationRoot.commit(); + + // notify + DatabaseRegistrationEvent aEvent( *this, _Name, sOldLocation, _NewLocation ); + aGuard.clear(); + m_aRegistrationListeners.notifyEach( &XDatabaseRegistrationsListener::changedDatabaseLocation, aEvent ); + } + + //-------------------------------------------------------------------- + ::sal_Bool SAL_CALL DatabaseRegistrations::isDatabaseRegistrationReadOnly( const ::rtl::OUString& _Name ) throw (IllegalArgumentException, NoSuchElementException, RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + ::utl::OConfigurationNode aDataSourceRegistration = impl_checkValidName_throw( _Name, true ); + return aDataSourceRegistration.isReadonly(); + } + + //-------------------------------------------------------------------- + void SAL_CALL DatabaseRegistrations::addDatabaseRegistrationsListener( const Reference< XDatabaseRegistrationsListener >& _Listener ) throw (RuntimeException) + { + if ( _Listener.is() ) + m_aRegistrationListeners.addInterface( _Listener ); + } + + //-------------------------------------------------------------------- + void SAL_CALL DatabaseRegistrations::removeDatabaseRegistrationsListener( const Reference< XDatabaseRegistrationsListener >& _Listener ) throw (RuntimeException) + { + if ( _Listener.is() ) + m_aRegistrationListeners.removeInterface( _Listener ); + } + + //==================================================================== + //= DatabaseRegistrations - factory + //==================================================================== + Reference< XAggregation > createDataSourceRegistrations( const ::comphelper::ComponentContext& _rxContext ) + { + return new DatabaseRegistrations( _rxContext ); + } + +//........................................................................ +} // namespace dbaccess +//........................................................................ diff --git a/dbaccess/source/core/dataaccess/databaseregistrations.hxx b/dbaccess/source/core/dataaccess/databaseregistrations.hxx new file mode 100644 index 000000000000..3d771625aa4a --- /dev/null +++ b/dbaccess/source/core/dataaccess/databaseregistrations.hxx @@ -0,0 +1,51 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 OOO_DATASOURCEREGISTRATIONS_HXX +#define OOO_DATASOURCEREGISTRATIONS_HXX + +/** === begin UNO includes === **/ +#include <com/sun/star/uno/XAggregation.hpp> +/** === end UNO includes === **/ + +namespace comphelper +{ + class ComponentContext; +} + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XAggregation > + createDataSourceRegistrations( const ::comphelper::ComponentContext& _rxContext ); + +//........................................................................ +} // namespace dbaccess +//........................................................................ + +#endif // OOO_DATASOURCEREGISTRATIONS_HXX diff --git a/dbaccess/source/core/dataaccess/datasource.cxx b/dbaccess/source/core/dataaccess/datasource.cxx new file mode 100755 index 000000000000..835f5398efc7 --- /dev/null +++ b/dbaccess/source/core/dataaccess/datasource.cxx @@ -0,0 +1,1476 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#include "datasource.hxx" +#include "module_dba.hxx" +#include "userinformation.hxx" +#include "commandcontainer.hxx" +#include "dbastrings.hrc" +#include "core_resource.hxx" +#include "core_resource.hrc" +#include "connection.hxx" +#include "SharedConnection.hxx" +#include "databasedocument.hxx" +#include "OAuthenticationContinuation.hxx" + + +/** === begin UNO includes === **/ +#include <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/beans/PropertyState.hpp> +#include <com/sun/star/beans/XPropertyContainer.hpp> +#include <com/sun/star/document/XDocumentSubStorageSupplier.hpp> +#include <com/sun/star/document/XEventBroadcaster.hpp> +#include <com/sun/star/embed/XTransactedObject.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/reflection/XProxyFactory.hpp> +#include <com/sun/star/sdbc/XDriverAccess.hpp> +#include <com/sun/star/sdbc/XDriverManager.hpp> +#include <com/sun/star/sdbcx/XTablesSupplier.hpp> +#include <com/sun/star/ucb/AuthenticationRequest.hpp> +#include <com/sun/star/ucb/XInteractionSupplyAuthentication.hpp> +#include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp> +#include <com/sun/star/view/XPrintable.hpp> +/** === end UNO includes === **/ + +#include <comphelper/extract.hxx> +#include <comphelper/guarding.hxx> +#include <comphelper/interaction.hxx> +#include <comphelper/namedvaluecollection.hxx> +#include <comphelper/property.hxx> +#include <comphelper/seqstream.hxx> +#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> +#include <tools/urlobj.hxx> +#include <typelib/typedescription.hxx> +#include <unotools/confignode.hxx> +#include <unotools/sharedunocomponent.hxx> +#include <rtl/logfile.hxx> +#include <rtl/digest.h> +#include <algorithm> + +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::embed; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::task; +using namespace ::com::sun::star::ucb; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::reflection; +using namespace ::cppu; +using namespace ::osl; +using namespace ::vos; +using namespace ::dbtools; +using namespace ::comphelper; +namespace css = ::com::sun::star; + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + +//============================================================ +//= FlushNotificationAdapter +//============================================================ +typedef ::cppu::WeakImplHelper1< XFlushListener > FlushNotificationAdapter_Base; +/** helper class which implements a XFlushListener, and forwards all + notification events to another XFlushListener + + The speciality is that the foreign XFlushListener instance, to which + the notifications are forwarded, is held weak. + + Thus, the class can be used with XFlushable instance which hold + their listeners with a hard reference, if you simply do not *want* + to be held hard-ref-wise. +*/ +class FlushNotificationAdapter : public FlushNotificationAdapter_Base +{ +private: + WeakReference< XFlushable > m_aBroadcaster; + WeakReference< XFlushListener > m_aListener; + +public: + static void installAdapter( const Reference< XFlushable >& _rxBroadcaster, const Reference< XFlushListener >& _rxListener ) + { + Reference< XFlushListener > xAdapter( new FlushNotificationAdapter( _rxBroadcaster, _rxListener ) ); + } + +protected: + FlushNotificationAdapter( const Reference< XFlushable >& _rxBroadcaster, const Reference< XFlushListener >& _rxListener ); + ~FlushNotificationAdapter(); + + void SAL_CALL impl_dispose( bool _bRevokeListener ); + +protected: + // XFlushListener + virtual void SAL_CALL flushed( const ::com::sun::star::lang::EventObject& rEvent ) 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); +}; + +//------------------------------------------------------------ +DBG_NAME( FlushNotificationAdapter ) +//------------------------------------------------------------ +FlushNotificationAdapter::FlushNotificationAdapter( const Reference< XFlushable >& _rxBroadcaster, const Reference< XFlushListener >& _rxListener ) + :m_aBroadcaster( _rxBroadcaster ) + ,m_aListener( _rxListener ) +{ + DBG_CTOR( FlushNotificationAdapter, NULL ); + DBG_ASSERT( _rxBroadcaster.is(), "FlushNotificationAdapter::FlushNotificationAdapter: invalid flushable!" ); + + osl_incrementInterlockedCount( &m_refCount ); + { + if ( _rxBroadcaster.is() ) + _rxBroadcaster->addFlushListener( this ); + } + osl_decrementInterlockedCount( &m_refCount ); + DBG_ASSERT( m_refCount == 1, "FlushNotificationAdapter::FlushNotificationAdapter: broadcaster isn't holding by hard ref!?" ); +} + +//------------------------------------------------------------ +FlushNotificationAdapter::~FlushNotificationAdapter() +{ + DBG_DTOR( FlushNotificationAdapter, NULL ); +} + +//-------------------------------------------------------------------- +void SAL_CALL FlushNotificationAdapter::impl_dispose( bool _bRevokeListener ) +{ + Reference< XFlushListener > xKeepAlive( this ); + + if ( _bRevokeListener ) + { + Reference< XFlushable > xFlushable( m_aBroadcaster ); + if ( xFlushable.is() ) + xFlushable->removeFlushListener( this ); + } + + m_aListener = Reference< XFlushListener >(); + m_aBroadcaster = Reference< XFlushable >(); +} + +//-------------------------------------------------------------------- +void SAL_CALL FlushNotificationAdapter::flushed( const EventObject& rEvent ) throw (RuntimeException) +{ + Reference< XFlushListener > xListener( m_aListener ); + if ( xListener.is() ) + xListener->flushed( rEvent ); + else + impl_dispose( true ); +} + +//-------------------------------------------------------------------- +void SAL_CALL FlushNotificationAdapter::disposing( const EventObject& Source ) throw (RuntimeException) +{ + Reference< XFlushListener > xListener( m_aListener ); + if ( xListener.is() ) + xListener->disposing( Source ); + + impl_dispose( false ); +} + +//-------------------------------------------------------------------------- +OAuthenticationContinuation::OAuthenticationContinuation() + :m_bRemberPassword(sal_True), // TODO: a meaningfull default + m_bCanSetUserName(sal_True) +{ +} + +//-------------------------------------------------------------------------- +sal_Bool SAL_CALL OAuthenticationContinuation::canSetRealm( ) throw(RuntimeException) +{ + return sal_False; +} + +//-------------------------------------------------------------------------- +void SAL_CALL OAuthenticationContinuation::setRealm( const ::rtl::OUString& /*Realm*/ ) throw(RuntimeException) +{ + DBG_ERROR("OAuthenticationContinuation::setRealm: not supported!"); +} + +//-------------------------------------------------------------------------- +sal_Bool SAL_CALL OAuthenticationContinuation::canSetUserName( ) throw(RuntimeException) +{ + // we alwas allow this, even if the database document is read-only. In this case, + // it's simply that the user cannot store the new user name. + return m_bCanSetUserName; +} + +//-------------------------------------------------------------------------- +void SAL_CALL OAuthenticationContinuation::setUserName( const ::rtl::OUString& _rUser ) throw(RuntimeException) +{ + m_sUser = _rUser; +} + +//-------------------------------------------------------------------------- +sal_Bool SAL_CALL OAuthenticationContinuation::canSetPassword( ) throw(RuntimeException) +{ + return sal_True; +} + +//-------------------------------------------------------------------------- +void SAL_CALL OAuthenticationContinuation::setPassword( const ::rtl::OUString& _rPassword ) throw(RuntimeException) +{ + m_sPassword = _rPassword; +} + +//-------------------------------------------------------------------------- +Sequence< RememberAuthentication > SAL_CALL OAuthenticationContinuation::getRememberPasswordModes( RememberAuthentication& _reDefault ) throw(RuntimeException) +{ + Sequence< RememberAuthentication > aReturn(1); + _reDefault = aReturn[0] = RememberAuthentication_SESSION; + return aReturn; +} + +//-------------------------------------------------------------------------- +void SAL_CALL OAuthenticationContinuation::setRememberPassword( RememberAuthentication _eRemember ) throw(RuntimeException) +{ + m_bRemberPassword = (RememberAuthentication_NO != _eRemember); +} + +//-------------------------------------------------------------------------- +sal_Bool SAL_CALL OAuthenticationContinuation::canSetAccount( ) throw(RuntimeException) +{ + return sal_False; +} + +//-------------------------------------------------------------------------- +void SAL_CALL OAuthenticationContinuation::setAccount( const ::rtl::OUString& ) throw(RuntimeException) +{ + DBG_ERROR("OAuthenticationContinuation::setAccount: not supported!"); +} + +//-------------------------------------------------------------------------- +Sequence< RememberAuthentication > SAL_CALL OAuthenticationContinuation::getRememberAccountModes( RememberAuthentication& _reDefault ) throw(RuntimeException) +{ + Sequence < RememberAuthentication > aReturn(1); + aReturn[0] = RememberAuthentication_NO; + _reDefault = RememberAuthentication_NO; + return aReturn; +} + +//-------------------------------------------------------------------------- +void SAL_CALL OAuthenticationContinuation::setRememberAccount( RememberAuthentication /*Remember*/ ) throw(RuntimeException) +{ + DBG_ERROR("OAuthenticationContinuation::setRememberAccount: not supported!"); +} + +/** The class OSharedConnectionManager implements a structure to share connections. + It owns the master connections which will be disposed when the last connection proxy is gone. +*/ +typedef ::cppu::WeakImplHelper1< XEventListener > OConnectionHelper_BASE; +// need to hold the digest +struct TDigestHolder +{ + sal_uInt8 m_pBuffer[RTL_DIGEST_LENGTH_SHA1]; + TDigestHolder() + { + m_pBuffer[0] = 0; + } + +}; + +class OSharedConnectionManager : public OConnectionHelper_BASE +{ + + // contains the currently used master connections + typedef struct + { + Reference< XConnection > xMasterConnection; + oslInterlockedCount nALiveCount; + } TConnectionHolder; + + // the less-compare functor, used for the stl::map + struct TDigestLess : public ::std::binary_function< TDigestHolder, TDigestHolder, bool> + { + bool operator() (const TDigestHolder& x, const TDigestHolder& y) const + { + sal_uInt32 i; + for(i=0;i < RTL_DIGEST_LENGTH_SHA1 && (x.m_pBuffer[i] >= y.m_pBuffer[i]); ++i) + ; + return i < RTL_DIGEST_LENGTH_SHA1; + } + }; + + typedef ::std::map< TDigestHolder,TConnectionHolder,TDigestLess> TConnectionMap; // holds the master connections + typedef ::std::map< Reference< XConnection >,TConnectionMap::iterator> TSharedConnectionMap;// holds the shared connections + + ::osl::Mutex m_aMutex; + TConnectionMap m_aConnections; // remeber the master connection in conjunction with the digest + TSharedConnectionMap m_aSharedConnection; // the shared connections with conjunction with an iterator into the connections map + Reference< XProxyFactory > m_xProxyFactory; + +protected: + ~OSharedConnectionManager(); + +public: + OSharedConnectionManager(const Reference< XMultiServiceFactory >& _rxServiceFactory); + + void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw(RuntimeException); + Reference<XConnection> getConnection( const rtl::OUString& url, + const rtl::OUString& user, + const rtl::OUString& password, + const Sequence< PropertyValue >& _aInfo, + ODatabaseSource* _pDataSource); + void addEventListener(const Reference<XConnection>& _rxConnection,TConnectionMap::iterator& _rIter); +}; + +DBG_NAME(OSharedConnectionManager) +OSharedConnectionManager::OSharedConnectionManager(const Reference< XMultiServiceFactory >& _rxServiceFactory) +{ + DBG_CTOR(OSharedConnectionManager,NULL); + m_xProxyFactory.set(_rxServiceFactory->createInstance(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.reflection.ProxyFactory"))),UNO_QUERY); +} + +OSharedConnectionManager::~OSharedConnectionManager() +{ + DBG_DTOR(OSharedConnectionManager,NULL); +} + +void SAL_CALL OSharedConnectionManager::disposing( const ::com::sun::star::lang::EventObject& Source ) throw(RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + Reference<XConnection> xConnection(Source.Source,UNO_QUERY); + TSharedConnectionMap::iterator aFind = m_aSharedConnection.find(xConnection); + if ( m_aSharedConnection.end() != aFind ) + { + osl_decrementInterlockedCount(&aFind->second->second.nALiveCount); + if ( !aFind->second->second.nALiveCount ) + { + ::comphelper::disposeComponent(aFind->second->second.xMasterConnection); + m_aConnections.erase(aFind->second); + } + m_aSharedConnection.erase(aFind); + } +} + +Reference<XConnection> OSharedConnectionManager::getConnection( const rtl::OUString& url, + const rtl::OUString& user, + const rtl::OUString& password, + const Sequence< PropertyValue >& _aInfo, + ODatabaseSource* _pDataSource) +{ + MutexGuard aGuard(m_aMutex); + TConnectionMap::key_type nId; + Sequence< PropertyValue > aInfoCopy(_aInfo); + sal_Int32 nPos = aInfoCopy.getLength(); + aInfoCopy.realloc( nPos + 2 ); + aInfoCopy[nPos].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("TableFilter")); + aInfoCopy[nPos++].Value <<= _pDataSource->m_pImpl->m_aTableFilter; + aInfoCopy[nPos].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("TableTypeFilter")); + aInfoCopy[nPos++].Value <<= _pDataSource->m_pImpl->m_aTableTypeFilter; // #22377# OJ + + ::rtl::OUString sUser = user; + ::rtl::OUString sPassword = password; + if ((0 == sUser.getLength()) && (0 == sPassword.getLength()) && (0 != _pDataSource->m_pImpl->m_sUser.getLength())) + { // ease the usage of this method. data source which are intended to have a user automatically + // fill in the user/password combination if the caller of this method does not specify otherwise + // 86951 - 05/08/2001 - frank.schoenheit@germany.sun.com + sUser = _pDataSource->m_pImpl->m_sUser; + if (0 != _pDataSource->m_pImpl->m_aPassword.getLength()) + sPassword = _pDataSource->m_pImpl->m_aPassword; + } + + ::connectivity::OConnectionWrapper::createUniqueId(url,aInfoCopy,nId.m_pBuffer,sUser,sPassword); + TConnectionMap::iterator aIter = m_aConnections.find(nId); + + if ( m_aConnections.end() == aIter ) + { + TConnectionHolder aHolder; + aHolder.nALiveCount = 0; // will be incremented by addListener + aHolder.xMasterConnection = _pDataSource->buildIsolatedConnection(user,password); + aIter = m_aConnections.insert(TConnectionMap::value_type(nId,aHolder)).first; + } + + Reference<XConnection> xRet; + if ( aIter->second.xMasterConnection.is() ) + { + Reference< XAggregation > xConProxy = m_xProxyFactory->createProxy(aIter->second.xMasterConnection.get()); + xRet = new OSharedConnection(xConProxy); + m_aSharedConnection.insert(TSharedConnectionMap::value_type(xRet,aIter)); + addEventListener(xRet,aIter); + } + + return xRet; +} +void OSharedConnectionManager::addEventListener(const Reference<XConnection>& _rxConnection,TConnectionMap::iterator& _rIter) +{ + Reference<XComponent> xComp(_rxConnection,UNO_QUERY); + xComp->addEventListener(this); + OSL_ENSURE( m_aConnections.end() != _rIter , "Iterator is end!"); + osl_incrementInterlockedCount(&_rIter->second.nALiveCount); +} + +//---------------------------------------------------------------------- +namespace +{ + //------------------------------------------------------------------ + Sequence< PropertyValue > lcl_filterDriverProperties( const Reference< XDriver >& _xDriver, const ::rtl::OUString& _sUrl, + const Sequence< PropertyValue >& _rDataSourceSettings, const AsciiPropertyValue* _pKnownSettings ) + { + if ( _xDriver.is() ) + { + Sequence< DriverPropertyInfo > aDriverInfo(_xDriver->getPropertyInfo(_sUrl,_rDataSourceSettings)); + + const PropertyValue* pDataSourceSetting = _rDataSourceSettings.getConstArray(); + const PropertyValue* pEnd = pDataSourceSetting + _rDataSourceSettings.getLength(); + + ::std::vector< PropertyValue > aRet; + + for ( ; pDataSourceSetting != pEnd ; ++pDataSourceSetting ) + { + sal_Bool bAllowSetting = sal_False; + const AsciiPropertyValue* pSetting = _pKnownSettings; + for ( ; pSetting->AsciiName; ++pSetting ) + { + if ( !pDataSourceSetting->Name.compareToAscii( pSetting->AsciiName ) ) + { // the particular data source setting is known + + const DriverPropertyInfo* pAllowedDriverSetting = aDriverInfo.getConstArray(); + const DriverPropertyInfo* pDriverSettingsEnd = pAllowedDriverSetting + aDriverInfo.getLength(); + for ( ; pAllowedDriverSetting != pDriverSettingsEnd; ++pAllowedDriverSetting ) + { + if ( !pAllowedDriverSetting->Name.compareToAscii( pSetting->AsciiName ) ) + { // the driver also allows this setting + bAllowSetting = sal_True; + break; + } + } + break; + } + } + if ( bAllowSetting || !pSetting->AsciiName ) + { // if the driver allows this particular setting, or if the setting is completely unknown, + // we pass it to the driver + aRet.push_back( *pDataSourceSetting ); + } + } + if ( !aRet.empty() ) + return Sequence< PropertyValue >(&(*aRet.begin()),aRet.size()); + } + return Sequence< PropertyValue >(); + } + + //------------------------------------------------------------------ + typedef ::std::map< ::rtl::OUString, sal_Int32 > PropertyAttributeCache; + + //------------------------------------------------------------------ + struct IsDefaultAndNotRemoveable : public ::std::unary_function< PropertyValue, bool > + { + private: + const PropertyAttributeCache& m_rAttribs; + + public: + IsDefaultAndNotRemoveable( const PropertyAttributeCache& _rAttribs ) : m_rAttribs( _rAttribs ) { } + + bool operator()( const PropertyValue& _rProp ) + { + if ( _rProp.State != PropertyState_DEFAULT_VALUE ) + return false; + + bool bRemoveable = true; + + PropertyAttributeCache::const_iterator pos = m_rAttribs.find( _rProp.Name ); + OSL_ENSURE( pos != m_rAttribs.end(), "IsDefaultAndNotRemoveable: illegal property name!" ); + if ( pos != m_rAttribs.end() ) + bRemoveable = ( ( pos->second & PropertyAttribute::REMOVEABLE ) != 0 ); + + return !bRemoveable; + } + }; +} +//============================================================ +//= ODatabaseContext +//============================================================ +DBG_NAME(ODatabaseSource) +//-------------------------------------------------------------------------- +extern "C" void SAL_CALL createRegistryInfo_ODatabaseSource() +{ + static ::dba::OAutoRegistration< ODatabaseSource > aAutoRegistration; +} + +//-------------------------------------------------------------------------- +ODatabaseSource::ODatabaseSource(const ::rtl::Reference<ODatabaseModelImpl>& _pImpl) + :ModelDependentComponent( _pImpl ) + ,ODatabaseSource_Base( getMutex() ) + ,OPropertySetHelper( ODatabaseSource_Base::rBHelper ) + ,m_aBookmarks( *this, getMutex() ) + ,m_aFlushListeners( getMutex() ) +{ + // some kind of default + DBG_CTOR(ODatabaseSource,NULL); + OSL_TRACE( "DS: ctor: %p: %p", this, m_pImpl.get() ); +} + +//-------------------------------------------------------------------------- +ODatabaseSource::~ODatabaseSource() +{ + OSL_TRACE( "DS: dtor: %p: %p", this, m_pImpl.get() ); + DBG_DTOR(ODatabaseSource,NULL); + if ( !ODatabaseSource_Base::rBHelper.bInDispose && !ODatabaseSource_Base::rBHelper.bDisposed ) + { + acquire(); + dispose(); + } +} + +//-------------------------------------------------------------------------- +void ODatabaseSource::setName( const Reference< XDocumentDataSource >& _rxDocument, const ::rtl::OUString& _rNewName, DBContextAccess ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::setName" ); + ODatabaseSource& rModelImpl = dynamic_cast< ODatabaseSource& >( *_rxDocument.get() ); + + ::osl::MutexGuard aGuard( rModelImpl.m_aMutex ); + if ( rModelImpl.m_pImpl.is() ) + rModelImpl.m_pImpl->m_sName = _rNewName; +} + +// com::sun::star::lang::XTypeProvider +//-------------------------------------------------------------------------- +Sequence< Type > ODatabaseSource::getTypes() throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getTypes" ); + OTypeCollection aPropertyHelperTypes( ::getCppuType( (const Reference< XFastPropertySet > *)0 ), + ::getCppuType( (const Reference< XPropertySet > *)0 ), + ::getCppuType( (const Reference< XMultiPropertySet > *)0 )); + + return ::comphelper::concatSequences( + ODatabaseSource_Base::getTypes(), + aPropertyHelperTypes.getTypes() + ); +} + +//-------------------------------------------------------------------------- +Sequence< sal_Int8 > ODatabaseSource::getImplementationId() throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getImplementationId" ); + static OImplementationId * pId = 0; + if (! pId) + { + MutexGuard aGuard( Mutex::getGlobalMutex() ); + if (! pId) + { + static OImplementationId aId; + pId = &aId; + } + } + return pId->getImplementationId(); +} + +// com::sun::star::uno::XInterface +//-------------------------------------------------------------------------- +Any ODatabaseSource::queryInterface( const Type & rType ) throw (RuntimeException) +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::queryInterface" ); + Any aIface = ODatabaseSource_Base::queryInterface( rType ); + if ( !aIface.hasValue() ) + aIface = ::cppu::OPropertySetHelper::queryInterface( rType ); + return aIface; +} + +//-------------------------------------------------------------------------- +void ODatabaseSource::acquire() throw () +{ + ODatabaseSource_Base::acquire(); +} + +//-------------------------------------------------------------------------- +void ODatabaseSource::release() throw () +{ + ODatabaseSource_Base::release(); +} +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseSource::disposing( const ::com::sun::star::lang::EventObject& Source ) throw(RuntimeException) +{ + if ( m_pImpl.is() ) + m_pImpl->disposing(Source); +} +// XServiceInfo +//------------------------------------------------------------------------------ +rtl::OUString ODatabaseSource::getImplementationName( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getImplementationName" ); + return getImplementationName_static(); +} + +//------------------------------------------------------------------------------ +rtl::OUString ODatabaseSource::getImplementationName_static( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getImplementationName_static" ); + return rtl::OUString::createFromAscii("com.sun.star.comp.dba.ODatabaseSource"); +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > ODatabaseSource::getSupportedServiceNames( ) throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getSupportedServiceNames" ); + return getSupportedServiceNames_static(); +} +//------------------------------------------------------------------------------ +Reference< XInterface > ODatabaseSource::Create( const Reference< XComponentContext >& _rxContext ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::Create" ); + ::comphelper::ComponentContext aContext( _rxContext ); + Reference< XSingleServiceFactory > xDBContext( aContext.createComponent( (::rtl::OUString)SERVICE_SDB_DATABASECONTEXT ), UNO_QUERY_THROW ); + return xDBContext->createInstance(); +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > ODatabaseSource::getSupportedServiceNames_static( ) throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getSupportedServiceNames_static" ); + Sequence< ::rtl::OUString > aSNS( 2 ); + aSNS[0] = SERVICE_SDB_DATASOURCE; + aSNS[1] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sdb.DocumentDataSource")); + return aSNS; +} + +//------------------------------------------------------------------------------ +sal_Bool ODatabaseSource::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::supportsService" ); + return ::comphelper::findValue(getSupportedServiceNames(), _rServiceName, sal_True).getLength() != 0; +} +// OComponentHelper +//------------------------------------------------------------------------------ +void ODatabaseSource::disposing() +{ + OSL_TRACE( "DS: disp: %p, %p", this, m_pImpl.get() ); + ODatabaseSource_Base::WeakComponentImplHelperBase::disposing(); + OPropertySetHelper::disposing(); + + EventObject aDisposeEvent(static_cast<XWeak*>(this)); + m_aFlushListeners.disposeAndClear( aDisposeEvent ); + + ODatabaseDocument::clearObjectContainer(m_pImpl->m_xCommandDefinitions); + ODatabaseDocument::clearObjectContainer(m_pImpl->m_xTableDefinitions); + m_pImpl.clear(); +} +//------------------------------------------------------------------------------ +Reference< XConnection > ODatabaseSource::buildLowLevelConnection(const ::rtl::OUString& _rUid, const ::rtl::OUString& _rPwd) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::buildLowLevelConnection" ); + Reference< XConnection > xReturn; + + Reference< XDriverManager > xManager; + if ( !m_pImpl->m_aContext.createComponent( "com.sun.star.sdbc.ConnectionPool", xManager ) ) + // no connection pool installed, fall back to driver manager + m_pImpl->m_aContext.createComponent( "com.sun.star.sdbc.DriverManager", xManager ); + + ::rtl::OUString sUser(_rUid); + ::rtl::OUString sPwd(_rPwd); + if ((0 == sUser.getLength()) && (0 == sPwd.getLength()) && (0 != m_pImpl->m_sUser.getLength())) + { // ease the usage of this method. data source which are intended to have a user automatically + // fill in the user/password combination if the caller of this method does not specify otherwise + // 86951 - 05/08/2001 - frank.schoenheit@germany.sun.com + sUser = m_pImpl->m_sUser; + if (0 != m_pImpl->m_aPassword.getLength()) + sPwd = m_pImpl->m_aPassword; + } + + sal_uInt16 nExceptionMessageId = RID_STR_COULDNOTCONNECT_UNSPECIFIED; + if (xManager.is()) + { + sal_Int32 nAdditionalArgs(0); + if (sUser.getLength()) ++nAdditionalArgs; + if (sPwd.getLength()) ++nAdditionalArgs; + + Sequence< PropertyValue > aUserPwd(nAdditionalArgs); + sal_Int32 nArgPos = 0; + if (sUser.getLength()) + { + aUserPwd[ nArgPos ].Name = ::rtl::OUString::createFromAscii("user"); + aUserPwd[ nArgPos ].Value <<= sUser; + ++nArgPos; + } + if (sPwd.getLength()) + { + aUserPwd[ nArgPos ].Name = ::rtl::OUString::createFromAscii("password"); + aUserPwd[ nArgPos ].Value <<= sPwd; + } + Reference< XDriver > xDriver; + try + { + Reference< XDriverAccess > xAccessDrivers( xManager, UNO_QUERY ); + if ( xAccessDrivers.is() ) + xDriver = xAccessDrivers->getDriverByURL( m_pImpl->m_sConnectURL ); + } + catch( const Exception& ) + { + DBG_ERROR( "ODatabaseSource::buildLowLevelConnection: got a strange exception while analyzing the error!" ); + } + if ( !xDriver.is() || !xDriver->acceptsURL( m_pImpl->m_sConnectURL ) ) + { + // Nowadays, it's allowed for a driver to be registered for a given URL, but actually not to accept it. + // This is because registration nowadays happens at compile time (by adding respective configuration data), + // but acceptance is decided at runtime. + nExceptionMessageId = RID_STR_COULDNOTCONNECT_NODRIVER; + } + else + { + Sequence< PropertyValue > aDriverInfo = lcl_filterDriverProperties( + xDriver, + m_pImpl->m_sConnectURL, + m_pImpl->m_xSettings->getPropertyValues(), + m_pImpl->getDefaultDataSourceSettings() + ); + + if ( m_pImpl->isEmbeddedDatabase() ) + { + sal_Int32 nCount = aDriverInfo.getLength(); + aDriverInfo.realloc(nCount + 2 ); + aDriverInfo[nCount].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("URL")); + aDriverInfo[nCount++].Value <<= m_pImpl->getURL(); + aDriverInfo[nCount].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Storage")); + Reference< css::document::XDocumentSubStorageSupplier> xDocSup( m_pImpl->getDocumentSubStorageSupplier() ); + aDriverInfo[nCount++].Value <<= xDocSup->getDocumentSubStorage(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("database")),ElementModes::READWRITE); + } + if (nAdditionalArgs) + xReturn = xManager->getConnectionWithInfo(m_pImpl->m_sConnectURL, ::comphelper::concatSequences(aUserPwd,aDriverInfo)); + else + xReturn = xManager->getConnectionWithInfo(m_pImpl->m_sConnectURL,aDriverInfo); + + if ( m_pImpl->isEmbeddedDatabase() ) + { + // see ODatabaseSource::flushed for comment on why we register as FlushListener + // at the connection + Reference< XFlushable > xFlushable( xReturn, UNO_QUERY ); + if ( xFlushable.is() ) + FlushNotificationAdapter::installAdapter( xFlushable, this ); + } + } + } + else + nExceptionMessageId = RID_STR_COULDNOTLOAD_MANAGER; + + if ( !xReturn.is() ) + { + ::rtl::OUString sMessage = DBACORE_RESSTRING( nExceptionMessageId ); + + SQLContext aContext; + aContext.Message = DBACORE_RESSTRING( RID_STR_CONNECTION_REQUEST ); + ::comphelper::string::searchAndReplaceAsciiI( aContext.Message, "$name$", m_pImpl->m_sConnectURL ); + + throwGenericSQLException( sMessage, static_cast< XDataSource* >( this ), makeAny( aContext ) ); + } + + return xReturn; +} + +// OPropertySetHelper +//------------------------------------------------------------------------------ +Reference< XPropertySetInfo > ODatabaseSource::getPropertySetInfo() throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getPropertySetInfo" ); + return createPropertySetInfo( getInfoHelper() ) ; +} + +// comphelper::OPropertyArrayUsageHelper +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper* ODatabaseSource::createArrayHelper( ) const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::createArrayHelper" ); + BEGIN_PROPERTY_HELPER(13) + DECL_PROP1(INFO, Sequence< PropertyValue >, BOUND); + DECL_PROP1_BOOL(ISPASSWORDREQUIRED, BOUND); + DECL_PROP1_BOOL(ISREADONLY, READONLY); + DECL_PROP1(LAYOUTINFORMATION, Sequence< PropertyValue >, BOUND); + DECL_PROP1(NAME, ::rtl::OUString, READONLY); + DECL_PROP2_IFACE(NUMBERFORMATSSUPPLIER, XNumberFormatsSupplier, READONLY, TRANSIENT); + DECL_PROP1(PASSWORD, ::rtl::OUString, TRANSIENT); + DECL_PROP2_IFACE(SETTINGS, XPropertySet, BOUND, READONLY); + DECL_PROP1_BOOL(SUPPRESSVERSIONCL, BOUND); + DECL_PROP1(TABLEFILTER, Sequence< ::rtl::OUString >,BOUND); + DECL_PROP1(TABLETYPEFILTER, Sequence< ::rtl::OUString >,BOUND); + DECL_PROP1(URL, ::rtl::OUString, BOUND); + DECL_PROP1(USER, ::rtl::OUString, BOUND); + END_PROPERTY_HELPER(); +} + +// cppu::OPropertySetHelper +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper& ODatabaseSource::getInfoHelper() +{ + return *getArrayHelper(); +} + +//------------------------------------------------------------------------------ +sal_Bool ODatabaseSource::convertFastPropertyValue(Any & rConvertedValue, Any & rOldValue, sal_Int32 nHandle, const Any& rValue ) throw( IllegalArgumentException ) +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::convertFastPropertyValue" ); + sal_Bool bModified(sal_False); + if ( m_pImpl.is() ) + { + switch (nHandle) + { + case PROPERTY_ID_TABLEFILTER: + bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_aTableFilter); + break; + case PROPERTY_ID_TABLETYPEFILTER: + bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_aTableTypeFilter); + break; + case PROPERTY_ID_USER: + bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_sUser); + break; + case PROPERTY_ID_PASSWORD: + bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_aPassword); + break; + case PROPERTY_ID_ISPASSWORDREQUIRED: + bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_bPasswordRequired); + break; + case PROPERTY_ID_SUPPRESSVERSIONCL: + bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_bSuppressVersionColumns); + break; + case PROPERTY_ID_LAYOUTINFORMATION: + bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_aLayoutInformation); + break; + case PROPERTY_ID_URL: + { + bModified = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_pImpl->m_sConnectURL); + } break; + case PROPERTY_ID_INFO: + { + Sequence<PropertyValue> aValues; + if (!(rValue >>= aValues)) + throw IllegalArgumentException(); + + const PropertyValue* valueEnd = aValues.getConstArray() + aValues.getLength(); + const PropertyValue* checkName = aValues.getConstArray(); + for ( ;checkName != valueEnd; ++checkName ) + { + if ( !checkName->Name.getLength() ) + throw IllegalArgumentException(); + } + + Sequence< PropertyValue > aSettings = m_pImpl->m_xSettings->getPropertyValues(); + bModified = aSettings.getLength() != aValues.getLength(); + if ( !bModified ) + { + const PropertyValue* pInfoIter = aSettings.getConstArray(); + const PropertyValue* checkValue = aValues.getConstArray(); + for ( ;!bModified && checkValue != valueEnd ; ++checkValue,++pInfoIter) + { + bModified = checkValue->Name != pInfoIter->Name; + if ( !bModified ) + { + bModified = !::comphelper::compare(checkValue->Value,pInfoIter->Value); + } + } + } + + rConvertedValue = rValue; + rOldValue <<= aSettings; + } + break; + default: + DBG_ERROR( "ODatabaseSource::convertFastPropertyValue: unknown or readonly Property!" ); + } + } + return bModified; +} + +//------------------------------------------------------------------------------ +namespace +{ + struct SelectPropertyName : public ::std::unary_function< PropertyValue, ::rtl::OUString > + { + public: + const ::rtl::OUString& operator()( const PropertyValue& _lhs ) + { + return _lhs.Name; + } + }; + + /** sets a new set of property values at a given property bag instance + + The methods takes a property bag, and a sequence of property values to set at this bag. + Upon return, every property which is not part of the given sequence is + <ul><li>removed from the bag, if it's a removeable property</li> + <li><em>or</em>reset to its default value, if it's not a removeable property</li> + </ul>. + + @param _rxPropertyBag + the property bag to operate on + @param _rAllNewPropertyValues + the new property values to set at the bag + */ + void lcl_setPropertyValues_resetOrRemoveOther( const Reference< XPropertyAccess >& _rxPropertyBag, const Sequence< PropertyValue >& _rAllNewPropertyValues ) + { + // sequences are ugly to operate on + typedef ::std::set< ::rtl::OUString > StringSet; + StringSet aToBeSetPropertyNames; + ::std::transform( + _rAllNewPropertyValues.getConstArray(), + _rAllNewPropertyValues.getConstArray() + _rAllNewPropertyValues.getLength(), + ::std::insert_iterator< StringSet >( aToBeSetPropertyNames, aToBeSetPropertyNames.end() ), + SelectPropertyName() + ); + + try + { + // obtain all properties currently known at the bag + Reference< XPropertySet > xPropertySet( _rxPropertyBag, UNO_QUERY_THROW ); + Reference< XPropertySetInfo > xPSI( xPropertySet->getPropertySetInfo(), UNO_QUERY_THROW ); + Sequence< Property > aAllExistentProperties( xPSI->getProperties() ); + + Reference< XPropertyState > xPropertyState( _rxPropertyBag, UNO_QUERY_THROW ); + Reference< XPropertyContainer > xPropertyContainer( _rxPropertyBag, UNO_QUERY_THROW ); + + // loop through them, and reset resp. default properties which are not to be set + const Property* pExistentProperty( aAllExistentProperties.getConstArray() ); + const Property* pExistentPropertyEnd( aAllExistentProperties.getConstArray() + aAllExistentProperties.getLength() ); + for ( ; pExistentProperty != pExistentPropertyEnd; ++pExistentProperty ) + { + if ( aToBeSetPropertyNames.find( pExistentProperty->Name ) != aToBeSetPropertyNames.end() ) + continue; + + // this property is not to be set, but currently exists in the bag. + // -> Remove, respectively default, it + if ( ( pExistentProperty->Attributes & PropertyAttribute::REMOVEABLE ) != 0 ) + xPropertyContainer->removeProperty( pExistentProperty->Name ); + else + xPropertyState->setPropertyToDefault( pExistentProperty->Name ); + } + + // finally, set the new property values + _rxPropertyBag->setPropertyValues( _rAllNewPropertyValues ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } +} + +//------------------------------------------------------------------------------ +void ODatabaseSource::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue ) throw (Exception) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::setFastPropertyValue_NoBroadcast" ); + if ( m_pImpl.is() ) + { + switch(nHandle) + { + case PROPERTY_ID_TABLEFILTER: + rValue >>= m_pImpl->m_aTableFilter; + break; + case PROPERTY_ID_TABLETYPEFILTER: + rValue >>= m_pImpl->m_aTableTypeFilter; + break; + case PROPERTY_ID_USER: + rValue >>= m_pImpl->m_sUser; + // if the user name changed, reset the password + m_pImpl->m_aPassword = ::rtl::OUString(); + break; + case PROPERTY_ID_PASSWORD: + rValue >>= m_pImpl->m_aPassword; + break; + case PROPERTY_ID_ISPASSWORDREQUIRED: + m_pImpl->m_bPasswordRequired = any2bool(rValue); + break; + case PROPERTY_ID_SUPPRESSVERSIONCL: + m_pImpl->m_bSuppressVersionColumns = any2bool(rValue); + break; + case PROPERTY_ID_URL: + rValue >>= m_pImpl->m_sConnectURL; + break; + case PROPERTY_ID_INFO: + { + Sequence< PropertyValue > aInfo; + OSL_VERIFY( rValue >>= aInfo ); + lcl_setPropertyValues_resetOrRemoveOther( m_pImpl->m_xSettings, aInfo ); + } + break; + case PROPERTY_ID_LAYOUTINFORMATION: + rValue >>= m_pImpl->m_aLayoutInformation; + break; + } + m_pImpl->setModified(sal_True); + } +} + +//------------------------------------------------------------------------------ +void ODatabaseSource::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getFastPropertyValue" ); + if ( m_pImpl.is() ) + { + switch (nHandle) + { + case PROPERTY_ID_TABLEFILTER: + rValue <<= m_pImpl->m_aTableFilter; + break; + case PROPERTY_ID_TABLETYPEFILTER: + rValue <<= m_pImpl->m_aTableTypeFilter; + break; + case PROPERTY_ID_USER: + rValue <<= m_pImpl->m_sUser; + break; + case PROPERTY_ID_PASSWORD: + rValue <<= m_pImpl->m_aPassword; + break; + case PROPERTY_ID_ISPASSWORDREQUIRED: + rValue = bool2any(m_pImpl->m_bPasswordRequired); + break; + case PROPERTY_ID_SUPPRESSVERSIONCL: + rValue = bool2any(m_pImpl->m_bSuppressVersionColumns); + break; + case PROPERTY_ID_ISREADONLY: + rValue = bool2any(m_pImpl->m_bReadOnly); + break; + case PROPERTY_ID_INFO: + { + try + { + // collect the property attributes of all current settings + Reference< XPropertySet > xSettingsAsProps( m_pImpl->m_xSettings, UNO_QUERY_THROW ); + Reference< XPropertySetInfo > xPST( xSettingsAsProps->getPropertySetInfo(), UNO_QUERY_THROW ); + Sequence< Property > aSettings( xPST->getProperties() ); + ::std::map< ::rtl::OUString, sal_Int32 > aPropertyAttributes; + for ( const Property* pSettings = aSettings.getConstArray(); + pSettings != aSettings.getConstArray() + aSettings.getLength(); + ++pSettings + ) + { + aPropertyAttributes[ pSettings->Name ] = pSettings->Attributes; + } + + // get all current settings with their values + Sequence< PropertyValue > aValues( m_pImpl->m_xSettings->getPropertyValues() ); + + // transform them so that only property values which fulfill certain + // criterions survive + Sequence< PropertyValue > aNonDefaultOrUserDefined( aValues.getLength() ); + const PropertyValue* pCopyEnd = ::std::remove_copy_if( + aValues.getConstArray(), + aValues.getConstArray() + aValues.getLength(), + aNonDefaultOrUserDefined.getArray(), + IsDefaultAndNotRemoveable( aPropertyAttributes ) + ); + aNonDefaultOrUserDefined.realloc( pCopyEnd - aNonDefaultOrUserDefined.getArray() ); + rValue <<= aNonDefaultOrUserDefined; + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + break; + case PROPERTY_ID_SETTINGS: + rValue <<= m_pImpl->m_xSettings; + break; + case PROPERTY_ID_URL: + rValue <<= m_pImpl->m_sConnectURL; + break; + case PROPERTY_ID_NUMBERFORMATSSUPPLIER: + rValue <<= m_pImpl->getNumberFormatsSupplier(); + break; + case PROPERTY_ID_NAME: + rValue <<= m_pImpl->m_sName; + break; + case PROPERTY_ID_LAYOUTINFORMATION: + rValue <<= m_pImpl->m_aLayoutInformation; + break; + default: + DBG_ERROR("unknown Property"); + } + } +} + +// XDataSource +//------------------------------------------------------------------------------ +void ODatabaseSource::setLoginTimeout(sal_Int32 seconds) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::setLoginTimeout" ); + ModelMethodGuard aGuard( *this ); + m_pImpl->m_nLoginTimeout = seconds; +} + +//------------------------------------------------------------------------------ +sal_Int32 ODatabaseSource::getLoginTimeout(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getLoginTimeout" ); + ModelMethodGuard aGuard( *this ); + return m_pImpl->m_nLoginTimeout; +} + + +// XCompletedConnection +//------------------------------------------------------------------------------ +Reference< XConnection > SAL_CALL ODatabaseSource::connectWithCompletion( const Reference< XInteractionHandler >& _rxHandler ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::connectWithCompletion" ); + return connectWithCompletion(_rxHandler,sal_False); +} +// ----------------------------------------------------------------------------- +Reference< XConnection > ODatabaseSource::getConnection(const rtl::OUString& user, const rtl::OUString& password) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getConnection" ); + return getConnection(user,password,sal_False); +} +// ----------------------------------------------------------------------------- +Reference< XConnection > SAL_CALL ODatabaseSource::getIsolatedConnection( const ::rtl::OUString& user, const ::rtl::OUString& password ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getIsolatedConnection" ); + return getConnection(user,password,sal_True); +} +// ----------------------------------------------------------------------------- +Reference< XConnection > SAL_CALL ODatabaseSource::getIsolatedConnectionWithCompletion( const Reference< XInteractionHandler >& _rxHandler ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getIsolatedConnectionWithCompletion" ); + return connectWithCompletion(_rxHandler,sal_True); +} +// ----------------------------------------------------------------------------- +Reference< XConnection > SAL_CALL ODatabaseSource::connectWithCompletion( const Reference< XInteractionHandler >& _rxHandler,sal_Bool _bIsolated ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::connectWithCompletion" ); + ModelMethodGuard aGuard( *this ); + + if (!_rxHandler.is()) + { + DBG_ERROR("ODatabaseSource::connectWithCompletion: invalid interaction handler!"); + return getConnection(m_pImpl->m_sUser, m_pImpl->m_aPassword,_bIsolated); + } + + ::rtl::OUString sUser(m_pImpl->m_sUser), sPassword(m_pImpl->m_aPassword); + sal_Bool bNewPasswordGiven = sal_False; + + if (m_pImpl->m_bPasswordRequired && (0 == sPassword.getLength())) + { // we need a password, but don't have one yet. + // -> ask the user + + // build an interaction request + // two continuations (Ok and Cancel) + OInteractionAbort* pAbort = new OInteractionAbort; + OAuthenticationContinuation* pAuthenticate = new OAuthenticationContinuation; + + // the name which should be referred in the login dialog + ::rtl::OUString sServerName( m_pImpl->m_sName ); + INetURLObject aURLCheck( sServerName ); + if ( aURLCheck.GetProtocol() != INET_PROT_NOT_VALID ) + sServerName = aURLCheck.getBase( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_UNAMBIGUOUS ); + + // the request + AuthenticationRequest aRequest; + aRequest.ServerName = sServerName; + aRequest.HasRealm = aRequest.HasAccount = sal_False; + aRequest.HasUserName = aRequest.HasPassword = sal_True; + aRequest.UserName = m_pImpl->m_sUser; + aRequest.Password = m_pImpl->m_sFailedPassword.getLength() ? m_pImpl->m_sFailedPassword : m_pImpl->m_aPassword; + OInteractionRequest* pRequest = new OInteractionRequest(makeAny(aRequest)); + Reference< XInteractionRequest > xRequest(pRequest); + // some knittings + pRequest->addContinuation(pAbort); + pRequest->addContinuation(pAuthenticate); + + // handle the request + try + { + MutexRelease aRelease( getMutex() ); + // release the mutex when calling the handler, it may need to lock the SolarMutex + _rxHandler->handle(xRequest); + } + catch(Exception&) + { + DBG_UNHANDLED_EXCEPTION(); + } + + if (!pAuthenticate->wasSelected()) + return Reference< XConnection >(); + + // get the result + sUser = m_pImpl->m_sUser = pAuthenticate->getUser(); + sPassword = pAuthenticate->getPassword(); + + if (pAuthenticate->getRememberPassword()) + { + m_pImpl->m_aPassword = pAuthenticate->getPassword(); + bNewPasswordGiven = sal_True; + } + m_pImpl->m_sFailedPassword = ::rtl::OUString(); + } + + try + { + return getConnection(sUser, sPassword,_bIsolated); + } + catch(Exception&) + { + if (bNewPasswordGiven) + { + m_pImpl->m_sFailedPassword = m_pImpl->m_aPassword; + // assume that we had an authentication problem. Without this we may, after an unsucessful connect, while + // the user gave us a password an the order to remember it, never allow an password input again (at least + // not without restarting the session) + m_pImpl->m_aPassword = ::rtl::OUString(); + } + throw; + } +} + +// ----------------------------------------------------------------------------- +Reference< XConnection > ODatabaseSource::buildIsolatedConnection(const rtl::OUString& user, const rtl::OUString& password) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::buildIsolatedConnection" ); + Reference< XConnection > xConn; + Reference< XConnection > xSdbcConn = buildLowLevelConnection(user, password); + DBG_ASSERT( xSdbcConn.is(), "ODatabaseSource::buildIsolatedConnection: invalid return value of buildLowLevelConnection!" ); + // buildLowLevelConnection is expected to always succeed + if ( xSdbcConn.is() ) + { + // build a connection server and return it (no stubs) + xConn = new OConnection(*this, xSdbcConn, m_pImpl->m_aContext.getLegacyServiceFactory()); + } + return xConn; +} +//------------------------------------------------------------------------------ +Reference< XConnection > ODatabaseSource::getConnection(const rtl::OUString& user, const rtl::OUString& password,sal_Bool _bIsolated) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getConnection" ); + ModelMethodGuard aGuard( *this ); + + Reference< XConnection > xConn; + if ( _bIsolated ) + { + xConn = buildIsolatedConnection(user,password); + } + else + { // create a new proxy for the connection + if ( !m_pImpl->m_xSharedConnectionManager.is() ) + { + m_pImpl->m_pSharedConnectionManager = new OSharedConnectionManager( m_pImpl->m_aContext.getLegacyServiceFactory() ); + m_pImpl->m_xSharedConnectionManager = m_pImpl->m_pSharedConnectionManager; + } + xConn = m_pImpl->m_pSharedConnectionManager->getConnection( + m_pImpl->m_sConnectURL, user, password, m_pImpl->m_xSettings->getPropertyValues(), this ); + } + + if ( xConn.is() ) + { + Reference< XComponent> xComp(xConn,UNO_QUERY); + if ( xComp.is() ) + xComp->addEventListener( static_cast< XContainerListener* >( this ) ); + m_pImpl->m_aConnections.push_back(OWeakConnection(xConn)); + } + + return xConn; +} + +//------------------------------------------------------------------------------ +Reference< XNameAccess > SAL_CALL ODatabaseSource::getBookmarks( ) throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getBookmarks" ); + ModelMethodGuard aGuard( *this ); + return static_cast< XNameContainer* >(&m_aBookmarks); +} + +//------------------------------------------------------------------------------ +Reference< XNameAccess > SAL_CALL ODatabaseSource::getQueryDefinitions( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getQueryDefinitions" ); + ModelMethodGuard aGuard( *this ); + + Reference< XNameAccess > xContainer = m_pImpl->m_xCommandDefinitions; + if ( !xContainer.is() ) + { + 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; +} +//------------------------------------------------------------------------------ +// XTablesSupplier +//------------------------------------------------------------------------------ +Reference< XNameAccess > ODatabaseSource::getTables() throw( RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getTables" ); + ModelMethodGuard aGuard( *this ); + + Reference< XNameAccess > xContainer = m_pImpl->m_xTableDefinitions; + if ( !xContainer.is() ) + { + TContentPtr& rContainerData( m_pImpl->getObjectContainer( ODatabaseModelImpl::E_TABLE ) ); + xContainer = new OCommandContainer( m_pImpl->m_aContext.getLegacyServiceFactory(), *this, rContainerData, sal_True ); + m_pImpl->m_xTableDefinitions = xContainer; + } + return xContainer; +} +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseSource::flush( ) throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::flush" ); + try + { + // SYNCHRONIZED -> + { + ModelMethodGuard aGuard( *this ); + + typedef ::utl::SharedUNOComponent< XModel, ::utl::CloseableComponent > SharedModel; + SharedModel xModel( m_pImpl->getModel_noCreate(), SharedModel::NoTakeOwnership ); + + if ( !xModel.is() ) + xModel.reset( m_pImpl->createNewModel_deliverOwnership( false ), SharedModel::TakeOwnership ); + + Reference< css::frame::XStorable> xStorable( xModel, UNO_QUERY_THROW ); + xStorable->store(); + } + // <- SYNCHRONIZED + + css::lang::EventObject aFlushedEvent(*this); + m_aFlushListeners.notifyEach( &XFlushListener::flushed, aFlushedEvent ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } +} + +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseSource::flushed( const EventObject& /*rEvent*/ ) throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::flushed" ); + ModelMethodGuard aGuard( *this ); + + // Okay, this is some hack. + // + // In general, we have the problem that embedded databases write into their underlying storage, which + // logically is one of our sub storage, and practically is a temporary file maintained by the + // package implementation. As long as we did not commit this storage and our main storage, + // the changes made by the embedded database engine are not really reflected in the database document + // file. This is Bad (TM) for a "real" database application - imagine somebody entering some + // data, and then crashing: For a database application, you would expect that the data still is present + // when you connect to the database next time. + // + // Since this is a conceptual problem as long as we do use those ZIP packages (in fact, we *cannot* + // provide the desired functionality as long as we do not have a package format which allows O(1) writes), + // we cannot completely fix this. However, we can relax the problem by commiting more often - often + // enough so that data loss is more seldom, and seldom enough so that there's no noticable performance + // decrease. + // + // For this, we introduced a few places which XFlushable::flush their connections, and register as + // XFlushListener at the embedded connection (which needs to provide the XFlushable functionality). + // Then, when the connection is flushed, we commit both the database storage and our main storage. + // + // #i55274# / 2005-09-30 / frank.schoenheit@sun.com + + OSL_ENSURE( m_pImpl->isEmbeddedDatabase(), "ODatabaseSource::flushed: no embedded database?!" ); + sal_Bool bWasModified = m_pImpl->m_bModified; + m_pImpl->commitEmbeddedStorage(); + m_pImpl->setModified( bWasModified ); +} + +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseSource::addFlushListener( const Reference< ::com::sun::star::util::XFlushListener >& _xListener ) throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::addFlushListener" ); + m_aFlushListeners.addInterface(_xListener); +} +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseSource::removeFlushListener( const Reference< ::com::sun::star::util::XFlushListener >& _xListener ) throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::removeFlushListener" ); + m_aFlushListeners.removeInterface(_xListener); +} +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseSource::elementInserted( const ContainerEvent& /*Event*/ ) throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::elementInserted" ); + ModelMethodGuard aGuard( *this ); + if ( m_pImpl.is() ) + m_pImpl->setModified(sal_True); +} +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseSource::elementRemoved( const ContainerEvent& /*Event*/ ) throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::elementRemoved" ); + ModelMethodGuard aGuard( *this ); + if ( m_pImpl.is() ) + m_pImpl->setModified(sal_True); +} +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseSource::elementReplaced( const ContainerEvent& /*Event*/ ) throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::elementReplaced" ); + ModelMethodGuard aGuard( *this ); + if ( m_pImpl.is() ) + m_pImpl->setModified(sal_True); +} +// ----------------------------------------------------------------------------- +// XDocumentDataSource +Reference< XOfficeDatabaseDocument > SAL_CALL ODatabaseSource::getDatabaseDocument() throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getDatabaseDocument" ); + ModelMethodGuard aGuard( *this ); + + Reference< XModel > xModel( m_pImpl->getModel_noCreate() ); + if ( !xModel.is() ) + xModel = m_pImpl->createNewModel_deliverOwnership( false ); + + return Reference< XOfficeDatabaseDocument >( xModel, UNO_QUERY_THROW ); +} +// ----------------------------------------------------------------------------- +Reference< XInterface > ODatabaseSource::getThis() const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "ODatabaseSource::getThis" ); + return *const_cast< ODatabaseSource* >( this ); +} +// ----------------------------------------------------------------------------- +//........................................................................ +} // namespace dbaccess +//........................................................................ + + diff --git a/dbaccess/source/core/dataaccess/datasource.hxx b/dbaccess/source/core/dataaccess/datasource.hxx new file mode 100644 index 000000000000..b84b3d74c727 --- /dev/null +++ b/dbaccess/source/core/dataaccess/datasource.hxx @@ -0,0 +1,305 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 _DBA_COREDATAACCESS_DATASOURCE_HXX_ +#define _DBA_COREDATAACCESS_DATASOURCE_HXX_ + +#ifndef _COM_SUN_STAR_UTIL_XNUMBERFORMATSSUPPLIER_HPP_ +#include <com/sun/star/util/XNumberFormatsSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_ +#include <com/sun/star/lang/XServiceInfo.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XDATASOURCE_HPP_ +#include <com/sun/star/sdbc/XDataSource.hpp> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XCONTAINERLISTENER_HPP_ +#include <com/sun/star/container/XContainerListener.hpp> +#endif +#ifndef _COM_SUN_STAR_SDB_XBOOKMARKSSUPPLIER_HPP_ +#include <com/sun/star/sdb/XBookmarksSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_SDB_XQUERYDEFINITIONSSUPPLIER_HPP_ +#include <com/sun/star/sdb/XQueryDefinitionsSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XISOLATEDCONNECTION_HPP_ +#include <com/sun/star/sdbc/XIsolatedConnection.hpp> +#endif +#ifndef _COM_SUN_STAR_UTIL_XNUMBERFORMATTER_HPP_ +#include <com/sun/star/util/XNumberFormatter.hpp> +#endif +#ifndef _COM_SUN_STAR_DOCUMENT_XEVENTLISTENER_HPP_ +#include <com/sun/star/document/XEventListener.hpp> +#endif +#ifndef _COM_SUN_STAR_UTIL_XFLUSHABLE_HPP_ +#include <com/sun/star/util/XFlushable.hpp> +#endif +#ifndef _CPPUHELPER_PROPSHLP_HXX +#include <cppuhelper/propshlp.hxx> +#endif +#ifndef _COMPHELPER_PROPERTY_ARRAY_HELPER_HXX_ +#include <comphelper/proparrhlp.hxx> +#endif +#ifndef _CPPUHELPER_WEAKREF_HXX_ +#include <cppuhelper/weakref.hxx> +#endif +#ifndef _CPPUHELPER_COMPBASE11_HXX_ +#include <cppuhelper/compbase11.hxx> +#endif +#ifndef _COM_SUN_STAR_EMBED_XTRANSACTIONLISTENER_HPP_ +#include <com/sun/star/embed/XTransactionListener.hpp> +#endif +#ifndef _DBASHARED_APITOOLS_HXX_ +#include "apitools.hxx" +#endif +#ifndef _DBA_CORE_BOOKMARKCONTAINER_HXX_ +#include "bookmarkcontainer.hxx" +#endif +#ifndef _VOS_REF_HXX_ +#include <vos/ref.hxx> +#endif +#ifndef _STRING_HXX +#include <tools/string.hxx> +#endif +#ifndef _CONNECTIVITY_COMMONTOOLS_HXX_ +#include <connectivity/CommonTools.hxx> +#endif +#ifndef _COMPHELPER_BROADCASTHELPER_HXX_ +#include <comphelper/broadcasthelper.hxx> +#endif +#ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBUTE_HPP_ +#include <com/sun/star/beans/PropertyAttribute.hpp> +#endif +#ifndef _COM_SUN_STAR_BEANS_PROPERTYVALUE_HPP_ +#include <com/sun/star/beans/PropertyValue.hpp> +#endif +#ifndef _COM_SUN_STAR_SDB_XCOMPLETEDCONNECTION_HPP_ +#include <com/sun/star/sdb/XCompletedConnection.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBCX_XTABLESSUPPLIER_HPP_ +#include <com/sun/star/sdbcx/XTablesSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_EMBED_XSTORAGE_HPP_ +#include <com/sun/star/embed/XStorage.hpp> +#endif +#ifndef DBA_CONTENTHELPER_HXX +#include "ContentHelper.hxx" +#endif +#ifndef _COM_SUN_STAR_DOCUMENT_XSTORAGEBASEDDOCUMENT_HPP_ +#include <com/sun/star/document/XStorageBasedDocument.hpp> +#endif +#ifndef _COM_SUN_STAR_EMBED_ELEMENTMODES_HPP_ +#include <com/sun/star/embed/ElementModes.hpp> +#endif +#ifndef _COM_SUN_STAR_UTIL_XREFRESHABLE_HPP_ +#include <com/sun/star/util/XRefreshable.hpp> +#endif +#ifndef _COM_SUN_STAR_SDB_XDOCUMENTDATASOURCE_HPP_ +#include <com/sun/star/sdb/XDocumentDataSource.hpp> +#endif +#ifndef _DBA_COREDATAACCESS_MODELIMPL_HXX_ +#include "ModelImpl.hxx" +#endif + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + +class OSharedConnectionManager; +class OChildCommitListen_Impl; + +//============================================================ +//= ODatabaseSource +//============================================================ +typedef ::cppu::WeakComponentImplHelper11 < ::com::sun::star::lang::XServiceInfo + , ::com::sun::star::sdbc::XDataSource + , ::com::sun::star::sdb::XBookmarksSupplier + , ::com::sun::star::sdb::XQueryDefinitionsSupplier + , ::com::sun::star::sdb::XCompletedConnection + , ::com::sun::star::container::XContainerListener + , ::com::sun::star::sdbc::XIsolatedConnection + , ::com::sun::star::sdbcx::XTablesSupplier + , ::com::sun::star::util::XFlushable + , ::com::sun::star::util::XFlushListener + , ::com::sun::star::sdb::XDocumentDataSource + > ODatabaseSource_Base; + + +class ODatabaseSource :public ModelDependentComponent // must be first + ,public ODatabaseSource_Base + ,public ::cppu::OPropertySetHelper + ,public ::comphelper::OPropertyArrayUsageHelper < ODatabaseSource > +{ + friend class ODatabaseContext; + friend class OConnection; + friend class OSharedConnectionManager; + +private: + using ODatabaseSource_Base::rBHelper; + OBookmarkContainer m_aBookmarks; + ::cppu::OInterfaceContainerHelper m_aFlushListeners; + +private: + virtual ~ODatabaseSource(); + +public: + ODatabaseSource( const ::rtl::Reference< ODatabaseModelImpl >& _pImpl ); + + struct DBContextAccess { friend class ODatabaseContext; private: DBContextAccess() { } }; + + /** sets a new name for the data source + + The name of a data source (our m_sName member) is the registration name, *if* the + data source actually *is* registered at the database context. + + Normally, this name is passed at time of creation of the ODatabaseModelImpl instance, + but if a newly creaed data source is registered, then it must be possible to propagate + the new trgistration name. + */ + static void setName( + const ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XDocumentDataSource >& _rxDocument, + const ::rtl::OUString& _rNewName, + DBContextAccess + ); + + // XContainerListener + virtual void SAL_CALL elementInserted( const ::com::sun::star::container::ContainerEvent& Event ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL elementRemoved( const ::com::sun::star::container::ContainerEvent& Event ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL elementReplaced( const ::com::sun::star::container::ContainerEvent& Event ) throw (::com::sun::star::uno::RuntimeException); + // ::com::sun::star::sdbcx::XTablesSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > SAL_CALL getTables( ) throw(::com::sun::star::uno::RuntimeException); + +// com::sun::star::lang::XTypeProvider + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes() throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() throw (::com::sun::star::uno::RuntimeException); + +// com::sun::star::uno::XInterface + virtual ::com::sun::star::uno::Any SAL_CALL queryInterface( const ::com::sun::star::uno::Type & rType ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL acquire() throw( ); + virtual void SAL_CALL release() throw( ); + +// ::com::sun::star::lang::XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw(::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::lang::XServiceInfo - static methods + static ::com::sun::star::uno::Sequence< ::rtl::OUString > getSupportedServiceNames_static(void) throw( ::com::sun::star::uno::RuntimeException ); + static ::rtl::OUString getImplementationName_static(void) throw( ::com::sun::star::uno::RuntimeException ); + static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > + SAL_CALL Create(const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >&); + +// OComponentHelper + virtual void SAL_CALL disposing(void); + +// 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); + // XEventListener + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw(::com::sun::star::uno::RuntimeException); + +// comphelper::OPropertyArrayUsageHelper + virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const; + +// cppu::OPropertySetHelper + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(); + + virtual sal_Bool SAL_CALL convertFastPropertyValue( + ::com::sun::star::uno::Any & rConvertedValue, + ::com::sun::star::uno::Any & rOldValue, + sal_Int32 nHandle, + const ::com::sun::star::uno::Any& rValue ) + throw (::com::sun::star::lang::IllegalArgumentException); + virtual void SAL_CALL setFastPropertyValue_NoBroadcast( + sal_Int32 nHandle, + const ::com::sun::star::uno::Any& rValue + ) + throw (::com::sun::star::uno::Exception); + virtual void SAL_CALL getFastPropertyValue( ::com::sun::star::uno::Any& rValue, sal_Int32 nHandle ) const; + +// ::com::sun::star::sdb::XCompletedConnection + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection > SAL_CALL connectWithCompletion( const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& handler ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::sdbc::XDataSource + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection > SAL_CALL getConnection( const ::rtl::OUString& user, const ::rtl::OUString& password ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setLoginTimeout( sal_Int32 seconds ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getLoginTimeout( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + +// :: com::sun::star::sdb::XBookmarksSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > SAL_CALL getBookmarks( ) throw (::com::sun::star::uno::RuntimeException); + +// :: com::sun::star::sdb::XQueryDefinitionsSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > SAL_CALL getQueryDefinitions( ) throw(::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::sdbc::XIsolatedConnection + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection > SAL_CALL getIsolatedConnection( const ::rtl::OUString& user, const ::rtl::OUString& password ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection > SAL_CALL getIsolatedConnectionWithCompletion( const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& handler ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + +// XFlushable + virtual void SAL_CALL flush( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addFlushListener( const ::com::sun::star::uno::Reference< ::com::sun::star::util::XFlushListener >& l ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeFlushListener( const ::com::sun::star::uno::Reference< ::com::sun::star::util::XFlushListener >& l ) throw (::com::sun::star::uno::RuntimeException); + + // XFlushListener + virtual void SAL_CALL flushed( const ::com::sun::star::lang::EventObject& rEvent ) throw (::com::sun::star::uno::RuntimeException); + + // XDocumentDataSource + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XOfficeDatabaseDocument > SAL_CALL getDatabaseDocument() throw (::com::sun::star::uno::RuntimeException); + +protected: + // ModelDependentComponent overridables + virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > getThis() const; + +private: +// helper + /** open a connection for the current settings. this is the simple connection we get from the driver + manager, so it can be used as a master for a "high level" sdb connection. + */ + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection > buildLowLevelConnection( + const ::rtl::OUString& _rUid, const ::rtl::OUString& _rPwd + ); + + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection > buildIsolatedConnection( + const rtl::OUString& user, const rtl::OUString& password + ); + + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection > SAL_CALL getConnection( const ::rtl::OUString& user, const ::rtl::OUString& password , sal_Bool _bIsolated) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection > SAL_CALL connectWithCompletion( const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& handler , sal_Bool _bIsolated) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + void clearConnections(); + +protected: + using ::cppu::OPropertySetHelper::getFastPropertyValue; +}; + +//........................................................................ +} // namespace dbaccess +//........................................................................ + +#endif // _DBA_COREDATAACCESS_DATALINK_HXX_ + + diff --git a/dbaccess/source/core/dataaccess/definitioncontainer.cxx b/dbaccess/source/core/dataaccess/definitioncontainer.cxx new file mode 100644 index 000000000000..33ce2782a1dd --- /dev/null +++ b/dbaccess/source/core/dataaccess/definitioncontainer.cxx @@ -0,0 +1,748 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#ifndef _DBA_CORE_DEFINITIONCONTAINER_HXX_ +#include "definitioncontainer.hxx" +#endif +#ifndef DBACCESS_SHARED_DBASTRINGS_HRC +#include "dbastrings.hrc" +#endif +#ifndef _DBASHARED_APITOOLS_HXX_ +#include "apitools.hxx" +#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 +#ifndef TOOLS_DIAGNOSE_EX_H +#include <tools/diagnose_ex.h> +#endif +#ifndef _COMPHELPER_SEQUENCE_HXX_ +#include <comphelper/sequence.hxx> +#endif +#ifndef _COMPHELPER_ENUMHELPER_HXX_ +#include <comphelper/enumhelper.hxx> +#endif +#ifndef _COMPHELPER_EXTRACT_HXX_ +#include <comphelper/extract.hxx> +#endif +#ifndef _COM_SUN_STAR_LANG_XCOMPONENT_HPP_ +#include <com/sun/star/lang/XComponent.hpp> +#endif +#ifndef _COM_SUN_STAR_UCB_COMMANDINFO_HPP_ +#include <com/sun/star/ucb/CommandInfo.hpp> +#endif +#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_ +#include <com/sun/star/beans/XPropertySet.hpp> +#endif +#ifndef _COM_SUN_STAR_SDB_ERRORCONDITION_HPP_ +#include <com/sun/star/sdb/ErrorCondition.hpp> +#endif +#ifndef _COMPHELPER_TYPES_HXX_ +#include <comphelper/types.hxx> +#endif +#ifndef _UCBHELPER_CONTENTIDENTIFIER_HXX +#include <ucbhelper/contentidentifier.hxx> +#endif + + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::sdb; +using namespace ::osl; +using namespace ::comphelper; +using namespace ::cppu; +using namespace ::com::sun::star::ucb; + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + +//========================================================================== +//= ODefinitionContainer_Impl +//========================================================================== +//-------------------------------------------------------------------------- +void ODefinitionContainer_Impl::erase( TContentPtr _pDefinition ) +{ + NamedDefinitions::iterator aPos = find( _pDefinition ); + if ( aPos != end() ) + m_aDefinitions.erase( aPos ); +} + +//-------------------------------------------------------------------------- +ODefinitionContainer_Impl::const_iterator ODefinitionContainer_Impl::find( TContentPtr _pDefinition ) const +{ + return ::std::find_if( + m_aDefinitions.begin(), + m_aDefinitions.end(), + ::std::compose1( + ::std::bind2nd( ::std::equal_to< TContentPtr >(), _pDefinition ), + ::std::select2nd< NamedDefinitions::value_type >() + ) + ); +} + +//-------------------------------------------------------------------------- +ODefinitionContainer_Impl::iterator ODefinitionContainer_Impl::find( TContentPtr _pDefinition ) +{ + return ::std::find_if( + m_aDefinitions.begin(), + m_aDefinitions.end(), + ::std::compose1( + ::std::bind2nd( ::std::equal_to< TContentPtr >(), _pDefinition ), + ::std::select2nd< NamedDefinitions::value_type >() + ) + ); +} + +//========================================================================== +//= ODefinitionContainer +//========================================================================== +DBG_NAME(ODefinitionContainer) +//-------------------------------------------------------------------------- +ODefinitionContainer::ODefinitionContainer( const Reference< XMultiServiceFactory >& _xORB + , const Reference< XInterface >& _xParentContainer + , const TContentPtr& _pImpl + , bool _bCheckSlash + ) + :OContentHelper(_xORB,_xParentContainer,_pImpl) + ,m_aApproveListeners(m_aMutex) + ,m_aContainerListeners(m_aMutex) + ,m_bInPropertyChange(sal_False) + ,m_bCheckSlash(_bCheckSlash) +{ + m_pImpl->m_aProps.bIsDocument = sal_False; + m_pImpl->m_aProps.bIsFolder = sal_True; + + const ODefinitionContainer_Impl& rDefinitions( getDefinitions() ); + ODefinitionContainer_Impl::const_iterator aEnd = rDefinitions.end(); + for ( ODefinitionContainer_Impl::const_iterator aDefinition = rDefinitions.begin(); + aDefinition != aEnd; + ++aDefinition + ) + m_aDocuments.push_back( + m_aDocumentMap.insert( + Documents::value_type( aDefinition->first, Documents::mapped_type() ) ).first ); + + DBG_CTOR(ODefinitionContainer, NULL); +} + +//-------------------------------------------------------------------------- +void SAL_CALL ODefinitionContainer::disposing() +{ + OContentHelper::disposing(); + + MutexGuard aGuard(m_aMutex); + + // say our listeners goobye + EventObject aEvt(*this); + m_aApproveListeners.disposeAndClear(aEvt); + m_aContainerListeners.disposeAndClear(aEvt); + + // dispose our elements + Documents::iterator aIter = m_aDocumentMap.begin(); + Documents::iterator aEnd = m_aDocumentMap.end(); + + for (; aIter != aEnd; ++aIter) + { + Reference<XContent> xProp = aIter->second; + if ( xProp.is() ) + { + removeObjectListener(xProp); + ::comphelper::disposeComponent(xProp); + } + } + + // remove our elements + m_aDocuments.clear(); + // !!! do this before clearing the map which the vector elements refer to !!! + m_aDocumentMap.clear(); +} + +//-------------------------------------------------------------------------- +ODefinitionContainer::~ODefinitionContainer() +{ + DBG_DTOR(ODefinitionContainer, NULL); +} + +IMPLEMENT_FORWARD_XINTERFACE2( ODefinitionContainer,OContentHelper,ODefinitionContainer_Base) +IMPLEMENT_TYPEPROVIDER2(ODefinitionContainer,OContentHelper,ODefinitionContainer_Base); +// XServiceInfo +//-------------------------------------------------------------------------- +::rtl::OUString SAL_CALL ODefinitionContainer::getImplementationName( ) throw(RuntimeException) +{ + return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sdb.ODefinitionContainer")); +} +//-------------------------------------------------------------------------- +Sequence< ::rtl::OUString > SAL_CALL ODefinitionContainer::getSupportedServiceNames( ) throw(RuntimeException) +{ + Sequence< ::rtl::OUString > aReturn(2); + aReturn.getArray()[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sdb.DefinitionContainer")); + aReturn.getArray()[1] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.ucb.Content")); + return aReturn; +} + +// XNameContainer +//-------------------------------------------------------------------------- +void SAL_CALL ODefinitionContainer::insertByName( const ::rtl::OUString& _rName, const Any& aElement ) throw(IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException) +{ + ResettableMutexGuard aGuard(m_aMutex); + + // approve the new object + Reference< XContent > xNewElement(aElement,UNO_QUERY); + approveNewObject( _rName, xNewElement ); // will throw if necessary + + notifyByName( aGuard, _rName, xNewElement, NULL, E_INSERTED, ApproveListeners ); + implAppend( _rName, xNewElement ); + notifyByName( aGuard, _rName, xNewElement, NULL, E_INSERTED, ContainerListemers ); +} + +//-------------------------------------------------------------------------- +void SAL_CALL ODefinitionContainer::removeByName( const ::rtl::OUString& _rName ) throw(NoSuchElementException, WrappedTargetException, RuntimeException) +{ + ResettableMutexGuard aGuard(m_aMutex); + + // check the arguments + if (!_rName.getLength()) + throw IllegalArgumentException(); + + if (!checkExistence(_rName)) + throw NoSuchElementException(_rName,*this); + + // the old element (for the notifications) + Reference< XContent > xOldElement = implGetByName( _rName, impl_haveAnyListeners_nothrow() ); + + // do the removal + notifyByName( aGuard, _rName, NULL, xOldElement, E_REMOVED, ApproveListeners ); + implRemove( _rName ); + notifyByName( aGuard, _rName, NULL, xOldElement, E_REMOVED, ContainerListemers ); + + removeObjectListener( xOldElement ); + disposeComponent(xOldElement); +} + +// XNameReplace +//-------------------------------------------------------------------------- +void SAL_CALL ODefinitionContainer::replaceByName( const ::rtl::OUString& _rName, const Any& aElement ) throw(IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException) +{ + ResettableMutexGuard aGuard(m_aMutex); + + // let derived classes approve the new object + Reference< XContent > xNewElement(aElement,UNO_QUERY); + approveNewObject( _rName, xNewElement ); // will throw if necessary + + // the old element (for the notifications) + Reference< XContent > xOldElement = implGetByName( _rName, impl_haveAnyListeners_nothrow() ); + + notifyByName( aGuard, _rName, xNewElement, xOldElement, E_REPLACED, ApproveListeners ); + implReplace( _rName, xNewElement ); + notifyByName( aGuard, _rName, xNewElement, xOldElement, E_REPLACED, ContainerListemers ); + + // and dispose it + disposeComponent(xOldElement); +} + +// ----------------------------------------------------------------------------- +namespace +{ + typedef Reference< XVeto > ( SAL_CALL XContainerApproveListener::*ContainerApprovalMethod )( const ContainerEvent& ); + + struct RaiseExceptionFromVeto + { + private: + ContainerApprovalMethod m_pMethod; + const ContainerEvent& m_rEvent; + + public: + RaiseExceptionFromVeto( ContainerApprovalMethod _pMethod, const ContainerEvent& _rEvent ) + :m_pMethod( _pMethod ) + ,m_rEvent( _rEvent ) + { + } + + void operator()( const Reference< XContainerApproveListener >& _Listener ) const + { + Reference< XVeto > xVeto = (_Listener.get()->*m_pMethod)( m_rEvent ); + if ( !xVeto.is() ) + return; + + Any eVetoDetails = xVeto->getDetails(); + + IllegalArgumentException aIllegalArgumentError; + if ( eVetoDetails >>= aIllegalArgumentError ) + throw aIllegalArgumentError; + + WrappedTargetException aWrappedError; + if ( eVetoDetails >>= aWrappedError ) + throw aWrappedError; + + throw WrappedTargetException( xVeto->getReason(), _Listener.get(), eVetoDetails ); + } + }; +} + +// ----------------------------------------------------------------------------- +void ODefinitionContainer::notifyByName( ResettableMutexGuard& _rGuard, const ::rtl::OUString& _rName, + const Reference< XContent >& _xNewElement, const Reference< XContent >& _xOldElement, + ContainerOperation _eOperation, ListenerType _eType ) +{ + bool bApprove = ( _eType == ApproveListeners ); + + ::cppu::OInterfaceContainerHelper& rContainer( bApprove ? m_aApproveListeners : m_aContainerListeners ); + if ( !rContainer.getLength() ) + return; + + ContainerEvent aEvent( *this, makeAny( _rName ), makeAny( _xNewElement ), makeAny( _xOldElement ) ); + + _rGuard.clear(); + switch ( _eOperation ) + { + case E_INSERTED: + if ( bApprove ) + rContainer.forEach< XContainerApproveListener, RaiseExceptionFromVeto >( + RaiseExceptionFromVeto( &XContainerApproveListener::approveInsertElement, aEvent ) ); + else + rContainer.notifyEach( &XContainerListener::elementInserted, aEvent ); + break; + case E_REPLACED: + if ( bApprove ) + rContainer.forEach< XContainerApproveListener, RaiseExceptionFromVeto >( + RaiseExceptionFromVeto( &XContainerApproveListener::approveReplaceElement, aEvent ) ); + else + rContainer.notifyEach( &XContainerListener::elementReplaced, aEvent ); + break; + case E_REMOVED: + if ( bApprove ) + rContainer.forEach< XContainerApproveListener, RaiseExceptionFromVeto >( + RaiseExceptionFromVeto( &XContainerApproveListener::approveRemoveElement, aEvent ) ); + else + rContainer.notifyEach( &XContainerListener::elementRemoved, aEvent ); + break; + } + + if ( bApprove ) + _rGuard.reset(); +} + +//-------------------------------------------------------------------------- +void SAL_CALL ODefinitionContainer::addContainerListener( const Reference< XContainerListener >& _rxListener ) throw(RuntimeException) +{ + if (_rxListener.is()) + m_aContainerListeners.addInterface(_rxListener); +} + +//-------------------------------------------------------------------------- +void SAL_CALL ODefinitionContainer::removeContainerListener( const Reference< XContainerListener >& _rxListener ) throw(RuntimeException) +{ + if (_rxListener.is()) + m_aContainerListeners.removeInterface(_rxListener); +} + +//-------------------------------------------------------------------------- +void SAL_CALL ODefinitionContainer::addContainerApproveListener( const Reference< XContainerApproveListener >& _Listener ) throw (RuntimeException) +{ + if ( _Listener.is() ) + m_aApproveListeners.addInterface( _Listener ); +} + +//-------------------------------------------------------------------------- +void SAL_CALL ODefinitionContainer::removeContainerApproveListener( const Reference< XContainerApproveListener >& _Listener ) throw (RuntimeException) +{ + if ( _Listener.is() ) + m_aApproveListeners.removeInterface( _Listener ); +} + + +// XElementAccess +//-------------------------------------------------------------------------- +Type SAL_CALL ODefinitionContainer::getElementType( ) throw (RuntimeException) +{ + return ::getCppuType( static_cast< Reference< XContent >* >(NULL) ); +} + +//-------------------------------------------------------------------------- +sal_Bool SAL_CALL ODefinitionContainer::hasElements( ) throw (RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + return !m_aDocuments.empty(); +} + +// XEnumerationAccess +//-------------------------------------------------------------------------- +Reference< XEnumeration > SAL_CALL ODefinitionContainer::createEnumeration( ) throw(RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + return new ::comphelper::OEnumerationByIndex(static_cast<XIndexAccess*>(this)); +} + +//-------------------------------------------------------------------------- +// XIndexAccess +sal_Int32 SAL_CALL ODefinitionContainer::getCount( ) throw(RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + return m_aDocuments.size(); +} + +//-------------------------------------------------------------------------- +Any SAL_CALL ODefinitionContainer::getByIndex( sal_Int32 _nIndex ) throw(IndexOutOfBoundsException, WrappedTargetException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + + if ((_nIndex < 0) || (_nIndex >= (sal_Int32)m_aDocuments.size())) + throw IndexOutOfBoundsException(); + + Documents::iterator aPos = m_aDocuments[_nIndex]; + Reference<XContent> xProp = aPos->second; + if (!xProp.is()) + { // that's the first access to the object + // -> create it + xProp = createObject(aPos->first); + aPos->second = Documents::mapped_type(); + // and update the name-access map + } + + return makeAny(xProp); +} + +//-------------------------------------------------------------------------- +Any SAL_CALL ODefinitionContainer::getByName( const ::rtl::OUString& _rName ) throw(NoSuchElementException, WrappedTargetException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + + return makeAny( implGetByName( _rName, sal_True ) ); +} + +//-------------------------------------------------------------------------- +Reference< XContent > ODefinitionContainer::implGetByName(const ::rtl::OUString& _rName, sal_Bool _bReadIfNeccessary) throw (NoSuchElementException) +{ + Documents::iterator aMapPos = m_aDocumentMap.find(_rName); + if (aMapPos == m_aDocumentMap.end()) + throw NoSuchElementException(_rName,*this); + + Reference< XContent > xProp = aMapPos->second; + + if (_bReadIfNeccessary && !xProp.is()) + { // the object has never been accessed before, so we have to read it now + // (that's the expensive part) + + // create the object and insert it into the map + xProp = createObject(_rName); + aMapPos->second = xProp; + addObjectListener(xProp); + } + + return xProp; +} + +//-------------------------------------------------------------------------- +Sequence< ::rtl::OUString > SAL_CALL ODefinitionContainer::getElementNames( ) throw(RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + + Sequence< ::rtl::OUString > aNames(m_aDocumentMap.size()); + ::rtl::OUString* pNames = aNames.getArray(); + Documents::iterator aEnd = m_aDocumentMap.end(); + for ( Documents::iterator aNameIter = m_aDocumentMap.begin(); + aNameIter != aEnd; + ++pNames, ++aNameIter + ) + { + *pNames = aNameIter->first; + } + + return aNames; +} + +//-------------------------------------------------------------------------- +sal_Bool SAL_CALL ODefinitionContainer::hasByName( const ::rtl::OUString& _rName ) throw(RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + + return checkExistence(_rName); +} + +//-------------------------------------------------------------------------- +void SAL_CALL ODefinitionContainer::disposing( const EventObject& _rSource ) throw(RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + Reference< XContent > xSource(_rSource.Source, UNO_QUERY); + // it's one of our documents .... + Documents::iterator aIter = m_aDocumentMap.begin(); + Documents::iterator aEnd = m_aDocumentMap.end(); + for (;aIter != aEnd;++aIter ) + { + if ( xSource == aIter->second.get() ) + { + removeObjectListener(xSource); + // and clear our document map/vector, so the object will be recreated on next access + aIter->second = Documents::mapped_type(); + } + } +} + +//-------------------------------------------------------------------------- +void ODefinitionContainer::implRemove(const ::rtl::OUString& _rName) +{ + // from the object maps + Documents::iterator aFind = m_aDocumentMap.find(_rName); + if ( aFind != m_aDocumentMap.end() ) + { + m_aDocuments.erase( ::std::find(m_aDocuments.begin(),m_aDocuments.end(),aFind)); + m_aDocumentMap.erase(aFind); + + getDefinitions().erase( _rName ); + + notifyDataSourceModified(); + } +} + +//-------------------------------------------------------------------------- +namespace +{ + bool lcl_ensureName( const Reference< XContent >& _rxContent, const ::rtl::OUString& _rName ) + { + if ( !_rxContent.is() ) + return true; + + // .......................................................... + // obtain the current name. If it's the same as the new one, + // don't do anything + try + { + Reference< XPropertySet > xProps( _rxContent, UNO_QUERY ); + if ( xProps.is() ) + { + ::rtl::OUString sCurrentName; + OSL_VERIFY( xProps->getPropertyValue( PROPERTY_NAME ) >>= sCurrentName ); + if ( sCurrentName.equals( _rName ) ) + return true; + } + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "lcl_ensureName: caught an exception while obtaining the current name!" ); + } + + // .......................................................... + // set the new name + Reference< XRename > xRename( _rxContent, UNO_QUERY ); + OSL_ENSURE( xRename.is(), "lcl_ensureName: invalid content (not renameable)!" ); + if ( !xRename.is() ) + return false; + try + { + xRename->rename( _rName ); + return true; + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "lcl_ensureName: caught an exception!" ); + } + return false; + } +} +//-------------------------------------------------------------------------- +void ODefinitionContainer::implAppend(const ::rtl::OUString& _rName, const Reference< XContent >& _rxNewObject) +{ + MutexGuard aGuard(m_aMutex); + try + { + Reference<XChild> xChild(_rxNewObject,UNO_QUERY); + if ( xChild.is() ) + xChild->setParent(static_cast<OWeakObject*>(this)); + + ODefinitionContainer_Impl& rDefinitions( getDefinitions() ); + ODefinitionContainer_Impl::const_iterator aFind = rDefinitions.find( _rName ); + if ( aFind == rDefinitions.end() ) + { + // ensure that the new object thas the proper name. + // Somebody could create an object with name "foo", and insert it as "bar" + // into a container. In this case, we need to ensure that the object name + // is also "bar" + // #i44786# / 2005-03-11 / frank.schoenheit@sun.com + lcl_ensureName( _rxNewObject, _rName ); + + ::rtl::Reference< OContentHelper > pContent = OContentHelper::getImplementation( _rxNewObject ); + if ( pContent.is() ) + { + TContentPtr pImpl = pContent->getImpl(); + rDefinitions.erase( pImpl ); + pImpl->m_aProps.aTitle = _rName; + rDefinitions.insert( _rName, pImpl ); + } + } + + + m_aDocuments.push_back(m_aDocumentMap.insert(Documents::value_type(_rName,_rxNewObject)).first); + notifyDataSourceModified(); + // now update our structures + if ( _rxNewObject.is() ) + addObjectListener(_rxNewObject); + } + catch(Exception&) + { + DBG_ERROR("ODefinitionContainer::implAppend: caught something !"); + } +} + +//-------------------------------------------------------------------------- +void ODefinitionContainer::implReplace(const ::rtl::OUString& _rName, const Reference< XContent >& _rxNewObject) +{ + DBG_ASSERT(checkExistence(_rName), "ODefinitionContainer::implReplace : invalid name !"); + + Documents::iterator aFind = m_aDocumentMap.find(_rName); + removeObjectListener(aFind->second); + aFind->second = _rxNewObject; + addObjectListener(aFind->second); +} + +// ----------------------------------------------------------------------------- +void ODefinitionContainer::approveNewObject(const ::rtl::OUString& _sName,const Reference< XContent >& _rxObject) const +{ + // check the arguments + if ( !_sName.getLength() ) + throw IllegalArgumentException( + DBA_RES( RID_STR_NAME_MUST_NOT_BE_EMPTY ), + *this, + 0 ); + + if ( m_bCheckSlash && _sName.indexOf( '/' ) != -1 ) + throw IllegalArgumentException( + m_aErrorHelper.getErrorMessage( ErrorCondition::DB_OBJECT_NAME_WITH_SLASHES ), + *this, + 0 ); + + if ( !_rxObject.is() ) + throw IllegalArgumentException( + DBA_RES( RID_STR_NO_NULL_OBJECTS_IN_CONTAINER ), + *this, + 0 ); + + const ODefinitionContainer_Impl& rDefinitions( getDefinitions() ); + if ( rDefinitions.find( _sName ) != rDefinitions.end() ) + throw ElementExistException( + DBA_RES( RID_STR_NAME_ALREADY_USED ), + *this ); + + ::rtl::Reference< OContentHelper > pContent( OContentHelper::getImplementation( _rxObject ) ); + if ( !pContent.is() ) + throw IllegalArgumentException( + DBA_RES( RID_STR_OBJECT_CONTAINER_MISMATCH ), + *this, + 1 ); + + if ( rDefinitions.find( pContent->getImpl() ) != rDefinitions.end() ) + throw ElementExistException( + DBA_RES( RID_STR_OBJECT_ALREADY_CONTAINED ), + *this ); +} + +// ----------------------------------------------------------------------------- +// XPropertyChangeListener +void SAL_CALL ODefinitionContainer::propertyChange( const PropertyChangeEvent& evt ) throw (RuntimeException) +{ + ClearableMutexGuard aGuard(m_aMutex); + if(evt.PropertyName == (rtl::OUString) PROPERTY_NAME || evt.PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Title" ) )) + { + m_bInPropertyChange = sal_True; + try + { + ::rtl::OUString sNewName,sOldName; + evt.OldValue >>= sOldName; + evt.NewValue >>= sNewName; + Reference<XContent> xContent( evt.Source, UNO_QUERY ); + removeObjectListener( xContent ); + implRemove( sOldName ); + implAppend( sNewName, xContent ); + } + catch(const Exception&) + { + DBG_UNHANDLED_EXCEPTION(); + throw RuntimeException(); + } + m_bInPropertyChange = sal_False; + } +} +// ----------------------------------------------------------------------------- +// XVetoableChangeListener +void SAL_CALL ODefinitionContainer::vetoableChange( const PropertyChangeEvent& aEvent ) throw (PropertyVetoException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + + if(aEvent.PropertyName == (rtl::OUString) PROPERTY_NAME || aEvent.PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) + { + ::rtl::OUString sNewName; + aEvent.NewValue >>= sNewName; + if(hasByName(sNewName)) + throw PropertyVetoException(); + } +} +// ----------------------------------------------------------------------------- +void ODefinitionContainer::addObjectListener(const Reference< XContent >& _xNewObject) +{ + OSL_ENSURE(_xNewObject.is(),"ODefinitionContainer::addObjectListener: Object is null!"); + Reference<XPropertySet> xProp(_xNewObject,UNO_QUERY); + if ( xProp.is() ) + { + xProp->addPropertyChangeListener(PROPERTY_NAME, this); + xProp->addVetoableChangeListener(PROPERTY_NAME, this); + } +} +// ----------------------------------------------------------------------------- +void ODefinitionContainer::removeObjectListener(const Reference< XContent >& _xNewObject) +{ + Reference<XPropertySet> xProp(_xNewObject,UNO_QUERY); + if ( xProp.is() ) + { + xProp->removePropertyChangeListener(PROPERTY_NAME, this); + xProp->removeVetoableChangeListener(PROPERTY_NAME, this); + } +} +// ----------------------------------------------------------------------------- +sal_Bool ODefinitionContainer::checkExistence(const ::rtl::OUString& _rName) +{ + return m_aDocumentMap.find(_rName) != m_aDocumentMap.end(); +} + +//........................................................................ +} +// namespace dbaccess +//........................................................................ diff --git a/dbaccess/source/core/dataaccess/documentcontainer.cxx b/dbaccess/source/core/dataaccess/documentcontainer.cxx new file mode 100644 index 000000000000..d9427eff0463 --- /dev/null +++ b/dbaccess/source/core/dataaccess/documentcontainer.cxx @@ -0,0 +1,833 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#ifndef _DBA_COREDATAACCESS_DOCUMENTCONTAINER_HXX_ +#include "documentcontainer.hxx" +#endif +#ifndef DBACCESS_SHARED_DBASTRINGS_HRC +#include "dbastrings.hrc" +#endif +#ifndef _DBA_COREDATAACCESS_DOCUMENTDEFINITION_HXX_ +#include "documentdefinition.hxx" +#endif +#ifndef _COM_SUN_STAR_UCB_OPENCOMMANDARGUMENT2_HPP_ +#include <com/sun/star/ucb/OpenCommandArgument2.hpp> +#endif +#ifndef _COM_SUN_STAR_UCB_OPENMODE_HPP_ +#include <com/sun/star/ucb/OpenMode.hpp> +#endif +#ifndef _TOOLS_DEBUG_HXX +#include <tools/debug.hxx> +#endif +#ifndef _CONNECTIVITY_DBTOOLS_HXX_ +#include <connectivity/dbtools.hxx> +#endif +#ifndef DBA_UCPRESULTSET_HXX +#include "myucp_resultset.hxx" +#endif +#ifndef _UCBHELPER_CANCELCOMMANDEXECUTION_HXX_ +#include <ucbhelper/cancelcommandexecution.hxx> +#endif +#ifndef _COM_SUN_STAR_UCB_UNSUPPORTEDOPENMODEEXCEPTION_HPP_ +#include <com/sun/star/ucb/UnsupportedOpenModeException.hpp> +#endif +#ifndef _COM_SUN_STAR_UCB_INSERTCOMMANDARGUMENT_HPP_ +#include <com/sun/star/ucb/InsertCommandArgument.hpp> +#endif +#ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBUTE_HPP_ +#include <com/sun/star/beans/PropertyAttribute.hpp> +#endif +#ifndef _COM_SUN_STAR_SDB_ERRORCONDITION_HPP_ +#include <com/sun/star/sdb/ErrorCondition.hpp> +#endif +#ifndef _DBA_COREDATAACCESS_DATASOURCE_HXX_ +#include "datasource.hxx" +#endif +#include <comphelper/classids.hxx> +#ifndef _COMPHELPER_MIMECONFIGHELPER_HXX_ +#include <comphelper/mimeconfighelper.hxx> +#endif +#ifndef INCLUDED_COMPHELPER_STRING_HXX +#include <comphelper/string.hxx> +#endif +#ifndef CONNECTIVITY_SQLERROR_HXX +#include <connectivity/sqlerror.hxx> +#endif +#include "core_resource.hxx" +#include "core_resource.hrc" +#include <comphelper/namedvaluecollection.hxx> + +#include <vcl/svapp.hxx> +#include <vos/mutex.hxx> +#include <comphelper/namedvaluecollection.hxx> + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::embed; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::ucb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::io; +using namespace ::osl; +using namespace ::comphelper; +using namespace ::cppu; + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + +//========================================================================== +//= LocalNameApproval +//========================================================================== +class LocalNameApproval : public IContainerApprove +{ + ::connectivity::SQLError m_aErrors; + +public: + LocalNameApproval( const Reference< XMultiServiceFactory >& _rxFactory ) + :m_aErrors( ::comphelper::ComponentContext( _rxFactory ) ) + { + } + virtual ~LocalNameApproval() + { + } + + void SAL_CALL approveElement( const ::rtl::OUString& _rName, const Reference< XInterface >& _rxElement ); +}; + +//-------------------------------------------------------------------------- +void SAL_CALL LocalNameApproval::approveElement( const ::rtl::OUString& _rName, const Reference< XInterface >& /*_rxElement*/ ) +{ + if ( _rName.indexOf( '/' ) != -1 ) + throw IllegalArgumentException( + m_aErrors.getErrorMessage( ErrorCondition::DB_OBJECT_NAME_WITH_SLASHES ), + NULL, + 0 + ); +} + +//========================================================================== +//= ODocumentContainer +//========================================================================== +DBG_NAME(ODocumentContainer) +//-------------------------------------------------------------------------- +ODocumentContainer::ODocumentContainer(const Reference< XMultiServiceFactory >& _xORB + ,const Reference< XInterface >& _xParentContainer + ,const TContentPtr& _pImpl + , sal_Bool _bFormsContainer + ) + :ODefinitionContainer(_xORB,_xParentContainer,_pImpl) + ,OPropertyStateContainer(OContentHelper::rBHelper) + ,m_bFormsContainer(_bFormsContainer) +{ + DBG_CTOR(ODocumentContainer, NULL); + registerProperty(PROPERTY_NAME, PROPERTY_ID_NAME, PropertyAttribute::BOUND | PropertyAttribute::READONLY | PropertyAttribute::CONSTRAINED, + &m_pImpl->m_aProps.aTitle, ::getCppuType(&m_pImpl->m_aProps.aTitle)); + + setElementApproval( PContainerApprove( new LocalNameApproval ( _xORB ) ) ); +} + +//-------------------------------------------------------------------------- +ODocumentContainer::~ODocumentContainer() +{ + DBG_DTOR(ODocumentContainer, NULL); + + if ( !OContentHelper::rBHelper.bInDispose && !OContentHelper::rBHelper.bDisposed ) + { + acquire(); + dispose(); + } +} +// ----------------------------------------------------------------------------- +IMPLEMENT_FORWARD_XINTERFACE3( ODocumentContainer,ODefinitionContainer,ODocumentContainer_Base,OPropertyStateContainer) +IMPLEMENT_TYPEPROVIDER3(ODocumentContainer,ODefinitionContainer,OPropertyStateContainer,ODocumentContainer_Base); +IMPLEMENT_SERVICE_INFO_IMPLNAME(ODocumentContainer, "com.sun.star.comp.dba.ODocumentContainer"); +IMPLEMENT_SERVICE_INFO_SUPPORTS(ODocumentContainer); +IMPLEMENT_PROPERTYCONTAINER_DEFAULTS(ODocumentContainer) + +Sequence< ::rtl::OUString > SAL_CALL ODocumentContainer::getSupportedServiceNames( ) throw(RuntimeException) +{ + Sequence< ::rtl::OUString > aSupported(1); + aSupported[0] = m_bFormsContainer ? SERVICE_NAME_FORM_COLLECTION : SERVICE_NAME_REPORT_COLLECTION; + return aSupported; +} + +// ----------------------------------------------------------------------------- +::rtl::OUString ODocumentContainer::determineContentType() const +{ + return ::rtl::OUString(); +} + +//-------------------------------------------------------------------------- +Reference< XContent > ODocumentContainer::createObject( const ::rtl::OUString& _rName) +{ + const ODefinitionContainer_Impl& rDefinitions( getDefinitions() ); + ODefinitionContainer_Impl::const_iterator aFind = rDefinitions.find( _rName ); + OSL_ENSURE( aFind != rDefinitions.end(), "ODocumentContainer::createObject:Invalid entry in map!" ); + if ( aFind->second->m_aProps.bIsFolder ) + return new ODocumentContainer( m_aContext.getLegacyServiceFactory(), *this, aFind->second, m_bFormsContainer ); + return new ODocumentDefinition( *this, m_aContext.getLegacyServiceFactory(), aFind->second, m_bFormsContainer ); +} +// ----------------------------------------------------------------------------- +Reference< XInterface > SAL_CALL ODocumentContainer::createInstance( const ::rtl::OUString& aServiceSpecifier ) throw (Exception, RuntimeException) +{ + 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) +{ + Reference< XInterface > xRet; + Reference< XContent > xContent; + if ( ServiceSpecifier == SERVICE_SDB_DOCUMENTDEFINITION ) + { + MutexGuard aGuard(m_aMutex); + + // 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; + + ::comphelper::NamedValueCollection aArgs( _aArguments ); + 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() ) + { + if ( !( aClassIDArg >>= aClassID ) ) + { + // 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 ) + { + const static ::rtl::OUString sBaseName(RTL_CONSTASCII_USTRINGPARAM("Obj")); + // ----------------------------------------------------------------------------- + sPersistentName = sBaseName; + sPersistentName += ::rtl::OUString::valueOf(sal_Int32(rDefinitions.size() + 1)); + Reference<XNameAccess> xElements(getContainerStorage(),UNO_QUERY); + if ( xElements.is() ) + sPersistentName = ::dbtools::createUniqueName(xElements,sPersistentName); + + const bool bNeedClassID = ( aClassID.getLength() == 0 ) && ( 0 == sURL.getLength() ); + if ( xCopyFrom.is() ) + { + Sequence<Any> aIni(2); + aIni[0] <<= getContainerStorage(); + aIni[1] <<= sPersistentName; + Command aCommand; + aCommand.Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("copyTo")); + aCommand.Argument <<= aIni; + + xCopyFrom->execute(aCommand,-1,Reference< XCommandEnvironment >()); + Reference<XPropertySet> xProp(xCopyFrom,UNO_QUERY); + if ( xProp.is() && xProp->getPropertySetInfo().is() && xProp->getPropertySetInfo()->hasPropertyByName(PROPERTY_AS_TEMPLATE) ) + xProp->getPropertyValue(PROPERTY_AS_TEMPLATE) >>= bAsTemplate; + + // if we do not have an own class ID, see if we can determine one from the copy we just created + if ( bNeedClassID ) + ODocumentDefinition::GetDocumentServiceFromMediaType( getContainerStorage(), sPersistentName, m_aContext, aClassID ); + } + else + { + 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 >() ); + } + } + } + } + + ODefinitionContainer_Impl::const_iterator aFind = rDefinitions.find( sName ); + TContentPtr pElementImpl; + if ( bNew || ( aFind == rDefinitions.end() ) ) + { + pElementImpl.reset( new OContentHelper_Impl ); + if ( !bNew ) + pElementImpl->m_aProps.aTitle = sName; + + pElementImpl->m_aProps.sPersistentName = sPersistentName; + pElementImpl->m_aProps.bAsTemplate = bAsTemplate; + pElementImpl->m_pDataSource = m_pImpl->m_pDataSource; + } + else + pElementImpl = aFind->second; + + ::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() ) + { + Sequence<Any> aIni(2); + aIni[0] <<= sURL; + Command aCommand; + aCommand.Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("insert")); + aCommand.Argument <<= aIni; + Reference< XCommandProcessor > xCommandProcessor(xContent,UNO_QUERY); + if ( xContent.is() ) + { + xCommandProcessor->execute(aCommand,-1,Reference< XCommandEnvironment >()); + } + } + + // xRet = xContent; + } + else if ( ServiceSpecifier == SERVICE_NAME_FORM_COLLECTION || SERVICE_NAME_REPORT_COLLECTION == ServiceSpecifier ) + { + const Any* pBegin = _aArguments.getConstArray(); + const Any* pEnd = pBegin + _aArguments.getLength(); + PropertyValue aValue; + ::rtl::OUString sName; + Reference<XNameAccess> xCopyFrom; + for(;pBegin != pEnd;++pBegin) + { + *pBegin >>= aValue; + if ( aValue.Name.equalsAscii(PROPERTY_NAME) ) + { + aValue.Value >>= sName; + } + else if ( aValue.Name.equalsAscii(PROPERTY_EMBEDDEDOBJECT) ) + { + xCopyFrom.set(aValue.Value,UNO_QUERY); + } + } + OSL_ENSURE(sName.getLength(),"Invalid name for a document container!"); + const ODefinitionContainer_Impl& rDefinitions( getDefinitions() ); + ODefinitionContainer_Impl::const_iterator aFind = rDefinitions.find( sName ); + TContentPtr pElementImpl; + if ( aFind == rDefinitions.end() ) + { + pElementImpl.reset(new ODefinitionContainer_Impl); + pElementImpl->m_aProps.aTitle = sName; + pElementImpl->m_pDataSource = m_pImpl->m_pDataSource; + } + else + pElementImpl = aFind->second; + OSL_ENSURE( pElementImpl ," Invalid entry in map!"); + xContent = new ODocumentContainer( m_aContext.getLegacyServiceFactory(), *this, pElementImpl, ServiceSpecifier == SERVICE_NAME_FORM_COLLECTION ); + + // copy children + if ( xCopyFrom.is() ) + { + Sequence< ::rtl::OUString> aSeq = xCopyFrom->getElementNames(); + const ::rtl::OUString* elements = aSeq.getConstArray(); + const ::rtl::OUString* elementsEnd = elements + aSeq.getLength(); + Reference<XContent> xObjectToCopy; + + Reference<XMultiServiceFactory> xORB(xContent,UNO_QUERY); + OSL_ENSURE(xORB.is(),"No service factory given"); + if ( xORB.is() ) + { + for(;elements != elementsEnd;++elements) + { + xCopyFrom->getByName(*elements) >>= xObjectToCopy; + Sequence< Any > aArguments(3); + PropertyValue aArgument; + // set as folder + aArgument.Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Name")); + aArgument.Value <<= *elements; + aArguments[0] <<= aArgument; + //parent + aArgument.Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Parent")); + aArgument.Value <<= xContent; + aArguments[1] <<= aArgument; + + aArgument.Name = PROPERTY_EMBEDDEDOBJECT; + aArgument.Value <<= xObjectToCopy; + aArguments[2] <<= aArgument; + + ::rtl::OUString sServiceName; + if ( Reference< XNameAccess >( xObjectToCopy, UNO_QUERY ).is() ) + { + if ( m_bFormsContainer ) + sServiceName = SERVICE_NAME_FORM_COLLECTION; + else + sServiceName = SERVICE_NAME_REPORT_COLLECTION; + } + else + sServiceName = SERVICE_SDB_DOCUMENTDEFINITION; + + Reference<XContent > xNew(xORB->createInstanceWithArguments(sServiceName,aArguments),UNO_QUERY); + Reference<XNameContainer> xNameContainer(xContent,UNO_QUERY); + if ( xNameContainer.is() ) + xNameContainer->insertByName(*elements,makeAny(xNew)); + } + } + } + } + xRet = xContent; + return xRet; +} +// ----------------------------------------------------------------------------- +Sequence< ::rtl::OUString > SAL_CALL ODocumentContainer::getAvailableServiceNames( ) throw (RuntimeException) +{ + Sequence< ::rtl::OUString > aSe(3); + aSe[0] = SERVICE_SDB_DOCUMENTDEFINITION; + aSe[1] = SERVICE_NAME_FORM_COLLECTION; + aSe[2] = SERVICE_NAME_REPORT_COLLECTION; + return aSe; +} +// ----------------------------------------------------------------------------- +Any SAL_CALL ODocumentContainer::execute( const Command& aCommand, sal_Int32 CommandId, const Reference< XCommandEnvironment >& Environment ) throw (Exception, CommandAbortedException, RuntimeException) +{ + Any aRet; + if ( aCommand.Name.compareToAscii( "open" ) == 0 ) + { + ////////////////////////////////////////////////////////////////// + // open command for a folder content + ////////////////////////////////////////////////////////////////// + OpenCommandArgument2 aOpenCommand; + if ( !( aCommand.Argument >>= aOpenCommand ) ) + { + OSL_ENSURE( sal_False, "Wrong argument type!" ); + ucbhelper::cancelCommandExecution( + makeAny( IllegalArgumentException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + sal_Bool bOpenFolder = + ( ( aOpenCommand.Mode == OpenMode::ALL ) || + ( aOpenCommand.Mode == OpenMode::FOLDERS ) || + ( aOpenCommand.Mode == OpenMode::DOCUMENTS ) ); + + if ( bOpenFolder ) + { + // open as folder - return result set + + Reference< XDynamicResultSet > xSet + = new DynamicResultSet( m_aContext.getLegacyServiceFactory(), + this, + aOpenCommand, + Environment ); + aRet <<= xSet; + } + else + { + // Unsupported. + ucbhelper::cancelCommandExecution( + makeAny( UnsupportedOpenModeException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + sal_Int16( aOpenCommand.Mode ) ) ), + Environment ); + // Unreachable + } + } + else if ( aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "insert" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // insert + ////////////////////////////////////////////////////////////////// + + InsertCommandArgument arg; + if ( !( aCommand.Argument >>= arg ) ) + { + OSL_ENSURE( sal_False, "Wrong argument type!" ); + ucbhelper::cancelCommandExecution( + makeAny( IllegalArgumentException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + } + else if ( aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "delete" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // delete + ////////////////////////////////////////////////////////////////// + Sequence< ::rtl::OUString> aSeq = getElementNames(); + const ::rtl::OUString* pIter = aSeq.getConstArray(); + const ::rtl::OUString* pEnd = pIter + aSeq.getLength(); + for(;pIter != pEnd;++pIter) + removeByName(*pIter); + + dispose(); + } + else + aRet = OContentHelper::execute(aCommand,CommandId,Environment); + return aRet; +} +// ----------------------------------------------------------------------------- +namespace +{ + sal_Bool lcl_queryContent(const ::rtl::OUString& _sName,Reference< XNameContainer >& _xNameContainer,Any& _rRet,::rtl::OUString& _sSimpleName) + { + sal_Bool bRet = sal_False; + sal_Int32 nIndex = 0; + ::rtl::OUString sName = _sName.getToken(0,'/',nIndex); + bRet = _xNameContainer->hasByName(sName); + if ( bRet ) + { + _rRet = _xNameContainer->getByName(_sSimpleName = sName); + while ( nIndex != -1 && bRet ) + { + sName = _sName.getToken(0,'/',nIndex); + _xNameContainer.set(_rRet,UNO_QUERY); + bRet = _xNameContainer.is(); + if ( bRet ) + { + bRet = _xNameContainer->hasByName(sName); + _sSimpleName = sName; + if ( bRet ) + _rRet = _xNameContainer->getByName(sName); + } + } + } + if ( nIndex == -1 ) + _sSimpleName = sName; // a content + else + _xNameContainer.clear(); // a sub folder doesn't exist + return bRet; + } +} +// ----------------------------------------------------------------------------- +Reference< XComponent > SAL_CALL ODocumentContainer::loadComponentFromURL( const ::rtl::OUString& _sURL + , const ::rtl::OUString& /*TargetFrameName*/ + , sal_Int32 /*SearchFlags*/ + , const Sequence< PropertyValue >& Arguments ) throw (IOException, IllegalArgumentException, RuntimeException) +{ + vos::OGuard aSolarGuard(Application::GetSolarMutex()); + + MutexGuard aGuard(m_aMutex); + Reference< XComponent > xComp; + try + { + Any aContent; + Reference< XNameContainer > xNameContainer(this); + ::rtl::OUString sName; + if ( !lcl_queryContent(_sURL,xNameContainer,aContent,sName) ) + { + ::rtl::OUString sMessage( DBA_RES( RID_STR_NAME_NOT_FOUND ) ); + ::comphelper::string::searchAndReplaceAsciiI( sMessage, "$name$", _sURL ); + throw IllegalArgumentException( sMessage, *this, 1 ); + } + + Reference< XCommandProcessor > xContent(aContent,UNO_QUERY); + if ( xContent.is() ) + { + Command aCommand; + + ::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 ); + + aCommand.Argument <<= aArgs.getPropertyValues(); + xComp.set(xContent->execute(aCommand,xContent->createCommandIdentifier(),Reference< XCommandEnvironment >()),UNO_QUERY); + } + } + catch(NoSuchElementException) + { + throw IllegalArgumentException(); + } + catch(WrappedTargetException e) + { + // throw IllegalArgumentException(); + throw; + } + return xComp; +} +// ----------------------------------------------------------------------------- +Any SAL_CALL ODocumentContainer::getByHierarchicalName( const ::rtl::OUString& _sName ) throw (NoSuchElementException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + Any aContent; + Reference< XNameContainer > xNameContainer(this); + ::rtl::OUString sName; + if ( lcl_queryContent(_sName,xNameContainer,aContent,sName) ) + return aContent; + throw NoSuchElementException(_sName,*this); +} +// ----------------------------------------------------------------------------- +sal_Bool SAL_CALL ODocumentContainer::hasByHierarchicalName( const ::rtl::OUString& _sName ) throw (RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + Any aContent; + Reference< XNameContainer > xNameContainer(this); + ::rtl::OUString sName; + return lcl_queryContent(_sName,xNameContainer,aContent,sName); +} +// ----------------------------------------------------------------------------- +// XHierarchicalNameContainer +void SAL_CALL ODocumentContainer::insertByHierarchicalName( const ::rtl::OUString& _sName, const Any& _aElement ) throw (IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException) +{ + Reference< XContent > xContent(_aElement,UNO_QUERY); + if ( !xContent.is() ) + throw IllegalArgumentException(); + + ClearableMutexGuard aGuard(m_aMutex); + Any aContent; + Reference< XNameContainer > xNameContainer(this); + ::rtl::OUString sName; + if ( lcl_queryContent(_sName,xNameContainer,aContent,sName) ) + throw ElementExistException(_sName,*this); + + if ( !xNameContainer.is() ) + { + ::rtl::OUString sMessage( DBA_RES( RID_STR_NO_SUB_FOLDER ) ); + sal_Int32 index = sName.getLength(); + ::comphelper::string::searchAndReplaceAsciiI( sMessage, "$folder$", _sName.getToken(0,'/',index) ); + throw IllegalArgumentException( sMessage, *this, 1 ); + } + + xNameContainer->insertByName(sName,_aElement); +} +// ----------------------------------------------------------------------------- +void SAL_CALL ODocumentContainer::removeByHierarchicalName( const ::rtl::OUString& _sName ) throw (NoSuchElementException, WrappedTargetException, RuntimeException) +{ + if ( !_sName.getLength() ) + throw NoSuchElementException(_sName,*this); + + ClearableMutexGuard aGuard(m_aMutex); + Any aContent; + ::rtl::OUString sName; + Reference< XNameContainer > xNameContainer(this); + if ( !lcl_queryContent(_sName,xNameContainer,aContent,sName) ) + throw NoSuchElementException(_sName,*this); + + xNameContainer->removeByName(sName); +} +// ----------------------------------------------------------------------------- +// XHierarchicalNameReplace +void SAL_CALL ODocumentContainer::replaceByHierarchicalName( const ::rtl::OUString& _sName, const Any& _aElement ) throw (IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException) +{ + Reference< XContent > xContent(_aElement,UNO_QUERY); + if ( !xContent.is() ) + throw IllegalArgumentException(); + + ClearableMutexGuard aGuard(m_aMutex); + Any aContent; + ::rtl::OUString sName; + Reference< XNameContainer > xNameContainer(this); + if ( !lcl_queryContent(_sName,xNameContainer,aContent,sName) ) + throw NoSuchElementException(_sName,*this); + + 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 +{ + ::rtl::Reference<OContentHelper> pContent = NULL; + try + { + Reference<XUnoTunnel> xUnoTunnel(const_cast<ODocumentContainer*>(this)->implGetByName( _sName, sal_True ), UNO_QUERY ); + if ( xUnoTunnel.is() ) + pContent = reinterpret_cast<OContentHelper*>(xUnoTunnel->getSomething(OContentHelper::getUnoTunnelImplementationId())); + } + catch(Exception) + { + } + return pContent; +} +// ----------------------------------------------------------------------------- +void ODocumentContainer::getPropertyDefaultByHandle( sal_Int32 /*_nHandle*/, Any& _rDefault ) const +{ + _rDefault.clear(); +} +// ----------------------------------------------------------------------------- +void SAL_CALL ODocumentContainer::commit( ) throw (::com::sun::star::io::IOException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + Documents::iterator aIter = m_aDocumentMap.begin(); + Documents::iterator aEnd = m_aDocumentMap.end(); + for (; aIter != aEnd ; ++aIter) + { + Reference<XTransactedObject> xTrans(aIter->second.get(),UNO_QUERY); + if ( xTrans.is() ) + xTrans->commit(); + } + Reference<XTransactedObject> xTrans(getContainerStorage(),UNO_QUERY); + if ( xTrans.is() ) + xTrans->commit(); +} +// ----------------------------------------------------------------------------- +void SAL_CALL ODocumentContainer::revert( ) throw (::com::sun::star::io::IOException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + Documents::iterator aIter = m_aDocumentMap.begin(); + Documents::iterator aEnd = m_aDocumentMap.end(); + for (; aIter != aEnd ; ++aIter) + { + Reference<XTransactedObject> xTrans(aIter->second.get(),UNO_QUERY); + if ( xTrans.is() ) + xTrans->revert(); + } + Reference<XTransactedObject> xTrans(getContainerStorage(),UNO_QUERY); + if ( xTrans.is() ) + xTrans->revert(); +} +// ----------------------------------------------------------------------------- +Reference< XStorage> ODocumentContainer::getContainerStorage() const +{ + return m_pImpl->m_pDataSource + ? m_pImpl->m_pDataSource->getStorage( m_bFormsContainer ? ODatabaseModelImpl::E_FORM : ODatabaseModelImpl::E_REPORT ) + : Reference< XStorage>(); +} + +// ----------------------------------------------------------------------------- +void SAL_CALL ODocumentContainer::removeByName( const ::rtl::OUString& _rName ) throw(NoSuchElementException, WrappedTargetException, RuntimeException) +{ + ResettableMutexGuard aGuard(m_aMutex); + + // check the arguments + if (!_rName.getLength()) + throw IllegalArgumentException(); + + if (!checkExistence(_rName)) + throw NoSuchElementException(_rName,*this); + + Reference< XCommandProcessor > xContent( implGetByName( _rName, sal_True ), UNO_QUERY ); + if ( xContent.is() ) + { + Command aCommand; + + aCommand.Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("delete")); + xContent->execute(aCommand,xContent->createCommandIdentifier(),Reference< XCommandEnvironment >()); + } + + // do the removal + implRemove(_rName); + + // disposeComponent(xContent); // no dispose here, the object may be inserted again under a different name + + notifyByName( aGuard, _rName, NULL, NULL, E_REMOVED, ContainerListemers ); +} +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +void SAL_CALL ODocumentContainer::rename( const ::rtl::OUString& newName ) throw (SQLException, ElementExistException, RuntimeException) +{ + try + { + osl::ClearableGuard< osl::Mutex > aGuard(m_aMutex); + if ( newName.equals( m_pImpl->m_aProps.aTitle ) ) + return; + + sal_Int32 nHandle = PROPERTY_ID_NAME; + Any aOld = makeAny(m_pImpl->m_aProps.aTitle); + Any aNew = makeAny(newName); + + aGuard.clear(); + fire(&nHandle, &aNew, &aOld, 1, sal_True ); + m_pImpl->m_aProps.aTitle = newName; + fire(&nHandle, &aNew, &aOld, 1, sal_False ); + } + catch(const PropertyVetoException&) + { + throw ElementExistException(newName,*this); + } +} + +//........................................................................ +} // namespace dbaccess +//........................................................................ + diff --git a/dbaccess/source/core/dataaccess/documentcontainer.hxx b/dbaccess/source/core/dataaccess/documentcontainer.hxx new file mode 100644 index 000000000000..c1a9c424d7d3 --- /dev/null +++ b/dbaccess/source/core/dataaccess/documentcontainer.hxx @@ -0,0 +1,168 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 _DBA_COREDATAACCESS_DOCUMENTCONTAINER_HXX_ +#define _DBA_COREDATAACCESS_DOCUMENTCONTAINER_HXX_ + +#ifndef _DBA_CORE_DEFINITIONCONTAINER_HXX_ +#include "definitioncontainer.hxx" +#endif +#ifndef _CPPUHELPER_IMPLBASE5_HXX_ +#include <cppuhelper/implbase5.hxx> +#endif +#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_ +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#endif +#ifndef _COM_SUN_STAR_FRAME_XCOMPONENTLOADER_HPP_ +#include <com/sun/star/frame/XComponentLoader.hpp> +#endif +#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 +#ifndef COMPHELPER_PROPERTYSTATECONTAINER_HXX +#include <comphelper/propertystatecontainer.hxx> +#endif +#ifndef _COMPHELPER_PROPERTY_ARRAY_HELPER_HXX_ +#include <comphelper/proparrhlp.hxx> +#endif +#ifndef _DBASHARED_APITOOLS_HXX_ +#include "apitools.hxx" +#endif + +//........................................................................ +namespace dbaccess +{ +//........................................................................ +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; +//========================================================================== +//= ODocumentContainer - collections of database documents (reports/forms) +//========================================================================== +class ODocumentContainer : public ODefinitionContainer + , public ODocumentContainer_Base + , public ::comphelper::OPropertyStateContainer + , public ::comphelper::OPropertyArrayUsageHelper< ODocumentContainer > +{ + sal_Bool m_bFormsContainer; + +public: + /** constructs the container.<BR> + */ + ODocumentContainer( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _xORB + , const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _xParentContainer + ,const TContentPtr& _pImpl + , sal_Bool _bFormsContainer + ); + + // ::com::sun::star::uno::XInterface + DECLARE_XINTERFACE( ) + // com::sun::star::lang::XTypeProvider + DECLARE_TYPEPROVIDER( ); + // ::com::sun::star::lang::XServiceInfo + DECLARE_SERVICE_INFO(); + + // XComponentLoader + virtual ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > SAL_CALL loadComponentFromURL( const ::rtl::OUString& URL, const ::rtl::OUString& TargetFrameName, sal_Int32 SearchFlags, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& Arguments ) throw (::com::sun::star::io::IOException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::lang::XMultiServiceFactory + virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL createInstance( const ::rtl::OUString& aServiceSpecifier ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL createInstanceWithArguments( const ::rtl::OUString& ServiceSpecifier, const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& Arguments ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getAvailableServiceNames( ) throw (::com::sun::star::uno::RuntimeException); + + // XCommandProcessor + virtual ::com::sun::star::uno::Any SAL_CALL execute( const ::com::sun::star::ucb::Command& aCommand, sal_Int32 CommandId, const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >& Environment ) throw (::com::sun::star::uno::Exception, ::com::sun::star::ucb::CommandAbortedException, ::com::sun::star::uno::RuntimeException) ; + + // XHierarchicalNameAccess + virtual ::com::sun::star::uno::Any SAL_CALL getByHierarchicalName( const ::rtl::OUString& _sName ) throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL hasByHierarchicalName( const ::rtl::OUString& _sName ) throw (::com::sun::star::uno::RuntimeException); + + // XHierarchicalNameContainer + 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); + + // XHierarchicalNameReplace + virtual void SAL_CALL replaceByHierarchicalName( const ::rtl::OUString& aName, const ::com::sun::star::uno::Any& aElement ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + + // ::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); + + // XTransactedObject + virtual void SAL_CALL commit( ) throw (::com::sun::star::io::IOException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL revert( ) throw (::com::sun::star::io::IOException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + + // XRename + virtual void SAL_CALL rename( const ::rtl::OUString& newName ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::container::ElementExistException, ::com::sun::star::uno::RuntimeException); + + // OPropertySetHelper + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(); + + // helper + ::rtl::Reference<OContentHelper> getContent(const ::rtl::OUString& _sName) const; + ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage > getContainerStorage() const; + +protected: + virtual ~ODocumentContainer(); + + /** OContentHelper + */ + virtual ::rtl::OUString determineContentType() const; + + // ODefinitionContainer + virtual ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContent > createObject( + const ::rtl::OUString& _rName + ); + + virtual void getPropertyDefaultByHandle( sal_Int32 _nHandle, ::com::sun::star::uno::Any& _rDefault ) const; + + // OPropertyArrayUsageHelper + virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const; +}; + +//........................................................................ +} // namespace dbaccess +//........................................................................ + +#endif // _DBA_COREDATAACCESS_DOCUMENTCONTAINER_HXX_ + diff --git a/dbaccess/source/core/dataaccess/documentdefinition.cxx b/dbaccess/source/core/dataaccess/documentdefinition.cxx new file mode 100644 index 000000000000..7678cfbba62e --- /dev/null +++ b/dbaccess/source/core/dataaccess/documentdefinition.cxx @@ -0,0 +1,2404 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#ifndef _DBA_COREDATAACCESS_DOCUMENTDEFINITION_HXX_ +#include "documentdefinition.hxx" +#endif +#ifndef DBACCESS_SHARED_DBASTRINGS_HRC +#include "dbastrings.hrc" +#endif +#ifndef DBACORE_SDBCORETOOLS_HXX +#include "sdbcoretools.hxx" +#endif +#ifndef _TOOLS_DEBUG_HXX +#include <tools/debug.hxx> +#endif +#ifndef TOOLS_DIAGNOSE_EX_H +#include <tools/diagnose_ex.h> +#endif +#ifndef _COMPHELPER_PROPERTY_HXX_ +#include <comphelper/property.hxx> +#endif +#ifndef _COMPHELPER_SEQUENCE_HXX_ +#include <comphelper/sequence.hxx> +#endif +#ifndef _COMPHELPER_MEDIADESCRIPTOR_HXX_ +#include <comphelper/mediadescriptor.hxx> +#endif +#ifndef COMPHELPER_NAMEDVALUECOLLECTION_HXX +#include <comphelper/namedvaluecollection.hxx> +#endif +#ifndef _COMPHELPER_CLASSIDS_HXX +#include <comphelper/classids.hxx> +#endif +#include <com/sun/star/frame/XUntitledNumbers.hpp> +#ifndef _COM_SUN_STAR_AWT_XTOPWINDOW_HPP_ +#include <com/sun/star/awt/XTopWindow.hpp> +#endif +#ifndef _COM_SUN_STAR_AWT_SIZE_HPP_ +#include <com/sun/star/awt/Size.hpp> +#endif +#ifndef _COM_SUN_STAR_LANG_DISPOSEDEXCEPTION_HPP_ +#include <com/sun/star/lang/DisposedException.hpp> +#endif +#ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBUTE_HPP_ +#include <com/sun/star/beans/PropertyAttribute.hpp> +#endif +#ifndef _COM_SUN_STAR_FRAME_XMODEL_HPP_ +#include <com/sun/star/frame/XModel.hpp> +#endif +#include <com/sun/star/frame/XTitle.hpp> +#ifndef _COM_SUN_STAR_FRAME_XCONTROLLER_HPP_ +#include <com/sun/star/frame/XController.hpp> +#endif +#ifndef _COM_SUN_STAR_TASK_XJOBEXECUTOR_HPP_ +#include <com/sun/star/task/XJobExecutor.hpp> +#endif +#ifndef _COM_SUN_STAR_FRAME_XDISPATCHPROVIDERINTERCEPTION_HPP_ +#include <com/sun/star/frame/XDispatchProviderInterception.hpp> +#endif +#ifndef _COM_SUN_STAR_FRAME_XFRAMESSUPPLIER_HPP_ +#include <com/sun/star/frame/XFramesSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_UCB_INSERTCOMMANDARGUMENT_HPP_ +#include <com/sun/star/ucb/InsertCommandArgument.hpp> +#endif +#include <com/sun/star/report/XReportDefinition.hpp> +#include <com/sun/star/report/XReportEngine.hpp> +#ifndef _COM_SUN_STAR_UCB_OPENMODE_HPP_ +#include <com/sun/star/ucb/OpenMode.hpp> +#endif +#ifndef _COM_SUN_STAR_XEMBEDOBJECTFACTORY_HPP_ +#include <com/sun/star/embed/XEmbedObjectFactory.hpp> +#endif +#ifndef _COM_SUN_STAR_XEMBEDOBJECTCREATOR_HPP_ +#include <com/sun/star/embed/XEmbedObjectCreator.hpp> +#endif +#ifndef _COM_SUN_STAR_EMBED_ASPECTS_HPP_ +#include <com/sun/star/embed/Aspects.hpp> +#endif +#ifndef _UCBHELPER_CANCELCOMMANDEXECUTION_HXX_ +#include <ucbhelper/cancelcommandexecution.hxx> +#endif +#ifndef _COM_SUN_STAR_UCB_UNSUPPORTEDDATASINKEXCEPTION_HPP_ +#include <com/sun/star/ucb/UnsupportedDataSinkException.hpp> +#endif +#ifndef _COM_SUN_STAR_UCB_UNSUPPORTEDOPENMODEEXCEPTION_HPP_ +#include <com/sun/star/ucb/UnsupportedOpenModeException.hpp> +#endif +#ifndef _COM_SUN_STAR_ELEMENTMODES_HPP_ +#include <com/sun/star/embed/ElementModes.hpp> +#endif +#ifndef _COM_SUN_STAR_XEMBEDPERSIST_HPP_ +#include <com/sun/star/embed/XEmbedPersist.hpp> +#endif +#ifndef _COM_SUN_STAR_EMBEDSTATES_HPP_ +#include <com/sun/star/embed/EmbedStates.hpp> +#endif +#ifndef _COM_SUN_STAR_XCOMPONENTSUPPLIER_HPP_ +#include <com/sun/star/embed/XComponentSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_ENTRYINITMODES_HPP_ +#include <com/sun/star/embed/EntryInitModes.hpp> +#endif +#ifndef _COM_SUN_STAR_UCB_MISSINGPROPERTIESEXCEPTION_HPP_ +#include <com/sun/star/ucb/MissingPropertiesException.hpp> +#endif +#ifndef _COM_SUN_STAR_UCB_MISSINGINPUTSTREAMEXCEPTION_HPP_ +#include <com/sun/star/ucb/MissingInputStreamException.hpp> +#endif +#ifndef _COM_SUN_STAR_UCB_OPENCOMMANDARGUMENT2_HPP_ +#include <com/sun/star/ucb/OpenCommandArgument2.hpp> +#endif +#ifndef _COM_SUN_STAR_UTIL_XCLOSEBROADCASTER_HPP_ +#include <com/sun/star/util/XCloseBroadcaster.hpp> +#endif +#ifndef _COM_SUN_STAR_FRAME_XMODULE_HPP_ +#include <com/sun/star/frame/XModule.hpp> +#endif +#ifndef _COM_SUN_STAR_DATATRANSFER_DATAFLAVOR_HPP_ +#include <com/sun/star/datatransfer/DataFlavor.hpp> +#endif +#ifndef _COM_SUN_STAR_DATATRANSFER_XTRANSFERABLE_HPP_ +#include <com/sun/star/datatransfer/XTransferable.hpp> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XNAMECONTAINER_HPP_ +#include <com/sun/star/container/XNameContainer.hpp> +#endif +#ifndef _COM_SUN_STAR_XTRANSACTEDOBJECT_HPP_ +#include <com/sun/star/embed/XTransactedObject.hpp> +#endif +#ifndef _COM_SUN_STAR_EMBED_XCOMMONEMBEDPERSIST_HPP_ +#include <com/sun/star/embed/XCommonEmbedPersist.hpp> +#endif +#ifndef DBA_INTERCEPT_HXX +#include "intercept.hxx" +#endif +#ifndef _COM_SUN_STAR_SDB_ERRORCONDITION_HPP_ +#include <com/sun/star/sdb/ErrorCondition.hpp> +#endif +#ifndef _COM_SUN_STAR_SDB_XINTERACTIONDOCUMENTSAVE_HPP_ +#include <com/sun/star/sdb/XInteractionDocumentSave.hpp> +#endif +#ifndef _COM_SUN_STAR_TASK_XINTERACTIONHANDLER_HPP_ +#include <com/sun/star/task/XInteractionHandler.hpp> +#endif +#ifndef _COM_SUN_STAR_SDB_DOCUMENTSAVEREQUEST_HPP_ +#include <com/sun/star/sdb/DocumentSaveRequest.hpp> +#endif +#ifndef _COM_SUN_STAR_DOCUMENT_XDOCUMENTPROPERTIESSUPPLIER_HPP_ +#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_DOCUMENT_MACROEXECMODE_HPP_ +#include <com/sun/star/document/MacroExecMode.hpp> +#endif +#ifndef _COM_SUN_STAR_DRAWING_XDRAWPAGESUPPLIER_HPP_ +#include <com/sun/star/drawing/XDrawPageSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XINDEXCONTAINER_HPP_ +#include <com/sun/star/container/XIndexContainer.hpp> +#endif +#ifndef _COM_SUN_STAR_FORM_XFORMSSUPPLIER_HPP_ +#include <com/sun/star/form/XFormsSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_FORM_XFORM_HPP_ +#include <com/sun/star/form/XForm.hpp> +#endif +#ifndef _COMPHELPER_INTERACTION_HXX_ +#include <comphelper/interaction.hxx> +#endif +#ifndef _CONNECTIVITY_DBTOOLS_HXX_ +#include <connectivity/dbtools.hxx> +#endif +#ifndef _SV_SVAPP_HXX +#include <vcl/svapp.hxx> +#endif +#ifndef _VOS_MUTEX_HXX_ +#include <vos/mutex.hxx> +#endif +#ifndef _COM_SUN_STAR_VIEW_XVIEWSETTINGSSUPPLIER_HPP_ +#include <com/sun/star/view/XViewSettingsSupplier.hpp> +#endif +#ifndef _DBA_CORE_RESOURCE_HXX_ +#include "core_resource.hxx" +#endif +#ifndef _DBA_CORE_RESOURCE_HRC_ +#include "core_resource.hrc" +#endif +#ifndef _DBA_COREDATAACCESS_DATASOURCE_HXX_ +#include "datasource.hxx" +#endif +#ifndef _COM_SUN_STAR_EMBED_XSTATECHANGEBROADCASTER_HPP_ +#include <com/sun/star/embed/XStateChangeBroadcaster.hpp> +#endif +#ifndef _COM_SUN_STAR_TASK_XINTERACTIONAPPROVE_HPP_ +#include <com/sun/star/task/XInteractionApprove.hpp> +#endif +#ifndef _COM_SUN_STAR_TASK_XINTERACTIONDISAPPROVE_HPP_ +#include <com/sun/star/task/XInteractionDisapprove.hpp> +#endif +#ifndef _COM_SUN_STAR_FRAME_XLAYOUTMANAGER_HPP_ +#include <com/sun/star/frame/XLayoutManager.hpp> +#endif +#ifndef _CPPUHELPER_COMPBASE1_HXX_ +#include <cppuhelper/compbase1.hxx> +#endif +#include <cppuhelper/exc_hlp.hxx> +#ifndef _COM_SUN_STAR_FRAME_FRAMESEARCHFLAG_HPP_ +#include <com/sun/star/frame/FrameSearchFlag.hpp> +#endif +#ifndef _COMPHELPER_SEQUENCEASHASHMAP_HXX_ +#include <comphelper/sequenceashashmap.hxx> +#endif +#ifndef _COMPHELPER_MIMECONFIGHELPER_HXX_ +#include <comphelper/mimeconfighelper.hxx> +#endif +#ifndef _COMPHELPER_STORAGEHELPER_HXX +#include <comphelper/storagehelper.hxx> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XCONTENTENUMERATIONACCESS_HPP_ +#include <com/sun/star/container/XContentEnumerationAccess.hpp> +#endif +#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; +using namespace uno; +using namespace util; +using namespace ucb; +using namespace beans; +using namespace lang; +using namespace awt; +using namespace embed; +using namespace frame; +using namespace document; +using namespace sdbc; +using namespace sdb; +using namespace io; +using namespace container; +using namespace datatransfer; +using namespace task; +using namespace form; +using namespace drawing; +using namespace ::osl; +using namespace ::comphelper; +using namespace ::cppu; +namespace css = ::com::sun::star; + +using sdb::application::XDatabaseDocumentUI; +namespace DatabaseObject = sdb::application::DatabaseObject; + + +#define DEFAULT_WIDTH 10000 +#define DEFAULT_HEIGHT 7500 +//............................................................................. +namespace dbaccess +{ +//............................................................................. + + typedef ::boost::optional< bool > optional_bool; + + //========================================================================= + //= helper + //========================================================================= + namespace + { + // -------------------------------------------------------------------- + ::rtl::OUString lcl_determineContentType_nothrow( const Reference< XStorage >& _rxContainerStorage, + const ::rtl::OUString& _rEntityName ) + { + ::rtl::OUString sContentType; + try + { + Reference< XStorage > xContainerStorage( _rxContainerStorage, UNO_QUERY_THROW ); + ::utl::SharedUNOComponent< XPropertySet > xStorageProps( + xContainerStorage->openStorageElement( _rEntityName, ElementModes::READ ), UNO_QUERY_THROW ); + OSL_VERIFY( xStorageProps->getPropertyValue( INFO_MEDIATYPE ) >>= sContentType ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + return sContentType; + } + } + + //================================================================== + // OEmbedObjectHolder + //================================================================== + typedef ::cppu::WeakComponentImplHelper1< embed::XStateChangeListener > TEmbedObjectHolder; + class OEmbedObjectHolder : public ::comphelper::OBaseMutex + ,public TEmbedObjectHolder + { + Reference< XEmbeddedObject > m_xBroadCaster; + ODocumentDefinition* m_pDefinition; + bool m_bInStateChange; + bool m_bInChangingState; + protected: + virtual void SAL_CALL disposing(); + public: + OEmbedObjectHolder(const Reference< XEmbeddedObject >& _xBroadCaster,ODocumentDefinition* _pDefinition) + : TEmbedObjectHolder(m_aMutex) + ,m_xBroadCaster(_xBroadCaster) + ,m_pDefinition(_pDefinition) + ,m_bInStateChange(false) + ,m_bInChangingState(false) + { + osl_incrementInterlockedCount( &m_refCount ); + { + if ( m_xBroadCaster.is() ) + m_xBroadCaster->addStateChangeListener(this); + } + osl_decrementInterlockedCount( &m_refCount ); + } + + virtual void SAL_CALL changingState( const lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState ) throw (embed::WrongStateException, uno::RuntimeException); + virtual void SAL_CALL stateChanged( const lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState ) throw (uno::RuntimeException); + virtual void SAL_CALL disposing( const lang::EventObject& Source ) throw (uno::RuntimeException); + }; + //------------------------------------------------------------------ + void SAL_CALL OEmbedObjectHolder::disposing() + { + if ( m_xBroadCaster.is() ) + m_xBroadCaster->removeStateChangeListener(this); + m_xBroadCaster = NULL; + m_pDefinition = NULL; + } + //------------------------------------------------------------------ + void SAL_CALL OEmbedObjectHolder::changingState( const lang::EventObject& /*aEvent*/, ::sal_Int32 nOldState, ::sal_Int32 nNewState ) throw (embed::WrongStateException, uno::RuntimeException) + { + if ( !m_bInChangingState && nNewState == EmbedStates::RUNNING && nOldState == EmbedStates::ACTIVE && m_pDefinition ) + { + m_bInChangingState = true; + //m_pDefinition->save(sal_False); + m_bInChangingState = false; + } + } + //------------------------------------------------------------------ + void SAL_CALL OEmbedObjectHolder::stateChanged( const lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState ) throw (uno::RuntimeException) + { + if ( !m_bInStateChange && nNewState == EmbedStates::RUNNING && nOldState == EmbedStates::ACTIVE && m_pDefinition ) + { + m_bInStateChange = true; + Reference<XInterface> xInt(static_cast< ::cppu::OWeakObject* >(m_pDefinition),UNO_QUERY); + { + Reference<XEmbeddedObject> xEmbeddedObject(aEvent.Source,UNO_QUERY); + if ( xEmbeddedObject.is() ) + xEmbeddedObject->changeState(EmbedStates::LOADED); + } + m_bInStateChange = false; + } + } + //------------------------------------------------------------------ + void SAL_CALL OEmbedObjectHolder::disposing( const lang::EventObject& /*Source*/ ) throw (uno::RuntimeException) + { + m_xBroadCaster = NULL; + } + + //================================================================== + // OEmbeddedClientHelper + //================================================================== + typedef ::cppu::WeakImplHelper1 < XEmbeddedClient + > EmbeddedClientHelper_BASE; + class OEmbeddedClientHelper : public EmbeddedClientHelper_BASE + { + ODocumentDefinition* m_pClient; + public: + OEmbeddedClientHelper(ODocumentDefinition* _pClient) :m_pClient(_pClient) {} + + virtual void SAL_CALL saveObject( ) throw (ObjectSaveVetoException, Exception, RuntimeException) + { + } + virtual void SAL_CALL onShowWindow( sal_Bool /*bVisible*/ ) throw (RuntimeException) + { + } + // XComponentSupplier + virtual Reference< util::XCloseable > SAL_CALL getComponent( ) throw (RuntimeException) + { + return Reference< css::util::XCloseable >(); + } + + // XEmbeddedClient + virtual void SAL_CALL visibilityChanged( ::sal_Bool /*bVisible*/ ) throw (WrongStateException, RuntimeException) + { + } + inline void resetClient(ODocumentDefinition* _pClient) { m_pClient = _pClient; } + }; + + //================================================================== + // 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 + > LifetimeCoupler_Base; + /** helper class which couples the lifetime of a component to the lifetime + of another component + + Instances of this class are constructed with two components. The first is + simply held by reference, and thus kept alive. The second one is observed + for <code>disposing</code> calls - if they occur, i.e. if the component dies, + the reference to the first component is cleared. + + This way, you can ensure that a certain component is kept alive as long + as a second component is not disposed. + */ + class LifetimeCoupler : public LifetimeCoupler_Base + { + private: + Reference< XInterface > m_xClient; + + public: + inline static void couple( const Reference< XInterface >& _rxClient, const Reference< XComponent >& _rxActor ) + { + Reference< css::lang::XEventListener > xEnsureDelete( new LifetimeCoupler( _rxClient, _rxActor ) ); + } + + private: + inline LifetimeCoupler( const Reference< XInterface >& _rxClient, const Reference< XComponent >& _rxActor ) + :m_xClient( _rxClient ) + { + DBG_ASSERT( _rxActor.is(), "LifetimeCoupler::LifetimeCoupler: this will crash!" ); + osl_incrementInterlockedCount( &m_refCount ); + { + _rxActor->addEventListener( this ); + } + osl_decrementInterlockedCount( &m_refCount ); + DBG_ASSERT( m_refCount, "LifetimeCoupler::LifetimeCoupler: the actor is not holding us by hard ref - this won't work!" ); + } + + virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) throw (RuntimeException); + protected: + }; + + //------------------------------------------------------------------ + void SAL_CALL LifetimeCoupler::disposing( const css::lang::EventObject& /*Source*/ ) throw (RuntimeException) + { + m_xClient.clear(); + } + + //================================================================== + // ODocumentSaveContinuation + //================================================================== + class ODocumentSaveContinuation : public OInteraction< XInteractionDocumentSave > + { + ::rtl::OUString m_sName; + Reference<XContent> m_xParentContainer; + + public: + ODocumentSaveContinuation() { } + + inline Reference<XContent> getContent() const { return m_xParentContainer; } + inline ::rtl::OUString getName() const { return m_sName; } + + // XInteractionDocumentSave + virtual void SAL_CALL setName( const ::rtl::OUString& _sName,const Reference<XContent>& _xParent) throw(RuntimeException); + }; + + //------------------------------------------------------------------ + void SAL_CALL ODocumentSaveContinuation::setName( const ::rtl::OUString& _sName,const Reference<XContent>& _xParent) throw(RuntimeException) + { + m_sName = _sName; + m_xParentContainer = _xParent; + } + +// ----------------------------------------------------------------------------- +::rtl::OUString ODocumentDefinition::GetDocumentServiceFromMediaType( const Reference< XStorage >& _rxContainerStorage, + const ::rtl::OUString& _rEntityName, const ::comphelper::ComponentContext& _rContext, + Sequence< sal_Int8 >& _rClassId ) +{ + return GetDocumentServiceFromMediaType( + lcl_determineContentType_nothrow( _rxContainerStorage, _rEntityName ), + _rContext, _rClassId ); +} + +// ----------------------------------------------------------------------------- +::rtl::OUString ODocumentDefinition::GetDocumentServiceFromMediaType( const ::rtl::OUString& _rMediaType, + const ::comphelper::ComponentContext& _rContext, Sequence< sal_Int8 >& _rClassId ) +{ + ::rtl::OUString sResult; + try + { + ::comphelper::MimeConfigurationHelper aConfigHelper( _rContext.getLegacyServiceFactory() ); + sResult = aConfigHelper.GetDocServiceNameFromMediaType( _rMediaType ); + _rClassId = aConfigHelper.GetSequenceClassIDRepresentation(aConfigHelper.GetExplicitlyRegisteredObjClassID( _rMediaType )); + if ( !_rClassId.getLength() && sResult.getLength() ) + { + Reference< XNameAccess > xObjConfig = aConfigHelper.GetObjConfiguration(); + if ( xObjConfig.is() ) + { + Sequence< ::rtl::OUString > aClassIDs = xObjConfig->getElementNames(); + for ( sal_Int32 nInd = 0; nInd < aClassIDs.getLength(); nInd++ ) + { + Reference< XNameAccess > xObjectProps; + ::rtl::OUString aEntryDocName; + + if ( ( xObjConfig->getByName( aClassIDs[nInd] ) >>= xObjectProps ) && xObjectProps.is() + && ( xObjectProps->getByName(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ObjectDocumentServiceName")) + ) >>= aEntryDocName ) + && aEntryDocName.equals( sResult ) ) + { + _rClassId = aConfigHelper.GetSequenceClassIDRepresentation(aClassIDs[nInd]); + break; + } + } + } + } +#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& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + return sResult; +} +// ----------------------------------------------------------------------------- +//========================================================================== +//= ODocumentDefinition +//========================================================================== +DBG_NAME(ODocumentDefinition) + +//-------------------------------------------------------------------------- +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) + ,m_bOpenInDesign(sal_False) + ,m_bInExecute(sal_False) + ,m_bRemoveListener(sal_False) + ,m_pClientHelper(NULL) +{ + DBG_CTOR(ODocumentDefinition, NULL); + registerProperties(); +} + +//-------------------------------------------------------------------------- +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() +{ + DBG_DTOR(ODocumentDefinition, NULL); + if ( !OContentHelper::rBHelper.bInDispose && !OContentHelper::rBHelper.bDisposed ) + { + acquire(); + dispose(); + } + + if ( m_pInterceptor ) + { + m_pInterceptor->dispose(); + m_pInterceptor->release(); + m_pInterceptor = NULL; + } +} +// ----------------------------------------------------------------------------- +void ODocumentDefinition::closeObject() +{ + ::osl::MutexGuard aGuard(m_aMutex); + if ( m_xEmbeddedObject.is() ) + { + try + { + Reference< com::sun::star::util::XCloseable> xCloseable(m_xEmbeddedObject,UNO_QUERY); + if ( xCloseable.is() ) + xCloseable->close(sal_True); + } + catch(Exception) + { + } + m_xEmbeddedObject = NULL; + if ( m_pClientHelper ) + { + m_pClientHelper->resetClient(NULL); + m_pClientHelper->release(); + m_pClientHelper = NULL; + } + } +} +// ----------------------------------------------------------------------------- +void SAL_CALL ODocumentDefinition::disposing() +{ + OContentHelper::disposing(); + ::osl::MutexGuard aGuard(m_aMutex); + closeObject(); + ::comphelper::disposeComponent(m_xListener); + if ( m_bRemoveListener ) + { + Reference<util::XCloseable> xCloseable(m_pImpl->m_pDataSource->getModel_noCreate(),UNO_QUERY); + if ( xCloseable.is() ) + xCloseable->removeCloseListener(this); + } +} +// ----------------------------------------------------------------------------- +IMPLEMENT_TYPEPROVIDER3(ODocumentDefinition,OContentHelper,OPropertyStateContainer,ODocumentDefinition_Base); +IMPLEMENT_FORWARD_XINTERFACE3( ODocumentDefinition,OContentHelper,OPropertyStateContainer,ODocumentDefinition_Base) +IMPLEMENT_SERVICE_INFO1(ODocumentDefinition,"com.sun.star.comp.dba.ODocumentDefinition",SERVICE_SDB_DOCUMENTDEFINITION) +//-------------------------------------------------------------------------- +void ODocumentDefinition::registerProperties() +{ +#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) +{ + Reference<XPropertySetInfo> xInfo( createPropertySetInfo( getInfoHelper() ) ); + return xInfo; +} + +//-------------------------------------------------------------------------- +IPropertyArrayHelper& ODocumentDefinition::getInfoHelper() +{ + return *getArrayHelper(); +} + + +//-------------------------------------------------------------------------- +IPropertyArrayHelper* ODocumentDefinition::createArrayHelper( ) const +{ + // properties maintained by our base class (see registerProperties) + Sequence< Property > 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; +public: + OExecuteImpl(sal_Bool& _rbSet) : m_rbSet(_rbSet){ m_rbSet=sal_True; } + ~OExecuteImpl(){ m_rbSet = sal_False; } +}; + +// ----------------------------------------------------------------------------- +namespace +{ + bool lcl_extractOpenMode( const Any& _rValue, sal_Int32& _out_rMode ) + { + OpenCommandArgument aOpenCommand; + if ( _rValue >>= aOpenCommand ) + _out_rMode = aOpenCommand.Mode; + else + { + OpenCommandArgument2 aOpenCommand2; + if ( _rValue >>= aOpenCommand2 ) + _out_rMode = aOpenCommand2.Mode; + else + return false; + } + return true; + } +} + +// ----------------------------------------------------------------------------- +void ODocumentDefinition::impl_removeFrameFromDesktop_throw( const ::comphelper::ComponentContext& _rContxt, const Reference< XFrame >& _rxFrame ) +{ + Reference< XFramesSupplier > xDesktop( _rContxt.createComponent( (::rtl::OUString)SERVICE_FRAME_DESKTOP ), UNO_QUERY_THROW ); + Reference< XFrames > xFrames( xDesktop->getFrames(), UNO_QUERY_THROW ); + xFrames->remove( _rxFrame ); +} + +// ----------------------------------------------------------------------------- +void ODocumentDefinition::impl_onActivateEmbeddedObject_nothrow( const bool i_bReactivated ) +{ + try + { + Reference< XModel > xModel( getComponent(), UNO_QUERY ); + Reference< XController > xController( xModel.is() ? xModel->getCurrentController() : Reference< XController >() ); + if ( !xController.is() ) + return; + + if ( !m_xListener.is() ) + // it's the first time the embedded object has been activated + // create an OEmbedObjectHolder + m_xListener = new OEmbedObjectHolder( m_xEmbeddedObject, this ); + + // raise the window to top (especially necessary if this is not the first activation) + Reference< XFrame > xFrame( xController->getFrame(), UNO_SET_THROW ); + Reference< XTopWindow > xTopWindow( xFrame->getContainerWindow(), UNO_QUERY_THROW ); + xTopWindow->toFront(); + + // remove the frame from the desktop's frame collection because we need full control of it. + impl_removeFrameFromDesktop_throw( m_aContext, xFrame ); + + // ensure that we ourself are kept alive as long as the embedded object's frame is + // opened + LifetimeCoupler::couple( *this, xFrame.get() ); + + // init the edit view + if ( m_bForm && m_bOpenInDesign && !i_bReactivated ) + impl_initFormEditView( xController ); + } + catch( const RuntimeException& ) + { + DBG_UNHANDLED_EXCEPTION(); + } +} + +// ----------------------------------------------------------------------------- +namespace +{ + // ========================================================================= + // = PreserveVisualAreaSize + // ========================================================================= + /** stack-guard for preserving the size of the VisArea of an XModel + */ + class PreserveVisualAreaSize + { + private: + Reference< XVisualObject > m_xVisObject; + awt::Size m_aOriginalSize; + + public: + inline PreserveVisualAreaSize( const Reference< XModel >& _rxModel ) + :m_xVisObject( _rxModel, UNO_QUERY ) + { + if ( m_xVisObject.is() ) + { + try + { + m_aOriginalSize = m_xVisObject->getVisualAreaSize( Aspects::MSOLE_CONTENT ); + } + catch ( Exception& ) + { + DBG_ERROR( "PreserveVisualAreaSize::PreserveVisualAreaSize: caught an exception!" ); + } + } + } + + inline ~PreserveVisualAreaSize() + { + if ( m_xVisObject.is() && m_aOriginalSize.Width && m_aOriginalSize.Height ) + { + try + { + m_xVisObject->setVisualAreaSize( Aspects::MSOLE_CONTENT, m_aOriginalSize ); + } + catch ( Exception& ) + { + DBG_ERROR( "PreserveVisualAreaSize::~PreserveVisualAreaSize: caught an exception!" ); + } + } + } + }; + + // ========================================================================= + // = LayoutManagerLock + // ========================================================================= + /** helper class for stack-usage which during its lifetime locks a layout manager + */ + class LayoutManagerLock + { + private: + Reference< XLayoutManager > m_xLayoutManager; + + public: + inline LayoutManagerLock( const Reference< XController >& _rxController ) + { + DBG_ASSERT( _rxController.is(), "LayoutManagerLock::LayoutManagerLock: this will crash!" ); + Reference< XFrame > xFrame( _rxController->getFrame() ); + try + { + Reference< XPropertySet > xPropSet( xFrame, UNO_QUERY_THROW ); + m_xLayoutManager.set( + xPropSet->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LayoutManager" ) ) ), + UNO_QUERY_THROW ); + m_xLayoutManager->lock(); + + } + catch( Exception& ) + { + DBG_ERROR( "LayoutManagerLock::LayoutManagerLock: caught an exception!" ); + } + } + + inline ~LayoutManagerLock() + { + try + { + // unlock the layout manager + if ( m_xLayoutManager.is() ) + m_xLayoutManager->unlock(); + } + catch( Exception& ) + { + DBG_ERROR( "LayoutManagerLock::~LayoutManagerLock: caught an exception!" ); + } + } + }; +} + +// ----------------------------------------------------------------------------- +void ODocumentDefinition::impl_initFormEditView( const Reference< XController >& _rxController ) +{ + try + { + 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() ); + + // Layout manager should not layout while the size is still not restored + // so it will stay locked for this time + LayoutManagerLock aLockLayout( _rxController ); + + // setting of the visual properties + xViewSettings->setPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ShowRulers")),makeAny(sal_True)); + xViewSettings->setPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ShowVertRuler")),makeAny(sal_True)); + xViewSettings->setPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ShowHoriRuler")),makeAny(sal_True)); + xViewSettings->setPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("IsRasterVisible")),makeAny(sal_True)); + xViewSettings->setPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("IsSnapToRaster")),makeAny(sal_True)); + 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))); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } +} + +// ----------------------------------------------------------------------------- +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 ) +{ + OExecuteImpl aExecuteGuard( m_bInExecute ); + + Reference< XConnection > xConnection; + sal_Int32 nOpenMode = OpenMode::DOCUMENT; + + ::comphelper::NamedValueCollection aDocumentArgs; + + // for the document, default to the interaction handler as used for loading the DB doc + // This might be overwritten below, when examining _rOpenArgument. + const ::comphelper::NamedValueCollection& aDBDocArgs( m_pImpl->m_pDataSource->getMediaDescriptor() ); + Reference< XInteractionHandler > xHandler( aDBDocArgs.getOrDefault( "InteractionHandler", Reference< XInteractionHandler >() ) ); + if ( xHandler.is() ) + aDocumentArgs.put( "InteractionHandler", xHandler ); + + ::boost::optional< sal_Int16 > aDocumentMacroMode; + + if ( !lcl_extractOpenMode( _rOpenArgument, nOpenMode ) ) + { + Sequence< PropertyValue > aArguments; + if ( _rOpenArgument >>= aArguments ) + { + const PropertyValue* pIter = aArguments.getConstArray(); + const PropertyValue* pEnd = pIter + aArguments.getLength(); + for ( ;pIter != pEnd; ++pIter ) + { + if ( pIter->Name == PROPERTY_ACTIVE_CONNECTION ) + { + xConnection.set( pIter->Value, UNO_QUERY ); + continue; + } + + if ( lcl_extractOpenMode( pIter->Value, nOpenMode ) ) + continue; + + if ( pIter->Name.equalsAscii( "MacroExecutionMode" ) ) + { + sal_Int16 nMacroExecMode( !aDocumentMacroMode ? MacroExecMode::USE_CONFIG : *aDocumentMacroMode ); + OSL_VERIFY( pIter->Value >>= nMacroExecMode ); + aDocumentMacroMode.reset( nMacroExecMode ); + continue; + } + + // unknown argument -> pass to the loaded document + aDocumentArgs.put( pIter->Name, pIter->Value ); + } + } + } + + bool bExecuteDBDocMacros = m_pImpl->m_pDataSource->checkMacrosOnLoading(); + // Note that this call implies the user might be asked for the macro execution mode. + // Normally, this would happen when the database document is loaded, and subsequent calls + // will simply use the user's decision from this point in time. + // However, it is possible to programmatically load forms/reports, without actually + // loading the database document into a frame. In this case, the user will be asked + // here and now. + // #i87741# / 2008-05-05 / frank.schoenheit@sun.com + + // allow the command arguments to downgrade the macro execution mode, but not to upgrade + // it + if ( ( m_pImpl->m_pDataSource->getImposedMacroExecMode() == MacroExecMode::USE_CONFIG ) + && bExecuteDBDocMacros + ) + { + // while loading the whole database document, USE_CONFIG, was passed. + // Additionally, *by now* executing macros from the DB doc is allowed (this is what bExecuteDBDocMacros + // indicates). This means either one of: + // 1. The DB doc or one of the sub docs contained macros and + // 1a. the user explicitly allowed executing them + // 1b. the configuration allows executing them without asking the user + // 2. Neither the DB doc nor the sub docs contained macros, thus macro + // execution was silently enabled, assuming that any macro will be a + // user-created macro + // + // The problem with this: If the to-be-opened sub document has macros embedded in + // the content.xml (which is valid ODF, but normally not produced by OOo itself), + // then this has not been detected while loading the database document - it would + // be too expensive, as it effectively would require loading all forms/reports. + // + // So, in such a case, and with 2. above, we would silently execute those macros, + // regardless of the global security settings - which would be a security issue, of + // course. + if ( m_pImpl->m_pDataSource->determineEmbeddedMacros() == ODatabaseModelImpl::eNoMacros ) + { + // this is case 2. from above + // So, pass a USE_CONFIG to the to-be-loaded document. This means that + // the user will be prompted with a security message upon opening this + // sub document, in case the settings require this, *and* the document + // contains scripts in the content.xml. But this is better than the security + // issue we had before ... + aDocumentMacroMode.reset( MacroExecMode::USE_CONFIG ); + } + } + + if ( !aDocumentMacroMode ) + { + // nobody so far felt responsible for setting it + // => use the DBDoc-wide macro exec mode for the document, too + aDocumentMacroMode.reset( bExecuteDBDocMacros ? MacroExecMode::ALWAYS_EXECUTE_NO_WARN : MacroExecMode::NEVER_EXECUTE ); + } + aDocumentArgs.put( "MacroExecutionMode", *aDocumentMacroMode ); + + if ( ( nOpenMode == OpenMode::ALL ) + || ( nOpenMode == OpenMode::FOLDERS ) + || ( nOpenMode == OpenMode::DOCUMENTS ) + || ( nOpenMode == OpenMode::DOCUMENT_SHARE_DENY_NONE ) + || ( nOpenMode == OpenMode::DOCUMENT_SHARE_DENY_WRITE ) + ) + { + // not supported + ucbhelper::cancelCommandExecution( + makeAny( UnsupportedOpenModeException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + sal_Int16( nOpenMode ) ) ), + _rxEnvironment ); + // Unreachable + DBG_ERROR( "unreachable" ); + } + + OSL_ENSURE( m_pImpl->m_aProps.sPersistentName.getLength(), + "ODocumentDefinition::onCommandOpenSomething: no persistent name - cannot load!" ); + if ( !m_pImpl->m_aProps.sPersistentName.getLength() ) + return Any(); + + // embedded objects themself do not support the hidden flag. We implement support for + // it by changing the STATE to RUNNING only, instead of ACTIVE. + bool bOpenHidden = aDocumentArgs.getOrDefault( "Hidden", false ); + aDocumentArgs.remove( "Hidden" ); + + loadEmbeddedObject( xConnection, Sequence< sal_Int8 >(), aDocumentArgs.getPropertyValues(), false, !m_bOpenInDesign ); + OSL_ENSURE( m_xEmbeddedObject.is(), "ODocumentDefinition::onCommandOpenSomething: what's this?" ); + if ( !m_xEmbeddedObject.is() ) + return Any(); + + Reference< XModel > xModel( getComponent(), UNO_QUERY ); + Reference< report::XReportDefinition > xReportDefinition(xModel,UNO_QUERY); + + Reference< XModule > xModule( xModel, UNO_QUERY ); + if ( xModule.is() ) + { + if ( m_bForm ) + xModule->setIdentifier( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sdb.FormDesign" ) ) ); + else if ( !xReportDefinition.is() ) + xModule->setIdentifier( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sdb.TextReportDesign" ) ) ); + + updateDocumentTitle(); + } + + bool bIsAliveNewStyleReport = ( !m_bOpenInDesign && xReportDefinition.is() ); + if ( bIsAliveNewStyleReport ) + { + // we are in ReadOnly mode + // we would like to open the Writer or Calc with the report direct, without design it. + Reference< report::XReportEngine > xReportEngine( m_aContext.createComponent( "com.sun.star.comp.report.OReportEngineJFree" ), UNO_QUERY_THROW ); + + xReportEngine->setReportDefinition(xReportDefinition); + xReportEngine->setActiveConnection(m_xLastKnownConnection); + if ( bOpenHidden ) + return makeAny( xReportEngine->createDocumentModel() ); + return makeAny( xReportEngine->createDocumentAlive( NULL ) ); + } + + if ( _bActivate && !bOpenHidden ) + { + LockModifiable aLockModify( impl_getComponent_throw() ); + m_xEmbeddedObject->changeState( EmbedStates::ACTIVE ); + 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 ) + ODocumentDefinition::fillReportData( m_aContext, getComponent(), xConnection ); + + return makeAny( xModel ); +} + +// ----------------------------------------------------------------------------- +Any SAL_CALL ODocumentDefinition::execute( const Command& aCommand, sal_Int32 CommandId, const Reference< XCommandEnvironment >& Environment ) throw (Exception, CommandAbortedException, RuntimeException) +{ + Any aRet; + + sal_Bool bOpen = aCommand.Name.equalsAscii( "open" ); + sal_Bool bOpenInDesign = aCommand.Name.equalsAscii( "openDesign" ); + sal_Bool bOpenForMail = aCommand.Name.equalsAscii( "openForMail" ); + if ( bOpen || bOpenInDesign || bOpenForMail ) + { + // opening the document involves a lot of VCL code, which is not thread-safe, but needs the SolarMutex locked. + // Unfortunately, the DocumentDefinition, as well as the EmbeddedObject implementation, calls into VCL-dependent + // components *without* releasing the own mutex, which is a guaranteed recipe for deadlocks. + // We have control over this implementation here, and in modifying it to release the own mutex before calling into + // the VCL-dependent components is not too difficult (was there, seen it). + // However, we do /not/ have control over the EmbeddedObject implementation, and from a first look, it seems as + // making it release the own mutex before calling SolarMutex-code is ... difficult, at least. + // So, to be on the same side, we lock the SolarMutex here. Yes, it sucks. + ::vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + ::osl::ClearableMutexGuard aGuard(m_aMutex); + if ( m_bInExecute ) + return aRet; + + bool bActivateObject = true; + if ( bOpenForMail ) + { + OSL_ENSURE( false, "ODocumentDefinition::execute: 'openForMail' should not be used anymore - use the 'Hidden' parameter instead!" ); + bActivateObject = false; + } + + // if the object is already opened, do nothing + // #i89509# / 2008-05-22 / frank.schoenheit@sun.com + if ( m_xEmbeddedObject.is() ) + { + sal_Int32 nCurrentState = m_xEmbeddedObject->getCurrentState(); + bool bIsActive = ( nCurrentState == EmbedStates::ACTIVE ); + + if ( bIsActive ) + { + // 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() ); + } + } + } + + m_bOpenInDesign = bOpenInDesign || bOpenForMail; + return onCommandOpenSomething( aCommand.Argument, bActivateObject, Environment ); + } + + ::osl::ClearableMutexGuard aGuard(m_aMutex); + if ( m_bInExecute ) + return aRet; + + if ( aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "copyTo" ) ) ) + { + Sequence<Any> aIni; + aCommand.Argument >>= aIni; + if ( aIni.getLength() != 2 ) + { + OSL_ENSURE( sal_False, "Wrong argument type!" ); + ucbhelper::cancelCommandExecution( + makeAny( IllegalArgumentException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + Reference< XStorage> xDest(aIni[0],UNO_QUERY); + ::rtl::OUString sPersistentName; + aIni[1] >>= sPersistentName; + Reference< XStorage> xStorage = getContainerStorage(); + // ----------------------------------------------------------------------------- + xStorage->copyElementTo(m_pImpl->m_aProps.sPersistentName,xDest,sPersistentName); + } + else if ( aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "preview" ) ) ) + { + onCommandPreview(aRet); + } + else if ( aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "insert" ) ) ) + { + Sequence<Any> aIni; + aCommand.Argument >>= aIni; + if ( !aIni.getLength() ) + { + OSL_ENSURE( sal_False, "Wrong argument count!" ); + ucbhelper::cancelCommandExecution( + makeAny( IllegalArgumentException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + ::rtl::OUString sURL; + aIni[0] >>= sURL; + onCommandInsert( sURL, Environment ); + } + else if ( aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "getdocumentinfo" ) ) // compatibility + || aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "getDocumentInfo" ) ) + ) + { + onCommandGetDocumentProperties( aRet ); + } + else if ( aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "delete" ) ) ) + { + ////////////////////////////////////////////////////////////////// + // delete + ////////////////////////////////////////////////////////////////// + closeObject(); + Reference< XStorage> xStorage = getContainerStorage(); + if ( xStorage.is() ) + xStorage->removeElement(m_pImpl->m_aProps.sPersistentName); + + dispose(); + + } + else if ( ( aCommand.Name.compareToAscii( "storeOwn" ) == 0 ) // compatibility + || ( aCommand.Name.compareToAscii( "store" ) == 0 ) + ) + { + impl_store_throw(); + } + else if ( ( aCommand.Name.compareToAscii( "shutdown" ) == 0 ) // compatibility + || ( aCommand.Name.compareToAscii( "close" ) == 0 ) + ) + { + 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); + } + + return aRet; +} +// ----------------------------------------------------------------------------- +namespace +{ + void lcl_resetChildFormsToEmptyDataSource( const Reference< XIndexAccess>& _rxFormsContainer ) + { + OSL_PRECOND( _rxFormsContainer.is(), "lcl_resetChildFormsToEmptyDataSource: illegal call!" ); + sal_Int32 count = _rxFormsContainer->getCount(); + for ( sal_Int32 i = 0; i < count; ++i ) + { + Reference< XForm > xForm( _rxFormsContainer->getByIndex( i ), UNO_QUERY ); + if ( !xForm.is() ) + continue; + + // if the element is a form, reset its DataSourceName property to an empty string + try + { + Reference< XPropertySet > xFormProps( xForm, UNO_QUERY_THROW ); + xFormProps->setPropertyValue( PROPERTY_DATASOURCENAME, makeAny( ::rtl::OUString() ) ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + // if the element is a container itself, step down the component hierarchy + Reference< XIndexAccess > xContainer( xForm, UNO_QUERY ); + if ( xContainer.is() ) + lcl_resetChildFormsToEmptyDataSource( xContainer ); + } + } + + void lcl_resetFormsToEmptyDataSource( const Reference< XEmbeddedObject>& _rxEmbeddedObject ) + { + try + { + Reference< XComponentSupplier > xCompProv( _rxEmbeddedObject, UNO_QUERY_THROW ); + Reference< XDrawPageSupplier > xSuppPage( xCompProv->getComponent(), UNO_QUERY_THROW ); + // if this interface does not exist, then either getComponent returned NULL, + // or the document is a multi-page document. The latter is allowed, but currently + // simply not handled by this code, as it would not normally happen. + + Reference< XFormsSupplier > xSuppForms( xSuppPage->getDrawPage(), UNO_QUERY_THROW ); + Reference< XIndexAccess > xForms( xSuppForms->getForms(), UNO_QUERY_THROW ); + lcl_resetChildFormsToEmptyDataSource( xForms ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + } +} +// ----------------------------------------------------------------------------- +void ODocumentDefinition::onCommandInsert( const ::rtl::OUString& _sURL, const Reference< XCommandEnvironment >& Environment ) + throw( Exception ) +{ + osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); + + // Check, if all required properties were set. + if ( !_sURL.getLength() || m_xEmbeddedObject.is() ) + { + OSL_ENSURE( sal_False, "Content::onCommandInsert - property value missing!" ); + + Sequence< rtl::OUString > aProps( 1 ); + aProps[ 0 ] = PROPERTY_URL; + ucbhelper::cancelCommandExecution( + makeAny( MissingPropertiesException( + rtl::OUString(), + static_cast< cppu::OWeakObject * >( this ), + aProps ) ), + Environment ); + // Unreachable + } + + + if ( !m_xEmbeddedObject.is() ) + { + Reference< XStorage> xStorage = getContainerStorage(); + if ( xStorage.is() ) + { + Reference< XEmbedObjectCreator> xEmbedFactory( m_aContext.createComponent( "com.sun.star.embed.EmbeddedObjectCreator" ), UNO_QUERY ); + if ( xEmbedFactory.is() ) + { + Sequence<PropertyValue> aEmpty,aMediaDesc(1); + aMediaDesc[0].Name = PROPERTY_URL; + aMediaDesc[0].Value <<= _sURL; + m_xEmbeddedObject.set(xEmbedFactory->createInstanceInitFromMediaDescriptor( xStorage + ,m_pImpl->m_aProps.sPersistentName + ,aMediaDesc + ,aEmpty),UNO_QUERY); + + lcl_resetFormsToEmptyDataSource( m_xEmbeddedObject ); + // #i57669# / 2005-12-01 / frank.schoenheit@sun.com + + Reference<XEmbedPersist> xPersist(m_xEmbeddedObject,UNO_QUERY); + if ( xPersist.is() ) + { + xPersist->storeOwn(); + } + try + { + Reference< com::sun::star::util::XCloseable> xCloseable(m_xEmbeddedObject,UNO_QUERY); + if ( xCloseable.is() ) + xCloseable->close(sal_True); + } + catch(Exception) + { + } + m_xEmbeddedObject = NULL; + } + } + } + +// @@@ +// storeData(); + + aGuard.clear(); +// inserted(); +} +// ----------------------------------------------------------------------------- +sal_Bool ODocumentDefinition::save(sal_Bool _bApprove) +{ + // default handling: instantiate an interaction handler and let it handle the parameter request + if ( !m_bOpenInDesign ) + return sal_False; + try + { + + { + ::vos::OGuard aSolarGuard(Application::GetSolarMutex()); + + // the request + Reference<XNameAccess> xName(m_xParentContainer,UNO_QUERY); + DocumentSaveRequest aRequest; + aRequest.Name = m_pImpl->m_aProps.aTitle; + if ( !aRequest.Name.getLength() ) + { + if ( m_bForm ) + aRequest.Name = DBACORE_RESSTRING( RID_STR_FORM ); + else + aRequest.Name = DBACORE_RESSTRING( RID_STR_REPORT ); + aRequest.Name = ::dbtools::createUniqueName(xName,aRequest.Name); + } + + aRequest.Content.set(m_xParentContainer,UNO_QUERY); + OInteractionRequest* pRequest = new OInteractionRequest(makeAny(aRequest)); + Reference< XInteractionRequest > xRequest(pRequest); + // some knittings + // two continuations allowed: OK and Cancel + ODocumentSaveContinuation* pDocuSave = NULL; + + if ( !m_pImpl->m_aProps.aTitle.getLength() ) + { + pDocuSave = new ODocumentSaveContinuation; + pRequest->addContinuation(pDocuSave); + } + OInteraction< XInteractionApprove >* pApprove = NULL; + if ( _bApprove ) + { + pApprove = new OInteraction< XInteractionApprove >; + pRequest->addContinuation(pApprove); + } + + OInteraction< XInteractionDisapprove >* pDisApprove = new OInteraction< XInteractionDisapprove >; + pRequest->addContinuation(pDisApprove); + + OInteractionAbort* pAbort = new OInteractionAbort; + pRequest->addContinuation(pAbort); + + // create the handler, let it handle the request + Reference< XInteractionHandler > xHandler( m_aContext.createComponent( (::rtl::OUString)SERVICE_TASK_INTERACTION_HANDLER ), UNO_QUERY ); + if ( xHandler.is() ) + xHandler->handle(xRequest); + + if ( pAbort->wasSelected() ) + return sal_False; + if ( pDisApprove->wasSelected() ) + return sal_True; + if ( pDocuSave && pDocuSave->wasSelected() ) + { + Reference<XNameContainer> xNC( pDocuSave->getContent(), UNO_QUERY_THROW ); + + ::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(); + } + } + + ::osl::MutexGuard aGuard(m_aMutex); + Reference<XEmbedPersist> xPersist(m_xEmbeddedObject,UNO_QUERY); + if ( xPersist.is() ) + { + xPersist->storeOwn(); + notifyDataSourceModified(); + } + } + catch(Exception&) + { + OSL_ENSURE(0,"ODocumentDefinition::save: caught an Exception (tried to let the InteractionHandler handle it)!"); + } + return sal_True; +} +// ----------------------------------------------------------------------------- +sal_Bool ODocumentDefinition::saveAs() +{ + // default handling: instantiate an interaction handler and let it handle the parameter request + if ( !m_bOpenInDesign ) + return sal_False; + + { + osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); + if ( !m_pImpl->m_aProps.aTitle.getLength() ) + { + aGuard.clear(); + return save(sal_False); // (sal_False) : we don't want an approve dialog + } + } + try + { + { + ::vos::OGuard aSolarGuard(Application::GetSolarMutex()); + + // the request + Reference<XNameAccess> xName(m_xParentContainer,UNO_QUERY); + DocumentSaveRequest aRequest; + aRequest.Name = m_pImpl->m_aProps.aTitle; + + aRequest.Content.set(m_xParentContainer,UNO_QUERY); + OInteractionRequest* pRequest = new OInteractionRequest(makeAny(aRequest)); + Reference< XInteractionRequest > xRequest(pRequest); + // some knittings + // two continuations allowed: OK and Cancel + ODocumentSaveContinuation* pDocuSave = new ODocumentSaveContinuation; + pRequest->addContinuation(pDocuSave); + OInteraction< XInteractionDisapprove >* pDisApprove = new OInteraction< XInteractionDisapprove >; + pRequest->addContinuation(pDisApprove); + OInteractionAbort* pAbort = new OInteractionAbort; + pRequest->addContinuation(pAbort); + + // create the handler, let it handle the request + Reference< XInteractionHandler > xHandler(m_aContext.createComponent(::rtl::OUString(SERVICE_TASK_INTERACTION_HANDLER)), UNO_QUERY); + if ( xHandler.is() ) + xHandler->handle(xRequest); + + if ( pAbort->wasSelected() ) + return sal_False; + if ( pDisApprove->wasSelected() ) + return sal_True; + if ( pDocuSave->wasSelected() ) + { + ::osl::MutexGuard aGuard(m_aMutex); + Reference<XNameContainer> xNC(pDocuSave->getContent(),UNO_QUERY); + if ( xNC.is() ) + { + if ( m_pImpl->m_aProps.aTitle != pDocuSave->getName() ) + { + try + { + Reference< XStorage> xStorage = getContainerStorage(); + const static ::rtl::OUString sBaseName(RTL_CONSTASCII_USTRINGPARAM("Obj")); + // ----------------------------------------------------------------------------- + Reference<XNameAccess> xElements(xStorage,UNO_QUERY_THROW); + ::rtl::OUString sPersistentName = ::dbtools::createUniqueName(xElements,sBaseName); + xStorage->copyElementTo(m_pImpl->m_aProps.sPersistentName,xStorage,sPersistentName); + + ::rtl::OUString sOldName = m_pImpl->m_aProps.aTitle; + rename(pDocuSave->getName()); + updateDocumentTitle(); + + Sequence< Any > aArguments(3); + PropertyValue aValue; + // set as folder + aValue.Name = PROPERTY_NAME; + aValue.Value <<= sOldName; + aArguments[0] <<= aValue; + + aValue.Name = PROPERTY_PERSISTENT_NAME; + aValue.Value <<= sPersistentName; + aArguments[1] <<= aValue; + + aValue.Name = PROPERTY_AS_TEMPLATE; + aValue.Value <<= m_pImpl->m_aProps.bAsTemplate; + aArguments[2] <<= aValue; + + Reference< XMultiServiceFactory > xORB( m_xParentContainer, UNO_QUERY_THROW ); + Reference< XInterface > xComponent( xORB->createInstanceWithArguments( SERVICE_SDB_DOCUMENTDEFINITION, aArguments ) ); + Reference< XNameContainer > xNameContainer( m_xParentContainer, UNO_QUERY_THROW ); + xNameContainer->insertByName( sOldName, makeAny( xComponent ) ); + } + catch(Exception&) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + Reference<XEmbedPersist> xPersist(m_xEmbeddedObject,UNO_QUERY); + if ( xPersist.is() ) + { + xPersist->storeOwn(); + notifyDataSourceModified(); + } + } + } + } + + + } + catch(Exception&) + { + OSL_ENSURE(0,"ODocumentDefinition::save: caught an Exception (tried to let the InteractionHandler handle it)!"); + } + return sal_True; +} + +namespace +{ + // ......................................................................... + void lcl_putLoadArgs( ::comphelper::NamedValueCollection& _io_rArgs, const optional_bool _bSuppressMacros, const optional_bool _bReadOnly ) + { + if ( !!_bSuppressMacros ) + { + if ( *_bSuppressMacros ) + { + // if we're to suppress macros, do exactly this + _io_rArgs.put( "MacroExecutionMode", MacroExecMode::NEVER_EXECUTE ); + } + else + { + // otherwise, put the setting only if not already present + if ( !_io_rArgs.has( "MacroExecutionMode" ) ) + { + _io_rArgs.put( "MacroExecutionMode", MacroExecMode::USE_CONFIG ); + } + } + } + + if ( !!_bReadOnly ) + _io_rArgs.put( "ReadOnly", *_bReadOnly ); + } +} + +// ----------------------------------------------------------------------------- +namespace +{ + Reference< XFrame > lcl_getDatabaseDocumentFrame( ODatabaseModelImpl& _rImpl ) + { + Reference< XModel > xDatabaseDocumentModel( _rImpl.getModel_noCreate() ); + + Reference< XController > xDatabaseDocumentController; + if ( xDatabaseDocumentModel.is() ) + xDatabaseDocumentController = xDatabaseDocumentModel->getCurrentController(); + + Reference< XFrame > xFrame; + if ( xDatabaseDocumentController.is() ) + xFrame = xDatabaseDocumentController->getFrame(); + + return xFrame; + } +} + +// ----------------------------------------------------------------------------- +sal_Bool ODocumentDefinition::objectSupportsEmbeddedScripts() const +{ + bool bAllowDocumentMacros = !m_pImpl->m_pDataSource + || ( m_pImpl->m_pDataSource->determineEmbeddedMacros() == ODatabaseModelImpl::eSubDocumentMacros ); + + // if *any* of the objects of the database document already has macros, we continue to allow it + // to have them, until the user did a migration. + // If there are no macros, yet, we don't allow to create them + + return bAllowDocumentMacros; +} + +// ----------------------------------------------------------------------------- +::rtl::OUString ODocumentDefinition::determineContentType() const +{ + return lcl_determineContentType_nothrow( getContainerStorage(), m_pImpl->m_aProps.sPersistentName ); +} + +// ----------------------------------------------------------------------------- +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 >& i_rOpenCommandArguments, Sequence< PropertyValue >& _out_rEmbeddedObjectDescriptor ) +{ + // ......................................................................... + // (re-)create interceptor, and put it into the descriptor of the embedded object + if ( m_pInterceptor ) + { + m_pInterceptor->dispose(); + m_pInterceptor->release(); + m_pInterceptor = NULL; + } + + m_pInterceptor = new OInterceptor( this ,_bReadOnly); + m_pInterceptor->acquire(); + Reference<XDispatchProviderInterceptor> xInterceptor = m_pInterceptor; + + ::comphelper::NamedValueCollection aEmbeddedDescriptor; + 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 ); + + Reference< XFrame > xParentFrame; + if ( m_pImpl->m_pDataSource ) + xParentFrame = lcl_getDatabaseDocumentFrame( *m_pImpl->m_pDataSource ); + if ( !xParentFrame.is() ) + { // i87957 we need a parent frame + Reference< XComponentLoader > xDesktop( m_aContext.createComponent( (::rtl::OUString)SERVICE_FRAME_DESKTOP ), UNO_QUERY_THROW ); + xParentFrame.set( xDesktop, UNO_QUERY ); + if ( xParentFrame.is() ) + { + Reference<util::XCloseable> xCloseable(m_pImpl->m_pDataSource->getModel_noCreate(),UNO_QUERY); + if ( xCloseable.is() ) + { + xCloseable->addCloseListener(this); + m_bRemoveListener = sal_True; + } + } + } + OSL_ENSURE( xParentFrame.is(), "ODocumentDefinition::fillLoadArgs: no parent frame!" ); + if ( xParentFrame.is() ) + OutplaceFrameProperties.put( "ParentFrame", xParentFrame ); + + aEmbeddedDescriptor.put( "OutplaceFrameProperties", OutplaceFrameProperties.getNamedValues() ); + + // ......................................................................... + // tell the embedded object to have (or not have) script support + aEmbeddedDescriptor.put( "EmbeddedScriptSupport", (sal_Bool)objectSupportsEmbeddedScripts() ); + + // ......................................................................... + // 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 ); + + // ......................................................................... + // 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 + { + ::comphelper::NamedValueCollection aComponentData; + aComponentData.put( "ActiveConnection", _xConnection ); + aComponentData.put( "ApplyFormDesignMode", !_bReadOnly ); + aMediaDesc.put( "ComponentData", aComponentData.getPropertyValues() ); + } + + if ( m_pImpl->m_aProps.aTitle.getLength() ) + aMediaDesc.put( "DocumentTitle", m_pImpl->m_aProps.aTitle ); + + aMediaDesc.put( "DocumentBaseURL", m_pImpl->m_pDataSource->getURL() ); + + // ......................................................................... + // put the common load arguments into the document's media descriptor + lcl_putLoadArgs( aMediaDesc, optional_bool( _bSuppressMacros ), optional_bool( _bReadOnly ) ); + + return aMediaDesc.getPropertyValues(); +} +// ----------------------------------------------------------------------------- +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() ) + { + Reference< XStorage> xStorage = getContainerStorage(); + if ( xStorage.is() ) + { + Reference< XEmbedObjectFactory> xEmbedFactory( m_aContext.createComponent( "com.sun.star.embed.OOoEmbeddedObjectFactory" ), UNO_QUERY ); + if ( xEmbedFactory.is() ) + { + ::rtl::OUString sDocumentService; + sal_Bool bSetSize = sal_False; + sal_Int32 nEntryConnectionMode = EntryInitModes::DEFAULT_INIT; + Sequence< sal_Int8 > aClassID = _aClassID; + if ( aClassID.getLength() ) + { + nEntryConnectionMode = EntryInitModes::TRUNCATE_INIT; + bSetSize = sal_True; + } + else + { + sDocumentService = GetDocumentServiceFromMediaType( getContentType(), m_aContext, aClassID ); + // check if we are not a form and + // the com.sun.star.report.pentaho.SOReportJobFactory is not present. + if ( !m_bForm && !sDocumentService.equalsAscii("com.sun.star.text.TextDocument")) + { + // 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); + if ( !xEnumDrivers.is() || !xEnumDrivers->hasMoreElements() ) + { + com::sun::star::io::WrongFormatException aWFE; + aWFE.Message = DBACORE_RESSTRING( RID_STR_MISSING_EXTENSION ); + throw aWFE; + } + } + if ( !aClassID.getLength() ) + { + if ( m_bForm ) + aClassID = MimeConfigurationHelper::GetSequenceClassID(SO3_SW_CLASSID); + else + { + aClassID = MimeConfigurationHelper::GetSequenceClassID(SO3_RPT_CLASSID_90); + } + } + } + + OSL_ENSURE( aClassID.getLength(),"No Class ID" ); + + Sequence< PropertyValue > aEmbeddedObjectDescriptor; + Sequence< PropertyValue > aLoadArgs( fillLoadArgs( + i_rConnection, _bSuppressMacros, _bReadOnly, i_rOpenCommandArguments, aEmbeddedObjectDescriptor ) ); + + m_xEmbeddedObject.set(xEmbedFactory->createInstanceUserInit(aClassID + ,sDocumentService + ,xStorage + ,m_pImpl->m_aProps.sPersistentName + ,nEntryConnectionMode + ,aLoadArgs + ,aEmbeddedObjectDescriptor + ),UNO_QUERY); + if ( m_xEmbeddedObject.is() ) + { + if ( !m_pClientHelper ) + { + m_pClientHelper = new OEmbeddedClientHelper(this); + m_pClientHelper->acquire(); + } + Reference<XEmbeddedClient> xClient = m_pClientHelper; + m_xEmbeddedObject->setClientSite(xClient); + m_xEmbeddedObject->changeState(EmbedStates::RUNNING); + if ( bSetSize ) + { + LockModifiable aLockModify( impl_getComponent_throw( false ) ); + + awt::Size aSize( DEFAULT_WIDTH, DEFAULT_HEIGHT ); + m_xEmbeddedObject->setVisualAreaSize(Aspects::MSOLE_CONTENT,aSize); + } + } + } + } + } + else + { + sal_Int32 nCurrentState = m_xEmbeddedObject->getCurrentState(); + if ( nCurrentState == EmbedStates::LOADED ) + { + if ( !m_pClientHelper ) + { + m_pClientHelper = new OEmbeddedClientHelper(this); + m_pClientHelper->acquire(); + } + Reference<XEmbeddedClient> xClient = m_pClientHelper; + m_xEmbeddedObject->setClientSite(xClient); + + Sequence< PropertyValue > aEmbeddedObjectDescriptor; + Sequence< PropertyValue > aLoadArgs( fillLoadArgs( + i_rConnection, _bSuppressMacros, _bReadOnly, i_rOpenCommandArguments, aEmbeddedObjectDescriptor ) ); + + Reference<XCommonEmbedPersist> xCommon(m_xEmbeddedObject,UNO_QUERY); + OSL_ENSURE(xCommon.is(),"unsupported interface!"); + if ( xCommon.is() ) + xCommon->reload( aLoadArgs, aEmbeddedObjectDescriptor ); + m_xEmbeddedObject->changeState(EmbedStates::RUNNING); + } + else + { + OSL_ENSURE( ( nCurrentState == EmbedStates::RUNNING ) || ( nCurrentState == EmbedStates::ACTIVE ), + "ODocumentDefinition::loadEmbeddedObject: unexpected state!" ); + + // if the document was already loaded (which means the embedded object is in state RUNNING or ACTIVE), + // then just re-set some model parameters + try + { + // 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 + + xModel->attachResource( xModel->getURL(), aExistentMediaDesc.getPropertyValues() ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + } + + // set the OfficeDatabaseDocument instance as parent of the embedded document + // #i40358# / 2005-01-19 / frank.schoenheit@sun.com + Reference< XChild > xDepdendDocAsChild( getComponent(), UNO_QUERY ); + if ( xDepdendDocAsChild.is() ) + { + try + { + if ( !xDepdendDocAsChild->getParent().is() ) + { // first encounter + xDepdendDocAsChild->setParent( getDataSource( m_xParentContainer ) ); + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + if ( i_rConnection.is() ) + m_xLastKnownConnection = i_rConnection; +} + +// ----------------------------------------------------------------------------- +void ODocumentDefinition::onCommandPreview(Any& _rImage) +{ + loadEmbeddedObjectForPreview(); + if ( m_xEmbeddedObject.is() ) + { + try + { + Reference<XTransferable> xTransfer(getComponent(),UNO_QUERY); + if ( xTransfer.is() ) + { + DataFlavor aFlavor; + aFlavor.MimeType = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("image/png")); + aFlavor.HumanPresentableName = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Portable Network Graphics")); + aFlavor.DataType = ::getCppuType(static_cast< const Sequence < sal_Int8 >* >(NULL)); + + _rImage = xTransfer->getTransferData( aFlavor ); + } + } + catch( Exception ) + { + } + } +} +// ----------------------------------------------------------------------------- +void ODocumentDefinition::getPropertyDefaultByHandle( sal_Int32 /*_nHandle*/, Any& _rDefault ) const +{ + _rDefault.clear(); +} +// ----------------------------------------------------------------------------- +void ODocumentDefinition::onCommandGetDocumentProperties( Any& _rProps ) +{ + loadEmbeddedObjectForPreview(); + if ( m_xEmbeddedObject.is() ) + { + try + { + Reference<XDocumentPropertiesSupplier> xDocSup( + getComponent(), UNO_QUERY ); + if ( xDocSup.is() ) + _rProps <<= xDocSup->getDocumentProperties(); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } +} +// ----------------------------------------------------------------------------- +Reference< util::XCloseable > ODocumentDefinition::impl_getComponent_throw( const bool i_ForceCreate ) +{ + OSL_ENSURE(m_xEmbeddedObject.is(),"Illegal call for embeddedObject"); + Reference< util::XCloseable > xComp; + if ( m_xEmbeddedObject.is() ) + { + int nState = m_xEmbeddedObject->getCurrentState(); + if ( ( nState == EmbedStates::LOADED ) && i_ForceCreate ) + { + m_xEmbeddedObject->changeState( 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 ) + { + Reference<XComponentSupplier> xCompProv(m_xEmbeddedObject,UNO_QUERY); + if ( xCompProv.is() ) + { + xComp = xCompProv->getComponent(); + OSL_ENSURE(xComp.is(),"No valid component"); + } + } + } + return xComp; +} + +// ----------------------------------------------------------------------------- +Reference< util::XCloseable > ODocumentDefinition::getComponent() throw (RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + return impl_getComponent_throw( true ); +} + +// ----------------------------------------------------------------------------- +namespace +{ + Reference< XDatabaseDocumentUI > lcl_getDatabaseDocumentUI( ODatabaseModelImpl& _rModelImpl ) + { + Reference< XDatabaseDocumentUI > xUI; + + Reference< XModel > xModel( _rModelImpl.getModel_noCreate() ); + if ( xModel.is() ) + xUI.set( xModel->getCurrentController(), UNO_QUERY ); + return xUI; + } +} + +// ----------------------------------------------------------------------------- +Reference< XComponent > ODocumentDefinition::impl_openUI_nolck_throw( bool _bForEditing ) +{ + ::osl::ClearableMutexGuard aGuard( m_aMutex ); + if ( !m_pImpl || !m_pImpl->m_pDataSource ) + throw DisposedException(); + + Reference< XDatabaseDocumentUI > xUI( lcl_getDatabaseDocumentUI( *m_pImpl->m_pDataSource ) ); + if ( !xUI.is() ) + { + // no XDatabaseDocumentUI -> just execute the respective command + m_bOpenInDesign = _bForEditing; + Reference< XComponent > xComponent( onCommandOpenSomething( Any(), true, NULL ), UNO_QUERY ); + OSL_ENSURE( xComponent.is(), "ODocumentDefinition::impl_openUI_nolck_throw: opening the thingie failed." ); + return xComponent; + } + + Reference< XComponent > xComponent; + try + { + ::rtl::OUString sName( impl_getHierarchicalName( false ) ); + sal_Int32 nObjectType = m_bForm ? DatabaseObject::FORM : DatabaseObject::REPORT; + aGuard.clear(); + + xComponent = xUI->loadComponent( + nObjectType, sName, _bForEditing + ); + } + catch( RuntimeException& ) { throw; } + catch( const Exception& ) + { + throw WrappedTargetException( + ::rtl::OUString(), *this, ::cppu::getCaughtException() ); + } + return xComponent; +} + +// ----------------------------------------------------------------------------- +void ODocumentDefinition::impl_store_throw() +{ + Reference<XEmbedPersist> xPersist( m_xEmbeddedObject, UNO_QUERY ); + if ( xPersist.is() ) + { + xPersist->storeOwn(); + notifyDataSourceModified(); + } +} + +// ----------------------------------------------------------------------------- +bool ODocumentDefinition::impl_close_throw() +{ + bool bSuccess = prepareClose(); + if ( bSuccess && m_xEmbeddedObject.is() ) + { + m_xEmbeddedObject->changeState( EmbedStates::LOADED ); + bSuccess = m_xEmbeddedObject->getCurrentState() == EmbedStates::LOADED; + } + return bSuccess; +} + +// ----------------------------------------------------------------------------- +Reference< XComponent > SAL_CALL ODocumentDefinition::open( ) throw (WrappedTargetException, RuntimeException) +{ + return impl_openUI_nolck_throw( false ); +} + +// ----------------------------------------------------------------------------- +Reference< XComponent > SAL_CALL ODocumentDefinition::openDesign( ) throw (WrappedTargetException, RuntimeException) +{ + return impl_openUI_nolck_throw( true ); +} + +// ----------------------------------------------------------------------------- +void SAL_CALL ODocumentDefinition::store( ) throw (WrappedTargetException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + try + { + impl_store_throw(); + } + catch( RuntimeException& ) { throw; } + catch( const Exception& ) + { + throw WrappedTargetException( + ::rtl::OUString(), *this, ::cppu::getCaughtException() ); + } +} + +// ----------------------------------------------------------------------------- +::sal_Bool SAL_CALL ODocumentDefinition::close( ) throw (WrappedTargetException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + sal_Bool bSuccess = sal_False; + try + { + bSuccess = impl_close_throw(); + } + catch( RuntimeException& ) { throw; } + catch( const Exception& ) + { + throw WrappedTargetException( + ::rtl::OUString(), *this, ::cppu::getCaughtException() ); + } + 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::ResettableMutexGuard aGuard(m_aMutex); + if ( _rNewName.equals( m_pImpl->m_aProps.aTitle ) ) + return; + + // document definitions are organized in a hierarchical way, so reject names + // which contain a /, as this is reserved for hierarchy level separation + if ( _rNewName.indexOf( '/' ) != -1 ) + m_aErrorHelper.raiseException( ErrorCondition::DB_OBJECT_NAME_WITH_SLASHES, *this ); + + NameChangeNotifier aNameChangeAndNotify( *this, _rNewName, aGuard ); + m_pImpl->m_aProps.aTitle = _rNewName; + + if ( m_xEmbeddedObject.is() && m_xEmbeddedObject->getCurrentState() == EmbedStates::ACTIVE ) + updateDocumentTitle(); + } + catch(const PropertyVetoException&) + { + throw ElementExistException(_rNewName,*this); + } +} +// ----------------------------------------------------------------------------- +Reference< XStorage> ODocumentDefinition::getContainerStorage() const +{ + return m_pImpl->m_pDataSource + ? m_pImpl->m_pDataSource->getStorage( m_bForm ? ODatabaseModelImpl::E_FORM : ODatabaseModelImpl::E_REPORT ) + : Reference< XStorage>(); +} +// ----------------------------------------------------------------------------- +sal_Bool ODocumentDefinition::isModified() +{ + osl::ClearableGuard< osl::Mutex > aGuard(m_aMutex); + sal_Bool bRet = sal_False; + if ( m_xEmbeddedObject.is() ) + { + Reference<XModifiable> xModel(getComponent(),UNO_QUERY); + bRet = xModel.is() && xModel->isModified(); + } + return bRet; +} +// ----------------------------------------------------------------------------- +bool ODocumentDefinition::prepareClose() +{ + if ( !m_xEmbeddedObject.is() ) + return true; + + try + { + // suspend the controller. Embedded objects are not allowed to raise + // own UI at their own discretion, instead, this has always to be triggered + // by the embedding component. Thus, we do the suspend call here. + // #i49370# / 2005-06-09 / frank.schoenheit@sun.com + + 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(); + + OSL_ENSURE( xController.is() || ( m_xEmbeddedObject->getCurrentState() < EmbedStates::ACTIVE ), + "ODocumentDefinition::prepareClose: no controller!" ); + if ( !xController.is() ) + // document has not yet been activated, i.e. has no UI, yet + return true; + + sal_Bool bCouldSuspend = xController->suspend( sal_True ); + if ( !bCouldSuspend ) + // controller vetoed the closing + return false; + + if ( isModified() ) + { + Reference< XFrame > xFrame( xController->getFrame() ); + if ( xFrame.is() ) + { + Reference< XTopWindow > xTopWindow( xFrame->getContainerWindow(), UNO_QUERY_THROW ); + xTopWindow->toFront(); + } + if ( !save( sal_True ) ) + { + if ( bCouldSuspend ) + // revert suspension + xController->suspend( sal_False ); + // saving failed or was cancelled + return false; + } + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + return true; +} +// ----------------------------------------------------------------------------- +void ODocumentDefinition::fillReportData( const ::comphelper::ComponentContext& _rContext, + const Reference< util::XCloseable >& _rxComponent, + const Reference< XConnection >& _rxActiveConnection ) +{ + Sequence< Any > aArgs(2); + PropertyValue aValue; + aValue.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TextDocument" ) ); + aValue.Value <<= _rxComponent; + aArgs[0] <<= aValue; + aValue.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ActiveConnection" ) ); + aValue.Value <<= _rxActiveConnection; + aArgs[1] <<= aValue; + + try + { + Reference< XJobExecutor > xExecuteable( + _rContext.createComponentWithArguments( "com.sun.star.wizards.report.CallReportWizard", aArgs ), UNO_QUERY_THROW ); + xExecuteable->trigger( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "fill" ) ) ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } +} +// ----------------------------------------------------------------------------- +void ODocumentDefinition::updateDocumentTitle() +{ + ::rtl::OUString sName = m_pImpl->m_aProps.aTitle; + if ( m_pImpl->m_pDataSource ) + { + if ( !sName.getLength() ) + { + if ( m_bForm ) + sName = DBACORE_RESSTRING( RID_STR_FORM ); + else + sName = DBACORE_RESSTRING( RID_STR_REPORT ); + Reference< XUntitledNumbers > xUntitledProvider(m_pImpl->m_pDataSource->getModel_noCreate(), UNO_QUERY ); + if ( xUntitledProvider.is() ) + sName += ::rtl::OUString::valueOf( xUntitledProvider->leaseNumber(getComponent()) ); + } + + Reference< XTitle > xDatabaseDocumentModel(m_pImpl->m_pDataSource->getModel_noCreate(),uno::UNO_QUERY); + if ( xDatabaseDocumentModel.is() ) + sName = xDatabaseDocumentModel->getTitle() + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" : ")) + sName; + } + Reference< XTitle> xTitle(getComponent(),UNO_QUERY); + if ( xTitle.is() ) + xTitle->setTitle(sName); +} +// ----------------------------------------------------------------------------- +void SAL_CALL ODocumentDefinition::queryClosing( const lang::EventObject& Source, ::sal_Bool GetsOwnership ) throw (util::CloseVetoException, uno::RuntimeException) +{ + (void) Source; + (void) GetsOwnership; + try + { + if ( !close() ) + throw util::CloseVetoException(); + } + catch(const lang::WrappedTargetException&) + { + throw util::CloseVetoException(); + } +} +// ----------------------------------------------------------------------------- +void SAL_CALL ODocumentDefinition::notifyClosing( const lang::EventObject& /*Source*/ ) throw (uno::RuntimeException) +{ +} +// ----------------------------------------------------------------------------- +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 new file mode 100644 index 000000000000..76427ea78baf --- /dev/null +++ b/dbaccess/source/core/dataaccess/documentdefinition.hxx @@ -0,0 +1,410 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 _DBA_COREDATAACCESS_DOCUMENTDEFINITION_HXX_ +#define _DBA_COREDATAACCESS_DOCUMENTDEFINITION_HXX_ + +#ifndef _CPPUHELPER_PROPSHLP_HXX +#include <cppuhelper/propshlp.hxx> +#endif +#ifndef _CPPUHELPER_IMPLBASE4_HXX_ +#include <cppuhelper/implbase4.hxx> +#endif +#ifndef DBA_CONTENTHELPER_HXX +#include "ContentHelper.hxx" +#endif +#ifndef COMPHELPER_PROPERTYSTATECONTAINER_HXX +#include <comphelper/propertystatecontainer.hxx> +#endif +#ifndef _COMPHELPER_PROPERTY_ARRAY_HELPER_HXX_ +#include <comphelper/proparrhlp.hxx> +#endif +#ifndef _DBASHARED_APITOOLS_HXX_ +#include "apitools.hxx" +#endif +#ifndef _COMPHELPER_UNO3_HXX_ +#include <comphelper/uno3.hxx> +#endif +#ifndef _COM_SUN_STAR_SDBC_XCONNECTION_HPP_ +#include <com/sun/star/sdbc/XConnection.hpp> +#endif +#ifndef _COM_SUN_STAR_FRAME_XCOMPONENTLOADER_HPP_ +#include <com/sun/star/frame/XComponentLoader.hpp> +#endif +#ifndef _COM_SUN_STAR_FRAME_XCONTROLLER_HPP_ +#include <com/sun/star/frame/XController.hpp> +#endif +#ifndef _COM_SUN_STAR_EMBED_XSTATECHANGELISTENER_HPP_ +#include <com/sun/star/embed/XStateChangeListener.hpp> +#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 +{ +//........................................................................ + + class OInterceptor; + class OEmbeddedClientHelper; +//========================================================================== +//= ODocumentDefinition - a database "document" which is simply a link to a real +//= document +//========================================================================== + +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 + :public OContentHelper + ,public ::comphelper::OPropertyStateContainer + ,public ::comphelper::OPropertyArrayUsageHelper< ODocumentDefinition > + ,public ODocumentDefinition_Base +{ + ::com::sun::star::uno::Reference< ::com::sun::star::embed::XEmbeddedObject> m_xEmbeddedObject; + ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStateChangeListener > m_xListener; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection > m_xLastKnownConnection; + + OInterceptor* m_pInterceptor; + sal_Bool m_bForm; // <TRUE/> if it is a form + sal_Bool m_bOpenInDesign; + sal_Bool m_bInExecute; + sal_Bool m_bRemoveListener; + OEmbeddedClientHelper* m_pClientHelper; + +protected: + virtual ~ODocumentDefinition(); + +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 + ); + + 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( ); + +// ::com::sun::star::uno::XInterface + DECLARE_XINTERFACE( ) + +// ::com::sun::star::lang::XServiceInfo + DECLARE_SERVICE_INFO_STATIC(); + +// ::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); + + // XSubDocument + virtual ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > SAL_CALL open( ) throw (::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > SAL_CALL openDesign( ) throw (::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + 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(); + + // XCommandProcessor + virtual ::com::sun::star::uno::Any SAL_CALL execute( const ::com::sun::star::ucb::Command& aCommand, sal_Int32 CommandId, const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >& Environment ) throw (::com::sun::star::uno::Exception, ::com::sun::star::ucb::CommandAbortedException, ::com::sun::star::uno::RuntimeException) ; + + // XRename + virtual void SAL_CALL rename( const ::rtl::OUString& newName ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::container::ElementExistException, ::com::sun::star::uno::RuntimeException); + + // XCloseListener + virtual void SAL_CALL queryClosing( const ::com::sun::star::lang::EventObject& Source, ::sal_Bool GetsOwnership ) throw (::com::sun::star::util::CloseVetoException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL notifyClosing( const ::com::sun::star::lang::EventObject& Source ) 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); + + /** returns the forms/reports container storage, depending on m_bForm. Our own storage + inside this container storage is the one with the name as indicated by m_pImpl->m_aProps.sPersistentName. + */ + ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage > + getContainerStorage() const; + + sal_Bool save(sal_Bool _bApprove); + sal_Bool saveAs(); + void closeObject(); + sal_Bool isModified(); + inline sal_Bool isNewReport() const { return !m_bForm && !m_pImpl->m_aProps.bAsTemplate; } + + static void fillReportData( + const ::comphelper::ComponentContext& _rContext, + const ::com::sun::star::uno::Reference< ::com::sun::star::util::XCloseable >& _rxComponent, + const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _rxActiveConnection + ); + + const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& + getConnection() const { return m_xLastKnownConnection; } + + /** prepares closing the document component + + The method suspends the controller associated with the document, and saves the document + if necessary. + + @return + <TRUE/> if and only if the document component can be closed + */ + bool prepareClose(); + + static ::com::sun::star::uno::Sequence< sal_Int8 > getDefaultDocumentTypeClassId(); + + static ::rtl::OUString GetDocumentServiceFromMediaType( + const ::rtl::OUString& _rMediaType, + const ::comphelper::ComponentContext& _rContext, + ::com::sun::star::uno::Sequence< sal_Int8 >& _rClassId + ); + static ::rtl::OUString GetDocumentServiceFromMediaType( + const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& _rxContainerStorage, + const ::rtl::OUString& _rEntityName, + const ::comphelper::ComponentContext& _rContext, + ::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( const bool i_bReactivated ); + + /** initializes a newly created view/controller of a form which is displaying our embedded object + + Has only to be called if the respective embedded object has been loaded for design (and + not for data entry) + + @param _rxController + the controller which belongs to the XModel of our (active) embedded object + */ + static void impl_initFormEditView( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XController >& _rxController ); + + /** removes the given frame from the desktop's frame collection + @raises ::com::sun::star::uno::RuntimeException + */ + static void impl_removeFrameFromDesktop_throw( + const ::comphelper::ComponentContext& _rContxt, + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& _rxFrame + ); + + /** opens the UI for this sub document + */ + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > + impl_openUI_nolck_throw( bool _bForEditing ); + + /** stores our document, if it's already loaded + */ + void impl_store_throw(); + + /** closes our document, if it's open + */ + 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 ); + + // OPropertyArrayUsageHelper + virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const; + + virtual void getPropertyDefaultByHandle( sal_Int32 _nHandle, ::com::sun::star::uno::Any& _rDefault ) const; + + // helper + virtual void SAL_CALL disposing(); + + // OContentHelper overridables + virtual ::rtl::OUString determineContentType() const; + + /** fills the load arguments + */ + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > + fillLoadArgs( + 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 >& 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. + */ + void loadEmbeddedObject( + const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection>& _xConnection, + const ::com::sun::star::uno::Sequence< sal_Int8 >& _aClassID, + const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& _rAdditionalArgs, + const bool _bSuppressMacros, + const bool _bReadOnly + ); + + /** loads the embedded object, if not already loaded. No new object can be created with this method. + */ + void loadEmbeddedObject( bool _bSuppressMacros = false ) + { + loadEmbeddedObject( + NULL, + ::com::sun::star::uno::Sequence< sal_Int8 >(), + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >(), + _bSuppressMacros, + false + ); + } + + /** loads the embedded object for preview. Macros will be suppressed, and the document will + be read-only. + */ + void loadEmbeddedObjectForPreview() + { + loadEmbeddedObject( + NULL, + ::com::sun::star::uno::Sequence< sal_Int8 >(), + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >(), + true, + true + ); + } + + /** searches for read-only flag in the args of the model and sets it to the given value, + if the value was not found, it will be appended. + @param _bReadOnly + If <TRUE/> the document will be switched to readonly mode + */ + void updateDocumentTitle(); + + void registerProperties(); + + /** determines whether the document we represent supports embedded scripts and macros + */ + sal_Bool objectSupportsEmbeddedScripts() const; + + //------------------------------------------------------------------------- + //- commands + //------------------------------------------------------------------------- + + void onCommandGetDocumentProperties( ::com::sun::star::uno::Any& _rProps ); + void onCommandInsert( const ::rtl::OUString& _sURL, const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >& Environment ) throw( ::com::sun::star::uno::Exception ); + void onCommandPreview( ::com::sun::star::uno::Any& _rImage ); + ::com::sun::star::uno::Any + onCommandOpenSomething( + const ::com::sun::star::uno::Any& _rArgument, + 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 ); +}; + +//........................................................................ +} // namespace dbaccess +//........................................................................ + +#endif // _DBA_COREDATAACCESS_DOCUMENTDEFINITION_HXX_ + diff --git a/dbaccess/source/core/dataaccess/documenteventexecutor.cxx b/dbaccess/source/core/dataaccess/documenteventexecutor.cxx new file mode 100644 index 000000000000..c25d052a396c --- /dev/null +++ b/dbaccess/source/core/dataaccess/documenteventexecutor.cxx @@ -0,0 +1,231 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * +************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#include "documenteventexecutor.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/document/XDocumentEventBroadcaster.hpp> +#include <com/sun/star/util/XURLTransformer.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +/** === end UNO includes === **/ + +#include <comphelper/componentcontext.hxx> +#include <comphelper/namedvaluecollection.hxx> +#include <cppuhelper/weakref.hxx> +#include <tools/diagnose_ex.h> +#include <vcl/svapp.hxx> +#include <vos/mutex.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::uno::WeakReference; + using ::com::sun::star::document::XDocumentEventBroadcaster; + using ::com::sun::star::document::XEventsSupplier; + using ::com::sun::star::container::XNameAccess; + using ::com::sun::star::frame::XModel; + using ::com::sun::star::util::XURLTransformer; + using ::com::sun::star::frame::XDispatchProvider; + using ::com::sun::star::frame::XDispatch; + using ::com::sun::star::util::URL; + using ::com::sun::star::beans::PropertyValue; + using ::com::sun::star::frame::XController; + using ::com::sun::star::document::DocumentEvent; + /** === end UNO using === **/ + using namespace ::com::sun::star; + + //==================================================================== + //= DocumentEventExecutor_Data + //==================================================================== + struct DocumentEventExecutor_Data + { + WeakReference< XEventsSupplier > xDocument; + Reference< XURLTransformer > xURLTransformer; + + DocumentEventExecutor_Data( const Reference< XEventsSupplier >& _rxDocument ) + :xDocument( _rxDocument ) + { + } + }; + + //-------------------------------------------------------------------- + namespace + { + static void lcl_dispatchScriptURL_throw( DocumentEventExecutor_Data& _rDocExecData, + const ::rtl::OUString& _rScriptURL, const DocumentEvent& _rTrigger ) + { + Reference< XModel > xDocument( _rDocExecData.xDocument.get(), UNO_QUERY_THROW ); + + Reference< XController > xController( xDocument->getCurrentController() ); + Reference< XDispatchProvider > xDispProv; + if ( xController.is() ) + xDispProv.set( xController->getFrame(), UNO_QUERY ); + if ( !xDispProv.is() ) + { + OSL_ENSURE( false, "lcl_dispatchScriptURL_throw: no controller/frame? How should I dispatch?" ); + return; + } + + URL aScriptURL; + aScriptURL.Complete = _rScriptURL; + if ( _rDocExecData.xURLTransformer.is() ) + _rDocExecData.xURLTransformer->parseStrict( aScriptURL ); + + // unfortunately, executing a script can trigger all kind of complex stuff, and unfortunately, not + // every component involved into this properly cares for thread safety. To be on the safe side, + // we lock the solar mutex here. + ::vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + + Reference< XDispatch > xDispatch( xDispProv->queryDispatch( aScriptURL, ::rtl::OUString(), 0 ) ); + if ( !xDispatch.is() ) + { + OSL_ENSURE( false, "lcl_dispatchScriptURL_throw: no dispatcher for the script URL!" ); + return; + } + + PropertyValue aEventParam; + aEventParam.Value <<= _rTrigger; + Sequence< PropertyValue > aDispatchArgs( &aEventParam, 1 ); + xDispatch->dispatch( aScriptURL, aDispatchArgs ); + } + } + + //==================================================================== + //= DocumentEventExecutor + //==================================================================== + //-------------------------------------------------------------------- + DocumentEventExecutor::DocumentEventExecutor( const ::comphelper::ComponentContext& _rContext, + const Reference< XEventsSupplier >& _rxDocument ) + :m_pData( new DocumentEventExecutor_Data( _rxDocument ) ) + { + Reference< XDocumentEventBroadcaster > xBroadcaster( _rxDocument, UNO_QUERY_THROW ); + + osl_incrementInterlockedCount( &m_refCount ); + { + xBroadcaster->addDocumentEventListener( this ); + } + osl_decrementInterlockedCount( &m_refCount ); + + try + { + _rContext.createComponent( "com.sun.star.util.URLTransformer", m_pData->xURLTransformer ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + //-------------------------------------------------------------------- + DocumentEventExecutor::~DocumentEventExecutor() + { + } + + //-------------------------------------------------------------------- + void SAL_CALL DocumentEventExecutor::documentEventOccured( const DocumentEvent& _Event ) throw (RuntimeException) + { + Reference< XEventsSupplier > xEventsSupplier( m_pData->xDocument.get(), UNO_QUERY ); + if ( !xEventsSupplier.is() ) + { + OSL_ENSURE( false, "DocumentEventExecutor::documentEventOccured: no document anymore, but still being notified?" ); + return; + } + + Reference< XModel > xDocument( xEventsSupplier, UNO_QUERY_THROW ); + + try + { + Reference< XNameAccess > xDocEvents( xEventsSupplier->getEvents().get(), UNO_SET_THROW ); + if ( !xDocEvents->hasByName( _Event.EventName ) ) + { + // this is worth an assertion: We are listener at the very same document which we just asked + // for its events. So when EventName is fired, why isn't it supported by xDocEvents? + OSL_ENSURE( false, "DocumentEventExecutor::documentEventOccured: an unsupported event is notified!" ); + return; + } + + const ::comphelper::NamedValueCollection aScriptDescriptor( xDocEvents->getByName( _Event.EventName ) ); + + + ::rtl::OUString sEventType; + bool bScriptAssigned = aScriptDescriptor.get_ensureType( "EventType", sEventType ); + + ::rtl::OUString sScript; + bScriptAssigned = bScriptAssigned && aScriptDescriptor.get_ensureType( "Script", sScript ); + + if ( !bScriptAssigned ) + // no script is assigned to this event + return; + + bool bDispatchScriptURL = + ( sEventType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Script" ) ) + || sEventType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Service" ) ) + ); + bool bNonEmptyScript = sScript.getLength() != 0; + + OSL_ENSURE( bDispatchScriptURL && bNonEmptyScript, + "DocumentEventExecutor::documentEventOccured: invalid/unsupported script descriptor" ); + + if ( bDispatchScriptURL && bNonEmptyScript ) + { + lcl_dispatchScriptURL_throw( *m_pData, sScript, _Event ); + } + } + catch( const RuntimeException& ) { throw; } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + //-------------------------------------------------------------------- + void SAL_CALL DocumentEventExecutor::disposing( const lang::EventObject& /*_Source*/ ) throw (RuntimeException) + { + // not interested in + } + + +//........................................................................ +} // namespace dbaccess +//........................................................................ diff --git a/dbaccess/source/core/dataaccess/documenteventexecutor.hxx b/dbaccess/source/core/dataaccess/documenteventexecutor.hxx new file mode 100644 index 000000000000..5705c5304bd7 --- /dev/null +++ b/dbaccess/source/core/dataaccess/documenteventexecutor.hxx @@ -0,0 +1,78 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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_DOCUMENTEVENTEXECUTOR_HXX +#define DBACCESS_DOCUMENTEVENTEXECUTOR_HXX + +/** === begin UNO includes === **/ +#include <com/sun/star/document/XDocumentEventListener.hpp> +#include <com/sun/star/document/XEventsSupplier.hpp> +/** === end UNO includes === **/ + +#include <cppuhelper/implbase1.hxx> + +#include <memory> + +namespace comphelper +{ + class ComponentContext; +} + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + + struct DocumentEventExecutor_Data; + //==================================================================== + //= DocumentEventExecutor + //==================================================================== + typedef ::cppu::WeakImplHelper1 < ::com::sun::star::document::XDocumentEventListener + > DocumentEventExecutor_Base; + class DocumentEventExecutor : public DocumentEventExecutor_Base + { + public: + DocumentEventExecutor( + const ::comphelper::ComponentContext& _rContext, + const ::com::sun::star::uno::Reference< ::com::sun::star::document::XEventsSupplier >& _rxDocument ); + + protected: + virtual ~DocumentEventExecutor(); + + // css.document.XDocumentEventListener + virtual void SAL_CALL documentEventOccured( const ::com::sun::star::document::DocumentEvent& Event ) throw (::com::sun::star::uno::RuntimeException); + // css.lang.XEventListener + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException); + + private: + ::std::auto_ptr< DocumentEventExecutor_Data > m_pData; + }; + +//........................................................................ +} // namespace dbaccess +//........................................................................ + +#endif // DBACCESS_DOCUMENTEVENTEXECUTOR_HXX diff --git a/dbaccess/source/core/dataaccess/documenteventnotifier.cxx b/dbaccess/source/core/dataaccess/documenteventnotifier.cxx new file mode 100644 index 000000000000..cfbf96433971 --- /dev/null +++ b/dbaccess/source/core/dataaccess/documenteventnotifier.cxx @@ -0,0 +1,319 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * +************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#include "documenteventnotifier.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/frame/DoubleInitializationException.hpp> +/** === end UNO includes === **/ + +#include <comphelper/asyncnotification.hxx> +#include <cppuhelper/interfacecontainer.hxx> +#include <cppuhelper/weak.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::frame::DoubleInitializationException; + using ::com::sun::star::document::XDocumentEventListener; + using ::com::sun::star::document::DocumentEvent; + using ::com::sun::star::frame::XController2; + /** === end UNO using === **/ + using namespace ::com::sun::star; + + //================================================================== + //= DocumentEventHolder + //================================================================== + typedef ::comphelper::EventHolder< DocumentEvent > DocumentEventHolder; + + //==================================================================== + //= DocumentEventNotifier_Impl + //==================================================================== + class DocumentEventNotifier_Impl : public ::comphelper::IEventProcessor + { + oslInterlockedCount m_refCount; + ::cppu::OWeakObject& m_rDocument; + ::osl::Mutex& m_rMutex; + bool m_bInitialized; + bool m_bDisposed; + ::rtl::Reference< ::comphelper::AsyncEventNotifier > m_pEventBroadcaster; + ::cppu::OInterfaceContainerHelper m_aLegacyEventListeners; + ::cppu::OInterfaceContainerHelper m_aDocumentEventListeners; + + public: + DocumentEventNotifier_Impl( ::cppu::OWeakObject& _rBroadcasterDocument, ::osl::Mutex& _rMutex ) + :m_refCount( 0 ) + ,m_rDocument( _rBroadcasterDocument ) + ,m_rMutex( _rMutex ) + ,m_bInitialized( false ) + ,m_bDisposed( false ) + ,m_aLegacyEventListeners( _rMutex ) + ,m_aDocumentEventListeners( _rMutex ) + { + } + + // IReference + virtual void SAL_CALL acquire(); + virtual void SAL_CALL release(); + + void addLegacyEventListener( const Reference< document::XEventListener >& _Listener ) + { + m_aLegacyEventListeners.addInterface( _Listener ); + } + + void removeLegacyEventListener( const Reference< document::XEventListener >& _Listener ) + { + m_aLegacyEventListeners.removeInterface( _Listener ); + } + + void addDocumentEventListener( const Reference< XDocumentEventListener >& _Listener ) + { + m_aDocumentEventListeners.addInterface( _Listener ); + } + + void removeDocumentEventListener( const Reference< XDocumentEventListener >& _Listener ) + { + m_aDocumentEventListeners.removeInterface( _Listener ); + } + + void disposing(); + + void onDocumentInitialized(); + + void notifyDocumentEvent( const ::rtl::OUString& _EventName, const Reference< XController2 >& _ViewController, + const Any& _Supplement ) + { + impl_notifyEvent_nothrow( DocumentEvent( + m_rDocument, _EventName, _ViewController, _Supplement ) ); + } + + void notifyDocumentEventAsync( const ::rtl::OUString& _EventName, const Reference< XController2 >& _ViewController, + const Any& _Supplement ) + { + impl_notifyEventAsync_nothrow( DocumentEvent( + m_rDocument, _EventName, _ViewController, _Supplement ) ); + } + + protected: + virtual ~DocumentEventNotifier_Impl() + { + } + + // IEventProcessor + virtual void processEvent( const ::comphelper::AnyEvent& _rEvent ); + + private: + void impl_notifyEvent_nothrow( const DocumentEvent& _rEvent ); + void impl_notifyEventAsync_nothrow( const DocumentEvent& _rEvent ); + }; + + //-------------------------------------------------------------------- + void SAL_CALL DocumentEventNotifier_Impl::acquire() + { + osl_incrementInterlockedCount( &m_refCount ); + } + + //-------------------------------------------------------------------- + void SAL_CALL DocumentEventNotifier_Impl::release() + { + if ( 0 == osl_decrementInterlockedCount( &m_refCount ) ) + delete this; + } + + //-------------------------------------------------------------------- + void DocumentEventNotifier_Impl::disposing() + { + // SYNCHRONIZED -> + // cancel any pending asynchronous events + ::osl::ResettableMutexGuard aGuard( m_rMutex ); + if ( m_pEventBroadcaster.is() ) + { + m_pEventBroadcaster->removeEventsForProcessor( this ); + m_pEventBroadcaster->terminate(); + m_pEventBroadcaster = NULL; + } + + lang::EventObject aEvent( m_rDocument ); + aGuard.clear(); + // <-- SYNCHRONIZED + + m_aLegacyEventListeners.disposeAndClear( aEvent ); + m_aDocumentEventListeners.disposeAndClear( aEvent ); + + // SYNCHRONIZED -> + aGuard.reset(); + m_bDisposed = true; + // <-- SYNCHRONIZED + } + + //-------------------------------------------------------------------- + void DocumentEventNotifier_Impl::onDocumentInitialized() + { + if ( m_bInitialized ) + throw DoubleInitializationException(); + + m_bInitialized = true; + if ( m_pEventBroadcaster.is() ) + // there are already pending asynchronous events + m_pEventBroadcaster->create(); + } + + //-------------------------------------------------------------------- + void DocumentEventNotifier_Impl::impl_notifyEvent_nothrow( const DocumentEvent& _rEvent ) + { + OSL_PRECOND( m_bInitialized, + "DocumentEventNotifier_Impl::impl_notifyEvent_nothrow: only to be called when the document is already initialized!" ); + try + { + document::EventObject aLegacyEvent( _rEvent.Source, _rEvent.EventName ); + m_aLegacyEventListeners.notifyEach( &document::XEventListener::notifyEvent, aLegacyEvent ); + } + catch(const Exception&) + { + DBG_UNHANDLED_EXCEPTION(); + } + try + { + m_aDocumentEventListeners.notifyEach( &XDocumentEventListener::documentEventOccured, _rEvent ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + //-------------------------------------------------------------------- + void DocumentEventNotifier_Impl::impl_notifyEventAsync_nothrow( const DocumentEvent& _rEvent ) + { + if ( !m_pEventBroadcaster.is() ) + { + m_pEventBroadcaster.set( new ::comphelper::AsyncEventNotifier ); + if ( m_bInitialized ) + // start processing the events if and only if we (our document, respectively) are + // already initialized + m_pEventBroadcaster->create(); + } + m_pEventBroadcaster->addEvent( new DocumentEventHolder( _rEvent ), this ); + } + + // ----------------------------------------------------------------------------- + void DocumentEventNotifier_Impl::processEvent( const ::comphelper::AnyEvent& _rEvent ) + { + // beware, this is called from the notification thread + { + ::osl::MutexGuard aGuard( m_rMutex ); + if ( m_bDisposed ) + return; + } + const DocumentEventHolder& rEventHolder = dynamic_cast< const DocumentEventHolder& >( _rEvent ); + impl_notifyEvent_nothrow( rEventHolder.getEventObject() ); + } + + //==================================================================== + //= DocumentEventNotifier + //==================================================================== + //-------------------------------------------------------------------- + DocumentEventNotifier::DocumentEventNotifier( ::cppu::OWeakObject& _rBroadcasterDocument, ::osl::Mutex& _rMutex ) + :m_pImpl( new DocumentEventNotifier_Impl( _rBroadcasterDocument, _rMutex ) ) + { + } + + //-------------------------------------------------------------------- + DocumentEventNotifier::~DocumentEventNotifier() + { + } + + //-------------------------------------------------------------------- + void DocumentEventNotifier::disposing() + { + m_pImpl->disposing(); + } + + //-------------------------------------------------------------------- + void DocumentEventNotifier::onDocumentInitialized() + { + m_pImpl->onDocumentInitialized(); + } + + //-------------------------------------------------------------------- + void DocumentEventNotifier::addLegacyEventListener( const Reference< document::XEventListener >& _Listener ) + { + m_pImpl->addLegacyEventListener( _Listener ); + } + + //-------------------------------------------------------------------- + void DocumentEventNotifier::removeLegacyEventListener( const Reference< document::XEventListener >& _Listener ) + { + m_pImpl->removeLegacyEventListener( _Listener ); + } + + //-------------------------------------------------------------------- + void DocumentEventNotifier::addDocumentEventListener( const Reference< XDocumentEventListener >& _Listener ) + { + m_pImpl->addDocumentEventListener( _Listener ); + } + + //-------------------------------------------------------------------- + void DocumentEventNotifier::removeDocumentEventListener( const Reference< XDocumentEventListener >& _Listener ) + { + m_pImpl->removeDocumentEventListener( _Listener ); + } + + //-------------------------------------------------------------------- + void DocumentEventNotifier::notifyDocumentEvent( const ::rtl::OUString& _EventName, + const Reference< XController2 >& _ViewController, const Any& _Supplement ) + { + m_pImpl->notifyDocumentEvent( _EventName, _ViewController, _Supplement ); + } + + //-------------------------------------------------------------------- + void DocumentEventNotifier::notifyDocumentEventAsync( const ::rtl::OUString& _EventName, + const Reference< XController2 >& _ViewController, const Any& _Supplement ) + { + m_pImpl->notifyDocumentEventAsync( _EventName, _ViewController, _Supplement ); + } + +//........................................................................ +} // namespace dbaccess +//........................................................................ diff --git a/dbaccess/source/core/dataaccess/documenteventnotifier.hxx b/dbaccess/source/core/dataaccess/documenteventnotifier.hxx new file mode 100644 index 000000000000..870f5decf984 --- /dev/null +++ b/dbaccess/source/core/dataaccess/documenteventnotifier.hxx @@ -0,0 +1,144 @@ + +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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_DOCUMENTEVENTNOTIFIER_HXX +#define DBACCESS_DOCUMENTEVENTNOTIFIER_HXX + +/** === begin UNO includes === **/ +#include <com/sun/star/document/XEventListener.hpp> +#include <com/sun/star/document/XDocumentEventListener.hpp> +/** === end UNO includes === **/ + +#include <rtl/ref.hxx> + +namespace cppu +{ + class OWeakObject; +} + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + + class DocumentEventNotifier_Impl; + //==================================================================== + //= DocumentEventNotifier + //==================================================================== + class DocumentEventNotifier + { + public: + DocumentEventNotifier( ::cppu::OWeakObject& _rBroadcasterDocument, ::osl::Mutex& _rMutex ); + ~DocumentEventNotifier(); + + void addLegacyEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::document::XEventListener >& _Listener ); + void removeLegacyEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::document::XEventListener >& _Listener ); + void addDocumentEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::document::XDocumentEventListener >& _Listener ); + void removeDocumentEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::document::XDocumentEventListener >& _Listener ); + + /** disposes the instance + @precond + the mutex is not locked + */ + void disposing(); + + /** tells the instance that its document is completely initialized now. + + Before you call this method, no notification will actually happen + + @precond + the mutex is locked + */ + void onDocumentInitialized(); + + /** notifies a document event described by the given parameters + + @precond + the mutex is not locked + @precond + ->onDocumentInitialized has been called + */ + void notifyDocumentEvent( + const ::rtl::OUString& _EventName, + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XController2 >& _rxViewController = NULL, + const ::com::sun::star::uno::Any& _Supplement = ::com::sun::star::uno::Any() + ); + + /** notifies a document event, described by the given parameters, asynchronously + + Note that no event is actually notified before you called ->onDocumentInitialized. + + @precond + the mutex is locked + */ + void notifyDocumentEventAsync( + const ::rtl::OUString& _EventName, + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XController2 >& _ViewController = NULL, + const ::com::sun::star::uno::Any& _Supplement = ::com::sun::star::uno::Any() + ); + + /** notifies a document event to all registered listeners + + @precond + the mutex is not locked + @precond + ->onDocumentInitialized has been called + */ + void notifyDocumentEvent( + const sal_Char* _pAsciiEventName, + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XController2 >& _rxViewController = NULL, + const ::com::sun::star::uno::Any& _rSupplement = ::com::sun::star::uno::Any() + ) + { + notifyDocumentEvent( ::rtl::OUString::createFromAscii( _pAsciiEventName ), _rxViewController, _rSupplement ); + } + + /** notifies a document event to all registered listeners, asynchronously + + Note that no event is actually notified before you called ->onDocumentInitialized. + + @precond + the mutex is locked + */ + void notifyDocumentEventAsync( + const sal_Char* _pAsciiEventName, + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XController2 >& _rxViewController = NULL, + const ::com::sun::star::uno::Any& _rSupplement = ::com::sun::star::uno::Any() + ) + { + notifyDocumentEventAsync( ::rtl::OUString::createFromAscii( _pAsciiEventName ), _rxViewController, _rSupplement ); + } + + private: + ::rtl::Reference< DocumentEventNotifier_Impl > m_pImpl; + }; + +//........................................................................ +} // namespace dbaccess +//........................................................................ + +#endif // DBACCESS_DOCUMENTEVENTNOTIFIER_HXX diff --git a/dbaccess/source/core/dataaccess/documentevents.cxx b/dbaccess/source/core/dataaccess/documentevents.cxx new file mode 100644 index 000000000000..8d191c1d3503 --- /dev/null +++ b/dbaccess/source/core/dataaccess/documentevents.cxx @@ -0,0 +1,265 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * +************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#include "documentevents.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/beans/PropertyValue.hpp> +/** === end UNO includes === **/ + +#include <comphelper/namedvaluecollection.hxx> + +#include <algorithm> +#include <functional> + +//........................................................................ +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::beans::PropertyValue; + using ::com::sun::star::container::NoSuchElementException; + using ::com::sun::star::lang::WrappedTargetException; + using ::com::sun::star::lang::IllegalArgumentException; + using ::com::sun::star::uno::Sequence; + using ::com::sun::star::uno::Type; + /** === end UNO using === **/ + + //==================================================================== + //= DocumentEvents_Data + //==================================================================== + struct DocumentEvents_Data : public ::boost::noncopyable + { + ::cppu::OWeakObject& rParent; + ::osl::Mutex& rMutex; + DocumentEventsData& rEventsData; + + DocumentEvents_Data( ::cppu::OWeakObject& _rParent, ::osl::Mutex& _rMutex, DocumentEventsData& _rEventsData ) + :rParent( _rParent ) + ,rMutex( _rMutex ) + ,rEventsData( _rEventsData ) + { + } + }; + + //==================================================================== + //= helper + //==================================================================== + struct DocumentEventData + { + const sal_Char* pAsciiEventName; + bool bNeedsSyncNotify; + }; + + //-------------------------------------------------------------------- + namespace + { + static const DocumentEventData* lcl_getDocumentEventData() + { + static const DocumentEventData s_aData[] = { + { "OnCreate", true }, + { "OnLoadFinished", true }, + { "OnNew", false }, // compatibility, see http://www.openoffice.org/issues/show_bug.cgi?id=46484 + { "OnLoad", false }, // compatibility, see http://www.openoffice.org/issues/show_bug.cgi?id=46484 + { "OnSaveAs", true }, + { "OnSaveAsDone", false }, + { "OnSaveAsFailed", false }, + { "OnSave", true }, + { "OnSaveDone", false }, + { "OnSaveFailed", false }, + { "OnSaveTo", true }, + { "OnSaveToDone", false }, + { "OnSaveToFailed", false }, + { "OnPrepareUnload", true }, + { "OnUnload", true }, + { "OnFocus", false }, + { "OnUnfocus", false }, + { "OnModifyChanged", false }, + { "OnViewCreated", false }, + { "OnPrepareViewClosing", true }, + { "OnViewClosed", false }, + { "OnTitleChanged", false }, + { "OnSubComponentOpened", false }, + { "OnSubComponentClosed", false }, + { NULL, false } + }; + return s_aData; + } + } + + //==================================================================== + //= DocumentEvents + //==================================================================== + //-------------------------------------------------------------------- + DocumentEvents::DocumentEvents( ::cppu::OWeakObject& _rParent, ::osl::Mutex& _rMutex, DocumentEventsData& _rEventsData ) + :m_pData( new DocumentEvents_Data( _rParent, _rMutex, _rEventsData ) ) + { + const DocumentEventData* pEventData = lcl_getDocumentEventData(); + while ( pEventData->pAsciiEventName ) + { + ::rtl::OUString sEventName = ::rtl::OUString::createFromAscii( pEventData->pAsciiEventName ); + DocumentEventsData::iterator existingPos = m_pData->rEventsData.find( sEventName ); + if ( existingPos == m_pData->rEventsData.end() ) + m_pData->rEventsData[ sEventName ] = Sequence< PropertyValue >(); + ++pEventData; + } + } + + //-------------------------------------------------------------------- + DocumentEvents::~DocumentEvents() + { + } + + //-------------------------------------------------------------------- + void SAL_CALL DocumentEvents::acquire() throw() + { + m_pData->rParent.acquire(); + } + + //-------------------------------------------------------------------- + void SAL_CALL DocumentEvents::release() throw() + { + m_pData->rParent.release(); + } + + //-------------------------------------------------------------------- + bool DocumentEvents::needsSynchronousNotification( const ::rtl::OUString& _rEventName ) + { + const DocumentEventData* pEventData = lcl_getDocumentEventData(); + while ( pEventData->pAsciiEventName ) + { + if ( _rEventName.compareToAscii( pEventData->pAsciiEventName ) == 0 ) + return pEventData->bNeedsSyncNotify; + ++pEventData; + } + + // this is an unknown event ... assume async notification + return false; + } + + //-------------------------------------------------------------------- + void SAL_CALL DocumentEvents::replaceByName( const ::rtl::OUString& _Name, const Any& _Element ) throw (IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException) + { + ::osl::MutexGuard aGuard( m_pData->rMutex ); + + DocumentEventsData::iterator elementPos = m_pData->rEventsData.find( _Name ); + if ( elementPos == m_pData->rEventsData.end() ) + throw NoSuchElementException( _Name, *this ); + + Sequence< PropertyValue > aEventDescriptor; + if ( _Element.hasValue() && !( _Element >>= aEventDescriptor ) ) + throw IllegalArgumentException( _Element.getValueTypeName(), *this, 2 ); + + // Weird enough, the event assignment UI has (well: had) the idea of using an empty "EventType"/"Script" + // to indicate the event descriptor should be reset, instead of just passing an empty event descriptor. + ::comphelper::NamedValueCollection aCheck( aEventDescriptor ); + if ( aCheck.has( "EventType" ) ) + { + ::rtl::OUString sEventType = aCheck.getOrDefault( "EventType", ::rtl::OUString() ); + OSL_ENSURE( sEventType.getLength(), "DocumentEvents::replaceByName: doing a reset via an empty EventType is weird!" ); + if ( !sEventType.getLength() ) + aEventDescriptor.realloc( 0 ); + } + if ( aCheck.has( "Script" ) ) + { + ::rtl::OUString sScript = aCheck.getOrDefault( "Script", ::rtl::OUString() ); + OSL_ENSURE( sScript.getLength(), "DocumentEvents::replaceByName: doing a reset via an empty Script is weird!" ); + if ( !sScript.getLength() ) + aEventDescriptor.realloc( 0 ); + } + + elementPos->second = aEventDescriptor; + } + + //-------------------------------------------------------------------- + Any SAL_CALL DocumentEvents::getByName( const ::rtl::OUString& _Name ) throw (NoSuchElementException, WrappedTargetException, RuntimeException) + { + ::osl::MutexGuard aGuard( m_pData->rMutex ); + + DocumentEventsData::const_iterator elementPos = m_pData->rEventsData.find( _Name ); + if ( elementPos == m_pData->rEventsData.end() ) + throw NoSuchElementException( _Name, *this ); + + Any aReturn; + const Sequence< PropertyValue >& rEventDesc( elementPos->second ); + if ( rEventDesc.getLength() > 0 ) + aReturn <<= rEventDesc; + return aReturn; + } + + //-------------------------------------------------------------------- + Sequence< ::rtl::OUString > SAL_CALL DocumentEvents::getElementNames( ) throw (RuntimeException) + { + ::osl::MutexGuard aGuard( m_pData->rMutex ); + + Sequence< ::rtl::OUString > aNames( m_pData->rEventsData.size() ); + ::std::transform( + m_pData->rEventsData.begin(), + m_pData->rEventsData.end(), + aNames.getArray(), + ::std::select1st< DocumentEventsData::value_type >() + ); + return aNames; + } + + //-------------------------------------------------------------------- + ::sal_Bool SAL_CALL DocumentEvents::hasByName( const ::rtl::OUString& _Name ) throw (RuntimeException) + { + ::osl::MutexGuard aGuard( m_pData->rMutex ); + + return m_pData->rEventsData.find( _Name ) != m_pData->rEventsData.end(); + } + + //-------------------------------------------------------------------- + Type SAL_CALL DocumentEvents::getElementType( ) throw (RuntimeException) + { + return ::cppu::UnoType< Sequence< PropertyValue > >::get(); + } + + //-------------------------------------------------------------------- + ::sal_Bool SAL_CALL DocumentEvents::hasElements( ) throw (RuntimeException) + { + ::osl::MutexGuard aGuard( m_pData->rMutex ); + return !m_pData->rEventsData.empty(); + } + + +//........................................................................ +} // namespace dbaccess +//........................................................................ diff --git a/dbaccess/source/core/dataaccess/documentevents.hxx b/dbaccess/source/core/dataaccess/documentevents.hxx new file mode 100644 index 000000000000..6d761027e0ca --- /dev/null +++ b/dbaccess/source/core/dataaccess/documentevents.hxx @@ -0,0 +1,90 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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_DOCUMENTEVENTS_HXX +#define DBACCESS_DOCUMENTEVENTS_HXX + +/** === begin UNO includes === **/ +#include <com/sun/star/container/XNameReplace.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +/** === end UNO includes === **/ + +#include <cppuhelper/implbase1.hxx> + +#include <memory> +#include <map> +#include <boost/noncopyable.hpp> + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + + typedef ::std::map< ::rtl::OUString, ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > > + DocumentEventsData; + + //==================================================================== + //= DocumentEvents + //==================================================================== + struct DocumentEvents_Data; + + typedef ::cppu::WeakImplHelper1 < ::com::sun::star::container::XNameReplace + > DocumentEvents_Base; + + class DocumentEvents :public DocumentEvents_Base + ,public ::boost::noncopyable + { + public: + DocumentEvents( ::cppu::OWeakObject& _rParent, ::osl::Mutex& _rMutex, DocumentEventsData& _rEventsData ); + ~DocumentEvents(); + + static bool needsSynchronousNotification( const ::rtl::OUString& _rEventName ); + + // XInterface + virtual void SAL_CALL acquire() throw(); + virtual void SAL_CALL release() throw(); + + // XNameReplace + virtual void SAL_CALL replaceByName( const ::rtl::OUString& aName, const ::com::sun::star::uno::Any& aElement ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + + // XNameAccess + virtual ::com::sun::star::uno::Any SAL_CALL getByName( const ::rtl::OUString& aName ) throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getElementNames( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName ) throw (::com::sun::star::uno::RuntimeException); + + // XElementAccess + virtual ::com::sun::star::uno::Type SAL_CALL getElementType( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::sal_Bool SAL_CALL hasElements( ) throw (::com::sun::star::uno::RuntimeException); + + private: + ::std::auto_ptr< DocumentEvents_Data > m_pData; + }; + +//........................................................................ +} // namespace dbaccess +//........................................................................ + +#endif // DBACCESS_DOCUMENTEVENTS_HXX diff --git a/dbaccess/source/core/dataaccess/intercept.cxx b/dbaccess/source/core/dataaccess/intercept.cxx new file mode 100644 index 000000000000..8a24bbcdf4a3 --- /dev/null +++ b/dbaccess/source/core/dataaccess/intercept.cxx @@ -0,0 +1,447 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#include "intercept.hxx" +#include "dbastrings.hrc" + +#include <com/sun/star/embed/EmbedStates.hpp> +#include <com/sun/star/document/XEventBroadcaster.hpp> +#include <com/sun/star/util/XModifiable.hpp> +#include <cppuhelper/weak.hxx> + +#include <comphelper/types.hxx> +#include <tools/debug.hxx> +#include <tools/diagnose_ex.h> + + +namespace dbaccess +{ +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::ucb; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::embed; +using namespace ::com::sun::star::container; +using namespace ::comphelper; +using namespace ::cppu; + +#define DISPATCH_SAVEAS 0 +#define DISPATCH_SAVE 1 +#define DISPATCH_CLOSEDOC 2 +#define DISPATCH_CLOSEWIN 3 +#define DISPATCH_CLOSEFRAME 4 +#define DISPATCH_RELOAD 5 +// the OSL_ENSURE in CTOR has to be changed too, when adding new defines + +void SAL_CALL OInterceptor::dispose() + throw( RuntimeException ) +{ + EventObject aEvt( *this ); + + osl::MutexGuard aGuard(m_aMutex); + + if ( m_pDisposeEventListeners && m_pDisposeEventListeners->getLength() ) + m_pDisposeEventListeners->disposeAndClear( aEvt ); + + if ( m_pStatCL ) + m_pStatCL->disposeAndClear( aEvt ); + + m_xSlaveDispatchProvider.clear(); + m_xMasterDispatchProvider.clear(); + + m_pContentHolder = NULL; +} + + +DBG_NAME(OInterceptor) + +OInterceptor::OInterceptor( ODocumentDefinition* _pContentHolder,sal_Bool _bAllowEditDoc ) + :m_pContentHolder( _pContentHolder ) + ,m_aInterceptedURL(7) + ,m_pDisposeEventListeners(0) + ,m_pStatCL(0) + ,m_bAllowEditDoc(_bAllowEditDoc) +{ + DBG_CTOR(OInterceptor,NULL); + + OSL_ENSURE(DISPATCH_RELOAD < m_aInterceptedURL.getLength(),"Illegal size."); + + m_aInterceptedURL[DISPATCH_SAVEAS] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".uno:SaveAs")); + m_aInterceptedURL[DISPATCH_SAVE] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".uno:Save")); + m_aInterceptedURL[DISPATCH_CLOSEDOC] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".uno:CloseDoc")); + m_aInterceptedURL[DISPATCH_CLOSEWIN] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".uno:CloseWin")); + m_aInterceptedURL[DISPATCH_CLOSEFRAME] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".uno:CloseFrame")); + m_aInterceptedURL[DISPATCH_RELOAD] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".uno:Reload")); +} + + +OInterceptor::~OInterceptor() +{ + if( m_pDisposeEventListeners ) + delete m_pDisposeEventListeners; + + if(m_pStatCL) + delete m_pStatCL; + + DBG_DTOR(OInterceptor,NULL); +} + +struct DispatchHelper +{ + URL aURL; + Sequence<PropertyValue > aArguments; +}; + +//XDispatch +void SAL_CALL OInterceptor::dispatch( const URL& _URL,const Sequence<PropertyValue >& Arguments ) throw (RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + if ( !m_pContentHolder ) + return; + + if ( _URL.Complete == m_aInterceptedURL[ DISPATCH_SAVE ] ) + { + m_pContentHolder->save( sal_False ); + return; + } + + if ( _URL.Complete == m_aInterceptedURL[ DISPATCH_RELOAD ] ) + { + ODocumentDefinition::fillReportData( + m_pContentHolder->getContext(), + m_pContentHolder->getComponent(), + m_pContentHolder->getConnection() + ); + return; + } + + if( _URL.Complete == m_aInterceptedURL[ DISPATCH_SAVEAS ] ) + { + if ( m_pContentHolder->isNewReport() ) + { + m_pContentHolder->saveAs(); + } + else if ( m_xSlaveDispatchProvider.is() ) + { + Sequence< PropertyValue > aNewArgs = Arguments; + sal_Int32 nInd = 0; + + while( nInd < aNewArgs.getLength() ) + { + if ( aNewArgs[nInd].Name.equalsAscii( "SaveTo" ) ) + { + aNewArgs[nInd].Value <<= sal_True; + break; + } + nInd++; + } + + if ( nInd == aNewArgs.getLength() ) + { + aNewArgs.realloc( nInd + 1 ); + aNewArgs[nInd].Name = ::rtl::OUString::createFromAscii( "SaveTo" ); + aNewArgs[nInd].Value <<= sal_True; + } + + Reference< XDispatch > xDispatch = m_xSlaveDispatchProvider->queryDispatch( + _URL, ::rtl::OUString::createFromAscii( "_self" ), 0 ); + if ( xDispatch.is() ) + xDispatch->dispatch( _URL, aNewArgs ); + } + return; + } + + if ( _URL.Complete == m_aInterceptedURL[ DISPATCH_CLOSEDOC ] + || _URL.Complete == m_aInterceptedURL[ DISPATCH_CLOSEWIN ] + || _URL.Complete == m_aInterceptedURL[ DISPATCH_CLOSEFRAME ] + ) + { + DispatchHelper* pHelper = new DispatchHelper; + pHelper->aArguments = Arguments; + pHelper->aURL = _URL; + Application::PostUserEvent( LINK( this, OInterceptor, OnDispatch ), reinterpret_cast< void* >( pHelper ) ); + return; + } +} + +IMPL_LINK( OInterceptor, OnDispatch, void*, _pDispatcher ) +{ + ::std::auto_ptr<DispatchHelper> pHelper( reinterpret_cast< DispatchHelper* >( _pDispatcher ) ); + try + { + if ( m_pContentHolder && m_pContentHolder->prepareClose() && m_xSlaveDispatchProvider.is() ) + { + Reference< XDispatch > xDispatch = m_xSlaveDispatchProvider->queryDispatch( + pHelper->aURL, ::rtl::OUString::createFromAscii( "_self" ), 0 ); + if ( xDispatch.is() ) + { + Reference< ::com::sun::star::document::XEventBroadcaster> xEvtB(m_pContentHolder->getComponent(),UNO_QUERY); + if ( xEvtB.is() ) + xEvtB->removeEventListener(this); + + Reference< XInterface > xKeepContentHolderAlive( *m_pContentHolder ); + xDispatch->dispatch( pHelper->aURL,pHelper->aArguments); + } + } + } + catch ( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + return 0L; +} + +void SAL_CALL OInterceptor::addStatusListener( + const Reference< + XStatusListener >& Control, + const URL& _URL ) + throw ( + RuntimeException + ) +{ + if(!Control.is()) + return; + + if ( m_pContentHolder && _URL.Complete == m_aInterceptedURL[DISPATCH_SAVEAS] ) + { // SaveAs + + if ( !m_pContentHolder->isNewReport() ) + { + FeatureStateEvent aStateEvent; + aStateEvent.FeatureURL.Complete = m_aInterceptedURL[DISPATCH_SAVEAS]; + aStateEvent.FeatureDescriptor = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SaveCopyTo")); + aStateEvent.IsEnabled = sal_True; + aStateEvent.Requery = sal_False; + aStateEvent.State <<= (rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("($3)"))); + Control->statusChanged(aStateEvent); + } + + { + osl::MutexGuard aGuard(m_aMutex); + if(!m_pStatCL) + m_pStatCL = new PropertyChangeListenerContainer(m_aMutex); + } + + m_pStatCL->addInterface(_URL.Complete,Control); + } + else if ( m_pContentHolder && _URL.Complete == m_aInterceptedURL[DISPATCH_SAVE] ) + { // Save + FeatureStateEvent aStateEvent; + aStateEvent.FeatureURL.Complete = m_aInterceptedURL[DISPATCH_SAVE]; + aStateEvent.FeatureDescriptor = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Update")); + aStateEvent.IsEnabled = m_pContentHolder != NULL && m_pContentHolder->isModified(); + aStateEvent.Requery = sal_False; + + Control->statusChanged(aStateEvent); + { + osl::MutexGuard aGuard(m_aMutex); + if(!m_pStatCL) + m_pStatCL = new PropertyChangeListenerContainer(m_aMutex); + } + + m_pStatCL->addInterface(_URL.Complete,Control); + Reference< ::com::sun::star::document::XEventBroadcaster> xEvtB(m_pContentHolder->getComponent(),UNO_QUERY); + if ( xEvtB.is() ) + xEvtB->addEventListener(this); + } + else + { + sal_Int32 i = 2; + if(_URL.Complete == m_aInterceptedURL[i] || + _URL.Complete == m_aInterceptedURL[++i] || + _URL.Complete == m_aInterceptedURL[++i] || + _URL.Complete == m_aInterceptedURL[i = DISPATCH_RELOAD] ) + { // Close and return + FeatureStateEvent aStateEvent; + aStateEvent.FeatureURL.Complete = m_aInterceptedURL[i]; + aStateEvent.FeatureDescriptor = rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("Close and Return")); + aStateEvent.IsEnabled = sal_True; + aStateEvent.Requery = sal_False; + Control->statusChanged(aStateEvent); + + + { + osl::MutexGuard aGuard(m_aMutex); + if(!m_pStatCL) + m_pStatCL = new PropertyChangeListenerContainer(m_aMutex); + } + + m_pStatCL->addInterface(_URL.Complete,Control); + return; + } + } +} + + +void SAL_CALL OInterceptor::removeStatusListener( + const Reference< + XStatusListener >& Control, + const URL& _URL ) + throw ( + RuntimeException + ) +{ + if(!(Control.is() && m_pStatCL)) + return; + else + { + m_pStatCL->removeInterface(_URL.Complete,Control); + return; + } +} + + +//XInterceptorInfo +Sequence< ::rtl::OUString > SAL_CALL OInterceptor::getInterceptedURLs( ) throw ( RuntimeException ) +{ + // now implemented as update + return m_aInterceptedURL; +} + + +// XDispatchProvider + +Reference< XDispatch > SAL_CALL OInterceptor::queryDispatch( const URL& _URL,const ::rtl::OUString& TargetFrameName,sal_Int32 SearchFlags ) + throw (RuntimeException) +{ + osl::MutexGuard aGuard(m_aMutex); + const ::rtl::OUString* pIter = m_aInterceptedURL.getConstArray(); + const ::rtl::OUString* pEnd = pIter + m_aInterceptedURL.getLength(); + for(;pIter != pEnd;++pIter) + { + if ( _URL.Complete == *pIter ) + return (XDispatch*)this; + } + + if(m_xSlaveDispatchProvider.is()) + return m_xSlaveDispatchProvider->queryDispatch(_URL,TargetFrameName,SearchFlags); + else + return Reference<XDispatch>(); +} + +Sequence< Reference< XDispatch > > SAL_CALL OInterceptor::queryDispatches( const Sequence<DispatchDescriptor >& Requests ) throw ( RuntimeException ) +{ + Sequence< Reference< XDispatch > > aRet; + osl::MutexGuard aGuard(m_aMutex); + if(m_xSlaveDispatchProvider.is()) + aRet = m_xSlaveDispatchProvider->queryDispatches(Requests); + else + aRet.realloc(Requests.getLength()); + + for(sal_Int32 i = 0; i < Requests.getLength(); ++i) + { + const ::rtl::OUString* pIter = m_aInterceptedURL.getConstArray(); + const ::rtl::OUString* pEnd = pIter + m_aInterceptedURL.getLength(); + for(;pIter != pEnd;++pIter) + { + if ( Requests[i].FeatureURL.Complete == *pIter ) + { + aRet[i] = (XDispatch*) this; + break; + } + } + } + + return aRet; +} + + + +//XDispatchProviderInterceptor + +Reference< XDispatchProvider > SAL_CALL OInterceptor::getSlaveDispatchProvider( ) throw ( RuntimeException ) +{ + osl::MutexGuard aGuard(m_aMutex); + return m_xSlaveDispatchProvider; +} + +void SAL_CALL +OInterceptor::setSlaveDispatchProvider( const Reference< XDispatchProvider >& NewDispatchProvider ) + throw ( RuntimeException ) +{ + osl::MutexGuard aGuard(m_aMutex); + m_xSlaveDispatchProvider = NewDispatchProvider; +} + + +Reference< XDispatchProvider > SAL_CALL OInterceptor::getMasterDispatchProvider( ) + throw ( + RuntimeException + ) +{ + osl::MutexGuard aGuard(m_aMutex); + return m_xMasterDispatchProvider; +} + + +void SAL_CALL OInterceptor::setMasterDispatchProvider( + const Reference< XDispatchProvider >& NewSupplier ) + throw ( + RuntimeException + ) +{ + osl::MutexGuard aGuard(m_aMutex); + m_xMasterDispatchProvider = NewSupplier; +} +// ----------------------------------------------------------------------------- +void SAL_CALL OInterceptor::notifyEvent( const ::com::sun::star::document::EventObject& Event ) throw (::com::sun::star::uno::RuntimeException) +{ + osl::ResettableMutexGuard _rGuard(m_aMutex); + if ( m_pStatCL && Event.EventName == ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("OnModifyChanged")) ) + { + OInterfaceContainerHelper* pListener = m_pStatCL->getContainer(m_aInterceptedURL[DISPATCH_SAVE]); + if ( pListener ) + { + FeatureStateEvent aEvt; + aEvt.FeatureURL.Complete = m_aInterceptedURL[DISPATCH_SAVE]; + aEvt.FeatureDescriptor = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Update")); + Reference<XModifiable> xModel(Event.Source,UNO_QUERY); + aEvt.IsEnabled = xModel.is() && xModel->isModified(); + aEvt.Requery = sal_False; + + NOTIFY_LISTERNERS((*pListener),XStatusListener,statusChanged) + } + } +} +// ----------------------------------------------------------------------------- +void SAL_CALL OInterceptor::disposing( const ::com::sun::star::lang::EventObject& /*Source*/ ) throw (::com::sun::star::uno::RuntimeException) +{ +} + +//........................................................................ +} // namespace dbaccess +//........................................................................ + diff --git a/dbaccess/source/core/dataaccess/intercept.hxx b/dbaccess/source/core/dataaccess/intercept.hxx new file mode 100644 index 000000000000..9c69ee0d59d7 --- /dev/null +++ b/dbaccess/source/core/dataaccess/intercept.hxx @@ -0,0 +1,190 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 DBA_INTERCEPT_HXX +#define DBA_INTERCEPT_HXX + +#ifndef _OSL_MUTEX_HXX_ +#include <osl/mutex.hxx> +#endif +#ifndef _CPPUHELPER_IMPLBASE4_HXX_ +#include <cppuhelper/implbase4.hxx> +#endif +#ifndef _CPPUHELPER_INTERFACECONTAINER_HXX_ +#include <cppuhelper/interfacecontainer.hxx> +#endif +#ifndef _COM_SUN_STAR_FRAME_XDISPATCHPROVIDERINTERCEPTOR_HPP_ +#include <com/sun/star/frame/XDispatchProviderInterceptor.hpp> +#endif +#ifndef _COM_SUN_STAR_FRAME_XINTERCEPTORINFO_HPP_ +#include <com/sun/star/frame/XInterceptorInfo.hpp> +#endif +#ifndef _COM_SUN_STAR_DOCUMENT_XEVENTLISTENER_HPP_ +#include <com/sun/star/document/XEventListener.hpp> +#endif +#ifndef _COM_SUN_STAR_FRAME_XDISPATCH_HPP_ +#include <com/sun/star/frame/XDispatch.hpp> +#endif +#ifndef _DBA_COREDATAACCESS_DOCUMENTDEFINITION_HXX_ +#include "documentdefinition.hxx" +#endif +#include <vcl/svapp.hxx> + +namespace dbaccess +{ + + +class OInterceptor : public ::cppu::WeakImplHelper4< ::com::sun::star::frame::XDispatchProviderInterceptor, + ::com::sun::star::frame::XInterceptorInfo, + ::com::sun::star::frame::XDispatch, + ::com::sun::star::document::XEventListener> +{ + DECL_LINK( OnDispatch, void* _aURL ); +protected: + virtual ~OInterceptor(); +public: + + OInterceptor( ODocumentDefinition* _pContentHolder,sal_Bool _bAllowEditDoc ); + + void SAL_CALL dispose() throw(::com::sun::star::uno::RuntimeException); + + //XDispatch + virtual void SAL_CALL + dispatch( + const ::com::sun::star::util::URL& URL, + const ::com::sun::star::uno::Sequence< + ::com::sun::star::beans::PropertyValue >& Arguments ) + throw (::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + addStatusListener( + const ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XStatusListener >& Control, + const ::com::sun::star::util::URL& URL ) + throw ( + ::com::sun::star::uno::RuntimeException + ); + + virtual void SAL_CALL + removeStatusListener( + const ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XStatusListener >& Control, + const ::com::sun::star::util::URL& URL ) + throw ( + ::com::sun::star::uno::RuntimeException + ); + + //XInterceptorInfo + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > + SAL_CALL getInterceptedURLs( ) + throw ( + ::com::sun::star::uno::RuntimeException + ); + + //XDispatchProvider ( inherited by XDispatchProviderInterceptor ) + virtual ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XDispatch > SAL_CALL + queryDispatch( + const ::com::sun::star::util::URL& URL, + const ::rtl::OUString& TargetFrameName, + sal_Int32 SearchFlags ) + throw ( + ::com::sun::star::uno::RuntimeException + ); + + virtual ::com::sun::star::uno::Sequence< + ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XDispatch > > SAL_CALL + queryDispatches( + const ::com::sun::star::uno::Sequence< + ::com::sun::star::frame::DispatchDescriptor >& Requests ) + throw ( + ::com::sun::star::uno::RuntimeException + ); + + + //XDispatchProviderInterceptor + virtual ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XDispatchProvider > SAL_CALL + getSlaveDispatchProvider( ) + throw ( + ::com::sun::star::uno::RuntimeException + ); + + virtual void SAL_CALL + setSlaveDispatchProvider( + const ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XDispatchProvider >& NewDispatchProvider ) + throw ( + ::com::sun::star::uno::RuntimeException + ); + + virtual ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XDispatchProvider > SAL_CALL + getMasterDispatchProvider( ) + throw ( + ::com::sun::star::uno::RuntimeException + ); + + virtual void SAL_CALL + setMasterDispatchProvider( + const ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XDispatchProvider >& NewSupplier ) + throw ( + ::com::sun::star::uno::RuntimeException + ); + + // XEventListener + virtual void SAL_CALL notifyEvent( const ::com::sun::star::document::EventObject& Event ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException); + + +private: + + osl::Mutex m_aMutex; + + ODocumentDefinition* m_pContentHolder; + + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > m_xSlaveDispatchProvider; + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > m_xMasterDispatchProvider; + + ::com::sun::star::uno::Sequence< ::rtl::OUString > m_aInterceptedURL; + + cppu::OInterfaceContainerHelper* m_pDisposeEventListeners; + PropertyChangeListenerContainer* m_pStatCL; + sal_Bool m_bAllowEditDoc; +}; + + +//........................................................................ +} // namespace dbaccess +//........................................................................ + + +#endif //DBA_INTERCEPT_HXX + + diff --git a/dbaccess/source/core/dataaccess/makefile.mk b/dbaccess/source/core/dataaccess/makefile.mk new file mode 100644 index 000000000000..831eae349858 --- /dev/null +++ b/dbaccess/source/core/dataaccess/makefile.mk @@ -0,0 +1,69 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# 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. +# +#************************************************************************* + +PRJ=..$/..$/.. +PRJINC=$(PRJ)$/source +PRJNAME=dbaccess +TARGET=dataaccess + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ---------------------------------- + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/util$/dba.pmk + +# --- Files ------------------------------------- + +SLOFILES= \ + $(SLO)$/SharedConnection.obj \ + $(SLO)$/ContentHelper.obj \ + $(SLO)$/bookmarkcontainer.obj \ + $(SLO)$/definitioncontainer.obj \ + $(SLO)$/commanddefinition.obj \ + $(SLO)$/documentcontainer.obj \ + $(SLO)$/commandcontainer.obj \ + $(SLO)$/documentdefinition.obj \ + $(SLO)$/ComponentDefinition.obj \ + $(SLO)$/databasecontext.obj \ + $(SLO)$/connection.obj \ + $(SLO)$/datasource.obj \ + $(SLO)$/databaseregistrations.obj \ + $(SLO)$/intercept.obj \ + $(SLO)$/myucp_datasupplier.obj \ + $(SLO)$/myucp_resultset.obj \ + $(SLO)$/databasedocument.obj \ + $(SLO)$/dataaccessdescriptor.obj\ + $(SLO)$/ModelImpl.obj \ + $(SLO)$/documentevents.obj \ + $(SLO)$/documenteventexecutor.obj \ + $(SLO)$/documenteventnotifier.obj \ + +# --- Targets ---------------------------------- + +.INCLUDE : target.mk + diff --git a/dbaccess/source/core/dataaccess/myucp_datasupplier.cxx b/dbaccess/source/core/dataaccess/myucp_datasupplier.cxx new file mode 100644 index 000000000000..725c7c01e17a --- /dev/null +++ b/dbaccess/source/core/dataaccess/myucp_datasupplier.cxx @@ -0,0 +1,430 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ + +#include <vector> + +#ifndef _UCBHELPER_CONTENTIDENTIFIER_HXX +#include <ucbhelper/contentidentifier.hxx> +#endif +#ifndef _UCBHELPER_PROVIDERHELPER_HXX +#include <ucbhelper/providerhelper.hxx> +#endif + +#ifndef DBA_DATASUPPLIER_HXX +#include "myucp_datasupplier.hxx" +#endif +#ifndef DBA_CONTENTHELPER_HXX +#include "ContentHelper.hxx" +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XHIERARCHICALNAMEACCESS_HPP_ +#include <com/sun/star/container/XHierarchicalNameAccess.hpp> +#endif +#ifndef _TOOLS_DEBUG_HXX +#include <tools/debug.hxx> +#endif + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::ucb; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::container; + +// @@@ Adjust namespace name. +using namespace dbaccess; + +// @@@ Adjust namespace name. +namespace dbaccess +{ + +//========================================================================= +// +// struct ResultListEntry. +// +//========================================================================= + +struct ResultListEntry +{ + rtl::OUString aId; + Reference< XContentIdentifier > xId; + ::rtl::Reference< OContentHelper > xContent; + Reference< XRow > xRow; + const ContentProperties& rData; + + ResultListEntry( const ContentProperties& rEntry ) : rData( rEntry ) {} +}; + +//========================================================================= +// +// ResultList. +// +//========================================================================= + +typedef std::vector< ResultListEntry* > ResultList; + +//========================================================================= +// +// struct DataSupplier_Impl. +// +//========================================================================= + +struct DataSupplier_Impl +{ + osl::Mutex m_aMutex; + ResultList m_aResults; + rtl::Reference< ODocumentContainer > m_xContent; + Reference< XMultiServiceFactory > m_xSMgr; + sal_Int32 m_nOpenMode; + sal_Bool m_bCountFinal; + + DataSupplier_Impl( const Reference< XMultiServiceFactory >& rxSMgr, + const rtl::Reference< ODocumentContainer >& rContent, + sal_Int32 nOpenMode ) + : m_xContent(rContent) + , m_xSMgr( rxSMgr ) + , m_nOpenMode( nOpenMode ) + , m_bCountFinal( sal_False ) {} + ~DataSupplier_Impl(); +}; + +//========================================================================= +DataSupplier_Impl::~DataSupplier_Impl() +{ + ResultList::const_iterator it = m_aResults.begin(); + ResultList::const_iterator end = m_aResults.end(); + + while ( it != end ) + { + delete (*it); + it++; + } +} + +} + +//========================================================================= +//========================================================================= +// +// DataSupplier Implementation. +// +//========================================================================= +//========================================================================= +DBG_NAME(DataSupplier) + +DataSupplier::DataSupplier( const Reference< XMultiServiceFactory >& rxSMgr, + const rtl::Reference< ODocumentContainer >& rContent, + sal_Int32 nOpenMode ) +: m_pImpl( new DataSupplier_Impl( rxSMgr, rContent,nOpenMode ) ) +{ + DBG_CTOR(DataSupplier,NULL); + +} + +//========================================================================= +// virtual +DataSupplier::~DataSupplier() +{ + + DBG_DTOR(DataSupplier,NULL); +} + +//========================================================================= +// virtual +rtl::OUString DataSupplier::queryContentIdentifierString( sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( (size_t)nIndex < m_pImpl->m_aResults.size() ) + { + rtl::OUString aId = m_pImpl->m_aResults[ nIndex ]->aId; + if ( aId.getLength() ) + { + // Already cached. + return aId; + } + } + + if ( getResult( nIndex ) ) + { + rtl::OUString aId + = m_pImpl->m_xContent->getIdentifier()->getContentIdentifier(); + + if ( aId.getLength() ) + aId += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/")); + + aId += m_pImpl->m_aResults[ nIndex ]->rData.aTitle; + + m_pImpl->m_aResults[ nIndex ]->aId = aId; + return aId; + } + return rtl::OUString(); +} + +//========================================================================= +// virtual +Reference< XContentIdentifier > +DataSupplier::queryContentIdentifier( sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( (size_t)nIndex < m_pImpl->m_aResults.size() ) + { + Reference< XContentIdentifier > xId = m_pImpl->m_aResults[ nIndex ]->xId; + if ( xId.is() ) + { + // Already cached. + return xId; + } + } + + rtl::OUString aId = queryContentIdentifierString( nIndex ); + if ( aId.getLength() ) + { + Reference< XContentIdentifier > xId = new ::ucbhelper::ContentIdentifier( aId ); + m_pImpl->m_aResults[ nIndex ]->xId = xId; + return xId; + } + return Reference< XContentIdentifier >(); +} + +//========================================================================= +// virtual +Reference< XContent > +DataSupplier::queryContent( sal_uInt32 _nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( (size_t)_nIndex < m_pImpl->m_aResults.size() ) + { + Reference< XContent > xContent = m_pImpl->m_aResults[ _nIndex ]->xContent.get(); + if ( xContent.is() ) + { + // Already cached. + return xContent; + } + } + + Reference< XContentIdentifier > xId = queryContentIdentifier( _nIndex ); + if ( xId.is() ) + { + try + { + Reference< XContent > xContent; + ::rtl::OUString sName = xId->getContentIdentifier(); + sal_Int32 nIndex = sName.lastIndexOf('/') + 1; + sName = sName.getToken(0,'/',nIndex); + + m_pImpl->m_aResults[ _nIndex ]->xContent = m_pImpl->m_xContent->getContent(sName); + + xContent = m_pImpl->m_aResults[ _nIndex ]->xContent.get(); + return xContent; + + } + catch ( IllegalIdentifierException& ) + { + } + } + return Reference< XContent >(); +} + +//========================================================================= +// virtual +sal_Bool DataSupplier::getResult( sal_uInt32 nIndex ) +{ + osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( (size_t)nIndex < m_pImpl->m_aResults.size() ) + { + // Result already present. + return sal_True; + } + + // Result not (yet) present. + + if ( m_pImpl->m_bCountFinal ) + return sal_False; + + // Try to obtain result... + + sal_uInt32 nOldCount = m_pImpl->m_aResults.size(); + sal_Bool bFound = sal_False; + sal_uInt32 nPos = nOldCount; + + // @@@ Obtain data and put it into result list... + Sequence< ::rtl::OUString> aSeq = m_pImpl->m_xContent->getElementNames(); + if ( nIndex < sal::static_int_cast< sal_uInt32 >( aSeq.getLength() ) ) + { + const ::rtl::OUString* pIter = aSeq.getConstArray(); + const ::rtl::OUString* pEnd = pIter + aSeq.getLength(); + for(pIter = pIter + nPos;pIter != pEnd;++pIter,++nPos) + { + m_pImpl->m_aResults.push_back( + new ResultListEntry( m_pImpl->m_xContent->getContent(*pIter)->getContentProperties() ) ); + + if ( nPos == nIndex ) + { + // Result obtained. + bFound = sal_True; + break; + } + } + } + + if ( !bFound ) + m_pImpl->m_bCountFinal = sal_True; + + rtl::Reference< ::ucbhelper::ResultSet > xResultSet = getResultSet().get(); + if ( xResultSet.is() ) + { + // Callbacks follow! + aGuard.clear(); + + if ( (size_t)nOldCount < m_pImpl->m_aResults.size() ) + xResultSet->rowCountChanged( + nOldCount, m_pImpl->m_aResults.size() ); + + if ( m_pImpl->m_bCountFinal ) + xResultSet->rowCountFinal(); + } + + return bFound; +} + +//========================================================================= +// virtual +sal_uInt32 DataSupplier::totalCount() +{ + osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( m_pImpl->m_bCountFinal ) + return m_pImpl->m_aResults.size(); + + sal_uInt32 nOldCount = m_pImpl->m_aResults.size(); + + // @@@ Obtain data and put it into result list... + Sequence< ::rtl::OUString> aSeq = m_pImpl->m_xContent->getElementNames(); + const ::rtl::OUString* pIter = aSeq.getConstArray(); + const ::rtl::OUString* pEnd = pIter + aSeq.getLength(); + for(;pIter != pEnd;++pIter) + m_pImpl->m_aResults.push_back( + new ResultListEntry( m_pImpl->m_xContent->getContent(*pIter)->getContentProperties() ) ); + + m_pImpl->m_bCountFinal = sal_True; + + rtl::Reference< ::ucbhelper::ResultSet > xResultSet = getResultSet().get(); + if ( xResultSet.is() ) + { + // Callbacks follow! + aGuard.clear(); + + if ( (size_t)nOldCount < m_pImpl->m_aResults.size() ) + xResultSet->rowCountChanged( + nOldCount, m_pImpl->m_aResults.size() ); + + xResultSet->rowCountFinal(); + } + + return m_pImpl->m_aResults.size(); +} + +//========================================================================= +// virtual +sal_uInt32 DataSupplier::currentCount() +{ + return m_pImpl->m_aResults.size(); +} + +//========================================================================= +// virtual +sal_Bool DataSupplier::isCountFinal() +{ + return m_pImpl->m_bCountFinal; +} + +//========================================================================= +// virtual +Reference< XRow > +DataSupplier::queryPropertyValues( sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( (size_t)nIndex < m_pImpl->m_aResults.size() ) + { + Reference< XRow > xRow = m_pImpl->m_aResults[ nIndex ]->xRow; + if ( xRow.is() ) + { + // Already cached. + return xRow; + } + } + + if ( getResult( nIndex ) ) + { + if ( !m_pImpl->m_aResults[ nIndex ]->xContent.is() ) + queryContent(nIndex); + + Reference< XRow > xRow = m_pImpl->m_aResults[ nIndex ]->xContent->getPropertyValues(getResultSet()->getProperties()); + m_pImpl->m_aResults[ nIndex ]->xRow = xRow; + return xRow; + } + + return Reference< XRow >(); +} + +//========================================================================= +// virtual +void DataSupplier::releasePropertyValues( sal_uInt32 nIndex ) +{ + osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex ); + + if ( (size_t)nIndex < m_pImpl->m_aResults.size() ) + m_pImpl->m_aResults[ nIndex ]->xRow = Reference< XRow >(); +} + +//========================================================================= +// virtual +void DataSupplier::close() +{ +} + +//========================================================================= +// virtual +void DataSupplier::validate() + throw( ResultSetException ) +{ +} + diff --git a/dbaccess/source/core/dataaccess/myucp_datasupplier.hxx b/dbaccess/source/core/dataaccess/myucp_datasupplier.hxx new file mode 100644 index 000000000000..7b1e5bd814df --- /dev/null +++ b/dbaccess/source/core/dataaccess/myucp_datasupplier.hxx @@ -0,0 +1,83 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 DBA_DATASUPPLIER_HXX +#define DBA_DATASUPPLIER_HXX + +#ifndef _RTL_REF_HXX_ +#include <rtl/ref.hxx> +#endif +#ifndef _UCBHELPER_RESULTSET_HXX +#include <ucbhelper/resultset.hxx> +#endif +#ifndef _DBA_COREDATAACCESS_DOCUMENTCONTAINER_HXX_ +#include "documentcontainer.hxx" +#endif +#include <memory> + +namespace dbaccess { + +struct DataSupplier_Impl; +class OContentHelper; + +class DataSupplier : public ucbhelper::ResultSetDataSupplier +{ + ::std::auto_ptr<DataSupplier_Impl> m_pImpl; + +public: + DataSupplier( const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + const rtl::Reference< ODocumentContainer >& rxContent, + sal_Int32 nOpenMode ); + virtual ~DataSupplier(); + + virtual rtl::OUString queryContentIdentifierString( sal_uInt32 nIndex ); + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XContentIdentifier > + queryContentIdentifier( sal_uInt32 nIndex ); + virtual com::sun::star::uno::Reference< com::sun::star::ucb::XContent > + queryContent( sal_uInt32 nIndex ); + + virtual sal_Bool getResult( sal_uInt32 nIndex ); + + virtual sal_uInt32 totalCount(); + virtual sal_uInt32 currentCount(); + virtual sal_Bool isCountFinal(); + + virtual com::sun::star::uno::Reference< com::sun::star::sdbc::XRow > + queryPropertyValues( sal_uInt32 nIndex ); + virtual void releasePropertyValues( sal_uInt32 nIndex ); + + virtual void close(); + + virtual void validate() + throw( com::sun::star::ucb::ResultSetException ); +}; + +} + +#endif // DBA_DATASUPPLIER_HXX diff --git a/dbaccess/source/core/dataaccess/myucp_resultset.cxx b/dbaccess/source/core/dataaccess/myucp_resultset.cxx new file mode 100644 index 000000000000..0543c7f35326 --- /dev/null +++ b/dbaccess/source/core/dataaccess/myucp_resultset.cxx @@ -0,0 +1,106 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +/************************************************************************** + TODO + ************************************************************************** + + - This implementation is not a dynamic result set!!! It only implements + the necessary interfaces, but never recognizes/notifies changes!!! + + *************************************************************************/ + +#ifndef DBA_DATASUPPLIER_HXX +#include "myucp_datasupplier.hxx" +#endif +#ifndef DBA_UCPRESULTSET_HXX +#include "myucp_resultset.hxx" +#endif + + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::ucb; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::container; + +using namespace dbaccess; + +//========================================================================= +//========================================================================= +// +// DynamicResultSet Implementation. +// +//========================================================================= +//========================================================================= + +DynamicResultSet::DynamicResultSet( + const Reference< XMultiServiceFactory >& rxSMgr, + const rtl::Reference< ODocumentContainer >& rxContent, + const OpenCommandArgument2& rCommand, + const Reference< XCommandEnvironment >& rxEnv ) + :ResultSetImplHelper( rxSMgr, rCommand ) + ,m_xContent(rxContent) + ,m_xEnv( rxEnv ) +{ +} + +//========================================================================= +// +// Non-interface methods. +// +//========================================================================= + +void DynamicResultSet::initStatic() +{ + m_xResultSet1 + = new ::ucbhelper::ResultSet( m_xSMgr, + m_aCommand.Properties, + new DataSupplier( m_xSMgr, + m_xContent, + m_aCommand.Mode ), + m_xEnv ); +} + +//========================================================================= +void DynamicResultSet::initDynamic() +{ + m_xResultSet1 + = new ::ucbhelper::ResultSet( m_xSMgr, + m_aCommand.Properties, + new DataSupplier( m_xSMgr, + m_xContent, + m_aCommand.Mode ), + m_xEnv ); + m_xResultSet2 = m_xResultSet1; +} + diff --git a/dbaccess/source/core/dataaccess/myucp_resultset.hxx b/dbaccess/source/core/dataaccess/myucp_resultset.hxx new file mode 100644 index 000000000000..a81658587003 --- /dev/null +++ b/dbaccess/source/core/dataaccess/myucp_resultset.hxx @@ -0,0 +1,67 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 DBA_UCPRESULTSET_HXX +#define DBA_UCPRESULTSET_HXX + +#ifndef _RTL_REF_HXX_ +#include <rtl/ref.hxx> +#endif +#ifndef _UCBHELPER_RESULTSETHELPER_HXX +#include <ucbhelper/resultsethelper.hxx> +#endif +#ifndef _DBA_COREDATAACCESS_DOCUMENTCONTAINER_HXX_ +#include "documentcontainer.hxx" +#endif + + +// @@@ Adjust namespace name. +namespace dbaccess { + +class DynamicResultSet : public ::ucbhelper::ResultSetImplHelper +{ + rtl::Reference< ODocumentContainer > m_xContent; + com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > m_xEnv; + +private: + virtual void initStatic(); + virtual void initDynamic(); + +public: + DynamicResultSet( + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + const rtl::Reference< ODocumentContainer >& rxContent, + const com::sun::star::ucb::OpenCommandArgument2& rCommand, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& rxEnv ); +}; + +} + +#endif // DBA_UCPRESULTSET_HXX diff --git a/dbaccess/source/core/inc/ContainerListener.hxx b/dbaccess/source/core/inc/ContainerListener.hxx new file mode 100644 index 000000000000..2a6b976504e5 --- /dev/null +++ b/dbaccess/source/core/inc/ContainerListener.hxx @@ -0,0 +1,97 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 DBA_CONTAINERLISTENER_HXX +#define DBA_CONTAINERLISTENER_HXX + +#ifndef _CPPUHELPER_IMPLBASE2_HXX_ +#include <cppuhelper/implbase2.hxx> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XCONTAINERLISTENER_HPP_ +#include <com/sun/star/container/XContainerListener.hpp> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XCONTAINERAPPROVELISTENER_HPP_ +#include <com/sun/star/container/XContainerApproveListener.hpp> +#endif + +#ifndef _CPPUHELPER_WEAK_HXX_ +#include <cppuhelper/weak.hxx> +#endif + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + + //========================================================================== + //= OContainerListener + //========================================================================== + typedef ::cppu::WeakImplHelper2 < ::com::sun::star::container::XContainerListener + , ::com::sun::star::container::XContainerApproveListener + > OContainerListener_BASE; + + /** is helper class to avoid a cycle in refcount + */ + class OContainerListener : public OContainerListener_BASE + { + ::osl::Mutex& m_rMutex; + OWeakObject& m_rDestination; + bool m_bDisposed; + + public: + OContainerListener( OWeakObject& _rDestination, ::osl::Mutex& _rMutex ) + :m_rMutex( _rMutex ) + ,m_rDestination( _rDestination ) + ,m_bDisposed( false ) + { + } + + // XContainerApproveListener + virtual ::com::sun::star::uno::Reference< ::com::sun::star::util::XVeto > SAL_CALL approveInsertElement( const ::com::sun::star::container::ContainerEvent& Event ) throw (::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::util::XVeto > SAL_CALL approveReplaceElement( const ::com::sun::star::container::ContainerEvent& Event ) throw (::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::util::XVeto > SAL_CALL approveRemoveElement( const ::com::sun::star::container::ContainerEvent& Event ) throw (::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + + // XContainerListener + virtual void SAL_CALL elementInserted( const ::com::sun::star::container::ContainerEvent& Event ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL elementRemoved( const ::com::sun::star::container::ContainerEvent& Event ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL elementReplaced( const ::com::sun::star::container::ContainerEvent& Event ) 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); + + void SAL_CALL dispose() + { + m_bDisposed = true; + } + + protected: + virtual ~OContainerListener(); + }; +//........................................................................ +} // namespace dbaccess +//........................................................................ +#endif // DBA_CONTAINERLISTENER_HXX + diff --git a/dbaccess/source/core/inc/ContainerMediator.hxx b/dbaccess/source/core/inc/ContainerMediator.hxx new file mode 100644 index 000000000000..f35a0bfca58b --- /dev/null +++ b/dbaccess/source/core/inc/ContainerMediator.hxx @@ -0,0 +1,123 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 DBA_CONTAINERMEDIATOR_HXX +#define DBA_CONTAINERMEDIATOR_HXX + +#ifndef _COM_SUN_STAR_CONTAINER_XCONTAINERLISTENER_HPP_ +#include <com/sun/star/container/XContainerListener.hpp> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XCONTAINER_HPP_ +#include <com/sun/star/container/XContainer.hpp> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XNAMECONTAINER_HPP_ +#include <com/sun/star/container/XNameContainer.hpp> +#endif +#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 _COMPHELPER_BROADCASTHELPER_HXX_ +#include <comphelper/broadcasthelper.hxx> +#endif +#ifndef _COMPHELPER_BROADCASTHELPER_HXX_ +#include <comphelper/broadcasthelper.hxx> +#endif +#ifndef _CPPUHELPER_IMPLBASE1_HXX_ +#include <cppuhelper/implbase1.hxx> +#endif +#ifndef _RTL_REF_HXX_ +#include <rtl/ref.hxx> +#endif + +#include <map> + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + + class OPropertyForward; + + class OContainerMediator : public ::comphelper::OBaseMutex + ,public ::cppu::WeakImplHelper1< ::com::sun::star::container::XContainerListener > + { + public: + enum ContainerType + { + eColumns, + eTables + }; + + private: + typedef ::rtl::Reference< OPropertyForward > TPropertyForward; + typedef ::std::map< ::rtl::OUString, TPropertyForward > PropertyForwardList; + PropertyForwardList m_aForwardList; + ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > m_xSettings; // can not be weak + ::com::sun::star::uno::Reference< ::com::sun::star::container::XContainer > m_xContainer; // can not be weak + ::com::sun::star::uno::WeakReference< ::com::sun::star::sdbc::XConnection > m_aConnection; + ContainerType m_eType; + + protected: + virtual ~OContainerMediator(); + + public: + OContainerMediator( + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XContainer >& _xContainer, + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& _xSettings, + const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _rxConnection, + ContainerType _eType + ); + + virtual void SAL_CALL elementInserted( const ::com::sun::star::container::ContainerEvent& _rEvent ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL elementRemoved( const ::com::sun::star::container::ContainerEvent& _rEvent ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL elementReplaced( const ::com::sun::star::container::ContainerEvent& _rEvent ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw(::com::sun::star::uno::RuntimeException); + + void notifyElementCreated(const ::rtl::OUString& _sElementName + ,const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet>& _xElement); + + private: + /** cleans up the instance, by deregistering as listener at the containers, + and resetting them to <NULL/> + */ + void impl_cleanup_nothrow(); + + /** initializes the properties of the given object from its counterpart in our settings container + */ + void impl_initSettings_nothrow( + const ::rtl::OUString& _rName, + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxDestination + ); + }; +//........................................................................ +} // namespace dbaccess +//........................................................................ + +#endif // DBA_CONTAINERMEDIATOR_HXX diff --git a/dbaccess/source/core/inc/ContentHelper.hxx b/dbaccess/source/core/inc/ContentHelper.hxx new file mode 100644 index 000000000000..10c5df0cd5f3 --- /dev/null +++ b/dbaccess/source/core/inc/ContentHelper.hxx @@ -0,0 +1,249 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 DBA_CONTENTHELPER_HXX +#define DBA_CONTENTHELPER_HXX + +#ifndef _COM_SUN_STAR_UCB_XCONTENT_HPP_ +#include <com/sun/star/ucb/XContent.hpp> +#endif +#ifndef _COM_SUN_STAR_UCB_XCOMMANDPROCESSOR_HPP_ +#include <com/sun/star/ucb/XCommandProcessor.hpp> +#endif +#ifndef _COM_SUN_STAR_BEANS_XPROPERTIESCHANGENOTIFIER_HPP_ +#include <com/sun/star/beans/XPropertiesChangeNotifier.hpp> +#endif +#ifndef _COM_SUN_STAR_BEANS_XPROPERTYCONTAINER_HPP_ +#include <com/sun/star/beans/XPropertyContainer.hpp> +#endif +#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_ +#include <com/sun/star/lang/XServiceInfo.hpp> +#endif +#ifndef _COM_SUN_STAR_LANG_XSINGLESERVICEFACTORY_HPP_ +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#endif +#ifndef _COM_SUN_STAR_LANG_XINITIALIZATION_HPP_ +#include <com/sun/star/lang/XInitialization.hpp> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_ +#include <com/sun/star/container/XNameAccess.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XROW_HPP_ +#include <com/sun/star/sdbc/XRow.hpp> +#endif +#ifndef _COM_SUN_STAR_EMBED_XSTORAGE_HPP_ +#include <com/sun/star/embed/XStorage.hpp> +#endif +#ifndef _COM_SUN_STAR_EMBED_XEMBEDDEDOBJECT_HPP_ +#include <com/sun/star/embed/XEmbeddedObject.hpp> +#endif +#ifndef _COM_SUN_STAR_LANG_XUNOTUNNEL_HPP_ +#include <com/sun/star/lang/XUnoTunnel.hpp> +#endif +#ifndef _CPPUHELPER_COMPBASE9_HXX_ +#include <cppuhelper/compbase9.hxx> +#endif +#ifndef _COMPHELPER_BROADCASTHELPER_HXX_ +#include <comphelper/broadcasthelper.hxx> +#endif +#ifndef COMPHELPER_COMPONENTCONTEXT_HXX +#include <comphelper/componentcontext.hxx> +#endif +#ifndef _COMPHELPER_UNO3_HXX_ +#include <comphelper/uno3.hxx> +#endif +#ifndef _COMPHELPER_STLTYPES_HXX_ +#include <comphelper/stl_types.hxx> +#endif +#ifndef _COM_SUN_STAR_BEANS_PROPERTY_HPP_ +#include <com/sun/star/beans/Property.hpp> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XCHILD_HPP_ +#include <com/sun/star/container/XChild.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBCX_XRENAME_HPP_ +#include <com/sun/star/sdbcx/XRename.hpp> +#endif +#ifndef CONNECTIVITY_SQLERROR_HXX +#include <connectivity/sqlerror.hxx> +#endif +#ifndef BOOST_SHARED_PTR_HPP_INCLUDED +#include <boost/shared_ptr.hpp> +#endif + +namespace dbaccess +{ + class ODatabaseModelImpl; + struct ContentProperties + { + ::rtl::OUString aTitle; // Title + ::boost::optional< ::rtl::OUString > + aContentType; // ContentType (aka MediaType aka MimeType) + sal_Bool bIsDocument; // IsDocument + sal_Bool bIsFolder; // IsFolder + sal_Bool bAsTemplate; // AsTemplate + ::rtl::OUString sPersistentName;// persistent name of the document + + ContentProperties() + :bIsDocument( sal_True ) + ,bIsFolder( sal_False ) + ,bAsTemplate( sal_False ) + { + } + }; + + class OContentHelper_Impl + { + public: + OContentHelper_Impl(); + virtual ~OContentHelper_Impl(); + + ContentProperties m_aProps; + ODatabaseModelImpl* m_pDataSource; // this will stay alive as long as the content exists + }; + + typedef ::boost::shared_ptr<OContentHelper_Impl> TContentPtr; + + + typedef ::cppu::OMultiTypeInterfaceContainerHelperVar< ::rtl::OUString, + ::comphelper::UStringHash, + ::comphelper::UStringEqual + > PropertyChangeListenerContainer; + typedef ::comphelper::OBaseMutex OContentHelper_MBASE; + typedef ::cppu::WeakComponentImplHelper9 < ::com::sun::star::ucb::XContent + , ::com::sun::star::ucb::XCommandProcessor + , ::com::sun::star::lang::XServiceInfo + , ::com::sun::star::beans::XPropertiesChangeNotifier + , ::com::sun::star::beans::XPropertyContainer + , ::com::sun::star::lang::XInitialization + , ::com::sun::star::lang::XUnoTunnel + , ::com::sun::star::container::XChild + , ::com::sun::star::sdbcx::XRename + > OContentHelper_COMPBASE; + + class OContentHelper : public OContentHelper_MBASE + ,public OContentHelper_COMPBASE + { + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > + setPropertyValues( const ::com::sun::star::uno::Sequence< + ::com::sun::star::beans::PropertyValue >& rValues, + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment >& xEnv ); + com::sun::star::uno::Sequence< com::sun::star::beans::Property > + getProperties( const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ); + + void impl_rename_throw(const ::rtl::OUString& _sNewName,bool _bNotify = true); + + protected: + ::cppu::OInterfaceContainerHelper m_aContentListeners; + PropertyChangeListenerContainer m_aPropertyChangeListeners; + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > + m_xParentContainer; + const ::comphelper::ComponentContext m_aContext; + const ::connectivity::SQLError m_aErrorHelper; + TContentPtr m_pImpl; + sal_uInt32 m_nCommandId; + + // helper + virtual void SAL_CALL disposing(); + + virtual void notifyDataSourceModified(); + + /** + * This method can be used to propagate changes of property values. + * + * @param evt is a sequence of property change events. + */ + void notifyPropertiesChange( const com::sun::star::uno::Sequence< com::sun::star::beans::PropertyChangeEvent >& evt ) const; + + ::rtl::OUString impl_getHierarchicalName( bool _includingRootContainer ) const; + + public: + + OContentHelper( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _xORB + ,const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _xParentContainer + ,const TContentPtr& _pImpl + ); + + // com::sun::star::lang::XTypeProvider + virtual ::com::sun::star::uno::Sequence<sal_Int8> SAL_CALL getImplementationId( ) throw(::com::sun::star::uno::RuntimeException); + static ::com::sun::star::uno::Sequence< sal_Int8 > getUnoTunnelImplementationId(); + // ::com::sun::star::lang::XServiceInfo + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw(::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw (::com::sun::star::uno::RuntimeException); + + // XContent + virtual ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContentIdentifier > SAL_CALL getIdentifier( ) throw (::com::sun::star::uno::RuntimeException) ; + virtual ::rtl::OUString SAL_CALL getContentType( ) throw (::com::sun::star::uno::RuntimeException) ; + virtual void SAL_CALL addContentEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContentEventListener >& Listener ) throw (::com::sun::star::uno::RuntimeException) ; + virtual void SAL_CALL removeContentEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContentEventListener >& Listener ) throw (::com::sun::star::uno::RuntimeException) ; + + // XCommandProcessor + virtual sal_Int32 SAL_CALL createCommandIdentifier( ) throw (::com::sun::star::uno::RuntimeException) ; + virtual ::com::sun::star::uno::Any SAL_CALL execute( const ::com::sun::star::ucb::Command& aCommand, sal_Int32 CommandId, const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >& Environment ) throw (::com::sun::star::uno::Exception, ::com::sun::star::ucb::CommandAbortedException, ::com::sun::star::uno::RuntimeException) ; + virtual void SAL_CALL abort( sal_Int32 CommandId ) throw (::com::sun::star::uno::RuntimeException) ; + + // XPropertiesChangeNotifier + virtual void SAL_CALL addPropertiesChangeListener( const ::com::sun::star::uno::Sequence< ::rtl::OUString >& PropertyNames, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertiesChangeListener >& Listener ) throw (::com::sun::star::uno::RuntimeException) ; + virtual void SAL_CALL removePropertiesChangeListener( const ::com::sun::star::uno::Sequence< ::rtl::OUString >& PropertyNames, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertiesChangeListener >& Listener ) throw (::com::sun::star::uno::RuntimeException) ; + + // XPropertyContainer + virtual void SAL_CALL addProperty( const ::rtl::OUString& Name, sal_Int16 Attributes, const ::com::sun::star::uno::Any& DefaultValue ) throw (::com::sun::star::beans::PropertyExistException, ::com::sun::star::beans::IllegalTypeException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) ; + virtual void SAL_CALL removeProperty( const ::rtl::OUString& Name ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::NotRemoveableException, ::com::sun::star::uno::RuntimeException) ; + + // XInitialization + virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + + // com::sun::star::lang::XUnoTunnel + virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& aIdentifier ) throw(::com::sun::star::uno::RuntimeException); + static OContentHelper* getImplementation( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxComponent ); + + // ::com::sun::star::container::XChild + virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL getParent( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setParent( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& Parent ) throw (::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException); + + // XRename + virtual void SAL_CALL rename( const ::rtl::OUString& newName ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::container::ElementExistException, ::com::sun::star::uno::RuntimeException); + + inline const ContentProperties& getContentProperties() const { return m_pImpl->m_aProps; } + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRow > + getPropertyValues( const ::com::sun::star::uno::Sequence< + ::com::sun::star::beans::Property >& rProperties ); + + const ::comphelper::ComponentContext& getContext() const { return m_aContext; } + + inline TContentPtr getImpl() const { return m_pImpl; } + + protected: + virtual ::rtl::OUString determineContentType() const = 0; + }; + +//........................................................................ +} // namespace dbaccess +//........................................................................ +#endif // DBA_CONTENTHELPER_HXX diff --git a/dbaccess/source/core/inc/DatabaseDataProvider.hxx b/dbaccess/source/core/inc/DatabaseDataProvider.hxx new file mode 100644 index 000000000000..e75c980e2a93 --- /dev/null +++ b/dbaccess/source/core/inc/DatabaseDataProvider.hxx @@ -0,0 +1,278 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 DBA_DATABASEDATAPROVIDER_HXX_INCLUDED +#define DBA_DATABASEDATAPROVIDER_HXX_INCLUDED + +#include "sal/config.h" + +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/chart2/data/XDatabaseDataProvider.hpp" +#include "com/sun/star/chart2/XInternalDataProvider.hpp" +#include <com/sun/star/chart/XComplexDescriptionAccess.hpp> +#include <com/sun/star/sdbc/XRowSet.hpp> +#include <com/sun/star/sdbc/XParameters.hpp> +#include <com/sun/star/container/XChild.hpp> + +#include "cppuhelper/compbase4.hxx" +#include "cppuhelper/basemutex.hxx" +#include "cppuhelper/propertysetmixin.hxx" +#include <cppuhelper/implementationentry.hxx> + +#include <comphelper/sequence.hxx> + +#include "connectivity/parameters.hxx" +#include "connectivity/filtermanager.hxx" + + +namespace dbaccess +{ + +class DatabaseDataSource; +typedef ::cppu::WeakComponentImplHelper4< ::com::sun::star::chart2::data::XDatabaseDataProvider + , ::com::sun::star::container::XChild + , ::com::sun::star::chart::XComplexDescriptionAccess + , ::com::sun::star::lang::XServiceInfo > TDatabaseDataProvider; + +class DatabaseDataProvider: private ::cppu::BaseMutex, + public TDatabaseDataProvider, + public ::cppu::PropertySetMixin< ::com::sun::star::chart2::data::XDatabaseDataProvider > +{ +public: + explicit DatabaseDataProvider(::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > const & context); + + // ::com::sun::star::lang::XServiceInfo - static methods + static ::com::sun::star::uno::Sequence< ::rtl::OUString > getSupportedServiceNames_Static(void) throw( ::com::sun::star::uno::RuntimeException ); + static ::rtl::OUString getImplementationName_Static(void) throw( ::com::sun::star::uno::RuntimeException ); + static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > + SAL_CALL Create(::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > const & context); + +private: + // ::com::sun::star::uno::XInterface: + virtual ::com::sun::star::uno::Any SAL_CALL queryInterface(::com::sun::star::uno::Type const & type) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL acquire() throw () + { TDatabaseDataProvider::acquire(); } + virtual void SAL_CALL release() throw () + { TDatabaseDataProvider::release(); } + + // ::com::sun::star::lang::XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw(::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::chart2::data::XDataProvider: + virtual ::sal_Bool SAL_CALL createDataSourcePossible(const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > & aArguments) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XDataSource > SAL_CALL createDataSource(const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > & aArguments) throw (::com::sun::star::uno::RuntimeException, ::com::sun::star::lang::IllegalArgumentException); + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > SAL_CALL detectArguments(const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XDataSource > & xDataSource) throw (::com::sun::star::uno::RuntimeException); + virtual ::sal_Bool SAL_CALL createDataSequenceByRangeRepresentationPossible(const ::rtl::OUString & aRangeRepresentation) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XDataSequence > SAL_CALL createDataSequenceByRangeRepresentation(const ::rtl::OUString & aRangeRepresentation) throw (::com::sun::star::uno::RuntimeException, ::com::sun::star::lang::IllegalArgumentException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XRangeSelection > SAL_CALL getRangeSelection() throw (::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::chart2::data::XRangeXMLConversion: + virtual ::rtl::OUString SAL_CALL convertRangeToXML(const ::rtl::OUString & aRangeRepresentation) throw (::com::sun::star::uno::RuntimeException, ::com::sun::star::lang::IllegalArgumentException); + virtual ::rtl::OUString SAL_CALL convertRangeFromXML(const ::rtl::OUString & aXMLRange) throw (::com::sun::star::uno::RuntimeException, ::com::sun::star::lang::IllegalArgumentException); + + // ::com::sun::star::lang::XInitialization: + virtual void SAL_CALL initialize(const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > & aArguments) throw (::com::sun::star::uno::RuntimeException, ::com::sun::star::uno::Exception); + + // ::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); + virtual void SAL_CALL setPropertyValue(const ::rtl::OUString & aPropertyName, const ::com::sun::star::uno::Any & aValue) throw (::com::sun::star::uno::RuntimeException, ::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException); + virtual ::com::sun::star::uno::Any SAL_CALL getPropertyValue(const ::rtl::OUString & PropertyName) throw (::com::sun::star::uno::RuntimeException, ::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException); + virtual void SAL_CALL addPropertyChangeListener(const ::rtl::OUString & aPropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener > & xListener) throw (::com::sun::star::uno::RuntimeException, ::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException); + virtual void SAL_CALL removePropertyChangeListener(const ::rtl::OUString & aPropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener > & aListener) throw (::com::sun::star::uno::RuntimeException, ::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException); + virtual void SAL_CALL addVetoableChangeListener(const ::rtl::OUString & PropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XVetoableChangeListener > & aListener) throw (::com::sun::star::uno::RuntimeException, ::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException); + virtual void SAL_CALL removeVetoableChangeListener(const ::rtl::OUString & PropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XVetoableChangeListener > & aListener) throw (::com::sun::star::uno::RuntimeException, ::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException); + + // ::com::sun::star::chart2::data::XDatabaseDataProvider: + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getMasterFields() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setMasterFields(const ::com::sun::star::uno::Sequence< ::rtl::OUString > & the_value) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getDetailFields() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setDetailFields(const ::com::sun::star::uno::Sequence< ::rtl::OUString > & the_value) throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getCommand() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setCommand(const ::rtl::OUString & the_value) throw (::com::sun::star::uno::RuntimeException); + virtual ::sal_Int32 SAL_CALL getCommandType() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setCommandType(::sal_Int32 the_value) throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getFilter() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setFilter(const ::rtl::OUString & the_value) throw (::com::sun::star::uno::RuntimeException); + virtual ::sal_Bool SAL_CALL getApplyFilter() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setApplyFilter( ::sal_Bool _applyfilter ) throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getHavingClause() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setHavingClause( const ::rtl::OUString& _havingclause ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getGroupBy() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setGroupBy( const ::rtl::OUString& _groupby ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getOrder() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setOrder( const ::rtl::OUString& _order ) throw (::com::sun::star::uno::RuntimeException); + virtual ::sal_Bool SAL_CALL getEscapeProcessing() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setEscapeProcessing(::sal_Bool the_value) throw (::com::sun::star::uno::RuntimeException); + virtual ::sal_Int32 SAL_CALL getRowLimit() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setRowLimit( ::sal_Int32 _rowlimit ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection > SAL_CALL getActiveConnection() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setActiveConnection(const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection > & the_value) throw (::com::sun::star::uno::RuntimeException, ::com::sun::star::lang::IllegalArgumentException); + virtual ::rtl::OUString SAL_CALL getDataSourceName() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setDataSourceName( const ::rtl::OUString& _datasourcename ) throw (::com::sun::star::uno::RuntimeException); + + // com::sun::star::sdbc::XParameters + virtual void SAL_CALL setNull(sal_Int32 parameterIndex, sal_Int32 sqlType) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setObjectNull(sal_Int32 parameterIndex, sal_Int32 sqlType, const ::rtl::OUString& typeName) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setBoolean(sal_Int32 parameterIndex, sal_Bool x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setByte(sal_Int32 parameterIndex, sal_Int8 x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setShort(sal_Int32 parameterIndex, sal_Int16 x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setInt(sal_Int32 parameterIndex, sal_Int32 x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setLong(sal_Int32 parameterIndex, sal_Int64 x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setFloat(sal_Int32 parameterIndex, float x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setDouble(sal_Int32 parameterIndex, double x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setString(sal_Int32 parameterIndex, const ::rtl::OUString& x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setBytes(sal_Int32 parameterIndex, const ::com::sun::star::uno::Sequence< sal_Int8 >& x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setDate(sal_Int32 parameterIndex, const ::com::sun::star::util::Date& x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setTime(sal_Int32 parameterIndex, const ::com::sun::star::util::Time& x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setTimestamp(sal_Int32 parameterIndex, const ::com::sun::star::util::DateTime& x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setBinaryStream(sal_Int32 parameterIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream>& x, sal_Int32 length) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setCharacterStream(sal_Int32 parameterIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream>& x, sal_Int32 length) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setObject(sal_Int32 parameterIndex, const ::com::sun::star::uno::Any& x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setObjectWithInfo(sal_Int32 parameterIndex, const ::com::sun::star::uno::Any& x, sal_Int32 targetSqlType, sal_Int32 scale) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setRef(sal_Int32 parameterIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRef>& x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setBlob(sal_Int32 parameterIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XBlob>& x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setClob(sal_Int32 parameterIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XClob>& x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setArray(sal_Int32 parameterIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XArray>& x) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL clearParameters() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // com::sun::star::sdbc::XRowSet + virtual void SAL_CALL execute() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addRowSetListener(const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowSetListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeRowSetListener(const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowSetListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException); + + // com::sun::star::sdbc::XResultSet + virtual sal_Bool SAL_CALL next() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isBeforeFirst() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isAfterLast() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isFirst() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isLast() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL beforeFirst() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL afterLast() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL first() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL last() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getRow() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL absolute(sal_Int32 row) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL relative(sal_Int32 rows) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL previous() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL refreshRow() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL rowUpdated() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL rowInserted() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL rowDeleted() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL getStatement() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // conatiner::XChild + virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL getParent( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setParent( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& Parent ) throw (::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException); + + // ____ XComplexDescriptionAccess ____ + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::rtl::OUString > > SAL_CALL getComplexRowDescriptions() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setComplexRowDescriptions( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::rtl::OUString > >& aRowDescriptions ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::rtl::OUString > > SAL_CALL getComplexColumnDescriptions() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setComplexColumnDescriptions( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::rtl::OUString > >& aColumnDescriptions ) throw (::com::sun::star::uno::RuntimeException); + + // ____ XChartDataArray (base of XComplexDescriptionAccess) ____ + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< double > > SAL_CALL getData() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setData( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< double > >& aData ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getRowDescriptions() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setRowDescriptions( const ::com::sun::star::uno::Sequence< ::rtl::OUString >& aRowDescriptions ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getColumnDescriptions() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setColumnDescriptions( const ::com::sun::star::uno::Sequence< ::rtl::OUString >& aColumnDescriptions ) throw (::com::sun::star::uno::RuntimeException); + + // ____ XChartData (base of XChartDataArray) ____ + virtual void SAL_CALL addChartDataChangeEventListener(const ::com::sun::star::uno::Reference< ::com::sun::star::chart::XChartDataChangeEventListener >& aListener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeChartDataChangeEventListener(const ::com::sun::star::uno::Reference< ::com::sun::star::chart::XChartDataChangeEventListener >& aListener )throw (::com::sun::star::uno::RuntimeException); + virtual double SAL_CALL getNotANumber()throw (::com::sun::star::uno::RuntimeException); + virtual ::sal_Bool SAL_CALL isNotANumber(double nNumber )throw (::com::sun::star::uno::RuntimeException); +private: + DatabaseDataProvider(DatabaseDataProvider &); // not defined + void operator =(DatabaseDataProvider &); // not defined + + virtual ~DatabaseDataProvider() {} + + // This function is called upon disposing the component, + // if your component needs special work when it becomes + // disposed, do it here. + virtual void SAL_CALL disposing(); + + void impl_fillRowSet_throw(); + void impl_executeRowSet_throw(::osl::ResettableMutexGuard& _rClearForNotifies); + bool impl_fillParameters_nothrow( ::osl::ResettableMutexGuard& _rClearForNotifies); + void impl_fillInternalDataProvider_throw(sal_Bool _bHasCategories,const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::rtl::OUString > >& i_aColumnNames); + void impl_invalidateParameter_nothrow(); + ::com::sun::star::uno::Any impl_getNumberFormatKey_nothrow(const ::rtl::OUString & _sRangeRepresentation) const; + + template <typename T> void set( const ::rtl::OUString& _sProperty + ,const T& _Value + ,T& _member) + { + BoundListeners l; + { + ::osl::MutexGuard aGuard(m_aMutex); + if ( _member != _Value ) + { + prepareSet(_sProperty, ::com::sun::star::uno::makeAny(_member), ::com::sun::star::uno::makeAny(_Value), &l); + _member = _Value; + } + } + l.notify(); + } + + ::dbtools::ParameterManager m_aParameterManager; + ::dbtools::FilterManager m_aFilterManager; + ::std::map< ::rtl::OUString, ::com::sun::star::uno::Any> m_aNumberFormats; + + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > m_xContext; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection > m_xActiveConnection; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowSet > m_xRowSet; + ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XInternalDataProvider > m_xInternal; + ::com::sun::star::uno::Reference< ::com::sun::star::chart::XComplexDescriptionAccess > m_xComplexDescriptionAccess; + ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XRangeXMLConversion> m_xRangeConversion; + ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler> m_xHandler; + // the object doin' most of the work - an SDB-rowset + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XAggregation> m_xAggregate; + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet> m_xAggregateSet; + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface> m_xParent; + ::com::sun::star::uno::Sequence< ::rtl::OUString > m_MasterFields; + ::com::sun::star::uno::Sequence< ::rtl::OUString > m_DetailFields; + + ::rtl::OUString m_Command; + ::rtl::OUString m_DataSourceName; + ::sal_Int32 m_CommandType; + sal_Int32 m_RowLimit; + ::rtl::OUString m_Filter; + ::rtl::OUString m_HavingClause; + ::rtl::OUString m_Order; + ::rtl::OUString m_GroupBy; + ::sal_Bool m_EscapeProcessing; + ::sal_Bool m_ApplyFilter; +}; + +} // namespace dbaccess + +#endif // DBA_DATABASEDATAPROVIDER_HXX_INCLUDED diff --git a/dbaccess/source/core/inc/FilteredContainer.hxx b/dbaccess/source/core/inc/FilteredContainer.hxx new file mode 100644 index 000000000000..f02c3da87d19 --- /dev/null +++ b/dbaccess/source/core/inc/FilteredContainer.hxx @@ -0,0 +1,144 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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_CORE_FILTERED_CONTAINER_HXX +#define DBACCESS_CORE_FILTERED_CONTAINER_HXX + +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/sdbc/XConnection.hpp> + +#include <connectivity/sdbcx/VCollection.hxx> + +namespace dbtools +{ + class IWarningsContainer; +} + +namespace dbaccess +{ + class IRefreshListener; + + class OFilteredContainer : public ::connectivity::sdbcx::OCollection + { + private: + mutable sal_Bool m_bConstructed; // late ctor called + + protected: + ::dbtools::IWarningsContainer* m_pWarningsContainer; + IRefreshListener* m_pRefreshListener; + oslInterlockedCount& m_nInAppend; + + // holds the original container which where set in construct but they can be null + ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > m_xMasterContainer; + ::com::sun::star::uno::WeakReference< ::com::sun::star::sdbc::XConnection > m_xConnection; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XDatabaseMetaData > m_xMetaData; + + /** returns a string denoting the only type of tables allowed in this container, or an empty string + if there is no such restriction + */ + virtual ::rtl::OUString getTableTypeRestriction() const = 0; + + inline virtual void addMasterContainerListener(){} + inline virtual void removeMasterContainerListener(){} + + // ::connectivity::sdbcx::OCollection + virtual void impl_refresh() throw(::com::sun::star::uno::RuntimeException); + + virtual ::rtl::OUString getNameForObject(const ::connectivity::sdbcx::ObjectType& _xObject); + + /** tell the container to free all elements and all additional resources.<BR> + After using this method the object may be reconstructed by calling one of the <code>constrcuct</code> methods. + */ + virtual void SAL_CALL disposing(); + + class EnsureReset + { + public: + EnsureReset( oslInterlockedCount& _rValueLocation) + :m_rValue( _rValueLocation ) + { + osl_incrementInterlockedCount(&m_rValue); + } + + ~EnsureReset() + { + osl_decrementInterlockedCount(&m_rValue); + } + + private: + oslInterlockedCount& m_rValue; + }; + + /** retrieve a table type filter to pass to <member scope="com::sun::star::sdbc">XDatabaseMetaData::getTables</member>, + according to the current data source settings + */ + void getAllTableTypeFilter( ::com::sun::star::uno::Sequence< ::rtl::OUString >& /* [out] */ _rFilter ) const; + + public: + /** ctor of the container. The parent has to support the <type scope="com::sun::star::sdbc">XConnection</type> + interface.<BR> + @param _rParent the object which acts as parent for the container. + all refcounting is rerouted to this object + @param _rMutex the access safety object of the parent + @param _rTableFilter restricts the visible tables by name + @param _rTableTypeFilter restricts the visible tables by type + @see construct + */ + OFilteredContainer( ::cppu::OWeakObject& _rParent, + ::osl::Mutex& _rMutex, + const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _xCon, + sal_Bool _bCase, + IRefreshListener* _pRefreshListener, + ::dbtools::IWarningsContainer* _pWarningsContainer, + oslInterlockedCount& _nInAppend + ); + + inline void dispose() { disposing(); } + + /** late ctor. The container will fill itself with the data got by the connection meta data, considering the + filters given (the connection is the parent object you passed in the ctor). + */ + void construct( + const ::com::sun::star::uno::Sequence< ::rtl::OUString >& _rTableFilter, + const ::com::sun::star::uno::Sequence< ::rtl::OUString >& _rTableTypeFilter + ); + + /** late ctor. The container will fill itself with wrapper objects for the tables returned by the given + name container. + */ + void construct( + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& _rxMasterContainer, + const ::com::sun::star::uno::Sequence< ::rtl::OUString >& _rTableFilter, + const ::com::sun::star::uno::Sequence< ::rtl::OUString >& _rTableTypeFilter + ); + + inline sal_Bool isInitialized() const { return m_bConstructed; } + }; +// .............................................................................. +} // namespace +// .............................................................................. + +#endif // DBACCESS_CORE_FILTERED_CONTAINER_HXX diff --git a/dbaccess/source/core/inc/PropertyForward.hxx b/dbaccess/source/core/inc/PropertyForward.hxx new file mode 100644 index 000000000000..b0e5696387b4 --- /dev/null +++ b/dbaccess/source/core/inc/PropertyForward.hxx @@ -0,0 +1,96 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 DBA_PROPERTYSETFORWARD_HXX +#define DBA_PROPERTYSETFORWARD_HXX + +#ifndef _COM_SUN_STAR_BEANS_XPROPERTYCHANGELISTENER_HPP_ +#include <com/sun/star/beans/XPropertyChangeListener.hpp> +#endif +#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_ +#include <com/sun/star/beans/XPropertySet.hpp> +#endif +#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSETINFO_HPP_ +#include <com/sun/star/beans/XPropertySetInfo.hpp> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XNAMECONTAINER_HPP_ +#include <com/sun/star/container/XNameContainer.hpp> +#endif +#ifndef _CPPUHELPER_IMPLBASE1_HXX_ +#include <cppuhelper/implbase1.hxx> +#endif +#ifndef _COMPHELPER_BROADCASTHELPER_HXX_ +#include <comphelper/broadcasthelper.hxx> +#endif + +#include <vector> + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + + // =================================================================== + // = OPropertyForward + // =================================================================== + typedef ::cppu::WeakImplHelper1 < ::com::sun::star::beans::XPropertyChangeListener + > OPropertyForward_Base; + class OPropertyForward :public ::comphelper::OBaseMutex + ,public OPropertyForward_Base + { + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > m_xSource; + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > m_xDest; + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > m_xDestInfo; + ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > m_xDestContainer; + ::rtl::OUString m_sName; + sal_Bool m_bInInsert; + + protected: + virtual ~OPropertyForward(); + + public: + OPropertyForward( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet>& _xSource, + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess>& _xDestContainer, + const ::rtl::OUString& _sName, + const ::std::vector< ::rtl::OUString >& _aPropertyList + ); + + // ::com::sun::star::beans::XPropertyChangeListener + virtual void SAL_CALL propertyChange( const ::com::sun::star::beans::PropertyChangeEvent& evt ) throw(::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::lang::XEventListener + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& _rSource ) throw (::com::sun::star::uno::RuntimeException); + + inline void setName( const ::rtl::OUString& _sName ) { m_sName = _sName; } + void setDefinition( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _xDest); + inline ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > getDefinition() const { return m_xDest; } + }; + +//........................................................................ +} // namespace dbaccess +//........................................................................ +#endif // DBA_PROPERTYSETFORWARD_HXX + diff --git a/dbaccess/source/core/inc/RefreshListener.hxx b/dbaccess/source/core/inc/RefreshListener.hxx new file mode 100644 index 000000000000..2b4bdda0f5a0 --- /dev/null +++ b/dbaccess/source/core/inc/RefreshListener.hxx @@ -0,0 +1,59 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 DBA_CORE_REFRESHLISTENER_HXX +#define DBA_CORE_REFRESHLISTENER_HXX + +#ifndef _COM_SUN_STAR_UNO_REFERENCE_H_ +#include <com/sun/star/uno/Reference.h> +#endif + +namespace com { namespace sun { namespace star { namespace container +{ + class XNameAccess; +} +}}} + +//......................................................................... +namespace dbaccess +{ +//......................................................................... + + //===================================================================== + //= IRefreshListener + //===================================================================== + class SAL_NO_VTABLE IRefreshListener + { + public: + virtual void refresh(const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& _rToBeRefreshed) = 0; + }; +//......................................................................... +} // namespace dbaccess +//......................................................................... + +#endif // DBA_CORE_REFRESHLISTENER_HXX + diff --git a/dbaccess/source/core/inc/SingleSelectQueryComposer.hxx b/dbaccess/source/core/inc/SingleSelectQueryComposer.hxx new file mode 100644 index 000000000000..7c0d2ba4cea3 --- /dev/null +++ b/dbaccess/source/core/inc/SingleSelectQueryComposer.hxx @@ -0,0 +1,283 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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_CORE_API_SINGLESELECTQUERYCOMPOSER_HXX +#define DBACCESS_CORE_API_SINGLESELECTQUERYCOMPOSER_HXX + +#ifndef _COM_SUN_STAR_SDB_XPARAMETERSSUPPLIER_HPP_ +#include <com/sun/star/sdb/XParametersSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBCX_XTABLESSUPPLIER_HPP_ +#include <com/sun/star/sdbcx/XTablesSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBCX_XCOLUMNSSUPPLIER_HPP_ +#include <com/sun/star/sdbcx/XColumnsSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_SDB_XSINGLESELECTQUERYCOMPOSER_HPP_ +#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp> +#endif +#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_ +#include <com/sun/star/lang/XServiceInfo.hpp> +#endif +#ifndef _COM_SUN_STAR_SCRIPT_XTYPECONVERTER_HPP_ +#include <com/sun/star/script/XTypeConverter.hpp> +#endif +#ifndef _CPPUHELPER_IMPLBASE5_HXX_ +#include <cppuhelper/implbase5.hxx> +#endif +#ifndef _CONNECTIVITY_PARSE_SQLITERATOR_HXX_ +#include <connectivity/sqliterator.hxx> +#endif +#ifndef _CONNECTIVITY_SQLPARSE_HXX +#include <connectivity/sqlparse.hxx> +#endif +#ifndef _DBASHARED_APITOOLS_HXX_ +#include "apitools.hxx" +#endif +#ifndef _COMPHELPER_BROADCASTHELPER_HXX_ +#include <comphelper/broadcasthelper.hxx> +#endif +#ifndef _COMPHELPER_UNO3_HXX_ +#include <comphelper/uno3.hxx> +#endif +#ifndef _COMPHELPER_PROPERTY_ARRAY_HELPER_HXX_ +#include <comphelper/proparrhlp.hxx> +#endif +#ifndef _COMPHELPER_PROPERTYCONTAINER_HXX_ +#include <comphelper/propertycontainer.hxx> +#endif +#ifndef COMPHELPER_COMPONENTCONTEXT_HXX +#include <comphelper/componentcontext.hxx> +#endif + +#include <memory> + +namespace com { namespace sun { namespace star { namespace util { + class XNumberFormatsSupplier; + class XNumberFormatter; +}}}} + +namespace dbaccess +{ + typedef ::cppu::ImplHelper5< ::com::sun::star::sdb::XSingleSelectQueryComposer, + ::com::sun::star::sdb::XParametersSupplier, + ::com::sun::star::sdbcx::XColumnsSupplier, + ::com::sun::star::sdbcx::XTablesSupplier, + ::com::sun::star::lang::XServiceInfo > OSingleSelectQueryComposer_BASE; + + class OPrivateColumns; + class OPrivateTables; + + class OSingleSelectQueryComposer : public ::comphelper::OMutexAndBroadcastHelper + ,public OSubComponent + ,public ::comphelper::OPropertyContainer + ,public ::comphelper::OPropertyArrayUsageHelper < OSingleSelectQueryComposer > + ,public OSingleSelectQueryComposer_BASE + { + enum SQLPart + { + Where = 0, // the 0 is important, as it will be used as index into arrays + Group, + Having, + Order, + + SQLPartCount + }; + inline void incSQLPart( SQLPart& e ) { e = (SQLPart)(1 + (size_t)e); } + enum EColumnType + { + SelectColumns = 0, + GroupByColumns = 1, + OrderColumns = 2, + ParameterColumns = 3 + }; + typedef ::std::const_mem_fun_t< const ::connectivity::OSQLParseNode*, ::connectivity::OSQLParseTreeIterator > + TGetParseNode; + ::connectivity::OSQLParser m_aSqlParser; + ::connectivity::OSQLParseTreeIterator m_aSqlIterator; // the iterator for the complete statement + ::connectivity::OSQLParseTreeIterator m_aAdditiveIterator; // the iterator for the "additive statement" (means without the clauses of the elementary statement) + ::std::vector<OPrivateColumns*> m_aColumnsCollection; // used for columns and parameters of old queries + ::std::vector<OPrivateTables*> m_aTablesCollection; + + ::std::vector< ::rtl::OUString > m_aElementaryParts; // the filter/groupby/having/order of the elementary statement + + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection> m_xConnection; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XDatabaseMetaData> m_xMetaData; + ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess> m_xConnectionTables; + ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess> m_xConnectionQueries; + ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier > m_xNumberFormatsSupplier; + ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess> m_xColumns; + ::comphelper::ComponentContext m_aContext; + ::com::sun::star::uno::Reference< ::com::sun::star::script::XTypeConverter > m_xTypeConverter; + + ::std::vector<OPrivateColumns*> m_aCurrentColumns; + OPrivateTables* m_pTables; // currently used tables + + ::rtl::OUString m_aPureSelectSQL; // the pure select statement, without filter/order/groupby/having + ::rtl::OUString m_sDecimalSep; + ::rtl::OUString m_sCommand; + ::com::sun::star::lang::Locale m_aLocale; + sal_Int32 m_nBoolCompareMode; // how to compare bool values + sal_Int32 m_nCommandType; + + // <properties> + ::rtl::OUString m_sOrignal; + // </properties> + + + sal_Bool setORCriteria(::connectivity::OSQLParseNode* pCondition, ::connectivity::OSQLParseTreeIterator& _rIterator, + ::std::vector< ::std::vector < ::com::sun::star::beans::PropertyValue > >& rFilters, const ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatter > & xFormatter) const; + sal_Bool setANDCriteria(::connectivity::OSQLParseNode* pCondition, ::connectivity::OSQLParseTreeIterator& _rIterator, + ::std::vector < ::com::sun::star::beans::PropertyValue > & rFilters, const ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatter > & xFormatter) const; + sal_Bool setComparsionPredicate(::connectivity::OSQLParseNode* pCondition, ::connectivity::OSQLParseTreeIterator& _rIterator, + ::std::vector < ::com::sun::star::beans::PropertyValue > & rFilters, const ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatter > & xFormatter) const; + + ::rtl::OUString getColumnName(::connectivity::OSQLParseNode* pColumnRef,::connectivity::OSQLParseTreeIterator& _rIterator) const; + ::rtl::OUString getTableAlias(const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& column ) const; + sal_Int32 getPredicateType(::connectivity::OSQLParseNode * _pPredicate) const; + // clears all Columns,Parameters and tables and insert it to their vectors + void clearCurrentCollections(); + // clears the columns collection given by EColumnType + void clearColumns( const EColumnType _eType ); + + /** retrieves a particular part of a statement + @param _rIterator + the iterator to use. + */ + ::rtl::OUString getStatementPart( TGetParseNode& _aGetFunctor, ::connectivity::OSQLParseTreeIterator& _rIterator ); + void setQuery_Impl( const ::rtl::OUString& command ); + + void setConditionByColumn( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& column + , sal_Bool andCriteria + ,::std::mem_fun1_t<bool,OSingleSelectQueryComposer,::rtl::OUString>& _aSetFunctor + ,sal_Int32 filterOperator); + + /** getStructuredCondition returns the structured condition for the where or having clause + @param _aGetFunctor + A member function to get the correct parse node. + + @return + The structured filter + */ + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > > + getStructuredCondition( TGetParseNode& _aGetFunctor ); + + ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess > + setCurrentColumns( EColumnType _eType, const ::vos::ORef< ::connectivity::OSQLColumns >& _rCols ); + + //helper methods for mem_fun_t + inline bool implSetFilter(::rtl::OUString _sFilter) { setFilter(_sFilter); return true;} + inline bool implSetHavingClause(::rtl::OUString _sFilter) { setHavingClause(_sFilter); return true;} + + /** returns the part of the seelect statement + @param _ePart + Which part should be returned. + @param _bWithKeyword + If <TRUE/> the keyword will be added too. Otherwise not. + @param _rIterator + The iterator to use. + + @return + The part of the select statement. + */ + ::rtl::OUString getSQLPart( SQLPart _ePart, ::connectivity::OSQLParseTreeIterator& _rIterator, sal_Bool _bWithKeyword ); + + /** retrieves the keyword for the given SQLPart + */ + ::rtl::OUString getKeyword( SQLPart _ePart ) const; + + /** sets a single "additive" clause, means a filter/groupby/having/order clause + */ + void setSingleAdditiveClause( SQLPart _ePart, const ::rtl::OUString& _rClause ); + + /** composes a statement from m_aPureSelectSQL and the 4 usual clauses + */ + ::rtl::OUString composeStatementFromParts( const ::std::vector< ::rtl::OUString >& _rParts ); + + /** return the name of the column. + */ + ::rtl::OUString impl_getColumnName_throw(const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& column); + + protected: + virtual ~OSingleSelectQueryComposer(); + public: + + OSingleSelectQueryComposer( const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess>& _xTableSupplier, + const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection>& _xConnection, + const ::comphelper::ComponentContext& _rContext); + + + void SAL_CALL disposing(void); + // ::com::sun::star::lang::XTypeProvider + DECLARE_TYPEPROVIDER( ); + + // com::sun::star::lang::XUnoTunnel + virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& aIdentifier ) throw(::com::sun::star::uno::RuntimeException); + // ::com::sun::star::uno::XInterface + DECLARE_XINTERFACE( ) + + // XServiceInfo + DECLARE_SERVICE_INFO(); + + DECLARE_PROPERTYCONTAINER_DEFAULTS(); + + // ::com::sun::star::sdb::XSingleSelectQueryComposer + virtual ::rtl::OUString SAL_CALL getElementaryQuery() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setElementaryQuery( const ::rtl::OUString& _rElementary ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setFilter( const ::rtl::OUString& filter ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setStructuredFilter( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > >& filter ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL appendFilterByColumn( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& column, sal_Bool andCriteria,sal_Int32 filterOperator ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL appendGroupByColumn( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& column ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setGroup( const ::rtl::OUString& group ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setHavingClause( const ::rtl::OUString& filter ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setStructuredHavingClause( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > >& filter ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL appendHavingClauseByColumn( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& column, sal_Bool andCriteria,sal_Int32 filterOperator ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL appendOrderByColumn( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& column, sal_Bool ascending ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setOrder( const ::rtl::OUString& order ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // XSingleSelectQueryAnalyzer + virtual ::rtl::OUString SAL_CALL getQuery( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setQuery( const ::rtl::OUString& command ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setCommand( const ::rtl::OUString& command,sal_Int32 CommandType ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getFilter( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > > SAL_CALL getStructuredFilter( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getGroup( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess > SAL_CALL getGroupColumns( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getHavingClause( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > > SAL_CALL getStructuredHavingClause( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getOrder( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess > SAL_CALL getOrderColumns( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getQueryWithSubstitution( ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // XColumnsSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > SAL_CALL getColumns( ) throw(::com::sun::star::uno::RuntimeException); + // XTablesSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > SAL_CALL getTables( ) throw(::com::sun::star::uno::RuntimeException); + // XParametersSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess > SAL_CALL getParameters( ) throw(::com::sun::star::uno::RuntimeException); + }; +} +#endif // DBACCESS_CORE_API_SINGLESELECTQUERYCOMPOSER_HXX diff --git a/dbaccess/source/core/inc/TableDeco.hxx b/dbaccess/source/core/inc/TableDeco.hxx new file mode 100644 index 000000000000..8f8ec5bf9652 --- /dev/null +++ b/dbaccess/source/core/inc/TableDeco.hxx @@ -0,0 +1,220 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 _DBA_CORE_TABLEDECORATOR_HXX_ +#define _DBA_CORE_TABLEDECORATOR_HXX_ + +#ifndef _COM_SUN_STAR_UTIL_XNUMBERFORMATSSUPPLIER_HPP_ +#include <com/sun/star/util/XNumberFormatsSupplier.hpp> +#endif +#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_COMPBASE9_HXX_ +#include <cppuhelper/compbase9.hxx> +#endif +#ifndef _CPPUHELPER_IMPLBASE5_HXX_ +#include <cppuhelper/implbase5.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_SDBCX_IREFRESHABLE_HXX_ +#include <connectivity/sdbcx/IRefreshable.hxx> +#endif +#ifndef COMPHELPER_IDPROPERTYARRAYUSAGEHELPER_HXX +#include <comphelper/IdPropArrayHelper.hxx> +#endif + +namespace dbaccess +{ + typedef ::cppu::WeakComponentImplHelper9< ::com::sun::star::sdbcx::XColumnsSupplier, + ::com::sun::star::sdbcx::XKeysSupplier, + ::com::sun::star::container::XNamed, + ::com::sun::star::lang::XServiceInfo, + ::com::sun::star::sdbcx::XDataDescriptorFactory, + ::com::sun::star::sdbcx::XIndexesSupplier, + ::com::sun::star::sdbcx::XRename, + ::com::sun::star::lang::XUnoTunnel, + ::com::sun::star::sdbcx::XAlterTable> OTableDescriptor_BASE; + //========================================================================== + //= OTables + //========================================================================== + class ODBTableDecorator; + typedef ::comphelper::OIdPropertyArrayUsageHelper< ODBTableDecorator > ODBTableDecorator_PROP; + + class ODBTableDecorator :public comphelper::OBaseMutex + ,public OTableDescriptor_BASE + ,public ODataSettings //ODataSettings_Base + ,public IColumnFactory + ,public ::connectivity::sdbcx::IRefreshableColumns + ,public ODBTableDecorator_PROP + { + void fillPrivileges() const; + protected: + ::com::sun::star::uno::Reference< ::com::sun::star::container::XContainerListener > m_xColumnMediator; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbcx::XColumnsSupplier > m_xTable; + ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > m_xColumnDefinitions; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection > m_xConnection; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XDatabaseMetaData > m_xMetaData; + ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier > m_xNumberFormats; + + // <properties> + mutable sal_Int32 m_nPrivileges; + // </properties> + ::connectivity::sdbcx::OCollection* m_pColumns; + ::connectivity::sdbcx::OCollection* m_pTables; + + // IColumnFactory + virtual OColumn* createColumn(const ::rtl::OUString& _rName) const; + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > createColumnDescriptor(); + virtual void columnAppended( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxSourceDescriptor ); + virtual void columnDropped(const ::rtl::OUString& _sName); + + virtual void refreshColumns(); + + virtual ::cppu::IPropertyArrayHelper* createArrayHelper(sal_Int32 _nId) const; + virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper(); + + // OPropertySetHelper + virtual sal_Bool SAL_CALL convertFastPropertyValue( + ::com::sun::star::uno::Any & rConvertedValue, + ::com::sun::star::uno::Any & rOldValue, + sal_Int32 nHandle, + const ::com::sun::star::uno::Any& rValue ) + throw (::com::sun::star::lang::IllegalArgumentException); + virtual void SAL_CALL getFastPropertyValue(::com::sun::star::uno::Any& rValue, sal_Int32 nHandle) const; + virtual void SAL_CALL setFastPropertyValue_NoBroadcast( + sal_Int32 nHandle, + const ::com::sun::star::uno::Any& rValue + ) + + throw (::com::sun::star::uno::Exception); + + virtual ~ODBTableDecorator(); + public: + /** constructs a wrapper supporting the com.sun.star.sdb.Table service. + + @param _rxConn + the connection the table belongs to. Must not be <NULL/> + @param _rxTable + the table from the driver can be <NULL/> + */ + ODBTableDecorator( + const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _rxConn, + const ::com::sun::star::uno::Reference< ::com::sun::star::sdbcx::XColumnsSupplier >& _rxTable, + const ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier >& _rxNumberFormats, + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& _rxColumnDefinitions + ) throw(::com::sun::star::sdbc::SQLException); + + + + // ODescriptor + virtual void construct(); + + //XInterface + virtual ::com::sun::star::uno::Any SAL_CALL queryInterface( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL acquire() throw(); + virtual void SAL_CALL release() throw(); + //XTypeProvider + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes( ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() throw (::com::sun::star::uno::RuntimeException); + + // OComponentHelper + virtual void SAL_CALL disposing(void); + + // ::com::sun::star::lang::XServiceInfo + DECLARE_SERVICE_INFO(); + // XPropertySet + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) throw(::com::sun::star::uno::RuntimeException); + // ::com::sun::star::sdbcx::XRename, + virtual void SAL_CALL rename( const ::rtl::OUString& _rNewName ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::container::ElementExistException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbcx::XAlterTable, + virtual void SAL_CALL alterColumnByName( const ::rtl::OUString& _rName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxDescriptor ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL alterColumnByIndex( sal_Int32 _nIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxDescriptor ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + + // XNamed + virtual ::rtl::OUString SAL_CALL getName() throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setName( const ::rtl::OUString& aName ) throw (::com::sun::star::uno::RuntimeException); + // com::sun::star::lang::XUnoTunnel + virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& aIdentifier ) throw(::com::sun::star::uno::RuntimeException); + static ::com::sun::star::uno::Sequence< sal_Int8 > getUnoTunnelImplementationId(); + + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XDatabaseMetaData> getMetaData() const { return m_xMetaData; } + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection> getConnection() const { return m_xMetaData.is() ? m_xMetaData->getConnection() : ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection>(); } + + // XColumnsSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > SAL_CALL getColumns( ) throw (::com::sun::star::uno::RuntimeException); + // XKeysSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess > SAL_CALL getKeys( ) throw (::com::sun::star::uno::RuntimeException); + // XIndexesSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > SAL_CALL getIndexes( ) throw (::com::sun::star::uno::RuntimeException); + // XDataDescriptorFactory + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > SAL_CALL createDataDescriptor( ) throw (::com::sun::star::uno::RuntimeException); + + protected: + using ODataSettings::getFastPropertyValue; + }; +} +#endif // _DBA_CORE_TABLEDECORATOR_HXX_ + + 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/callablestatement.hxx b/dbaccess/source/core/inc/callablestatement.hxx new file mode 100644 index 000000000000..64f281e7b6aa --- /dev/null +++ b/dbaccess/source/core/inc/callablestatement.hxx @@ -0,0 +1,95 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 _DBA_COREAPI_CALLABLESTATEMENT_HXX_ +#define _DBA_COREAPI_CALLABLESTATEMENT_HXX_ + +#ifndef _COM_SUN_STAR_SDBC_XROW_HPP_ +#include <com/sun/star/sdbc/XRow.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XOUTPARAMETERS_HPP_ +#include <com/sun/star/sdbc/XOutParameters.hpp> +#endif +#ifndef _DBA_COREAPI_PREPAREDSTATEMENT_HXX_ +#include <preparedstatement.hxx> +#endif + +namespace dbaccess +{ + //************************************************************ + // OCallableStatement + //************************************************************ + class OCallableStatement : public OPreparedStatement, + public ::com::sun::star::sdbc::XRow, + public ::com::sun::star::sdbc::XOutParameters + { + public: + OCallableStatement(const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection > & _xConn, + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > & _xStatement) + :OPreparedStatement(_xConn, _xStatement){} + + // ::com::sun::star::lang::XTypeProvider + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes() throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() throw (::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::uno::XInterface + virtual ::com::sun::star::uno::Any SAL_CALL queryInterface( const ::com::sun::star::uno::Type & rType ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL acquire() throw(); + virtual void SAL_CALL release() throw(); + + // ::com::sun::star::lang::XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw(::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbc::XOutParameters + virtual void SAL_CALL registerOutParameter( sal_Int32 parameterIndex, sal_Int32 sqlType, const ::rtl::OUString& typeName ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL registerNumericOutParameter( sal_Int32 parameterIndex, sal_Int32 sqlType, sal_Int32 scale ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbc::XRow + virtual sal_Bool SAL_CALL wasNull( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getString( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL getBoolean( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int8 SAL_CALL getByte( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int16 SAL_CALL getShort( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getInt( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int64 SAL_CALL getLong( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual float SAL_CALL getFloat( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual double SAL_CALL getDouble( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getBytes( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::util::Date SAL_CALL getDate( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::util::Time SAL_CALL getTime( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::util::DateTime SAL_CALL getTimestamp( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getBinaryStream( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getCharacterStream( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Any SAL_CALL getObject( sal_Int32 columnIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& typeMap ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRef > SAL_CALL getRef( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XBlob > SAL_CALL getBlob( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XClob > SAL_CALL getClob( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XArray > SAL_CALL getArray( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + }; +} +#endif // _DBA_COREAPI_CALLABLESTATEMENT_HXX_ + diff --git a/dbaccess/source/core/inc/column.hxx b/dbaccess/source/core/inc/column.hxx new file mode 100644 index 000000000000..543e999f715f --- /dev/null +++ b/dbaccess/source/core/inc/column.hxx @@ -0,0 +1,258 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 _DBA_COREAPI_COLUMN_HXX_ +#define _DBA_COREAPI_COLUMN_HXX_ + +#include "columnsettings.hxx" + +#include <com/sun/star/container/XChild.hpp> +#include <com/sun/star/container/XEnumerationAccess.hpp> +#include <com/sun/star/container/XIndexAccess.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/container/XNamed.hpp> +#include <com/sun/star/io/IOException.hpp> +#include <com/sun/star/io/XObjectInputStream.hpp> +#include <com/sun/star/io/XObjectOutputStream.hpp> +#include <com/sun/star/lang/WrappedTargetException.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XUnoTunnel.hpp> +#include <com/sun/star/sdbc/XResultSet.hpp> +#include <com/sun/star/sdbcx/XAppend.hpp> +#include <com/sun/star/sdbcx/XDrop.hpp> +#include <com/sun/star/util/XNumberFormatsSupplier.hpp> + +#include <comphelper/broadcasthelper.hxx> +#include <comphelper/proparrhlp.hxx> +#include <comphelper/propertycontainer.hxx> +#include <comphelper/stl_types.hxx> +#include <connectivity/CommonTools.hxx> +#include <connectivity/FValue.hxx> +#include <connectivity/TColumnsHelper.hxx> +#include <connectivity/sdbcx/IRefreshable.hxx> +#include <cppuhelper/compbase2.hxx> +#include <cppuhelper/compbase4.hxx> +#include <cppuhelper/implbase1.hxx> +#include <cppuhelper/propshlp.hxx> +#include <osl/diagnose.h> + +#include <hash_map> + +namespace dbaccess +{ + + //************************************************************ + // OColumn + //************************************************************ + typedef ::cppu::WeakComponentImplHelper2< ::com::sun::star::lang::XServiceInfo, + ::com::sun::star::container::XNamed + > OColumnBase; + + //------------------------------------------------------------ + class OColumn :public comphelper::OBaseMutex + ,public OColumnBase + ,public ::comphelper::OPropertyContainer + ,public IPropertyContainer // convenience for the derived class which also derive from OColumnSettings + { + friend class OColumns; + + protected: + // <properties> + ::rtl::OUString m_sName; + // </properties> + + protected: + OColumn( const bool _bNameIsReadOnly ); + + public: + virtual ~OColumn(); + + // com::sun::star::lang::XTypeProvider + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes() throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() throw (::com::sun::star::uno::RuntimeException) = 0; + + // com::sun::star::uno::XInterface + virtual ::com::sun::star::uno::Any SAL_CALL queryInterface( const ::com::sun::star::uno::Type & rType ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL acquire() throw(); + virtual void SAL_CALL release() throw(); + + // 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); + + // cppu::OComponentHelper + virtual void SAL_CALL disposing(void); + + // ::com::sun::star::lang::XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw(::com::sun::star::uno::RuntimeException); + + // XNamed + virtual ::rtl::OUString SAL_CALL getName( ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setName( const ::rtl::OUString& _rName ) throw(::com::sun::star::uno::RuntimeException); + + virtual void fireValueChange( const ::connectivity::ORowSetValue& _rOldValue ); + + protected: + // IPropertyContainer + virtual void registerProperty( const ::rtl::OUString& _rName, sal_Int32 _nHandle, sal_Int32 _nAttributes, void* _pPointerToMember, const ::com::sun::star::uno::Type& _rMemberType ); + virtual void registerMayBeVoidProperty( const ::rtl::OUString& _rName, sal_Int32 _nHandle, sal_Int32 _nAttributes, ::com::sun::star::uno::Any* _pPointerToMember, const ::com::sun::star::uno::Type& _rExpectedType ); + virtual void registerPropertyNoMember( const ::rtl::OUString& _rName, sal_Int32 _nHandle, sal_Int32 _nAttributes, const ::com::sun::star::uno::Type& _rType, const void* _pInitialValue ); + }; + + //============================================================ + //= IColumnFactory - used by OColumns for creating new columns + //============================================================ + class SAL_NO_VTABLE IColumnFactory + { + public: + /** creates a OColumn object which should represent the column with a given name + */ + virtual OColumn* + createColumn( const ::rtl::OUString& _rName ) const = 0; + + /** creates a column descriptor object. + + A column descriptor object is used to append new columns to the collection. If such an append + actually happened, columnAppended is called afterwards. + */ + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > createColumnDescriptor() = 0; + + /** notifies that a column, created from a column descriptor, has been appended + */ + virtual void columnAppended( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxSourceDescriptor ) = 0; + + /** notifies that a column with a given name has been dropped + */ + virtual void columnDropped( const ::rtl::OUString& _sName ) = 0; + }; + + //============================================================ + //= OColumns + //= general columns map, could be used for readonly access + //= no appending and dropping is supported + //============================================================ + typedef ::std::hash_map<rtl::OUString, OColumn*, ::comphelper::UStringMixHash, ::comphelper::UStringMixEqual> OColumnMap; + typedef ::std::vector<OColumn*> OColumnArray; + + class OContainerMediator; + typedef ::cppu::ImplHelper1< ::com::sun::star::container::XChild > TXChild; + typedef connectivity::OColumnsHelper OColumns_BASE; + //------------------------------------------------------------ + class OColumns : public OColumns_BASE + ,public TXChild + { + OContainerMediator* m_pMediator; + + protected: + // comes from the driver can be null + ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > m_xDrvColumns; + ::com::sun::star::uno::WeakReference< ::com::sun::star::uno::XInterface > m_xParent; + IColumnFactory* m_pColFactoryImpl; + ::connectivity::sdbcx::IRefreshableColumns* m_pRefreshColumns; + + sal_Bool m_bInitialized : 1; + sal_Bool m_bAddColumn : 1; + sal_Bool m_bDropColumn : 1; + + virtual void impl_refresh() throw(::com::sun::star::uno::RuntimeException); + virtual connectivity::sdbcx::ObjectType createObject(const ::rtl::OUString& _rName); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > createDescriptor(); + virtual connectivity::sdbcx::ObjectType appendObject( const ::rtl::OUString& _rForName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& descriptor ); + virtual void dropObject(sal_Int32 _nPos,const ::rtl::OUString _sElementName); + + public: + connectivity::sdbcx::ObjectType createBaseObject(const ::rtl::OUString& _rName) + { + return OColumns_BASE::createObject(_rName); + } + /** flag which determines whether the container is filled or not + */ + inline sal_Bool isInitialized() const { return m_bInitialized; } + inline void setInitialized() {m_bInitialized = sal_True;} + inline void setMediator(OContainerMediator* _pMediator) { m_pMediator = _pMediator; } + + public: + /** constructs an empty container without configuration location. + @param rParent the parent object. This instance will be used for refcounting, so the parent + cannot die before the container does. + @param _rMutex the mutex of the parent. + @param _bCaseSensitive the initial case sensitivity flag + @see setCaseSensitive + */ + OColumns( + ::cppu::OWeakObject& _rParent, + ::osl::Mutex& _rMutex, + sal_Bool _bCaseSensitive, + const ::std::vector< ::rtl::OUString>& _rVector, + IColumnFactory* _pColFactory, + ::connectivity::sdbcx::IRefreshableColumns* _pRefresh, + sal_Bool _bAddColumn = sal_False, + sal_Bool _bDropColumn = sal_False, + sal_Bool _bUseHardRef = sal_True); + + OColumns( + ::cppu::OWeakObject& _rParent, + ::osl::Mutex& _rMutex, + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& _rxDrvColumns, + sal_Bool _bCaseSensitive, + const ::std::vector< ::rtl::OUString> &_rVector, + IColumnFactory* _pColFactory, + ::connectivity::sdbcx::IRefreshableColumns* _pRefresh, + sal_Bool _bAddColumn = sal_False, + sal_Bool _bDropColumn = sal_False, + sal_Bool _bUseHardRef = sal_True); + virtual ~OColumns(); + + //XInterface + virtual ::com::sun::star::uno::Any SAL_CALL queryInterface( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL acquire() throw() { OColumns_BASE::acquire(); } + virtual void SAL_CALL release() throw() { OColumns_BASE::release(); } + //XTypeProvider + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes( ) throw(::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::lang::XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw(::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::container::XChild + virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL getParent( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setParent( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& Parent ) throw (::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException); + + void append(const ::rtl::OUString& rName, OColumn*); + void clearColumns(); + // only the name is identical to ::cppu::OComponentHelper + virtual void SAL_CALL disposing(void); + + private: + using OColumns_BASE::setParent; + }; +} +#endif // _DBA_COREAPI_COLUMN_HXX_ + diff --git a/dbaccess/source/core/inc/columnsettings.hxx b/dbaccess/source/core/inc/columnsettings.hxx new file mode 100644 index 000000000000..c9f6fa5b1cda --- /dev/null +++ b/dbaccess/source/core/inc/columnsettings.hxx @@ -0,0 +1,109 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 COLUMNSETTINGS_HXX +#define COLUMNSETTINGS_HXX + +/** === begin UNO includes === **/ +#include <com/sun/star/beans/XPropertySet.hpp> +/** === end UNO includes === **/ + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + + // TODO: move the following to comphelper/propertycontainerhelper.hxx + class IPropertyContainer + { + public: + virtual void registerProperty( + const ::rtl::OUString& _rName, + sal_Int32 _nHandle, + sal_Int32 _nAttributes, + void* _pPointerToMember, + const ::com::sun::star::uno::Type& _rMemberType + ) = 0; + + virtual void registerMayBeVoidProperty( + const ::rtl::OUString& _rName, + sal_Int32 _nHandle, + sal_Int32 _nAttributes, + ::com::sun::star::uno::Any* _pPointerToMember, + const ::com::sun::star::uno::Type& _rExpectedType + ) = 0; + + virtual void registerPropertyNoMember( + const ::rtl::OUString& _rName, + sal_Int32 _nHandle, + sal_Int32 _nAttributes, + const ::com::sun::star::uno::Type& _rType, + const void* _pInitialValue + ) = 0; + }; + + //==================================================================== + //= OColumnSettings + //==================================================================== + class OColumnSettings + { + // <properties> + ::com::sun::star::uno::Any m_aWidth; // sal_Int32 or void + ::com::sun::star::uno::Any m_aFormatKey; // sal_Int32 or void + ::com::sun::star::uno::Any m_aRelativePosition; // sal_Int32 or void + ::com::sun::star::uno::Any m_aAlignment; // sal_Int32 (::com::sun::star::awt::TextAlign) or void + ::com::sun::star::uno::Any m_aHelpText; // the description of the column which is visible in the helptext of the column + ::com::sun::star::uno::Any m_aControlDefault; // the default value which should be displayed as by a control when moving to a new row + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > + m_xControlModel; + sal_Bool m_bHidden; + // </properties> + + protected: + virtual ~OColumnSettings(); + + public: + OColumnSettings(); + + protected: + void registerProperties( IPropertyContainer& _rPropertyContainer ); + + /** determines whether the property with the given handle is handled by the class + */ + static bool isColumnSettingProperty( const sal_Int32 _nPropertyHandle ); + static bool isDefaulted( const sal_Int32 _nPropertyHandle, const ::com::sun::star::uno::Any& _rPropertyValue ); + + public: + /** check if the persistent settings have their default value + */ + static bool hasDefaultSettings( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxColumn ); + }; + +//........................................................................ +} // namespace dbaccess +//........................................................................ + +#endif // COLUMNSETTINGS_HXX diff --git a/dbaccess/source/core/inc/commandbase.hxx b/dbaccess/source/core/inc/commandbase.hxx new file mode 100644 index 000000000000..ea0e9644c714 --- /dev/null +++ b/dbaccess/source/core/inc/commandbase.hxx @@ -0,0 +1,71 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 _DBA_CORE_COMMANDBASE_HXX_ +#define _DBA_CORE_COMMANDBASE_HXX_ + +#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_ +#include <com/sun/star/uno/Sequence.hxx> +#endif +#ifndef _COM_SUN_STAR_BEANS_PROPERTYVALUE_HPP_ +#include <com/sun/star/beans/PropertyValue.hpp> +#endif + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + +//========================================================================== +//= OCommandBase - a base class (in fact just a container for some members) +//= for classes implementing the sdb.CommandDefinition service +//========================================================================== +class OCommandBase +{ +public: // need public access +// <properties> + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue> + m_aLayoutInformation; + ::rtl::OUString m_sCommand; + sal_Bool m_bEscapeProcessing; // no BitField ! so it can be used with a OPropertyStateContainer + ::rtl::OUString m_sUpdateTableName; + ::rtl::OUString m_sUpdateSchemaName; + ::rtl::OUString m_sUpdateCatalogName; +// </properties> + +protected: + OCommandBase() : m_bEscapeProcessing(sal_True) { } + +}; + +//........................................................................ +} // namespace dbaccess +//........................................................................ + +#endif // _DBA_CORE_COMMANDBASE_HXX_ + + diff --git a/dbaccess/source/core/inc/composertools.hxx b/dbaccess/source/core/inc/composertools.hxx new file mode 100644 index 000000000000..4f7c4b7f66ef --- /dev/null +++ b/dbaccess/source/core/inc/composertools.hxx @@ -0,0 +1,142 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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_SOURCE_CORE_INC_COMPOSERTOOLS_HXX +#define DBACCESS_SOURCE_CORE_INC_COMPOSERTOOLS_HXX + +/** === begin UNO includes === **/ +/** === end UNO includes === **/ + +#ifndef _RTL_USTRBUF_HXX_ +#include <rtl/ustrbuf.hxx> +#endif + +#include <functional> + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + + //==================================================================== + //= TokenComposer + //==================================================================== + struct TokenComposer : public ::std::unary_function< ::rtl::OUString, void > + { + private: + #ifdef DBG_UTIL + bool m_bUsed; + #endif + + protected: + ::rtl::OUStringBuffer m_aBuffer; + + public: + ::rtl::OUString getComposedAndClear() + { + #ifdef DBG_UTIL + m_bUsed = true; + #endif + return m_aBuffer.makeStringAndClear(); + } + + void clear() + { + #ifdef DBG_UTIL + m_bUsed = false; + #endif + m_aBuffer.makeStringAndClear(); + } + + public: + TokenComposer() + #ifdef DBG_UTIL + :m_bUsed( false ) + #endif + { + } + + virtual ~TokenComposer() + { + } + + void operator() (const ::rtl::OUString& lhs) + { + append(lhs); + } + + void append( const ::rtl::OUString& lhs ) + { + #ifdef DBG_UTIL + OSL_ENSURE( !m_bUsed, "FilterCreator::append: already used up!" ); + #endif + if ( lhs.getLength() ) + { + if ( m_aBuffer.getLength() ) + appendNonEmptyToNonEmpty( lhs ); + else + m_aBuffer.append( lhs ); + } + } + + /// append the given part. Only to be called when both the part and our buffer so far are not empty + virtual void appendNonEmptyToNonEmpty( const ::rtl::OUString& lhs ) = 0; + }; + + //==================================================================== + //= FilterCreator + //==================================================================== + struct FilterCreator : public TokenComposer + { + virtual void appendNonEmptyToNonEmpty( const ::rtl::OUString& lhs ) + { + m_aBuffer.insert( 0, (sal_Unicode)' ' ); + m_aBuffer.insert( 0, (sal_Unicode)'(' ); + m_aBuffer.appendAscii( " ) AND ( " ); + m_aBuffer.append( lhs ); + m_aBuffer.appendAscii( " )" ); + } + }; + + //==================================================================== + //= FilterCreator + //==================================================================== + struct OrderCreator : public TokenComposer + { + virtual void appendNonEmptyToNonEmpty( const ::rtl::OUString& lhs ) + { + m_aBuffer.appendAscii( ", " ); + m_aBuffer.append( lhs ); + } + }; + +//........................................................................ +} // namespace dbaccess +//........................................................................ + +#endif // DBACCESS_SOURCE_CORE_INC_COMPOSERTOOLS_HXX + diff --git a/dbaccess/source/core/inc/containerapprove.hxx b/dbaccess/source/core/inc/containerapprove.hxx new file mode 100644 index 000000000000..0f27559201d7 --- /dev/null +++ b/dbaccess/source/core/inc/containerapprove.hxx @@ -0,0 +1,80 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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_CONTAINERAPPROVE_HXX +#define DBACCESS_CONTAINERAPPROVE_HXX + +/** === begin UNO includes === **/ +#ifndef _COM_SUN_STAR_UNO_XINTERFACE_HPP_ +#include <com/sun/star/uno/XInterface.hpp> +#endif +/** === end UNO includes === **/ + +#include <boost/shared_ptr.hpp> + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + + //==================================================================== + //= IContainerApprove + //==================================================================== + /** interface for approving elements to be inserted into a container + + On the long run, one could imagine that this interface completely encapsulates + container/element approvals in all our various container classes herein (document + containers, definition containers, table containers, query containers, + command definition containers, bookmark containers). This would decrease coupling + of the respective classes. + */ + class SAL_NO_VTABLE IContainerApprove + { + public: + /** approves a given element for insertion into the container + @param _rName + specifies the name under which the element is going to be inserted + @param _rxElement + specifies the element which is going to be inserted + @throws Exception + if the name or the object are invalid, or not eligible for insertion + into the container + */ + virtual void SAL_CALL approveElement( + const ::rtl::OUString& _rName, + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxElement + ) = 0; + }; + + typedef ::boost::shared_ptr< IContainerApprove > PContainerApprove; + +//........................................................................ +} // namespace dbaccess +//........................................................................ + +#endif // DBACCESS_CONTAINERAPPROVE_HXX + diff --git a/dbaccess/source/core/inc/core_resource.hrc b/dbaccess/source/core/inc/core_resource.hrc new file mode 100644 index 000000000000..fb6320f38932 --- /dev/null +++ b/dbaccess/source/core/inc/core_resource.hrc @@ -0,0 +1,113 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 _DBA_CORE_RESOURCE_HRC_ +#define _DBA_CORE_RESOURCE_HRC_ + +#ifndef _SOLAR_HRC +#include <svl/solar.hrc> +#endif + +//------------------------------------------------------------------------------ +#define RID_CORE_STRINGS_START RID_DBACCESS_START + +//------------------------------------------------------------------------------ +//- String-IDs +#define RID_STR_TRIED_OPEN_TABLE ( RID_CORE_STRINGS_START + 0 ) +#define RID_STR_CONNECTION_INVALID ( RID_CORE_STRINGS_START + 1 ) +#define RID_STR_TABLE_IS_FILTERED ( RID_CORE_STRINGS_START + 2 ) +#define RID_STR_NEED_CONFIG_WRITE_ACCESS ( RID_CORE_STRINGS_START + 3 ) +#define RID_STR_COULDNOTCONNECT_NODRIVER ( RID_CORE_STRINGS_START + 4 ) +#define RID_STR_COULDNOTCONNECT_UNSPECIFIED ( RID_CORE_STRINGS_START + 5 ) +#define RID_STR_COULDNOTLOAD_MANAGER ( RID_CORE_STRINGS_START + 6 ) +#define RID_STR_ONLY_QUERY ( RID_CORE_STRINGS_START + 7 ) +#define RID_STR_NO_VALUE_CHANGED ( RID_CORE_STRINGS_START + 8 ) +#define RID_STR_NO_XROWUPDATE ( RID_CORE_STRINGS_START + 9 ) +#define RID_STR_NO_XRESULTSETUPDATE ( RID_CORE_STRINGS_START + 10 ) +#define RID_STR_NO_UPDATE_MISSING_CONDITION ( RID_CORE_STRINGS_START + 11 ) +#define RID_STR_NO_COLUMN_ADD ( RID_CORE_STRINGS_START + 12 ) +#define RID_STR_NO_COLUMN_DROP ( RID_CORE_STRINGS_START + 13 ) +#define RID_STR_NO_CONDITION_FOR_PK ( RID_CORE_STRINGS_START + 14 ) +#define RID_STR_NO_XQUERIESSUPPLIER ( RID_CORE_STRINGS_START + 15 ) +#define RID_STR_NO_ABS_ZERO ( RID_CORE_STRINGS_START + 16 ) +#define RID_STR_NO_RELATIVE ( RID_CORE_STRINGS_START + 17 ) +#define RID_STR_NO_REFESH_AFTERLAST ( RID_CORE_STRINGS_START + 18 ) +#define RID_STR_NO_MOVETOINSERTROW_CALLED ( RID_CORE_STRINGS_START + 19 ) +#define RID_STR_NO_UPDATEROW ( RID_CORE_STRINGS_START + 20 ) +#define RID_STR_NO_DELETEROW ( RID_CORE_STRINGS_START + 21 ) +#define RID_STR_COLUMN_MUST_VISIBLE ( RID_CORE_STRINGS_START + 22 ) +#define RID_STR_COLUMN_NOT_VALID ( RID_CORE_STRINGS_START + 23 ) +#define RID_STR_COLUMN_NOT_SEARCHABLE ( RID_CORE_STRINGS_START + 24 ) +#define RID_STR_NOT_SEQUENCE_INT8 ( RID_CORE_STRINGS_START + 25 ) +#define RID_STR_NOT_SUPPORTED_BY_DRIVER ( RID_CORE_STRINGS_START + 26 ) +#define RID_STR_NO_TABLE_RENAME ( RID_CORE_STRINGS_START + 27 ) +#define RID_STR_COLUMN_ALTER_BY_NAME ( RID_CORE_STRINGS_START + 28 ) +#define RID_STR_COLUMN_ALTER_BY_INDEX ( RID_CORE_STRINGS_START + 29 ) +#define RID_STR_NO_ALTER_COLUMN_DEF ( RID_CORE_STRINGS_START + 30 ) +#define RID_STR_COLUMN_UNKNOWN_PROP ( RID_CORE_STRINGS_START + 31 ) +#define RID_STR_FORM ( RID_CORE_STRINGS_START + 32 ) +#define RID_STR_REPORT ( RID_CORE_STRINGS_START + 33 ) +#define RID_STR_DATASOURCE_NOT_STORED ( RID_CORE_STRINGS_START + 34 ) +#define RID_STR_FILE_DOES_NOT_EXIST ( RID_CORE_STRINGS_START + 35 ) +#define RID_STR_TABLE_DOES_NOT_EXIST ( RID_CORE_STRINGS_START + 36 ) +#define RID_STR_CONFLICTING_NAMES ( RID_CORE_STRINGS_START + 37 ) +#define RID_STR_COMMAND_LEADING_TO_ERROR ( RID_CORE_STRINGS_START + 38 ) +#define RID_STR_STATEMENT_WITHOUT_RESULT_SET ( RID_CORE_STRINGS_START + 39 ) +#define RID_STR_NAME_MUST_NOT_BE_EMPTY ( RID_CORE_STRINGS_START + 40 ) +#define RID_STR_NO_NULL_OBJECTS_IN_CONTAINER ( RID_CORE_STRINGS_START + 41 ) +#define RID_STR_NAME_ALREADY_USED ( RID_CORE_STRINGS_START + 42 ) +#define RID_STR_OBJECT_CONTAINER_MISMATCH ( RID_CORE_STRINGS_START + 43 ) +#define RID_STR_OBJECT_ALREADY_CONTAINED ( RID_CORE_STRINGS_START + 44 ) +#define RID_STR_NAME_NOT_FOUND ( RID_CORE_STRINGS_START + 45 ) +#define RID_STR_QUERY_DOES_NOT_EXIST ( RID_CORE_STRINGS_START + 46 ) +#define RID_STR_ERROR_WHILE_SAVING ( RID_CORE_STRINGS_START + 47 ) +#define RID_STR_NO_SUB_FOLDER ( RID_CORE_STRINGS_START + 48 ) + +#define RID_STR_NO_DELETE_BEFORE_AFTER ( RID_CORE_STRINGS_START + 49 ) +#define RID_STR_NO_DELETE_INSERT_ROW ( RID_CORE_STRINGS_START + 50 ) +#define RID_STR_RESULT_IS_READONLY ( RID_CORE_STRINGS_START + 51 ) +#define RID_STR_NO_DELETE_PRIVILEGE ( RID_CORE_STRINGS_START + 52 ) +#define RID_STR_ROW_ALREADY_DELETED ( RID_CORE_STRINGS_START + 53 ) +#define RID_STR_UPDATE_FAILED ( RID_CORE_STRINGS_START + 54 ) + +#define RID_STR_INVALID_INDEX ( RID_CORE_STRINGS_START + 55 ) +#define RID_STR_NO_INSERT_PRIVILEGE ( RID_CORE_STRINGS_START + 56 ) +#define RID_STR_INTERNAL_ERROR ( RID_CORE_STRINGS_START + 57 ) +#define RID_STR_EXPRESSION1 ( RID_CORE_STRINGS_START + 58 ) +#define RID_STR_NO_SQL_COMMAND ( RID_CORE_STRINGS_START + 59 ) +#define RID_STR_INVALID_CURSOR_STATE ( RID_CORE_STRINGS_START + 60 ) +#define RID_STR_CURSOR_BEFORE_OR_AFTER ( RID_CORE_STRINGS_START + 61 ) +#define RID_STR_NO_BOOKMARK_BEFORE_OR_AFTER ( RID_CORE_STRINGS_START + 62 ) +#define RID_STR_NO_BOOKMARK_DELETED ( RID_CORE_STRINGS_START + 63 ) +#define RID_STR_NO_EMBEDDING ( RID_CORE_STRINGS_START + 64 ) +#define RID_STR_CONNECTION_REQUEST ( RID_CORE_STRINGS_START + 65 ) +#define RID_STR_MISSING_EXTENSION ( RID_CORE_STRINGS_START + 66 ) + +#define RID_NO_SUCH_DATA_SOURCE ( RID_CORE_STRINGS_START + 67 ) + +#endif // _DBA_CORE_RESOURCE_HRC_ + diff --git a/dbaccess/source/core/inc/core_resource.hxx b/dbaccess/source/core/inc/core_resource.hxx new file mode 100644 index 000000000000..fd8023e15322 --- /dev/null +++ b/dbaccess/source/core/inc/core_resource.hxx @@ -0,0 +1,130 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 _DBA_CORE_RESOURCE_HXX_ +#define _DBA_CORE_RESOURCE_HXX_ + +#ifndef _RTL_USTRING_HXX_ +#include <rtl/ustring.hxx> +#endif +#include <osl/mutex.hxx> + +class ResMgr; +//......................................................................... +namespace dbaccess +{ + +#define DBA_RES( id ) ResourceManager::loadString( id ) +#define DBA_RES_PARAM( id, ascii, replace ) ResourceManager::loadString( id, ascii, replace ) + +#define DBACORE_RESSTRING( id ) DBA_RES( id ) + // (compatibility) + + //================================================================== + //= ResourceManager + //= handling ressources within the DBA-Core library + //================================================================== + class ResourceManager + { + friend class OModuleClient; + static ::osl::Mutex s_aMutex; /// access safety + static sal_Int32 s_nClients; /// number of registered clients + static ResMgr* m_pImpl; + + private: + // no instantiation allowed + ResourceManager() { } + ~ResourceManager() { } + + protected: + static void ensureImplExists(); + /// register a client for the module + static void registerClient(); + /// revoke a client for the module + static void revokeClient(); + + public: + /** loads the string with the specified resource id + */ + static ::rtl::OUString loadString(sal_uInt16 _nResId); + + /** loads a string from the resource file, substituting a placeholder with a given string + + @param _nResId + the resource ID of the string to load + @param _pPlaceholderAscii + the ASCII representation of the placeholder string + @param _rReplace + the string which should substitute the placeholder + */ + static ::rtl::OUString loadString( + sal_uInt16 _nResId, + const sal_Char* _pPlaceholderAscii, + const ::rtl::OUString& _rReplace + ); + + /** loads a string from the resource file, substituting two placeholders with given strings + + @param _nResId + the resource ID of the string to load + @param _pPlaceholderAscii1 + the ASCII representation of the first placeholder string + @param _rReplace1 + the string which should substitute the first placeholder + @param _pPlaceholderAscii2 + the ASCII representation of the second placeholder string + @param _rReplace2 + the string which should substitute the second placeholder + */ + static ::rtl::OUString loadString( + sal_uInt16 _nResId, + const sal_Char* _pPlaceholderAscii1, + const ::rtl::OUString& _rReplace1, + const sal_Char* _pPlaceholderAscii2, + const ::rtl::OUString& _rReplace2 + ); + }; + + //========================================================================= + //= OModuleClient + //========================================================================= + /** base class for objects which uses any global module-specific ressources + */ + class OModuleClient + { + public: + OModuleClient() { ResourceManager::registerClient(); } + ~OModuleClient() { ResourceManager::revokeClient(); } + }; + + +//......................................................................... +} +//......................................................................... + +#endif // _DBA_CORE_RESOURCE_HXX_ + diff --git a/dbaccess/source/core/inc/datasettings.hxx b/dbaccess/source/core/inc/datasettings.hxx new file mode 100644 index 000000000000..9b42c7d57cf9 --- /dev/null +++ b/dbaccess/source/core/inc/datasettings.hxx @@ -0,0 +1,109 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 _DBA_CORE_DATASETTINGS_HXX_ +#define _DBA_CORE_DATASETTINGS_HXX_ + +#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_ +#include <com/sun/star/uno/Sequence.hxx> +#endif +#ifndef _COM_SUN_STAR_BEANS_PROPERTY_HPP_ +#include <com/sun/star/beans/Property.hpp> +#endif +#ifndef _COM_SUN_STAR_AWT_FONTDESCRIPTOR_HPP_ +#include <com/sun/star/awt/FontDescriptor.hpp> +#endif +#ifndef _COM_SUN_STAR_LANG_ILLEGALARGUMENTEXCEPTION_HPP_ +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#endif +#ifndef _RTL_USTRING_HXX_ +#include <rtl/ustring.hxx> +#endif +#ifndef COMPHELPER_PROPERTYSTATECONTAINER_HXX +#include <comphelper/propertystatecontainer.hxx> +#endif + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + +//========================================================================== +//= ODataSettings_Base - a base class which implements the property member +//= for an object implementing the sdb::DataSettings +//= service +//= the properties have to to be registered when used +//========================================================================== +class ODataSettings_Base +{ +public: +// <properties> + ::rtl::OUString m_sFilter; + ::rtl::OUString m_sHavingClause; + ::rtl::OUString m_sGroupBy; + ::rtl::OUString m_sOrder; + sal_Bool m_bApplyFilter; // no BitField ! the base class needs a pointer to this member ! + ::com::sun::star::awt::FontDescriptor m_aFont; + ::com::sun::star::uno::Any m_aRowHeight; + ::com::sun::star::uno::Any m_aTextColor; + ::com::sun::star::uno::Any m_aTextLineColor; + sal_Int16 m_nFontEmphasis; + sal_Int16 m_nFontRelief; +// </properties> + +protected: + ODataSettings_Base(); + ODataSettings_Base(const ODataSettings_Base& _rSource); + ~ODataSettings_Base(); +}; +//========================================================================== +//= ODataSettings - a base class which implements the property handling +//= for an object implementing the sdb::DataSettings +//= service +//========================================================================== + +class ODataSettings : public ::comphelper::OPropertyStateContainer + , public ODataSettings_Base +{ + sal_Bool m_bQuery; +protected: + ODataSettings(::cppu::OBroadcastHelper& _rBHelper,sal_Bool _bQuery = sal_False); + virtual void getPropertyDefaultByHandle( sal_Int32 _nHandle, ::com::sun::star::uno::Any& _rDefault ) const; + + /** register the properties from the param given. The parameter instance must be alive as long as tis object live. + @param _pItem + The database settings, can be <br>this</br> + */ + void registerPropertiesFor(ODataSettings_Base* _pItem); +}; + +//........................................................................ +} // namespace dbaccess +//........................................................................ + +#endif // _DBA_CORE_DATASETTINGS_HXX_ + diff --git a/dbaccess/source/core/inc/dbamiscres.hrc b/dbaccess/source/core/inc/dbamiscres.hrc new file mode 100644 index 000000000000..a383ed4189d2 --- /dev/null +++ b/dbaccess/source/core/inc/dbamiscres.hrc @@ -0,0 +1,62 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 _DBA_MISCRES_HRC_ +#define _DBA_MISCRES_HRC_ + +//======================================================================== +// string ids (relative to other resources, that's why not unique) +#define STR_MYSQL_ODBC 1 +#define STR_MYSQL_JDBC 2 +#define STR_ADABAS 3 +#define STR_ORACLE_JDBC 4 +#define STR_JDBC 5 +#define STR_ODBC 6 +#define STR_DBASE 7 +#define STR_MSACCESS 8 +#define STR_MSACCESS2007 9 +#define STR_ADO 10 +#define STR_FLAT 11 +#define STR_CALC 12 +#define STR_MOZILLA 13 +#define STR_LDAP 14 +#define STR_OUTLOOK 15 +#define STR_OUTLOOKEXP 16 +#define STR_EVOLUTION 17 +#define STR_EVOLUTION_GROUPWISE 18 +#define STR_EVOLUTION_LDAP 19 +#define STR_KAB 20 +#define STR_MACAB 21 +#define STR_EMBEDDED_HSQLDB 22 +#define STR_THUNDERBIRD 23 +#define STR_MYSQL_NATIVE 24 + +#define STR_END STR_MYSQL_NATIVE + 1 + + +#endif // _DBA_MISCRES_HRC_ + diff --git a/dbaccess/source/core/inc/definitioncolumn.hxx b/dbaccess/source/core/inc/definitioncolumn.hxx new file mode 100644 index 000000000000..185e7d1426d8 --- /dev/null +++ b/dbaccess/source/core/inc/definitioncolumn.hxx @@ -0,0 +1,318 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 _DBACORE_DEFINITIONCOLUMN_HXX_ +#define _DBACORE_DEFINITIONCOLUMN_HXX_ + +#include "apitools.hxx" +#include "column.hxx" +#include "columnsettings.hxx" + +#include <com/sun/star/sdbc/DataType.hpp> +#include <com/sun/star/sdbc/ColumnValue.hpp> +#include <com/sun/star/container/XChild.hpp> + +#include <comphelper/IdPropArrayHelper.hxx> +#include <comphelper/uno3.hxx> +#include <cppuhelper/implbase1.hxx> + + +namespace dbaccess +{ + + typedef ::cppu::ImplHelper1< ::com::sun::star::container::XChild > TXChild; + // ========================================================================= + //= OTableColumnDescriptor + // ========================================================================= + /** + * provides the properties for description. A descriptor could be used to create a new table column. + */ + class OTableColumnDescriptor : public OColumn + ,public OColumnSettings + ,public ::comphelper::OPropertyArrayUsageHelper < OTableColumnDescriptor > + ,public TXChild + { + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > m_xParent; + const bool m_bActAsDescriptor; + + protected: + // <properties> + rtl::OUString m_aTypeName; + rtl::OUString m_aDescription; + rtl::OUString m_aDefaultValue; + rtl::OUString m_aAutoIncrementValue; + sal_Int32 m_nType; + sal_Int32 m_nPrecision; + sal_Int32 m_nScale; + sal_Int32 m_nIsNullable; + sal_Bool m_bAutoIncrement; + sal_Bool m_bRowVersion; + sal_Bool m_bCurrency; + // </properties> + + public: + OTableColumnDescriptor( const bool _bActAsDescriptor ) + :OColumn( !_bActAsDescriptor ) + ,m_bActAsDescriptor( _bActAsDescriptor ) + ,m_nType( ::com::sun::star::sdbc::DataType::SQLNULL ) + ,m_nPrecision( 0 ) + ,m_nScale( 0 ) + ,m_nIsNullable( ::com::sun::star::sdbc::ColumnValue::NULLABLE_UNKNOWN ) + ,m_bAutoIncrement( sal_False ) + ,m_bRowVersion( sal_False ) + ,m_bCurrency( sal_False ) + { + impl_registerProperties(); + } + + DECLARE_XINTERFACE( ) + + // com::sun::star::lang::XTypeProvider + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() throw (::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::lang::XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw(::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::container::XChild + virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL getParent( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setParent( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& Parent ) throw (::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException); + + // ::comphelper::OPropertyArrayUsageHelper + virtual ::cppu::IPropertyArrayHelper* createArrayHelper() const; + + // ::cppu::OPropertySetHelper + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(); + virtual void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue ) throw (::com::sun::star::uno::Exception); + + private: + void impl_registerProperties(); + }; + + // ========================================================================= + // = OTableColumn + // ========================================================================= + class OTableColumn; + typedef ::comphelper::OPropertyArrayUsageHelper < OTableColumn > OTableColumn_PBase; + /** describes a column of a table + */ + class OTableColumn :public OTableColumnDescriptor + ,public OTableColumn_PBase + { + protected: + virtual ~OTableColumn(); + + public: + OTableColumn(const ::rtl::OUString& _rName); + + // XTypeProvider + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() throw (::com::sun::star::uno::RuntimeException); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw(::com::sun::star::uno::RuntimeException); + + // OPropertyArrayUsageHelper + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(); + virtual ::cppu::IPropertyArrayHelper* createArrayHelper() const; + }; + + // ========================================================================= + // = OQueryColumn + // ========================================================================= + class OQueryColumn; + typedef ::comphelper::OPropertyArrayUsageHelper< OQueryColumn > OQueryColumn_PBase; + /** a column of a Query, with additional information obtained from parsing the query statement + */ + class OQueryColumn :public OTableColumnDescriptor + ,public OQueryColumn_PBase + { + // <properties> + ::rtl::OUString m_sCatalogName; + ::rtl::OUString m_sSchemaName; + ::rtl::OUString m_sTableName; + ::rtl::OUString m_sRealName; + ::rtl::OUString m_sLabel; + // </properties> + + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > m_xOriginalTableColumn; + + protected: + ~OQueryColumn(); + + 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 ::rtl::OUString i_sLabel + ); + + // XTypeProvider + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() throw (::com::sun::star::uno::RuntimeException); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw(::com::sun::star::uno::RuntimeException); + + // *Property* + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(); + virtual ::cppu::IPropertyArrayHelper* createArrayHelper() const; + virtual void SAL_CALL getFastPropertyValue( ::com::sun::star::uno::Any& rValue, sal_Int32 nHandle ) const; + + private: + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > + impl_determineOriginalTableColumn( + const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _rxConnection + ); + + using ::cppu::OPropertySetHelper::getFastPropertyValue; + }; + + // ========================================================================= + // = OColumnWrapper + // ========================================================================= + /** + * describes all properties for a columns of a table. Only the view parts are provided + * directly, all the other parts are derived from a driver implementation + */ + class OColumnWrapper :public OColumn + { + protected: + // definition which is provided by a driver! + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > + m_xAggregate; + + sal_Int32 m_nColTypeID; + + protected: + OColumnWrapper( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rCol, const bool _bNameIsReadOnly ); + virtual ~OColumnWrapper(); + + public: + virtual void SAL_CALL getFastPropertyValue( + ::com::sun::star::uno::Any& rValue, + sal_Int32 nHandle + ) const; + virtual sal_Bool SAL_CALL convertFastPropertyValue( + ::com::sun::star::uno::Any & rConvertedValue, + ::com::sun::star::uno::Any & rOldValue, + sal_Int32 nHandle, + const ::com::sun::star::uno::Any& rValue ) + throw (::com::sun::star::lang::IllegalArgumentException); + virtual void SAL_CALL setFastPropertyValue_NoBroadcast( + sal_Int32 nHandle, + const ::com::sun::star::uno::Any& rValue + ) + throw (::com::sun::star::uno::Exception); + + virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& aIdentifier ) throw(::com::sun::star::uno::RuntimeException); + + protected: + ::rtl::OUString impl_getPropertyNameFromHandle( const sal_Int32 _nHandle ) const; + + protected: + using OColumn::getFastPropertyValue; + }; + + // ========================================================================= + // = OTableColumnDescriptorWrapper + // ========================================================================= + /** + * provides the properties for description. A descriptor could be used to create a new table column. + */ + class OTableColumnDescriptorWrapper :public OColumnWrapper + ,public OColumnSettings + ,public ::comphelper::OIdPropertyArrayUsageHelper < OTableColumnDescriptorWrapper > + { + const bool m_bPureWrap; + const bool m_bIsDescriptor; + + public: + OTableColumnDescriptorWrapper(const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& rCol, + const bool _bPureWrap, const bool _bIsDescriptor ); + + // com::sun::star::lang::XTypeProvider + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() throw (::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::lang::XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw(::com::sun::star::uno::RuntimeException); + + // OIdPropertyArrayUsageHelper + virtual ::cppu::IPropertyArrayHelper* createArrayHelper(sal_Int32 nId) const; + + // cppu::OPropertySetHelper + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(); + virtual void SAL_CALL getFastPropertyValue( + ::com::sun::star::uno::Any& rValue, + sal_Int32 nHandle + ) const; + virtual sal_Bool SAL_CALL convertFastPropertyValue( + ::com::sun::star::uno::Any & rConvertedValue, + ::com::sun::star::uno::Any & rOldValue, + sal_Int32 nHandle, + const ::com::sun::star::uno::Any& rValue ) + throw (::com::sun::star::lang::IllegalArgumentException); + virtual void SAL_CALL setFastPropertyValue_NoBroadcast( + sal_Int32 nHandle, + const ::com::sun::star::uno::Any& rValue + ) + throw (::com::sun::star::uno::Exception); + + protected: + using OColumnWrapper::getFastPropertyValue; + }; + + // ========================================================================= + // = OTableColumnWrapper + // ========================================================================= + /** + * describes all properties for a columns of a table. Only the view parts are provided + * directly, all the other parts are derived from a driver implementation + */ + class OTableColumnWrapper :public OTableColumnDescriptorWrapper + ,public ::comphelper::OIdPropertyArrayUsageHelper < OTableColumnWrapper > + { + protected: + ~OTableColumnWrapper(); + + public: + OTableColumnWrapper( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& rCol, + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& rColDefintion, + const bool _bPureWrap ); + + // ::com::sun::star::lang::XTypeProvider + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() throw (::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::lang::XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw(::com::sun::star::uno::RuntimeException); + + // OIdPropertyArrayUsageHelper + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(); + virtual ::cppu::IPropertyArrayHelper* createArrayHelper(sal_Int32 nId) const; + }; +} +#endif // _DBACORE_DEFINITIONCOLUMN_HXX_ + diff --git a/dbaccess/source/core/inc/definitioncontainer.hxx b/dbaccess/source/core/inc/definitioncontainer.hxx new file mode 100644 index 000000000000..d70a0813e18c --- /dev/null +++ b/dbaccess/source/core/inc/definitioncontainer.hxx @@ -0,0 +1,375 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 _DBA_CORE_DEFINITIONCONTAINER_HXX_ +#define _DBA_CORE_DEFINITIONCONTAINER_HXX_ + +#ifndef _CPPUHELPER_INTERFACECONTAINER_HXX_ +#include <cppuhelper/interfacecontainer.hxx> +#endif +#ifndef _CPPUHELPER_IMPLBASE7_HXX_ +#include <cppuhelper/implbase7.hxx> +#endif +#ifndef _COMPHELPER_STLTYPES_HXX_ +#include <comphelper/stl_types.hxx> +#endif +#ifndef _OSL_MUTEX_HXX_ +#include <osl/mutex.hxx> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XCHILD_HPP_ +#include <com/sun/star/container/XChild.hpp> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XNAMECONTAINER_HPP_ +#include <com/sun/star/container/XNameContainer.hpp> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XCONTAINER_HPP_ +#include <com/sun/star/container/XContainer.hpp> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XENUMERATIONACCESS_HPP_ +#include <com/sun/star/container/XEnumerationAccess.hpp> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XINDEXACCESS_HPP_ +#include <com/sun/star/container/XIndexAccess.hpp> +#endif +#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_ +#include <com/sun/star/lang/XServiceInfo.hpp> +#endif +#ifndef _COM_SUN_STAR_LANG_DISPOSEDEXCEPTION_HPP_ +#include <com/sun/star/lang/DisposedException.hpp> +#endif +#ifndef _COM_SUN_STAR_BEANS_XPROPERTYCHANGELISTENER_HPP_ +#include <com/sun/star/beans/XPropertyChangeListener.hpp> +#endif +#ifndef _COM_SUN_STAR_BEANS_XVETOABLECHANGELISTENER_HPP_ +#include <com/sun/star/beans/XVetoableChangeListener.hpp> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XCONTAINERAPPROVEBROADCASTER_HPP_ +#include <com/sun/star/container/XContainerApproveBroadcaster.hpp> +#endif +#ifndef DBA_CONTENTHELPER_HXX +#include "ContentHelper.hxx" +#endif +#ifndef DBACCESS_CONTAINERAPPROVE_HXX +#include "containerapprove.hxx" +#endif +#ifndef _COMPHELPER_UNO3_HXX_ +#include <comphelper/uno3.hxx> +#endif +#ifndef _RTL_REF_HXX_ +#include <rtl/ref.hxx> +#endif +#ifndef _DBASHARED_APITOOLS_HXX_ +#include "apitools.hxx" +#endif +//........................................................................ +namespace dbaccess +{ +//........................................................................ + +class ODefinitionContainer_Impl : public OContentHelper_Impl +{ +public: + typedef ::std::map< ::rtl::OUString, TContentPtr > NamedDefinitions; + typedef NamedDefinitions::iterator iterator; + typedef NamedDefinitions::const_iterator const_iterator; + +private: + NamedDefinitions m_aDefinitions; + +public: + inline size_t size() const { return m_aDefinitions.size(); } + + inline const_iterator begin() const { return m_aDefinitions.begin(); } + inline const_iterator end() const { return m_aDefinitions.end(); } + + inline const_iterator find( const ::rtl::OUString& _rName ) const { return m_aDefinitions.find( _rName ); } + const_iterator find( TContentPtr _pDefinition ) const; + + inline void erase( const ::rtl::OUString& _rName ) { m_aDefinitions.erase( _rName ); } + void erase( TContentPtr _pDefinition ); + + inline void insert( const ::rtl::OUString& _rName, TContentPtr _pDefinition ) + { + m_aDefinitions.insert( NamedDefinitions::value_type( _rName, _pDefinition ) ); + } + +private: + iterator find( TContentPtr _pDefinition ); + // (for the moment, this is private. Make it public if needed. If really needed.) +}; + +//========================================================================== +//= ODefinitionContainer - base class of collections of database definition +//= documents +//========================================================================== +typedef ::cppu::ImplHelper7 < ::com::sun::star::container::XIndexAccess + , ::com::sun::star::container::XNameContainer + , ::com::sun::star::container::XEnumerationAccess + , ::com::sun::star::container::XContainer + , ::com::sun::star::container::XContainerApproveBroadcaster + , ::com::sun::star::beans::XPropertyChangeListener + , ::com::sun::star::beans::XVetoableChangeListener + > ODefinitionContainer_Base; + +class ODefinitionContainer + :public OContentHelper + ,public ODefinitionContainer_Base +{ +protected: + DECLARE_STL_USTRINGACCESS_MAP(::com::sun::star::uno::WeakReference< ::com::sun::star::ucb::XContent >, Documents); + DECLARE_STL_VECTOR(Documents::iterator, DocumentsIndexAccess); + + enum ContainerOperation + { + E_REPLACED, + E_REMOVED, + E_INSERTED + }; + + enum ListenerType + { + ApproveListeners, + ContainerListemers + }; + +private: + PContainerApprove m_pElementApproval; + +protected: + // we can't just hold a vector of XContentRefs, as after initialization they're all empty + // cause we load them only on access + DocumentsIndexAccess m_aDocuments; // for a efficient index access + Documents m_aDocumentMap; // for a efficient name access + + ::cppu::OInterfaceContainerHelper + m_aApproveListeners; + ::cppu::OInterfaceContainerHelper + m_aContainerListeners; + + sal_Bool m_bInPropertyChange; + bool m_bCheckSlash; + +protected: + /** Additionally to our own approvals which new elements must pass, derived classes + can specifiy an additional approval instance here. + + Every time a new element is inserted into the container (or an element is replaced + with a new one), this new element must pass our own internal approval, plus the approval + given here. + */ + void setElementApproval( PContainerApprove _pElementApproval ) { m_pElementApproval = _pElementApproval; } + PContainerApprove getElementApproval() const { return m_pElementApproval; } + +protected: + virtual ~ODefinitionContainer(); + + inline const ODefinitionContainer_Impl& getDefinitions() const + { + return dynamic_cast< const ODefinitionContainer_Impl& >( *m_pImpl.get() ); + } + + inline ODefinitionContainer_Impl& getDefinitions() + { + return dynamic_cast< ODefinitionContainer_Impl& >( *m_pImpl.get() ); + } +public: + /** constructs the container. + */ + ODefinitionContainer( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _xORB + , const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _xParentContainer + , const TContentPtr& _pImpl + , bool _bCheckSlash = true + ); + +// ::com::sun::star::uno::XInterface + DECLARE_XINTERFACE( ) +// com::sun::star::lang::XTypeProvider + DECLARE_TYPEPROVIDER( ); + +// ::com::sun::star::lang::XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw(::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::container::XElementAccess + virtual ::com::sun::star::uno::Type SAL_CALL getElementType( ) throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL hasElements( ) throw(::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::container::XEnumerationAccess + virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XEnumeration > SAL_CALL createEnumeration( ) throw(::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::container::XIndexAccess + virtual sal_Int32 SAL_CALL getCount( ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Any SAL_CALL getByIndex( sal_Int32 _nIndex ) throw(::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::container::XNameContainer + virtual void SAL_CALL insertByName( const ::rtl::OUString& _rName, 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 removeByName( const ::rtl::OUString& _rName ) throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::container::XNameReplace + virtual void SAL_CALL replaceByName( const ::rtl::OUString& _rName, const ::com::sun::star::uno::Any& aElement ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::container::XNameAccess + virtual ::com::sun::star::uno::Any SAL_CALL getByName( const ::rtl::OUString& aName ) throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getElementNames( ) throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName ) throw(::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::container::XContainer + virtual void SAL_CALL addContainerListener( const ::com::sun::star::uno::Reference< ::com::sun::star::container::XContainerListener >& xListener ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeContainerListener( const ::com::sun::star::uno::Reference< ::com::sun::star::container::XContainerListener >& xListener ) throw(::com::sun::star::uno::RuntimeException); + + // XContainerApproveBroadcaster + virtual void SAL_CALL addContainerApproveListener( const ::com::sun::star::uno::Reference< ::com::sun::star::container::XContainerApproveListener >& Listener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeContainerApproveListener( const ::com::sun::star::uno::Reference< ::com::sun::star::container::XContainerApproveListener >& Listener ) throw (::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::lang::XEventListener + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw(::com::sun::star::uno::RuntimeException); + + // XPropertyChangeListener + virtual void SAL_CALL propertyChange( const ::com::sun::star::beans::PropertyChangeEvent& evt ) throw (::com::sun::star::uno::RuntimeException); + // XVetoableChangeListener + virtual void SAL_CALL vetoableChange( const ::com::sun::star::beans::PropertyChangeEvent& aEvent ) throw (::com::sun::star::beans::PropertyVetoException, ::com::sun::star::uno::RuntimeException); + +protected: + // helper + virtual void SAL_CALL disposing(); + + /** create a object from it's persistent data within the configuration. To be overwritten by derived classes. + @param _rName the name the object has within the container + @return the newly created object or an empty reference if somthing went wrong + */ + virtual ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContent > createObject( + const ::rtl::OUString& _rName) = 0; + + /** get the object specified by the given name. If desired, the object will be read if not already done so.<BR> + @param _rName the object name + @param _bReadIfNeccessary if sal_True, the object will be created if necessary + @return the property set interface of the object. Usually the return value is not NULL, but + if so, then the object could not be read from the configuration + @throws NoSuchElementException if there is no object with the given name. + @see createObject + */ + virtual ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContent > + implGetByName(const ::rtl::OUString& _rName, sal_Bool _bCreateIfNecessary) throw (::com::sun::star::container::NoSuchElementException); + + /** quickly checks if there already is an element with a given name. No access to the configuration occures, i.e. + if there is such an object which is not already loaded, it won't be loaded now. + @param _rName the object name to check + @return sal_True if there already exists such an object + */ + virtual sal_Bool checkExistence(const ::rtl::OUString& _rName); + + /** append a new object to the container. No plausibility checks are done, e.g. if the object is non-NULL or + if the name is already used by another object or anything like this. This method is for derived classes + which may support different methods to create and/or append objects, and don't want to deal with the + internal structures of this class.<BR> + The old component will not be disposed, this is the callers responsibility, too. + @param _rName the name of the new object + @param _rxNewObject the new object (not surprising, is it ?) + @see createConfigKey + @see implReplace + @see implRemove + */ + void implAppend( + const ::rtl::OUString& _rName, + const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContent >& _rxNewObject + ); + + /** remove all references to an object from the container. No plausibility checks are done, e.g. whether + or not there exists an object with the given name. This is the responsibility of the caller.<BR> + Additionally the node for the given object will be removed from the registry (including all sub nodes).<BR> + The old component will not be disposed, this is the callers responsibility, too. + @param _rName the objects name + @see implReplace + @see implAppend + */ + void implRemove(const ::rtl::OUString& _rName); + + /** remove a object in the container. No plausibility checks are done, e.g. whether + or not there exists an object with the given name or the object is non-NULL. This is the responsibility of the caller.<BR> + Additionally all object-related informations within the registry will be deleted. The new object config node, + where the caller may want to store the new objects information, is returned.<BR> + The old component will not be disposed, this is the callers responsibility, too. + @param _rName the objects name + @param _rxNewObject the new object + @param _rNewObjectNode the configuration node where the new object may be stored + @see implAppend + @see implRemove + */ + void implReplace( + const ::rtl::OUString& _rName, + const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContent >& _rxNewObject + ); + + /** notifies our container/approve listeners + */ + void notifyByName( + ::osl::ResettableMutexGuard& _rGuard, + const ::rtl::OUString& _rName, + const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContent >& _xNewElement, + const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContent >& xOldElement, + ContainerOperation _eOperation, + ListenerType _eType + ); + + inline SAL_CALL operator ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > () const + { + return const_cast< XContainer* >( static_cast< const XContainer* >( this ) ); + } + +private: + void addObjectListener(const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContent >& _xNewObject); + void removeObjectListener(const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContent >& _xNewObject); + + /** approve that the object given may be inserted into the container. Should be overloaded by derived classes, + the default implementation just checks the object to be non-void. + + @throws IllegalArgumentException + if the name or the object are invalid + @throws ElementExistException + if the object already exists in the container, or another object with the same name + already exists + @throws WrappedTargetException + if another error occures which prevents insertion of the object into the container + */ + void approveNewObject( + const ::rtl::OUString& _sName, + const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContent >& _rxObject + ) const; + + inline bool impl_haveAnyListeners_nothrow() const + { + return ( m_aContainerListeners.getLength() > 0 ) || ( m_aApproveListeners.getLength() > 0 ); + } +}; + +//........................................................................ +} // namespace dbaccess +//........................................................................ + +#endif // _DBA_CORE_DEFINITIONCONTAINER_HXX_ + diff --git a/dbaccess/source/core/inc/module_dba.hxx b/dbaccess/source/core/inc/module_dba.hxx new file mode 100644 index 000000000000..03a5faefa1d2 --- /dev/null +++ b/dbaccess/source/core/inc/module_dba.hxx @@ -0,0 +1,45 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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_MODULE_DBA_HXX +#define DBACCESS_MODULE_DBA_HXX + +#include <unotools/componentresmodule.hxx> + +//........................................................................ +namespace dba +{ +//........................................................................ + + DEFINE_MODULE( DbaModule, DbaClient, DbaRes ) + +//........................................................................ +} // namespace sdbtools +//........................................................................ + +#endif // DBACCESS_MODULE_DBA_HXX + diff --git a/dbaccess/source/core/inc/object.hxx b/dbaccess/source/core/inc/object.hxx new file mode 100644 index 000000000000..917cc9e05e42 --- /dev/null +++ b/dbaccess/source/core/inc/object.hxx @@ -0,0 +1,40 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 _DBA_OBJECT_HXX_ +#define _DBA_OBJECT_HXX_ + +enum ObjectType +{ + dbaTable, + dbaQuery, + dbaForm, + dbaReport +}; + +#endif // _DBA_OBJECT_HXX_ + diff --git a/dbaccess/source/core/inc/objectnameapproval.hxx b/dbaccess/source/core/inc/objectnameapproval.hxx new file mode 100644 index 000000000000..bea104c77443 --- /dev/null +++ b/dbaccess/source/core/inc/objectnameapproval.hxx @@ -0,0 +1,95 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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_OBJECTNAMEAPPROVAL_HXX +#define DBACCESS_OBJECTNAMEAPPROVAL_HXX + +#ifndef DBACCESS_CONTAINERAPPROVE_HXX +#include "containerapprove.hxx" +#endif + +/** === begin UNO includes === **/ +#ifndef _COM_SUN_STAR_SDBC_XCONNECTION_HPP_ +#include <com/sun/star/sdbc/XConnection.hpp> +#endif +/** === end UNO includes === **/ + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + + //==================================================================== + //= ObjectNameApproval + //==================================================================== + struct ObjectNameApproval_Impl; + /** implementation of the IContainerApprove interface which approves + elements for insertion into a query or tables container. + + The only check done by this instance is whether the query name is + not already used, taking into account that in some databases, queries + and tables share the same namespace. + + The class is not thread-safe. + */ + class ObjectNameApproval : public IContainerApprove + { + ::std::auto_ptr< ObjectNameApproval_Impl > m_pImpl; + + public: + enum ObjectType + { + TypeQuery, + TypeTable + }; + + public: + /** constructs the instance + + @param _rxConnection + the connection relative to which the names should be checked. This connection + will be held weak. In case it is closed, subsequent calls to this instance's + methods throw a DisposedException. + @param _eType + specifies which type of objects is to be approved with this instance + */ + ObjectNameApproval( + const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _rxConnection, + ObjectType _eType + ); + virtual ~ObjectNameApproval(); + + // IContainerApprove + virtual void SAL_CALL approveElement( const ::rtl::OUString& _rName, const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxElement ); + + }; + +//........................................................................ +} // namespace dbaccess +//........................................................................ + +#endif // DBACCESS_OBJECTNAMEAPPROVAL_HXX diff --git a/dbaccess/source/core/inc/preparedstatement.hxx b/dbaccess/source/core/inc/preparedstatement.hxx new file mode 100644 index 000000000000..e0df114b22af --- /dev/null +++ b/dbaccess/source/core/inc/preparedstatement.hxx @@ -0,0 +1,132 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 _DBA_COREAPI_PREPAREDSTATEMENT_HXX_ +#define _DBA_COREAPI_PREPAREDSTATEMENT_HXX_ + +#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_ +#include <com/sun/star/lang/XServiceInfo.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XPREPAREDSTATEMENT_HPP_ +#include <com/sun/star/sdbc/XPreparedStatement.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBCX_XCOLUMNSSUPPLIER_HPP_ +#include <com/sun/star/sdbcx/XColumnsSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XPARAMETERS_HPP_ +#include <com/sun/star/sdbc/XParameters.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XRESULTSETMETADATASUPPLIER_HPP_ +#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XPARAMETERS_HPP_ +#include <com/sun/star/sdbc/XParameters.hpp> +#endif +#ifndef _DBA_COREAPI_STATEMENT_HXX_ +#include <statement.hxx> +#endif +#ifndef _DBA_COREAPI_COLUMN_HXX_ +#include <column.hxx> +#endif + +namespace dbaccess +{ + //************************************************************ + // OPreparedStatement + //************************************************************ + class OPreparedStatement : public OStatementBase, + public ::com::sun::star::sdbc::XPreparedStatement, + public ::com::sun::star::sdbc::XParameters, + public ::com::sun::star::sdbc::XResultSetMetaDataSupplier, + public ::com::sun::star::sdbcx::XColumnsSupplier, + public ::com::sun::star::lang::XServiceInfo + { + protected: + OColumns* m_pColumns; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XParameters > m_xAggregateAsParameters; + + public: + OPreparedStatement(const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection > & _xConn, + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > & _xStatement); + virtual ~OPreparedStatement(); + + // ::com::sun::star::lang::XTypeProvider + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes() throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() throw (::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::uno::XInterface + virtual ::com::sun::star::uno::Any SAL_CALL queryInterface( const ::com::sun::star::uno::Type & rType ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL acquire() throw(); + virtual void SAL_CALL release() throw(); + + // ::com::sun::star::lang::XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw(::com::sun::star::uno::RuntimeException); + + // OComponentHelper + virtual void SAL_CALL disposing(void); + + // ::com::sun::star::sdbc::XPreparedStatement + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet > SAL_CALL executeQuery( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL executeUpdate( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL execute( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection > SAL_CALL getConnection( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbcx::XColumnsSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > SAL_CALL getColumns( ) throw(::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbc::XResultSetMetaDataSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSetMetaData > SAL_CALL getMetaData( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbc::XParameters + virtual void SAL_CALL setNull( sal_Int32 parameterIndex, sal_Int32 sqlType ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setObjectNull( sal_Int32 parameterIndex, sal_Int32 sqlType, const ::rtl::OUString& typeName ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setBoolean( sal_Int32 parameterIndex, sal_Bool x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setByte( sal_Int32 parameterIndex, sal_Int8 x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setShort( sal_Int32 parameterIndex, sal_Int16 x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setInt( sal_Int32 parameterIndex, sal_Int32 x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setLong( sal_Int32 parameterIndex, sal_Int64 x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setFloat( sal_Int32 parameterIndex, float x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setDouble( sal_Int32 parameterIndex, double x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setString( sal_Int32 parameterIndex, const ::rtl::OUString& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setBytes( sal_Int32 parameterIndex, const ::com::sun::star::uno::Sequence< sal_Int8 >& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setDate( sal_Int32 parameterIndex, const ::com::sun::star::util::Date& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setTime( sal_Int32 parameterIndex, const ::com::sun::star::util::Time& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setTimestamp( sal_Int32 parameterIndex, const ::com::sun::star::util::DateTime& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setBinaryStream( sal_Int32 parameterIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setCharacterStream( sal_Int32 parameterIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setObject( sal_Int32 parameterIndex, const ::com::sun::star::uno::Any& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setObjectWithInfo( sal_Int32 parameterIndex, const ::com::sun::star::uno::Any& x, sal_Int32 targetSqlType, sal_Int32 scale ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setRef( sal_Int32 parameterIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRef >& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setBlob( sal_Int32 parameterIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XBlob >& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setClob( sal_Int32 parameterIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XClob >& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setArray( sal_Int32 parameterIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XArray >& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL clearParameters( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + }; +} +#endif // _DBA_COREAPI_PREPAREDSTATEMENT_HXX_ + diff --git a/dbaccess/source/core/inc/querycomposer.hxx b/dbaccess/source/core/inc/querycomposer.hxx new file mode 100644 index 000000000000..839e5e39a772 --- /dev/null +++ b/dbaccess/source/core/inc/querycomposer.hxx @@ -0,0 +1,139 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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_CORE_API_QUERYCOMPOSER_HXX +#define DBACCESS_CORE_API_QUERYCOMPOSER_HXX + +#ifndef _CONNECTIVITY_COMMONTOOLS_HXX_ +#include <connectivity/CommonTools.hxx> +#endif +#ifndef _COM_SUN_STAR_SDB_XSQLQUERYCOMPOSER_HPP_ +#include <com/sun/star/sdb/XSQLQueryComposer.hpp> +#endif +#ifndef _COM_SUN_STAR_SDB_XPARAMETERSSUPPLIER_HPP_ +#include <com/sun/star/sdb/XParametersSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBCX_XTABLESSUPPLIER_HPP_ +#include <com/sun/star/sdbcx/XTablesSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBCX_XCOLUMNSSUPPLIER_HPP_ +#include <com/sun/star/sdbcx/XColumnsSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_ +#include <com/sun/star/lang/XServiceInfo.hpp> +#endif +#ifndef _COM_SUN_STAR_SCRIPT_XTYPECONVERTER_HPP_ +#include <com/sun/star/script/XTypeConverter.hpp> +#endif +#ifndef _CPPUHELPER_IMPLBASE5_HXX_ +#include <cppuhelper/implbase5.hxx> +#endif +#ifndef _CONNECTIVITY_PARSE_SQLITERATOR_HXX_ +#include <connectivity/sqliterator.hxx> +#endif +#ifndef _CONNECTIVITY_SQLPARSE_HXX +#include <connectivity/sqlparse.hxx> +#endif +#ifndef _DBASHARED_APITOOLS_HXX_ +#include "apitools.hxx" +#endif +#ifndef _COMPHELPER_BROADCASTHELPER_HXX_ +#include <comphelper/broadcasthelper.hxx> +#endif +#ifndef _COM_SUN_STAR_SDB_XSINGLESELECTQUERYCOMPOSER_HPP_ +#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp> +#endif + + + +namespace com { namespace sun { namespace star { namespace util { + class XNumberFormatsSupplier; + class XNumberFormatter; +}}}} + +namespace dbaccess +{ + typedef ::cppu::ImplHelper5< ::com::sun::star::sdb::XSQLQueryComposer, + ::com::sun::star::sdb::XParametersSupplier, + ::com::sun::star::sdbcx::XTablesSupplier, + ::com::sun::star::sdbcx::XColumnsSupplier, + ::com::sun::star::lang::XServiceInfo > OQueryComposer_BASE; + + class OPrivateColumns; + class OPrivateTables; + + class OQueryComposer : public ::comphelper::OBaseMutex, + public OSubComponent, + public OQueryComposer_BASE + { + ::std::vector< ::rtl::OUString> m_aFilters; + ::std::vector< ::rtl::OUString> m_aOrders; + ::rtl::OUString m_sOrgFilter; + ::rtl::OUString m_sOrgOrder; + ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XSingleSelectQueryComposer> m_xComposer; + ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XSingleSelectQueryComposer> m_xComposerHelper; + + protected: + virtual void SAL_CALL disposing(); + virtual ~OQueryComposer(); + public: + + OQueryComposer( const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection>& _xConnection ); + + // ::com::sun::star::lang::XTypeProvider + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes() throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() throw (::com::sun::star::uno::RuntimeException); + // com::sun::star::lang::XUnoTunnel + virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& aIdentifier ) throw(::com::sun::star::uno::RuntimeException); + // ::com::sun::star::uno::XInterface + virtual ::com::sun::star::uno::Any SAL_CALL queryInterface( const ::com::sun::star::uno::Type & rType ) + throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL acquire() throw(); + virtual void SAL_CALL release() throw(); + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw(::com::sun::star::uno::RuntimeException); + // XSQLQueryComposer + virtual ::rtl::OUString SAL_CALL getQuery( ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setQuery( const ::rtl::OUString& command ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getComposedQuery( ) throw(::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getFilter( ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > > SAL_CALL getStructuredFilter( ) throw(::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getOrder( ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL appendFilterByColumn( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& column ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL appendOrderByColumn( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& column, sal_Bool ascending ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setFilter( const ::rtl::OUString& filter ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setOrder( const ::rtl::OUString& order ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + // XTablesSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > SAL_CALL getTables( ) throw(::com::sun::star::uno::RuntimeException); + // XColumnsSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > SAL_CALL getColumns( ) throw(::com::sun::star::uno::RuntimeException); + // XParametersSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess > SAL_CALL getParameters( ) throw(::com::sun::star::uno::RuntimeException); + }; +} +#endif // DBACCESS_CORE_API_QUERYCOMPOSER_HXX diff --git a/dbaccess/source/core/inc/querycontainer.hxx b/dbaccess/source/core/inc/querycontainer.hxx new file mode 100644 index 000000000000..9502a7002aa7 --- /dev/null +++ b/dbaccess/source/core/inc/querycontainer.hxx @@ -0,0 +1,234 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 _DBA_CORE_QUERYCONTAINER_HXX_ +#define _DBA_CORE_QUERYCONTAINER_HXX_ + +#ifndef _CPPUHELPER_IMPLBASE5_HXX_ +#include <cppuhelper/implbase5.hxx> +#endif +#ifndef _COMPHELPER_STLTYPES_HXX_ +#include <comphelper/stl_types.hxx> +#endif +#ifndef _CPPUHELPER_INTERFACECONTAINER_HXX_ +#include <cppuhelper/interfacecontainer.hxx> +#endif + +/** === begin UNO includes == **/ +#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_ +#include <com/sun/star/beans/XPropertySet.hpp> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XENUMERATIONACCESS_HPP_ +#include <com/sun/star/container/XEnumerationAccess.hpp> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XCONTAINERLISTENER_HPP_ +#include <com/sun/star/container/XContainerListener.hpp> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XNAMECONTAINER_HPP_ +#include <com/sun/star/container/XNameContainer.hpp> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_ +#include <com/sun/star/container/XNameAccess.hpp> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XINDEXACCESS_HPP_ +#include <com/sun/star/container/XIndexAccess.hpp> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XCONTAINER_HPP_ +#include <com/sun/star/container/XContainer.hpp> +#endif +#ifndef _COM_SUN_STAR_UTIL_XREFRESHABLE_HPP_ +#include <com/sun/star/util/XRefreshable.hpp> +#endif +#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_ +#include <com/sun/star/lang/XServiceInfo.hpp> +#endif +#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_ +#include <com/sun/star/uno/Sequence.hxx> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XNAMECONTAINER_HPP_ +#include <com/sun/star/container/XNameContainer.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBCX_XDATADESCRIPTORFACTORY_HPP_ +#include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBCX_XAPPEND_HPP_ +#include <com/sun/star/sdbcx/XAppend.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBCX_XDROP_HPP_ +#include <com/sun/star/sdbcx/XDrop.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XCONNECTION_HPP_ +#include <com/sun/star/sdbc/XConnection.hpp> +#endif +#ifndef _COM_SUN_STAR_BEANS_XPROPERTYCHANGELISTENER_HPP_ +#include <com/sun/star/beans/XPropertyChangeListener.hpp> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XCONTAINERAPPROVELISTENER_HPP_ +#include <com/sun/star/container/XContainerApproveListener.hpp> +#endif +/** === end UNO includes === **/ + +#ifndef _DBA_CORE_DEFINITIONCONTAINER_HXX_ +#include "definitioncontainer.hxx" +#endif +#ifndef _DBASHARED_APITOOLS_HXX_ +#include "apitools.hxx" +#endif + +namespace dbtools +{ + class IWarningsContainer; +} + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + + typedef ::cppu::ImplHelper5 < ::com::sun::star::container::XContainerListener + , ::com::sun::star::container::XContainerApproveListener + , ::com::sun::star::sdbcx::XDataDescriptorFactory + , ::com::sun::star::sdbcx::XAppend + , ::com::sun::star::sdbcx::XDrop + > OQueryContainer_Base; + + //========================================================================== + //= OQueryContainer + //========================================================================== + class OQueryContainer; + class OContainerListener; + class OQuery; + class OQueryContainer : public ODefinitionContainer + , public OQueryContainer_Base + { + protected: + ::dbtools::IWarningsContainer* m_pWarnings; + ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer > + m_xCommandDefinitions; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection > + m_xConnection; + // possible actions on our "aggregate" + enum AGGREGATE_ACTION { NONE, INSERTING, FLUSHING }; + AGGREGATE_ACTION m_eDoingCurrently; + + OContainerListener* m_pCommandsListener; + + // ------------------------------------------------------------------------ + /** a class which automatically resets m_eDoingCurrently in it's destructor + */ + class OAutoActionReset; // just for the following friend declaration + friend class OAutoActionReset; + class OAutoActionReset + { + OQueryContainer* m_pActor; + public: + OAutoActionReset(OQueryContainer* _pActor) : m_pActor(_pActor) { } + ~OAutoActionReset() { m_pActor->m_eDoingCurrently = NONE; } + }; + + // ODefinitionContainer + virtual ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContent > createObject( const ::rtl::OUString& _rName); + virtual sal_Bool checkExistence(const ::rtl::OUString& _rName); + + // helper + virtual void SAL_CALL disposing(); + virtual ~OQueryContainer(); + public: + /** ctor of the container. The parent has to support the <type scope="com::sun::star::sdbc">XConnection</type> + interface.<BR> + + @param _pWarnings + specifies a warnings container (May be <NULL/>) + + Any errors which occur during the lifetime of the query container, + which cannot be reported as exceptionts (for instance in methods where throwing an SQLException is + not allowed) will be appended to this container.</p> + <p>The caller is responsible for ensuring the lifetime of the object pointed to by this parameter. + */ + OQueryContainer( + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >& _rxCommandDefinitions, + const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _rxConn, + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB, + ::dbtools::IWarningsContainer* _pWarnings + ); + + DECLARE_XINTERFACE( ) + DECLARE_XTYPEPROVIDER( ) + DECLARE_SERVICE_INFO(); + + // ::com::sun::star::container::XContainerListener + virtual void SAL_CALL elementInserted( const ::com::sun::star::container::ContainerEvent& Event ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL elementRemoved( const ::com::sun::star::container::ContainerEvent& Event ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL elementReplaced( const ::com::sun::star::container::ContainerEvent& Event ) throw(::com::sun::star::uno::RuntimeException); + + // XContainerApproveListener + virtual ::com::sun::star::uno::Reference< ::com::sun::star::util::XVeto > SAL_CALL approveInsertElement( const ::com::sun::star::container::ContainerEvent& Event ) throw (::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::util::XVeto > SAL_CALL approveReplaceElement( const ::com::sun::star::container::ContainerEvent& Event ) throw (::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::util::XVeto > SAL_CALL approveRemoveElement( const ::com::sun::star::container::ContainerEvent& Event ) throw (::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::lang::XEventListener + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw(::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbcx::XDataDescriptorFactory + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > SAL_CALL createDataDescriptor( ) throw(::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbcx::XAppend + virtual void SAL_CALL appendByDescriptor( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& descriptor ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::container::ElementExistException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbcx::XDrop + virtual void SAL_CALL dropByName( const ::rtl::OUString& elementName ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL dropByIndex( sal_Int32 index ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::container::XElementAccess + virtual sal_Bool SAL_CALL hasElements( ) throw(::com::sun::star::uno::RuntimeException); + // ::com::sun::star::container::XIndexAccess + virtual sal_Int32 SAL_CALL getCount( ) throw(::com::sun::star::uno::RuntimeException); + // ::com::sun::star::container::XNameAccess + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getElementNames( ) throw(::com::sun::star::uno::RuntimeException); + + protected: + // OContentHelper overridables + virtual ::rtl::OUString determineContentType() const; + + private: + // helper + /** create a query object wrapping a CommandDefinition given by name. To retrieve the object, the CommandDescription + container will be asked for the given name.<BR> + The returned object is acquired once. + */ + ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContent > implCreateWrapper(const ::rtl::OUString& _rName); + /// create a query object wrapping a CommandDefinition. The returned object is acquired once. + ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContent > implCreateWrapper(const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContent >& _rxCommandDesc); + + }; +//........................................................................ +} // namespace dbaccess +//........................................................................ + +#endif // _DBA_CORE_QUERYCONTAINER_HXX_ + + 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 new file mode 100644 index 000000000000..d6044a6b9110 --- /dev/null +++ b/dbaccess/source/core/inc/sdbcoretools.hxx @@ -0,0 +1,88 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 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 +{ + class ComponentContext; +} + +//......................................................................... +namespace dbaccess +{ +//......................................................................... + + // ----------------------------------------------------------------------------- + void notifyDataSourceModified(const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxObject,sal_Bool _bModified); + + // ----------------------------------------------------------------------------- + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > + getDataSource( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxDependentObject ); + + // ----------------------------------------------------------------------------- + + // ----------------------------------------------------------------------------- + /** 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 +//......................................................................... + +#endif // DBACORE_SDBCORETOOLS_HXX + diff --git a/dbaccess/source/core/inc/statement.hxx b/dbaccess/source/core/inc/statement.hxx new file mode 100644 index 000000000000..ae821c7a516b --- /dev/null +++ b/dbaccess/source/core/inc/statement.hxx @@ -0,0 +1,220 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 _DBA_COREAPI_STATEMENT_HXX_ +#define _DBA_COREAPI_STATEMENT_HXX_ + +#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_ +#include <com/sun/star/lang/XServiceInfo.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XSTATEMENT_HPP_ +#include <com/sun/star/sdbc/XStatement.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XCONNECTION_HPP_ +#include <com/sun/star/sdbc/XConnection.hpp> +#endif +#ifndef _COM_SUN_STAR_UTIL_XCANCELLABLE_HPP_ +#include <com/sun/star/util/XCancellable.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XWARNINGSSUPPLIER_HPP_ +#include <com/sun/star/sdbc/XWarningsSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XCLOSEABLE_HPP_ +#include <com/sun/star/sdbc/XCloseable.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XMULTIPLERESULTS_HDL_ +#include <com/sun/star/sdbc/XMultipleResults.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XPREPAREDBATCHEXECUTION_HDL_ +#include <com/sun/star/sdbc/XPreparedBatchExecution.hpp> +#endif +#include <com/sun/star/sdbc/XBatchExecution.hpp> +#ifndef _COM_SUN_STAR_SDBC_XGENERATEDRESULTSET_HPP_ +#include <com/sun/star/sdbc/XGeneratedResultSet.hpp> +#endif +#ifndef _COM_SUN_STAR_SDB_XSINGLESELECTQUERYCOMPOSER_HPP_ +#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp> +#endif +#ifndef _CPPUHELPER_PROPSHLP_HXX +#include <cppuhelper/propshlp.hxx> +#endif +#ifndef _COMPHELPER_PROPERTY_ARRAY_HELPER_HXX_ +#include <comphelper/proparrhlp.hxx> +#endif +#ifndef _DBASHARED_APITOOLS_HXX_ +#include "apitools.hxx" +#endif +#ifndef _COMPHELPER_BROADCASTHELPER_HXX_ +#include <comphelper/broadcasthelper.hxx> +#endif + +#include <cppuhelper/implbase3.hxx> + +//************************************************************ +// OStatementBase +//************************************************************ +class OStatementBase : public comphelper::OBaseMutex, + public OSubComponent, + public ::cppu::OPropertySetHelper, + public ::comphelper::OPropertyArrayUsageHelper < OStatementBase >, + public ::com::sun::star::util::XCancellable, + public ::com::sun::star::sdbc::XWarningsSupplier, + public ::com::sun::star::sdbc::XPreparedBatchExecution, + public ::com::sun::star::sdbc::XMultipleResults, + public ::com::sun::star::sdbc::XCloseable, + public ::com::sun::star::sdbc::XGeneratedResultSet +{ +protected: + ::osl::Mutex m_aCancelMutex; + + ::com::sun::star::uno::WeakReferenceHelper m_aResultSet; + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > m_xAggregateAsSet; + ::com::sun::star::uno::Reference< ::com::sun::star::util::XCancellable > m_xAggregateAsCancellable; + sal_Bool m_bUseBookmarks; + sal_Bool m_bEscapeProcessing; + + virtual ~OStatementBase(); + +public: + OStatementBase(const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection > & _xConn, + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > & _xStatement); + + +// ::com::sun::star::lang::XTypeProvider + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes() throw (::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::uno::XInterface + virtual ::com::sun::star::uno::Any SAL_CALL queryInterface( const ::com::sun::star::uno::Type & rType ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL acquire() throw(); + virtual void SAL_CALL release() throw(); + +// OComponentHelper + virtual void SAL_CALL disposing(void); + +// 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); + +// comphelper::OPropertyArrayUsageHelper + virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const; + +// cppu::OPropertySetHelper + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(); + + virtual sal_Bool SAL_CALL convertFastPropertyValue( + ::com::sun::star::uno::Any & rConvertedValue, + ::com::sun::star::uno::Any & rOldValue, + sal_Int32 nHandle, + const ::com::sun::star::uno::Any& rValue ) + throw (::com::sun::star::lang::IllegalArgumentException); + virtual void SAL_CALL setFastPropertyValue_NoBroadcast( + sal_Int32 nHandle, + const ::com::sun::star::uno::Any& rValue + ) + throw (::com::sun::star::uno::Exception); + virtual void SAL_CALL getFastPropertyValue( ::com::sun::star::uno::Any& rValue, sal_Int32 nHandle ) const; + +// ::com::sun::star::sdbc::XWarningsSupplier + virtual ::com::sun::star::uno::Any SAL_CALL getWarnings( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL clearWarnings( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::util::XCancellable + virtual void SAL_CALL cancel( ) throw(::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::sdbc::XCloseable + virtual void SAL_CALL close( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::sdbc::XMultipleResults + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet > SAL_CALL getResultSet( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getUpdateCount( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL getMoreResults( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::sdbc::XPreparedBatchExecution + virtual void SAL_CALL addBatch( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL clearBatch( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< sal_Int32 > SAL_CALL executeBatch( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); +// ::com::sun::star::sdbc::XGeneratedResultSet + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet > SAL_CALL getGeneratedValues( ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + +// Helper + void disposeResultSet(); + +protected: + using ::cppu::OPropertySetHelper::getFastPropertyValue; +}; + +//************************************************************ +// OStatement +//************************************************************ +typedef ::cppu::ImplHelper3 < ::com::sun::star::sdbc::XStatement + , ::com::sun::star::lang::XServiceInfo + , ::com::sun::star::sdbc::XBatchExecution + > OStatement_IFACE; +class OStatement :public OStatementBase + ,public OStatement_IFACE +{ +private: + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XStatement > m_xAggregateStatement; + ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XSingleSelectQueryComposer > m_xComposer; + bool m_bAttemptedComposerCreation; + +public: + OStatement(const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection > & _xConn, + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > & _xStatement); + + DECLARE_XINTERFACE() + DECLARE_XTYPEPROVIDER() + +// ::com::sun::star::lang::XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw(::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::sdbc::XStatement + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet > SAL_CALL executeQuery( const ::rtl::OUString& sql ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL executeUpdate( const ::rtl::OUString& sql ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL execute( const ::rtl::OUString& sql ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection > SAL_CALL getConnection( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // OComponentHelper + virtual void SAL_CALL disposing(); + + // XBatchExecution + virtual void SAL_CALL addBatch( const ::rtl::OUString& sql ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL clearBatch( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< sal_Int32 > SAL_CALL executeBatch( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + using OStatementBase::addBatch; + +private: + /** does escape processing for the given SQL command, if the our EscapeProcessing + property allows so. + */ + ::rtl::OUString impl_doEscapeProcessing_nothrow( const ::rtl::OUString& _rSQL ) const; + bool impl_ensureComposer_nothrow() const; +}; + +#endif // _DBA_COREAPI_STATEMENT_HXX_ + diff --git a/dbaccess/source/core/inc/table.hxx b/dbaccess/source/core/inc/table.hxx new file mode 100644 index 000000000000..95e984949619 --- /dev/null +++ b/dbaccess/source/core/inc/table.hxx @@ -0,0 +1,164 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 _DBA_CORE_TABLE_HXX_ +#define _DBA_CORE_TABLE_HXX_ + +#include <com/sun/star/sdbcx/XColumnsSupplier.hpp> +#include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp> +#include <com/sun/star/sdbcx/XIndexesSupplier.hpp> +#include <com/sun/star/sdbcx/XKeysSupplier.hpp> +#include <com/sun/star/sdbcx/XRename.hpp> +#include <com/sun/star/sdbcx/XAlterTable.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/sdbc/XConnection.hpp> + +#include <cppuhelper/compbase7.hxx> +#include "apitools.hxx" +#include "datasettings.hxx" +#include <column.hxx> +#include <connectivity/CommonTools.hxx> +#include <connectivity/TTableHelper.hxx> +#include <comphelper/uno3.hxx> +#include <comphelper/IdPropArrayHelper.hxx> + +namespace dbaccess +{ + + //========================================================================== + //= OTables + //========================================================================== + class ODBTable; + class OContainerMediator; + typedef ::comphelper::OIdPropertyArrayUsageHelper< ODBTable > ODBTable_PROP; + typedef ::connectivity::OTableHelper OTable_Base; + + class ODBTable :public ODataSettings_Base + ,public ODBTable_PROP + ,public OTable_Base + ,public IColumnFactory + { + private: + ::rtl::Reference< OContainerMediator > m_pColumnMediator; + + protected: + ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > m_xColumnDefinitions; + ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > m_xDriverColumns; + + // <properties> + sal_Int32 m_nPrivileges; + // </properties> + + virtual ::cppu::IPropertyArrayHelper* createArrayHelper( sal_Int32 _nId) const; + virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper(); + + // IColumnFactory + virtual OColumn* createColumn(const ::rtl::OUString& _rName) const; + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > createColumnDescriptor(); + virtual void columnAppended( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxSourceDescriptor ); + virtual void columnDropped(const ::rtl::OUString& _sName); + + /** creates the column collection for the table + @param _rNames + The column names. + */ + virtual ::connectivity::sdbcx::OCollection* createColumns(const ::connectivity::TStringVector& _rNames); + + /** creates the key collection for the table + @param _rNames + The key names. + */ + virtual ::connectivity::sdbcx::OCollection* createKeys(const ::connectivity::TStringVector& _rNames); + + /** creates the index collection for the table + @param _rNames + The index names. + */ + virtual ::connectivity::sdbcx::OCollection* createIndexes(const ::connectivity::TStringVector& _rNames); + + // OComponentHelper + virtual void SAL_CALL disposing(void); + public: + /** constructs a wrapper supporting the com.sun.star.sdb.Table service.<BR> + @param _rxConn the connection the table belongs to + @param _rxTable the table from the driver can be null + @param _rCatalog the name of the catalog the table belongs to. May be empty. + @param _rSchema the name of the schema the table belongs to. May be empty. + @param _rName the name of the table + @param _rType the type of the table, as supplied by the driver + @param _rDesc the description of the table, as supplied by the driver + */ + ODBTable(connectivity::sdbcx::OCollection* _pTables + ,const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _rxConn + ,const ::rtl::OUString& _rCatalog + , const ::rtl::OUString& _rSchema + , const ::rtl::OUString& _rName + ,const ::rtl::OUString& _rType + , const ::rtl::OUString& _rDesc + ,const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& _rxColumnDefinitions) + throw(::com::sun::star::sdbc::SQLException); + + ODBTable(connectivity::sdbcx::OCollection* _pTables + ,const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _rxConn) + throw(::com::sun::star::sdbc::SQLException); + virtual ~ODBTable(); + + // ODescriptor + virtual void construct(); + + //XInterface + DECLARE_XINTERFACE() + //XTypeProvider + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes( ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() throw (::com::sun::star::uno::RuntimeException); + static ::com::sun::star::uno::Sequence< sal_Int8 > getUnoTunnelImplementationId(); + + // ::com::sun::star::lang::XServiceInfo + DECLARE_SERVICE_INFO(); + + // 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); + virtual void SAL_CALL getFastPropertyValue(::com::sun::star::uno::Any& rValue, sal_Int32 nHandle) const; + + // ::com::sun::star::sdbcx::XRename, + virtual void SAL_CALL rename( const ::rtl::OUString& _rNewName ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::container::ElementExistException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbcx::XAlterTable, + virtual void SAL_CALL alterColumnByName( const ::rtl::OUString& _rName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxDescriptor ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException); + + // com::sun::star::lang::XUnoTunnel + virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& aIdentifier ) throw(::com::sun::star::uno::RuntimeException); + + private: + using OTable_Base::createArrayHelper; + using OTable_Base::getFastPropertyValue; + }; +} +#endif // _DBA_CORE_TABLE_HXX_ + + diff --git a/dbaccess/source/core/inc/tablecontainer.hxx b/dbaccess/source/core/inc/tablecontainer.hxx new file mode 100644 index 000000000000..5e64e8896d55 --- /dev/null +++ b/dbaccess/source/core/inc/tablecontainer.hxx @@ -0,0 +1,149 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 _DBA_CORE_TABLECONTAINER_HXX_ +#define _DBA_CORE_TABLECONTAINER_HXX_ + +#ifndef _CPPUHELPER_IMPLBASE1_HXX_ +#include <cppuhelper/implbase1.hxx> +#endif +#ifndef _COMPHELPER_STLTYPES_HXX_ +#include <comphelper/stl_types.hxx> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XENUMERATIONACCESS_HPP_ +#include <com/sun/star/container/XEnumerationAccess.hpp> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_ +#include <com/sun/star/container/XNameAccess.hpp> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XINDEXACCESS_HPP_ +#include <com/sun/star/container/XIndexAccess.hpp> +#endif +#ifndef _COM_SUN_STAR_UTIL_XREFRESHABLE_HPP_ +#include <com/sun/star/util/XRefreshable.hpp> +#endif +#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_ +#include <com/sun/star/lang/XServiceInfo.hpp> +#endif +#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_ +#include <com/sun/star/uno/Sequence.hxx> +#endif +#ifndef _COM_SUN_STAR_SDBC_XCONNECTION_HPP_ +#include <com/sun/star/sdbc/XConnection.hpp> +#endif +#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_ +#include <com/sun/star/beans/XPropertySet.hpp> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XCONTAINERLISTENER_HPP_ +#include <com/sun/star/container/XContainerListener.hpp> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XNAMECONTAINER_HPP_ +#include <com/sun/star/container/XNameContainer.hpp> +#endif +#ifndef DBACCESS_CORE_FILTERED_CONTAINER_HXX +#include "FilteredContainer.hxx" +#endif +#ifndef DBTOOLS_WARNINGSCONTAINER_HXX +#include <connectivity/warningscontainer.hxx> +#endif +#ifndef DBA_CORE_REFRESHLISTENER_HXX +#include "RefreshListener.hxx" +#endif +#ifndef _DBASHARED_APITOOLS_HXX_ +#include "apitools.hxx" +#endif + +namespace dbaccess +{ + typedef ::cppu::ImplHelper1< ::com::sun::star::container::XContainerListener> OTableContainer_Base; + + //========================================================================== + //= OTableContainer + //========================================================================== + class OTable; + class OTableContainer; + class OContainerMediator; + + class OTableContainer : public OFilteredContainer, + public OTableContainer_Base + { + ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer > m_xTableDefinitions; + ::rtl::Reference< OContainerMediator > m_pTableMediator; + sal_Bool m_bInDrop; // set when we are in the drop method + + + // OFilteredContainer + virtual void addMasterContainerListener(); + virtual void removeMasterContainerListener(); + virtual ::rtl::OUString getTableTypeRestriction() const; + + // ::connectivity::sdbcx::OCollection + virtual connectivity::sdbcx::ObjectType createObject(const ::rtl::OUString& _rName); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > createDescriptor(); + virtual connectivity::sdbcx::ObjectType appendObject( const ::rtl::OUString& _rForName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& descriptor ); + virtual void dropObject(sal_Int32 _nPos,const ::rtl::OUString _sElementName); + + virtual void SAL_CALL disposing(); + + inline virtual void SAL_CALL acquire() throw(){ OFilteredContainer::acquire();} + inline virtual void SAL_CALL release() throw(){ OFilteredContainer::release();} + // ::com::sun::star::lang::XServiceInfo + DECLARE_SERVICE_INFO(); + + // XEventListener + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException); + // XContainerListener + virtual void SAL_CALL elementInserted( const ::com::sun::star::container::ContainerEvent& Event ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL elementRemoved( const ::com::sun::star::container::ContainerEvent& Event ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL elementReplaced( const ::com::sun::star::container::ContainerEvent& Event ) throw (::com::sun::star::uno::RuntimeException); + + public: + /** ctor of the container. The parent has to support the <type scope="com::sun::star::sdbc">XConnection</type> + interface.<BR> + @param _rParent the object which acts as parent for the container. + all refcounting is rerouted to this object + @param _rMutex the access safety object of the parent + @param _rTableFilter restricts the visible tables by name + @param _rTableTypeFilter restricts the visible tables by type + @see construct + */ + OTableContainer( ::cppu::OWeakObject& _rParent, + ::osl::Mutex& _rMutex, + const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _xCon, + sal_Bool _bCase, + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >& _xTableDefinitions, + IRefreshListener* _pRefreshListener, + ::dbtools::IWarningsContainer* _pWarningsContainer, + oslInterlockedCount& _nInAppend + ); + + virtual ~OTableContainer(); + }; +} +#endif // _DBA_CORE_TABLECONTAINER_HXX_ + + diff --git a/dbaccess/source/core/inc/userinformation.hxx b/dbaccess/source/core/inc/userinformation.hxx new file mode 100644 index 000000000000..24dbbb206f2c --- /dev/null +++ b/dbaccess/source/core/inc/userinformation.hxx @@ -0,0 +1,50 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 _DBA_CORE_USERINFORMATION_HXX_ +#define _DBA_CORE_USERINFORMATION_HXX_ + +#ifndef _COM_SUN_STAR_LANG_LOCALE_HPP_ +#include <com/sun/star/lang/Locale.hpp> +#endif + +#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_ +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#endif + +class UserInformation +{ + ::com::sun::star::lang::Locale m_aUserLocale; + +public: + UserInformation(); + + ::com::sun::star::lang::Locale getUserLanguage() const { return m_aUserLocale; } +}; + +#endif // _DBA_CORE_USERINFORMATION_HXX_ + diff --git a/dbaccess/source/core/inc/veto.hxx b/dbaccess/source/core/inc/veto.hxx new file mode 100644 index 000000000000..00de76c7b73e --- /dev/null +++ b/dbaccess/source/core/inc/veto.hxx @@ -0,0 +1,79 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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_VETO_HXX +#define DBACCESS_VETO_HXX + +/** === begin UNO includes === **/ +#ifndef _COM_SUN_STAR_UTIL_XVETO_HPP_ +#include <com/sun/star/util/XVeto.hpp> +#endif +/** === end UNO includes === **/ + +#ifndef _CPPUHELPER_IMPLBASE1_HXX_ +#include <cppuhelper/implbase1.hxx> +#endif + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + + //==================================================================== + //= Veto + //==================================================================== + typedef ::cppu::WeakImplHelper1 < ::com::sun::star::util::XVeto + > Veto_Base; + /** implements ::com::sun::star::util::XVeto + */ + class Veto : public Veto_Base + { + private: + const ::rtl::OUString m_sReason; + const ::com::sun::star::uno::Any m_aDetails; + + public: + Veto( const ::rtl::OUString& _rReason, const ::com::sun::star::uno::Any& _rDetails ); + + virtual ::rtl::OUString SAL_CALL getReason() throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Any SAL_CALL getDetails() throw (::com::sun::star::uno::RuntimeException); + + protected: + ~Veto(); + + private: + Veto(); // never implemented + Veto( const Veto& ); // never implemented + Veto& operator=( const Veto& ); // never implemented + }; + +//........................................................................ +} // namespace dbaccess +//........................................................................ + +#endif // DBACCESS_VETO_HXX + diff --git a/dbaccess/source/core/inc/viewcontainer.hxx b/dbaccess/source/core/inc/viewcontainer.hxx new file mode 100644 index 000000000000..beb5c08e6350 --- /dev/null +++ b/dbaccess/source/core/inc/viewcontainer.hxx @@ -0,0 +1,139 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 _DBA_CORE_VIEWCONTAINER_HXX_ +#define _DBA_CORE_VIEWCONTAINER_HXX_ + +#ifndef _CPPUHELPER_IMPLBASE1_HXX_ +#include <cppuhelper/implbase1.hxx> +#endif +#ifndef _COMPHELPER_STLTYPES_HXX_ +#include <comphelper/stl_types.hxx> +#endif + +#ifndef _COM_SUN_STAR_CONTAINER_XENUMERATIONACCESS_HPP_ +#include <com/sun/star/container/XEnumerationAccess.hpp> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XINDEXACCESS_HPP_ +#include <com/sun/star/container/XIndexAccess.hpp> +#endif +#ifndef _COM_SUN_STAR_UTIL_XREFRESHABLE_HPP_ +#include <com/sun/star/util/XRefreshable.hpp> +#endif +#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_ +#include <com/sun/star/lang/XServiceInfo.hpp> +#endif +#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_ +#include <com/sun/star/uno/Sequence.hxx> +#endif +#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_ +#include <com/sun/star/beans/XPropertySet.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_SQLWARNING_HPP_ +#include <com/sun/star/sdbc/SQLWarning.hpp> +#endif +#ifndef _COM_SUN_STAR_SDB_SQLCONTEXT_HPP_ +#include <com/sun/star/sdb/SQLContext.hpp> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XCONTAINERLISTENER_HPP_ +#include <com/sun/star/container/XContainerListener.hpp> +#endif +#ifndef _DBASHARED_APITOOLS_HXX_ +#include "apitools.hxx" +#endif + +#ifndef DBACCESS_CORE_FILTERED_CONTAINER_HXX +#include "FilteredContainer.hxx" +#endif + +namespace dbtools +{ + class IWarningsContainer; +} + +namespace dbaccess +{ + typedef ::cppu::ImplHelper1< ::com::sun::star::container::XContainerListener> OViewContainer_Base; + + //========================================================================== + //= OViewContainer + //========================================================================== + class OViewContainer : public OFilteredContainer, + public OViewContainer_Base + { + public: + /** ctor of the container. The parent has to support the <type scope="com::sun::star::sdbc">XConnection</type> + interface.<BR> + @param _rParent the object which acts as parent for the container. + all refcounting is rerouted to this object + @param _rMutex the access safety object of the parent + @param _rTableFilter restricts the visible tables by name + @param _rTableTypeFilter restricts the visible tables by type + @see construct + */ + OViewContainer( ::cppu::OWeakObject& _rParent, + ::osl::Mutex& _rMutex, + const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _xCon, + sal_Bool _bCase, + IRefreshListener* _pRefreshListener, + ::dbtools::IWarningsContainer* _pWarningsContainer, + oslInterlockedCount& _nInAppend + ); + + virtual ~OViewContainer(); + + protected: + // OFilteredContainer overridables + virtual ::rtl::OUString getTableTypeRestriction() const; + + private: + inline virtual void SAL_CALL acquire() throw(){ OFilteredContainer::acquire();} + inline virtual void SAL_CALL release() throw(){ OFilteredContainer::release();} + // ::com::sun::star::lang::XServiceInfo + DECLARE_SERVICE_INFO(); + + // XEventListener + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException); + // XContainerListener + virtual void SAL_CALL elementInserted( const ::com::sun::star::container::ContainerEvent& Event ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL elementRemoved( const ::com::sun::star::container::ContainerEvent& Event ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL elementReplaced( const ::com::sun::star::container::ContainerEvent& Event ) throw (::com::sun::star::uno::RuntimeException); + + // ::connectivity::sdbcx::OCollection + virtual ::connectivity::sdbcx::ObjectType createObject(const ::rtl::OUString& _rName); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > createDescriptor(); + virtual connectivity::sdbcx::ObjectType appendObject( const ::rtl::OUString& _rForName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& descriptor ); + virtual void dropObject(sal_Int32 _nPos,const ::rtl::OUString _sElementName); + + using OFilteredContainer::disposing; + + bool m_bInElementRemoved; + }; +} +#endif // _DBA_CORE_VIEWCONTAINER_HXX_ + + diff --git a/dbaccess/source/core/misc/ContainerListener.cxx b/dbaccess/source/core/misc/ContainerListener.cxx new file mode 100644 index 000000000000..efdd32c1fee3 --- /dev/null +++ b/dbaccess/source/core/misc/ContainerListener.cxx @@ -0,0 +1,131 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#ifndef DBA_CONTAINERLISTENER_HXX +#include "ContainerListener.hxx" +#endif + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + + /** === begin UNO using === **/ + using ::com::sun::star::container::ContainerEvent; + using ::com::sun::star::lang::WrappedTargetException; + using ::com::sun::star::uno::RuntimeException; + using ::com::sun::star::container::XContainerApproveListener; + using ::com::sun::star::container::XContainerListener; + using ::com::sun::star::lang::EventObject; + using ::com::sun::star::util::XVeto; + using ::com::sun::star::uno::Reference; + /** === end UNO using === **/ + + //==================================================================== + //= OContainerListener + //==================================================================== + //-------------------------------------------------------------------- + OContainerListener::~OContainerListener() + { + } + + //-------------------------------------------------------------------- + Reference< XVeto > SAL_CALL OContainerListener::approveInsertElement( const ContainerEvent& _Event ) throw (WrappedTargetException, RuntimeException) + { + ::osl::MutexGuard aGuard( m_rMutex ); + if ( m_bDisposed ) + return NULL; + + return dynamic_cast< XContainerApproveListener& >( m_rDestination ).approveInsertElement( _Event ); + } + + //-------------------------------------------------------------------- + Reference< XVeto > SAL_CALL OContainerListener::approveReplaceElement( const ContainerEvent& _Event ) throw (WrappedTargetException, RuntimeException) + { + ::osl::MutexGuard aGuard( m_rMutex ); + if ( m_bDisposed ) + return NULL; + + return dynamic_cast< XContainerApproveListener& >( m_rDestination ).approveReplaceElement( _Event ); + } + + //-------------------------------------------------------------------- + Reference< XVeto > SAL_CALL OContainerListener::approveRemoveElement( const ContainerEvent& _Event ) throw (WrappedTargetException, RuntimeException) + { + ::osl::MutexGuard aGuard( m_rMutex ); + if ( m_bDisposed ) + return NULL; + + return dynamic_cast< XContainerApproveListener& >( m_rDestination ).approveRemoveElement( _Event ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OContainerListener::elementInserted( const ContainerEvent& _Event ) throw(RuntimeException) + { + ::osl::MutexGuard aGuard( m_rMutex ); + if ( m_bDisposed ) + return; + + dynamic_cast< XContainerListener& >( m_rDestination ).elementInserted( _Event ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OContainerListener::elementRemoved( const ContainerEvent& _Event ) throw(RuntimeException) + { + ::osl::MutexGuard aGuard( m_rMutex ); + if ( m_bDisposed ) + return; + + dynamic_cast< XContainerListener& >( m_rDestination ).elementRemoved( _Event ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OContainerListener::elementReplaced( const ContainerEvent& _Event ) throw(RuntimeException) + { + ::osl::MutexGuard aGuard( m_rMutex ); + if ( m_bDisposed ) + return; + + dynamic_cast< XContainerListener& >( m_rDestination ).elementReplaced( _Event ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OContainerListener::disposing( const EventObject& _Source ) throw(RuntimeException) + { + ::osl::MutexGuard aGuard( m_rMutex ); + if ( m_bDisposed ) + return; + + dynamic_cast< XContainerListener& >( m_rDestination ).disposing( _Source ); + } + +//........................................................................ +} // namespace dbaccess +//........................................................................ diff --git a/dbaccess/source/core/misc/ContainerMediator.cxx b/dbaccess/source/core/misc/ContainerMediator.cxx new file mode 100644 index 000000000000..7d7ea80f558a --- /dev/null +++ b/dbaccess/source/core/misc/ContainerMediator.cxx @@ -0,0 +1,281 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" +#ifndef DBA_CONTAINERMEDIATOR_HXX +#include "ContainerMediator.hxx" +#endif +#ifndef DBACCESS_SHARED_DBASTRINGS_HRC +#include "dbastrings.hrc" +#endif +#ifndef DBA_PROPERTYSETFORWARD_HXX +#include "PropertyForward.hxx" +#endif + +#ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBUTE_HPP_ +#include <com/sun/star/beans/PropertyAttribute.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 +#include <com/sun/star/sdbcx/XRename.hpp> +#ifndef _CONNECTIVITY_DBTOOLS_HXX_ +#include <connectivity/dbtools.hxx> +#endif +#ifndef _COMPHELPER_PROPERTY_HXX_ +#include <comphelper/property.hxx> +#endif +#ifndef _TOOLS_DEBUG_HXX +#include <tools/debug.hxx> +#endif +#ifndef TOOLS_DIAGNOSE_EX_H +#include <tools/diagnose_ex.h> +#endif + + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::sdbc; + using namespace ::com::sun::star::sdbcx; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::container; + +DBG_NAME(OContainerMediator) +OContainerMediator::OContainerMediator( const Reference< XContainer >& _xContainer, const Reference< XNameAccess >& _xSettings, + const Reference< XConnection >& _rxConnection, ContainerType _eType ) + : m_xSettings( _xSettings ) + , m_xContainer( _xContainer ) + , m_aConnection( _rxConnection ) + , m_eType( _eType ) +{ + DBG_CTOR(OContainerMediator,NULL); + + if ( _xSettings.is() && _xContainer.is() ) + { + osl_incrementInterlockedCount(&m_refCount); + try + { + m_xContainer->addContainerListener(this); + Reference< XContainer > xContainer(_xSettings, UNO_QUERY); + if ( xContainer.is() ) + xContainer->addContainerListener(this); + } + catch(Exception&) + { + OSL_ENSURE(sal_False, "OContainerMediator::OContainerMediator: caught an exception!"); + } + osl_decrementInterlockedCount( &m_refCount ); + } + else + { + m_xSettings.clear(); + m_xContainer.clear(); + } +} +// ----------------------------------------------------------------------------- +OContainerMediator::~OContainerMediator() +{ + DBG_DTOR(OContainerMediator,NULL); + acquire(); + impl_cleanup_nothrow(); +} + +// ----------------------------------------------------------------------------- +void OContainerMediator::impl_cleanup_nothrow() +{ + try + { + Reference< XContainer > xContainer( m_xSettings, UNO_QUERY ); + if ( xContainer.is() ) + xContainer->removeContainerListener( this ); + m_xSettings.clear(); + + xContainer = m_xContainer; + if ( xContainer.is() ) + xContainer->removeContainerListener( this ); + m_xContainer.clear(); + + m_aForwardList.clear(); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } +} + +// ----------------------------------------------------------------------------- +void SAL_CALL OContainerMediator::elementInserted( const ContainerEvent& _rEvent ) throw(RuntimeException) +{ + ::osl::MutexGuard aGuard(m_aMutex); + if ( _rEvent.Source == m_xSettings && m_xSettings.is() ) + { + ::rtl::OUString sElementName; + _rEvent.Accessor >>= sElementName; + PropertyForwardList::iterator aFind = m_aForwardList.find(sElementName); + if ( aFind != m_aForwardList.end() ) + { + Reference< XPropertySet> xDest(_rEvent.Element,UNO_QUERY); + aFind->second->setDefinition( xDest ); + } + } +} +// ----------------------------------------------------------------------------- +void SAL_CALL OContainerMediator::elementRemoved( const ContainerEvent& _rEvent ) throw(RuntimeException) +{ + ::osl::MutexGuard aGuard(m_aMutex); + Reference< XContainer > xContainer = m_xContainer; + if ( _rEvent.Source == xContainer && xContainer.is() ) + { + ::rtl::OUString sElementName; + _rEvent.Accessor >>= sElementName; + m_aForwardList.erase(sElementName); + try + { + Reference<XNameContainer> xNameContainer( m_xSettings, UNO_QUERY ); + if ( xNameContainer.is() && m_xSettings->hasByName( sElementName ) ) + xNameContainer->removeByName( sElementName ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } +} +// ----------------------------------------------------------------------------- +void SAL_CALL OContainerMediator::elementReplaced( const ContainerEvent& _rEvent ) throw(RuntimeException) +{ + Reference< XContainer > xContainer = m_xContainer; + if ( _rEvent.Source == xContainer && xContainer.is() ) + { + ::rtl::OUString sElementName; + _rEvent.ReplacedElement >>= sElementName; + + PropertyForwardList::iterator aFind = m_aForwardList.find(sElementName); + if ( aFind != m_aForwardList.end() ) + { + ::rtl::OUString sNewName; + _rEvent.Accessor >>= sNewName; + try + { + Reference<XNameContainer> xNameContainer( m_xSettings, UNO_QUERY_THROW ); + if ( xNameContainer.is() && m_xSettings->hasByName( sElementName ) ) + { + Reference<XRename> xSource(m_xSettings->getByName(sElementName),UNO_QUERY_THROW); + xSource->rename(sNewName); + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + aFind->second->setName(sNewName); + } + } +} + +// ----------------------------------------------------------------------------- +void SAL_CALL OContainerMediator::disposing( const EventObject& /*Source*/ ) throw(RuntimeException) +{ + ::osl::MutexGuard aGuard(m_aMutex); + + impl_cleanup_nothrow(); +} + +// ----------------------------------------------------------------------------- +void OContainerMediator::impl_initSettings_nothrow( const ::rtl::OUString& _rName, const Reference< XPropertySet >& _rxDestination ) +{ + try + { + if ( m_xSettings.is() && m_xSettings->hasByName( _rName ) ) + { + Reference< XPropertySet > xSettings( m_xSettings->getByName( _rName ), UNO_QUERY_THROW ); + ::comphelper::copyProperties( xSettings, _rxDestination ); + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } +} + +// ----------------------------------------------------------------------------- +void OContainerMediator::notifyElementCreated( const ::rtl::OUString& _sName, const Reference< XPropertySet >& _xDest ) +{ + if ( !m_xSettings.is() ) + return; + + PropertyForwardList::iterator aFind = m_aForwardList.find( _sName ); + if ( aFind != m_aForwardList.end() + && aFind->second->getDefinition().is() + ) + { + OSL_ENSURE( false, "OContainerMediator::notifyElementCreated: is this really a valid case?" ); + return; + } + + ::std::vector< ::rtl::OUString > aPropertyList; + try + { + // initially copy from the settings object (if existent) to the newly created object + impl_initSettings_nothrow( _sName, _xDest ); + + // collect the to-be-monitored properties + Reference< XPropertySetInfo > xPSI( _xDest->getPropertySetInfo(), UNO_QUERY_THROW ); + Sequence< Property > aProperties( xPSI->getProperties() ); + const Property* property = aProperties.getConstArray(); + const Property* propertyEnd = aProperties.getConstArray() + aProperties.getLength(); + for ( ; property != propertyEnd; ++property ) + { + if ( ( property->Attributes & PropertyAttribute::READONLY ) != 0 ) + continue; + if ( ( property->Attributes & PropertyAttribute::BOUND ) == 0 ) + continue; + + aPropertyList.push_back( property->Name ); + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + ::rtl::Reference< OPropertyForward > pForward( new OPropertyForward( _xDest, m_xSettings, _sName, aPropertyList ) ); + m_aForwardList[ _sName ] = pForward; +} +// ----------------------------------------------------------------------------- +//........................................................................ +} // namespace dbaccess +//........................................................................ diff --git a/dbaccess/source/core/misc/DatabaseDataProvider.cxx b/dbaccess/source/core/misc/DatabaseDataProvider.cxx new file mode 100644 index 000000000000..802e052297f9 --- /dev/null +++ b/dbaccess/source/core/misc/DatabaseDataProvider.cxx @@ -0,0 +1,1090 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#include "DatabaseDataProvider.hxx" +#include "dbastrings.hrc" +#include "cppuhelper/implbase1.hxx" +#include <comphelper/types.hxx> +#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> +#include <com/sun/star/sdb/CommandType.hpp> +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/sdbc/XResultSet.hpp> +#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp> +#include <com/sun/star/sdbc/XResultSetMetaData.hpp> +#include <com/sun/star/sdbc/XColumnLocate.hpp> +#include <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/chart/ChartDataRowSource.hpp> +#include <com/sun/star/chart/XChartDataArray.hpp> + +#include <vector> +#include <list> + +namespace dbaccess +{ +using namespace ::com::sun::star; +using ::com::sun::star::sdbc::SQLException; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::RuntimeException; +// ----------------------------------------------------------------------------- +DatabaseDataProvider::DatabaseDataProvider(uno::Reference< uno::XComponentContext > const & context) : + TDatabaseDataProvider(m_aMutex), + ::cppu::PropertySetMixin< chart2::data::XDatabaseDataProvider >( + context, static_cast< Implements >( + IMPLEMENTS_PROPERTY_SET), uno::Sequence< ::rtl::OUString >()), + m_aParameterManager( m_aMutex, uno::Reference< lang::XMultiServiceFactory >(context->getServiceManager(),uno::UNO_QUERY) ), + m_aFilterManager( uno::Reference< lang::XMultiServiceFactory >(context->getServiceManager(),uno::UNO_QUERY) ), + m_xContext(context), + m_CommandType(sdb::CommandType::COMMAND), // #i94114 + m_RowLimit(0), + m_EscapeProcessing(sal_True), + m_ApplyFilter(sal_True) +{ + m_xInternal.set( m_xContext->getServiceManager()->createInstanceWithContext(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.chart.InternalDataProvider")),m_xContext ), uno::UNO_QUERY ); + m_xRangeConversion.set(m_xInternal,uno::UNO_QUERY); + m_xComplexDescriptionAccess.set(m_xInternal,uno::UNO_QUERY); + + osl_incrementInterlockedCount( &m_refCount ); + { + m_xRowSet.set( m_xContext->getServiceManager()->createInstanceWithContext(SERVICE_SDB_ROWSET,m_xContext ), uno::UNO_QUERY ); + m_xAggregate.set(m_xRowSet,uno::UNO_QUERY); + m_xAggregateSet.set(m_xRowSet,uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xProp(static_cast< ::cppu::OWeakObject* >( this ),uno::UNO_QUERY); + m_aFilterManager.initialize( m_xAggregateSet ); + m_aParameterManager.initialize( xProp, m_xAggregate ); + m_xAggregateSet->setPropertyValue(PROPERTY_COMMAND_TYPE,uno::makeAny(m_CommandType)); + m_xAggregateSet->setPropertyValue(PROPERTY_ESCAPE_PROCESSING,uno::makeAny(m_EscapeProcessing)); + } + osl_decrementInterlockedCount( &m_refCount ); +} +// ----------------------------------------------------------------------------- +void SAL_CALL DatabaseDataProvider::disposing() +{ + lang::EventObject aEvt(static_cast<XWeak*>(this)); + m_aParameterManager.disposing( aEvt ); + + m_aParameterManager.dispose(); // (to free any references it may have to me) + m_aFilterManager.dispose(); // (dito) + + m_xParent.clear(); + m_xAggregateSet.clear(); + m_xAggregate.clear(); + m_xRangeConversion.clear(); + ::comphelper::disposeComponent(m_xRowSet); + ::comphelper::disposeComponent(m_xInternal); + m_xActiveConnection.clear(); +} +// ----------------------------------------------------------------------------- +uno::Any DatabaseDataProvider::queryInterface(uno::Type const & type) throw (uno::RuntimeException) +{ + return TDatabaseDataProvider::queryInterface(type); +} +// ----------------------------------------------------------------------------- + +//------------------------------------------------------------------------------ +rtl::OUString DatabaseDataProvider::getImplementationName_Static( ) throw(uno::RuntimeException) +{ + return rtl::OUString::createFromAscii("com.sun.star.comp.chart2.data.DatabaseDataProvider"); +} +// ----------------------------------------------------------------------------- +// ------------------------------------------------------------------------- +// XServiceInfo +::rtl::OUString SAL_CALL DatabaseDataProvider::getImplementationName( ) throw(uno::RuntimeException) +{ + return getImplementationName_Static(); +} +// ----------------------------------------------------------------------------- +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL DatabaseDataProvider::supportsService( const ::rtl::OUString& _rServiceName ) throw(uno::RuntimeException) +{ + return ::comphelper::findValue(getSupportedServiceNames(), _rServiceName, sal_True).getLength() != 0; +} +// ----------------------------------------------------------------------------- +//------------------------------------------------------------------------------ +uno::Sequence< ::rtl::OUString > DatabaseDataProvider::getSupportedServiceNames_Static( ) throw (uno::RuntimeException) +{ + uno::Sequence< rtl::OUString > aSNS( 1 ); + aSNS[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.chart2.data.DatabaseDataProvider")); + return aSNS; +} +// ----------------------------------------------------------------------------- +uno::Sequence< ::rtl::OUString > SAL_CALL DatabaseDataProvider::getSupportedServiceNames( ) throw(uno::RuntimeException) +{ + return getSupportedServiceNames_Static(); +} +// ----------------------------------------------------------------------------- +uno::Reference< uno::XInterface > DatabaseDataProvider::Create(uno::Reference< uno::XComponentContext > const & context) +{ + return *(new DatabaseDataProvider(context)) ; +} +// ----------------------------------------------------------------------------- +// lang::XInitialization: +void SAL_CALL DatabaseDataProvider::initialize(const uno::Sequence< uno::Any > & aArguments) throw (uno::RuntimeException, uno::Exception) +{ + osl::MutexGuard g(m_aMutex); + const uno::Any* pIter = aArguments.getConstArray(); + const uno::Any* pEnd = pIter + aArguments.getLength(); + for(;pIter != pEnd;++pIter) + { + if ( !m_xActiveConnection.is() ) + (*pIter) >>= m_xActiveConnection; + else if ( !m_xHandler.is() ) + (*pIter) >>= m_xHandler; + } + m_xAggregateSet->setPropertyValue( PROPERTY_ACTIVE_CONNECTION, uno::makeAny( m_xActiveConnection ) ); +} +// ----------------------------------------------------------------------------- + +// chart2::data::XDataProvider: +::sal_Bool SAL_CALL DatabaseDataProvider::createDataSourcePossible(const uno::Sequence< beans::PropertyValue > & _aArguments) throw (uno::RuntimeException) +{ + //::osl::ResettableMutexGuard aClearForNotifies(m_aMutex); + const beans::PropertyValue* pArgIter = _aArguments.getConstArray(); + const beans::PropertyValue* pArgEnd = pArgIter + _aArguments.getLength(); + for(;pArgIter != pArgEnd;++pArgIter) + { + if ( pArgIter->Name.equalsAscii("DataRowSource") ) + { + ::com::sun::star::chart::ChartDataRowSource eRowSource = ::com::sun::star::chart::ChartDataRowSource_COLUMNS; + pArgIter->Value >>= eRowSource; + if ( eRowSource != ::com::sun::star::chart::ChartDataRowSource_COLUMNS ) + return sal_False; + } // if ( pArgIter->Name.equalsAscii("DataRowSource") ) + else if ( pArgIter->Name.equalsAscii("CellRangeRepresentation") ) + { + ::rtl::OUString sRange; + pArgIter->Value >>= sRange; + if ( !sRange.equalsAscii("all") ) + return sal_False; + } + else if ( pArgIter->Name.equalsAscii("FirstCellAsLabel") ) + { + sal_Bool bFirstCellAsLabel = sal_True; + pArgIter->Value >>= bFirstCellAsLabel; + if ( !bFirstCellAsLabel ) + return sal_False; + } + } + return sal_True; +} +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +uno::Reference< chart2::data::XDataSource > SAL_CALL DatabaseDataProvider::createDataSource(const uno::Sequence< beans::PropertyValue > & _aArguments) throw (uno::RuntimeException, lang::IllegalArgumentException) +{ + osl::ResettableMutexGuard aClearForNotifies(m_aMutex); + if ( createDataSourcePossible(_aArguments) ) + { + sal_Bool bHasCategories = sal_True; + uno::Sequence< uno::Sequence< ::rtl::OUString > > aColumnNames; + const beans::PropertyValue* pArgIter = _aArguments.getConstArray(); + const beans::PropertyValue* pArgEnd = pArgIter + _aArguments.getLength(); + for(;pArgIter != pArgEnd;++pArgIter) + { + if ( pArgIter->Name.equalsAscii("HasCategories") ) + { + pArgIter->Value >>= bHasCategories; + + } + else if ( pArgIter->Name.equalsAscii("ComplexColumnDescriptions") ) + { + pArgIter->Value >>= aColumnNames; + } + } + bool bRet = false; + if ( m_Command.getLength() != 0 && m_xActiveConnection.is() ) + { + try + { + impl_fillRowSet_throw(); + impl_executeRowSet_throw(aClearForNotifies); + impl_fillInternalDataProvider_throw(bHasCategories,aColumnNames); + bRet = true; + } + catch(const uno::Exception& /*e*/) + { + } + } + if ( !bRet ) // no command set or an error occured, use Internal data handler + { + uno::Reference< lang::XInitialization> xIni(m_xInternal,uno::UNO_QUERY); + if ( xIni.is() ) + { + uno::Sequence< uno::Any > aArgs(1); + beans::NamedValue aParam(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CreateDefaultData")),uno::makeAny(sal_True)); + aArgs[0] <<= aParam; + xIni->initialize(aArgs); + } + } + + } + return m_xInternal->createDataSource(_aArguments); +} +// ----------------------------------------------------------------------------- + +uno::Sequence< beans::PropertyValue > SAL_CALL DatabaseDataProvider::detectArguments(const uno::Reference< chart2::data::XDataSource > & _xDataSource) throw (uno::RuntimeException) +{ + uno::Sequence< beans::PropertyValue > aArguments( 4 ); + aArguments[0] = beans::PropertyValue( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CellRangeRepresentation")), -1, uno::Any(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("all")) ), + beans::PropertyState_DIRECT_VALUE ); + aArguments[1] = beans::PropertyValue( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DataRowSource")), -1, uno::makeAny( chart::ChartDataRowSource_COLUMNS ), + beans::PropertyState_DIRECT_VALUE ); + // internal data always contains labels and categories + aArguments[2] = beans::PropertyValue( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("FirstCellAsLabel")), -1, uno::makeAny( true ), beans::PropertyState_DIRECT_VALUE ); + sal_Bool bHasCategories = sal_False; + if( _xDataSource.is()) + { + uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aSequences(_xDataSource->getDataSequences()); + const sal_Int32 nCount( aSequences.getLength()); + for( sal_Int32 nIdx=0; nIdx<nCount; ++nIdx ) + { + if( aSequences[nIdx].is() ) + { + uno::Reference< beans::XPropertySet > xSeqProp( aSequences[nIdx]->getValues(), uno::UNO_QUERY ); + ::rtl::OUString aRole; + if( xSeqProp.is() && + (xSeqProp->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Role"))) >>= aRole) && + aRole.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("categories")) ) + { + bHasCategories = sal_True; + break; + } + } + } + } + + aArguments[3] = beans::PropertyValue( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("HasCategories")), -1, uno::makeAny( bHasCategories ), beans::PropertyState_DIRECT_VALUE ); + return aArguments; +} +// ----------------------------------------------------------------------------- + +::sal_Bool SAL_CALL DatabaseDataProvider::createDataSequenceByRangeRepresentationPossible(const ::rtl::OUString & /*aRangeRepresentation*/) throw (uno::RuntimeException) +{ + return sal_True; +} +// ----------------------------------------------------------------------------- +uno::Any DatabaseDataProvider::impl_getNumberFormatKey_nothrow(const ::rtl::OUString & _sRangeRepresentation) const +{ + ::std::map< ::rtl::OUString,com::sun::star::uno::Any>::const_iterator aFind = m_aNumberFormats.find(_sRangeRepresentation); + if ( aFind != m_aNumberFormats.end() ) + return aFind->second; + return uno::makeAny(sal_Int32(0)); +} +// ----------------------------------------------------------------------------- +uno::Reference< chart2::data::XDataSequence > SAL_CALL DatabaseDataProvider::createDataSequenceByRangeRepresentation(const ::rtl::OUString & _sRangeRepresentation) throw (uno::RuntimeException, lang::IllegalArgumentException) +{ + osl::MutexGuard g(m_aMutex); + uno::Reference< chart2::data::XDataSequence > xData = m_xInternal->createDataSequenceByRangeRepresentation(_sRangeRepresentation);; + uno::Reference<beans::XPropertySet> xProp(xData,uno::UNO_QUERY); + const static ::rtl::OUString s_sNumberFormatKey(RTL_CONSTASCII_USTRINGPARAM("NumberFormatKey")); + if ( xProp.is() && xProp->getPropertySetInfo()->hasPropertyByName(s_sNumberFormatKey) ) + { + xProp->setPropertyValue(s_sNumberFormatKey,impl_getNumberFormatKey_nothrow(_sRangeRepresentation)); + } + return xData; +} + +uno::Sequence< uno::Sequence< rtl::OUString > > SAL_CALL DatabaseDataProvider::getComplexRowDescriptions() throw (uno::RuntimeException) +{ + return m_xComplexDescriptionAccess->getComplexRowDescriptions(); +} +void SAL_CALL DatabaseDataProvider::setComplexRowDescriptions( const uno::Sequence< uno::Sequence< ::rtl::OUString > >& aRowDescriptions ) throw (uno::RuntimeException) +{ + m_xComplexDescriptionAccess->setComplexRowDescriptions(aRowDescriptions); +} +uno::Sequence< uno::Sequence< rtl::OUString > > SAL_CALL DatabaseDataProvider::getComplexColumnDescriptions() throw (uno::RuntimeException) +{ + return m_xComplexDescriptionAccess->getComplexColumnDescriptions(); +} +void SAL_CALL DatabaseDataProvider::setComplexColumnDescriptions( const uno::Sequence< uno::Sequence< rtl::OUString > >& aColumnDescriptions ) throw (uno::RuntimeException) +{ + m_xComplexDescriptionAccess->setComplexColumnDescriptions(aColumnDescriptions); +} +// ____ XChartDataArray ____ +uno::Sequence< uno::Sequence< double > > SAL_CALL DatabaseDataProvider::getData() throw (uno::RuntimeException) +{ + return m_xComplexDescriptionAccess->getData(); +} + +void SAL_CALL DatabaseDataProvider::setData( const uno::Sequence< uno::Sequence< double > >& rDataInRows ) throw (uno::RuntimeException) +{ + m_xComplexDescriptionAccess->setData(rDataInRows); +} + +void SAL_CALL DatabaseDataProvider::setRowDescriptions( const uno::Sequence< rtl::OUString >& aRowDescriptions ) throw (uno::RuntimeException) +{ + m_xComplexDescriptionAccess->setRowDescriptions(aRowDescriptions); +} + +void SAL_CALL DatabaseDataProvider::setColumnDescriptions( const uno::Sequence< rtl::OUString >& aColumnDescriptions ) throw (uno::RuntimeException) +{ + m_xComplexDescriptionAccess->setColumnDescriptions(aColumnDescriptions); +} + +uno::Sequence< rtl::OUString > SAL_CALL DatabaseDataProvider::getRowDescriptions() throw (uno::RuntimeException) +{ + return m_xComplexDescriptionAccess->getRowDescriptions(); +} + +uno::Sequence< rtl::OUString > SAL_CALL DatabaseDataProvider::getColumnDescriptions() throw (uno::RuntimeException) +{ + return m_xComplexDescriptionAccess->getColumnDescriptions(); +} + +// ____ XChartData (base of XChartDataArray) ____ +void SAL_CALL DatabaseDataProvider::addChartDataChangeEventListener(const uno::Reference< ::com::sun::star::chart::XChartDataChangeEventListener >& x) throw (uno::RuntimeException) +{ + m_xComplexDescriptionAccess->addChartDataChangeEventListener(x); +} + +void SAL_CALL DatabaseDataProvider::removeChartDataChangeEventListener(const uno::Reference< ::com::sun::star::chart::XChartDataChangeEventListener >& x) throw (uno::RuntimeException) +{ + m_xComplexDescriptionAccess->removeChartDataChangeEventListener(x); +} + +double SAL_CALL DatabaseDataProvider::getNotANumber() throw (uno::RuntimeException) +{ + return m_xComplexDescriptionAccess->getNotANumber(); +} + +::sal_Bool SAL_CALL DatabaseDataProvider::isNotANumber( double nNumber ) throw (uno::RuntimeException) +{ + return m_xComplexDescriptionAccess->isNotANumber(nNumber); +} + +// ----------------------------------------------------------------------------- + +uno::Reference< sheet::XRangeSelection > SAL_CALL DatabaseDataProvider::getRangeSelection() throw (uno::RuntimeException) +{ + // TODO: Exchange the default return implementation for "getRangeSelection" !!! + // Exchange the default return implementation. + // NOTE: Default initialized polymorphic structs can cause problems because of + // missing default initialization of primitive types of some C++ compilers or + // different Any initialization in Java and C++ polymorphic structs. + return uno::Reference< sheet::XRangeSelection >(); +} +// ----------------------------------------------------------------------------- +// chart2::data::XRangeXMLConversion: +::rtl::OUString SAL_CALL DatabaseDataProvider::convertRangeToXML(const ::rtl::OUString & _sRangeRepresentation) throw (uno::RuntimeException, lang::IllegalArgumentException) +{ + osl::MutexGuard g(m_aMutex); + return m_xRangeConversion->convertRangeToXML(_sRangeRepresentation); +} +// ----------------------------------------------------------------------------- + +::rtl::OUString SAL_CALL DatabaseDataProvider::convertRangeFromXML(const ::rtl::OUString & _sXMLRange) throw (uno::RuntimeException, lang::IllegalArgumentException) +{ + osl::MutexGuard g(m_aMutex); + return m_xRangeConversion->convertRangeFromXML(_sXMLRange); +} +// ----------------------------------------------------------------------------- + +// com.sun.star.beans.XPropertySet: +uno::Reference< beans::XPropertySetInfo > SAL_CALL DatabaseDataProvider::getPropertySetInfo() throw (uno::RuntimeException) +{ + return ::cppu::PropertySetMixin< chart2::data::XDatabaseDataProvider >::getPropertySetInfo(); +} +// ----------------------------------------------------------------------------- + +void SAL_CALL DatabaseDataProvider::setPropertyValue(const ::rtl::OUString & aPropertyName, const uno::Any & aValue) throw (uno::RuntimeException, beans::UnknownPropertyException, beans::PropertyVetoException, lang::IllegalArgumentException, lang::WrappedTargetException) +{ + ::cppu::PropertySetMixin< chart2::data::XDatabaseDataProvider >::setPropertyValue(aPropertyName, aValue); +} +// ----------------------------------------------------------------------------- + +uno::Any SAL_CALL DatabaseDataProvider::getPropertyValue(const ::rtl::OUString & aPropertyName) throw (uno::RuntimeException, beans::UnknownPropertyException, lang::WrappedTargetException) +{ + return ::cppu::PropertySetMixin< chart2::data::XDatabaseDataProvider >::getPropertyValue(aPropertyName); +} +// ----------------------------------------------------------------------------- + +void SAL_CALL DatabaseDataProvider::addPropertyChangeListener(const ::rtl::OUString & aPropertyName, const uno::Reference< beans::XPropertyChangeListener > & xListener) throw (uno::RuntimeException, beans::UnknownPropertyException, lang::WrappedTargetException) +{ + ::cppu::PropertySetMixin< chart2::data::XDatabaseDataProvider >::addPropertyChangeListener(aPropertyName, xListener); +} +// ----------------------------------------------------------------------------- + +void SAL_CALL DatabaseDataProvider::removePropertyChangeListener(const ::rtl::OUString & aPropertyName, const uno::Reference< beans::XPropertyChangeListener > & xListener) throw (uno::RuntimeException, beans::UnknownPropertyException, lang::WrappedTargetException) +{ + ::cppu::PropertySetMixin< chart2::data::XDatabaseDataProvider >::removePropertyChangeListener(aPropertyName, xListener); +} +// ----------------------------------------------------------------------------- + +void SAL_CALL DatabaseDataProvider::addVetoableChangeListener(const ::rtl::OUString & aPropertyName, const uno::Reference< beans::XVetoableChangeListener > & xListener) throw (uno::RuntimeException, beans::UnknownPropertyException, lang::WrappedTargetException) +{ + ::cppu::PropertySetMixin< chart2::data::XDatabaseDataProvider >::addVetoableChangeListener(aPropertyName, xListener); +} +// ----------------------------------------------------------------------------- + +void SAL_CALL DatabaseDataProvider::removeVetoableChangeListener(const ::rtl::OUString & aPropertyName, const uno::Reference< beans::XVetoableChangeListener > & xListener) throw (uno::RuntimeException, beans::UnknownPropertyException, lang::WrappedTargetException) +{ + ::cppu::PropertySetMixin< chart2::data::XDatabaseDataProvider >::removeVetoableChangeListener(aPropertyName, xListener); +} +// ----------------------------------------------------------------------------- + +// chart2::data::XDatabaseDataProvider: +uno::Sequence< ::rtl::OUString > SAL_CALL DatabaseDataProvider::getMasterFields() throw (uno::RuntimeException) +{ + osl::MutexGuard g(m_aMutex); + return m_MasterFields; +} +// ----------------------------------------------------------------------------- + +void SAL_CALL DatabaseDataProvider::setMasterFields(const uno::Sequence< ::rtl::OUString > & the_value) throw (uno::RuntimeException) +{ + impl_invalidateParameter_nothrow(); + set(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MasterFields")),the_value,m_MasterFields); +} +// ----------------------------------------------------------------------------- + +uno::Sequence< ::rtl::OUString > SAL_CALL DatabaseDataProvider::getDetailFields() throw (uno::RuntimeException) +{ + osl::MutexGuard g(m_aMutex); + return m_DetailFields; +} +// ----------------------------------------------------------------------------- + +void SAL_CALL DatabaseDataProvider::setDetailFields(const uno::Sequence< ::rtl::OUString > & the_value) throw (uno::RuntimeException) +{ + set(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DetailFields")),the_value,m_DetailFields); +} +// ----------------------------------------------------------------------------- +::rtl::OUString SAL_CALL DatabaseDataProvider::getCommand() throw (uno::RuntimeException) +{ + osl::MutexGuard g(m_aMutex); + return m_Command; +} +// ----------------------------------------------------------------------------- + +void SAL_CALL DatabaseDataProvider::setCommand(const ::rtl::OUString & the_value) throw (uno::RuntimeException) +{ + { + osl::MutexGuard g(m_aMutex); + impl_invalidateParameter_nothrow(); + m_xAggregateSet->setPropertyValue( PROPERTY_COMMAND, uno::makeAny( the_value ) ); + } + set(PROPERTY_COMMAND,the_value,m_Command); +} +// ----------------------------------------------------------------------------- + +::sal_Int32 SAL_CALL DatabaseDataProvider::getCommandType() throw (uno::RuntimeException) +{ + osl::MutexGuard g(m_aMutex); + return m_CommandType; +} +// ----------------------------------------------------------------------------- + +void SAL_CALL DatabaseDataProvider::setCommandType(::sal_Int32 the_value) throw (uno::RuntimeException) +{ + { + osl::MutexGuard g(m_aMutex); + m_xAggregateSet->setPropertyValue( PROPERTY_COMMAND_TYPE, uno::makeAny( the_value ) ); + } + set(PROPERTY_COMMAND_TYPE,the_value,m_CommandType); +} +// ----------------------------------------------------------------------------- + +::rtl::OUString SAL_CALL DatabaseDataProvider::getFilter() throw (uno::RuntimeException) +{ + osl::MutexGuard g(m_aMutex); + return m_aFilterManager.getFilterComponent( dbtools::FilterManager::fcPublicFilter ); +} +// ----------------------------------------------------------------------------- + +void SAL_CALL DatabaseDataProvider::setFilter(const ::rtl::OUString & the_value) throw (uno::RuntimeException) +{ + { + osl::MutexGuard g(m_aMutex); + m_aFilterManager.setFilterComponent( dbtools::FilterManager::fcPublicFilter, the_value ); + } + set(PROPERTY_FILTER,the_value,m_Filter); +} +// ----------------------------------------------------------------------------- +::sal_Bool SAL_CALL DatabaseDataProvider::getApplyFilter() throw (RuntimeException) +{ + osl::MutexGuard g(m_aMutex); + return m_ApplyFilter; +} +// ----------------------------------------------------------------------------- +void SAL_CALL DatabaseDataProvider::setApplyFilter( ::sal_Bool the_value ) throw (RuntimeException) +{ + { + osl::MutexGuard g(m_aMutex); + m_xAggregateSet->setPropertyValue( PROPERTY_APPLYFILTER, uno::makeAny( the_value ) ); + } + set(PROPERTY_APPLYFILTER,the_value,m_ApplyFilter); +} +// ----------------------------------------------------------------------------- +::rtl::OUString SAL_CALL DatabaseDataProvider::getHavingClause() throw (uno::RuntimeException) +{ + osl::MutexGuard g(m_aMutex); + return m_HavingClause; +} +// ----------------------------------------------------------------------------- +void SAL_CALL DatabaseDataProvider::setHavingClause( const ::rtl::OUString& the_value ) throw (beans::UnknownPropertyException, uno::RuntimeException) +{ + { + osl::MutexGuard g(m_aMutex); + m_xAggregateSet->setPropertyValue( PROPERTY_HAVING_CLAUSE, uno::makeAny( the_value ) ); + } + set(PROPERTY_HAVING_CLAUSE,the_value,m_HavingClause); +} +// ----------------------------------------------------------------------------- +::rtl::OUString SAL_CALL DatabaseDataProvider::getGroupBy() throw (uno::RuntimeException) +{ + osl::MutexGuard g(m_aMutex); + return m_GroupBy; +} +// ----------------------------------------------------------------------------- +void SAL_CALL DatabaseDataProvider::setGroupBy( const ::rtl::OUString& the_value ) throw (beans::UnknownPropertyException, uno::RuntimeException) +{ + { + osl::MutexGuard g(m_aMutex); + m_xAggregateSet->setPropertyValue( PROPERTY_GROUP_BY, uno::makeAny( the_value ) ); + } + set(PROPERTY_GROUP_BY,the_value,m_GroupBy); +} +// ----------------------------------------------------------------------------- +::rtl::OUString SAL_CALL DatabaseDataProvider::getOrder() throw (uno::RuntimeException) +{ + osl::MutexGuard g(m_aMutex); + return m_Order; +} +// ----------------------------------------------------------------------------- +void SAL_CALL DatabaseDataProvider::setOrder( const ::rtl::OUString& the_value ) throw (uno::RuntimeException) +{ + { + osl::MutexGuard g(m_aMutex); + m_xAggregateSet->setPropertyValue( PROPERTY_ORDER, uno::makeAny( the_value ) ); + } + set(PROPERTY_ORDER,the_value,m_Order); +} +// ----------------------------------------------------------------------------- +::sal_Bool SAL_CALL DatabaseDataProvider::getEscapeProcessing() throw (uno::RuntimeException) +{ + osl::MutexGuard g(m_aMutex); + return m_EscapeProcessing; +} +// ----------------------------------------------------------------------------- + +void SAL_CALL DatabaseDataProvider::setEscapeProcessing(::sal_Bool the_value) throw (uno::RuntimeException) +{ + set(PROPERTY_ESCAPE_PROCESSING,the_value,m_EscapeProcessing); +} +// ----------------------------------------------------------------------------- +::sal_Int32 SAL_CALL DatabaseDataProvider::getRowLimit() throw (uno::RuntimeException) +{ + osl::MutexGuard g(m_aMutex); + return m_RowLimit; +} +// ----------------------------------------------------------------------------- + +void SAL_CALL DatabaseDataProvider::setRowLimit(::sal_Int32 the_value) throw (uno::RuntimeException) +{ + set(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("RowLimit")),the_value,m_RowLimit); +} +// ----------------------------------------------------------------------------- +uno::Reference< sdbc::XConnection > SAL_CALL DatabaseDataProvider::getActiveConnection() throw (uno::RuntimeException) +{ + osl::MutexGuard g(m_aMutex); + return m_xActiveConnection; +} +// ----------------------------------------------------------------------------- + +void SAL_CALL DatabaseDataProvider::setActiveConnection(const uno::Reference< sdbc::XConnection > & the_value) throw (uno::RuntimeException, lang::IllegalArgumentException) +{ + if ( !the_value.is() ) + throw lang::IllegalArgumentException(); + set(PROPERTY_ACTIVE_CONNECTION,the_value,m_xActiveConnection); +} +// ----------------------------------------------------------------------------- +::rtl::OUString SAL_CALL DatabaseDataProvider::getDataSourceName() throw (uno::RuntimeException) +{ + osl::MutexGuard g(m_aMutex); + return m_DataSourceName; +} +// ----------------------------------------------------------------------------- + +void SAL_CALL DatabaseDataProvider::setDataSourceName(const ::rtl::OUString& the_value) throw (uno::RuntimeException) +{ + set(PROPERTY_DATASOURCENAME,the_value,m_DataSourceName); +} +// ----------------------------------------------------------------------------- +void DatabaseDataProvider::impl_executeRowSet_throw(::osl::ResettableMutexGuard& _rClearForNotifies) +{ + if ( impl_fillParameters_nothrow(_rClearForNotifies) ) + m_xRowSet->execute(); +} +// ----------------------------------------------------------------------------- +void DatabaseDataProvider::impl_fillInternalDataProvider_throw(sal_Bool _bHasCategories,const uno::Sequence< uno::Sequence< ::rtl::OUString > >& i_aColumnNames) +{ + // clear the data before fill the new one + uno::Reference< chart::XChartDataArray> xChartData(m_xInternal,uno::UNO_QUERY); + if ( xChartData.is() ) + { + xChartData->setData(uno::Sequence< uno::Sequence<double> >()); + xChartData->setColumnDescriptions(uno::Sequence< ::rtl::OUString >()); + if ( m_xInternal->hasDataByRangeRepresentation(::rtl::OUString::valueOf(sal_Int32(0))) ) + m_xInternal->deleteSequence(0); + } + + uno::Reference< sdbcx::XColumnsSupplier> xColSup(m_xRowSet,uno::UNO_QUERY_THROW); + uno::Reference< container::XNameAccess > xColumns = xColSup->getColumns(); + uno::Sequence< ::rtl::OUString > aColumns; + if ( i_aColumnNames.getLength() ) + { + aColumns.realloc(1); + aColumns[0] = xColumns->getElementNames()[0]; + for(sal_Int32 i = 0 ; i < i_aColumnNames.getLength();++i) + { + if ( i_aColumnNames[i].getLength() ) + { + sal_Int32 nCount = aColumns.getLength(); + aColumns.realloc(nCount+1); + aColumns[nCount] = i_aColumnNames[i][0]; + } + } + } + else + { + aColumns = xColumns->getElementNames(); + } + // fill the data + uno::Reference< sdbc::XResultSet> xRes(m_xRowSet,uno::UNO_QUERY_THROW); + uno::Reference< sdbc::XRow> xRow(m_xRowSet,uno::UNO_QUERY_THROW); + uno::Reference< sdbc::XResultSetMetaData> xResultSetMetaData = uno::Reference< sdbc::XResultSetMetaDataSupplier>(m_xRowSet,uno::UNO_QUERY)->getMetaData(); + uno::Reference< sdbc::XColumnLocate> xColumnLocate(m_xRowSet,uno::UNO_QUERY_THROW); + + ::std::vector<sal_Int32> aColumnTypes; + uno::Sequence< uno::Any > aLabelArgs(1); + const sal_Int32 nCount = aColumns.getLength(); + if ( nCount ) + aColumnTypes.push_back(xResultSetMetaData->getColumnType(1)); + + ::std::vector< sal_Int32 > aColumnPositions; + const ::rtl::OUString* pIter = aColumns.getConstArray(); + const ::rtl::OUString* pEnd = pIter + aColumns.getLength(); + for(sal_Int32 k = 0;pIter != pEnd;++pIter,++k) + { + aColumnPositions.push_back(xColumnLocate->findColumn(*pIter)); + uno::Reference< beans::XPropertySet> xColumn(xColumns->getByName(*pIter),uno::UNO_QUERY); + sal_Int32 nType = sdbc::DataType::VARCHAR; + if ( xColumn.is() ) + { + m_aNumberFormats.insert( ::std::map< ::rtl::OUString,uno::Any>::value_type(::rtl::OUString::valueOf(k),xColumn->getPropertyValue(PROPERTY_NUMBERFORMAT))); + xColumn->getPropertyValue(PROPERTY_TYPE) >>= nType; + } + aColumnTypes.push_back(nType); + } + + ::std::vector< ::rtl::OUString > aRowLabels; + ::std::vector< ::std::vector< double > > aDataValues; + sal_Int32 nRowCount = 0; + ::connectivity::ORowSetValue aValue; + while( xRes->next() && (!m_RowLimit || nRowCount < m_RowLimit) ) + { + ++nRowCount; + + aValue.fill(1,aColumnTypes[0],xRow); + aRowLabels.push_back(aValue.getString()); + ::std::vector< double > aRow; + ::std::vector< sal_Int32 >::iterator aColumnPosIter = aColumnPositions.begin(); + ::std::vector< sal_Int32 >::iterator aColumnPosEnd = aColumnPositions.end(); + sal_Int32 i = 0; + if ( _bHasCategories ) + { + ++aColumnPosIter; + ++i; + } + for (; aColumnPosIter != aColumnPosEnd; ++aColumnPosIter,++i) + { + aValue.fill(*aColumnPosIter,aColumnTypes[i],xRow); + if ( aValue.isNull() ) + { + double nValue; + ::rtl::math::setNan( &nValue ); + aRow.push_back(nValue); + } + else + aRow.push_back(aValue.getDouble()); + } + aDataValues.push_back(aRow); + } // while( xRes->next() && (!m_RowLimit || nRowCount < m_RowLimit) ) + + // insert default data when no rows exist + if ( !nRowCount ) + { + nRowCount = 3; + const double fDefaultData[ ] = + { 9.10, 3.20, 4.54, + 2.40, 8.80, 9.65, + 3.10, 1.50, 3.70, + 4.30, 9.02, 6.20 }; + for(sal_Int32 h = 0,k = 0; h < nRowCount; ++h,++k ) + { + aRowLabels.push_back(::rtl::OUString::valueOf(h+1)); + ::std::vector< double > aRow; + const sal_Int32 nSize = sizeof(fDefaultData)/sizeof(fDefaultData[0]); + for (sal_Int32 j = 0; j < (nCount-1); ++j,++k) + { + if ( k >= nSize ) + k = 0; + aRow.push_back(fDefaultData[k]); + } // for (sal_Int32 j = 0,k = 0; j < (nCount-1); ++j,++k) + aDataValues.push_back(aRow); + } + } // if ( !nRowCount ) + + uno::Reference< chart::XChartDataArray> xData(m_xInternal,uno::UNO_QUERY); + xData->setRowDescriptions(uno::Sequence< ::rtl::OUString >(&(*aRowLabels.begin()),aRowLabels.size())); + xData->setColumnDescriptions(uno::Sequence< ::rtl::OUString >(aColumns.getArray()+ (_bHasCategories ? 1 : 0),aColumns.getLength() - (_bHasCategories ? 1 : 0) )); + uno::Sequence< uno::Sequence< double > > aData(aDataValues.size()); + uno::Sequence< double >* pDataIter = aData.getArray(); + uno::Sequence< double >* pDataEnd = pDataIter + aData.getLength(); + for(sal_Int32 i= 0;pDataIter != pDataEnd; ++pDataIter,++i ) + { + if ( !aDataValues[i].empty() ) + *pDataIter = uno::Sequence< double >(&(*(aDataValues[i]).begin()),(aDataValues[i]).size()); + } + xData->setData(aData); +} +// ----------------------------------------------------------------------------- +void DatabaseDataProvider::impl_fillRowSet_throw() +{ + m_xAggregateSet->setPropertyValue( PROPERTY_FILTER, uno::makeAny( getFilter() ) ); + uno::Reference< sdbc::XParameters> xParam(m_xRowSet,uno::UNO_QUERY_THROW); + xParam->clearParameters( ); +} +// ----------------------------------------------------------------------------- +bool DatabaseDataProvider::impl_fillParameters_nothrow( ::osl::ResettableMutexGuard& _rClearForNotifies) +{ + // do we have to fill the parameters again? + if ( !m_aParameterManager.isUpToDate() ) + m_aParameterManager.updateParameterInfo( m_aFilterManager ); + + if ( m_aParameterManager.isUpToDate() ) + return m_aParameterManager.fillParameterValues( m_xHandler, _rClearForNotifies ); + + return true; +} +// com::sun::star::sdbc::XParameters +//------------------------------------------------------------------------------ +void SAL_CALL DatabaseDataProvider::setNull(sal_Int32 parameterIndex, sal_Int32 sqlType) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setNull(parameterIndex, sqlType); +} + +//------------------------------------------------------------------------------ +void SAL_CALL DatabaseDataProvider::setObjectNull(sal_Int32 parameterIndex, sal_Int32 sqlType, const ::rtl::OUString& typeName) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setObjectNull(parameterIndex, sqlType, typeName); +} + +//------------------------------------------------------------------------------ +void SAL_CALL DatabaseDataProvider::setBoolean(sal_Int32 parameterIndex, sal_Bool x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setBoolean(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL DatabaseDataProvider::setByte(sal_Int32 parameterIndex, sal_Int8 x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setByte(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL DatabaseDataProvider::setShort(sal_Int32 parameterIndex, sal_Int16 x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setShort(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL DatabaseDataProvider::setInt(sal_Int32 parameterIndex, sal_Int32 x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setInt(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL DatabaseDataProvider::setLong(sal_Int32 parameterIndex, sal_Int64 x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setLong(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL DatabaseDataProvider::setFloat(sal_Int32 parameterIndex, float x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setFloat(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL DatabaseDataProvider::setDouble(sal_Int32 parameterIndex, double x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setDouble(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL DatabaseDataProvider::setString(sal_Int32 parameterIndex, const ::rtl::OUString& x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setString(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL DatabaseDataProvider::setBytes(sal_Int32 parameterIndex, const uno::Sequence< sal_Int8 >& x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setBytes(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL DatabaseDataProvider::setDate(sal_Int32 parameterIndex, const util::Date& x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setDate(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL DatabaseDataProvider::setTime(sal_Int32 parameterIndex, const util::Time& x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setTime(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL DatabaseDataProvider::setTimestamp(sal_Int32 parameterIndex, const util::DateTime& x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setTimestamp(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL DatabaseDataProvider::setBinaryStream(sal_Int32 parameterIndex, const uno::Reference<io::XInputStream>& x, sal_Int32 length) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setBinaryStream(parameterIndex, x, length); +} + +//------------------------------------------------------------------------------ +void SAL_CALL DatabaseDataProvider::setCharacterStream(sal_Int32 parameterIndex, const uno::Reference<io::XInputStream>& x, sal_Int32 length) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setCharacterStream(parameterIndex, x, length); +} + +//------------------------------------------------------------------------------ +void SAL_CALL DatabaseDataProvider::setObjectWithInfo(sal_Int32 parameterIndex, const uno::Any& x, sal_Int32 targetSqlType, sal_Int32 scale) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setObjectWithInfo(parameterIndex, x, targetSqlType, scale); +} + +//------------------------------------------------------------------------------ +void SAL_CALL DatabaseDataProvider::setObject(sal_Int32 parameterIndex, const uno::Any& x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setObject(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL DatabaseDataProvider::setRef(sal_Int32 parameterIndex, const uno::Reference<sdbc::XRef>& x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setRef(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL DatabaseDataProvider::setBlob(sal_Int32 parameterIndex, const uno::Reference<sdbc::XBlob>& x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setBlob(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL DatabaseDataProvider::setClob(sal_Int32 parameterIndex, const uno::Reference<sdbc::XClob>& x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setClob(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL DatabaseDataProvider::setArray(sal_Int32 parameterIndex, const Reference<sdbc::XArray>& x) throw( SQLException, RuntimeException ) +{ + m_aParameterManager.setArray(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL DatabaseDataProvider::clearParameters() throw( SQLException, RuntimeException ) +{ + m_aParameterManager.clearParameters(); +} +//============================================================================== +// com::sun::star::sdbc::XRowSet +//------------------------------------------------------------------------------ +void SAL_CALL DatabaseDataProvider::execute() throw( SQLException, RuntimeException ) +{ + uno::Sequence< beans::PropertyValue > aEmpty; + createDataSource(aEmpty); +} +//------------------------------------------------------------------------------ +void SAL_CALL DatabaseDataProvider::addRowSetListener(const uno::Reference<sdbc::XRowSetListener>& _rListener) throw( RuntimeException ) +{ + if (m_xRowSet.is()) + m_xRowSet->addRowSetListener(_rListener); +} + +//------------------------------------------------------------------------------ +void SAL_CALL DatabaseDataProvider::removeRowSetListener(const uno::Reference<sdbc::XRowSetListener>& _rListener) throw( RuntimeException ) +{ + if (m_xRowSet.is()) + m_xRowSet->removeRowSetListener(_rListener); +} +//============================================================================== +// com::sun::star::sdbc::XResultSet +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL DatabaseDataProvider::next() throw( SQLException, RuntimeException ) +{ + return m_xRowSet->next(); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL DatabaseDataProvider::isBeforeFirst() throw( SQLException, RuntimeException ) +{ + return m_xRowSet->isBeforeFirst(); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL DatabaseDataProvider::isAfterLast() throw( SQLException, RuntimeException ) +{ + return m_xRowSet->isAfterLast(); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL DatabaseDataProvider::isFirst() throw( SQLException, RuntimeException ) +{ + return m_xRowSet->isFirst(); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL DatabaseDataProvider::isLast() throw( SQLException, RuntimeException ) +{ + return m_xRowSet->isLast(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL DatabaseDataProvider::beforeFirst() throw( SQLException, RuntimeException ) +{ + m_xRowSet->beforeFirst(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL DatabaseDataProvider::afterLast() throw( SQLException, RuntimeException ) +{ + m_xRowSet->afterLast(); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL DatabaseDataProvider::first() throw( SQLException, RuntimeException ) +{ + return m_xRowSet->first(); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL DatabaseDataProvider::last() throw( SQLException, RuntimeException ) +{ + return m_xRowSet->last(); +} + +//------------------------------------------------------------------------------ +sal_Int32 SAL_CALL DatabaseDataProvider::getRow() throw( SQLException, RuntimeException ) +{ + return m_xRowSet->getRow(); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL DatabaseDataProvider::absolute(sal_Int32 row) throw( SQLException, RuntimeException ) +{ + return m_xRowSet->absolute(row); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL DatabaseDataProvider::relative(sal_Int32 rows) throw( SQLException, RuntimeException ) +{ + return m_xRowSet->relative(rows); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL DatabaseDataProvider::previous() throw( SQLException, RuntimeException ) +{ + return m_xRowSet->previous(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL DatabaseDataProvider::refreshRow() throw( SQLException, RuntimeException ) +{ + m_xRowSet->refreshRow(); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL DatabaseDataProvider::rowUpdated() throw( SQLException, RuntimeException ) +{ + return m_xRowSet->rowUpdated(); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL DatabaseDataProvider::rowInserted() throw( SQLException, RuntimeException ) +{ + return m_xRowSet->rowInserted(); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL DatabaseDataProvider::rowDeleted() throw( SQLException, RuntimeException ) +{ + return m_xRowSet->rowDeleted(); +} + +//------------------------------------------------------------------------------ +uno::Reference< uno::XInterface > SAL_CALL DatabaseDataProvider::getStatement() throw( SQLException, RuntimeException ) +{ + return m_xRowSet->getStatement(); +} +// ----------------------------------------------------------------------------- +uno::Reference< uno::XInterface > SAL_CALL DatabaseDataProvider::getParent( ) throw (uno::RuntimeException) +{ + return m_xParent; +} +// ----------------------------------------------------------------------------- +void SAL_CALL DatabaseDataProvider::setParent( const uno::Reference< uno::XInterface >& _xParent ) throw (lang::NoSupportException, uno::RuntimeException) +{ + osl::MutexGuard g(m_aMutex); + m_xParent = _xParent; +} +// ----------------------------------------------------------------------------- +void DatabaseDataProvider::impl_invalidateParameter_nothrow() +{ + osl::MutexGuard g(m_aMutex); + m_aParameterManager.clearAllParameterInformation(); +} +// ----------------------------------------------------------------------------- +} // namespace dbaccess diff --git a/dbaccess/source/core/misc/PropertyForward.cxx b/dbaccess/source/core/misc/PropertyForward.cxx new file mode 100644 index 000000000000..4f9aa81ab28c --- /dev/null +++ b/dbaccess/source/core/misc/PropertyForward.cxx @@ -0,0 +1,173 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#include "PropertyForward.hxx" +#include "dbastrings.hrc" + +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp> +#include <com/sun/star/sdbcx/XAppend.hpp> + +#include <comphelper/property.hxx> +#include <tools/debug.hxx> +#include <tools/diagnose_ex.h> + + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::container; + using namespace ::com::sun::star::sdbcx; + using namespace ::com::sun::star::lang; + + DBG_NAME(OPropertyForward) + + //------------------------------------------------------------------------ + OPropertyForward::OPropertyForward( const Reference< XPropertySet>& _xSource, const Reference< XNameAccess>& _xDestContainer, + const ::rtl::OUString& _sName, const ::std::vector< ::rtl::OUString>& _aPropertyList ) + :m_xSource( _xSource, UNO_SET_THROW ) + ,m_xDestContainer( _xDestContainer, UNO_SET_THROW ) + ,m_sName( _sName ) + ,m_bInInsert( sal_False ) + { + DBG_CTOR(OPropertyForward,NULL); + + osl_incrementInterlockedCount(&m_refCount); + try + { + if ( _aPropertyList.empty() ) + _xSource->addPropertyChangeListener( ::rtl::OUString(), this ); + else + { + ::std::vector< ::rtl::OUString >::const_iterator aIter = _aPropertyList.begin(); + ::std::vector< ::rtl::OUString >::const_iterator aEnd = _aPropertyList.end(); + for (; aIter != aEnd ; ++aIter ) + _xSource->addPropertyChangeListener( *aIter, this ); + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + osl_decrementInterlockedCount( &m_refCount ); + } + + // ----------------------------------------------------------------------------- + OPropertyForward::~OPropertyForward() + { + DBG_DTOR(OPropertyForward,NULL); + } + + // ----------------------------------------------------------------------------- + void SAL_CALL OPropertyForward::propertyChange( const PropertyChangeEvent& evt ) throw(RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( !m_xDestContainer.is() ) + throw DisposedException( ::rtl::OUString(), *this ); + + try + { + if ( !m_xDest.is() ) + { + if ( m_xDestContainer->hasByName( m_sName ) ) + { + m_xDest.set( m_xDestContainer->getByName( m_sName ), UNO_QUERY_THROW ); + } + else + { + Reference< XDataDescriptorFactory > xFactory( m_xDestContainer, UNO_QUERY_THROW ); + m_xDest.set( xFactory->createDataDescriptor(), UNO_SET_THROW ); + + ::comphelper::copyProperties( m_xSource, m_xDest ); + + m_bInInsert = sal_True; + Reference< XAppend > xAppend( m_xDestContainer, UNO_QUERY_THROW ); + xAppend->appendByDescriptor( m_xDest ); + m_bInInsert = sal_False; + } + + m_xDestInfo.set( m_xDest->getPropertySetInfo(), UNO_SET_THROW ); + } + + if ( m_xDestInfo->hasPropertyByName( evt.PropertyName ) ) + { + m_xDest->setPropertyValue( evt.PropertyName, evt.NewValue ); + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + // ----------------------------------------------------------------------------- + void SAL_CALL OPropertyForward::disposing( const ::com::sun::star::lang::EventObject& /*_rSource*/ ) throw (RuntimeException) + { + ::osl::MutexGuard aGuard(m_aMutex); + + if ( !m_xSource.is() ) + throw DisposedException( ::rtl::OUString(), *this ); + + m_xSource->removePropertyChangeListener( ::rtl::OUString(), this ); + m_xSource = NULL; + m_xDestContainer = NULL; + m_xDestInfo = NULL; + m_xDest = NULL; + } + + // ----------------------------------------------------------------------------- + void OPropertyForward::setDefinition( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet>& _xDest ) + { + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bInInsert ) + return; + + OSL_ENSURE( !m_xDest.is(), "OPropertyForward::setDefinition: definition object is already set!" ); + try + { + m_xDest.set( _xDest, UNO_SET_THROW ); + m_xDestInfo.set( m_xDest->getPropertySetInfo(), UNO_SET_THROW ); + ::comphelper::copyProperties( m_xDest, m_xSource ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + +//........................................................................ +} // namespace dbaccess +//........................................................................ + diff --git a/dbaccess/source/core/misc/apitools.cxx b/dbaccess/source/core/misc/apitools.cxx new file mode 100644 index 000000000000..c53f936df234 --- /dev/null +++ b/dbaccess/source/core/misc/apitools.cxx @@ -0,0 +1,155 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#ifndef _DBASHARED_APITOOLS_HXX_ +#include "apitools.hxx" +#endif +#ifndef DBACCESS_SHARED_DBASTRINGS_HRC +#include "dbastrings.hrc" +#endif +#ifndef _CPPUHELPER_TYPEPROVIDER_HXX_ +#include <cppuhelper/typeprovider.hxx> +#endif +#include <com/sun/star/lang/XServiceInfo.hpp> +#ifndef _OSL_DIAGNOSE_H_ +#include <osl/diagnose.h> +#endif +#ifndef _TOOLS_DEBUG_HXX +#include <tools/debug.hxx> +#endif + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace cppu; +using namespace osl; +using namespace dbaccess; + +//================================================================================== +//= various helper functions +//================================================================================== +//============================================================ +//= OSubComponent +//============================================================ +DBG_NAME(OSubComponent) +//-------------------------------------------------------------------------- +OSubComponent::OSubComponent(Mutex& _rMutex, const Reference< XInterface > & xParent) + :OComponentHelper(_rMutex) + ,m_xParent(xParent) +{ + DBG_CTOR(OSubComponent,NULL); + +} +// ----------------------------------------------------------------------------- +OSubComponent::~OSubComponent() +{ + m_xParent = NULL; + + DBG_DTOR(OSubComponent,NULL); +} + +// com::sun::star::lang::XTypeProvider +//-------------------------------------------------------------------------- +Sequence< Type > OSubComponent::getTypes() throw (RuntimeException) +{ + OTypeCollection aTypes(::getCppuType( (const Reference< XComponent > *)0 ), + ::getCppuType( (const Reference< XTypeProvider > *)0 ), + ::getCppuType( (const Reference< XWeak > *)0 )); + + return aTypes.getTypes(); +} + +// XInterface +//-------------------------------------------------------------------------- +void OSubComponent::acquire() throw ( ) +{ + OComponentHelper::acquire(); +} + +//-------------------------------------------------------------------------- +void OSubComponent::release() throw ( ) +{ + Reference< XInterface > x( xDelegator ); + if (! x.is()) + { + if (osl_decrementInterlockedCount( &m_refCount ) == 0 ) + { + if (! rBHelper.bDisposed) + { + // *before* again incrementing our ref count, ensure that our weak connection point + // will not create references to us anymore (via XAdapter::queryAdapted) + disposeWeakConnectionPoint(); + + Reference< XInterface > xHoldAlive( *this ); + // remember the parent + Reference< XInterface > xParent; + { + MutexGuard aGuard( rBHelper.rMutex ); + xParent = m_xParent; + m_xParent = NULL; + } + + OSL_ENSURE( m_refCount == 1, "OSubComponent::release: invalid ref count (before dispose)!" ); + + // First dispose + dispose(); + + // only the alive ref holds the object + OSL_ENSURE( m_refCount == 1, "OSubComponent::release: invalid ref count (after dispose)!" ); + + // release the parent in the ~ + if (xParent.is()) + { + MutexGuard aGuard( rBHelper.rMutex ); + m_xParent = xParent; + } + + // destroy the object if xHoldAlive decrement the refcount to 0 + return; + } + } + // restore the reference count + osl_incrementInterlockedCount( &m_refCount ); + } + + // as we cover the job of the componenthelper we use the ... + OWeakAggObject::release(); +} + +//-------------------------------------------------------------------------- +Any OSubComponent::queryInterface( const Type & rType ) throw(RuntimeException) +{ + Any aReturn; + if (!rType.equals(::getCppuType(static_cast< Reference< XAggregation >* >(NULL)))) + aReturn = OComponentHelper::queryInterface(rType); + + return aReturn; +} + + diff --git a/dbaccess/source/core/misc/dbastrings.cxx b/dbaccess/source/core/misc/dbastrings.cxx new file mode 100644 index 000000000000..80f1427842e8 --- /dev/null +++ b/dbaccess/source/core/misc/dbastrings.cxx @@ -0,0 +1,49 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" +#ifndef DBACCESS_SHARED_DBASTRINGS_HRC +#include "dbastrings.hrc" +#endif + +namespace dbaccess +{ + +#include "stringconstants.inc" + //============================================================ + //= SQLSTATE + //============================================================ + IMPLEMENT_CONSTASCII_USTRING(SQLSTATE_GENERAL, "01000"); + + //============================================================ + //= Properties + //============================================================ + 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/dsntypes.cxx b/dbaccess/source/core/misc/dsntypes.cxx new file mode 100644 index 000000000000..b21707cb3add --- /dev/null +++ b/dbaccess/source/core/misc/dsntypes.cxx @@ -0,0 +1,629 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#include "dsntypes.hxx" +#include "dbamiscres.hrc" +#include <unotools/confignode.hxx> +#include <tools/debug.hxx> +#include <tools/wldcrd.hxx> +#include <osl/file.hxx> +#include "dbastrings.hrc" +#include "core_resource.hxx" +#include "core_resource.hrc" +#include <comphelper/documentconstants.hxx> + +//......................................................................... +namespace dbaccess +{ +//......................................................................... + + using namespace ::com::sun::star; + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::lang; + //using namespace ::com::sun::star::sdbc; + + namespace + { + void lcl_extractHostAndPort(const String& _sUrl,String& _sHostname,sal_Int32& _nPortNumber) + { + if ( _sUrl.GetTokenCount(':') >= 2 ) + { + _sHostname = _sUrl.GetToken(0,':'); + _nPortNumber = _sUrl.GetToken(1,':').ToInt32(); + } + } + } +//========================================================================= +//= ODsnTypeCollection +//========================================================================= +DBG_NAME(ODsnTypeCollection) +//------------------------------------------------------------------------- +ODsnTypeCollection::ODsnTypeCollection(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _xFactory) +:m_aDriverConfig(_xFactory) +,m_xFactory(_xFactory) +#ifdef DBG_UTIL +,m_nLivingIterators(0) +#endif +{ + DBG_CTOR(ODsnTypeCollection,NULL); + const uno::Sequence< ::rtl::OUString > aURLs = m_aDriverConfig.getURLs(); + const ::rtl::OUString* pIter = aURLs.getConstArray(); + const ::rtl::OUString* pEnd = pIter + aURLs.getLength(); + for(;pIter != pEnd;++pIter ) + { + m_aDsnPrefixes.push_back(*pIter); + m_aDsnTypesDisplayNames.push_back(m_aDriverConfig.getDriverTypeDisplayName(*pIter)); + } + + DBG_ASSERT(m_aDsnTypesDisplayNames.size() == m_aDsnPrefixes.size(), + "ODsnTypeCollection::ODsnTypeCollection : invalid resources !"); +} + +//------------------------------------------------------------------------- +ODsnTypeCollection::~ODsnTypeCollection() +{ + DBG_DTOR(ODsnTypeCollection,NULL); + DBG_ASSERT(0 == m_nLivingIterators, "ODsnTypeCollection::~ODsnTypeCollection : there are still living iterator objects!"); +} +//------------------------------------------------------------------------- +String ODsnTypeCollection::getTypeDisplayName(const ::rtl::OUString& _sURL) const +{ + return m_aDriverConfig.getDriverTypeDisplayName(_sURL); +} +//------------------------------------------------------------------------- +String ODsnTypeCollection::cutPrefix(const ::rtl::OUString& _sURL) const +{ + String sURL( _sURL); + String sRet; + String sOldPattern; + StringVector::const_iterator aIter = m_aDsnPrefixes.begin(); + StringVector::const_iterator aEnd = m_aDsnPrefixes.end(); + for(;aIter != aEnd;++aIter) + { + WildCard aWildCard(*aIter); + if ( sOldPattern.Len() < aIter->Len() && aWildCard.Matches(_sURL) ) + { + if ( aIter->Len() < sURL.Len() ) + sRet = sURL.Copy(sURL.Match(*aIter)); + else + sRet = sURL.Copy(aIter->Match(sURL)); + sOldPattern = *aIter; + } + } + + return sRet; +} + +//------------------------------------------------------------------------- +String ODsnTypeCollection::getPrefix(const ::rtl::OUString& _sURL) const +{ + String sURL( _sURL); + String sRet; + String sOldPattern; + StringVector::const_iterator aIter = m_aDsnPrefixes.begin(); + StringVector::const_iterator aEnd = m_aDsnPrefixes.end(); + for(;aIter != aEnd;++aIter) + { + WildCard aWildCard(*aIter); + if ( sOldPattern.Len() < aIter->Len() && aWildCard.Matches(sURL) ) + { + if ( aIter->Len() < sURL.Len() ) + sRet = aIter->Copy(0,sURL.Match(*aIter)); + else + sRet = sURL.Copy(0,aIter->Match(sURL)); + sRet.EraseTrailingChars('*'); + sOldPattern = *aIter; + } + } + + return sRet; +} + +//------------------------------------------------------------------------- +bool ODsnTypeCollection::hasDriver( const sal_Char* _pAsciiPattern ) const +{ + String sPrefix( getPrefix( ::rtl::OUString::createFromAscii( _pAsciiPattern ) ) ); + return ( sPrefix.Len() > 0 ); +} + +// ----------------------------------------------------------------------------- +bool ODsnTypeCollection::isConnectionUrlRequired(const ::rtl::OUString& _sURL) const +{ + String sURL( _sURL); + String sRet; + String sOldPattern; + StringVector::const_iterator aIter = m_aDsnPrefixes.begin(); + StringVector::const_iterator aEnd = m_aDsnPrefixes.end(); + for(;aIter != aEnd;++aIter) + { + WildCard aWildCard(*aIter); + if ( sOldPattern.Len() < aIter->Len() && aWildCard.Matches(sURL) ) + { + sRet = *aIter; + sOldPattern = *aIter; + } + } // for(;aIter != aEnd;++aIter) + return sRet.GetChar(sRet.Len()-1) == '*'; +} +// ----------------------------------------------------------------------------- +String ODsnTypeCollection::getMediaType(const ::rtl::OUString& _sURL) const +{ + const ::comphelper::NamedValueCollection& aFeatures = m_aDriverConfig.getMetaData(_sURL); + return aFeatures.getOrDefault("MediaType",::rtl::OUString()); +} +// ----------------------------------------------------------------------------- +String ODsnTypeCollection::getDatasourcePrefixFromMediaType(const ::rtl::OUString& _sMediaType,const ::rtl::OUString& _sExtension) +{ + String sURL, sFallbackURL; + const uno::Sequence< ::rtl::OUString > aURLs = m_aDriverConfig.getURLs(); + const ::rtl::OUString* pIter = aURLs.getConstArray(); + const ::rtl::OUString* pEnd = pIter + aURLs.getLength(); + for(;pIter != pEnd;++pIter ) + { + const ::comphelper::NamedValueCollection& aFeatures = m_aDriverConfig.getMetaData(*pIter); + if ( aFeatures.getOrDefault("MediaType",::rtl::OUString()) == _sMediaType ) + { + const ::rtl::OUString sFileExtension = aFeatures.getOrDefault("Extension",::rtl::OUString()); + if ( _sExtension == sFileExtension ) + { + sURL = *pIter; + break; + } + if ( !sFileExtension.getLength() && _sExtension.getLength() ) + sFallbackURL = *pIter; + } + } // for(;pIter != pEnd;++pIter ) + + if ( !sURL.Len() && sFallbackURL.Len() ) + sURL = sFallbackURL; + + sURL.EraseTrailingChars('*'); + return sURL; +} +// ----------------------------------------------------------------------------- +bool ODsnTypeCollection::isShowPropertiesEnabled( const ::rtl::OUString& _sURL ) const +{ + return !( _sURL.matchIgnoreAsciiCaseAsciiL("sdbc:embedded:hsqldb",sizeof("sdbc:embedded:hsqldb")-1) + || _sURL.matchIgnoreAsciiCaseAsciiL("sdbc:address:outlook",sizeof("sdbc:address:outlook")-1) + || _sURL.matchIgnoreAsciiCaseAsciiL("sdbc:address:outlookexp",sizeof("sdbc:address:outlookexp")-1) + || _sURL.matchIgnoreAsciiCaseAsciiL("sdbc:address:mozilla:",sizeof("sdbc:address:mozilla:")-1) + || _sURL.matchIgnoreAsciiCaseAsciiL("sdbc:address:kab",sizeof("sdbc:address:kab")-1) + || _sURL.matchIgnoreAsciiCaseAsciiL("sdbc:address:evolution:local",sizeof("sdbc:address:evolution:local")-1) + || _sURL.matchIgnoreAsciiCaseAsciiL("sdbc:address:evolution:groupwise",sizeof("sdbc:address:evolution:groupwise")-1) + || _sURL.matchIgnoreAsciiCaseAsciiL("sdbc:address:evolution:ldap",sizeof("sdbc:address:evolution:ldap")-1) + || _sURL.matchIgnoreAsciiCaseAsciiL("sdbc:address:macab",sizeof("sdbc:address:macab")-1) ); +} +// ----------------------------------------------------------------------------- +void ODsnTypeCollection::extractHostNamePort(const ::rtl::OUString& _rDsn,String& _sDatabaseName,String& _rsHostname,sal_Int32& _nPortNumber) const +{ + String sUrl = cutPrefix(_rDsn); + if ( _rDsn.matchIgnoreAsciiCaseAsciiL("jdbc:oracle:thin:",sizeof("jdbc:oracle:thin:")-1) ) + { + lcl_extractHostAndPort(sUrl,_rsHostname,_nPortNumber); + if ( !_rsHostname.Len() && sUrl.GetTokenCount(':') == 2 ) + { + _nPortNumber = -1; + _rsHostname = sUrl.GetToken(0,':'); + } + if ( _rsHostname.Len() ) + _rsHostname = _rsHostname.GetToken(_rsHostname.GetTokenCount('@') - 1,'@'); + _sDatabaseName = sUrl.GetToken(sUrl.GetTokenCount(':') - 1,':'); + } // if ( _rDsn.matchIgnoreAsciiCaseAsciiL("jdbc:oracle:thin:",sizeof("jdbc:oracle:thin:")-1) ) + else if ( _rDsn.matchIgnoreAsciiCaseAsciiL("sdbc:address:ldap:",sizeof("sdbc:address:ldap:")-1) ) + { + lcl_extractHostAndPort(sUrl,_sDatabaseName,_nPortNumber); + } + else if ( _rDsn.matchIgnoreAsciiCaseAsciiL("sdbc:adabas:",sizeof("sdbc:adabas:")-1) ) + { + if ( sUrl.GetTokenCount(':') == 2 ) + _rsHostname = sUrl.GetToken(0,':'); + _sDatabaseName = sUrl.GetToken(sUrl.GetTokenCount(':') - 1,':'); + } + else if ( _rDsn.matchIgnoreAsciiCaseAsciiL("sdbc:mysql:mysqlc:",sizeof("sdbc:mysql:mysqlc:")-1) || _rDsn.matchIgnoreAsciiCaseAsciiL("sdbc:mysql:jdbc:",sizeof("sdbc:mysql:jdbc:")-1) ) + { + lcl_extractHostAndPort(sUrl,_rsHostname,_nPortNumber); + + if ( _nPortNumber == -1 && !_rsHostname.Len() && sUrl.GetTokenCount('/') == 2 ) + _rsHostname = sUrl.GetToken(0,'/'); + _sDatabaseName = sUrl.GetToken(sUrl.GetTokenCount('/') - 1,'/'); + } + else if ( _rDsn.matchIgnoreAsciiCaseAsciiL("sdbc:ado:access:Provider=Microsoft.ACE.OLEDB.12.0;DATA SOURCE=",sizeof("sdbc:ado:access:Provider=Microsoft.ACE.OLEDB.12.0;DATA SOURCE=")-1) + || _rDsn.matchIgnoreAsciiCaseAsciiL("sdbc:ado:access:PROVIDER=Microsoft.Jet.OLEDB.4.0;DATA SOURCE=",sizeof("sdbc:ado:access:PROVIDER=Microsoft.Jet.OLEDB.4.0;DATA SOURCE=")-1)) + { + ::rtl::OUString sNewFileName; + if ( ::osl::FileBase::getFileURLFromSystemPath( sUrl, sNewFileName ) == ::osl::FileBase::E_None ) + { + _sDatabaseName = sNewFileName; + } + } +} +// ----------------------------------------------------------------------------- +String ODsnTypeCollection::getJavaDriverClass(const ::rtl::OUString& _sURL) const +{ + const ::comphelper::NamedValueCollection& aFeatures = m_aDriverConfig.getProperties(_sURL); + return aFeatures.getOrDefault("JavaDriverClass",::rtl::OUString()); +} +//------------------------------------------------------------------------- +sal_Bool ODsnTypeCollection::isFileSystemBased(const ::rtl::OUString& _sURL) const +{ + const ::comphelper::NamedValueCollection& aFeatures = m_aDriverConfig.getMetaData(_sURL); + return aFeatures.getOrDefault("FileSystemBased",sal_False); +} +// ----------------------------------------------------------------------------- +sal_Bool ODsnTypeCollection::supportsTableCreation(const ::rtl::OUString& _sURL) const +{ + const ::comphelper::NamedValueCollection& aFeatures = m_aDriverConfig.getMetaData(_sURL); + return aFeatures.getOrDefault("SupportsTableCreation",sal_False); +} +// ----------------------------------------------------------------------------- +sal_Bool ODsnTypeCollection::supportsColumnDescription(const ::rtl::OUString& _sURL) const +{ + const ::comphelper::NamedValueCollection& aFeatures = m_aDriverConfig.getMetaData(_sURL); + return aFeatures.getOrDefault("SupportsColumnDescription",sal_False); +} +// ----------------------------------------------------------------------------- +sal_Bool ODsnTypeCollection::supportsBrowsing(const ::rtl::OUString& _sURL) const +{ + const ::comphelper::NamedValueCollection& aFeatures = m_aDriverConfig.getMetaData(_sURL); + return aFeatures.getOrDefault("SupportsBrowsing",sal_False); +} +// ----------------------------------------------------------------------------- +bool ODsnTypeCollection::needsJVM(const String& _sURL) const +{ + const ::comphelper::NamedValueCollection& aFeatures = m_aDriverConfig.getMetaData(_sURL); + return aFeatures.getOrDefault("UseJava",sal_False); +} +// ----------------------------------------------------------------------------- +Sequence<PropertyValue> ODsnTypeCollection::getDefaultDBSettings( const ::rtl::OUString& _sURL ) const +{ + const ::comphelper::NamedValueCollection& aProperties = m_aDriverConfig.getProperties(_sURL); + return aProperties.getPropertyValues(); +} + +//------------------------------------------------------------------------- +bool ODsnTypeCollection::isEmbeddedDatabase( const ::rtl::OUString& _sURL ) const +{ + const ::rtl::OUString sEmbeddedDatabaseURL = getEmbeddedDatabase(); + WildCard aWildCard(sEmbeddedDatabaseURL); + return aWildCard.Matches(_sURL); +} +// ----------------------------------------------------------------------------- +::rtl::OUString ODsnTypeCollection::getEmbeddedDatabase() const +{ + ::rtl::OUString sEmbeddedDatabaseURL; + static const ::rtl::OUString s_sNodeName(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.Office.DataAccess")); ///Installed + const ::utl::OConfigurationTreeRoot aInstalled = ::utl::OConfigurationTreeRoot::createWithServiceFactory(m_xFactory, s_sNodeName, -1, ::utl::OConfigurationTreeRoot::CM_READONLY); + if ( aInstalled.isValid() ) + { + if ( aInstalled.hasByName("EmbeddedDatabases/DefaultEmbeddedDatabase/Value") ) + { + static const ::rtl::OUString s_sValue(RTL_CONSTASCII_USTRINGPARAM("EmbeddedDatabases/DefaultEmbeddedDatabase/Value")); + + aInstalled.getNodeValue(s_sValue) >>= sEmbeddedDatabaseURL; + if ( sEmbeddedDatabaseURL.getLength() ) + aInstalled.getNodeValue(s_sValue + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/")) + sEmbeddedDatabaseURL + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/URL"))) >>= sEmbeddedDatabaseURL; + } + } // if ( aInstalled.isValid() ) + if ( !sEmbeddedDatabaseURL.getLength() ) + sEmbeddedDatabaseURL = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("sdbc:embedded:hsqldb")); + return sEmbeddedDatabaseURL; +} +//------------------------------------------------------------------------- +ODsnTypeCollection::TypeIterator ODsnTypeCollection::begin() const +{ + return TypeIterator(this, 0); +} + +//------------------------------------------------------------------------- +ODsnTypeCollection::TypeIterator ODsnTypeCollection::end() const +{ + return TypeIterator(this, m_aDsnTypesDisplayNames.size()); +} +//------------------------------------------------------------------------- +DATASOURCE_TYPE ODsnTypeCollection::determineType(const String& _rDsn) const +{ + String sDsn(_rDsn); + sDsn.EraseTrailingChars('*'); + sal_uInt16 nSeparator = sDsn.Search((sal_Unicode)':'); + if (STRING_NOTFOUND == nSeparator) + { + // there should be at least one such separator + DBG_ERROR("ODsnTypeCollection::implDetermineType : missing the colon !"); + return DST_UNKNOWN; + } + // find first : + sal_uInt16 nOracleSeparator = sDsn.Search((sal_Unicode)':', nSeparator + 1); + if ( nOracleSeparator != STRING_NOTFOUND ) + { + nOracleSeparator = sDsn.Search((sal_Unicode)':', nOracleSeparator + 1); + if (nOracleSeparator != STRING_NOTFOUND && sDsn.EqualsIgnoreCaseAscii("jdbc:oracle:thin", 0, nOracleSeparator)) + return DST_ORACLE_JDBC; + } + + if (sDsn.EqualsIgnoreCaseAscii("jdbc", 0, nSeparator)) + return DST_JDBC; + + if (sDsn.EqualsIgnoreCaseAscii("sdbc:embedded:hsqldb", 0, sDsn.Len())) + return DST_EMBEDDED_HSQLDB; + + // find second : + nSeparator = sDsn.Search((sal_Unicode)':', nSeparator + 1); + if (STRING_NOTFOUND == nSeparator) + { + // at the moment only jdbc is allowed to have just one separator + DBG_ERROR("ODsnTypeCollection::implDetermineType : missing the second colon !"); + return DST_UNKNOWN; + } + + if (sDsn.EqualsIgnoreCaseAscii("sdbc:ado:", 0, nSeparator)) + { + nSeparator = sDsn.Search((sal_Unicode)':', nSeparator + 1); + if (STRING_NOTFOUND != nSeparator && sDsn.EqualsIgnoreCaseAscii("sdbc:ado:access",0, nSeparator) ) + { + nSeparator = sDsn.Search((sal_Unicode)';', nSeparator + 1); + if (STRING_NOTFOUND != nSeparator && sDsn.EqualsIgnoreCaseAscii("sdbc:ado:access:Provider=Microsoft.ACE.OLEDB.12.0",0, nSeparator) ) + return DST_MSACCESS_2007; + + return DST_MSACCESS; + } + return DST_ADO; + } + + struct KnownPrefix + { + const sal_Char* pAsciiPrefix; + const DATASOURCE_TYPE eType; + const bool bMatchComplete; + + KnownPrefix() + :pAsciiPrefix( NULL ) + ,eType( DST_UNKNOWN ) + ,bMatchComplete( false ) + { + } + KnownPrefix( const sal_Char* _p, const DATASOURCE_TYPE _t, const bool _m ) + :pAsciiPrefix( _p ) + ,eType ( _t ) + ,bMatchComplete( _m ) + { + } + }; + KnownPrefix aKnowPrefixes[] = + { + KnownPrefix( "sdbc:calc:", DST_CALC, false ), + KnownPrefix( "sdbc:flat:", DST_FLAT, false ), + KnownPrefix( "sdbc:adabas:", DST_ADABAS, false ), + KnownPrefix( "sdbc:odbc:", DST_ODBC, false ), + KnownPrefix( "sdbc:dbase:", DST_DBASE, false ), + KnownPrefix( "sdbc:mysql:odbc:", DST_MYSQL_ODBC, false ), + KnownPrefix( "sdbc:mysql:jdbc:", DST_MYSQL_JDBC, false ), + KnownPrefix( "sdbc:mysql:mysqlc:", DST_MYSQL_NATIVE, false ), + KnownPrefix( "sdbc:mysqlc:", DST_MYSQL_NATIVE_DIRECT,false ), + + KnownPrefix( "sdbc:address:mozilla:", DST_MOZILLA, true ), + KnownPrefix( "sdbc:address:thunderbird:", DST_THUNDERBIRD, true ), + KnownPrefix( "sdbc:address:ldap:", DST_LDAP, true ), + KnownPrefix( "sdbc:address:outlook", DST_OUTLOOK, true ), + KnownPrefix( "sdbc:address:outlookexp", DST_OUTLOOKEXP, true ), + KnownPrefix( "sdbc:address:evolution:ldap", DST_EVOLUTION_LDAP, true ), + KnownPrefix( "sdbc:address:evolution:groupwise",DST_EVOLUTION_GROUPWISE,true ), + KnownPrefix( "sdbc:address:evolution:local", DST_EVOLUTION, true ), + KnownPrefix( "sdbc:address:kab", DST_KAB, true ), + KnownPrefix( "sdbc:address:macab", DST_MACAB, true ) + }; + + for ( size_t i=0; i < sizeof( aKnowPrefixes ) / sizeof( aKnowPrefixes[0] ); ++i ) + { + USHORT nMatchLen = aKnowPrefixes[i].bMatchComplete ? sDsn.Len() : (USHORT)rtl_str_getLength( aKnowPrefixes[i].pAsciiPrefix ); + if ( sDsn.EqualsIgnoreCaseAscii( aKnowPrefixes[i].pAsciiPrefix, 0, nMatchLen ) ) + return aKnowPrefixes[i].eType; + } + + return DST_UNKNOWN; +} +// ----------------------------------------------------------------------------- +void ODsnTypeCollection::fillPageIds(const ::rtl::OUString& _sURL,::std::vector<sal_Int16>& _rOutPathIds) const +{ + DATASOURCE_TYPE eType = determineType(_sURL); + switch(eType) + { + case DST_ADO: + _rOutPathIds.push_back(PAGE_DBSETUPWIZARD_ADO); + break; + case DST_DBASE: + _rOutPathIds.push_back(PAGE_DBSETUPWIZARD_DBASE); + break; + case DST_FLAT: + _rOutPathIds.push_back(PAGE_DBSETUPWIZARD_TEXT); + break; + case DST_CALC: + _rOutPathIds.push_back(PAGE_DBSETUPWIZARD_SPREADSHEET); + break; + case DST_ODBC: + _rOutPathIds.push_back(PAGE_DBSETUPWIZARD_ODBC); + break; + case DST_JDBC: + _rOutPathIds.push_back(PAGE_DBSETUPWIZARD_JDBC); + break; + case DST_MYSQL_ODBC: + _rOutPathIds.push_back(PAGE_DBSETUPWIZARD_MYSQL_INTRO); + _rOutPathIds.push_back(PAGE_DBSETUPWIZARD_MYSQL_ODBC); + break; + case DST_MYSQL_JDBC: + _rOutPathIds.push_back(PAGE_DBSETUPWIZARD_MYSQL_INTRO); + _rOutPathIds.push_back(PAGE_DBSETUPWIZARD_MYSQL_JDBC); + break; + case DST_MYSQL_NATIVE: + _rOutPathIds.push_back(PAGE_DBSETUPWIZARD_MYSQL_INTRO); + _rOutPathIds.push_back(PAGE_DBSETUPWIZARD_MYSQL_NATIVE); + break; + case DST_ORACLE_JDBC: + _rOutPathIds.push_back(PAGE_DBSETUPWIZARD_ORACLE); + break; + case DST_ADABAS: + _rOutPathIds.push_back(PAGE_DBSETUPWIZARD_ADABAS); + break; + case DST_LDAP: + _rOutPathIds.push_back(PAGE_DBSETUPWIZARD_LDAP); + break; + case DST_MSACCESS: + case DST_MSACCESS_2007: + _rOutPathIds.push_back(PAGE_DBSETUPWIZARD_MSACCESS); + break; + case DST_OUTLOOKEXP: + case DST_OUTLOOK: + case DST_MOZILLA: + case DST_THUNDERBIRD: + case DST_EVOLUTION: + case DST_EVOLUTION_GROUPWISE: + case DST_EVOLUTION_LDAP: + case DST_KAB: + case DST_MACAB: + case DST_EMBEDDED_HSQLDB: + break; + default: + _rOutPathIds.push_back(PAGE_DBSETUPWIZARD_USERDEFINED); + break; + } +} +// ----------------------------------------------------------------------------- +::rtl::OUString ODsnTypeCollection::getType(const ::rtl::OUString& _sURL) const +{ + ::rtl::OUString sOldPattern; + StringVector::const_iterator aIter = m_aDsnPrefixes.begin(); + StringVector::const_iterator aEnd = m_aDsnPrefixes.end(); + for(;aIter != aEnd;++aIter) + { + WildCard aWildCard(*aIter); + if ( sOldPattern.getLength() < aIter->Len() && aWildCard.Matches(_sURL) ) + { + sOldPattern = *aIter; + } + } // for(sal_Int32 i = 0;aIter != aEnd;++aIter,++i) + return sOldPattern; +} +// ----------------------------------------------------------------------------- +sal_Int32 ODsnTypeCollection::getIndexOf(const ::rtl::OUString& _sURL) const +{ + sal_Int32 nRet = -1; + String sURL( _sURL); + String sOldPattern; + StringVector::const_iterator aIter = m_aDsnPrefixes.begin(); + StringVector::const_iterator aEnd = m_aDsnPrefixes.end(); + for(sal_Int32 i = 0;aIter != aEnd;++aIter,++i) + { + WildCard aWildCard(*aIter); + if ( sOldPattern.Len() < aIter->Len() && aWildCard.Matches(sURL) ) + { + nRet = i; + sOldPattern = *aIter; + } + } + + return nRet; +} +// ----------------------------------------------------------------------------- +sal_Int32 ODsnTypeCollection::size() const +{ + return m_aDsnPrefixes.size(); +} +//========================================================================= +//= ODsnTypeCollection::TypeIterator +//========================================================================= +//------------------------------------------------------------------------- +ODsnTypeCollection::TypeIterator::TypeIterator(const ODsnTypeCollection* _pContainer, sal_Int32 _nInitialPos) + :m_pContainer(_pContainer) + ,m_nPosition(_nInitialPos) +{ + DBG_ASSERT(m_pContainer, "ODsnTypeCollection::TypeIterator::TypeIterator : invalid container!"); +#ifdef DBG_UTIL + ++const_cast<ODsnTypeCollection*>(m_pContainer)->m_nLivingIterators; +#endif +} + +//------------------------------------------------------------------------- +ODsnTypeCollection::TypeIterator::TypeIterator(const TypeIterator& _rSource) + :m_pContainer(_rSource.m_pContainer) + ,m_nPosition(_rSource.m_nPosition) +{ +#ifdef DBG_UTIL + ++const_cast<ODsnTypeCollection*>(m_pContainer)->m_nLivingIterators; +#endif +} + +//------------------------------------------------------------------------- +ODsnTypeCollection::TypeIterator::~TypeIterator() +{ +#ifdef DBG_UTIL + --const_cast<ODsnTypeCollection*>(m_pContainer)->m_nLivingIterators; +#endif +} + +//------------------------------------------------------------------------- +String ODsnTypeCollection::TypeIterator::getDisplayName() const +{ + DBG_ASSERT(m_nPosition < (sal_Int32)m_pContainer->m_aDsnTypesDisplayNames.size(), "ODsnTypeCollection::TypeIterator::getDisplayName : invalid position!"); + return m_pContainer->m_aDsnTypesDisplayNames[m_nPosition]; +} +// ----------------------------------------------------------------------------- +::rtl::OUString ODsnTypeCollection::TypeIterator::getURLPrefix() const +{ + DBG_ASSERT(m_nPosition < (sal_Int32)m_pContainer->m_aDsnPrefixes.size(), "ODsnTypeCollection::TypeIterator::getDisplayName : invalid position!"); + return m_pContainer->m_aDsnPrefixes[m_nPosition]; +} +//------------------------------------------------------------------------- +const ODsnTypeCollection::TypeIterator& ODsnTypeCollection::TypeIterator::operator++() +{ + DBG_ASSERT(m_nPosition < (sal_Int32)m_pContainer->m_aDsnTypesDisplayNames.size(), "ODsnTypeCollection::TypeIterator::operator++ : invalid position!"); + if (m_nPosition < (sal_Int32)m_pContainer->m_aDsnTypesDisplayNames.size()) + ++m_nPosition; + return *this; +} + +//------------------------------------------------------------------------- +const ODsnTypeCollection::TypeIterator& ODsnTypeCollection::TypeIterator::operator--() +{ + DBG_ASSERT(m_nPosition >= 0, "ODsnTypeCollection::TypeIterator::operator-- : invalid position!"); + if (m_nPosition >= 0) + --m_nPosition; + return *this; +} + +//------------------------------------------------------------------------- +bool operator==(const ODsnTypeCollection::TypeIterator& lhs, const ODsnTypeCollection::TypeIterator& rhs) +{ + return (lhs.m_pContainer == rhs.m_pContainer) && (lhs.m_nPosition == rhs.m_nPosition); +} + +//......................................................................... +} // namespace dbaccess +//......................................................................... + diff --git a/dbaccess/source/core/misc/makefile.mk b/dbaccess/source/core/misc/makefile.mk new file mode 100644 index 000000000000..3f41bbf80fe8 --- /dev/null +++ b/dbaccess/source/core/misc/makefile.mk @@ -0,0 +1,60 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# 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. +# +#************************************************************************* + +PRJ=..$/..$/.. +PRJINC=$(PRJ)$/source +PRJNAME=dbaccess +TARGET=misc + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ---------------------------------- + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/util$/dba.pmk + +# --- Files ------------------------------------- + +SLOFILES= \ + $(SLO)$/sdbcoretools.obj \ + $(SLO)$/services.obj \ + $(SLO)$/PropertyForward.obj \ + $(SLO)$/ContainerMediator.obj \ + $(SLO)$/userinformation.obj \ + $(SLO)$/ContainerListener.obj \ + $(SLO)$/objectnameapproval.obj \ + $(SLO)$/DatabaseDataProvider.obj \ + $(SLO)$/module_dba.obj \ + $(SLO)$/dsntypes.obj \ + $(SLO)$/veto.obj \ + $(SLO)$/apitools.obj \ + $(SLO)$/dbastrings.obj + +# --- Targets ---------------------------------- + +.INCLUDE : target.mk + diff --git a/dbaccess/source/core/misc/module_dba.cxx b/dbaccess/source/core/misc/module_dba.cxx new file mode 100644 index 000000000000..0010927f733c --- /dev/null +++ b/dbaccess/source/core/misc/module_dba.cxx @@ -0,0 +1,43 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#include "module_dba.hxx" + +//........................................................................ +namespace dba +{ +//........................................................................ + + IMPLEMENT_MODULE( DbaModule, "dba" ) + +//........................................................................ +} // namespace sdbtools +//........................................................................ + diff --git a/dbaccess/source/core/misc/objectnameapproval.cxx b/dbaccess/source/core/misc/objectnameapproval.cxx new file mode 100644 index 000000000000..50b78e386d98 --- /dev/null +++ b/dbaccess/source/core/misc/objectnameapproval.cxx @@ -0,0 +1,116 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#ifndef DBACCESS_OBJECTNAMEAPPROVAL_HXX +#include "objectnameapproval.hxx" +#endif + +/** === begin UNO includes === **/ +#ifndef _COM_SUN_STAR_LANG_DISPOSEDEXCEPTION_HPP_ +#include <com/sun/star/lang/DisposedException.hpp> +#endif +#ifndef _COM_SUN_STAR_SDB_TOOLS_XCONNECTIONTOOLS_HPP_ +#include <com/sun/star/sdb/tools/XConnectionTools.hpp> +#endif +#ifndef _COM_SUN_STAR_SDB_COMMANDTYPE_HPP_ +#include <com/sun/star/sdb/CommandType.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_SQLEXCEPTION_HPP_ +#include <com/sun/star/sdbc/SQLException.hpp> +#endif +/** === end UNO includes === **/ + +#ifndef _CPPUHELPER_WEAKREF_HXX_ +#include <cppuhelper/weakref.hxx> +#endif +#ifndef _CPPUHELPER_EXC_HLP_HXX_ +#include <cppuhelper/exc_hlp.hxx> +#endif + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + + /** === begin UNO using === **/ + using ::com::sun::star::sdbc::XConnection; + using ::com::sun::star::uno::WeakReference; + using ::com::sun::star::uno::Reference; + using ::com::sun::star::lang::DisposedException; + using ::com::sun::star::sdb::tools::XConnectionTools; + using ::com::sun::star::uno::UNO_QUERY_THROW; + using ::com::sun::star::sdb::tools::XObjectNames; + using ::com::sun::star::uno::XInterface; + using ::com::sun::star::sdbc::SQLException; + /** === end UNO using === **/ + + namespace CommandType = com::sun::star::sdb::CommandType; + + //==================================================================== + //= ObjectNameApproval_Impl + //==================================================================== + struct ObjectNameApproval_Impl + { + WeakReference< XConnection > aConnection; + sal_Int32 nCommandType; + }; + + //==================================================================== + //= ObjectNameApproval + //==================================================================== + //-------------------------------------------------------------------- + ObjectNameApproval::ObjectNameApproval( const Reference< XConnection >& _rxConnection, ObjectType _eType ) + :m_pImpl( new ObjectNameApproval_Impl ) + { + m_pImpl->aConnection = _rxConnection; + m_pImpl->nCommandType = _eType == TypeQuery ? CommandType::QUERY : CommandType::TABLE; + } + + //-------------------------------------------------------------------- + ObjectNameApproval::~ObjectNameApproval() + { + } + + //-------------------------------------------------------------------- + void SAL_CALL ObjectNameApproval::approveElement( const ::rtl::OUString& _rName, const Reference< XInterface >& /*_rxElement*/ ) + { + Reference< XConnection > xConnection( m_pImpl->aConnection ); + if ( !xConnection.is() ) + throw DisposedException(); + + Reference< XConnectionTools > xConnectionTools( xConnection, UNO_QUERY_THROW ); + Reference< XObjectNames > xObjectNames( xConnectionTools->getObjectNames(), UNO_QUERY_THROW ); + xObjectNames->checkNameForCreate( m_pImpl->nCommandType, _rName ); + } + +//........................................................................ +} // namespace dbaccess +//........................................................................ + diff --git a/dbaccess/source/core/misc/sdbcoretools.cxx b/dbaccess/source/core/misc/sdbcoretools.cxx new file mode 100644 index 000000000000..dea2328dc907 --- /dev/null +++ b/dbaccess/source/core/misc/sdbcoretools.cxx @@ -0,0 +1,175 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#include "sdbcoretools.hxx" +#include "dbastrings.hrc" + +/** === begin UNO includes === **/ +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/container/XChild.hpp> +#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> +#include <tools/debug.hxx> +#include <comphelper/componentcontext.hxx> +#include <comphelper/interaction.hxx> +#include <rtl/ref.hxx> +#include <rtl/ustrbuf.hxx> + +//......................................................................... +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; + + // ========================================================================= + // ------------------------------------------------------------------------- + void notifyDataSourceModified(const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxObject,sal_Bool _bModified) + { + Reference< XInterface > xDs = getDataSource( _rxObject ); + Reference<XDocumentDataSource> xDocumentDataSource(xDs,UNO_QUERY); + if ( xDocumentDataSource.is() ) + xDs = xDocumentDataSource->getDatabaseDocument(); + Reference< XModifiable > xModi( xDs, UNO_QUERY ); + if ( xModi.is() ) + xModi->setModified(_bModified); + } + + // ------------------------------------------------------------------------- + Reference< XInterface > getDataSource( const Reference< XInterface >& _rxDependentObject ) + { + Reference< XInterface > xParent = _rxDependentObject; + Reference< XInterface > xReturn; + while( xParent.is() ) + { + xReturn = xParent; + Reference<XChild> xChild(xParent,UNO_QUERY); + xParent.set(xChild.is() ? xChild->getParent() : Reference< XInterface >(),UNO_QUERY); + } + return xReturn; + } + +// ----------------------------------------------------------------------------- + ::rtl::OUString extractExceptionMessage( const ::comphelper::ComponentContext& _rContext, const Any& _rError ) + { + ::rtl::OUString sDisplayMessage; + + try + { + Reference< XInteractionRequestStringResolver > xStringResolver; + if ( _rContext.createComponent( "com.sun.star.task.InteractionRequestStringResolver", xStringResolver ) ) + { + ::rtl::Reference< ::comphelper::OInteractionRequest > pRequest( new ::comphelper::OInteractionRequest( _rError ) ); + ::rtl::Reference< ::comphelper::OInteractionApprove > pApprove( new ::comphelper::OInteractionApprove ); + pRequest->addContinuation( pApprove.get() ); + Optional< ::rtl::OUString > aMessage = xStringResolver->getStringFromInformationalRequest( pRequest.get() ); + if ( aMessage.IsPresent ) + sDisplayMessage = aMessage.Value; + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + if ( !sDisplayMessage.getLength() ) + { + Exception aExcept; + _rError >>= aExcept; + + ::rtl::OUStringBuffer aBuffer; + aBuffer.append( _rError.getValueTypeName() ); + aBuffer.appendAscii( ":\n" ); + aBuffer.append( aExcept.Message ); + + sDisplayMessage = aBuffer.makeStringAndClear(); + } + + 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/misc/services.cxx b/dbaccess/source/core/misc/services.cxx new file mode 100644 index 000000000000..5c427d1eb57e --- /dev/null +++ b/dbaccess/source/core/misc/services.cxx @@ -0,0 +1,138 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#include <cppuhelper/factory.hxx> +#include <cppuhelper/implementationentry.hxx> +#include "module_dba.hxx" +#include <osl/diagnose.h> +#include "DatabaseDataProvider.hxx" +#include "dbadllapi.hxx" + +/********************************************************************************************/ + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::registry; + +//*************************************************************************************** +// +// registry functions +extern "C" void SAL_CALL createRegistryInfo_ODatabaseContext(); +extern "C" void SAL_CALL createRegistryInfo_OCommandDefinition(); +extern "C" void SAL_CALL createRegistryInfo_OComponentDefinition(); +extern "C" void SAL_CALL createRegistryInfo_ORowSet(); +extern "C" void SAL_CALL createRegistryInfo_ODatabaseDocument(); +extern "C" void SAL_CALL createRegistryInfo_ODatabaseSource(); +extern "C" void SAL_CALL createRegistryInfo_DataAccessDescriptorFactory(); + +namespace dba{ +//-------------------------------------------------------------------------- + ::cppu::ImplementationEntry entries[] = { + { &::dbaccess::DatabaseDataProvider::Create, &::dbaccess::DatabaseDataProvider::getImplementationName_Static, &::dbaccess::DatabaseDataProvider::getSupportedServiceNames_Static, + &cppu::createSingleComponentFactory, 0, 0 }, + { 0, 0, 0, 0, 0, 0 } + }; +} + +//*************************************************************************************** +// +// Die vorgeschriebene C-Api muss erfuellt werden! +// Sie besteht aus drei Funktionen, die von dem Modul exportiert werden muessen. +// +extern "C" void SAL_CALL createRegistryInfo_DBA() +{ + static sal_Bool bInit = sal_False; + if (!bInit) + { + createRegistryInfo_ODatabaseContext(); + createRegistryInfo_OCommandDefinition(); + createRegistryInfo_OComponentDefinition(); + createRegistryInfo_ORowSet(); + createRegistryInfo_ODatabaseDocument(); + createRegistryInfo_ODatabaseSource(); + createRegistryInfo_DataAccessDescriptorFactory(); + bInit = sal_True; + } +} + +//--------------------------------------------------------------------------------------- + +extern "C" OOO_DLLPUBLIC_DBA void SAL_CALL component_getImplementationEnvironment( + const sal_Char **ppEnvTypeName, + uno_Environment ** + ) +{ + createRegistryInfo_DBA(); + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +//--------------------------------------------------------------------------------------- +extern "C" OOO_DLLPUBLIC_DBA sal_Bool SAL_CALL component_writeInfo( + void* pServiceManager, + void* pRegistryKey + ) +{ + if (pRegistryKey) + try + { + return ::dba::DbaModule::getInstance().writeComponentInfos( + static_cast< XMultiServiceFactory* >( pServiceManager ), + static_cast< XRegistryKey* >( pRegistryKey ) ) + && cppu::component_writeInfoHelper(pServiceManager, pRegistryKey, dba::entries); + } + catch (InvalidRegistryException& ) + { + OSL_ENSURE( false, "DBA::component_writeInfo : could not create a registry key ! ## InvalidRegistryException !" ); + } + + return sal_False; +} + +//--------------------------------------------------------------------------------------- +extern "C" OOO_DLLPUBLIC_DBA void* SAL_CALL component_getFactory( + const sal_Char* pImplementationName, + void* pServiceManager, + void* pRegistryKey) +{ + Reference< XInterface > xRet; + if (pServiceManager && pImplementationName) + { + xRet = ::dba::DbaModule::getInstance().getComponentFactory( + ::rtl::OUString::createFromAscii( pImplementationName ), + static_cast< XMultiServiceFactory* >( pServiceManager ) ); + } + + if (xRet.is()) + xRet->acquire(); + else + return cppu::component_getFactoryHelper( + pImplementationName, pServiceManager, pRegistryKey, dba::entries); + return xRet.get(); +}; diff --git a/dbaccess/source/core/misc/userinformation.cxx b/dbaccess/source/core/misc/userinformation.cxx new file mode 100644 index 000000000000..9143b123899b --- /dev/null +++ b/dbaccess/source/core/misc/userinformation.cxx @@ -0,0 +1,59 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#ifndef _DBA_CORE_USERINFORMATION_HXX_ +#include "userinformation.hxx" +#endif + +#ifndef _OSL_DIAGNOSE_H_ +#include <osl/diagnose.h> +#endif +#ifndef INCLUDED_I18NPOOL_MSLANGID_HXX +#include <i18npool/mslangid.hxx> +#endif +#ifndef _UTL_CONFIGMGR_HXX_ +#include <unotools/configmgr.hxx> +#endif +#ifndef _COMPHELPER_TYPES_HXX_ +#include <comphelper/types.hxx> +#endif + +using namespace ::utl; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; + +//-------------------------------------------------------------------------- +UserInformation::UserInformation() +{ + Any aValue = ConfigManager::GetDirectConfigProperty(ConfigManager::LOCALE); + LanguageType eLanguage = MsLangId::convertIsoStringToLanguage(comphelper::getString(aValue),'-'); + m_aUserLocale = MsLangId::convertLanguageToLocale(eLanguage); +} + diff --git a/dbaccess/source/core/misc/veto.cxx b/dbaccess/source/core/misc/veto.cxx new file mode 100644 index 000000000000..b3ab20bf9beb --- /dev/null +++ b/dbaccess/source/core/misc/veto.cxx @@ -0,0 +1,78 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#ifndef DBACCESS_VETO_HXX +#include "veto.hxx" +#endif + +/** === begin UNO includes === **/ +/** === end UNO includes === **/ + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + + /** === begin UNO using === **/ + using ::com::sun::star::uno::Any; + using ::com::sun::star::uno::RuntimeException; + /** === end UNO using === **/ + + //==================================================================== + //= Veto + //==================================================================== + //-------------------------------------------------------------------- + Veto::Veto( const ::rtl::OUString& _rReason, const Any& _rDetails ) + :m_sReason( _rReason ) + ,m_aDetails( _rDetails ) + { + } + + //-------------------------------------------------------------------- + Veto::~Veto() + { + } + + //-------------------------------------------------------------------- + ::rtl::OUString SAL_CALL Veto::getReason() throw (RuntimeException) + { + return m_sReason; + } + + //-------------------------------------------------------------------- + Any SAL_CALL Veto::getDetails() throw (RuntimeException) + { + return m_aDetails; + } + +//........................................................................ +} // 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 diff --git a/dbaccess/source/core/resource/core_resource.cxx b/dbaccess/source/core/resource/core_resource.cxx new file mode 100644 index 000000000000..f2efb811418d --- /dev/null +++ b/dbaccess/source/core/resource/core_resource.cxx @@ -0,0 +1,119 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#include "core_resource.hxx" + +#include <tools/resmgr.hxx> + +// ---- needed as long as we have no contexts for components --- +#ifndef _SV_SVAPP_HXX +#include <vcl/svapp.hxx> +#endif +//--------------------------------------------------- + +#ifndef _SOLAR_HRC +#include <svl/solar.hrc> +#endif + +//......................................................................... +namespace dbaccess +{ + + //================================================================== + //= ResourceManager + //================================================================== + ::osl::Mutex ResourceManager::s_aMutex; + sal_Int32 ResourceManager::s_nClients = 0; + ResMgr* ResourceManager::m_pImpl = NULL; + + //------------------------------------------------------------------ + void ResourceManager::ensureImplExists() + { + if (m_pImpl) + return; + + ::com::sun::star::lang::Locale aLocale = Application::GetSettings().GetUILocale(); + + ByteString sFileName("dba"); + + m_pImpl = ResMgr::CreateResMgr(sFileName.GetBuffer(), aLocale); + } + + //------------------------------------------------------------------ + ::rtl::OUString ResourceManager::loadString(sal_uInt16 _nResId) + { + ::rtl::OUString sReturn; + + ensureImplExists(); + if (m_pImpl) + sReturn = String(ResId(_nResId,*m_pImpl)); + + return sReturn; + } + + //------------------------------------------------------------------ + ::rtl::OUString ResourceManager::loadString( sal_uInt16 _nResId, const sal_Char* _pPlaceholderAscii, const ::rtl::OUString& _rReplace ) + { + String sString( loadString( _nResId ) ); + sString.SearchAndReplaceAscii( _pPlaceholderAscii, _rReplace ); + return sString; + } + + //------------------------------------------------------------------ + ::rtl::OUString ResourceManager::loadString( sal_uInt16 _nResId, const sal_Char* _pPlaceholderAscii1, const ::rtl::OUString& _rReplace1, + const sal_Char* _pPlaceholderAscii2, const ::rtl::OUString& _rReplace2 ) + { + String sString( loadString( _nResId ) ); + sString.SearchAndReplaceAscii( _pPlaceholderAscii1, _rReplace1 ); + sString.SearchAndReplaceAscii( _pPlaceholderAscii2, _rReplace2 ); + return sString; + } + + //------------------------------------------------------------------------- + void ResourceManager::registerClient() + { + ::osl::MutexGuard aGuard(s_aMutex); + ++s_nClients; + } + + //------------------------------------------------------------------------- + void ResourceManager::revokeClient() + { + ::osl::MutexGuard aGuard(s_aMutex); + if (!--s_nClients && m_pImpl) + { + delete m_pImpl; + m_pImpl = NULL; + } + } +//......................................................................... +} +//......................................................................... + diff --git a/dbaccess/source/core/resource/makefile.mk b/dbaccess/source/core/resource/makefile.mk new file mode 100644 index 000000000000..293b92b5e4cf --- /dev/null +++ b/dbaccess/source/core/resource/makefile.mk @@ -0,0 +1,48 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# 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. +# +#************************************************************************* + +PRJ=..$/..$/.. +PRJINC=$(PRJ)$/source +PRJNAME=dbaccess +TARGET=core_resource + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/util$/dba.pmk + +# --- Files -------------------------------------------------------- + +SRS1NAME=core_strings +SRC1FILES= \ + strings.src \ + +SLOFILES= $(SLO)$/core_resource.obj \ + +# --- Targets ---------------------------------- + +.INCLUDE : target.mk diff --git a/dbaccess/source/core/resource/strings.src b/dbaccess/source/core/resource/strings.src new file mode 100644 index 000000000000..dc7023ca6fba --- /dev/null +++ b/dbaccess/source/core/resource/strings.src @@ -0,0 +1,326 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * 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 "core_resource.hrc" +#include "dbamiscres.hrc" + +String RID_STR_TRIED_OPEN_TABLE +{ + Text [ en-US ] = "Tried to open the table $name$."; +}; +String RID_STR_CONNECTION_INVALID +{ + Text [ en-US ] = "No connection could be established."; +}; + +String RID_STR_TABLE_IS_FILTERED +{ + Text [ en-US ] = "The table $name$ already exists. It is not visible because it has been filtered out."; +}; + +String RID_STR_NEED_CONFIG_WRITE_ACCESS +{ + Text [ en-US ] = "You have no write access to the configuration data the object is based on."; +}; + + +String RID_STR_COULDNOTCONNECT_UNSPECIFIED +{ + Text [ en-US ] = "The connection to the external data source could not be established. An unknown error occurred. The driver is probably defective."; +}; + +String RID_STR_COULDNOTCONNECT_NODRIVER +{ + Text [ en-US ] = "The connection to the external data source could not be established. No SDBC driver was found for the given URL."; +}; + +String RID_STR_COULDNOTLOAD_MANAGER +{ + Text [ en-US ] = "The connection to the external data source could not be established. The SDBC driver manager could not be loaded."; +}; + +String RID_STR_FORM +{ + Text [ en-US ] = "Form"; +}; + +String RID_STR_REPORT +{ + Text [ en-US ] = "Report"; +}; + +String RID_STR_DATASOURCE_NOT_STORED +{ + Text [ en-US ] = "The data source was not saved. Please use the interface XStorable to save the data source."; +}; +String RID_STR_ONLY_QUERY +{ + Text [ en-US ] = "The given command is not a SELECT statement.\nOnly queries are allowed."; +}; +String RID_STR_NO_VALUE_CHANGED +{ + Text [ en-US ] = "No values were modified."; +}; +String RID_STR_NO_XROWUPDATE +{ + Text [ en-US ] = "Values could not be inserted. The XRowUpdate interface is not supported by ResultSet."; +}; +String RID_STR_NO_XRESULTSETUPDATE +{ + Text [ en-US ] = "Values could not be inserted. The XResultSetUpdate interface is not supported by ResultSet."; +}; +String RID_STR_NO_UPDATE_MISSING_CONDITION +{ + Text [ en-US ] = "Values could not be modified, due to a missing condition statement."; +}; +String RID_STR_NO_COLUMN_ADD +{ + Text [ en-US ] = "The adding of columns is not supported."; +}; +String RID_STR_NO_COLUMN_DROP +{ + Text [ en-US ] = "The dropping of columns is not supported."; +}; +String RID_STR_NO_CONDITION_FOR_PK +{ + Text [ en-US ] = "The WHERE condition could not be created for the primary key."; +}; +String RID_STR_COLUMN_UNKNOWN_PROP +{ + Text [ en-US ] = "The column does not support the property '%value'."; +}; +String RID_STR_COLUMN_NOT_SEARCHABLE +{ + Text [ en-US ] = "The column is not searchable!"; +}; +String RID_STR_NOT_SEQUENCE_INT8 +{ + Text [ en-US ] = "The value of the columns is not of the type Sequence<sal_Int8>."; +}; +String RID_STR_COLUMN_NOT_VALID +{ + Text [ en-US ] = "The column is not valid."; +}; +String RID_STR_COLUMN_MUST_VISIBLE +{ + Text [ en-US ] = "The column '%name' must be visible as a column."; +}; +String RID_STR_NO_XQUERIESSUPPLIER +{ + Text [ en-US ] = "The interface XQueriesSupplier is not available."; +}; +String RID_STR_NOT_SUPPORTED_BY_DRIVER +{ + Text [ en-US ] = "The driver does not support this function."; +}; +String RID_STR_NO_ABS_ZERO +{ + Text [ en-US ] = "An 'absolute(0)' call is not allowed."; +}; +String RID_STR_NO_RELATIVE +{ + Text [ en-US ] = "Relative positioning is not allowed in this state."; +}; +String RID_STR_NO_REFESH_AFTERLAST +{ + Text [ en-US ] = "A row cannot be refreshed when the ResultSet is positioned after the last row."; +}; +String RID_STR_NO_MOVETOINSERTROW_CALLED +{ + Text [ en-US ] = "A new row cannot be inserted when the ResultSet is not first moved to the insert row."; +}; +String RID_STR_NO_UPDATEROW +{ + Text [ en-US ] = "A row cannot be modified in this state"; +}; +String RID_STR_NO_DELETEROW +{ + Text [ en-US ] = "A row cannot be deleted in this state."; +}; +String RID_STR_NO_TABLE_RENAME +{ + Text [ en-US ] = "The driver does not support table renaming."; +}; +String RID_STR_NO_ALTER_COLUMN_DEF +{ + Text [ en-US ] = "The driver does not support the modification of column descriptions."; +}; +String RID_STR_COLUMN_ALTER_BY_NAME +{ + Text [ en-US ] = "The driver does not support the modification of column descriptions by changing the name."; +}; +String RID_STR_COLUMN_ALTER_BY_INDEX +{ + Text [ en-US ] = "The driver does not support the modification of column descriptions by changing the index."; +}; +String RID_STR_FILE_DOES_NOT_EXIST +{ + Text[ en-US ] = "The file \"$file$\" does not exist."; +}; + +String RID_STR_TABLE_DOES_NOT_EXIST +{ + Text [ en-US ] = "There exists no table named \"$table$\"."; +}; + +String RID_STR_QUERY_DOES_NOT_EXIST +{ + Text [ en-US ] = "There exists no query named \"$table$\"."; +}; + +String RID_STR_CONFLICTING_NAMES +{ + Text [ en-US ] = "There are tables in the database whose names conflict with the names of existing queries. To make full use of all queries and tables, make sure they have distinct names."; +}; + +String RID_STR_COMMAND_LEADING_TO_ERROR +{ + Text [ en-US ] = "The SQL command leading to this error is:\n\n$command$"; + +}; + +String RID_STR_STATEMENT_WITHOUT_RESULT_SET +{ + Text [ en-US ] = "The SQL command does not describe a result set."; +}; + +String RID_STR_NAME_MUST_NOT_BE_EMPTY +{ + Text [ en-US ] = "The name must not be empty."; +}; + +String RID_STR_NO_NULL_OBJECTS_IN_CONTAINER +{ + Text [ en-US ] = "The container cannot contain NULL objects."; +}; + +String RID_STR_NAME_ALREADY_USED +{ + Text [ en-US ] = "There already is an object with the given name."; +}; + +String RID_STR_OBJECT_CONTAINER_MISMATCH +{ + Text [ en-US ] = "This object cannot be part of this container."; +}; + +String RID_STR_OBJECT_ALREADY_CONTAINED +{ + Text [ en-US ] = "The object already is, with a different name, part of the container."; +}; + +String RID_STR_NAME_NOT_FOUND +{ + Text [ en-US ] = "Unable to find the document '$name$'."; +}; + +String RID_STR_ERROR_WHILE_SAVING +{ + Text [ en-US ] = "Could not save the document to $location$:\n$message$"; +}; + +String RID_NO_SUCH_DATA_SOURCE +{ + Text [ en-US ] = "Error accessing data source '$name$':\n$error$"; +}; +String RID_STR_NO_SUB_FOLDER +{ + Text [ en-US ] = "There exists no folder named \"$folder$\"."; +}; +String RID_STR_NO_DELETE_BEFORE_AFTER +{ + Text [ en-US ] = "Cannot delete the before-first or after-last row."; +}; +String RID_STR_NO_DELETE_INSERT_ROW +{ + Text [ en-US ] = "Cannot delete the insert-row."; +}; +String RID_STR_RESULT_IS_READONLY +{ + Text [ en-US ] = "Result set is read only."; +}; +String RID_STR_NO_DELETE_PRIVILEGE +{ + Text [ en-US ] = "DELETE privilege not available."; +}; +String RID_STR_ROW_ALREADY_DELETED +{ + Text [ en-US ] = "Current row is already deleted."; +}; +String RID_STR_UPDATE_FAILED +{ + Text [ en-US ] = "Current row could be updated."; +}; +//------------------------------------------------------------------------- +String RID_STR_NO_INSERT_PRIVILEGE +{ + Text [ en-US ] = "INSERT privilege not available."; +}; +String RID_STR_INTERNAL_ERROR +{ + Text [ en-US ] = "Internal error: no statement object provided by the database driver."; +}; +String RID_STR_EXPRESSION1 +{ + Text [ en-US ] = "Expression1"; +}; +String RID_STR_NO_SQL_COMMAND +{ + Text [ en-US ] = "No SQL command was provided."; +}; +String RID_STR_INVALID_INDEX +{ + Text [ en-US ] = "Invalid column index."; +}; +String RID_STR_INVALID_CURSOR_STATE +{ + Text [ en-US ] = "Invalid cursor state."; +}; +String RID_STR_CURSOR_BEFORE_OR_AFTER +{ + Text [ en-US ] = "The cursor points to before the first or after the last row."; +}; +String RID_STR_NO_BOOKMARK_BEFORE_OR_AFTER +{ + Text [ en-US ] = "The rows before the first and after the last row don't have a bookmark."; +}; +String RID_STR_NO_BOOKMARK_DELETED +{ + Text [ en-US ] = "The current row is deleted, and thus doesn't have a bookmark."; +}; +String RID_STR_NO_EMBEDDING +{ + Text [ en-US ] = "Embedding of database documents is not supported."; +}; +String RID_STR_CONNECTION_REQUEST +{ + Text [ en-US ] = "A connection for the following URL was requested \"$name$\"."; +}; +String RID_STR_MISSING_EXTENSION +{ + Text [ en-US ] = "The extension is not installed."; +}; |