/************************************************************************* * * 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 * * 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 #include #include #include #include "core_resource.hxx" #include "core_resource.hrc" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "TableDeco.hxx" #include "sdbcoretools.hxx" #include "ContainerMediator.hxx" #include "definitioncolumn.hxx" #include "objectnameapproval.hxx" #include #include #ifndef TOOLS_DIAGNOSE_EX_H #include #endif #ifndef TOOLS_DIAGNOSE_EX_H #include #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& _xProp) { Reference 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 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& _xTableDefinition ,Reference& _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(_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 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 xTableDefinition; Reference 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 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 xMasterColumnsSup; Reference 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(static_cast(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(m_xMasterContainer,UNO_QUERY); if(xAppend.is()) { xAppend->appendByDescriptor(descriptor); } else { ::rtl::OUString aSql = ::dbtools::createSqlCreateTableStatement(descriptor,m_xConnection); Reference 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 xTableDefinition; Reference xColumnDefinitions; lcl_createDefintionObject(getNameForObject(descriptor),m_xTableDefinitions,xTableDefinition,xColumnDefinitions,sal_False); Reference xSup(descriptor,UNO_QUERY); Reference xFac(xColumnDefinitions,UNO_QUERY); Reference xAppend(xColumnDefinitions,UNO_QUERY); sal_Bool bModified = sal_False; if ( xSup.is() && xColumnDefinitions.is() && xFac.is() && xAppend.is() ) { Reference xNames = xSup->getColumns(); if ( xNames.is() ) { Reference 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 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 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(static_cast(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 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(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(); } }