/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /************************************************************************* * * 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 "ContentHelper.hxx" #include #include #include #include #include #include #include #include #include #include #include "myucp_resultset.hxx" #include #include "sdbcoretools.hxx" #include "dbastrings.hrc" #include 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 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 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 ) ); } } 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); } } 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(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); } void OContentHelper::notifyDataSourceModified() { ::dbaccess::notifyDataSourceModified(m_xParentContainer,sal_True); } } // namespace dbaccess /* vim:set shiftwidth=4 softtabstop=4 expandtab: */